diff --git a/.circleci/config.yml b/.circleci/config.yml index 83ccb67ee..6648b608d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -52,6 +52,9 @@ workflows: - test-lint-lockfile: requires: - prep-deps + - test-lint-changelog: + requires: + - prep-deps - test-e2e-chrome: requires: - prep-build-test @@ -83,6 +86,7 @@ workflows: - test-lint - test-lint-shellcheck - test-lint-lockfile + - test-lint-changelog - test-unit - test-unit-global - validate-source-maps @@ -282,6 +286,33 @@ jobs: name: lockfile-lint command: yarn lint:lockfile + test-lint-changelog: + executor: node-browsers + steps: + - checkout + - attach_workspace: + at: . + - when: + condition: + not: + matches: + pattern: /^Version-v(\d+)[.](\d+)[.](\d+)$/ + value: << pipeline.git.branch >> + steps: + - run: + name: Validate changelog + command: yarn auto-changelog validate + - when: + condition: + matches: + pattern: /^Version-v(\d+)[.](\d+)[.](\d+)$/ + value: << pipeline.git.branch >> + steps: + - run: + name: Validate release candidate changelog + command: yarn auto-changelog validate --rc + + test-deps: executor: node-browsers steps: @@ -474,7 +505,7 @@ jobs: at: . - run: name: sentry sourcemaps upload - command: yarn sentry:publish + command: SENTRY_ORG=metamask SENTRY_PROJECT=metamask yarn sentry:publish - run: name: Create GitHub release command: | @@ -485,7 +516,7 @@ jobs: steps: - add_ssh_keys: fingerprints: - - "5e:a3:2d:35:b6:25:b5:87:b1:41:11:0d:77:50:96:73" + - "3d:49:29:f4:b2:e8:ea:af:d1:32:eb:2a:fc:15:85:d8" - checkout - attach_workspace: at: . diff --git a/.circleci/scripts/release-bump-manifest-version.sh b/.circleci/scripts/release-bump-manifest-version.sh index 776a33a63..e00382504 100755 --- a/.circleci/scripts/release-bump-manifest-version.sh +++ b/.circleci/scripts/release-bump-manifest-version.sh @@ -19,9 +19,7 @@ fi printf '%s\n' 'Updating the manifest version if needed' version="${CIRCLE_BRANCH/Version-v/}" -updated_manifest="$(jq ".version = \"$version\"" app/manifest/_base.json)" -printf '%s\n' "$updated_manifest" > app/manifest/_base.json -yarn prettier --write app/manifest/_base.json +yarn version --no-git-tag-version --new-version "${version}" if [[ -z $(git status --porcelain) ]] then diff --git a/.circleci/scripts/release-commit-version-bump.sh b/.circleci/scripts/release-commit-version-bump.sh index 6ceb67fb9..554350646 100755 --- a/.circleci/scripts/release-commit-version-bump.sh +++ b/.circleci/scripts/release-commit-version-bump.sh @@ -16,9 +16,19 @@ then exit 1 fi +if [[ -z "${GITHUB_TOKEN:-}" ]] +then + printf '%s\n' 'GITHUB_TOKEN environment variable must be set' + exit 1 +elif [[ -z "${GITHUB_TOKEN_USER:-}" ]] +then + printf '%s\n' 'GITHUB_TOKEN_USER environment variable must be set' + exit 1 +fi + printf '%s\n' 'Commit the manifest version and changelog if the manifest has changed' -if git diff --quiet app/manifest/_base.json; +if git diff --quiet package.json; then printf '%s\n' 'No manifest changes to commit' exit 0 @@ -28,7 +38,7 @@ git \ -c user.name='MetaMask Bot' \ -c user.email='metamaskbot@users.noreply.github.com' \ commit --message "${CIRCLE_BRANCH/-/ }" \ - CHANGELOG.md app/manifest/_base.json + CHANGELOG.md package.json repo_slug="$CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME" git push "https://$GITHUB_TOKEN_USER:$GITHUB_TOKEN@github.com/$repo_slug" "$CIRCLE_BRANCH" diff --git a/.circleci/scripts/release-create-release-pr.sh b/.circleci/scripts/release-create-release-pr.sh index a1d05c777..9aa5d39bd 100755 --- a/.circleci/scripts/release-create-release-pr.sh +++ b/.circleci/scripts/release-create-release-pr.sh @@ -16,12 +16,6 @@ then exit 1 fi -if [[ -z "${GITHUB_TOKEN:-}" ]] -then - printf '%s\n' 'GITHUB_TOKEN environment variable must be set' - exit 1 -fi - function install_github_cli () { printf '%s\n' 'Installing hub CLI' diff --git a/.eslintrc.js b/.eslintrc.js index 8b9f27b12..fa67adaaf 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -108,7 +108,7 @@ module.exports = { }, { files: ['**/*.test.js'], - excludedFiles: ['ui/**/*.test.js', 'ui/app/__mocks__/*.js'], + excludedFiles: ['ui/**/*.test.js', 'ui/__mocks__/*.js'], extends: ['@metamask/eslint-config-mocha'], rules: { 'mocha/no-setup-in-describe': 'off', @@ -125,7 +125,7 @@ module.exports = { }, }, { - files: ['ui/**/*.test.js', 'ui/app/__mocks__/*.js'], + files: ['ui/**/*.test.js', 'ui/__mocks__/*.js'], extends: ['@metamask/eslint-config-jest'], rules: { 'jest/no-restricted-matchers': 'off', diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index a5b579a96..95077129c 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ blank_issues_enabled: false contact_links: - name: Request a new feature - url: https://metamask.zendesk.com/hc/en-us/community/topics/360000682552-Feature-Requests + url: https://community.metamask.io/c/feature-requests-ideas/ about: Request new features and vote on the ones that are important to you - name: Get support or ask a question url: https://metamask.zendesk.com/hc/en-us/requests/new diff --git a/.gitignore b/.gitignore index 6333a39a1..21c882a97 100644 --- a/.gitignore +++ b/.gitignore @@ -39,7 +39,7 @@ test-builds build-artifacts #ignore css output and sourcemaps -ui/app/css/output/ +ui/css/output/ notes.txt diff --git a/.storybook/i18n.js b/.storybook/i18n.js index 9eadca331..314ea544e 100644 --- a/.storybook/i18n.js +++ b/.storybook/i18n.js @@ -1,12 +1,12 @@ import React, { Component, createContext, useMemo } from 'react'; import PropTypes from 'prop-types'; -import { getMessage } from '../ui/app/helpers/utils/i18n-helper'; -import { I18nContext } from '../ui/app/contexts/i18n'; +import { getMessage } from '../ui/helpers/utils/i18n-helper'; +import { I18nContext } from '../ui/contexts/i18n'; -export { I18nContext } +export { I18nContext }; export const I18nProvider = (props) => { - const { currentLocale, current, en } = props + const { currentLocale, current, en } = props; const t = useMemo(() => { return (key, ...args) => diff --git a/.storybook/initial-states/approval-screens/token-approval.js b/.storybook/initial-states/approval-screens/token-approval.js new file mode 100644 index 000000000..f03990ea5 --- /dev/null +++ b/.storybook/initial-states/approval-screens/token-approval.js @@ -0,0 +1,56 @@ +export const currentNetworkTxListSample = { + "id": 7900715443136469, + "time": 1621395091737, + "status": "unapproved", + "metamaskNetworkId": "1337", + "chainId": "0x539", + "loadingDefaults": false, + "txParams": { + "from": "0x90f79bf6eb2c4f870365e785982e1f101e93b906", + "to": "0x057ef64e23666f000b34ae31332854acbd1c8544", + "value": "0x0", + "data": "0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef40000000000000000000000000000000000000000000000000000000000011170", + "gas": "0xea60", + "gasPrice": "0x4a817c800" + }, + "origin": "https://metamask.github.io", + "type": "approve", + "history": [ + { + "id": 7900715443136469, + "time": 1621395091737, + "status": "unapproved", + "metamaskNetworkId": "1337", + "chainId": "0x539", + "loadingDefaults": true, + "txParams": { + "from": "0x90f79bf6eb2c4f870365e785982e1f101e93b906", + "to": "0x057ef64e23666f000b34ae31332854acbd1c8544", + "value": "0x0", + "data": "0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef40000000000000000000000000000000000000000000000000000000000011170", + "gas": "0xea60", + "gasPrice": "0x4a817c800" + }, + "origin": "https://metamask.github.io", + "type": "approve" + }, + [ + { + "op": "replace", + "path": "/loadingDefaults", + "value": false, + "note": "Added new unapproved transaction.", + "timestamp": 1621395091742 + } + ] + ] +} + +export const domainMetadata = { + "https://metamask.github.io": { + "name": "E2E Test Dapp", + "icon": "https://metamask.github.io/test-dapp/metamask-fox.svg", + "lastUpdated": 1620723443380, + "host": "metamask.github.io" + } +} \ No newline at end of file diff --git a/.storybook/main.js b/.storybook/main.js index 2e708e264..310bce17d 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -1,9 +1,9 @@ -const path = require('path') +const path = require('path'); -const CopyWebpackPlugin = require('copy-webpack-plugin') +const CopyWebpackPlugin = require('copy-webpack-plugin'); module.exports = { - stories: ['../ui/app/**/*.stories.js'], + stories: ['../ui/**/*.stories.js'], addons: [ '@storybook/addon-knobs', '@storybook/addon-actions', @@ -12,7 +12,7 @@ module.exports = { './i18n-party-addon/register.js', ], webpackFinal: async (config) => { - config.module.strictExportPresence = true + config.module.strictExportPresence = true; config.module.rules.push({ test: /\.scss$/, loaders: [ @@ -31,12 +31,12 @@ module.exports = { sourceMap: true, implementation: require('sass'), sassOptions: { - includePaths: ['ui/app/css/'], + includePaths: ['ui/css/'], }, }, }, ], - }) + }); config.plugins.push( new CopyWebpackPlugin({ patterns: [ @@ -51,7 +51,7 @@ module.exports = { }, ], }), - ) - return config + ); + return config; }, -} +}; diff --git a/.storybook/metametrics.js b/.storybook/metametrics.js new file mode 100644 index 000000000..387b0d467 --- /dev/null +++ b/.storybook/metametrics.js @@ -0,0 +1,24 @@ +import React from 'react'; +import { + MetaMetricsProvider, + LegacyMetaMetricsProvider, +} from '../ui/contexts/metametrics'; +import { + MetaMetricsProvider as NewMetaMetricsProvider, + LegacyMetaMetricsProvider as NewLegacyMetaMetricsProvider, +} from '../ui/contexts/metametrics.new'; + +const MetaMetricsProviderStorybook = (props) => + ( + <MetaMetricsProvider> + <LegacyMetaMetricsProvider> + <NewMetaMetricsProvider> + <NewLegacyMetaMetricsProvider> + {props.children} + </NewLegacyMetaMetricsProvider> + </NewMetaMetricsProvider> + </LegacyMetaMetricsProvider> + </MetaMetricsProvider> + ); + +export default MetaMetricsProviderStorybook \ No newline at end of file diff --git a/.storybook/preview.js b/.storybook/preview.js index 112c8f16e..525401408 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,14 +1,18 @@ import React, { useEffect } from 'react'; import { addDecorator, addParameters } from '@storybook/react'; -import { useGlobals } from '@storybook/api'; +import { action } from '@storybook/addon-actions'; import { withKnobs } from '@storybook/addon-knobs'; import { Provider } from 'react-redux'; -import configureStore from '../ui/app/store/store'; -import '../ui/app/css/index.scss'; +import configureStore from '../ui/store/store'; +import '../ui/css/index.scss'; import localeList from '../app/_locales/index.json'; import * as allLocales from './locales'; import { I18nProvider, LegacyI18nProvider } from './i18n'; -import testData from './test-data.js' +import MetaMetricsProviderStorybook from './metametrics' +import testData from './test-data.js'; +import { Router } from "react-router-dom"; +import { createBrowserHistory } from "history"; +import { _setBackgroundConnection } from '../ui/store/actions' addParameters({ backgrounds: { @@ -41,22 +45,36 @@ const styles = { alignItems: 'center', }; -const store = configureStore(testData) +export const store = configureStore(testData); +const history = createBrowserHistory(); +const proxiedBackground = new Proxy({}, { + get(_, method) { + return function() { + action(`Background call: ${method}`)() + return new Promise(() => {}) + } + } + }) +_setBackgroundConnection(proxiedBackground) const metamaskDecorator = (story, context) => { const currentLocale = context.globals.locale; const current = allLocales[currentLocale]; return ( <Provider store={store}> - <I18nProvider - currentLocale={currentLocale} - current={current} - en={allLocales.en} - > - <LegacyI18nProvider> - <div style={styles}>{story()}</div> - </LegacyI18nProvider> - </I18nProvider> + <Router history={history}> + <MetaMetricsProviderStorybook> + <I18nProvider + currentLocale={currentLocale} + current={current} + en={allLocales.en} + > + <LegacyI18nProvider> + <div style={styles}>{story()}</div> + </LegacyI18nProvider> + </I18nProvider> + </MetaMetricsProviderStorybook> + </Router> </Provider> ); }; diff --git a/.storybook/test-data.js b/.storybook/test-data.js index ef9e15e64..32c24690f 100644 --- a/.storybook/test-data.js +++ b/.storybook/test-data.js @@ -1,217 +1,782 @@ import { TRANSACTION_STATUSES } from '../shared/constants/transaction'; const state = { - metamask: { - isInitialized: true, - isUnlocked: true, - featureFlags: { sendHexData: true }, - identities: { - '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825': { - address: '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825', - name: 'Send Account 1', + "invalidCustomNetwork": { + "state": "CLOSED", + "networkName": "" + }, + "unconnectedAccount": { + "state": "CLOSED" + }, + "activeTab": {}, + "metamask": { + "isInitialized": true, + "isUnlocked": true, + "isAccountMenuOpen": false, + "rpcUrl": "https://rawtestrpc.metamask.io/", + "identities": { + "0x983211ce699ea5ab57cc528086154b6db1ad8e55": { + "name": "Account 1", + "address": "0x983211ce699ea5ab57cc528086154b6db1ad8e55" }, - '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb': { - address: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb', - name: 'Send Account 2', - }, - '0x2f8d4a878cfa04a6e60d46362f5644deab66572d': { - address: '0x2f8d4a878cfa04a6e60d46362f5644deab66572d', - name: 'Send Account 3', - }, - '0xd85a4b6a394794842887b8284293d69163007bbb': { - address: '0xd85a4b6a394794842887b8284293d69163007bbb', - name: 'Send Account 4', + "0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e": { + "name": "Account 2", + "address": "0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e" }, + "0x9d0ba4ddac06032527b140912ec808ab9451b788": { + "name": "Account 3", + "address": "0x9d0ba4ddac06032527b140912ec808ab9451b788" + } }, - cachedBalances: {}, - currentBlockGasLimit: '0x4c1878', - currentCurrency: 'USD', - conversionRate: 1200.88200327, - conversionDate: 1489013762, - nativeCurrency: 'ETH', - frequentRpcList: [], - network: '3', - provider: { - type: 'ropsten', - chainId: '0x3', - }, - accounts: { - '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825': { - code: '0x', - balance: '0x47c9d71831c76efe', - nonce: '0x1b', - address: '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825', - }, - '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb': { - code: '0x', - balance: '0x37452b1315889f80', - nonce: '0xa', - address: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb', - }, - '0x2f8d4a878cfa04a6e60d46362f5644deab66572d': { - code: '0x', - balance: '0x30c9d71831c76efe', - nonce: '0x1c', - address: '0x2f8d4a878cfa04a6e60d46362f5644deab66572d', - }, - '0xd85a4b6a394794842887b8284293d69163007bbb': { - code: '0x', - balance: '0x0', - nonce: '0x0', - address: '0xd85a4b6a394794842887b8284293d69163007bbb', - }, - }, - addressBook: { - '0x3': { - '0x06195827297c7a80a443b6894d3bdb8824b43896': { - address: '0x06195827297c7a80a443b6894d3bdb8824b43896', - name: 'Address Book Account 1', - chainId: '0x3', + "unapprovedTxs": { + "7786962153682822": { + "id": 7786962153682822, + "time": 1620710815484, + "status": "unapproved", + "metamaskNetworkId": "3", + "chainId": "0x3", + "loadingDefaults": false, + "txParams": { + "from": "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4", + "to": "0xad6d458402f60fd3bd25163575031acdce07538d", + "value": "0x0", + "data": "0xa9059cbb000000000000000000000000b19ac54efa18cc3a14a5b821bfec73d284bf0c5e0000000000000000000000000000000000000000000000003782dace9d900000", + "gas": "0xcb28", + "gasPrice": "0x77359400" }, - }, + "type": "standard", + "origin": "metamask", + "transactionCategory": "transfer", + "history": [ + { + "id": 7786962153682822, + "time": 1620710815484, + "status": "unapproved", + "metamaskNetworkId": "3", + "chainId": "0x3", + "loadingDefaults": true, + "txParams": { + "from": "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4", + "to": "0xad6d458402f60fd3bd25163575031acdce07538d", + "value": "0x0", + "data": "0xa9059cbb000000000000000000000000b19ac54efa18cc3a14a5b821bfec73d284bf0c5e0000000000000000000000000000000000000000000000003782dace9d900000", + "gas": "0xcb28", + "gasPrice": "0x77359400" + }, + "type": "standard", + "origin": "metamask", + "transactionCategory": "transfer" + }, + [ + { + "op": "replace", + "path": "/loadingDefaults", + "value": false, + "note": "Added new unapproved transaction.", + "timestamp": 1620710815497 + } + ] + ] + } }, - tokens: [ + "frequentRpcList": [], + "addressBook": { + "undefined": { + "0": { + "address": "0x39a4e4Af7cCB654dB9500F258c64781c8FbD39F0", + "name": "", + "isEns": false + } + } + }, + "contractExchangeRates": { + "0xad6d458402f60fd3bd25163575031acdce07538d": 0 + }, + "tokens": [ { - address: '0x1a195821297c7a80a433b6894d3bdb8824b43896', - decimals: 18, - symbol: 'ABC', - }, - { - address: '0x8d6b81208414189a58339873ab429b6c47ab92d3', - decimals: 4, - symbol: 'DEF', - }, - { - address: '0xa42084c8d1d9a2198631988579bb36b48433a72b', - decimals: 18, - symbol: 'GHI', - }, + "address": "0xad6d458402f60fd3bd25163575031acdce07538d", + "symbol": "DAI", + "decimals": 18 + } ], - transactions: {}, - currentNetworkTxList: [ - { - id: 'mockTokenTx1', - txParams: { - to: '0x8d6b81208414189a58339873ab429b6c47ab92d3', - from: '0xd85a4b6a394794842887b8284293d69163007bbb', - }, - time: 1700000000000, - }, - { - id: 'mockTokenTx2', - txParams: { - to: '0xafaketokenaddress', - from: '0xd85a4b6a394794842887b8284293d69163007bbb', - }, - time: 1600000000000, - }, - { - id: 'mockTokenTx3', - txParams: { - to: '0x8d6b81208414189a58339873ab429b6c47ab92d3', - from: '0xd85a4b6a394794842887b8284293d69163007bbb', - }, - time: 1500000000000, - }, - { - id: 'mockEthTx1', - txParams: { - to: '0xd85a4b6a394794842887b8284293d69163007bbb', - from: '0xd85a4b6a394794842887b8284293d69163007bbb', - }, - time: 1400000000000, - }, - ], - unapprovedMsgs: { - '0xabc': { id: 'unapprovedMessage1', time: 1650000000000 }, - '0xdef': { id: 'unapprovedMessage2', time: 1550000000000 }, - '0xghi': { id: 'unapprovedMessage3', time: 1450000000000 }, + "pendingTokens": {}, + "customNonceValue": "", + "send": { + "gasLimit": "0xcb28", + "gasPrice": null, + "gasTotal": null, + "tokenBalance": "8.7a73149c048545a3fe58", + "from": "", + "to": "0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e", + "amount": "3782dace9d900000", + "memo": "", + "errors": {}, + "maxModeOn": false, + "editingTransactionId": null, + "toNickname": "Account 2", + "ensResolution": null, + "ensResolutionError": "", + "token": { + "address": "0xad6d458402f60fd3bd25163575031acdce07538d", + "symbol": "DAI", + "decimals": 18 + } }, - unapprovedMsgCount: 0, - unapprovedPersonalMsgs: {}, - unapprovedPersonalMsgCount: 0, - unapprovedDecryptMsgs: {}, - unapprovedDecryptMsgCount: 0, - unapprovedEncryptionPublicKeyMsgs: {}, - unapprovedEncryptionPublicKeyMsgCount: 0, - keyringTypes: ['Simple Key Pair', 'HD Key Tree'], - keyrings: [ + "useBlockie": false, + "featureFlags": {}, + "welcomeScreenSeen": false, + "currentLocale": "en", + "preferences": { + "useNativeCurrencyAsPrimaryCurrency": true + }, + "firstTimeFlowType": "create", + "completedOnboarding": true, + "knownMethodData": { + "0x60806040": { + "name": "Approve Tokens" + }, + "0x095ea7b3": { + "name": "Approve Tokens" + } + }, + "participateInMetaMetrics": true, + "metaMetricsSendCount": 2, + "nextNonce": 71, + "connectedStatusPopoverHasBeenShown": true, + "swapsWelcomeMessageHasBeenShown": true, + "defaultHomeActiveTabName": "Assets", + "provider": { + "type": "ropsten", + "ticker": "ETH", + "nickname": "", + "rpcUrl": "", + "chainId": "0x3" + }, + "previousProviderStore": { + "type": "ropsten", + "ticker": "ETH", + "nickname": "", + "rpcUrl": "", + "chainId": "0x3" + }, + "network": "3", + "accounts": { + "0x983211ce699ea5ab57cc528086154b6db1ad8e55": { + "address": "0x983211ce699ea5ab57cc528086154b6db1ad8e55", + "balance": "0x176e5b6f173ebe66" + }, + "0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e": { + "address": "0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e", + "balance": "0x2d3142f5000" + }, + "0x9d0ba4ddac06032527b140912ec808ab9451b788": { + "address": "0x9d0ba4ddac06032527b140912ec808ab9451b788", + "balance": "0x15f6f0b9d4f8d000" + } + }, + "currentBlockGasLimit": "0x793af4", + "currentNetworkTxList": [ + + ], + "cachedBalances": { + "1": { + "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4": "0x0", + "0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e": "0xcaf5317161f400", + "0x9d0ba4ddac06032527b140912ec808ab9451b788": "0x0" + }, + "3": { + "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4": "0x18d289d450bace66", + "0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e": "0x2d3142f5000", + "0x9d0ba4ddac06032527b140912ec808ab9451b788": "0x15f6f0b9d4f8d000" + }, + "0x3": { + "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4": "0x176e5b6f173ebe66", + "0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e": "0x2d3142f5000", + "0x9d0ba4ddac06032527b140912ec808ab9451b788": "0x15f6f0b9d4f8d000" + } + }, + "unapprovedMsgs": {}, + "unapprovedMsgCount": 0, + "unapprovedPersonalMsgs": {}, + "unapprovedPersonalMsgCount": 0, + "unapprovedDecryptMsgs": {}, + "unapprovedDecryptMsgCount": 0, + "unapprovedEncryptionPublicKeyMsgs": {}, + "unapprovedEncryptionPublicKeyMsgCount": 0, + "unapprovedTypedMessages": {}, + "unapprovedTypedMessagesCount": 0, + "keyringTypes": [ + "Simple Key Pair", + "HD Key Tree", + "Trezor Hardware", + "Ledger Hardware" + ], + "keyrings": [ { - type: 'HD Key Tree', - accounts: [ - 'fdea65c8e26263f6d9a1b5de9555d2931a33b825', - 'c5b8dbac4c1d3f152cdeb400e2313f309c410acb', - '2f8d4a878cfa04a6e60d46362f5644deab66572d', + "type": "HD Key Tree", + "accounts": [ + "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4", + "0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e", + "0x9d0ba4ddac06032527b140912ec808ab9451b788" + ] + } + ], + "frequentRpcListDetail": [ + { + "rpcUrl": "http://localhost:8545", + "chainId": "0x539", + "ticker": "ETH", + "nickname": "Localhost 8545", + "rpcPrefs": {} + } + ], + "accountTokens": { + "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4": { + "0x1": [ + { + "address": "0x6b175474e89094c44da98b954eedeac495271d0f", + "symbol": "DAI", + "decimals": 18 + }, + { + "address": "0x0d8775f648430679a709e98d2b0cb6250d2887ef", + "symbol": "BAT", + "decimals": 18 + } ], + "0x3": [ + { + "address": "0xad6d458402f60fd3bd25163575031acdce07538d", + "symbol": "DAI", + "decimals": 18 + } + ] + }, + "0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e": {}, + "0x9d0ba4ddac06032527b140912ec808ab9451b788": {} + }, + "accountHiddenTokens": { + "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4": { + "0x3": [] + } + }, + "assetImages": { + "0xad6d458402f60fd3bd25163575031acdce07538d": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xaD6D458402F60fD3Bd25163575031ACDce07538D/logo.png" + }, + "hiddenTokens": [], + "suggestedTokens": {}, + "useNonceField": false, + "usePhishDetect": true, + "lostIdentities": {}, + "forgottenPassword": false, + "ipfsGateway": "dweb.link", + "infuraBlocked": false, + "migratedPrivacyMode": false, + "selectedAddress": "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4", + "metaMetricsId": "0xc2377d11fec1c3b7dd88c4854240ee5e3ed0d9f63b00456d98d80320337b827f", + "conversionDate": 1620710825.03, + "conversionRate": 3910.28, + "currentCurrency": "usd", + "nativeCurrency": "ETH", + "usdConversionRate": 3910.28, + "ticker": "ETH", + "alertEnabledness": { + "unconnectedAccount": true, + "web3ShimUsage": true + }, + "unconnectedAccountAlertShownOrigins": {}, + "web3ShimUsageOrigins": {}, + "seedPhraseBackedUp": null, + "onboardingTabs": {}, + "incomingTransactions": { + "0x2de9256a7c604586f7ecfd87ae9509851e217f588f9f85feed793c54ed2ce0aa": { + "blockNumber": "8888976", + "id": 4678200543090532, + "metamaskNetworkId": "1", + "status": "confirmed", + "time": 1573114896000, + "txParams": { + "from": "0x3f1b52850109023775d238c7ed5d5e7161041fd1", + "gas": "0x5208", + "gasPrice": "0x124101100", + "nonce": "0x35", + "to": "0x045c619e4d29bba3b92769508831b681b83d6a96", + "value": "0xbca9bce4d98ca3" + }, + "hash": "0x2de9256a7c604586f7ecfd87ae9509851e217f588f9f85feed793c54ed2ce0aa", + "transactionCategory": "incoming" + }, + "0x320a1fd769373578f78570e5d8f56e89bc7bce9657bb5f4c12d8fe790d471bfd": { + "blockNumber": "9453174", + "id": 4678200543090535, + "metamaskNetworkId": "1", + "status": "confirmed", + "time": 1581312411000, + "txParams": { + "from": "0xa17bd07d6d38cb9e37b29f7659a4b1047701e969", + "gas": "0xc350", + "gasPrice": "0x1a13b8600", + "nonce": "0x0", + "to": "0x045c619e4d29bba3b92769508831b681b83d6a96", + "value": "0xcdb08ab4254000" + }, + "hash": "0x320a1fd769373578f78570e5d8f56e89bc7bce9657bb5f4c12d8fe790d471bfd", + "transactionCategory": "incoming" + }, + "0x8add6c1ea089a8de9b15fa2056b1875360f17916755c88ace9e5092b7a4b1239": { + "blockNumber": "10892417", + "id": 4678200543090542, + "metamaskNetworkId": "1", + "status": "confirmed", + "time": 1600515224000, + "txParams": { + "from": "0x0681d8db095565fe8a346fa0277bffde9c0edbbf", + "gas": "0x5208", + "gasPrice": "0x1d1a94a200", + "nonce": "0x2bb8a5", + "to": "0x045c619e4d29bba3b92769508831b681b83d6a96", + "value": "0xe6ed27d6668000" + }, + "hash": "0x8add6c1ea089a8de9b15fa2056b1875360f17916755c88ace9e5092b7a4b1239", + "transactionCategory": "incoming" + }, + "0x50be62ab1cabd03ff104c602c11fdef7a50f3d73c55006d5583ba97950ab1144": { + "blockNumber": "10902987", + "id": 4678200543090545, + "metamaskNetworkId": "1", + "status": "confirmed", + "time": 1600654021000, + "txParams": { + "from": "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4", + "gas": "0x5208", + "gasPrice": "0x147d357000", + "nonce": "0xf", + "to": "0x045c619e4d29bba3b92769508831b681b83d6a96", + "value": "0x63eb89da4ed00000" + }, + "hash": "0x50be62ab1cabd03ff104c602c11fdef7a50f3d73c55006d5583ba97950ab1144", + "transactionCategory": "incoming" + } + }, + "incomingTxLastFetchedBlocksByNetwork": { + "ropsten": 8872820, + "rinkeby": null, + "kovan": null, + "goerli": null, + "mainnet": 10902989 + }, + "permissionsRequests": [], + "permissionsDescriptions": {}, + "domains": { + "https://app.uniswap.org": { + "permissions": [ + { + "@context": [ + "https://github.com/MetaMask/rpc-cap" + ], + "invoker": "https://app.uniswap.org", + "parentCapability": "eth_accounts", + "id": "a7342e4b-beae-4525-a36c-c0635fd03359", + "date": 1620710693178, + "caveats": [ + { + "type": "limitResponseLength", + "value": 1, + "name": "primaryAccountOnly" + }, + { + "type": "filterResponse", + "value": [ + "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4" + ], + "name": "exposedAccounts" + } + ] + } + ] + } + }, + "permissionsLog": [ + { + "id": 522690215, + "method": "eth_accounts", + "methodType": "restricted", + "origin": "https://metamask.io", + "request": { + "method": "eth_accounts", + "params": [], + "jsonrpc": "2.0", + "id": 522690215, + "origin": "https://metamask.io", + "tabId": 5 + }, + "requestTime": 1602643170686, + "response": { + "id": 522690215, + "jsonrpc": "2.0", + "result": [] + }, + "responseTime": 1602643170688, + "success": true }, { - type: 'Simple Key Pair', - accounts: ['0xd85a4b6a394794842887b8284293d69163007bbb'], - }, - ], - selectedAddress: '0xd85a4b6a394794842887b8284293d69163007bbb', - send: { - gasLimit: '0xFFFF', - gasPrice: '0xaa', - gasTotal: '0xb451dc41b578', - tokenBalance: 3434, - from: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb', - to: '0x987fedabc', - amount: '0x080', - memo: '', - errors: { - someError: null, - }, - maxModeOn: false, - editingTransactionId: 97531, - }, - unapprovedTxs: { - 4768706228115573: { - id: 4768706228115573, - time: 1487363153561, - status: TRANSACTION_STATUSES.UNAPPROVED, - gasMultiplier: 1, - metamaskNetworkId: '3', - txParams: { - from: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb', - to: '0x18a3462427bcc9133bb46e88bcbe39cd7ef0e761', - value: '0xde0b6b3a7640000', - metamaskId: 4768706228115573, - metamaskNetworkId: '3', - gas: '0x5209', + "id": 1620464600, + "method": "eth_accounts", + "methodType": "restricted", + "origin": "https://widget.getacute.io", + "request": { + "method": "eth_accounts", + "params": [], + "jsonrpc": "2.0", + "id": 1620464600, + "origin": "https://widget.getacute.io", + "tabId": 5 }, - txFee: '17e0186e60800', - txValue: 'de0b6b3a7640000', - maxCost: 'de234b52e4a0800', - gasPrice: '4a817c800', + "requestTime": 1602643172935, + "response": { + "id": 1620464600, + "jsonrpc": "2.0", + "result": [] + }, + "responseTime": 1602643172935, + "success": true }, + { + "id": 4279100021, + "method": "eth_accounts", + "methodType": "restricted", + "origin": "https://app.uniswap.org", + "request": { + "method": "eth_accounts", + "jsonrpc": "2.0", + "id": 4279100021, + "origin": "https://app.uniswap.org", + "tabId": 5 + }, + "requestTime": 1620710669962, + "response": { + "id": 4279100021, + "jsonrpc": "2.0", + "result": [] + }, + "responseTime": 1620710669963, + "success": true + }, + { + "id": 4279100022, + "method": "eth_requestAccounts", + "methodType": "restricted", + "origin": "https://app.uniswap.org", + "request": { + "method": "eth_requestAccounts", + "jsonrpc": "2.0", + "id": 4279100022, + "origin": "https://app.uniswap.org", + "tabId": 5 + }, + "requestTime": 1620710686872, + "response": { + "id": 4279100022, + "jsonrpc": "2.0", + "result": [ + "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4" + ] + }, + "responseTime": 1620710693187, + "success": true + }, + { + "id": 4279100023, + "method": "eth_requestAccounts", + "methodType": "restricted", + "origin": "https://app.uniswap.org", + "request": { + "method": "eth_requestAccounts", + "jsonrpc": "2.0", + "id": 4279100023, + "origin": "https://app.uniswap.org", + "tabId": 5 + }, + "requestTime": 1620710693204, + "response": { + "id": 4279100023, + "jsonrpc": "2.0", + "result": [ + "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4" + ] + }, + "responseTime": 1620710693213, + "success": true + }, + { + "id": 4279100034, + "method": "eth_accounts", + "methodType": "restricted", + "origin": "https://app.uniswap.org", + "request": { + "method": "eth_accounts", + "params": [], + "jsonrpc": "2.0", + "id": 4279100034, + "origin": "https://app.uniswap.org", + "tabId": 5 + }, + "requestTime": 1620710712072, + "response": { + "id": 4279100034, + "jsonrpc": "2.0", + "result": [ + "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4" + ] + }, + "responseTime": 1620710712075, + "success": true + } + ], + "permissionsHistory": { + "https://app.uniswap.org": { + "eth_accounts": { + "lastApproved": 1620710693213, + "accounts": { + "0x64a845a5b02460acf8a3d84503b0d68d028b4bb4": 1620710693213 + } + } + } }, - currentLocale: 'en', + "domainMetadata": { + "https://metamask.github.io": { + "name": "E2E Test Dapp", + "icon": "https://metamask.github.io/test-dapp/metamask-fox.svg", + "lastUpdated": 1620723443380, + "host": "metamask.github.io" + } + }, + "threeBoxSyncingAllowed": false, + "showRestorePrompt": true, + "threeBoxLastUpdated": 0, + "threeBoxAddress": null, + "threeBoxSynced": false, + "threeBoxDisabled": false, + "swapsState": { + "quotes": {}, + "fetchParams": null, + "tokens": null, + "tradeTxId": null, + "approveTxId": null, + "quotesLastFetched": null, + "customMaxGas": "", + "customGasPrice": null, + "selectedAggId": null, + "customApproveTxData": "", + "errorKey": "", + "topAggId": null, + "routeState": "", + "swapsFeatureIsLive": false, + "swapsQuoteRefreshTime": 60000 + }, + "ensResolutionsByAddress": {}, + "pendingApprovals": {}, + "pendingApprovalCount": 0 }, - appState: { - menuOpen: false, - currentView: { - name: 'accountDetail', - detailView: null, - context: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + "appState": { + "shouldClose": false, + "menuOpen": false, + "modal": { + "open": false, + "modalState": { + "name": null, + "props": {} + }, + "previousModalState": { + "name": null + } }, - accountDetail: { - subview: 'transactions', + "sidebar": { + "isOpen": false, + "transitionName": "", + "type": "", + "props": {} }, - modal: { - modalState: {}, - previousModalState: {}, + "alertOpen": false, + "alertMessage": null, + "qrCodeData": null, + "networkDropdownOpen": false, + "accountDetail": { + "subview": "transactions" }, - isLoading: false, - warning: null, - scrollToBottom: false, - forgottenPassword: null, + "isLoading": false, + "warning": null, + "buyView": {}, + "isMouseUser": true, + "gasIsLoading": false, + "defaultHdPaths": { + "trezor": "m/44'/60'/0'/0", + "ledger": "m/44'/60'/0'/0/0" + }, + "networksTabSelectedRpcUrl": "", + "networksTabIsInAddMode": false, + "loadingMethodData": false, + "show3BoxModalAfterImport": false, + "threeBoxLastUpdated": null, + "requestAccountTabs": {}, + "openMetaMaskTabs": {}, + "currentWindowTab": {} }, - send: { - fromDropdownOpen: false, - toDropdownOpen: false, - errors: { someError: null }, + "history": { + "mostRecentOverviewPage": "/" }, -}; + "send": { + "toDropdownOpen": false, + "gasButtonGroupShown": true, + "errors": {} + }, + "confirmTransaction": { + "txData": { + "id": 3111025347726181, + "time": 1620723786838, + "status": "unapproved", + "metamaskNetworkId": "3", + "chainId": "0x3", + "loadingDefaults": false, + "txParams": { + "from": "0x983211ce699ea5ab57cc528086154b6db1ad8e55", + "to": "0xad6d458402f60fd3bd25163575031acdce07538d", + "value": "0x0", + "data": "0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef40000000000000000000000000000000000000000000000000000000000011170", + "gas": "0xea60", + "gasPrice": "0x4a817c800" + }, + "type": "standard", + "origin": "https://metamask.github.io", + "transactionCategory": "approve", + "history": [ + { + "id": 3111025347726181, + "time": 1620723786838, + "status": "unapproved", + "metamaskNetworkId": "3", + "chainId": "0x3", + "loadingDefaults": true, + "txParams": { + "from": "0x983211ce699ea5ab57cc528086154b6db1ad8e55", + "to": "0xad6d458402f60fd3bd25163575031acdce07538d", + "value": "0x0", + "data": "0x095ea7b30000000000000000000000009bc5baf874d2da8d216ae9f137804184ee5afef40000000000000000000000000000000000000000000000000000000000011170", + "gas": "0xea60", + "gasPrice": "0x4a817c800" + }, + "type": "standard", + "origin": "https://metamask.github.io", + "transactionCategory": "approve" + }, + [ + { + "op": "replace", + "path": "/loadingDefaults", + "value": false, + "note": "Added new unapproved transaction.", + "timestamp": 1620723786844 + } + ] + ] + }, + "tokenData": { + "args": [ + "0x9bc5baF874d2DA8D216aE9f137804184EE5AfEF4", + { + "type": "BigNumber", + "hex": "0x011170" + } + ], + "functionFragment": { + "type": "function", + "name": "approve", + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address", + "indexed": null, + "components": null, + "arrayLength": null, + "arrayChildren": null, + "baseType": "address", + "_isParamType": true + }, + { + "name": "_value", + "type": "uint256", + "indexed": null, + "components": null, + "arrayLength": null, + "arrayChildren": null, + "baseType": "uint256", + "_isParamType": true + } + ], + "outputs": [ + { + "name": "success", + "type": "bool", + "indexed": null, + "components": null, + "arrayLength": null, + "arrayChildren": null, + "baseType": "bool", + "_isParamType": true + } + ], + "payable": false, + "stateMutability": "nonpayable", + "gas": null, + "_isFragment": true + }, + "name": "approve", + "signature": "approve(address,uint256)", + "sighash": "0x095ea7b3", + "value": { + "type": "BigNumber", + "hex": "0x00" + } + }, + "fiatTransactionAmount": "0", + "fiatTransactionFee": "4.72", + "fiatTransactionTotal": "4.72", + "ethTransactionAmount": "0", + "ethTransactionFee": "0.0012", + "ethTransactionTotal": "0.0012", + "hexTransactionAmount": "0x0", + "hexTransactionFee": "0x44364c5bb0000", + "hexTransactionTotal": "0x44364c5bb0000", + "nonce": "" + }, + "swaps": { + "aggregatorMetadata": null, + "approveTxId": null, + "balanceError": false, + "fetchingQuotes": false, + "fromToken": null, + "quotesFetchStartTime": null, + "topAssets": {}, + "toToken": null, + "customGas": { + "price": null, + "limit": null, + "loading": "INITIAL", + "priceEstimates": {}, + "fallBackPrice": null + } + }, + "gas": { + "customData": { + "price": null, + "limit": "0xcb28" + }, + "basicEstimates": { + "average": 2 + }, + "basicEstimateIsLoading": false + } +} export default state; diff --git a/CHANGELOG.md b/CHANGELOG.md index 293984443..68b579118 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ## [9.5.9] +## [9.5.8] +### Added +- Re-added "Add Ledger Live Support" ([#10293](https://github.com/MetaMask/metamask-extension/pull/10293)), which was reverted in the previous version ### Fixed - [#11225](https://github.com/MetaMask/metamask-extension/pull/11225) - Fix persistent display of chrome ledger What's New popup message @@ -36,234 +39,235 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [9.5.3] ### Fixed -- [#11103](https://github.com/MetaMask/metamask-extension/pull/11103): Fixes bug that made MetaMask unusable and displayed 'Minified React error #130' on certain networks and accounts -- [#11015](https://github.com/MetaMask/metamask-extension/pull/11015): Prevent big number error when attempting to view transaction list +- Fixes bug that made MetaMask unusable and displayed 'Minified React error #130' on certain networks and accounts ([#11103](https://github.com/MetaMask/metamask-extension/pull/11103)) +- Prevent big number error when attempting to view transaction list ([#11015](https://github.com/MetaMask/metamask-extension/pull/11015)) ## [9.5.2] ### Fixed -- [#11071](https://github.com/MetaMask/metamask-extension/pull/11071): Fixing address entry error when sending a transaction on a custom network +- Fixing address entry error when sending a transaction on a custom network ([#11071](https://github.com/MetaMask/metamask-extension/pull/11071)) ## [9.5.1] ### Fixed -- [#11048](https://github.com/MetaMask/metamask-extension/pull/11048): Fixed icon on approval screen -- [#11036](https://github.com/MetaMask/metamask-extension/pull/11036): Fixed broken app state for some users with Chinese, Portugese or Spanish browser language settings. +- Fixed icon on approval screen ([#11048](https://github.com/MetaMask/metamask-extension/pull/11048)) +- Fixed broken app state for some users with Chinese, Portugese or Spanish browser language settings. ([#11036](https://github.com/MetaMask/metamask-extension/pull/11036)) ## [9.5.0] - 2021-04-28 ### Added -- [#10583](https://github.com/MetaMask/metamask-extension/pull/10583): Adding popup display to show new MetaMask notifications -- [#10938](https://github.com/MetaMask/metamask-extension/pull/10938): Add menu with "View on Etherscan" and "Account details" links to ETH asset page -- [#10932](https://github.com/MetaMask/metamask-extension/pull/10932): Add view account details menu item to token page menu -- [#10895](https://github.com/MetaMask/metamask-extension/pull/10895): Adding new links to contact MetaMask support -- [#10595](https://github.com/MetaMask/metamask-extension/pull/10595): Adding option to set Custom Nonce to Confirm Approve Page -- [#10616](https://github.com/MetaMask/metamask-extension/pull/10616): add trezor HD path for ledger wallets +- Adding popup display to show new MetaMask notifications ([#10583](https://github.com/MetaMask/metamask-extension/pull/10583)) +- Add menu with "View on Etherscan" and "Account details" links to ETH asset page ([#10938](https://github.com/MetaMask/metamask-extension/pull/10938)) +- Add view account details menu item to token page menu ([#10932](https://github.com/MetaMask/metamask-extension/pull/10932)) +- Adding new links to contact MetaMask support ([#10895](https://github.com/MetaMask/metamask-extension/pull/10895)) +- Adding option to set Custom Nonce to Confirm Approve Page ([#10595](https://github.com/MetaMask/metamask-extension/pull/10595)) +- Adding recovery phrase video to onboarding process ([#10717](https://github.com/MetaMask/metamask-extension/pull/10717)) +- add trezor HD path for ledger wallets ([#10616](https://github.com/MetaMask/metamask-extension/pull/10616)) ### Changed -- [#10939](https://github.com/MetaMask/metamask-extension/pull/10939): Use custom token icons in the send flow token dropdown -- [#10680](https://github.com/MetaMask/metamask-extension/pull/10680): Remove "My Wallet Account" section in Settings > Contact -- [#10912](https://github.com/MetaMask/metamask-extension/pull/10912): Harden contract address validation for token swaps -- [#10882](https://github.com/MetaMask/metamask-extension/pull/10882): Show the custom network name in swaps network fee tooltip -- [#10859](https://github.com/MetaMask/metamask-extension/pull/10859): Only check whether the swaps feature is live after entering the feature -- [#10871](https://github.com/MetaMask/metamask-extension/pull/10871): Update swaps metadata every 5 minutes as opposed to an hour -- [#10842](https://github.com/MetaMask/metamask-extension/pull/10842): Increase default slippage from 2% to 3% in swaps and show Advanced Options by default -- [#10593](https://github.com/MetaMask/metamask-extension/pull/10593): Prevent tokens without addresses from being added to token list -- [#10746](https://github.com/MetaMask/metamask-extension/pull/10746): Add New Zealand Dollar to currency options -- [#10670](https://github.com/MetaMask/metamask-extension/pull/10670): Allow 11 characters in symbol for custom RPCs -- [#10702](https://github.com/MetaMask/metamask-extension/pull/10702): Hide the suggested token pane when not on Mainnet or test network -- [#10700](https://github.com/MetaMask/metamask-extension/pull/10700): Prevents autocomplete text from displaying in the Add Token input -- [#10704](https://github.com/MetaMask/metamask-extension/pull/10704): Removing hard references to 12 word seed phrases in copy -- [#10703](https://github.com/MetaMask/metamask-extension/pull/10703): Add MetaMask to list of BIP44 HD path examples -- [#10651](https://github.com/MetaMask/metamask-extension/pull/10651): Change 'Send ETH' title to 'Send' in the send flow -- [#10674](https://github.com/MetaMask/metamask-extension/pull/10674): Don't render faucet row in deposit modal for custom chains +- Use custom token icons in the send flow token dropdown ([#10939](https://github.com/MetaMask/metamask-extension/pull/10939)) +- Remove "My Wallet Account" section in Settings > Contact ([#10680](https://github.com/MetaMask/metamask-extension/pull/10680)) +- Harden contract address validation for token swaps ([#10912](https://github.com/MetaMask/metamask-extension/pull/10912)) +- Show the custom network name in swaps network fee tooltip ([#10882](https://github.com/MetaMask/metamask-extension/pull/10882)) +- Only check whether the swaps feature is live after entering the feature ([#10859](https://github.com/MetaMask/metamask-extension/pull/10859)) +- Update swaps metadata every 5 minutes as opposed to an hour ([#10871](https://github.com/MetaMask/metamask-extension/pull/10871)) +- Increase default slippage from 2% to 3% in swaps and show Advanced Options by default ([#10842](https://github.com/MetaMask/metamask-extension/pull/10842)) +- Prevent tokens without addresses from being added to token list ([#10593](https://github.com/MetaMask/metamask-extension/pull/10593)) +- Add New Zealand Dollar to currency options ([#10746](https://github.com/MetaMask/metamask-extension/pull/10746)) +- Allow 11 characters in symbol for custom RPCs ([#10670](https://github.com/MetaMask/metamask-extension/pull/10670)) +- Hide the suggested token pane when not on Mainnet or test network ([#10702](https://github.com/MetaMask/metamask-extension/pull/10702)) +- Prevents autocomplete text from displaying in the Add Token input ([#10700](https://github.com/MetaMask/metamask-extension/pull/10700)) +- Removing hard references to 12 word seed phrases in copy ([#10704](https://github.com/MetaMask/metamask-extension/pull/10704)) +- Add MetaMask to list of BIP44 HD path examples ([#10703](https://github.com/MetaMask/metamask-extension/pull/10703)) +- Change 'Send ETH' title to 'Send' in the send flow ([#10651](https://github.com/MetaMask/metamask-extension/pull/10651)) +- Don't render faucet row in deposit modal for custom chains ([#10674](https://github.com/MetaMask/metamask-extension/pull/10674)) ### Fixed -- [#10935](https://github.com/MetaMask/metamask-extension/pull/10935): Prevent overflow of hostname on confirmation page -- [#10923](https://github.com/MetaMask/metamask-extension/pull/10923): Fixing ENS input entry in send flow -- [#10723](https://github.com/MetaMask/metamask-extension/pull/10723): Fix mismatchedChain typo in custom network approval screen -- [#10695](https://github.com/MetaMask/metamask-extension/pull/10695): Excluding sourcemaps comment in production builds -- [#10643](https://github.com/MetaMask/metamask-extension/pull/10643): Prevent network dropdown label highlighting -- [#10644](https://github.com/MetaMask/metamask-extension/pull/10644): Ensure swaps detail height doesn't create jump in vertical height -- [#10642](https://github.com/MetaMask/metamask-extension/pull/10642): Position the 3dot menu in the same spot on asset screen and home screen -- [#10594](https://github.com/MetaMask/metamask-extension/pull/10594): Ensure MetaMask works correctly when on a custom network that shares a chain id with a default Infura network -- [#10579](https://github.com/MetaMask/metamask-extension/pull/10579): Fixed bug that prevented speeding up cancelled transactions -- [#10630](https://github.com/MetaMask/metamask-extension/pull/10630): Fixes hidden token bug when zero balance preference is on -- [#10628](https://github.com/MetaMask/metamask-extension/pull/10628): Removing double click bug from delete custom network modal +- Prevent overflow of hostname on confirmation page ([#10935](https://github.com/MetaMask/metamask-extension/pull/10935)) +- Fixing ENS input entry in send flow ([#10923](https://github.com/MetaMask/metamask-extension/pull/10923)) +- Fix mismatchedChain typo in custom network approval screen ([#10723](https://github.com/MetaMask/metamask-extension/pull/10723)) +- Excluding sourcemaps comment in production builds ([#10695](https://github.com/MetaMask/metamask-extension/pull/10695)) +- Prevent network dropdown label highlighting ([#10643](https://github.com/MetaMask/metamask-extension/pull/10643)) +- Ensure swaps detail height doesn't create jump in vertical height ([#10644](https://github.com/MetaMask/metamask-extension/pull/10644)) +- Position the 3dot menu in the same spot on asset screen and home screen ([#10642](https://github.com/MetaMask/metamask-extension/pull/10642)) +- Ensure MetaMask works correctly when on a custom network that shares a chain id with a default Infura network ([#10594](https://github.com/MetaMask/metamask-extension/pull/10594)) +- Fixed bug that prevented speeding up cancelled transactions ([#10579](https://github.com/MetaMask/metamask-extension/pull/10579)) +- Fixes hidden token bug when zero balance preference is on ([#10630](https://github.com/MetaMask/metamask-extension/pull/10630)) +- Removing double click bug from delete custom network modal ([#10628](https://github.com/MetaMask/metamask-extension/pull/10628)) ## [9.4.0] - 2021-04-15 ### Added -- [#10883](https://github.com/MetaMask/metamask-extension/pull/10883): Notify users when MetaMask is unable to connect to the blockchain host +- Notify users when MetaMask is unable to connect to the blockchain host ([#10883](https://github.com/MetaMask/metamask-extension/pull/10883)) ## [9.3.0] - 2021-04-02 ### Added -- [#10721](https://github.com/MetaMask/metamask-extension/pull/10721): Swaps support for the Binance network -- [#10658](https://github.com/MetaMask/metamask-extension/pull/10658): Swaps support for forked Mainnet on localhost +- Swaps support for the Binance network ([#10721](https://github.com/MetaMask/metamask-extension/pull/10721)) +- Swaps support for forked Mainnet on localhost ([#10658](https://github.com/MetaMask/metamask-extension/pull/10658)) ### Fixed -- [#10777](https://github.com/MetaMask/metamask-extension/pull/10777): Display BNB token image for default currency on BSC network home screen -- [#10650](https://github.com/MetaMask/metamask-extension/pull/10650): Fix: ETH now only appears once in the swaps "to" and "from" dropdowns. +- Display BNB token image for default currency on BSC network home screen ([#10777](https://github.com/MetaMask/metamask-extension/pull/10777)) +- Fix: ETH now only appears once in the swaps "to" and "from" dropdowns. ([#10650](https://github.com/MetaMask/metamask-extension/pull/10650)) ## [9.2.1] - 2021-03-26 ### Fixed -- [#10692](https://github.com/MetaMask/metamask-extension/pull/10692): Prevent UI crash when a 'wallet_requestPermissions" confirmation is queued behind a "wallet_addEthereumChain" confirmation -- [#10712](https://github.com/MetaMask/metamask-extension/pull/10712): Fix infinite spinner when request for token symbol fails while attempting an approve transaction +- Prevent UI crash when a 'wallet_requestPermissions" confirmation is queued behind a "wallet_addEthereumChain" confirmation ([#10692](https://github.com/MetaMask/metamask-extension/pull/10692)) +- Fix infinite spinner when request for token symbol fails while attempting an approve transaction ([#10712](https://github.com/MetaMask/metamask-extension/pull/10712)) ## [9.2.0] - 2021-03-15 ### Added -- [#10546](https://github.com/MetaMask/metamask-extension/pull/10546): Add a warning when sending a token to its own contract address -- [#10582](https://github.com/MetaMask/metamask-extension/pull/10582): Adding warnings for excessive custom gas input -- [#10505](https://github.com/MetaMask/metamask-extension/pull/10505): Add support for multiple Ledger & Trezor hardware accounts -- [#10486](https://github.com/MetaMask/metamask-extension/pull/10486): Add setting to hide zero balance tokens +- Add a warning when sending a token to its own contract address ([#10546](https://github.com/MetaMask/metamask-extension/pull/10546)) +- Adding warnings for excessive custom gas input ([#10582](https://github.com/MetaMask/metamask-extension/pull/10582)) +- Add support for multiple Ledger & Trezor hardware accounts ([#10505](https://github.com/MetaMask/metamask-extension/pull/10505)) +- Add setting to hide zero balance tokens ([#10486](https://github.com/MetaMask/metamask-extension/pull/10486)) ### Changed -- [#10563](https://github.com/MetaMask/metamask-extension/pull/10563): Update references to MetaMask support -- [#10126](https://github.com/MetaMask/metamask-extension/pull/10126): Update Italian translation +- Update references to MetaMask support ([#10563](https://github.com/MetaMask/metamask-extension/pull/10563)) +- Update Italian translation ([#10126](https://github.com/MetaMask/metamask-extension/pull/10126)) ### Fixed -- [#10591](https://github.com/MetaMask/metamask-extension/pull/10591): Fix mobile sync of ERC20 tokens -- [#10601](https://github.com/MetaMask/metamask-extension/pull/10601): Fix activity title text truncation -- [#10598](https://github.com/MetaMask/metamask-extension/pull/10598): Remove 'Ethereum' from custom RPC endpoint warning -- [#10606](https://github.com/MetaMask/metamask-extension/pull/10606): Show loading screen while fetching token data for approve screen -- [#10587](https://github.com/MetaMask/metamask-extension/pull/10587): Show correct block explorer for custom RPC endpoints for built-in networks +- Fix mobile sync of ERC20 tokens ([#10591](https://github.com/MetaMask/metamask-extension/pull/10591)) +- Fix activity title text truncation ([#10601](https://github.com/MetaMask/metamask-extension/pull/10601)) +- Remove 'Ethereum' from custom RPC endpoint warning ([#10598](https://github.com/MetaMask/metamask-extension/pull/10598)) +- Show loading screen while fetching token data for approve screen ([#10606](https://github.com/MetaMask/metamask-extension/pull/10606)) +- Show correct block explorer for custom RPC endpoints for built-in networks ([#10587](https://github.com/MetaMask/metamask-extension/pull/10587)) ## [9.1.1] - 2021-03-03 ### Fixed -- [#10560](https://github.com/MetaMask/metamask-extension/pull/10560): Fix ENS resolution related crashes when switching networks on send screen -- [#10561](https://github.com/MetaMask/metamask-extension/pull/10561): Fix crash when speeding up an attempt to cancel a transaction on custom networks +- Fix ENS resolution related crashes when switching networks on send screen ([#10560](https://github.com/MetaMask/metamask-extension/pull/10560)) +- Fix crash when speeding up an attempt to cancel a transaction on custom networks ([#10561](https://github.com/MetaMask/metamask-extension/pull/10561)) ## [9.1.0] - 2021-02-01 ### Uncategorized -- [#10265](https://github.com/MetaMask/metamask-extension/pull/10265): Update Japanese translations. -- [#9388](https://github.com/MetaMask/metamask-extension/pull/9388): Update Chinese(Simplified) translations. -- [#10270](https://github.com/MetaMask/metamask-extension/pull/10270): Update Vietnamese translations. -- [#10258](https://github.com/MetaMask/metamask-extension/pull/10258): Update Spanish and Spanish(Latin American and Carribean) translations. -- [#10268](https://github.com/MetaMask/metamask-extension/pull/10268): Update Russian translations. -- [#10269](https://github.com/MetaMask/metamask-extension/pull/10269): Update Tagalog localized messages. -- [#10448](https://github.com/MetaMask/metamask-extension/pull/10448): Fix 'imported' translation use case for Dutch. -- [#10391](https://github.com/MetaMask/metamask-extension/pull/10391): Use translated transaction category for confirmations. -- [#10357](https://github.com/MetaMask/metamask-extension/pull/10357): Cancel unapproved confirmations on network change -- [#10413](https://github.com/MetaMask/metamask-extension/pull/10413): Use native currency in asset row. -- [#10421](https://github.com/MetaMask/metamask-extension/pull/10421): Fix color indicator size on connected site indicator. -- [#10423](https://github.com/MetaMask/metamask-extension/pull/10423): Fix multiple notification window prompts. -- [#10424](https://github.com/MetaMask/metamask-extension/pull/10424): Fix icons on token options menu. -- [#10414](https://github.com/MetaMask/metamask-extension/pull/10414): Fix token fiat conversion rates when switching from certain custom networks. -- [#10453](https://github.com/MetaMask/metamask-extension/pull/10453): Disable BUY button from home screen when not on Ethereum Mainnet. -- [#10465](https://github.com/MetaMask/metamask-extension/pull/10465): Fixes gas selection check mark on the notification view. -- [#10467](https://github.com/MetaMask/metamask-extension/pull/10467): Fix confirm page header with from/to addresses in fullscreen for tx confirmations. -- [#10455](https://github.com/MetaMask/metamask-extension/pull/10455): Hide links to etherscan when no block explorer is specified for a custom network for notifications. -- [#10456](https://github.com/MetaMask/metamask-extension/pull/10456): Fix swap insufficient balance error message. -- [#10350](https://github.com/MetaMask/metamask-extension/pull/10350): Fix encypt/decrypt tx queueing. -- [#10473](https://github.com/MetaMask/metamask-extension/pull/10473): Improve autofocus in the add network form. -- [#10444](https://github.com/MetaMask/metamask-extension/pull/10444): Use eth_gasprice for tx gas price estimation on non-Mainnet networks. -- [#10477](https://github.com/MetaMask/metamask-extension/pull/10477): Fix accountsChanged event not triggering when manually connecting. -- [#10471](https://github.com/MetaMask/metamask-extension/pull/10471): Fix navigation from jumping vertically when clicking into token. -- [#9724](https://github.com/MetaMask/metamask-extension/pull/9724): Add custom network RPC method. -- [#10496](https://github.com/MetaMask/metamask-extension/pull/10496): Eliminate artificial delay in swaps loading screen after request loading is complete. -- [#10501](https://github.com/MetaMask/metamask-extension/pull/10501): Ensure that swap approve tx and swap tx always have the same gas price. -- [#10485](https://github.com/MetaMask/metamask-extension/pull/10485): Fixes signTypedData message overflow. -- [#10525](https://github.com/MetaMask/metamask-extension/pull/10525): Update swaps failure message to include a support link. -- [#10521](https://github.com/MetaMask/metamask-extension/pull/10521): Accommodate for 0 sources verifying swap token -- [#10530](https://github.com/MetaMask/metamask-extension/pull/10530): Show warnings on Add Recipient page of Send flow -- [#9187](https://github.com/MetaMask/metamask-extension/pull/9187): Warn users when an ENS name contains 'confusable' characters -- [#10507](https://github.com/MetaMask/metamask-extension/pull/10507): Fixes ENS IPFS resolution on custom networks with the chainID of 1. +- Update Japanese translations. ([#10265](https://github.com/MetaMask/metamask-extension/pull/10265)) +- Update Chinese(Simplified) translations. ([#9388](https://github.com/MetaMask/metamask-extension/pull/9388)) +- Update Vietnamese translations. ([#10270](https://github.com/MetaMask/metamask-extension/pull/10270)) +- Update Spanish and Spanish(Latin American and Carribean) translations. ([#10258](https://github.com/MetaMask/metamask-extension/pull/10258)) +- Update Russian translations. ([#10268](https://github.com/MetaMask/metamask-extension/pull/10268)) +- Update Tagalog localized messages. ([#10269](https://github.com/MetaMask/metamask-extension/pull/10269)) +- Fix 'imported' translation use case for Dutch. ([#10448](https://github.com/MetaMask/metamask-extension/pull/10448)) +- Use translated transaction category for confirmations. ([#10391](https://github.com/MetaMask/metamask-extension/pull/10391)) +- Cancel unapproved confirmations on network change ([#10357](https://github.com/MetaMask/metamask-extension/pull/10357)) +- Use native currency in asset row. ([#10413](https://github.com/MetaMask/metamask-extension/pull/10413)) +- Fix color indicator size on connected site indicator. ([#10421](https://github.com/MetaMask/metamask-extension/pull/10421)) +- Fix multiple notification window prompts. ([#10423](https://github.com/MetaMask/metamask-extension/pull/10423)) +- Fix icons on token options menu. ([#10424](https://github.com/MetaMask/metamask-extension/pull/10424)) +- Fix token fiat conversion rates when switching from certain custom networks. ([#10414](https://github.com/MetaMask/metamask-extension/pull/10414)) +- Disable BUY button from home screen when not on Ethereum Mainnet. ([#10453](https://github.com/MetaMask/metamask-extension/pull/10453)) +- Fixes gas selection check mark on the notification view. ([#10465](https://github.com/MetaMask/metamask-extension/pull/10465)) +- Fix confirm page header with from/to addresses in fullscreen for tx confirmations. ([#10467](https://github.com/MetaMask/metamask-extension/pull/10467)) +- Hide links to etherscan when no block explorer is specified for a custom network for notifications. ([#10455](https://github.com/MetaMask/metamask-extension/pull/10455)) +- Fix swap insufficient balance error message. ([#10456](https://github.com/MetaMask/metamask-extension/pull/10456)) +- Fix encypt/decrypt tx queueing. ([#10350](https://github.com/MetaMask/metamask-extension/pull/10350)) +- Improve autofocus in the add network form. ([#10473](https://github.com/MetaMask/metamask-extension/pull/10473)) +- Use eth_gasprice for tx gas price estimation on non-Mainnet networks. ([#10444](https://github.com/MetaMask/metamask-extension/pull/10444)) +- Fix accountsChanged event not triggering when manually connecting. ([#10477](https://github.com/MetaMask/metamask-extension/pull/10477)) +- Fix navigation from jumping vertically when clicking into token. ([#10471](https://github.com/MetaMask/metamask-extension/pull/10471)) +- Add custom network RPC method. ([#9724](https://github.com/MetaMask/metamask-extension/pull/9724)) +- Eliminate artificial delay in swaps loading screen after request loading is complete. ([#10496](https://github.com/MetaMask/metamask-extension/pull/10496)) +- Ensure that swap approve tx and swap tx always have the same gas price. ([#10501](https://github.com/MetaMask/metamask-extension/pull/10501)) +- Fixes signTypedData message overflow. ([#10485](https://github.com/MetaMask/metamask-extension/pull/10485)) +- Update swaps failure message to include a support link. ([#10525](https://github.com/MetaMask/metamask-extension/pull/10525)) +- Accommodate for 0 sources verifying swap token ([#10521](https://github.com/MetaMask/metamask-extension/pull/10521)) +- Show warnings on Add Recipient page of Send flow ([#10530](https://github.com/MetaMask/metamask-extension/pull/10530)) +- Warn users when an ENS name contains 'confusable' characters ([#9187](https://github.com/MetaMask/metamask-extension/pull/9187)) +- Fixes ENS IPFS resolution on custom networks with the chainID of 1. ([#10507](https://github.com/MetaMask/metamask-extension/pull/10507)) ## [9.0.5] - 2021-02-09 ### Uncategorized -- [#10278](https://github.com/MetaMask/metamask-extension/pull/10278): Allow editing transaction amount after clicking max -- [#10214](https://github.com/MetaMask/metamask-extension/pull/10214): Standardize size, shape and color of network color indicators -- [#10298](https://github.com/MetaMask/metamask-extension/pull/10298): Use network primary currency instead of always defaulting to ETH in the confirm approve screen -- [#10300](https://github.com/MetaMask/metamask-extension/pull/10300): Add origin to signature request confirmation page -- [#10296](https://github.com/MetaMask/metamask-extension/pull/10296): Add origin to transaction confirmation -- [#10266](https://github.com/MetaMask/metamask-extension/pull/10266): Update `ko` localized messages -- [#10263](https://github.com/MetaMask/metamask-extension/pull/10263): Update `id` localized messages -- [#10347](https://github.com/MetaMask/metamask-extension/pull/10347): Require click of "Continue" button to interact with swap screen if there is a price impact warning for present swap -- [#10373](https://github.com/MetaMask/metamask-extension/pull/10373): Change copy of submit button on swaps screen -- [#10346](https://github.com/MetaMask/metamask-extension/pull/10346): Swaps token sources/verification messaging update -- [#10378](https://github.com/MetaMask/metamask-extension/pull/10378): Stop showing the window.web3 in-app popup if the dapp is just using web3.currentProvider -- [#10326](https://github.com/MetaMask/metamask-extension/pull/10326): Throw error when attempting to get an encryption key via eth_getEncryptionPublicKey when connected to Ledger HW -- [#10386](https://github.com/MetaMask/metamask-extension/pull/10386): Make action buttons on message components in swaps flow accessible +- Allow editing transaction amount after clicking max ([#10278](https://github.com/MetaMask/metamask-extension/pull/10278)) +- Standardize size, shape and color of network color indicators ([#10214](https://github.com/MetaMask/metamask-extension/pull/10214)) +- Use network primary currency instead of always defaulting to ETH in the confirm approve screen ([#10298](https://github.com/MetaMask/metamask-extension/pull/10298)) +- Add origin to signature request confirmation page ([#10300](https://github.com/MetaMask/metamask-extension/pull/10300)) +- Add origin to transaction confirmation ([#10296](https://github.com/MetaMask/metamask-extension/pull/10296)) +- Update `ko` localized messages ([#10266](https://github.com/MetaMask/metamask-extension/pull/10266)) +- Update `id` localized messages ([#10263](https://github.com/MetaMask/metamask-extension/pull/10263)) +- Require click of "Continue" button to interact with swap screen if there is a price impact warning for present swap ([#10347](https://github.com/MetaMask/metamask-extension/pull/10347)) +- Change copy of submit button on swaps screen ([#10373](https://github.com/MetaMask/metamask-extension/pull/10373)) +- Swaps token sources/verification messaging update ([#10346](https://github.com/MetaMask/metamask-extension/pull/10346)) +- Stop showing the window.web3 in-app popup if the dapp is just using web3.currentProvider ([#10378](https://github.com/MetaMask/metamask-extension/pull/10378)) +- Throw error when attempting to get an encryption key via eth_getEncryptionPublicKey when connected to Ledger HW ([#10326](https://github.com/MetaMask/metamask-extension/pull/10326)) +- Make action buttons on message components in swaps flow accessible ([#10386](https://github.com/MetaMask/metamask-extension/pull/10386)) ## [9.0.4] - 2021-01-27 ### Uncategorized -- [#10285](https://github.com/MetaMask/metamask-extension/pull/10285): Update @metamask/contract-metadata from v1.21.0 to 1.22.0 -- [#10264](https://github.com/MetaMask/metamask-extension/pull/10264): Update `hi` localized messages -- [#10174](https://github.com/MetaMask/metamask-extension/pull/10174): Move fox to bottom of 'About' page -- [#10198](https://github.com/MetaMask/metamask-extension/pull/10198): Fix hardware account selection -- [#10101](https://github.com/MetaMask/metamask-extension/pull/10101): Add a timeout to all network requests -- [#10212](https://github.com/MetaMask/metamask-extension/pull/10212): Fix displayed balance of tokens with 0 decimals in swaps flow -- [#10162](https://github.com/MetaMask/metamask-extension/pull/10162): Prevent accidentally submitting a swap twice -- [#10224](https://github.com/MetaMask/metamask-extension/pull/10224): Improve chain ID validation -- [#10195](https://github.com/MetaMask/metamask-extension/pull/10195): Increase minimum Firefox version to v68 -- [#10192](https://github.com/MetaMask/metamask-extension/pull/10192): Update TrezorConnect to v8 -- [#10166](https://github.com/MetaMask/metamask-extension/pull/10166): Fix back button on swaps loading page -- [#9947](https://github.com/MetaMask/metamask-extension/pull/9947): Do not publish swaps transaction if the estimateGas call made when adding the transaction fails. +- Update @metamask/contract-metadata from v1.21.0 to 1.22.0 ([#10285](https://github.com/MetaMask/metamask-extension/pull/10285)) +- Update `hi` localized messages ([#10264](https://github.com/MetaMask/metamask-extension/pull/10264)) +- Move fox to bottom of 'About' page ([#10174](https://github.com/MetaMask/metamask-extension/pull/10174)) +- Fix hardware account selection ([#10198](https://github.com/MetaMask/metamask-extension/pull/10198)) +- Add a timeout to all network requests ([#10101](https://github.com/MetaMask/metamask-extension/pull/10101)) +- Fix displayed balance of tokens with 0 decimals in swaps flow ([#10212](https://github.com/MetaMask/metamask-extension/pull/10212)) +- Prevent accidentally submitting a swap twice ([#10162](https://github.com/MetaMask/metamask-extension/pull/10162)) +- Improve chain ID validation ([#10224](https://github.com/MetaMask/metamask-extension/pull/10224)) +- Increase minimum Firefox version to v68 ([#10195](https://github.com/MetaMask/metamask-extension/pull/10195)) +- Update TrezorConnect to v8 ([#10192](https://github.com/MetaMask/metamask-extension/pull/10192)) +- Fix back button on swaps loading page ([#10166](https://github.com/MetaMask/metamask-extension/pull/10166)) +- Do not publish swaps transaction if the estimateGas call made when adding the transaction fails. ([#9947](https://github.com/MetaMask/metamask-extension/pull/9947)) ## [9.0.3] - 2021-01-22 ### Uncategorized -- [#10243](https://github.com/MetaMask/metamask-extension/pull/10243): Fix site metadata handling -- [#10252](https://github.com/MetaMask/metamask-extension/pull/10252): Fix decrypt message confirmation UI crash +- Fix site metadata handling ([#10243](https://github.com/MetaMask/metamask-extension/pull/10243)) +- Fix decrypt message confirmation UI crash ([#10252](https://github.com/MetaMask/metamask-extension/pull/10252)) ## [9.0.2] - 2021-01-20 ### Uncategorized -- [#10191](https://github.com/MetaMask/metamask-extension/pull/10191): zh_TW: 乙太 -> 以太 (#10191) -- [#10207](https://github.com/MetaMask/metamask-extension/pull/10207): zh_TW: Translate buy, assets, activity (#10207) -- [#10219](https://github.com/MetaMask/metamask-extension/pull/10219): Restore provider 'data' event (#10219) +- zh_TW: 乙太 -> 以太 ([#10191](https://github.com/MetaMask/metamask-extension/pull/10191)) +- zh_TW: Translate buy, assets, activity ([#10207](https://github.com/MetaMask/metamask-extension/pull/10207)) +- Restore provider 'data' event ([#10219](https://github.com/MetaMask/metamask-extension/pull/10219)) ## [9.0.1] - 2021-01-13 ### Uncategorized -- [#10169](https://github.com/MetaMask/metamask-extension/pull/10169): Improved detection of contract methods with array parameters -- [#10178](https://github.com/MetaMask/metamask-extension/pull/10178): Only warn of injected web3 usage once per page -- [#10179](https://github.com/MetaMask/metamask-extension/pull/10179): Restore support for @metamask/inpage provider@"< 8.0.0" -- [#10180](https://github.com/MetaMask/metamask-extension/pull/10180): Fix UI crash when domain metadata is missing on public encryption key confirmation page +- Improved detection of contract methods with array parameters ([#10169](https://github.com/MetaMask/metamask-extension/pull/10169)) +- Only warn of injected web3 usage once per page ([#10178](https://github.com/MetaMask/metamask-extension/pull/10178)) +- Restore support for @metamask/inpage provider@"< 8.0.0" ([#10179](https://github.com/MetaMask/metamask-extension/pull/10179)) +- Fix UI crash when domain metadata is missing on public encryption key confirmation page ([#10180](https://github.com/MetaMask/metamask-extension/pull/10180)) ## [9.0.0] - 2021-01-12 ### Uncategorized -- [#9156](https://github.com/MetaMask/metamask-extension/pull/9156): Remove window.web3 injection -- [#10039](https://github.com/MetaMask/metamask-extension/pull/10039): Add web3 shim usage notification -- [#8640](https://github.com/MetaMask/metamask-extension/pull/8640): Implement breaking window.ethereum API changes -- [#8629](https://github.com/MetaMask/metamask-extension/pull/8629): Fix `eth_chainId` return values for Infura networks -- [#10019](https://github.com/MetaMask/metamask-extension/pull/10019): Increase Chrome minimum version to v63 -- [#10135](https://github.com/MetaMask/metamask-extension/pull/10135): Fix error where a swap only completed the token approval transaction -- [#10100](https://github.com/MetaMask/metamask-extension/pull/10100): Remove unnecessary swaps footer space when in dropdown mode -- [#9905](https://github.com/MetaMask/metamask-extension/pull/9905): Redesign view quote screens -- [#9320](https://github.com/MetaMask/metamask-extension/pull/9320): Prevent hidden tokens from reappearing -- [#10000](https://github.com/MetaMask/metamask-extension/pull/10000): Use consistent font size for modal top right Close links -- [#10046](https://github.com/MetaMask/metamask-extension/pull/10046): Improve home screen notification appearance -- [#10093](https://github.com/MetaMask/metamask-extension/pull/10093): Always roll back to the previously selected network when unable to connect to a newly selected network -- [#10117](https://github.com/MetaMask/metamask-extension/pull/10117): Fix network settings Kovan block explorer link -- [#10143](https://github.com/MetaMask/metamask-extension/pull/10143): Prevent malformed next nonce warning -- [#10142](https://github.com/MetaMask/metamask-extension/pull/10142): Update @metamask/contract-metadata from v1.20.0 to 1.21.0 -- [#10160](https://github.com/MetaMask/metamask-extension/pull/10160): Fix French "Block Explorer URL" translations -- [#10157](https://github.com/MetaMask/metamask-extension/pull/10157): Automatically detect tokens on custom Mainnet RPC endpoints -- [#9772](https://github.com/MetaMask/metamask-extension/pull/9772): Improve zh_CN translation -- [#10170](https://github.com/MetaMask/metamask-extension/pull/10170): Fix bug where swaps button was disabled on Mainnet if the user hadn't switched networks in a long time +- Remove window.web3 injection ([#9156](https://github.com/MetaMask/metamask-extension/pull/9156)) +- Add web3 shim usage notification ([#10039](https://github.com/MetaMask/metamask-extension/pull/10039)) +- Implement breaking window.ethereum API changes ([#8640](https://github.com/MetaMask/metamask-extension/pull/8640)) +- Fix `eth_chainId` return values for Infura networks ([#8629](https://github.com/MetaMask/metamask-extension/pull/8629)) +- Increase Chrome minimum version to v63 ([#10019](https://github.com/MetaMask/metamask-extension/pull/10019)) +- Fix error where a swap only completed the token approval transaction ([#10135](https://github.com/MetaMask/metamask-extension/pull/10135)) +- Remove unnecessary swaps footer space when in dropdown mode ([#10100](https://github.com/MetaMask/metamask-extension/pull/10100)) +- Redesign view quote screens ([#9905](https://github.com/MetaMask/metamask-extension/pull/9905)) +- Prevent hidden tokens from reappearing ([#9320](https://github.com/MetaMask/metamask-extension/pull/9320)) +- Use consistent font size for modal top right Close links ([#10000](https://github.com/MetaMask/metamask-extension/pull/10000)) +- Improve home screen notification appearance ([#10046](https://github.com/MetaMask/metamask-extension/pull/10046)) +- Always roll back to the previously selected network when unable to connect to a newly selected network ([#10093](https://github.com/MetaMask/metamask-extension/pull/10093)) +- Fix network settings Kovan block explorer link ([#10117](https://github.com/MetaMask/metamask-extension/pull/10117)) +- Prevent malformed next nonce warning ([#10143](https://github.com/MetaMask/metamask-extension/pull/10143)) +- Update @metamask/contract-metadata from v1.20.0 to 1.21.0 ([#10142](https://github.com/MetaMask/metamask-extension/pull/10142)) +- Fix French "Block Explorer URL" translations ([#10160](https://github.com/MetaMask/metamask-extension/pull/10160)) +- Automatically detect tokens on custom Mainnet RPC endpoints ([#10157](https://github.com/MetaMask/metamask-extension/pull/10157)) +- Improve zh_CN translation ([#9772](https://github.com/MetaMask/metamask-extension/pull/9772)) +- Fix bug where swaps button was disabled on Mainnet if the user hadn't switched networks in a long time ([#10170](https://github.com/MetaMask/metamask-extension/pull/10170)) ## [8.1.11] - 2021-01-07 ### Uncategorized -- [#10155](https://github.com/MetaMask/metamask-extension/pull/10155): Disable swaps when the current network's chainId does not match the mainnet chain ID, instead of disabling based on network ID +- Disable swaps when the current network's chainId does not match the mainnet chain ID, instead of disabling based on network ID ([#10155](https://github.com/MetaMask/metamask-extension/pull/10155)) ## [8.1.10] - 2021-01-04 ### Uncategorized -- [#10084](https://github.com/MetaMask/metamask-extension/pull/10084): Set last provider when switching to a customRPC -- [#10096](https://github.com/MetaMask/metamask-extension/pull/10096): Update `@metamask/controllers` to v5.1.0 -- [#10103](https://github.com/MetaMask/metamask-extension/pull/10103): Prevent stuck loading screen in some situations -- [#10104](https://github.com/MetaMask/metamask-extension/pull/10104): Bump @metamask/contract-metadata from 1.19.0 to 1.20.0 -- [#10110](https://github.com/MetaMask/metamask-extension/pull/10110): Fix frozen loading screen on Firefox when strict Enhanced Tracking Protection is enabled +- Set last provider when switching to a customRPC ([#10084](https://github.com/MetaMask/metamask-extension/pull/10084)) +- Update `@metamask/controllers` to v5.1.0 ([#10096](https://github.com/MetaMask/metamask-extension/pull/10096)) +- Prevent stuck loading screen in some situations ([#10103](https://github.com/MetaMask/metamask-extension/pull/10103)) +- Bump @metamask/contract-metadata from 1.19.0 to 1.20.0 ([#10104](https://github.com/MetaMask/metamask-extension/pull/10104)) +- Fix frozen loading screen on Firefox when strict Enhanced Tracking Protection is enabled ([#10110](https://github.com/MetaMask/metamask-extension/pull/10110)) ## [8.1.9] - 2020-12-15 ### Uncategorized -- [#10034](https://github.com/MetaMask/metamask-extension/pull/10034): Fix contentscript injection failure on Firefox 56 -- [#10045](https://github.com/MetaMask/metamask-extension/pull/10045): Fix token validation in Send flow -- [#10048](https://github.com/MetaMask/metamask-extension/pull/10048): Display boolean values when signing typed data -- [#10070](https://github.com/MetaMask/metamask-extension/pull/10070): Add eth_getProof -- [#10043](https://github.com/MetaMask/metamask-extension/pull/10043): Improve swaps maximum gas estimation -- [#10069](https://github.com/MetaMask/metamask-extension/pull/10069): Fetch swap quote refresh time from API -- [#10040](https://github.com/MetaMask/metamask-extension/pull/10040): Disable console in contentscript to reduce noise +- Fix contentscript injection failure on Firefox 56 ([#10034](https://github.com/MetaMask/metamask-extension/pull/10034)) +- Fix token validation in Send flow ([#10045](https://github.com/MetaMask/metamask-extension/pull/10045)) +- Display boolean values when signing typed data ([#10048](https://github.com/MetaMask/metamask-extension/pull/10048)) +- Add eth_getProof ([#10070](https://github.com/MetaMask/metamask-extension/pull/10070)) +- Improve swaps maximum gas estimation ([#10043](https://github.com/MetaMask/metamask-extension/pull/10043)) +- Fetch swap quote refresh time from API ([#10069](https://github.com/MetaMask/metamask-extension/pull/10069)) +- Disable console in contentscript to reduce noise ([#10040](https://github.com/MetaMask/metamask-extension/pull/10040)) ## [8.1.8] - 2020-12-09 ### Uncategorized -- [#9992](https://github.com/MetaMask/metamask-extension/pull/9992): Improve transaction params validation -- [#9991](https://github.com/MetaMask/metamask-extension/pull/9991): Don't allow more than 15% slippage -- [#9994](https://github.com/MetaMask/metamask-extension/pull/9994): Prevent unwanted 'no quotes available' message when going back to build quote screen while having insufficient funds -- [#9999](https://github.com/MetaMask/metamask-extension/pull/9999): Fix missing contacts upon restart +- Improve transaction params validation ([#9992](https://github.com/MetaMask/metamask-extension/pull/9992)) +- Don't allow more than 15% slippage ([#9991](https://github.com/MetaMask/metamask-extension/pull/9991)) +- Prevent unwanted 'no quotes available' message when going back to build quote screen while having insufficient funds ([#9994](https://github.com/MetaMask/metamask-extension/pull/9994)) +- Fix missing contacts upon restart ([#9999](https://github.com/MetaMask/metamask-extension/pull/9999)) ## [8.1.7] - 2020-12-09 ### Uncategorized @@ -271,840 +275,841 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [8.1.6] - 2020-12-04 ### Uncategorized -- [#9916](https://github.com/MetaMask/metamask-extension/pull/9916): Fix QR code scans interpretting payment requests as token addresses -- [#9847](https://github.com/MetaMask/metamask-extension/pull/9847): Add alt text for images in list items -- [#9960](https://github.com/MetaMask/metamask-extension/pull/9960): Ensure watchAsset returns errors for invalid token symbols -- [#9968](https://github.com/MetaMask/metamask-extension/pull/9968): Adds tokens from v1.19.0 of metamask/contract-metadata to add token lists -- [#9970](https://github.com/MetaMask/metamask-extension/pull/9970): Etherscan links support Goerli network -- [#9899](https://github.com/MetaMask/metamask-extension/pull/9899): Show price impact warnings on swaps quote screen -- [#9867](https://github.com/MetaMask/metamask-extension/pull/9867): Replace use of ethgasstation -- [#9984](https://github.com/MetaMask/metamask-extension/pull/9984): Show correct gas estimates when users don't have sufficient balance for contract transaction -- [#9993](https://github.com/MetaMask/metamask-extension/pull/9993): Add 48x48 MetaMask icon for use by browsers +- Fix QR code scans interpretting payment requests as token addresses ([#9916](https://github.com/MetaMask/metamask-extension/pull/9916)) +- Add alt text for images in list items ([#9847](https://github.com/MetaMask/metamask-extension/pull/9847)) +- Ensure watchAsset returns errors for invalid token symbols ([#9960](https://github.com/MetaMask/metamask-extension/pull/9960)) +- Adds tokens from v1.19.0 of metamask/contract-metadata to add token lists ([#9968](https://github.com/MetaMask/metamask-extension/pull/9968)) +- Etherscan links support Goerli network ([#9970](https://github.com/MetaMask/metamask-extension/pull/9970)) +- Show price impact warnings on swaps quote screen ([#9899](https://github.com/MetaMask/metamask-extension/pull/9899)) +- Replace use of ethgasstation ([#9867](https://github.com/MetaMask/metamask-extension/pull/9867)) +- Show correct gas estimates when users don't have sufficient balance for contract transaction ([#9984](https://github.com/MetaMask/metamask-extension/pull/9984)) +- Add 48x48 MetaMask icon for use by browsers ([#9993](https://github.com/MetaMask/metamask-extension/pull/9993)) ## [8.1.5] - 2020-11-19 ### Uncategorized -- [#9871](https://github.com/MetaMask/metamask-extension/pull/9871): Show send text upon hover in main asset list -- [#9855](https://github.com/MetaMask/metamask-extension/pull/9855): Make edit icon and account name in account details modal focusable -- [#9853](https://github.com/MetaMask/metamask-extension/pull/9853): Provide alternative text for images where appropriate -- [#9869](https://github.com/MetaMask/metamask-extension/pull/9869): Remove CoinSwitch from the Deposit modal -- [#9883](https://github.com/MetaMask/metamask-extension/pull/9883): Move add contact button in fullscreen/expanded view of settings lower to expose the close button. -- [#9891](https://github.com/MetaMask/metamask-extension/pull/9891): Add token verification message to swaps build quote screen -- [#9896](https://github.com/MetaMask/metamask-extension/pull/9896): Show failed token balance updates -- [#9909](https://github.com/MetaMask/metamask-extension/pull/9909): Update asset page etherscan link to the address-filtered token page on Etherscan -- [#9910](https://github.com/MetaMask/metamask-extension/pull/9910): Revert "Show a 'send eth' button on home screen in full screen mode" -- [#9907](https://github.com/MetaMask/metamask-extension/pull/9907): Ensure "Known contract address" warning is shown on send screen even when changing asset -- [#9911](https://github.com/MetaMask/metamask-extension/pull/9911): Fix display of Ledger connection error -- [#9918](https://github.com/MetaMask/metamask-extension/pull/9918): Fix missing icon in asset page dropdown and in advanced gas modal button group +- Show send text upon hover in main asset list ([#9871](https://github.com/MetaMask/metamask-extension/pull/9871)) +- Make edit icon and account name in account details modal focusable ([#9855](https://github.com/MetaMask/metamask-extension/pull/9855)) +- Provide alternative text for images where appropriate ([#9853](https://github.com/MetaMask/metamask-extension/pull/9853)) +- Remove CoinSwitch from the Deposit modal ([#9869](https://github.com/MetaMask/metamask-extension/pull/9869)) +- Move add contact button in fullscreen/expanded view of settings lower to expose the close button. ([#9883](https://github.com/MetaMask/metamask-extension/pull/9883)) +- Add token verification message to swaps build quote screen ([#9891](https://github.com/MetaMask/metamask-extension/pull/9891)) +- Show failed token balance updates ([#9896](https://github.com/MetaMask/metamask-extension/pull/9896)) +- Update asset page etherscan link to the address-filtered token page on Etherscan ([#9909](https://github.com/MetaMask/metamask-extension/pull/9909)) +- Revert "Show a 'send eth' button on home screen in full screen mode" ([#9910](https://github.com/MetaMask/metamask-extension/pull/9910)) +- Ensure "Known contract address" warning is shown on send screen even when changing asset ([#9907](https://github.com/MetaMask/metamask-extension/pull/9907)) +- Fix display of Ledger connection error ([#9911](https://github.com/MetaMask/metamask-extension/pull/9911)) +- Fix missing icon in asset page dropdown and in advanced gas modal button group ([#9918](https://github.com/MetaMask/metamask-extension/pull/9918)) ## [8.1.4] - 2020-11-16 ### Uncategorized -- [#9687](https://github.com/MetaMask/metamask-extension/pull/9687): Allow speeding up of underpriced transactions -- [#9694](https://github.com/MetaMask/metamask-extension/pull/9694): normalize UI component font styles -- [#9695](https://github.com/MetaMask/metamask-extension/pull/9695): normalize app component font styles -- [#9696](https://github.com/MetaMask/metamask-extension/pull/9696): normalize deprecated itcss font styles -- [#9697](https://github.com/MetaMask/metamask-extension/pull/9697): normalize page font styles -- [#9740](https://github.com/MetaMask/metamask-extension/pull/9740): Standardize network settings page -- [#9750](https://github.com/MetaMask/metamask-extension/pull/9750): Make swap arrows accessible, make swaps advanced options accessible -- [#9766](https://github.com/MetaMask/metamask-extension/pull/9766): Use 1px borders on inputs and buttons -- [#9767](https://github.com/MetaMask/metamask-extension/pull/9767): Remove border radius from transfer button -- [#9764](https://github.com/MetaMask/metamask-extension/pull/9764): Update custom RPC network dropdown icons -- [#9763](https://github.com/MetaMask/metamask-extension/pull/9763): Add confirmation for network dropdown delete action -- [#9583](https://github.com/MetaMask/metamask-extension/pull/9583): Use `chainId` for incoming transactions controller -- [#9748](https://github.com/MetaMask/metamask-extension/pull/9748): Autofocus input, improve accessibility of restore page -- [#9778](https://github.com/MetaMask/metamask-extension/pull/9778): Shorten unit input width and use ellipses for overflow -- [#9746](https://github.com/MetaMask/metamask-extension/pull/9746): Make the login screen's Restore and Import links accessible -- [#9780](https://github.com/MetaMask/metamask-extension/pull/9780): Display decimal chain ID in network form -- [#9599](https://github.com/MetaMask/metamask-extension/pull/9599): Use MetaSwap API for gas price estimation in swaps -- [#9518](https://github.com/MetaMask/metamask-extension/pull/9518): Make all UI tabs accessible via keyboard -- [#9808](https://github.com/MetaMask/metamask-extension/pull/9808): Always allow overwriting invalid custom RPC chain ID -- [#9812](https://github.com/MetaMask/metamask-extension/pull/9812): Fix send header cancel button alignment -- [#9271](https://github.com/MetaMask/metamask-extension/pull/9271): Do not check popupIsOpen on Vivaldi -- [#9306](https://github.com/MetaMask/metamask-extension/pull/9306): Fix UI crash when dapp submits negative gas price -- [#9257](https://github.com/MetaMask/metamask-extension/pull/9257): Add sort and search to AddRecipient accounts list -- [#9824](https://github.com/MetaMask/metamask-extension/pull/9824): Move `externally_connectable` from base to Chrome manifest -- [#9815](https://github.com/MetaMask/metamask-extension/pull/9815): Add support for custom network RPC URL with basic auth -- [#9822](https://github.com/MetaMask/metamask-extension/pull/9822): Make QR code button focusable -- [#9832](https://github.com/MetaMask/metamask-extension/pull/9832): Warn instead of throw on duplicate web3 -- [#9838](https://github.com/MetaMask/metamask-extension/pull/9838): @metamask/controllers@4.0.0 -- [#9856](https://github.com/MetaMask/metamask-extension/pull/9856): Prevent user from getting stuck on opt in page -- [#9845](https://github.com/MetaMask/metamask-extension/pull/9845): Show a 'send eth' button on home screen in full screen mode -- [#9871](https://github.com/MetaMask/metamask-extension/pull/9871): Show send text upon hover in main asset list -- [#9880](https://github.com/MetaMask/metamask-extension/pull/9880): Properly detect U2F errors in hardware wallet +- Allow speeding up of underpriced transactions ([#9687](https://github.com/MetaMask/metamask-extension/pull/9687)) +- normalize UI component font styles ([#9694](https://github.com/MetaMask/metamask-extension/pull/9694)) +- normalize app component font styles ([#9695](https://github.com/MetaMask/metamask-extension/pull/9695)) +- normalize deprecated itcss font styles ([#9696](https://github.com/MetaMask/metamask-extension/pull/9696)) +- normalize page font styles ([#9697](https://github.com/MetaMask/metamask-extension/pull/9697)) +- Standardize network settings page ([#9740](https://github.com/MetaMask/metamask-extension/pull/9740)) +- Make swap arrows accessible, make swaps advanced options accessible ([#9750](https://github.com/MetaMask/metamask-extension/pull/9750)) +- Use 1px borders on inputs and buttons ([#9766](https://github.com/MetaMask/metamask-extension/pull/9766)) +- Remove border radius from transfer button ([#9767](https://github.com/MetaMask/metamask-extension/pull/9767)) +- Update custom RPC network dropdown icons ([#9764](https://github.com/MetaMask/metamask-extension/pull/9764)) +- Add confirmation for network dropdown delete action ([#9763](https://github.com/MetaMask/metamask-extension/pull/9763)) +- Use `chainId` for incoming transactions controller ([#9583](https://github.com/MetaMask/metamask-extension/pull/9583)) +- Autofocus input, improve accessibility of restore page ([#9748](https://github.com/MetaMask/metamask-extension/pull/9748)) +- Shorten unit input width and use ellipses for overflow ([#9778](https://github.com/MetaMask/metamask-extension/pull/9778)) +- Make the login screen's Restore and Import links accessible ([#9746](https://github.com/MetaMask/metamask-extension/pull/9746)) +- Display decimal chain ID in network form ([#9780](https://github.com/MetaMask/metamask-extension/pull/9780)) +- Use MetaSwap API for gas price estimation in swaps ([#9599](https://github.com/MetaMask/metamask-extension/pull/9599)) +- Make all UI tabs accessible via keyboard ([#9518](https://github.com/MetaMask/metamask-extension/pull/9518)) +- Always allow overwriting invalid custom RPC chain ID ([#9808](https://github.com/MetaMask/metamask-extension/pull/9808)) +- Fix send header cancel button alignment ([#9812](https://github.com/MetaMask/metamask-extension/pull/9812)) +- Do not check popupIsOpen on Vivaldi ([#9271](https://github.com/MetaMask/metamask-extension/pull/9271)) +- Fix UI crash when dapp submits negative gas price ([#9306](https://github.com/MetaMask/metamask-extension/pull/9306)) +- Add sort and search to AddRecipient accounts list ([#9257](https://github.com/MetaMask/metamask-extension/pull/9257)) +- Move `externally_connectable` from base to Chrome manifest ([#9824](https://github.com/MetaMask/metamask-extension/pull/9824)) +- Add support for custom network RPC URL with basic auth ([#9815](https://github.com/MetaMask/metamask-extension/pull/9815)) +- Make QR code button focusable ([#9822](https://github.com/MetaMask/metamask-extension/pull/9822)) +- Warn instead of throw on duplicate web3 ([#9832](https://github.com/MetaMask/metamask-extension/pull/9832)) +- @metamask/controllers@4.0.0 ([#9838](https://github.com/MetaMask/metamask-extension/pull/9838)) +- Prevent user from getting stuck on opt in page ([#9856](https://github.com/MetaMask/metamask-extension/pull/9856)) +- Show a 'send eth' button on home screen in full screen mode ([#9845](https://github.com/MetaMask/metamask-extension/pull/9845)) +- Show send text upon hover in main asset list ([#9871](https://github.com/MetaMask/metamask-extension/pull/9871)) +- Properly detect U2F errors in hardware wallet ([#9880](https://github.com/MetaMask/metamask-extension/pull/9880)) ## [8.1.3] - 2020-10-29 ### Uncategorized -- [#9642](https://github.com/MetaMask/metamask-extension/pull/9642) Prevent excessive overflow from swap dropdowns -- [#9658](https://github.com/MetaMask/metamask-extension/pull/9658): Fix sorting Quote Source column of quote sort list -- [#9667](https://github.com/MetaMask/metamask-extension/pull/9667): Fix adding contact with QR code -- [#9674](https://github.com/MetaMask/metamask-extension/pull/9674): Fix ENS resolution of `.eth` URLs with query strings -- [#9691](https://github.com/MetaMask/metamask-extension/pull/9691): Bump @metamask/inpage-provider from 6.1.0 to 6.3.0 -- [#9700](https://github.com/MetaMask/metamask-extension/pull/9700): Provide image sizing so there's no jump when opening the swaps token search -- [#9568](https://github.com/MetaMask/metamask-extension/pull/9568): Add ses lockdown to build system -- [#9705](https://github.com/MetaMask/metamask-extension/pull/9705): Prevent memory leak from selected account copy tooltip -- [#9671](https://github.com/MetaMask/metamask-extension/pull/9671): Prevent old fetches from polluting the swap state -- [#9702](https://github.com/MetaMask/metamask-extension/pull/9702): Keyboard navigation for swaps dropdowns -- [#9646](https://github.com/MetaMask/metamask-extension/pull/9646): Switch from Matomo to Segment -- [#9745](https://github.com/MetaMask/metamask-extension/pull/9745): Fix fetching swaps when initial network not Mainnet -- [#9621](https://github.com/MetaMask/metamask-extension/pull/9621): Include aggregator fee as part of displayed network fees -- [#9736](https://github.com/MetaMask/metamask-extension/pull/9736): Bump eth-contract-metadata from 1.16.0 to 1.17.0 -- [#9743](https://github.com/MetaMask/metamask-extension/pull/9743): Fix "+-" prefix on swap token amount -- [#9715](https://github.com/MetaMask/metamask-extension/pull/9715): Focus on wallet address in buy workflow +- Prevent excessive overflow from swap dropdowns ([#9642](https://github.com/MetaMask/metamask-extension/pull/9642)) +- Fix sorting Quote Source column of quote sort list ([#9658](https://github.com/MetaMask/metamask-extension/pull/9658)) +- Fix adding contact with QR code ([#9667](https://github.com/MetaMask/metamask-extension/pull/9667)) +- Fix ENS resolution of `.eth` URLs with query strings ([#9674](https://github.com/MetaMask/metamask-extension/pull/9674)) +- Bump @metamask/inpage-provider from 6.1.0 to 6.3.0 ([#9691](https://github.com/MetaMask/metamask-extension/pull/9691)) +- Provide image sizing so there's no jump when opening the swaps token search ([#9700](https://github.com/MetaMask/metamask-extension/pull/9700)) +- Add ses lockdown to build system ([#9568](https://github.com/MetaMask/metamask-extension/pull/9568)) +- Prevent memory leak from selected account copy tooltip ([#9705](https://github.com/MetaMask/metamask-extension/pull/9705)) +- Prevent old fetches from polluting the swap state ([#9671](https://github.com/MetaMask/metamask-extension/pull/9671)) +- Keyboard navigation for swaps dropdowns ([#9702](https://github.com/MetaMask/metamask-extension/pull/9702)) +- Switch from Matomo to Segment ([#9646](https://github.com/MetaMask/metamask-extension/pull/9646)) +- Fix fetching swaps when initial network not Mainnet ([#9745](https://github.com/MetaMask/metamask-extension/pull/9745)) +- Include aggregator fee as part of displayed network fees ([#9621](https://github.com/MetaMask/metamask-extension/pull/9621)) +- Bump eth-contract-metadata from 1.16.0 to 1.17.0 ([#9736](https://github.com/MetaMask/metamask-extension/pull/9736)) +- Fix "+-" prefix on swap token amount ([#9743](https://github.com/MetaMask/metamask-extension/pull/9743)) +- Focus on wallet address in buy workflow ([#9715](https://github.com/MetaMask/metamask-extension/pull/9715)) ## [8.1.2] - 2020-10-20 ### Uncategorized -- [#9608](https://github.com/MetaMask/metamask-extension/pull/9608): Ensure QR code scanner works -- [#9624](https://github.com/MetaMask/metamask-extension/pull/9624): Help users avoid insufficient gas prices in swaps -- [#9614](https://github.com/MetaMask/metamask-extension/pull/9614): Update swaps network fee tooltip -- [#9623](https://github.com/MetaMask/metamask-extension/pull/9623): Prevent reducing the gas limit for swaps -- [#9630](https://github.com/MetaMask/metamask-extension/pull/9630): Fix UI crash when trying to render estimated time remaining of non-submitted transaction -- [#9633](https://github.com/MetaMask/metamask-extension/pull/9633): Update View Quote page to better represent the MetaMask fee +- Ensure QR code scanner works ([#9608](https://github.com/MetaMask/metamask-extension/pull/9608)) +- Help users avoid insufficient gas prices in swaps ([#9624](https://github.com/MetaMask/metamask-extension/pull/9624)) +- Update swaps network fee tooltip ([#9614](https://github.com/MetaMask/metamask-extension/pull/9614)) +- Prevent reducing the gas limit for swaps ([#9623](https://github.com/MetaMask/metamask-extension/pull/9623)) +- Fix UI crash when trying to render estimated time remaining of non-submitted transaction ([#9630](https://github.com/MetaMask/metamask-extension/pull/9630)) +- Update View Quote page to better represent the MetaMask fee ([#9633](https://github.com/MetaMask/metamask-extension/pull/9633)) ## [8.1.1] - 2020-10-15 ### Uncategorized -- [#9586](https://github.com/MetaMask/metamask-extension/pull/9586): Prevent build quote crash when swapping from non-tracked token with balance (#9586) -- [#9592](https://github.com/MetaMask/metamask-extension/pull/9592): Remove commitment to maintain a public metrics dashboard (#9592) -- [#9596](https://github.com/MetaMask/metamask-extension/pull/9596): Fix TypeError when `signTypedData` throws (#9596) -- [#9591](https://github.com/MetaMask/metamask-extension/pull/9591): Fix Firefox overflow on transaction items with long amounts (#9591) -- [#9601](https://github.com/MetaMask/metamask-extension/pull/9601): Update text content of invalid custom network alert (#9601) -- [#9575](https://github.com/MetaMask/metamask-extension/pull/9575): Ensure proper hover display for accounts in main menu (#9575) -- [#9576](https://github.com/MetaMask/metamask-extension/pull/9576): Autofocus the appropriate text fields in the Create/Import/Hardware screen (#9576) -- [#9581](https://github.com/MetaMask/metamask-extension/pull/9581): AutoFocus the from input on swaps screen (#9581) -- [#9602](https://github.com/MetaMask/metamask-extension/pull/9602): Prevent swap button from being focused when disabled (#9602) -- [#9609](https://github.com/MetaMask/metamask-extension/pull/9609): Ensure swaps customize gas modal values are set correctly (#9609) +- Prevent build quote crash when swapping from non-tracked token with balance ([#9586](https://github.com/MetaMask/metamask-extension/pull/9586)) +- Remove commitment to maintain a public metrics dashboard ([#9592](https://github.com/MetaMask/metamask-extension/pull/9592)) +- Fix TypeError when `signTypedData` throws ([#9596](https://github.com/MetaMask/metamask-extension/pull/9596)) +- Fix Firefox overflow on transaction items with long amounts ([#9591](https://github.com/MetaMask/metamask-extension/pull/9591)) +- Update text content of invalid custom network alert ([#9601](https://github.com/MetaMask/metamask-extension/pull/9601)) +- Ensure proper hover display for accounts in main menu ([#9575](https://github.com/MetaMask/metamask-extension/pull/9575)) +- Autofocus the appropriate text fields in the Create/Import/Hardware screen ([#9576](https://github.com/MetaMask/metamask-extension/pull/9576)) +- AutoFocus the from input on swaps screen ([#9581](https://github.com/MetaMask/metamask-extension/pull/9581)) +- Prevent swap button from being focused when disabled ([#9602](https://github.com/MetaMask/metamask-extension/pull/9602)) +- Ensure swaps customize gas modal values are set correctly ([#9609](https://github.com/MetaMask/metamask-extension/pull/9609)) ## [8.1.0] - 2020-10-13 ### Uncategorized -- [#9565](https://github.com/MetaMask/metamask-extension/pull/9565): Ensure address book entries are shared between networks with the same chain ID -- [#9552](https://github.com/MetaMask/metamask-extension/pull/9552): Fix `eth_signTypedData_v4` chain ID validation for non-default networks -- [#9551](https://github.com/MetaMask/metamask-extension/pull/9551): Allow the "Localhost 8545" network to be edited, and require a chain ID to be specified for it -- [#9491](https://github.com/MetaMask/metamask-extension/pull/9491): Validate custom network chain IDs against endpoint `eth_chainId` return values -- [#9487](https://github.com/MetaMask/metamask-extension/pull/9487): Require chain IDs to be specified for custom networks -- [#9482](https://github.com/MetaMask/metamask-extension/pull/9482): Add MetaMask Swaps 🌻 -- [#9422](https://github.com/MetaMask/metamask-extension/pull/9422): Fix data backup feature (i.e. syncing with 3box) -- [#9434](https://github.com/MetaMask/metamask-extension/pull/9434): Improve gas input UI by using tooltip instead of a modal to communicate gas data -- [#9433](https://github.com/MetaMask/metamask-extension/pull/9433): Improve visual style and layout of the basic tab of the customize gas modal -- [#9415](https://github.com/MetaMask/metamask-extension/pull/9415): Fix UI bug in token approval confirmation notifications -- [#9414](https://github.com/MetaMask/metamask-extension/pull/9414): Update Wyre purchase URL -- [#9411](https://github.com/MetaMask/metamask-extension/pull/9411): Rename 'Ethereum Main Network' in network selector to 'Etherum Mainnet' -- [#9409](https://github.com/MetaMask/metamask-extension/pull/9409): Fix info tooltip on the alert settings screen when used in firefox -- [#9406](https://github.com/MetaMask/metamask-extension/pull/9406): Fix UI bug in customize gas modal: shwo left border when the first button is selected -- [#9395](https://github.com/MetaMask/metamask-extension/pull/9395): Correctly save new Contact Book addressed after editing them in 'Settings > Contact' -- [#9293](https://github.com/MetaMask/metamask-extension/pull/9293): Improve Italian translations -- [#9295](https://github.com/MetaMask/metamask-extension/pull/9295): Ensure the extension can be unlocked without network/internet access -- [#9344](https://github.com/MetaMask/metamask-extension/pull/9344): Add messages to Ledger connection process -- [#9329](https://github.com/MetaMask/metamask-extension/pull/9329): Hide seedphrase by default when restoring vault, and provide option for it to be shown -- [#9333](https://github.com/MetaMask/metamask-extension/pull/9333): Ensure names of token symbols are shown when token amounts in the token list are long -- [#9321](https://github.com/MetaMask/metamask-extension/pull/9321): Warn users when sending tokens to the token address -- [#9288](https://github.com/MetaMask/metamask-extension/pull/9288): Fix bug that caused the accounts list to be empty after entering an incorrect password when attempting to export private key -- [#9314](https://github.com/MetaMask/metamask-extension/pull/9314): Improve/fix error text for when ENS names are not found, on mainnet -- [#9307](https://github.com/MetaMask/metamask-extension/pull/9307): Improve 'Contact Us' copy in settings -- [#9283](https://github.com/MetaMask/metamask-extension/pull/9283): Fix capitalization of copy on MetaMetrics opt-in page -- [#9269](https://github.com/MetaMask/metamask-extension/pull/9269): Add lock icon to default networks in the Settings network page, to indicate they are not editable -- [#9189](https://github.com/MetaMask/metamask-extension/pull/9189): Hide gas price/speed estimate button, and link to advanced gas modal, in send flow on non-main network -- [#9184](https://github.com/MetaMask/metamask-extension/pull/9184): Improve visual styling of back button in account modal -- [#9152](https://github.com/MetaMask/metamask-extension/pull/9152): Fix vertical align of the network name in network dropdown button -- [#9073](https://github.com/MetaMask/metamask-extension/pull/9073): Use new Euclid font throughout MetaMask +- Ensure address book entries are shared between networks with the same chain ID ([#9565](https://github.com/MetaMask/metamask-extension/pull/9565)) +- Fix `eth_signTypedData_v4` chain ID validation for non-default networks ([#9552](https://github.com/MetaMask/metamask-extension/pull/9552)) +- Allow the "Localhost 8545" network to be edited, and require a chain ID to be specified for it ([#9551](https://github.com/MetaMask/metamask-extension/pull/9551)) +- Validate custom network chain IDs against endpoint `eth_chainId` return values ([#9491](https://github.com/MetaMask/metamask-extension/pull/9491)) +- Require chain IDs to be specified for custom networks ([#9487](https://github.com/MetaMask/metamask-extension/pull/9487)) +- Add MetaMask Swaps 🌻 ([#9482](https://github.com/MetaMask/metamask-extension/pull/9482)) +- Fix data backup feature ([#9422](https://github.com/MetaMask/metamask-extension/pull/9422)) +- Improve gas input UI by using tooltip instead of a modal to communicate gas data ([#9434](https://github.com/MetaMask/metamask-extension/pull/9434)) +- Improve visual style and layout of the basic tab of the customize gas modal ([#9433](https://github.com/MetaMask/metamask-extension/pull/9433)) +- Fix UI bug in token approval confirmation notifications ([#9415](https://github.com/MetaMask/metamask-extension/pull/9415)) +- Update Wyre purchase URL ([#9414](https://github.com/MetaMask/metamask-extension/pull/9414)) +- Rename 'Ethereum Main Network' in network selector to 'Etherum Mainnet' ([#9411](https://github.com/MetaMask/metamask-extension/pull/9411)) +- Fix info tooltip on the alert settings screen when used in firefox ([#9409](https://github.com/MetaMask/metamask-extension/pull/9409)) +- Fix UI bug in customize gas modal: shwo left border when the first button is selected ([#9406](https://github.com/MetaMask/metamask-extension/pull/9406)) +- Correctly save new Contact Book addressed after editing them in 'Settings > Contact' ([#9395](https://github.com/MetaMask/metamask-extension/pull/9395)) +- Improve Italian translations ([#9293](https://github.com/MetaMask/metamask-extension/pull/9293)) +- Ensure the extension can be unlocked without network/internet access ([#9295](https://github.com/MetaMask/metamask-extension/pull/9295)) +- Add messages to Ledger connection process ([#9344](https://github.com/MetaMask/metamask-extension/pull/9344)) +- Hide seedphrase by default when restoring vault, and provide option for it to be shown ([#9329](https://github.com/MetaMask/metamask-extension/pull/9329)) +- Ensure names of token symbols are shown when token amounts in the token list are long ([#9333](https://github.com/MetaMask/metamask-extension/pull/9333)) +- Warn users when sending tokens to the token address ([#9321](https://github.com/MetaMask/metamask-extension/pull/9321)) +- Fix bug that caused the accounts list to be empty after entering an incorrect password when attempting to export private key ([#9288](https://github.com/MetaMask/metamask-extension/pull/9288)) +- Improve/fix error text for when ENS names are not found, on mainnet ([#9314](https://github.com/MetaMask/metamask-extension/pull/9314)) +- Improve 'Contact Us' copy in settings ([#9307](https://github.com/MetaMask/metamask-extension/pull/9307)) +- Fix capitalization of copy on MetaMetrics opt-in page ([#9283](https://github.com/MetaMask/metamask-extension/pull/9283)) +- Add lock icon to default networks in the Settings network page, to indicate they are not editable ([#9269](https://github.com/MetaMask/metamask-extension/pull/9269)) +- Hide gas price/speed estimate button, and link to advanced gas modal, in send flow on non-main network ([#9189](https://github.com/MetaMask/metamask-extension/pull/9189)) +- Improve visual styling of back button in account modal ([#9184](https://github.com/MetaMask/metamask-extension/pull/9184)) +- Fix vertical align of the network name in network dropdown button ([#9152](https://github.com/MetaMask/metamask-extension/pull/9152)) +- Use new Euclid font throughout MetaMask ([#9073](https://github.com/MetaMask/metamask-extension/pull/9073)) ## [8.0.10] - 2020-09-16 ### Uncategorized -- [#9423](https://github.com/MetaMask/metamask-extension/pull/9423): Update default phishing list -- [#9416](https://github.com/MetaMask/metamask-extension/pull/9416): Fix fetching a new phishing list on Firefox +- Update default phishing list ([#9423](https://github.com/MetaMask/metamask-extension/pull/9423)) +- Fix fetching a new phishing list on Firefox ([#9416](https://github.com/MetaMask/metamask-extension/pull/9416)) ## [8.0.9] - 2020-08-19 ### Uncategorized -- [#9228](https://github.com/MetaMask/metamask-extension/pull/9228): Move transaction confirmation footer buttons to scrollable area -- [#9256](https://github.com/MetaMask/metamask-extension/pull/9256): Handle non-String web3 property access -- [#9266](https://github.com/MetaMask/metamask-extension/pull/9266): Use @metamask/controllers@2.0.5 -- [#9189](https://github.com/MetaMask/metamask-extension/pull/9189): Hide ETH Gas Station estimates on non-main network +- Move transaction confirmation footer buttons to scrollable area ([#9228](https://github.com/MetaMask/metamask-extension/pull/9228)) +- Handle non-String web3 property access ([#9256](https://github.com/MetaMask/metamask-extension/pull/9256)) +- Use @metamask/controllers@2.0.5 ([#9266](https://github.com/MetaMask/metamask-extension/pull/9266)) +- Hide ETH Gas Station estimates on non-main network ([#9189](https://github.com/MetaMask/metamask-extension/pull/9189)) ## [8.0.8] - 2020-08-14 ### Uncategorized -- [#9211](https://github.com/MetaMask/metamask-extension/pull/9211): Fix Etherscan redirect on notification click -- [#9237](https://github.com/MetaMask/metamask-extension/pull/9237): Reduce volume of web3 usage metrics -- [#9227](https://github.com/MetaMask/metamask-extension/pull/9227): Permit all-caps addresses +- Fix Etherscan redirect on notification click ([#9211](https://github.com/MetaMask/metamask-extension/pull/9211)) +- Reduce volume of web3 usage metrics ([#9237](https://github.com/MetaMask/metamask-extension/pull/9237)) +- Permit all-caps addresses ([#9227](https://github.com/MetaMask/metamask-extension/pull/9227)) ## [8.0.7] - 2020-08-10 ### Uncategorized -- [#9065](https://github.com/MetaMask/metamask-extension/pull/9065): Change title of "Reveal Seed Words" page to "Reveal Seed Phrase" -- [#8974](https://github.com/MetaMask/metamask-extension/pull/8974): Add tooltip to copy button for contacts and seed phrase -- [#9063](https://github.com/MetaMask/metamask-extension/pull/9063): Fix broken UI upon failed password validation -- [#9075](https://github.com/MetaMask/metamask-extension/pull/9075): Fix shifted popup notification when browser is in fullscreen on macOS -- [#9085](https://github.com/MetaMask/metamask-extension/pull/9085): Support longer text in network dropdown -- [#8873](https://github.com/MetaMask/metamask-extension/pull/8873): Fix onboarding bug where user can be asked to verify seed phrase twice -- [#9104](https://github.com/MetaMask/metamask-extension/pull/9104): Replace "Email us" button with "Contact us" button -- [#9137](https://github.com/MetaMask/metamask-extension/pull/9137): Fix bug where `accountsChanged` events stop after a dapp connection is closed. -- [#9152](https://github.com/MetaMask/metamask-extension/pull/9152): Fix network name alignment -- [#9144](https://github.com/MetaMask/metamask-extension/pull/9144): Add web3 usage metrics and prepare for web3 removal +- Change title of "Reveal Seed Words" page to "Reveal Seed Phrase" ([#9065](https://github.com/MetaMask/metamask-extension/pull/9065)) +- Add tooltip to copy button for contacts and seed phrase ([#8974](https://github.com/MetaMask/metamask-extension/pull/8974)) +- Fix broken UI upon failed password validation ([#9063](https://github.com/MetaMask/metamask-extension/pull/9063)) +- Fix shifted popup notification when browser is in fullscreen on macOS ([#9075](https://github.com/MetaMask/metamask-extension/pull/9075)) +- Support longer text in network dropdown ([#9085](https://github.com/MetaMask/metamask-extension/pull/9085)) +- Fix onboarding bug where user can be asked to verify seed phrase twice ([#8873](https://github.com/MetaMask/metamask-extension/pull/8873)) +- Replace "Email us" button with "Contact us" button ([#9104](https://github.com/MetaMask/metamask-extension/pull/9104)) +- Fix bug where `accountsChanged` events stop after a dapp connection is closed. ([#9137](https://github.com/MetaMask/metamask-extension/pull/9137)) +- Fix network name alignment ([#9152](https://github.com/MetaMask/metamask-extension/pull/9152)) +- Add web3 usage metrics and prepare for web3 removal ([#9144](https://github.com/MetaMask/metamask-extension/pull/9144)) ## [8.0.6] - 2020-07-23 ### Uncategorized -- [#9030](https://github.com/MetaMask/metamask-extension/pull/9030): Hide "delete" button when editing contact of wallet account -- [#9031](https://github.com/MetaMask/metamask-extension/pull/9031): Fix crash upon removing contact -- [#9032](https://github.com/MetaMask/metamask-extension/pull/9032): Do not show spend limit for approvals -- [#9046](https://github.com/MetaMask/metamask-extension/pull/9046): Update @metamask/inpage-provider@6.1.0 -- [#9048](https://github.com/MetaMask/metamask-extension/pull/9048): Skip attempts to resolve 0x contract prefix -- [#9051](https://github.com/MetaMask/metamask-extension/pull/9051): Use content-hash@2.5.2 -- [#9056](https://github.com/MetaMask/metamask-extension/pull/9056): Display at least one significant digit of small non-zero token balances +- Hide "delete" button when editing contact of wallet account ([#9030](https://github.com/MetaMask/metamask-extension/pull/9030)) +- Fix crash upon removing contact ([#9031](https://github.com/MetaMask/metamask-extension/pull/9031)) +- Do not show spend limit for approvals ([#9032](https://github.com/MetaMask/metamask-extension/pull/9032)) +- Update @metamask/inpage-provider@6.1.0 ([#9046](https://github.com/MetaMask/metamask-extension/pull/9046)) +- Skip attempts to resolve 0x contract prefix ([#9048](https://github.com/MetaMask/metamask-extension/pull/9048)) +- Use content-hash@2.5.2 ([#9051](https://github.com/MetaMask/metamask-extension/pull/9051)) +- Display at least one significant digit of small non-zero token balances ([#9056](https://github.com/MetaMask/metamask-extension/pull/9056)) ## [8.0.5] - 2020-07-17 ### Uncategorized -- [#8942](https://github.com/MetaMask/metamask-extension/pull/8942): Fix display of incoming transactions (#8942) -- [#8998](https://github.com/MetaMask/metamask-extension/pull/8998): Fix `web3_clientVersion` method (#8998) -- [#9003](https://github.com/MetaMask/metamask-extension/pull/9003): @metamask/inpage-provider@6.0.1 (#9003) -- [#9006](https://github.com/MetaMask/metamask-extension/pull/9006): Hide loading indication after `personal_sign` (#9006) -- [#9011](https://github.com/MetaMask/metamask-extension/pull/9011): Display pending notifications after connect flow (#9011) -- [#9012](https://github.com/MetaMask/metamask-extension/pull/9012): Skip render when home page is closing or redirecting (#9012) -- [#9010](https://github.com/MetaMask/metamask-extension/pull/9010): Limit number of transactions passed outside of TransactionController (#9010) -- [#9023](https://github.com/MetaMask/metamask-extension/pull/9023): Clear AccountTracker accounts and CachedBalances on createNewVaultAndRestore (#9023) -- [#9025](https://github.com/MetaMask/metamask-extension/pull/9025): Catch gas estimate errors (#9025) -- [#9026](https://github.com/MetaMask/metamask-extension/pull/9026): Clear transactions on createNewVaultAndRestore (#9026) +- Fix display of incoming transactions ([#8942](https://github.com/MetaMask/metamask-extension/pull/8942)) +- Fix `web3_clientVersion` method ([#8998](https://github.com/MetaMask/metamask-extension/pull/8998)) +- @metamask/inpage-provider@6.0.1 ([#9003](https://github.com/MetaMask/metamask-extension/pull/9003)) +- Hide loading indication after `personal_sign` ([#9006](https://github.com/MetaMask/metamask-extension/pull/9006)) +- Display pending notifications after connect flow ([#9011](https://github.com/MetaMask/metamask-extension/pull/9011)) +- Skip render when home page is closing or redirecting ([#9012](https://github.com/MetaMask/metamask-extension/pull/9012)) +- Limit number of transactions passed outside of TransactionController ([#9010](https://github.com/MetaMask/metamask-extension/pull/9010)) +- Clear AccountTracker accounts and CachedBalances on createNewVaultAndRestore ([#9023](https://github.com/MetaMask/metamask-extension/pull/9023)) +- Catch gas estimate errors ([#9025](https://github.com/MetaMask/metamask-extension/pull/9025)) +- Clear transactions on createNewVaultAndRestore ([#9026](https://github.com/MetaMask/metamask-extension/pull/9026)) ## [8.0.4] - 2020-07-08 ### Uncategorized -- [#8934](https://github.com/MetaMask/metamask-extension/pull/8934): Fix transaction activity on custom networks -- [#8936](https://github.com/MetaMask/metamask-extension/pull/8936): Fix account tracker optimization +- Fix transaction activity on custom networks ([#8934](https://github.com/MetaMask/metamask-extension/pull/8934)) +- Fix account tracker optimization ([#8936](https://github.com/MetaMask/metamask-extension/pull/8936)) ## [8.0.3] - 2020-07-06 ### Uncategorized -- [#8921](https://github.com/MetaMask/metamask-extension/pull/8921): Restore missing 'data' provider event, and fix 'notification' event -- [#8923](https://github.com/MetaMask/metamask-extension/pull/8923): Normalize the 'from' parameter for `eth_sendTransaction` -- [#8924](https://github.com/MetaMask/metamask-extension/pull/8924): Fix handling of multiple `eth_requestAccount` messages from the same domain -- [#8917](https://github.com/MetaMask/metamask-extension/pull/8917): Update Italian translations +- Restore missing 'data' provider event, and fix 'notification' event ([#8921](https://github.com/MetaMask/metamask-extension/pull/8921)) +- Normalize the 'from' parameter for `eth_sendTransaction` ([#8923](https://github.com/MetaMask/metamask-extension/pull/8923)) +- Fix handling of multiple `eth_requestAccount` messages from the same domain ([#8924](https://github.com/MetaMask/metamask-extension/pull/8924)) +- Update Italian translations ([#8917](https://github.com/MetaMask/metamask-extension/pull/8917)) ## [8.0.2] - 2020-07-03 ### Uncategorized -- [#8907](https://github.com/MetaMask/metamask-extension/pull/8907): Tolerate missing or falsey substitutions -- [#8908](https://github.com/MetaMask/metamask-extension/pull/8908): Fix activity log inline buttons -- [#8909](https://github.com/MetaMask/metamask-extension/pull/8909): Prevent confirming blank suggested token -- [#8910](https://github.com/MetaMask/metamask-extension/pull/8910): Handle suggested token resolved elsewhere -- [#8913](https://github.com/MetaMask/metamask-extension/pull/8913): Fix Kovan chain ID constant +- Tolerate missing or falsey substitutions ([#8907](https://github.com/MetaMask/metamask-extension/pull/8907)) +- Fix activity log inline buttons ([#8908](https://github.com/MetaMask/metamask-extension/pull/8908)) +- Prevent confirming blank suggested token ([#8909](https://github.com/MetaMask/metamask-extension/pull/8909)) +- Handle suggested token resolved elsewhere ([#8910](https://github.com/MetaMask/metamask-extension/pull/8910)) +- Fix Kovan chain ID constant ([#8913](https://github.com/MetaMask/metamask-extension/pull/8913)) ## [8.0.1] - 2020-07-02 ### Uncategorized -- [#8874](https://github.com/MetaMask/metamask-extension/pull/8874): Fx overflow behaviour of add token list -- [#8885](https://github.com/MetaMask/metamask-extension/pull/8885): Show `origin` in connect flow rather than site name -- [#8883](https://github.com/MetaMask/metamask-extension/pull/8883): Allow setting a custom nonce of zero -- [#8889](https://github.com/MetaMask/metamask-extension/pull/8889): Fix language code format mismatch -- [#8891](https://github.com/MetaMask/metamask-extension/pull/8891): Prevent showing connected accounts without origin -- [#8893](https://github.com/MetaMask/metamask-extension/pull/8893): Prevent manually connecting to extension UI -- [#8895](https://github.com/MetaMask/metamask-extension/pull/8895): Allow localized messages to not use substitutions -- [#8897](https://github.com/MetaMask/metamask-extension/pull/8897): Update eth-keyring-controller to fix erasure of imported/hardware account names -- [#8896](https://github.com/MetaMask/metamask-extension/pull/8896): Include relative time polyfill locale data -- [#8898](https://github.com/MetaMask/metamask-extension/pull/8898): Replace percentage opacity value +- Fx overflow behaviour of add token list ([#8874](https://github.com/MetaMask/metamask-extension/pull/8874)) +- Show `origin` in connect flow rather than site name ([#8885](https://github.com/MetaMask/metamask-extension/pull/8885)) +- Allow setting a custom nonce of zero ([#8883](https://github.com/MetaMask/metamask-extension/pull/8883)) +- Fix language code format mismatch ([#8889](https://github.com/MetaMask/metamask-extension/pull/8889)) +- Prevent showing connected accounts without origin ([#8891](https://github.com/MetaMask/metamask-extension/pull/8891)) +- Prevent manually connecting to extension UI ([#8893](https://github.com/MetaMask/metamask-extension/pull/8893)) +- Allow localized messages to not use substitutions ([#8895](https://github.com/MetaMask/metamask-extension/pull/8895)) +- Update eth-keyring-controller to fix erasure of imported/hardware account names ([#8897](https://github.com/MetaMask/metamask-extension/pull/8897)) +- Include relative time polyfill locale data ([#8896](https://github.com/MetaMask/metamask-extension/pull/8896)) +- Replace percentage opacity value ([#8898](https://github.com/MetaMask/metamask-extension/pull/8898)) ## [8.0.0] - 2020-07-01 ### Uncategorized -- [#7004](https://github.com/MetaMask/metamask-extension/pull/7004): Add permission system -- [#7261](https://github.com/MetaMask/metamask-extension/pull/7261): Search accounts by name -- [#7483](https://github.com/MetaMask/metamask-extension/pull/7483): Buffer 3 blocks before dropping a transaction -- [#7620](https://github.com/MetaMask/metamask-extension/pull/7620): Handle one specific permissions request per tab -- [#7686](https://github.com/MetaMask/metamask-extension/pull/7686): Add description to Reset Account in settings -- [#7362](https://github.com/MetaMask/metamask-extension/pull/7362): Allow custom IPFS gateway and use more secure default gateway -- [#7696](https://github.com/MetaMask/metamask-extension/pull/7696): Adjust colour of Reset Account button to reflect danger -- [#7602](https://github.com/MetaMask/metamask-extension/pull/7602): Support new onboarding library -- [#7672](https://github.com/MetaMask/metamask-extension/pull/7672): Update custom token symbol length restriction message -- [#7747](https://github.com/MetaMask/metamask-extension/pull/7747): Handle 'Enter' keypress on restore from seed screen -- [#7810](https://github.com/MetaMask/metamask-extension/pull/7810): Remove padding around advanced gas info icon -- [#7840](https://github.com/MetaMask/metamask-extension/pull/7840): Force background state update after removing an account -- [#7853](https://github.com/MetaMask/metamask-extension/pull/7853): Change "Log In/Out" terminology to "Unlock/Lock" -- [#7863](https://github.com/MetaMask/metamask-extension/pull/7863): Add mechanism to randomize seed phrase filename -- [#7933](https://github.com/MetaMask/metamask-extension/pull/7933): Sort seed phrase confirmation buttons alphabetically -- [#7987](https://github.com/MetaMask/metamask-extension/pull/7987): Add support for 24 word seed phrases -- [#7971](https://github.com/MetaMask/metamask-extension/pull/7971): Use contact name instead of address during send flow -- [#8050](https://github.com/MetaMask/metamask-extension/pull/8050): Add title attribute to transaction title -- [#7831](https://github.com/MetaMask/metamask-extension/pull/7831): Implement encrypt/decrypt feature -- [#8125](https://github.com/MetaMask/metamask-extension/pull/8125): Add setting for disabling Eth Phishing Detection -- [#8148](https://github.com/MetaMask/metamask-extension/pull/8148): Prevent external domains from submitting more than one perm request at a time -- [#8149](https://github.com/MetaMask/metamask-extension/pull/8149): Wait for extension unlock before processing eth_requestAccounts -- [#8201](https://github.com/MetaMask/metamask-extension/pull/8201): Add Idle Timeout for Sync with mobile -- [#8247](https://github.com/MetaMask/metamask-extension/pull/8247): Update Italian translation -- [#8246](https://github.com/MetaMask/metamask-extension/pull/8246): Make seed phrase import case-insensitive -- [#8254](https://github.com/MetaMask/metamask-extension/pull/8254): Convert Connected Sites page to modal -- [#8259](https://github.com/MetaMask/metamask-extension/pull/8259): Update token cell to show inline stale balance warning -- [#8264](https://github.com/MetaMask/metamask-extension/pull/8264): Move asset list to home tab on small screens -- [#8270](https://github.com/MetaMask/metamask-extension/pull/8270): Connected status indicator -- [#8078](https://github.com/MetaMask/metamask-extension/pull/8078): Allow selecting multiple accounts during connect flow -- [#8318](https://github.com/MetaMask/metamask-extension/pull/8318): Focus the notification popup if it's already open -- [#8356](https://github.com/MetaMask/metamask-extension/pull/8356): Position notification relative to last focused window -- [#8358](https://github.com/MetaMask/metamask-extension/pull/8358): Close notification UI if no unapproved confirmations -- [#8293](https://github.com/MetaMask/metamask-extension/pull/8293): Add popup explaining connection indicator to existing users -- [#8435](https://github.com/MetaMask/metamask-extension/pull/8435): Correctly detect changes to background state -- [#7912](https://github.com/MetaMask/metamask-extension/pull/7912): Disable import button for empty string/file -- [#8246](https://github.com/MetaMask/metamask-extension/pull/8246): Make seed phrase import case-insensitive -- [#8312](https://github.com/MetaMask/metamask-extension/pull/8312): Alert user upon switching to unconnected account -- [#8445](https://github.com/MetaMask/metamask-extension/pull/8445): Only updating pending transactions upon block update -- [#8467](https://github.com/MetaMask/metamask-extension/pull/8467): Fix firefox popup location -- [#8486](https://github.com/MetaMask/metamask-extension/pull/8486): Prevent race condition where transaction value set in UI is overwritten -- [#8490](https://github.com/MetaMask/metamask-extension/pull/8490): Fix default gas race condition -- [#8491](https://github.com/MetaMask/metamask-extension/pull/8491): Update tokens after importing account -- [#8496](https://github.com/MetaMask/metamask-extension/pull/8496): Enable disconnecting a single account or all accounts -- [#8502](https://github.com/MetaMask/metamask-extension/pull/8502): Add support for IPFS address resolution -- [#8419](https://github.com/MetaMask/metamask-extension/pull/8419): Add version dimension to metrics event -- [#8508](https://github.com/MetaMask/metamask-extension/pull/8508): Open notification UI when eth_requestAccounts waits for unlock -- [#8533](https://github.com/MetaMask/metamask-extension/pull/8533): Prevent negative values on gas inputs -- [#8550](https://github.com/MetaMask/metamask-extension/pull/8550): Allow disabling alerts -- [#8563](https://github.com/MetaMask/metamask-extension/pull/8563): Synchronously update transaction status -- [#8567](https://github.com/MetaMask/metamask-extension/pull/8567): Improve Spanish localized message -- [#8532](https://github.com/MetaMask/metamask-extension/pull/8532): Add switch to connected account alert -- [#8575](https://github.com/MetaMask/metamask-extension/pull/8575): Stop polling for recent blocks on custom networks when UI is closed -- [#8579](https://github.com/MetaMask/metamask-extension/pull/8579): Fix Matomo dimension IDs -- [#8592](https://github.com/MetaMask/metamask-extension/pull/8592): Handle trailing / in block explorer URLs -- [#8313](https://github.com/MetaMask/metamask-extension/pull/8313): Add Connected Accounts modal -- [#8609](https://github.com/MetaMask/metamask-extension/pull/8609): Sticky position the tabs at the top -- [#8634](https://github.com/MetaMask/metamask-extension/pull/8634): Define global `web3` as non-enumerable -- [#8601](https://github.com/MetaMask/metamask-extension/pull/8601): warn user when sending from different account -- [#8612](https://github.com/MetaMask/metamask-extension/pull/8612): Persist home tab state -- [#8564](https://github.com/MetaMask/metamask-extension/pull/8564): Implement new transaction list design -- [#8596](https://github.com/MetaMask/metamask-extension/pull/8596): Restrict the size of the permissions metadata store -- [#8654](https://github.com/MetaMask/metamask-extension/pull/8654): Update account options menu design -- [#8657](https://github.com/MetaMask/metamask-extension/pull/8657): Implement new fullscreen design -- [#8663](https://github.com/MetaMask/metamask-extension/pull/8663): Show hostname in the disconnect confirmation -- [#8665](https://github.com/MetaMask/metamask-extension/pull/8665): Make address display wider in Account Details -- [#8670](https://github.com/MetaMask/metamask-extension/pull/8670): Fix token `decimal` type -- [#8653](https://github.com/MetaMask/metamask-extension/pull/8653): Limit Dapp permissions to primary account -- [#8666](https://github.com/MetaMask/metamask-extension/pull/8666): Manually connect via the full connect flow -- [#8677](https://github.com/MetaMask/metamask-extension/pull/8677): Add metrics events for Wyre and CoinSwitch -- [#8680](https://github.com/MetaMask/metamask-extension/pull/8680): Fix connect hardware styling -- [#8689](https://github.com/MetaMask/metamask-extension/pull/8689): Fix create account form styling -- [#8702](https://github.com/MetaMask/metamask-extension/pull/8702): Fix tab content disappearing during scrolling on macOS Firefox -- [#8696](https://github.com/MetaMask/metamask-extension/pull/8696): Implement asset page -- [#8716](https://github.com/MetaMask/metamask-extension/pull/8716): Add nonce to transaction details -- [#8717](https://github.com/MetaMask/metamask-extension/pull/8717): Use URL origin instead of hostname for permission domains -- [#8747](https://github.com/MetaMask/metamask-extension/pull/8747): Fix account menu entry for imported accounts -- [#8768](https://github.com/MetaMask/metamask-extension/pull/8768): Permissions: Do not display HTTP/HTTPS URL schemes for unique hosts -- [#8730](https://github.com/MetaMask/metamask-extension/pull/8730): Hide seed phrase during Account Import -- [#8785](https://github.com/MetaMask/metamask-extension/pull/8785): Rename 'History' tab to 'Activity' -- [#8781](https://github.com/MetaMask/metamask-extension/pull/8781): use UI button for add token functionality -- [#8786](https://github.com/MetaMask/metamask-extension/pull/8786): Show fiat amounts inline on token transfers -- [#8789](https://github.com/MetaMask/metamask-extension/pull/8789): Warn users to only add custom networks that they trust -- [#8802](https://github.com/MetaMask/metamask-extension/pull/8802): Consolidate connected account alerts -- [#8810](https://github.com/MetaMask/metamask-extension/pull/8810): Remove all user- and translator-facing instances of 'dapp' -- [#8836](https://github.com/MetaMask/metamask-extension/pull/8836): Update method data when cached method data is empty -- [#8833](https://github.com/MetaMask/metamask-extension/pull/8833): Improve error handling when signature requested without a keyholder address -- [#8850](https://github.com/MetaMask/metamask-extension/pull/8850): Stop upper-casing exported private key -- [#8631](https://github.com/MetaMask/metamask-extension/pull/8631): Include imported accounts in mobile sync +- Add permission system ([#7004](https://github.com/MetaMask/metamask-extension/pull/7004)) +- Search accounts by name ([#7261](https://github.com/MetaMask/metamask-extension/pull/7261)) +- Buffer 3 blocks before dropping a transaction ([#7483](https://github.com/MetaMask/metamask-extension/pull/7483)) +- Handle one specific permissions request per tab ([#7620](https://github.com/MetaMask/metamask-extension/pull/7620)) +- Add description to Reset Account in settings ([#7686](https://github.com/MetaMask/metamask-extension/pull/7686)) +- Allow custom IPFS gateway and use more secure default gateway ([#7362](https://github.com/MetaMask/metamask-extension/pull/7362)) +- Adjust colour of Reset Account button to reflect danger ([#7696](https://github.com/MetaMask/metamask-extension/pull/7696)) +- Support new onboarding library ([#7602](https://github.com/MetaMask/metamask-extension/pull/7602)) +- Update custom token symbol length restriction message ([#7672](https://github.com/MetaMask/metamask-extension/pull/7672)) +- Handle 'Enter' keypress on restore from seed screen ([#7747](https://github.com/MetaMask/metamask-extension/pull/7747)) +- Remove padding around advanced gas info icon ([#7810](https://github.com/MetaMask/metamask-extension/pull/7810)) +- Force background state update after removing an account ([#7840](https://github.com/MetaMask/metamask-extension/pull/7840)) +- Change "Log In/Out" terminology to "Unlock/Lock" ([#7853](https://github.com/MetaMask/metamask-extension/pull/7853)) +- Add mechanism to randomize seed phrase filename ([#7863](https://github.com/MetaMask/metamask-extension/pull/7863)) +- Sort seed phrase confirmation buttons alphabetically ([#7933](https://github.com/MetaMask/metamask-extension/pull/7933)) +- Add support for 24 word seed phrases ([#7987](https://github.com/MetaMask/metamask-extension/pull/7987)) +- Use contact name instead of address during send flow ([#7971](https://github.com/MetaMask/metamask-extension/pull/7971)) +- Add title attribute to transaction title ([#8050](https://github.com/MetaMask/metamask-extension/pull/8050)) +- Implement encrypt/decrypt feature ([#7831](https://github.com/MetaMask/metamask-extension/pull/7831)) +- Add setting for disabling Eth Phishing Detection ([#8125](https://github.com/MetaMask/metamask-extension/pull/8125)) +- Prevent external domains from submitting more than one perm request at a time ([#8148](https://github.com/MetaMask/metamask-extension/pull/8148)) +- Wait for extension unlock before processing eth_requestAccounts ([#8149](https://github.com/MetaMask/metamask-extension/pull/8149)) +- Add Idle Timeout for Sync with mobile ([#8201](https://github.com/MetaMask/metamask-extension/pull/8201)) +- Update Italian translation ([#8247](https://github.com/MetaMask/metamask-extension/pull/8247)) +- Make seed phrase import case-insensitive ([#8246](https://github.com/MetaMask/metamask-extension/pull/8246)) +- Convert Connected Sites page to modal ([#8254](https://github.com/MetaMask/metamask-extension/pull/8254)) +- Update token cell to show inline stale balance warning ([#8259](https://github.com/MetaMask/metamask-extension/pull/8259)) +- Move asset list to home tab on small screens ([#8264](https://github.com/MetaMask/metamask-extension/pull/8264)) +- Connected status indicator ([#8270](https://github.com/MetaMask/metamask-extension/pull/8270)) +- Allow selecting multiple accounts during connect flow ([#8078](https://github.com/MetaMask/metamask-extension/pull/8078)) +- Focus the notification popup if it's already open ([#8318](https://github.com/MetaMask/metamask-extension/pull/8318)) +- Position notification relative to last focused window ([#8356](https://github.com/MetaMask/metamask-extension/pull/8356)) +- Close notification UI if no unapproved confirmations ([#8358](https://github.com/MetaMask/metamask-extension/pull/8358)) +- Add popup explaining connection indicator to existing users ([#8293](https://github.com/MetaMask/metamask-extension/pull/8293)) +- Correctly detect changes to background state ([#8435](https://github.com/MetaMask/metamask-extension/pull/8435)) +- Disable import button for empty string/file ([#7912](https://github.com/MetaMask/metamask-extension/pull/7912)) +- Make seed phrase import case-insensitive ([#8246](https://github.com/MetaMask/metamask-extension/pull/8246)) +- Alert user upon switching to unconnected account ([#8312](https://github.com/MetaMask/metamask-extension/pull/8312)) +- Only updating pending transactions upon block update ([#8445](https://github.com/MetaMask/metamask-extension/pull/8445)) +- Fix firefox popup location ([#8467](https://github.com/MetaMask/metamask-extension/pull/8467)) +- Prevent race condition where transaction value set in UI is overwritten ([#8486](https://github.com/MetaMask/metamask-extension/pull/8486)) +- Fix default gas race condition ([#8490](https://github.com/MetaMask/metamask-extension/pull/8490)) +- Update tokens after importing account ([#8491](https://github.com/MetaMask/metamask-extension/pull/8491)) +- Enable disconnecting a single account or all accounts ([#8496](https://github.com/MetaMask/metamask-extension/pull/8496)) +- Add support for IPFS address resolution ([#8502](https://github.com/MetaMask/metamask-extension/pull/8502)) +- Add version dimension to metrics event ([#8419](https://github.com/MetaMask/metamask-extension/pull/8419)) +- Open notification UI when eth_requestAccounts waits for unlock ([#8508](https://github.com/MetaMask/metamask-extension/pull/8508)) +- Prevent negative values on gas inputs ([#8533](https://github.com/MetaMask/metamask-extension/pull/8533)) +- Allow disabling alerts ([#8550](https://github.com/MetaMask/metamask-extension/pull/8550)) +- Synchronously update transaction status ([#8563](https://github.com/MetaMask/metamask-extension/pull/8563)) +- Improve Spanish localized message ([#8567](https://github.com/MetaMask/metamask-extension/pull/8567)) +- Add switch to connected account alert ([#8532](https://github.com/MetaMask/metamask-extension/pull/8532)) +- Stop polling for recent blocks on custom networks when UI is closed ([#8575](https://github.com/MetaMask/metamask-extension/pull/8575)) +- Fix Matomo dimension IDs ([#8579](https://github.com/MetaMask/metamask-extension/pull/8579)) +- Handle trailing / in block explorer URLs ([#8592](https://github.com/MetaMask/metamask-extension/pull/8592)) +- Add Connected Accounts modal ([#8313](https://github.com/MetaMask/metamask-extension/pull/8313)) +- Sticky position the tabs at the top ([#8609](https://github.com/MetaMask/metamask-extension/pull/8609)) +- Define global `web3` as non-enumerable ([#8634](https://github.com/MetaMask/metamask-extension/pull/8634)) +- warn user when sending from different account ([#8601](https://github.com/MetaMask/metamask-extension/pull/8601)) +- Persist home tab state ([#8612](https://github.com/MetaMask/metamask-extension/pull/8612)) +- Implement new transaction list design ([#8564](https://github.com/MetaMask/metamask-extension/pull/8564)) +- Restrict the size of the permissions metadata store ([#8596](https://github.com/MetaMask/metamask-extension/pull/8596)) +- Update account options menu design ([#8654](https://github.com/MetaMask/metamask-extension/pull/8654)) +- Implement new fullscreen design ([#8657](https://github.com/MetaMask/metamask-extension/pull/8657)) +- Show hostname in the disconnect confirmation ([#8663](https://github.com/MetaMask/metamask-extension/pull/8663)) +- Make address display wider in Account Details ([#8665](https://github.com/MetaMask/metamask-extension/pull/8665)) +- Fix token `decimal` type ([#8670](https://github.com/MetaMask/metamask-extension/pull/8670)) +- Limit Dapp permissions to primary account ([#8653](https://github.com/MetaMask/metamask-extension/pull/8653)) +- Manually connect via the full connect flow ([#8666](https://github.com/MetaMask/metamask-extension/pull/8666)) +- Add metrics events for Wyre and CoinSwitch ([#8677](https://github.com/MetaMask/metamask-extension/pull/8677)) +- Fix connect hardware styling ([#8680](https://github.com/MetaMask/metamask-extension/pull/8680)) +- Fix create account form styling ([#8689](https://github.com/MetaMask/metamask-extension/pull/8689)) +- Fix tab content disappearing during scrolling on macOS Firefox ([#8702](https://github.com/MetaMask/metamask-extension/pull/8702)) +- Implement asset page ([#8696](https://github.com/MetaMask/metamask-extension/pull/8696)) +- Add nonce to transaction details ([#8716](https://github.com/MetaMask/metamask-extension/pull/8716)) +- Use URL origin instead of hostname for permission domains ([#8717](https://github.com/MetaMask/metamask-extension/pull/8717)) +- Fix account menu entry for imported accounts ([#8747](https://github.com/MetaMask/metamask-extension/pull/8747)) +- Permissions: Do not display HTTP/HTTPS URL schemes for unique hosts ([#8768](https://github.com/MetaMask/metamask-extension/pull/8768)) +- Hide seed phrase during Account Import ([#8730](https://github.com/MetaMask/metamask-extension/pull/8730)) +- Rename 'History' tab to 'Activity' ([#8785](https://github.com/MetaMask/metamask-extension/pull/8785)) +- use UI button for add token functionality ([#8781](https://github.com/MetaMask/metamask-extension/pull/8781)) +- Show fiat amounts inline on token transfers ([#8786](https://github.com/MetaMask/metamask-extension/pull/8786)) +- Warn users to only add custom networks that they trust ([#8789](https://github.com/MetaMask/metamask-extension/pull/8789)) +- Consolidate connected account alerts ([#8802](https://github.com/MetaMask/metamask-extension/pull/8802)) +- Remove all user- and translator-facing instances of 'dapp' ([#8810](https://github.com/MetaMask/metamask-extension/pull/8810)) +- Update method data when cached method data is empty ([#8836](https://github.com/MetaMask/metamask-extension/pull/8836)) +- Improve error handling when signature requested without a keyholder address ([#8833](https://github.com/MetaMask/metamask-extension/pull/8833)) +- Stop upper-casing exported private key ([#8850](https://github.com/MetaMask/metamask-extension/pull/8850)) +- Include imported accounts in mobile sync ([#8631](https://github.com/MetaMask/metamask-extension/pull/8631)) ## [7.7.9] - 2020-05-04 ### Uncategorized -- [#8446](https://github.com/MetaMask/metamask-extension/pull/8446): Fix popup not opening -- [#8449](https://github.com/MetaMask/metamask-extension/pull/8449): Skip adding history entry for empty txMeta diffs -- [#8447](https://github.com/MetaMask/metamask-extension/pull/8447): Delete Dai/Sai migration notification -- [#8460](https://github.com/MetaMask/metamask-extension/pull/8460): Update deposit copy for Wyre -- [#8458](https://github.com/MetaMask/metamask-extension/pull/8458): Snapshot txMeta without cloning history -- [#8459](https://github.com/MetaMask/metamask-extension/pull/8459): Fix method registry initialization -- [#8455](https://github.com/MetaMask/metamask-extension/pull/8455): Add Dai/Sai to currency display -- [#8461](https://github.com/MetaMask/metamask-extension/pull/8461): Prevent network switch upon close of network timeout overlay -- [#8457](https://github.com/MetaMask/metamask-extension/pull/8457): Add INR currency option -- [#8462](https://github.com/MetaMask/metamask-extension/pull/8462): Fix display of Kovan and Rinkeby chain IDs -- [#8465](https://github.com/MetaMask/metamask-extension/pull/8465): Use ethereum-ens-network-map for network support -- [#8463](https://github.com/MetaMask/metamask-extension/pull/8463): Update deprecated Etherscam link -- [#8474](https://github.com/MetaMask/metamask-extension/pull/8474): Only update pending transactions upon block update -- [#8476](https://github.com/MetaMask/metamask-extension/pull/8476): Update eth-contract-metadata -- [#8509](https://github.com/MetaMask/metamask-extension/pull/8509): Fix Tohen Typo +- Fix popup not opening ([#8446](https://github.com/MetaMask/metamask-extension/pull/8446)) +- Skip adding history entry for empty txMeta diffs ([#8449](https://github.com/MetaMask/metamask-extension/pull/8449)) +- Delete Dai/Sai migration notification ([#8447](https://github.com/MetaMask/metamask-extension/pull/8447)) +- Update deposit copy for Wyre ([#8460](https://github.com/MetaMask/metamask-extension/pull/8460)) +- Snapshot txMeta without cloning history ([#8458](https://github.com/MetaMask/metamask-extension/pull/8458)) +- Fix method registry initialization ([#8459](https://github.com/MetaMask/metamask-extension/pull/8459)) +- Add Dai/Sai to currency display ([#8455](https://github.com/MetaMask/metamask-extension/pull/8455)) +- Prevent network switch upon close of network timeout overlay ([#8461](https://github.com/MetaMask/metamask-extension/pull/8461)) +- Add INR currency option ([#8457](https://github.com/MetaMask/metamask-extension/pull/8457)) +- Fix display of Kovan and Rinkeby chain IDs ([#8462](https://github.com/MetaMask/metamask-extension/pull/8462)) +- Use ethereum-ens-network-map for network support ([#8465](https://github.com/MetaMask/metamask-extension/pull/8465)) +- Update deprecated Etherscam link ([#8463](https://github.com/MetaMask/metamask-extension/pull/8463)) +- Only update pending transactions upon block update ([#8474](https://github.com/MetaMask/metamask-extension/pull/8474)) +- Update eth-contract-metadata ([#8476](https://github.com/MetaMask/metamask-extension/pull/8476)) +- Fix Tohen Typo ([#8509](https://github.com/MetaMask/metamask-extension/pull/8509)) ## [7.7.8] - 2020-03-13 ### Uncategorized -- [#8176](https://github.com/MetaMask/metamask-extension/pull/8176): Handle and set gas estimation when max mode is clicked -- [#8178](https://github.com/MetaMask/metamask-extension/pull/8178): Use specified gas limit when speeding up a transaction +- Handle and set gas estimation when max mode is clicked ([#8176](https://github.com/MetaMask/metamask-extension/pull/8176)) +- Use specified gas limit when speeding up a transaction ([#8178](https://github.com/MetaMask/metamask-extension/pull/8178)) ## [7.7.7] - 2020-03-04 ### Uncategorized -- [#8162](https://github.com/MetaMask/metamask-extension/pull/8162): Remove invalid Ledger accounts -- [#8163](https://github.com/MetaMask/metamask-extension/pull/8163): Fix account index check +- Remove invalid Ledger accounts ([#8162](https://github.com/MetaMask/metamask-extension/pull/8162)) +- Fix account index check ([#8163](https://github.com/MetaMask/metamask-extension/pull/8163)) ## [7.7.6] - 2020-03-03 ### Uncategorized -- [#8154](https://github.com/MetaMask/metamask-extension/pull/8154): Prevent signing from incorrect Ledger account +- Prevent signing from incorrect Ledger account ([#8154](https://github.com/MetaMask/metamask-extension/pull/8154)) ## [7.7.5] - 2020-02-18 ### Uncategorized -- [#8053](https://github.com/MetaMask/metamask-extension/pull/8053): Inline the source text not the binary encoding for inpage script -- [#8049](https://github.com/MetaMask/metamask-extension/pull/8049): Add warning to watchAsset API when editing a known token -- [#8051](https://github.com/MetaMask/metamask-extension/pull/8051): Update Wyre ETH purchase url -- [#8059](https://github.com/MetaMask/metamask-extension/pull/8059): Attempt ENS resolution on any valid domain name +- Inline the source text not the binary encoding for inpage script ([#8053](https://github.com/MetaMask/metamask-extension/pull/8053)) +- Add warning to watchAsset API when editing a known token ([#8049](https://github.com/MetaMask/metamask-extension/pull/8049)) +- Update Wyre ETH purchase url ([#8051](https://github.com/MetaMask/metamask-extension/pull/8051)) +- Attempt ENS resolution on any valid domain name ([#8059](https://github.com/MetaMask/metamask-extension/pull/8059)) ## [7.7.4] - 2020-01-31 ### Uncategorized -- [#7918](https://github.com/MetaMask/metamask-extension/pull/7918): Update data on Approve screen after updating custom spend limit -- [#7919](https://github.com/MetaMask/metamask-extension/pull/7919): Allow editing max spend limit -- [#7920](https://github.com/MetaMask/metamask-extension/pull/7920): Validate custom spend limit -- [#7944](https://github.com/MetaMask/metamask-extension/pull/7944): Only resolve ENS on mainnet -- [#7954](https://github.com/MetaMask/metamask-extension/pull/7954): Update ENS registry addresses +- Update data on Approve screen after updating custom spend limit ([#7918](https://github.com/MetaMask/metamask-extension/pull/7918)) +- Allow editing max spend limit ([#7919](https://github.com/MetaMask/metamask-extension/pull/7919)) +- Validate custom spend limit ([#7920](https://github.com/MetaMask/metamask-extension/pull/7920)) +- Only resolve ENS on mainnet ([#7944](https://github.com/MetaMask/metamask-extension/pull/7944)) +- Update ENS registry addresses ([#7954](https://github.com/MetaMask/metamask-extension/pull/7954)) ## [7.7.3] - 2020-01-27 ### Uncategorized -- [#7894](https://github.com/MetaMask/metamask-extension/pull/7894): Update GABA dependency version -- [#7901](https://github.com/MetaMask/metamask-extension/pull/7901): Use eth-contract-metadata@1.12.1 -- [#7910](https://github.com/MetaMask/metamask-extension/pull/7910): Fixing broken JSON import help link +- Update GABA dependency version ([#7894](https://github.com/MetaMask/metamask-extension/pull/7894)) +- Use eth-contract-metadata@1.12.1 ([#7901](https://github.com/MetaMask/metamask-extension/pull/7901)) +- Fixing broken JSON import help link ([#7910](https://github.com/MetaMask/metamask-extension/pull/7910)) ## [7.7.2] - 2020-01-13 ### Uncategorized -- [#7753](https://github.com/MetaMask/metamask-extension/pull/7753): Fix gas estimate for tokens -- [#7473](https://github.com/MetaMask/metamask-extension/pull/7473): Fix transaction order on transaction confirmation screen +- Fix gas estimate for tokens ([#7753](https://github.com/MetaMask/metamask-extension/pull/7753)) +- Fix transaction order on transaction confirmation screen ([#7473](https://github.com/MetaMask/metamask-extension/pull/7473)) ## [7.7.1] - 2019-12-09 ### Uncategorized -- [#7488](https://github.com/MetaMask/metamask-extension/pull/7488): Fix text overlap when expanding transaction -- [#7491](https://github.com/MetaMask/metamask-extension/pull/7491): Update gas when asset is changed on send screen -- [#7500](https://github.com/MetaMask/metamask-extension/pull/7500): Remove unused onClick prop from Dropdown component -- [#7502](https://github.com/MetaMask/metamask-extension/pull/7502): Fix chainId for non standard networks -- [#7519](https://github.com/MetaMask/metamask-extension/pull/7519): Fixing hardware connect error display -- [#7501](https://github.com/MetaMask/metamask-extension/pull/7501): Fix accessibility of first-time-flow terms checkboxes -- [#7579](https://github.com/MetaMask/metamask-extension/pull/7579): Prevent Maker migration dismissal timeout state from being overwritten -- [#7581](https://github.com/MetaMask/metamask-extension/pull/7581): Persist Maker migration dismissal timeout -- [#7484](https://github.com/MetaMask/metamask-extension/pull/7484): Ensure transactions are shown in the order they are received -- [#7604](https://github.com/MetaMask/metamask-extension/pull/7604): Process URL fragment for ens-ipfs redirects -- [#7628](https://github.com/MetaMask/metamask-extension/pull/7628): Fix typo that resulted in degrated account menu performance -- [#7558](https://github.com/MetaMask/metamask-extension/pull/7558): Use localized messages for NotificationModal buttons +- Fix text overlap when expanding transaction ([#7488](https://github.com/MetaMask/metamask-extension/pull/7488)) +- Update gas when asset is changed on send screen ([#7491](https://github.com/MetaMask/metamask-extension/pull/7491)) +- Remove unused onClick prop from Dropdown component ([#7500](https://github.com/MetaMask/metamask-extension/pull/7500)) +- Fix chainId for non standard networks ([#7502](https://github.com/MetaMask/metamask-extension/pull/7502)) +- Fixing hardware connect error display ([#7519](https://github.com/MetaMask/metamask-extension/pull/7519)) +- Fix accessibility of first-time-flow terms checkboxes ([#7501](https://github.com/MetaMask/metamask-extension/pull/7501)) +- Prevent Maker migration dismissal timeout state from being overwritten ([#7579](https://github.com/MetaMask/metamask-extension/pull/7579)) +- Persist Maker migration dismissal timeout ([#7581](https://github.com/MetaMask/metamask-extension/pull/7581)) +- Ensure transactions are shown in the order they are received ([#7484](https://github.com/MetaMask/metamask-extension/pull/7484)) +- Process URL fragment for ens-ipfs redirects ([#7604](https://github.com/MetaMask/metamask-extension/pull/7604)) +- Fix typo that resulted in degrated account menu performance ([#7628](https://github.com/MetaMask/metamask-extension/pull/7628)) +- Use localized messages for NotificationModal buttons ([#7558](https://github.com/MetaMask/metamask-extension/pull/7558)) ## [7.7.0] - 2019-12-03 [WITHDRAWN] ### Uncategorized -- [#7004](https://github.com/MetaMask/metamask-extension/pull/7004): Connect distinct accounts per site -- [#7480](https://github.com/MetaMask/metamask-extension/pull/7480): Fixed link on root README.md -- [#7482](https://github.com/MetaMask/metamask-extension/pull/7482): Update Wyre ETH purchase url -- [#7484](https://github.com/MetaMask/metamask-extension/pull/7484): Ensure transactions are shown in the order they are received -- [#7491](https://github.com/MetaMask/metamask-extension/pull/7491): Update gas when token is changed on the send screen -- [#7501](https://github.com/MetaMask/metamask-extension/pull/7501): Fix accessibility of first-time-flow terms checkboxes -- [#7502](https://github.com/MetaMask/metamask-extension/pull/7502): Fix chainId for non standard networks -- [#7579](https://github.com/MetaMask/metamask-extension/pull/7579): Fix timing of DAI migration notifications after dismissal -- [#7519](https://github.com/MetaMask/metamask-extension/pull/7519): Fixing hardware connect error display -- [#7558](https://github.com/MetaMask/metamask-extension/pull/7558): Use localized messages for NotificationModal buttons -- [#7488](https://github.com/MetaMask/metamask-extension/pull/7488): Fix text overlap when expanding transaction +- Connect distinct accounts per site ([#7004](https://github.com/MetaMask/metamask-extension/pull/7004)) +- Fixed link on root README.md ([#7480](https://github.com/MetaMask/metamask-extension/pull/7480)) +- Update Wyre ETH purchase url ([#7482](https://github.com/MetaMask/metamask-extension/pull/7482)) +- Ensure transactions are shown in the order they are received ([#7484](https://github.com/MetaMask/metamask-extension/pull/7484)) +- Update gas when token is changed on the send screen ([#7491](https://github.com/MetaMask/metamask-extension/pull/7491)) +- Fix accessibility of first-time-flow terms checkboxes ([#7501](https://github.com/MetaMask/metamask-extension/pull/7501)) +- Fix chainId for non standard networks ([#7502](https://github.com/MetaMask/metamask-extension/pull/7502)) +- Fix timing of DAI migration notifications after dismissal ([#7579](https://github.com/MetaMask/metamask-extension/pull/7579)) +- Fixing hardware connect error display ([#7519](https://github.com/MetaMask/metamask-extension/pull/7519)) +- Use localized messages for NotificationModal buttons ([#7558](https://github.com/MetaMask/metamask-extension/pull/7558)) +- Fix text overlap when expanding transaction ([#7488](https://github.com/MetaMask/metamask-extension/pull/7488)) ## [7.6.1] - 2019-11-19 ### Uncategorized -- [#7475](https://github.com/MetaMask/metamask-extension/pull/7475): Add 'Remind Me Later' to the Maker notification -- [#7436](https://github.com/MetaMask/metamask-extension/pull/7436): Add additional rpcUrl verification -- [#7468](https://github.com/MetaMask/metamask-extension/pull/7468): Show transaction fee units on approve screen +- Add 'Remind Me Later' to the Maker notification ([#7475](https://github.com/MetaMask/metamask-extension/pull/7475)) +- Add additional rpcUrl verification ([#7436](https://github.com/MetaMask/metamask-extension/pull/7436)) +- Show transaction fee units on approve screen ([#7468](https://github.com/MetaMask/metamask-extension/pull/7468)) ## [7.6.0] - 2019-11-18 ### Uncategorized -- [#7450](https://github.com/MetaMask/metamask-extension/pull/7450): Add migration notification for users with non-zero Sai -- [#7461](https://github.com/MetaMask/metamask-extension/pull/7461): Import styles for showing multiple notifications -- [#7451](https://github.com/MetaMask/metamask-extension/pull/7451): Add button disabled when password is empty +- Add migration notification for users with non-zero Sai ([#7450](https://github.com/MetaMask/metamask-extension/pull/7450)) +- Import styles for showing multiple notifications ([#7461](https://github.com/MetaMask/metamask-extension/pull/7461)) +- Add button disabled when password is empty ([#7451](https://github.com/MetaMask/metamask-extension/pull/7451)) ## [7.5.3] - 2019-11-15 ### Uncategorized -- [#7412](https://github.com/MetaMask/metamask-extension/pull/7412): lock eth-contract-metadata (#7412) -- [#7416](https://github.com/MetaMask/metamask-extension/pull/7416): Add eslint import plugin to help detect unresolved paths -- [#7414](https://github.com/MetaMask/metamask-extension/pull/7414): Ensure SignatureRequestOriginal 'beforeunload' handler is bound (#7414) -- [#7430](https://github.com/MetaMask/metamask-extension/pull/7430): Update badge colour -- [#7408](https://github.com/MetaMask/metamask-extension/pull/7408): Utilize the full size of icon space (#7408) -- [#7431](https://github.com/MetaMask/metamask-extension/pull/7431): Add all icons to manifest (#7431) -- [#7426](https://github.com/MetaMask/metamask-extension/pull/7426): Ensure Etherscan result is valid before reading it (#7426) -- [#7434](https://github.com/MetaMask/metamask-extension/pull/7434): Update 512px icon (#7434) -- [#7410](https://github.com/MetaMask/metamask-extension/pull/7410): Fix sourcemaps for Sentry -- [#7420](https://github.com/MetaMask/metamask-extension/pull/7420): Adds and end to end test for typed signature requests -- [#7439](https://github.com/MetaMask/metamask-extension/pull/7439): Add metricsEvent to contextTypes (#7439) -- [#7419](https://github.com/MetaMask/metamask-extension/pull/7419): Added webRequest.RequestFilter to filter main_frame .eth requests (#7419) +- lock eth-contract-metadata ([#7412](https://github.com/MetaMask/metamask-extension/pull/7412)) +- Add eslint import plugin to help detect unresolved paths ([#7416](https://github.com/MetaMask/metamask-extension/pull/7416)) +- Ensure SignatureRequestOriginal 'beforeunload' handler is bound ([#7414](https://github.com/MetaMask/metamask-extension/pull/7414)) +- Update badge colour ([#7430](https://github.com/MetaMask/metamask-extension/pull/7430)) +- Utilize the full size of icon space ([#7408](https://github.com/MetaMask/metamask-extension/pull/7408)) +- Add all icons to manifest ([#7431](https://github.com/MetaMask/metamask-extension/pull/7431)) +- Ensure Etherscan result is valid before reading it ([#7426](https://github.com/MetaMask/metamask-extension/pull/7426)) +- Update 512px icon ([#7434](https://github.com/MetaMask/metamask-extension/pull/7434)) +- Fix sourcemaps for Sentry ([#7410](https://github.com/MetaMask/metamask-extension/pull/7410)) +- Adds and end to end test for typed signature requests ([#7420](https://github.com/MetaMask/metamask-extension/pull/7420)) +- Add metricsEvent to contextTypes ([#7439](https://github.com/MetaMask/metamask-extension/pull/7439)) +- Added webRequest.RequestFilter to filter main_frame .eth requests ([#7419](https://github.com/MetaMask/metamask-extension/pull/7419)) ## [7.5.2] - 2019-11-14 ### Uncategorized -- [#7414](https://github.com/MetaMask/metamask-extension/pull/7414): Ensure SignatureRequestOriginal 'beforeunload' handler is bound +- Ensure SignatureRequestOriginal 'beforeunload' handler is bound ([#7414](https://github.com/MetaMask/metamask-extension/pull/7414)) ## [7.5.1] - 2019-11-13 ### Uncategorized -- [#7402](https://github.com/MetaMask/metamask-extension/pull/7402): Fix regression for signed types data screens -- [#7390](https://github.com/MetaMask/metamask-extension/pull/7390): Update json-rpc-engine -- [#7401](https://github.com/MetaMask/metamask-extension/pull/7401): Reject connection request on window close +- Fix regression for signed types data screens ([#7402](https://github.com/MetaMask/metamask-extension/pull/7402)) +- Update json-rpc-engine ([#7390](https://github.com/MetaMask/metamask-extension/pull/7390)) +- Reject connection request on window close ([#7401](https://github.com/MetaMask/metamask-extension/pull/7401)) ## [7.5.0] - 2019-11-12 ### Uncategorized -- [#7328](https://github.com/MetaMask/metamask-extension/pull/7328): ignore known transactions on first broadcast and continue with normal flow -- [#7327](https://github.com/MetaMask/metamask-extension/pull/7327): eth_getTransactionByHash will now check metamask's local history for pending transactions -- [#7333](https://github.com/MetaMask/metamask-extension/pull/7333): Cleanup beforeunload handler after transaction is resolved -- [#7038](https://github.com/MetaMask/metamask-extension/pull/7038): Add support for ZeroNet -- [#7334](https://github.com/MetaMask/metamask-extension/pull/7334): Add web3 deprecation warning -- [#6924](https://github.com/MetaMask/metamask-extension/pull/6924): Add Estimated time to pending tx -- [#7177](https://github.com/MetaMask/metamask-extension/pull/7177): ENS Reverse Resolution support -- [#6891](https://github.com/MetaMask/metamask-extension/pull/6891): New signature request v3 UI -- [#7348](https://github.com/MetaMask/metamask-extension/pull/7348): fix width in first time flow button -- [#7271](https://github.com/MetaMask/metamask-extension/pull/7271): Redesign approve screen -- [#7354](https://github.com/MetaMask/metamask-extension/pull/7354): fix account menu width -- [#7379](https://github.com/MetaMask/metamask-extension/pull/7379): Set default advanced tab gas limit -- [#7380](https://github.com/MetaMask/metamask-extension/pull/7380): Fix advanced tab gas chart -- [#7374](https://github.com/MetaMask/metamask-extension/pull/7374): Hide accounts dropdown scrollbars on Firefox -- [#7357](https://github.com/MetaMask/metamask-extension/pull/7357): Update to gaba@1.8.0 -- [#7335](https://github.com/MetaMask/metamask-extension/pull/7335): Add onbeforeunload and have it call onCancel +- ignore known transactions on first broadcast and continue with normal flow ([#7328](https://github.com/MetaMask/metamask-extension/pull/7328)) +- eth_getTransactionByHash will now check metamask's local history for pending transactions ([#7327](https://github.com/MetaMask/metamask-extension/pull/7327)) +- Cleanup beforeunload handler after transaction is resolved ([#7333](https://github.com/MetaMask/metamask-extension/pull/7333)) +- Add support for ZeroNet ([#7038](https://github.com/MetaMask/metamask-extension/pull/7038)) +- Add web3 deprecation warning ([#7334](https://github.com/MetaMask/metamask-extension/pull/7334)) +- Add Estimated time to pending tx ([#6924](https://github.com/MetaMask/metamask-extension/pull/6924)) +- ENS Reverse Resolution support ([#7177](https://github.com/MetaMask/metamask-extension/pull/7177)) +- New signature request v3 UI ([#6891](https://github.com/MetaMask/metamask-extension/pull/6891)) +- fix width in first time flow button ([#7348](https://github.com/MetaMask/metamask-extension/pull/7348)) +- Redesign approve screen ([#7271](https://github.com/MetaMask/metamask-extension/pull/7271)) +- fix account menu width ([#7354](https://github.com/MetaMask/metamask-extension/pull/7354)) +- Set default advanced tab gas limit ([#7379](https://github.com/MetaMask/metamask-extension/pull/7379)) +- Fix advanced tab gas chart ([#7380](https://github.com/MetaMask/metamask-extension/pull/7380)) +- Hide accounts dropdown scrollbars on Firefox ([#7374](https://github.com/MetaMask/metamask-extension/pull/7374)) +- Update to gaba@1.8.0 ([#7357](https://github.com/MetaMask/metamask-extension/pull/7357)) +- Add onbeforeunload and have it call onCancel ([#7335](https://github.com/MetaMask/metamask-extension/pull/7335)) ## [7.4.0] - 2019-11-04 ### Uncategorized -- [#7186](https://github.com/MetaMask/metamask-extension/pull/7186): Use `AdvancedGasInputs` in `AdvancedTabContent` -- [#7304](https://github.com/MetaMask/metamask-extension/pull/7304): Move signTypedData signing out to keyrings -- [#7306](https://github.com/MetaMask/metamask-extension/pull/7306): correct the zh-TW translation -- [#7309](https://github.com/MetaMask/metamask-extension/pull/7309): Freeze Promise global on boot -- [#7296](https://github.com/MetaMask/metamask-extension/pull/7296): Add "Retry" option for failed transactions -- [#7319](https://github.com/MetaMask/metamask-extension/pull/7319): Fix transaction list item status spacing issue -- [#7218](https://github.com/MetaMask/metamask-extension/pull/7218): Add hostname and extensionId to site metadata -- [#7324](https://github.com/MetaMask/metamask-extension/pull/7324): Fix contact deletion -- [#7326](https://github.com/MetaMask/metamask-extension/pull/7326): Fix edit contact details -- [#7325](https://github.com/MetaMask/metamask-extension/pull/7325): Update eth-json-rpc-filters to fix memory leak -- [#7334](https://github.com/MetaMask/metamask-extension/pull/7334): Add web3 deprecation warning +- Use `AdvancedGasInputs` in `AdvancedTabContent` ([#7186](https://github.com/MetaMask/metamask-extension/pull/7186)) +- Move signTypedData signing out to keyrings ([#7304](https://github.com/MetaMask/metamask-extension/pull/7304)) +- correct the zh-TW translation ([#7306](https://github.com/MetaMask/metamask-extension/pull/7306)) +- Freeze Promise global on boot ([#7309](https://github.com/MetaMask/metamask-extension/pull/7309)) +- Add "Retry" option for failed transactions ([#7296](https://github.com/MetaMask/metamask-extension/pull/7296)) +- Fix transaction list item status spacing issue ([#7319](https://github.com/MetaMask/metamask-extension/pull/7319)) +- Add hostname and extensionId to site metadata ([#7218](https://github.com/MetaMask/metamask-extension/pull/7218)) +- Fix contact deletion ([#7324](https://github.com/MetaMask/metamask-extension/pull/7324)) +- Fix edit contact details ([#7326](https://github.com/MetaMask/metamask-extension/pull/7326)) +- Update eth-json-rpc-filters to fix memory leak ([#7325](https://github.com/MetaMask/metamask-extension/pull/7325)) +- Add web3 deprecation warning ([#7334](https://github.com/MetaMask/metamask-extension/pull/7334)) ## [7.3.1] - 2019-10-22 ### Uncategorized -- [#7298](https://github.com/MetaMask/metamask-extension/pull/7298): Turn off full screen vs popup a/b test +- Turn off full screen vs popup a/b test ([#7298](https://github.com/MetaMask/metamask-extension/pull/7298)) ## [7.3.0] - 2019-10-21 ### Uncategorized -- [#6972](https://github.com/MetaMask/metamask-extension/pull/6972): 3box integration -- [#7168](https://github.com/MetaMask/metamask-extension/pull/7168): Add fixes for German translations -- [#7170](https://github.com/MetaMask/metamask-extension/pull/7170): Remove the disk store -- [#7176](https://github.com/MetaMask/metamask-extension/pull/7176): Performance: Delivery optimized images -- [#7189](https://github.com/MetaMask/metamask-extension/pull/7189): add goerli to incoming tx -- [#7190](https://github.com/MetaMask/metamask-extension/pull/7190): Remove unused locale messages -- [#7173](https://github.com/MetaMask/metamask-extension/pull/7173): Fix RPC error messages -- [#7205](https://github.com/MetaMask/metamask-extension/pull/7205): address book entries by chainId -- [#7207](https://github.com/MetaMask/metamask-extension/pull/7207): obs-store/local-store should upgrade webextension error to real error -- [#7162](https://github.com/MetaMask/metamask-extension/pull/7162): Add a/b test for full screen transaction confirmations -- [#7089](https://github.com/MetaMask/metamask-extension/pull/7089): Add advanced setting to enable editing nonce on confirmation screens -- [#7239](https://github.com/MetaMask/metamask-extension/pull/7239): Update ETH logo, update deposit Ether logo height and width -- [#7255](https://github.com/MetaMask/metamask-extension/pull/7255): Use translated string for state log -- [#7266](https://github.com/MetaMask/metamask-extension/pull/7266): fix issue of xyz ens not resolving -- [#7253](https://github.com/MetaMask/metamask-extension/pull/7253): Prevent Logout Timer that's longer than a week. -- [#7285](https://github.com/MetaMask/metamask-extension/pull/7285): Lessen the length of ENS validation to 3 -- [#7287](https://github.com/MetaMask/metamask-extension/pull/7287): Fix phishing detect script +- 3box integration ([#6972](https://github.com/MetaMask/metamask-extension/pull/6972)) +- Add fixes for German translations ([#7168](https://github.com/MetaMask/metamask-extension/pull/7168)) +- Remove the disk store ([#7170](https://github.com/MetaMask/metamask-extension/pull/7170)) +- Performance: Delivery optimized images ([#7176](https://github.com/MetaMask/metamask-extension/pull/7176)) +- add goerli to incoming tx ([#7189](https://github.com/MetaMask/metamask-extension/pull/7189)) +- Remove unused locale messages ([#7190](https://github.com/MetaMask/metamask-extension/pull/7190)) +- Fix RPC error messages ([#7173](https://github.com/MetaMask/metamask-extension/pull/7173)) +- address book entries by chainId ([#7205](https://github.com/MetaMask/metamask-extension/pull/7205)) +- obs-store/local-store should upgrade webextension error to real error ([#7207](https://github.com/MetaMask/metamask-extension/pull/7207)) +- Add a/b test for full screen transaction confirmations ([#7162](https://github.com/MetaMask/metamask-extension/pull/7162)) +- Add advanced setting to enable editing nonce on confirmation screens ([#7089](https://github.com/MetaMask/metamask-extension/pull/7089)) +- Update ETH logo, update deposit Ether logo height and width ([#7239](https://github.com/MetaMask/metamask-extension/pull/7239)) +- Use translated string for state log ([#7255](https://github.com/MetaMask/metamask-extension/pull/7255)) +- fix issue of xyz ens not resolving ([#7266](https://github.com/MetaMask/metamask-extension/pull/7266)) +- Prevent Logout Timer that's longer than a week. ([#7253](https://github.com/MetaMask/metamask-extension/pull/7253)) +- Lessen the length of ENS validation to 3 ([#7285](https://github.com/MetaMask/metamask-extension/pull/7285)) +- Fix phishing detect script ([#7287](https://github.com/MetaMask/metamask-extension/pull/7287)) ## [7.2.3] - 2019-10-08 ### Uncategorized -- [#7252](https://github.com/MetaMask/metamask-extension/pull/7252): Fix gas limit when sending tx without data to a contract -- [#7260](https://github.com/MetaMask/metamask-extension/pull/7260): Do not transate on seed phrases -- [#7252](https://github.com/MetaMask/metamask-extension/pull/7252): Ensure correct tx category when sending to contracts without tx data +- Fix gas limit when sending tx without data to a contract ([#7252](https://github.com/MetaMask/metamask-extension/pull/7252)) +- Do not transate on seed phrases ([#7260](https://github.com/MetaMask/metamask-extension/pull/7260)) +- Ensure correct tx category when sending to contracts without tx data ([#7252](https://github.com/MetaMask/metamask-extension/pull/7252)) ## [7.2.2] - 2019-09-25 ### Uncategorized -- [#7213](https://github.com/MetaMask/metamask-extension/pull/7213): Update minimum Firefox verison to 56.0 +- Update minimum Firefox verison to 56.0 ([#7213](https://github.com/MetaMask/metamask-extension/pull/7213)) ## [7.2.1] - 2019-09-17 ### Uncategorized -- [#7180](https://github.com/MetaMask/metamask-extension/pull/7180): Add `appName` message to each locale +- Add `appName` message to each locale ([#7180](https://github.com/MetaMask/metamask-extension/pull/7180)) ## [7.2.0] - 2019-09-17 ### Uncategorized -- [#7099](https://github.com/MetaMask/metamask-extension/pull/7099): Update localization from Transifex Brave -- [#7137](https://github.com/MetaMask/metamask-extension/pull/7137): Fix validation of empty block explorer url's in custom network form -- [#7128](https://github.com/MetaMask/metamask-extension/pull/7128): Support for eth_signTypedData_v4 -- [#7110](https://github.com/MetaMask/metamask-extension/pull/7110): Adds `chaindIdChanged` event to the ethereum provider -- [#7091](https://github.com/MetaMask/metamask-extension/pull/7091): Improve browser performance issues caused by missing locale errors -- [#7085](https://github.com/MetaMask/metamask-extension/pull/7085): Prevent ineffectual speed ups of pending transactions that don't have the lowest nonce -- [#7156](https://github.com/MetaMask/metamask-extension/pull/7156): Set minimum Firefox version to v56.2 to support Waterfox -- [#7157](https://github.com/MetaMask/metamask-extension/pull/7157): Add polyfill for AbortController -- [#7161](https://github.com/MetaMask/metamask-extension/pull/7161): Replace `undefined` selectedAddress with `null` -- [#7171](https://github.com/MetaMask/metamask-extension/pull/7171): Fix recipient field of approve screen +- Update localization from Transifex Brave ([#7099](https://github.com/MetaMask/metamask-extension/pull/7099)) +- Fix validation of empty block explorer url's in custom network form ([#7137](https://github.com/MetaMask/metamask-extension/pull/7137)) +- Support for eth_signTypedData_v4 ([#7128](https://github.com/MetaMask/metamask-extension/pull/7128)) +- Adds `chaindIdChanged` event to the ethereum provider ([#7110](https://github.com/MetaMask/metamask-extension/pull/7110)) +- Improve browser performance issues caused by missing locale errors ([#7091](https://github.com/MetaMask/metamask-extension/pull/7091)) +- Prevent ineffectual speed ups of pending transactions that don't have the lowest nonce ([#7085](https://github.com/MetaMask/metamask-extension/pull/7085)) +- Set minimum Firefox version to v56.2 to support Waterfox ([#7156](https://github.com/MetaMask/metamask-extension/pull/7156)) +- Add polyfill for AbortController ([#7157](https://github.com/MetaMask/metamask-extension/pull/7157)) +- Replace `undefined` selectedAddress with `null` ([#7161](https://github.com/MetaMask/metamask-extension/pull/7161)) +- Fix recipient field of approve screen ([#7171](https://github.com/MetaMask/metamask-extension/pull/7171)) ## [7.1.1] - 2019-09-03 ### Uncategorized -- [#7059](https://github.com/MetaMask/metamask-extension/pull/7059): Remove blockscale, replace with ethgasstation -- [#7037](https://github.com/MetaMask/metamask-extension/pull/7037): Remove Babel 6 from internal dependencies -- [#7093](https://github.com/MetaMask/metamask-extension/pull/7093): Allow dismissing privacy mode notification from popup -- [#7087](https://github.com/MetaMask/metamask-extension/pull/7087): Add breadcrumb spacing on Contacts page -- [#7081](https://github.com/MetaMask/metamask-extension/pull/7081): Fix confirm token transaction amount display -- [#7088](https://github.com/MetaMask/metamask-extension/pull/7088): Fix BigNumber conversion error -- [#7072](https://github.com/MetaMask/metamask-extension/pull/7072): Right-to-left CSS (using module for conversion) -- [#6878](https://github.com/MetaMask/metamask-extension/pull/6878): Persian translation -- [#7012](https://github.com/MetaMask/metamask-extension/pull/7012): Added missed phrases to RU locale +- Remove blockscale, replace with ethgasstation ([#7059](https://github.com/MetaMask/metamask-extension/pull/7059)) +- Remove Babel 6 from internal dependencies ([#7037](https://github.com/MetaMask/metamask-extension/pull/7037)) +- Allow dismissing privacy mode notification from popup ([#7093](https://github.com/MetaMask/metamask-extension/pull/7093)) +- Add breadcrumb spacing on Contacts page ([#7087](https://github.com/MetaMask/metamask-extension/pull/7087)) +- Fix confirm token transaction amount display ([#7081](https://github.com/MetaMask/metamask-extension/pull/7081)) +- Fix BigNumber conversion error ([#7088](https://github.com/MetaMask/metamask-extension/pull/7088)) +- Right-to-left CSS ([#7072](https://github.com/MetaMask/metamask-extension/pull/7072)) +- Persian translation ([#6878](https://github.com/MetaMask/metamask-extension/pull/6878)) +- Added missed phrases to RU locale ([#7012](https://github.com/MetaMask/metamask-extension/pull/7012)) ## [7.1.0] - 2019-08-26 ### Uncategorized -- [#7035](https://github.com/MetaMask/metamask-extension/pull/7035): Filter non-ERC-20 assets during mobile sync (#7035) -- [#7021](https://github.com/MetaMask/metamask-extension/pull/7021): Using translated string for end of flow messaging (#7021) -- [#7018](https://github.com/MetaMask/metamask-extension/pull/7018): Rename Contacts List settings tab to Contacts (#7018) -- [#7013](https://github.com/MetaMask/metamask-extension/pull/7013): Connections settings tab (#7013) -- [#6996](https://github.com/MetaMask/metamask-extension/pull/6996): Fetch & display received transactions (#6996) -- [#6991](https://github.com/MetaMask/metamask-extension/pull/6991): Remove reload from Share Address button (#6991) -- [#6978](https://github.com/MetaMask/metamask-extension/pull/6978): Address book fixes (#6978) -- [#6944](https://github.com/MetaMask/metamask-extension/pull/6944): Show recipient alias in confirm header if exists (#6944) -- [#6930](https://github.com/MetaMask/metamask-extension/pull/6930): Add support for eth_signTypedData_v4 (#6930) -- [#7046](https://github.com/MetaMask/metamask-extension/pull/7046): Update Italian translation (#7046) -- [#7047](https://github.com/MetaMask/metamask-extension/pull/7047): Add warning about reload on network change +- Filter non-ERC-20 assets during mobile sync ([#7035](https://github.com/MetaMask/metamask-extension/pull/7035)) +- Using translated string for end of flow messaging ([#7021](https://github.com/MetaMask/metamask-extension/pull/7021)) +- Rename Contacts List settings tab to Contacts ([#7018](https://github.com/MetaMask/metamask-extension/pull/7018)) +- Connections settings tab ([#7013](https://github.com/MetaMask/metamask-extension/pull/7013)) +- Fetch & display received transactions ([#6996](https://github.com/MetaMask/metamask-extension/pull/6996)) +- Remove reload from Share Address button ([#6991](https://github.com/MetaMask/metamask-extension/pull/6991)) +- Address book fixes ([#6978](https://github.com/MetaMask/metamask-extension/pull/6978)) +- Show recipient alias in confirm header if exists ([#6944](https://github.com/MetaMask/metamask-extension/pull/6944)) +- Add support for eth_signTypedData_v4 ([#6930](https://github.com/MetaMask/metamask-extension/pull/6930)) +- Update Italian translation ([#7046](https://github.com/MetaMask/metamask-extension/pull/7046)) +- Add warning about reload on network change ([#7047](https://github.com/MetaMask/metamask-extension/pull/7047)) ## [7.0.1] - 2019-08-08 ### Uncategorized -- [#6975](https://github.com/MetaMask/metamask-extension/pull/6975): Ensure seed phrase backup notification only shows up for new users +- Ensure seed phrase backup notification only shows up for new users ([#6975](https://github.com/MetaMask/metamask-extension/pull/6975)) ## [7.0.0] - 2019-08-07 ### Uncategorized -- [#6828](https://github.com/MetaMask/metamask-extension/pull/6828): Capitalized speed up label to match rest of UI -- [#6874](https://github.com/MetaMask/metamask-extension/pull/6928): Allows skipping of seed phrase challenge during onboarding, and completing it at a later time -- [#6900](https://github.com/MetaMask/metamask-extension/pull/6900): Prevent opening of asset dropdown if no tokens in account -- [#6904](https://github.com/MetaMask/metamask-extension/pull/6904): Set privacy mode as default -- [#6914](https://github.com/MetaMask/metamask-extension/pull/6914): Adds Address Book feature -- [#6928](https://github.com/MetaMask/metamask-extension/pull/6928): Disable Copy Tx ID and block explorer link for transactions without hash -- [#6967](https://github.com/MetaMask/metamask-extension/pull/6967): Fix mobile sync +- Capitalized speed up label to match rest of UI ([#6828](https://github.com/MetaMask/metamask-extension/pull/6828)) +- Allows skipping of seed phrase challenge during onboarding, and completing it at a later time ([#6874](https://github.com/MetaMask/metamask-extension/pull/6928)) +- Prevent opening of asset dropdown if no tokens in account ([#6900](https://github.com/MetaMask/metamask-extension/pull/6900)) +- Set privacy mode as default ([#6904](https://github.com/MetaMask/metamask-extension/pull/6904)) +- Adds Address Book feature ([#6914](https://github.com/MetaMask/metamask-extension/pull/6914)) +- Disable Copy Tx ID and block explorer link for transactions without hash ([#6928](https://github.com/MetaMask/metamask-extension/pull/6928)) +- Fix mobile sync ([#6967](https://github.com/MetaMask/metamask-extension/pull/6967)) ## [6.7.3] - 2019-07-19 ### Uncategorized -- [#6888](https://github.com/MetaMask/metamask-extension/pull/6888): Fix bug with resubmitting unsigned transactions. +- Fix bug with resubmitting unsigned transactions. ([#6888](https://github.com/MetaMask/metamask-extension/pull/6888)) ## [6.7.2] - 2019-07-03 ### Uncategorized -- [#6713](https://github.com/MetaMask/metamask-extension/pull/6713): \* Normalize and Validate txParams in TransactionStateManager.addTx too -- [#6759](https://github.com/MetaMask/metamask-extension/pull/6759): Update to Node.js v10 -- [#6694](https://github.com/MetaMask/metamask-extension/pull/6694): Fixes #6694 -- [#6743](https://github.com/MetaMask/metamask-extension/pull/6743): \* Add tests for ImportWithSeedPhrase#parseSeedPhrase -- [#6740](https://github.com/MetaMask/metamask-extension/pull/6740): Fixes #6740 -- [#6741](https://github.com/MetaMask/metamask-extension/pull/6741): Fixes #6741 -- [#6761](https://github.com/MetaMask/metamask-extension/pull/6761): Fixes #6760, correct PropTypes for nextRoute -- [#6754](https://github.com/MetaMask/metamask-extension/pull/6754): Use inline source maps in development -- [#6589](https://github.com/MetaMask/metamask-extension/pull/6589): Document hotfix protocol -- [#6738](https://github.com/MetaMask/metamask-extension/pull/6738): Add codeowner for package-lock-old.json package-lock.json package.json packagelock-old.json files -- [#6648](https://github.com/MetaMask/metamask-extension/pull/6648): Add loading view to notification.html -- [#6731](https://github.com/MetaMask/metamask-extension/pull/6731): Add brave as a platform type for MetaMask +- Normalize and Validate txParams in TransactionStateManager.addTx too ([#6713](https://github.com/MetaMask/metamask-extension/pull/6713)) +- Update to Node.js v10 ([#6759](https://github.com/MetaMask/metamask-extension/pull/6759)) +- Fixes #6694 ([#6694](https://github.com/MetaMask/metamask-extension/pull/6694)) +- Add tests for ImportWithSeedPhrase#parseSeedPhrase ([#6743](https://github.com/MetaMask/metamask-extension/pull/6743)) +- Fixes #6740 ([#6740](https://github.com/MetaMask/metamask-extension/pull/6740)) +- Fixes #6741 ([#6741](https://github.com/MetaMask/metamask-extension/pull/6741)) +- Fixes #6760, correct PropTypes for nextRoute ([#6761](https://github.com/MetaMask/metamask-extension/pull/6761)) +- Use inline source maps in development ([#6754](https://github.com/MetaMask/metamask-extension/pull/6754)) +- Document hotfix protocol ([#6589](https://github.com/MetaMask/metamask-extension/pull/6589)) +- Add codeowner for package-lock-old.json package-lock.json package.json packagelock-old.json files ([#6738](https://github.com/MetaMask/metamask-extension/pull/6738)) +- Add loading view to notification.html ([#6648](https://github.com/MetaMask/metamask-extension/pull/6648)) +- Add brave as a platform type for MetaMask ([#6731](https://github.com/MetaMask/metamask-extension/pull/6731)) ## [6.7.1] - 2019-07-28 ### Uncategorized -- [#6764](https://github.com/MetaMask/metamask-extension/pull/6764): Fix display of token amount on confirm transaction screen +- Fix display of token amount on confirm transaction screen ([#6764](https://github.com/MetaMask/metamask-extension/pull/6764)) ## [6.7.0] - 2019-07-26 ### Uncategorized -- [#6623](https://github.com/MetaMask/metamask-extension/pull/6623): Improve contract method data fetching (#6623) -- [#6551](https://github.com/MetaMask/metamask-extension/pull/6551): Adds 4byte registry fallback to getMethodData() (#6435) -- [#6718](https://github.com/MetaMask/metamask-extension/pull/6718): Add delete to custom RPC form -- [#6700](https://github.com/MetaMask/metamask-extension/pull/6700): Fix styles on 'import account' page, update help link -- [#6714](https://github.com/MetaMask/metamask-extension/pull/6714): Wrap smaller custom block explorer url text -- [#6706](https://github.com/MetaMask/metamask-extension/pull/6706): Pin ethereumjs-tx -- [#6700](https://github.com/MetaMask/metamask-extension/pull/6700): Fix styles on 'import account' page, update help link -- [#6775](https://github.com/MetaMask/metamask-extension/pull/6775): Started adding visual documentation of MetaMask plugin components with the account menu component first +- Improve contract method data fetching ([#6623](https://github.com/MetaMask/metamask-extension/pull/6623)) +- Adds 4byte registry fallback to getMethodData() ([#6551](https://github.com/MetaMask/metamask-extension/pull/6551)) +- Add delete to custom RPC form ([#6718](https://github.com/MetaMask/metamask-extension/pull/6718)) +- Fix styles on 'import account' page, update help link ([#6700](https://github.com/MetaMask/metamask-extension/pull/6700)) +- Wrap smaller custom block explorer url text ([#6714](https://github.com/MetaMask/metamask-extension/pull/6714)) +- Pin ethereumjs-tx ([#6706](https://github.com/MetaMask/metamask-extension/pull/6706)) +- Fix styles on 'import account' page, update help link ([#6700](https://github.com/MetaMask/metamask-extension/pull/6700)) +- Started adding visual documentation of MetaMask plugin components with the account menu component first ([#6775](https://github.com/MetaMask/metamask-extension/pull/6775)) ## [6.6.2] - 2019-07-17 ### Uncategorized -- [#6690](https://github.com/MetaMask/metamask-extension/pull/6690): Update dependencies, re-enable npm audit CI job -- [#6700](https://github.com/MetaMask/metamask-extension/pull/6700): Fix styles on 'import account' page, update help link +- Update dependencies, re-enable npm audit CI job ([#6690](https://github.com/MetaMask/metamask-extension/pull/6690)) +- Fix styles on 'import account' page, update help link ([#6700](https://github.com/MetaMask/metamask-extension/pull/6700)) ## [6.6.1] - 2019-06-06 ### Uncategorized -- [#6691](https://github.com/MetaMask/metamask-extension/pull/6691): Revert "Improve ENS Address Input" to fix bugs on input field on non-main networks. +- Revert "Improve ENS Address Input" to fix bugs on input field on non-main networks. ([#6691](https://github.com/MetaMask/metamask-extension/pull/6691)) ## [6.6.0] - 2019-06-04 ### Uncategorized -- [#6659](https://github.com/MetaMask/metamask-extension/pull/6659): Enable Ledger hardware wallet support on Firefox -- [#6671](https://github.com/MetaMask/metamask-extension/pull/6671): bugfix: reject enable promise on user rejection -- [#6625](https://github.com/MetaMask/metamask-extension/pull/6625): Ensures that transactions cannot be confirmed if gas limit is below 21000. -- [#6633](https://github.com/MetaMask/metamask-extension/pull/6633): Fix grammatical error in i18n endOfFlowMessage6 +- Enable Ledger hardware wallet support on Firefox ([#6659](https://github.com/MetaMask/metamask-extension/pull/6659)) +- bugfix: reject enable promise on user rejection ([#6671](https://github.com/MetaMask/metamask-extension/pull/6671)) +- Ensures that transactions cannot be confirmed if gas limit is below 21000. ([#6625](https://github.com/MetaMask/metamask-extension/pull/6625)) +- Fix grammatical error in i18n endOfFlowMessage6 ([#6633](https://github.com/MetaMask/metamask-extension/pull/6633)) ## [6.5.3] - 2019-05-16 ### Uncategorized -- [#6619](https://github.com/MetaMask/metamask-extension/pull/6619): bugfix: show extension window if locked regardless of approval -- [#6388](https://github.com/MetaMask/metamask-extension/pull/6388): Transactions/pending - check nonce against the network and mark as dropped if not included in a block -- [#6606](https://github.com/MetaMask/metamask-extension/pull/6606): Improve ENS Address Input -- [#6615](https://github.com/MetaMask/metamask-extension/pull/6615): Adds e2e test for removing imported accounts. +- bugfix: show extension window if locked regardless of approval ([#6619](https://github.com/MetaMask/metamask-extension/pull/6619)) +- Transactions/pending - check nonce against the network and mark as dropped if not included in a block ([#6388](https://github.com/MetaMask/metamask-extension/pull/6388)) +- Improve ENS Address Input ([#6606](https://github.com/MetaMask/metamask-extension/pull/6606)) +- Adds e2e test for removing imported accounts. ([#6615](https://github.com/MetaMask/metamask-extension/pull/6615)) ## [6.5.2] - 2019-05-15 ### Uncategorized -- [#6613](https://github.com/MetaMask/metamask-extension/pull/6613): Hardware Wallet Fix +- Hardware Wallet Fix ([#6613](https://github.com/MetaMask/metamask-extension/pull/6613)) ## [6.5.1] - 2019-05-14 ### Uncategorized - Fix bug where approve method would show a warning. #6602 -- [#6593](https://github.com/MetaMask/metamask-extension/pull/6593): Fix wording of autoLogoutTimeLimitDescription +- Fix wording of autoLogoutTimeLimitDescription ([#6593](https://github.com/MetaMask/metamask-extension/pull/6593)) ## [6.5.0] - 2019-05-13 ### Uncategorized -- [#6568](https://github.com/MetaMask/metamask-extension/pull/6568): feature: integrate gaba/PhishingController -- [#6490](https://github.com/MetaMask/metamask-extension/pull/6490): Redesign custom RPC form -- [#6558](https://github.com/MetaMask/metamask-extension/pull/6558): Adds auto logout with customizable time frame -- [#6578](https://github.com/MetaMask/metamask-extension/pull/6578): Fixes ability to send to token contract addresses -- [#6557](https://github.com/MetaMask/metamask-extension/pull/6557): Adds drag and drop functionality to seed phrase entry. -- [#6526](https://github.com/MetaMask/metamask-extension/pull/6526): Include token checksum address in prices lookup for token rates -- [#6502](https://github.com/MetaMask/metamask-extension/pull/6502): Add subheader to all settings subviews -- [#6501](https://github.com/MetaMask/metamask-extension/pull/6501): Improve confirm screen loading performance by fixing home screen rendering bug +- feature: integrate gaba/PhishingController ([#6568](https://github.com/MetaMask/metamask-extension/pull/6568)) +- Redesign custom RPC form ([#6490](https://github.com/MetaMask/metamask-extension/pull/6490)) +- Adds auto logout with customizable time frame ([#6558](https://github.com/MetaMask/metamask-extension/pull/6558)) +- Fixes ability to send to token contract addresses ([#6578](https://github.com/MetaMask/metamask-extension/pull/6578)) +- Adds drag and drop functionality to seed phrase entry. ([#6557](https://github.com/MetaMask/metamask-extension/pull/6557)) +- Include token checksum address in prices lookup for token rates ([#6526](https://github.com/MetaMask/metamask-extension/pull/6526)) +- Add subheader to all settings subviews ([#6502](https://github.com/MetaMask/metamask-extension/pull/6502)) +- Improve confirm screen loading performance by fixing home screen rendering bug ([#6501](https://github.com/MetaMask/metamask-extension/pull/6501)) ## [6.4.1] - 2019-04-26 ### Uncategorized -- [#6521](https://github.com/MetaMask/metamask-extension/pull/6521): Revert "Adds 4byte registry fallback to getMethodData()" to fix stalling bug. +- Revert "Adds 4byte registry fallback to getMethodData()" to fix stalling bug. ([#6521](https://github.com/MetaMask/metamask-extension/pull/6521)) ## [6.4.0] - 2019-04-18 ### Uncategorized -- [#6445](https://github.com/MetaMask/metamask-extension/pull/6445): \* Move send to pages/ -- [#6470](https://github.com/MetaMask/metamask-extension/pull/6470): update publishing.md with dev diagram -- [#6403](https://github.com/MetaMask/metamask-extension/pull/6403): Update to eth-method-registry@1.2.0 -- [#6468](https://github.com/MetaMask/metamask-extension/pull/6468): Fix switcher height when Custom RPC is selected or loading -- [#6459](https://github.com/MetaMask/metamask-extension/pull/6459): feature: add Goerli support -- [#6444](https://github.com/MetaMask/metamask-extension/pull/6444): Fixes #6321 & #6421 - Add Localhost 8545 for network dropdown names -- [#6454](https://github.com/MetaMask/metamask-extension/pull/6454): Bump eth-contract-metadata -- [#6448](https://github.com/MetaMask/metamask-extension/pull/6448): Remove unneeded array cloning in getSendToAccounts selector -- [#6056](https://github.com/MetaMask/metamask-extension/pull/6056): repeated getSelectedAddress() func send.selectors.js removed -- [#6422](https://github.com/MetaMask/metamask-extension/pull/6422): Added Chrome limited site access solution doc -- [#6424](https://github.com/MetaMask/metamask-extension/pull/6424): feature: switch token pricing to CoinGecko API -- [#6428](https://github.com/MetaMask/metamask-extension/pull/6428): Don't inject web3 on sharefile.com -- [#6417](https://github.com/MetaMask/metamask-extension/pull/6417): Metrics updates -- [#6420](https://github.com/MetaMask/metamask-extension/pull/6420): Fix links to MetamaskInpageProvider in porting_to_new_environment.md -- [#6362](https://github.com/MetaMask/metamask-extension/pull/6362): Remove broken image walkthrough from metamaskbot comment -- [#6401](https://github.com/MetaMask/metamask-extension/pull/6401): metamask-controller - use improved provider-as-middleware utility -- [#6406](https://github.com/MetaMask/metamask-extension/pull/6406): remove user actions controller -- [#6399](https://github.com/MetaMask/metamask-extension/pull/6399): doc - publishing - typo fix -- [#6396](https://github.com/MetaMask/metamask-extension/pull/6396): pin eth-contract-metadata to last commit hash -- [#6397](https://github.com/MetaMask/metamask-extension/pull/6397): Change coinbase to wyre -- [#6395](https://github.com/MetaMask/metamask-extension/pull/6395): bump ledger and trezor keyring -- [#6389](https://github.com/MetaMask/metamask-extension/pull/6389): Fix display of gas chart on Ethereum networks -- [#6382](https://github.com/MetaMask/metamask-extension/pull/6382): Remove NoticeController +- Move send to pages/ ([#6445](https://github.com/MetaMask/metamask-extension/pull/6445)) +- update publishing.md with dev diagram ([#6470](https://github.com/MetaMask/metamask-extension/pull/6470)) +- Update to eth-method-registry@1.2.0 ([#6403](https://github.com/MetaMask/metamask-extension/pull/6403)) +- Fix switcher height when Custom RPC is selected or loading ([#6468](https://github.com/MetaMask/metamask-extension/pull/6468)) +- feature: add Goerli support ([#6459](https://github.com/MetaMask/metamask-extension/pull/6459)) +- Fixes #6321 & #6421 - Add Localhost 8545 for network dropdown names ([#6444](https://github.com/MetaMask/metamask-extension/pull/6444)) +- Bump eth-contract-metadata ([#6454](https://github.com/MetaMask/metamask-extension/pull/6454)) +- Remove unneeded array cloning in getSendToAccounts selector ([#6448](https://github.com/MetaMask/metamask-extension/pull/6448)) +- repeated getSelectedAddress() func send.selectors.js removed ([#6056](https://github.com/MetaMask/metamask-extension/pull/6056)) +- Added Chrome limited site access solution doc ([#6422](https://github.com/MetaMask/metamask-extension/pull/6422)) +- feature: switch token pricing to CoinGecko API ([#6424](https://github.com/MetaMask/metamask-extension/pull/6424)) +- Don't inject web3 on sharefile.com ([#6428](https://github.com/MetaMask/metamask-extension/pull/6428)) +- Metrics updates ([#6417](https://github.com/MetaMask/metamask-extension/pull/6417)) +- Fix links to MetamaskInpageProvider in porting_to_new_environment.md ([#6420](https://github.com/MetaMask/metamask-extension/pull/6420)) +- Remove broken image walkthrough from metamaskbot comment ([#6362](https://github.com/MetaMask/metamask-extension/pull/6362)) +- metamask-controller - use improved provider-as-middleware utility ([#6401](https://github.com/MetaMask/metamask-extension/pull/6401)) +- remove user actions controller ([#6406](https://github.com/MetaMask/metamask-extension/pull/6406)) +- doc - publishing - typo fix ([#6399](https://github.com/MetaMask/metamask-extension/pull/6399)) +- pin eth-contract-metadata to last commit hash ([#6396](https://github.com/MetaMask/metamask-extension/pull/6396)) +- Change coinbase to wyre ([#6397](https://github.com/MetaMask/metamask-extension/pull/6397)) +- bump ledger and trezor keyring ([#6395](https://github.com/MetaMask/metamask-extension/pull/6395)) +- Fix display of gas chart on Ethereum networks ([#6389](https://github.com/MetaMask/metamask-extension/pull/6389)) +- Remove NoticeController ([#6382](https://github.com/MetaMask/metamask-extension/pull/6382)) ## [6.3.2] - 2019-04-08 ### Uncategorized -- [#6389](https://github.com/MetaMask/metamask-extension/pull/6389): Fix display of gas chart on ethereum networks -- [#6395](https://github.com/MetaMask/metamask-extension/pull/6395): Fixes for signing methods for ledger and trezor devices -- [#6397](https://github.com/MetaMask/metamask-extension/pull/6397): Fix Wyre link +- Fix display of gas chart on ethereum networks ([#6389](https://github.com/MetaMask/metamask-extension/pull/6389)) +- Fixes for signing methods for ledger and trezor devices ([#6395](https://github.com/MetaMask/metamask-extension/pull/6395)) +- Fix Wyre link ([#6397](https://github.com/MetaMask/metamask-extension/pull/6397)) ## [6.3.1] - 2019-03-29 ### Uncategorized -- [#6353](https://github.com/MetaMask/metamask-extension/pull/6353): Open restore vault in full screen when clicked from popup -- [#6372](https://github.com/MetaMask/metamask-extension/pull/6372): Prevents duplicates of account addresses from showing in send screen "To" dropdown -- [#6374](https://github.com/MetaMask/metamask-extension/pull/6374): Ensures users are placed on correct confirm screens even when registry service fails +- Open restore vault in full screen when clicked from popup ([#6353](https://github.com/MetaMask/metamask-extension/pull/6353)) +- Prevents duplicates of account addresses from showing in send screen "To" dropdown ([#6372](https://github.com/MetaMask/metamask-extension/pull/6372)) +- Ensures users are placed on correct confirm screens even when registry service fails ([#6374](https://github.com/MetaMask/metamask-extension/pull/6374)) ## [6.3.0] - 2019-03-26 ### Uncategorized -- [#6300](https://github.com/MetaMask/metamask-extension/pull/6300): Gas chart hidden on custom networks -- [#6301](https://github.com/MetaMask/metamask-extension/pull/6301): Fix gas fee in the submitted step of the transaction details activity log -- [#6302](https://github.com/MetaMask/metamask-extension/pull/6302): Replaces the coinbase link in the deposit modal with one for wyre -- [#6307](https://github.com/MetaMask/metamask-extension/pull/6307): Centre the notification in the current window -- [#6312](https://github.com/MetaMask/metamask-extension/pull/6312): Fixes popups not showing when screen size is odd -- [#6326](https://github.com/MetaMask/metamask-extension/pull/6326): Fix oversized loading overlay on gas customization modal. -- [#6330](https://github.com/MetaMask/metamask-extension/pull/6330): Stop reloading dapps on network change allowing dapps to decide if it should refresh or not -- [#6332](https://github.com/MetaMask/metamask-extension/pull/6332): Enable mobile sync -- [#6333](https://github.com/MetaMask/metamask-extension/pull/6333): Redesign of the settings screen -- [#6340](https://github.com/MetaMask/metamask-extension/pull/6340): Cancel transactions and signature requests on the closing of notification windows -- [#6341](https://github.com/MetaMask/metamask-extension/pull/6341): Disable transaction "Cancel" button when balance is insufficient -- [#6347](https://github.com/MetaMask/metamask-extension/pull/6347): Enable privacy mode by default for first time users +- Gas chart hidden on custom networks ([#6300](https://github.com/MetaMask/metamask-extension/pull/6300)) +- Fix gas fee in the submitted step of the transaction details activity log ([#6301](https://github.com/MetaMask/metamask-extension/pull/6301)) +- Replaces the coinbase link in the deposit modal with one for wyre ([#6302](https://github.com/MetaMask/metamask-extension/pull/6302)) +- Centre the notification in the current window ([#6307](https://github.com/MetaMask/metamask-extension/pull/6307)) +- Fixes popups not showing when screen size is odd ([#6312](https://github.com/MetaMask/metamask-extension/pull/6312)) +- Fix oversized loading overlay on gas customization modal. ([#6326](https://github.com/MetaMask/metamask-extension/pull/6326)) +- Stop reloading dapps on network change allowing dapps to decide if it should refresh or not ([#6330](https://github.com/MetaMask/metamask-extension/pull/6330)) +- Enable mobile sync ([#6332](https://github.com/MetaMask/metamask-extension/pull/6332)) +- Redesign of the settings screen ([#6333](https://github.com/MetaMask/metamask-extension/pull/6333)) +- Cancel transactions and signature requests on the closing of notification windows ([#6340](https://github.com/MetaMask/metamask-extension/pull/6340)) +- Disable transaction "Cancel" button when balance is insufficient ([#6341](https://github.com/MetaMask/metamask-extension/pull/6341)) +- Enable privacy mode by default for first time users ([#6347](https://github.com/MetaMask/metamask-extension/pull/6347)) ## [6.2.2] - 2019-03-12 ### Uncategorized -- [#6271](https://github.com/MetaMask/metamask-extension/pull/6271): Centre all notification popups -- [#6268](https://github.com/MetaMask/metamask-extension/pull/6268): Improve Korean translations -- [#6279](https://github.com/MetaMask/metamask-extension/pull/6279): Nonmultiple notifications for batch txs -- [#6280](https://github.com/MetaMask/metamask-extension/pull/6280): No longer check network when validating checksum addresses +- Centre all notification popups ([#6271](https://github.com/MetaMask/metamask-extension/pull/6271)) +- Improve Korean translations ([#6268](https://github.com/MetaMask/metamask-extension/pull/6268)) +- Nonmultiple notifications for batch txs ([#6279](https://github.com/MetaMask/metamask-extension/pull/6279)) +- No longer check network when validating checksum addresses ([#6280](https://github.com/MetaMask/metamask-extension/pull/6280)) ## [6.2.1] - 2019-03-11 ## [6.2.0] - 2019-03-05 ### Uncategorized -- [#6192](https://github.com/MetaMask/metamask-extension/pull/6192): Improves design and UX of onboarding flow -- [#6195](https://github.com/MetaMask/metamask-extension/pull/6195): Fixes gas estimation when sending to contracts -- [#6223](https://github.com/MetaMask/metamask-extension/pull/6223): Fixes display of notification windows when metamask is active in a tab -- [#6171](https://github.com/MetaMask/metamask-extension/pull/6171): Adds MetaMetrics usage analytics system +- Improves design and UX of onboarding flow ([#6192](https://github.com/MetaMask/metamask-extension/pull/6192)) +- Fixes gas estimation when sending to contracts ([#6195](https://github.com/MetaMask/metamask-extension/pull/6195)) +- Fixes display of notification windows when metamask is active in a tab ([#6223](https://github.com/MetaMask/metamask-extension/pull/6223)) +- Adds MetaMetrics usage analytics system ([#6171](https://github.com/MetaMask/metamask-extension/pull/6171)) ## [6.1.0] - 2019-02-20 ### Uncategorized -- [#6182](https://github.com/MetaMask/metamask-extension/pull/6182): Change "Token Address" to "Token Contract Address" -- [#6177](https://github.com/MetaMask/metamask-extension/pull/6177): Fixes #6176 -- [#6146](https://github.com/MetaMask/metamask-extension/pull/6146): \* Add Copy Tx ID button to transaction-list-item-details -- [#6133](https://github.com/MetaMask/metamask-extension/pull/6133): Checksum address before slicing it for the confirm screen -- [#6147](https://github.com/MetaMask/metamask-extension/pull/6147): Add button to force edit token symbol when adding custom token -- [#6124](https://github.com/MetaMask/metamask-extension/pull/6124): recent-blocks - dont listen for block when on infura providers -[#5973] (https://github.com/MetaMask/metamask-extension/pull/5973): Fix incorrectly showing checksums on non-ETH blockchains (issue 5838) +- Change "Token Address" to "Token Contract Address" ([#6182](https://github.com/MetaMask/metamask-extension/pull/6182)) +- Fixes #6176 ([#6177](https://github.com/MetaMask/metamask-extension/pull/6177)) +- Add Copy Tx ID button to transaction-list-item-details ([#6146](https://github.com/MetaMask/metamask-extension/pull/6146)) +- Checksum address before slicing it for the confirm screen ([#6133](https://github.com/MetaMask/metamask-extension/pull/6133)) +- Add button to force edit token symbol when adding custom token ([#6147](https://github.com/MetaMask/metamask-extension/pull/6147)) +- Fix incorrectly showing checksums on non-ETH blockchains ([#6124](https://github.com/MetaMask/metamask-extension/pull/6124): recent-blocks - dont listen for block when on infura providers -[#5973] (https://github.com/MetaMask/metamask-extension/pull/5973)) ## [6.0.1] - 2019-02-12 ### Uncategorized -- [#6139](https://github.com/MetaMask/metamask-extension/pull/6139) Fix advanced gas controls on the confirm screen -- [#6134](https://github.com/MetaMask/metamask-extension/pull/6134) Trim whitespace from seed phrase during import -- [#6119](https://github.com/MetaMask/metamask-extension/pull/6119) Update Italian translation -- [#6125](https://github.com/MetaMask/metamask-extension/pull/6125) Improved Traditional Chinese translation +- Fix advanced gas controls on the confirm screen ([#6139](https://github.com/MetaMask/metamask-extension/pull/6139)) +- Trim whitespace from seed phrase during import ([#6134](https://github.com/MetaMask/metamask-extension/pull/6134)) +- Update Italian translation ([#6119](https://github.com/MetaMask/metamask-extension/pull/6119)) +- Improved Traditional Chinese translation ([#6125](https://github.com/MetaMask/metamask-extension/pull/6125)) ## [6.0.0] - 2019-02-11 ### Uncategorized -- [#6082](https://github.com/MetaMask/metamask-extension/pull/6082): Migrate all users to the new UI -- [#6114](https://github.com/MetaMask/metamask-extension/pull/6114): Add setting for inputting gas price with a text field for advanced users. -- [#6091](https://github.com/MetaMask/metamask-extension/pull/6091): Add Swap feature to CurrencyInput -- [#6090](https://github.com/MetaMask/metamask-extension/pull/6090): Change gas labels to Slow/Average/Fast -- [#6112](https://github.com/MetaMask/metamask-extension/pull/6112): Extract advanced gas input controls to their own component -- [#5929](https://github.com/MetaMask/metamask-extension/pull/5929): Update design of phishing warning screen -- [#6120](https://github.com/MetaMask/metamask-extension/pull/6120): Add class to sign footer button -- [#6116](https://github.com/MetaMask/metamask-extension/pull/6116): Fix locale codes contains underscore never being preferred +- Migrate all users to the new UI ([#6082](https://github.com/MetaMask/metamask-extension/pull/6082)) +- Add setting for inputting gas price with a text field for advanced users. ([#6114](https://github.com/MetaMask/metamask-extension/pull/6114)) +- Add Swap feature to CurrencyInput ([#6091](https://github.com/MetaMask/metamask-extension/pull/6091)) +- Change gas labels to Slow/Average/Fast ([#6090](https://github.com/MetaMask/metamask-extension/pull/6090)) +- Extract advanced gas input controls to their own component ([#6112](https://github.com/MetaMask/metamask-extension/pull/6112)) +- Update design of phishing warning screen ([#5929](https://github.com/MetaMask/metamask-extension/pull/5929)) +- Add class to sign footer button ([#6120](https://github.com/MetaMask/metamask-extension/pull/6120)) +- Fix locale codes contains underscore never being preferred ([#6116](https://github.com/MetaMask/metamask-extension/pull/6116)) ## [5.3.5] - 2019-02-04 ### Uncategorized -- [#6084](https://github.com/MetaMask/metamask-extension/pull/6087): Privacy mode fixes +- Privacy mode fixes ([#6084](https://github.com/MetaMask/metamask-extension/pull/6087)) ## [5.3.4] - 2019-01-31 ### Uncategorized -- [#6079](https://github.com/MetaMask/metamask-extension/pull/6079): fix - migration 30 +- fix - migration 30 ([#6079](https://github.com/MetaMask/metamask-extension/pull/6079)) ## [5.3.3] - 2019-01-30 ### Uncategorized -- [#6006](https://github.com/MetaMask/metamask-extension/pull/6006): Update privacy notice -- [#6072](https://github.com/MetaMask/metamask-extension/pull/6072): Improved Spanish translations -- [#5854](https://github.com/MetaMask/metamask-extension/pull/5854): Add visual indicator when displaying a cached balance. -- [#6044](https://github.com/MetaMask/metamask-extension/pull/6044): Fix bug that interferred with using multiple custom networks. +- Update privacy notice ([#6006](https://github.com/MetaMask/metamask-extension/pull/6006)) +- Improved Spanish translations ([#6072](https://github.com/MetaMask/metamask-extension/pull/6072)) +- Add visual indicator when displaying a cached balance. ([#5854](https://github.com/MetaMask/metamask-extension/pull/5854)) +- Fix bug that interferred with using multiple custom networks. ([#6044](https://github.com/MetaMask/metamask-extension/pull/6044)) ## [5.3.2] - 2019-01-28 ### Uncategorized -- [#6021](https://github.com/MetaMask/metamask-extension/pull/6021): Order shapeshift transactions by time within the transactions list -- [#6052](https://github.com/MetaMask/metamask-extension/pull/6052): Add and use cached method signatures to reduce provider requests -- [#6048](https://github.com/MetaMask/metamask-extension/pull/6048): Refactor BalanceComponent to jsx -- [#6026](https://github.com/MetaMask/metamask-extension/pull/6026): Prevent invalid chainIds when adding custom rpcs -- [#6029](https://github.com/MetaMask/metamask-extension/pull/6029): Fix grammar error in Current Conversion -- [#6024](https://github.com/MetaMask/metamask-extension/pull/6024): Disable account dropdown on signing screens +- Order shapeshift transactions by time within the transactions list ([#6021](https://github.com/MetaMask/metamask-extension/pull/6021)) +- Add and use cached method signatures to reduce provider requests ([#6052](https://github.com/MetaMask/metamask-extension/pull/6052)) +- Refactor BalanceComponent to jsx ([#6048](https://github.com/MetaMask/metamask-extension/pull/6048)) +- Prevent invalid chainIds when adding custom rpcs ([#6026](https://github.com/MetaMask/metamask-extension/pull/6026)) +- Fix grammar error in Current Conversion ([#6029](https://github.com/MetaMask/metamask-extension/pull/6029)) +- Disable account dropdown on signing screens ([#6024](https://github.com/MetaMask/metamask-extension/pull/6024)) ## [5.3.1] - 2019-01-16 ### Uncategorized -- [#5966](https://github.com/MetaMask/metamask-extension/pull/5966): Update Slovenian translation -- [#6005](https://github.com/MetaMask/metamask-extension/pull/6005): Set auto conversion off for token/eth conversion -- [#6008](https://github.com/MetaMask/metamask-extension/pull/6008): Fix confirm screen for sending ether tx with hex data -- [#5999](https://github.com/MetaMask/metamask-extension/pull/5999): Refine app description -- [#5997](https://github.com/MetaMask/metamask-extension/pull/5997): Harden Drizzle test runner script -- [#5995](https://github.com/MetaMask/metamask-extension/pull/5995): Fix bug where MetaMask user calls non-standard ERC20 methods such as `mint`, `tokenData` will be `undefined` and an uncaught error will break the UI -- [#5970](https://github.com/MetaMask/metamask-extension/pull/5970): Fixed a word in french translation (several occurrences of connection instead of connexion) -- [#5977](https://github.com/MetaMask/metamask-extension/pull/5977): Fix Component#componentDidUpdate usage -- [#5992](https://github.com/MetaMask/metamask-extension/pull/5992): Add scrolling button to account list -- [#5989](https://github.com/MetaMask/metamask-extension/pull/5989): fix typo in phishing.html title +- Update Slovenian translation ([#5966](https://github.com/MetaMask/metamask-extension/pull/5966)) +- Set auto conversion off for token/eth conversion ([#6005](https://github.com/MetaMask/metamask-extension/pull/6005)) +- Fix confirm screen for sending ether tx with hex data ([#6008](https://github.com/MetaMask/metamask-extension/pull/6008)) +- Refine app description ([#5999](https://github.com/MetaMask/metamask-extension/pull/5999)) +- Harden Drizzle test runner script ([#5997](https://github.com/MetaMask/metamask-extension/pull/5997)) +- Fix bug where MetaMask user calls non-standard ERC20 methods such as `mint`, `tokenData` will be `undefined` and an uncaught error will break the UI ([#5995](https://github.com/MetaMask/metamask-extension/pull/5995)) +- Fixed a word in french translation ([#5970](https://github.com/MetaMask/metamask-extension/pull/5970)) +- Fix Component#componentDidUpdate usage ([#5977](https://github.com/MetaMask/metamask-extension/pull/5977)) +- Add scrolling button to account list ([#5992](https://github.com/MetaMask/metamask-extension/pull/5992)) +- fix typo in phishing.html title ([#5989](https://github.com/MetaMask/metamask-extension/pull/5989)) ## [5.3.0] - 2019-01-02 ### Uncategorized -- [#5978](https://github.com/MetaMask/metamask-extension/pull/5978): Fix etherscan links on notifications -- [#5980](https://github.com/MetaMask/metamask-extension/pull/5980): Fix drizzle tests -- [#5922](https://github.com/MetaMask/metamask-extension/pull/5922): Prevent users from changing the From field in the send screen -- [#5932](https://github.com/MetaMask/metamask-extension/pull/5932): Fix displayed time and date in the activity log. Remove vreme library, add luxon library. -- [#5924](https://github.com/MetaMask/metamask-extension/pull/5924): transactions - throw an error if a transaction is generated while the network is loading -- [#5893](https://github.com/MetaMask/metamask-extension/pull/5893): Add loading network screen +- Fix etherscan links on notifications ([#5978](https://github.com/MetaMask/metamask-extension/pull/5978)) +- Fix drizzle tests ([#5980](https://github.com/MetaMask/metamask-extension/pull/5980)) +- Prevent users from changing the From field in the send screen ([#5922](https://github.com/MetaMask/metamask-extension/pull/5922)) +- Fix displayed time and date in the activity log. Remove vreme library, add luxon library. ([#5932](https://github.com/MetaMask/metamask-extension/pull/5932)) +- transactions - throw an error if a transaction is generated while the network is loading ([#5924](https://github.com/MetaMask/metamask-extension/pull/5924)) +- Add loading network screen ([#5893](https://github.com/MetaMask/metamask-extension/pull/5893)) ## [5.2.2] - 2018-12-13 ### Uncategorized -- [#5925](https://github.com/MetaMask/metamask-extension/pull/5925): Fix speed up button not showing for transactions with the lowest nonce -- [#5923](https://github.com/MetaMask/metamask-extension/pull/5923): Update the Phishing Warning notice text to not use inline URLs -- [#5919](https://github.com/MetaMask/metamask-extension/pull/5919): Fix some styling and translations in the gas customization modal +- Fix speed up button not showing for transactions with the lowest nonce ([#5925](https://github.com/MetaMask/metamask-extension/pull/5925)) +- Update the Phishing Warning notice text to not use inline URLs ([#5923](https://github.com/MetaMask/metamask-extension/pull/5923)) +- Fix some styling and translations in the gas customization modal ([#5919](https://github.com/MetaMask/metamask-extension/pull/5919)) ## [5.2.1] - 2018-12-12 ### Uncategorized -- [#5917] bugfix: Ensures that advanced tab gas limit reflects tx gas limit +- bugfix: Ensures that advanced tab gas limit reflects tx gas limit ([#5917](https://github.com/MetaMask/metamask-extension/pull/5917)) ## [5.2.0] - 2018-12-11 ### Uncategorized -- [#5704] Implements new gas customization features for sending, confirming and speeding up transactions -- [#5886] Groups transactions - speed up, cancel and original - by nonce in the transaction history list -- [#5892] bugfix: eliminates infinite spinner issues caused by switching quickly from a loading network that ultimately fails to resolve -- [$5902] bugfix: provider crashes caused caching issues in `json-rpc-engine`. Fixed in (https://github.com/MetaMask/json-rpc-engine/commit/6de511afbd03ccef4550ea43ff4010b7d7a84039) +- Implements new gas customization features for sending, confirming and speeding up transactions ([#5704](https://github.com/MetaMask/metamask-extension/pull/5704)) +- Groups transactions - speed up, cancel and original - by nonce in the transaction history list ([#5886](https://github.com/MetaMask/metamask-extension/pull/5886)) +- bugfix: eliminates infinite spinner issues caused by switching quickly from a loading network that ultimately fails to resolve ([#5892](https://github.com/MetaMask/metamask-extension/pull/5892)) +- bugfix: provider crashes caused caching issues in `json-rpc-engine`. ([#5902](https://github.com/MetaMask/metamask-extension/pull/5902)) + - Fixed in (https://github.com/MetaMask/json-rpc-engine/commit/6de511afbd03ccef4550ea43ff4010b7d7a84039) ## [5.1.0] - 2018-12-03 ### Uncategorized -- [#5860](https://github.com/MetaMask/metamask-extension/pull/5860): Fixed an infinite spinner bug. -- [#5875](https://github.com/MetaMask/metamask-extension/pull/5875): Update phishing warning copy -- [#5863](https://github.com/MetaMask/metamask-extension/pull/5863): bugfix: normalize contract addresss when fetching exchange rates -- [#5843](https://github.com/MetaMask/metamask-extension/pull/5843): Use selector for state.metamask.accounts in all cases. +- Fixed an infinite spinner bug. ([#5860](https://github.com/MetaMask/metamask-extension/pull/5860)) +- Update phishing warning copy ([#5875](https://github.com/MetaMask/metamask-extension/pull/5875)) +- bugfix: normalize contract addresss when fetching exchange rates ([#5863](https://github.com/MetaMask/metamask-extension/pull/5863)) +- Use selector for state.metamask.accounts in all cases. ([#5843](https://github.com/MetaMask/metamask-extension/pull/5843)) ## [5.0.4] - 2018-11-29 ### Uncategorized -- [#5878](https://github.com/MetaMask/metamask-extension/pull/5878): Formats 32-length byte strings passed to personal_sign as hex, rather than UTF8. -- [#5840](https://github.com/MetaMask/metamask-extension/pull/5840): transactions/tx-gas-utils - add the acctual response for eth_getCode for NO_CONTRACT_ERROR's && add a debug object to simulationFailed -- [#5848](https://github.com/MetaMask/metamask-extension/pull/5848): Soften accusatory language on phishing warning -- [#5835](https://github.com/MetaMask/metamask-extension/pull/5835): Open full-screen UI on install +- Formats 32-length byte strings passed to personal_sign as hex, rather than UTF8. ([#5878](https://github.com/MetaMask/metamask-extension/pull/5878)) +- transactions/tx-gas-utils - add the acctual response for eth_getCode for NO_CONTRACT_ERROR's && add a debug object to simulationFailed ([#5840](https://github.com/MetaMask/metamask-extension/pull/5840)) +- Soften accusatory language on phishing warning ([#5848](https://github.com/MetaMask/metamask-extension/pull/5848)) +- Open full-screen UI on install ([#5835](https://github.com/MetaMask/metamask-extension/pull/5835)) - Locked versions for some dependencies to avoid possible issues from event-stream hack. -- [#5831](https://github.com/MetaMask/metamask-extension/pull/5831): Hide app-header when provider request pending -- [#5786](https://github.com/MetaMask/metamask-extension/pull/5786): \* transactions - autofill gasPrice for retry attempts with either the recomened gasprice or a %10 bump -- [#5801](https://github.com/MetaMask/metamask-extension/pull/5801): transactions - ensure err is defined when setting tx failed -- [#5792](https://github.com/MetaMask/metamask-extension/pull/5792): Consider HW Wallets for signTypedMessage -- [#5829](https://github.com/MetaMask/metamask-extension/pull/5829): Show disabled cursor in .network-disabled state -- [#5827](https://github.com/MetaMask/metamask-extension/pull/5827): Trim whitespace from seed phrase during import -- [#5832](https://github.com/MetaMask/metamask-extension/pull/5832): Show Connect Requests count in extension badge -- [#5816](https://github.com/MetaMask/metamask-extension/pull/5816): Increase Token Symbol length to twelve -- [#5819](https://github.com/MetaMask/metamask-extension/pull/5819): With the EIP 1102 updates, MetaMask _does_ now open itself when visiting some websites. Changed the wording here to clarify that MetaMask will not open itself to ask you for your seed phrase. -- [#5810](https://github.com/MetaMask/metamask-extension/pull/5810): Bump Node version to 8.13 -- [#5797](https://github.com/MetaMask/metamask-extension/pull/5797): Add Firefox and Brave support for Trezor -- [#5799](https://github.com/MetaMask/metamask-extension/pull/5799): Fix usage of setState in ConfirmTransactionBase#handleSubmit -- [#5798](https://github.com/MetaMask/metamask-extension/pull/5798): Show byte count for hex data on confirm screen -- [#5334](https://github.com/MetaMask/metamask-extension/pull/5334): Default to the new UI for first time users -- [#5791](https://github.com/MetaMask/metamask-extension/pull/5791): Bump eth-ledger-bridge-keyring +- Hide app-header when provider request pending ([#5831](https://github.com/MetaMask/metamask-extension/pull/5831)) +- transactions - autofill gasPrice for retry attempts with either the recomened gasprice or a %10 bump ([#5786](https://github.com/MetaMask/metamask-extension/pull/5786)) +- transactions - ensure err is defined when setting tx failed ([#5801](https://github.com/MetaMask/metamask-extension/pull/5801)) +- Consider HW Wallets for signTypedMessage ([#5792](https://github.com/MetaMask/metamask-extension/pull/5792)) +- Show disabled cursor in .network-disabled state ([#5829](https://github.com/MetaMask/metamask-extension/pull/5829)) +- Trim whitespace from seed phrase during import ([#5827](https://github.com/MetaMask/metamask-extension/pull/5827)) +- Show Connect Requests count in extension badge ([#5832](https://github.com/MetaMask/metamask-extension/pull/5832)) +- Increase Token Symbol length to twelve ([#5816](https://github.com/MetaMask/metamask-extension/pull/5816)) +- With the EIP 1102 updates, MetaMask _does_ now open itself when visiting some websites. Changed the wording here to clarify that MetaMask will not open itself to ask you for your seed phrase. ([#5819](https://github.com/MetaMask/metamask-extension/pull/5819)) +- Bump Node version to 8.13 ([#5810](https://github.com/MetaMask/metamask-extension/pull/5810)) +- Add Firefox and Brave support for Trezor ([#5797](https://github.com/MetaMask/metamask-extension/pull/5797)) +- Fix usage of setState in ConfirmTransactionBase#handleSubmit ([#5799](https://github.com/MetaMask/metamask-extension/pull/5799)) +- Show byte count for hex data on confirm screen ([#5798](https://github.com/MetaMask/metamask-extension/pull/5798)) +- Default to the new UI for first time users ([#5334](https://github.com/MetaMask/metamask-extension/pull/5334)) +- Bump eth-ledger-bridge-keyring ([#5791](https://github.com/MetaMask/metamask-extension/pull/5791)) ## [5.0.3] - 2018-11-20 ### Uncategorized -- [#5547](https://github.com/MetaMask/metamask-extension/pull/5547): Bundle some ui dependencies separately to limit the build size of ui.js +- Bundle some ui dependencies separately to limit the build size of ui.js ([#5547](https://github.com/MetaMask/metamask-extension/pull/5547)) - Resubmit approved transactions on new block, to fix bug where an error can stick transactions in this state. - Fixed a bug that could cause an error when sending the max number of tokens. @@ -1129,9 +1134,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Uncategorized - Fix bug where data lookups like balances would get stale data (stopped block-tracker bug) - Transaction Details now show entry for onchain failure -- [#5559](https://github.com/MetaMask/metamask-extension/pull/5559) Localize language names in translation select list -- [#5283](https://github.com/MetaMask/metamask-extension/pull/5283): Fix bug when eth.getCode() called with no contract -- [#5563](https://github.com/MetaMask/metamask-extension/pull/5563#pullrequestreview-166769174) Feature: improve Hatian Creole translations +- Localize language names in translation select list ([#5559](https://github.com/MetaMask/metamask-extension/pull/5559)) +- Fix bug when eth.getCode() called with no contract ([#5283](https://github.com/MetaMask/metamask-extension/pull/5283)) +- Feature: improve Hatian Creole translations ([#5563](https://github.com/MetaMask/metamask-extension/pull/5563#pullrequestreview-166769174)) - Feature: improve Slovenian translations - Add support for alternate `wallet_watchAsset` rpc method name - Attempt chain ID lookup via `eth_chainId` before `net_version` @@ -1156,9 +1161,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [4.14.0] - 2018-10-11 ### Uncategorized - Update transaction statuses when switching networks. -- [#5470](https://github.com/MetaMask/metamask-extension/pull/5470) 100% coverage in French locale, fixed the procedure to verify proposed locale. +- 100% coverage in French locale, fixed the procedure to verify proposed locale. ([#5470](https://github.com/MetaMask/metamask-extension/pull/5470)) - Added rudimentary support for the subscription API to support web3 1.0 and Truffle's Drizzle. -- [#5502](https://github.com/MetaMask/metamask-extension/pull/5502) Update Italian translation. +- Update Italian translation. ([#5502](https://github.com/MetaMask/metamask-extension/pull/5502)) ## [4.13.0] - 2018-10-04 ### Uncategorized @@ -1178,61 +1183,61 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [4.10.0] - 2018-09-18 ### Uncategorized -- [#4803](https://github.com/MetaMask/metamask-extension/pull/4803): Implement EIP-712: Sign typed data, but continue to support v1. -- [#4898](https://github.com/MetaMask/metamask-extension/pull/4898): Restore multiple consecutive accounts with balances. -- [#4279](https://github.com/MetaMask/metamask-extension/pull/4279): New BlockTracker and Json-Rpc-Engine based Provider. -- [#5050](https://github.com/MetaMask/metamask-extension/pull/5050): Add Ledger hardware wallet support. -- [#4919](https://github.com/MetaMask/metamask-extension/pull/4919): Refactor and Redesign Transaction List. -- [#5182](https://github.com/MetaMask/metamask-extension/pull/5182): Add Transaction Details to the Transaction List view. -- [#5229](https://github.com/MetaMask/metamask-extension/pull/5229): Clear old seed words when importing new seed words. -- [#5264](https://github.com/MetaMask/metamask-extension/pull/5264): Improve click area for adjustment arrows buttons. -- [#4606](https://github.com/MetaMask/metamask-extension/pull/4606): Add new metamask_watchAsset method. -- [#5189](https://github.com/MetaMask/metamask-extension/pull/5189): Fix bug where Ropsten loading message is shown when connecting to Kovan. -- [#5256](https://github.com/MetaMask/metamask-extension/pull/5256): Add mock EIP-1102 support +- Implement EIP-712: Sign typed data, but continue to support v1. ([#4803](https://github.com/MetaMask/metamask-extension/pull/4803)) +- Restore multiple consecutive accounts with balances. ([#4898](https://github.com/MetaMask/metamask-extension/pull/4898)) +- New BlockTracker and Json-Rpc-Engine based Provider. ([#4279](https://github.com/MetaMask/metamask-extension/pull/4279)) +- Add Ledger hardware wallet support. ([#5050](https://github.com/MetaMask/metamask-extension/pull/5050)) +- Refactor and Redesign Transaction List. ([#4919](https://github.com/MetaMask/metamask-extension/pull/4919)) +- Add Transaction Details to the Transaction List view. ([#5182](https://github.com/MetaMask/metamask-extension/pull/5182)) +- Clear old seed words when importing new seed words. ([#5229](https://github.com/MetaMask/metamask-extension/pull/5229)) +- Improve click area for adjustment arrows buttons. ([#5264](https://github.com/MetaMask/metamask-extension/pull/5264)) +- Add new metamask_watchAsset method. ([#4606](https://github.com/MetaMask/metamask-extension/pull/4606)) +- Fix bug where Ropsten loading message is shown when connecting to Kovan. ([#5189](https://github.com/MetaMask/metamask-extension/pull/5189)) +- Add mock EIP-1102 support ([#5256](https://github.com/MetaMask/metamask-extension/pull/5256)) ## [4.9.3] - 2018-08-16 ### Uncategorized -- [#4897](https://github.com/MetaMask/metamask-extension/pull/4897): QR code scan for recipient addresses. -- [#4961](https://github.com/MetaMask/metamask-extension/pull/4961): Add a download seed phrase link. -- [#5060](https://github.com/MetaMask/metamask-extension/pull/5060): Fix bug where gas was not updating properly. +- QR code scan for recipient addresses. ([#4897](https://github.com/MetaMask/metamask-extension/pull/4897)) +- Add a download seed phrase link. ([#4961](https://github.com/MetaMask/metamask-extension/pull/4961)) +- Fix bug where gas was not updating properly. ([#5060](https://github.com/MetaMask/metamask-extension/pull/5060)) ## [4.9.2] - 2018-08-10 ### Uncategorized -- [#5020](https://github.com/MetaMask/metamask-extension/pull/5020): Fix bug in migration #28 ( moving tokens to specific accounts ) +- Fix bug in migration #28 ([#5020](https://github.com/MetaMask/metamask-extension/pull/5020)) ## [4.9.1] - 2018-08-09 ### Uncategorized -- [#4884](https://github.com/MetaMask/metamask-extension/pull/4884): Allow to have tokens per account and network. -- [#4989](https://github.com/MetaMask/metamask-extension/pull/4989): Continue to use original signedTypedData. -- [#5010](https://github.com/MetaMask/metamask-extension/pull/5010): Fix ENS resolution issues. -- [#5000](https://github.com/MetaMask/metamask-extension/pull/5000): Show error while allowing confirmation of tx where simulation fails. -- [#4995](https://github.com/MetaMask/metamask-extension/pull/4995): Shows retry button on dApp initialized transactions. +- Allow to have tokens per account and network. ([#4884](https://github.com/MetaMask/metamask-extension/pull/4884)) +- Continue to use original signedTypedData. ([#4989](https://github.com/MetaMask/metamask-extension/pull/4989)) +- Fix ENS resolution issues. ([#5010](https://github.com/MetaMask/metamask-extension/pull/5010)) +- Show error while allowing confirmation of tx where simulation fails. ([#5000](https://github.com/MetaMask/metamask-extension/pull/5000)) +- Shows retry button on dApp initialized transactions. ([#4995](https://github.com/MetaMask/metamask-extension/pull/4995)) ## [4.9.0] - 2018-08-07 ### Uncategorized -- [#4926](https://github.com/MetaMask/metamask-extension/pull/4926): Show retry button on the latest tx of the earliest nonce. -- [#4888](https://github.com/MetaMask/metamask-extension/pull/4888): Suggest using the new user interface. -- [#4947](https://github.com/MetaMask/metamask-extension/pull/4947): Prevent sending multiple transasctions on multiple confirm clicks. -- [#4844](https://github.com/MetaMask/metamask-extension/pull/4844): Add new tokens auto detection. -- [#4667](https://github.com/MetaMask/metamask-extension/pull/4667): Remove rejected transactions from transaction history. -- [#4625](https://github.com/MetaMask/metamask-extension/pull/4625): Add Trezor Support. -- [#4625](https://github.com/MetaMask/metamask-extension/pull/4625/commits/523cf9ad33d88719520ae5e7293329d133b64d4d): Allow to remove accounts (Imported and Hardware Wallets) -- [#4814](https://github.com/MetaMask/metamask-extension/pull/4814): Add hex data input to send screen. -- [#4691](https://github.com/MetaMask/metamask-extension/pull/4691): Redesign of the Confirm Transaction Screen. -- [#4840](https://github.com/MetaMask/metamask-extension/pull/4840): Now shows notifications when transactions are completed. -- [#4855](https://github.com/MetaMask/metamask-extension/pull/4855): Allow the use of HTTP prefix for custom rpc urls. -- [#4855](https://github.com/MetaMask/metamask-extension/pull/4855): network.js: convert rpc protocol to lower case. -- [#4898](https://github.com/MetaMask/metamask-extension/pull/4898): Restore multiple consecutive accounts with balances. +- Show retry button on the latest tx of the earliest nonce. ([#4926](https://github.com/MetaMask/metamask-extension/pull/4926)) +- Suggest using the new user interface. ([#4888](https://github.com/MetaMask/metamask-extension/pull/4888)) +- Prevent sending multiple transasctions on multiple confirm clicks. ([#4947](https://github.com/MetaMask/metamask-extension/pull/4947)) +- Add new tokens auto detection. ([#4844](https://github.com/MetaMask/metamask-extension/pull/4844)) +- Remove rejected transactions from transaction history. ([#4667](https://github.com/MetaMask/metamask-extension/pull/4667)) +- Add Trezor Support. ([#4625](https://github.com/MetaMask/metamask-extension/pull/4625)) +- Allow to remove accounts ([#4625](https://github.com/MetaMask/metamask-extension/pull/4625/commits/523cf9ad33d88719520ae5e7293329d133b64d4d)) +- Add hex data input to send screen. ([#4814](https://github.com/MetaMask/metamask-extension/pull/4814)) +- Redesign of the Confirm Transaction Screen. ([#4691](https://github.com/MetaMask/metamask-extension/pull/4691)) +- Now shows notifications when transactions are completed. ([#4840](https://github.com/MetaMask/metamask-extension/pull/4840)) +- Allow the use of HTTP prefix for custom rpc urls. ([#4855](https://github.com/MetaMask/metamask-extension/pull/4855)) +- network.js: convert rpc protocol to lower case. ([#4855](https://github.com/MetaMask/metamask-extension/pull/4855)) +- Restore multiple consecutive accounts with balances. ([#4898](https://github.com/MetaMask/metamask-extension/pull/4898)) ## [4.8.0] - 2018-06-18 ### Uncategorized -- [#4513](https://github.com/MetaMask/metamask-extension/pull/4513): Attempting to import an empty private key will now show a clear error. -- [#4570](https://github.com/MetaMask/metamask-extension/pull/4570): Fix bug where metamask data would stop being written to disk after prolonged use. -- [#4523](https://github.com/MetaMask/metamask-extension/pull/4523): Fix bug where account reset did not work with custom RPC providers. -- [#4524](https://github.com/MetaMask/metamask-extension/pull/4524): Fix for Brave i18n getAcceptLanguages. -- [#4557](https://github.com/MetaMask/metamask-extension/pull/4557): Fix bug where nonce mutex was never released. -- [#4566](https://github.com/MetaMask/metamask-extension/pull/4566): Add phishing notice. -- [#4591](https://github.com/MetaMask/metamask-extension/pull/4591): Allow Copying Token Addresses and link to Token on Etherscan. +- Attempting to import an empty private key will now show a clear error. ([#4513](https://github.com/MetaMask/metamask-extension/pull/4513)) +- Fix bug where metamask data would stop being written to disk after prolonged use. ([#4570](https://github.com/MetaMask/metamask-extension/pull/4570)) +- Fix bug where account reset did not work with custom RPC providers. ([#4523](https://github.com/MetaMask/metamask-extension/pull/4523)) +- Fix for Brave i18n getAcceptLanguages. ([#4524](https://github.com/MetaMask/metamask-extension/pull/4524)) +- Fix bug where nonce mutex was never released. ([#4557](https://github.com/MetaMask/metamask-extension/pull/4557)) +- Add phishing notice. ([#4566](https://github.com/MetaMask/metamask-extension/pull/4566)) +- Allow Copying Token Addresses and link to Token on Etherscan. ([#4591](https://github.com/MetaMask/metamask-extension/pull/4591)) ## [4.7.4] - 2018-06-05 ### Uncategorized @@ -2265,6 +2270,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v9.5.9...HEAD [9.5.9]: https://github.com/MetaMask/metamask-extension/compare/v9.5.8...v9.5.9 +[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v9.5.8...HEAD [9.5.8]: https://github.com/MetaMask/metamask-extension/compare/v9.5.7...v9.5.8 [9.5.7]: https://github.com/MetaMask/metamask-extension/compare/v9.5.6...v9.5.7 [9.5.6]: https://github.com/MetaMask/metamask-extension/compare/v9.5.5...v9.5.6 diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 66dcee019..7bdda532f 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -52,6 +52,10 @@ "addContact": { "message": "Add contact" }, + "addCustomTokenByContractAddress": { + "message": "Can’t find a token? You can manually add any token by pasting its address. Token contract addresses can be found on $1.", + "description": "$1 is a blockchain explorer for a specific network, e.g. Etherscan for Ethereum" + }, "addEthereumChainConfirmationDescription": { "message": "This will allow this network to be used within MetaMask." }, @@ -410,6 +414,9 @@ "continueToWyre": { "message": "Continue to Wyre" }, + "contract": { + "message": "Contract" + }, "contractAddressError": { "message": "You are sending tokens to the token's contract address. This may result in the loss of these tokens." }, @@ -486,7 +493,7 @@ "message": "Some of your account data was backed up during a previous installation of MetaMask. This could include your settings, contacts, and tokens. Would you like to restore this data now?" }, "decimal": { - "message": "Decimals of Precision" + "message": "Token Decimal" }, "decimalsMustZerotoTen": { "message": "Decimals must be at least 0, and not over 36." @@ -556,6 +563,15 @@ "dismiss": { "message": "Dismiss" }, + "dismissReminderDescriptionField": { + "message": "Turn this on to dismiss the recovery phrase backup reminder message. We highly recommend that you back up your Secret Recovery Phrase to avoid loss of funds" + }, + "dismissReminderField": { + "message": "Dismiss recovery phrase backup reminder" + }, + "domain": { + "message": "Domain" + }, "done": { "message": "Done" }, @@ -597,7 +613,7 @@ "message": "Request encryption public key" }, "endOfFlowMessage1": { - "message": "You passed the test - keep your seedphrase safe, it's your responsibility!" + "message": "You passed the test - keep your Secret Recovery Phrase safe, it's your responsibility!" }, "endOfFlowMessage10": { "message": "All Done" @@ -612,17 +628,17 @@ "message": "Never share the phrase with anyone." }, "endOfFlowMessage5": { - "message": "Be careful of phishing! MetaMask will never spontaneously ask for your seed phrase." + "message": "Be careful of phishing! MetaMask will never spontaneously ask for your Secret Recovery Phrase." }, "endOfFlowMessage6": { - "message": "If you need to back up your seed phrase again, you can find it in Settings -> Security." + "message": "If you need to back up your Secret Recovery Phrase again, you can find it in Settings -> Security." }, "endOfFlowMessage7": { "message": "If you ever have questions or see something fishy, contact our support $1.", "description": "$1 is a clickable link with text defined by the 'here' key. The link will open to a form where users can file support tickets." }, "endOfFlowMessage8": { - "message": "MetaMask cannot recover your seedphrase." + "message": "MetaMask cannot recover your Secret Recovery Phrase." }, "endOfFlowMessage9": { "message": "Learn more." @@ -684,6 +700,9 @@ "estimatedProcessingTimes": { "message": "Estimated Processing Times" }, + "ethGasPriceFetchWarning": { + "message": "Backup gas price is provided as the main gas estimation service is unavailable right now." + }, "eth_accounts": { "message": "View the addresses of your permitted accounts (required)", "description": "The description for the `eth_accounts` permission" @@ -780,6 +799,9 @@ "gasPriceExtremelyLow": { "message": "Gas Price Extremely Low" }, + "gasPriceFetchFailed": { + "message": "Gas price estimation failed due to network error." + }, "gasPriceInfoTooltipContent": { "message": "Gas price specifies the amount of Ether you are willing to pay for each unit of gas." }, @@ -866,23 +888,29 @@ "message": "Import Account" }, "importAccountLinkText": { - "message": "import using seed phrase" + "message": "import using Secret Recovery Phrase" }, "importAccountMsg": { - "message": " Imported accounts will not be associated with your originally created MetaMask account seedphrase. Learn more about imported accounts " + "message": " Imported accounts will not be associated with your originally created MetaMask account Secret Recovery Phrase. Learn more about imported accounts " }, "importAccountSeedPhrase": { - "message": "Import an account with seed phrase" + "message": "Import an account with Secret Recovery Phrase" }, "importAccountText": { "message": "or $1", "description": "$1 represents the text from `importAccountLinkText` as a link" }, + "importTokenQuestion": { + "message": "Import token?" + }, + "importTokenWarning": { + "message": "Anyone can create a token with any name, including fake versions of existing tokens. Add and trade at your own risk!" + }, "importWallet": { "message": "Import wallet" }, "importYourExisting": { - "message": "Import your existing wallet using a seed phrase" + "message": "Import your existing wallet using a Secret Recovery Phrase" }, "imported": { "message": "Imported", @@ -952,7 +980,7 @@ "message": "Invalid RPC URL" }, "invalidSeedPhrase": { - "message": "Invalid seed phrase" + "message": "Invalid Secret Recovery Phrase" }, "ipfsGateway": { "message": "IPFS Gateway" @@ -1027,6 +1055,9 @@ "mainnet": { "message": "Ethereum Mainnet" }, + "makeAnotherSwap": { + "message": "Create a new swap" + }, "max": { "message": "Max" }, @@ -1105,6 +1136,9 @@ "myAccounts": { "message": "My Accounts" }, + "name": { + "message": "Name" + }, "needEtherInWallet": { "message": "To interact with decentralized applications using MetaMask, you’ll need Ether in your wallet." }, @@ -1203,7 +1237,7 @@ "message": "No address has been set for this name." }, "noAlreadyHaveSeed": { - "message": "No, I already have a seed phrase" + "message": "No, I already have a Secret Recovery Phrase" }, "noConversionRateAvailable": { "message": "No Conversion Rate Available" @@ -1246,18 +1280,6 @@ "message": "Swapping on mobile is here!", "description": "Title for a notification in the 'See What's New' popup. Tells users that they can now use MetaMask Swaps on Mobile." }, - "notifications2ActionText": { - "message": "Start survey", - "description": "The 'call to action' label on the button, or link, of the 'Help improve MetaMask' 'See What's New' notification. Upon clicking, users will be taken to an external page where they can complete a survey." - }, - "notifications2Description": { - "message": "Please share your experience in this 5 minute survey.", - "description": "Description of a notification in the 'See What's New' popup. Further clarifies how the users can help: by completing a 5 minute survey about MetaMask." - }, - "notifications2Title": { - "message": "Help improve MetaMask", - "description": "Title for a notification in the 'See What's New' popup. Asks users to take action to make MetaMask better." - }, "notifications3ActionText": { "message": "Read more", "description": "The 'call to action' on the button, or link, of the 'Stay secure' notification. Upon clicking, users will be taken to a page about security on the metamask support website." @@ -1270,6 +1292,22 @@ "message": "Stay secure", "description": "Title for a notification in the 'See What's New' popup. Encourages users to consider security." }, + "notifications4ActionText": { + "message": "Start swapping", + "description": "The 'call to action' on the button, or link, of the 'Swap on Binance Smart Chain!' notification. Upon clicking, users will be taken to a page where then can swap tokens on Binance Smart Chain." + }, + "notifications4Description": { + "message": "Get the best prices on token swaps right inside your wallet. MetaMask now connects you to multiple decentralized exchange aggregators and professional market makers on Binance Smart Chain.", + "description": "Description of a notification in the 'See What's New' popup." + }, + "notifications4Title": { + "message": "Swap on Binance Smart Chain", + "description": "Title for a notification in the 'See What's New' popup. Encourages users to do swaps on Binance Smart Chain." + }, + "notifications5Description": { + "message": "Your \"Seed Phrase\" is now called your \"Secret Recovery Phrase.\"", + "description": "Description of a notification in the 'See What's New' popup. Describes the seed phrase wording update." + }, "notifications6DescriptionOne": { "message": "As of Chrome version 91, the API that enabled our Ledger support (U2F) no longer supports hardware wallets. MetaMask has implemented a new Ledger Live support that allows you to continue to connect to your Ledger device via the Ledger Live desktop app.", "description": "Description of a notification in the 'See What's New' popup. Describes the Ledger support update." @@ -1392,6 +1430,9 @@ "provide": { "message": "Provide" }, + "publicAddress": { + "message": "Public Address" + }, "queue": { "message": "Queue" }, @@ -1438,7 +1479,7 @@ "message": "Remove account" }, "removeAccountDescription": { - "message": "This account will be removed from your wallet. Please make sure you have the original seed phrase or private key for this imported account before continuing. You can import or create accounts again from the account drop-down. " + "message": "This account will be removed from your wallet. Please make sure you have the original Secret Recovery Phrase or private key for this imported account before continuing. You can import or create accounts again from the account drop-down. " }, "requestsAwaitingAcknowledgement": { "message": "requests waiting to be acknowledged" @@ -1453,13 +1494,13 @@ "message": "Reset Account" }, "resetAccountDescription": { - "message": "Resetting your account will clear your transaction history. This will not change the balances in your accounts or require you to re-enter your seed phrase." + "message": "Resetting your account will clear your transaction history. This will not change the balances in your accounts or require you to re-enter your Secret Recovery Phrase." }, "restore": { "message": "Restore" }, "restoreAccountWithSeed": { - "message": "Restore your Account with Seed Phrase" + "message": "Restore your Account with Secret Recovery Phrase" }, "restoreWalletPreferences": { "message": "A backup of your data from $1 has been found. Would you like to restore your wallet preferences?", @@ -1472,13 +1513,13 @@ "message": "A token here reuses a symbol from another token you watch, this can be confusing or deceptive." }, "revealSeedWords": { - "message": "Reveal Seed Phrase" + "message": "Reveal Secret Recovery Phrase" }, "revealSeedWordsDescription": { - "message": "If you ever change browsers or move computers, you will need this seed phrase to access your accounts. Save them somewhere safe and secret." + "message": "If you ever change browsers or move computers, you will need this Secret Recovery Phrase to access your accounts. Save them somewhere safe and secret." }, "revealSeedWordsTitle": { - "message": "Seed Phrase" + "message": "Secret Recovery Phrase" }, "revealSeedWordsWarning": { "message": "These words can be used to steal all your accounts." @@ -1538,16 +1579,52 @@ "message": "Security & Privacy" }, "securitySettingsDescription": { - "message": "Privacy settings and wallet seed phrase" + "message": "Privacy settings and wallet Secret Recovery Phrase" + }, + "seedPhraseIntroSidebarBulletFour": { + "message": "Write down and store in multiple secret places." + }, + "seedPhraseIntroSidebarBulletOne": { + "message": "Save in a password manager" + }, + "seedPhraseIntroSidebarBulletThree": { + "message": "Store in a safe-deposit box." + }, + "seedPhraseIntroSidebarBulletTwo": { + "message": "Store in a bank vault." + }, + "seedPhraseIntroSidebarCopyOne": { + "message": "Your recovery phrase is the “master key” to your wallet and funds." + }, + "seedPhraseIntroSidebarCopyThree": { + "message": "If someone asks for your recovery phrase, they are most likely trying to scam you." + }, + "seedPhraseIntroSidebarCopyTwo": { + "message": "Never, ever share your recovery phrase, even with MetaMask!" + }, + "seedPhraseIntroSidebarTitleOne": { + "message": "What is a recovery phrase?" + }, + "seedPhraseIntroSidebarTitleThree": { + "message": "Should I share my recovery phrase?" + }, + "seedPhraseIntroSidebarTitleTwo": { + "message": "How do I save my recovery phrase?" + }, + "seedPhraseIntroTitle": { + "message": "Secure your wallet" + }, + "seedPhraseIntroTitleCopy": { + "message": "Before getting started, watch this short video to learn about your recovery phrase and how to keep your wallet safe." }, "seedPhrasePlaceholder": { "message": "Separate each word with a single space" }, "seedPhrasePlaceholderPaste": { - "message": "Paste seed phrase from clipboard" + "message": "Paste Secret Recovery Phrase from clipboard" }, "seedPhraseReq": { - "message": "Seed phrases contain 12, 15, 18, 21, or 24 words" + "message": "Secret Recovery Phrases contain 12, 15, 18, 21, or 24 words" }, "selectAHigherGasFee": { "message": "Select a higher gas fee to accelerate the processing of your transaction.*" @@ -1639,7 +1716,7 @@ "message": "Show Private Keys" }, "showSeedPhrase": { - "message": "Show seed phrase" + "message": "Show Secret Recovery Phrase" }, "sigRequest": { "message": "Signature Request" @@ -1756,6 +1833,10 @@ "swapAggregator": { "message": "Aggregator" }, + "swapAllowSwappingOf": { + "message": "Allow swapping of $1", + "description": "Shows a user that they need to allow a token for swapping on their hardware wallet" + }, "swapAmountReceived": { "message": "Guaranteed amount" }, @@ -1781,6 +1862,15 @@ "message": "Checking $1", "description": "Shown to the user during quote loading. $1 is the name of an aggregator. The message indicates that metamask is currently checking if that aggregator has a trade/quote for their requested swap." }, + "swapConfirmWithHwWallet": { + "message": "Confirm with your hardware wallet" + }, + "swapContractDataDisabledErrorDescription": { + "message": "In the Ethereum app on your Ledger, go to \"Settings\" and allow contract data. Then, try your swap again." + }, + "swapContractDataDisabledErrorTitle": { + "message": "Contract data is not enabled on your Ledger" + }, "swapCustom": { "message": "custom" }, @@ -1826,8 +1916,15 @@ "swapFinalizing": { "message": "Finalizing..." }, + "swapFromTo": { + "message": "The swap of $1 to $2", + "description": "Tells a user that they need to confirm on their hardware wallet a swap of 2 tokens. $1 is a source token and $2 is a destination token" + }, + "swapGasFeesSplit": { + "message": "Gas fees on the previous screen are split between these two transactions." + }, "swapHighSlippageWarning": { - "message": "Slippage amount is very high. Make sure you know what you are doing!" + "message": "Slippage amount is very high." }, "swapLowSlippageError": { "message": "Transaction may fail, max slippage too low." @@ -1868,18 +1965,18 @@ "message": "You are about to swap $1 $2 (~$3) for $4 $5 (~$6).", "description": "This message represents the price slippage for the swap. $1 and $4 are a number (ex: 2.89), $2 and $5 are symbols (ex: ETH), and $3 and $6 are fiat currency amounts." }, - "swapPriceDifferenceAcknowledgement": { - "message": "I'm aware" - }, "swapPriceDifferenceTitle": { "message": "Price difference of ~$1%", "description": "$1 is a number (ex: 1.23) that represents the price difference." }, - "swapPriceDifferenceTooltip": { - "message": "The difference in market prices can be affected by fees taken by intermediaries, size of market, size of trade, or market inefficiencies." + "swapPriceImpactTooltip": { + "message": "Price impact is the difference between the current market price and the amount received during transaction execution. Price impact is a function of the size of your trade relative to the size of the liquidity pool." }, - "swapPriceDifferenceUnavailable": { - "message": "Market price is unavailable. Make sure you feel comfortable with the returned amount before proceeding." + "swapPriceUnavailableDescription": { + "message": "Price impact could not be determined due to lack of market price data. Please confirm that you are comfortable with the amount of tokens you are about to receive before swapping." + }, + "swapPriceUnavailableTitle": { + "message": "Check your rate before proceeding" }, "swapProcessing": { "message": "Processing" @@ -1946,8 +2043,8 @@ "swapSelectQuotePopoverDescription": { "message": "Below are all the quotes gathered from multiple liquidity sources." }, - "swapSlippageTooLow": { - "message": "Slippage must be greater than zero" + "swapSlippageNegative": { + "message": "Slippage must be greater or equal to zero" }, "swapSource": { "message": "Liquidity source" @@ -1967,6 +2064,9 @@ "swapThisWillAllowApprove": { "message": "This will allow $1 to be swapped." }, + "swapToConfirmWithHwWallet": { + "message": "to confirm with your hardware wallet" + }, "swapTokenAvailable": { "message": "Your $1 has been added to your account.", "description": "This message is shown after a swap is successful and communicates the exact amount of tokens the user has received for a swap. The $1 is a decimal number of tokens followed by the token symbol." @@ -1979,13 +2079,13 @@ "message": "Swap $1 to $2", "description": "Used in the transaction display list to describe a swap. $1 and $2 are the symbols of tokens in involved in a swap." }, + "swapTokenVerificationAddedManually": { + "message": "This token has been added manually." + }, "swapTokenVerificationMessage": { "message": "Always confirm the token address on $1.", "description": "Points the user to Etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"Etherscan\" followed by an info icon that shows more info on hover." }, - "swapTokenVerificationNoSource": { - "message": "This token has not been verified." - }, "swapTokenVerificationOnlyOneSource": { "message": "Only verified on 1 source." }, @@ -1996,6 +2096,9 @@ "swapTransactionComplete": { "message": "Transaction complete" }, + "swapTwoTransactions": { + "message": "2 transactions" + }, "swapUnknown": { "message": "Unknown" }, @@ -2006,9 +2109,6 @@ "message": "Multiple tokens can use the same name and symbol. Check $1 to verify this is the token you're looking for.", "description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network." }, - "swapViewToken": { - "message": "View $1" - }, "swapYourTokenBalance": { "message": "$1 $2 available to swap", "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" @@ -2102,7 +2202,7 @@ "message": "Test Faucet" }, "thisWillCreate": { - "message": "This will create a new wallet and seed phrase" + "message": "This will create a new wallet and Secret Recovery Phrase" }, "tips": { "message": "Tips" @@ -2126,9 +2226,15 @@ "tokenContractAddress": { "message": "Token Contract Address" }, + "tokenDecimalFetchFailed": { + "message": "Token decimal required." + }, "tokenSymbol": { "message": "Token Symbol" }, + "tooltipApproveButton": { + "message": "I understand" + }, "total": { "message": "Total" }, @@ -2257,10 +2363,18 @@ "userName": { "message": "Username" }, + "verifyThisTokenDecimalOn": { + "message": "Token decimal can be found on $1", + "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" + }, "verifyThisTokenOn": { "message": "Verify this token on $1", "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" }, + "verifyThisUnconfirmedTokenOn": { + "message": "Verify this token on $1 and make sure this is the token you want to trade.", + "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" + }, "viewAccount": { "message": "View Account" }, @@ -2270,6 +2384,9 @@ "viewContact": { "message": "View Contact" }, + "viewMore": { + "message": "View More" + }, "viewOnCustomBlockExplorer": { "message": "View at $1" }, @@ -2286,10 +2403,10 @@ "message": "our hardware wallet connection guide" }, "walletSeed": { - "message": "Seed phrase" + "message": "Secret Recovery Phrase" }, "walletSeedRestore": { - "message": "Wallet Seed" + "message": "Wallet Secret Recovery Phrase" }, "web3ShimUsageNotification": { "message": "We noticed that the current website tried to use the removed window.web3 API. If the site appears to be broken, please click $1 for more information.", @@ -2329,7 +2446,7 @@ "message": "You are signing" }, "yourPrivateSeedPhrase": { - "message": "Your private seed phrase" + "message": "Your private Secret Recovery Phrase" }, "zeroGasPriceOnSpeedUpError": { "message": "Zero gas price on speed up" diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index c85673d74..39a786e9c 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -497,6 +497,9 @@ "dismiss": { "message": "Descartar" }, + "dismissReminderDescriptionField": { + "message": "Active esta opción para ignorar el recordatorio de respaldo de la frase de recuperación. Le recomendamos que respalde la frase secreta de recuperación para evitar la pérdida de fondos." + }, "done": { "message": "Completo" }, @@ -532,7 +535,7 @@ "message": "Solicitar clave pública de cifrado" }, "endOfFlowMessage1": { - "message": "Pasó la prueba - mantenga su frase semilla segura, ¡es su responsabilidad!" + "message": "Pasó la prueba. Es importante que guarde la frase secreta de recuperación en un lugar seguro." }, "endOfFlowMessage10": { "message": "Todo Listo" @@ -547,13 +550,13 @@ "message": "Nunca comparta la frase con nadie." }, "endOfFlowMessage5": { - "message": "¡Cuidado con el phishing! MetaMask nunca le pedirá espontáneamente su frase semilla." + "message": "Tenga cuidado con el phishing. MetaMask nunca le pedirá la frase secreta de recuperación sin anticipárselo." }, "endOfFlowMessage6": { - "message": "Si necesita hacer una copia de seguridad de su frase semilla nuevamente, puede encontrarla en Configuración -> Seguridad." + "message": "Si necesita volver a crear una copia de seguridad de la frase secreta de recuperación, puede encontrarla en Configuración -> Seguridad." }, "endOfFlowMessage8": { - "message": "MetaMask no puede recuperar tu frase semilla. Saber más." + "message": "MetaMask no puede recuperar la frase secreta de recuperación." }, "endOfFlowMessage9": { "message": "Saber más." @@ -772,15 +775,21 @@ "importAccount": { "message": "Importar cuenta" }, + "importAccountLinkText": { + "message": "importar con la frase secreta de recuperación" + }, "importAccountMsg": { - "message": "Las cuentas importadas no serán asociadas con tu cuenta original creada con tu MetaMask. Aprende más acerca de importar cuentas " + "message": " Las cuentas importadas no se asociarán con la frase secreta de recuperación de la cuenta original de MetaMask. Más información sobre las cuentas importadas " }, "importAccountSeedPhrase": { - "message": "Importar una cuenta con la frase semilla" + "message": "Importar una cuenta con la frase secreta de recuperación" }, "importWallet": { "message": "Importar Monedero" }, + "importYourExisting": { + "message": "Importar la cartera existente con una frase secreta de recuperación" + }, "imported": { "message": "Importado", "description": "status showing that an account has been fully loaded into the keyring" @@ -842,7 +851,7 @@ "message": "URL del RPC inválida " }, "invalidSeedPhrase": { - "message": "Frase semilla inválida." + "message": "Frase secreta de recuperación no válida" }, "ipfsGateway": { "message": "Puerta de enlace IPFS" @@ -1042,7 +1051,7 @@ "message": "No se ha establecido ninguna dirección para este nombre." }, "noAlreadyHaveSeed": { - "message": "No, ya tengo una frase semilla" + "message": "No, ya tengo una frase secreta de recuperación" }, "noConversionRateAvailable": { "message": "No hay ninguna Tasa de Conversión Disponible" @@ -1226,7 +1235,7 @@ "message": "Borrar cuenta" }, "removeAccountDescription": { - "message": "Se borrará esta cuenta de tu monedero. Por favor, asegúrate de tener la frase semilla o clave personal original para esta cuenta importada antes de seguir adelante. Podrás importar o crear cuentas de nuevo del menu desplegable de cuentas." + "message": "Esta cuenta se quitará de la cartera. Antes de continuar, asegúrese de tener la frase secreta de recuperación original o la clave privada de esta cuenta importada. Puede importar o crear cuentas nuevamente desde el menú desplegable de la cuenta." }, "requestsAwaitingAcknowledgement": { "message": "peticiones pendientes de reconocimiento" @@ -1241,13 +1250,13 @@ "message": "Reiniciar cuenta" }, "resetAccountDescription": { - "message": "Reiniciar tu cuenta borrará tu historial de transacciones." + "message": "Restablecer la cuenta borrará el historial de transacciones. Esto no cambiará los saldos de las cuentas ni se le pedirá que vuelva a escribir la frase secreta de recuperación." }, "restore": { "message": "Restaurar" }, "restoreAccountWithSeed": { - "message": "Restaurar tu Cuenta con la Frase Semilla" + "message": "Restaurar la cuenta con la frase secreta de recuperación" }, "restoreWalletPreferences": { "message": "Se ha encontrado una copia de seguridad de sus datos de $1. ¿Le gustaría restaurar sus preferencias de monedero?", @@ -1260,13 +1269,13 @@ "message": "Un token aquí reutiliza un símbolo de otro token que está observando, esto puede ser confuso o engañoso." }, "revealSeedWords": { - "message": "Revelar Frase Semilla" + "message": "Revelar frase secreta de recuperación" }, "revealSeedWordsDescription": { - "message": "Si en algún momento cambias de navegador o de ordenador, necesitarás esta frase semilla para acceder a tus cuentas. Guárdatela en un lugar seguro y secreto." + "message": "Si alguna vez cambia de explorador o de equipo, necesitará esta frase secreta de recuperación para acceder a sus cuentas. Guárdela en un lugar seguro y secreto." }, "revealSeedWordsTitle": { - "message": "Frase Semilla" + "message": "Frase secreta de recuperación" }, "revealSeedWordsWarning": { "message": "¡No recuperes tu semilla en un lugar público! Esas palabras pueden ser usadas para robarte todas tus cuentas" @@ -1323,16 +1332,16 @@ "message": "Seguridad y Privacidad" }, "securitySettingsDescription": { - "message": "Configuración de privacidad y frase semilla de monedero" + "message": "Configuración de privacidad y frase secreta de recuperación de la cartera" }, "seedPhrasePlaceholder": { "message": "Separar a cada palabra con un sólo espacio" }, "seedPhrasePlaceholderPaste": { - "message": "Pegar la frase semilla del portapapeles" + "message": "Pegar la frase secreta de recuperación desde el Portapapeles" }, "seedPhraseReq": { - "message": "Las frases semilla contienen 12, 15, 18, 21 oo 24 palabras" + "message": "Las frases secretas de recuperación contienen 12, 15, 18, 21 o 24 palabras" }, "selectAHigherGasFee": { "message": "Seleccione una comisión de gas más elevada para agilizar el procesamiento de tu transacción.*" @@ -1417,7 +1426,7 @@ "message": "Mostrar claves privadas" }, "showSeedPhrase": { - "message": "Mostrar frase semilla" + "message": "Mostrar frase secreta de recuperación" }, "sigRequest": { "message": "Solicitud de firma" @@ -1576,9 +1585,6 @@ "swapFinalizing": { "message": "Finalizando..." }, - "swapHighSlippageWarning": { - "message": "La cantidad de deslizamiento es muy alta. ¡Asegúrate de saber lo que estás haciendo!" - }, "swapLowSlippageError": { "message": "La transacción puede fallar, el deslizamiento máximo es demasiado bajo." }, @@ -1622,12 +1628,6 @@ "message": "Diferencia de precio de ~$1%", "description": "$1 is a number (ex: 1.23) that represents the price difference." }, - "swapPriceDifferenceTooltip": { - "message": "La diferencia en los precios de mercado puede verse afectada por las tarifas cobradas por los intermediarios, el tamaño del mercado, el tamaño del comercio o las ineficiencias del mercado." - }, - "swapPriceDifferenceUnavailable": { - "message": "El precio de mercado no está disponible. Asegúrese de sentirse cómodo con el monto devuelto antes de continuar." - }, "swapProcessing": { "message": "Procesando" }, @@ -1690,9 +1690,6 @@ "swapSelectQuotePopoverDescription": { "message": "A continuación se muestran todas las cotizaciones recopiladas de múltiples fuentes de liquidez." }, - "swapSlippageTooLow": { - "message": "El deslizamiento debe ser mayor que cero" - }, "swapSource": { "message": "Fuente de liquidez" }, @@ -1732,9 +1729,6 @@ "message": "Varios tokens pueden usar el mismo nombre y símbolo. Verifique $1 para verificar que este es el token que está buscando.", "description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network." }, - "swapViewToken": { - "message": "Ver $1" - }, "swapYourTokenBalance": { "message": "$1 $2 están disponibles para intercambiar", "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" @@ -1810,7 +1804,7 @@ "message": "Grifo de prueba" }, "thisWillCreate": { - "message": "Esto creará un nuevo monedero y frase semilla" + "message": "Esto creará una cartera y una frase secreta de recuperación nuevas" }, "tips": { "message": "Consejos" @@ -1983,7 +1977,10 @@ "message": "nuestra guía de monedero físico" }, "walletSeed": { - "message": "Semilla del monedero" + "message": "Frase secreta de recuperación" + }, + "walletSeedRestore": { + "message": "Frase secreta de recuperación de la cartera" }, "web3ShimUsageNotification": { "message": "Notamos que el sitio web actual intentó utilizar la API window.web3 eliminada. Si el sitio parece estar roto, haga clic en $1 para obtener más información.", @@ -2015,7 +2012,7 @@ "message": "Usted está firmando" }, "yourPrivateSeedPhrase": { - "message": "Tu frase semilla privada" + "message": "Su frase secreta de recuperación privada" }, "zeroGasPriceOnSpeedUpError": { "message": "No hubo precio de gas al agilizar" diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index 1fe79aad6..a4fd64e03 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -1576,9 +1576,6 @@ "swapFinalizing": { "message": "Finalizando..." }, - "swapHighSlippageWarning": { - "message": "La cantidad de deslizamiento es muy alta. ¡Asegúrate de saber lo que estás haciendo!" - }, "swapLowSlippageError": { "message": "La transacción puede fallar, el deslizamiento máximo es demasiado bajo." }, @@ -1622,12 +1619,6 @@ "message": "Diferencia de precio de ~$1%", "description": "$1 is a number (ex: 1.23) that represents the price difference." }, - "swapPriceDifferenceTooltip": { - "message": "La diferencia en los precios de mercado puede verse afectada por las tarifas cobradas por los intermediarios, el tamaño del mercado, el tamaño del comercio o las ineficiencias del mercado." - }, - "swapPriceDifferenceUnavailable": { - "message": "El precio de mercado no está disponible. Asegúrese de sentirse cómodo con el monto devuelto antes de continuar." - }, "swapProcessing": { "message": "Procesando" }, @@ -1690,9 +1681,6 @@ "swapSelectQuotePopoverDescription": { "message": "A continuación se muestran todas las cotizaciones recopiladas de múltiples fuentes de liquidez." }, - "swapSlippageTooLow": { - "message": "El deslizamiento debe ser mayor que cero" - }, "swapSource": { "message": "Fuente de liquidez" }, @@ -1732,9 +1720,6 @@ "message": "Varios tokens pueden usar el mismo nombre y símbolo. Verifique $1 para verificar que este es el token que está buscando.", "description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network." }, - "swapViewToken": { - "message": "Ver $1" - }, "swapYourTokenBalance": { "message": "$1 $2 están disponibles para intercambiar", "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index c222c9c13..a275ff123 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -488,6 +488,9 @@ "dismiss": { "message": "खारिज करें" }, + "dismissReminderDescriptionField": { + "message": "रिकवरी फ्रेज़ बैकअप अनुस्मारक संदेश को खारिज करने के लिए इसे चालू करें। हम ज़ोर देकर अनुशंसा करते हैं कि आप धन के नुकसान से बचने के लिए अपने गुप्त रिकवरी फ्रेज़ का बैकअप लें" + }, "done": { "message": "संपन्न" }, @@ -523,7 +526,7 @@ "message": "एन्क्रिप्शन सार्वजनिक कुंजी का अनुरोध करें" }, "endOfFlowMessage1": { - "message": "आप टेस्ट में उत्तीर्ण हो गए हैं - अपने सीडफ्रेज़ को सुरक्षित रखें, यह आपकी ज़िम्मेदारी है!" + "message": "आप टेस्ट में उत्तीर्ण हो गए हैं - अपने गुप्त रिकवरी फ्रेज़ को सुरक्षित रखें, यह आपकी ज़िम्मेदारी है!" }, "endOfFlowMessage10": { "message": "सब कुछ हो गया" @@ -538,13 +541,13 @@ "message": "वाक्यांश को कभी भी किसी के साथ साझा न करें।" }, "endOfFlowMessage5": { - "message": "फ़िशिंग से सावधान रहें! MetaMask कभी भी अनायास ही आपके सीड फ्रेज़ के बारे में नहीं पूछेगा।" + "message": "फ़िशिंग से सावधान रहें! MetaMask कभी भी अनायास ही आपके गुप्त रिकवरी फ्रेज़ के बारे में नहीं पूछेगा।" }, "endOfFlowMessage6": { - "message": "यदि आपको अपने सीड फ्रेज़ को फिर से बैकअप लेने की आवश्यकता है, तो आप इसे सेटिंग्स -> सुरक्षा में पा सकते हैं।" + "message": "यदि आपको अपने गुप्त रिकवरी फ्रेज़ को फिर से बैकअप लेने की आवश्यकता है, तो आप इसे सेटिंग्स -> सुरक्षा में पा सकते हैं।" }, "endOfFlowMessage8": { - "message": "MetaMask आपके सीडफ्रेज़ को पुनर्प्राप्त नहीं कर सकता है।" + "message": "MetaMask आपके गुप्त रिकवरी फ्रेज़ को पुनर्प्राप्त नहीं कर सकता है।" }, "endOfFlowMessage9": { "message": "अधिक जानें।" @@ -763,15 +766,21 @@ "importAccount": { "message": "खाता आयात करें" }, + "importAccountLinkText": { + "message": "गुप्त रिकवरी फ्रेज़ का उपयोग करके आयात करें" + }, "importAccountMsg": { - "message": " आयातित खाते आपके मूल रूप से बनाए गए MetaMask खाते सीडफ्रेज़ से संबद्ध नहीं होंगे। आयातित खातों के बारे में अधिक जानें " + "message": " आयातित खाते आपके मूल रूप से बनाए गए MetaMask खाते के गुप्त रिकवरी फ्रेज़ से संबद्ध नहीं होंगे। आयातित खातों के बारे में अधिक जानें " }, "importAccountSeedPhrase": { - "message": "सीडफ्रेज़ के साथ कोई खाता आयात करें" + "message": "गुप्त रिकवरी फ्रेज़ के साथ एक खाता आयात करें" }, "importWallet": { "message": "वॉलेट आयात करें" }, + "importYourExisting": { + "message": "गुप्त रिकवरी फ्रेज़ का उपयोग करके अपने मौजूदा वॉलेट को आयात करें" + }, "imported": { "message": "आयातित", "description": "status showing that an account has been fully loaded into the keyring" @@ -833,7 +842,7 @@ "message": "अमान्य RPC URL" }, "invalidSeedPhrase": { - "message": "अमान्य सीड फ्रेज़" + "message": "अमान्य गुप्त रिकवरी फ्रेज़" }, "ipfsGateway": { "message": "IPFS गेटवे" @@ -1033,7 +1042,7 @@ "message": "इस नाम के लिए कोई पता नहीं सेट किया गया है।" }, "noAlreadyHaveSeed": { - "message": "नहीं, मेरे पास पहले से ही एक सीड फ्रेज़ है" + "message": "नहीं, मेरे पास पहले से ही एक गुप्त रिकवरी फ्रेज़ है" }, "noConversionRateAvailable": { "message": "कोई भी रूपांतरण दर उपलब्ध नहीं है" @@ -1217,7 +1226,7 @@ "message": "खाता निकालें" }, "removeAccountDescription": { - "message": "यह खाता आपके वॉलेट से निकाल दिया जाएगा। कृपया सुनिश्चित करें कि जारी रखने से पहले आपके पास इस आयातित खाते के लिए मूल सीड फ्रेज़ या निजी कुंजी है। आप खाता ड्रॉप-डाउन से फिर से खाते आयात कर सकते हैं या बना सकते हैं। " + "message": "यह खाता आपके वॉलेट से निकाल दिया जाएगा। कृपया सुनिश्चित करें कि जारी रखने से पहले आपके पास इस आयातित खाते के लिए मूल गुप्त रिकवरी फ्रेज़ या निजी कुंजी है। आप खाता ड्रॉप-डाउन से फिर से खाते आयात कर सकते हैं या बना सकते हैं। " }, "requestsAwaitingAcknowledgement": { "message": "अनुरोधों के स्वीकार किए जाने की प्रतीक्षा की जा रही है" @@ -1232,13 +1241,13 @@ "message": "खाता रीसेट करें" }, "resetAccountDescription": { - "message": "आपके खाते को रीसेट करने से आपका लेनदेन इतिहास साफ़ हो जाएगा। इससे आपके खातों में शेषराशि नहीं बदलेगी या आपको अपने सीड फ्रेज़ को फिर से दर्ज करने की आवश्यकता नहीं होगी।" + "message": "आपके खाते को रीसेट करने से आपका लेनदेन इतिहास साफ़ हो जाएगा। इससे आपके खातों में शेषराशि नहीं बदलेगी या आपको अपने गुप्त रिकवरी फ्रेज़ को फिर से दर्ज करने की आवश्यकता नहीं होगी।" }, "restore": { "message": "पुनर्स्थापित करें" }, "restoreAccountWithSeed": { - "message": "सीड फ्रेज़ के साथ अपने खाते को पुनर्स्थापित करें" + "message": "गुप्त रिकवरी फ्रेज़ के साथ अपने खाते को पुनर्स्थापित करें" }, "restoreWalletPreferences": { "message": "$1 से आपके डेटा का बैकअप मिला है। क्या आप अपनी वॉलेट वरीयताओं को पुनर्स्थापित करना चाहते हैं?", @@ -1251,13 +1260,13 @@ "message": "यहाँ पर एक टोकन आपके द्वारा देखे जाने वाले दूसरे टोकन से प्रतीक का पुनः उपयोग करता है, यह भ्रामक या धोखाधड़ी वाला हो सकता है।" }, "revealSeedWords": { - "message": "सीड फ्रेज़ प्रकट करें" + "message": "गुप्त रिकवरी फ्रेज़ प्रकट करें" }, "revealSeedWordsDescription": { - "message": "यदि आप कभी ब्राउज़र बदलते हैं या कंप्यूटर को स्थानांतरित करते हैं, तो आपको अपने खातों तक पहुँचने के लिए इस सीड फ्रेज़ की आवश्यकता होगी। उन्हें कहीं सुरक्षित और गोपनीय तरीके से सहेजें।" + "message": "यदि आप कभी ब्राउज़र बदलते हैं या कंप्यूटर को स्थानांतरित करते हैं, तो आपको अपने खातों तक पहुँचने के लिए इस गुप्त रिकवरी फ्रेज़ की आवश्यकता होगी। उन्हें कहीं सुरक्षित और गोपनीय तरीके से सहेजें।" }, "revealSeedWordsTitle": { - "message": "सीड फ्रेज़" + "message": "गुप्त रिकवरी फ्रेज़" }, "revealSeedWordsWarning": { "message": "इन शब्दों का उपयोग आपके सभी खातों को चुराने के लिए किया जा सकता है।" @@ -1314,16 +1323,16 @@ "message": "सुरक्षा और गोपनीयता" }, "securitySettingsDescription": { - "message": "गोपनीयता सेटिंग और वॉलेट सीड फ्रेज़" + "message": "गोपनीयता सेटिंग्स और वॉलेट का गुप्त रिकवरी फ्रेज़" }, "seedPhrasePlaceholder": { "message": "प्रत्येक शब्द को एक रिक्ति से अलग करें" }, "seedPhrasePlaceholderPaste": { - "message": "क्लिपबोर्ड से सीड फ्रेज़ को चिपकाएँ" + "message": "क्लिपबोर्ड से गुप्त रिकवरी फ्रेज़ को चिपकाएँ" }, "seedPhraseReq": { - "message": "सीड फ्रेज़ में 12, 15, 18, 21 या 24 शब्द हैं" + "message": "गुप्त रिकवरी फ्रेज़ में 12, 15, 18, 21 या 24 शब्द होते हैं" }, "selectAHigherGasFee": { "message": "अपने लेनदेन की प्रक्रिया में तेज़ी लाने के लिए उच्च गैस शुल्क का चयन करें। *" @@ -1408,7 +1417,7 @@ "message": "निजी कुंजियाँ दिखाएँ" }, "showSeedPhrase": { - "message": "सीड फ्रेज़ दिखाएँ" + "message": "गुप्त रिकवरी फ्रेज़ दिखाएँ" }, "sigRequest": { "message": "हस्ताक्षर का अनुरोध" @@ -1564,9 +1573,6 @@ "swapFinalizing": { "message": "अंतिम रूप दिया जा रहा है..." }, - "swapHighSlippageWarning": { - "message": "स्लिपेज राशि बहुत अधिक है। सुनिश्चित करें कि आप जानते हैं कि आप क्या कर रहे हैं!" - }, "swapLowSlippageError": { "message": "लेनदेन विफल हो सकता है, अधिकतम स्लिपेज बहुत कम हो सकता है।" }, @@ -1660,9 +1666,6 @@ "swapSelectQuotePopoverDescription": { "message": "नीचे दिए गए सभी उद्धरण कई चलनिधि स्रोतों से एकत्र किए गए हैं।" }, - "swapSlippageTooLow": { - "message": "स्लिपेज शून्य से अधिक होना चाहिए" - }, "swapSource": { "message": "चलनिधि का स्रोत" }, @@ -1699,9 +1702,6 @@ "message": "एकाधिक टोकन एक ही नाम और प्रतीक का उपयोग कर सकते हैं। यह सत्यापित करने के लिए $1 की जाँच करें कि यह वही टोकन है, जिसकी आप तलाश कर रहे हैं।", "description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network." }, - "swapViewToken": { - "message": "$1 देखें" - }, "swapYourTokenBalance": { "message": "$1 $2 स्वैप के लिए उपलब्ध है", "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" @@ -1774,7 +1774,7 @@ "message": "फ़ॉसेट का परीक्षण करें" }, "thisWillCreate": { - "message": "यह एक नया वॉलेट और सीड फ्रेज़ बनाएगा" + "message": "यह एक नया वॉलेट और गुप्त रिकवरी फ्रेज़ बनाएगा" }, "tips": { "message": "युक्तियाँ" @@ -1947,7 +1947,10 @@ "message": "हमारी हार्डवेयर वॉलेट कनेक्शन गाइड" }, "walletSeed": { - "message": "सीड फ्रेज़" + "message": "गुप्त रिकवरी फ्रेज़" + }, + "walletSeedRestore": { + "message": "वॉलेट का गुप्त रिकवरी फ्रेज़" }, "welcome": { "message": "MetaMask में आपका स्वागत है" @@ -1975,7 +1978,7 @@ "message": "आप हस्ताक्षर कर रहे हैं" }, "yourPrivateSeedPhrase": { - "message": "आपका निजी सीड फ्रेज़" + "message": "आपका निजी गुप्त रिकवरी फ्रेज़" }, "zeroGasPriceOnSpeedUpError": { "message": "ज़ीरो गैस मूल्य में तेज़ी" diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index e497c2eb0..153a20974 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -488,6 +488,9 @@ "dismiss": { "message": "Lewatkan" }, + "dismissReminderDescriptionField": { + "message": "Aktifkan ini untuk melewatkan pesan pengingat pencadangan frasa pemulihan. Kami sangat merekomendasikan agar Anda mencadangkan Frasa Pemulihan Rahasia Anda untuk menghindari hilangnya dana" + }, "done": { "message": "Selesai" }, @@ -523,7 +526,7 @@ "message": "Minta kunci publik enkripsi" }, "endOfFlowMessage1": { - "message": "Anda lulus ujian - jaga frasa pemulihan Anda tetap aman, ini tanggung jawab Anda!" + "message": "Anda lulus ujian - jaga Frasa Pemulihan Rahasia Anda tetap aman, ini tanggung jawab Anda!" }, "endOfFlowMessage10": { "message": "Semua Selesai" @@ -538,13 +541,13 @@ "message": "Jangan bagikan frasa kepada siapa pun." }, "endOfFlowMessage5": { - "message": "Berhati-hatilah dengan phishing! MetaMask tidak pernah secara spontan meminta frasa pemulihan Anda." + "message": "Berhati-hatilah dengan phishing! MetaMask tidak pernah secara spontan meminta Frasa Pemulihan Rahasia Anda." }, "endOfFlowMessage6": { - "message": "Jika Anda perlu mencadangkan frasa pemulihan lagi, Anda dapat menemukannya di Pengaturan -> Keamanan." + "message": "Jika Anda perlu mencadangkan Frasa Pemulihan Rahasia lagi, Anda dapat menemukannya di Pengaturan -> Keamanan." }, "endOfFlowMessage8": { - "message": "MetaMask tidak dapat memulihkan frasa pemulihan Anda." + "message": "MetaMask tidak dapat memulihkan Frasa Pemulihan Rahasia Anda." }, "endOfFlowMessage9": { "message": "Pelajari selengkapnya." @@ -763,15 +766,21 @@ "importAccount": { "message": "Impor Akun" }, + "importAccountLinkText": { + "message": "impor menggunakan Frasa Pemulihan Rahasia" + }, "importAccountMsg": { - "message": " Akun yang diimpor tidak akan dikaitkan dengan frasa pemulihan akun MetaMask yang asli dibuat. Pelajari selengkapnya tentang akun yang diimpor " + "message": " Akun yang diimpor tidak akan dikaitkan dengan Frasa Pemulihan Rahasia akun MetaMask yang asli dibuat. Pelajari selengkapnya tentang akun yang diimpor " }, "importAccountSeedPhrase": { - "message": "Impor akun dengan frasa pemulihan" + "message": "Impor akun dengan Frasa Pemulihan Rahasia" }, "importWallet": { "message": "Impor dompet" }, + "importYourExisting": { + "message": "Impor dompet Anda yang ada menggunakan Frasa Pemulihan Rahasia" + }, "imported": { "message": "Diimpor", "description": "status showing that an account has been fully loaded into the keyring" @@ -833,7 +842,7 @@ "message": "URL RPC Tidak Valid" }, "invalidSeedPhrase": { - "message": "Frasa pemulihan tidak valid" + "message": "Frasa Pemulihan Rahasia Tidak Valid" }, "ipfsGateway": { "message": "Gateway IPFS" @@ -1033,7 +1042,7 @@ "message": "Tidak ada alamat yang ditetapkan untuk nama ini." }, "noAlreadyHaveSeed": { - "message": "Tidak, saya sudah memiliki frasa pemulihan" + "message": "Tidak, saya sudah memiliki Frasa Pemulihan Rahasia" }, "noConversionRateAvailable": { "message": "Tidak Ada Nilai Konversi yang Tersedia" @@ -1217,7 +1226,7 @@ "message": "Hapus akun" }, "removeAccountDescription": { - "message": "Akun ini akan dihapus dari dompet Anda. Pastikan Anda memiliki frasa pemulihan asli atau kunci privat untuk akun impor ini sebelum melanjutkan. Anda dapat mengimpor atau membuat akun lagi dari akun drop down. " + "message": "Akun ini akan dihapus dari dompet Anda. Pastikan Anda memiliki Frasa Pemulihan Rahasia asli atau kunci privat untuk akun impor ini sebelum melanjutkan. Anda dapat mengimpor atau membuat akun lagi dari drop down akun. " }, "requestsAwaitingAcknowledgement": { "message": "permintaan menunggu untuk diakui" @@ -1232,13 +1241,13 @@ "message": "Atur Ulang Akun" }, "resetAccountDescription": { - "message": "Mengatur ulang akun akan mengosongkan riwayat transaksi Anda. Ini tidak akan mengubah saldo di akun atau mengharuskan Anda untuk memasukkan kembali frasa pemulihan Anda." + "message": "Mengatur ulang akun akan mengosongkan riwayat transaksi Anda. Ini tidak akan mengubah saldo di akun atau mengharuskan Anda untuk memasukkan kembali Frasa Pemulihan Rahasia Anda." }, "restore": { "message": "Pulihkan" }, "restoreAccountWithSeed": { - "message": "Memulihkan Akun dengan Frasa Pemulihan" + "message": "Memulihkan Akun dengan Frasa Pemulihan Rahasia" }, "restoreWalletPreferences": { "message": "Cadangan data Anda dari $1 telah ditemukan. Apakah Anda ingin memulihkan preferensi dompet Anda?", @@ -1251,13 +1260,13 @@ "message": "Token di sini menggunakan kembali simbol dari token lain yang Anda lihat, ini bisa jadi membingungkan atau menipu." }, "revealSeedWords": { - "message": "Mengungkapkan Frasa Pemulihan" + "message": "Mengungkapkan Frasa Pemulihan Rahasia" }, "revealSeedWordsDescription": { - "message": "Jika Anda pernah mengubah browser atau mengganti komputer, Anda akan memerlukan frasa pemulihan ini untuk mengakses akun Anda. Simpan di tempat yang aman dan rahasia." + "message": "Jika Anda pernah mengubah browser atau mengganti komputer, Anda akan memerlukan Frasa Pemulihan Rahasia ini untuk mengakses akun Anda. Simpan di tempat yang aman dan rahasia." }, "revealSeedWordsTitle": { - "message": "Frasa Pemulihan" + "message": "Frasa Pemulihan Rahasia" }, "revealSeedWordsWarning": { "message": "Kata-kata ini dapat digunakan untuk mencuri semua akun Anda." @@ -1314,16 +1323,16 @@ "message": "Keamanan & Privasi" }, "securitySettingsDescription": { - "message": "Pengaturan privasi dan frasa pemulihan dompet" + "message": "Pengaturan privasi dan Frasa Pemulihan Rahasia dompet" }, "seedPhrasePlaceholder": { "message": "Pisahkan setiap kata dengan satu spasi" }, "seedPhrasePlaceholderPaste": { - "message": "Tempel frasa pemulihan dari clipboard" + "message": "Tempel Frasa Pemulihan Rahasia dari clipboard" }, "seedPhraseReq": { - "message": "Frasa pemulihan berisi 12, 15, 18, 21, atau 24 kata" + "message": "Frasa Pemulihan Rahasia berisi 12, 15, 18, 21, atau 24 kata" }, "selectAHigherGasFee": { "message": "Pilih biaya jaringan yang lebih tinggi untuk mempercepat pemrosesan transaksi Anda.*" @@ -1408,7 +1417,7 @@ "message": "Tampilkan Kunci Privat" }, "showSeedPhrase": { - "message": "Tampilkan frasa pemulihan" + "message": "Menampilkan Frasa Pemulihan Rahasia" }, "sigRequest": { "message": "Permintaan Tanda Tangan" @@ -1564,9 +1573,6 @@ "swapFinalizing": { "message": "Menyelesaikan..." }, - "swapHighSlippageWarning": { - "message": "Jumlah slippage sangat tinggi. Pastikan Anda mengetahui yang Anda kerjakan!" - }, "swapLowSlippageError": { "message": "Transaksi bisa gagal, slippage maks. terlalu rendah." }, @@ -1660,9 +1666,6 @@ "swapSelectQuotePopoverDescription": { "message": "Di bawah ini adalah semua kuota yang dikumpulkan dari beberapa sumber likuiditas." }, - "swapSlippageTooLow": { - "message": "Slippage harus lebih besar dari nol" - }, "swapSource": { "message": "Sumber likuiditas" }, @@ -1699,9 +1702,6 @@ "message": "Beberapa token dapat menggunakan simbol dan nama yang sama. Periksa $1 untuk memverifikasi inilah token yang Anda cari.", "description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network." }, - "swapViewToken": { - "message": "Lihat $1" - }, "swapYourTokenBalance": { "message": "$1 $2 tersedia untuk ditukar", "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" @@ -1774,7 +1774,7 @@ "message": "Uji Fungsi" }, "thisWillCreate": { - "message": "Ini akan membuat frasa pemulihan dan dompet baru" + "message": "Ini akan membuat Frasa Pemulihan Rahasia dan dompet baru" }, "tips": { "message": "Kiat" @@ -1947,7 +1947,10 @@ "message": "panduan koneksi dompet perangkat keras kami" }, "walletSeed": { - "message": "Frasa pemulihan" + "message": "Frasa Pemulihan Rahasia" + }, + "walletSeedRestore": { + "message": "Frasa Pemulihan Rahasia Dompet" }, "welcome": { "message": "Selamat datang di MetaMask" @@ -1975,7 +1978,7 @@ "message": "Anda sudah masuk" }, "yourPrivateSeedPhrase": { - "message": "Frasa pemulihan privat Anda" + "message": "Frasa Pemulihan Rahasia pribadi Anda" }, "zeroGasPriceOnSpeedUpError": { "message": "Biaya jaringan nol dipercepat" diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index a312707c4..161086c29 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -1582,9 +1582,6 @@ "swapFinalizing": { "message": "Finalizzando..." }, - "swapHighSlippageWarning": { - "message": "L'importo di slippage è molto alto. Assicurati di sapere cosa stai facendo!" - }, "swapLowSlippageError": { "message": "La transazione può fallire, il massimo slippage è troppo basso." }, @@ -1624,19 +1621,10 @@ "message": "Stai per scambiare $1 $2 (~$3) per $4 $5 (~$6).", "description": "This message represents the price slippage for the swap. $1 and $4 are a number (ex: 2.89), $2 and $5 are symbols (ex: ETH), and $3 and $6 are fiat currency amounts." }, - "swapPriceDifferenceAcknowledgement": { - "message": "Sono consapevole" - }, "swapPriceDifferenceTitle": { "message": "Differenza di prezzo di circa ~$1%", "description": "$1 is a number (ex: 1.23) that represents the price difference." }, - "swapPriceDifferenceTooltip": { - "message": "La differenza tra i prezzi del mercato può essere influenzata da commissioni prelevate da intermediari, dimensione del mercato, dimensione dello scambio, o inefficienze del mercato." - }, - "swapPriceDifferenceUnavailable": { - "message": "Il prezzo di mercato non è disponibile. Assicurati di sentirti a tuo agio con l'importo restituito prima di procedere." - }, "swapProcessing": { "message": "In elaborazione" }, @@ -1702,9 +1690,6 @@ "swapSelectQuotePopoverDescription": { "message": "Sotto trovi tutte le quotazioni raccolte da multiple sorgenti di liquidità." }, - "swapSlippageTooLow": { - "message": "Lo slippage deve essere maggiore di zero" - }, "swapSource": { "message": "Sorgente di liquidità" }, @@ -1755,9 +1740,6 @@ "message": "Più token possono usare lo stesso nome e simbolo. Verifica su $1 che questo sia il token che stai cercando.", "description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network." }, - "swapViewToken": { - "message": "Vedi $1" - }, "swapYourTokenBalance": { "message": "$1 $2 disponibili allo scambio", "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index 78d2132a2..6b10b2c45 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -497,6 +497,9 @@ "dismiss": { "message": "却下" }, + "dismissReminderDescriptionField": { + "message": "これをオンにすると、リカバリー フレーズ バックアップのリマインダーメッセージが解除されます。資金の損失を防ぐために、シークレット リカバリー フレーズのバックアップを取ることを強くお勧めします。" + }, "done": { "message": "完了" }, @@ -532,7 +535,7 @@ "message": "公開暗号鍵の要求" }, "endOfFlowMessage1": { - "message": "テストに合格しました。シードフレーズを安全に保管してください。これは利用者の責務です。" + "message": "テストに合格しました。シークレット リカバリー フレーズを安全に保管してください。保管はお客様の責任となります。" }, "endOfFlowMessage10": { "message": "全て完了" @@ -547,13 +550,13 @@ "message": "シードフレーズは絶対に誰にも教えないでください。" }, "endOfFlowMessage5": { - "message": "フィッシング詐欺に注意してください!MetaMaskは自発的にシードフレーズを絶対に要求しません。" + "message": "フィッシングにご注意ください!MetaMask の動作として、シークレット リカバリー フレーズを要求することは絶対にありません。" }, "endOfFlowMessage6": { - "message": "シードフレーズを再度バックアップする場合は、[設定] -> [セキュリティとプライバシー] で見つけることができます。" + "message": "シークレット リカバリー フレーズを再度バックアップする場合は、[設定] -> [セキュリティとプライバシー] にアクセスしてください。" }, "endOfFlowMessage8": { - "message": "MetaMaskはシードフレーズを復元できません。" + "message": "MetaMask はシークレット リカバリー フレーズを復元できません。" }, "endOfFlowMessage9": { "message": "詳細を表示。" @@ -772,15 +775,21 @@ "importAccount": { "message": "アカウントのインポート" }, + "importAccountLinkText": { + "message": "シークレット リカバリー フレーズを使用してインポートする" + }, "importAccountMsg": { - "message": "追加したアカウントはMetaMaskのアカウントパスフレーズとは関連付けられません。インポートしたアカウントについての詳細は" + "message": " インポートされたアカウントは、最初に作成した MetaMask アカウントのシークレット リカバリー フレーズと関連付けられません。インポートされたアカウントの詳細を表示" }, "importAccountSeedPhrase": { - "message": "シードフレーズを使用してアカウントをインポート" + "message": "シークレット リカバリー フレーズを使用してアカウントをインポートする:" }, "importWallet": { "message": "ウォレットのインポート" }, + "importYourExisting": { + "message": "シークレット リカバリー フレーズを使用して既存のウォレットをインポートする" + }, "imported": { "message": "インポート済", "description": "status showing that an account has been fully loaded into the keyring" @@ -845,7 +854,7 @@ "message": "無効な RPC URL" }, "invalidSeedPhrase": { - "message": "無効なシードフレーズ" + "message": "無効なシークレット リカバリー フレーズ" }, "ipfsGateway": { "message": "IPFSゲートウェイ" @@ -1045,7 +1054,7 @@ "message": "この名前にはアドレスが設定されていません。" }, "noAlreadyHaveSeed": { - "message": "いいえ、既にシードフレーズがあります" + "message": "いいえ、既にシークレット リカバリー フレーズを持っています" }, "noConversionRateAvailable": { "message": "どの換算レートも利用できません" @@ -1226,7 +1235,7 @@ "message": "アカウントの削除" }, "removeAccountDescription": { - "message": "このアカウントはウォレットから削除されます。続行する前に、ウォレットにインポートしたアカウントのシードフレーズか秘密鍵を保管してください。アカウントは、アカウントのドロップダウンから再度インポート、または作成できます。" + "message": "このアカウントはウォレットから削除されます。続行する前に、インポートしたアカウントの元のシークレット リカバリー フレーズまたは秘密鍵を持っていることを確認してください。アカウントはアカウント ドロップダウンから再度インポートまたは作成できます。" }, "requestsAwaitingAcknowledgement": { "message": "承認されるまで待機する" @@ -1241,13 +1250,13 @@ "message": "アカウントをリセット" }, "resetAccountDescription": { - "message": "アカウントをリセットするとトランザクション履歴がクリアされます。シードフレーズの再入力は不要です。これによりアカウント内の残高が変更されることはありません。" + "message": "アカウントをリセットすると、トランザクション履歴がクリアされます。これによってアカウント内の残高が変更されることはありません。また、シークレット リカバリー フレーズの再入力を要求することはありません。" }, "restore": { "message": "復元" }, "restoreAccountWithSeed": { - "message": "シードフレーズでアカウントを復元" + "message": "シークレット リカバリー フレーズでアカウントを復元する" }, "restoreWalletPreferences": { "message": "$1 のデータバックアップが見つかりました。ウォレットの基本設定を復元しますか?", @@ -1260,13 +1269,13 @@ "message": "既に登録されているトークンシンボルと同じシンボルの登録はお勧めしません。混乱や操作ミスの原因になります。" }, "revealSeedWords": { - "message": "シードフレーズを表示" + "message": "シークレット リカバリー フレーズを公開する" }, "revealSeedWordsDescription": { - "message": "ブラウザを変更したりコンピュータを変更した場合は、アカウントにアクセスするためにシードフレーズが必要になります。安全で秘密の場所に保管してください。" + "message": "ブラウザーを変更した場合や、コンピューターを移動した場合は、自分のアカウントにアクセスするためにこのシークレット リカバリー フレーズが必要になります。安全で秘密の場所に保管してください。" }, "revealSeedWordsTitle": { - "message": "シードフレーズ" + "message": "シークレット リカバリー フレーズ" }, "revealSeedWordsWarning": { "message": "シードフレーズは全てのアカウントを盗む手段にも使えます。" @@ -1323,16 +1332,16 @@ "message": "セキュリティとプライバシー" }, "securitySettingsDescription": { - "message": "プライバシーの設定とウォレットのシードフレーズ" + "message": "プライバシーの設定とシークレット リカバリー フレーズ" }, "seedPhrasePlaceholder": { "message": "シードフレーズを単語ごとに半角スペースで分割して入力して下さい" }, "seedPhrasePlaceholderPaste": { - "message": "シードフレーズをクリップボードからペーストして下さい" + "message": "クリップボードからシークレット リカバリー フレーズを貼り付けます" }, "seedPhraseReq": { - "message": "シードフレーズには、12,15,18,21、または24単語が含まれます" + "message": "シークレット リカバリー フレーズには、12、15、18、21、24 語が含まれます" }, "selectAHigherGasFee": { "message": "トランザクションの処理を早めるには、より高いガス料金を選択してください。" @@ -1417,7 +1426,7 @@ "message": "秘密鍵の表示" }, "showSeedPhrase": { - "message": "シードフレーズの表示" + "message": "シークレット リカバリー フレーズを表示する" }, "sigRequest": { "message": "署名リクエスト" @@ -1576,9 +1585,6 @@ "swapFinalizing": { "message": "終了中..." }, - "swapHighSlippageWarning": { - "message": "非常に大きいスリッページ額です。本当に実行するか確認してください。" - }, "swapLowSlippageError": { "message": "トランザクションが失敗する可能性があります。最大スリッページが少なすぎます。" }, @@ -1622,12 +1628,6 @@ "message": "価格差は $1% です", "description": "$1 is a number (ex: 1.23) that represents the price difference." }, - "swapPriceDifferenceTooltip": { - "message": "市場価格の違いは、仲介業者が負担する手数料、市場規模、取引量、または取引価格差の影響を受けることがあります。" - }, - "swapPriceDifferenceUnavailable": { - "message": "マーケット価格は利用できません。続行する前に、返金額に問題がないことを確認してください。" - }, "swapProcessing": { "message": "処理中" }, @@ -1690,9 +1690,6 @@ "swapSelectQuotePopoverDescription": { "message": "以下は複数の流動性ソースから収集したすべての見積です。" }, - "swapSlippageTooLow": { - "message": "スリッページは 0 より多くする必要があります。" - }, "swapSource": { "message": "流動性ソース" }, @@ -1732,9 +1729,6 @@ "message": "複数のトークンが同じ名前とシンボルであることがあります。$1で実際のトークンでを確認してください。", "description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network." }, - "swapViewToken": { - "message": "$1 を表示" - }, "swapYourTokenBalance": { "message": "$1 $2 はスワップに使用できます", "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" @@ -1810,7 +1804,7 @@ "message": "テストFaucet" }, "thisWillCreate": { - "message": "新しいウォレットとシードフレーズが作成されます" + "message": "これにより、新しいウォレットとシークレット リカバリー フレーズが作成されます" }, "tips": { "message": "ヒント" @@ -1983,7 +1977,10 @@ "message": "ハードウェアウォレット接続ガイド" }, "walletSeed": { - "message": "シードフレーズ" + "message": "シークレット リカバリー フレーズ" + }, + "walletSeedRestore": { + "message": "ウォレット シークレット リカバリー フレーズ" }, "web3ShimUsageNotification": { "message": "このサイトは削除されたwindow.web3 APIを使用します。サイトに問題が発生しているなら、$1 で詳細を見ることができます。", @@ -2015,7 +2012,7 @@ "message": "署名しています" }, "yourPrivateSeedPhrase": { - "message": "秘密のシードフレーズ" + "message": "秘密のシークレット リカバリー フレーズ" }, "zeroGasPriceOnSpeedUpError": { "message": "追加のGas価格を0にできません" diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index 5cd7c37fc..735e81dcf 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -488,6 +488,9 @@ "dismiss": { "message": "해지" }, + "dismissReminderDescriptionField": { + "message": "이것을 켜서 복구 구문 백업 알림 메시지를 해지하십시오. 지갑을 복원할 수 있도록 비밀 복구 구문을 저장할 것을 강력하게 권장합니다." + }, "done": { "message": "완료" }, @@ -523,7 +526,7 @@ "message": "암호화 공개 키 요구" }, "endOfFlowMessage1": { - "message": "테스트를 통과하셨습니다. 시드 구문을 안전하게 보관할 책임은 귀하에게 있습니다!" + "message": "테스트를 통과하셨습니다. 비밀 복구 구문을 안전하게 보관할 책임은 귀하에게 있습니다!" }, "endOfFlowMessage10": { "message": "모두 완료" @@ -538,13 +541,13 @@ "message": "구문을 누구와도 공유하지 마세요." }, "endOfFlowMessage5": { - "message": "피싱을 조심하세요! MetaMask에서는 절대로 시드 구문을 갑자기 물어보지 않습니다." + "message": "피싱을 조심하십시오! MetaMask에서는 절대로 시드 구문을 갑자기 물어보지 않습니다." }, "endOfFlowMessage6": { - "message": "시드 구문을 다시 백업해야 한다면 설정 -> 보안에서 시드 구문을 찾을 수 있습니다." + "message": "비밀 복구 구문을 다시 백업해야 한다면 설정 -> 보안에서 시드 구문을 찾을 수 있습니다." }, "endOfFlowMessage8": { - "message": "MetaMask에서는 시드 구문을 복구할 수 없습니다." + "message": "MetaMask에서는 계정 시드 구문을 복구할 수 없습니다." }, "endOfFlowMessage9": { "message": "자세한 내용을 알아보세요." @@ -763,8 +766,11 @@ "importAccount": { "message": "계정 가져오기" }, + "importAccountLinkText": { + "message": "계정 시드 구문으로 가져오기" + }, "importAccountMsg": { - "message": " 가져온 계정은 생성한 MetaMask 계정 시드 구문 원본에 연결되지 않습니다. 가져온 계정에 대해 자세히 알아보세요. " + "message": " 가져온 계정은 생성한 MetaMask 계정 시드 구문 원본에 연결되지 않습니다. 가져온 계정에 대해 자세히 알아보십시오. " }, "importAccountSeedPhrase": { "message": "시드 구문으로 계정 가져오기" @@ -772,6 +778,9 @@ "importWallet": { "message": "지갑 가져오기" }, + "importYourExisting": { + "message": "12단어 시드 구문을 사용하여 지갑 가져오기" + }, "imported": { "message": "가져옴", "description": "status showing that an account has been fully loaded into the keyring" @@ -833,7 +842,7 @@ "message": "잘못된 RPC URL" }, "invalidSeedPhrase": { - "message": "잘못된 시드 구문" + "message": "잘못된 계정 시드 구문" }, "ipfsGateway": { "message": "IPFS 게이트웨이" @@ -1217,7 +1226,7 @@ "message": "계정 제거" }, "removeAccountDescription": { - "message": "이 계정이 지갑에서 제거됩니다. 계속하기 전에 가져온 이 계정에 대한 원본 시드 구문이나 비공개 키가 있는지 확인하세요. 계정 드롭다운에서 계정을 가져오거나 다시 만들 수 있습니다. " + "message": "이 계정이 지갑에서 제거됩니다. 계속하기 전에 가져온 이 계정에 대한 원본 시드 구문이나 비공개 키가 있는지 확인하십시오. 계정 드롭다운에서 계정을 가져오거나 다시 만들 수 있습니다. " }, "requestsAwaitingAcknowledgement": { "message": "확인 대기 중인 요청" @@ -1232,7 +1241,7 @@ "message": "계정 재설정" }, "resetAccountDescription": { - "message": "계정을 재설정하면 거래 내역이 지워집니다. 계정의 잔액이 변경되지는 않으면 시드 구문을 다시 입력하지 않아도 됩니다." + "message": "계정을 재설정하면 거래 내역이 지워집니다. 계정의 잔액이 변경되지 않으면 시드 구문을 다시 입력하지 않아도 됩니다." }, "restore": { "message": "복구" @@ -1251,13 +1260,13 @@ "message": "여기에 있는 토큰은 사용자가 확인한 다른 토큰의 기호를 재사용하기 때문에 혼란스럽거나 속기 쉽습니다." }, "revealSeedWords": { - "message": "시드 단어 공개" + "message": "계정 시드 구문 공개" }, "revealSeedWordsDescription": { - "message": "브라우저를 변경하거나 컴퓨터를 옮긴 경우, 계정에 액세스하려면 이 시드 구문이 필요합니다. 기밀이 보장된 안전한 곳에 보관하세요." + "message": "브라우저를 변경하거나 컴퓨터를 옮긴 경우, 계정에 액세스하려면 이 시드 구문이 필요합니다. 기밀이 보장된 안전한 곳에 보관하십시오." }, "revealSeedWordsTitle": { - "message": "시드 구문" + "message": "계정 시드 구문" }, "revealSeedWordsWarning": { "message": "이 구문은 계정 전체를 도용하는 데 사용될 수 있습니다." @@ -1408,7 +1417,7 @@ "message": "비공개 키 표시" }, "showSeedPhrase": { - "message": "시드 구문 표시" + "message": "계정 시드 구문 표시" }, "sigRequest": { "message": "서명 요청" @@ -1564,9 +1573,6 @@ "swapFinalizing": { "message": "마무리 중..." }, - "swapHighSlippageWarning": { - "message": "슬리패지 금액이 아주 큽니다. 현재 어떤 작업을 하고 있는지 확인하세요!" - }, "swapLowSlippageError": { "message": "거래가 실패할 수도 있습니다. 최대 슬리패지가 너무 낮습니다." }, @@ -1660,9 +1666,6 @@ "swapSelectQuotePopoverDescription": { "message": "다음은 여러 유동성 소스에서 수집한 전체 견적입니다." }, - "swapSlippageTooLow": { - "message": "슬리패지는 0보다 커야 합니다." - }, "swapSource": { "message": "유동성 소스" }, @@ -1699,9 +1702,6 @@ "message": "여러 토큰이 같은 이름과 기호를 사용할 수 있습니다. $1을 확인하여 이것이 원하는 토큰인지 확인하세요.", "description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network." }, - "swapViewToken": { - "message": "$1 보기" - }, "swapYourTokenBalance": { "message": "$1 $2 스왑 가능", "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" @@ -1947,7 +1947,10 @@ "message": "당사의 하드웨어 지갑 연결 가이드" }, "walletSeed": { - "message": "시드 구문" + "message": "계정 시드 구문" + }, + "walletSeedRestore": { + "message": "지갑 계정 시드 구문" }, "welcome": { "message": "MetaMask 방문을 환영합니다" @@ -1975,7 +1978,7 @@ "message": "서명 중입니다." }, "yourPrivateSeedPhrase": { - "message": "귀하의 비공개 시드 구문입니다." + "message": "비밀 백업 구문 확인" }, "zeroGasPriceOnSpeedUpError": { "message": "가속화 시 Gas 가격 0" diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index f5c307e86..69c028186 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -299,6 +299,9 @@ "directDepositEtherExplainer": { "message": "Se você já tem Ether, a forma mais rápida de colocá-lo em sua nova carteira é o depósito direto." }, + "dismissReminderDescriptionField": { + "message": "Ative isso para descartar a mensagem de lembrete de backup da frase de recuperação. Recomendamos enfaticamente que você faça o backup da sua Frase de recuperação secreta para evitar perda de fundos" + }, "done": { "message": "Concluído" }, @@ -321,7 +324,7 @@ "message": "Editar Contato" }, "endOfFlowMessage1": { - "message": "Você passou no teste — mantenha sua frase semente segura, a responsabilidade é sua!" + "message": "Você passou no teste. Guarde sua Frase de recuperação secreta em segurança, é sua responsabilidade!" }, "endOfFlowMessage10": { "message": "Pronto" @@ -336,13 +339,13 @@ "message": "Nunca compartilhe a frase com ninguém." }, "endOfFlowMessage5": { - "message": "Cuidado com o phishing! O MetaMask nunca solicitará espontaneamente sua frase semente." + "message": "Cuidado com phishing! O MetaMask jamais pedirá espontaneamente sua Frase de recuperação secreta." }, "endOfFlowMessage6": { - "message": "Se precisar fazer backup de sua frase-semente de novo, acesse Configurações -> Segurança." + "message": "Se você precisar fazer backup da sua Frase de recuperação secreta novamente, encontre-a em Configurações -> Segurança." }, "endOfFlowMessage8": { - "message": "O MetaMask não pode recuperar sua frase semente. Saiba mais." + "message": "O MetaMask não pode recuperar sua Frase de recuperação secreta." }, "endOfFlowMessage9": { "message": "Saiba mais." @@ -478,15 +481,21 @@ "importAccount": { "message": "Importar Conta" }, + "importAccountLinkText": { + "message": "importar usando a Frase de recuperação secreta" + }, "importAccountMsg": { - "message": "As contas importadas não serão associadas à sua frase-semente da conta MetaMask criada originalmente. Saiba mais sobre contas importadas" + "message": " As contas importadas não estarão associadas à Frase de recuperação secreta da conta do MetaMask criada originalmente. Saiba mais sobre as contas importadas " }, "importAccountSeedPhrase": { - "message": "Importar uma Conta com Frase-semente" + "message": "Importe uma conta com a Frase de recuperação secreta" }, "importWallet": { "message": "Importar Carteira" }, + "importYourExisting": { + "message": "Importar a carteira existente usando uma Frase de recuperação secreta" + }, "imported": { "message": "Importado", "description": "status showing that an account has been fully loaded into the keyring" @@ -519,7 +528,7 @@ "message": "URL de RPC inválida" }, "invalidSeedPhrase": { - "message": "Frase semente inválida" + "message": "Frase de recuperação secreta inválida" }, "jsonFile": { "message": "Arquivo JSON", @@ -645,7 +654,7 @@ "message": "Nenhum endereço foi definido para este nome." }, "noAlreadyHaveSeed": { - "message": "Não, eu já tenho uma frase semente" + "message": "Não, eu já tenho uma Frase de recuperação secreta" }, "noConversionRateAvailable": { "message": "Nenhuma Taxa de Conversão Disponível" @@ -773,7 +782,7 @@ "message": "Remover conta" }, "removeAccountDescription": { - "message": "Esta conta será removida de sua carteira. Verifique se você tem a frase-semente original ou a chave particular desta conta importada antes de continuar. Você pode importar ou criar contas novamente no menu suspenso da conta." + "message": "Esta conta será removida da sua carteira. Antes de continuar, você precisa garantir que tem a Frase de recuperação secreta original ou chave privada para esta conta importada. Você pode importar ou criar contas novamente a partir do menu suspenso da conta. " }, "requestsAwaitingAcknowledgement": { "message": "solicitações aguardando confirmação" @@ -788,22 +797,22 @@ "message": "Redefinir Conta" }, "resetAccountDescription": { - "message": "Restabelecer a sua conta limpará todo o seu histórico de transações." + "message": "Redefinir sua conta limpará o histórico de transações. Isso não alterará os saldos nas suas contas nem exigirá a reinserção da Frase de recuperação secreta." }, "restore": { "message": "Restaurar" }, "restoreAccountWithSeed": { - "message": "Restaurar sua conta com a frase semente" + "message": "Restaure sua conta com a Frase de recuperação secreta" }, "revealSeedWords": { - "message": "Revelar Palavras-semente" + "message": "Revelar Frase de recuperação secreta" }, "revealSeedWordsDescription": { - "message": "Se você mudar de navegador ou computador, precisará dessa frase semente para acessar suas contas. Salve-as em algum lugar seguro e secreto." + "message": "Se você alguma vez mudou de navegador ou trocou de computador, precisará dessa Frase de recuperação secreta para acessar suas contas. Salve-as em um lugar seguro e secreto." }, "revealSeedWordsTitle": { - "message": "Frase Semente" + "message": "Frase de recuperação secreta" }, "revealSeedWordsWarning": { "message": "Essas palavras podem ser usadas para roubar todas as suas contas." @@ -854,13 +863,16 @@ "message": "Segurança & Privacidade" }, "securitySettingsDescription": { - "message": "Configurações de privacidade e frase-semente da carteira" + "message": "Configurações de privacidade e Frase de recuperação secreta" }, "seedPhrasePlaceholder": { "message": "Separe cada palavra com um único espaço" }, + "seedPhrasePlaceholderPaste": { + "message": "Cole a Frase de recuperação secreta da área de transferência" + }, "seedPhraseReq": { - "message": "As frases-semente têm 12 palavras" + "message": "As Frases de recuperação secreta contêm 12, 15, 18, 21 ou 24 palavras" }, "selectAHigherGasFee": { "message": "Selecione uma taxa de gás mais alta para acelerar o processamento de sua transação.*" @@ -922,6 +934,9 @@ "showPrivateKeys": { "message": "Mostrar Chaves Privadas" }, + "showSeedPhrase": { + "message": "Mostrar Frase de recuperação secreta" + }, "sigRequest": { "message": "Solicitação de Assinatura" }, @@ -1007,7 +1022,7 @@ "message": "Torneira de Testes" }, "thisWillCreate": { - "message": "Isso criará uma nova carteira e frase-semente" + "message": "Isso criará uma nova carteira e Frase de recuperação secreta" }, "tips": { "message": "Doações" @@ -1140,7 +1155,10 @@ "message": "Visite nosso site" }, "walletSeed": { - "message": "Semente da Carteira" + "message": "Frase de recuperação secreta" + }, + "walletSeedRestore": { + "message": "Frase de recuperação secreta da carteira" }, "welcome": { "message": "Bem-vindo ao MetaMask" @@ -1161,7 +1179,7 @@ "message": "Você está assinando" }, "yourPrivateSeedPhrase": { - "message": "Sua frase-semente particular" + "message": "Sua Frase de recuperação secreta privada" }, "zeroGasPriceOnSpeedUpError": { "message": "Preço de Gas zero na agilização" diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index 7208b08fe..85fd35b9d 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -488,6 +488,9 @@ "dismiss": { "message": "Отклонить" }, + "dismissReminderDescriptionField": { + "message": "Включите этот параметр, чтобы отклонить сообщение с напоминанием о резервном копировании фразы восстановления. Мы настоятельно рекомендуем сделать резервную копию секретной фразы восстановления, чтобы избежать потери средств" + }, "done": { "message": "Выполнено" }, @@ -523,7 +526,7 @@ "message": "Запросить открытый ключ шифрования." }, "endOfFlowMessage1": { - "message": "Вы прошли тест — храните свою исходную фразу в безопасности, это ваша ответственность!" + "message": "Вы прошли тест — храните свою секретную фразу восстановления в безопасности, это ваша ответственность!" }, "endOfFlowMessage10": { "message": "Выполнено" @@ -538,13 +541,13 @@ "message": "Никогда не говорите никому эту фразу." }, "endOfFlowMessage5": { - "message": "Остерегайтесь фишинга! MetaMask никогда неожиданно не запросит вашу исходную фразу." + "message": "Остерегайтесь фишинга! MetaMask никогда неожиданно не запросит вашу секретную фразу восстановления." }, "endOfFlowMessage6": { - "message": "Если вам нужно снова создать резервную копию исходной фразы, вы можете найти ее в Настройки -> Безопасность." + "message": "Если вам нужно снова создать резервную копию секретной фразы восстановления, вы можете найти ее в Настройки -> Безопасность." }, "endOfFlowMessage8": { - "message": "Просто помните, что MetaMask не может восстановить исходную фразу." + "message": "Просто помните, что MetaMask не может восстановить секретную фразу восстановления." }, "endOfFlowMessage9": { "message": "Дополнительная информация" @@ -763,15 +766,21 @@ "importAccount": { "message": "Импортировать счет" }, + "importAccountLinkText": { + "message": "импортировать с использованием секретной фразы восстановления" + }, "importAccountMsg": { - "message": " Импортированные счета не будут связаны с исходной фразой вашей изначально созданного счета MetaMask. Узнайте больше об импортированных счетах " + "message": " Импортированные счета не будут связаны с секретной фразой восстановления вашего изначально созданного счета MetaMask. Узнайте больше об импортированных счетах " }, "importAccountSeedPhrase": { - "message": "Импортировать счет с исходной фразой" + "message": "Импортировать счет с секретной фразой восстановления" }, "importWallet": { "message": "Импортировать кошелек" }, + "importYourExisting": { + "message": "Импортируйте существующий кошелек, используя начальную секретную фразу восстановления" + }, "imported": { "message": "Импортированный", "description": "status showing that an account has been fully loaded into the keyring" @@ -833,7 +842,7 @@ "message": "Недействительный URL-адрес RPC" }, "invalidSeedPhrase": { - "message": "Неверная исходная фраза" + "message": "Недействительная секретная фраза восстановления" }, "ipfsGateway": { "message": "Шлюз IPFS" @@ -1033,7 +1042,7 @@ "message": "Для этого имени не задан адрес." }, "noAlreadyHaveSeed": { - "message": "Нет, у меня уже есть исходная фраза" + "message": "Нет, у меня уже есть секретная фраза восстановления" }, "noConversionRateAvailable": { "message": "Нет доступного курса обмена" @@ -1217,7 +1226,7 @@ "message": "Удалить счет" }, "removeAccountDescription": { - "message": "Этот счет будет удален из вашего кошелька. Перед продолжением убедитесь, что у вас есть исходная фраза или закрытый ключ для этой импортированного счета. Вы можете импортировать или снова создать счета из раскрывающегося списка. " + "message": "Этот счет будет удален из вашего кошелька. Перед продолжением убедитесь, что у вас есть секретная фраза восстановления или закрытый ключ для этой импортированного счета. Вы можете импортировать или снова создать счета из раскрывающегося списка. " }, "requestsAwaitingAcknowledgement": { "message": "запросы, ожидающие подтверждения" @@ -1232,13 +1241,13 @@ "message": "Сбросить счет" }, "resetAccountDescription": { - "message": "Сброс вашего счета удалит историю транзакций. Это не изменит остатки на ваших счетах и не потребует повторного ввода исходной фразы." + "message": "Сброс вашего счета удалит историю транзакций. Это не изменит остатки на ваших счетах и не потребует повторного ввода секретной фразы восстановления." }, "restore": { "message": "Восстановить" }, "restoreAccountWithSeed": { - "message": "Восстановите свой счет с помощью исходной фразы" + "message": "Восстановите свой счет с помощью секретной фразы восстановления" }, "restoreWalletPreferences": { "message": "Найдена резервная копия ваших данных из $1. Хотите восстановить настройки кошелька?", @@ -1251,13 +1260,13 @@ "message": "Токен здесь повторно использует символ из другого токена, который вы смотрите, это может запутать или ввести в заблуждение." }, "revealSeedWords": { - "message": "Раскрыть исходную фразу" + "message": "Показать секретную фразу восстановления" }, "revealSeedWordsDescription": { - "message": "Если вы меняете браузер или переходите на другой компьютер, вам понадобится эта исходная фраза для доступа к своим счетам. Сохраните ее в безопасном секретном месте." + "message": "Если вы меняете браузер или переходите на другой компьютер, вам понадобится эта секретная фраза восстановления для доступа к своим счетам. Сохраните ее в безопасном секретном месте." }, "revealSeedWordsTitle": { - "message": "Исходная фраза" + "message": "Секретная фраза восстановления" }, "revealSeedWordsWarning": { "message": "Эти слова можно использовать для кражи всех ваших счетов." @@ -1314,16 +1323,16 @@ "message": "Безопасность и конфиденциальность" }, "securitySettingsDescription": { - "message": "Настройки конфиденциальности и исходная фраза кошелька" + "message": "Настройки конфиденциальности и секретная фраза восстановления кошелька" }, "seedPhrasePlaceholder": { "message": "Отделяйте каждое слово одним пробелом" }, "seedPhrasePlaceholderPaste": { - "message": "Вставить исходную фразу из буфера обмена" + "message": "Вставить секретную фразу восстановления из буфера обмена" }, "seedPhraseReq": { - "message": "Исходные фразы содержат 12, 15, 18, 21 или 24 слова" + "message": "Секретные фразы восстановления содержат 12, 15, 18, 21 или 24 слова" }, "selectAHigherGasFee": { "message": "Выберите более высокую плату за топливо, чтобы ускорить обработку транзакции. *" @@ -1408,7 +1417,7 @@ "message": "Показать закрытые ключи" }, "showSeedPhrase": { - "message": "Показать исходную фразу" + "message": "Показать секретную фразу восстановления" }, "sigRequest": { "message": "Запрос на подпись" @@ -1564,9 +1573,6 @@ "swapFinalizing": { "message": "Завершение..." }, - "swapHighSlippageWarning": { - "message": "Величина проскальзывания очень велика. Убедитесь, что вы знаете, что делаете!" - }, "swapLowSlippageError": { "message": "Транзакции могут завершиться неудачей, максимальное проскальзывание слишком мало." }, @@ -1660,9 +1666,6 @@ "swapSelectQuotePopoverDescription": { "message": "Ниже приведены все котировки, собранные из нескольких источников ликвидности." }, - "swapSlippageTooLow": { - "message": "Проскальзывание должно быть больше нуля" - }, "swapSource": { "message": "Источник ликвидности" }, @@ -1699,9 +1702,6 @@ "message": "Несколько токенов могут использовать одно и то же имя и символ. Проверьте $1, чтобы убедиться, что это именно тот токен, который вы ищете.", "description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network." }, - "swapViewToken": { - "message": "Просмотреть $1" - }, "swapYourTokenBalance": { "message": "$1 $2 доступны для свопа", "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" @@ -1774,7 +1774,7 @@ "message": "Тестовый кран" }, "thisWillCreate": { - "message": "Это создаст новый кошелек и начальную фразу" + "message": "Это создаст новый кошелек и секретную фразу восстановления" }, "tips": { "message": "Советы" @@ -1947,7 +1947,10 @@ "message": "наше руководство по подключению аппаратного кошелька" }, "walletSeed": { - "message": "Исходная фраза" + "message": "Секретная фраза восстановления" + }, + "walletSeedRestore": { + "message": "Секретная фраза восстановления кошелька" }, "welcome": { "message": "Добро пожаловать в MetaMask" @@ -1975,7 +1978,7 @@ "message": "Вы подписываете" }, "yourPrivateSeedPhrase": { - "message": "Ваша личная исходная фраза" + "message": "Ваша личная секретная фраза восстановления" }, "zeroGasPriceOnSpeedUpError": { "message": "Нулевая цена на топливо при ускорении" diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json index 70b7b8ad8..caf6059fd 100644 --- a/app/_locales/tl/messages.json +++ b/app/_locales/tl/messages.json @@ -488,6 +488,9 @@ "dismiss": { "message": "I-dismiss" }, + "dismissReminderDescriptionField": { + "message": "I-on ito para i-dismiss ang mensahe ng paalala ng pag-back up ng recovery phrase. Lubos naming inirerekomendang i-back up mo ang iyong Secret Recovery Phrase para maiwasan ang pagkawala ng pondo" + }, "done": { "message": "Tapos na" }, @@ -523,7 +526,7 @@ "message": "Mag-request ng pampublikong encryption key" }, "endOfFlowMessage1": { - "message": "Naipasa mo ang pagsusulit - panatilihing ligtas ang iyong seedphrase, responsibilidad mo ito!" + "message": "Pumasa ka sa test - panatilihing ligtas ang iyong Secret Recovery Phrase, responsibilidad mo ito!" }, "endOfFlowMessage10": { "message": "Tapos Na Lahat" @@ -538,13 +541,13 @@ "message": "Huwag kailanmang ibahagi ang parirala sa sinuman." }, "endOfFlowMessage5": { - "message": "Mag-ingat sa phishing! Hindi kailanman basta na lang hihingin ng MetaMask ang iyong seed phrase." + "message": "Mag-ingat sa phishing! Hindi kailanman basta na lang hihingin ng MetaMask ang iyong Secret Recovery Phrase." }, "endOfFlowMessage6": { - "message": "Kung kailangan mong i-back up ulit ang iyong seed phrase, makikita mo ito sa Mga Setting -> Seguridad." + "message": "Kung kailangan mong i-back up ulit ang iyong Secret Recovery Phrase, makikita mo ito sa Mga Setting -> Seguridad." }, "endOfFlowMessage8": { - "message": "Hindi mababawi ng MetaMask ang iyong seedphrase." + "message": "Hindi mababawi ng MetaMask ang iyong Secret Recovery Phrase." }, "endOfFlowMessage9": { "message": "Matuto pa." @@ -763,15 +766,21 @@ "importAccount": { "message": "Mag-import ng Account" }, + "importAccountLinkText": { + "message": "i-import gamit ang Secret Recovery Phrase" + }, "importAccountMsg": { - "message": " Ang mga na-import na account ay hindi mauugnay sa orihinal mong nagawang seedphrase ng MetaMask account. Matuto pa tungkol sa mga na-import account " + "message": " Ang mga na-import na account ay hindi mauugnay sa orihinal mong nagawang Secret Recovery Phrase ng MetaMask account. Matuto pa tungkol sa mga na-import account " }, "importAccountSeedPhrase": { - "message": "Mag-import ng account gamit ang seed phrase" + "message": "Mag-import ng account gamit ang Secret Recovery Phrase" }, "importWallet": { "message": "I-import ang wallet" }, + "importYourExisting": { + "message": "I-import ang iyong kasalukuyang wallet gamit ang isang Secret Recovery Phrase" + }, "imported": { "message": "Na-import", "description": "status showing that an account has been fully loaded into the keyring" @@ -833,7 +842,7 @@ "message": "Hindi valid ang RPC URL" }, "invalidSeedPhrase": { - "message": "Hindi valid ang seed phrase" + "message": "Hindi valid ang Secret Recovery Phrase" }, "ipfsGateway": { "message": "IPFS Gateway" @@ -1033,7 +1042,7 @@ "message": "Walang naitakdang address para sa pangalang ito." }, "noAlreadyHaveSeed": { - "message": "May seed phrase na ako" + "message": "Hindi, may Secret Recovery Phrase na ako" }, "noConversionRateAvailable": { "message": "Hindi Available ang Rate ng Conversion" @@ -1214,7 +1223,7 @@ "message": "Tanggalin ang account" }, "removeAccountDescription": { - "message": "Tatanggalin ang account na ito sa iyong wallet. Tiyaking nasa iyo ang orihinal na seed phrase o pribadong key para sa na-import na account na ito bago magpatuloy. Puwede kang mag-import o gumawa ulit ng mga account mula sa drop-down ng account. " + "message": "Tatanggalin ang account na ito sa iyong wallet. Tiyaking nasa iyo ang orihinal na Secret Recovery Phrase o private key para sa na-import na account na ito bago magpatuloy. Puwede kang mag-import o gumawa ulit ng mga account mula sa drop-down ng account. " }, "requestsAwaitingAcknowledgement": { "message": "mga request na hinihintay na tanggapin" @@ -1229,13 +1238,13 @@ "message": "I-reset ang Account" }, "resetAccountDescription": { - "message": "Kapag ni-reset ang iyong account, maki-clear ang history ng iyong transaksyon. Hindi nito babaguhin ang mga balanse sa iyong mga account o hindi mo kakailanganing ilagay ulit ang iyong seed phrase." + "message": "Kapag ni-reset ang iyong account, maki-clear ang history ng iyong transaksyon. Hindi nito babaguhin ang mga balanse sa iyong mga account o hindi mo kakailanganing ilagay ulit ang iyong Secret Recovery Phrase." }, "restore": { "message": "I-restore" }, "restoreAccountWithSeed": { - "message": "I-restore ang iyong Account gamit ang Seed Phrase" + "message": "I-restore ang iyong Account gamit ang Secret Recovery Phrase" }, "restoreWalletPreferences": { "message": "Nakita ang backup ng iyong data mula sa $1. Gusto mo bang i-restore ang mga kagustuhan mo sa wallet?", @@ -1248,13 +1257,13 @@ "message": "Ang isang token dito ay muling ginagamit ang isang simbolo mula sa ibang token na tinitingnan mo, maaari itong maging nakakalito." }, "revealSeedWords": { - "message": "Ipakita ang Seed Phrase" + "message": "Ipakita ang Secret Recovery Phrase" }, "revealSeedWordsDescription": { - "message": "Kung papalitan mo ang iyong browser o ililipat ang mga computer, kakailanganin mo ang seed phrase na ito para ma-access ang iyong mga account. I-save ang mga iyon sa isang ligtas at sikretong lugar." + "message": "Kung magpapalit ka man ng browser o computer, kakailanganin mo ang Secret Recovery Phrase na ito para ma-access ang iyong mga account. I-save ang mga iyon sa isang ligtas at sikretong lugar." }, "revealSeedWordsTitle": { - "message": "Seed Phrase" + "message": "Secret Recovery Phrase" }, "revealSeedWordsWarning": { "message": "Magagamit ang mga salitang ito para manakaw ang lahat ng iyong account." @@ -1311,16 +1320,16 @@ "message": "Seguridad at Pagkapribado" }, "securitySettingsDescription": { - "message": "Mga setting ng pagkapribado at seed phrase ng wallet" + "message": "Mga setting ng privacy at Secret Recovery Phrase ng wallet" }, "seedPhrasePlaceholder": { "message": "Paghiwa-hiwalayin ang bawat salita gamit ang espasyo" }, "seedPhrasePlaceholderPaste": { - "message": "I-paste ang seed phrase mula sa clipboard" + "message": "I-paste ang Secret Recovery Phrase mula sa clipboard" }, "seedPhraseReq": { - "message": "Ang mga seed phrase ay naglalaman ng 12, 15, 18, 21, o 24 na salita" + "message": "Ang mga Secret Recovery Phrase ay naglalaman ng 12, 15, 18, 21, o 24 na salita" }, "selectAHigherGasFee": { "message": "Pumili ng mas malaking bayarin sa gas para mapabilis ang pagproseso ng iyong transaksyon.*" @@ -1405,7 +1414,7 @@ "message": "Ipakita ang Mga Pribadong Key" }, "showSeedPhrase": { - "message": "Ipakita ang seed phrase" + "message": "Ipakita ang Secret Recovery Phrase" }, "sigRequest": { "message": "Request na Paglagda" @@ -1561,9 +1570,6 @@ "swapFinalizing": { "message": "Isinasapinal..." }, - "swapHighSlippageWarning": { - "message": "Sobrang laki ng halaga ng slippage. Tiyaking alam mo ang ginagawa mo!" - }, "swapLowSlippageError": { "message": "Maaaring hindi magtagumpay ang transaksyon, masyadong mababa ang max na slippage." }, @@ -1657,9 +1663,6 @@ "swapSelectQuotePopoverDescription": { "message": "Makikita sa ibaba ang lahat ng quote na nakuha mula sa maraming pinagkukunan ng liquidity." }, - "swapSlippageTooLow": { - "message": "Dapat ay mas malaki sa zero ang slippage" - }, "swapSource": { "message": "Pinagkunan ng liquidity" }, @@ -1696,9 +1699,6 @@ "message": "Maaaring gamitin ng maraming token ang iisang pangalan at simbolo. Suriin ang $1 para ma-verify na ito ang token na hinahanap mo.", "description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network." }, - "swapViewToken": { - "message": "Tingnan ang $1" - }, "swapYourTokenBalance": { "message": "Available ang $1 $2 na i-swap", "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" @@ -1771,7 +1771,7 @@ "message": "Test Faucet" }, "thisWillCreate": { - "message": "Gagawa ito ng bagong wallet at seed phrase" + "message": "Gagawa ito ng bagong wallet at Secret Recovery Phrase" }, "tips": { "message": "Mga Tip" @@ -1944,7 +1944,10 @@ "message": "ang aming gabay sa pagkonekta ng hardware wallet" }, "walletSeed": { - "message": "Seed phrase" + "message": "Secret Recovery Phrase" + }, + "walletSeedRestore": { + "message": "Recovery Phrase ng Wallet Secret" }, "welcome": { "message": "Welcome sa MetaMask" diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index 883c2f67d..671004f16 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -488,6 +488,9 @@ "dismiss": { "message": "Đóng" }, + "dismissReminderDescriptionField": { + "message": "Bật tùy chọn này để tắt thông báo nhắc sao lưu cụm mật khẩu khôi phục. Bạn nên sao lưu Cụm mật khẩu khôi phục bí mật của mình để tránh mất tiền" + }, "done": { "message": "Hoàn tất" }, @@ -523,7 +526,7 @@ "message": "Yêu cầu khóa mã hóa công khai" }, "endOfFlowMessage1": { - "message": "Bạn đã vượt qua bài kiểm tra. Hãy lưu giữ cụm mật khẩu gốc của bạn an toàn, đó là trách nhiệm của bạn!" + "message": "Bạn đã vượt qua bài kiểm tra. Hãy lưu giữ Cụm mật khẩu khôi phục bí mật của bạn an toàn, đó là trách nhiệm của bạn!" }, "endOfFlowMessage10": { "message": "Tất cả đã hoàn tất" @@ -538,13 +541,13 @@ "message": "Tuyệt đối không chia sẻ cụm mật khẩu với bất kỳ ai." }, "endOfFlowMessage5": { - "message": "Hãy cẩn thận với hoạt động lừa đảo! MetaMask sẽ không bao giờ tự ý hỏi cụm mật khẩu gốc của bạn." + "message": "Hãy cẩn thận với hoạt động lừa đảo! MetaMask sẽ không bao giờ tự ý hỏi Cụm mật khẩu khôi phục bí mật của bạn." }, "endOfFlowMessage6": { - "message": "Nếu cần sao lưu lại cụm mật khẩu gốc của mình, bạn có thể tìm thấy cụm mật khẩu này trong phần Cài đặt -> Bảo mật." + "message": "Nếu bạn cần sao lưu lại Cụm mật khẩu khôi phục bí mật, bạn có thể tìm thấy chức năng này trong Cài đặt -> Bảo mật." }, "endOfFlowMessage8": { - "message": "MetaMask không thể khôi phục cụm mật khẩu gốc của bạn." + "message": "MetaMask không thể khôi phục Cụm mật khẩu khôi phục bí mật của bạn." }, "endOfFlowMessage9": { "message": "Tìm hiểu thêm." @@ -763,15 +766,21 @@ "importAccount": { "message": "Nhập tài khoản" }, + "importAccountLinkText": { + "message": "nhập bằng Cụm mật khẩu khôi phục bí mật" + }, "importAccountMsg": { - "message": " Tài khoản đã nhập sẽ không được liên kết với cụm mật khẩu gốc cho tài khoản MetaMask đã tạo ban đầu của bạn. Tìm hiểu thêm về các tài khoản đã nhập " + "message": " Tài khoản đã nhập sẽ không được liên kết với Cụm mật khẩu khôi phục bí mật cho tài khoản MetaMask đã tạo ban đầu của bạn. Tìm hiểu thêm về các tài khoản đã nhập " }, "importAccountSeedPhrase": { - "message": "Nhập một tài khoản bằng cụm mật khẩu gốc" + "message": "Nhập một tài khoản bằng Cụm mật khẩu khôi phục bí mật" }, "importWallet": { "message": "Nhập ví" }, + "importYourExisting": { + "message": "Nhập ví hiện tại của bạn bằng Cụm mật khẩu khôi phục bí mật" + }, "imported": { "message": "Đã nhập", "description": "status showing that an account has been fully loaded into the keyring" @@ -833,7 +842,7 @@ "message": "URL RPC không hợp lệ" }, "invalidSeedPhrase": { - "message": "Cụm mật khẩu gốc không hợp lệ" + "message": "Cụm mật khẩu khôi phục bí mật không hợp lệ" }, "ipfsGateway": { "message": "Cổng kết nối IPFS" @@ -1033,7 +1042,7 @@ "message": "Chưa có địa chỉ nào được đặt cho tên này." }, "noAlreadyHaveSeed": { - "message": "Không, tôi đã có cụm mật khẩu gốc" + "message": "Không, tôi đã có Cụm mật khẩu bí mật" }, "noConversionRateAvailable": { "message": "Không có sẵn tỷ lệ quy đổi nào" @@ -1217,7 +1226,7 @@ "message": "Xóa tài khoản" }, "removeAccountDescription": { - "message": "Tài khoản này sẽ được xóa khỏi ví của bạn. Xin đảm bảo rằng bạn có cụm mật khẩu gốc ban đầu hoặc khóa riêng tư cho tài khoản được nhập trước khi tiếp tục. Bạn có thể nhập hoặc tạo lại tài khoản từ trình đơn tài khoản thả xuống. " + "message": "Tài khoản này sẽ được xóa khỏi ví của bạn. Xin đảm bảo rằng bạn có Cụm mật khẩu khôi phục bí mật ban đầu hoặc khóa riêng tư cho tài khoản được nhập trước khi tiếp tục. Bạn có thể nhập hoặc tạo lại tài khoản từ trình đơn tài khoản thả xuống. " }, "requestsAwaitingAcknowledgement": { "message": "yêu cầu đang chờ xác nhận" @@ -1232,13 +1241,13 @@ "message": "Đặt lại tài khoản" }, "resetAccountDescription": { - "message": "Nếu đặt lại tài khoản của bạn, toàn bộ lịch sử giao dịch sẽ bị xóa. Việc này sẽ không làm thay đổi số dư trong tài khoản của bạn hoặc yêu cầu bạn phải nhập lại cụm mật khẩu gốc." + "message": "Nếu đặt lại tài khoản của bạn, toàn bộ lịch sử giao dịch sẽ bị xóa. Việc này sẽ không làm thay đổi số dư trong tài khoản của bạn hoặc yêu cầu bạn phải nhập lại Cụm mật khẩu khôi phục bí mật." }, "restore": { "message": "Khôi phục" }, "restoreAccountWithSeed": { - "message": "Khôi phục tài khoản của bạn bằng cụm mật khẩu gốc" + "message": "Khôi phục tài khoản của bạn bằng cụm mật khẩu khôi phục bí mật" }, "restoreWalletPreferences": { "message": "Đã tìm thấy bản sao lưu dữ liệu của bạn từ $1. Bạn có muốn khôi phục các tùy chọn ưu tiên trong ví của mình không?", @@ -1251,13 +1260,13 @@ "message": "Một token trong đây sử dụng lại ký hiệu của một token khác mà bạn thấy, điều này có thể gây nhầm lẫn hoặc mang tính lừa dối." }, "revealSeedWords": { - "message": "Hiện cụm mật khẩu gốc" + "message": "Hiện cụm mật khẩu khôi phục bí mật" }, "revealSeedWordsDescription": { - "message": "Nếu thay đổi trình duyệt hoặc chuyển máy tính, bạn sẽ cần cụm mật khẩu gốc này để truy cập tài khoản của mình. Hãy lưu cụm mật khẩu gốc này ở nơi an toàn và bí mật." + "message": "Nếu thay đổi trình duyệt hoặc chuyển máy tính, bạn sẽ cần Cụm mật khẩu khôi phục bí mật này để truy cập tài khoản của mình. Hãy lưu cụm mật khẩu gốc này ở nơi an toàn và bí mật." }, "revealSeedWordsTitle": { - "message": "Cụm mật khẩu gốc" + "message": "Cụm mật khẩu khôi phục bí mật" }, "revealSeedWordsWarning": { "message": "Kẻ xấu có thể dùng các từ này để đánh cắp tất cả các tài khoản của bạn." @@ -1314,16 +1323,16 @@ "message": "Bảo mật và quyền riêng tư" }, "securitySettingsDescription": { - "message": "Cụm mật khẩu gốc của ví và các tùy chọn cài đặt quyền riêng tư" + "message": "Các cài đặt quyền riêng tư và Cụm mật khẩu khôi phục bí mật của ví" }, "seedPhrasePlaceholder": { "message": "Phân tách mỗi từ bằng một dấu cách" }, "seedPhrasePlaceholderPaste": { - "message": "Dán cụm mật khẩu gốc từ khay nhớ tạm" + "message": "Dán Cụm mật khẩu khôi phục bí mật từ khay nhớ tạm" }, "seedPhraseReq": { - "message": "Cụm mật khẩu gốc gồm 12, 15, 18, 21 hoặc 24 từ" + "message": "Cụm mật khẩu khôi phục bí mật gồm 12, 15, 18, 21 hoặc 24 từ" }, "selectAHigherGasFee": { "message": "Chọn phí gas cao hơn để tăng tốc quá trình xử lý giao dịch của bạn.*" @@ -1408,7 +1417,7 @@ "message": "Hiện khóa riêng tư" }, "showSeedPhrase": { - "message": "Hiển thị cụm mật khẩu gốc" + "message": "Hiển thị Cụm mật khẩu khôi phục bí mật" }, "sigRequest": { "message": "Yêu cầu chữ ký" @@ -1564,9 +1573,6 @@ "swapFinalizing": { "message": "Đang hoàn tất..." }, - "swapHighSlippageWarning": { - "message": "Số tiền trượt giá rất cao. Hãy chắc chắn rằng bạn hiểu những gì mình đang làm!" - }, "swapLowSlippageError": { "message": "Giao dịch có thể không thành công, mức trượt giá tối đa quá thấp." }, @@ -1660,9 +1666,6 @@ "swapSelectQuotePopoverDescription": { "message": "Dưới đây là tất cả các báo giá thu thập từ nhiều nguồn thanh khoản." }, - "swapSlippageTooLow": { - "message": "Mức trượt giá phải lớn hơn 0" - }, "swapSource": { "message": "Nguồn thanh khoản" }, @@ -1699,9 +1702,6 @@ "message": "Nhiều token có thể dùng cùng một tên và ký hiệu. Hãy kiểm tra trên $1 để xác minh xem đây có phải là token bạn đang tìm kiếm không.", "description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network." }, - "swapViewToken": { - "message": "Xem $1" - }, "swapYourTokenBalance": { "message": "Có sẵn $1 $2 để hoán đổi", "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" @@ -1774,7 +1774,7 @@ "message": "Vòi thử nghiệm" }, "thisWillCreate": { - "message": "Thao tác này sẽ tạo một ví mới và cụm mật khẩu gốc" + "message": "Thao tác này sẽ tạo một ví mới và Cụm mật khẩu khôi phục bí mật" }, "tips": { "message": "Mẹo" @@ -1947,7 +1947,10 @@ "message": "hướng dẫn của chúng tôi về cách kết nối ví cứng" }, "walletSeed": { - "message": "Cụm mật khẩu gốc" + "message": "Cụm mật khẩu khôi phục bí mật" + }, + "walletSeedRestore": { + "message": "Cụm mật khẩu khôi phục bí mật của ví" }, "welcome": { "message": "Chào mừng bạn đến với MetaMask" @@ -1975,7 +1978,7 @@ "message": "Bạn đang ký" }, "yourPrivateSeedPhrase": { - "message": "Cụm mật khẩu gốc riêng tư của bạn" + "message": "Cụm mật khẩu bí mật, riêng tư của bạn" }, "zeroGasPriceOnSpeedUpError": { "message": "Giá gas bằng 0 khi tăng tốc" diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index 1c0071709..cb1950b2c 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -1576,9 +1576,6 @@ "swapFinalizing": { "message": "确定中……" }, - "swapHighSlippageWarning": { - "message": "滑点数量非常大。确保您知道您的操作!" - }, "swapLowSlippageError": { "message": "交易可能失败,最大滑点过低。" }, @@ -1622,12 +1619,6 @@ "message": "价格差异 ~$1%", "description": "$1 is a number (ex: 1.23) that represents the price difference." }, - "swapPriceDifferenceTooltip": { - "message": "市场价格的差异可能受到中介机构收取的费用、市场规模、交易规模或市场效率低下的影响。" - }, - "swapPriceDifferenceUnavailable": { - "message": "市场价格不可用。 请确认您对退回的数额感到满意后再继续。" - }, "swapProcessing": { "message": "处理中" }, @@ -1690,9 +1681,6 @@ "swapSelectQuotePopoverDescription": { "message": "以下是从多个流动资金来源收集到的所有报价。" }, - "swapSlippageTooLow": { - "message": "滑点必须大于零" - }, "swapSource": { "message": "流动资金来源" }, @@ -1732,9 +1720,6 @@ "message": "多个代币可以使用相同的名称和符号。检查 $1(以太坊浏览器)以确认这是您正在寻找的代币。", "description": "This appears in a tooltip next to the verifyThisTokenOn message. It gives the user more information about why they should check the token on a block explorer. $1 will be the name or url of the block explorer, which will be the translation of 'etherscan' or a block explorer url specified for a custom network." }, - "swapViewToken": { - "message": "查看 $1" - }, "swapYourTokenBalance": { "message": "$1 $2 可用", "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" diff --git a/app/images/source-logos-bsc.svg b/app/images/source-logos-bsc.svg new file mode 100644 index 000000000..cfb0c8440 --- /dev/null +++ b/app/images/source-logos-bsc.svg @@ -0,0 +1,100 @@ +<svg width="269" height="160" viewBox="0 0 269 160" fill="none" xmlns="http://www.w3.org/2000/svg"> +<rect width="269" height="160" rx="8" fill="#F2F3F4"/> +<path d="M157.778 79.2663C157.539 79.2663 157.371 79.2169 157.272 79.1182C157.181 79.0195 157.136 78.8632 157.136 78.6494V71.5055C157.136 71.2917 157.185 71.1354 157.284 71.0367C157.383 70.9297 157.547 70.8763 157.778 70.8763H160.801C161.952 70.8763 162.799 71.1189 163.342 71.6042C163.885 72.0895 164.157 72.8134 164.157 73.7758C164.157 74.7299 163.885 75.4496 163.342 75.935C162.808 76.412 161.96 76.6506 160.801 76.6506H159.628V78.6494C159.628 78.8632 159.579 79.0195 159.48 79.1182C159.382 79.2169 159.213 79.2663 158.975 79.2663H157.778ZM160.603 74.8615C160.94 74.8615 161.2 74.771 161.381 74.5901C161.57 74.4091 161.664 74.1376 161.664 73.7758C161.664 73.4056 161.57 73.13 161.381 72.9491C161.2 72.7681 160.94 72.6777 160.603 72.6777H159.628V74.8615H160.603Z" fill="#141414"/> +<path d="M167.071 79.4509C166.298 79.4509 165.677 79.2042 165.208 78.7106C164.747 78.2089 164.517 77.5056 164.517 76.6008C164.517 75.9099 164.673 75.3053 164.986 74.7871C165.307 74.2689 165.755 73.8699 166.331 73.5903C166.915 73.3024 167.585 73.1584 168.342 73.1584C168.967 73.1584 169.518 73.2284 169.995 73.3682C170.48 73.4998 170.925 73.6931 171.328 73.9481V78.8833C171.328 79.0396 171.299 79.1425 171.241 79.1918C171.184 79.2412 171.069 79.2659 170.896 79.2659H169.637C169.547 79.2659 169.477 79.2535 169.427 79.2289C169.378 79.1959 169.337 79.1466 169.304 79.0808L169.144 78.7106C168.905 78.9657 168.617 79.1507 168.28 79.2659C167.951 79.3893 167.548 79.4509 167.071 79.4509ZM167.996 77.7729C168.317 77.7729 168.568 77.6948 168.749 77.5385C168.93 77.3823 169.02 77.1601 169.02 76.8722V74.9475C168.864 74.8734 168.667 74.8364 168.428 74.8364C167.992 74.8364 167.643 74.9886 167.379 75.2929C167.124 75.5973 166.997 76.025 166.997 76.5761C166.997 77.374 167.33 77.7729 167.996 77.7729Z" fill="#141414"/> +<path d="M173.045 79.2659C172.806 79.2659 172.638 79.2165 172.539 79.1178C172.44 79.0191 172.391 78.8628 172.391 78.649V73.726C172.391 73.5779 172.416 73.4792 172.465 73.4299C172.523 73.3723 172.638 73.3435 172.811 73.3435H174.081C174.18 73.3435 174.254 73.36 174.304 73.3929C174.361 73.4175 174.394 73.4669 174.402 73.5409L174.464 73.9111C174.694 73.6808 174.994 73.4998 175.365 73.3682C175.743 73.2284 176.162 73.1584 176.623 73.1584C177.289 73.1584 177.828 73.3476 178.239 73.726C178.651 74.0962 178.856 74.6473 178.856 75.3793V78.649C178.856 78.8628 178.807 79.0191 178.708 79.1178C178.618 79.2165 178.453 79.2659 178.215 79.2659H177.018C176.779 79.2659 176.607 79.2165 176.5 79.1178C176.401 79.0191 176.352 78.8628 176.352 78.649V75.5397C176.352 75.2929 176.298 75.1161 176.191 75.0091C176.084 74.9022 175.916 74.8488 175.685 74.8488C175.439 74.8488 175.241 74.9146 175.093 75.0462C174.953 75.1778 174.883 75.3588 174.883 75.589V78.649C174.883 78.8628 174.834 79.0191 174.735 79.1178C174.645 79.2165 174.48 79.2659 174.242 79.2659H173.045Z" fill="#141414"/> +<path d="M183.217 79.4509C182.065 79.4509 181.177 79.1836 180.552 78.649C179.927 78.1143 179.614 77.337 179.614 76.317C179.614 75.6919 179.758 75.1408 180.046 74.6637C180.334 74.1866 180.749 73.8165 181.292 73.5532C181.843 73.29 182.493 73.1584 183.241 73.1584C183.809 73.1584 184.286 73.2119 184.673 73.3188C185.068 73.4257 185.417 73.5903 185.721 73.8124C185.812 73.8699 185.857 73.944 185.857 74.0345C185.857 74.1003 185.824 74.1866 185.758 74.2935L185.253 75.1696C185.195 75.2847 185.125 75.3423 185.043 75.3423C184.993 75.3423 184.915 75.3094 184.808 75.2436C184.586 75.1038 184.377 75.0009 184.179 74.9352C183.99 74.8693 183.751 74.8364 183.464 74.8364C183.052 74.8364 182.719 74.9681 182.464 75.2313C182.217 75.4945 182.094 75.8564 182.094 76.317C182.094 76.7859 182.221 77.1478 182.477 77.4028C182.731 77.6496 183.081 77.7729 183.525 77.7729C183.788 77.7729 184.027 77.7359 184.241 77.6619C184.455 77.5878 184.673 77.485 184.895 77.3534C185.01 77.2876 185.092 77.2547 185.142 77.2547C185.216 77.2547 185.281 77.3123 185.339 77.4274L185.894 78.3775C185.935 78.4597 185.956 78.5256 185.956 78.5749C185.956 78.649 185.907 78.7188 185.808 78.7847C185.462 79.0067 185.084 79.1712 184.673 79.2782C184.27 79.3934 183.784 79.4509 183.217 79.4509Z" fill="#141414"/> +<path d="M189.084 79.4509C188.311 79.4509 187.69 79.2042 187.221 78.7106C186.761 78.2089 186.53 77.5056 186.53 76.6008C186.53 75.9099 186.687 75.3053 186.999 74.7871C187.32 74.2689 187.768 73.8699 188.344 73.5903C188.928 73.3024 189.598 73.1584 190.355 73.1584C190.98 73.1584 191.531 73.2284 192.009 73.3682C192.494 73.4998 192.938 73.6931 193.341 73.9481V78.8833C193.341 79.0396 193.312 79.1425 193.255 79.1918C193.197 79.2412 193.082 79.2659 192.909 79.2659H191.651C191.56 79.2659 191.49 79.2535 191.441 79.2289C191.392 79.1959 191.35 79.1466 191.318 79.0808L191.157 78.7106C190.919 78.9657 190.631 79.1507 190.294 79.2659C189.965 79.3893 189.561 79.4509 189.084 79.4509ZM190.01 77.7729C190.33 77.7729 190.581 77.6948 190.762 77.5385C190.943 77.3823 191.034 77.1601 191.034 76.8722V74.9475C190.878 74.8734 190.68 74.8364 190.442 74.8364C190.006 74.8364 189.656 74.9886 189.393 75.2929C189.138 75.5973 189.01 76.025 189.01 76.5761C189.01 77.374 189.343 77.7729 190.01 77.7729Z" fill="#141414"/> +<path d="M201.092 78.7974C201.149 78.8632 201.178 78.9372 201.178 79.0195C201.178 79.0935 201.154 79.1552 201.104 79.2046C201.055 79.2457 200.989 79.2663 200.907 79.2663H198.994C198.879 79.2663 198.793 79.258 198.735 79.2416C198.686 79.2169 198.632 79.1716 198.575 79.1059L196.897 76.8233V78.6494C196.897 78.8632 196.848 79.0195 196.749 79.1182C196.65 79.2169 196.481 79.2663 196.243 79.2663H195.046C194.808 79.2663 194.639 79.2169 194.54 79.1182C194.45 79.0195 194.405 78.8632 194.405 78.6494V71.5055C194.405 71.2917 194.454 71.1354 194.553 71.0367C194.651 70.9297 194.816 70.8763 195.046 70.8763H196.243C196.481 70.8763 196.65 70.9297 196.749 71.0367C196.848 71.1354 196.897 71.2917 196.897 71.5055V75.6388L198.526 73.5167C198.575 73.4508 198.628 73.4056 198.686 73.3809C198.743 73.3563 198.83 73.3439 198.945 73.3439H200.857C200.94 73.3439 201.001 73.3686 201.043 73.4179C201.092 73.4591 201.117 73.5167 201.117 73.5907C201.117 73.6729 201.088 73.747 201.03 73.8128L198.92 76.2311L201.092 78.7974Z" fill="#141414"/> +<path d="M205.098 79.4509C204.407 79.4509 203.79 79.3358 203.247 79.1055C202.713 78.8751 202.289 78.5297 201.976 78.0691C201.664 77.6084 201.507 77.045 201.507 76.3787C201.507 75.3341 201.804 74.5362 202.396 73.9851C202.988 73.434 203.84 73.1584 204.95 73.1584C206.036 73.1584 206.858 73.4299 207.417 73.9728C207.985 74.5074 208.269 75.2518 208.269 76.206C208.269 76.6172 208.088 76.8229 207.726 76.8229H203.852C203.852 77.1766 203.983 77.448 204.247 77.6372C204.518 77.8264 204.925 77.921 205.468 77.921C205.805 77.921 206.085 77.8922 206.307 77.8346C206.537 77.7688 206.768 77.6743 206.998 77.5509C207.097 77.5097 207.163 77.4892 207.195 77.4892C207.269 77.4892 207.331 77.5385 207.381 77.6372L207.8 78.4268C207.841 78.5091 207.861 78.5708 207.861 78.6119C207.861 78.686 207.812 78.7559 207.713 78.8217C207.376 79.0438 206.994 79.2042 206.566 79.3028C206.138 79.4016 205.649 79.4509 205.098 79.4509ZM206.048 75.6014C206.048 75.2888 205.958 75.0462 205.776 74.8734C205.595 74.7007 205.324 74.6144 204.962 74.6144C204.6 74.6144 204.325 74.7048 204.136 74.8858C203.947 75.0585 203.852 75.297 203.852 75.6014H206.048Z" fill="#141414"/> +<path d="M212.498 79.452C211.807 79.452 211.153 79.3821 210.536 79.2423C209.92 79.0942 209.422 78.8886 209.043 78.6254C208.904 78.5349 208.834 78.4403 208.834 78.3416C208.834 78.2758 208.858 78.2059 208.907 78.1318L209.512 77.1694C209.578 77.0708 209.644 77.0214 209.709 77.0214C209.751 77.0214 209.821 77.0502 209.92 77.1078C210.224 77.2805 210.569 77.4203 210.956 77.5273C211.342 77.6342 211.725 77.6877 212.103 77.6877C212.49 77.6877 212.774 77.6301 212.954 77.5149C213.144 77.3998 213.238 77.2147 213.238 76.9597C213.238 76.7129 213.136 76.5197 212.93 76.3798C212.733 76.24 212.358 76.0631 211.807 75.8493C210.976 75.5367 210.327 75.1871 209.858 74.8006C209.397 74.4057 209.167 73.871 209.167 73.1966C209.167 72.3822 209.459 71.7612 210.043 71.3335C210.627 70.9058 211.404 70.6919 212.375 70.6919C213.049 70.6919 213.625 70.7536 214.102 70.877C214.587 70.9921 214.999 71.1731 215.336 71.4199C215.476 71.5268 215.546 71.6255 215.546 71.716C215.546 71.7735 215.521 71.8394 215.472 71.9134L214.867 72.8758C214.793 72.9745 214.727 73.0238 214.67 73.0238C214.628 73.0238 214.558 72.995 214.46 72.9375C213.983 72.6249 213.415 72.4686 212.757 72.4686C212.404 72.4686 212.132 72.5262 211.943 72.6413C211.754 72.7565 211.659 72.9457 211.659 73.2089C211.659 73.3899 211.708 73.5379 211.807 73.6531C211.906 73.7682 212.038 73.871 212.202 73.9615C212.375 74.0438 212.638 74.1507 212.992 74.2823L213.226 74.3687C213.835 74.6072 214.312 74.8375 214.657 75.0596C215.011 75.2735 215.278 75.5408 215.459 75.8616C215.64 76.1742 215.731 76.569 215.731 77.0461C215.731 77.7781 215.455 78.3622 214.904 78.7981C214.361 79.2341 213.559 79.452 212.498 79.452Z" fill="#141414"/> +<path d="M218.351 79.2662C218.228 79.2662 218.133 79.2456 218.067 79.2045C218.002 79.1634 217.952 79.0811 217.92 78.9577L216.328 73.6276C216.311 73.5783 216.303 73.5413 216.303 73.5166C216.303 73.4015 216.386 73.3439 216.55 73.3439H218.179C218.286 73.3439 218.363 73.3644 218.413 73.4056C218.462 73.4385 218.495 73.496 218.511 73.5783L219.178 76.379L220.016 74.1212C220.058 74.0225 220.099 73.9567 220.14 73.9237C220.19 73.8827 220.272 73.8621 220.387 73.8621H221.164C221.279 73.8621 221.358 73.8827 221.399 73.9237C221.448 73.9567 221.493 74.0225 221.534 74.1212L222.361 76.379L223.04 73.5783C223.064 73.496 223.097 73.4385 223.138 73.4056C223.179 73.3644 223.254 73.3439 223.36 73.3439H225.001C225.166 73.3439 225.248 73.4015 225.248 73.5166C225.248 73.5413 225.24 73.5783 225.224 73.6276L223.62 78.9577C223.586 79.0811 223.537 79.1634 223.472 79.2045C223.414 79.2456 223.324 79.2662 223.2 79.2662H221.991C221.876 79.2662 221.79 79.2456 221.732 79.2045C221.674 79.1552 221.625 79.0729 221.584 78.9577L220.77 76.7246L219.955 78.9577C219.922 79.0729 219.873 79.1552 219.807 79.2045C219.749 79.2456 219.663 79.2662 219.548 79.2662H218.351Z" fill="#141414"/> +<path d="M228.376 79.4509C227.603 79.4509 226.982 79.2042 226.513 78.7106C226.052 78.2089 225.822 77.5056 225.822 76.6008C225.822 75.9099 225.979 75.3053 226.291 74.7871C226.612 74.2689 227.06 73.8699 227.636 73.5903C228.22 73.3024 228.89 73.1584 229.647 73.1584C230.272 73.1584 230.823 73.2284 231.3 73.3682C231.785 73.4998 232.229 73.6931 232.633 73.9481V78.8833C232.633 79.0396 232.604 79.1425 232.546 79.1918C232.488 79.2412 232.374 79.2659 232.201 79.2659H230.942C230.852 79.2659 230.782 79.2535 230.733 79.2289C230.683 79.1959 230.642 79.1466 230.609 79.0808L230.449 78.7106C230.21 78.9657 229.922 79.1507 229.585 79.2659C229.256 79.3893 228.853 79.4509 228.376 79.4509ZM229.301 77.7729C229.622 77.7729 229.873 77.6948 230.054 77.5385C230.235 77.3823 230.325 77.1601 230.325 76.8722V74.9475C230.169 74.8734 229.972 74.8364 229.733 74.8364C229.297 74.8364 228.948 74.9886 228.684 75.2929C228.429 75.5973 228.302 76.025 228.302 76.5761C228.302 77.374 228.635 77.7729 229.301 77.7729Z" fill="#141414"/> +<path d="M234.338 81.7581C234.099 81.7581 233.931 81.7088 233.832 81.6101C233.742 81.5114 233.696 81.3551 233.696 81.1413V74.0715C234.067 73.8083 234.531 73.5903 235.09 73.4175C235.65 73.2448 236.234 73.1584 236.842 73.1584C239.326 73.1584 240.569 74.2113 240.569 76.317C240.569 77.2712 240.305 78.032 239.779 78.5996C239.253 79.1671 238.508 79.4509 237.546 79.4509C237.274 79.4509 237.011 79.418 236.756 79.3522C236.51 79.2864 236.304 79.1959 236.139 79.0808V81.1413C236.139 81.3551 236.09 81.5114 235.991 81.6101C235.892 81.7088 235.724 81.7581 235.485 81.7581H234.338ZM237.015 77.7853C237.369 77.7853 237.632 77.6537 237.805 77.3905C237.986 77.119 238.076 76.7571 238.076 76.3047C238.076 75.77 237.969 75.3958 237.756 75.1819C237.55 74.9598 237.229 74.8488 236.793 74.8488C236.513 74.8488 236.292 74.8858 236.127 74.9598V76.9216C236.127 77.2013 236.205 77.4151 236.362 77.5632C236.518 77.7112 236.736 77.7853 237.015 77.7853Z" fill="#141414"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M140.814 69.478C140.574 68.19 141.562 67 142.872 67C144.029 67 144.966 67.9374 144.966 69.0937V71.6749C145.255 71.6545 145.549 71.644 145.847 71.644C146.133 71.644 146.415 71.6537 146.693 71.6725V69.0937C146.693 67.9374 147.631 67 148.787 67C150.097 67 151.086 68.19 150.845 69.478L150.279 72.5121C152.223 73.3611 153.694 74.8355 153.694 76.6884V77.8093C153.694 79.333 152.686 80.6087 151.276 81.4698C149.856 82.3377 147.935 82.8536 145.847 82.8536C143.759 82.8536 141.837 82.3377 140.417 81.4698C139.008 80.6087 138 79.333 138 77.8093V76.6884C138 74.8453 139.455 73.3765 141.383 72.5259L140.814 69.478ZM149.553 72.9107L150.216 69.3604C150.382 68.4665 149.697 67.6406 148.787 67.6406C147.985 67.6406 147.334 68.2911 147.334 69.0937V72.3784C147.124 72.3515 146.91 72.3301 146.693 72.3146C146.416 72.2948 146.133 72.2846 145.847 72.2846C145.549 72.2846 145.255 72.2956 144.966 72.3171C144.749 72.3332 144.536 72.3553 144.325 72.3829V69.0937C144.325 68.2911 143.675 67.6406 142.872 67.6406C141.963 67.6406 141.277 68.4665 141.444 69.3604L142.109 72.9225C140.03 73.6949 138.641 75.0925 138.641 76.6884V77.8093C138.641 80.2415 141.867 82.2131 145.847 82.2131C149.827 82.2131 153.053 80.2415 153.053 77.8093V76.6884C153.053 75.0843 151.65 73.6807 149.553 72.9107Z" fill="#633001"/> +<path d="M153.053 77.8091C153.053 80.2412 149.827 82.2129 145.847 82.2129C141.867 82.2129 138.64 80.2412 138.64 77.8091V76.6881H153.053V77.8091Z" fill="#FEDC90"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M141.444 69.3603C141.277 68.4664 141.963 67.6404 142.872 67.6404C143.675 67.6404 144.325 68.291 144.325 69.0936V72.3828C144.816 72.3184 145.325 72.2844 145.847 72.2844C146.357 72.2844 146.854 72.3168 147.334 72.3783V69.0936C147.334 68.291 147.984 67.6404 148.787 67.6404C149.696 67.6404 150.382 68.4664 150.215 69.3603L149.552 72.9106C151.65 73.6806 153.053 75.0843 153.053 76.6883C153.053 79.1204 149.827 81.092 145.847 81.092C141.867 81.092 138.64 79.1204 138.64 76.6883C138.64 75.0924 140.029 73.6948 142.109 72.9224L141.444 69.3603Z" fill="#D1884F"/> +<path d="M143.845 76.368C143.845 77.0314 143.487 77.5691 143.045 77.5691C142.602 77.5691 142.244 77.0314 142.244 76.368C142.244 75.7047 142.602 75.167 143.045 75.167C143.487 75.167 143.845 75.7047 143.845 76.368Z" fill="#633001"/> +<path d="M149.37 76.368C149.37 77.0314 149.012 77.5691 148.57 77.5691C148.127 77.5691 147.769 77.0314 147.769 76.368C147.769 75.7047 148.127 75.167 148.57 75.167C149.012 75.167 149.37 75.7047 149.37 76.368Z" fill="#633001"/> +<g filter="url(#filter0_d)"> +<path d="M34.1637 25.5997C35.2356 24.1705 36.6569 23.456 38.4278 23.456C40.1987 23.456 41.6123 24.1705 42.6686 25.5997C43.7405 27.0133 44.2764 29.1259 44.2764 31.9376C44.2764 34.7493 43.7405 36.8619 42.6686 38.2755C41.6123 39.6891 40.1987 40.396 38.4278 40.396C36.6569 40.396 35.2356 39.6891 34.1637 38.2755C33.1074 36.8619 32.5792 34.7493 32.5792 31.9376C32.5792 29.1259 33.1074 27.0133 34.1637 25.5997ZM34.0938 31.9376C34.0938 34.2056 34.4433 35.9454 35.1424 37.1571L40.7346 25.5764C40.1133 25.0638 39.3443 24.8074 38.4278 24.8074C37.0142 24.8074 35.9346 25.421 35.189 26.6482C34.4589 27.8599 34.0938 29.623 34.0938 31.9376ZM38.4278 39.0445C39.8414 39.0445 40.9133 38.4386 41.6434 37.227C42.389 36.0153 42.7618 34.2522 42.7618 31.9376C42.7618 29.6696 42.4123 27.9376 41.7133 26.7414L36.121 38.2988C36.7579 38.7959 37.5268 39.0445 38.4278 39.0445ZM55.5049 40.093L52.3825 34.9435H51.5437L48.3048 40.093H46.6737L50.4485 34.1279L47.0699 28.4424H48.6543L51.5437 33.3124H52.3825L55.3185 28.4424H56.903L53.4777 34.058L57.2292 40.093H55.5049ZM73.8562 23.456L79.8213 40.093H78.1669L76.2795 34.7105H68.6134L66.726 40.093H65.1183L71.0601 23.456H73.8562ZM71.9921 25.0871L69.1028 33.3124H75.7902L72.9009 25.0871H71.9921ZM82.4975 23.456H89.3246C91.08 23.456 92.4315 23.8832 93.379 24.7375C94.3266 25.5919 94.8004 26.7803 94.8004 28.3026C94.8004 29.825 94.3266 31.0133 93.379 31.8677C92.4315 32.7221 91.08 33.1493 89.3246 33.1493H84.0354V40.093H82.4975V23.456ZM84.0354 31.7512H89.0683C91.8645 31.7512 93.2625 30.6017 93.2625 28.3026C93.2625 26.0036 91.8645 24.854 89.0683 24.854H84.0354V31.7512ZM98.4074 23.456H99.9453V40.093H98.4074V23.456Z" fill="#24292E"/> +</g> +<path d="M158.357 44.5082C157.246 44.5082 156.268 44.2323 155.45 43.6805C154.34 42.9379 153.628 41.7493 153.389 40.2471C153.164 38.8359 153.364 37.1695 153.966 35.4282C154.568 33.6868 155.561 31.9105 156.84 30.2782C158.732 27.8646 161.082 25.9641 163.458 24.9268C164.732 24.3718 165.944 24.0922 167.063 24.0922C168.174 24.0922 169.152 24.3681 169.97 24.9199C170.778 25.4611 171.381 26.2488 171.739 27.2222C171.807 27.0951 171.863 26.9621 171.908 26.8249L172.276 25.6395L172.489 26.8622C172.928 29.388 172.238 31.6843 171.47 33.3116C171.671 33.1916 171.859 33.0517 172.032 32.8941L172.936 32.0448L172.518 33.2127C171.84 35.1058 170.7 36.8232 169.124 38.3278C169.476 38.2956 169.838 38.2326 170.123 38.1144L171.269 37.6399L170.465 38.5844C168.519 40.8687 165.83 42.0454 163.901 42.6308C163.282 43.0273 162.634 43.3754 161.961 43.6718C160.687 44.2245 159.474 44.5082 158.357 44.5082ZM167.059 26.0653C166.22 26.0653 165.275 26.292 164.251 26.7394C162.169 27.648 160.091 29.3383 158.397 31.4981C156.142 34.3761 154.97 37.6109 155.341 39.9362C155.494 40.8959 155.901 41.6031 156.55 42.0381C157.039 42.365 157.647 42.531 158.36 42.531C159.199 42.531 160.144 42.3043 161.169 41.8569C163.25 40.9483 165.329 39.258 167.022 37.0982C169.278 34.2197 170.449 30.9868 170.078 28.6601C169.926 27.7004 169.519 26.9932 168.869 26.5582C168.381 26.2313 167.772 26.0653 167.059 26.0653Z" fill="#56A4CB"/> +<path d="M170.581 30.8745C171.211 30.0298 171.447 28.9134 171.577 28.1749C171.079 28.7888 170.696 29.0582 170.696 29.0582C170.753 29.6155 170.788 30.1618 170.581 30.8745Z" fill="#277DAD"/> +<path d="M162.277 26.2351C167.523 22.912 170.851 26.4756 170.903 27.357C170.69 25.9661 169.708 24.989 168.542 24.4395C167.53 23.9157 164.489 24.6441 164.489 24.6441L162.277 26.2351Z" fill="#DDEDF5"/> +<path d="M160.495 43.4755C159.556 44.1004 157.2 43.8511 156.724 43.6806C156.724 43.0828 156.918 42.4455 156.918 42.4455H158.074C158.074 42.4455 158.059 42.9159 159.278 42.617C159.936 42.9545 160.495 43.4755 160.495 43.4755Z" fill="#277DAD"/> +<path d="M153.476 38.4156C154.536 34.7656 158.166 27.7478 165.08 24.667C163.982 24.2021 159.296 26.7463 156.84 30.2768C153.82 34.6221 153.82 35.7027 153.476 38.4156Z" fill="#DDEDF5"/> +<path d="M168.542 34.9288C168.542 34.9288 169.709 34.5357 170.427 33.9935C170.979 33.0707 171.914 30.8566 171.914 28.9203C170.565 32.0692 169.615 32.4347 169.615 32.4347C169.114 33.9476 168.925 34.1729 168.542 34.9288Z" fill="#277DAD"/> +<path d="M169.277 39.0056C167.116 40.6871 165.642 41.3608 163.734 41.9944L162.511 42.669L162.225 41.4886C162.225 41.4886 166.835 39.046 168.367 35.2199C169.11 35.5726 171.103 34.6299 171.577 33.9476C170.657 35.6029 167.531 38.9752 167.531 38.9752L169.277 39.0056Z" fill="#277DAD"/> +<path d="M167.063 24.3887C168.102 24.3887 169.032 24.6472 169.803 25.164C170.726 25.782 171.355 26.7347 171.642 27.9353C171.872 27.6135 172.087 27.2502 172.194 26.909C172.659 29.5801 171.841 31.9978 170.923 33.7318C170.89 33.815 170.855 33.8987 170.82 33.982C171.326 33.7521 171.864 33.4573 172.236 33.1083C171.387 35.481 169.891 37.2973 168.317 38.6524H168.422C168.958 38.6524 169.706 38.6064 170.237 38.3866C168.377 40.5707 165.823 41.7364 163.775 42.3539C163.159 42.7511 162.512 43.0992 161.841 43.3949C160.6 43.9366 159.422 44.2074 158.357 44.2074C157.318 44.2074 156.388 43.949 155.617 43.4322C154.578 42.7369 153.91 41.6191 153.685 40.2001C153.468 38.8372 153.664 37.2209 154.251 35.526C154.839 33.8196 155.817 32.0691 157.076 30.463C158.938 28.0875 161.247 26.2193 163.579 25.2012C164.82 24.6596 165.998 24.3887 167.063 24.3887ZM158.36 42.8298C159.229 42.8298 160.221 42.5962 161.288 42.1304C163.414 41.2025 165.534 39.4809 167.257 37.2825C169.562 34.3397 170.756 31.0193 170.373 28.6131C170.207 27.5679 169.757 26.7931 169.036 26.3099C168.494 25.9471 167.824 25.7664 167.058 25.7664C166.189 25.7664 165.197 25.9999 164.13 26.4653C162.004 27.3937 159.884 29.1152 158.161 31.3136C155.856 34.2565 154.662 37.5768 155.045 39.9831C155.212 41.0282 155.662 41.803 156.383 42.2863C156.924 42.6491 157.594 42.8298 158.36 42.8298ZM167.063 23.7933C165.903 23.7933 164.65 24.0834 163.338 24.6559C160.918 25.7135 158.526 27.6447 156.604 30.0965C155.306 31.7518 154.296 33.5644 153.684 35.3306C153.065 37.1179 152.862 38.8344 153.092 40.2939C153.345 41.8817 154.103 43.1388 155.282 43.9265C156.15 44.5082 157.184 44.8029 158.355 44.8029C159.514 44.8029 160.767 44.5128 162.079 43.9403C162.754 43.6435 163.405 43.2957 164.026 42.8997C165.19 42.5485 166.311 42.0705 167.371 41.4743C169.704 40.1463 170.564 39.2074 172.202 37.1138L170.033 37.8205C172.216 35.4474 172.767 34.0086 173.466 31.2911L172.213 32.3091C173.6 29.0734 172.68 25.5443 172.386 24.8279C172.194 25.3948 171.88 26.1912 171.715 26.4322C171.344 25.7217 170.801 25.1151 170.136 24.6674C169.268 24.0857 168.234 23.791 167.063 23.791V23.7933ZM158.36 42.2321C157.708 42.2321 157.154 42.0831 156.716 41.7897C156.139 41.4025 155.775 40.7634 155.636 39.8893C155.278 37.6417 156.426 34.4974 158.632 31.6824C160.295 29.5608 162.333 27.9027 164.37 27.0134C165.357 26.5825 166.262 26.3641 167.059 26.3641C167.711 26.3641 168.264 26.5131 168.703 26.8065C169.28 27.1936 169.644 27.8328 169.783 28.7069C170.141 30.9545 168.992 34.0988 166.787 36.9138C165.124 39.0363 163.086 40.6917 161.049 41.5828C160.062 42.0136 159.157 42.2321 158.36 42.2321Z" fill="#083751"/> +<path d="M158.36 42.2322C157.708 42.2322 157.154 42.0832 156.716 41.7898C156.139 41.4027 155.775 40.7635 155.636 39.8894C155.278 37.6418 156.426 34.4975 158.632 31.6825C160.295 29.5609 162.333 27.9028 164.37 27.0135C165.357 26.5827 166.262 26.3642 167.059 26.3642C167.711 26.3642 168.264 26.5132 168.703 26.8066C169.28 27.1938 169.644 27.8329 169.783 28.707C170.141 30.9546 168.992 34.0989 166.787 36.9139C165.124 39.0364 163.086 40.6918 161.049 41.5829C160.062 42.0138 159.157 42.2322 158.36 42.2322Z" fill="#083751"/> +<path d="M155.335 21.0048C155.308 21.3474 155.331 22.9876 155.95 23.2667C155.521 22.2551 155.977 20.3698 158.128 20.3606C157.734 20.654 157.432 21.1354 157.3 21.4568C157.158 21.612 157.032 21.7815 156.924 21.9626C157.079 21.8706 157.582 21.0163 159.47 21.0103C159.971 21.0103 160.516 21.065 160.96 21.3179C160.196 21.129 159.384 21.5479 158.75 21.9741C159.196 21.8306 159.846 21.4007 160.76 21.5796C161.375 21.6996 161.627 22.2656 162.134 22.5576C162.548 22.7963 163.136 22.7783 163.406 22.3332C163.474 22.2227 163.508 22.0948 163.503 21.9654C163.62 22.0881 163.721 22.2239 163.806 22.37C163.994 22.6961 164.073 23.0741 164.03 23.4483C163.583 23.4055 163.143 23.56 162.694 23.5081C162.259 23.4503 161.848 23.2754 161.506 23.0023C161.75 23.3678 162.118 23.6323 162.542 23.7467C163.082 23.8916 163.608 23.6892 164.147 23.7849C164.763 23.8934 165.539 24.2948 166.241 23.8276C166.366 23.7429 166.47 23.6321 166.548 23.503C166.66 23.8117 166.668 24.1485 166.572 24.4627C166.523 24.6393 166.43 24.8009 166.303 24.9331C166.187 25.0475 166.046 25.0866 165.914 25.1657C165.469 24.9818 164.971 24.9197 164.488 24.8898C164.922 25.0278 165.366 25.1657 165.776 25.3621C166.186 25.5584 166.462 25.8679 166.749 26.2127C166.988 26.4997 167.266 26.7608 167.64 26.8496C167.897 26.9107 168.166 26.8976 168.415 26.8119C168.482 27.1866 168.135 27.7977 167.651 27.8787C167.885 28.0281 168.137 28.1472 168.401 28.2332C168.218 28.3987 167.778 28.5224 167.496 28.5371C168.175 28.893 168.516 29.8412 168.501 30.6109C168.392 30.3759 168.267 30.1051 167.983 29.9C168.063 30.2288 168.048 30.6302 167.987 31.0036C167.853 30.8758 167.343 30.2854 167.126 29.9998C167.232 29.671 167.213 29.4443 167.141 29.1096C167.049 29.6614 166.654 30.2946 166.451 30.5484C166.543 30.2049 166.507 29.8352 166.451 29.4908C166.382 29.1026 166.269 28.7237 166.113 28.3615C165.778 27.5434 165.778 27.5434 165.489 26.8312C165.321 27.5113 165.177 27.8285 164.954 28.104C164.965 27.8861 164.95 27.6676 164.91 27.4533C164.894 27.3641 164.755 26.6666 164.102 25.7299C164.159 26.164 164.332 26.6794 164.127 27.165C164.113 26.8008 163.873 25.7465 163.144 25.3257C163.348 25.677 163.527 26.7774 163.282 27.0597C163.305 26.4528 162.883 25.8932 162.422 25.5258C162.081 25.2535 160.189 24.1978 160.192 24.2024C160.195 24.207 160.543 25.7244 159.782 25.8444C160.014 25.3198 159.429 24.2157 158.77 24.0125C158.847 23.6423 158.827 23.1972 158.699 22.8629C158.371 23.2184 157.542 23.2336 157.093 23.6235C156.9 23.7899 156.694 24.0438 156.611 24.3385L156.362 24.6824C156.356 24.6529 156.345 24.6246 156.329 24.5992L155.088 23.4193C154.806 22.8813 154.728 21.5828 155.335 21.0048Z" fill="#E61C3F"/> +<path d="M153.925 22.7211L154.63 23.432C154.592 23.5005 154.54 23.5769 154.465 23.5943C154.509 23.6046 154.555 23.6019 154.598 23.5866C154.64 23.5714 154.678 23.5442 154.705 23.5083L155.038 23.8445C154.97 23.9967 154.859 24.1834 154.686 24.2123C154.907 24.2758 155.077 24.1351 155.155 23.9631L155.579 24.3907C155.523 24.5926 155.4 24.8506 155.047 24.8965C155.431 24.9885 155.648 24.7664 155.719 24.5314L156.018 24.8331C156.116 25.155 155.564 25.5293 155.237 25.4433L153.925 22.7211Z" fill="white"/> +<path d="M156.649 42.6979C156.596 43.4079 156.396 44.7381 155.649 45.0729C155.419 44.9809 155.217 44.6747 155.057 44.3137C155.14 43.7845 155.379 43.624 155.839 43.2778C156.105 43.0777 156.288 42.726 156.401 42.4455C156.507 42.5568 156.597 42.6469 156.649 42.6979Z" fill="white"/> +<path d="M161.614 41.1516C161.696 41.3457 161.805 41.6115 161.915 41.8906C161.984 42.0662 162.053 42.2474 162.115 42.4212C162.279 42.8778 162.398 43.2792 162.345 43.3717C162.292 43.4641 161.987 43.4967 161.583 43.4636C161.34 43.1174 161.347 42.8599 161.399 42.4364C161.406 42.3775 161.414 42.315 161.422 42.2488C161.438 42.0864 161.426 41.9224 161.386 41.7641C161.324 41.5188 161.231 41.2821 161.11 41.0597C161.281 41.071 161.45 41.1018 161.614 41.1516Z" fill="white"/> +<path d="M168.925 33.4068C168.354 34.6402 167.64 35.8021 166.797 36.8688C166.483 37.2716 166.156 37.6569 165.816 38.0248C165.928 37.1833 165.685 36.2995 165.146 35.8829C165.646 36.9506 165.514 37.85 165.094 38.5301C164.468 39.5376 163.296 39.9712 162.591 39.956C162.056 39.9398 161.534 39.7891 161.073 39.5178C161.073 39.5178 159.115 39.0364 158.987 39.4801C158.859 39.9238 159.536 41.0596 159.536 41.0596C159.536 41.0596 160.004 41.0375 160.046 41.3741C160.233 41.219 160.458 41.1172 160.698 41.0794C160.884 41.203 161.023 41.3855 161.093 41.5976C161.22 41.9944 161.084 42.4344 161.012 42.7513C160.997 42.8099 160.986 42.8693 160.978 42.9292C160.968 43.0011 160.971 43.074 160.986 43.1449C161.007 43.2355 161.046 43.3208 161.102 43.3955C160.943 43.3649 160.787 43.3253 160.633 43.2768C160.466 43.2248 160.303 43.1599 160.146 43.0828C159.901 42.9686 159.683 42.8026 159.508 42.5963C158.788 42.6455 158.542 42.7995 158.322 42.3981C158.256 42.2687 158.202 42.1336 158.16 41.9944C157.874 41.1088 157.23 40.2085 156.967 39.8424C156.704 39.4764 157.037 38.7067 157.667 38.4299C158.296 38.1531 160.855 37.4974 161.234 36.992C161.612 36.4867 161.44 35.4102 163.279 34.7246C162.753 34.554 161.233 35.3104 160.855 36.6485C160.142 37.1157 158.319 37.6454 157.823 37.7926C157.003 38.0353 156.543 38.6285 156.41 39.0037C156.005 39.1472 155.344 39.3757 155.338 39.6935C155.331 40.0489 155.584 40.563 155.568 41.2996C155.568 41.4155 155.685 41.6095 155.847 41.8183C155.949 41.9503 156.069 42.0882 156.185 42.216C156.158 42.4638 156.042 42.6933 155.858 42.8621C155.727 42.9853 155.582 43.0933 155.426 43.1839C155.272 43.2787 155.127 43.3564 155.028 43.4309C154.942 43.4959 154.874 43.5819 154.831 43.6806C154.757 43.4321 154.707 43.1771 154.682 42.9191C154.286 42.3779 154.142 42.2294 154.068 41.9995C154.063 41.9789 154.059 41.9578 154.057 41.9365C154.028 41.6661 154.097 40.8573 154.142 40.3896C154.196 40.3832 154.312 40.4614 154.533 40.5864L154.579 40.614L154.52 40.522C154.198 40.0282 153.833 39.4838 153.994 38.9895C154.08 38.7237 154.249 38.5756 154.516 38.4161C154.518 38.4147 154.52 38.4137 154.521 38.4129C154.624 38.3508 154.742 38.2869 154.875 38.2133C155.356 37.9471 157.294 37.3208 157.546 36.8076C157.689 36.5226 157.849 36.2462 158.025 35.9799C158.066 36.3544 158.147 36.7235 158.267 37.0808C158.238 34.5058 159.173 32.8927 159.542 32.357C159.584 32.8711 159.585 33.3878 159.544 33.902C160.058 33.4197 160.091 31.2939 159.435 29.5701C159.381 29.4263 159.321 29.2857 159.257 29.1484C159.188 29.0017 159.113 28.8596 159.033 28.7235C159.163 28.4415 159.22 28.1312 159.198 27.8214C159.188 27.675 159.163 27.5301 159.122 27.3891C159.053 27.1346 158.929 26.898 158.76 26.6957C158.832 27.0217 158.897 27.3031 158.905 27.5823C158.912 27.7777 158.885 27.9728 158.826 28.1593C158.81 28.2113 158.79 28.2637 158.768 28.3175C158.772 28.2803 158.775 28.2435 158.776 28.2067C158.781 28.0508 158.766 27.8949 158.73 27.7432C158.709 27.6543 158.681 27.5672 158.647 27.4825C158.642 27.4705 158.623 27.4793 158.626 27.4912C158.65 27.5928 158.664 27.6964 158.668 27.8007C158.675 27.9911 158.655 28.1817 158.607 28.3662C158.587 28.4484 158.562 28.5295 158.533 28.609C158.491 28.7264 158.442 28.8415 158.388 28.9539C158.026 29.3981 157.449 29.5374 157.152 30.0648C157.125 30.0533 157.094 30.0404 157.06 30.0271C156.949 29.9833 156.834 29.948 156.717 29.9214C156.509 29.8754 156.276 29.8588 156.084 29.9361C155.985 29.967 155.891 30.0121 155.805 30.0699C155.726 30.1208 155.66 30.1892 155.613 30.2699C155.725 30.1434 156.072 30.04 156.348 30.0441C156.425 30.0519 156.498 30.0796 156.56 30.1246C156.65 30.1907 156.72 30.2813 156.761 30.3858C156.761 30.3909 156.759 30.3959 156.757 30.4005C156.759 30.3971 156.761 30.3936 156.763 30.3899V30.3936C156.826 30.5467 156.861 30.7674 156.834 31.0856C156.757 31.4034 156.683 31.6875 156.575 31.8172C156.37 32.0673 155.697 32.4683 155.336 32.5387C155.308 32.5452 155.281 32.5499 155.253 32.5529C155.157 32.5583 155.061 32.546 154.969 32.5166C154.937 32.5078 154.905 32.4968 154.873 32.4844C154.935 32.4353 155 32.3894 155.067 32.3464C155.137 32.3008 155.211 32.2595 155.286 32.2228C155.375 32.1801 155.459 32.1391 155.537 32.0995C156.108 31.8163 156.411 31.6277 156.505 31.453C156.592 31.2925 156.527 31.0695 156.391 30.8759C156.33 30.7864 156.256 30.706 156.173 30.6368C156.132 30.6036 156.089 30.5737 156.044 30.5476C156.109 30.53 156.178 30.5271 156.244 30.5394C156.304 30.5494 156.363 30.5626 156.421 30.5789C156.387 30.5403 156.212 30.498 156.161 30.4685C155.996 30.3711 155.848 30.4129 155.736 30.5398C155.589 30.7053 155.387 31.2921 155.043 31.694C154.808 31.9699 154.365 32.0706 154.106 32.1078C153.738 31.8475 153.508 31.4907 153.478 31.2075C153.445 30.8704 153.524 30.4157 153.866 30.206C154.125 29.5861 154.583 27.889 154.611 27.625C154.64 27.3611 154.319 26.6539 154.348 26.3233C154.369 26.0888 154.709 25.5287 154.8 25.3825L154.913 25.6423C154.916 25.645 154.927 25.6584 154.947 25.6763C154.779 26.0901 154.763 26.6157 154.867 27.0332C154.891 26.7688 154.913 26.5077 154.987 26.2515C155.033 26.0892 155.092 25.9324 155.149 25.7752C155.313 25.8106 155.569 25.7862 155.947 25.5489C156.111 25.4545 156.242 25.3119 156.322 25.1406L156.597 24.8247C156.617 24.9018 156.645 24.9763 156.683 25.0463C156.683 24.8431 156.821 24.5042 156.981 24.2504C157.28 23.7703 157.854 23.6264 158.218 23.4485C158.073 23.5837 157.921 23.7115 157.78 23.8508C157.481 24.1442 157.301 24.4946 157.348 24.9167C157.513 24.466 157.773 24.135 158.143 23.8333C158.235 23.757 158.373 23.6554 158.49 23.5381C158.439 23.872 158.398 24.2058 158.18 24.4936C157.921 24.8371 157.477 25.1719 157.876 25.6165C157.766 25.3199 158.167 25.0367 158.336 24.8514C158.485 24.6878 158.603 24.4987 158.684 24.2932C159.42 24.7332 159.905 25.8441 159.174 26.0478C159.486 26.2262 160.8 26.3283 160.606 24.8417C160.974 25.0716 161.366 25.2629 161.755 25.4813L161.786 25.4983C161.902 25.5634 162.015 25.6343 162.124 25.7108C162.481 25.9618 162.703 26.2166 162.834 26.458C162.908 26.5891 162.959 26.7314 162.986 26.8792C163.055 27.2641 162.919 27.5528 162.851 27.6149C163.211 27.6057 163.633 27.3441 163.652 26.5343V26.4382L163.655 26.4451C163.663 26.4709 163.672 26.4957 163.681 26.5205C163.95 27.3436 163.953 27.8108 163.953 27.8108C164.183 27.6052 164.441 27.3385 164.475 26.8346C164.491 26.9187 164.73 27.751 164.674 28.592C164.838 28.5364 165.263 28.4417 165.507 27.7873C165.584 28.0172 165.824 28.5065 165.978 29.0477C166.08 29.4068 166.156 29.7908 166.14 30.166C166.114 30.7826 165.818 31.0856 165.795 31.1555C165.816 31.1587 166.503 31.2144 166.925 30.5012C167.333 31.2374 167.966 32.3575 168.925 33.4068Z" fill="#E5ECEF"/> +<path d="M156.06 27.8124C156.218 27.5282 156.48 27.1291 156.822 26.8367C156.914 26.9171 156.968 27.0974 156.987 27.2114C157.059 27.6473 156.671 27.4919 156.06 27.8124Z" fill="#FFCE55"/> +<path d="M153.399 31.6486C153.399 31.6486 153.48 30.9171 154.145 30.7515C154.058 30.4057 154.315 29.7652 154.774 29.8976C154.875 29.001 155.12 27.8744 155.12 27.8744C155.12 27.8744 155.611 28.0239 155.672 27.7595C155.732 27.4951 155.947 26.6559 156.719 26.426C156.061 26.426 155.688 27.0573 155.435 27.4942C155.06 27.4827 154.757 27.1148 154.876 26.54C154.995 25.9653 155.06 25.5859 155.06 25.5859L154.776 25.2525C154.776 25.2525 154.072 25.9556 154.19 26.426C154.309 26.8964 154.625 27.4785 154.466 27.8119C154.308 28.1453 153.717 30.0301 153.717 30.0301C153.221 30.6338 153.177 31.061 153.399 31.6486Z" fill="white"/> +<path d="M163.791 34.9289C163.236 34.9289 161.688 36.0246 161.688 37.1664C160.835 37.5342 158.718 38.3086 158.718 38.3086L161.966 37.772C161.966 37.772 162.905 38.1628 163.534 37.772C164.163 37.3811 164.007 36.6187 164.007 36.6187C163.233 37.2891 161.987 35.9405 163.791 34.9289Z" fill="white"/> +<path d="M160.866 27.4367C161.921 28.451 164.114 30.8977 163.236 33.0589C162.963 31.5148 161.987 29.2884 160.866 27.4367Z" fill="white"/> +<path d="M153.66 31.8481C153.66 31.8481 153.919 32.0472 154.149 31.8481C154.492 31.5515 154.208 30.7868 154.425 30.5909C154.643 30.3951 155.089 30.4378 155.135 30.5146C155.016 30.1927 154.916 29.84 154.993 29.7021C155.069 29.5642 155.343 28.7365 155.912 28.3686C155.669 28.7889 155.247 29.8134 155.433 30.2691C155.606 30.03 156.402 29.806 156.755 30.1527C157.108 30.4994 157.131 31.4683 156.755 31.9341C156.379 32.3999 155.395 32.89 155.135 32.8211C154.362 32.513 154.021 32.2596 153.66 31.8481Z" fill="white"/> +<path d="M155.434 30.2691C155.959 29.4607 156.528 29.8056 156.997 28.7365C157.058 28.8917 157.058 29.0641 156.997 29.2193C157.787 28.8749 158.847 27.3763 158.49 25.9661C158.812 26.4103 159.099 27.8053 158.915 28.4606C158.731 29.1158 157.903 29.5757 157.742 29.84C157.582 30.1044 157.031 30.5183 157.031 30.5183C156.757 30.0309 155.981 30.1449 155.434 30.2691Z" fill="white"/> +<path d="M155.729 28.0927C155.729 28.0927 156.588 28.1897 157.029 27.9662C157.47 27.7428 157.706 27.0121 157.706 26.7592C157.578 27.1041 157.143 27.34 157.143 27.34C156.986 27.5012 156.793 27.6235 156.58 27.6972C156.234 27.8126 155.867 27.9202 155.867 27.9202L155.729 28.0927Z" fill="white"/> +<path d="M155.434 24.8165C155.434 24.8165 155.646 24.6036 155.597 24.3134C155.52 24.5521 155.356 24.598 155.282 24.598C155.208 24.598 154.92 24.1382 154.92 24.1382C154.92 24.1382 155.232 23.843 155.135 23.6462C155.038 23.8472 154.774 24.0256 154.774 24.0256L154.465 23.597C154.465 23.597 154.833 23.4278 154.774 23.2669C154.66 23.2669 155.97 24.4371 155.97 24.4371L156.233 24.8647C156.233 24.8647 156.233 25.1176 155.839 25.3641C155.533 25.0169 155.434 24.8165 155.434 24.8165Z" fill="white"/> +<path d="M159.017 27.8398C159.423 27.6228 158.488 26.2985 158.488 25.9661C159.983 27.3248 161.27 29.5067 160.695 31.397C160.557 31.0062 160.166 30.2079 160.166 30.2079C160.166 30.2079 160.834 32.0242 159.742 33.2657C159.845 31.6563 159.176 29.2322 158.856 28.9204C159.143 28.4215 159.017 27.8398 159.017 27.8398Z" fill="white"/> +<path d="M162.824 34.7394C162.088 34.676 160.787 35.1969 160.442 36.2315C160.463 35.849 160.4 35.4117 160.88 34.9289C160.236 34.9289 159.408 35.8485 159.408 36.6187C158.327 37.1245 155.04 38.6916 154.775 38.9215C154.51 39.1514 154.553 39.3946 154.994 40.4463C154.718 41.2206 154.309 41.679 155.345 42.5771C155.771 42.9449 155.971 42.9909 155.971 42.9909L156.412 42.0841C156.412 42.0841 155.369 40.146 155.67 39.6572C156.379 39.1744 156.649 39.1054 156.649 39.1054C156.649 39.1054 156.901 38.3467 158.189 37.9789C159.476 37.611 161.111 36.8523 161.111 36.8523C161.453 35.151 162.511 34.9362 162.824 34.7394Z" fill="white"/> +<path d="M165.569 38.2317C165.569 38.2317 165.753 36.1625 164.765 35.3119C165.017 35.8407 165.133 36.8983 164.765 37.4271C164.77 36.9568 164.607 36.5002 164.305 36.1396C164.305 36.1396 164.804 38.0018 163.409 38.4502C162.31 38.6916 161.868 38.1858 161.868 38.1858C160.696 38.5996 159.017 38.7605 158.535 38.8755C158.213 39.6112 158.213 41.0964 159.328 42.1535C159.246 41.8929 159.181 41.6274 159.132 41.3585C159.132 41.3585 159.488 41.9333 159.873 41.8413C160.258 41.7494 160.805 41.2256 161.428 42.051C161.181 41.1976 160.89 40.8757 160.89 40.8757L160.097 40.9217L159.545 40.6228L159.154 39.5882L160.89 39.7491C160.89 39.7491 162.602 40.718 163.684 40.071C164.766 39.4241 165.569 38.2317 165.569 38.2317Z" fill="white"/> +<path d="M155.903 30.7252C155.935 30.7246 155.967 30.7286 155.998 30.7372C155.988 31.0191 155.646 31.3773 155.646 31.3773C155.915 31.2251 156.098 31.0959 156.204 30.8673C156.261 30.9273 156.302 30.9998 156.325 31.0789C156.348 31.1579 156.352 31.2413 156.336 31.3221C156.286 31.5377 155.404 31.9015 154.993 32.0693C155.583 31.6872 155.613 30.7331 155.903 30.7252Z" fill="white"/> +<path d="M167.362 30.5983L166.995 30.03C166.995 30.03 166.507 30.7597 166.19 30.8976C166.477 29.6561 165.937 28.2054 165.477 27.4366C165.437 27.6357 165.352 27.8232 165.229 27.9846C165.106 28.1461 164.947 28.2774 164.766 28.3686C164.766 28.3686 164.779 27.5621 164.596 26.9184C164.549 26.7382 164.474 26.5667 164.374 26.4103C164.356 26.6347 164.312 26.8564 164.242 27.0706C164.203 27.2003 164.147 27.324 164.075 27.4384C164.075 27.4384 164.048 27.335 164.005 27.1828C163.959 27.0232 163.898 26.8094 163.829 26.6043C163.734 26.3183 163.629 26.0498 163.546 25.9679C163.534 26.1321 163.583 26.4351 163.533 26.7496C163.503 26.9683 163.411 27.1737 163.267 27.3409L163.236 27.2977C163.219 27.1785 163.195 27.0603 163.165 26.9437C163.079 26.6075 162.904 26.116 162.572 25.8493C162.537 25.8212 162.497 25.7913 162.454 25.761C162.298 25.6502 162.096 25.5256 161.88 25.4005C161.259 25.0423 160.53 24.6855 160.497 24.6694C160.9 24.9246 161.274 25.2233 161.612 25.5601C161.754 25.7037 161.886 25.8573 162.006 26.0199C162.363 26.5082 162.502 26.9538 162.53 27.3156C162.542 27.467 162.534 27.6193 162.506 27.7686C162.085 27.4076 161.569 27.02 161.181 26.8986C161.389 27.0945 161.871 27.6656 162.316 28.2123L162.309 28.2192C162.329 28.2367 162.348 28.256 162.367 28.2744C162.587 28.5429 162.796 28.8022 162.957 29.0036C163.802 30.3238 164.225 32.3383 163.73 33.497C164.248 33.4165 164.814 32.502 164.753 31.7267C164.707 31.1289 164.468 30.3863 164.324 29.9794C167.328 32.9319 167.581 35.0176 167.662 35.2213C167.254 34.6558 165.817 33.3099 165.771 33.268C165.797 33.314 166.93 35.3046 167.31 36.2155C168.072 35.1395 168.681 34.0318 169.11 32.9567L167.362 30.5983Z" fill="white"/> +<path d="M157.822 25.2993C158.169 25.211 158.638 25.0464 158.753 24.7935C159.029 24.9084 159.649 25.5053 159.477 25.966C159.83 25.5398 159.506 24.4854 158.664 24.1382C158.664 23.9543 158.58 23.2646 158.58 23.2646C158.58 23.2646 156.879 24.4537 157.454 25.4561C157.546 25.0142 157.868 24.5636 157.868 24.5636L157.822 25.2993Z" fill="white"/> +<path d="M154.938 23.4727C154.938 23.4727 154.872 22.2988 155.181 21.9158C155.181 22.268 155.372 22.9311 155.95 23.2663C155.572 22.4676 155.49 20.6683 155.49 20.6683C154.55 21.5144 154.476 22.3388 154.938 23.4727Z" fill="#F0ABAB"/> +<path d="M155.713 22.9119C155.713 22.9119 155.456 21.0114 156.918 20.5056C158.381 19.9998 158.488 20.1989 158.488 20.1989C158.488 20.1989 157.093 21.5862 156.718 22.3141C156.718 21.9311 156.861 21.2013 157.335 20.8427C156.528 20.9346 155.791 22.0874 155.713 22.9119Z" fill="#F0ABAB"/> +<path d="M157.434 21.4367C158.074 21.2804 159.281 21.1378 160.174 21.456C159.162 21.6399 158.541 22.0308 158.338 22.3678C159.361 21.908 160.598 21.754 161.198 22.2377C161.799 22.7214 162.494 23.6632 163.533 22.7214C163.533 23.0654 163.628 23.3256 163.533 23.6172C164.093 23.7786 164.297 23.6172 164.297 23.6172C164.297 23.6172 164.357 22.1301 163.454 21.7623C163.445 22.2621 162.886 22.5899 162.427 22.4672C161.967 22.3444 161.181 21.4712 161.181 21.4712C161.181 21.4712 161.122 20.6325 159.161 20.7966C158.074 20.7755 157.434 21.4367 157.434 21.4367Z" fill="#F0ABAB"/> +<path d="M161.507 23.0047C161.691 23.4471 162.058 24.0858 162.711 24.2003C163.363 24.3148 163.963 24.0113 164.299 24.2003C164.636 24.3893 165.663 24.7346 166.138 24.3143C166.307 24.507 165.878 25.2119 165.526 25.1355C164.56 24.8863 164.794 24.9006 163.824 24.89C164.876 25.2418 165.691 25.7324 165.967 26.1614C166.243 26.5904 166.661 27.4365 167.622 27.3399C167.515 27.602 167.331 27.7344 166.871 27.6972C167.009 27.9239 167.392 28.2421 167.76 28.2421C167.546 28.3685 166.979 28.3685 166.979 28.3685C166.979 28.3685 167.902 29.2882 168.021 29.9701C168.301 30.7178 168.593 30.8566 168.593 30.8566C168.593 30.8566 168.941 29.5066 168.082 28.6596C168.757 28.3685 168.849 28.2536 168.849 28.2536L168.006 27.8126C168.006 27.8126 169.045 27.2392 168.604 26.5752C167.822 26.7592 167.584 26.7619 167.059 26.3642C166.533 25.9664 166.121 25.3618 166.121 25.3618C166.121 25.3618 167.3 24.7819 166.535 23.2645C165.952 23.791 165.586 23.9051 164.757 23.6889C163.929 23.4728 162.902 23.7915 162.657 23.6889C162.411 23.5864 161.507 23.0047 161.507 23.0047Z" fill="#F0ABAB"/> +<path d="M158.641 36.5226C158.488 35.511 158.813 33.9587 159.278 33.2657C159.278 33.7945 159.618 34.5914 159.618 34.5914C159.618 34.5914 160.854 33.1319 160.695 32.0693C161.112 33.0588 160.341 34.653 159.656 35.3119C158.971 35.9708 158.641 36.5226 158.641 36.5226Z" fill="white"/> +<path d="M158.028 38.5536C157.578 38.5996 156.997 39.2663 157.2 39.7262C157.404 40.186 158.028 41.1516 158.028 41.1516L157.602 39.8526C157.602 39.8526 158.028 39.5767 158.028 39.2204C158.028 38.864 158.478 38.5076 158.028 38.5536Z" fill="white"/> +<path d="M162.309 28.2177C163.366 29.6169 163.737 30.7136 163.829 31.4392C163.875 31.8144 163.886 32.3524 163.918 32.5727C164.107 32.2637 164.19 31.9017 164.155 31.5413C163.979 29.5677 162.38 28.2674 162.309 28.2177Z" fill="#083751"/> +<path d="M154.46 30.4084C154.251 30.5054 154.306 30.9142 154.336 31.2094L154.376 31.1634C154.424 30.7445 154.496 30.5137 154.718 30.4884C154.718 30.4866 154.669 30.3114 154.46 30.4084Z" fill="#083751"/> +<path d="M157.092 27.8977C156.847 28.021 156.466 28.0619 156.236 28.1152C156.523 28.2279 156.944 28.1667 157.17 28.049C157.467 27.8977 157.59 27.5506 157.604 27.2213C157.442 27.4949 157.362 27.7616 157.092 27.8977Z" fill="#082E44"/> +<path d="M168.208 31.4521C168.245 31.3229 168.337 31.1303 168.292 30.7785C168.398 30.9795 168.464 31.1993 168.487 31.4255C169.343 30.3854 168.5 28.8965 168.38 28.7921C168.708 28.7001 168.932 28.4339 169.162 28.0564C168.84 28.0665 168.651 28.0476 168.364 27.9455C168.945 27.643 168.817 26.8162 168.708 26.355C168.365 26.5932 167.797 26.5311 167.433 26.309C166.995 26.0405 166.925 25.7035 166.39 25.3683C166.55 25.3072 166.687 25.1995 166.784 25.0593C166.89 24.9025 166.959 24.7238 166.986 24.5364C167.072 24.0141 166.918 23.3782 166.584 22.9616C165.933 23.8426 164.621 23.5055 164.528 23.483C164.608 22.9105 164.193 21.5058 163.217 21.4883C163.313 22.2668 162.721 22.505 162.171 22.0976C161.959 21.6331 161.661 21.1977 161.225 20.9379C160.724 20.6385 160.066 20.5792 159.494 20.5976C159.027 20.611 158.578 20.7383 158.214 20.8652C158.326 20.5475 158.75 20.2298 158.825 20.1985C157.722 19.638 155.872 20.3181 155.631 21.5669C155.586 20.9572 155.597 20.439 155.614 20.3737C154.497 20.8418 154.469 22.315 154.482 22.8411L153.143 21.566L154.508 24.7181C154.472 24.8188 154.424 24.9388 154.37 25.0657C154.278 25.2781 154.174 25.5108 154.086 25.7136C154.011 25.8694 153.947 26.0301 153.895 26.1946C153.842 26.4341 154.21 27.3105 154.171 27.6172C154.13 27.9197 154.071 28.2194 153.994 28.5148C153.889 28.9346 153.759 29.3544 153.645 29.6768C153.595 29.8175 153.548 29.9398 153.507 30.035C153.048 30.4106 153.038 31.0268 153.032 31.3151C153.023 31.7952 153.756 32.3419 154.041 32.5157C154.087 32.5433 154.14 32.5746 154.199 32.6077C154.399 32.7216 154.608 32.8202 154.823 32.9029C154.961 32.9586 155.106 32.9924 155.255 33.0031C155.703 33.0118 156.805 32.3515 156.953 32.1626C157.1 31.9736 157.235 30.9394 157.39 30.5725C157.656 29.9412 157.85 30.2046 158.698 29.2349C158.867 29.5604 159.242 30.3803 159.444 31.5597C158.397 32.5654 158.025 33.8809 157.988 35.0493C157.881 35.1543 157.781 35.2659 157.688 35.3836C157.465 35.66 157.275 35.9617 157.122 36.2825C156.921 36.7093 156.416 36.9879 155.863 37.2201C155.691 37.2919 155.515 37.3581 155.341 37.4257C155.086 37.5236 154.836 37.6183 154.617 37.7195C153.886 38.0584 153.585 38.4819 153.463 38.9647C153.366 39.344 153.574 39.8986 153.667 40.1193C153.614 40.5469 153.475 41.7811 153.593 42.0892C153.736 42.4644 153.771 42.5458 154.271 43.1541C154.451 44.0944 154.91 45.3502 155.82 45.6422C156.619 45.5162 157.117 43.419 157.131 42.5996L157.065 42.4579C157.065 42.4579 156.135 41.4422 156.094 41.101C156.052 40.7598 156.104 40.5147 155.843 39.7542C156.029 39.6695 156.222 39.6019 156.421 39.5523C156.447 39.7749 156.545 40.145 156.872 40.6099C157.421 41.3884 157.761 42.8529 158.125 43.0828C158.489 43.3127 159.183 43.1026 159.183 43.1026C159.183 43.1026 161.089 44.7722 162.885 43.8452C162.954 43.4144 162.801 42.7361 162.606 42.1333C162.544 41.9443 162.478 41.7631 162.414 41.5985C162.257 41.1994 162.108 40.9028 162.046 40.849C162.046 40.849 161.515 40.5198 160.334 40.7617C160.255 40.6803 159.912 40.6016 159.782 40.5832C159.673 40.3731 159.467 39.791 159.568 39.7303C159.676 39.6654 160.274 39.7763 160.672 39.8636C161.113 39.9602 161.619 40.5216 162.563 40.5391C163.575 40.5584 165.069 39.8342 165.542 38.9297C166.074 37.9149 165.893 36.4545 165.152 35.8797C165.651 36.9474 165.519 37.8469 165.1 38.5269C164.472 39.5362 163.301 39.9694 162.595 39.9561C162.061 39.9401 161.539 39.7896 161.078 39.5183C161.078 39.5183 159.117 39.0364 158.989 39.4801C158.931 39.6815 159.038 40.0232 159.173 40.3377C159.281 40.5854 159.404 40.8265 159.54 41.0596C159.54 41.0596 160.008 41.0366 160.05 41.3737C160.165 41.2774 160.296 41.2016 160.437 41.1497C160.523 41.1179 160.611 41.0942 160.702 41.0789C160.877 41.1968 161.011 41.367 161.084 41.5654C161.164 41.7894 161.156 42.0298 161.12 42.2552C161.079 42.5168 161 42.7573 160.979 42.9288C160.957 43.0945 161.002 43.2621 161.103 43.395C160.508 43.2783 159.852 43.0272 159.509 42.5968C158.613 42.6575 158.449 42.8805 158.162 41.9944C157.874 41.1084 157.232 40.2085 156.969 39.8425C156.892 39.7243 156.862 39.582 156.884 39.4429C156.911 39.243 156.988 39.0532 157.108 38.8911C157.25 38.6892 157.444 38.5294 157.668 38.4285C158.298 38.1526 160.857 37.4956 161.235 36.9907C161.613 36.4858 161.441 35.4089 163.28 34.7228C162.755 34.5522 161.235 35.3086 160.857 36.6472C160.144 37.1139 158.321 37.6441 157.825 37.7908C157.397 37.914 157.014 38.1574 156.721 38.492C156.592 38.6391 156.489 38.8078 156.417 38.9904C156.417 38.9955 156.413 39.0005 156.412 39.0056C156.006 39.1486 155.345 39.3781 155.34 39.6953C155.333 40.0508 155.586 40.5649 155.569 41.3015C155.566 41.4909 155.887 41.8882 156.186 42.2184C156.12 42.9247 155.347 43.1973 155.032 43.4332C154.946 43.4973 154.877 43.5825 154.832 43.6806C154.758 43.4322 154.708 43.1772 154.684 42.9191C154.288 42.3779 154.143 42.2294 154.07 41.9995C154.016 41.8284 154.095 40.9024 154.143 40.3901C154.202 40.3832 154.33 40.4733 154.584 40.6141C154.251 40.0981 153.829 39.5155 153.998 38.9904C154.118 38.6226 154.397 38.4805 154.879 38.2143C155.02 38.1361 155.287 38.0266 155.6 37.8988C155.765 37.8312 155.943 37.7581 156.122 37.6813C156.759 37.4091 157.409 37.0914 157.55 36.8077C157.763 36.3736 157.918 36.1639 158.029 35.98C158.07 36.3543 158.151 36.7232 158.271 37.0803C158.242 34.5053 159.177 32.8918 159.546 32.3566C159.588 32.8706 159.588 33.3871 159.546 33.9011C160.15 33.336 160.091 30.51 159.036 28.7231C159.426 27.8724 159.057 27.0218 158.76 26.6953C158.894 27.2995 159.004 27.7529 158.768 28.3171C158.796 28.0332 158.755 27.7467 158.647 27.4825C158.642 27.4696 158.624 27.4784 158.626 27.4908C158.714 27.8665 158.664 28.2476 158.534 28.6086C158.492 28.7254 158.442 28.8413 158.388 28.9535C158.026 29.3977 157.45 29.5374 157.153 30.0644C156.93 29.9688 156.438 29.7931 156.084 29.9356C155.986 29.9669 155.892 30.0121 155.807 30.0699C155.728 30.1207 155.662 30.1892 155.614 30.2699C155.727 30.1435 156.074 30.04 156.35 30.0442C156.396 30.0474 156.633 30.08 156.764 30.3863C156.763 30.3912 156.762 30.396 156.76 30.4005L156.765 30.3895C156.829 30.5431 156.865 30.7652 156.838 31.0852C156.762 31.4011 156.689 31.6866 156.581 31.8177C156.375 32.0678 155.703 32.4693 155.342 32.5387C155.185 32.5643 155.024 32.5444 154.879 32.4812C155.007 32.3783 155.145 32.29 155.293 32.2177C156.028 31.8632 156.405 31.6466 156.512 31.448C156.657 31.1785 156.374 30.7325 156.052 30.5463C156.181 30.5067 156.324 30.5513 156.429 30.5776C156.283 30.4125 155.862 30.3205 155.703 30.4746C155.315 30.8502 155.319 31.6862 154.652 31.9639C154.479 32.0336 154.298 32.0815 154.114 32.1065L154.11 32.1037C153.737 31.8457 153.508 31.4903 153.481 31.208C153.451 30.9091 153.511 30.5182 153.762 30.2883C153.795 30.258 153.831 30.2311 153.869 30.2079C153.951 30.0101 154.052 29.7021 154.157 29.3659C154.375 28.6495 154.594 27.8067 154.614 27.6274C154.643 27.3639 154.321 26.6562 154.35 26.3251C154.366 26.1495 154.561 25.7917 154.696 25.5614C154.742 25.4846 154.78 25.4234 154.803 25.3848L154.861 25.5177L154.916 25.6423C154.926 25.6542 154.938 25.6654 154.95 25.6759C154.781 26.0897 154.766 26.6157 154.869 27.0333C154.893 26.7689 154.915 26.5082 154.989 26.2516C155.035 26.0893 155.094 25.9329 155.152 25.7752C155.315 25.8106 155.572 25.7862 155.95 25.5494C156.109 25.4562 156.237 25.3175 156.318 25.1512C156.319 25.1476 156.32 25.1441 156.322 25.1406L156.598 24.8247C156.617 24.902 156.645 24.9764 156.683 25.0464C156.683 24.8891 156.766 24.6509 156.878 24.4339C156.911 24.37 156.946 24.3079 156.982 24.25C157.282 23.7704 157.855 23.626 158.219 23.4485C158.075 23.5832 157.922 23.7111 157.782 23.8499C157.649 23.9762 157.539 24.1242 157.457 24.2877C157.366 24.475 157.328 24.6839 157.348 24.8914V24.9163C157.351 24.9071 157.355 24.8974 157.358 24.8882C157.45 24.6421 157.584 24.4136 157.753 24.2127C157.871 24.0742 158.001 23.9471 158.142 23.8329C158.234 23.7566 158.372 23.655 158.489 23.5382C158.468 23.7112 158.435 23.8826 158.391 24.0513C158.349 24.2106 158.277 24.3604 158.179 24.4932C158.12 24.5723 158.051 24.6505 157.984 24.73C157.761 24.9963 157.568 25.2735 157.875 25.6166C157.766 25.32 158.166 25.0363 158.335 24.8505C158.409 24.7707 158.475 24.684 158.532 24.5916C158.591 24.4966 158.642 24.3966 158.683 24.2927C158.777 24.3492 158.865 24.4143 158.946 24.4872C159.521 24.9976 159.812 25.8695 159.173 26.0474C159.486 26.2254 160.799 26.3274 160.605 24.8413C160.984 25.0753 161.387 25.2726 161.786 25.4979C163.415 26.4176 162.989 27.4848 162.851 27.6172C163.225 27.608 163.665 27.3257 163.652 26.4396C163.652 26.4419 163.654 26.4447 163.655 26.4475C163.95 27.3165 163.953 27.8122 163.953 27.8122C164.186 27.6071 164.442 27.34 164.475 26.8365C164.492 26.9206 164.73 27.7524 164.674 28.5939C164.838 28.5387 165.263 28.4435 165.507 27.7892C165.584 28.0191 165.825 28.5084 165.978 29.0496C166.08 29.4087 166.156 29.7926 166.141 30.1679C166.114 30.7845 165.819 31.0875 165.795 31.1574C165.817 31.1606 166.504 31.2162 166.925 30.5035C167.339 31.2512 167.986 32.398 168.974 33.4629C169.006 33.4979 169.055 33.5485 169.112 33.6046C169.181 33.3792 169.254 33.1548 169.33 32.9318C168.974 32.6058 168.572 32.1285 168.208 31.4521ZM161.113 41.0596C161.284 41.071 161.452 41.1019 161.616 41.1516C161.697 41.3456 161.806 41.6114 161.916 41.8905C161.985 42.0662 162.054 42.2473 162.116 42.4211C162.28 42.8777 162.4 43.2792 162.346 43.3716C162.293 43.464 161.989 43.4967 161.584 43.4636C161.341 43.1173 161.348 42.8598 161.4 42.4363C161.407 42.3775 161.415 42.3149 161.423 42.2487C161.439 42.0863 161.427 41.9223 161.388 41.7641C161.326 41.5188 161.234 41.2822 161.113 41.0596ZM155.839 43.2778C156.106 43.0778 156.289 42.726 156.401 42.4455C156.508 42.5568 156.599 42.6469 156.651 42.698C156.598 43.4079 156.398 44.7382 155.65 45.0729C155.42 44.981 155.219 44.6747 155.059 44.3138C155.142 43.7845 155.38 43.624 155.839 43.2778ZM155.905 30.7247C155.937 30.7241 155.969 30.7281 156 30.7367C155.99 31.0185 155.648 31.3767 155.648 31.3767C155.917 31.2245 156.1 31.0953 156.206 30.8668C156.263 30.9268 156.304 30.9993 156.327 31.0783C156.35 31.1574 156.353 31.2407 156.338 31.3215C156.288 31.5372 155.406 31.9009 154.995 32.0688C155.585 31.6871 155.615 30.733 155.905 30.7252V30.7247ZM155.802 25.2804C155.634 25.4096 155.407 25.4873 155.239 25.4432L155.231 25.4244L154.983 24.9107L153.925 22.7211L154.631 23.432C154.593 23.5005 154.543 23.5768 154.467 23.5947C154.511 23.6048 154.557 23.6021 154.6 23.5867C154.642 23.5714 154.68 23.5442 154.707 23.5083L155.04 23.8449C154.972 23.9966 154.86 24.1833 154.688 24.2127C154.909 24.2762 155.078 24.1355 155.157 23.9635L155.581 24.3916C155.535 24.5571 155.443 24.7595 155.218 24.8514C155.163 24.874 155.107 24.8895 155.048 24.8974C155.3 24.9572 155.481 24.8822 155.596 24.7595C155.654 24.6948 155.696 24.6179 155.721 24.5346L155.874 24.6886L156.02 24.8362C156.068 24.9894 155.961 25.1586 155.802 25.2809V25.2804ZM167.987 31.0057C167.853 30.8783 167.343 30.287 167.126 30.0019C167.231 29.6731 167.213 29.4459 167.14 29.1112C167.048 29.663 166.654 30.2966 166.451 30.5509C166.543 30.2069 166.507 29.8372 166.451 29.491C166.382 29.1028 166.269 28.7239 166.114 28.3617C165.778 27.5432 165.778 27.5432 165.489 26.8314C165.321 27.5115 165.177 27.8288 164.954 28.1037C164.966 27.8861 164.952 27.6678 164.911 27.4535C164.895 27.3639 164.757 26.6668 164.103 25.7297C164.161 26.1642 164.333 26.6792 164.128 27.1652C164.114 26.8011 163.874 25.7467 163.146 25.326C163.35 25.6773 163.529 26.7781 163.284 27.0599C163.308 26.453 162.885 25.8938 162.424 25.5255C162.084 25.2538 160.201 24.2031 160.194 24.2031C160.198 24.2077 160.545 25.7246 159.784 25.8446C159.947 25.4768 159.707 24.8211 159.322 24.3939C159.159 24.2132 158.97 24.072 158.774 24.0127C158.778 23.9929 158.782 23.9732 158.785 23.9529C158.848 23.5952 158.824 23.1795 158.703 22.8645C158.373 23.2186 157.544 23.2338 157.094 23.6237C156.898 23.7906 156.693 24.0463 156.61 24.3387L156.467 24.5369L156.361 24.6827C156.356 24.6531 156.345 24.6248 156.329 24.5994L156.306 24.5774L155.09 23.4195C154.807 22.8815 154.73 21.583 155.336 21.005C155.309 21.3476 155.333 22.9887 155.952 23.2646C155.523 22.253 155.978 20.37 158.13 20.3585C157.736 20.6523 157.434 21.1333 157.302 21.4552C157.16 21.6106 157.034 21.7801 156.926 21.961C157.081 21.869 157.584 21.0142 159.472 21.0087C159.973 21.0087 160.518 21.0634 160.962 21.3163C160.198 21.1273 159.385 21.5462 158.751 21.9725C159.198 21.829 159.848 21.3991 160.762 21.578C161.376 21.698 161.629 22.264 162.136 22.5565C162.55 22.7946 163.138 22.7772 163.408 22.3321C163.476 22.2214 163.509 22.0936 163.505 21.9642C163.621 22.0874 163.723 22.2237 163.808 22.3702C163.996 22.6964 164.075 23.0743 164.032 23.4485C163.816 23.4349 163.6 23.4451 163.386 23.4789C163.156 23.5069 162.926 23.5345 162.696 23.5083C162.374 23.468 162.063 23.3613 161.784 23.1947C161.688 23.1376 161.596 23.0743 161.508 23.0052C161.561 23.0811 161.619 23.1533 161.681 23.2214C161.912 23.4778 162.212 23.6613 162.546 23.7492C163.085 23.8945 163.611 23.6922 164.15 23.7874C164.498 23.8485 164.897 24.0035 165.305 24.0426C165.619 24.0725 165.939 24.0334 166.245 23.8302C166.369 23.745 166.473 23.6343 166.55 23.5055C166.657 23.7987 166.67 24.1177 166.589 24.4187L166.575 24.4647C166.526 24.6345 166.438 24.7905 166.318 24.9199L166.305 24.9337C166.189 25.0482 166.048 25.0873 165.915 25.1664C165.47 24.9825 164.972 24.9199 164.49 24.8905C164.923 25.0284 165.367 25.1664 165.777 25.3623C166.188 25.5582 166.463 25.8681 166.75 26.2129C166.989 26.5008 167.267 26.7615 167.641 26.8503C167.898 26.9112 168.167 26.8981 168.416 26.8126C168.483 27.1873 168.136 27.7984 167.652 27.8793C167.886 28.0287 168.138 28.1478 168.403 28.2339C168.219 28.3998 167.779 28.5231 167.497 28.5378C168.176 28.8937 168.517 29.8418 168.502 30.612C168.393 30.3766 168.268 30.1062 167.983 29.9007C168.064 30.2332 168.049 30.635 167.989 31.0061L167.987 31.0057Z" fill="#083751"/> +<path d="M157.211 27.1729C157.181 27.0065 157.119 26.8226 157.002 26.6984C157.174 26.5768 157.371 26.4963 157.578 26.463C157.065 26.3397 156.72 26.5338 156.329 26.9136C156.085 27.1509 155.795 27.7473 155.735 27.922C155.665 28.1289 155.183 27.9597 155.183 27.9597C155.284 28.0866 155.492 28.2485 155.714 28.2526C155.88 28.2558 155.884 28.1666 155.96 28.0084C156.412 27.8011 156.901 27.7983 157.086 27.647C157.227 27.5316 157.242 27.3569 157.211 27.1729ZM156.062 27.8121C156.22 27.5279 156.482 27.1288 156.824 26.8364C156.916 26.9168 156.97 27.0971 156.989 27.2111C157.059 27.6475 156.671 27.4921 156.06 27.8126L156.062 27.8121Z" fill="#083751"/> +<path d="M154.431 29.8479C153.989 30.172 153.993 30.9878 154.176 31.2733C154.128 30.888 154.23 30.0837 154.598 30.0778C154.839 30.0727 154.961 30.1463 155.017 30.1978L155.058 30.2461C155.063 30.2088 155.061 30.1709 155.052 30.1343C155.048 29.6626 155.321 29.2381 155.49 28.793C155.216 29.0954 154.985 29.4345 154.805 29.8005C154.701 29.7449 154.572 29.7449 154.431 29.8479Z" fill="#083751"/> +<path d="M176.373 30.5861C176.104 30.4279 175.866 30.2215 175.672 29.9771C175.45 29.7092 175.339 29.3377 175.339 28.8625C175.339 28.0046 175.883 27.3764 176.971 26.9779L179.774 25.9667H180.602C181.245 25.9667 181.747 26.1507 182.107 26.5185C182.467 26.8864 182.647 27.392 182.647 28.0353V40.7902C182.416 40.8487 182.182 40.8947 181.946 40.9281C181.623 40.9759 181.296 40.9989 180.969 40.9971C180.234 40.9971 179.702 40.8745 179.372 40.6292C179.043 40.384 178.878 39.9167 178.878 39.2273V29.7358L176.373 30.5861Z" fill="#323232"/> +<path d="M185.313 26.5414C185.313 25.9594 185.508 25.4691 185.899 25.0706C186.29 24.6721 186.807 24.473 187.45 24.4731C188.094 24.4731 188.611 24.6723 189.001 25.0706C189.392 25.4689 189.588 25.9592 189.588 26.5414C189.588 27.1239 189.392 27.6142 189.001 28.0123C188.611 28.4108 188.094 28.61 187.45 28.61C186.807 28.61 186.29 28.4108 185.899 28.0123C185.508 27.614 185.313 27.1237 185.313 26.5414ZM185.497 29.8049C185.735 29.7452 185.977 29.6992 186.221 29.6669C186.56 29.6192 186.901 29.5962 187.244 29.598C188.01 29.598 188.561 29.7243 188.898 29.9771C189.236 30.2299 189.404 30.7163 189.404 31.4365V40.79C189.165 40.8496 188.924 40.8957 188.68 40.928C188.341 40.9757 187.999 40.9987 187.657 40.9969C186.891 40.9969 186.339 40.8706 186.003 40.6178C185.666 40.365 185.497 39.8786 185.497 39.1584L185.497 29.8049Z" fill="#323232"/> +<path d="M202.871 40.7901C202.633 40.8497 202.391 40.8958 202.147 40.9281C201.809 40.9758 201.467 40.9988 201.125 40.997C200.358 40.997 199.807 40.8706 199.47 40.6179C199.133 40.3651 198.965 39.8786 198.964 39.1585V33.7348C198.964 33.26 198.822 32.9115 198.539 32.6891C198.256 32.4667 197.884 32.3557 197.424 32.3559C197.133 32.3539 196.843 32.3926 196.563 32.4708C196.297 32.5465 196.04 32.6465 195.793 32.7697V40.7903C195.554 40.8499 195.313 40.8959 195.069 40.9282C194.73 40.9759 194.388 40.9989 194.046 40.9972C193.28 40.9972 192.728 40.8708 192.391 40.618C192.055 40.3652 191.886 39.8788 191.886 39.1587V32.241C191.886 31.8273 191.974 31.4903 192.15 31.2298C192.346 30.9499 192.591 30.7084 192.874 30.5173C193.395 30.1495 194.05 29.8545 194.839 29.6325C195.628 29.4105 196.505 29.2994 197.47 29.2993C199.201 29.2993 200.534 29.6785 201.469 30.4369C202.404 31.1952 202.871 32.2563 202.871 33.6199L202.871 40.7901Z" fill="#323232"/> +<path d="M211.581 32.3788C211.209 32.3769 210.84 32.4391 210.489 32.5627C210.154 32.6795 209.848 32.8677 209.593 33.1142C209.331 33.3728 209.124 33.6816 208.984 34.022C208.831 34.3822 208.754 34.7997 208.754 35.2744C208.754 36.2247 209.022 36.9295 209.558 37.3888C210.095 37.8481 210.761 38.0779 211.558 38.0782C211.97 38.0851 212.381 38.0269 212.776 37.9059C213.089 37.8062 213.396 37.6872 213.695 37.5497C213.986 37.7643 214.204 37.9941 214.35 38.2391C214.495 38.4843 214.568 38.7831 214.568 39.1354C214.568 39.7485 214.266 40.2387 213.661 40.6062C213.055 40.9737 212.194 41.1576 211.075 41.158C210.11 41.158 209.24 41.0316 208.467 40.7788C207.693 40.526 207.034 40.1507 206.49 39.6527C205.938 39.1433 205.51 38.5144 205.238 37.8142C204.947 37.0866 204.801 36.2401 204.801 35.2746C204.801 34.2635 204.966 33.3826 205.295 32.6318C205.625 31.881 206.073 31.2605 206.64 30.7703C207.215 30.2754 207.883 29.9004 208.605 29.6672C209.365 29.4194 210.16 29.2952 210.96 29.2994C212.063 29.2994 212.914 29.4986 213.511 29.8971C214.109 30.2956 214.407 30.8089 214.407 31.4369C214.409 31.722 214.338 32.0028 214.2 32.2527C214.072 32.4931 213.909 32.7136 213.718 32.9077C213.412 32.768 213.097 32.649 212.775 32.5514C212.388 32.4337 211.986 32.3755 211.581 32.3788Z" fill="#323232"/> +<path d="M226.829 40.9281C226.491 40.9758 226.149 40.9989 225.807 40.9971C225.04 40.9971 224.489 40.8707 224.152 40.6179C223.815 40.3652 223.647 39.8787 223.646 39.1586V34.0566C223.646 33.4286 223.489 32.9881 223.175 32.7352C222.861 32.4822 222.474 32.3558 222.014 32.356C221.731 32.3529 221.448 32.3916 221.176 32.4709C220.932 32.544 220.696 32.6443 220.475 32.7698V40.7904C220.236 40.85 219.994 40.896 219.751 40.9283C219.412 40.976 219.07 40.9991 218.728 40.9973C217.962 40.9973 217.41 40.8709 217.073 40.6181C216.737 40.3653 216.568 39.8789 216.568 39.1588V25.8291C216.806 25.7695 217.048 25.7234 217.292 25.6912C217.63 25.6435 217.972 25.6204 218.314 25.6222C219.08 25.6222 219.632 25.7486 219.969 26.0014C220.306 26.2541 220.475 26.7406 220.475 27.4607V29.7359C220.81 29.6046 221.156 29.5008 221.509 29.4257C221.917 29.3389 222.333 29.2965 222.75 29.2992C224.266 29.2992 225.446 29.6784 226.289 30.4368C227.132 31.1952 227.553 32.3252 227.553 33.8267V40.7901C227.314 40.8497 227.073 40.8958 226.829 40.9281Z" fill="#323232"/> +<g filter="url(#filter1_d)"> +<path fill-rule="evenodd" clip-rule="evenodd" d="M57.3386 69.6297H55.5587V79.4075H57.3386V69.6297Z" fill="#2B71FF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M73.116 73.7249C74.9508 74.1552 76.0099 74.7634 76.2635 75.9652C76.3071 76.165 76.3271 76.3691 76.3232 76.5734C76.3232 78.3983 75.0403 79.5555 72.9519 79.5555C71.3584 79.5423 69.8209 78.9696 68.6109 77.9384L69.67 76.707C70.6247 77.5229 71.7585 78.0422 72.9966 78.0422C74.2348 78.0422 74.5779 77.4933 74.5779 76.7366C74.5779 75.98 74.1751 75.6536 72.3253 75.2382C70.2071 74.7486 68.9838 74.0513 68.9838 72.2413C68.9838 70.4313 70.2518 69.4818 72.2209 69.4818C73.5927 69.4665 74.9307 69.9049 76.0248 70.728L75.085 72.0188C74.19 71.366 73.1756 70.9209 72.2657 70.9209C71.3557 70.9209 70.7292 71.4401 70.7292 72.0929C70.7292 72.7457 71.2214 73.2798 73.116 73.7249Z" fill="#2B71FF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M89.7788 69.6297L87.3932 76.8368L84.9483 69.6297H83.4814L81.0365 76.8368L78.6509 69.6297H76.7691L80.2364 79.4075H81.7478L84.1926 72.4383L86.6375 79.4075H88.1341L91.6013 69.6297H89.7788Z" fill="#2B71FF"/> +<path d="M105.471 71.19H102.99V74.6226H105.471C106.8 74.6226 107.622 74.1174 107.622 72.8543C107.622 71.5912 106.785 71.19 105.471 71.19ZM105.411 76.1532H102.99V79.4075H101.242V69.6297H105.62C107.936 69.6297 109.4 70.8037 109.4 72.78C109.4 74.9793 107.771 76.1532 105.411 76.1532Z" fill="#2B71FF"/> +<path d="M63.8429 71.19H61.3168V74.6078H63.8577C65.1059 74.6078 65.9083 73.8797 65.9083 72.884C65.9083 71.8884 65.1356 71.19 63.8429 71.19ZM65.6557 79.4075L63.4862 76.1235H61.3168V79.4075H59.5634V69.6297H63.9915C66.2649 69.6297 67.6765 70.982 67.6765 72.884C67.6765 74.4889 66.6958 75.4548 65.2991 75.8412L67.7211 79.4075H65.6557Z" fill="#2B71FF"/> +<path d="M49.0329 71.6655L50.4504 75.3805C49.3733 75.3787 48.3088 75.612 47.3319 76.0641L49.0329 71.6655ZM43.9895 79.4075H45.8248C45.8248 79.4075 47.1528 76.599 51.0473 76.9111L52.0918 79.4075H53.9271L49.8685 69.6297H48.1525L43.9895 79.4075Z" fill="#2B71FF"/> +<path d="M96.8666 76.0641C95.8909 75.6129 94.8281 75.3796 93.7527 75.3805L95.1681 71.6655L96.8666 76.0641ZM96.0471 69.6297H94.3338L90.2664 79.4075H92.0989L93.1568 76.9111C97.0305 76.599 98.3565 79.4075 98.3565 79.4075H100.204L96.0471 69.6297Z" fill="#2B71FF"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M36.091 78.963L30.9956 84L28.4705 81.5038C31.1936 81.3394 33.8235 80.4626 36.091 78.963Z" fill="#2B71FF"/> +<path d="M40.8585 73.8454L40.2328 73.2199L31.0112 64L21.7896 73.2199L21 74.0093L21.2831 74.2625C21.6108 74.5306 21.9386 74.7838 22.2812 75.0221C24.784 76.7742 27.7556 77.7339 30.8107 77.7763C33.8657 77.8188 36.863 76.9422 39.4135 75.2604C39.771 75.0221 40.1285 74.754 40.4712 74.4859C40.8138 74.2178 40.8436 74.1731 41.0224 74.0093L40.8585 73.8454ZM33.4395 76.1541C30.6884 74.4655 27.5205 73.5784 24.2924 73.5922C28.5084 71.7602 33.663 71.507 38.4004 74.2327C36.8868 75.1882 35.2019 75.8409 33.4395 76.1541Z" fill="#2B71FF"/> +</g> +<path d="M39.9463 110.396C39.9463 110.804 39.8703 111.188 39.7183 111.548C39.5663 111.9 39.3543 112.208 39.0823 112.472C38.8183 112.728 38.5023 112.932 38.1343 113.084C37.7743 113.228 37.3783 113.3 36.9463 113.3H35.9623V116H34.0543V107.48H36.9463C37.3783 107.48 37.7743 107.556 38.1343 107.708C38.5023 107.852 38.8183 108.056 39.0823 108.32C39.3543 108.584 39.5663 108.896 39.7183 109.256C39.8703 109.608 39.9463 109.988 39.9463 110.396ZM38.0983 110.396C38.0983 110.076 37.9863 109.812 37.7623 109.604C37.5463 109.388 37.2663 109.28 36.9223 109.28H35.9623V111.512H36.9223C37.2663 111.512 37.5463 111.404 37.7623 111.188C37.9863 110.972 38.0983 110.708 38.0983 110.396ZM40.8827 110H42.6947V110.9C42.7907 110.636 42.9667 110.408 43.2227 110.216C43.4867 110.024 43.7867 109.928 44.1227 109.928C44.2107 109.928 44.3027 109.932 44.3987 109.94C44.4947 109.948 44.5987 109.968 44.7107 110V111.836C44.5747 111.788 44.4427 111.752 44.3147 111.728C44.1867 111.704 44.0507 111.692 43.9067 111.692C43.5147 111.692 43.2147 111.828 43.0067 112.1C42.7987 112.372 42.6947 112.724 42.6947 113.156V116H40.8827V110ZM48.2956 116.132C47.8636 116.132 47.4556 116.052 47.0716 115.892C46.6876 115.732 46.3516 115.512 46.0636 115.232C45.7836 114.944 45.5596 114.612 45.3916 114.236C45.2236 113.852 45.1396 113.44 45.1396 113C45.1396 112.56 45.2236 112.152 45.3916 111.776C45.5596 111.392 45.7836 111.06 46.0636 110.78C46.3516 110.492 46.6876 110.268 47.0716 110.108C47.4556 109.948 47.8636 109.868 48.2956 109.868C48.7276 109.868 49.1356 109.948 49.5196 110.108C49.9036 110.268 50.2356 110.492 50.5156 110.78C50.8036 111.06 51.0316 111.392 51.1996 111.776C51.3676 112.152 51.4516 112.56 51.4516 113C51.4516 113.44 51.3676 113.852 51.1996 114.236C51.0316 114.612 50.8036 114.944 50.5156 115.232C50.2356 115.512 49.9036 115.732 49.5196 115.892C49.1356 116.052 48.7276 116.132 48.2956 116.132ZM48.2956 114.44C48.6796 114.44 48.9956 114.308 49.2436 114.044C49.4996 113.78 49.6276 113.432 49.6276 113C49.6276 112.568 49.4996 112.22 49.2436 111.956C48.9956 111.692 48.6796 111.56 48.2956 111.56C47.9116 111.56 47.5916 111.692 47.3356 111.956C47.0876 112.22 46.9636 112.568 46.9636 113C46.9636 113.432 47.0876 113.78 47.3356 114.044C47.5916 114.308 47.9116 114.44 48.2956 114.44ZM53.1211 111.572H51.9211V110H53.1211V109.34C53.1211 108.956 53.1851 108.616 53.3131 108.32C53.4411 108.024 53.6131 107.772 53.8291 107.564C54.0451 107.356 54.2971 107.2 54.5851 107.096C54.8811 106.984 55.1971 106.928 55.5331 106.928C55.7731 106.928 55.9771 106.94 56.1451 106.964C56.3211 106.988 56.4771 107.02 56.6131 107.06V108.656C56.5171 108.616 56.4171 108.588 56.3131 108.572C56.2171 108.556 56.1011 108.548 55.9651 108.548C55.5971 108.548 55.3331 108.628 55.1731 108.788C55.0131 108.948 54.9331 109.208 54.9331 109.568V110H56.6131V111.572H54.9331V116H53.1211V111.572ZM60.1912 116.132C59.7512 116.132 59.3352 116.06 58.9432 115.916C58.5592 115.772 58.2232 115.564 57.9352 115.292C57.6472 115.02 57.4192 114.692 57.2512 114.308C57.0832 113.916 56.9992 113.48 56.9992 113C56.9992 112.552 57.0752 112.14 57.2272 111.764C57.3872 111.38 57.6072 111.048 57.8872 110.768C58.1752 110.488 58.5112 110.268 58.8952 110.108C59.2792 109.948 59.6992 109.868 60.1552 109.868C60.5472 109.868 60.9232 109.932 61.2832 110.06C61.6512 110.18 61.9712 110.364 62.2432 110.612C62.5152 110.852 62.7312 111.156 62.8912 111.524C63.0592 111.884 63.1432 112.308 63.1432 112.796C63.1432 112.876 63.1392 112.968 63.1312 113.072C63.1312 113.168 63.1232 113.288 63.1072 113.432H58.7512C58.8072 113.792 58.9792 114.06 59.2672 114.236C59.5552 114.404 59.8712 114.488 60.2152 114.488C60.5672 114.488 60.8672 114.42 61.1152 114.284C61.3712 114.14 61.5552 113.98 61.6672 113.804L63.0112 114.812C62.7312 115.212 62.3472 115.532 61.8592 115.772C61.3792 116.012 60.8232 116.132 60.1912 116.132ZM61.3432 112.244C61.2632 111.924 61.1032 111.696 60.8632 111.56C60.6232 111.416 60.3712 111.344 60.1072 111.344C59.9712 111.344 59.8352 111.36 59.6992 111.392C59.5632 111.424 59.4352 111.476 59.3152 111.548C59.1952 111.62 59.0872 111.712 58.9912 111.824C58.9032 111.936 58.8392 112.076 58.7992 112.244H61.3432ZM66.349 116.132C65.821 116.132 65.341 116.044 64.909 115.868C64.485 115.692 64.133 115.42 63.853 115.052L65.053 113.96C65.189 114.16 65.369 114.316 65.593 114.428C65.817 114.532 66.069 114.584 66.349 114.584C66.485 114.584 66.609 114.56 66.721 114.512C66.841 114.456 66.901 114.368 66.901 114.248C66.901 114.144 66.857 114.06 66.769 113.996C66.681 113.932 66.481 113.86 66.169 113.78L65.773 113.684C65.197 113.548 64.765 113.308 64.477 112.964C64.189 112.612 64.053 112.196 64.069 111.716C64.077 111.436 64.137 111.184 64.249 110.96C64.369 110.728 64.529 110.532 64.729 110.372C64.937 110.212 65.181 110.088 65.461 110C65.741 109.912 66.045 109.868 66.373 109.868C67.301 109.868 68.005 110.2 68.485 110.864L67.309 111.836C67.173 111.66 67.025 111.536 66.865 111.464C66.705 111.392 66.537 111.356 66.361 111.356C66.249 111.356 66.137 111.38 66.025 111.428C65.921 111.476 65.869 111.556 65.869 111.668C65.869 111.732 65.893 111.804 65.941 111.884C65.997 111.964 66.141 112.036 66.373 112.1L66.925 112.244C67.469 112.388 67.897 112.608 68.209 112.904C68.529 113.192 68.689 113.604 68.689 114.14C68.689 114.428 68.629 114.696 68.509 114.944C68.389 115.184 68.221 115.392 68.005 115.568C67.797 115.744 67.549 115.884 67.261 115.988C66.981 116.084 66.677 116.132 66.349 116.132ZM71.8803 116.132C71.3523 116.132 70.8723 116.044 70.4403 115.868C70.0163 115.692 69.6643 115.42 69.3843 115.052L70.5843 113.96C70.7203 114.16 70.9003 114.316 71.1243 114.428C71.3483 114.532 71.6003 114.584 71.8803 114.584C72.0163 114.584 72.1403 114.56 72.2523 114.512C72.3723 114.456 72.4323 114.368 72.4323 114.248C72.4323 114.144 72.3883 114.06 72.3003 113.996C72.2123 113.932 72.0123 113.86 71.7003 113.78L71.3043 113.684C70.7283 113.548 70.2963 113.308 70.0083 112.964C69.7203 112.612 69.5843 112.196 69.6003 111.716C69.6083 111.436 69.6683 111.184 69.7803 110.96C69.9003 110.728 70.0603 110.532 70.2603 110.372C70.4683 110.212 70.7123 110.088 70.9923 110C71.2723 109.912 71.5763 109.868 71.9043 109.868C72.8323 109.868 73.5363 110.2 74.0163 110.864L72.8403 111.836C72.7043 111.66 72.5563 111.536 72.3963 111.464C72.2363 111.392 72.0683 111.356 71.8923 111.356C71.7803 111.356 71.6683 111.38 71.5563 111.428C71.4523 111.476 71.4003 111.556 71.4003 111.668C71.4003 111.732 71.4243 111.804 71.4723 111.884C71.5283 111.964 71.6723 112.036 71.9043 112.1L72.4563 112.244C73.0003 112.388 73.4283 112.608 73.7403 112.904C74.0603 113.192 74.2203 113.604 74.2203 114.14C74.2203 114.428 74.1603 114.696 74.0403 114.944C73.9203 115.184 73.7523 115.392 73.5363 115.568C73.3283 115.744 73.0803 115.884 72.7923 115.988C72.5123 116.084 72.2083 116.132 71.8803 116.132ZM76.2475 109.184C76.0955 109.184 75.9515 109.156 75.8155 109.1C75.6795 109.036 75.5595 108.956 75.4555 108.86C75.3515 108.756 75.2675 108.636 75.2035 108.5C75.1475 108.364 75.1195 108.216 75.1195 108.056C75.1195 107.904 75.1475 107.76 75.2035 107.624C75.2675 107.48 75.3515 107.36 75.4555 107.264C75.5595 107.16 75.6795 107.08 75.8155 107.024C75.9515 106.96 76.0955 106.928 76.2475 106.928C76.4075 106.928 76.5555 106.96 76.6915 107.024C76.8355 107.08 76.9555 107.16 77.0515 107.264C77.1555 107.36 77.2355 107.48 77.2915 107.624C77.3555 107.76 77.3875 107.904 77.3875 108.056C77.3875 108.216 77.3555 108.364 77.2915 108.5C77.2355 108.636 77.1555 108.756 77.0515 108.86C76.9555 108.956 76.8355 109.036 76.6915 109.1C76.5555 109.156 76.4075 109.184 76.2475 109.184ZM75.3475 110H77.1595V116H75.3475V110ZM81.4362 116.132C81.0042 116.132 80.5962 116.052 80.2122 115.892C79.8282 115.732 79.4922 115.512 79.2042 115.232C78.9242 114.944 78.7002 114.612 78.5322 114.236C78.3642 113.852 78.2802 113.44 78.2802 113C78.2802 112.56 78.3642 112.152 78.5322 111.776C78.7002 111.392 78.9242 111.06 79.2042 110.78C79.4922 110.492 79.8282 110.268 80.2122 110.108C80.5962 109.948 81.0042 109.868 81.4362 109.868C81.8682 109.868 82.2762 109.948 82.6602 110.108C83.0442 110.268 83.3762 110.492 83.6562 110.78C83.9442 111.06 84.1722 111.392 84.3402 111.776C84.5082 112.152 84.5922 112.56 84.5922 113C84.5922 113.44 84.5082 113.852 84.3402 114.236C84.1722 114.612 83.9442 114.944 83.6562 115.232C83.3762 115.512 83.0442 115.732 82.6602 115.892C82.2762 116.052 81.8682 116.132 81.4362 116.132ZM81.4362 114.44C81.8202 114.44 82.1362 114.308 82.3842 114.044C82.6402 113.78 82.7682 113.432 82.7682 113C82.7682 112.568 82.6402 112.22 82.3842 111.956C82.1362 111.692 81.8202 111.56 81.4362 111.56C81.0522 111.56 80.7322 111.692 80.4762 111.956C80.2282 112.22 80.1042 112.568 80.1042 113C80.1042 113.432 80.2282 113.78 80.4762 114.044C80.7322 114.308 81.0522 114.44 81.4362 114.44ZM85.7069 110H87.5189V110.612C87.6629 110.404 87.8789 110.228 88.1669 110.084C88.4549 109.94 88.7949 109.868 89.1869 109.868C89.5549 109.868 89.8829 109.936 90.1709 110.072C90.4589 110.2 90.7029 110.38 90.9029 110.612C91.1029 110.844 91.2549 111.124 91.3589 111.452C91.4629 111.78 91.5149 112.14 91.5149 112.532V116H89.7029V112.844C89.7029 112.428 89.6229 112.104 89.4629 111.872C89.3029 111.632 89.0589 111.512 88.7309 111.512C88.3869 111.512 88.0989 111.64 87.8669 111.896C87.6349 112.144 87.5189 112.54 87.5189 113.084V116H85.7069V110ZM95.3496 116.132C94.9576 116.132 94.5896 116.048 94.2456 115.88C93.9096 115.712 93.6176 115.488 93.3696 115.208C93.1216 114.92 92.9256 114.588 92.7816 114.212C92.6376 113.828 92.5656 113.424 92.5656 113C92.5656 112.576 92.6376 112.176 92.7816 111.8C92.9256 111.416 93.1216 111.084 93.3696 110.804C93.6176 110.516 93.9096 110.288 94.2456 110.12C94.5896 109.952 94.9576 109.868 95.3496 109.868C95.5496 109.868 95.7336 109.892 95.9016 109.94C96.0776 109.98 96.2336 110.036 96.3696 110.108C96.5136 110.18 96.6336 110.26 96.7296 110.348C96.8336 110.436 96.9176 110.52 96.9816 110.6V110H98.7936V116H96.9816V115.4C96.9176 115.48 96.8336 115.564 96.7296 115.652C96.6336 115.74 96.5136 115.82 96.3696 115.892C96.2336 115.964 96.0776 116.02 95.9016 116.06C95.7336 116.108 95.5496 116.132 95.3496 116.132ZM95.7576 114.488C96.1656 114.488 96.4936 114.348 96.7416 114.068C96.9976 113.788 97.1256 113.432 97.1256 113C97.1256 112.568 96.9976 112.212 96.7416 111.932C96.4936 111.652 96.1656 111.512 95.7576 111.512C95.3496 111.512 95.0176 111.652 94.7616 111.932C94.5136 112.212 94.3896 112.568 94.3896 113C94.3896 113.432 94.5136 113.788 94.7616 114.068C95.0176 114.348 95.3496 114.488 95.7576 114.488ZM100.285 107H102.097V116H100.285V107ZM28.0775 124.48L30.7295 128.152L33.4055 124.48H35.1455V133H33.2255V127.756L30.7415 131.188L28.2455 127.744V133H26.3375V124.48H28.0775ZM39.0586 133.132C38.6666 133.132 38.2986 133.048 37.9546 132.88C37.6186 132.712 37.3266 132.488 37.0786 132.208C36.8306 131.92 36.6346 131.588 36.4906 131.212C36.3466 130.828 36.2746 130.424 36.2746 130C36.2746 129.576 36.3466 129.176 36.4906 128.8C36.6346 128.416 36.8306 128.084 37.0786 127.804C37.3266 127.516 37.6186 127.288 37.9546 127.12C38.2986 126.952 38.6666 126.868 39.0586 126.868C39.2586 126.868 39.4426 126.892 39.6106 126.94C39.7866 126.98 39.9426 127.036 40.0786 127.108C40.2226 127.18 40.3426 127.26 40.4386 127.348C40.5426 127.436 40.6266 127.52 40.6906 127.6V127H42.5026V133H40.6906V132.4C40.6266 132.48 40.5426 132.564 40.4386 132.652C40.3426 132.74 40.2226 132.82 40.0786 132.892C39.9426 132.964 39.7866 133.02 39.6106 133.06C39.4426 133.108 39.2586 133.132 39.0586 133.132ZM39.4666 131.488C39.8746 131.488 40.2026 131.348 40.4506 131.068C40.7066 130.788 40.8346 130.432 40.8346 130C40.8346 129.568 40.7066 129.212 40.4506 128.932C40.2026 128.652 39.8746 128.512 39.4666 128.512C39.0586 128.512 38.7266 128.652 38.4706 128.932C38.2226 129.212 38.0986 129.568 38.0986 130C38.0986 130.432 38.2226 130.788 38.4706 131.068C38.7266 131.348 39.0586 131.488 39.4666 131.488ZM43.994 127H45.806V127.9C45.902 127.636 46.078 127.408 46.334 127.216C46.598 127.024 46.898 126.928 47.234 126.928C47.322 126.928 47.414 126.932 47.51 126.94C47.606 126.948 47.71 126.968 47.822 127V128.836C47.686 128.788 47.554 128.752 47.426 128.728C47.298 128.704 47.162 128.692 47.018 128.692C46.626 128.692 46.326 128.828 46.118 129.1C45.91 129.372 45.806 129.724 45.806 130.156V133H43.994V127ZM50.6458 130.324V133H48.8338V124H50.6458V129.148L52.3978 127H54.5458L52.3378 129.712L55.0738 133H52.8778L50.6458 130.324ZM58.0174 133.132C57.5774 133.132 57.1614 133.06 56.7694 132.916C56.3854 132.772 56.0494 132.564 55.7614 132.292C55.4734 132.02 55.2454 131.692 55.0774 131.308C54.9094 130.916 54.8254 130.48 54.8254 130C54.8254 129.552 54.9014 129.14 55.0534 128.764C55.2134 128.38 55.4334 128.048 55.7134 127.768C56.0014 127.488 56.3374 127.268 56.7214 127.108C57.1054 126.948 57.5254 126.868 57.9814 126.868C58.3734 126.868 58.7494 126.932 59.1094 127.06C59.4774 127.18 59.7974 127.364 60.0694 127.612C60.3414 127.852 60.5574 128.156 60.7174 128.524C60.8854 128.884 60.9694 129.308 60.9694 129.796C60.9694 129.876 60.9654 129.968 60.9574 130.072C60.9574 130.168 60.9494 130.288 60.9334 130.432H56.5774C56.6334 130.792 56.8054 131.06 57.0934 131.236C57.3814 131.404 57.6974 131.488 58.0414 131.488C58.3934 131.488 58.6934 131.42 58.9414 131.284C59.1974 131.14 59.3814 130.98 59.4934 130.804L60.8374 131.812C60.5574 132.212 60.1734 132.532 59.6854 132.772C59.2054 133.012 58.6494 133.132 58.0174 133.132ZM59.1694 129.244C59.0894 128.924 58.9294 128.696 58.6894 128.56C58.4494 128.416 58.1974 128.344 57.9334 128.344C57.7974 128.344 57.6614 128.36 57.5254 128.392C57.3894 128.424 57.2614 128.476 57.1414 128.548C57.0214 128.62 56.9134 128.712 56.8174 128.824C56.7294 128.936 56.6654 129.076 56.6254 129.244H59.1694ZM65.054 133.072C64.718 133.072 64.402 133.028 64.106 132.94C63.818 132.844 63.566 132.704 63.35 132.52C63.134 132.328 62.962 132.092 62.834 131.812C62.706 131.524 62.642 131.188 62.642 130.804V128.572H61.442V127H62.642V125.332H64.454V127H66.134V128.572H64.454V130.432C64.454 130.792 64.534 131.052 64.694 131.212C64.854 131.372 65.114 131.452 65.474 131.452C65.61 131.452 65.73 131.444 65.834 131.428C65.938 131.412 66.038 131.384 66.134 131.344V132.952C65.998 132.992 65.842 133.02 65.666 133.036C65.498 133.06 65.294 133.072 65.054 133.072ZM71.8705 124.48L74.5225 128.152L77.1985 124.48H78.9385V133H77.0185V127.756L74.5345 131.188L72.0385 127.744V133H70.1305V124.48H71.8705ZM82.8516 133.132C82.4596 133.132 82.0916 133.048 81.7476 132.88C81.4116 132.712 81.1196 132.488 80.8716 132.208C80.6236 131.92 80.4276 131.588 80.2836 131.212C80.1396 130.828 80.0676 130.424 80.0676 130C80.0676 129.576 80.1396 129.176 80.2836 128.8C80.4276 128.416 80.6236 128.084 80.8716 127.804C81.1196 127.516 81.4116 127.288 81.7476 127.12C82.0916 126.952 82.4596 126.868 82.8516 126.868C83.0516 126.868 83.2356 126.892 83.4036 126.94C83.5796 126.98 83.7356 127.036 83.8716 127.108C84.0156 127.18 84.1356 127.26 84.2316 127.348C84.3356 127.436 84.4196 127.52 84.4836 127.6V127H86.2956V133H84.4836V132.4C84.4196 132.48 84.3356 132.564 84.2316 132.652C84.1356 132.74 84.0156 132.82 83.8716 132.892C83.7356 132.964 83.5796 133.02 83.4036 133.06C83.2356 133.108 83.0516 133.132 82.8516 133.132ZM83.2596 131.488C83.6676 131.488 83.9956 131.348 84.2436 131.068C84.4996 130.788 84.6276 130.432 84.6276 130C84.6276 129.568 84.4996 129.212 84.2436 128.932C83.9956 128.652 83.6676 128.512 83.2596 128.512C82.8516 128.512 82.5196 128.652 82.2636 128.932C82.0156 129.212 81.8916 129.568 81.8916 130C81.8916 130.432 82.0156 130.788 82.2636 131.068C82.5196 131.348 82.8516 131.488 83.2596 131.488ZM89.599 130.324V133H87.787V124H89.599V129.148L91.351 127H93.499L91.291 129.712L94.027 133H91.831L89.599 130.324ZM96.9705 133.132C96.5305 133.132 96.1145 133.06 95.7225 132.916C95.3385 132.772 95.0025 132.564 94.7145 132.292C94.4265 132.02 94.1985 131.692 94.0305 131.308C93.8625 130.916 93.7785 130.48 93.7785 130C93.7785 129.552 93.8545 129.14 94.0065 128.764C94.1665 128.38 94.3865 128.048 94.6665 127.768C94.9545 127.488 95.2905 127.268 95.6745 127.108C96.0585 126.948 96.4785 126.868 96.9345 126.868C97.3265 126.868 97.7025 126.932 98.0625 127.06C98.4305 127.18 98.7505 127.364 99.0225 127.612C99.2945 127.852 99.5105 128.156 99.6705 128.524C99.8385 128.884 99.9225 129.308 99.9225 129.796C99.9225 129.876 99.9185 129.968 99.9105 130.072C99.9105 130.168 99.9025 130.288 99.8865 130.432H95.5305C95.5865 130.792 95.7585 131.06 96.0465 131.236C96.3345 131.404 96.6505 131.488 96.9945 131.488C97.3465 131.488 97.6465 131.42 97.8945 131.284C98.1505 131.14 98.3345 130.98 98.4465 130.804L99.7905 131.812C99.5105 132.212 99.1265 132.532 98.6385 132.772C98.1585 133.012 97.6025 133.132 96.9705 133.132ZM98.1225 129.244C98.0425 128.924 97.8825 128.696 97.6425 128.56C97.4025 128.416 97.1505 128.344 96.8865 128.344C96.7505 128.344 96.6145 128.36 96.4785 128.392C96.3425 128.424 96.2145 128.476 96.0945 128.548C95.9745 128.62 95.8665 128.712 95.7705 128.824C95.6825 128.936 95.6185 129.076 95.5785 129.244H98.1225ZM101.064 127H102.876V127.9C102.972 127.636 103.148 127.408 103.404 127.216C103.668 127.024 103.968 126.928 104.304 126.928C104.392 126.928 104.484 126.932 104.58 126.94C104.676 126.948 104.78 126.968 104.892 127V128.836C104.756 128.788 104.624 128.752 104.496 128.728C104.368 128.704 104.232 128.692 104.088 128.692C103.696 128.692 103.396 128.828 103.188 129.1C102.98 129.372 102.876 129.724 102.876 130.156V133H101.064V127ZM107.839 133.132C107.311 133.132 106.831 133.044 106.399 132.868C105.975 132.692 105.623 132.42 105.343 132.052L106.543 130.96C106.679 131.16 106.859 131.316 107.083 131.428C107.307 131.532 107.559 131.584 107.839 131.584C107.975 131.584 108.099 131.56 108.211 131.512C108.331 131.456 108.391 131.368 108.391 131.248C108.391 131.144 108.347 131.06 108.259 130.996C108.171 130.932 107.971 130.86 107.659 130.78L107.263 130.684C106.687 130.548 106.255 130.308 105.967 129.964C105.679 129.612 105.543 129.196 105.559 128.716C105.567 128.436 105.627 128.184 105.739 127.96C105.859 127.728 106.019 127.532 106.219 127.372C106.427 127.212 106.671 127.088 106.951 127C107.231 126.912 107.535 126.868 107.863 126.868C108.791 126.868 109.495 127.2 109.975 127.864L108.799 128.836C108.663 128.66 108.515 128.536 108.355 128.464C108.195 128.392 108.027 128.356 107.851 128.356C107.739 128.356 107.627 128.38 107.515 128.428C107.411 128.476 107.359 128.556 107.359 128.668C107.359 128.732 107.383 128.804 107.431 128.884C107.487 128.964 107.631 129.036 107.863 129.1L108.415 129.244C108.959 129.388 109.387 129.608 109.699 129.904C110.019 130.192 110.179 130.604 110.179 131.14C110.179 131.428 110.119 131.696 109.999 131.944C109.879 132.184 109.711 132.392 109.495 132.568C109.287 132.744 109.039 132.884 108.751 132.988C108.471 133.084 108.167 133.132 107.839 133.132Z" fill="#24292E"/> +<path d="M157.587 107.48L160.743 111.728L163.923 107.48H164.931V116H163.827V109.376L160.755 113.504L157.683 109.376V116H156.567V107.48H157.587ZM169.599 116.12C169.143 116.12 168.723 116.04 168.339 115.88C167.955 115.712 167.623 115.488 167.343 115.208C167.063 114.928 166.843 114.6 166.683 114.224C166.531 113.84 166.455 113.432 166.455 113C166.455 112.568 166.531 112.164 166.683 111.788C166.843 111.404 167.063 111.072 167.343 110.792C167.623 110.512 167.955 110.292 168.339 110.132C168.723 109.964 169.143 109.88 169.599 109.88C170.047 109.88 170.463 109.964 170.847 110.132C171.231 110.292 171.563 110.512 171.843 110.792C172.123 111.072 172.339 111.404 172.491 111.788C172.651 112.164 172.731 112.568 172.731 113C172.731 113.432 172.651 113.84 172.491 114.224C172.339 114.6 172.123 114.928 171.843 115.208C171.563 115.488 171.231 115.712 170.847 115.88C170.463 116.04 170.047 116.12 169.599 116.12ZM169.599 115.16C169.911 115.16 170.195 115.104 170.451 114.992C170.707 114.88 170.923 114.728 171.099 114.536C171.283 114.336 171.423 114.108 171.519 113.852C171.623 113.588 171.675 113.304 171.675 113C171.675 112.704 171.623 112.424 171.519 112.16C171.423 111.896 171.283 111.668 171.099 111.476C170.923 111.276 170.707 111.12 170.451 111.008C170.195 110.896 169.911 110.84 169.599 110.84C169.287 110.84 169.003 110.896 168.747 111.008C168.491 111.12 168.271 111.276 168.087 111.476C167.903 111.668 167.759 111.896 167.655 112.16C167.559 112.424 167.511 112.704 167.511 113C167.511 113.304 167.559 113.588 167.655 113.852C167.759 114.108 167.903 114.336 168.087 114.536C168.271 114.728 168.491 114.88 168.747 114.992C169.003 115.104 169.287 115.16 169.599 115.16ZM174.212 110H175.244V111.164C175.3 110.972 175.388 110.8 175.508 110.648C175.628 110.496 175.764 110.368 175.916 110.264C176.068 110.16 176.228 110.08 176.396 110.024C176.572 109.968 176.748 109.94 176.924 109.94C177.084 109.94 177.24 109.956 177.392 109.988V111.056C177.296 111.016 177.204 110.992 177.116 110.984C177.028 110.968 176.932 110.96 176.828 110.96C176.636 110.96 176.444 111.004 176.252 111.092C176.068 111.172 175.9 111.296 175.748 111.464C175.604 111.632 175.484 111.848 175.388 112.112C175.292 112.368 175.244 112.672 175.244 113.024V116H174.212V110ZM181.036 116.12C180.572 116.12 180.148 116.04 179.764 115.88C179.38 115.72 179.052 115.5 178.78 115.22C178.508 114.94 178.296 114.612 178.144 114.236C178 113.852 177.928 113.44 177.928 113C177.928 112.56 178.004 112.152 178.156 111.776C178.308 111.392 178.52 111.06 178.792 110.78C179.072 110.5 179.404 110.28 179.788 110.12C180.172 109.96 180.592 109.88 181.048 109.88C181.44 109.88 181.808 109.948 182.152 110.084C182.496 110.212 182.796 110.408 183.052 110.672C183.316 110.928 183.524 111.244 183.676 111.62C183.828 111.988 183.904 112.412 183.904 112.892C183.904 112.948 183.904 113 183.904 113.048C183.904 113.088 183.9 113.14 183.892 113.204H178.972C178.98 113.484 179.036 113.744 179.14 113.984C179.252 114.224 179.396 114.432 179.572 114.608C179.756 114.784 179.972 114.924 180.22 115.028C180.476 115.124 180.752 115.172 181.048 115.172C181.512 115.172 181.892 115.08 182.188 114.896C182.492 114.704 182.736 114.448 182.92 114.128L183.736 114.692C183.464 115.132 183.1 115.48 182.644 115.736C182.196 115.992 181.66 116.12 181.036 116.12ZM182.848 112.364C182.808 112.116 182.732 111.896 182.62 111.704C182.516 111.512 182.38 111.348 182.212 111.212C182.052 111.076 181.868 110.972 181.66 110.9C181.452 110.828 181.236 110.792 181.012 110.792C180.788 110.792 180.568 110.828 180.352 110.9C180.136 110.972 179.94 111.076 179.764 111.212C179.588 111.34 179.436 111.504 179.308 111.704C179.18 111.896 179.092 112.116 179.044 112.364H182.848ZM190.939 116.12C190.483 116.12 190.063 116.04 189.679 115.88C189.295 115.72 188.963 115.5 188.683 115.22C188.403 114.932 188.183 114.6 188.023 114.224C187.871 113.84 187.795 113.432 187.795 113C187.795 112.568 187.871 112.164 188.023 111.788C188.183 111.404 188.403 111.072 188.683 110.792C188.963 110.504 189.295 110.28 189.679 110.12C190.063 109.96 190.483 109.88 190.939 109.88C191.563 109.88 192.115 110.028 192.595 110.324C193.075 110.62 193.447 111.008 193.711 111.488L192.811 111.992C192.643 111.648 192.395 111.372 192.067 111.164C191.747 110.948 191.371 110.84 190.939 110.84C190.627 110.84 190.343 110.896 190.087 111.008C189.831 111.12 189.607 111.276 189.415 111.476C189.231 111.668 189.087 111.896 188.983 112.16C188.887 112.424 188.839 112.704 188.839 113C188.839 113.304 188.887 113.588 188.983 113.852C189.087 114.108 189.231 114.336 189.415 114.536C189.607 114.728 189.831 114.88 190.087 114.992C190.343 115.104 190.627 115.16 190.939 115.16C191.371 115.16 191.747 115.056 192.067 114.848C192.395 114.632 192.643 114.352 192.811 114.008L193.711 114.512C193.447 114.992 193.075 115.38 192.595 115.676C192.115 115.972 191.563 116.12 190.939 116.12ZM197.712 116.12C197.256 116.12 196.836 116.04 196.452 115.88C196.068 115.712 195.736 115.488 195.456 115.208C195.176 114.928 194.956 114.6 194.796 114.224C194.644 113.84 194.568 113.432 194.568 113C194.568 112.568 194.644 112.164 194.796 111.788C194.956 111.404 195.176 111.072 195.456 110.792C195.736 110.512 196.068 110.292 196.452 110.132C196.836 109.964 197.256 109.88 197.712 109.88C198.16 109.88 198.576 109.964 198.96 110.132C199.344 110.292 199.676 110.512 199.956 110.792C200.236 111.072 200.452 111.404 200.604 111.788C200.764 112.164 200.844 112.568 200.844 113C200.844 113.432 200.764 113.84 200.604 114.224C200.452 114.6 200.236 114.928 199.956 115.208C199.676 115.488 199.344 115.712 198.96 115.88C198.576 116.04 198.16 116.12 197.712 116.12ZM197.712 115.16C198.024 115.16 198.308 115.104 198.564 114.992C198.82 114.88 199.036 114.728 199.212 114.536C199.396 114.336 199.536 114.108 199.632 113.852C199.736 113.588 199.788 113.304 199.788 113C199.788 112.704 199.736 112.424 199.632 112.16C199.536 111.896 199.396 111.668 199.212 111.476C199.036 111.276 198.82 111.12 198.564 111.008C198.308 110.896 198.024 110.84 197.712 110.84C197.4 110.84 197.116 110.896 196.86 111.008C196.604 111.12 196.384 111.276 196.2 111.476C196.016 111.668 195.872 111.896 195.768 112.16C195.672 112.424 195.624 112.704 195.624 113C195.624 113.304 195.672 113.588 195.768 113.852C195.872 114.108 196.016 114.336 196.2 114.536C196.384 114.728 196.604 114.88 196.86 114.992C197.116 115.104 197.4 115.16 197.712 115.16ZM210.054 112.472C210.054 111.984 209.954 111.588 209.754 111.284C209.554 110.98 209.258 110.828 208.866 110.828C208.386 110.828 207.994 111.016 207.69 111.392C207.394 111.768 207.238 112.28 207.222 112.928V116H206.19V112.472C206.19 111.984 206.09 111.588 205.89 111.284C205.698 110.98 205.406 110.828 205.014 110.828C204.526 110.828 204.126 111.024 203.814 111.416C203.51 111.808 203.358 112.344 203.358 113.024V116H202.326V110H203.358V110.924C203.534 110.604 203.778 110.352 204.09 110.168C204.402 109.976 204.762 109.88 205.17 109.88C205.618 109.88 205.998 109.996 206.31 110.228C206.63 110.452 206.866 110.764 207.018 111.164C207.178 110.772 207.43 110.46 207.774 110.228C208.126 109.996 208.53 109.88 208.986 109.88C209.314 109.88 209.606 109.94 209.862 110.06C210.126 110.172 210.346 110.336 210.522 110.552C210.706 110.76 210.846 111.016 210.942 111.32C211.038 111.616 211.086 111.948 211.086 112.316V116H210.054V112.472ZM213.471 108.392C213.263 108.392 213.087 108.324 212.943 108.188C212.799 108.044 212.727 107.868 212.727 107.66C212.727 107.46 212.799 107.288 212.943 107.144C213.087 107 213.263 106.928 213.471 106.928C213.679 106.928 213.851 107 213.987 107.144C214.123 107.288 214.191 107.46 214.191 107.66C214.191 107.868 214.123 108.044 213.987 108.188C213.851 108.324 213.679 108.392 213.471 108.392ZM212.943 110H213.975V116H212.943V110ZM215.931 110H216.963V110.924C217.171 110.564 217.443 110.3 217.779 110.132C218.115 109.964 218.479 109.88 218.871 109.88C219.207 109.88 219.515 109.936 219.795 110.048C220.075 110.16 220.311 110.324 220.503 110.54C220.703 110.748 220.859 111.004 220.971 111.308C221.083 111.604 221.139 111.936 221.139 112.304V116H220.119V112.46C220.119 111.956 219.987 111.56 219.723 111.272C219.467 110.976 219.127 110.828 218.703 110.828C218.463 110.828 218.235 110.876 218.019 110.972C217.811 111.068 217.627 111.212 217.467 111.404C217.315 111.588 217.191 111.816 217.095 112.088C217.007 112.36 216.963 112.672 216.963 113.024V116H215.931V110ZM225.613 115.028C225.909 115.028 226.181 114.976 226.429 114.872C226.685 114.768 226.901 114.624 227.077 114.44C227.253 114.248 227.389 114.024 227.485 113.768C227.589 113.512 227.641 113.232 227.641 112.928C227.641 112.632 227.589 112.356 227.485 112.1C227.389 111.836 227.253 111.612 227.077 111.428C226.901 111.244 226.685 111.1 226.429 110.996C226.181 110.884 225.909 110.828 225.613 110.828C225.309 110.828 225.033 110.884 224.785 110.996C224.537 111.1 224.325 111.244 224.149 111.428C223.973 111.612 223.833 111.836 223.729 112.1C223.633 112.356 223.585 112.632 223.585 112.928C223.585 113.232 223.633 113.512 223.729 113.768C223.833 114.024 223.973 114.248 224.149 114.44C224.325 114.624 224.537 114.768 224.785 114.872C225.033 114.976 225.309 115.028 225.613 115.028ZM225.553 118.628C224.905 118.628 224.337 118.508 223.849 118.268C223.361 118.028 222.989 117.74 222.733 117.404L223.453 116.684C223.693 116.988 223.985 117.232 224.329 117.416C224.681 117.6 225.089 117.692 225.553 117.692C225.809 117.692 226.057 117.652 226.297 117.572C226.537 117.492 226.749 117.364 226.933 117.188C227.125 117.02 227.277 116.804 227.389 116.54C227.501 116.284 227.557 115.976 227.557 115.616V114.932C227.349 115.236 227.061 115.488 226.693 115.688C226.325 115.888 225.917 115.988 225.469 115.988C225.053 115.988 224.665 115.912 224.305 115.76C223.945 115.6 223.633 115.384 223.369 115.112C223.105 114.832 222.897 114.508 222.745 114.14C222.601 113.764 222.529 113.36 222.529 112.928C222.529 112.504 222.601 112.108 222.745 111.74C222.897 111.364 223.105 111.04 223.369 110.768C223.633 110.488 223.945 110.272 224.305 110.12C224.665 109.96 225.053 109.88 225.469 109.88C225.917 109.88 226.325 109.98 226.693 110.18C227.061 110.372 227.349 110.62 227.557 110.924V110H228.589V115.652C228.589 116.156 228.509 116.592 228.349 116.96C228.197 117.336 227.985 117.644 227.713 117.884C227.441 118.132 227.121 118.316 226.753 118.436C226.385 118.564 225.985 118.628 225.553 118.628ZM180.143 133.12C179.607 133.12 179.127 133.008 178.703 132.784C178.279 132.552 177.975 132.2 177.791 131.728L178.631 131.26C178.743 131.564 178.939 131.8 179.219 131.968C179.507 132.128 179.819 132.208 180.155 132.208C180.443 132.208 180.687 132.14 180.887 132.004C181.095 131.86 181.199 131.66 181.199 131.404C181.199 131.188 181.123 131.008 180.971 130.864C180.819 130.72 180.547 130.588 180.155 130.468L179.555 130.276C179.059 130.132 178.683 129.912 178.427 129.616C178.179 129.312 178.055 128.948 178.055 128.524C178.055 128.268 178.107 128.04 178.211 127.84C178.323 127.632 178.471 127.46 178.655 127.324C178.847 127.18 179.067 127.072 179.315 127C179.563 126.92 179.831 126.88 180.119 126.88C180.567 126.88 180.959 126.972 181.295 127.156C181.631 127.332 181.899 127.588 182.099 127.924L181.331 128.452C181.195 128.26 181.023 128.1 180.815 127.972C180.615 127.836 180.371 127.768 180.083 127.768C179.827 127.768 179.595 127.832 179.387 127.96C179.187 128.088 179.087 128.264 179.087 128.488C179.087 128.672 179.143 128.836 179.255 128.98C179.375 129.124 179.603 129.248 179.939 129.352L180.599 129.556C181.119 129.716 181.519 129.936 181.799 130.216C182.087 130.496 182.231 130.864 182.231 131.32C182.231 131.608 182.179 131.864 182.075 132.088C181.971 132.312 181.823 132.5 181.631 132.652C181.447 132.804 181.227 132.92 180.971 133C180.715 133.08 180.439 133.12 180.143 133.12ZM186.398 133.12C185.942 133.12 185.522 133.04 185.138 132.88C184.754 132.712 184.422 132.488 184.142 132.208C183.862 131.928 183.642 131.6 183.482 131.224C183.33 130.84 183.254 130.432 183.254 130C183.254 129.568 183.33 129.164 183.482 128.788C183.642 128.404 183.862 128.072 184.142 127.792C184.422 127.512 184.754 127.292 185.138 127.132C185.522 126.964 185.942 126.88 186.398 126.88C186.846 126.88 187.262 126.964 187.646 127.132C188.03 127.292 188.362 127.512 188.642 127.792C188.922 128.072 189.138 128.404 189.29 128.788C189.45 129.164 189.53 129.568 189.53 130C189.53 130.432 189.45 130.84 189.29 131.224C189.138 131.6 188.922 131.928 188.642 132.208C188.362 132.488 188.03 132.712 187.646 132.88C187.262 133.04 186.846 133.12 186.398 133.12ZM186.398 132.16C186.71 132.16 186.994 132.104 187.25 131.992C187.506 131.88 187.722 131.728 187.898 131.536C188.082 131.336 188.222 131.108 188.318 130.852C188.422 130.588 188.474 130.304 188.474 130C188.474 129.704 188.422 129.424 188.318 129.16C188.222 128.896 188.082 128.668 187.898 128.476C187.722 128.276 187.506 128.12 187.25 128.008C186.994 127.896 186.71 127.84 186.398 127.84C186.086 127.84 185.802 127.896 185.546 128.008C185.29 128.12 185.07 128.276 184.886 128.476C184.702 128.668 184.558 128.896 184.454 129.16C184.358 129.424 184.31 129.704 184.31 130C184.31 130.304 184.358 130.588 184.454 130.852C184.558 131.108 184.702 131.336 184.886 131.536C185.07 131.728 185.29 131.88 185.546 131.992C185.802 132.104 186.086 132.16 186.398 132.16ZM193.675 133.12C193.219 133.12 192.799 133.04 192.415 132.88C192.031 132.712 191.699 132.488 191.419 132.208C191.139 131.928 190.919 131.6 190.759 131.224C190.607 130.84 190.531 130.432 190.531 130C190.531 129.568 190.607 129.164 190.759 128.788C190.919 128.404 191.139 128.072 191.419 127.792C191.699 127.512 192.031 127.292 192.415 127.132C192.799 126.964 193.219 126.88 193.675 126.88C194.123 126.88 194.539 126.964 194.923 127.132C195.307 127.292 195.639 127.512 195.919 127.792C196.199 128.072 196.415 128.404 196.567 128.788C196.727 129.164 196.807 129.568 196.807 130C196.807 130.432 196.727 130.84 196.567 131.224C196.415 131.6 196.199 131.928 195.919 132.208C195.639 132.488 195.307 132.712 194.923 132.88C194.539 133.04 194.123 133.12 193.675 133.12ZM193.675 132.16C193.987 132.16 194.271 132.104 194.527 131.992C194.783 131.88 194.999 131.728 195.175 131.536C195.359 131.336 195.499 131.108 195.595 130.852C195.699 130.588 195.751 130.304 195.751 130C195.751 129.704 195.699 129.424 195.595 129.16C195.499 128.896 195.359 128.668 195.175 128.476C194.999 128.276 194.783 128.12 194.527 128.008C194.271 127.896 193.987 127.84 193.675 127.84C193.363 127.84 193.079 127.896 192.823 128.008C192.567 128.12 192.347 128.276 192.163 128.476C191.979 128.668 191.835 128.896 191.731 129.16C191.635 129.424 191.587 129.704 191.587 130C191.587 130.304 191.635 130.588 191.731 130.852C191.835 131.108 191.979 131.336 192.163 131.536C192.347 131.728 192.567 131.88 192.823 131.992C193.079 132.104 193.363 132.16 193.675 132.16ZM198.288 127H199.32V127.924C199.528 127.564 199.8 127.3 200.136 127.132C200.472 126.964 200.836 126.88 201.228 126.88C201.564 126.88 201.872 126.936 202.152 127.048C202.432 127.16 202.668 127.324 202.86 127.54C203.06 127.748 203.216 128.004 203.328 128.308C203.44 128.604 203.496 128.936 203.496 129.304V133H202.476V129.46C202.476 128.956 202.344 128.56 202.08 128.272C201.824 127.976 201.484 127.828 201.06 127.828C200.82 127.828 200.592 127.876 200.376 127.972C200.168 128.068 199.984 128.212 199.824 128.404C199.672 128.588 199.548 128.816 199.452 129.088C199.364 129.36 199.32 129.672 199.32 130.024V133H198.288V127ZM205.487 127.888V124.48H206.531V127.888L206.327 130.336H205.691L205.487 127.888ZM206.003 133.096C205.755 133.096 205.543 133.008 205.367 132.832C205.199 132.656 205.115 132.444 205.115 132.196C205.115 131.956 205.199 131.748 205.367 131.572C205.543 131.388 205.755 131.296 206.003 131.296C206.251 131.296 206.459 131.388 206.627 131.572C206.803 131.748 206.891 131.956 206.891 132.196C206.891 132.444 206.803 132.656 206.627 132.832C206.459 133.008 206.251 133.096 206.003 133.096Z" fill="#24292E"/> +<defs> +<filter id="filter0_d" x="4" y="5.23883" width="124.525" height="61.374" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> +<feOffset dy="4"/> +<feGaussianBlur stdDeviation="10"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.141176 0 0 0 0 0.160784 0 0 0 0 0.180392 0 0 0 0.25 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> +</filter> +<filter id="filter1_d" x="1" y="48" width="128.4" height="60" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"> +<feFlood flood-opacity="0" result="BackgroundImageFix"/> +<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/> +<feOffset dy="4"/> +<feGaussianBlur stdDeviation="10"/> +<feColorMatrix type="matrix" values="0 0 0 0 0.168627 0 0 0 0 0.443137 0 0 0 0 1 0 0 0 0.25 0"/> +<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/> +<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/> +</filter> +</defs> +</svg> diff --git a/app/images/videos/recovery-onboarding/subtitles-en.vtt b/app/images/videos/recovery-onboarding/subtitles-en.vtt new file mode 100644 index 000000000..c78e8ff15 --- /dev/null +++ b/app/images/videos/recovery-onboarding/subtitles-en.vtt @@ -0,0 +1,116 @@ +WEBVTT + +1 +00:00:00.780 --> 00:00:04.580 +MetaMask is a new way to connect +to sites and applications. + +2 +00:00:04.580 --> 00:00:08.860 +On traditional websites, a central database +or bank is responsible for controlling and + +3 +00:00:08.860 --> 00:00:10.179 +recovering your accounts. + +4 +00:00:10.179 --> 00:00:15.050 +But on MetaMask, all of the power belongs +to the holder of a master key. + +5 +00:00:15.050 --> 00:00:18.460 +Whoever holds the key, controls the accounts. + +6 +00:00:18.460 --> 00:00:21.110 +Your secret recovery phrase +is your "master key". + +7 +00:00:21.110 --> 00:00:26.070 +It's a series of 12 words that are generated +when you first set up MetaMask, which allow + +8 +00:00:26.070 --> 00:00:30.120 +you to recover your wallet and funds if you +ever lose access. + +9 +00:00:30.120 --> 00:00:33.451 +It's important that you secure +your wallet by keeping your + +10 +00:00:33.451 --> 00:00:37.510 +secret recovery phrase +very safe, and very secret. + +11 +00:00:37.510 --> 00:00:41.429 +If anyone gets access to it, they will have +the "master key" to your wallet and can + +12 +00:00:41.429 --> 00:00:45.190 +freely access and take all of your funds. + +13 +00:00:45.190 --> 00:00:50.109 +To secure your MetaMask wallet you'll want +to safely save your secret recovery phrase. + +14 +00:00:50.109 --> 00:00:54.930 +You can write it down, hide it somewhere, +put it in a safe deposit box + +15 +00:00:54.930 --> 00:00:57.729 +or use a secure password manager. + +16 +00:00:57.729 --> 00:01:01.050 +Some users even engrave their +phrase onto a metal plate! + +17 +00:01:01.050 --> 00:01:04.440 +Nobody, not even the team +at MetaMask, can help you + +18 +00:01:04.440 --> 00:01:07.820 +recover your wallet if you lose +your secret recovery phrase. + +19 +00:01:07.820 --> 00:01:12.072 +If you haven't written down your secret recovery +phrase and stored it somewhere safe, + +20 +00:01:12.072 --> 00:01:15.492 +do it now. We'll wait. + +21 +00:01:15.500 --> 00:01:20.780 +And remember, never share your secret recovery +phrase with anyone: not even us. + +22 +00:01:20.780 --> 00:01:24.910 +If anyone ever asks you for it, +they're trying to scam you. + +23 +00:01:24.910 --> 00:01:26.250 +That's it! + +24 +00:01:26.250 --> 00:01:31.020 +Now you know what a secret recovery phrase +is and how to keep your wallet safe and secure. + diff --git a/app/images/videos/recovery-onboarding/video.webm b/app/images/videos/recovery-onboarding/video.webm new file mode 100644 index 000000000..a0d5cedeb Binary files /dev/null and b/app/images/videos/recovery-onboarding/video.webm differ diff --git a/app/manifest/_base.json b/app/manifest/_base.json index a5969f337..437ef1d2e 100644 --- a/app/manifest/_base.json +++ b/app/manifest/_base.json @@ -71,6 +71,5 @@ "notifications" ], "short_name": "__MSG_appName__", - "version": "9.5.9", "web_accessible_resources": ["inpage.js", "phishing.html"] } diff --git a/app/scripts/account-import-strategies/account-import-strategies.test.js b/app/scripts/account-import-strategies/account-import-strategies.test.js index e29561639..7886f1717 100644 --- a/app/scripts/account-import-strategies/account-import-strategies.test.js +++ b/app/scripts/account-import-strategies/account-import-strategies.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import { stripHexPrefix } from 'ethereumjs-util'; import accountImporter from '.'; diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index a404a9cd8..236952f61 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -1,6 +1,6 @@ import querystring from 'querystring'; import pump from 'pump'; -import LocalMessageDuplexStream from 'post-message-stream'; +import { WindowPostMessageStream } from '@metamask/post-message-stream'; import ObjectMultiplex from 'obj-multiplex'; import extension from 'extensionizer'; import PortStream from 'extension-port-stream'; @@ -57,7 +57,7 @@ function injectScript(content) { */ async function setupStreams() { // the transport-specific streams for communication between inpage and background - const pageStream = new LocalMessageDuplexStream({ + const pageStream = new WindowPostMessageStream({ name: CONTENT_SCRIPT, target: INPAGE, }); @@ -89,7 +89,7 @@ async function setupStreams() { // TODO:LegacyProvider: Delete // handle legacy provider - const legacyPageStream = new LocalMessageDuplexStream({ + const legacyPageStream = new WindowPostMessageStream({ name: LEGACY_CONTENT_SCRIPT, target: LEGACY_INPAGE, }); diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index 261b735dc..ce92798e0 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -23,6 +23,7 @@ export default class AppStateController extends EventEmitter { timeoutMinutes: 0, connectedStatusPopoverHasBeenShown: true, defaultHomeActiveTabName: null, + browserEnvironment: {}, ...initState, }); this.timer = null; @@ -158,4 +159,12 @@ export default class AppStateController extends EventEmitter { timeoutMinutes * 60 * 1000, ); } + + /** + * Sets the current browser and OS environment + * @returns {void} + */ + setBrowserEnvironment(os, browser) { + this.store.updateState({ browserEnvironment: { os, browser } }); + } } diff --git a/app/scripts/controllers/cached-balances.test.js b/app/scripts/controllers/cached-balances.test.js index 94e86b41a..5ef473110 100644 --- a/app/scripts/controllers/cached-balances.test.js +++ b/app/scripts/controllers/cached-balances.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import sinon from 'sinon'; import { KOVAN_CHAIN_ID } from '../../../shared/constants/network'; import CachedBalancesController from './cached-balances'; diff --git a/app/scripts/controllers/detect-tokens.test.js b/app/scripts/controllers/detect-tokens.test.js index c472c7977..3b5eddd24 100644 --- a/app/scripts/controllers/detect-tokens.test.js +++ b/app/scripts/controllers/detect-tokens.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import sinon from 'sinon'; import { ObservableStore } from '@metamask/obs-store'; import contracts from '@metamask/contract-metadata'; diff --git a/app/scripts/controllers/ens/index.test.js b/app/scripts/controllers/ens/index.test.js index 24197dbd7..c94f73a5d 100644 --- a/app/scripts/controllers/ens/index.test.js +++ b/app/scripts/controllers/ens/index.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import sinon from 'sinon'; import EnsController from '.'; diff --git a/app/scripts/controllers/incoming-transactions.test.js b/app/scripts/controllers/incoming-transactions.test.js index 74aaad78c..347fa7952 100644 --- a/app/scripts/controllers/incoming-transactions.test.js +++ b/app/scripts/controllers/incoming-transactions.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import sinon from 'sinon'; import proxyquire from 'proxyquire'; import nock from 'nock'; diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index cd0fc0bce..a308a7d4b 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import EventEmitter from 'events'; import { ComposedStore, ObservableStore } from '@metamask/obs-store'; import { JsonRpcEngine } from 'json-rpc-engine'; diff --git a/app/scripts/controllers/network/pending-middleware.test.js b/app/scripts/controllers/network/pending-middleware.test.js index 1ce327b22..49e60aaa4 100644 --- a/app/scripts/controllers/network/pending-middleware.test.js +++ b/app/scripts/controllers/network/pending-middleware.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import { txMetaStub } from '../../../../test/stub/tx-meta-stub'; import { createPendingNonceMiddleware, diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index e7b532ba8..19aef453e 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -43,6 +43,7 @@ export default class PreferencesController { useBlockie: false, useNonceField: false, usePhishDetect: true, + dismissSeedBackUpReminder: false, // WARNING: Do not use feature flags for security-sensitive things. // Feature flag toggling is available in the global namespace @@ -669,7 +670,7 @@ export default class PreferencesController { /** * A setter for the `useLedgerLive` property - * @param {bool} domain - Value for ledger live support + * @param {bool} useLedgerLive - Value for ledger live support * @returns {Promise<string>} A promise of the update to useLedgerLive */ async setLedgerLivePreference(useLedgerLive) { @@ -685,6 +686,17 @@ export default class PreferencesController { return this.store.getState().useLedgerLive; } + /** + * A setter for the user preference to dismiss the seed phrase backup reminder + * @param {bool} dismissBackupReminder- User preference for dismissing the back up reminder + * @returns {void} + */ + async setDismissSeedBackUpReminder(dismissSeedBackUpReminder) { + await this.store.updateState({ + dismissSeedBackUpReminder, + }); + } + // // PRIVATE METHODS // diff --git a/app/scripts/controllers/preferences.test.js b/app/scripts/controllers/preferences.test.js index 1c765a92b..4141f0f5f 100644 --- a/app/scripts/controllers/preferences.test.js +++ b/app/scripts/controllers/preferences.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import sinon from 'sinon'; import { MAINNET_CHAIN_ID, diff --git a/app/scripts/controllers/swaps.js b/app/scripts/controllers/swaps.js index 2496e9b0b..9e4247231 100644 --- a/app/scripts/controllers/swaps.js +++ b/app/scripts/controllers/swaps.js @@ -4,9 +4,9 @@ import BigNumber from 'bignumber.js'; import { ObservableStore } from '@metamask/obs-store'; import { mapValues, cloneDeep } from 'lodash'; import abi from 'human-standard-token-abi'; -import { calcTokenAmount } from '../../../ui/app/helpers/utils/token-util'; -import { calcGasTotal } from '../../../ui/app/pages/send/send.utils'; -import { conversionUtil } from '../../../ui/app/helpers/utils/conversion-util'; +import { calcTokenAmount } from '../../../ui/helpers/utils/token-util'; +import { calcGasTotal } from '../../../ui/pages/send/send.utils'; +import { conversionUtil } from '../../../ui/helpers/utils/conversion-util'; import { DEFAULT_ERC20_APPROVE_GAS, QUOTES_EXPIRED_ERROR, @@ -20,7 +20,7 @@ import { fetchTradesInfo as defaultFetchTradesInfo, fetchSwapsFeatureLiveness as defaultFetchSwapsFeatureLiveness, fetchSwapsQuoteRefreshTime as defaultFetchSwapsQuoteRefreshTime, -} from '../../../ui/app/pages/swaps/swaps.util'; +} from '../../../ui/pages/swaps/swaps.util'; import { NETWORK_EVENTS } from './network'; // The MAX_GAS_LIMIT is a number that is higher than the maximum gas costs we have observed on any aggregator diff --git a/app/scripts/controllers/swaps.test.js b/app/scripts/controllers/swaps.test.js index 4e85aa393..0fb1d80ac 100644 --- a/app/scripts/controllers/swaps.test.js +++ b/app/scripts/controllers/swaps.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import sinon from 'sinon'; import { ethers } from 'ethers'; @@ -645,7 +645,7 @@ describe('SwapsController', function () { topAggId, resultQuotes, ] = await swapsController._findTopQuoteAndCalculateSavings(testInput); - assert.equal(topAggId, [TEST_AGG_ID_2]); + assert.equal(topAggId, TEST_AGG_ID_2); assert.deepStrictEqual(resultQuotes, expectedResultQuotes); }); }); diff --git a/app/scripts/controllers/token-rates-controller.test.js b/app/scripts/controllers/token-rates-controller.test.js index fc5d3af52..444e53977 100644 --- a/app/scripts/controllers/token-rates-controller.test.js +++ b/app/scripts/controllers/token-rates-controller.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import sinon from 'sinon'; import { ObservableStore } from '@metamask/obs-store'; import TokenRatesController from './token-rates'; diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 3067b3e4f..9b7011a66 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -16,8 +16,8 @@ import { BnMultiplyByFraction, addHexPrefix, } from '../../lib/util'; -import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/app/helpers/constants/error-keys'; -import { getSwapsTokensReceivedFromTxMeta } from '../../../../ui/app/pages/swaps/swaps.util'; +import { TRANSACTION_NO_CONTRACT_ERROR_KEY } from '../../../../ui/helpers/constants/error-keys'; +import { getSwapsTokensReceivedFromTxMeta } from '../../../../ui/pages/swaps/swaps.util'; import { TRANSACTION_STATUSES, TRANSACTION_TYPES, diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 72bbf7901..9b4952a5e 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -32,8 +32,8 @@ cleanContextForImports(); /* eslint-disable import/first */ import log from 'loglevel'; -import LocalMessageDuplexStream from 'post-message-stream'; -import { initializeProvider } from '@metamask/inpage-provider'; +import { WindowPostMessageStream } from '@metamask/post-message-stream'; +import { initializeProvider } from '@metamask/providers/dist/initializeInpageProvider'; restoreContextAfterImports(); @@ -44,7 +44,7 @@ log.setDefaultLevel(process.env.METAMASK_DEBUG ? 'debug' : 'warn'); // // setup background connection -const metamaskStream = new LocalMessageDuplexStream({ +const metamaskStream = new WindowPostMessageStream({ name: 'metamask-inpage', target: 'metamask-contentscript', }); diff --git a/app/scripts/lib/ComposableObservableStore.js b/app/scripts/lib/ComposableObservableStore.js index 68ce42d08..789a12d80 100644 --- a/app/scripts/lib/ComposableObservableStore.js +++ b/app/scripts/lib/ComposableObservableStore.js @@ -1,34 +1,68 @@ import { ObservableStore } from '@metamask/obs-store'; +/** + * @typedef {import('@metamask/controllers').ControllerMessenger} ControllerMessenger + */ + /** * An ObservableStore that can composes a flat * structure of child stores based on configuration */ export default class ComposableObservableStore extends ObservableStore { + /** + * Describes which stores are being composed. The key is the name of the + * store, and the value is either an ObserableStore, or a controller that + * extends one of the two base controllers in the `@metamask/controllers` + * package. + * @type {Record<string, Object>} + */ + config = {}; + /** * Create a new store * - * @param {Object} [initState] - The initial store state - * @param {Object} [config] - Map of internal state keys to child stores + * @param {Object} options + * @param {Object} [options.config] - Map of internal state keys to child stores + * @param {ControllerMessenger} options.controllerMessenger - The controller + * messenger, used for subscribing to events from BaseControllerV2-based + * controllers. + * @param {Object} [options.state] - The initial store state */ - constructor(initState, config) { - super(initState); - this.updateStructure(config); + constructor({ config, controllerMessenger, state }) { + super(state); + this.controllerMessenger = controllerMessenger; + if (config) { + this.updateStructure(config); + } } /** * Composes a new internal store subscription structure * - * @param {Object} [config] - Map of internal state keys to child stores + * @param {Record<string, Object>} config - Describes which stores are being + * composed. The key is the name of the store, and the value is either an + * ObserableStore, or a controller that extends one of the two base + * controllers in the `@metamask/controllers` package. */ updateStructure(config) { this.config = config; this.removeAllListeners(); - for (const key in config) { - if (Object.prototype.hasOwnProperty.call(config, key)) { + for (const key of Object.keys(config)) { + if (!config[key]) { + throw new Error(`Undefined '${key}'`); + } + const store = config[key]; + if (store.subscribe) { config[key].subscribe((state) => { this.updateState({ [key]: state }); }); + } else { + this.controllerMessenger.subscribe( + `${store.name}:stateChange`, + (state) => { + this.updateState({ [key]: state }); + }, + ); } } } @@ -40,15 +74,16 @@ export default class ComposableObservableStore extends ObservableStore { * @returns {Object} Object containing merged child store state */ getFlatState() { + if (!this.config) { + return {}; + } let flatState = {}; - for (const key in this.config) { - if (Object.prototype.hasOwnProperty.call(this.config, key)) { - const controller = this.config[key]; - const state = controller.getState - ? controller.getState() - : controller.state; - flatState = { ...flatState, ...state }; - } + for (const key of Object.keys(this.config)) { + const controller = this.config[key]; + const state = controller.getState + ? controller.getState() + : controller.state; + flatState = { ...flatState, ...state }; } return flatState; } diff --git a/app/scripts/lib/ComposableObservableStore.test.js b/app/scripts/lib/ComposableObservableStore.test.js index a079984c1..063f97cbf 100644 --- a/app/scripts/lib/ComposableObservableStore.test.js +++ b/app/scripts/lib/ComposableObservableStore.test.js @@ -1,35 +1,194 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import { ObservableStore } from '@metamask/obs-store'; +import { + BaseController, + BaseControllerV2, + ControllerMessenger, +} from '@metamask/controllers'; import ComposableObservableStore from './ComposableObservableStore'; +class OldExampleController extends BaseController { + name = 'OldExampleController'; + + defaultState = { + baz: 'baz', + }; + + constructor() { + super(); + this.initialize(); + } + + updateBaz(contents) { + this.update({ baz: contents }); + } +} +class ExampleController extends BaseControllerV2 { + static defaultState = { + bar: 'bar', + }; + + static metadata = { + bar: { persist: true, anonymous: true }, + }; + + constructor({ messenger }) { + super({ + messenger, + name: 'ExampleController', + metadata: ExampleController.metadata, + state: ExampleController.defaultState, + }); + } + + updateBar(contents) { + this.update(() => { + return { bar: contents }; + }); + } +} + describe('ComposableObservableStore', function () { it('should register initial state', function () { - const store = new ComposableObservableStore('state'); + const controllerMessenger = new ControllerMessenger(); + const store = new ComposableObservableStore({ + controllerMessenger, + state: 'state', + }); assert.strictEqual(store.getState(), 'state'); }); it('should register initial structure', function () { + const controllerMessenger = new ControllerMessenger(); const testStore = new ObservableStore(); - const store = new ComposableObservableStore(null, { TestStore: testStore }); + const store = new ComposableObservableStore({ + config: { TestStore: testStore }, + controllerMessenger, + }); testStore.putState('state'); assert.deepEqual(store.getState(), { TestStore: 'state' }); }); - it('should update structure', function () { + it('should update structure with observable store', function () { + const controllerMessenger = new ControllerMessenger(); const testStore = new ObservableStore(); - const store = new ComposableObservableStore(); + const store = new ComposableObservableStore({ controllerMessenger }); store.updateStructure({ TestStore: testStore }); testStore.putState('state'); assert.deepEqual(store.getState(), { TestStore: 'state' }); }); - it('should return flattened state', function () { - const fooStore = new ObservableStore({ foo: 'foo' }); - const barStore = new ObservableStore({ bar: 'bar' }); - const store = new ComposableObservableStore(null, { - FooStore: fooStore, - BarStore: barStore, + it('should update structure with BaseController-based controller', function () { + const controllerMessenger = new ControllerMessenger(); + const oldExampleController = new OldExampleController(); + const store = new ComposableObservableStore({ controllerMessenger }); + store.updateStructure({ OldExample: oldExampleController }); + oldExampleController.updateBaz('state'); + assert.deepEqual(store.getState(), { OldExample: { baz: 'state' } }); + }); + + it('should update structure with BaseControllerV2-based controller', function () { + const controllerMessenger = new ControllerMessenger(); + const exampleController = new ExampleController({ + messenger: controllerMessenger, }); - assert.deepEqual(store.getFlatState(), { foo: 'foo', bar: 'bar' }); + const store = new ComposableObservableStore({ controllerMessenger }); + store.updateStructure({ Example: exampleController }); + exampleController.updateBar('state'); + console.log(exampleController.state); + assert.deepEqual(store.getState(), { Example: { bar: 'state' } }); + }); + + it('should update structure with all three types of stores', function () { + const controllerMessenger = new ControllerMessenger(); + const exampleStore = new ObservableStore(); + const exampleController = new ExampleController({ + messenger: controllerMessenger, + }); + const oldExampleController = new OldExampleController(); + const store = new ComposableObservableStore({ controllerMessenger }); + store.updateStructure({ + Example: exampleController, + OldExample: oldExampleController, + Store: exampleStore, + }); + exampleStore.putState('state'); + exampleController.updateBar('state'); + oldExampleController.updateBaz('state'); + assert.deepEqual(store.getState(), { + Example: { bar: 'state' }, + OldExample: { baz: 'state' }, + Store: 'state', + }); + }); + + it('should return flattened state', function () { + const controllerMessenger = new ControllerMessenger(); + const fooStore = new ObservableStore({ foo: 'foo' }); + const barController = new ExampleController({ + messenger: controllerMessenger, + }); + const bazController = new OldExampleController(); + const store = new ComposableObservableStore({ + config: { + FooStore: fooStore, + BarStore: barController, + BazStore: bazController, + }, + controllerMessenger, + state: { + FooStore: fooStore.getState(), + BarStore: barController.state, + BazStore: bazController.state, + }, + }); + assert.deepEqual(store.getFlatState(), { + foo: 'foo', + bar: 'bar', + baz: 'baz', + }); + }); + + it('should return empty flattened state when not configured', function () { + const controllerMessenger = new ControllerMessenger(); + const store = new ComposableObservableStore({ controllerMessenger }); + assert.deepEqual(store.getFlatState(), {}); + }); + + it('should throw if the controller messenger is omitted and the config includes a BaseControllerV2 controller', function () { + const controllerMessenger = new ControllerMessenger(); + const exampleController = new ExampleController({ + messenger: controllerMessenger, + }); + assert.throws( + () => + new ComposableObservableStore({ + config: { + Example: exampleController, + }, + }), + ); + }); + + it('should throw if the controller messenger is omitted and updateStructure called with a BaseControllerV2 controller', function () { + const controllerMessenger = new ControllerMessenger(); + const exampleController = new ExampleController({ + messenger: controllerMessenger, + }); + const store = new ComposableObservableStore({}); + assert.throws(() => store.updateStructure({ Example: exampleController })); + }); + + it('should throw if initialized with undefined config entry', function () { + const controllerMessenger = new ControllerMessenger(); + assert.throws( + () => + new ComposableObservableStore({ + config: { + Example: undefined, + }, + controllerMessenger, + }), + ); }); }); diff --git a/app/scripts/lib/buy-eth-url.test.js b/app/scripts/lib/buy-eth-url.test.js index 17ba3d64a..01837c8ef 100644 --- a/app/scripts/lib/buy-eth-url.test.js +++ b/app/scripts/lib/buy-eth-url.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import { KOVAN_CHAIN_ID, MAINNET_CHAIN_ID, diff --git a/app/scripts/lib/cleanErrorStack.test.js b/app/scripts/lib/cleanErrorStack.test.js index 9f01e8252..b87152f21 100644 --- a/app/scripts/lib/cleanErrorStack.test.js +++ b/app/scripts/lib/cleanErrorStack.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import cleanErrorStack from './cleanErrorStack'; describe('Clean Error Stack', function () { @@ -14,7 +14,7 @@ describe('Clean Error Stack', function () { }); it('tests error with message', function () { - assert.equal(cleanErrorStack(testError), 'Error: Test Message'); + assert.equal(cleanErrorStack(testError).toString(), 'Error: Test Message'); }); it('tests error with undefined name', function () { @@ -29,6 +29,6 @@ describe('Clean Error Stack', function () { }); it('tests error with blank message', function () { - assert.equal(cleanErrorStack(blankMsgError), 'Error'); + assert.equal(cleanErrorStack(blankMsgError).toString(), 'Error'); }); }); diff --git a/app/scripts/lib/createMetaRPCHandler.test.js b/app/scripts/lib/createMetaRPCHandler.test.js index c3f644ec8..d6472b5e1 100644 --- a/app/scripts/lib/createMetaRPCHandler.test.js +++ b/app/scripts/lib/createMetaRPCHandler.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import { obj as createThoughStream } from 'through2'; import createMetaRPCHandler from './createMetaRPCHandler'; diff --git a/app/scripts/lib/get-first-preferred-lang-code.js b/app/scripts/lib/get-first-preferred-lang-code.js index 4639d6dc9..bcac7937a 100644 --- a/app/scripts/lib/get-first-preferred-lang-code.js +++ b/app/scripts/lib/get-first-preferred-lang-code.js @@ -40,9 +40,7 @@ export default async function getFirstPreferredLangCode() { const firstPreferredLangCode = userPreferredLocaleCodes .map((code) => code.toLowerCase().replace('_', '-')) - .find((code) => - Object.prototype.hasOwnProperty.call(existingLocaleCodes, code), - ); + .find((code) => existingLocaleCodes[code] !== undefined); return existingLocaleCodes[firstPreferredLangCode] || 'en'; } diff --git a/app/scripts/lib/message-manager.test.js b/app/scripts/lib/message-manager.test.js index 947cb2688..39183fb7a 100644 --- a/app/scripts/lib/message-manager.test.js +++ b/app/scripts/lib/message-manager.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; import MessageManager from './message-manager'; diff --git a/app/scripts/lib/metaRPCClientFactory.js b/app/scripts/lib/metaRPCClientFactory.js index 108da0e4c..689774f91 100644 --- a/app/scripts/lib/metaRPCClientFactory.js +++ b/app/scripts/lib/metaRPCClientFactory.js @@ -6,6 +6,7 @@ class MetaRPCClient { constructor(connectionStream) { this.connectionStream = connectionStream; this.notificationChannel = new SafeEventEmitter(); + this.uncaughtErrorChannel = new SafeEventEmitter(); this.requests = new Map(); this.connectionStream.on('data', this.handleResponse.bind(this)); this.connectionStream.on('end', this.close.bind(this)); @@ -17,34 +18,47 @@ class MetaRPCClient { }); } + onUncaughtError(handler) { + this.uncaughtErrorChannel.addListener('error', (error) => { + handler(error); + }); + } + close() { this.notificationChannel.removeAllListeners(); + this.uncaughtErrorChannel.removeAllListeners(); } handleResponse(data) { const { id, result, error, method, params } = data; + const isNotification = id === undefined && error === undefined; const cb = this.requests.get(id); - if (method && params && id) { + if (method && params && !isNotification) { // dont handle server-side to client-side requests return; } - if (method && params && !id) { + if (method && params && isNotification) { // handle servier-side to client-side notification this.notificationChannel.emit('notification', data); return; } - if (!cb) { - // not found in request list - return; - } if (error) { const e = new EthereumRpcError(error.code, error.message, error.data); // preserve the stack from serializeError e.stack = error.stack; - this.requests.delete(id); - cb(e); + if (cb) { + this.requests.delete(id); + cb(e); + return; + } + this.uncaughtErrorChannel.emit('error', e); + return; + } + + if (!cb) { + // not found in request list return; } diff --git a/app/scripts/lib/metaRPCClientFactory.test.js b/app/scripts/lib/metaRPCClientFactory.test.js index d270a4e1a..d0553da73 100644 --- a/app/scripts/lib/metaRPCClientFactory.test.js +++ b/app/scripts/lib/metaRPCClientFactory.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import { obj as createThoughStream } from 'through2'; import metaRPCClientFactory from './metaRPCClientFactory'; @@ -85,4 +85,58 @@ describe('metaRPCClientFactory', function () { }); }); }); + + it('should be able to handle notifications', function (done) { + const streamTest = createThoughStream(); + const metaRPCClient = metaRPCClientFactory(streamTest); + + metaRPCClient.onNotification((notification) => { + assert(notification.method, 'foobarbaz'); + done(); + }); + + // send a notification + streamTest.write({ + jsonrpc: '2.0', + method: 'foobarbaz', + params: ['bar'], + }); + }); + + it('should be able to handle errors with no id', function (done) { + const streamTest = createThoughStream(); + const metaRPCClient = metaRPCClientFactory(streamTest); + + metaRPCClient.onUncaughtError((error) => { + assert(error.code, 1); + done(); + }); + + streamTest.write({ + jsonrpc: '2.0', + error: { + code: 1, + message: 'error msg', + }, + }); + }); + + it('should be able to handle errors with null id', function (done) { + const streamTest = createThoughStream(); + const metaRPCClient = metaRPCClientFactory(streamTest); + + metaRPCClient.onUncaughtError((error) => { + assert(error.code, 1); + done(); + }); + + streamTest.write({ + jsonrpc: '2.0', + id: null, + error: { + code: 1, + message: 'error msg', + }, + }); + }); }); diff --git a/app/scripts/lib/migrator/index.test.js b/app/scripts/lib/migrator/index.test.js index 0fbb3e8a9..cdaac9e82 100644 --- a/app/scripts/lib/migrator/index.test.js +++ b/app/scripts/lib/migrator/index.test.js @@ -1,5 +1,5 @@ import fs from 'fs'; -import assert from 'assert'; +import { strict as assert } from 'assert'; import { cloneDeep } from 'lodash'; import liveMigrations from '../../migrations'; import data from '../../first-time-state'; diff --git a/app/scripts/lib/nodeify.test.js b/app/scripts/lib/nodeify.test.js index 4f2c2a2eb..accfc48e8 100644 --- a/app/scripts/lib/nodeify.test.js +++ b/app/scripts/lib/nodeify.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import nodeify from './nodeify'; describe('nodeify', function () { diff --git a/app/scripts/lib/personal-message-manager.test.js b/app/scripts/lib/personal-message-manager.test.js index c3ce3f615..de241fff0 100644 --- a/app/scripts/lib/personal-message-manager.test.js +++ b/app/scripts/lib/personal-message-manager.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; import PersonalMessageManager from './personal-message-manager'; diff --git a/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js b/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js index ac170b399..50399c3ab 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js @@ -1,4 +1,4 @@ -import { ethErrors } from 'eth-rpc-errors'; +import { ethErrors, errorCodes } from 'eth-rpc-errors'; import validUrl from 'valid-url'; import { omit } from 'lodash'; import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; @@ -123,12 +123,16 @@ async function addEthereumChainHandler( const existingNetwork = findCustomRpcBy({ chainId: _chainId }); - if (existingNetwork !== null) { + if (existingNetwork) { + // If the network already exists, the request is considered successful + res.result = null; + const currentChainId = getCurrentChainId(); if (currentChainId === _chainId) { - res.result = null; return end(); } + + // Ask the user to switch the network try { await updateRpcTarget( await requestUserApproval({ @@ -144,7 +148,12 @@ async function addEthereumChainHandler( ); res.result = null; } catch (error) { - return end(error); + // For the purposes of this method, it does not matter if the user + // declines to switch the selected network. However, other errors indicate + // that something is wrong. + if (error.code !== errorCodes.provider.userRejectedRequest) { + return end(error); + } } return end(); } @@ -251,6 +260,14 @@ async function addEthereumChainHandler( }, }); + // Once the network has been added, the requested is considered successful + res.result = null; + } catch (error) { + return end(error); + } + + // Ask the user to switch the network + try { await updateRpcTarget( await requestUserApproval({ origin, @@ -263,10 +280,13 @@ async function addEthereumChainHandler( }, }), ); - - res.result = null; } catch (error) { - return end(error); + // For the purposes of this method, it does not matter if the user + // declines to switch the selected network. However, other errors indicate + // that something is wrong. + if (error.code !== errorCodes.provider.userRejectedRequest) { + return end(error); + } } return end(); } diff --git a/app/scripts/lib/rpc-method-middleware/handlers/index.js b/app/scripts/lib/rpc-method-middleware/handlers/index.js index 541256a1c..fb0c1ef8f 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/index.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/index.js @@ -1,10 +1,12 @@ import addEthereumChain from './add-ethereum-chain'; +import switchEthereumChain from './switch-ethereum-chain'; import getProviderState from './get-provider-state'; import logWeb3ShimUsage from './log-web3-shim-usage'; import watchAsset from './watch-asset'; const handlers = [ addEthereumChain, + switchEthereumChain, getProviderState, logWeb3ShimUsage, watchAsset, diff --git a/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js b/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js new file mode 100644 index 000000000..bba11d26c --- /dev/null +++ b/app/scripts/lib/rpc-method-middleware/handlers/switch-ethereum-chain.js @@ -0,0 +1,113 @@ +import { ethErrors } from 'eth-rpc-errors'; +import { omit } from 'lodash'; +import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; +import { + ETH_SYMBOL, + CHAIN_ID_TO_TYPE_MAP, + NETWORK_TO_NAME_MAP, +} from '../../../../../shared/constants/network'; +import { + isPrefixedFormattedHexString, + isSafeChainId, +} from '../../../../../shared/modules/network.utils'; + +const switchEthereumChain = { + methodNames: [MESSAGE_TYPE.SWITCH_ETHEREUM_CHAIN], + implementation: switchEthereumChainHandler, +}; +export default switchEthereumChain; + +function findExistingNetwork(chainId, findCustomRpcBy) { + if (chainId in CHAIN_ID_TO_TYPE_MAP) { + return { + chainId, + nickname: NETWORK_TO_NAME_MAP[chainId], + ticker: ETH_SYMBOL, + }; + } + + return findCustomRpcBy({ chainId }); +} + +async function switchEthereumChainHandler( + req, + res, + _next, + end, + { getCurrentChainId, findCustomRpcBy, updateRpcTarget, requestUserApproval }, +) { + if (!req.params?.[0] || typeof req.params[0] !== 'object') { + return end( + ethErrors.rpc.invalidParams({ + message: `Expected single, object parameter. Received:\n${JSON.stringify( + req.params, + )}`, + }), + ); + } + + const { origin } = req; + + const { chainId } = req.params[0]; + + const otherKeys = Object.keys(omit(req.params[0], ['chainId'])); + + if (otherKeys.length > 0) { + return end( + ethErrors.rpc.invalidParams({ + message: `Received unexpected keys on object parameter. Unsupported keys:\n${otherKeys}`, + }), + ); + } + + const _chainId = typeof chainId === 'string' && chainId.toLowerCase(); + + if (!isPrefixedFormattedHexString(_chainId)) { + return end( + ethErrors.rpc.invalidParams({ + message: `Expected 0x-prefixed, unpadded, non-zero hexadecimal string 'chainId'. Received:\n${chainId}`, + }), + ); + } + + if (!isSafeChainId(parseInt(_chainId, 16))) { + return end( + ethErrors.rpc.invalidParams({ + message: `Invalid chain ID "${_chainId}": numerical value greater than max safe value. Received:\n${chainId}`, + }), + ); + } + + const existingNetwork = findExistingNetwork(_chainId, findCustomRpcBy); + + if (existingNetwork) { + const currentChainId = getCurrentChainId(); + if (currentChainId === _chainId) { + res.result = null; + return end(); + } + try { + await updateRpcTarget( + await requestUserApproval({ + origin, + type: MESSAGE_TYPE.SWITCH_ETHEREUM_CHAIN, + requestData: { + chainId: existingNetwork.chainId, + nickname: existingNetwork.nickname, + ticker: existingNetwork.ticker, + }, + }), + ); + res.result = null; + } catch (error) { + return end(error); + } + return end(); + } + return end( + ethErrors.provider.custom({ + code: 4902, // To-be-standardized "unrecognized chain ID" error + message: `Unrecognized chain ID "${chainId}". Try adding the chain using ${MESSAGE_TYPE.ADD_ETHEREUM_CHAIN} first.`, + }), + ); +} diff --git a/app/scripts/lib/seed-phrase-verifier.test.js b/app/scripts/lib/seed-phrase-verifier.test.js index d7ac0143f..1a6443935 100644 --- a/app/scripts/lib/seed-phrase-verifier.test.js +++ b/app/scripts/lib/seed-phrase-verifier.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import { cloneDeep } from 'lodash'; import KeyringController from 'eth-keyring-controller'; import firstTimeState from '../first-time-state'; diff --git a/app/scripts/lib/setupSentry.js b/app/scripts/lib/setupSentry.js index 09482d24b..25bbd7a46 100644 --- a/app/scripts/lib/setupSentry.js +++ b/app/scripts/lib/setupSentry.js @@ -7,9 +7,8 @@ import extractEthjsErrorMessage from './extractEthjsErrorMessage'; // Destructuring breaks the inlining of the environment variables const METAMASK_DEBUG = process.env.METAMASK_DEBUG; const METAMASK_ENVIRONMENT = process.env.METAMASK_ENVIRONMENT; +const SENTRY_DSN_DEV = process.env.SENTRY_DSN_DEV; /* eslint-enable prefer-destructuring */ -const SENTRY_DSN_DEV = - 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496'; // This describes the subset of Redux state attached to errors sent to Sentry // These properties have some potential to be useful for debugging, and they do diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index df0488df8..8e205520b 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -1,5 +1,5 @@ import EventEmitter from 'events'; -import assert from 'assert'; +import { strict as assert } from 'assert'; import { ObservableStore } from '@metamask/obs-store'; import { ethErrors } from 'eth-rpc-errors'; import { typedSignatureHash, TYPED_MESSAGE_SCHEMA } from 'eth-sig-util'; diff --git a/app/scripts/lib/typed-message-manager.test.js b/app/scripts/lib/typed-message-manager.test.js index c994a586f..a9722211e 100644 --- a/app/scripts/lib/typed-message-manager.test.js +++ b/app/scripts/lib/typed-message-manager.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import sinon from 'sinon'; import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; import TypedMessageManager from './typed-message-manager'; diff --git a/app/scripts/lib/util.js b/app/scripts/lib/util.js index 46e5b8641..126e5c4f6 100644 --- a/app/scripts/lib/util.js +++ b/app/scripts/lib/util.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import extension from 'extensionizer'; import { stripHexPrefix } from 'ethereumjs-util'; import BN from 'bn.js'; diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 950601e5d..5fbd164bb 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -20,6 +20,7 @@ import contractMap from '@metamask/contract-metadata'; import { AddressBookController, ApprovalController, + ControllerMessenger, CurrencyRateController, PhishingController, NotificationController, @@ -96,8 +97,13 @@ export default class MetamaskController extends EventEmitter { this.getRequestAccountTabIds = opts.getRequestAccountTabIds; this.getOpenMetamaskTabsIds = opts.getOpenMetamaskTabsIds; + const controllerMessenger = new ControllerMessenger(); + // observable state store - this.store = new ComposableObservableStore(initState); + this.store = new ComposableObservableStore({ + state: initState, + controllerMessenger, + }); // external connections by origin // Do not modify directly. Use the associated methods. @@ -157,10 +163,14 @@ export default class MetamaskController extends EventEmitter { preferencesStore: this.preferencesController.store, }); - this.currencyRateController = new CurrencyRateController( - { includeUSDRate: true }, - initState.CurrencyController, - ); + const currencyRateMessenger = controllerMessenger.getRestricted({ + name: 'CurrencyRateController', + }); + this.currencyRateController = new CurrencyRateController({ + includeUSDRate: true, + messenger: currencyRateMessenger, + state: initState.CurrencyController, + }); this.phishingController = new PhishingController(); @@ -222,10 +232,12 @@ export default class MetamaskController extends EventEmitter { this.accountTracker.start(); this.incomingTransactionsController.start(); this.tokenRatesController.start(); + this.currencyRateController.start(); } else { this.accountTracker.stop(); this.incomingTransactionsController.stop(); this.tokenRatesController.stop(); + this.currencyRateController.stop(); } }); @@ -364,18 +376,15 @@ export default class MetamaskController extends EventEmitter { } }); - this.networkController.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, () => { - this.setCurrentCurrency( - this.currencyRateController.state.currentCurrency, - (error) => { - if (error) { - throw error; - } - }, - ); + this.networkController.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, async () => { + const { ticker } = this.networkController.getProviderConfig(); + try { + await this.currencyRateController.setNativeCurrency(ticker); + } catch (error) { + // TODO: Handle failure to get conversion rate more gracefully + console.error(error); + } }); - const { ticker } = this.networkController.getProviderConfig(); - this.currencyRateController.configure({ nativeCurrency: ticker ?? 'ETH' }); this.networkController.lookupNetwork(); this.messageManager = new MessageManager(); this.personalMessageManager = new PersonalMessageManager(); @@ -439,33 +448,37 @@ export default class MetamaskController extends EventEmitter { NotificationController: this.notificationController, }); - this.memStore = new ComposableObservableStore(null, { - AppStateController: this.appStateController.store, - NetworkController: this.networkController.store, - AccountTracker: this.accountTracker.store, - TxController: this.txController.memStore, - CachedBalancesController: this.cachedBalancesController.store, - TokenRatesController: this.tokenRatesController.store, - MessageManager: this.messageManager.memStore, - PersonalMessageManager: this.personalMessageManager.memStore, - DecryptMessageManager: this.decryptMessageManager.memStore, - EncryptionPublicKeyManager: this.encryptionPublicKeyManager.memStore, - TypesMessageManager: this.typedMessageManager.memStore, - KeyringController: this.keyringController.memStore, - PreferencesController: this.preferencesController.store, - MetaMetricsController: this.metaMetricsController.store, - AddressBookController: this.addressBookController, - CurrencyController: this.currencyRateController, - AlertController: this.alertController.store, - OnboardingController: this.onboardingController.store, - IncomingTransactionsController: this.incomingTransactionsController.store, - PermissionsController: this.permissionsController.permissions, - PermissionsMetadata: this.permissionsController.store, - ThreeBoxController: this.threeBoxController.store, - SwapsController: this.swapsController.store, - EnsController: this.ensController.store, - ApprovalController: this.approvalController, - NotificationController: this.notificationController, + this.memStore = new ComposableObservableStore({ + config: { + AppStateController: this.appStateController.store, + NetworkController: this.networkController.store, + AccountTracker: this.accountTracker.store, + TxController: this.txController.memStore, + CachedBalancesController: this.cachedBalancesController.store, + TokenRatesController: this.tokenRatesController.store, + MessageManager: this.messageManager.memStore, + PersonalMessageManager: this.personalMessageManager.memStore, + DecryptMessageManager: this.decryptMessageManager.memStore, + EncryptionPublicKeyManager: this.encryptionPublicKeyManager.memStore, + TypesMessageManager: this.typedMessageManager.memStore, + KeyringController: this.keyringController.memStore, + PreferencesController: this.preferencesController.store, + MetaMetricsController: this.metaMetricsController.store, + AddressBookController: this.addressBookController, + CurrencyController: this.currencyRateController, + AlertController: this.alertController.store, + OnboardingController: this.onboardingController.store, + IncomingTransactionsController: this.incomingTransactionsController + .store, + PermissionsController: this.permissionsController.permissions, + PermissionsMetadata: this.permissionsController.store, + ThreeBoxController: this.threeBoxController.store, + SwapsController: this.swapsController.store, + EnsController: this.ensController.store, + ApprovalController: this.approvalController, + NotificationController: this.notificationController, + }, + controllerMessenger, }); this.memStore.subscribe(this.sendUpdate.bind(this)); @@ -478,6 +491,17 @@ export default class MetamaskController extends EventEmitter { this.submitPassword(password); } + // Lazily update the store with the current extension environment + this.extension.runtime.getPlatformInfo(({ os }) => { + this.appStateController.setBrowserEnvironment( + os, + // This method is presently only supported by Firefox + this.extension.runtime.getBrowserInfo === undefined + ? 'chrome' + : 'firefox', + ); + }); + // TODO:LegacyProvider: Delete this.publicConfigStore = this.createPublicConfigStore(); } @@ -638,7 +662,11 @@ export default class MetamaskController extends EventEmitter { return { // etc getState: (cb) => cb(null, this.getState()), - setCurrentCurrency: this.setCurrentCurrency.bind(this), + setCurrentCurrency: nodeify( + this.currencyRateController.setCurrentCurrency.bind( + this.currencyRateController, + ), + ), setUseBlockie: this.setUseBlockie.bind(this), setUseNonceField: this.setUseNonceField.bind(this), setUsePhishDetect: this.setUsePhishDetect.bind(this), @@ -724,6 +752,10 @@ export default class MetamaskController extends EventEmitter { preferencesController.addKnownMethodData, preferencesController, ), + setDismissSeedBackUpReminder: nodeify( + this.preferencesController.setDismissSeedBackUpReminder, + this.preferencesController, + ), // AddressController setAddressBook: nodeify( @@ -2493,29 +2525,6 @@ export default class MetamaskController extends EventEmitter { // Log blocks - /** - * A method for setting the user's preferred display currency. - * @param {string} currencyCode - The code of the preferred currency. - * @param {Function} cb - A callback function returning currency info. - */ - setCurrentCurrency(currencyCode, cb) { - const { ticker } = this.networkController.getProviderConfig(); - try { - const currencyState = { - nativeCurrency: ticker, - currentCurrency: currencyCode, - }; - this.currencyRateController.update(currencyState); - this.currencyRateController.configure(currencyState); - cb(null, this.currencyRateController.state); - return; - } catch (err) { - cb(err); - // eslint-disable-next-line no-useless-return - return; - } - } - /** * A method for selecting a custom URL for an ethereum RPC provider and updating it * @param {string} rpcUrl - A URL for a valid Ethereum RPC API. diff --git a/app/scripts/metamask-controller.test.js b/app/scripts/metamask-controller.test.js index 25caa7892..87fed2aef 100644 --- a/app/scripts/metamask-controller.test.js +++ b/app/scripts/metamask-controller.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import sinon from 'sinon'; import { cloneDeep } from 'lodash'; import nock from 'nock'; @@ -52,6 +52,7 @@ const ExtensionizerMock = { onInstalled: { addListener: () => undefined, }, + getPlatformInfo: async () => 'mac', }, }; @@ -492,8 +493,8 @@ describe('MetaMaskController', function () { ); } catch (e) { assert.equal( - e, - 'Error: MetamaskController:getKeyringForDevice - Unknown device', + e.message, + 'MetamaskController:getKeyringForDevice - Unknown device', ); } }); @@ -534,8 +535,8 @@ describe('MetaMaskController', function () { ); } catch (e) { assert.equal( - e, - 'Error: MetamaskController:getKeyringForDevice - Unknown device', + e.message, + 'MetamaskController:getKeyringForDevice - Unknown device', ); } }); @@ -553,8 +554,8 @@ describe('MetaMaskController', function () { await metamaskController.forgetDevice('Some random device name'); } catch (e) { assert.equal( - e, - 'Error: MetamaskController:getKeyringForDevice - Unknown device', + e.message, + 'MetamaskController:getKeyringForDevice - Unknown device', ); } }); @@ -653,46 +654,24 @@ describe('MetaMaskController', function () { }); describe('#setCustomRpc', function () { - let rpcUrl; - - beforeEach(function () { - rpcUrl = metamaskController.setCustomRpc( + it('returns custom RPC that when called', async function () { + const rpcUrl = await metamaskController.setCustomRpc( CUSTOM_RPC_URL, CUSTOM_RPC_CHAIN_ID, ); + assert.equal(rpcUrl, CUSTOM_RPC_URL); }); - it('returns custom RPC that when called', async function () { - assert.equal(await rpcUrl, CUSTOM_RPC_URL); - }); - - it('changes the network controller rpc', function () { + it('changes the network controller rpc', async function () { + await metamaskController.setCustomRpc( + CUSTOM_RPC_URL, + CUSTOM_RPC_CHAIN_ID, + ); const networkControllerState = metamaskController.networkController.store.getState(); assert.equal(networkControllerState.provider.rpcUrl, CUSTOM_RPC_URL); }); }); - describe('#setCurrentCurrency', function () { - let defaultMetaMaskCurrency; - - beforeEach(function () { - defaultMetaMaskCurrency = - metamaskController.currencyRateController.state.currentCurrency; - }); - - it('defaults to usd', function () { - assert.equal(defaultMetaMaskCurrency, 'usd'); - }); - - it('sets currency to JPY', function () { - metamaskController.setCurrentCurrency('JPY', noop); - assert.equal( - metamaskController.currencyRateController.state.currentCurrency, - 'JPY', - ); - }); - }); - describe('#addNewAccount', function () { it('errors when an primary keyring is does not exist', async function () { const addNewAccount = metamaskController.addNewAccount(); diff --git a/app/scripts/migrations/021.test.js b/app/scripts/migrations/021.test.js index 45c727e57..261d40f81 100644 --- a/app/scripts/migrations/021.test.js +++ b/app/scripts/migrations/021.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import wallet2 from '../../../test/lib/migrations/002.json'; import migration21 from './021'; diff --git a/app/scripts/migrations/022.test.js b/app/scripts/migrations/022.test.js index a102bcb7e..425bfeb91 100644 --- a/app/scripts/migrations/022.test.js +++ b/app/scripts/migrations/022.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; import migration22 from './022'; diff --git a/app/scripts/migrations/023.test.js b/app/scripts/migrations/023.test.js index 0b40679b2..0ef74beb6 100644 --- a/app/scripts/migrations/023.test.js +++ b/app/scripts/migrations/023.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; import migration23 from './023'; diff --git a/app/scripts/migrations/024.test.js b/app/scripts/migrations/024.test.js index b2056193d..f87e45748 100644 --- a/app/scripts/migrations/024.test.js +++ b/app/scripts/migrations/024.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import data from '../first-time-state'; import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; import migration24 from './024'; diff --git a/app/scripts/migrations/025.test.js b/app/scripts/migrations/025.test.js index 7d666c517..9e0ff846b 100644 --- a/app/scripts/migrations/025.test.js +++ b/app/scripts/migrations/025.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import data from '../first-time-state'; import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; import migration25 from './025'; diff --git a/app/scripts/migrations/026.test.js b/app/scripts/migrations/026.test.js index 71245115b..ca4ac9a64 100644 --- a/app/scripts/migrations/026.test.js +++ b/app/scripts/migrations/026.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import firstTimeState from '../first-time-state'; import migration26 from './026'; diff --git a/app/scripts/migrations/027.test.js b/app/scripts/migrations/027.test.js index 2687e17c2..29df2dfb0 100644 --- a/app/scripts/migrations/027.test.js +++ b/app/scripts/migrations/027.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import firstTimeState from '../first-time-state'; import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; import migration27 from './027'; diff --git a/app/scripts/migrations/028.test.js b/app/scripts/migrations/028.test.js index 01381e754..5d755f50c 100644 --- a/app/scripts/migrations/028.test.js +++ b/app/scripts/migrations/028.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import firstTimeState from '../first-time-state'; import migration28 from './028'; diff --git a/app/scripts/migrations/029.test.js b/app/scripts/migrations/029.test.js index 90d698fd7..53ce28695 100644 --- a/app/scripts/migrations/029.test.js +++ b/app/scripts/migrations/029.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; import migration29 from './029'; diff --git a/app/scripts/migrations/030.test.js b/app/scripts/migrations/030.test.js index 985aa02e1..f03f51231 100644 --- a/app/scripts/migrations/030.test.js +++ b/app/scripts/migrations/030.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migrationTemplate from './030'; const storage = { diff --git a/app/scripts/migrations/031.test.js b/app/scripts/migrations/031.test.js index d7b6ee046..62216e85d 100644 --- a/app/scripts/migrations/031.test.js +++ b/app/scripts/migrations/031.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migration31 from './031'; describe('migration #31', function () { diff --git a/app/scripts/migrations/033.test.js b/app/scripts/migrations/033.test.js index bb12e83d7..382622d39 100644 --- a/app/scripts/migrations/033.test.js +++ b/app/scripts/migrations/033.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migration33 from './033'; describe('Migration to delete notice controller', function () { diff --git a/app/scripts/migrations/034.test.js b/app/scripts/migrations/034.test.js index bfb929997..7902b5f13 100644 --- a/app/scripts/migrations/034.test.js +++ b/app/scripts/migrations/034.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migration34 from './034'; describe('migration #34', function () { diff --git a/app/scripts/migrations/035.test.js b/app/scripts/migrations/035.test.js index 385f12fb5..03454b2ea 100644 --- a/app/scripts/migrations/035.test.js +++ b/app/scripts/migrations/035.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migration35 from './035'; describe('migration #35', function () { diff --git a/app/scripts/migrations/036.test.js b/app/scripts/migrations/036.test.js index 679080bf7..ecc44c557 100644 --- a/app/scripts/migrations/036.test.js +++ b/app/scripts/migrations/036.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migration36 from './036'; describe('migration #36', function () { diff --git a/app/scripts/migrations/037.test.js b/app/scripts/migrations/037.test.js index 0c145bccf..688f66a9a 100644 --- a/app/scripts/migrations/037.test.js +++ b/app/scripts/migrations/037.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migration37 from './037'; describe('migration #37', function () { diff --git a/app/scripts/migrations/039.test.js b/app/scripts/migrations/039.test.js index 55ba12982..3efbbf49d 100644 --- a/app/scripts/migrations/039.test.js +++ b/app/scripts/migrations/039.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migration39 from './039'; describe('migration #39', function () { diff --git a/app/scripts/migrations/040.test.js b/app/scripts/migrations/040.test.js index f4d1de68e..ba10e4b75 100644 --- a/app/scripts/migrations/040.test.js +++ b/app/scripts/migrations/040.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migration40 from './040'; describe('migration #40', function () { diff --git a/app/scripts/migrations/041.test.js b/app/scripts/migrations/041.test.js index 7c6e4c567..f1a06a151 100644 --- a/app/scripts/migrations/041.test.js +++ b/app/scripts/migrations/041.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migration41 from './041'; describe('migration #41', function () { diff --git a/app/scripts/migrations/042.test.js b/app/scripts/migrations/042.test.js index 7cca8d2a7..8c1a46513 100644 --- a/app/scripts/migrations/042.test.js +++ b/app/scripts/migrations/042.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migration42 from './042'; describe('migration #42', function () { diff --git a/app/scripts/migrations/045.test.js b/app/scripts/migrations/045.test.js index 907489195..de47bef32 100644 --- a/app/scripts/migrations/045.test.js +++ b/app/scripts/migrations/045.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migration45 from './045'; describe('migration #45', function () { diff --git a/app/scripts/migrations/049.test.js b/app/scripts/migrations/049.test.js index 5242fab52..f3c89d66b 100644 --- a/app/scripts/migrations/049.test.js +++ b/app/scripts/migrations/049.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migration49 from './049'; describe('migration #49', function () { diff --git a/app/scripts/migrations/052.test.js b/app/scripts/migrations/052.test.js index 8d9d13afb..3896d0a77 100644 --- a/app/scripts/migrations/052.test.js +++ b/app/scripts/migrations/052.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import { GOERLI, GOERLI_CHAIN_ID, diff --git a/app/scripts/migrations/056.test.js b/app/scripts/migrations/056.test.js index e311d4aee..927997fbe 100644 --- a/app/scripts/migrations/056.test.js +++ b/app/scripts/migrations/056.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migration56 from './056'; const BAD_TOKEN_DATA = { symbol: null, decimals: null }; diff --git a/app/scripts/migrations/060.js b/app/scripts/migrations/060.js new file mode 100644 index 000000000..db985f6e5 --- /dev/null +++ b/app/scripts/migrations/060.js @@ -0,0 +1,35 @@ +import { cloneDeep, isPlainObject } from 'lodash'; + +const version = 60; +const SUPPORT_NOTIFICATION_KEY = 2; +const SUPPORT_NOTIFICATION_DATE = '2020-08-31'; + +/** + * Removes the support survey notification + */ +export default { + version, + async migrate(originalVersionedData) { + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + const newState = transformState(state); + versionedData.data = newState; + return versionedData; + }, +}; + +function transformState(state) { + const notifications = state?.NotificationController?.notifications; + if (isPlainObject(notifications)) { + if ( + notifications[SUPPORT_NOTIFICATION_KEY]?.date === + SUPPORT_NOTIFICATION_DATE + ) { + delete state.NotificationController.notifications[ + SUPPORT_NOTIFICATION_KEY + ]; + } + } + return state; +} diff --git a/app/scripts/migrations/060.test.js b/app/scripts/migrations/060.test.js new file mode 100644 index 000000000..c0116c9a7 --- /dev/null +++ b/app/scripts/migrations/060.test.js @@ -0,0 +1,143 @@ +import { strict as assert } from 'assert'; +import migration60 from './060'; + +describe('migration #60', function () { + it('should update the version metadata', async function () { + const oldStorage = { + meta: { + version: 59, + }, + data: {}, + }; + + const newStorage = await migration60.migrate(oldStorage); + assert.deepEqual(newStorage.meta, { + version: 60, + }); + }); + + it('prunes the support notification', async function () { + const oldStorage = { + meta: {}, + data: { + NotificationController: { + notifications: { + 1: { + id: 1, + date: '2021-03-17', + image: { + src: 'images/mobile-link-qr.svg', + height: '230px', + width: '230px', + placeImageBelowDescription: true, + }, + }, + 2: { + id: 2, + date: '2020-08-31', + }, + 3: { + id: 3, + date: '2021-03-08', + }, + 4: { + id: 4, + date: '2021-05-11', + image: { + src: 'images/source-logos-bsc.svg', + width: '100%', + }, + }, + }, + }, + }, + }; + + const newStorage = await migration60.migrate(oldStorage); + const { notifications } = newStorage.data.NotificationController; + const notificationKeys = Object.keys(notifications); + // Assert support notification is removed + assert.equal(notificationKeys.length, 3); + notificationKeys.forEach((key) => { + assert.notEqual(notifications[key].date, '2020-08-31'); + }); + }); + + it('does not modify state when the support notification does not exist', async function () { + const oldStorage = { + meta: {}, + data: { + NotificationController: { + notifications: { + 1: { + id: 1, + date: '2021-03-17', + image: { + src: 'images/mobile-link-qr.svg', + height: '230px', + width: '230px', + placeImageBelowDescription: true, + }, + }, + 3: { + id: 3, + date: '2021-03-08', + }, + 4: { + id: 4, + date: '2021-05-11', + image: { + src: 'images/source-logos-bsc.svg', + width: '100%', + }, + }, + }, + }, + }, + }; + + const newStorage = await migration60.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); + + it('does not modify state when NotificationsController is undefined', async function () { + const oldStorage = { + meta: {}, + data: { + arbitraryPropOne: 1, + arbitraryPropTwo: 2, + }, + }; + + const newStorage = await migration60.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); + + it('does not modify state when notifications are undefined', async function () { + const oldStorage = { + meta: {}, + data: { + NotificationController: { + arbitraryControllerProp: 'foo', + }, + }, + }; + + const newStorage = await migration60.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); + + it('does not modify state when notifications are not an object', async function () { + const oldStorage = { + meta: {}, + data: { + NotificationController: { + notifications: [], + }, + }, + }; + + const newStorage = await migration60.migrate(oldStorage); + assert.deepEqual(oldStorage.data, newStorage.data); + }); +}); diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 47925fbba..682ba6d08 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -64,6 +64,7 @@ const migrations = [ require('./057').default, require('./058').default, require('./059').default, + require('./060').default, ]; export default migrations; diff --git a/app/scripts/migrations/migrations.test.js b/app/scripts/migrations/migrations.test.js index a7c921323..82d15f501 100644 --- a/app/scripts/migrations/migrations.test.js +++ b/app/scripts/migrations/migrations.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import wallet1 from '../../../test/lib/migrations/001.json'; import vault4 from '../../../test/lib/migrations/004.json'; import migration2 from './002'; @@ -52,7 +52,7 @@ describe('wallet1 is migrated successfully', function () { const fourthData = fourthResult.data; assert.equal( fourthData.config.provider.rpcTarget, - null, + undefined, 'old rpcTarget should not exist.', ); assert.equal( @@ -65,15 +65,15 @@ describe('wallet1 is migrated successfully', function () { }) .then((fifthResult) => { const fifthData = fifthResult.data; - assert.equal(fifthData.vault, null, 'old vault should not exist'); + assert.equal(fifthData.vault, undefined, 'old vault should not exist'); assert.equal( fifthData.walletNicknames, - null, + undefined, 'old walletNicknames should not exist', ); assert.equal( fifthData.config.selectedAccount, - null, + undefined, 'old config.selectedAccount should not exist', ); assert.equal( @@ -102,7 +102,7 @@ describe('wallet1 is migrated successfully', function () { .then((sixthResult) => { assert.equal( sixthResult.data.KeyringController.selectedAccount, - null, + undefined, 'old selectedAccount should not exist', ); assert.equal( @@ -117,12 +117,12 @@ describe('wallet1 is migrated successfully', function () { .then((seventhResult) => { assert.equal( seventhResult.data.transactions, - null, + undefined, 'old transactions should not exist', ); assert.equal( seventhResult.data.gasMultiplier, - null, + undefined, 'old gasMultiplier should not exist', ); assert.equal( @@ -142,7 +142,7 @@ describe('wallet1 is migrated successfully', function () { .then((eighthResult) => { assert.equal( eighthResult.data.noticesList, - null, + undefined, 'old noticesList should not exist', ); assert.equal( @@ -157,22 +157,22 @@ describe('wallet1 is migrated successfully', function () { .then((ninthResult) => { assert.equal( ninthResult.data.currentFiat, - null, + undefined, 'old currentFiat should not exist', ); assert.equal( ninthResult.data.fiatCurrency, - null, + undefined, 'old fiatCurrency should not exist', ); assert.equal( ninthResult.data.conversionRate, - null, + undefined, 'old conversionRate should not exist', ); assert.equal( ninthResult.data.conversionDate, - null, + undefined, 'old conversionDate should not exist', ); @@ -198,7 +198,7 @@ describe('wallet1 is migrated successfully', function () { .then((tenthResult) => { assert.equal( tenthResult.data.shapeShiftTxList, - null, + undefined, 'old shapeShiftTxList should not exist', ); assert.equal( @@ -211,12 +211,12 @@ describe('wallet1 is migrated successfully', function () { .then((eleventhResult) => { assert.equal( eleventhResult.data.isDisclaimerConfirmed, - null, + undefined, 'isDisclaimerConfirmed should not exist', ); assert.equal( eleventhResult.data.TOSHash, - null, + undefined, 'TOSHash should not exist', ); diff --git a/app/scripts/migrations/template.test.js b/app/scripts/migrations/template.test.js index 92a4e8937..5277b86ba 100644 --- a/app/scripts/migrations/template.test.js +++ b/app/scripts/migrations/template.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import migrationTemplate from './template'; const storage = { diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 0eaeefaa8..e8820d602 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -1,8 +1,8 @@ import extension from 'extensionizer'; +import { getBlockExplorerLink } from '@metamask/etherscan-link'; import { getEnvironmentType, checkForError } from '../lib/util'; import { ENVIRONMENT_TYPE_BACKGROUND } from '../../../shared/constants/app'; import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; -import { getBlockExplorerUrlForTx } from '../../../shared/modules/transaction.utils'; export default class ExtensionPlatform { // @@ -192,7 +192,7 @@ export default class ExtensionPlatform { _showConfirmedTransaction(txMeta, rpcPrefs) { this._subscribeToNotificationClicked(); - const url = getBlockExplorerUrlForTx(txMeta, rpcPrefs); + const url = getBlockExplorerLink(txMeta, rpcPrefs); const nonce = parseInt(txMeta.txParams.nonce, 16); const title = 'Confirmed transaction'; diff --git a/development/announcer.js b/development/announcer.js index f0c42c07a..a3fc459a9 100644 --- a/development/announcer.js +++ b/development/announcer.js @@ -1,6 +1,6 @@ const fs = require('fs'); const path = require('path'); -const { version } = require('../app/manifest/_base.json'); +const { version } = require('../package.json'); const changelog = fs.readFileSync( path.join(__dirname, '..', 'CHANGELOG.md'), diff --git a/development/auto-changelog.js b/development/auto-changelog.js deleted file mode 100755 index 455bf5beb..000000000 --- a/development/auto-changelog.js +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env node -const fs = require('fs').promises; - -const path = require('path'); -const { version } = require('../app/manifest/_base.json'); -const { updateChangelog } = require('./lib/changelog/updateChangelog'); -const { unreleased } = require('./lib/changelog/constants'); - -const REPO_URL = 'https://github.com/MetaMask/metamask-extension'; - -const command = 'yarn update-changelog'; - -const helpText = `Usage: ${command} [--rc] [-h|--help] -Update CHANGELOG.md with any changes made since the most recent release. - -Options: - --rc Add new changes to the current release header, rather than to the - '${unreleased}' section. - -h, --help Display this help and exit. - -New commits will be added to the "${unreleased}" section (or to the section for the -current release if the '--rc' flag is used) in reverse chronological order. Any -commits for PRs that are represented already in the changelog will be ignored. - -If the '--rc' flag is used and the section for the current release does not yet -exist, it will be created. -`; - -async function main() { - const args = process.argv.slice(2); - let isReleaseCandidate = false; - - for (const arg of args) { - if (arg === '--rc') { - isReleaseCandidate = true; - } else if (['--help', '-h'].includes(arg)) { - console.log(helpText); - process.exit(0); - } else { - console.error( - `Unrecognized argument: ${arg}\nTry '${command} --help' for more information.\n`, - ); - process.exit(1); - } - } - - const changelogFilename = path.resolve(__dirname, '..', 'CHANGELOG.md'); - const changelogContent = await fs.readFile(changelogFilename, { - encoding: 'utf8', - }); - - const newChangelogContent = await updateChangelog({ - changelogContent, - currentVersion: version, - repoUrl: REPO_URL, - isReleaseCandidate, - }); - - await fs.writeFile(changelogFilename, newChangelogContent); - - console.log('CHANGELOG updated'); -} - -main().catch((error) => { - console.error(error); - process.exit(1); -}); diff --git a/development/build/etc.js b/development/build/etc.js index 49070887f..754a64f78 100644 --- a/development/build/etc.js +++ b/development/build/etc.js @@ -4,7 +4,7 @@ const gulpZip = require('gulp-zip'); const del = require('del'); const pify = require('pify'); const pump = pify(require('pump')); -const baseManifest = require('../../app/manifest/_base.json'); +const { version } = require('../../package.json'); const { createTask, composeParallel } = require('./task'); module.exports = createEtcTasks; @@ -38,7 +38,7 @@ function createZipTask(target) { return async () => { await pump( gulp.src(`dist/${target}/**`), - gulpZip(`metamask-${target}-${baseManifest.version}.zip`), + gulpZip(`metamask-${target}-${version}.zip`), gulp.dest('builds'), ); }; diff --git a/development/build/manifest.js b/development/build/manifest.js index 340db1272..09df35cbd 100644 --- a/development/build/manifest.js +++ b/development/build/manifest.js @@ -3,6 +3,7 @@ const path = require('path'); const { merge, cloneDeep } = require('lodash'); const baseManifest = require('../../app/manifest/_base.json'); +const { version } = require('../../package.json'); const { createTask, composeSeries } = require('./task'); @@ -23,7 +24,11 @@ function createManifestTasks({ browserPlatforms }) { `${platform}.json`, ), ); - const result = merge(cloneDeep(baseManifest), platformModifications); + const result = merge( + cloneDeep(baseManifest), + { version }, + platformModifications, + ); const dir = path.join('.', 'dist', platform); await fs.mkdir(dir, { recursive: true }); await writeJson(result, path.join(dir, 'manifest.json')); diff --git a/development/build/scripts.js b/development/build/scripts.js index 2bc5fe5c3..f0e399d47 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -20,9 +20,12 @@ const metamaskrc = require('rc')('metamask', { SEGMENT_HOST: process.env.SEGMENT_HOST, SEGMENT_WRITE_KEY: process.env.SEGMENT_WRITE_KEY, SEGMENT_LEGACY_WRITE_KEY: process.env.SEGMENT_LEGACY_WRITE_KEY, + SENTRY_DSN_DEV: + process.env.SENTRY_DSN_DEV || + 'https://f59f3dd640d2429d9d0e2445a87ea8e1@sentry.io/273496', }); -const baseManifest = require('../../app/manifest/_base.json'); +const { version } = require('../../package.json'); const packageJSON = require('../../package.json'); const { @@ -424,13 +427,14 @@ function getEnvironmentVariables({ devMode, testing }) { return { METAMASK_DEBUG: devMode, METAMASK_ENVIRONMENT: environment, - METAMASK_VERSION: baseManifest.version, + METAMASK_VERSION: version, NODE_ENV: devMode ? 'development' : 'production', IN_TEST: testing ? 'true' : false, PUBNUB_SUB_KEY: process.env.PUBNUB_SUB_KEY || '', PUBNUB_PUB_KEY: process.env.PUBNUB_PUB_KEY || '', CONF: devMode ? metamaskrc : {}, SENTRY_DSN: process.env.SENTRY_DSN, + SENTRY_DSN_DEV: metamaskrc.SENTRY_DSN_DEV, INFURA_PROJECT_ID: testing ? '00000000000000000000000000000000' : metamaskrc.INFURA_PROJECT_ID, diff --git a/development/build/static.js b/development/build/static.js index 0adba6745..9ae309e53 100644 --- a/development/build/static.js +++ b/development/build/static.js @@ -35,7 +35,7 @@ const copyTargets = [ dest: `fonts/fontawesome`, }, { - src: `./ui/app/css/output/`, + src: `./ui/css/output/`, pattern: `*.css`, dest: ``, }, diff --git a/development/build/styles.js b/development/build/styles.js index 108561261..ecda4b661 100644 --- a/development/build/styles.js +++ b/development/build/styles.js @@ -18,8 +18,8 @@ function createStyleTasks({ livereload }) { const prod = createTask( 'styles:prod', createScssBuildTask({ - src: 'ui/app/css/index.scss', - dest: 'ui/app/css/output', + src: 'ui/css/index.scss', + dest: 'ui/css/output', devMode: false, }), ); @@ -27,15 +27,15 @@ function createStyleTasks({ livereload }) { const dev = createTask( 'styles:dev', createScssBuildTask({ - src: 'ui/app/css/index.scss', - dest: 'ui/app/css/output', + src: 'ui/css/index.scss', + dest: 'ui/css/output', devMode: true, - pattern: 'ui/app/**/*.scss', + pattern: 'ui/**/*.scss', }), ); const lint = createTask('lint-scss', function () { - return gulp.src('ui/app/css/itcss/**/*.scss').pipe( + return gulp.src('ui/css/itcss/**/*.scss').pipe( gulpStylelint({ reporters: [{ formatter: 'string', console: true }], fix: true, diff --git a/development/lib/changelog/changelog.js b/development/lib/changelog/changelog.js deleted file mode 100644 index b16dca200..000000000 --- a/development/lib/changelog/changelog.js +++ /dev/null @@ -1,305 +0,0 @@ -const semver = require('semver'); - -const { orderedChangeCategories, unreleased } = require('./constants'); - -const changelogTitle = '# Changelog'; -const changelogDescription = `All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).`; - -// Stringification helpers - -function stringifyCategory(category, changes) { - const categoryHeader = `### ${category}`; - if (changes.length === 0) { - return categoryHeader; - } - const changeDescriptions = changes - .map((description) => `- ${description}`) - .join('\n'); - return `${categoryHeader}\n${changeDescriptions}`; -} - -function stringifyRelease(version, categories, { date, status } = {}) { - const releaseHeader = `## [${version}]${date ? ` - ${date}` : ''}${ - status ? ` [${status}]` : '' - }`; - const categorizedChanges = orderedChangeCategories - .filter((category) => categories[category]) - .map((category) => { - const changes = categories[category]; - return stringifyCategory(category, changes); - }) - .join('\n\n'); - if (categorizedChanges === '') { - return releaseHeader; - } - return `${releaseHeader}\n${categorizedChanges}`; -} - -function stringifyReleases(releases, changes) { - const stringifiedUnreleased = stringifyRelease( - unreleased, - changes[unreleased], - ); - const stringifiedReleases = releases.map(({ version, date, status }) => { - const categories = changes[version]; - return stringifyRelease(version, categories, { date, status }); - }); - - return [stringifiedUnreleased, ...stringifiedReleases].join('\n\n'); -} - -function withTrailingSlash(url) { - return url.endsWith('/') ? url : `${url}/`; -} - -function getCompareUrl(repoUrl, firstRef, secondRef) { - return `${withTrailingSlash(repoUrl)}compare/${firstRef}...${secondRef}`; -} - -function getTagUrl(repoUrl, tag) { - return `${withTrailingSlash(repoUrl)}releases/tag/${tag}`; -} - -function stringifyLinkReferenceDefinitions(repoUrl, releases) { - const orderedReleases = releases - .map(({ version }) => version) - .sort((a, b) => semver.gt(a, b)); - - // The "Unreleased" section represents all changes made since the *highest* - // release, not the most recent release. This is to accomodate patch releases - // of older versions that don't represent the latest set of changes. - // - // For example, if a library has a v2.0.0 but the v1.0.0 release needed a - // security update, the v1.0.1 release would then be the most recent, but the - // range of unreleased changes would remain `v2.0.0...HEAD`. - const unreleasedLinkReferenceDefinition = `[${unreleased}]: ${getCompareUrl( - repoUrl, - `v${orderedReleases[0]}`, - 'HEAD', - )}`; - - // The "previous" release that should be used for comparison is not always - // the most recent release chronologically. The _highest_ version that is - // lower than the current release is used as the previous release, so that - // patch releases on older releases can be accomodated. - const releaseLinkReferenceDefinitions = releases - .map(({ version }) => { - if (version === orderedReleases[orderedReleases.length - 1]) { - return `[${version}]: ${getTagUrl(repoUrl, `v${version}`)}`; - } - const versionIndex = orderedReleases.indexOf(version); - const previousVersion = orderedReleases - .slice(versionIndex) - .find((releaseVersion) => { - return semver.gt(version, releaseVersion); - }); - return `[${version}]: ${getCompareUrl( - repoUrl, - `v${previousVersion}`, - `v${version}`, - )}`; - }) - .join('\n'); - return `${unreleasedLinkReferenceDefinition}\n${releaseLinkReferenceDefinitions}${ - releases.length > 0 ? '\n' : '' - }`; -} - -/** - * @typedef {import('./constants.js').Unreleased} Unreleased - * @typedef {import('./constants.js').ChangeCategories ChangeCategories} - */ -/** - * @typedef {import('./constants.js').Version} Version - */ -/** - * Release metadata. - * @typedef {Object} ReleaseMetadata - * @property {string} date - An ISO-8601 formatted date, representing the - * release date. - * @property {string} status -The status of the release (e.g. 'WITHDRAWN', 'DEPRECATED') - * @property {Version} version - The version of the current release. - */ - -/** - * Category changes. A list of changes in a single category. - * @typedef {Array<string>} CategoryChanges - */ - -/** - * Release changes, organized by category - * @typedef {Record<keyof ChangeCategories, CategoryChanges>} ReleaseChanges - */ - -/** - * Changelog changes, organized by release and by category. - * @typedef {Record<Version|Unreleased, ReleaseChanges>} ChangelogChanges - */ - -/** - * A changelog that complies with the ["keep a changelog" v1.1.0 guidelines]{@link https://keepachangelog.com/en/1.0.0/}. - * - * This changelog starts out completely empty, and allows new releases and - * changes to be added such that the changelog remains compliant at all times. - * This can be used to help validate the contents of a changelog, normalize - * formatting, update a changelog, or build one from scratch. - */ -class Changelog { - /** - * Construct an empty changelog - * - * @param {Object} options - * @param {string} options.repoUrl - The GitHub repository URL for the current project - */ - constructor({ repoUrl }) { - this._releases = []; - this._changes = { [unreleased]: {} }; - this._repoUrl = repoUrl; - } - - /** - * Add a release to the changelog - * - * @param {Object} options - * @param {boolean} [options.addToStart] - Determines whether the release is - * added to the top or bottom of the changelog. This defaults to 'true' - * because new releases should be added to the top of the changelog. This - * should be set to 'false' when parsing a changelog top-to-bottom. - * @param {string} [options.date] - An ISO-8601 formatted date, representing the - * release date. - * @param {string} [options.status] - The status of the release (e.g. - * 'WITHDRAWN', 'DEPRECATED') - * @param {Version} options.version - The version of the current release, - * which should be a [semver]{@link https://semver.org/spec/v2.0.0.html}- - * compatible version. - */ - addRelease({ addToStart = true, date, status, version }) { - if (!version) { - throw new Error('Version required'); - } else if (semver.valid(version) === null) { - throw new Error(`Not a valid semver version: '${version}'`); - } else if (this._changes[version]) { - throw new Error(`Release already exists: '${version}'`); - } - - this._changes[version] = {}; - const newRelease = { version, date, status }; - if (addToStart) { - this._releases.unshift(newRelease); - } else { - this._releases.push(newRelease); - } - } - - /** - * Add a change to the changelog - * - * @param {Object} options - * @param {boolean} [options.addToStart] - Determines whether the change is - * added to the top or bottom of the list of changes in this category. This - * defaults to 'true' because changes should be in reverse-chronological - * order. This should be set to 'false' when parsing a changelog top-to- - * bottom. - * @param {string} options.category - The category of the change. - * @param {string} options.description - The description of the change. - * @param {Version} [options.version] - The version this change was released - * in. If this is not given, the change is assumed to be unreleased. - */ - addChange({ addToStart = true, category, description, version }) { - if (!category) { - throw new Error('Category required'); - } else if (!orderedChangeCategories.includes(category)) { - throw new Error(`Unrecognized category: '${category}'`); - } else if (!description) { - throw new Error('Description required'); - } else if (version !== undefined && !this._changes[version]) { - throw new Error(`Specified release version does not exist: '${version}'`); - } - - const release = version - ? this._changes[version] - : this._changes[unreleased]; - - if (!release[category]) { - release[category] = []; - } - if (addToStart) { - release[category].unshift(description); - } else { - release[category].push(description); - } - } - - /** - * Migrate all unreleased changes to a release section. - * - * Changes are migrated in their existing categories, and placed above any - * pre-existing changes in that category. - * - * @param {Version} version - The release version to migrate unreleased - * changes to. - */ - migrateUnreleasedChangesToRelease(version) { - const releaseChanges = this._changes[version]; - if (!releaseChanges) { - throw new Error(`Specified release version does not exist: '${version}'`); - } - - const unreleasedChanges = this._changes[unreleased]; - - for (const category of Object.keys(unreleasedChanges)) { - if (releaseChanges[category]) { - releaseChanges[category] = [ - ...unreleasedChanges[category], - ...releaseChanges[category], - ]; - } else { - releaseChanges[category] = unreleasedChanges[category]; - } - } - this._changes[unreleased] = {}; - } - - /** - * Gets the metadata for all releases. - * @returns {Array<ReleaseMetadata>} The metadata for each release. - */ - getReleases() { - return this._releases; - } - - /** - * Gets the changes in the given release, organized by category. - * @param {Version} version - The version of the release being retrieved. - * @returns {ReleaseChanges} The changes included in the given released. - */ - getReleaseChanges(version) { - return this._changes[version]; - } - - /** - * Gets all changes that have not yet been released - * @returns {ReleaseChanges} The changes that have not yet been released. - */ - getUnreleasedChanges() { - return this._changes[unreleased]; - } - - /** - * The stringified changelog, formatted according to [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - * @returns {string} The stringified changelog. - */ - toString() { - return `${changelogTitle} -${changelogDescription} - -${stringifyReleases(this._releases, this._changes)} - -${stringifyLinkReferenceDefinitions(this._repoUrl, this._releases)}`; - } -} - -module.exports = Changelog; diff --git a/development/lib/changelog/constants.js b/development/lib/changelog/constants.js deleted file mode 100644 index c2b8ae008..000000000 --- a/development/lib/changelog/constants.js +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Version string - * @typedef {string} Version - A [SemVer]{@link https://semver.org/spec/v2.0.0.html}- - * compatible version string. - */ - -/** - * Change categories. - * - * Most of these categories are from [Keep a Changelog]{@link https://keepachangelog.com/en/1.0.0/}. - * The "Uncategorized" category was added because we have many changes from - * older releases that would be difficult to categorize. - * - * @typedef {Record<string, string>} ChangeCategories - * @property {'Added'} Added - for new features. - * @property {'Changed'} Changed - for changes in existing functionality. - * @property {'Deprecated'} Deprecated - for soon-to-be removed features. - * @property {'Fixed'} Fixed - for any bug fixes. - * @property {'Removed'} Removed - for now removed features. - * @property {'Security'} Security - in case of vulnerabilities. - * @property {'Uncategorized'} Uncategorized - for any changes that have not - * yet been categorized. - */ - -/** - * @type {ChangeCategories} - */ -const changeCategories = { - Added: 'Added', - Changed: 'Changed', - Deprecated: 'Deprecated', - Fixed: 'Fixed', - Removed: 'Removed', - Security: 'Security', - Uncategorized: 'Uncategorized', -}; - -/** - * Change categories in the order in which they should be listed in the - * changelog. - * - * @type {Array<keyof ChangeCategories>} - */ -const orderedChangeCategories = [ - 'Uncategorized', - 'Added', - 'Changed', - 'Deprecated', - 'Removed', - 'Fixed', - 'Security', -]; - -/** - * The header for the section of the changelog listing unreleased changes. - * @typedef {'Unreleased'} Unreleased - */ - -/** - * @type {Unreleased} - */ -const unreleased = 'Unreleased'; - -module.exports = { - changeCategories, - orderedChangeCategories, - unreleased, -}; diff --git a/development/lib/changelog/parseChangelog.js b/development/lib/changelog/parseChangelog.js deleted file mode 100644 index 228da3635..000000000 --- a/development/lib/changelog/parseChangelog.js +++ /dev/null @@ -1,84 +0,0 @@ -const Changelog = require('./changelog'); -const { unreleased } = require('./constants'); - -function truncated(line) { - return line.length > 80 ? `${line.slice(0, 80)}...` : line; -} - -/** - * Constructs a Changelog instance that represents the given changelog, which - * is parsed for release and change informatino. - * @param {Object} options - * @param {string} options.changelogContent - The changelog to parse - * @param {string} options.repoUrl - The GitHub repository URL for the current - * project. - * @returns {Changelog} A changelog instance that reflects the changelog text - * provided. - */ -function parseChangelog({ changelogContent, repoUrl }) { - const changelogLines = changelogContent.split('\n'); - const changelog = new Changelog({ repoUrl }); - - const unreleasedHeaderIndex = changelogLines.indexOf(`## [${unreleased}]`); - if (unreleasedHeaderIndex === -1) { - throw new Error(`Failed to find ${unreleased} header`); - } - const unreleasedLinkReferenceDefinition = changelogLines.findIndex((line) => { - return line.startsWith(`[${unreleased}]: `); - }); - if (unreleasedLinkReferenceDefinition === -1) { - throw new Error(`Failed to find ${unreleased} link reference definition`); - } - - const contentfulChangelogLines = changelogLines - .slice(unreleasedHeaderIndex + 1, unreleasedLinkReferenceDefinition) - .filter((line) => line !== ''); - - let mostRecentRelease; - let mostRecentCategory; - for (const line of contentfulChangelogLines) { - if (line.startsWith('## [')) { - const results = line.match( - /^## \[(\d+\.\d+\.\d+)\](?: - (\d\d\d\d-\d\d-\d\d))?(?: \[(\w+)\])?/u, - ); - if (results === null) { - throw new Error(`Malformed release header: '${truncated(line)}'`); - } - mostRecentRelease = results[1]; - mostRecentCategory = undefined; - const date = results[2]; - const status = results[3]; - changelog.addRelease({ - addToStart: false, - date, - status, - version: mostRecentRelease, - }); - } else if (line.startsWith('### ')) { - const results = line.match(/^### (\w+)$\b/u); - if (results === null) { - throw new Error(`Malformed category header: '${truncated(line)}'`); - } - mostRecentCategory = results[1]; - } else if (line.startsWith('- ')) { - if (mostRecentCategory === undefined) { - throw new Error(`Category missing for change: '${truncated(line)}'`); - } - const description = line.slice(2); - changelog.addChange({ - addToStart: false, - category: mostRecentCategory, - description, - version: mostRecentRelease, - }); - } else if (mostRecentRelease === null) { - continue; - } else { - throw new Error(`Unrecognized line: '${truncated(line)}'`); - } - } - - return changelog; -} - -module.exports = { parseChangelog }; diff --git a/development/lib/changelog/updateChangelog.js b/development/lib/changelog/updateChangelog.js deleted file mode 100644 index b94d6caf1..000000000 --- a/development/lib/changelog/updateChangelog.js +++ /dev/null @@ -1,171 +0,0 @@ -const assert = require('assert').strict; -const runCommand = require('../runCommand'); -const { parseChangelog } = require('./parseChangelog'); -const { changeCategories } = require('./constants'); - -async function getMostRecentTag() { - const [mostRecentTagCommitHash] = await runCommand('git', [ - 'rev-list', - '--tags', - '--max-count=1', - ]); - const [mostRecentTag] = await runCommand('git', [ - 'describe', - '--tags', - mostRecentTagCommitHash, - ]); - assert.equal(mostRecentTag[0], 'v', 'Most recent tag should start with v'); - return mostRecentTag; -} - -async function getCommits(commitHashes) { - const commits = []; - for (const commitHash of commitHashes) { - const [subject] = await runCommand('git', [ - 'show', - '-s', - '--format=%s', - commitHash, - ]); - - let prNumber; - let description = subject; - - // Squash & Merge: the commit subject is parsed as `<description> (#<PR ID>)` - if (subject.match(/\(#\d+\)/u)) { - const matchResults = subject.match(/\(#(\d+)\)/u); - prNumber = matchResults[1]; - description = subject.match(/^(.+)\s\(#\d+\)/u)[1]; - // Merge: the PR ID is parsed from the git subject (which is of the form `Merge pull request - // #<PR ID> from <branch>`, and the description is assumed to be the first line of the body. - // If no body is found, the description is set to the commit subject - } else if (subject.match(/#\d+\sfrom/u)) { - const matchResults = subject.match(/#(\d+)\sfrom/u); - prNumber = matchResults[1]; - const [firstLineOfBody] = await runCommand('git', [ - 'show', - '-s', - '--format=%b', - commitHash, - ]); - description = firstLineOfBody || subject; - } - // Otherwise: - // Normal commits: The commit subject is the description, and the PR ID is omitted. - - commits.push({ prNumber, description }); - } - return commits; -} - -function getAllChangeDescriptions(changelog) { - const releases = changelog.getReleases(); - const changeDescriptions = Object.values( - changelog.getUnreleasedChanges(), - ).flat(); - for (const release of releases) { - changeDescriptions.push( - ...Object.values(changelog.getReleaseChanges(release.version)).flat(), - ); - } - return changeDescriptions; -} - -function getAllLoggedPrNumbers(changelog) { - const changeDescriptions = getAllChangeDescriptions(changelog); - - const prNumbersWithChangelogEntries = []; - for (const description of changeDescriptions) { - const matchResults = description.match(/^\[#(\d+)\]/u); - if (matchResults === null) { - continue; - } - const prNumber = matchResults[1]; - prNumbersWithChangelogEntries.push(prNumber); - } - - return prNumbersWithChangelogEntries; -} - -/** - * @typedef {import('./constants.js').Version} Version - */ - -/** - * Update a changelog with any commits made since the last release. Commits for - * PRs that are already included in the changelog are omitted. - * @param {Object} options - * @param {string} options.changelogContent - The current changelog - * @param {Version} options.currentVersion - The current version - * @param {string} options.repoUrl - The GitHub repository URL for the current - * project. - * @param {boolean} options.isReleaseCandidate - Denotes whether the current - * project is in the midst of release preparation or not. If this is set, any - * new changes are listed under the current release header. Otherwise, they - * are listed under the 'Unreleased' section. - * @returns - */ -async function updateChangelog({ - changelogContent, - currentVersion, - repoUrl, - isReleaseCandidate, -}) { - const changelog = parseChangelog({ changelogContent, repoUrl }); - - // Ensure we have all tags on remote - await runCommand('git', ['fetch', '--tags']); - const mostRecentTag = await getMostRecentTag(); - const commitsHashesSinceLastRelease = await runCommand('git', [ - 'rev-list', - `${mostRecentTag}..HEAD`, - ]); - const commits = await getCommits(commitsHashesSinceLastRelease); - - const loggedPrNumbers = getAllLoggedPrNumbers(changelog); - const newCommits = commits.filter( - ({ prNumber }) => !loggedPrNumbers.includes(prNumber), - ); - - const hasUnreleasedChanges = changelog.getUnreleasedChanges().length !== 0; - if ( - newCommits.length === 0 && - (!isReleaseCandidate || hasUnreleasedChanges) - ) { - return undefined; - } - - // Ensure release header exists, if necessary - if ( - isReleaseCandidate && - !changelog - .getReleases() - .find((release) => release.version === currentVersion) - ) { - changelog.addRelease({ version: currentVersion }); - } - - if (isReleaseCandidate && hasUnreleasedChanges) { - changelog.migrateUnreleasedChangesToRelease(currentVersion); - } - - const newChangeEntries = newCommits.map(({ prNumber, description }) => { - if (prNumber) { - const prefix = `[#${prNumber}](${repoUrl}/pull/${prNumber})`; - return `${prefix}: ${description}`; - } - return description; - }); - - for (const description of newChangeEntries.reverse()) { - changelog.addChange({ - version: isReleaseCandidate ? currentVersion : undefined, - category: changeCategories.Uncategorized, - description, - }); - } - - return changelog.toString(); -} - -module.exports = { updateChangelog }; diff --git a/development/lib/runCommand.js b/development/lib/run-command.js similarity index 57% rename from development/lib/runCommand.js rename to development/lib/run-command.js index 2d92ffe99..08bffcc1b 100644 --- a/development/lib/runCommand.js +++ b/development/lib/run-command.js @@ -76,4 +76,59 @@ async function runCommand(command, args) { return output; } -module.exports = runCommand; +/** + * Run a command to using the system shell. + * + * This will run a command with the specified arguments, and resolve when the + * process has exited. The STDIN, STDOUT and STDERR streams are inherited, + * letting the command take over completely until it completes. The success or + * failure of the process is determined entirely by the exit code; STDERR + * output is not used to indicate failure. + * + * @param {string} command - The command to run + * @param {Array<string>} [args] - The arguments to pass to the command + */ +async function runInShell(command, args) { + let errorSignal; + let errorCode; + const internalError = new Error('Internal'); + try { + await new Promise((resolve, reject) => { + const childProcess = spawn(command, args, { + encoding: 'utf8', + stdio: 'inherit', + }); + + childProcess.once('exit', (code, signal) => { + if (code === 0) { + return resolve(); + } + errorCode = code; + errorSignal = signal; + return reject(internalError); + }); + }); + } catch (error) { + /** + * The error is re-thrown here in an `async` context to preserve the stack trace. If this was + * was thrown inside the Promise constructor, the stack trace would show a few frames of + * Node.js internals then end, without indicating where `runInShell` was called. + */ + if (error === internalError) { + let errorMessage; + if (errorCode !== null && errorSignal !== null) { + errorMessage = `Terminated by signal '${errorSignal}'; exited with code '${errorCode}'`; + } else if (errorSignal !== null) { + errorMessage = `Terminaled by signal '${errorSignal}'`; + } else if (errorCode === null) { + errorMessage = 'Exited with no code or signal'; + } else { + errorMessage = `Exited with code '${errorCode}'`; + } + const improvedError = new Error(errorMessage); + throw improvedError; + } + } +} + +module.exports = { runCommand, runInShell }; diff --git a/development/sentry-publish.js b/development/sentry-publish.js index 6fee0f950..81fa58790 100644 --- a/development/sentry-publish.js +++ b/development/sentry-publish.js @@ -1,9 +1,6 @@ #!/usr/bin/env node -const childProcess = require('child_process'); -const pify = require('pify'); - -const exec = pify(childProcess.exec, { multiArgs: true }); const VERSION = require('../dist/chrome/manifest.json').version; // eslint-disable-line import/no-unresolved +const { runCommand, runInShell } = require('./lib/run-command'); start().catch((error) => { console.error(error); @@ -11,6 +8,12 @@ start().catch((error) => { }); async function start() { + if (!process.env.SENTRY_ORG) { + throw new Error('Missing required "SENTRY_ORG" environment variable'); + } else if (!process.env.SENTRY_PROJECT) { + throw new Error('Missing required "SENTRY_PROJECT" environment variable'); + } + const authWorked = await checkIfAuthWorks(); if (!authWorked) { throw new Error(`Sentry auth failed`); @@ -25,15 +28,17 @@ async function start() { } else { // create sentry release console.log(`creating Sentry release for "${VERSION}"...`); - await exec( - `sentry-cli releases --org 'metamask' --project 'metamask' new ${VERSION}`, - ); + await runCommand('sentry-cli', ['releases', 'new', VERSION]); console.log( `removing any existing files from Sentry release "${VERSION}"...`, ); - await exec( - `sentry-cli releases --org 'metamask' --project 'metamask' files ${VERSION} delete --all`, - ); + await runCommand('sentry-cli', [ + 'releases', + 'files', + VERSION, + 'delete', + '--all', + ]); } // check if version has artifacts or not @@ -47,40 +52,43 @@ async function start() { } // upload sentry source and sourcemaps - await exec(`./development/sentry-upload-artifacts.sh --release ${VERSION}`); + await runInShell('./development/sentry-upload-artifacts.sh', [ + '--release', + VERSION, + ]); } async function checkIfAuthWorks() { - const itWorked = await doesNotFail(async () => { - await exec( - `sentry-cli releases --org 'metamask' --project 'metamask' list`, - ); - }); - return itWorked; + return await doesNotFail(() => + runCommand('sentry-cli', ['releases', 'list']), + ); } async function checkIfVersionExists() { - const versionAlreadyExists = await doesNotFail(async () => { - await exec( - `sentry-cli releases --org 'metamask' --project 'metamask' info ${VERSION}`, - ); - }); - return versionAlreadyExists; + return await doesNotFail(() => + runCommand('sentry-cli', ['releases', 'info', VERSION]), + ); } async function checkIfVersionHasArtifacts() { - const artifacts = await exec( - `sentry-cli releases --org 'metamask' --project 'metamask' files ${VERSION} list`, - ); + const [artifact] = await runCommand('sentry-cli', [ + 'releases', + 'files', + VERSION, + 'list', + ]); // When there's no artifacts, we get a response from the shell like this ['', ''] - return artifacts[0] && artifacts[0].length > 0; + return artifact?.length > 0; } async function doesNotFail(asyncFn) { try { await asyncFn(); return true; - } catch (err) { - return false; + } catch (error) { + if (error.message === `Exited with code '1'`) { + return false; + } + throw error; } } diff --git a/development/sentry-upload-artifacts.sh b/development/sentry-upload-artifacts.sh index 3a605eff2..673e1dd73 100755 --- a/development/sentry-upload-artifacts.sh +++ b/development/sentry-upload-artifacts.sh @@ -1,6 +1,5 @@ #!/usr/bin/env bash -set -x set -e set -u set -o pipefail @@ -30,7 +29,7 @@ EOF function upload_sourcemaps { local release="${1}"; shift - sentry-cli releases --org 'metamask' --project 'metamask' files "${release}" upload-sourcemaps ./dist/chrome/*.js ./dist/sourcemaps/ --rewrite --url-prefix 'metamask' + sentry-cli releases files "${release}" upload-sourcemaps ./dist/chrome/*.js ./dist/sourcemaps/ --rewrite --url-prefix 'metamask' } function main { @@ -62,6 +61,12 @@ function main { if [[ -z $release ]] then die 'Required parameter "release" missing; either include parameter or set VERSION environment variable' + elif [[ -z $SENTRY_ORG ]] + then + die 'Required environment variable "SENTRY_ORG" missing' + elif [[ -z $SENTRY_PROJECT ]] + then + die 'Required environment variable "SENTRY_PROJECT" missing' fi printf 'uploading source files and sourcemaps for Sentry release "%s"...\n' "${release}" diff --git a/development/verify-locale-strings.js b/development/verify-locale-strings.js index 2e7b7584b..a37a7936e 100644 --- a/development/verify-locale-strings.js +++ b/development/verify-locale-strings.js @@ -171,8 +171,8 @@ async function verifyEnglishLocale() { // In the meantime we'll use glob to specify which paths can be strict searched // and gradually phase out the key based search const globsToStrictSearch = [ - 'ui/app/components/app/metamask-translation/*.js', - 'ui/app/pages/confirmation/templates/*.js', + 'ui/components/app/metamask-translation/*.js', + 'ui/pages/confirmation/templates/*.js', ]; const testGlob = '**/*.test.js'; const javascriptFiles = await glob(['ui/**/*.js', 'shared/**/*.js'], { diff --git a/jest.config.js b/jest.config.js index df0558fcf..6fce2ce4d 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,12 +1,12 @@ module.exports = { restoreMocks: true, coverageDirectory: 'jest-coverage/', - collectCoverageFrom: ['<rootDir>/ui/app/**/swaps/**'], + collectCoverageFrom: ['<rootDir>/ui/**/swaps/**'], coveragePathIgnorePatterns: ['.stories.js', '.snap'], coverageThreshold: { global: { branches: 32.75, - functions: 43.31, + functions: 42.9, lines: 43.12, statements: 43.67, }, diff --git a/jsconfig.json b/jsconfig.json index d0e8e66fc..b0cc155d5 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -1,3 +1,14 @@ { - "exclude": ["node:console"] + "exclude": [ + "*.log", + "builds", + "coverage", + "dist", + "docs", + "lavamoat", + "node:console", + "node_modules", + "patches", + "test-artifacts" + ] } diff --git a/lavamoat/node/policy.json b/lavamoat/node/policy.json index 56892f1bf..e744f1175 100644 --- a/lavamoat/node/policy.json +++ b/lavamoat/node/policy.json @@ -223,6 +223,11 @@ "js-tokens": true } }, + "@babel/parser": { + "globals": { + "BigInt": true + } + }, "@babel/plugin-proposal-async-generator-functions": { "packages": { "@babel/core": true, @@ -869,6 +874,7 @@ }, "acorn": { "globals": { + "BigInt": true, "define": true } }, @@ -878,6 +884,9 @@ } }, "acorn-node": { + "globals": { + "BigInt": true + }, "packages": { "acorn": true, "acorn-dynamic-import": true, @@ -950,6 +959,16 @@ "buffer-equal": true } }, + "are-we-there-yet": { + "builtin": { + "events.EventEmitter": true, + "util.inherits": true + }, + "packages": { + "delegates": true, + "readable-stream": true + } + }, "arr-diff": { "packages": { "arr-flatten": true, @@ -1302,6 +1321,7 @@ "anymatch": true, "async-each": true, "braces": true, + "fsevents": true, "glob-parent": true, "inherits": true, "is-binary-path": true, @@ -1553,6 +1573,16 @@ "through2": true } }, + "detect-libc": { + "builtin": { + "child_process.spawnSync": true, + "fs.readdirSync": true, + "os.platform": true + }, + "globals": { + "process.env": true + } + }, "detective": { "packages": { "acorn-node": true, @@ -1640,7 +1670,10 @@ "es-abstract": { "globals": { "AggregateError": true, + "Atomics": true, + "BigInt": true, "FinalizationRegistry": true, + "SharedArrayBuffer": true, "WeakRef": true }, "packages": { @@ -1993,6 +2026,45 @@ "process.version": true } }, + "fsevents": { + "builtin": { + "events.EventEmitter": true, + "fs.stat": true, + "path.join": true, + "util.inherits": true + }, + "globals": { + "__dirname": true, + "process.nextTick": true, + "process.platform": true, + "setImmediate": true + }, + "native": true, + "packages": { + "node-pre-gyp": true + } + }, + "gauge": { + "builtin": { + "util.format": true + }, + "globals": { + "clearInterval": true, + "process": true, + "setImmediate": true, + "setInterval": true + }, + "packages": { + "aproba": true, + "console-control-strings": true, + "has-unicode": true, + "object-assign": true, + "signal-exit": true, + "string-width": true, + "strip-ansi": true, + "wide-align": true + } + }, "get-assigned-identifiers": { "builtin": { "assert.equal": true @@ -2373,6 +2445,16 @@ "process.argv": true } }, + "has-unicode": { + "builtin": { + "os.type": true + }, + "globals": { + "process.env.LANG": true, + "process.env.LC_ALL": true, + "process.env.LC_CTYPE": true + } + }, "has-value": { "packages": { "get-value": true, @@ -2526,6 +2608,11 @@ "is-plain-object": true } }, + "is-fullwidth-code-point": { + "packages": { + "number-is-nan": true + } + }, "is-glob": { "packages": { "is-extglob": true @@ -2910,6 +2997,56 @@ "setTimeout": true } }, + "node-pre-gyp": { + "builtin": { + "events.EventEmitter": true, + "fs.existsSync": true, + "fs.readFileSync": true, + "fs.renameSync": true, + "path.dirname": true, + "path.existsSync": true, + "path.join": true, + "path.resolve": true, + "url.parse": true, + "url.resolve": true, + "util.inherits": true + }, + "globals": { + "__dirname": true, + "console.log": true, + "process.arch": true, + "process.cwd": true, + "process.env": true, + "process.platform": true, + "process.version.substr": true, + "process.versions": true + }, + "packages": { + "detect-libc": true, + "nopt": true, + "npmlog": true, + "rimraf": true, + "semver": true + } + }, + "nopt": { + "builtin": { + "path": true, + "stream.Stream": true, + "url": true + }, + "globals": { + "console": true, + "process.argv": true, + "process.env.DEBUG_NOPT": true, + "process.env.NOPT_DEBUG": true, + "process.platform": true + }, + "packages": { + "abbrev": true, + "osenv": true + } + }, "normalize-path": { "packages": { "remove-trailing-separator": true @@ -2925,6 +3062,22 @@ "once": true } }, + "npmlog": { + "builtin": { + "events.EventEmitter": true, + "util": true + }, + "globals": { + "process.nextTick": true, + "process.stderr": true + }, + "packages": { + "are-we-there-yet": true, + "console-control-strings": true, + "gauge": true, + "set-blocking": true + } + }, "object-copy": { "packages": { "copy-descriptor": true, @@ -2937,6 +3090,7 @@ "util.inspect": true }, "globals": { + "BigInt": true, "HTMLElement": true } }, @@ -2991,6 +3145,54 @@ "readable-stream": true } }, + "os-homedir": { + "builtin": { + "os.homedir": true + }, + "globals": { + "process.env": true, + "process.getuid": true, + "process.platform": true + } + }, + "os-tmpdir": { + "globals": { + "process.env.SystemRoot": true, + "process.env.TEMP": true, + "process.env.TMP": true, + "process.env.TMPDIR": true, + "process.env.windir": true, + "process.platform": true + } + }, + "osenv": { + "builtin": { + "child_process.exec": true, + "path": true + }, + "globals": { + "process.env.COMPUTERNAME": true, + "process.env.ComSpec": true, + "process.env.EDITOR": true, + "process.env.HOSTNAME": true, + "process.env.PATH": true, + "process.env.PROMPT": true, + "process.env.PS1": true, + "process.env.Path": true, + "process.env.SHELL": true, + "process.env.USER": true, + "process.env.USERDOMAIN": true, + "process.env.USERNAME": true, + "process.env.VISUAL": true, + "process.env.path": true, + "process.nextTick": true, + "process.platform": true + }, + "packages": { + "os-homedir": true, + "os-tmpdir": true + } + }, "parent-module": { "packages": { "callsites": true @@ -3573,6 +3775,12 @@ "process": true } }, + "set-blocking": { + "globals": { + "process.stderr": true, + "process.stdout": true + } + }, "set-value": { "packages": { "extend-shallow": true, @@ -3766,6 +3974,7 @@ }, "string-width": { "packages": { + "code-point-at": true, "emoji-regex": true, "is-fullwidth-code-point": true, "strip-ansi": true @@ -4322,6 +4531,11 @@ "isexe": true } }, + "wide-align": { + "packages": { + "string-width": true + } + }, "write": { "builtin": { "fs.createWriteStream": true, diff --git a/package.json b/package.json index f6e3c4dc6..f50426cbe 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,11 @@ { "name": "metamask-crx", - "version": "0.0.0", + "version": "9.5.9", "private": true, + "repository": { + "type": "git", + "url": "https://github.com/MetaMask/metamask-extension.git" + }, "scripts": { "setup": "yarn install && yarn setup:postinstall", "setup:postinstall": "yarn patch-package && yarn allow-scripts", @@ -49,7 +53,7 @@ "verify-locales": "node ./development/verify-locale-strings.js", "verify-locales:fix": "node ./development/verify-locale-strings.js --fix", "mozilla-lint": "addons-linter dist/firefox", - "watch": "mocha --watch --require test/env.js --require test/setup.js --reporter min --recursive \"test/unit/**/*.js\" \"ui/app/**/*.test.js\" \"shared/**/*.test.js\"", + "watch": "mocha --watch --require test/env.js --require test/setup.js --reporter min --recursive \"test/unit/**/*.js\" \"ui/**/*.test.js\" \"shared/**/*.test.js\"", "devtools:react": "react-devtools", "devtools:redux": "remotedev --hostname=localhost --port=8000", "start:dev": "concurrently -k -n build,react,redux yarn:start yarn:devtools:react yarn:devtools:redux", @@ -57,7 +61,7 @@ "storybook": "start-storybook -p 6006 -c .storybook --static-dir ./app ./storybook/images", "storybook:build": "build-storybook -c .storybook -o storybook-build --static-dir ./app ./storybook/images", "storybook:deploy": "storybook-to-ghpages --existing-output-dir storybook-build --remote storybook --branch master", - "update-changelog": "node ./development/auto-changelog.js", + "update-changelog": "auto-changelog update", "generate:migration": "./development/generate-migration.sh", "lavamoat:auto": "lavamoat ./development/build/index.js --writeAutoPolicy", "lavamoat:debug": "lavamoat ./development/build/index.js --writeAutoPolicyDebug" @@ -93,14 +97,15 @@ "@lavamoat/preinstall-always-fail": "^1.0.0", "@material-ui/core": "^4.11.0", "@metamask/contract-metadata": "^1.22.0", - "@metamask/controllers": "^6.2.1", - "@metamask/eth-ledger-bridge-keyring": "^0.4.0", + "@metamask/controllers": "^9.0.0", + "@metamask/eth-ledger-bridge-keyring": "^0.5.0", "@metamask/eth-token-tracker": "^3.0.1", - "@metamask/etherscan-link": "^2.0.0", - "@metamask/inpage-provider": "^8.0.4", + "@metamask/etherscan-link": "^2.1.0", "@metamask/jazzicon": "^2.0.0", "@metamask/logo": "^2.5.0", "@metamask/obs-store": "^5.0.0", + "@metamask/post-message-stream": "^4.0.0", + "@metamask/providers": "^8.1.1", "@popperjs/core": "^2.4.0", "@reduxjs/toolkit": "^1.5.0", "@sentry/browser": "^5.26.0", @@ -160,7 +165,6 @@ "nonce-tracker": "^1.0.0", "obj-multiplex": "^1.0.0", "pify": "^5.0.0", - "post-message-stream": "^3.0.0", "promise-to-callback": "^1.0.0", "prop-types": "^15.6.1", "pubnub": "4.27.3", @@ -207,7 +211,8 @@ "@babel/preset-env": "^7.5.5", "@babel/preset-react": "^7.0.0", "@babel/register": "^7.5.5", - "@lavamoat/allow-scripts": "^1.0.4", + "@lavamoat/allow-scripts": "^1.0.6", + "@metamask/auto-changelog": "^2.1.0", "@metamask/eslint-config": "^6.0.0", "@metamask/eslint-config-jest": "^6.0.0", "@metamask/eslint-config-mocha": "^6.0.0", @@ -267,6 +272,7 @@ "gulp-terser-js": "^5.2.2", "gulp-watch": "^5.0.1", "gulp-zip": "^4.0.0", + "history": "^5.0.0", "jest": "^26.6.3", "jsdom": "^11.2.0", "koa": "^2.7.0", @@ -331,7 +337,8 @@ "gc-stats": false, "github:assemblyscript/assemblyscript": false, "tiny-secp256k1": false, - "@lavamoat/preinstall-always-fail": false + "@lavamoat/preinstall-always-fail": false, + "fsevents": false } } } diff --git a/shared/constants/app.js b/shared/constants/app.js index 93c843846..7e1b66572 100644 --- a/shared/constants/app.js +++ b/shared/constants/app.js @@ -28,5 +28,5 @@ export const MESSAGE_TYPE = { WATCH_ASSET: 'wallet_watchAsset', WATCH_ASSET_LEGACY: 'metamask_watchAsset', ADD_ETHEREUM_CHAIN: 'wallet_addEthereumChain', - SWITCH_ETHEREUM_CHAIN: 'metamask_switchEthereumChain', + SWITCH_ETHEREUM_CHAIN: 'wallet_switchEthereumChain', }; diff --git a/shared/constants/swaps.js b/shared/constants/swaps.js index 3f345542b..42a2167f3 100644 --- a/shared/constants/swaps.js +++ b/shared/constants/swaps.js @@ -12,6 +12,7 @@ export const QUOTES_EXPIRED_ERROR = 'quotes-expired'; export const SWAP_FAILED_ERROR = 'swap-failed-error'; export const ERROR_FETCHING_QUOTES = 'error-fetching-quotes'; export const QUOTES_NOT_AVAILABLE_ERROR = 'quotes-not-avilable'; +export const CONTRACT_DATA_DISABLED_ERROR = 'contract-data-disabled'; export const OFFLINE_FOR_MAINTENANCE = 'offline-for-maintenance'; export const SWAPS_FETCH_ORDER_CONFLICT = 'swaps-fetch-order-conflict'; @@ -62,6 +63,7 @@ const SWAPS_TESTNET_CHAIN_ID = '0x539'; const SWAPS_TESTNET_HOST = 'https://metaswap-api.airswap-dev.codefi.network'; const BSC_DEFAULT_BLOCK_EXPLORER_URL = 'https://bscscan.com/'; +const MAINNET_DEFAULT_BLOCK_EXPLORER_URL = 'https://etherscan.io/'; export const ALLOWED_SWAPS_CHAIN_IDS = { [MAINNET_CHAIN_ID]: true, @@ -89,4 +91,5 @@ export const SWAPS_CHAINID_DEFAULT_TOKEN_MAP = { export const SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP = { [BSC_CHAIN_ID]: BSC_DEFAULT_BLOCK_EXPLORER_URL, + [MAINNET_CHAIN_ID]: MAINNET_DEFAULT_BLOCK_EXPLORER_URL, }; diff --git a/shared/modules/fetch-with-timeout.test.js b/shared/modules/fetch-with-timeout.test.js index a7b1daa1a..3b9ce1552 100644 --- a/shared/modules/fetch-with-timeout.test.js +++ b/shared/modules/fetch-with-timeout.test.js @@ -1,4 +1,4 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import nock from 'nock'; import getFetchWithTimeout from './fetch-with-timeout'; diff --git a/shared/modules/tests/transaction.utils.test.js b/shared/modules/tests/transaction.utils.test.js deleted file mode 100644 index 2aac76828..000000000 --- a/shared/modules/tests/transaction.utils.test.js +++ /dev/null @@ -1,96 +0,0 @@ -import assert from 'assert'; -import { - MAINNET_CHAIN_ID, - MAINNET_NETWORK_ID, - ROPSTEN_CHAIN_ID, - ROPSTEN_NETWORK_ID, -} from '../../constants/network'; -import { getBlockExplorerUrlForTx } from '../transaction.utils'; - -const tests = [ - { - expected: 'https://etherscan.io/tx/0xabcd', - transaction: { - metamaskNetworkId: MAINNET_NETWORK_ID, - hash: '0xabcd', - }, - }, - { - expected: 'https://ropsten.etherscan.io/tx/0xdef0', - transaction: { - metamaskNetworkId: ROPSTEN_NETWORK_ID, - hash: '0xdef0', - }, - rpcPrefs: {}, - }, - { - // test handling of `blockExplorerUrl` for a custom RPC - expected: 'https://block.explorer/tx/0xabcd', - transaction: { - metamaskNetworkId: '31', - hash: '0xabcd', - }, - rpcPrefs: { - blockExplorerUrl: 'https://block.explorer', - }, - }, - { - // test handling of trailing `/` in `blockExplorerUrl` for a custom RPC - expected: 'https://another.block.explorer/tx/0xdef0', - transaction: { - networkId: '33', - hash: '0xdef0', - }, - rpcPrefs: { - blockExplorerUrl: 'https://another.block.explorer/', - }, - }, - { - expected: 'https://etherscan.io/tx/0xabcd', - transaction: { - chainId: MAINNET_CHAIN_ID, - hash: '0xabcd', - }, - }, - { - expected: 'https://ropsten.etherscan.io/tx/0xdef0', - transaction: { - chainId: ROPSTEN_CHAIN_ID, - hash: '0xdef0', - }, - rpcPrefs: {}, - }, - { - // test handling of `blockExplorerUrl` for a custom RPC - expected: 'https://block.explorer/tx/0xabcd', - transaction: { - chainId: '0x1f', - hash: '0xabcd', - }, - rpcPrefs: { - blockExplorerUrl: 'https://block.explorer', - }, - }, - { - // test handling of trailing `/` in `blockExplorerUrl` for a custom RPC - expected: 'https://another.block.explorer/tx/0xdef0', - transaction: { - chainId: '0x21', - hash: '0xdef0', - }, - rpcPrefs: { - blockExplorerUrl: 'https://another.block.explorer/', - }, - }, -]; - -describe('getBlockExplorerUrlForTx', function () { - tests.forEach((test) => { - it(`should return '${test.expected}' for transaction with hash: '${test.transaction.hash}'`, function () { - assert.strictEqual( - getBlockExplorerUrlForTx(test.transaction, test.rpcPrefs), - test.expected, - ); - }); - }); -}); diff --git a/shared/modules/transaction.utils.js b/shared/modules/transaction.utils.js index 47a0a4334..9e89679f8 100644 --- a/shared/modules/transaction.utils.js +++ b/shared/modules/transaction.utils.js @@ -1,37 +1,6 @@ -import { - createExplorerLink, - createExplorerLinkForChain, -} from '@metamask/etherscan-link'; - export function transactionMatchesNetwork(transaction, chainId, networkId) { if (typeof transaction.chainId !== 'undefined') { return transaction.chainId === chainId; } return transaction.metamaskNetworkId === networkId; } - -/** - * build the etherscan link for a transaction by either chainId, if available - * or metamaskNetworkId as a fallback. If rpcPrefs is provided will build the - * url for the provided blockExplorerUrl. - * - * @param {Object} transaction - a transaction object from state - * @param {string} [transaction.metamaskNetworkId] - network id tx occurred on - * @param {string} [transaction.chainId] - chain id tx occurred on - * @param {string} [transaction.hash] - hash of the transaction - * @param {Object} [rpcPrefs] - the rpc preferences for the current RPC network - * @param {string} [rpcPrefs.blockExplorerUrl] - the block explorer url for RPC - * networks - * @returns {string} - */ -export function getBlockExplorerUrlForTx(transaction, rpcPrefs = {}) { - if (rpcPrefs.blockExplorerUrl) { - return `${rpcPrefs.blockExplorerUrl.replace(/\/+$/u, '')}/tx/${ - transaction.hash - }`; - } - if (transaction.chainId) { - return createExplorerLinkForChain(transaction.hash, transaction.chainId); - } - return createExplorerLink(transaction.hash, transaction.metamaskNetworkId); -} diff --git a/shared/notifications/index.js b/shared/notifications/index.js index efbc87223..a2604a32e 100644 --- a/shared/notifications/index.js +++ b/shared/notifications/index.js @@ -10,14 +10,22 @@ export const UI_NOTIFICATIONS = { placeImageBelowDescription: true, }, }, - 2: { - id: 2, - date: '2020-08-31', - }, 3: { id: 3, date: '2021-03-08', }, + 4: { + id: 4, + date: '2021-05-11', + image: { + src: 'images/source-logos-bsc.svg', + width: '100%', + }, + }, + 5: { + id: 5, + date: '2021-05-18', + }, 6: { id: 6, date: '2021-05-26', @@ -35,15 +43,6 @@ export const getTranslatedUINoficiations = (t, locale) => { new Date(UI_NOTIFICATIONS[1].date), ), }, - 2: { - ...UI_NOTIFICATIONS[2], - title: t('notifications2Title'), - description: t('notifications2Description'), - actionText: t('notifications2ActionText'), - date: new Intl.DateTimeFormat(formattedLocale).format( - new Date(UI_NOTIFICATIONS[2].date), - ), - }, 3: { ...UI_NOTIFICATIONS[3], title: t('notifications3Title'), @@ -53,6 +52,24 @@ export const getTranslatedUINoficiations = (t, locale) => { new Date(UI_NOTIFICATIONS[3].date), ), }, + 4: { + ...UI_NOTIFICATIONS[4], + title: t('notifications4Title'), + description: t('notifications4Description'), + actionText: t('notifications4ActionText'), + date: new Intl.DateTimeFormat(formattedLocale).format( + new Date(UI_NOTIFICATIONS[4].date), + ), + }, + 5: { + ...UI_NOTIFICATIONS[5], + title: t('walletSeed'), + description: t('notifications5Description'), + actionText: t('notifications3ActionText'), + date: new Intl.DateTimeFormat(formattedLocale).format( + new Date(UI_NOTIFICATIONS[5].date), + ), + }, 6: { ...UI_NOTIFICATIONS[6], title: t('notifications6Title'), diff --git a/test/data/mock-state.json b/test/data/mock-state.json index 412892d9a..caaa378d8 100644 --- a/test/data/mock-state.json +++ b/test/data/mock-state.json @@ -15,6 +15,12 @@ "provider": { "chainId": "0x4" }, + "keyrings": [ + { + "type": "Ledger Hardware", + "accounts": ["0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc"] + } + ], "identities": { "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc": { "address": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc", diff --git a/test/e2e/fixtures/address-entry/state.json b/test/e2e/fixtures/address-entry/state.json index 1c6f7c010..0bc9f3b9d 100644 --- a/test/e2e/fixtures/address-entry/state.json +++ b/test/e2e/fixtures/address-entry/state.json @@ -55,10 +55,10 @@ "1": { "isShown": true }, - "2": { + "3": { "isShown": true }, - "3": { + "5": { "isShown": true }, "6": { diff --git a/test/e2e/fixtures/connected-state/state.json b/test/e2e/fixtures/connected-state/state.json index b4f9f8e11..baebea6b7 100644 --- a/test/e2e/fixtures/connected-state/state.json +++ b/test/e2e/fixtures/connected-state/state.json @@ -45,10 +45,10 @@ "1": { "isShown": true }, - "2": { + "3": { "isShown": true }, - "3": { + "5": { "isShown": true }, "6": { diff --git a/test/e2e/fixtures/custom-rpc/state.json b/test/e2e/fixtures/custom-rpc/state.json new file mode 100644 index 000000000..aa93a938c --- /dev/null +++ b/test/e2e/fixtures/custom-rpc/state.json @@ -0,0 +1,153 @@ +{ + "data": { + "AppStateController": { + "mkrMigrationReminderTimestamp": null + }, + "CachedBalancesController": { + "cachedBalances": { + "4": {} + } + }, + "CurrencyController": { + "conversionDate": 1575697244.188, + "conversionRate": 149.61, + "currentCurrency": "usd", + "nativeCurrency": "ETH" + }, + "IncomingTransactionsController": { + "incomingTransactions": {}, + "incomingTxLastFetchedBlocksByNetwork": { + "goerli": null, + "kovan": null, + "mainnet": null, + "rinkeby": 5570536 + } + }, + "KeyringController": { + "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" + }, + "NetworkController": { + "network": "1337", + "provider": { + "nickname": "Localhost 8545", + "rpcUrl": "http://localhost:8545", + "chainId": "0x539", + "ticker": "ETH", + "type": "rpc" + } + }, + "NotificationController": { + "notifications": { + "1": { + "isShown": true + }, + "3": { + "isShown": true + }, + "5": { + "isShown": true + }, + "6": { + "isShown": true + } + } + }, + "OnboardingController": { + "onboardingTabs": {}, + "seedPhraseBackedUp": false + }, + "PermissionsMetadata": { + "domainMetadata": { + "metamask.github.io": { + "icon": null, + "name": "M E T A M A S K M E S H T E S T" + } + }, + "permissionsHistory": {}, + "permissionsLog": [ + { + "id": 746677923, + "method": "eth_accounts", + "methodType": "restricted", + "origin": "metamask.github.io", + "request": { + "id": 746677923, + "jsonrpc": "2.0", + "method": "eth_accounts", + "origin": "metamask.github.io", + "params": [] + }, + "requestTime": 1575697241368, + "response": { + "id": 746677923, + "jsonrpc": "2.0", + "result": [] + }, + "responseTime": 1575697241370, + "success": true + } + ] + }, + "PreferencesController": { + "frequentRpcListDetail": [ + { + "rpcUrl": "http://127.0.0.1:8545/1", + "chainId": "0x539", + "ticker": "ETH", + "nickname": "http://127.0.0.1:8545/1", + "rpcPrefs": {} + }, + { + "rpcUrl": "http://127.0.0.1:8545/2", + "chainId": "0x539", + "ticker": "ETH", + "nickname": "http://127.0.0.1:8545/2", + "rpcPrefs": {} + } + ], + "accountTokens": { + "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { + "rinkeby": [], + "ropsten": [] + } + }, + "assetImages": {}, + "completedOnboarding": true, + "currentLocale": "en", + "featureFlags": { + "showIncomingTransactions": true, + "transactionTime": false + }, + "firstTimeFlowType": "create", + "forgottenPassword": false, + "identities": { + "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { + "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", + "name": "Account 1" + } + }, + "knownMethodData": {}, + "lostIdentities": {}, + "metaMetricsId": null, + "metaMetricsSendCount": 0, + "participateInMetaMetrics": false, + "preferences": { + "useNativeCurrencyAsPrimaryCurrency": true + }, + "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", + "suggestedTokens": {}, + "tokens": [], + "useBlockie": false, + "useNonceField": false, + "usePhishDetect": true + }, + "config": {}, + "firstTimeInfo": { + "date": 1575697234195, + "version": "7.7.0" + } + }, + "meta": { + "version": 40 + } +} diff --git a/test/e2e/fixtures/custom-token/state.json b/test/e2e/fixtures/custom-token/state.json new file mode 100644 index 000000000..1d3a24437 --- /dev/null +++ b/test/e2e/fixtures/custom-token/state.json @@ -0,0 +1,151 @@ +{ + "data": { + "AppStateController": { + "mkrMigrationReminderTimestamp": null + }, + "CachedBalancesController": { + "cachedBalances": { + "4": {} + } + }, + "CurrencyController": { + "conversionDate": 1575697244.188, + "conversionRate": 149.61, + "currentCurrency": "usd", + "nativeCurrency": "ETH" + }, + "IncomingTransactionsController": { + "incomingTransactions": {}, + "incomingTxLastFetchedBlocksByNetwork": { + "goerli": null, + "kovan": null, + "mainnet": null, + "rinkeby": 5570536 + } + }, + "KeyringController": { + "vault": "{\"data\":\"s6TpYjlUNsn7ifhEFTkuDGBUM1GyOlPrim7JSjtfIxgTt8/6MiXgiR/CtFfR4dWW2xhq85/NGIBYEeWrZThGdKGarBzeIqBfLFhw9n509jprzJ0zc2Rf+9HVFGLw+xxC4xPxgCS0IIWeAJQ+XtGcHmn0UZXriXm8Ja4kdlow6SWinB7sr/WM3R0+frYs4WgllkwggDf2/Tv6VHygvLnhtzp6hIJFyTjh+l/KnyJTyZW1TkZhDaNDzX3SCOHT\",\"iv\":\"FbeHDAW5afeWNORfNJBR0Q==\",\"salt\":\"TxZ+WbCW6891C9LK/hbMAoUsSEW1E8pyGLVBU6x5KR8=\"}" + }, + "NetworkController": { + "network": "1337", + "provider": { + "nickname": "Localhost 8545", + "rpcUrl": "http://localhost:8545", + "chainId": "0x539", + "ticker": "ETH", + "type": "rpc" + } + }, + "NotificationController": { + "notifications": { + "1": { + "isShown": true + }, + "3": { + "isShown": true + }, + "5": { + "isShown": true + }, + "6": { + "isShown": true + } + } + }, + "OnboardingController": { + "onboardingTabs": {}, + "seedPhraseBackedUp": false + }, + "PermissionsMetadata": { + "domainMetadata": { + "metamask.github.io": { + "icon": null, + "name": "M E T A M A S K M E S H T E S T" + } + }, + "permissionsHistory": {}, + "permissionsLog": [ + { + "id": 746677923, + "method": "eth_accounts", + "methodType": "restricted", + "origin": "metamask.github.io", + "request": { + "id": 746677923, + "jsonrpc": "2.0", + "method": "eth_accounts", + "origin": "metamask.github.io", + "params": [] + }, + "requestTime": 1575697241368, + "response": { + "id": 746677923, + "jsonrpc": "2.0", + "result": [] + }, + "responseTime": 1575697241370, + "success": true + } + ] + }, + "PreferencesController": { + "accountTokens": { + "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { + "0x539": [ + { + "address": "0x86002be4cdd922de1ccb831582bf99284b99ac12", + "symbol": "TST", + "decimals": 4 + } + ], + "rinkeby": [], + "ropsten": [] + } + }, + "assetImages": {}, + "completedOnboarding": true, + "currentLocale": "en", + "featureFlags": { + "showIncomingTransactions": true, + "transactionTime": false + }, + "firstTimeFlowType": "create", + "forgottenPassword": false, + "frequentRpcListDetail": [], + "identities": { + "0x5cfe73b6021e818b776b421b1c4db2474086a7e1": { + "address": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", + "name": "Account 1" + } + }, + "knownMethodData": {}, + "lostIdentities": {}, + "metaMetricsId": null, + "metaMetricsSendCount": 0, + "participateInMetaMetrics": false, + "preferences": { + "useNativeCurrencyAsPrimaryCurrency": true + }, + "selectedAddress": "0x5cfe73b6021e818b776b421b1c4db2474086a7e1", + "suggestedTokens": {}, + "tokens": [ + { + "address": "0x86002be4cdd922de1ccb831582bf99284b99ac12", + "symbol": "TST", + "decimals": 4 + } + ], + "useBlockie": false, + "useNonceField": false, + "usePhishDetect": true + }, + "config": {}, + "firstTimeInfo": { + "date": 1575697234195, + "version": "7.7.0" + } + }, + "meta": { + "version": 40 + } +} diff --git a/test/e2e/fixtures/import-ui/state.json b/test/e2e/fixtures/import-ui/state.json index 920793cd7..1e6572574 100644 --- a/test/e2e/fixtures/import-ui/state.json +++ b/test/e2e/fixtures/import-ui/state.json @@ -96,10 +96,10 @@ "1": { "isShown": true }, - "2": { + "3": { "isShown": true }, - "3": { + "5": { "isShown": true }, "6": { diff --git a/test/e2e/fixtures/imported-account/state.json b/test/e2e/fixtures/imported-account/state.json index 24396e734..7c4a2108a 100644 --- a/test/e2e/fixtures/imported-account/state.json +++ b/test/e2e/fixtures/imported-account/state.json @@ -41,10 +41,10 @@ "1": { "isShown": true }, - "2": { + "3": { "isShown": true }, - "3": { + "5": { "isShown": true }, "6": { diff --git a/test/e2e/fixtures/localization/state.json b/test/e2e/fixtures/localization/state.json index eb90a0398..009e8ac77 100644 --- a/test/e2e/fixtures/localization/state.json +++ b/test/e2e/fixtures/localization/state.json @@ -41,10 +41,10 @@ "1": { "isShown": true }, - "2": { + "3": { "isShown": true }, - "3": { + "5": { "isShown": true }, "6": { diff --git a/test/e2e/fixtures/metrics-enabled/state.json b/test/e2e/fixtures/metrics-enabled/state.json index 5b107f9c4..8e0f082d5 100644 --- a/test/e2e/fixtures/metrics-enabled/state.json +++ b/test/e2e/fixtures/metrics-enabled/state.json @@ -45,10 +45,10 @@ "1": { "isShown": true }, - "2": { + "3": { "isShown": true }, - "3": { + "5": { "isShown": true }, "6": { diff --git a/test/e2e/fixtures/send-edit/state.json b/test/e2e/fixtures/send-edit/state.json index c93539f3a..a5f3a8bab 100644 --- a/test/e2e/fixtures/send-edit/state.json +++ b/test/e2e/fixtures/send-edit/state.json @@ -42,10 +42,10 @@ "1": { "isShown": true }, - "2": { + "3": { "isShown": true }, - "3": { + "5": { "isShown": true }, "6": { diff --git a/test/e2e/fixtures/threebox-enabled/state.json b/test/e2e/fixtures/threebox-enabled/state.json index 5b6cf9bce..f182c5d47 100644 --- a/test/e2e/fixtures/threebox-enabled/state.json +++ b/test/e2e/fixtures/threebox-enabled/state.json @@ -52,10 +52,10 @@ "1": { "isShown": true }, - "2": { + "3": { "isShown": true }, - "3": { + "5": { "isShown": true }, "6": { diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 78ed5f59d..b813a597d 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -1,4 +1,4 @@ -const assert = require('assert'); +const { strict: assert } = require('assert'); const enLocaleMessages = require('../../app/_locales/en/messages.json'); const { tinyDelayMs, regularDelayMs, largeDelayMs } = require('./helpers'); @@ -83,7 +83,12 @@ describe('MetaMask', function () { let seedPhrase; - it('reveals the seed phrase', async function () { + it('renders the Secret Recovery Phrase intro screen', async function () { + await driver.clickElement('.seed-phrase-intro__left button'); + await driver.delay(regularDelayMs); + }); + + it('reveals the Secret Recovery Phrase', async function () { const byRevealButton = '.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button'; await driver.findElement(byRevealButton); @@ -111,7 +116,7 @@ describe('MetaMask', function () { await driver.delay(tinyDelayMs); } - it('can retype the seed phrase', async function () { + it('can retype the Secret Recovery Phrase', async function () { const words = seedPhrase.split(' '); for (const word of words) { @@ -213,7 +218,7 @@ describe('MetaMask', function () { }); }); - describe('Import seed phrase', function () { + describe('Import Secret Recovery Phrase', function () { it('logs out of the vault', async function () { await driver.clickElement('.account-menu__icon'); await driver.delay(regularDelayMs); @@ -226,11 +231,14 @@ describe('MetaMask', function () { await driver.delay(regularDelayMs); }); - it('imports seed phrase', async function () { + it('imports Secret Recovery Phrase', async function () { const restoreSeedLink = await driver.findClickableElement( '.unlock-page__link--import', ); - assert.equal(await restoreSeedLink.getText(), 'import using seed phrase'); + assert.equal( + await restoreSeedLink.getText(), + 'import using Secret Recovery Phrase', + ); await restoreSeedLink.click(); await driver.delay(regularDelayMs); @@ -1112,16 +1120,10 @@ describe('MetaMask', function () { }); it('finds the transaction in the transactions list', async function () { - await driver.wait(async () => { - const confirmedTxes = await driver.findElements( - '.transaction-list__completed-transactions .transaction-list-item', - ); - return confirmedTxes.length === 1; - }, 10000); - await driver.waitForSelector( { - css: '.transaction-list-item__primary-currency', + css: + '.transaction-list__completed-transactions .transaction-list-item__primary-currency', text: '-1 TST', }, { timeout: 10000 }, @@ -1214,15 +1216,9 @@ describe('MetaMask', function () { }); it('finds the transaction in the transactions list', async function () { - await driver.wait(async () => { - const confirmedTxes = await driver.findElements( - '.transaction-list__completed-transactions .transaction-list-item', - ); - return confirmedTxes.length === 2; - }, 10000); - await driver.waitForSelector({ - css: '.transaction-list-item__primary-currency', + css: + '.transaction-list__completed-transactions .transaction-list-item__primary-currency', text: '-1.5 TST', }); @@ -1230,11 +1226,23 @@ describe('MetaMask', function () { css: '.list-item__heading', text: 'Send TST', }); + }); + + it('checks balance', async function () { + await driver.clickElement({ + text: 'Assets', + tag: 'button', + }); await driver.waitForSelector({ - css: '.token-overview__primary-balance', + css: '.asset-list-item__token-button', text: '7.5 TST', }); + + await driver.clickElement({ + text: 'Activity', + tag: 'button', + }); }); }); @@ -1363,13 +1371,6 @@ describe('MetaMask', function () { }); it('finds the transaction in the transactions list', async function () { - await driver.wait(async () => { - const confirmedTxes = await driver.findElements( - '.transaction-list__completed-transactions .transaction-list-item', - ); - return confirmedTxes.length === 3; - }, 10000); - await driver.waitForSelector({ // Select only the heading of the first entry in the transaction list. css: @@ -1422,13 +1423,6 @@ describe('MetaMask', function () { }); it('finds the transaction in the transactions list', async function () { - await driver.wait(async () => { - const confirmedTxes = await driver.findElements( - '.transaction-list__completed-transactions .transaction-list-item', - ); - return confirmedTxes.length === 4; - }, 10000); - await driver.waitForSelector({ // Select the heading of the first transaction list item in the // completed transaction list with text matching Send TST @@ -1438,7 +1432,8 @@ describe('MetaMask', function () { }); await driver.waitForSelector({ - css: '.transaction-list-item__primary-currency', + css: + '.transaction-list__completed-transactions .transaction-list-item:first-child .transaction-list-item__primary-currency', text: '-1.5 TST', }); }); @@ -1504,13 +1499,6 @@ describe('MetaMask', function () { }); it('finds the transaction in the transactions list', async function () { - await driver.wait(async () => { - const confirmedTxes = await driver.findElements( - '.transaction-list__completed-transactions .transaction-list-item', - ); - return confirmedTxes.length === 5; - }, 10000); - await driver.waitForSelector({ css: '.transaction-list__completed-transactions .transaction-list-item:first-child .list-item__heading', @@ -1518,157 +1506,4 @@ describe('MetaMask', function () { }); }); }); - - describe('Hide token', function () { - it('hides the token when clicked', async function () { - await driver.clickElement('[data-testid="asset-options__button"]'); - - await driver.clickElement('[data-testid="asset-options__hide"]'); - - // wait for confirm hide modal to be visible - const confirmHideModal = await driver.findVisibleElement('span .modal'); - - await driver.clickElement( - '[data-testid="hide-token-confirmation__hide"]', - ); - - // wait for confirm hide modal to be removed from DOM. - await confirmHideModal.waitForElementState('hidden'); - }); - }); - - describe('Add existing token using search', function () { - it('clicks on the Add Token button', async function () { - await driver.clickElement({ text: 'Add Token', tag: 'button' }); - await driver.delay(regularDelayMs); - }); - - it('can pick a token from the existing options', async function () { - await driver.fill('#search-tokens', 'BAT'); - await driver.delay(regularDelayMs); - - await driver.clickElement({ text: 'BAT', tag: 'span' }); - await driver.delay(regularDelayMs); - - await driver.clickElement({ text: 'Next', tag: 'button' }); - await driver.delay(regularDelayMs); - - await driver.clickElement({ text: 'Add Tokens', tag: 'button' }); - await driver.delay(largeDelayMs); - }); - - it('renders the balance for the chosen token', async function () { - await driver.waitForSelector({ - css: '.token-overview__primary-balance', - text: '0 BAT', - }); - await driver.delay(regularDelayMs); - }); - }); - - describe('Stores custom RPC history', function () { - it(`creates first custom RPC entry`, async function () { - const rpcUrl = 'http://127.0.0.1:8545/1'; - const chainId = '0x539'; // Ganache default, decimal 1337 - - await driver.clickElement('.network-display'); - await driver.delay(regularDelayMs); - - await driver.clickElement({ text: 'Custom RPC', tag: 'span' }); - await driver.delay(regularDelayMs); - - await driver.findElement('.settings-page__sub-header-text'); - - const customRpcInputs = await driver.findElements('input[type="text"]'); - const rpcUrlInput = customRpcInputs[1]; - const chainIdInput = customRpcInputs[2]; - - await rpcUrlInput.clear(); - await rpcUrlInput.sendKeys(rpcUrl); - - await chainIdInput.clear(); - await chainIdInput.sendKeys(chainId); - - await driver.clickElement('.network-form__footer .btn-secondary'); - await driver.findElement({ text: rpcUrl, tag: 'div' }); - }); - - it(`creates second custom RPC entry`, async function () { - const rpcUrl = 'http://127.0.0.1:8545/2'; - const chainId = '0x539'; // Ganache default, decimal 1337 - - await driver.clickElement('.network-display'); - await driver.delay(regularDelayMs); - - await driver.clickElement({ text: 'Custom RPC', tag: 'span' }); - await driver.delay(regularDelayMs); - - await driver.findElement('.settings-page__sub-header-text'); - - const customRpcInputs = await driver.findElements('input[type="text"]'); - const rpcUrlInput = customRpcInputs[1]; - const chainIdInput = customRpcInputs[2]; - - await rpcUrlInput.clear(); - await rpcUrlInput.sendKeys(rpcUrl); - - await chainIdInput.clear(); - await chainIdInput.sendKeys(chainId); - - await driver.clickElement('.network-form__footer .btn-secondary'); - await driver.findElement({ text: rpcUrl, tag: 'div' }); - }); - - it('selects another provider', async function () { - await driver.clickElement('.network-display'); - await driver.delay(regularDelayMs); - - await driver.clickElement({ text: 'Ethereum Mainnet', tag: 'span' }); - await driver.delay(largeDelayMs * 2); - }); - - it('finds all recent RPCs in history', async function () { - await driver.clickElement('.network-display'); - await driver.delay(regularDelayMs); - - // only recent 3 are found and in correct order (most recent at the top) - const customRpcs = await driver.findElements({ - text: 'http://127.0.0.1:8545/', - tag: 'span', - }); - - // click Mainnet to dismiss network dropdown - await driver.clickElement({ text: 'Ethereum Mainnet', tag: 'span' }); - - assert.equal(customRpcs.length, 2); - }); - - it('deletes a custom RPC', async function () { - const networkListItems = await driver.findClickableElements( - '.networks-tab__networks-list-name', - ); - const lastNetworkListItem = networkListItems[networkListItems.length - 1]; - await lastNetworkListItem.click(); - await driver.delay(100); - - await driver.clickElement('.btn-danger'); - await driver.delay(regularDelayMs); - - // wait for confirm delete modal to be visible - const confirmDeleteModal = await driver.findVisibleElement('span .modal'); - - await driver.clickElement( - '.button.btn-danger.modal-container__footer-button', - ); - - // wait for confirm delete modal to be removed from DOM. - await confirmDeleteModal.waitForElementState('hidden'); - - const newNetworkListItems = await driver.findElements( - '.networks-tab__networks-list-name', - ); - - assert.equal(networkListItems.length - 1, newNetworkListItems.length); - }); - }); }); diff --git a/test/e2e/tests/add-hide-token.spec.js b/test/e2e/tests/add-hide-token.spec.js new file mode 100644 index 000000000..8b98378cd --- /dev/null +++ b/test/e2e/tests/add-hide-token.spec.js @@ -0,0 +1,94 @@ +const { strict: assert } = require('assert'); +const { withFixtures } = require('../helpers'); + +describe('Hide token', function () { + const ganacheOptions = { + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: 25000000000000000000, + }, + ], + }; + it('hides the token when clicked', async function () { + await withFixtures( + { + fixtures: 'custom-token', + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + await driver.waitForSelector({ + css: '.asset-list-item__token-button', + text: '0 TST', + }); + + let assets = await driver.findElements('.asset-list-item'); + assert.equal(assets.length, 2); + + await driver.clickElement({ text: 'Assets', tag: 'button' }); + + await driver.clickElement({ text: 'TST', tag: 'span' }); + + await driver.clickElement('[data-testid="asset-options__button"]'); + + await driver.clickElement('[data-testid="asset-options__hide"]'); + + // wait for confirm hide modal to be visible + const confirmHideModal = await driver.findVisibleElement('span .modal'); + + await driver.clickElement( + '[data-testid="hide-token-confirmation__hide"]', + ); + + // wait for confirm hide modal to be removed from DOM. + await confirmHideModal.waitForElementState('hidden'); + + assets = await driver.findElements('.asset-list-item'); + assert.equal(assets.length, 1); + }, + ); + }); +}); + +describe('Add existing token using search', function () { + const ganacheOptions = { + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: 25000000000000000000, + }, + ], + }; + it('renders the balance for the chosen token', async function () { + await withFixtures( + { + fixtures: 'imported-account', + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + await driver.clickElement({ text: 'Add Token', tag: 'button' }); + await driver.fill('#search-tokens', 'BAT'); + await driver.clickElement({ text: 'BAT', tag: 'span' }); + await driver.clickElement({ text: 'Next', tag: 'button' }); + await driver.clickElement({ text: 'Add Tokens', tag: 'button' }); + + await driver.waitForSelector({ + css: '.token-overview__primary-balance', + text: '0 BAT', + }); + }, + ); + }); +}); diff --git a/test/e2e/tests/custom-rpc-history.spec.js b/test/e2e/tests/custom-rpc-history.spec.js new file mode 100644 index 000000000..a827ada2d --- /dev/null +++ b/test/e2e/tests/custom-rpc-history.spec.js @@ -0,0 +1,146 @@ +const { strict: assert } = require('assert'); +const { withFixtures } = require('../helpers'); + +describe('Stores custom RPC history', function () { + const ganacheOptions = { + accounts: [ + { + secretKey: + '0x7C9529A67102755B7E6102D6D950AC5D5863C98713805CEC576B945B15B71EAC', + balance: 25000000000000000000, + }, + ], + }; + it(`creates first custom RPC entry`, async function () { + await withFixtures( + { + fixtures: 'imported-account', + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + const rpcUrl = 'http://127.0.0.1:8545/1'; + const chainId = '0x539'; // Ganache default, decimal 1337 + + await driver.clickElement('.network-display'); + + await driver.clickElement({ text: 'Custom RPC', tag: 'span' }); + + await driver.findElement('.settings-page__sub-header-text'); + + const customRpcInputs = await driver.findElements('input[type="text"]'); + const rpcUrlInput = customRpcInputs[1]; + const chainIdInput = customRpcInputs[2]; + + await rpcUrlInput.clear(); + await rpcUrlInput.sendKeys(rpcUrl); + + await chainIdInput.clear(); + await chainIdInput.sendKeys(chainId); + + await driver.clickElement('.network-form__footer .btn-secondary'); + await driver.findElement({ text: rpcUrl, tag: 'div' }); + }, + ); + }); + + it('selects another provider', async function () { + await withFixtures( + { + fixtures: 'imported-account', + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + await driver.clickElement('.network-display'); + + await driver.clickElement({ text: 'Ethereum Mainnet', tag: 'span' }); + }, + ); + }); + + it('finds all recent RPCs in history', async function () { + await withFixtures( + { + fixtures: 'custom-rpc', + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + await driver.clickElement('.network-display'); + + // only recent 3 are found and in correct order (most recent at the top) + const customRpcs = await driver.findElements({ + text: 'http://127.0.0.1:8545/', + tag: 'span', + }); + + // click Mainnet to dismiss network dropdown + await driver.clickElement({ text: 'Ethereum Mainnet', tag: 'span' }); + + assert.equal(customRpcs.length, 2); + }, + ); + }); + + it('deletes a custom RPC', async function () { + await withFixtures( + { + fixtures: 'custom-rpc', + ganacheOptions, + title: this.test.title, + }, + async ({ driver }) => { + await driver.navigate(); + await driver.fill('#password', 'correct horse battery staple'); + await driver.press('#password', driver.Key.ENTER); + + await driver.clickElement('.network-display'); + + await driver.clickElement({ text: 'Custom RPC', tag: 'span' }); + + // cancel new custom rpc + await driver.clickElement('.network-form__footer button.btn-default'); + + const networkListItems = await driver.findClickableElements( + '.networks-tab__networks-list-name', + ); + const lastNetworkListItem = + networkListItems[networkListItems.length - 1]; + await lastNetworkListItem.click(); + + await driver.clickElement('.btn-danger'); + + // wait for confirm delete modal to be visible + const confirmDeleteModal = await driver.findVisibleElement( + 'span .modal', + ); + + await driver.clickElement( + '.button.btn-danger.modal-container__footer-button', + ); + + // wait for confirm delete modal to be removed from DOM. + await confirmDeleteModal.waitForElementState('hidden'); + + const newNetworkListItems = await driver.findElements( + '.networks-tab__networks-list-name', + ); + + assert.equal(networkListItems.length - 1, newNetworkListItems.length); + }, + ); + }); +}); diff --git a/test/e2e/tests/from-import-ui.spec.js b/test/e2e/tests/from-import-ui.spec.js index 7bef78294..b8c0abc52 100644 --- a/test/e2e/tests/from-import-ui.spec.js +++ b/test/e2e/tests/from-import-ui.spec.js @@ -3,7 +3,7 @@ const { withFixtures, regularDelayMs } = require('../helpers'); const enLocaleMessages = require('../../../app/_locales/en/messages.json'); describe('Metamask Import UI', function () { - it('Importing wallet using seed phrase', async function () { + it('Importing wallet using Secret Recovery Phrase', async function () { const ganacheOptions = { accounts: [ { @@ -40,9 +40,9 @@ describe('Metamask Import UI', function () { // clicks the "No thanks" option on the metametrics opt-in screen await driver.clickElement('.btn-default'); - // Import seed phrase + // Import Secret Recovery Phrase await driver.fill( - 'input[placeholder="Paste seed phrase from clipboard"]', + 'input[placeholder="Paste Secret Recovery Phrase from clipboard"]', testSeedPhrase, ); diff --git a/test/e2e/tests/incremental-security.spec.js b/test/e2e/tests/incremental-security.spec.js index 6ecd5580e..a07f44c96 100644 --- a/test/e2e/tests/incremental-security.spec.js +++ b/test/e2e/tests/incremental-security.spec.js @@ -17,7 +17,7 @@ describe('Incremental Security', function () { }, ], }; - it('Back up seed phrase from backup reminder', async function () { + it('Back up Secret Recovery Phrase from backup reminder', async function () { await withFixtures( { dapp: true, @@ -56,7 +56,10 @@ describe('Incremental Security', function () { await driver.clickElement('.first-time-flow__checkbox'); await driver.clickElement('.first-time-flow__form button'); - // skips the seed phrase challenge + // renders the Secret Recovery Phrase intro screen' + await driver.clickElement('.seed-phrase-intro__left button'); + + // skips the Secret Recovery Phrase challenge await driver.clickElement({ text: enLocaleMessages.remindMeLater.message, tag: 'button', @@ -115,7 +118,7 @@ describe('Incremental Security', function () { let balance = await currencyDisplay.getText(); assert.strictEqual(balance, '1'); - // backs up the seed phrase + // backs up the Secret Recovery Phrase // should show a backup reminder const backupReminder = await driver.findElements({ xpath: @@ -126,7 +129,7 @@ describe('Incremental Security', function () { // should take the user to the seedphrase backup screen await driver.clickElement('.home-notification__accept-button'); - // reveals the seed phrase + // reveals the Secret Recovery Phrase await driver.clickElement( '.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button', ); @@ -150,7 +153,7 @@ describe('Incremental Security', function () { await driver.delay(tinyDelayMs); } - // can retype the seed phrase + // can retype the Secret Recovery Phrase const words = seedPhrase.split(' '); for (const word of words) { diff --git a/test/e2e/tests/metamask-responsive-ui.spec.js b/test/e2e/tests/metamask-responsive-ui.spec.js index 8627b20d0..a50bdfff9 100644 --- a/test/e2e/tests/metamask-responsive-ui.spec.js +++ b/test/e2e/tests/metamask-responsive-ui.spec.js @@ -42,7 +42,10 @@ describe('Metamask Responsive UI', function () { await driver.clickElement('.first-time-flow__checkbox'); await driver.clickElement('.first-time-flow__form button'); - // reveals the seed phrase + // renders the Secret Recovery Phrase intro screen + await driver.clickElement('.seed-phrase-intro__left button'); + + // reveals the Secret Recovery Phrase await driver.clickElement( '.reveal-seed-phrase__secret-blocker .reveal-seed-phrase__reveal-button', ); @@ -64,7 +67,7 @@ describe('Metamask Responsive UI', function () { await driver.delay(tinyDelayMs); } - // can retype the seed phrase + // can retype the Secret Recovery Phrase const words = seedPhrase.split(' '); for (const word of words) { await clickWordAndWait(word); @@ -103,13 +106,13 @@ describe('Metamask Responsive UI', function () { async ({ driver }) => { await driver.navigate(); - // Import seed phrase + // Import Secret Recovery Phrase const restoreSeedLink = await driver.findClickableElement( '.unlock-page__link--import', ); assert.equal( await restoreSeedLink.getText(), - 'import using seed phrase', + 'import using Secret Recovery Phrase', ); await restoreSeedLink.click(); diff --git a/test/e2e/webdriver/firefox.js b/test/e2e/webdriver/firefox.js index ed90dc256..6d327305a 100644 --- a/test/e2e/webdriver/firefox.js +++ b/test/e2e/webdriver/firefox.js @@ -3,7 +3,7 @@ const os = require('os'); const path = require('path'); const { Builder, By, until } = require('selenium-webdriver'); const firefox = require('selenium-webdriver/firefox'); -const { version } = require('../../../app/manifest/_base.json'); +const { version } = require('../../../package.json'); /** * The prefix for temporary Firefox profiles. All Firefox profiles used for e2e tests diff --git a/test/jest/background.js b/test/jest/background.js index 49a6bdf8f..99d181308 100644 --- a/test/jest/background.js +++ b/test/jest/background.js @@ -1,4 +1,4 @@ -import * as actions from '../../ui/app/store/actions'; +import * as actions from '../../ui/store/actions'; export const setBackgroundConnection = (backgroundConnection = {}) => { actions._setBackgroundConnection(backgroundConnection); diff --git a/test/jest/mock-store.js b/test/jest/mock-store.js index 88d486193..f09999f10 100644 --- a/test/jest/mock-store.js +++ b/test/jest/mock-store.js @@ -24,6 +24,24 @@ export const createSwapsMockStore = () => { '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': 2, '0x1111111111111111111111111111111111111111': 0.1, }, + identities: { + '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825': { + address: '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825', + name: 'Send Account 1', + }, + '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb': { + address: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb', + name: 'Send Account 2', + }, + '0x2f8d4a878cfa04a6e60d46362f5644deab66572d': { + address: '0x2f8d4a878cfa04a6e60d46362f5644deab66572d', + name: 'Send Account 3', + }, + '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { + address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + name: 'Send Account 4', + }, + }, accounts: { '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc': { address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', @@ -35,6 +53,21 @@ export const createSwapsMockStore = () => { }, }, selectedAddress: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + keyringTypes: ['Simple Key Pair', 'HD Key Tree'], + keyrings: [ + { + type: 'HD Key Tree', + accounts: [ + '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + 'c5b8dbac4c1d3f152cdeb400e2313f309c410acb', + '2f8d4a878cfa04a6e60d46362f5644deab66572d', + ], + }, + { + type: 'Simple Key Pair', + accounts: ['0xd85a4b6a394794842887b8284293d69163007bbb'], + }, + ], frequentRpcListDetail: [], tokens: [ { diff --git a/test/jest/rendering.js b/test/jest/rendering.js index d215cbc0d..f84ecfe0b 100644 --- a/test/jest/rendering.js +++ b/test/jest/rendering.js @@ -4,8 +4,8 @@ import { render } from '@testing-library/react'; import { MemoryRouter } from 'react-router-dom'; import PropTypes from 'prop-types'; -import { I18nContext, LegacyI18nProvider } from '../../ui/app/contexts/i18n'; -import { getMessage } from '../../ui/app/helpers/utils/i18n-helper'; +import { I18nContext, LegacyI18nProvider } from '../../ui/contexts/i18n'; +import { getMessage } from '../../ui/helpers/utils/i18n-helper'; import * as en from '../../app/_locales/en/messages.json'; export const I18nProvider = (props) => { diff --git a/test/lib/render-helpers.js b/test/lib/render-helpers.js index fc4621015..37c5d6370 100644 --- a/test/lib/render-helpers.js +++ b/test/lib/render-helpers.js @@ -1,13 +1,19 @@ import React, { useMemo } from 'react'; import { Provider } from 'react-redux'; import { render } from '@testing-library/react'; -import { mount } from 'enzyme'; +import { mount, shallow } from 'enzyme'; import { MemoryRouter } from 'react-router-dom'; import PropTypes from 'prop-types'; -import { I18nContext, LegacyI18nProvider } from '../../ui/app/contexts/i18n'; -import { getMessage } from '../../ui/app/helpers/utils/i18n-helper'; +import { I18nContext, LegacyI18nProvider } from '../../ui/contexts/i18n'; +import { getMessage } from '../../ui/helpers/utils/i18n-helper'; import * as en from '../../app/_locales/en/messages.json'; +export function shallowWithContext(jsxComponent) { + return shallow(jsxComponent, { + context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) }, + }); +} + export function mountWithRouter(component, store = {}, pathname = '/') { // Instantiate router context const router = { diff --git a/test/unit-global/balance-formatter.test.js b/test/unit-global/balance-formatter.test.js index cd63ee68f..36c246bfd 100644 --- a/test/unit-global/balance-formatter.test.js +++ b/test/unit-global/balance-formatter.test.js @@ -1,6 +1,6 @@ -import assert from 'assert'; +import { strict as assert } from 'assert'; import currencyFormatter from 'currency-formatter'; -import availableCurrencies from '../../ui/app/helpers/constants/available-conversions.json'; +import availableCurrencies from '../../ui/helpers/constants/available-conversions.json'; describe('currencyFormatting', function () { it('be able to format any infura currency', function (done) { diff --git a/test/unit-global/frozenPromise.test.js b/test/unit-global/frozenPromise.test.js index de2409792..f96af0d2a 100644 --- a/test/unit-global/frozenPromise.test.js +++ b/test/unit-global/frozenPromise.test.js @@ -2,7 +2,7 @@ import './globalPatch'; import 'ses/lockdown'; import '../../app/scripts/runLockdown'; -import assert from 'assert'; /* eslint-disable-line import/first,import/order */ +import { strict as assert } from 'assert'; /* eslint-disable-line import/first,import/order */ describe('Promise global is immutable', function () { it('throws when reassinging promise (syntax 1)', function () { diff --git a/ui/app/__mocks__/react-router-dom.js b/ui/__mocks__/react-router-dom.js similarity index 100% rename from ui/app/__mocks__/react-router-dom.js rename to ui/__mocks__/react-router-dom.js diff --git a/ui/app/components/app/signature-request/signature-request.constants.js b/ui/app/components/app/signature-request/signature-request.constants.js deleted file mode 100644 index 34ac7b40d..000000000 --- a/ui/app/components/app/signature-request/signature-request.constants.js +++ /dev/null @@ -1,3 +0,0 @@ -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../../shared/constants/app'; - -export { ENVIRONMENT_TYPE_NOTIFICATION }; diff --git a/ui/app/components/app/account-list-item/account-list-item-component.test.js b/ui/components/app/account-list-item/account-list-item-component.test.js similarity index 96% rename from ui/app/components/app/account-list-item/account-list-item-component.test.js rename to ui/components/app/account-list-item/account-list-item-component.test.js index 03c038cf4..d8a05ce46 100644 --- a/ui/app/components/app/account-list-item/account-list-item-component.test.js +++ b/ui/components/app/account-list-item/account-list-item-component.test.js @@ -2,10 +2,10 @@ import React from 'react'; import { shallow } from 'enzyme'; import sinon from 'sinon'; import Identicon from '../../ui/identicon'; -import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import AccountListItem from './account-list-item'; -jest.mock('../../../../../shared/modules/hexstring-utils', () => ({ +jest.mock('../../../../shared/modules/hexstring-utils', () => ({ toChecksumHexAddress: jest.fn(() => 'mockCheckSumAddress'), })); diff --git a/ui/app/components/app/account-list-item/account-list-item.js b/ui/components/app/account-list-item/account-list-item.js similarity index 93% rename from ui/app/components/app/account-list-item/account-list-item.js rename to ui/components/app/account-list-item/account-list-item.js index fd1b80bc4..5220dede9 100644 --- a/ui/app/components/app/account-list-item/account-list-item.js +++ b/ui/components/app/account-list-item/account-list-item.js @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import Identicon from '../../ui/identicon'; import AccountMismatchWarning from '../../ui/account-mismatch-warning/account-mismatch-warning.component'; -import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; export default function AccountListItem({ account, diff --git a/ui/app/components/app/account-list-item/index.js b/ui/components/app/account-list-item/index.js similarity index 100% rename from ui/app/components/app/account-list-item/index.js rename to ui/components/app/account-list-item/index.js diff --git a/ui/app/components/app/account-list-item/index.scss b/ui/components/app/account-list-item/index.scss similarity index 100% rename from ui/app/components/app/account-list-item/index.scss rename to ui/components/app/account-list-item/index.scss diff --git a/ui/app/components/app/account-menu/account-menu.component.js b/ui/components/app/account-menu/account-menu.component.js similarity index 98% rename from ui/app/components/app/account-menu/account-menu.component.js rename to ui/components/app/account-menu/account-menu.component.js index fe3ebffe6..f6c5b75df 100644 --- a/ui/app/components/app/account-menu/account-menu.component.js +++ b/ui/components/app/account-menu/account-menu.component.js @@ -4,8 +4,8 @@ import { debounce } from 'lodash'; import Fuse from 'fuse.js'; import InputAdornment from '@material-ui/core/InputAdornment'; import classnames from 'classnames'; -import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app'; -import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import Identicon from '../../ui/identicon'; import SiteIcon from '../../ui/site-icon'; import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display'; @@ -78,7 +78,6 @@ export default class AccountMenu extends Component { }; addressFuse = new Fuse([], { - shouldSort: false, threshold: 0.45, location: 0, distance: 100, diff --git a/ui/app/components/app/account-menu/account-menu.container.js b/ui/components/app/account-menu/account-menu.container.js similarity index 100% rename from ui/app/components/app/account-menu/account-menu.container.js rename to ui/components/app/account-menu/account-menu.container.js diff --git a/ui/app/components/app/account-menu/account-menu.test.js b/ui/components/app/account-menu/account-menu.test.js similarity index 98% rename from ui/app/components/app/account-menu/account-menu.test.js rename to ui/components/app/account-menu/account-menu.test.js index 44666899d..fc715ead1 100644 --- a/ui/app/components/app/account-menu/account-menu.test.js +++ b/ui/components/app/account-menu/account-menu.test.js @@ -2,7 +2,7 @@ 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 { mountWithRouter } from '../../../../test/lib/render-helpers'; import AccountMenu from '.'; describe('Account Menu', () => { diff --git a/ui/app/components/app/account-menu/index.js b/ui/components/app/account-menu/index.js similarity index 100% rename from ui/app/components/app/account-menu/index.js rename to ui/components/app/account-menu/index.js diff --git a/ui/app/components/app/account-menu/index.scss b/ui/components/app/account-menu/index.scss similarity index 100% rename from ui/app/components/app/account-menu/index.scss rename to ui/components/app/account-menu/index.scss diff --git a/ui/app/components/app/add-token-button/add-token-button.component.js b/ui/components/app/add-token-button/add-token-button.component.js similarity index 100% rename from ui/app/components/app/add-token-button/add-token-button.component.js rename to ui/components/app/add-token-button/add-token-button.component.js diff --git a/ui/app/components/app/add-token-button/index.js b/ui/components/app/add-token-button/index.js similarity index 100% rename from ui/app/components/app/add-token-button/index.js rename to ui/components/app/add-token-button/index.js diff --git a/ui/app/components/app/add-token-button/index.scss b/ui/components/app/add-token-button/index.scss similarity index 100% rename from ui/app/components/app/add-token-button/index.scss rename to ui/components/app/add-token-button/index.scss diff --git a/ui/app/components/app/alerts/alerts.js b/ui/components/app/alerts/alerts.js similarity index 100% rename from ui/app/components/app/alerts/alerts.js rename to ui/components/app/alerts/alerts.js diff --git a/ui/app/components/app/alerts/alerts.scss b/ui/components/app/alerts/alerts.scss similarity index 100% rename from ui/app/components/app/alerts/alerts.scss rename to ui/components/app/alerts/alerts.scss diff --git a/ui/app/components/app/alerts/index.js b/ui/components/app/alerts/index.js similarity index 100% rename from ui/app/components/app/alerts/index.js rename to ui/components/app/alerts/index.js diff --git a/ui/app/components/app/alerts/invalid-custom-network-alert/index.js b/ui/components/app/alerts/invalid-custom-network-alert/index.js similarity index 100% rename from ui/app/components/app/alerts/invalid-custom-network-alert/index.js rename to ui/components/app/alerts/invalid-custom-network-alert/index.js diff --git a/ui/app/components/app/alerts/invalid-custom-network-alert/invalid-custom-network-alert.js b/ui/components/app/alerts/invalid-custom-network-alert/invalid-custom-network-alert.js similarity index 100% rename from ui/app/components/app/alerts/invalid-custom-network-alert/invalid-custom-network-alert.js rename to ui/components/app/alerts/invalid-custom-network-alert/invalid-custom-network-alert.js diff --git a/ui/app/components/app/alerts/invalid-custom-network-alert/invalid-custom-network-alert.scss b/ui/components/app/alerts/invalid-custom-network-alert/invalid-custom-network-alert.scss similarity index 100% rename from ui/app/components/app/alerts/invalid-custom-network-alert/invalid-custom-network-alert.scss rename to ui/components/app/alerts/invalid-custom-network-alert/invalid-custom-network-alert.scss diff --git a/ui/app/components/app/alerts/unconnected-account-alert/index.js b/ui/components/app/alerts/unconnected-account-alert/index.js similarity index 100% rename from ui/app/components/app/alerts/unconnected-account-alert/index.js rename to ui/components/app/alerts/unconnected-account-alert/index.js diff --git a/ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js b/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js similarity index 100% rename from ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js rename to ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js diff --git a/ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.scss b/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.scss similarity index 100% rename from ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.scss rename to ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.scss diff --git a/ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.test.js b/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.test.js similarity index 95% rename from ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.test.js rename to ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.test.js index dda361f4a..3aad2342b 100644 --- a/ui/app/components/app/alerts/unconnected-account-alert/unconnected-account-alert.test.js +++ b/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.test.js @@ -6,11 +6,11 @@ import thunk from 'redux-thunk'; import { fireEvent } from '@testing-library/react'; import configureMockStore from 'redux-mock-store'; -import { tick } from '../../../../../../test/lib/tick'; -import { renderWithProvider } from '../../../../../../test/lib/render-helpers'; +import { tick } from '../../../../../test/lib/tick'; +import { renderWithProvider } from '../../../../../test/lib/render-helpers'; import * as actions from '../../../../store/actions'; -import { KOVAN_CHAIN_ID } from '../../../../../../shared/constants/network'; +import { KOVAN_CHAIN_ID } from '../../../../../shared/constants/network'; import UnconnectedAccountAlert from '.'; describe('Unconnected Account Alert', () => { diff --git a/ui/app/components/app/app-components.scss b/ui/components/app/app-components.scss similarity index 100% rename from ui/app/components/app/app-components.scss rename to ui/components/app/app-components.scss diff --git a/ui/app/components/app/app-header/app-header.component.js b/ui/components/app/app-header/app-header.component.js similarity index 100% rename from ui/app/components/app/app-header/app-header.component.js rename to ui/components/app/app-header/app-header.component.js diff --git a/ui/app/components/app/app-header/app-header.container.js b/ui/components/app/app-header/app-header.container.js similarity index 100% rename from ui/app/components/app/app-header/app-header.container.js rename to ui/components/app/app-header/app-header.container.js diff --git a/ui/app/components/app/app-header/app-header.test.js b/ui/components/app/app-header/app-header.test.js similarity index 100% rename from ui/app/components/app/app-header/app-header.test.js rename to ui/components/app/app-header/app-header.test.js diff --git a/ui/app/components/app/app-header/index.js b/ui/components/app/app-header/index.js similarity index 100% rename from ui/app/components/app/app-header/index.js rename to ui/components/app/app-header/index.js diff --git a/ui/app/components/app/app-header/index.scss b/ui/components/app/app-header/index.scss similarity index 100% rename from ui/app/components/app/app-header/index.scss rename to ui/components/app/app-header/index.scss diff --git a/ui/app/components/app/asset-list-item/asset-list-item.js b/ui/components/app/asset-list-item/asset-list-item.js similarity index 100% rename from ui/app/components/app/asset-list-item/asset-list-item.js rename to ui/components/app/asset-list-item/asset-list-item.js diff --git a/ui/app/components/app/asset-list-item/asset-list-item.scss b/ui/components/app/asset-list-item/asset-list-item.scss similarity index 100% rename from ui/app/components/app/asset-list-item/asset-list-item.scss rename to ui/components/app/asset-list-item/asset-list-item.scss diff --git a/ui/app/components/app/asset-list-item/index.js b/ui/components/app/asset-list-item/index.js similarity index 100% rename from ui/app/components/app/asset-list-item/index.js rename to ui/components/app/asset-list-item/index.js diff --git a/ui/app/components/app/asset-list/asset-list.js b/ui/components/app/asset-list/asset-list.js similarity index 100% rename from ui/app/components/app/asset-list/asset-list.js rename to ui/components/app/asset-list/asset-list.js diff --git a/ui/app/components/app/asset-list/index.js b/ui/components/app/asset-list/index.js similarity index 100% rename from ui/app/components/app/asset-list/index.js rename to ui/components/app/asset-list/index.js diff --git a/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js b/ui/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js rename to ui/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.js diff --git a/ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.test.js b/ui/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.test.js similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.test.js rename to ui/components/app/confirm-page-container/confirm-detail-row/confirm-detail-row.component.test.js diff --git a/ui/app/components/app/confirm-page-container/confirm-detail-row/index.js b/ui/components/app/confirm-page-container/confirm-detail-row/index.js similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-detail-row/index.js rename to ui/components/app/confirm-page-container/confirm-detail-row/index.js diff --git a/ui/app/components/app/confirm-page-container/confirm-detail-row/index.scss b/ui/components/app/confirm-page-container/confirm-detail-row/index.scss similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-detail-row/index.scss rename to ui/components/app/confirm-page-container/confirm-detail-row/index.scss diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js similarity index 95% rename from ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js rename to ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js index 9009f9feb..e47bfaf78 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-content.component.js @@ -22,6 +22,7 @@ export default class ConfirmPageContainerContent extends Component { titleComponent: PropTypes.node, warning: PropTypes.string, origin: PropTypes.string.isRequired, + ethGasPriceWarning: PropTypes.string, // Footer onCancelAll: PropTypes.func, onCancel: PropTypes.func, @@ -81,11 +82,15 @@ export default class ConfirmPageContainerContent extends Component { unapprovedTxCount, rejectNText, origin, + ethGasPriceWarning, } = this.props; return ( <div className="confirm-page-container-content"> {warning && <ConfirmPageContainerWarning warning={warning} />} + {ethGasPriceWarning && ( + <ConfirmPageContainerWarning warning={ethGasPriceWarning} /> + )} <ConfirmPageContainerSummary className={classnames({ 'confirm-page-container-summary--border': diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js rename to ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/confirm-page-container-summary.component.js diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.js b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.js similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.js rename to ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.js diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.scss b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.scss similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.scss rename to ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-summary/index.scss diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js similarity index 93% rename from ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js rename to ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js index eef1ed09e..29f7b9edd 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/confirm-page-container-warning.component.js @@ -6,7 +6,7 @@ const ConfirmPageContainerWarning = (props) => { <div className="confirm-page-container-warning"> <img className="confirm-page-container-warning__icon" - src="/images/alert.svg" + src="./images/alert.svg" alt="" /> <div className="confirm-page-container-warning__warning"> diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.js b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.js similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.js rename to ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.js diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.scss b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.scss similarity index 91% rename from ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.scss rename to ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.scss index f439be370..bbfe812fe 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.scss +++ b/ui/components/app/confirm-page-container/confirm-page-container-content/confirm-page-container-warning/index.scss @@ -1,7 +1,6 @@ .confirm-page-container-warning { background-color: #fffcdb; display: flex; - justify-content: center; align-items: center; border-bottom: 1px solid $geyser; padding: 12px 24px; diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/index.js b/ui/components/app/confirm-page-container/confirm-page-container-content/index.js similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-page-container-content/index.js rename to ui/components/app/confirm-page-container/confirm-page-container-content/index.js diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-content/index.scss b/ui/components/app/confirm-page-container/confirm-page-container-content/index.scss similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-page-container-content/index.scss rename to ui/components/app/confirm-page-container/confirm-page-container-content/index.scss diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js b/ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js similarity index 92% rename from ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js rename to ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js index 2054f7daa..9c84a720a 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js @@ -3,8 +3,8 @@ import PropTypes from 'prop-types'; import { ENVIRONMENT_TYPE_POPUP, ENVIRONMENT_TYPE_NOTIFICATION, -} from '../../../../../../shared/constants/app'; -import { getEnvironmentType } from '../../../../../../app/scripts/lib/util'; +} from '../../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; import NetworkDisplay from '../../network-display'; import Identicon from '../../../ui/identicon'; import { shortenAddress } from '../../../../helpers/utils/util'; @@ -47,7 +47,7 @@ export default function ConfirmPageContainerHeader({ visibility: showEdit ? 'initial' : 'hidden', }} > - <img src="/images/caret-left.svg" alt="" /> + <img src="./images/caret-left.svg" alt="" /> <span className="confirm-page-container-header__back-button" onClick={() => onEdit()} diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js b/ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js similarity index 87% rename from ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js rename to ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js index b94d3d15d..98c1169b2 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js +++ b/ui/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.test.js @@ -3,10 +3,15 @@ import { shallow } from 'enzyme'; import sinon from 'sinon'; import { Provider } from 'react-redux'; import configureStore from '../../../../store/store'; -import testData from '../../../../../../.storybook/test-data'; +import testData from '../../../../../.storybook/test-data'; import ConfirmPageContainerHeader from './confirm-page-container-header.component'; -const util = require('../../../../../../app/scripts/lib/util'); +const util = require('../../../../../app/scripts/lib/util'); + +jest.mock('react', () => ({ + ...jest.requireActual('react'), + useLayoutEffect: jest.requireActual('react').useEffect, +})); describe('Confirm Detail Row Component', () => { describe('render', () => { diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.js b/ui/components/app/confirm-page-container/confirm-page-container-header/index.js similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-page-container-header/index.js rename to ui/components/app/confirm-page-container/confirm-page-container-header/index.js diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-header/index.scss b/ui/components/app/confirm-page-container/confirm-page-container-header/index.scss similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-page-container-header/index.scss rename to ui/components/app/confirm-page-container/confirm-page-container-header/index.scss diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js b/ui/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js similarity index 92% rename from ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js rename to ui/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js index 20e9c0ce5..8cc0985fb 100755 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container-navigation/confirm-page-container-navigation.component.js @@ -33,14 +33,14 @@ const ConfirmPageContainerNavigation = (props) => { data-testid="first-page" onClick={() => onNextTx(firstTx)} > - <img src="/images/double-arrow.svg" alt="" /> + <img src="./images/double-arrow.svg" alt="" /> </div> <div className="confirm-page-container-navigation__arrow" data-testid="previous-page" onClick={() => onNextTx(prevTxId)} > - <img src="/images/single-arrow.svg" alt="" /> + <img src="./images/single-arrow.svg" alt="" /> </div> </div> <div className="confirm-page-container-navigation__textcontainer"> @@ -64,7 +64,7 @@ const ConfirmPageContainerNavigation = (props) => { > <img className="confirm-page-container-navigation__imageflip" - src="/images/single-arrow.svg" + src="./images/single-arrow.svg" alt="" /> </div> @@ -75,7 +75,7 @@ const ConfirmPageContainerNavigation = (props) => { > <img className="confirm-page-container-navigation__imageflip" - src="/images/double-arrow.svg" + src="./images/double-arrow.svg" alt="" /> </div> diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/index.js b/ui/components/app/confirm-page-container/confirm-page-container-navigation/index.js similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-page-container-navigation/index.js rename to ui/components/app/confirm-page-container/confirm-page-container-navigation/index.js diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-navigation/index.scss b/ui/components/app/confirm-page-container/confirm-page-container-navigation/index.scss similarity index 100% rename from ui/app/components/app/confirm-page-container/confirm-page-container-navigation/index.scss rename to ui/components/app/confirm-page-container/confirm-page-container-navigation/index.scss diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container.component.js b/ui/components/app/confirm-page-container/confirm-page-container.component.js similarity index 97% rename from ui/app/components/app/confirm-page-container/confirm-page-container.component.js rename to ui/components/app/confirm-page-container/confirm-page-container.component.js index e344bedd5..71923e546 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container.component.js +++ b/ui/components/app/confirm-page-container/confirm-page-container.component.js @@ -43,6 +43,7 @@ export default class ConfirmPageContainer extends Component { warning: PropTypes.string, unapprovedTxCount: PropTypes.number, origin: PropTypes.string.isRequired, + ethGasPriceWarning: PropTypes.string, // Navigation totalTx: PropTypes.number, positionOfCurrentTx: PropTypes.number, @@ -103,6 +104,7 @@ export default class ConfirmPageContainer extends Component { hideSenderToRecipient, showAccountInHeader, origin, + ethGasPriceWarning, } = this.props; const renderAssetImage = contentComponent || !identiconAddress; @@ -162,6 +164,7 @@ export default class ConfirmPageContainer extends Component { unapprovedTxCount={unapprovedTxCount} rejectNText={this.context.t('rejectTxsN', [unapprovedTxCount])} origin={origin} + ethGasPriceWarning={ethGasPriceWarning} /> )} {contentComponent && ( diff --git a/ui/app/components/app/confirm-page-container/index.js b/ui/components/app/confirm-page-container/index.js similarity index 100% rename from ui/app/components/app/confirm-page-container/index.js rename to ui/components/app/confirm-page-container/index.js diff --git a/ui/app/components/app/confirm-page-container/index.scss b/ui/components/app/confirm-page-container/index.scss similarity index 100% rename from ui/app/components/app/confirm-page-container/index.scss rename to ui/components/app/confirm-page-container/index.scss diff --git a/ui/app/components/app/connected-accounts-list/connected-accounts-list-item/connected-accounts-list-item.component.js b/ui/components/app/connected-accounts-list/connected-accounts-list-item/connected-accounts-list-item.component.js similarity index 100% rename from ui/app/components/app/connected-accounts-list/connected-accounts-list-item/connected-accounts-list-item.component.js rename to ui/components/app/connected-accounts-list/connected-accounts-list-item/connected-accounts-list-item.component.js diff --git a/ui/app/components/app/connected-accounts-list/connected-accounts-list-item/index.js b/ui/components/app/connected-accounts-list/connected-accounts-list-item/index.js similarity index 100% rename from ui/app/components/app/connected-accounts-list/connected-accounts-list-item/index.js rename to ui/components/app/connected-accounts-list/connected-accounts-list-item/index.js diff --git a/ui/app/components/app/connected-accounts-list/connected-accounts-list-options/connected-accounts-list-options.component.js b/ui/components/app/connected-accounts-list/connected-accounts-list-options/connected-accounts-list-options.component.js similarity index 100% rename from ui/app/components/app/connected-accounts-list/connected-accounts-list-options/connected-accounts-list-options.component.js rename to ui/components/app/connected-accounts-list/connected-accounts-list-options/connected-accounts-list-options.component.js diff --git a/ui/app/components/app/connected-accounts-list/connected-accounts-list-options/index.js b/ui/components/app/connected-accounts-list/connected-accounts-list-options/index.js similarity index 100% rename from ui/app/components/app/connected-accounts-list/connected-accounts-list-options/index.js rename to ui/components/app/connected-accounts-list/connected-accounts-list-options/index.js diff --git a/ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js b/ui/components/app/connected-accounts-list/connected-accounts-list.component.js similarity index 100% rename from ui/app/components/app/connected-accounts-list/connected-accounts-list.component.js rename to ui/components/app/connected-accounts-list/connected-accounts-list.component.js diff --git a/ui/app/components/app/connected-accounts-list/index.js b/ui/components/app/connected-accounts-list/index.js similarity index 100% rename from ui/app/components/app/connected-accounts-list/index.js rename to ui/components/app/connected-accounts-list/index.js diff --git a/ui/app/components/app/connected-accounts-list/index.scss b/ui/components/app/connected-accounts-list/index.scss similarity index 100% rename from ui/app/components/app/connected-accounts-list/index.scss rename to ui/components/app/connected-accounts-list/index.scss diff --git a/ui/app/components/app/connected-accounts-permissions/connected-accounts-permissions.component.js b/ui/components/app/connected-accounts-permissions/connected-accounts-permissions.component.js similarity index 100% rename from ui/app/components/app/connected-accounts-permissions/connected-accounts-permissions.component.js rename to ui/components/app/connected-accounts-permissions/connected-accounts-permissions.component.js diff --git a/ui/app/components/app/connected-accounts-permissions/index.js b/ui/components/app/connected-accounts-permissions/index.js similarity index 100% rename from ui/app/components/app/connected-accounts-permissions/index.js rename to ui/components/app/connected-accounts-permissions/index.js diff --git a/ui/app/components/app/connected-accounts-permissions/index.scss b/ui/components/app/connected-accounts-permissions/index.scss similarity index 100% rename from ui/app/components/app/connected-accounts-permissions/index.scss rename to ui/components/app/connected-accounts-permissions/index.scss diff --git a/ui/app/components/app/connected-sites-list/connected-sites-list.component.js b/ui/components/app/connected-sites-list/connected-sites-list.component.js similarity index 100% rename from ui/app/components/app/connected-sites-list/connected-sites-list.component.js rename to ui/components/app/connected-sites-list/connected-sites-list.component.js diff --git a/ui/app/components/app/connected-sites-list/index.js b/ui/components/app/connected-sites-list/index.js similarity index 100% rename from ui/app/components/app/connected-sites-list/index.js rename to ui/components/app/connected-sites-list/index.js diff --git a/ui/app/components/app/connected-sites-list/index.scss b/ui/components/app/connected-sites-list/index.scss similarity index 100% rename from ui/app/components/app/connected-sites-list/index.scss rename to ui/components/app/connected-sites-list/index.scss diff --git a/ui/app/components/app/connected-status-indicator/connected-status-indicator.js b/ui/components/app/connected-status-indicator/connected-status-indicator.js similarity index 100% rename from ui/app/components/app/connected-status-indicator/connected-status-indicator.js rename to ui/components/app/connected-status-indicator/connected-status-indicator.js diff --git a/ui/app/components/app/connected-status-indicator/index.js b/ui/components/app/connected-status-indicator/index.js similarity index 100% rename from ui/app/components/app/connected-status-indicator/index.js rename to ui/components/app/connected-status-indicator/index.js diff --git a/ui/app/components/app/connected-status-indicator/index.scss b/ui/components/app/connected-status-indicator/index.scss similarity index 100% rename from ui/app/components/app/connected-status-indicator/index.scss rename to ui/components/app/connected-status-indicator/index.scss diff --git a/ui/app/components/app/contact-list/contact-list.component.js b/ui/components/app/contact-list/contact-list.component.js similarity index 100% rename from ui/app/components/app/contact-list/contact-list.component.js rename to ui/components/app/contact-list/contact-list.component.js diff --git a/ui/app/components/app/contact-list/index.js b/ui/components/app/contact-list/index.js similarity index 100% rename from ui/app/components/app/contact-list/index.js rename to ui/components/app/contact-list/index.js diff --git a/ui/app/components/app/contact-list/recipient-group/index.js b/ui/components/app/contact-list/recipient-group/index.js similarity index 100% rename from ui/app/components/app/contact-list/recipient-group/index.js rename to ui/components/app/contact-list/recipient-group/index.js diff --git a/ui/app/components/app/contact-list/recipient-group/recipient-group.component.js b/ui/components/app/contact-list/recipient-group/recipient-group.component.js similarity index 100% rename from ui/app/components/app/contact-list/recipient-group/recipient-group.component.js rename to ui/components/app/contact-list/recipient-group/recipient-group.component.js diff --git a/ui/app/components/app/dropdowns/dropdown.js b/ui/components/app/dropdowns/dropdown.js similarity index 100% rename from ui/app/components/app/dropdowns/dropdown.js rename to ui/components/app/dropdowns/dropdown.js diff --git a/ui/app/components/app/dropdowns/dropdown.test.js b/ui/components/app/dropdowns/dropdown.test.js similarity index 100% rename from ui/app/components/app/dropdowns/dropdown.test.js rename to ui/components/app/dropdowns/dropdown.test.js diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/components/app/dropdowns/network-dropdown.js similarity index 96% rename from ui/app/components/app/dropdowns/network-dropdown.js rename to ui/components/app/dropdowns/network-dropdown.js index e0742722d..66e44bd49 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/components/app/dropdowns/network-dropdown.js @@ -9,10 +9,10 @@ import { NETWORKS_ROUTE, NETWORKS_FORM_ROUTE, } from '../../../helpers/constants/routes'; -import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app'; -import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; -import { isPrefixedFormattedHexString } from '../../../../../shared/modules/network.utils'; -import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../shared/constants/app'; +import { NETWORK_TYPE_RPC } from '../../../../shared/constants/network'; +import { isPrefixedFormattedHexString } from '../../../../shared/modules/network.utils'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import ColorIndicator from '../../ui/color-indicator'; import { COLORS, SIZES } from '../../../helpers/constants/design-system'; diff --git a/ui/app/components/app/dropdowns/network-dropdown.test.js b/ui/components/app/dropdowns/network-dropdown.test.js similarity index 98% rename from ui/app/components/app/dropdowns/network-dropdown.test.js rename to ui/components/app/dropdowns/network-dropdown.test.js index 3452e8fef..f68fddd93 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.test.js +++ b/ui/components/app/dropdowns/network-dropdown.test.js @@ -1,7 +1,7 @@ import React from 'react'; import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; -import { mountWithRouter } from '../../../../../test/lib/render-helpers'; +import { mountWithRouter } from '../../../../test/lib/render-helpers'; import ColorIndicator from '../../ui/color-indicator'; import NetworkDropdown from './network-dropdown'; import { DropdownMenuItem } from './dropdown'; diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-input-component.test.js b/ui/components/app/gas-customization/advanced-gas-inputs/advanced-gas-input-component.test.js similarity index 100% rename from ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-input-component.test.js rename to ui/components/app/gas-customization/advanced-gas-inputs/advanced-gas-input-component.test.js diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js b/ui/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js similarity index 100% rename from ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js rename to ui/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.component.js diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js b/ui/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js similarity index 100% rename from ui/app/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js rename to ui/components/app/gas-customization/advanced-gas-inputs/advanced-gas-inputs.container.js diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/index.js b/ui/components/app/gas-customization/advanced-gas-inputs/index.js similarity index 100% rename from ui/app/components/app/gas-customization/advanced-gas-inputs/index.js rename to ui/components/app/gas-customization/advanced-gas-inputs/index.js diff --git a/ui/app/components/app/gas-customization/advanced-gas-inputs/index.scss b/ui/components/app/gas-customization/advanced-gas-inputs/index.scss similarity index 100% rename from ui/app/components/app/gas-customization/advanced-gas-inputs/index.scss rename to ui/components/app/gas-customization/advanced-gas-inputs/index.scss diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content-component.test.js b/ui/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content-component.test.js similarity index 93% rename from ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content-component.test.js rename to ui/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content-component.test.js index 0a91fbc69..4a7f86284 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content-component.test.js +++ b/ui/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content-component.test.js @@ -1,6 +1,6 @@ import React from 'react'; import sinon from 'sinon'; -import shallow from '../../../../../../lib/shallow-with-context'; +import { shallowWithContext } from '../../../../../../test/lib/render-helpers'; import AdvancedTabContent from './advanced-tab-content.component'; describe('AdvancedTabContent Component', () => { @@ -13,7 +13,7 @@ describe('AdvancedTabContent Component', () => { }; sinon.spy(AdvancedTabContent.prototype, 'renderDataSummary'); - wrapper = shallow( + wrapper = shallowWithContext( <AdvancedTabContent updateCustomGasPrice={propsMethodSpies.updateCustomGasPrice} updateCustomGasLimit={propsMethodSpies.updateCustomGasLimit} @@ -23,6 +23,7 @@ describe('AdvancedTabContent Component', () => { insufficientBalance={false} customPriceIsSafe isSpeedUp={false} + customPriceIsExcessive={false} />, ); }); @@ -59,7 +60,7 @@ describe('AdvancedTabContent Component', () => { let dataSummary; beforeEach(() => { - dataSummary = shallow( + dataSummary = shallowWithContext( wrapper.instance().renderDataSummary('mockTotalFee'), ); }); diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js b/ui/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js similarity index 100% rename from ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js rename to ui/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/advanced-tab-content.component.js diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.js b/ui/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.js similarity index 100% rename from ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.js rename to ui/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.js diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss b/ui/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss similarity index 100% rename from ui/app/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss rename to ui/components/app/gas-customization/gas-modal-page-container/advanced-tab-content/index.scss diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content-component.test.js b/ui/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content-component.test.js similarity index 96% rename from ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content-component.test.js rename to ui/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content-component.test.js index facda50a5..12114edcf 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content-component.test.js +++ b/ui/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content-component.test.js @@ -1,8 +1,8 @@ import React from 'react'; -import shallow from '../../../../../../lib/shallow-with-context'; import GasPriceButtonGroup from '../../gas-price-button-group'; import Loading from '../../../../ui/loading-screen'; import { GAS_ESTIMATE_TYPES } from '../../../../../helpers/constants/common'; +import { shallowWithContext } from '../../../../../../test/lib/render-helpers'; import BasicTabContent from './basic-tab-content.component'; const mockGasPriceButtonGroupProps = { @@ -42,7 +42,7 @@ describe('BasicTabContent Component', () => { let wrapper; beforeEach(() => { - wrapper = shallow( + wrapper = shallowWithContext( <BasicTabContent gasPriceButtonGroupProps={mockGasPriceButtonGroupProps} />, diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js b/ui/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js similarity index 100% rename from ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js rename to ui/components/app/gas-customization/gas-modal-page-container/basic-tab-content/basic-tab-content.component.js diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/index.js b/ui/components/app/gas-customization/gas-modal-page-container/basic-tab-content/index.js similarity index 100% rename from ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/index.js rename to ui/components/app/gas-customization/gas-modal-page-container/basic-tab-content/index.js diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/index.scss b/ui/components/app/gas-customization/gas-modal-page-container/basic-tab-content/index.scss similarity index 100% rename from ui/app/components/app/gas-customization/gas-modal-page-container/basic-tab-content/index.scss rename to ui/components/app/gas-customization/gas-modal-page-container/basic-tab-content/index.scss diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container-component.test.js b/ui/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container-component.test.js similarity index 94% rename from ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container-component.test.js rename to ui/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container-component.test.js index dd5f23e39..d88a3ab98 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container-component.test.js +++ b/ui/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container-component.test.js @@ -1,6 +1,6 @@ import React from 'react'; import sinon from 'sinon'; -import shallow from '../../../../../lib/shallow-with-context'; +import { shallowWithContext } from '../../../../../test/lib/render-helpers'; import PageContainer from '../../../ui/page-container'; @@ -63,7 +63,7 @@ describe('GasModalPageContainer Component', () => { let wrapper; beforeEach(() => { - wrapper = shallow( + wrapper = shallowWithContext( <GasModalPageContainer cancelAndClose={propsMethodSpies.cancelAndClose} onSubmit={propsMethodSpies.onSubmit} @@ -76,6 +76,7 @@ describe('GasModalPageContainer Component', () => { customGasLimitInHex="mockCustomGasLimitInHex" insufficientBalance={false} disableSave={false} + customPriceIsExcessive={false} />, ); }); @@ -120,10 +121,11 @@ describe('GasModalPageContainer Component', () => { it('should pass the correct renderTabs property to PageContainer', () => { sinon.stub(GP, 'renderTabs').returns('mockTabs'); - const renderTabsWrapperTester = shallow( + const renderTabsWrapperTester = shallowWithContext( <GasModalPageContainer fetchBasicGasEstimates={propsMethodSpies.fetchBasicGasEstimates} fetchGasEstimates={propsMethodSpies.fetchGasEstimates} + customPriceIsExcessive={false} />, { context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) } }, ); @@ -150,7 +152,7 @@ describe('GasModalPageContainer Component', () => { it('should render a Tabs component with "Basic" and "Advanced" tabs', () => { const renderTabsResult = wrapper.instance().renderTabs(); - const renderedTabs = shallow(renderTabsResult); + const renderedTabs = shallowWithContext(renderTabsResult); expect(renderedTabs.props().className).toStrictEqual('tabs'); const tabs = renderedTabs.find(Tab); @@ -189,7 +191,7 @@ describe('GasModalPageContainer Component', () => { }); it('should not render the basic tab if hideBasic is true', () => { - wrapper = shallow( + wrapper = shallowWithContext( <GasModalPageContainer cancelAndClose={propsMethodSpies.cancelAndClose} onSubmit={propsMethodSpies.onSubmit} @@ -202,12 +204,13 @@ describe('GasModalPageContainer Component', () => { customGasLimitInHex="mockCustomGasLimitInHex" insufficientBalance={false} disableSave={false} + customPriceIsExcessive={false} hideBasic />, ); const renderTabsResult = wrapper.instance().renderTabs(); - const renderedTabs = shallow(renderTabsResult); + const renderedTabs = shallowWithContext(renderTabsResult); const tabs = renderedTabs.find(Tab); expect(tabs).toHaveLength(1); expect(tabs.at(0).props().name).toStrictEqual('advanced'); @@ -229,7 +232,7 @@ describe('GasModalPageContainer Component', () => { describe('renderInfoRows', () => { it('should render the info rows with the passed data', () => { const baseClassName = 'gas-modal-content__info-row'; - const renderedInfoRowsContainer = shallow( + const renderedInfoRowsContainer = shallowWithContext( wrapper .instance() .renderInfoRows( diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container-container.test.js b/ui/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container-container.test.js similarity index 97% rename from ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container-container.test.js rename to ui/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container-container.test.js index ef5e62895..bcbbaa9d1 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container-container.test.js +++ b/ui/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container-container.test.js @@ -21,7 +21,7 @@ jest.mock('react-redux', () => ({ }, })); -jest.mock('../../../../../app/selectors', () => ({ +jest.mock('../../../../selectors', () => ({ getBasicGasEstimateLoadingStatus: (s) => `mockBasicGasEstimateLoadingStatus:${Object.keys(s).length}`, getRenderableBasicEstimateData: (s) => @@ -42,20 +42,20 @@ jest.mock('../../../../../app/selectors', () => ({ isCustomPriceSafe: jest.fn().mockReturnValue(true), })); -jest.mock('../../../../../app/store/actions', () => ({ +jest.mock('../../../../store/actions', () => ({ hideModal: jest.fn(), setGasLimit: jest.fn(), setGasPrice: jest.fn(), updateTransaction: jest.fn(), })); -jest.mock('../../../../../app/ducks/gas/gas.duck', () => ({ +jest.mock('../../../../ducks/gas/gas.duck', () => ({ setCustomGasPrice: jest.fn(), setCustomGasLimit: jest.fn(), resetCustomData: jest.fn(), })); -jest.mock('../../../../../app/ducks/send/send.duck', () => ({ +jest.mock('../../../../ducks/send/send.duck', () => ({ hideGasButtonGroup: jest.fn(), })); diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js b/ui/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js similarity index 92% rename from ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js rename to ui/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js index f57cce92d..ea59b7882 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js +++ b/ui/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.component.js @@ -123,19 +123,25 @@ export default class GasModalPageContainer extends Component { infoRowProps: { newTotalFiat, newTotalEth, sendAmount, transactionFee }, } = this.props; - let tabsToRender = [ - { - name: this.context.t('basic'), - content: this.renderBasicTabContent(gasPriceButtonGroupProps), - }, - { - name: this.context.t('advanced'), - content: this.renderAdvancedTabContent(), - }, - ]; - + let tabsToRender; if (hideBasic) { - tabsToRender = tabsToRender.slice(1); + tabsToRender = [ + { + name: this.context.t('advanced'), + content: this.renderAdvancedTabContent(), + }, + ]; + } else { + tabsToRender = [ + { + name: this.context.t('basic'), + content: this.renderBasicTabContent(gasPriceButtonGroupProps), + }, + { + name: this.context.t('advanced'), + content: this.renderAdvancedTabContent(), + }, + ]; } return ( diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js b/ui/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js similarity index 96% rename from ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js rename to ui/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js index 4d57502b2..4dbbeec22 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js +++ b/ui/components/app/gas-customization/gas-modal-page-container/gas-modal-page-container.container.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux'; -import { addHexPrefix } from '../../../../../../app/scripts/lib/util'; +import { addHexPrefix } from '../../../../../app/scripts/lib/util'; import { hideModal, setGasLimit, @@ -38,6 +38,7 @@ import { getSendMaxModeState, getAveragePriceEstimateInHexWEI, isCustomPriceExcessive, + getIsGasEstimatesFetched, } from '../../../../selectors'; import { @@ -54,7 +55,7 @@ import { } from '../../../../pages/send/send.utils'; import { MIN_GAS_LIMIT_DEC } from '../../../../pages/send/send.constants'; import { calcMaxAmount } from '../../../../pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils'; -import { TRANSACTION_STATUSES } from '../../../../../../shared/constants/transaction'; +import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction'; import GasModalPageContainer from './gas-modal-page-container.component'; const mapStateToProps = (state, ownProps) => { @@ -132,7 +133,7 @@ const mapStateToProps = (state, ownProps) => { balance, conversionRate, }); - + const isGasEstimate = getIsGasEstimatesFetched(state); return { hideBasic, isConfirm: isConfirm(state), @@ -142,7 +143,10 @@ const mapStateToProps = (state, ownProps) => { customGasLimit: calcCustomGasLimit(customModalGasLimitInHex), customGasTotal, newTotalFiat, - customPriceIsSafe: isCustomPriceSafe(state), + customPriceIsSafe: + (isMainnet || process.env.IN_TEST) && isGasEstimate + ? isCustomPriceSafe(state) + : true, customPriceIsExcessive: isCustomPriceExcessive(state), maxModeOn, gasPriceButtonGroupProps: { diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/index.js b/ui/components/app/gas-customization/gas-modal-page-container/index.js similarity index 100% rename from ui/app/components/app/gas-customization/gas-modal-page-container/index.js rename to ui/components/app/gas-customization/gas-modal-page-container/index.js diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/index.scss b/ui/components/app/gas-customization/gas-modal-page-container/index.scss similarity index 100% rename from ui/app/components/app/gas-customization/gas-modal-page-container/index.scss rename to ui/components/app/gas-customization/gas-modal-page-container/index.scss diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group-component.test.js b/ui/components/app/gas-customization/gas-price-button-group/gas-price-button-group-component.test.js similarity index 93% rename from ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group-component.test.js rename to ui/components/app/gas-customization/gas-price-button-group/gas-price-button-group-component.test.js index 2cb5cb428..2391c23a6 100644 --- a/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group-component.test.js +++ b/ui/components/app/gas-customization/gas-price-button-group/gas-price-button-group-component.test.js @@ -1,6 +1,6 @@ import React from 'react'; import sinon from 'sinon'; -import shallow from '../../../../../lib/shallow-with-context'; +import { shallowWithContext } from '../../../../../test/lib/render-helpers'; import { GAS_ESTIMATE_TYPES } from '../../../../helpers/constants/common'; import ButtonGroup from '../../../ui/button-group'; @@ -54,7 +54,7 @@ describe('GasPriceButtonGroup Component', () => { sinon.spy(GasPriceButtonGroup.prototype, 'renderButton'); sinon.spy(GasPriceButtonGroup.prototype, 'renderButtonContent'); - wrapper = shallow( + wrapper = shallowWithContext( <GasPriceButtonGroup {...mockGasPriceButtonGroupProps} />, ); }); @@ -119,7 +119,7 @@ describe('GasPriceButtonGroup Component', () => { { ...mockGasPriceButtonGroupProps.gasButtonInfo[0] }, mockButtonPropsAndFlags, ); - wrappedRenderButtonResult = shallow(renderButtonResult); + wrappedRenderButtonResult = shallowWithContext(renderButtonResult); }); it('should render a button', () => { @@ -183,7 +183,7 @@ describe('GasPriceButtonGroup Component', () => { className: 'someClass', }, ); - const wrappedRenderButtonContentResult = shallow( + const wrappedRenderButtonContentResult = shallowWithContext( renderButtonContentResult, ); expect( @@ -203,7 +203,7 @@ describe('GasPriceButtonGroup Component', () => { className: 'someClass', }, ); - const wrappedRenderButtonContentResult = shallow( + const wrappedRenderButtonContentResult = shallowWithContext( renderButtonContentResult, ); expect( @@ -225,7 +225,7 @@ describe('GasPriceButtonGroup Component', () => { className: 'someClass', }, ); - const wrappedRenderButtonContentResult = shallow( + const wrappedRenderButtonContentResult = shallowWithContext( renderButtonContentResult, ); expect( @@ -247,7 +247,7 @@ describe('GasPriceButtonGroup Component', () => { className: 'someClass', }, ); - const wrappedRenderButtonContentResult = shallow( + const wrappedRenderButtonContentResult = shallowWithContext( renderButtonContentResult, ); expect( @@ -268,7 +268,7 @@ describe('GasPriceButtonGroup Component', () => { showCheck: true, }, ); - const wrappedRenderButtonContentResult = shallow( + const wrappedRenderButtonContentResult = shallowWithContext( renderButtonContentResult, ); expect(wrappedRenderButtonContentResult.find('.fa-check')).toHaveLength( @@ -289,7 +289,7 @@ describe('GasPriceButtonGroup Component', () => { showCheck: true, }, ); - const wrappedRenderButtonContentResult = shallow( + const wrappedRenderButtonContentResult = shallowWithContext( renderButtonContentResult, ); expect(wrappedRenderButtonContentResult.children()).toHaveLength(5); @@ -300,7 +300,7 @@ describe('GasPriceButtonGroup Component', () => { {}, {}, ); - const wrappedRenderButtonContentResult = shallow( + const wrappedRenderButtonContentResult = shallowWithContext( renderButtonContentResult, ); expect(wrappedRenderButtonContentResult.children()).toHaveLength(0); diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js b/ui/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js similarity index 100% rename from ui/app/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js rename to ui/components/app/gas-customization/gas-price-button-group/gas-price-button-group.component.js diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/index.js b/ui/components/app/gas-customization/gas-price-button-group/index.js similarity index 100% rename from ui/app/components/app/gas-customization/gas-price-button-group/index.js rename to ui/components/app/gas-customization/gas-price-button-group/index.js diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/index.scss b/ui/components/app/gas-customization/gas-price-button-group/index.scss similarity index 100% rename from ui/app/components/app/gas-customization/gas-price-button-group/index.scss rename to ui/components/app/gas-customization/gas-price-button-group/index.scss diff --git a/ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js b/ui/components/app/gas-customization/gas-slider/gas-slider.component.js similarity index 100% rename from ui/app/components/app/gas-customization/gas-slider/gas-slider.component.js rename to ui/components/app/gas-customization/gas-slider/gas-slider.component.js diff --git a/ui/app/components/app/gas-customization/gas-slider/index.js b/ui/components/app/gas-customization/gas-slider/index.js similarity index 100% rename from ui/app/components/app/gas-customization/gas-slider/index.js rename to ui/components/app/gas-customization/gas-slider/index.js diff --git a/ui/app/components/app/gas-customization/gas-slider/index.scss b/ui/components/app/gas-customization/gas-slider/index.scss similarity index 100% rename from ui/app/components/app/gas-customization/gas-slider/index.scss rename to ui/components/app/gas-customization/gas-slider/index.scss diff --git a/ui/app/components/app/gas-customization/index.scss b/ui/components/app/gas-customization/index.scss similarity index 100% rename from ui/app/components/app/gas-customization/index.scss rename to ui/components/app/gas-customization/index.scss diff --git a/ui/app/components/app/home-notification/home-notification.component.js b/ui/components/app/home-notification/home-notification.component.js similarity index 100% rename from ui/app/components/app/home-notification/home-notification.component.js rename to ui/components/app/home-notification/home-notification.component.js diff --git a/ui/app/components/app/home-notification/index.js b/ui/components/app/home-notification/index.js similarity index 100% rename from ui/app/components/app/home-notification/index.js rename to ui/components/app/home-notification/index.js diff --git a/ui/app/components/app/home-notification/index.scss b/ui/components/app/home-notification/index.scss similarity index 100% rename from ui/app/components/app/home-notification/index.scss rename to ui/components/app/home-notification/index.scss diff --git a/ui/app/components/app/info-box/index.js b/ui/components/app/info-box/index.js similarity index 100% rename from ui/app/components/app/info-box/index.js rename to ui/components/app/info-box/index.js diff --git a/ui/app/components/app/info-box/index.scss b/ui/components/app/info-box/index.scss similarity index 100% rename from ui/app/components/app/info-box/index.scss rename to ui/components/app/info-box/index.scss diff --git a/ui/app/components/app/info-box/info-box.component.js b/ui/components/app/info-box/info-box.component.js similarity index 100% rename from ui/app/components/app/info-box/info-box.component.js rename to ui/components/app/info-box/info-box.component.js diff --git a/ui/app/components/app/info-box/info-box.test.js b/ui/components/app/info-box/info-box.test.js similarity index 100% rename from ui/app/components/app/info-box/info-box.test.js rename to ui/components/app/info-box/info-box.test.js diff --git a/ui/app/components/app/loading-network-screen/index.js b/ui/components/app/loading-network-screen/index.js similarity index 100% rename from ui/app/components/app/loading-network-screen/index.js rename to ui/components/app/loading-network-screen/index.js diff --git a/ui/app/components/app/loading-network-screen/loading-network-screen.component.js b/ui/components/app/loading-network-screen/loading-network-screen.component.js similarity index 100% rename from ui/app/components/app/loading-network-screen/loading-network-screen.component.js rename to ui/components/app/loading-network-screen/loading-network-screen.component.js diff --git a/ui/app/components/app/loading-network-screen/loading-network-screen.container.js b/ui/components/app/loading-network-screen/loading-network-screen.container.js similarity index 93% rename from ui/app/components/app/loading-network-screen/loading-network-screen.container.js rename to ui/components/app/loading-network-screen/loading-network-screen.container.js index bfce78fbe..2f1e711ce 100644 --- a/ui/app/components/app/loading-network-screen/loading-network-screen.container.js +++ b/ui/components/app/loading-network-screen/loading-network-screen.container.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux'; -import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; +import { NETWORK_TYPE_RPC } from '../../../../shared/constants/network'; import * as actions from '../../../store/actions'; import { getNetworkIdentifier, isNetworkLoading } from '../../../selectors'; import LoadingNetworkScreen from './loading-network-screen.component'; diff --git a/ui/app/components/app/menu-bar/account-options-menu.js b/ui/components/app/menu-bar/account-options-menu.js similarity index 84% rename from ui/app/components/app/menu-bar/account-options-menu.js rename to ui/components/app/menu-bar/account-options-menu.js index b8ea6d1d4..3ae13c385 100644 --- a/ui/app/components/app/menu-bar/account-options-menu.js +++ b/ui/components/app/menu-bar/account-options-menu.js @@ -2,11 +2,11 @@ import React from 'react'; import PropTypes from 'prop-types'; import { useHistory } from 'react-router-dom'; import { useDispatch, useSelector } from 'react-redux'; +import { getAccountLink } from '@metamask/etherscan-link'; import { showModal } from '../../../store/actions'; import { CONNECTED_ROUTE } from '../../../helpers/constants/routes'; import { Menu, MenuItem } from '../../ui/menu'; -import getAccountLink from '../../../../lib/account-link'; import { getCurrentChainId, getCurrentKeyring, @@ -14,14 +14,25 @@ import { getSelectedIdentity, } from '../../../selectors'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { useMetricEvent } from '../../../hooks/useMetricEvent'; -import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; -import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app'; +import { + useMetricEvent, + useNewMetricEvent, +} from '../../../hooks/useMetricEvent'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../shared/constants/app'; export default function AccountOptionsMenu({ anchorElement, onClose }) { const t = useI18nContext(); const dispatch = useDispatch(); const history = useHistory(); + + const keyring = useSelector(getCurrentKeyring); + const chainId = useSelector(getCurrentChainId); + const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); + const selectedIdentity = useSelector(getSelectedIdentity); + const { address } = selectedIdentity; + const addressLink = getAccountLink(address, chainId, rpcPrefs); + const openFullscreenEvent = useMetricEvent({ eventOpts: { category: 'Navigation', @@ -36,13 +47,7 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) { name: 'Viewed Account Details', }, }); - const viewOnEtherscanEvent = useMetricEvent({ - eventOpts: { - category: 'Navigation', - action: 'Account Options', - name: 'Clicked View on Etherscan', - }, - }); + const openConnectedSitesEvent = useMetricEvent({ eventOpts: { category: 'Navigation', @@ -51,12 +56,16 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) { }, }); - const keyring = useSelector(getCurrentKeyring); - const chainId = useSelector(getCurrentChainId); - const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); - const selectedIdentity = useSelector(getSelectedIdentity); + const blockExplorerLinkClickedEvent = useNewMetricEvent({ + category: 'Navigation', + event: 'Clicked Block Explorer Link', + properties: { + link_type: 'Account Tracker', + action: 'Account Options', + block_explorer_domain: addressLink ? new URL(addressLink)?.hostname : '', + }, + }); - const { address } = selectedIdentity; const isRemovable = keyring.type !== 'HD Key Tree'; return ( @@ -90,9 +99,9 @@ export default function AccountOptionsMenu({ anchorElement, onClose }) { </MenuItem> <MenuItem onClick={() => { - viewOnEtherscanEvent(); + blockExplorerLinkClickedEvent(); global.platform.openTab({ - url: getAccountLink(address, chainId, rpcPrefs), + url: addressLink, }); onClose(); }} diff --git a/ui/app/components/app/menu-bar/index.js b/ui/components/app/menu-bar/index.js similarity index 100% rename from ui/app/components/app/menu-bar/index.js rename to ui/components/app/menu-bar/index.js diff --git a/ui/app/components/app/menu-bar/index.scss b/ui/components/app/menu-bar/index.scss similarity index 100% rename from ui/app/components/app/menu-bar/index.scss rename to ui/components/app/menu-bar/index.scss diff --git a/ui/app/components/app/menu-bar/menu-bar.js b/ui/components/app/menu-bar/menu-bar.js similarity index 92% rename from ui/app/components/app/menu-bar/menu-bar.js rename to ui/components/app/menu-bar/menu-bar.js index 7b623c2c6..b5e3fdb7c 100644 --- a/ui/app/components/app/menu-bar/menu-bar.js +++ b/ui/components/app/menu-bar/menu-bar.js @@ -4,8 +4,8 @@ import { useHistory } from 'react-router-dom'; import { useSelector } from 'react-redux'; import SelectedAccount from '../selected-account'; import ConnectedStatusIndicator from '../connected-status-indicator'; -import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; -import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; import { CONNECTED_ACCOUNTS_ROUTE } from '../../../helpers/constants/routes'; import { useI18nContext } from '../../../hooks/useI18nContext'; import { useMetricEvent } from '../../../hooks/useMetricEvent'; diff --git a/ui/app/components/app/menu-bar/menu-bar.test.js b/ui/components/app/menu-bar/menu-bar.test.js similarity index 65% rename from ui/app/components/app/menu-bar/menu-bar.test.js rename to ui/components/app/menu-bar/menu-bar.test.js index 5db320352..89f933717 100644 --- a/ui/app/components/app/menu-bar/menu-bar.test.js +++ b/ui/components/app/menu-bar/menu-bar.test.js @@ -1,8 +1,9 @@ import React from 'react'; import { Provider } from 'react-redux'; import configureStore from 'redux-mock-store'; -import { mountWithRouter } from '../../../../../test/lib/render-helpers'; -import { ROPSTEN_CHAIN_ID } from '../../../../../shared/constants/network'; +import { waitFor } from '@testing-library/react'; +import { mountWithRouter } from '../../../../test/lib/render-helpers'; +import { ROPSTEN_CHAIN_ID } from '../../../../shared/constants/network'; import MenuBar from './menu-bar'; const initState = { @@ -30,21 +31,25 @@ const initState = { const mockStore = configureStore(); describe('MenuBar', () => { - it('opens account detail menu when account options is clicked', () => { + it('opens account detail menu when account options is clicked', async () => { const store = mockStore(initState); const wrapper = mountWithRouter( <Provider store={store}> <MenuBar /> </Provider>, ); - expect(!wrapper.exists('AccountOptionsMenu')).toStrictEqual(true); + await waitFor(() => + expect(!wrapper.exists('AccountOptionsMenu')).toStrictEqual(true), + ); const accountOptions = wrapper.find('.menu-bar__account-options'); accountOptions.simulate('click'); wrapper.update(); - expect(wrapper.exists('AccountOptionsMenu')).toStrictEqual(true); + await waitFor(() => + expect(wrapper.exists('AccountOptionsMenu')).toStrictEqual(true), + ); }); - it('sets accountDetailsMenuOpen to false when closed', () => { + it('sets accountDetailsMenuOpen to false when closed', async () => { const store = mockStore(initState); const wrapper = mountWithRouter( <Provider store={store}> @@ -54,10 +59,14 @@ describe('MenuBar', () => { const accountOptions = wrapper.find('.menu-bar__account-options'); accountOptions.simulate('click'); wrapper.update(); - expect(wrapper.exists('AccountOptionsMenu')).toStrictEqual(true); + await waitFor(() => + expect(wrapper.exists('AccountOptionsMenu')).toStrictEqual(true), + ); const accountDetailsMenu = wrapper.find('AccountOptionsMenu'); - accountDetailsMenu.prop('onClose')(); - wrapper.update(); - expect(!wrapper.exists('AccountOptionsMenu')).toStrictEqual(true); + await waitFor(() => { + accountDetailsMenu.prop('onClose')(); + wrapper.update(); + expect(!wrapper.exists('AccountOptionsMenu')).toStrictEqual(true); + }); }); }); diff --git a/ui/app/components/app/menu-droppo.js b/ui/components/app/menu-droppo.js similarity index 100% rename from ui/app/components/app/menu-droppo.js rename to ui/components/app/menu-droppo.js diff --git a/ui/app/components/app/metamask-template-renderer/index.js b/ui/components/app/metamask-template-renderer/index.js similarity index 100% rename from ui/app/components/app/metamask-template-renderer/index.js rename to ui/components/app/metamask-template-renderer/index.js diff --git a/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js b/ui/components/app/metamask-template-renderer/metamask-template-renderer.js similarity index 100% rename from ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js rename to ui/components/app/metamask-template-renderer/metamask-template-renderer.js diff --git a/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.stories.js b/ui/components/app/metamask-template-renderer/metamask-template-renderer.stories.js similarity index 100% rename from ui/app/components/app/metamask-template-renderer/metamask-template-renderer.stories.js rename to ui/components/app/metamask-template-renderer/metamask-template-renderer.stories.js diff --git a/ui/app/components/app/metamask-template-renderer/safe-component-list.js b/ui/components/app/metamask-template-renderer/safe-component-list.js similarity index 100% rename from ui/app/components/app/metamask-template-renderer/safe-component-list.js rename to ui/components/app/metamask-template-renderer/safe-component-list.js diff --git a/ui/app/components/app/metamask-translation/index.js b/ui/components/app/metamask-translation/index.js similarity index 100% rename from ui/app/components/app/metamask-translation/index.js rename to ui/components/app/metamask-translation/index.js diff --git a/ui/app/components/app/metamask-translation/metamask-translation.js b/ui/components/app/metamask-translation/metamask-translation.js similarity index 100% rename from ui/app/components/app/metamask-translation/metamask-translation.js rename to ui/components/app/metamask-translation/metamask-translation.js diff --git a/ui/app/components/app/metamask-translation/metamask-translation.stories.js b/ui/components/app/metamask-translation/metamask-translation.stories.js similarity index 95% rename from ui/app/components/app/metamask-translation/metamask-translation.stories.js rename to ui/components/app/metamask-translation/metamask-translation.stories.js index 21d321ccc..429037810 100644 --- a/ui/app/components/app/metamask-translation/metamask-translation.stories.js +++ b/ui/components/app/metamask-translation/metamask-translation.stories.js @@ -1,7 +1,7 @@ import React from 'react'; import { select, object } from '@storybook/addon-knobs'; import { groupBy } from 'lodash'; -import en from '../../../../../app/_locales/en/messages.json'; +import en from '../../../../app/_locales/en/messages.json'; import MetaMaskTranslation from './metamask-translation'; export default { diff --git a/ui/app/components/app/modal/index.js b/ui/components/app/modal/index.js similarity index 100% rename from ui/app/components/app/modal/index.js rename to ui/components/app/modal/index.js diff --git a/ui/app/components/app/modal/index.scss b/ui/components/app/modal/index.scss similarity index 100% rename from ui/app/components/app/modal/index.scss rename to ui/components/app/modal/index.scss diff --git a/ui/app/components/app/modal/modal-content/index.js b/ui/components/app/modal/modal-content/index.js similarity index 100% rename from ui/app/components/app/modal/modal-content/index.js rename to ui/components/app/modal/modal-content/index.js diff --git a/ui/app/components/app/modal/modal-content/index.scss b/ui/components/app/modal/modal-content/index.scss similarity index 100% rename from ui/app/components/app/modal/modal-content/index.scss rename to ui/components/app/modal/modal-content/index.scss diff --git a/ui/app/components/app/modal/modal-content/modal-content.component.js b/ui/components/app/modal/modal-content/modal-content.component.js similarity index 100% rename from ui/app/components/app/modal/modal-content/modal-content.component.js rename to ui/components/app/modal/modal-content/modal-content.component.js diff --git a/ui/app/components/app/modal/modal-content/modal-content.component.test.js b/ui/components/app/modal/modal-content/modal-content.component.test.js similarity index 100% rename from ui/app/components/app/modal/modal-content/modal-content.component.test.js rename to ui/components/app/modal/modal-content/modal-content.component.test.js diff --git a/ui/app/components/app/modal/modal.component.js b/ui/components/app/modal/modal.component.js similarity index 100% rename from ui/app/components/app/modal/modal.component.js rename to ui/components/app/modal/modal.component.js diff --git a/ui/app/components/app/modal/modal.component.test.js b/ui/components/app/modal/modal.component.test.js similarity index 100% rename from ui/app/components/app/modal/modal.component.test.js rename to ui/components/app/modal/modal.component.test.js diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js b/ui/components/app/modals/account-details-modal/account-details-modal.component.js similarity index 79% rename from ui/app/components/app/modals/account-details-modal/account-details-modal.component.js rename to ui/components/app/modals/account-details-modal/account-details-modal.component.js index 7e36e0a6c..6dc47f3d2 100644 --- a/ui/app/components/app/modals/account-details-modal/account-details-modal.component.js +++ b/ui/components/app/modals/account-details-modal/account-details-modal.component.js @@ -1,7 +1,8 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import { getAccountLink } from '@metamask/etherscan-link'; + import AccountModalContainer from '../account-modal-container'; -import getAccountLink from '../../../../../lib/account-link'; import QrView from '../../../ui/qr-code'; import EditableLabel from '../../../ui/editable-label'; import Button from '../../../ui/button'; @@ -18,6 +19,7 @@ export default class AccountDetailsModal extends Component { static contextTypes = { t: PropTypes.func, + trackEvent: PropTypes.func, }; render() { @@ -61,8 +63,20 @@ export default class AccountDetailsModal extends Component { type="secondary" className="account-details-modal__button" onClick={() => { + const accountLink = getAccountLink(address, chainId, rpcPrefs); + this.context.trackEvent({ + category: 'Navigation', + event: 'Clicked Block Explorer Link', + properties: { + link_type: 'Account Tracker', + action: 'Account Details Modal', + block_explorer_domain: accountLink + ? new URL(accountLink)?.hostname + : '', + }, + }); global.platform.openTab({ - url: getAccountLink(address, chainId, rpcPrefs), + url: accountLink, }); }} > diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.container.js b/ui/components/app/modals/account-details-modal/account-details-modal.container.js similarity index 100% rename from ui/app/components/app/modals/account-details-modal/account-details-modal.container.js rename to ui/components/app/modals/account-details-modal/account-details-modal.container.js diff --git a/ui/app/components/app/modals/account-details-modal/account-details-modal.test.js b/ui/components/app/modals/account-details-modal/account-details-modal.test.js similarity index 98% rename from ui/app/components/app/modals/account-details-modal/account-details-modal.test.js rename to ui/components/app/modals/account-details-modal/account-details-modal.test.js index a0e7a93ed..2f0fdb788 100644 --- a/ui/app/components/app/modals/account-details-modal/account-details-modal.test.js +++ b/ui/components/app/modals/account-details-modal/account-details-modal.test.js @@ -36,6 +36,7 @@ describe('Account Details Modal', () => { wrapper = shallow(<AccountDetailsModal.WrappedComponent {...props} />, { context: { t: (str) => str, + trackEvent: (e) => e, }, }); }); diff --git a/ui/app/components/app/modals/account-details-modal/index.js b/ui/components/app/modals/account-details-modal/index.js similarity index 100% rename from ui/app/components/app/modals/account-details-modal/index.js rename to ui/components/app/modals/account-details-modal/index.js diff --git a/ui/app/components/app/modals/account-details-modal/index.scss b/ui/components/app/modals/account-details-modal/index.scss similarity index 100% rename from ui/app/components/app/modals/account-details-modal/index.scss rename to ui/components/app/modals/account-details-modal/index.scss diff --git a/ui/app/components/app/modals/account-modal-container/account-modal-container.component.js b/ui/components/app/modals/account-modal-container/account-modal-container.component.js similarity index 100% rename from ui/app/components/app/modals/account-modal-container/account-modal-container.component.js rename to ui/components/app/modals/account-modal-container/account-modal-container.component.js diff --git a/ui/app/components/app/modals/account-modal-container/account-modal-container.container.js b/ui/components/app/modals/account-modal-container/account-modal-container.container.js similarity index 100% rename from ui/app/components/app/modals/account-modal-container/account-modal-container.container.js rename to ui/components/app/modals/account-modal-container/account-modal-container.container.js diff --git a/ui/app/components/app/modals/account-modal-container/index.js b/ui/components/app/modals/account-modal-container/index.js similarity index 100% rename from ui/app/components/app/modals/account-modal-container/index.js rename to ui/components/app/modals/account-modal-container/index.js diff --git a/ui/app/components/app/modals/account-modal-container/index.scss b/ui/components/app/modals/account-modal-container/index.scss similarity index 100% rename from ui/app/components/app/modals/account-modal-container/index.scss rename to ui/components/app/modals/account-modal-container/index.scss diff --git a/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.component.js b/ui/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.component.js similarity index 100% rename from ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.component.js rename to ui/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.component.js diff --git a/ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.container.js b/ui/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.container.js similarity index 100% rename from ui/app/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.container.js rename to ui/components/app/modals/add-to-addressbook-modal/add-to-addressbook-modal.container.js diff --git a/ui/app/components/app/modals/add-to-addressbook-modal/index.js b/ui/components/app/modals/add-to-addressbook-modal/index.js similarity index 100% rename from ui/app/components/app/modals/add-to-addressbook-modal/index.js rename to ui/components/app/modals/add-to-addressbook-modal/index.js diff --git a/ui/app/components/app/modals/add-to-addressbook-modal/index.scss b/ui/components/app/modals/add-to-addressbook-modal/index.scss similarity index 100% rename from ui/app/components/app/modals/add-to-addressbook-modal/index.scss rename to ui/components/app/modals/add-to-addressbook-modal/index.scss diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.js b/ui/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.js similarity index 100% rename from ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.js rename to ui/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.js diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.test.js b/ui/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.test.js similarity index 100% rename from ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.test.js rename to ui/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/cancel-transaction-gas-fee.component.test.js diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/index.js b/ui/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/index.js similarity index 100% rename from ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/index.js rename to ui/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/index.js diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/index.scss b/ui/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/index.scss similarity index 100% rename from ui/app/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/index.scss rename to ui/components/app/modals/cancel-transaction/cancel-transaction-gas-fee/index.scss diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js b/ui/components/app/modals/cancel-transaction/cancel-transaction.component.js similarity index 95% rename from ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js rename to ui/components/app/modals/cancel-transaction/cancel-transaction.component.js index d45ba6198..9b436f7d9 100644 --- a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.js +++ b/ui/components/app/modals/cancel-transaction/cancel-transaction.component.js @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import Modal from '../../modal'; -import { TRANSACTION_STATUSES } from '../../../../../../shared/constants/transaction'; +import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction'; import CancelTransactionGasFee from './cancel-transaction-gas-fee'; export default class CancelTransaction extends PureComponent { diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.test.js b/ui/components/app/modals/cancel-transaction/cancel-transaction.component.test.js similarity index 100% rename from ui/app/components/app/modals/cancel-transaction/cancel-transaction.component.test.js rename to ui/components/app/modals/cancel-transaction/cancel-transaction.component.test.js diff --git a/ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js b/ui/components/app/modals/cancel-transaction/cancel-transaction.container.js similarity index 100% rename from ui/app/components/app/modals/cancel-transaction/cancel-transaction.container.js rename to ui/components/app/modals/cancel-transaction/cancel-transaction.container.js diff --git a/ui/app/components/app/modals/cancel-transaction/index.js b/ui/components/app/modals/cancel-transaction/index.js similarity index 100% rename from ui/app/components/app/modals/cancel-transaction/index.js rename to ui/components/app/modals/cancel-transaction/index.js diff --git a/ui/app/components/app/modals/cancel-transaction/index.scss b/ui/components/app/modals/cancel-transaction/index.scss similarity index 100% rename from ui/app/components/app/modals/cancel-transaction/index.scss rename to ui/components/app/modals/cancel-transaction/index.scss diff --git a/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.component.js b/ui/components/app/modals/confirm-delete-network/confirm-delete-network.component.js similarity index 100% rename from ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.component.js rename to ui/components/app/modals/confirm-delete-network/confirm-delete-network.component.js diff --git a/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js b/ui/components/app/modals/confirm-delete-network/confirm-delete-network.container.js similarity index 100% rename from ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js rename to ui/components/app/modals/confirm-delete-network/confirm-delete-network.container.js diff --git a/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.test.js b/ui/components/app/modals/confirm-delete-network/confirm-delete-network.test.js similarity index 100% rename from ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.test.js rename to ui/components/app/modals/confirm-delete-network/confirm-delete-network.test.js diff --git a/ui/app/components/app/modals/confirm-delete-network/index.js b/ui/components/app/modals/confirm-delete-network/index.js similarity index 100% rename from ui/app/components/app/modals/confirm-delete-network/index.js rename to ui/components/app/modals/confirm-delete-network/index.js diff --git a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js b/ui/components/app/modals/confirm-remove-account/confirm-remove-account.component.js similarity index 70% rename from ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js rename to ui/components/app/modals/confirm-remove-account/confirm-remove-account.component.js index 8c2831c2c..5b90f0359 100644 --- a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.component.js +++ b/ui/components/app/modals/confirm-remove-account/confirm-remove-account.component.js @@ -1,9 +1,9 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import { getAccountLink } from '@metamask/etherscan-link'; import Modal from '../../modal'; import { addressSummary } from '../../../../helpers/utils/util'; import Identicon from '../../../ui/identicon'; -import getAccountLink from '../../../../../lib/account-link'; export default class ConfirmRemoveAccount extends Component { static propTypes = { @@ -16,6 +16,7 @@ export default class ConfirmRemoveAccount extends Component { static contextTypes = { t: PropTypes.func, + trackEvent: PropTypes.func, }; handleRemove = () => { @@ -29,19 +30,22 @@ export default class ConfirmRemoveAccount extends Component { }; renderSelectedAccount() { - const { identity } = this.props; + const { t } = this.context; + const { identity, rpcPrefs, chainId } = this.props; return ( <div className="confirm-remove-account__account"> <div className="confirm-remove-account__account__identicon"> <Identicon address={identity.address} diameter={32} /> </div> <div className="confirm-remove-account__account__name"> - <span className="confirm-remove-account__account__label">Name</span> + <span className="confirm-remove-account__account__label"> + {t('name')} + </span> <span className="account_value">{identity.name}</span> </div> <div className="confirm-remove-account__account__address"> <span className="confirm-remove-account__account__label"> - Public Address + {t('publicAddress')} </span> <span className="account_value"> {addressSummary(identity.address, 4, 4)} @@ -50,19 +54,32 @@ export default class ConfirmRemoveAccount extends Component { <div className="confirm-remove-account__account__link"> <a className="" - href={getAccountLink( - identity.address, - this.props.chainId, - this.props.rpcPrefs, - )} + onClick={() => { + const accountLink = getAccountLink( + identity.address, + chainId, + rpcPrefs, + ); + this.context.trackEvent({ + category: 'Accounts', + event: 'Clicked Block Explorer Link', + properties: { + link_type: 'Account Tracker', + action: 'Remove Account', + block_explorer_domain: accountLink + ? new URL(accountLink)?.hostname + : '', + }, + }); + global.platform.openTab({ + url: accountLink, + }); + }} target="_blank" rel="noopener noreferrer" - title={this.context.t('etherscanView')} + title={t('etherscanView')} > - <img - src="images/popout.svg" - alt={this.context.t('etherscanView')} - /> + <img src="images/popout.svg" alt={t('etherscanView')} /> </a> </div> </div> diff --git a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js b/ui/components/app/modals/confirm-remove-account/confirm-remove-account.container.js similarity index 100% rename from ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.container.js rename to ui/components/app/modals/confirm-remove-account/confirm-remove-account.container.js diff --git a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.test.js b/ui/components/app/modals/confirm-remove-account/confirm-remove-account.test.js similarity index 97% rename from ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.test.js rename to ui/components/app/modals/confirm-remove-account/confirm-remove-account.test.js index fd89e96f8..da59aeffa 100644 --- a/ui/app/components/app/modals/confirm-remove-account/confirm-remove-account.test.js +++ b/ui/components/app/modals/confirm-remove-account/confirm-remove-account.test.js @@ -21,6 +21,8 @@ describe('Confirm Remove Account', () => { address: '0x0', name: 'Account 1', }, + chainId: '0x0', + rpcPrefs: {}, }; const mockStore = configureStore(); diff --git a/ui/app/components/app/modals/confirm-remove-account/index.js b/ui/components/app/modals/confirm-remove-account/index.js similarity index 100% rename from ui/app/components/app/modals/confirm-remove-account/index.js rename to ui/components/app/modals/confirm-remove-account/index.js diff --git a/ui/app/components/app/modals/confirm-remove-account/index.scss b/ui/components/app/modals/confirm-remove-account/index.scss similarity index 100% rename from ui/app/components/app/modals/confirm-remove-account/index.scss rename to ui/components/app/modals/confirm-remove-account/index.scss diff --git a/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.component.js b/ui/components/app/modals/confirm-reset-account/confirm-reset-account.component.js similarity index 100% rename from ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.component.js rename to ui/components/app/modals/confirm-reset-account/confirm-reset-account.component.js diff --git a/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js b/ui/components/app/modals/confirm-reset-account/confirm-reset-account.container.js similarity index 100% rename from ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.container.js rename to ui/components/app/modals/confirm-reset-account/confirm-reset-account.container.js diff --git a/ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.test.js b/ui/components/app/modals/confirm-reset-account/confirm-reset-account.test.js similarity index 100% rename from ui/app/components/app/modals/confirm-reset-account/confirm-reset-account.test.js rename to ui/components/app/modals/confirm-reset-account/confirm-reset-account.test.js diff --git a/ui/app/components/app/modals/confirm-reset-account/index.js b/ui/components/app/modals/confirm-reset-account/index.js similarity index 100% rename from ui/app/components/app/modals/confirm-reset-account/index.js rename to ui/components/app/modals/confirm-reset-account/index.js diff --git a/ui/app/components/app/modals/customize-nonce/customize-nonce.component.js b/ui/components/app/modals/customize-nonce/customize-nonce.component.js similarity index 100% rename from ui/app/components/app/modals/customize-nonce/customize-nonce.component.js rename to ui/components/app/modals/customize-nonce/customize-nonce.component.js diff --git a/ui/app/components/app/modals/customize-nonce/index.js b/ui/components/app/modals/customize-nonce/index.js similarity index 100% rename from ui/app/components/app/modals/customize-nonce/index.js rename to ui/components/app/modals/customize-nonce/index.js diff --git a/ui/app/components/app/modals/customize-nonce/index.scss b/ui/components/app/modals/customize-nonce/index.scss similarity index 100% rename from ui/app/components/app/modals/customize-nonce/index.scss rename to ui/components/app/modals/customize-nonce/index.scss diff --git a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js b/ui/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js similarity index 98% rename from ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js rename to ui/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js index 553f25973..3f1775a47 100644 --- a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js +++ b/ui/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js @@ -1,6 +1,6 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; -import { NETWORK_TO_NAME_MAP } from '../../../../../../shared/constants/network'; +import { NETWORK_TO_NAME_MAP } from '../../../../../shared/constants/network'; import Button from '../../../ui/button'; export default class DepositEtherModal extends Component { diff --git a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js b/ui/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js similarity index 100% rename from ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js rename to ui/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js diff --git a/ui/app/components/app/modals/deposit-ether-modal/index.js b/ui/components/app/modals/deposit-ether-modal/index.js similarity index 100% rename from ui/app/components/app/modals/deposit-ether-modal/index.js rename to ui/components/app/modals/deposit-ether-modal/index.js diff --git a/ui/app/components/app/modals/deposit-ether-modal/index.scss b/ui/components/app/modals/deposit-ether-modal/index.scss similarity index 100% rename from ui/app/components/app/modals/deposit-ether-modal/index.scss rename to ui/components/app/modals/deposit-ether-modal/index.scss diff --git a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js b/ui/components/app/modals/edit-approval-permission/edit-approval-permission.component.js similarity index 100% rename from ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.component.js rename to ui/components/app/modals/edit-approval-permission/edit-approval-permission.component.js diff --git a/ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.container.js b/ui/components/app/modals/edit-approval-permission/edit-approval-permission.container.js similarity index 100% rename from ui/app/components/app/modals/edit-approval-permission/edit-approval-permission.container.js rename to ui/components/app/modals/edit-approval-permission/edit-approval-permission.container.js diff --git a/ui/app/components/app/modals/edit-approval-permission/index.js b/ui/components/app/modals/edit-approval-permission/index.js similarity index 100% rename from ui/app/components/app/modals/edit-approval-permission/index.js rename to ui/components/app/modals/edit-approval-permission/index.js diff --git a/ui/app/components/app/modals/edit-approval-permission/index.scss b/ui/components/app/modals/edit-approval-permission/index.scss similarity index 100% rename from ui/app/components/app/modals/edit-approval-permission/index.scss rename to ui/components/app/modals/edit-approval-permission/index.scss diff --git a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js b/ui/components/app/modals/export-private-key-modal/export-private-key-modal.component.js similarity index 98% rename from ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js rename to ui/components/app/modals/export-private-key-modal/export-private-key-modal.component.js index 4db92c4f5..ba6e4ca8b 100644 --- a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.component.js +++ b/ui/components/app/modals/export-private-key-modal/export-private-key-modal.component.js @@ -7,7 +7,7 @@ import copyToClipboard from 'copy-to-clipboard'; import ReadOnlyInput from '../../../ui/readonly-input'; import Button from '../../../ui/button'; import AccountModalContainer from '../account-modal-container'; -import { toChecksumHexAddress } from '../../../../../../shared/modules/hexstring-utils'; +import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; export default class ExportPrivateKeyModal extends Component { static contextTypes = { diff --git a/ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.container.js b/ui/components/app/modals/export-private-key-modal/export-private-key-modal.container.js similarity index 100% rename from ui/app/components/app/modals/export-private-key-modal/export-private-key-modal.container.js rename to ui/components/app/modals/export-private-key-modal/export-private-key-modal.container.js diff --git a/ui/app/components/app/modals/export-private-key-modal/index.js b/ui/components/app/modals/export-private-key-modal/index.js similarity index 100% rename from ui/app/components/app/modals/export-private-key-modal/index.js rename to ui/components/app/modals/export-private-key-modal/index.js diff --git a/ui/app/components/app/modals/export-private-key-modal/index.scss b/ui/components/app/modals/export-private-key-modal/index.scss similarity index 100% rename from ui/app/components/app/modals/export-private-key-modal/index.scss rename to ui/components/app/modals/export-private-key-modal/index.scss diff --git a/ui/app/components/app/modals/fade-modal.js b/ui/components/app/modals/fade-modal.js similarity index 100% rename from ui/app/components/app/modals/fade-modal.js rename to ui/components/app/modals/fade-modal.js diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js b/ui/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js similarity index 100% rename from ui/app/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js rename to ui/components/app/modals/hide-token-confirmation-modal/hide-token-confirmation-modal.js diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal/index.js b/ui/components/app/modals/hide-token-confirmation-modal/index.js similarity index 100% rename from ui/app/components/app/modals/hide-token-confirmation-modal/index.js rename to ui/components/app/modals/hide-token-confirmation-modal/index.js diff --git a/ui/app/components/app/modals/hide-token-confirmation-modal/index.scss b/ui/components/app/modals/hide-token-confirmation-modal/index.scss similarity index 100% rename from ui/app/components/app/modals/hide-token-confirmation-modal/index.scss rename to ui/components/app/modals/hide-token-confirmation-modal/index.scss diff --git a/ui/app/components/app/modals/index.js b/ui/components/app/modals/index.js similarity index 100% rename from ui/app/components/app/modals/index.js rename to ui/components/app/modals/index.js diff --git a/ui/app/components/app/modals/index.scss b/ui/components/app/modals/index.scss similarity index 100% rename from ui/app/components/app/modals/index.scss rename to ui/components/app/modals/index.scss diff --git a/ui/app/components/app/modals/loading-network-error/index.js b/ui/components/app/modals/loading-network-error/index.js similarity index 100% rename from ui/app/components/app/modals/loading-network-error/index.js rename to ui/components/app/modals/loading-network-error/index.js diff --git a/ui/app/components/app/modals/loading-network-error/loading-network-error.component.js b/ui/components/app/modals/loading-network-error/loading-network-error.component.js similarity index 100% rename from ui/app/components/app/modals/loading-network-error/loading-network-error.component.js rename to ui/components/app/modals/loading-network-error/loading-network-error.component.js diff --git a/ui/app/components/app/modals/loading-network-error/loading-network-error.container.js b/ui/components/app/modals/loading-network-error/loading-network-error.container.js similarity index 100% rename from ui/app/components/app/modals/loading-network-error/loading-network-error.container.js rename to ui/components/app/modals/loading-network-error/loading-network-error.container.js diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/index.js b/ui/components/app/modals/metametrics-opt-in-modal/index.js similarity index 100% rename from ui/app/components/app/modals/metametrics-opt-in-modal/index.js rename to ui/components/app/modals/metametrics-opt-in-modal/index.js diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/index.scss b/ui/components/app/modals/metametrics-opt-in-modal/index.scss similarity index 100% rename from ui/app/components/app/modals/metametrics-opt-in-modal/index.scss rename to ui/components/app/modals/metametrics-opt-in-modal/index.scss diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js b/ui/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js similarity index 69% rename from ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js rename to ui/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js index 833d8b49d..9daf60e56 100644 --- a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js +++ b/ui/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.component.js @@ -27,76 +27,81 @@ export default class MetaMetricsOptInModal extends Component { <img src="images/metrics-chart.svg" alt="" /> </div> <div className="metametrics-opt-in__title"> - Help Us Improve MetaMask + {t('metametricsHelpImproveMetaMask')} </div> <div className="metametrics-opt-in__body"> <div className="metametrics-opt-in__description"> - MetaMask would like to gather usage data to better understand - how our users interact with the extension. This data will be - used to continually improve the usability and user experience of - our product and the Ethereum ecosystem. + {t('metametricsOptInDescription')} </div> <div className="metametrics-opt-in__description"> - MetaMask will.. + {t('metametricsCommitmentsIntro')} </div> <div className="metametrics-opt-in__committments"> <div className="metametrics-opt-in__row"> <i className="fa fa-check" /> <div className="metametrics-opt-in__row-description"> - Always allow you to opt-out via Settings + {t('metametricsCommitmentsAllowOptOut')} </div> </div> <div className="metametrics-opt-in__row"> <i className="fa fa-check" /> <div className="metametrics-opt-in__row-description"> - Send anonymized click & pageview events - </div> - </div> - <div className="metametrics-opt-in__row"> - <i className="fa fa-check" /> - <div className="metametrics-opt-in__row-description"> - Maintain a public aggregate dashboard to educate the - community + {t('metametricsCommitmentsSendAnonymizedEvents')} </div> </div> <div className="metametrics-opt-in__row metametrics-opt-in__break-row"> <i className="fa fa-times" /> <div className="metametrics-opt-in__row-description"> - <span className="metametrics-opt-in__bold">Never</span>{' '} - collect keys, addresses, transactions, balances, hashes, or - any personal information + {t('metametricsCommitmentsNeverCollectKeysEtc', [ + <span + className="metametrics-opt-in__bold" + key="neverCollectKeys" + > + {t('metametricsCommitmentsBoldNever')} + </span>, + ])} </div> </div> <div className="metametrics-opt-in__row"> <i className="fa fa-times" /> <div className="metametrics-opt-in__row-description"> - <span className="metametrics-opt-in__bold">Never</span>{' '} - collect your full IP address + {t('metametricsCommitmentsNeverCollectIP', [ + <span + className="metametrics-opt-in__bold" + key="neverCollectIP" + > + {t('metametricsCommitmentsBoldNever')} + </span>, + ])} </div> </div> <div className="metametrics-opt-in__row"> <i className="fa fa-times" /> <div className="metametrics-opt-in__row-description"> - <span className="metametrics-opt-in__bold">Never</span> sell - data for profit. Ever! + {t('metametricsCommitmentsNeverSellDataForProfit', [ + <span + className="metametrics-opt-in__bold" + key="neverSellData" + > + {t('metametricsCommitmentsBoldNever')} + </span>, + ])} </div> </div> </div> </div> <div className="metametrics-opt-in__bottom-text"> - This data is aggregated and is therefore anonymous for the - purposes of General Data Protection Regulation (EU) 2016/679. For - more information in relation to our privacy practices, please see - our - <a - href="https://metamask.io/privacy.html" - target="_blank" - rel="noopener noreferrer" - > - Privacy Policy here - </a> - . + {t('gdprMessage', [ + <a + key="metametrics-bottom-text-wrapper" + href="https://metamask.io/privacy.html" + target="_blank" + rel="noopener noreferrer" + > + {t('gdprMessagePrivacyPolicy')} + </a>, + ])} </div> </div> <div className="metametrics-opt-in__footer"> diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js b/ui/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js similarity index 100% rename from ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js rename to ui/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.container.js diff --git a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.test.js b/ui/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.test.js similarity index 95% rename from ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.test.js rename to ui/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.test.js index fc45751b5..7b90b24ff 100644 --- a/ui/app/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.test.js +++ b/ui/components/app/modals/metametrics-opt-in-modal/metametrics-opt-in-modal.test.js @@ -1,7 +1,7 @@ import React from 'react'; import sinon from 'sinon'; import { mount } from 'enzyme'; -import messages from '../../../../../../app/_locales/en/messages.json'; +import messages from '../../../../../app/_locales/en/messages.json'; import MetaMetricsOptIn from './metametrics-opt-in-modal.container'; describe('MetaMetrics Opt In', () => { diff --git a/ui/app/components/app/modals/modal.js b/ui/components/app/modals/modal.js similarity index 98% rename from ui/app/components/app/modals/modal.js rename to ui/components/app/modals/modal.js index 74373354c..ce4282df3 100644 --- a/ui/app/components/app/modals/modal.js +++ b/ui/components/app/modals/modal.js @@ -4,9 +4,9 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; import * as actions from '../../../store/actions'; import { resetCustomData as resetCustomGasData } from '../../../ducks/gas/gas.duck'; -import isMobileView from '../../../../lib/is-mobile-view'; -import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; -import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app'; +import isMobileView from '../../../helpers/utils/is-mobile-view'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; // Modal Components import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container'; diff --git a/ui/app/components/app/modals/new-account-modal/index.js b/ui/components/app/modals/new-account-modal/index.js similarity index 100% rename from ui/app/components/app/modals/new-account-modal/index.js rename to ui/components/app/modals/new-account-modal/index.js diff --git a/ui/app/components/app/modals/new-account-modal/index.scss b/ui/components/app/modals/new-account-modal/index.scss similarity index 100% rename from ui/app/components/app/modals/new-account-modal/index.scss rename to ui/components/app/modals/new-account-modal/index.scss diff --git a/ui/app/components/app/modals/new-account-modal/new-account-modal.component.js b/ui/components/app/modals/new-account-modal/new-account-modal.component.js similarity index 100% rename from ui/app/components/app/modals/new-account-modal/new-account-modal.component.js rename to ui/components/app/modals/new-account-modal/new-account-modal.component.js diff --git a/ui/app/components/app/modals/new-account-modal/new-account-modal.container.js b/ui/components/app/modals/new-account-modal/new-account-modal.container.js similarity index 100% rename from ui/app/components/app/modals/new-account-modal/new-account-modal.container.js rename to ui/components/app/modals/new-account-modal/new-account-modal.container.js diff --git a/ui/app/components/app/modals/qr-scanner/index.js b/ui/components/app/modals/qr-scanner/index.js similarity index 100% rename from ui/app/components/app/modals/qr-scanner/index.js rename to ui/components/app/modals/qr-scanner/index.js diff --git a/ui/app/components/app/modals/qr-scanner/index.scss b/ui/components/app/modals/qr-scanner/index.scss similarity index 100% rename from ui/app/components/app/modals/qr-scanner/index.scss rename to ui/components/app/modals/qr-scanner/index.scss diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js b/ui/components/app/modals/qr-scanner/qr-scanner.component.js similarity index 97% rename from ui/app/components/app/modals/qr-scanner/qr-scanner.component.js rename to ui/components/app/modals/qr-scanner/qr-scanner.component.js index 7ca6a5089..6cad31f6e 100644 --- a/ui/app/components/app/modals/qr-scanner/qr-scanner.component.js +++ b/ui/components/app/modals/qr-scanner/qr-scanner.component.js @@ -2,10 +2,10 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import log from 'loglevel'; import { BrowserQRCodeReader } from '@zxing/library'; -import { getEnvironmentType } from '../../../../../../app/scripts/lib/util'; -import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app'; import Spinner from '../../../ui/spinner'; -import WebcamUtils from '../../../../../lib/webcam-utils'; +import WebcamUtils from '../../../../helpers/utils/webcam-utils'; import PageContainerFooter from '../../../ui/page-container/page-container-footer/page-container-footer.component'; const READY_STATE = { diff --git a/ui/app/components/app/modals/qr-scanner/qr-scanner.container.js b/ui/components/app/modals/qr-scanner/qr-scanner.container.js similarity index 100% rename from ui/app/components/app/modals/qr-scanner/qr-scanner.container.js rename to ui/components/app/modals/qr-scanner/qr-scanner.container.js diff --git a/ui/app/components/app/modals/reject-transactions/index.js b/ui/components/app/modals/reject-transactions/index.js similarity index 100% rename from ui/app/components/app/modals/reject-transactions/index.js rename to ui/components/app/modals/reject-transactions/index.js diff --git a/ui/app/components/app/modals/reject-transactions/index.scss b/ui/components/app/modals/reject-transactions/index.scss similarity index 100% rename from ui/app/components/app/modals/reject-transactions/index.scss rename to ui/components/app/modals/reject-transactions/index.scss diff --git a/ui/app/components/app/modals/reject-transactions/reject-transactions.component.js b/ui/components/app/modals/reject-transactions/reject-transactions.component.js similarity index 100% rename from ui/app/components/app/modals/reject-transactions/reject-transactions.component.js rename to ui/components/app/modals/reject-transactions/reject-transactions.component.js diff --git a/ui/app/components/app/modals/reject-transactions/reject-transactions.container.js b/ui/components/app/modals/reject-transactions/reject-transactions.container.js similarity index 100% rename from ui/app/components/app/modals/reject-transactions/reject-transactions.container.js rename to ui/components/app/modals/reject-transactions/reject-transactions.container.js diff --git a/ui/app/components/app/modals/reject-transactions/reject-transactions.test.js b/ui/components/app/modals/reject-transactions/reject-transactions.test.js similarity index 100% rename from ui/app/components/app/modals/reject-transactions/reject-transactions.test.js rename to ui/components/app/modals/reject-transactions/reject-transactions.test.js diff --git a/ui/app/components/app/modals/transaction-confirmed/index.js b/ui/components/app/modals/transaction-confirmed/index.js similarity index 100% rename from ui/app/components/app/modals/transaction-confirmed/index.js rename to ui/components/app/modals/transaction-confirmed/index.js diff --git a/ui/app/components/app/modals/transaction-confirmed/index.scss b/ui/components/app/modals/transaction-confirmed/index.scss similarity index 100% rename from ui/app/components/app/modals/transaction-confirmed/index.scss rename to ui/components/app/modals/transaction-confirmed/index.scss diff --git a/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.component.js b/ui/components/app/modals/transaction-confirmed/transaction-confirmed.component.js similarity index 100% rename from ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.component.js rename to ui/components/app/modals/transaction-confirmed/transaction-confirmed.component.js diff --git a/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.container.js b/ui/components/app/modals/transaction-confirmed/transaction-confirmed.container.js similarity index 100% rename from ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.container.js rename to ui/components/app/modals/transaction-confirmed/transaction-confirmed.container.js diff --git a/ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.test.js b/ui/components/app/modals/transaction-confirmed/transaction-confirmed.test.js similarity index 100% rename from ui/app/components/app/modals/transaction-confirmed/transaction-confirmed.test.js rename to ui/components/app/modals/transaction-confirmed/transaction-confirmed.test.js diff --git a/ui/app/components/app/multiple-notifications/index.js b/ui/components/app/multiple-notifications/index.js similarity index 100% rename from ui/app/components/app/multiple-notifications/index.js rename to ui/components/app/multiple-notifications/index.js diff --git a/ui/app/components/app/multiple-notifications/index.scss b/ui/components/app/multiple-notifications/index.scss similarity index 100% rename from ui/app/components/app/multiple-notifications/index.scss rename to ui/components/app/multiple-notifications/index.scss diff --git a/ui/app/components/app/multiple-notifications/multiple-notifications.component.js b/ui/components/app/multiple-notifications/multiple-notifications.component.js similarity index 100% rename from ui/app/components/app/multiple-notifications/multiple-notifications.component.js rename to ui/components/app/multiple-notifications/multiple-notifications.component.js diff --git a/ui/app/components/app/network-display/index.js b/ui/components/app/network-display/index.js similarity index 100% rename from ui/app/components/app/network-display/index.js rename to ui/components/app/network-display/index.js diff --git a/ui/app/components/app/network-display/index.scss b/ui/components/app/network-display/index.scss similarity index 100% rename from ui/app/components/app/network-display/index.scss rename to ui/components/app/network-display/index.scss diff --git a/ui/app/components/app/network-display/network-display.js b/ui/components/app/network-display/network-display.js similarity index 98% rename from ui/app/components/app/network-display/network-display.js rename to ui/components/app/network-display/network-display.js index ba83bb5c9..87b851535 100644 --- a/ui/app/components/app/network-display/network-display.js +++ b/ui/components/app/network-display/network-display.js @@ -5,7 +5,7 @@ import { useSelector } from 'react-redux'; import { NETWORK_TYPE_RPC, NETWORK_TYPE_TO_ID_MAP, -} from '../../../../../shared/constants/network'; +} from '../../../../shared/constants/network'; import LoadingIndicator from '../../ui/loading-indicator'; import ColorIndicator from '../../ui/color-indicator'; diff --git a/ui/app/components/app/permission-page-container/index.js b/ui/components/app/permission-page-container/index.js similarity index 100% rename from ui/app/components/app/permission-page-container/index.js rename to ui/components/app/permission-page-container/index.js diff --git a/ui/app/components/app/permission-page-container/index.scss b/ui/components/app/permission-page-container/index.scss similarity index 100% rename from ui/app/components/app/permission-page-container/index.scss rename to ui/components/app/permission-page-container/index.scss diff --git a/ui/app/components/app/permission-page-container/permission-page-container-content/index.js b/ui/components/app/permission-page-container/permission-page-container-content/index.js similarity index 100% rename from ui/app/components/app/permission-page-container/permission-page-container-content/index.js rename to ui/components/app/permission-page-container/permission-page-container-content/index.js diff --git a/ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js b/ui/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js similarity index 100% rename from ui/app/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js rename to ui/components/app/permission-page-container/permission-page-container-content/permission-page-container-content.component.js diff --git a/ui/app/components/app/permission-page-container/permission-page-container.component.js b/ui/components/app/permission-page-container/permission-page-container.component.js similarity index 100% rename from ui/app/components/app/permission-page-container/permission-page-container.component.js rename to ui/components/app/permission-page-container/permission-page-container.component.js diff --git a/ui/app/components/app/permission-page-container/permission-page-container.container.js b/ui/components/app/permission-page-container/permission-page-container.container.js similarity index 100% rename from ui/app/components/app/permission-page-container/permission-page-container.container.js rename to ui/components/app/permission-page-container/permission-page-container.container.js diff --git a/ui/app/components/app/permissions-connect-footer/index.js b/ui/components/app/permissions-connect-footer/index.js similarity index 100% rename from ui/app/components/app/permissions-connect-footer/index.js rename to ui/components/app/permissions-connect-footer/index.js diff --git a/ui/app/components/app/permissions-connect-footer/index.scss b/ui/components/app/permissions-connect-footer/index.scss similarity index 100% rename from ui/app/components/app/permissions-connect-footer/index.scss rename to ui/components/app/permissions-connect-footer/index.scss diff --git a/ui/app/components/app/permissions-connect-footer/permissions-connect-footer.component.js b/ui/components/app/permissions-connect-footer/permissions-connect-footer.component.js similarity index 100% rename from ui/app/components/app/permissions-connect-footer/permissions-connect-footer.component.js rename to ui/components/app/permissions-connect-footer/permissions-connect-footer.component.js diff --git a/ui/app/components/app/permissions-connect-header/index.js b/ui/components/app/permissions-connect-header/index.js similarity index 100% rename from ui/app/components/app/permissions-connect-header/index.js rename to ui/components/app/permissions-connect-header/index.js diff --git a/ui/app/components/app/permissions-connect-header/index.scss b/ui/components/app/permissions-connect-header/index.scss similarity index 100% rename from ui/app/components/app/permissions-connect-header/index.scss rename to ui/components/app/permissions-connect-header/index.scss diff --git a/ui/app/components/app/permissions-connect-header/permissions-connect-header.component.js b/ui/components/app/permissions-connect-header/permissions-connect-header.component.js similarity index 100% rename from ui/app/components/app/permissions-connect-header/permissions-connect-header.component.js rename to ui/components/app/permissions-connect-header/permissions-connect-header.component.js diff --git a/ui/app/components/app/selected-account/index.js b/ui/components/app/selected-account/index.js similarity index 100% rename from ui/app/components/app/selected-account/index.js rename to ui/components/app/selected-account/index.js diff --git a/ui/app/components/app/selected-account/index.scss b/ui/components/app/selected-account/index.scss similarity index 100% rename from ui/app/components/app/selected-account/index.scss rename to ui/components/app/selected-account/index.scss diff --git a/ui/app/components/app/selected-account/selected-account-component.test.js b/ui/components/app/selected-account/selected-account-component.test.js similarity index 100% rename from ui/app/components/app/selected-account/selected-account-component.test.js rename to ui/components/app/selected-account/selected-account-component.test.js diff --git a/ui/app/components/app/selected-account/selected-account.component.js b/ui/components/app/selected-account/selected-account.component.js similarity index 95% rename from ui/app/components/app/selected-account/selected-account.component.js rename to ui/components/app/selected-account/selected-account.component.js index 40d8c2a4e..b52dd033f 100644 --- a/ui/app/components/app/selected-account/selected-account.component.js +++ b/ui/components/app/selected-account/selected-account.component.js @@ -4,7 +4,7 @@ import copyToClipboard from 'copy-to-clipboard'; import { shortenAddress } from '../../../helpers/utils/util'; import Tooltip from '../../ui/tooltip'; -import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; class SelectedAccount extends Component { state = { diff --git a/ui/app/components/app/selected-account/selected-account.container.js b/ui/components/app/selected-account/selected-account.container.js similarity index 100% rename from ui/app/components/app/selected-account/selected-account.container.js rename to ui/components/app/selected-account/selected-account.container.js diff --git a/ui/app/components/app/sidebars/index.js b/ui/components/app/sidebars/index.js similarity index 100% rename from ui/app/components/app/sidebars/index.js rename to ui/components/app/sidebars/index.js diff --git a/ui/app/components/app/sidebars/index.scss b/ui/components/app/sidebars/index.scss similarity index 100% rename from ui/app/components/app/sidebars/index.scss rename to ui/components/app/sidebars/index.scss diff --git a/ui/app/components/app/sidebars/sidebar-content.scss b/ui/components/app/sidebars/sidebar-content.scss similarity index 100% rename from ui/app/components/app/sidebars/sidebar-content.scss rename to ui/components/app/sidebars/sidebar-content.scss diff --git a/ui/app/components/app/sidebars/sidebar.component.js b/ui/components/app/sidebars/sidebar.component.js similarity index 88% rename from ui/app/components/app/sidebars/sidebar.component.js rename to ui/components/app/sidebars/sidebar.component.js index 7b385db22..b9fff51cd 100644 --- a/ui/app/components/app/sidebars/sidebar.component.js +++ b/ui/components/app/sidebars/sidebar.component.js @@ -30,12 +30,16 @@ export default class Sidebar extends Component { renderSidebarContent() { const { type, sidebarProps = {} } = this.props; - const { transaction = {}, onSubmit } = sidebarProps; + const { transaction = {}, onSubmit, hideBasic } = sidebarProps; switch (type) { case 'customize-gas': return ( <div className="sidebar-left"> - <CustomizeGas transaction={transaction} onSubmit={onSubmit} /> + <CustomizeGas + transaction={transaction} + onSubmit={onSubmit} + hideBasic={hideBasic} + /> </div> ); default: diff --git a/ui/app/components/app/sidebars/sidebar.component.test.js b/ui/components/app/sidebars/sidebar.component.test.js similarity index 100% rename from ui/app/components/app/sidebars/sidebar.component.test.js rename to ui/components/app/sidebars/sidebar.component.test.js diff --git a/ui/app/components/app/signature-request-original/index.js b/ui/components/app/signature-request-original/index.js similarity index 100% rename from ui/app/components/app/signature-request-original/index.js rename to ui/components/app/signature-request-original/index.js diff --git a/ui/app/components/app/signature-request-original/index.scss b/ui/components/app/signature-request-original/index.scss similarity index 100% rename from ui/app/components/app/signature-request-original/index.scss rename to ui/components/app/signature-request-original/index.scss diff --git a/ui/app/components/app/signature-request-original/signature-request-original.component.js b/ui/components/app/signature-request-original/signature-request-original.component.js similarity index 97% rename from ui/app/components/app/signature-request-original/signature-request-original.component.js rename to ui/components/app/signature-request-original/signature-request-original.component.js index ae62fcad9..091916cc5 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.component.js +++ b/ui/components/app/signature-request-original/signature-request-original.component.js @@ -7,8 +7,8 @@ import { ObjectInspector } from 'react-inspector'; import { ENVIRONMENT_TYPE_NOTIFICATION, MESSAGE_TYPE, -} from '../../../../../shared/constants/app'; -import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +} from '../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import Identicon from '../../ui/identicon'; import AccountListItem from '../account-list-item'; import { conversionUtil } from '../../../helpers/utils/conversion-util'; @@ -188,12 +188,13 @@ export default class SignatureRequestOriginal extends Component { }; renderTypedData = (data) => { + const { t } = this.context; const { domain, message } = JSON.parse(data); return ( <div className="request-signature__typed-container"> {domain ? ( <div> - <h1>Domain</h1> + <h1>{t('domain')}</h1> <ObjectInspector data={domain} expandLevel={1} name="domain" /> </div> ) : ( @@ -201,7 +202,7 @@ export default class SignatureRequestOriginal extends Component { )} {message ? ( <div> - <h1>Message</h1> + <h1>{t('message')}</h1> <ObjectInspector data={message} expandLevel={1} name="message" /> </div> ) : ( diff --git a/ui/app/components/app/signature-request-original/signature-request-original.container.js b/ui/components/app/signature-request-original/signature-request-original.container.js similarity index 96% rename from ui/app/components/app/signature-request-original/signature-request-original.container.js rename to ui/components/app/signature-request-original/signature-request-original.container.js index c32e30d66..f6181cc5b 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.container.js +++ b/ui/components/app/signature-request-original/signature-request-original.container.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux'; import { compose } from 'redux'; import { withRouter } from 'react-router-dom'; -import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; +import { MESSAGE_TYPE } from '../../../../shared/constants/app'; import { goHome } from '../../../store/actions'; import { accountsWithSendEtherInfoSelector, diff --git a/ui/app/components/app/signature-request/index.js b/ui/components/app/signature-request/index.js similarity index 100% rename from ui/app/components/app/signature-request/index.js rename to ui/components/app/signature-request/index.js diff --git a/ui/app/components/app/signature-request/index.scss b/ui/components/app/signature-request/index.scss similarity index 100% rename from ui/app/components/app/signature-request/index.scss rename to ui/components/app/signature-request/index.scss diff --git a/ui/app/components/app/signature-request/signature-request-footer/index.js b/ui/components/app/signature-request/signature-request-footer/index.js similarity index 100% rename from ui/app/components/app/signature-request/signature-request-footer/index.js rename to ui/components/app/signature-request/signature-request-footer/index.js diff --git a/ui/app/components/app/signature-request/signature-request-footer/index.scss b/ui/components/app/signature-request/signature-request-footer/index.scss similarity index 100% rename from ui/app/components/app/signature-request/signature-request-footer/index.scss rename to ui/components/app/signature-request/signature-request-footer/index.scss diff --git a/ui/app/components/app/signature-request/signature-request-footer/signature-request-footer.component.js b/ui/components/app/signature-request/signature-request-footer/signature-request-footer.component.js similarity index 100% rename from ui/app/components/app/signature-request/signature-request-footer/signature-request-footer.component.js rename to ui/components/app/signature-request/signature-request-footer/signature-request-footer.component.js diff --git a/ui/app/components/app/signature-request/signature-request-header/index.js b/ui/components/app/signature-request/signature-request-header/index.js similarity index 100% rename from ui/app/components/app/signature-request/signature-request-header/index.js rename to ui/components/app/signature-request/signature-request-header/index.js diff --git a/ui/app/components/app/signature-request/signature-request-header/index.scss b/ui/components/app/signature-request/signature-request-header/index.scss similarity index 100% rename from ui/app/components/app/signature-request/signature-request-header/index.scss rename to ui/components/app/signature-request/signature-request-header/index.scss diff --git a/ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js b/ui/components/app/signature-request/signature-request-header/signature-request-header.component.js similarity index 100% rename from ui/app/components/app/signature-request/signature-request-header/signature-request-header.component.js rename to ui/components/app/signature-request/signature-request-header/signature-request-header.component.js diff --git a/ui/app/components/app/signature-request/signature-request-message/index.js b/ui/components/app/signature-request/signature-request-message/index.js similarity index 100% rename from ui/app/components/app/signature-request/signature-request-message/index.js rename to ui/components/app/signature-request/signature-request-message/index.js diff --git a/ui/app/components/app/signature-request/signature-request-message/index.scss b/ui/components/app/signature-request/signature-request-message/index.scss similarity index 100% rename from ui/app/components/app/signature-request/signature-request-message/index.scss rename to ui/components/app/signature-request/signature-request-message/index.scss diff --git a/ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js b/ui/components/app/signature-request/signature-request-message/signature-request-message.component.js similarity index 100% rename from ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js rename to ui/components/app/signature-request/signature-request-message/signature-request-message.component.js diff --git a/ui/app/components/app/signature-request/signature-request.component.js b/ui/components/app/signature-request/signature-request.component.js similarity index 77% rename from ui/app/components/app/signature-request/signature-request.component.js rename to ui/components/app/signature-request/signature-request.component.js index 9515ac02a..37eefcfeb 100644 --- a/ui/app/components/app/signature-request/signature-request.component.js +++ b/ui/components/app/signature-request/signature-request.component.js @@ -1,6 +1,6 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; -import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import Identicon from '../../ui/identicon'; import Header from './signature-request-header'; import Footer from './signature-request-footer'; @@ -27,23 +27,25 @@ export default class SignatureRequest extends PureComponent { }; componentDidMount() { - const { clearConfirmTransaction, cancel } = this.props; - const { metricsEvent } = this.context; if (getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION) { - window.addEventListener('beforeunload', (event) => { - metricsEvent({ - eventOpts: { - category: 'Transactions', - action: 'Sign Request', - name: 'Cancel Sig Request Via Notification Close', - }, - }); - clearConfirmTransaction(); - cancel(event); - }); + window.addEventListener('beforeunload', this._beforeUnload); } } + _beforeUnload = (event) => { + const { clearConfirmTransaction, cancel } = this.props; + const { metricsEvent } = this.context; + metricsEvent({ + eventOpts: { + category: 'Transactions', + action: 'Sign Request', + name: 'Cancel Sig Request Via Notification Close', + }, + }); + clearConfirmTransaction(); + cancel(event); + }; + formatWallet(wallet) { return `${wallet.slice(0, 8)}...${wallet.slice( wallet.length - 8, @@ -63,6 +65,16 @@ export default class SignatureRequest extends PureComponent { const { address: fromAddress } = fromAccount; const { message, domain = {} } = JSON.parse(data); + const onSign = (event) => { + window.removeEventListener('beforeunload', this._beforeUnload); + sign(event); + }; + + const onCancel = (event) => { + window.removeEventListener('beforeunload', this._beforeUnload); + cancel(event); + }; + return ( <div className="signature-request page-container"> <Header fromAccount={fromAccount} /> @@ -86,7 +98,7 @@ export default class SignatureRequest extends PureComponent { </div> </div> <Message data={message} /> - <Footer cancelAction={cancel} signAction={sign} /> + <Footer cancelAction={onCancel} signAction={onSign} /> </div> ); } diff --git a/ui/app/components/app/signature-request/signature-request.component.test.js b/ui/components/app/signature-request/signature-request.component.test.js similarity index 87% rename from ui/app/components/app/signature-request/signature-request.component.test.js rename to ui/components/app/signature-request/signature-request.component.test.js index 1afa1b98c..12da052ff 100644 --- a/ui/app/components/app/signature-request/signature-request.component.test.js +++ b/ui/components/app/signature-request/signature-request.component.test.js @@ -1,12 +1,12 @@ import React from 'react'; -import shallow from '../../../../lib/shallow-with-context'; +import { shallowWithContext } from '../../../../test/lib/render-helpers'; import SignatureRequest from './signature-request.component'; describe('Signature Request Component', () => { describe('render', () => { const fromAddress = '0x123456789abcdef'; it('should render a div with one child', () => { - const wrapper = shallow( + const wrapper = shallowWithContext( <SignatureRequest clearConfirmTransaction={() => undefined} cancel={() => undefined} diff --git a/ui/components/app/signature-request/signature-request.constants.js b/ui/components/app/signature-request/signature-request.constants.js new file mode 100644 index 000000000..e17841a0c --- /dev/null +++ b/ui/components/app/signature-request/signature-request.constants.js @@ -0,0 +1,3 @@ +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; + +export { ENVIRONMENT_TYPE_NOTIFICATION }; diff --git a/ui/app/components/app/signature-request/signature-request.container.js b/ui/components/app/signature-request/signature-request.container.js similarity index 95% rename from ui/app/components/app/signature-request/signature-request.container.js rename to ui/components/app/signature-request/signature-request.container.js index 4c45a256d..2d3546720 100644 --- a/ui/app/components/app/signature-request/signature-request.container.js +++ b/ui/components/app/signature-request/signature-request.container.js @@ -2,7 +2,7 @@ import { connect } from 'react-redux'; import { clearConfirmTransaction } from '../../../ducks/confirm-transaction/confirm-transaction.duck'; import { accountsWithSendEtherInfoSelector } from '../../../selectors'; import { getAccountByAddress } from '../../../helpers/utils/util'; -import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; +import { MESSAGE_TYPE } from '../../../../shared/constants/app'; import SignatureRequest from './signature-request.component'; function mapStateToProps(state) { diff --git a/ui/app/components/app/signature-request/signature-request.container.test.js b/ui/components/app/signature-request/signature-request.container.test.js similarity index 97% rename from ui/app/components/app/signature-request/signature-request.container.test.js rename to ui/components/app/signature-request/signature-request.container.test.js index c4de25b1a..c0bc03540 100644 --- a/ui/app/components/app/signature-request/signature-request.container.test.js +++ b/ui/components/app/signature-request/signature-request.container.test.js @@ -2,7 +2,7 @@ import React from 'react'; import { Provider } from 'react-redux'; import sinon from 'sinon'; import configureMockStore from 'redux-mock-store'; -import { mountWithRouter } from '../../../../../test/lib/render-helpers'; +import { mountWithRouter } from '../../../../test/lib/render-helpers'; import SignatureRequest from './signature-request.container'; describe('Signature Request', () => { diff --git a/ui/app/components/app/signature-request/signature-request.stories.js b/ui/components/app/signature-request/signature-request.stories.js similarity index 93% rename from ui/app/components/app/signature-request/signature-request.stories.js rename to ui/components/app/signature-request/signature-request.stories.js index fd121cc86..1590f84e1 100644 --- a/ui/app/components/app/signature-request/signature-request.stories.js +++ b/ui/components/app/signature-request/signature-request.stories.js @@ -1,5 +1,5 @@ import React from 'react'; -import testData from '../../../../../.storybook/test-data'; +import testData from '../../../../.storybook/test-data'; import SignatureRequest from './signature-request.component'; const primaryIdentity = Object.values(testData.metamask.identities)[0]; diff --git a/ui/app/components/app/tab-bar/index.js b/ui/components/app/tab-bar/index.js similarity index 100% rename from ui/app/components/app/tab-bar/index.js rename to ui/components/app/tab-bar/index.js diff --git a/ui/app/components/app/tab-bar/index.scss b/ui/components/app/tab-bar/index.scss similarity index 100% rename from ui/app/components/app/tab-bar/index.scss rename to ui/components/app/tab-bar/index.scss diff --git a/ui/app/components/app/tab-bar/tab-bar.js b/ui/components/app/tab-bar/tab-bar.js similarity index 100% rename from ui/app/components/app/tab-bar/tab-bar.js rename to ui/components/app/tab-bar/tab-bar.js diff --git a/ui/app/components/app/token-cell/index.js b/ui/components/app/token-cell/index.js similarity index 100% rename from ui/app/components/app/token-cell/index.js rename to ui/components/app/token-cell/index.js diff --git a/ui/app/components/app/token-cell/token-cell.js b/ui/components/app/token-cell/token-cell.js similarity index 100% rename from ui/app/components/app/token-cell/token-cell.js rename to ui/components/app/token-cell/token-cell.js diff --git a/ui/app/components/app/token-cell/token-cell.scss b/ui/components/app/token-cell/token-cell.scss similarity index 100% rename from ui/app/components/app/token-cell/token-cell.scss rename to ui/components/app/token-cell/token-cell.scss diff --git a/ui/app/components/app/token-cell/token-cell.test.js b/ui/components/app/token-cell/token-cell.test.js similarity index 100% rename from ui/app/components/app/token-cell/token-cell.test.js rename to ui/components/app/token-cell/token-cell.test.js diff --git a/ui/app/components/app/token-list/index.js b/ui/components/app/token-list/index.js similarity index 100% rename from ui/app/components/app/token-list/index.js rename to ui/components/app/token-list/index.js diff --git a/ui/app/components/app/token-list/token-list.js b/ui/components/app/token-list/token-list.js similarity index 100% rename from ui/app/components/app/token-list/token-list.js rename to ui/components/app/token-list/token-list.js diff --git a/ui/app/components/app/transaction-activity-log/index.js b/ui/components/app/transaction-activity-log/index.js similarity index 100% rename from ui/app/components/app/transaction-activity-log/index.js rename to ui/components/app/transaction-activity-log/index.js diff --git a/ui/app/components/app/transaction-activity-log/index.scss b/ui/components/app/transaction-activity-log/index.scss similarity index 100% rename from ui/app/components/app/transaction-activity-log/index.scss rename to ui/components/app/transaction-activity-log/index.scss diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log-icon/index.js b/ui/components/app/transaction-activity-log/transaction-activity-log-icon/index.js similarity index 100% rename from ui/app/components/app/transaction-activity-log/transaction-activity-log-icon/index.js rename to ui/components/app/transaction-activity-log/transaction-activity-log-icon/index.js diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log-icon/transaction-activity-log-icon.component.js b/ui/components/app/transaction-activity-log/transaction-activity-log-icon/transaction-activity-log-icon.component.js similarity index 100% rename from ui/app/components/app/transaction-activity-log/transaction-activity-log-icon/transaction-activity-log-icon.component.js rename to ui/components/app/transaction-activity-log/transaction-activity-log-icon/transaction-activity-log-icon.component.js diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js b/ui/components/app/transaction-activity-log/transaction-activity-log.component.js similarity index 88% rename from ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js rename to ui/components/app/transaction-activity-log/transaction-activity-log.component.js index 215932e9f..2e7cb77d3 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.js +++ b/ui/components/app/transaction-activity-log/transaction-activity-log.component.js @@ -2,19 +2,19 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; +import { getBlockExplorerLink } from '@metamask/etherscan-link'; import { getEthConversionFromWeiHex, getValueFromWeiHex, } from '../../../helpers/utils/conversions.util'; import { formatDate } from '../../../helpers/utils/util'; -import { getBlockExplorerUrlForTx } from '../../../../../shared/modules/transaction.utils'; import TransactionActivityLogIcon from './transaction-activity-log-icon'; import { CONFIRMED_STATUS } from './transaction-activity-log.constants'; export default class TransactionActivityLog extends PureComponent { static contextTypes = { t: PropTypes.func, - metricEvent: PropTypes.func, + trackEvent: PropTypes.func, }; static propTypes = { @@ -32,10 +32,21 @@ export default class TransactionActivityLog extends PureComponent { }; handleActivityClick = (activity) => { - const etherscanUrl = getBlockExplorerUrlForTx( - activity, - this.props.rpcPrefs, - ); + const { rpcPrefs } = this.props; + const etherscanUrl = getBlockExplorerLink(activity, rpcPrefs); + + this.context.trackEvent({ + category: 'Transactions', + event: 'Clicked Block Explorer Link', + properties: { + link_type: 'Transaction Block Explorer', + action: 'Activity Details', + block_explorer_domain: etherscanUrl + ? new URL(etherscanUrl)?.hostname + : '', + }, + }); + global.platform.openTab({ url: etherscanUrl }); }; diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.component.test.js b/ui/components/app/transaction-activity-log/transaction-activity-log.component.test.js similarity index 100% rename from ui/app/components/app/transaction-activity-log/transaction-activity-log.component.test.js rename to ui/components/app/transaction-activity-log/transaction-activity-log.component.test.js diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.constants.js b/ui/components/app/transaction-activity-log/transaction-activity-log.constants.js similarity index 100% rename from ui/app/components/app/transaction-activity-log/transaction-activity-log.constants.js rename to ui/components/app/transaction-activity-log/transaction-activity-log.constants.js diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js b/ui/components/app/transaction-activity-log/transaction-activity-log.container.js similarity index 100% rename from ui/app/components/app/transaction-activity-log/transaction-activity-log.container.js rename to ui/components/app/transaction-activity-log/transaction-activity-log.container.js diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.container.test.js b/ui/components/app/transaction-activity-log/transaction-activity-log.container.test.js similarity index 100% rename from ui/app/components/app/transaction-activity-log/transaction-activity-log.container.test.js rename to ui/components/app/transaction-activity-log/transaction-activity-log.container.test.js diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js b/ui/components/app/transaction-activity-log/transaction-activity-log.util.js similarity index 99% rename from ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js rename to ui/components/app/transaction-activity-log/transaction-activity-log.util.js index 624e1027d..ee3d7ee0a 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.js +++ b/ui/components/app/transaction-activity-log/transaction-activity-log.util.js @@ -1,4 +1,4 @@ -import { TRANSACTION_TYPES } from '../../../../../shared/constants/transaction'; +import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; import { getHexGasTotal } from '../../../helpers/utils/confirm-tx.util'; import { diff --git a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.test.js b/ui/components/app/transaction-activity-log/transaction-activity-log.util.test.js similarity index 99% rename from ui/app/components/app/transaction-activity-log/transaction-activity-log.util.test.js rename to ui/components/app/transaction-activity-log/transaction-activity-log.util.test.js index 16211afd4..af7adee79 100644 --- a/ui/app/components/app/transaction-activity-log/transaction-activity-log.util.test.js +++ b/ui/components/app/transaction-activity-log/transaction-activity-log.util.test.js @@ -1,11 +1,11 @@ import { ROPSTEN_CHAIN_ID, ROPSTEN_NETWORK_ID, -} from '../../../../../shared/constants/network'; +} from '../../../../shared/constants/network'; import { TRANSACTION_STATUSES, TRANSACTION_TYPES, -} from '../../../../../shared/constants/transaction'; +} from '../../../../shared/constants/transaction'; import { combineTransactionHistories, getActivities, diff --git a/ui/app/components/app/transaction-breakdown/index.js b/ui/components/app/transaction-breakdown/index.js similarity index 100% rename from ui/app/components/app/transaction-breakdown/index.js rename to ui/components/app/transaction-breakdown/index.js diff --git a/ui/app/components/app/transaction-breakdown/index.scss b/ui/components/app/transaction-breakdown/index.scss similarity index 100% rename from ui/app/components/app/transaction-breakdown/index.scss rename to ui/components/app/transaction-breakdown/index.scss diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/index.js b/ui/components/app/transaction-breakdown/transaction-breakdown-row/index.js similarity index 100% rename from ui/app/components/app/transaction-breakdown/transaction-breakdown-row/index.js rename to ui/components/app/transaction-breakdown/transaction-breakdown-row/index.js diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/index.scss b/ui/components/app/transaction-breakdown/transaction-breakdown-row/index.scss similarity index 100% rename from ui/app/components/app/transaction-breakdown/transaction-breakdown-row/index.scss rename to ui/components/app/transaction-breakdown/transaction-breakdown-row/index.scss diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.js b/ui/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.js similarity index 100% rename from ui/app/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.js rename to ui/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.js diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.test.js b/ui/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.test.js similarity index 100% rename from ui/app/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.test.js rename to ui/components/app/transaction-breakdown/transaction-breakdown-row/transaction-breakdown-row.component.test.js diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js b/ui/components/app/transaction-breakdown/transaction-breakdown.component.js similarity index 100% rename from ui/app/components/app/transaction-breakdown/transaction-breakdown.component.js rename to ui/components/app/transaction-breakdown/transaction-breakdown.component.js diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.test.js b/ui/components/app/transaction-breakdown/transaction-breakdown.component.test.js similarity index 91% rename from ui/app/components/app/transaction-breakdown/transaction-breakdown.component.test.js rename to ui/components/app/transaction-breakdown/transaction-breakdown.component.test.js index 9b34276db..fb7916c46 100644 --- a/ui/app/components/app/transaction-breakdown/transaction-breakdown.component.test.js +++ b/ui/components/app/transaction-breakdown/transaction-breakdown.component.test.js @@ -1,6 +1,6 @@ import React from 'react'; import { shallow } from 'enzyme'; -import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction'; +import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; import TransactionBreakdown from './transaction-breakdown.component'; describe('TransactionBreakdown Component', () => { diff --git a/ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js b/ui/components/app/transaction-breakdown/transaction-breakdown.container.js similarity index 100% rename from ui/app/components/app/transaction-breakdown/transaction-breakdown.container.js rename to ui/components/app/transaction-breakdown/transaction-breakdown.container.js diff --git a/ui/app/components/app/transaction-icon/index.js b/ui/components/app/transaction-icon/index.js similarity index 100% rename from ui/app/components/app/transaction-icon/index.js rename to ui/components/app/transaction-icon/index.js diff --git a/ui/app/components/app/transaction-icon/transaction-icon.js b/ui/components/app/transaction-icon/transaction-icon.js similarity index 97% rename from ui/app/components/app/transaction-icon/transaction-icon.js rename to ui/components/app/transaction-icon/transaction-icon.js index 1876e0535..6980a89cd 100644 --- a/ui/app/components/app/transaction-icon/transaction-icon.js +++ b/ui/components/app/transaction-icon/transaction-icon.js @@ -11,7 +11,7 @@ import { TRANSACTION_GROUP_CATEGORIES, TRANSACTION_GROUP_STATUSES, TRANSACTION_STATUSES, -} from '../../../../../shared/constants/transaction'; +} from '../../../../shared/constants/transaction'; const ICON_MAP = { [TRANSACTION_GROUP_CATEGORIES.APPROVAL]: Approve, @@ -56,14 +56,6 @@ export default function TransactionIcon({ status, category }) { TransactionIcon.propTypes = { status: PropTypes.oneOf([ - TRANSACTION_GROUP_CATEGORIES.APPROVAL, - TRANSACTION_GROUP_CATEGORIES.INTERACTION, - TRANSACTION_GROUP_CATEGORIES.SEND, - TRANSACTION_GROUP_CATEGORIES.SIGNATURE_REQUEST, - TRANSACTION_GROUP_CATEGORIES.RECEIVE, - TRANSACTION_GROUP_CATEGORIES.SWAP, - ]).isRequired, - category: PropTypes.oneOf([ TRANSACTION_GROUP_STATUSES.PENDING, TRANSACTION_STATUSES.UNAPPROVED, TRANSACTION_STATUSES.APPROVED, @@ -72,4 +64,12 @@ TransactionIcon.propTypes = { TRANSACTION_GROUP_STATUSES.CANCELLED, TRANSACTION_STATUSES.DROPPED, ]).isRequired, + category: PropTypes.oneOf([ + TRANSACTION_GROUP_CATEGORIES.APPROVAL, + TRANSACTION_GROUP_CATEGORIES.INTERACTION, + TRANSACTION_GROUP_CATEGORIES.SEND, + TRANSACTION_GROUP_CATEGORIES.SIGNATURE_REQUEST, + TRANSACTION_GROUP_CATEGORIES.RECEIVE, + TRANSACTION_GROUP_CATEGORIES.SWAP, + ]).isRequired, }; diff --git a/ui/app/components/app/transaction-icon/transaction-icon.scss b/ui/components/app/transaction-icon/transaction-icon.scss similarity index 100% rename from ui/app/components/app/transaction-icon/transaction-icon.scss rename to ui/components/app/transaction-icon/transaction-icon.scss diff --git a/ui/app/components/app/transaction-list-item-details/index.js b/ui/components/app/transaction-list-item-details/index.js similarity index 100% rename from ui/app/components/app/transaction-list-item-details/index.js rename to ui/components/app/transaction-list-item-details/index.js diff --git a/ui/app/components/app/transaction-list-item-details/index.scss b/ui/components/app/transaction-list-item-details/index.scss similarity index 100% rename from ui/app/components/app/transaction-list-item-details/index.scss rename to ui/components/app/transaction-list-item-details/index.scss diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js b/ui/components/app/transaction-list-item-details/transaction-list-item-details.component.js similarity index 91% rename from ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js rename to ui/components/app/transaction-list-item-details/transaction-list-item-details.component.js index c1256d7cb..d6f6bf159 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.js +++ b/ui/components/app/transaction-list-item-details/transaction-list-item-details.component.js @@ -1,6 +1,7 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import copyToClipboard from 'copy-to-clipboard'; +import { getBlockExplorerLink } from '@metamask/etherscan-link'; import SenderToRecipient from '../../ui/sender-to-recipient'; import { FLAT_VARIANT } from '../../ui/sender-to-recipient/sender-to-recipient.constants'; import TransactionActivityLog from '../transaction-activity-log'; @@ -9,13 +10,13 @@ import Button from '../../ui/button'; import Tooltip from '../../ui/tooltip'; import Copy from '../../ui/icon/copy-icon.component'; import Popover from '../../ui/popover'; -import { getBlockExplorerUrlForTx } from '../../../../../shared/modules/transaction.utils'; -import { TRANSACTION_TYPES } from '../../../../../shared/constants/transaction'; +import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; export default class TransactionListItemDetails extends PureComponent { static contextTypes = { t: PropTypes.func, metricsEvent: PropTypes.func, + trackEvent: PropTypes.func, }; static defaultProps = { @@ -47,22 +48,30 @@ export default class TransactionListItemDetails extends PureComponent { justCopied: false, }; - handleEtherscanClick = () => { + handleBlockExplorerClick = () => { const { transactionGroup: { primaryTransaction }, rpcPrefs, } = this.props; + const blockExplorerLink = getBlockExplorerLink( + primaryTransaction, + rpcPrefs, + ); - this.context.metricsEvent({ - eventOpts: { - category: 'Navigation', - action: 'Activity Log', - name: 'Clicked "View on Etherscan"', + this.context.trackEvent({ + category: 'Transactions', + event: 'Clicked Block Explorer Link', + properties: { + link_type: 'Transaction Block Explorer', + action: 'Transaction Details', + block_explorer_domain: blockExplorerLink + ? new URL(blockExplorerLink)?.hostname + : '', }, }); global.platform.openTab({ - url: getBlockExplorerUrlForTx(primaryTransaction, rpcPrefs), + url: blockExplorerLink, }); }; @@ -203,10 +212,10 @@ export default class TransactionListItemDetails extends PureComponent { > <Button type="raised" - onClick={this.handleEtherscanClick} + onClick={this.handleBlockExplorerClick} disabled={!hash} > - <img src="/images/arrow-popout.svg" alt="" /> + <img src="./images/arrow-popout.svg" alt="" /> </Button> </Tooltip> {showRetry && ( diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.test.js b/ui/components/app/transaction-list-item-details/transaction-list-item-details.component.test.js similarity index 98% rename from ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.test.js rename to ui/components/app/transaction-list-item-details/transaction-list-item-details.component.test.js index 42ac3c83b..409ca1092 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.component.test.js +++ b/ui/components/app/transaction-list-item-details/transaction-list-item-details.component.test.js @@ -4,7 +4,7 @@ import Button from '../../ui/button'; import SenderToRecipient from '../../ui/sender-to-recipient'; import TransactionBreakdown from '../transaction-breakdown'; import TransactionActivityLog from '../transaction-activity-log'; -import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction'; +import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; import TransactionListItemDetails from './transaction-list-item-details.component'; describe('TransactionListItemDetails Component', () => { diff --git a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js b/ui/components/app/transaction-list-item-details/transaction-list-item-details.container.js similarity index 94% rename from ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js rename to ui/components/app/transaction-list-item-details/transaction-list-item-details.container.js index f1cbf6237..280cec020 100644 --- a/ui/app/components/app/transaction-list-item-details/transaction-list-item-details.container.js +++ b/ui/components/app/transaction-list-item-details/transaction-list-item-details.container.js @@ -4,7 +4,7 @@ import { getAddressBook, getRpcPrefsForCurrentProvider, } from '../../../selectors'; -import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import TransactionListItemDetails from './transaction-list-item-details.component'; const mapStateToProps = (state, ownProps) => { diff --git a/ui/app/components/app/transaction-list-item/index.js b/ui/components/app/transaction-list-item/index.js similarity index 100% rename from ui/app/components/app/transaction-list-item/index.js rename to ui/components/app/transaction-list-item/index.js diff --git a/ui/app/components/app/transaction-list-item/index.scss b/ui/components/app/transaction-list-item/index.scss similarity index 100% rename from ui/app/components/app/transaction-list-item/index.scss rename to ui/components/app/transaction-list-item/index.scss diff --git a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js b/ui/components/app/transaction-list-item/transaction-list-item.component.js similarity index 99% rename from ui/app/components/app/transaction-list-item/transaction-list-item.component.js rename to ui/components/app/transaction-list-item/transaction-list-item.component.js index d3f957904..98635cce4 100644 --- a/ui/app/components/app/transaction-list-item/transaction-list-item.component.js +++ b/ui/components/app/transaction-list-item/transaction-list-item.component.js @@ -17,7 +17,7 @@ import TransactionIcon from '../transaction-icon'; import { TRANSACTION_GROUP_CATEGORIES, TRANSACTION_STATUSES, -} from '../../../../../shared/constants/transaction'; +} from '../../../../shared/constants/transaction'; export default function TransactionListItem({ transactionGroup, diff --git a/ui/app/components/app/transaction-list/index.js b/ui/components/app/transaction-list/index.js similarity index 100% rename from ui/app/components/app/transaction-list/index.js rename to ui/components/app/transaction-list/index.js diff --git a/ui/app/components/app/transaction-list/index.scss b/ui/components/app/transaction-list/index.scss similarity index 100% rename from ui/app/components/app/transaction-list/index.scss rename to ui/components/app/transaction-list/index.scss diff --git a/ui/app/components/app/transaction-list/transaction-list.component.js b/ui/components/app/transaction-list/transaction-list.component.js similarity index 97% rename from ui/app/components/app/transaction-list/transaction-list.component.js rename to ui/components/app/transaction-list/transaction-list.component.js index 389a76025..bfd294000 100644 --- a/ui/app/components/app/transaction-list/transaction-list.component.js +++ b/ui/components/app/transaction-list/transaction-list.component.js @@ -10,8 +10,8 @@ import { useI18nContext } from '../../../hooks/useI18nContext'; import TransactionListItem from '../transaction-list-item'; import Button from '../../ui/button'; import { TOKEN_CATEGORY_HASH } from '../../../helpers/constants/transactions'; -import { SWAPS_CHAINID_CONTRACT_ADDRESS_MAP } from '../../../../../shared/constants/swaps'; -import { TRANSACTION_TYPES } from '../../../../../shared/constants/transaction'; +import { SWAPS_CHAINID_CONTRACT_ADDRESS_MAP } from '../../../../shared/constants/swaps'; +import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; const PAGE_INCREMENT = 10; @@ -159,7 +159,7 @@ export default function TransactionList({ rounded onClick={viewMore} > - View More + {t('viewMore')} </Button> )} </div> diff --git a/ui/app/components/app/transaction-status/index.js b/ui/components/app/transaction-status/index.js similarity index 100% rename from ui/app/components/app/transaction-status/index.js rename to ui/components/app/transaction-status/index.js diff --git a/ui/app/components/app/transaction-status/index.scss b/ui/components/app/transaction-status/index.scss similarity index 100% rename from ui/app/components/app/transaction-status/index.scss rename to ui/components/app/transaction-status/index.scss diff --git a/ui/app/components/app/transaction-status/transaction-status.component.js b/ui/components/app/transaction-status/transaction-status.component.js similarity index 97% rename from ui/app/components/app/transaction-status/transaction-status.component.js rename to ui/components/app/transaction-status/transaction-status.component.js index 6049a33a9..f8f5f8018 100644 --- a/ui/app/components/app/transaction-status/transaction-status.component.js +++ b/ui/components/app/transaction-status/transaction-status.component.js @@ -7,7 +7,7 @@ import { useI18nContext } from '../../../hooks/useI18nContext'; import { TRANSACTION_GROUP_STATUSES, TRANSACTION_STATUSES, -} from '../../../../../shared/constants/transaction'; +} from '../../../../shared/constants/transaction'; const QUEUED_PSEUDO_STATUS = 'queued'; diff --git a/ui/app/components/app/transaction-status/transaction-status.component.test.js b/ui/components/app/transaction-status/transaction-status.component.test.js similarity index 100% rename from ui/app/components/app/transaction-status/transaction-status.component.test.js rename to ui/components/app/transaction-status/transaction-status.component.test.js diff --git a/ui/app/components/app/user-preferenced-currency-display/index.js b/ui/components/app/user-preferenced-currency-display/index.js similarity index 100% rename from ui/app/components/app/user-preferenced-currency-display/index.js rename to ui/components/app/user-preferenced-currency-display/index.js diff --git a/ui/app/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js similarity index 94% rename from ui/app/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js rename to ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js index aa1aba7e7..e572d8adb 100644 --- a/ui/app/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js +++ b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.js @@ -22,7 +22,9 @@ export default function UserPreferencedCurrencyDisplay({ const prefixComponent = useMemo(() => { return ( currency === ETH && - showEthLogo && <img src="/images/eth.svg" height={ethLogoHeight} alt="" /> + showEthLogo && ( + <img src="./images/eth.svg" height={ethLogoHeight} alt="" /> + ) ); }, [currency, showEthLogo, ethLogoHeight]); diff --git a/ui/app/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.test.js b/ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.test.js similarity index 100% rename from ui/app/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.test.js rename to ui/components/app/user-preferenced-currency-display/user-preferenced-currency-display.component.test.js diff --git a/ui/app/components/app/user-preferenced-currency-input/index.js b/ui/components/app/user-preferenced-currency-input/index.js similarity index 100% rename from ui/app/components/app/user-preferenced-currency-input/index.js rename to ui/components/app/user-preferenced-currency-input/index.js diff --git a/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.js b/ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.js similarity index 100% rename from ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.js rename to ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.js diff --git a/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.test.js b/ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.test.js similarity index 100% rename from ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.test.js rename to ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.component.test.js diff --git a/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js b/ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js similarity index 100% rename from ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js rename to ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.js diff --git a/ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.test.js b/ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.test.js similarity index 100% rename from ui/app/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.test.js rename to ui/components/app/user-preferenced-currency-input/user-preferenced-currency-input.container.test.js diff --git a/ui/app/components/app/user-preferenced-token-input/index.js b/ui/components/app/user-preferenced-token-input/index.js similarity index 100% rename from ui/app/components/app/user-preferenced-token-input/index.js rename to ui/components/app/user-preferenced-token-input/index.js diff --git a/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.component.js b/ui/components/app/user-preferenced-token-input/user-preferenced-token-input.component.js similarity index 100% rename from ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.component.js rename to ui/components/app/user-preferenced-token-input/user-preferenced-token-input.component.js diff --git a/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.component.test.js b/ui/components/app/user-preferenced-token-input/user-preferenced-token-input.component.test.js similarity index 100% rename from ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.component.test.js rename to ui/components/app/user-preferenced-token-input/user-preferenced-token-input.component.test.js diff --git a/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js b/ui/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js similarity index 100% rename from ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js rename to ui/components/app/user-preferenced-token-input/user-preferenced-token-input.container.js diff --git a/ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.test.js b/ui/components/app/user-preferenced-token-input/user-preferenced-token-input.container.test.js similarity index 100% rename from ui/app/components/app/user-preferenced-token-input/user-preferenced-token-input.container.test.js rename to ui/components/app/user-preferenced-token-input/user-preferenced-token-input.container.test.js diff --git a/ui/app/components/app/wallet-overview/eth-overview.js b/ui/components/app/wallet-overview/eth-overview.js similarity index 100% rename from ui/app/components/app/wallet-overview/eth-overview.js rename to ui/components/app/wallet-overview/eth-overview.js diff --git a/ui/app/components/app/wallet-overview/index.js b/ui/components/app/wallet-overview/index.js similarity index 100% rename from ui/app/components/app/wallet-overview/index.js rename to ui/components/app/wallet-overview/index.js diff --git a/ui/app/components/app/wallet-overview/index.scss b/ui/components/app/wallet-overview/index.scss similarity index 100% rename from ui/app/components/app/wallet-overview/index.scss rename to ui/components/app/wallet-overview/index.scss diff --git a/ui/app/components/app/wallet-overview/token-overview.js b/ui/components/app/wallet-overview/token-overview.js similarity index 100% rename from ui/app/components/app/wallet-overview/token-overview.js rename to ui/components/app/wallet-overview/token-overview.js diff --git a/ui/app/components/app/wallet-overview/wallet-overview.js b/ui/components/app/wallet-overview/wallet-overview.js similarity index 100% rename from ui/app/components/app/wallet-overview/wallet-overview.js rename to ui/components/app/wallet-overview/wallet-overview.js diff --git a/ui/app/components/app/whats-new-popup/index.js b/ui/components/app/whats-new-popup/index.js similarity index 100% rename from ui/app/components/app/whats-new-popup/index.js rename to ui/components/app/whats-new-popup/index.js diff --git a/ui/app/components/app/whats-new-popup/index.scss b/ui/components/app/whats-new-popup/index.scss similarity index 94% rename from ui/app/components/app/whats-new-popup/index.scss rename to ui/components/app/whats-new-popup/index.scss index 3bef99859..c00568ab2 100644 --- a/ui/app/components/app/whats-new-popup/index.scss +++ b/ui/components/app/whats-new-popup/index.scss @@ -25,6 +25,12 @@ } } + &__notification { + &:last-child { + border-bottom: none; + } + } + &__notification-image { align-self: center; margin-bottom: 16px; diff --git a/ui/app/components/app/whats-new-popup/whats-new-popup.js b/ui/components/app/whats-new-popup/whats-new-popup.js similarity index 84% rename from ui/app/components/app/whats-new-popup/whats-new-popup.js rename to ui/components/app/whats-new-popup/whats-new-popup.js index be9415d4b..9b944135a 100644 --- a/ui/app/components/app/whats-new-popup/whats-new-popup.js +++ b/ui/components/app/whats-new-popup/whats-new-popup.js @@ -1,4 +1,5 @@ import React, { useContext, useMemo, useRef, useState, useEffect } from 'react'; +import { useHistory } from 'react-router-dom'; import { useSelector } from 'react-redux'; import PropTypes from 'prop-types'; import classnames from 'classnames'; @@ -9,11 +10,12 @@ import Button from '../../ui/button'; import Popover from '../../ui/popover'; import Typography from '../../ui/typography'; import { updateViewedNotifications } from '../../../store/actions'; -import { getTranslatedUINoficiations } from '../../../../../shared/notifications'; +import { getTranslatedUINoficiations } from '../../../../shared/notifications'; import { getSortedNotificationsToShow } from '../../../selectors'; +import { BUILD_QUOTE_ROUTE } from '../../../helpers/constants/routes'; import { TYPOGRAPHY } from '../../../helpers/constants/design-system'; -function getActionFunctionById(id) { +function getActionFunctionById(id, history) { const actionFunctions = { 2: () => { global.platform.openTab({ @@ -26,6 +28,16 @@ function getActionFunctionById(id) { url: 'https://community.metamask.io/t/about-the-security-category/72', }); }, + 4: () => { + updateViewedNotifications({ 4: true }); + history.push(BUILD_QUOTE_ROUTE); + }, + 5: () => { + updateViewedNotifications({ 5: true }); + global.platform.openTab({ + url: 'https://metamask.zendesk.com/hc/en-us/articles/360060826432', + }); + }, }; return actionFunctions[id]; @@ -56,9 +68,9 @@ const renderDescription = (description) => { ); }; -const renderFirstNotification = (notification, idRefMap, isLast) => { +const renderFirstNotification = (notification, idRefMap, history, isLast) => { const { id, date, title, description, image, actionText } = notification; - const actionFunction = getActionFunctionById(id); + const actionFunction = getActionFunctionById(id, history); const imageComponent = image && ( <img className="whats-new-popup__notification-image" @@ -105,10 +117,15 @@ const renderFirstNotification = (notification, idRefMap, isLast) => { ); }; -const renderSubsequentNotification = (notification, idRefMap, isLast) => { +const renderSubsequentNotification = ( + notification, + idRefMap, + history, + isLast, +) => { const { id, date, title, description, actionText } = notification; - const actionFunction = getActionFunctionById(id); + const actionFunction = getActionFunctionById(id, history); return ( <div className={classnames('whats-new-popup__notification', { @@ -138,6 +155,7 @@ const renderSubsequentNotification = (notification, idRefMap, isLast) => { export default function WhatsNewPopup({ onClose }) { const t = useContext(I18nContext); + const history = useHistory(); const notifications = useSelector(getSortedNotificationsToShow); const locale = useSelector(getCurrentLocale); @@ -208,8 +226,13 @@ export default function WhatsNewPopup({ onClose }) { const isLast = index === notifications.length - 1; // Display the swaps notification with full image return index === 0 || id === 1 - ? renderFirstNotification(notification, idRefMap, isLast) - : renderSubsequentNotification(notification, idRefMap, isLast); + ? renderFirstNotification(notification, idRefMap, history, isLast) + : renderSubsequentNotification( + notification, + idRefMap, + history, + isLast, + ); })} </div> </Popover> diff --git a/ui/app/components/ui/account-mismatch-warning/acccount-mismatch-warning.component.test.js b/ui/components/ui/account-mismatch-warning/acccount-mismatch-warning.component.test.js similarity index 100% rename from ui/app/components/ui/account-mismatch-warning/acccount-mismatch-warning.component.test.js rename to ui/components/ui/account-mismatch-warning/acccount-mismatch-warning.component.test.js diff --git a/ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js b/ui/components/ui/account-mismatch-warning/account-mismatch-warning.component.js similarity index 100% rename from ui/app/components/ui/account-mismatch-warning/account-mismatch-warning.component.js rename to ui/components/ui/account-mismatch-warning/account-mismatch-warning.component.js diff --git a/ui/app/components/ui/account-mismatch-warning/index.scss b/ui/components/ui/account-mismatch-warning/index.scss similarity index 100% rename from ui/app/components/ui/account-mismatch-warning/index.scss rename to ui/components/ui/account-mismatch-warning/index.scss diff --git a/ui/app/components/ui/alert-circle-icon/alert-circle-icon.component.js b/ui/components/ui/alert-circle-icon/alert-circle-icon.component.js similarity index 100% rename from ui/app/components/ui/alert-circle-icon/alert-circle-icon.component.js rename to ui/components/ui/alert-circle-icon/alert-circle-icon.component.js diff --git a/ui/app/components/ui/alert-circle-icon/alert-circle-icon.stories.js b/ui/components/ui/alert-circle-icon/alert-circle-icon.stories.js similarity index 100% rename from ui/app/components/ui/alert-circle-icon/alert-circle-icon.stories.js rename to ui/components/ui/alert-circle-icon/alert-circle-icon.stories.js diff --git a/ui/app/components/ui/alert-circle-icon/index.js b/ui/components/ui/alert-circle-icon/index.js similarity index 100% rename from ui/app/components/ui/alert-circle-icon/index.js rename to ui/components/ui/alert-circle-icon/index.js diff --git a/ui/app/components/ui/alert-circle-icon/index.scss b/ui/components/ui/alert-circle-icon/index.scss similarity index 100% rename from ui/app/components/ui/alert-circle-icon/index.scss rename to ui/components/ui/alert-circle-icon/index.scss diff --git a/ui/app/components/ui/alert/index.js b/ui/components/ui/alert/index.js similarity index 100% rename from ui/app/components/ui/alert/index.js rename to ui/components/ui/alert/index.js diff --git a/ui/app/components/ui/alert/index.scss b/ui/components/ui/alert/index.scss similarity index 100% rename from ui/app/components/ui/alert/index.scss rename to ui/components/ui/alert/index.scss diff --git a/ui/app/components/ui/alert/index.test.js b/ui/components/ui/alert/index.test.js similarity index 100% rename from ui/app/components/ui/alert/index.test.js rename to ui/components/ui/alert/index.test.js diff --git a/ui/app/components/ui/box/box.js b/ui/components/ui/box/box.js similarity index 97% rename from ui/app/components/ui/box/box.js rename to ui/components/ui/box/box.js index bf4756084..47d9617e6 100644 --- a/ui/app/components/ui/box/box.js +++ b/ui/components/ui/box/box.js @@ -9,6 +9,7 @@ import { DISPLAY, JUSTIFY_CONTENT, SIZES, + TEXT_ALIGN, } from '../../../helpers/constants/design-system'; const ValidSize = PropTypes.oneOf([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); @@ -70,6 +71,7 @@ export default function Box({ borderStyle, alignItems, justifyContent, + textAlign, display, width, height, @@ -113,6 +115,8 @@ export default function Box({ !display && (Boolean(justifyContent) || Boolean(alignItems)), [`box--justify-content-${justifyContent}`]: Boolean(justifyContent), [`box--align-items-${alignItems}`]: Boolean(alignItems), + // text align + [`box--text-align-${textAlign}`]: Boolean(textAlign), // display [`box--display-${display}`]: Boolean(display), // width & height @@ -144,6 +148,7 @@ Box.propTypes = { borderStyle: PropTypes.oneOf(Object.values(BORDER_STYLE)), alignItems: PropTypes.oneOf(Object.values(ALIGN_ITEMS)), justifyContent: PropTypes.oneOf(Object.values(JUSTIFY_CONTENT)), + textAlign: PropTypes.oneOf(Object.values(TEXT_ALIGN)), display: PropTypes.oneOf(Object.values(DISPLAY)), width: PropTypes.oneOf(Object.values(BLOCK_SIZES)), height: PropTypes.oneOf(Object.values(BLOCK_SIZES)), diff --git a/ui/app/components/ui/box/box.scss b/ui/components/ui/box/box.scss similarity index 97% rename from ui/app/components/ui/box/box.scss rename to ui/components/ui/box/box.scss index 6ef762766..9e7c0b776 100644 --- a/ui/app/components/ui/box/box.scss +++ b/ui/components/ui/box/box.scss @@ -129,6 +129,8 @@ $attributes: padding, margin; // text @each $alignment in design-system.$text-align { - text-align: $alignment; + &--text-align-#{$alignment} { + text-align: $alignment; + } } } diff --git a/ui/app/components/ui/box/box.stories.js b/ui/components/ui/box/box.stories.js similarity index 96% rename from ui/app/components/ui/box/box.stories.js rename to ui/components/ui/box/box.stories.js index a76d2fff5..ba41f454f 100644 --- a/ui/app/components/ui/box/box.stories.js +++ b/ui/components/ui/box/box.stories.js @@ -7,6 +7,7 @@ import { COLORS, DISPLAY, JUSTIFY_CONTENT, + TEXT_ALIGN, } from '../../../helpers/constants/design-system'; import Box from './box'; @@ -38,6 +39,7 @@ export const box = () => { undefined, 'display', )} + textAlign={select('textAlign', TEXT_ALIGN, undefined, 'left')} alignItems={select('alignItems', ALIGN_ITEMS, undefined, 'display')} margin={select('margin', sizeKnobOptions, undefined, 'margin')} marginTop={select('marginTop', sizeKnobOptions, undefined, 'margin')} diff --git a/ui/app/components/ui/box/index.js b/ui/components/ui/box/index.js similarity index 100% rename from ui/app/components/ui/box/index.js rename to ui/components/ui/box/index.js diff --git a/ui/app/components/ui/breadcrumbs/breadcrumbs.component.js b/ui/components/ui/breadcrumbs/breadcrumbs.component.js similarity index 100% rename from ui/app/components/ui/breadcrumbs/breadcrumbs.component.js rename to ui/components/ui/breadcrumbs/breadcrumbs.component.js diff --git a/ui/app/components/ui/breadcrumbs/breadcrumbs.component.test.js b/ui/components/ui/breadcrumbs/breadcrumbs.component.test.js similarity index 100% rename from ui/app/components/ui/breadcrumbs/breadcrumbs.component.test.js rename to ui/components/ui/breadcrumbs/breadcrumbs.component.test.js diff --git a/ui/app/components/ui/breadcrumbs/index.js b/ui/components/ui/breadcrumbs/index.js similarity index 100% rename from ui/app/components/ui/breadcrumbs/index.js rename to ui/components/ui/breadcrumbs/index.js diff --git a/ui/app/components/ui/breadcrumbs/index.scss b/ui/components/ui/breadcrumbs/index.scss similarity index 100% rename from ui/app/components/ui/breadcrumbs/index.scss rename to ui/components/ui/breadcrumbs/index.scss diff --git a/ui/app/components/ui/button-group/button-group-component.test.js b/ui/components/ui/button-group/button-group-component.test.js similarity index 100% rename from ui/app/components/ui/button-group/button-group-component.test.js rename to ui/components/ui/button-group/button-group-component.test.js diff --git a/ui/app/components/ui/button-group/button-group.component.js b/ui/components/ui/button-group/button-group.component.js similarity index 100% rename from ui/app/components/ui/button-group/button-group.component.js rename to ui/components/ui/button-group/button-group.component.js diff --git a/ui/app/components/ui/button-group/button-group.stories.js b/ui/components/ui/button-group/button-group.stories.js similarity index 100% rename from ui/app/components/ui/button-group/button-group.stories.js rename to ui/components/ui/button-group/button-group.stories.js diff --git a/ui/app/components/ui/button-group/index.js b/ui/components/ui/button-group/index.js similarity index 100% rename from ui/app/components/ui/button-group/index.js rename to ui/components/ui/button-group/index.js diff --git a/ui/app/components/ui/button-group/index.scss b/ui/components/ui/button-group/index.scss similarity index 100% rename from ui/app/components/ui/button-group/index.scss rename to ui/components/ui/button-group/index.scss diff --git a/ui/app/components/ui/button/button.component.js b/ui/components/ui/button/button.component.js similarity index 100% rename from ui/app/components/ui/button/button.component.js rename to ui/components/ui/button/button.component.js diff --git a/ui/app/components/ui/button/button.stories.js b/ui/components/ui/button/button.stories.js similarity index 100% rename from ui/app/components/ui/button/button.stories.js rename to ui/components/ui/button/button.stories.js diff --git a/ui/app/components/ui/button/buttons.scss b/ui/components/ui/button/buttons.scss similarity index 100% rename from ui/app/components/ui/button/buttons.scss rename to ui/components/ui/button/buttons.scss diff --git a/ui/app/components/ui/button/index.js b/ui/components/ui/button/index.js similarity index 100% rename from ui/app/components/ui/button/index.js rename to ui/components/ui/button/index.js diff --git a/ui/app/components/ui/callout/callout.js b/ui/components/ui/callout/callout.js similarity index 100% rename from ui/app/components/ui/callout/callout.js rename to ui/components/ui/callout/callout.js diff --git a/ui/app/components/ui/callout/callout.scss b/ui/components/ui/callout/callout.scss similarity index 100% rename from ui/app/components/ui/callout/callout.scss rename to ui/components/ui/callout/callout.scss diff --git a/ui/app/components/ui/callout/callout.stories.js b/ui/components/ui/callout/callout.stories.js similarity index 100% rename from ui/app/components/ui/callout/callout.stories.js rename to ui/components/ui/callout/callout.stories.js diff --git a/ui/app/components/ui/callout/index.js b/ui/components/ui/callout/index.js similarity index 100% rename from ui/app/components/ui/callout/index.js rename to ui/components/ui/callout/index.js diff --git a/ui/app/components/ui/card/card.component.js b/ui/components/ui/card/card.component.js similarity index 100% rename from ui/app/components/ui/card/card.component.js rename to ui/components/ui/card/card.component.js diff --git a/ui/app/components/ui/card/card.component.test.js b/ui/components/ui/card/card.component.test.js similarity index 100% rename from ui/app/components/ui/card/card.component.test.js rename to ui/components/ui/card/card.component.test.js diff --git a/ui/app/components/ui/card/index.js b/ui/components/ui/card/index.js similarity index 100% rename from ui/app/components/ui/card/index.js rename to ui/components/ui/card/index.js diff --git a/ui/app/components/ui/card/index.scss b/ui/components/ui/card/index.scss similarity index 100% rename from ui/app/components/ui/card/index.scss rename to ui/components/ui/card/index.scss diff --git a/ui/app/components/ui/check-box/check-box.component.js b/ui/components/ui/check-box/check-box.component.js similarity index 100% rename from ui/app/components/ui/check-box/check-box.component.js rename to ui/components/ui/check-box/check-box.component.js diff --git a/ui/app/components/ui/check-box/check-box.stories.js b/ui/components/ui/check-box/check-box.stories.js similarity index 100% rename from ui/app/components/ui/check-box/check-box.stories.js rename to ui/components/ui/check-box/check-box.stories.js diff --git a/ui/app/components/ui/check-box/index.js b/ui/components/ui/check-box/index.js similarity index 100% rename from ui/app/components/ui/check-box/index.js rename to ui/components/ui/check-box/index.js diff --git a/ui/app/components/ui/check-box/index.scss b/ui/components/ui/check-box/index.scss similarity index 100% rename from ui/app/components/ui/check-box/index.scss rename to ui/components/ui/check-box/index.scss diff --git a/ui/app/components/ui/chip/chip.js b/ui/components/ui/chip/chip.js similarity index 100% rename from ui/app/components/ui/chip/chip.js rename to ui/components/ui/chip/chip.js diff --git a/ui/app/components/ui/chip/chip.scss b/ui/components/ui/chip/chip.scss similarity index 100% rename from ui/app/components/ui/chip/chip.scss rename to ui/components/ui/chip/chip.scss diff --git a/ui/app/components/ui/chip/chip.stories.js b/ui/components/ui/chip/chip.stories.js similarity index 100% rename from ui/app/components/ui/chip/chip.stories.js rename to ui/components/ui/chip/chip.stories.js diff --git a/ui/app/components/ui/chip/index.js b/ui/components/ui/chip/index.js similarity index 100% rename from ui/app/components/ui/chip/index.js rename to ui/components/ui/chip/index.js diff --git a/ui/app/components/ui/circle-icon/circle-icon.component.js b/ui/components/ui/circle-icon/circle-icon.component.js similarity index 100% rename from ui/app/components/ui/circle-icon/circle-icon.component.js rename to ui/components/ui/circle-icon/circle-icon.component.js diff --git a/ui/app/components/ui/circle-icon/circle-icon.stories.js b/ui/components/ui/circle-icon/circle-icon.stories.js similarity index 100% rename from ui/app/components/ui/circle-icon/circle-icon.stories.js rename to ui/components/ui/circle-icon/circle-icon.stories.js diff --git a/ui/app/components/ui/circle-icon/index.js b/ui/components/ui/circle-icon/index.js similarity index 100% rename from ui/app/components/ui/circle-icon/index.js rename to ui/components/ui/circle-icon/index.js diff --git a/ui/app/components/ui/circle-icon/index.scss b/ui/components/ui/circle-icon/index.scss similarity index 100% rename from ui/app/components/ui/circle-icon/index.scss rename to ui/components/ui/circle-icon/index.scss diff --git a/ui/app/components/ui/color-indicator/color-indicator.js b/ui/components/ui/color-indicator/color-indicator.js similarity index 100% rename from ui/app/components/ui/color-indicator/color-indicator.js rename to ui/components/ui/color-indicator/color-indicator.js diff --git a/ui/app/components/ui/color-indicator/color-indicator.scss b/ui/components/ui/color-indicator/color-indicator.scss similarity index 100% rename from ui/app/components/ui/color-indicator/color-indicator.scss rename to ui/components/ui/color-indicator/color-indicator.scss diff --git a/ui/app/components/ui/color-indicator/color-indicator.stories.js b/ui/components/ui/color-indicator/color-indicator.stories.js similarity index 100% rename from ui/app/components/ui/color-indicator/color-indicator.stories.js rename to ui/components/ui/color-indicator/color-indicator.stories.js diff --git a/ui/app/components/ui/color-indicator/index.js b/ui/components/ui/color-indicator/index.js similarity index 100% rename from ui/app/components/ui/color-indicator/index.js rename to ui/components/ui/color-indicator/index.js diff --git a/ui/app/components/ui/confusable/confusable.component.js b/ui/components/ui/confusable/confusable.component.js similarity index 100% rename from ui/app/components/ui/confusable/confusable.component.js rename to ui/components/ui/confusable/confusable.component.js diff --git a/ui/app/components/ui/confusable/confusable.component.test.js b/ui/components/ui/confusable/confusable.component.test.js similarity index 100% rename from ui/app/components/ui/confusable/confusable.component.test.js rename to ui/components/ui/confusable/confusable.component.test.js diff --git a/ui/app/components/ui/confusable/index.js b/ui/components/ui/confusable/index.js similarity index 100% rename from ui/app/components/ui/confusable/index.js rename to ui/components/ui/confusable/index.js diff --git a/ui/app/components/ui/confusable/index.scss b/ui/components/ui/confusable/index.scss similarity index 100% rename from ui/app/components/ui/confusable/index.scss rename to ui/components/ui/confusable/index.scss diff --git a/ui/app/components/ui/currency-display/currency-display.component.js b/ui/components/ui/currency-display/currency-display.component.js similarity index 100% rename from ui/app/components/ui/currency-display/currency-display.component.js rename to ui/components/ui/currency-display/currency-display.component.js diff --git a/ui/app/components/ui/currency-display/currency-display.component.test.js b/ui/components/ui/currency-display/currency-display.component.test.js similarity index 100% rename from ui/app/components/ui/currency-display/currency-display.component.test.js rename to ui/components/ui/currency-display/currency-display.component.test.js diff --git a/ui/app/components/ui/currency-display/index.js b/ui/components/ui/currency-display/index.js similarity index 100% rename from ui/app/components/ui/currency-display/index.js rename to ui/components/ui/currency-display/index.js diff --git a/ui/app/components/ui/currency-display/index.scss b/ui/components/ui/currency-display/index.scss similarity index 100% rename from ui/app/components/ui/currency-display/index.scss rename to ui/components/ui/currency-display/index.scss diff --git a/ui/app/components/ui/currency-input/currency-input.component.js b/ui/components/ui/currency-input/currency-input.component.js similarity index 100% rename from ui/app/components/ui/currency-input/currency-input.component.js rename to ui/components/ui/currency-input/currency-input.component.js diff --git a/ui/app/components/ui/currency-input/currency-input.component.test.js b/ui/components/ui/currency-input/currency-input.component.test.js similarity index 100% rename from ui/app/components/ui/currency-input/currency-input.component.test.js rename to ui/components/ui/currency-input/currency-input.component.test.js diff --git a/ui/app/components/ui/currency-input/currency-input.container.js b/ui/components/ui/currency-input/currency-input.container.js similarity index 100% rename from ui/app/components/ui/currency-input/currency-input.container.js rename to ui/components/ui/currency-input/currency-input.container.js diff --git a/ui/app/components/ui/currency-input/currency-input.container.test.js b/ui/components/ui/currency-input/currency-input.container.test.js similarity index 100% rename from ui/app/components/ui/currency-input/currency-input.container.test.js rename to ui/components/ui/currency-input/currency-input.container.test.js diff --git a/ui/app/components/ui/currency-input/index.js b/ui/components/ui/currency-input/index.js similarity index 100% rename from ui/app/components/ui/currency-input/index.js rename to ui/components/ui/currency-input/index.js diff --git a/ui/app/components/ui/currency-input/index.scss b/ui/components/ui/currency-input/index.scss similarity index 100% rename from ui/app/components/ui/currency-input/index.scss rename to ui/components/ui/currency-input/index.scss diff --git a/ui/app/components/ui/definition-list/definition-list.js b/ui/components/ui/definition-list/definition-list.js similarity index 100% rename from ui/app/components/ui/definition-list/definition-list.js rename to ui/components/ui/definition-list/definition-list.js diff --git a/ui/app/components/ui/definition-list/definition-list.scss b/ui/components/ui/definition-list/definition-list.scss similarity index 100% rename from ui/app/components/ui/definition-list/definition-list.scss rename to ui/components/ui/definition-list/definition-list.scss diff --git a/ui/app/components/ui/definition-list/definition-list.stories.js b/ui/components/ui/definition-list/definition-list.stories.js similarity index 100% rename from ui/app/components/ui/definition-list/definition-list.stories.js rename to ui/components/ui/definition-list/definition-list.stories.js diff --git a/ui/app/components/ui/definition-list/index.js b/ui/components/ui/definition-list/index.js similarity index 100% rename from ui/app/components/ui/definition-list/index.js rename to ui/components/ui/definition-list/index.js diff --git a/ui/app/components/ui/dialog/dialog.scss b/ui/components/ui/dialog/dialog.scss similarity index 100% rename from ui/app/components/ui/dialog/dialog.scss rename to ui/components/ui/dialog/dialog.scss diff --git a/ui/app/components/ui/dialog/index.js b/ui/components/ui/dialog/index.js similarity index 100% rename from ui/app/components/ui/dialog/index.js rename to ui/components/ui/dialog/index.js diff --git a/ui/app/components/ui/dropdown/dropdown.js b/ui/components/ui/dropdown/dropdown.js similarity index 100% rename from ui/app/components/ui/dropdown/dropdown.js rename to ui/components/ui/dropdown/dropdown.js diff --git a/ui/app/components/ui/dropdown/dropdown.scss b/ui/components/ui/dropdown/dropdown.scss similarity index 100% rename from ui/app/components/ui/dropdown/dropdown.scss rename to ui/components/ui/dropdown/dropdown.scss diff --git a/ui/app/components/ui/dropdown/dropdown.stories.js b/ui/components/ui/dropdown/dropdown.stories.js similarity index 100% rename from ui/app/components/ui/dropdown/dropdown.stories.js rename to ui/components/ui/dropdown/dropdown.stories.js diff --git a/ui/app/components/ui/dropdown/index.js b/ui/components/ui/dropdown/index.js similarity index 100% rename from ui/app/components/ui/dropdown/index.js rename to ui/components/ui/dropdown/index.js diff --git a/ui/app/components/ui/editable-label/editable-label.js b/ui/components/ui/editable-label/editable-label.js similarity index 100% rename from ui/app/components/ui/editable-label/editable-label.js rename to ui/components/ui/editable-label/editable-label.js diff --git a/ui/app/components/ui/editable-label/index.js b/ui/components/ui/editable-label/index.js similarity index 100% rename from ui/app/components/ui/editable-label/index.js rename to ui/components/ui/editable-label/index.js diff --git a/ui/app/components/ui/editable-label/index.scss b/ui/components/ui/editable-label/index.scss similarity index 100% rename from ui/app/components/ui/editable-label/index.scss rename to ui/components/ui/editable-label/index.scss diff --git a/ui/app/components/ui/error-message/error-message.component.js b/ui/components/ui/error-message/error-message.component.js similarity index 82% rename from ui/app/components/ui/error-message/error-message.component.js rename to ui/components/ui/error-message/error-message.component.js index 399c7c24c..542ecc47b 100644 --- a/ui/app/components/ui/error-message/error-message.component.js +++ b/ui/components/ui/error-message/error-message.component.js @@ -7,7 +7,11 @@ const ErrorMessage = (props, context) => { return ( <div className="error-message"> - <img src="/images/alert-red.svg" alt="" className="error-message__icon" /> + <img + src="./images/alert-red.svg" + alt="" + className="error-message__icon" + /> <div className="error-message__text">{`ALERT: ${error}`}</div> </div> ); diff --git a/ui/app/components/ui/error-message/error-message.component.test.js b/ui/components/ui/error-message/error-message.component.test.js similarity index 100% rename from ui/app/components/ui/error-message/error-message.component.test.js rename to ui/components/ui/error-message/error-message.component.test.js diff --git a/ui/app/components/ui/error-message/index.js b/ui/components/ui/error-message/index.js similarity index 100% rename from ui/app/components/ui/error-message/index.js rename to ui/components/ui/error-message/index.js diff --git a/ui/app/components/ui/error-message/index.scss b/ui/components/ui/error-message/index.scss similarity index 100% rename from ui/app/components/ui/error-message/index.scss rename to ui/components/ui/error-message/index.scss diff --git a/ui/app/components/ui/export-text-container/export-text-container.component.js b/ui/components/ui/export-text-container/export-text-container.component.js similarity index 100% rename from ui/app/components/ui/export-text-container/export-text-container.component.js rename to ui/components/ui/export-text-container/export-text-container.component.js diff --git a/ui/app/components/ui/export-text-container/index.js b/ui/components/ui/export-text-container/index.js similarity index 100% rename from ui/app/components/ui/export-text-container/index.js rename to ui/components/ui/export-text-container/index.js diff --git a/ui/app/components/ui/export-text-container/index.scss b/ui/components/ui/export-text-container/index.scss similarity index 100% rename from ui/app/components/ui/export-text-container/index.scss rename to ui/components/ui/export-text-container/index.scss diff --git a/ui/app/components/ui/hex-to-decimal/hex-to-decimal.component.js b/ui/components/ui/hex-to-decimal/hex-to-decimal.component.js similarity index 100% rename from ui/app/components/ui/hex-to-decimal/hex-to-decimal.component.js rename to ui/components/ui/hex-to-decimal/hex-to-decimal.component.js diff --git a/ui/app/components/ui/hex-to-decimal/hex-to-decimal.component.test.js b/ui/components/ui/hex-to-decimal/hex-to-decimal.component.test.js similarity index 100% rename from ui/app/components/ui/hex-to-decimal/hex-to-decimal.component.test.js rename to ui/components/ui/hex-to-decimal/hex-to-decimal.component.test.js diff --git a/ui/app/components/ui/hex-to-decimal/index.js b/ui/components/ui/hex-to-decimal/index.js similarity index 100% rename from ui/app/components/ui/hex-to-decimal/index.js rename to ui/components/ui/hex-to-decimal/index.js diff --git a/ui/app/components/ui/icon-border/icon-border.js b/ui/components/ui/icon-border/icon-border.js similarity index 100% rename from ui/app/components/ui/icon-border/icon-border.js rename to ui/components/ui/icon-border/icon-border.js diff --git a/ui/app/components/ui/icon-border/icon-border.scss b/ui/components/ui/icon-border/icon-border.scss similarity index 100% rename from ui/app/components/ui/icon-border/icon-border.scss rename to ui/components/ui/icon-border/icon-border.scss diff --git a/ui/app/components/ui/icon-border/index.js b/ui/components/ui/icon-border/index.js similarity index 100% rename from ui/app/components/ui/icon-border/index.js rename to ui/components/ui/icon-border/index.js diff --git a/ui/app/components/ui/icon-button/icon-button.js b/ui/components/ui/icon-button/icon-button.js similarity index 100% rename from ui/app/components/ui/icon-button/icon-button.js rename to ui/components/ui/icon-button/icon-button.js diff --git a/ui/app/components/ui/icon-button/icon-button.scss b/ui/components/ui/icon-button/icon-button.scss similarity index 100% rename from ui/app/components/ui/icon-button/icon-button.scss rename to ui/components/ui/icon-button/icon-button.scss diff --git a/ui/app/components/ui/icon-button/index.js b/ui/components/ui/icon-button/index.js similarity index 100% rename from ui/app/components/ui/icon-button/index.js rename to ui/components/ui/icon-button/index.js diff --git a/ui/app/components/ui/icon-with-fallback/icon-with-fallback.component.js b/ui/components/ui/icon-with-fallback/icon-with-fallback.component.js similarity index 100% rename from ui/app/components/ui/icon-with-fallback/icon-with-fallback.component.js rename to ui/components/ui/icon-with-fallback/icon-with-fallback.component.js diff --git a/ui/app/components/ui/icon-with-fallback/icon-with-fallback.scss b/ui/components/ui/icon-with-fallback/icon-with-fallback.scss similarity index 100% rename from ui/app/components/ui/icon-with-fallback/icon-with-fallback.scss rename to ui/components/ui/icon-with-fallback/icon-with-fallback.scss diff --git a/ui/app/components/ui/icon-with-fallback/index.js b/ui/components/ui/icon-with-fallback/index.js similarity index 100% rename from ui/app/components/ui/icon-with-fallback/index.js rename to ui/components/ui/icon-with-fallback/index.js diff --git a/ui/app/components/ui/icon-with-label/icon-with-label.js b/ui/components/ui/icon-with-label/icon-with-label.js similarity index 100% rename from ui/app/components/ui/icon-with-label/icon-with-label.js rename to ui/components/ui/icon-with-label/icon-with-label.js diff --git a/ui/app/components/ui/icon-with-label/index.js b/ui/components/ui/icon-with-label/index.js similarity index 100% rename from ui/app/components/ui/icon-with-label/index.js rename to ui/components/ui/icon-with-label/index.js diff --git a/ui/app/components/ui/icon-with-label/index.scss b/ui/components/ui/icon-with-label/index.scss similarity index 100% rename from ui/app/components/ui/icon-with-label/index.scss rename to ui/components/ui/icon-with-label/index.scss diff --git a/ui/app/components/ui/icon/approve-icon.component.js b/ui/components/ui/icon/approve-icon.component.js similarity index 100% rename from ui/app/components/ui/icon/approve-icon.component.js rename to ui/components/ui/icon/approve-icon.component.js diff --git a/ui/app/components/ui/icon/copy-icon.component.js b/ui/components/ui/icon/copy-icon.component.js similarity index 100% rename from ui/app/components/ui/icon/copy-icon.component.js rename to ui/components/ui/icon/copy-icon.component.js diff --git a/ui/app/components/ui/icon/icon.stories.js b/ui/components/ui/icon/icon.stories.js similarity index 100% rename from ui/app/components/ui/icon/icon.stories.js rename to ui/components/ui/icon/icon.stories.js diff --git a/ui/app/components/ui/icon/index.scss b/ui/components/ui/icon/index.scss similarity index 100% rename from ui/app/components/ui/icon/index.scss rename to ui/components/ui/icon/index.scss diff --git a/ui/app/components/ui/icon/info-icon-inverted.component.js b/ui/components/ui/icon/info-icon-inverted.component.js similarity index 100% rename from ui/app/components/ui/icon/info-icon-inverted.component.js rename to ui/components/ui/icon/info-icon-inverted.component.js diff --git a/ui/app/components/ui/icon/info-icon.component.js b/ui/components/ui/icon/info-icon.component.js similarity index 100% rename from ui/app/components/ui/icon/info-icon.component.js rename to ui/components/ui/icon/info-icon.component.js diff --git a/ui/app/components/ui/icon/interaction-icon.component.js b/ui/components/ui/icon/interaction-icon.component.js similarity index 100% rename from ui/app/components/ui/icon/interaction-icon.component.js rename to ui/components/ui/icon/interaction-icon.component.js diff --git a/ui/app/components/ui/icon/overview-buy-icon.component.js b/ui/components/ui/icon/overview-buy-icon.component.js similarity index 100% rename from ui/app/components/ui/icon/overview-buy-icon.component.js rename to ui/components/ui/icon/overview-buy-icon.component.js diff --git a/ui/app/components/ui/icon/overview-send-icon.component.js b/ui/components/ui/icon/overview-send-icon.component.js similarity index 100% rename from ui/app/components/ui/icon/overview-send-icon.component.js rename to ui/components/ui/icon/overview-send-icon.component.js diff --git a/ui/app/components/ui/icon/paper-airplane-icon.js b/ui/components/ui/icon/paper-airplane-icon.js similarity index 100% rename from ui/app/components/ui/icon/paper-airplane-icon.js rename to ui/components/ui/icon/paper-airplane-icon.js diff --git a/ui/app/components/ui/icon/preloader/index.js b/ui/components/ui/icon/preloader/index.js similarity index 100% rename from ui/app/components/ui/icon/preloader/index.js rename to ui/components/ui/icon/preloader/index.js diff --git a/ui/app/components/ui/icon/preloader/index.scss b/ui/components/ui/icon/preloader/index.scss similarity index 100% rename from ui/app/components/ui/icon/preloader/index.scss rename to ui/components/ui/icon/preloader/index.scss diff --git a/ui/app/components/ui/icon/preloader/preloader-icon.component.js b/ui/components/ui/icon/preloader/preloader-icon.component.js similarity index 100% rename from ui/app/components/ui/icon/preloader/preloader-icon.component.js rename to ui/components/ui/icon/preloader/preloader-icon.component.js diff --git a/ui/app/components/ui/icon/receive-icon.component.js b/ui/components/ui/icon/receive-icon.component.js similarity index 100% rename from ui/app/components/ui/icon/receive-icon.component.js rename to ui/components/ui/icon/receive-icon.component.js diff --git a/ui/app/components/ui/icon/send-icon.component.js b/ui/components/ui/icon/send-icon.component.js similarity index 100% rename from ui/app/components/ui/icon/send-icon.component.js rename to ui/components/ui/icon/send-icon.component.js diff --git a/ui/app/components/ui/icon/sign-icon.component.js b/ui/components/ui/icon/sign-icon.component.js similarity index 100% rename from ui/app/components/ui/icon/sign-icon.component.js rename to ui/components/ui/icon/sign-icon.component.js diff --git a/ui/app/components/ui/icon/sun-check-icon.component.js b/ui/components/ui/icon/sun-check-icon.component.js similarity index 100% rename from ui/app/components/ui/icon/sun-check-icon.component.js rename to ui/components/ui/icon/sun-check-icon.component.js diff --git a/ui/app/components/ui/icon/swap-icon-for-list.component.js b/ui/components/ui/icon/swap-icon-for-list.component.js similarity index 100% rename from ui/app/components/ui/icon/swap-icon-for-list.component.js rename to ui/components/ui/icon/swap-icon-for-list.component.js diff --git a/ui/app/components/ui/icon/swap-icon.component.js b/ui/components/ui/icon/swap-icon.component.js similarity index 100% rename from ui/app/components/ui/icon/swap-icon.component.js rename to ui/components/ui/icon/swap-icon.component.js diff --git a/ui/app/components/ui/identicon/blockieIdenticon/blockieIdenticon.component.js b/ui/components/ui/identicon/blockieIdenticon/blockieIdenticon.component.js similarity index 100% rename from ui/app/components/ui/identicon/blockieIdenticon/blockieIdenticon.component.js rename to ui/components/ui/identicon/blockieIdenticon/blockieIdenticon.component.js diff --git a/ui/app/components/ui/identicon/blockieIdenticon/index.js b/ui/components/ui/identicon/blockieIdenticon/index.js similarity index 100% rename from ui/app/components/ui/identicon/blockieIdenticon/index.js rename to ui/components/ui/identicon/blockieIdenticon/index.js diff --git a/ui/app/components/ui/identicon/identicon.component.js b/ui/components/ui/identicon/identicon.component.js similarity index 96% rename from ui/app/components/ui/identicon/identicon.component.js rename to ui/components/ui/identicon/identicon.component.js index 64a03ea01..dd6eb5beb 100644 --- a/ui/app/components/ui/identicon/identicon.component.js +++ b/ui/components/ui/identicon/identicon.component.js @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import contractMap from '@metamask/contract-metadata'; -import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import Jazzicon from '../jazzicon'; import BlockieIdenticon from './blockieIdenticon'; diff --git a/ui/app/components/ui/identicon/identicon.component.test.js b/ui/components/ui/identicon/identicon.component.test.js similarity index 100% rename from ui/app/components/ui/identicon/identicon.component.test.js rename to ui/components/ui/identicon/identicon.component.test.js diff --git a/ui/app/components/ui/identicon/identicon.container.js b/ui/components/ui/identicon/identicon.container.js similarity index 100% rename from ui/app/components/ui/identicon/identicon.container.js rename to ui/components/ui/identicon/identicon.container.js diff --git a/ui/app/components/ui/identicon/identicon.stories.js b/ui/components/ui/identicon/identicon.stories.js similarity index 100% rename from ui/app/components/ui/identicon/identicon.stories.js rename to ui/components/ui/identicon/identicon.stories.js diff --git a/ui/app/components/ui/identicon/index.js b/ui/components/ui/identicon/index.js similarity index 100% rename from ui/app/components/ui/identicon/index.js rename to ui/components/ui/identicon/index.js diff --git a/ui/app/components/ui/identicon/index.scss b/ui/components/ui/identicon/index.scss similarity index 100% rename from ui/app/components/ui/identicon/index.scss rename to ui/components/ui/identicon/index.scss diff --git a/ui/app/components/ui/info-tooltip/index.js b/ui/components/ui/info-tooltip/index.js similarity index 100% rename from ui/app/components/ui/info-tooltip/index.js rename to ui/components/ui/info-tooltip/index.js diff --git a/ui/app/components/ui/info-tooltip/index.scss b/ui/components/ui/info-tooltip/index.scss similarity index 100% rename from ui/app/components/ui/info-tooltip/index.scss rename to ui/components/ui/info-tooltip/index.scss diff --git a/ui/app/components/ui/info-tooltip/info-tooltip.js b/ui/components/ui/info-tooltip/info-tooltip.js similarity index 100% rename from ui/app/components/ui/info-tooltip/info-tooltip.js rename to ui/components/ui/info-tooltip/info-tooltip.js diff --git a/ui/app/components/ui/info-tooltip/info-tooltip.stories.js b/ui/components/ui/info-tooltip/info-tooltip.stories.js similarity index 100% rename from ui/app/components/ui/info-tooltip/info-tooltip.stories.js rename to ui/components/ui/info-tooltip/info-tooltip.stories.js diff --git a/ui/app/components/ui/jazzicon/index.js b/ui/components/ui/jazzicon/index.js similarity index 100% rename from ui/app/components/ui/jazzicon/index.js rename to ui/components/ui/jazzicon/index.js diff --git a/ui/app/components/ui/jazzicon/jazzicon.component.js b/ui/components/ui/jazzicon/jazzicon.component.js similarity index 95% rename from ui/app/components/ui/jazzicon/jazzicon.component.js rename to ui/components/ui/jazzicon/jazzicon.component.js index 5d1953009..b0a35cb6f 100644 --- a/ui/app/components/ui/jazzicon/jazzicon.component.js +++ b/ui/components/ui/jazzicon/jazzicon.component.js @@ -1,7 +1,7 @@ import React, { createRef, PureComponent } from 'react'; import PropTypes from 'prop-types'; import jazzicon from '@metamask/jazzicon'; -import iconFactoryGenerator from '../../../../lib/icon-factory'; +import iconFactoryGenerator from '../../../helpers/utils/icon-factory'; const iconFactory = iconFactoryGenerator(jazzicon); diff --git a/ui/app/components/ui/list-item/index.js b/ui/components/ui/list-item/index.js similarity index 100% rename from ui/app/components/ui/list-item/index.js rename to ui/components/ui/list-item/index.js diff --git a/ui/app/components/ui/list-item/index.scss b/ui/components/ui/list-item/index.scss similarity index 100% rename from ui/app/components/ui/list-item/index.scss rename to ui/components/ui/list-item/index.scss diff --git a/ui/app/components/ui/list-item/list-item.component.js b/ui/components/ui/list-item/list-item.component.js similarity index 100% rename from ui/app/components/ui/list-item/list-item.component.js rename to ui/components/ui/list-item/list-item.component.js diff --git a/ui/app/components/ui/list-item/list-item.component.test.js b/ui/components/ui/list-item/list-item.component.test.js similarity index 100% rename from ui/app/components/ui/list-item/list-item.component.test.js rename to ui/components/ui/list-item/list-item.component.test.js diff --git a/ui/app/components/ui/list-item/list-item.stories.js b/ui/components/ui/list-item/list-item.stories.js similarity index 100% rename from ui/app/components/ui/list-item/list-item.stories.js rename to ui/components/ui/list-item/list-item.stories.js diff --git a/ui/app/components/ui/loading-indicator/index.js b/ui/components/ui/loading-indicator/index.js similarity index 100% rename from ui/app/components/ui/loading-indicator/index.js rename to ui/components/ui/loading-indicator/index.js diff --git a/ui/app/components/ui/loading-indicator/loading-indicator.js b/ui/components/ui/loading-indicator/loading-indicator.js similarity index 100% rename from ui/app/components/ui/loading-indicator/loading-indicator.js rename to ui/components/ui/loading-indicator/loading-indicator.js diff --git a/ui/app/components/ui/loading-indicator/loading-indicator.scss b/ui/components/ui/loading-indicator/loading-indicator.scss similarity index 100% rename from ui/app/components/ui/loading-indicator/loading-indicator.scss rename to ui/components/ui/loading-indicator/loading-indicator.scss diff --git a/ui/app/components/ui/loading-screen/index.js b/ui/components/ui/loading-screen/index.js similarity index 100% rename from ui/app/components/ui/loading-screen/index.js rename to ui/components/ui/loading-screen/index.js diff --git a/ui/app/components/ui/loading-screen/index.scss b/ui/components/ui/loading-screen/index.scss similarity index 100% rename from ui/app/components/ui/loading-screen/index.scss rename to ui/components/ui/loading-screen/index.scss diff --git a/ui/app/components/ui/loading-screen/loading-screen.component.js b/ui/components/ui/loading-screen/loading-screen.component.js similarity index 100% rename from ui/app/components/ui/loading-screen/loading-screen.component.js rename to ui/components/ui/loading-screen/loading-screen.component.js diff --git a/ui/app/components/ui/lock-icon/index.js b/ui/components/ui/lock-icon/index.js similarity index 100% rename from ui/app/components/ui/lock-icon/index.js rename to ui/components/ui/lock-icon/index.js diff --git a/ui/app/components/ui/lock-icon/lock-icon.component.js b/ui/components/ui/lock-icon/lock-icon.component.js similarity index 100% rename from ui/app/components/ui/lock-icon/lock-icon.component.js rename to ui/components/ui/lock-icon/lock-icon.component.js diff --git a/ui/app/components/ui/mascot/index.js b/ui/components/ui/mascot/index.js similarity index 100% rename from ui/app/components/ui/mascot/index.js rename to ui/components/ui/mascot/index.js diff --git a/ui/app/components/ui/mascot/mascot.component.js b/ui/components/ui/mascot/mascot.component.js similarity index 100% rename from ui/app/components/ui/mascot/mascot.component.js rename to ui/components/ui/mascot/mascot.component.js diff --git a/ui/app/components/ui/mascot/mascot.stories.js b/ui/components/ui/mascot/mascot.stories.js similarity index 100% rename from ui/app/components/ui/mascot/mascot.stories.js rename to ui/components/ui/mascot/mascot.stories.js diff --git a/ui/app/components/ui/menu/index.js b/ui/components/ui/menu/index.js similarity index 100% rename from ui/app/components/ui/menu/index.js rename to ui/components/ui/menu/index.js diff --git a/ui/app/components/ui/menu/menu-item.js b/ui/components/ui/menu/menu-item.js similarity index 100% rename from ui/app/components/ui/menu/menu-item.js rename to ui/components/ui/menu/menu-item.js diff --git a/ui/app/components/ui/menu/menu.js b/ui/components/ui/menu/menu.js similarity index 100% rename from ui/app/components/ui/menu/menu.js rename to ui/components/ui/menu/menu.js diff --git a/ui/app/components/ui/menu/menu.scss b/ui/components/ui/menu/menu.scss similarity index 100% rename from ui/app/components/ui/menu/menu.scss rename to ui/components/ui/menu/menu.scss diff --git a/ui/app/components/ui/menu/menu.stories.js b/ui/components/ui/menu/menu.stories.js similarity index 100% rename from ui/app/components/ui/menu/menu.stories.js rename to ui/components/ui/menu/menu.stories.js diff --git a/ui/app/components/ui/metafox-logo/index.js b/ui/components/ui/metafox-logo/index.js similarity index 100% rename from ui/app/components/ui/metafox-logo/index.js rename to ui/components/ui/metafox-logo/index.js diff --git a/ui/app/components/ui/metafox-logo/metafox-logo.component.js b/ui/components/ui/metafox-logo/metafox-logo.component.js similarity index 91% rename from ui/app/components/ui/metafox-logo/metafox-logo.component.js rename to ui/components/ui/metafox-logo/metafox-logo.component.js index 363bf422c..2b0b36c87 100644 --- a/ui/app/components/ui/metafox-logo/metafox-logo.component.js +++ b/ui/components/ui/metafox-logo/metafox-logo.component.js @@ -25,7 +25,7 @@ export default class MetaFoxLogo extends PureComponent { > <img height="30" - src="/images/logo/metamask-logo-horizontal.svg" + src="./images/logo/metamask-logo-horizontal.svg" className={classnames( 'app-header__metafox-logo', 'app-header__metafox-logo--horizontal', @@ -34,7 +34,7 @@ export default class MetaFoxLogo extends PureComponent { /> <img {...iconProps} - src="/images/logo/metamask-fox.svg" + src="./images/logo/metamask-fox.svg" className={classnames( 'app-header__metafox-logo', 'app-header__metafox-logo--icon', diff --git a/ui/app/components/ui/metafox-logo/metafox-logo.component.test.js b/ui/components/ui/metafox-logo/metafox-logo.component.test.js similarity index 100% rename from ui/app/components/ui/metafox-logo/metafox-logo.component.test.js rename to ui/components/ui/metafox-logo/metafox-logo.component.test.js diff --git a/ui/app/components/ui/page-container/index.js b/ui/components/ui/page-container/index.js similarity index 100% rename from ui/app/components/ui/page-container/index.js rename to ui/components/ui/page-container/index.js diff --git a/ui/app/components/ui/page-container/index.scss b/ui/components/ui/page-container/index.scss similarity index 100% rename from ui/app/components/ui/page-container/index.scss rename to ui/components/ui/page-container/index.scss diff --git a/ui/app/components/ui/page-container/page-container-content.component.js b/ui/components/ui/page-container/page-container-content.component.js similarity index 100% rename from ui/app/components/ui/page-container/page-container-content.component.js rename to ui/components/ui/page-container/page-container-content.component.js diff --git a/ui/app/components/ui/page-container/page-container-footer/index.js b/ui/components/ui/page-container/page-container-footer/index.js similarity index 100% rename from ui/app/components/ui/page-container/page-container-footer/index.js rename to ui/components/ui/page-container/page-container-footer/index.js diff --git a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js b/ui/components/ui/page-container/page-container-footer/page-container-footer.component.js similarity index 100% rename from ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.js rename to ui/components/ui/page-container/page-container-footer/page-container-footer.component.js diff --git a/ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.test.js b/ui/components/ui/page-container/page-container-footer/page-container-footer.component.test.js similarity index 100% rename from ui/app/components/ui/page-container/page-container-footer/page-container-footer.component.test.js rename to ui/components/ui/page-container/page-container-footer/page-container-footer.component.test.js diff --git a/ui/app/components/ui/page-container/page-container-header/index.js b/ui/components/ui/page-container/page-container-header/index.js similarity index 100% rename from ui/app/components/ui/page-container/page-container-header/index.js rename to ui/components/ui/page-container/page-container-header/index.js diff --git a/ui/app/components/ui/page-container/page-container-header/page-container-header.component.js b/ui/components/ui/page-container/page-container-header/page-container-header.component.js similarity index 100% rename from ui/app/components/ui/page-container/page-container-header/page-container-header.component.js rename to ui/components/ui/page-container/page-container-header/page-container-header.component.js diff --git a/ui/app/components/ui/page-container/page-container-header/page-container-header.component.test.js b/ui/components/ui/page-container/page-container-header/page-container-header.component.test.js similarity index 100% rename from ui/app/components/ui/page-container/page-container-header/page-container-header.component.test.js rename to ui/components/ui/page-container/page-container-header/page-container-header.component.test.js diff --git a/ui/app/components/ui/page-container/page-container.component.js b/ui/components/ui/page-container/page-container.component.js similarity index 100% rename from ui/app/components/ui/page-container/page-container.component.js rename to ui/components/ui/page-container/page-container.component.js diff --git a/ui/app/components/ui/popover/index.js b/ui/components/ui/popover/index.js similarity index 100% rename from ui/app/components/ui/popover/index.js rename to ui/components/ui/popover/index.js diff --git a/ui/app/components/ui/popover/index.scss b/ui/components/ui/popover/index.scss similarity index 100% rename from ui/app/components/ui/popover/index.scss rename to ui/components/ui/popover/index.scss diff --git a/ui/app/components/ui/popover/popover.component.js b/ui/components/ui/popover/popover.component.js similarity index 100% rename from ui/app/components/ui/popover/popover.component.js rename to ui/components/ui/popover/popover.component.js diff --git a/ui/app/components/ui/popover/popover.stories.js b/ui/components/ui/popover/popover.stories.js similarity index 100% rename from ui/app/components/ui/popover/popover.stories.js rename to ui/components/ui/popover/popover.stories.js diff --git a/ui/app/components/ui/pulse-loader/index.js b/ui/components/ui/pulse-loader/index.js similarity index 100% rename from ui/app/components/ui/pulse-loader/index.js rename to ui/components/ui/pulse-loader/index.js diff --git a/ui/app/components/ui/pulse-loader/index.scss b/ui/components/ui/pulse-loader/index.scss similarity index 100% rename from ui/app/components/ui/pulse-loader/index.scss rename to ui/components/ui/pulse-loader/index.scss diff --git a/ui/app/components/ui/pulse-loader/pulse-loader.js b/ui/components/ui/pulse-loader/pulse-loader.js similarity index 100% rename from ui/app/components/ui/pulse-loader/pulse-loader.js rename to ui/components/ui/pulse-loader/pulse-loader.js diff --git a/ui/app/components/ui/pulse-loader/pulse-loader.stories.js b/ui/components/ui/pulse-loader/pulse-loader.stories.js similarity index 100% rename from ui/app/components/ui/pulse-loader/pulse-loader.stories.js rename to ui/components/ui/pulse-loader/pulse-loader.stories.js diff --git a/ui/app/components/ui/qr-code/index.js b/ui/components/ui/qr-code/index.js similarity index 100% rename from ui/app/components/ui/qr-code/index.js rename to ui/components/ui/qr-code/index.js diff --git a/ui/app/components/ui/qr-code/index.scss b/ui/components/ui/qr-code/index.scss similarity index 100% rename from ui/app/components/ui/qr-code/index.scss rename to ui/components/ui/qr-code/index.scss diff --git a/ui/app/components/ui/qr-code/qr-code.js b/ui/components/ui/qr-code/qr-code.js similarity index 95% rename from ui/app/components/ui/qr-code/qr-code.js rename to ui/components/ui/qr-code/qr-code.js index ae43dc49b..db0eeed2c 100644 --- a/ui/app/components/ui/qr-code/qr-code.js +++ b/ui/components/ui/qr-code/qr-code.js @@ -4,7 +4,7 @@ import qrCode from 'qrcode-generator'; import { connect } from 'react-redux'; import { isHexPrefixed } from 'ethereumjs-util'; import ReadOnlyInput from '../readonly-input/readonly-input'; -import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; export default connect(mapStateToProps)(QrCodeView); diff --git a/ui/app/components/ui/readonly-input/index.js b/ui/components/ui/readonly-input/index.js similarity index 100% rename from ui/app/components/ui/readonly-input/index.js rename to ui/components/ui/readonly-input/index.js diff --git a/ui/app/components/ui/readonly-input/index.scss b/ui/components/ui/readonly-input/index.scss similarity index 100% rename from ui/app/components/ui/readonly-input/index.scss rename to ui/components/ui/readonly-input/index.scss diff --git a/ui/app/components/ui/readonly-input/readonly-input.js b/ui/components/ui/readonly-input/readonly-input.js similarity index 100% rename from ui/app/components/ui/readonly-input/readonly-input.js rename to ui/components/ui/readonly-input/readonly-input.js diff --git a/ui/app/components/ui/search-icon/index.js b/ui/components/ui/search-icon/index.js similarity index 100% rename from ui/app/components/ui/search-icon/index.js rename to ui/components/ui/search-icon/index.js diff --git a/ui/app/components/ui/search-icon/search-icon.component.js b/ui/components/ui/search-icon/search-icon.component.js similarity index 100% rename from ui/app/components/ui/search-icon/search-icon.component.js rename to ui/components/ui/search-icon/search-icon.component.js diff --git a/ui/app/components/ui/sender-to-recipient/index.js b/ui/components/ui/sender-to-recipient/index.js similarity index 100% rename from ui/app/components/ui/sender-to-recipient/index.js rename to ui/components/ui/sender-to-recipient/index.js diff --git a/ui/app/components/ui/sender-to-recipient/index.scss b/ui/components/ui/sender-to-recipient/index.scss similarity index 100% rename from ui/app/components/ui/sender-to-recipient/index.scss rename to ui/components/ui/sender-to-recipient/index.scss diff --git a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js b/ui/components/ui/sender-to-recipient/sender-to-recipient.component.js similarity index 98% rename from ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js rename to ui/components/ui/sender-to-recipient/sender-to-recipient.component.js index 69db31e1d..30e42e46f 100644 --- a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.component.js +++ b/ui/components/ui/sender-to-recipient/sender-to-recipient.component.js @@ -7,7 +7,7 @@ import Identicon from '../identicon'; import { shortenAddress } from '../../../helpers/utils/util'; import AccountMismatchWarning from '../account-mismatch-warning/account-mismatch-warning.component'; import { useI18nContext } from '../../../hooks/useI18nContext'; -import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; +import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; import { DEFAULT_VARIANT, CARDS_VARIANT, diff --git a/ui/app/components/ui/sender-to-recipient/sender-to-recipient.constants.js b/ui/components/ui/sender-to-recipient/sender-to-recipient.constants.js similarity index 100% rename from ui/app/components/ui/sender-to-recipient/sender-to-recipient.constants.js rename to ui/components/ui/sender-to-recipient/sender-to-recipient.constants.js diff --git a/ui/app/components/ui/site-icon/index.js b/ui/components/ui/site-icon/index.js similarity index 100% rename from ui/app/components/ui/site-icon/index.js rename to ui/components/ui/site-icon/index.js diff --git a/ui/app/components/ui/site-icon/site-icon.js b/ui/components/ui/site-icon/site-icon.js similarity index 100% rename from ui/app/components/ui/site-icon/site-icon.js rename to ui/components/ui/site-icon/site-icon.js diff --git a/ui/app/components/ui/snackbar/index.js b/ui/components/ui/snackbar/index.js similarity index 100% rename from ui/app/components/ui/snackbar/index.js rename to ui/components/ui/snackbar/index.js diff --git a/ui/app/components/ui/snackbar/index.scss b/ui/components/ui/snackbar/index.scss similarity index 100% rename from ui/app/components/ui/snackbar/index.scss rename to ui/components/ui/snackbar/index.scss diff --git a/ui/app/components/ui/snackbar/snackbar.component.js b/ui/components/ui/snackbar/snackbar.component.js similarity index 100% rename from ui/app/components/ui/snackbar/snackbar.component.js rename to ui/components/ui/snackbar/snackbar.component.js diff --git a/ui/app/components/ui/spinner/index.js b/ui/components/ui/spinner/index.js similarity index 100% rename from ui/app/components/ui/spinner/index.js rename to ui/components/ui/spinner/index.js diff --git a/ui/app/components/ui/spinner/spinner.component.js b/ui/components/ui/spinner/spinner.component.js similarity index 100% rename from ui/app/components/ui/spinner/spinner.component.js rename to ui/components/ui/spinner/spinner.component.js diff --git a/ui/app/components/ui/tabs/index.js b/ui/components/ui/tabs/index.js similarity index 100% rename from ui/app/components/ui/tabs/index.js rename to ui/components/ui/tabs/index.js diff --git a/ui/app/components/ui/tabs/index.scss b/ui/components/ui/tabs/index.scss similarity index 100% rename from ui/app/components/ui/tabs/index.scss rename to ui/components/ui/tabs/index.scss diff --git a/ui/app/components/ui/tabs/tab/index.js b/ui/components/ui/tabs/tab/index.js similarity index 100% rename from ui/app/components/ui/tabs/tab/index.js rename to ui/components/ui/tabs/tab/index.js diff --git a/ui/app/components/ui/tabs/tab/index.scss b/ui/components/ui/tabs/tab/index.scss similarity index 100% rename from ui/app/components/ui/tabs/tab/index.scss rename to ui/components/ui/tabs/tab/index.scss diff --git a/ui/app/components/ui/tabs/tab/tab.component.js b/ui/components/ui/tabs/tab/tab.component.js similarity index 100% rename from ui/app/components/ui/tabs/tab/tab.component.js rename to ui/components/ui/tabs/tab/tab.component.js diff --git a/ui/app/components/ui/tabs/tabs.component.js b/ui/components/ui/tabs/tabs.component.js similarity index 100% rename from ui/app/components/ui/tabs/tabs.component.js rename to ui/components/ui/tabs/tabs.component.js diff --git a/ui/app/components/ui/tabs/tabs.stories.js b/ui/components/ui/tabs/tabs.stories.js similarity index 100% rename from ui/app/components/ui/tabs/tabs.stories.js rename to ui/components/ui/tabs/tabs.stories.js diff --git a/ui/app/components/ui/text-field/index.js b/ui/components/ui/text-field/index.js similarity index 100% rename from ui/app/components/ui/text-field/index.js rename to ui/components/ui/text-field/index.js diff --git a/ui/app/components/ui/text-field/text-field.component.js b/ui/components/ui/text-field/text-field.component.js similarity index 100% rename from ui/app/components/ui/text-field/text-field.component.js rename to ui/components/ui/text-field/text-field.component.js diff --git a/ui/app/components/ui/text-field/text-field.stories.js b/ui/components/ui/text-field/text-field.stories.js similarity index 100% rename from ui/app/components/ui/text-field/text-field.stories.js rename to ui/components/ui/text-field/text-field.stories.js diff --git a/ui/app/components/ui/toggle-button/index.js b/ui/components/ui/toggle-button/index.js similarity index 100% rename from ui/app/components/ui/toggle-button/index.js rename to ui/components/ui/toggle-button/index.js diff --git a/ui/app/components/ui/toggle-button/index.scss b/ui/components/ui/toggle-button/index.scss similarity index 100% rename from ui/app/components/ui/toggle-button/index.scss rename to ui/components/ui/toggle-button/index.scss diff --git a/ui/app/components/ui/toggle-button/toggle-button.component.js b/ui/components/ui/toggle-button/toggle-button.component.js similarity index 100% rename from ui/app/components/ui/toggle-button/toggle-button.component.js rename to ui/components/ui/toggle-button/toggle-button.component.js diff --git a/ui/app/components/ui/token-balance/index.js b/ui/components/ui/token-balance/index.js similarity index 100% rename from ui/app/components/ui/token-balance/index.js rename to ui/components/ui/token-balance/index.js diff --git a/ui/app/components/ui/token-balance/index.scss b/ui/components/ui/token-balance/index.scss similarity index 100% rename from ui/app/components/ui/token-balance/index.scss rename to ui/components/ui/token-balance/index.scss diff --git a/ui/app/components/ui/token-balance/token-balance.js b/ui/components/ui/token-balance/token-balance.js similarity index 100% rename from ui/app/components/ui/token-balance/token-balance.js rename to ui/components/ui/token-balance/token-balance.js diff --git a/ui/app/components/ui/token-currency-display/index.js b/ui/components/ui/token-currency-display/index.js similarity index 100% rename from ui/app/components/ui/token-currency-display/index.js rename to ui/components/ui/token-currency-display/index.js diff --git a/ui/app/components/ui/token-currency-display/token-currency-display.component.js b/ui/components/ui/token-currency-display/token-currency-display.component.js similarity index 100% rename from ui/app/components/ui/token-currency-display/token-currency-display.component.js rename to ui/components/ui/token-currency-display/token-currency-display.component.js diff --git a/ui/app/components/ui/token-input/index.js b/ui/components/ui/token-input/index.js similarity index 100% rename from ui/app/components/ui/token-input/index.js rename to ui/components/ui/token-input/index.js diff --git a/ui/app/components/ui/token-input/token-input.component.js b/ui/components/ui/token-input/token-input.component.js similarity index 98% rename from ui/app/components/ui/token-input/token-input.component.js rename to ui/components/ui/token-input/token-input.component.js index fe7001d4f..af11d86b5 100644 --- a/ui/app/components/ui/token-input/token-input.component.js +++ b/ui/components/ui/token-input/token-input.component.js @@ -8,7 +8,7 @@ import { multiplyCurrencies, } from '../../../helpers/utils/conversion-util'; import { ETH } from '../../../helpers/constants/common'; -import { addHexPrefix } from '../../../../../app/scripts/lib/util'; +import { addHexPrefix } from '../../../../app/scripts/lib/util'; /** * Component that allows user to enter token values as a number, and props receive a converted diff --git a/ui/app/components/ui/token-input/token-input.component.test.js b/ui/components/ui/token-input/token-input.component.test.js similarity index 100% rename from ui/app/components/ui/token-input/token-input.component.test.js rename to ui/components/ui/token-input/token-input.component.test.js diff --git a/ui/app/components/ui/token-input/token-input.container.js b/ui/components/ui/token-input/token-input.container.js similarity index 100% rename from ui/app/components/ui/token-input/token-input.container.js rename to ui/components/ui/token-input/token-input.container.js diff --git a/ui/app/components/ui/tooltip/index.js b/ui/components/ui/tooltip/index.js similarity index 100% rename from ui/app/components/ui/tooltip/index.js rename to ui/components/ui/tooltip/index.js diff --git a/ui/app/components/ui/tooltip/index.scss b/ui/components/ui/tooltip/index.scss similarity index 100% rename from ui/app/components/ui/tooltip/index.scss rename to ui/components/ui/tooltip/index.scss diff --git a/ui/app/components/ui/tooltip/tooltip.js b/ui/components/ui/tooltip/tooltip.js similarity index 100% rename from ui/app/components/ui/tooltip/tooltip.js rename to ui/components/ui/tooltip/tooltip.js diff --git a/ui/app/components/ui/truncated-definition-list/index.js b/ui/components/ui/truncated-definition-list/index.js similarity index 100% rename from ui/app/components/ui/truncated-definition-list/index.js rename to ui/components/ui/truncated-definition-list/index.js diff --git a/ui/app/components/ui/truncated-definition-list/truncated-definition-list.js b/ui/components/ui/truncated-definition-list/truncated-definition-list.js similarity index 100% rename from ui/app/components/ui/truncated-definition-list/truncated-definition-list.js rename to ui/components/ui/truncated-definition-list/truncated-definition-list.js diff --git a/ui/app/components/ui/truncated-definition-list/truncated-definition-list.scss b/ui/components/ui/truncated-definition-list/truncated-definition-list.scss similarity index 100% rename from ui/app/components/ui/truncated-definition-list/truncated-definition-list.scss rename to ui/components/ui/truncated-definition-list/truncated-definition-list.scss diff --git a/ui/app/components/ui/truncated-definition-list/truncated-definition-list.stories.js b/ui/components/ui/truncated-definition-list/truncated-definition-list.stories.js similarity index 100% rename from ui/app/components/ui/truncated-definition-list/truncated-definition-list.stories.js rename to ui/components/ui/truncated-definition-list/truncated-definition-list.stories.js diff --git a/ui/app/components/ui/typography/index.js b/ui/components/ui/typography/index.js similarity index 100% rename from ui/app/components/ui/typography/index.js rename to ui/components/ui/typography/index.js diff --git a/ui/app/components/ui/typography/typography.js b/ui/components/ui/typography/typography.js similarity index 100% rename from ui/app/components/ui/typography/typography.js rename to ui/components/ui/typography/typography.js diff --git a/ui/app/components/ui/typography/typography.scss b/ui/components/ui/typography/typography.scss similarity index 100% rename from ui/app/components/ui/typography/typography.scss rename to ui/components/ui/typography/typography.scss diff --git a/ui/app/components/ui/typography/typography.stories.js b/ui/components/ui/typography/typography.stories.js similarity index 100% rename from ui/app/components/ui/typography/typography.stories.js rename to ui/components/ui/typography/typography.stories.js diff --git a/ui/app/components/ui/ui-components.scss b/ui/components/ui/ui-components.scss similarity index 100% rename from ui/app/components/ui/ui-components.scss rename to ui/components/ui/ui-components.scss diff --git a/ui/app/components/ui/unit-input/index.js b/ui/components/ui/unit-input/index.js similarity index 100% rename from ui/app/components/ui/unit-input/index.js rename to ui/components/ui/unit-input/index.js diff --git a/ui/app/components/ui/unit-input/index.scss b/ui/components/ui/unit-input/index.scss similarity index 100% rename from ui/app/components/ui/unit-input/index.scss rename to ui/components/ui/unit-input/index.scss diff --git a/ui/app/components/ui/unit-input/unit-input.component.js b/ui/components/ui/unit-input/unit-input.component.js similarity index 100% rename from ui/app/components/ui/unit-input/unit-input.component.js rename to ui/components/ui/unit-input/unit-input.component.js diff --git a/ui/app/components/ui/unit-input/unit-input.component.test.js b/ui/components/ui/unit-input/unit-input.component.test.js similarity index 100% rename from ui/app/components/ui/unit-input/unit-input.component.test.js rename to ui/components/ui/unit-input/unit-input.component.test.js diff --git a/ui/app/components/ui/url-icon/index.js b/ui/components/ui/url-icon/index.js similarity index 100% rename from ui/app/components/ui/url-icon/index.js rename to ui/components/ui/url-icon/index.js diff --git a/ui/app/components/ui/url-icon/index.scss b/ui/components/ui/url-icon/index.scss similarity index 100% rename from ui/app/components/ui/url-icon/index.scss rename to ui/components/ui/url-icon/index.scss diff --git a/ui/app/components/ui/url-icon/url-icon.js b/ui/components/ui/url-icon/url-icon.js similarity index 100% rename from ui/app/components/ui/url-icon/url-icon.js rename to ui/components/ui/url-icon/url-icon.js diff --git a/ui/app/contexts/i18n.js b/ui/contexts/i18n.js similarity index 100% rename from ui/app/contexts/i18n.js rename to ui/contexts/i18n.js diff --git a/ui/app/contexts/metametrics.js b/ui/contexts/metametrics.js similarity index 98% rename from ui/app/contexts/metametrics.js rename to ui/contexts/metametrics.js index 5940f1088..7a1cafd80 100644 --- a/ui/app/contexts/metametrics.js +++ b/ui/contexts/metametrics.js @@ -17,7 +17,7 @@ import { } from '../selectors/selectors'; import { getSendToken } from '../selectors/send'; import { txDataSelector } from '../selectors/confirm-transaction'; -import { getEnvironmentType } from '../../../app/scripts/lib/util'; +import { getEnvironmentType } from '../../app/scripts/lib/util'; import { trackMetaMetricsEvent } from '../store/actions'; export const MetaMetricsContext = createContext(() => { diff --git a/ui/app/contexts/metametrics.new.js b/ui/contexts/metametrics.new.js similarity index 91% rename from ui/app/contexts/metametrics.new.js rename to ui/contexts/metametrics.new.js index e46638c13..720fd6ed0 100644 --- a/ui/app/contexts/metametrics.new.js +++ b/ui/contexts/metametrics.new.js @@ -16,7 +16,7 @@ import { matchPath, useLocation, useRouteMatch } from 'react-router-dom'; import { captureException, captureMessage } from '@sentry/browser'; import { omit } from 'lodash'; -import { getEnvironmentType } from '../../../app/scripts/lib/util'; +import { getEnvironmentType } from '../../app/scripts/lib/util'; import { PATH_NAME_MAP } from '../helpers/constants/routes'; import { txDataSelector } from '../selectors'; @@ -24,10 +24,10 @@ import { trackMetaMetricsEvent, trackMetaMetricsPage } from '../store/actions'; // type imports /** - * @typedef {import('../../../shared/constants/metametrics').MetaMetricsEventPayload} MetaMetricsEventPayload - * @typedef {import('../../../shared/constants/metametrics').MetaMetricsEventOptions} MetaMetricsEventOptions - * @typedef {import('../../../shared/constants/metametrics').MetaMetricsPageObject} MetaMetricsPageObject - * @typedef {import('../../../shared/constants/metametrics').MetaMetricsReferrerObject} MetaMetricsReferrerObject + * @typedef {import('../../shared/constants/metametrics').MetaMetricsEventPayload} MetaMetricsEventPayload + * @typedef {import('../../shared/constants/metametrics').MetaMetricsEventOptions} MetaMetricsEventOptions + * @typedef {import('../../shared/constants/metametrics').MetaMetricsPageObject} MetaMetricsPageObject + * @typedef {import('../../shared/constants/metametrics').MetaMetricsReferrerObject} MetaMetricsReferrerObject */ // types diff --git a/ui/app/css/base-styles.scss b/ui/css/base-styles.scss similarity index 78% rename from ui/app/css/base-styles.scss rename to ui/css/base-styles.scss index 4c209ff55..14ffafefc 100644 --- a/ui/app/css/base-styles.scss +++ b/ui/css/base-styles.scss @@ -31,11 +31,11 @@ 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 + /ui/pages/create-account/connect-hardware/index.js + /ui/pages/create-account/import-account/json.js + /ui/pages/create-account/import-account/private-key.js + /ui/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js + /ui/pages/keychains/restore-vault.js */ .error { color: #f7861c; @@ -45,8 +45,8 @@ html { /* 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 + /ui/pages/create-account/import-account/json.js + /ui/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js */ .warning { color: #ffae00; diff --git a/ui/app/css/design-system/attributes.scss b/ui/css/design-system/attributes.scss similarity index 100% rename from ui/app/css/design-system/attributes.scss rename to ui/css/design-system/attributes.scss diff --git a/ui/app/css/design-system/breakpoints.scss b/ui/css/design-system/breakpoints.scss similarity index 100% rename from ui/app/css/design-system/breakpoints.scss rename to ui/css/design-system/breakpoints.scss diff --git a/ui/app/css/design-system/colors.scss b/ui/css/design-system/colors.scss similarity index 100% rename from ui/app/css/design-system/colors.scss rename to ui/css/design-system/colors.scss diff --git a/ui/app/css/design-system/deprecated-colors.scss b/ui/css/design-system/deprecated-colors.scss similarity index 100% rename from ui/app/css/design-system/deprecated-colors.scss rename to ui/css/design-system/deprecated-colors.scss diff --git a/ui/app/css/design-system/index.scss b/ui/css/design-system/index.scss similarity index 100% rename from ui/app/css/design-system/index.scss rename to ui/css/design-system/index.scss diff --git a/ui/app/css/design-system/typography.scss b/ui/css/design-system/typography.scss similarity index 92% rename from ui/app/css/design-system/typography.scss rename to ui/css/design-system/typography.scss index 707170c24..12b7d37ea 100644 --- a/ui/app/css/design-system/typography.scss +++ b/ui/css/design-system/typography.scss @@ -1,8 +1,8 @@ $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'; +@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'; diff --git a/ui/app/css/design-system/z-index.scss b/ui/css/design-system/z-index.scss similarity index 100% rename from ui/app/css/design-system/z-index.scss rename to ui/css/design-system/z-index.scss diff --git a/ui/app/css/index.scss b/ui/css/index.scss similarity index 93% rename from ui/app/css/index.scss rename to ui/css/index.scss index aa2604242..fb0009d89 100644 --- a/ui/app/css/index.scss +++ b/ui/css/index.scss @@ -27,4 +27,4 @@ /* Third Party Library Styles */ -@import '../../../node_modules/react-tippy/dist/tippy'; +@import '../../node_modules/react-tippy/dist/tippy'; diff --git a/ui/app/css/itcss/README.md b/ui/css/itcss/README.md similarity index 100% rename from ui/app/css/itcss/README.md rename to ui/css/itcss/README.md diff --git a/ui/app/css/itcss/components/index.scss b/ui/css/itcss/components/index.scss similarity index 100% rename from ui/app/css/itcss/components/index.scss rename to ui/css/itcss/components/index.scss diff --git a/ui/app/css/itcss/components/network.scss b/ui/css/itcss/components/network.scss similarity index 100% rename from ui/app/css/itcss/components/network.scss rename to ui/css/itcss/components/network.scss diff --git a/ui/app/css/itcss/components/newui-sections.scss b/ui/css/itcss/components/newui-sections.scss similarity index 85% rename from ui/app/css/itcss/components/newui-sections.scss rename to ui/css/itcss/components/newui-sections.scss index 57c1f6d77..51f485600 100644 --- a/ui/app/css/itcss/components/newui-sections.scss +++ b/ui/css/itcss/components/newui-sections.scss @@ -14,6 +14,23 @@ $sub-mid-size-breakpoint-range: "screen and (min-width: #{$break-large}) and (ma align-items: center; } +// Fix for UI lag on external monitor: https://github.com/MetaMask/metamask-extension/issues/10173 +.app.os-mac.browser-chrome::after { + content: ""; + position: fixed; + top: 0; + left: 0; + width: 1px; + height: 1px; + background-color: $Grey-000; + animation: emptySpinningDiv 1s infinite linear; +} + +@keyframes emptySpinningDiv { + 0% { transform: rotate(0deg); } + to { transform: rotate(1turn); } +} + // Main container .main-container { z-index: $main-container-z-index; diff --git a/ui/app/css/itcss/components/send.scss b/ui/css/itcss/components/send.scss similarity index 100% rename from ui/app/css/itcss/components/send.scss rename to ui/css/itcss/components/send.scss diff --git a/ui/app/css/itcss/settings/index.scss b/ui/css/itcss/settings/index.scss similarity index 100% rename from ui/app/css/itcss/settings/index.scss rename to ui/css/itcss/settings/index.scss diff --git a/ui/app/css/itcss/settings/variables.scss b/ui/css/itcss/settings/variables.scss similarity index 100% rename from ui/app/css/itcss/settings/variables.scss rename to ui/css/itcss/settings/variables.scss diff --git a/ui/app/css/itcss/tools/index.scss b/ui/css/itcss/tools/index.scss similarity index 100% rename from ui/app/css/itcss/tools/index.scss rename to ui/css/itcss/tools/index.scss diff --git a/ui/app/css/itcss/tools/utilities.scss b/ui/css/itcss/tools/utilities.scss similarity index 100% rename from ui/app/css/itcss/tools/utilities.scss rename to ui/css/itcss/tools/utilities.scss diff --git a/ui/app/css/reset.scss b/ui/css/reset.scss similarity index 100% rename from ui/app/css/reset.scss rename to ui/css/reset.scss diff --git a/ui/app/css/utilities/_colors.scss b/ui/css/utilities/_colors.scss similarity index 100% rename from ui/app/css/utilities/_colors.scss rename to ui/css/utilities/_colors.scss diff --git a/ui/app/css/utilities/_spacing.scss b/ui/css/utilities/_spacing.scss similarity index 100% rename from ui/app/css/utilities/_spacing.scss rename to ui/css/utilities/_spacing.scss diff --git a/ui/app/css/utilities/index.scss b/ui/css/utilities/index.scss similarity index 100% rename from ui/app/css/utilities/index.scss rename to ui/css/utilities/index.scss diff --git a/ui/app/ducks/alerts/enums.js b/ui/ducks/alerts/enums.js similarity index 100% rename from ui/app/ducks/alerts/enums.js rename to ui/ducks/alerts/enums.js diff --git a/ui/app/ducks/alerts/index.js b/ui/ducks/alerts/index.js similarity index 100% rename from ui/app/ducks/alerts/index.js rename to ui/ducks/alerts/index.js diff --git a/ui/app/ducks/alerts/invalid-custom-network.js b/ui/ducks/alerts/invalid-custom-network.js similarity index 93% rename from ui/app/ducks/alerts/invalid-custom-network.js rename to ui/ducks/alerts/invalid-custom-network.js index ab033ed46..da3bd2e54 100644 --- a/ui/app/ducks/alerts/invalid-custom-network.js +++ b/ui/ducks/alerts/invalid-custom-network.js @@ -1,6 +1,6 @@ import { createSlice } from '@reduxjs/toolkit'; -import { ALERT_TYPES } from '../../../../shared/constants/alerts'; +import { ALERT_TYPES } from '../../../shared/constants/alerts'; import { ALERT_STATE } from './enums'; // Constants diff --git a/ui/app/ducks/alerts/unconnected-account.js b/ui/ducks/alerts/unconnected-account.js similarity index 98% rename from ui/app/ducks/alerts/unconnected-account.js rename to ui/ducks/alerts/unconnected-account.js index 2020def25..748389e18 100644 --- a/ui/app/ducks/alerts/unconnected-account.js +++ b/ui/ducks/alerts/unconnected-account.js @@ -1,7 +1,7 @@ import { createSlice } from '@reduxjs/toolkit'; import { captureException } from '@sentry/browser'; -import { ALERT_TYPES } from '../../../../shared/constants/alerts'; +import { ALERT_TYPES } from '../../../shared/constants/alerts'; import * as actionConstants from '../../store/actionConstants'; import { addPermittedAccount, diff --git a/ui/app/ducks/app/app.js b/ui/ducks/app/app.js similarity index 100% rename from ui/app/ducks/app/app.js rename to ui/ducks/app/app.js diff --git a/ui/app/ducks/app/app.test.js b/ui/ducks/app/app.test.js similarity index 100% rename from ui/app/ducks/app/app.test.js rename to ui/ducks/app/app.test.js diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js b/ui/ducks/confirm-transaction/confirm-transaction.duck.js similarity index 100% rename from ui/app/ducks/confirm-transaction/confirm-transaction.duck.js rename to ui/ducks/confirm-transaction/confirm-transaction.duck.js diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js b/ui/ducks/confirm-transaction/confirm-transaction.duck.test.js similarity index 98% rename from ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js rename to ui/ducks/confirm-transaction/confirm-transaction.duck.test.js index 75e580a60..8df65c35a 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js +++ b/ui/ducks/confirm-transaction/confirm-transaction.duck.test.js @@ -4,8 +4,8 @@ import sinon from 'sinon'; import { ROPSTEN_CHAIN_ID, ROPSTEN_NETWORK_ID, -} from '../../../../shared/constants/network'; -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; +} from '../../../shared/constants/network'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; import ConfirmTransactionReducer, * as actions from './confirm-transaction.duck'; diff --git a/ui/app/ducks/gas/gas-duck.test.js b/ui/ducks/gas/gas-duck.test.js similarity index 76% rename from ui/app/ducks/gas/gas-duck.test.js rename to ui/ducks/gas/gas-duck.test.js index eab7a74b6..d4301f9b3 100644 --- a/ui/app/ducks/gas/gas-duck.test.js +++ b/ui/ducks/gas/gas-duck.test.js @@ -3,15 +3,14 @@ import sinon from 'sinon'; import BN from 'bn.js'; import GasReducer, { - basicGasEstimatesLoadingStarted, - basicGasEstimatesLoadingFinished, + setBasicEstimateStatus, setBasicGasEstimateData, setCustomGasPrice, setCustomGasLimit, fetchBasicGasEstimates, } from './gas.duck'; -jest.mock('../../../lib/storage-helpers.js', () => ({ +jest.mock('../../helpers/utils/storage-helpers.js', () => ({ getStorageItem: jest.fn(), setStorageItem: jest.fn(), })); @@ -49,7 +48,8 @@ describe('Gas Duck', () => { fast: null, safeLow: null, }, - basicEstimateIsLoading: true, + basicEstimateStatus: 'LOADING', + estimateSource: '', }; const providerState = { @@ -61,14 +61,12 @@ describe('Gas Duck', () => { type: 'mainnet', }; - const BASIC_GAS_ESTIMATE_LOADING_FINISHED = - 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED'; - const BASIC_GAS_ESTIMATE_LOADING_STARTED = - 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_STARTED'; + const BASIC_GAS_ESTIMATE_STATUS = 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS'; const SET_BASIC_GAS_ESTIMATE_DATA = 'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA'; const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT'; const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE'; + const SET_ESTIMATE_SOURCE = 'metamask/gas/SET_ESTIMATE_SOURCE'; describe('GasReducer()', () => { it('should initialize state', () => { @@ -84,16 +82,13 @@ describe('Gas Duck', () => { ).toStrictEqual(mockState); }); - it('should set basicEstimateIsLoading to true when receiving a BASIC_GAS_ESTIMATE_LOADING_STARTED action', () => { + it('should set basicEstimateStatus to LOADING when receiving a BASIC_GAS_ESTIMATE_STATUS action with value LOADING', () => { expect( - GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }), - ).toStrictEqual({ basicEstimateIsLoading: true, ...mockState }); - }); - - it('should set basicEstimateIsLoading to false when receiving a BASIC_GAS_ESTIMATE_LOADING_FINISHED action', () => { - expect( - GasReducer(mockState, { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }), - ).toStrictEqual({ basicEstimateIsLoading: false, ...mockState }); + GasReducer(mockState, { + type: BASIC_GAS_ESTIMATE_STATUS, + value: 'LOADING', + }), + ).toStrictEqual({ basicEstimateStatus: 'LOADING', ...mockState }); }); it('should set basicEstimates when receiving a SET_BASIC_GAS_ESTIMATE_DATA action', () => { @@ -127,18 +122,17 @@ describe('Gas Duck', () => { }); }); - describe('basicGasEstimatesLoadingStarted', () => { - it('should create the correct action', () => { - expect(basicGasEstimatesLoadingStarted()).toStrictEqual({ - type: BASIC_GAS_ESTIMATE_LOADING_STARTED, - }); - }); + it('should set estimateSource to Metaswaps when receiving a SET_ESTIMATE_SOURCE action with value Metaswaps', () => { + expect( + GasReducer(mockState, { type: SET_ESTIMATE_SOURCE, value: 'Metaswaps' }), + ).toStrictEqual({ estimateSource: 'Metaswaps', ...mockState }); }); - describe('basicGasEstimatesLoadingFinished', () => { + describe('basicEstimateStatus', () => { it('should create the correct action', () => { - expect(basicGasEstimatesLoadingFinished()).toStrictEqual({ - type: BASIC_GAS_ESTIMATE_LOADING_FINISHED, + expect(setBasicEstimateStatus('LOADING')).toStrictEqual({ + type: BASIC_GAS_ESTIMATE_STATUS, + value: 'LOADING', }); }); }); @@ -158,7 +152,7 @@ describe('Gas Duck', () => { })); expect(mockDistpatch.getCall(0).args).toStrictEqual([ - { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }, + { type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS', value: 'LOADING' }, ]); expect( @@ -168,7 +162,11 @@ describe('Gas Duck', () => { ).toStrictEqual(true); expect(mockDistpatch.getCall(2).args).toStrictEqual([ - { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }, + { type: 'metamask/gas/SET_ESTIMATE_SOURCE', value: 'MetaSwaps' }, + ]); + + expect(mockDistpatch.getCall(4).args).toStrictEqual([ + { type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS', value: 'READY' }, ]); }); @@ -190,9 +188,12 @@ describe('Gas Duck', () => { metamask: { provider: { ...providerStateForTestNetwork } }, })); expect(mockDistpatch.getCall(0).args).toStrictEqual([ - { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }, + { type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS', value: 'LOADING' }, ]); expect(mockDistpatch.getCall(1).args).toStrictEqual([ + { type: 'metamask/gas/SET_ESTIMATE_SOURCE', value: 'eth_gasprice' }, + ]); + expect(mockDistpatch.getCall(2).args).toStrictEqual([ { type: SET_BASIC_GAS_ESTIMATE_DATA, value: { @@ -200,8 +201,8 @@ describe('Gas Duck', () => { }, }, ]); - expect(mockDistpatch.getCall(2).args).toStrictEqual([ - { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }, + expect(mockDistpatch.getCall(3).args).toStrictEqual([ + { type: 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS', value: 'READY' }, ]); }); }); diff --git a/ui/app/ducks/gas/gas.duck.js b/ui/ducks/gas/gas.duck.js similarity index 72% rename from ui/app/ducks/gas/gas.duck.js rename to ui/ducks/gas/gas.duck.js index 5785b2cf3..e991e5e73 100644 --- a/ui/app/ducks/gas/gas.duck.js +++ b/ui/ducks/gas/gas.duck.js @@ -1,6 +1,9 @@ import { cloneDeep } from 'lodash'; import BigNumber from 'bignumber.js'; -import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers'; +import { + getStorageItem, + setStorageItem, +} from '../../helpers/utils/storage-helpers'; import { decGWEIToHexWEI, getValueFromWeiHex, @@ -8,15 +11,24 @@ import { import { getIsMainnet, getCurrentChainId } from '../../selectors'; import fetchWithCache from '../../helpers/utils/fetch-with-cache'; +export const BASIC_ESTIMATE_STATES = { + LOADING: 'LOADING', + FAILED: 'FAILED', + READY: 'READY', +}; + +export const GAS_SOURCE = { + METASWAPS: 'MetaSwaps', + ETHGASPRICE: 'eth_gasprice', +}; + // Actions -const BASIC_GAS_ESTIMATE_LOADING_FINISHED = - 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED'; -const BASIC_GAS_ESTIMATE_LOADING_STARTED = - 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_STARTED'; +const BASIC_GAS_ESTIMATE_STATUS = 'metamask/gas/BASIC_GAS_ESTIMATE_STATUS'; const RESET_CUSTOM_DATA = 'metamask/gas/RESET_CUSTOM_DATA'; const SET_BASIC_GAS_ESTIMATE_DATA = 'metamask/gas/SET_BASIC_GAS_ESTIMATE_DATA'; const SET_CUSTOM_GAS_LIMIT = 'metamask/gas/SET_CUSTOM_GAS_LIMIT'; const SET_CUSTOM_GAS_PRICE = 'metamask/gas/SET_CUSTOM_GAS_PRICE'; +const SET_ESTIMATE_SOURCE = 'metamask/gas/SET_ESTIMATE_SOURCE'; const initState = { customData: { @@ -28,21 +40,17 @@ const initState = { average: null, fast: null, }, - basicEstimateIsLoading: true, + basicEstimateStatus: BASIC_ESTIMATE_STATES.LOADING, + estimateSource: '', }; // Reducer export default function reducer(state = initState, action) { switch (action.type) { - case BASIC_GAS_ESTIMATE_LOADING_STARTED: + case BASIC_GAS_ESTIMATE_STATUS: return { ...state, - basicEstimateIsLoading: true, - }; - case BASIC_GAS_ESTIMATE_LOADING_FINISHED: - return { - ...state, - basicEstimateIsLoading: false, + basicEstimateStatus: action.value, }; case SET_BASIC_GAS_ESTIMATE_DATA: return { @@ -70,21 +78,21 @@ export default function reducer(state = initState, action) { ...state, customData: cloneDeep(initState.customData), }; + case SET_ESTIMATE_SOURCE: + return { + ...state, + estimateSource: action.value, + }; default: return state; } } // Action Creators -export function basicGasEstimatesLoadingStarted() { +export function setBasicEstimateStatus(status) { return { - type: BASIC_GAS_ESTIMATE_LOADING_STARTED, - }; -} - -export function basicGasEstimatesLoadingFinished() { - return { - type: BASIC_GAS_ESTIMATE_LOADING_FINISHED, + type: BASIC_GAS_ESTIMATE_STATUS, + value: status, }; } @@ -106,18 +114,26 @@ export function fetchBasicGasEstimates() { return async (dispatch, getState) => { const isMainnet = getIsMainnet(getState()); - dispatch(basicGasEstimatesLoadingStarted()); - + dispatch(setBasicEstimateStatus(BASIC_ESTIMATE_STATES.LOADING)); let basicEstimates; - if (isMainnet || process.env.IN_TEST) { - basicEstimates = await fetchExternalBasicGasEstimates(); - } else { - basicEstimates = await fetchEthGasPriceEstimates(getState()); + try { + dispatch(setEstimateSource(GAS_SOURCE.ETHGASPRICE)); + if (isMainnet || process.env.IN_TEST) { + try { + basicEstimates = await fetchExternalBasicGasEstimates(); + dispatch(setEstimateSource(GAS_SOURCE.METASWAPS)); + } catch (error) { + basicEstimates = await fetchEthGasPriceEstimates(getState()); + } + } else { + basicEstimates = await fetchEthGasPriceEstimates(getState()); + } + dispatch(setBasicGasEstimateData(basicEstimates)); + dispatch(setBasicEstimateStatus(BASIC_ESTIMATE_STATES.READY)); + } catch (error) { + dispatch(setBasicEstimateStatus(BASIC_ESTIMATE_STATES.FAILED)); } - dispatch(setBasicGasEstimateData(basicEstimates)); - dispatch(basicGasEstimatesLoadingFinished()); - return basicEstimates; }; } @@ -211,3 +227,10 @@ export function setCustomGasLimit(newLimit) { export function resetCustomData() { return { type: RESET_CUSTOM_DATA }; } + +export function setEstimateSource(estimateSource) { + return { + type: SET_ESTIMATE_SOURCE, + value: estimateSource, + }; +} diff --git a/ui/app/ducks/history/history.js b/ui/ducks/history/history.js similarity index 100% rename from ui/app/ducks/history/history.js rename to ui/ducks/history/history.js diff --git a/ui/app/ducks/index.js b/ui/ducks/index.js similarity index 93% rename from ui/app/ducks/index.js rename to ui/ducks/index.js index 4782acc48..bae560536 100644 --- a/ui/app/ducks/index.js +++ b/ui/ducks/index.js @@ -1,5 +1,5 @@ import { combineReducers } from 'redux'; -import { ALERT_TYPES } from '../../../shared/constants/alerts'; +import { ALERT_TYPES } from '../../shared/constants/alerts'; import metamaskReducer from './metamask/metamask'; import localeMessagesReducer from './locale/locale'; import sendReducer from './send/send.duck'; diff --git a/ui/app/ducks/locale/locale.js b/ui/ducks/locale/locale.js similarity index 100% rename from ui/app/ducks/locale/locale.js rename to ui/ducks/locale/locale.js diff --git a/ui/app/ducks/metamask/metamask.js b/ui/ducks/metamask/metamask.js similarity index 95% rename from ui/app/ducks/metamask/metamask.js rename to ui/ducks/metamask/metamask.js index 7569f0ccb..093f3e925 100644 --- a/ui/app/ducks/metamask/metamask.js +++ b/ui/ducks/metamask/metamask.js @@ -1,6 +1,6 @@ import * as actionConstants from '../../store/actionConstants'; -import { ALERT_TYPES } from '../../../../shared/constants/alerts'; -import { NETWORK_TYPE_RPC } from '../../../../shared/constants/network'; +import { ALERT_TYPES } from '../../../shared/constants/alerts'; +import { NETWORK_TYPE_RPC } from '../../../shared/constants/network'; export default function reduceMetamask(state = {}, action) { const metamaskState = { @@ -93,13 +93,6 @@ export default function reduceMetamask(state = {}, action) { return Object.assign(metamaskState, { identities }); } - case actionConstants.SET_CURRENT_FIAT: - return Object.assign(metamaskState, { - currentCurrency: action.value.currentCurrency, - conversionRate: action.value.conversionRate, - conversionDate: action.value.conversionDate, - }); - case actionConstants.UPDATE_TOKENS: return { ...metamaskState, diff --git a/ui/app/ducks/metamask/metamask.test.js b/ui/ducks/metamask/metamask.test.js similarity index 94% rename from ui/app/ducks/metamask/metamask.test.js rename to ui/ducks/metamask/metamask.test.js index 2c268acc3..c830cd4a2 100644 --- a/ui/app/ducks/metamask/metamask.test.js +++ b/ui/ducks/metamask/metamask.test.js @@ -74,26 +74,6 @@ describe('MetaMask Reducers', () => { }); }); - it('sets current fiat', () => { - const value = { - currentCurrency: 'yen', - conversionRate: 3.14, - conversionDate: new Date(2018, 9), - }; - - const state = reduceMetamask( - {}, - { - type: actionConstants.SET_CURRENT_FIAT, - value, - }, - ); - - expect(state.currentCurrency).toStrictEqual(value.currentCurrency); - expect(state.conversionRate).toStrictEqual(value.conversionRate); - expect(state.conversionDate).toStrictEqual(value.conversionDate); - }); - it('updates tokens', () => { const newTokens = { address: '0x617b3f8050a0bd94b6b1da02b4384ee5b4df13f4', diff --git a/ui/app/ducks/send/send-duck.test.js b/ui/ducks/send/send-duck.test.js similarity index 100% rename from ui/app/ducks/send/send-duck.test.js rename to ui/ducks/send/send-duck.test.js diff --git a/ui/app/ducks/send/send.duck.js b/ui/ducks/send/send.duck.js similarity index 100% rename from ui/app/ducks/send/send.duck.js rename to ui/ducks/send/send.duck.js diff --git a/ui/app/ducks/swaps/swaps.js b/ui/ducks/swaps/swaps.js similarity index 93% rename from ui/app/ducks/swaps/swaps.js rename to ui/ducks/swaps/swaps.js index f33b06745..34f7a84fe 100644 --- a/ui/app/ducks/swaps/swaps.js +++ b/ui/ducks/swaps/swaps.js @@ -26,6 +26,7 @@ import { cancelTx, } from '../../store/actions'; import { + AWAITING_SIGNATURES_ROUTE, AWAITING_SWAP_ROUTE, BUILD_QUOTE_ROUTE, LOADING_QUOTES_ROUTE, @@ -52,14 +53,17 @@ import { getUSDConversionRate, getSwapsDefaultToken, getCurrentChainId, + isHardwareWallet, + getHardwareWalletType, } from '../../selectors'; import { ERROR_FETCHING_QUOTES, QUOTES_NOT_AVAILABLE_ERROR, + CONTRACT_DATA_DISABLED_ERROR, SWAP_FAILED_ERROR, SWAPS_FETCH_ORDER_CONFLICT, -} from '../../../../shared/constants/swaps'; -import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; +} from '../../../shared/constants/swaps'; +import { TRANSACTION_TYPES } from '../../../shared/constants/transaction'; const GAS_PRICES_LOADING_STATES = { INITIAL: 'INITIAL', @@ -73,6 +77,7 @@ export const FALLBACK_GAS_MULTIPLIER = 1.5; const initialState = { aggregatorMetadata: null, approveTxId: null, + tradeTxId: null, balanceError: false, fetchingQuotes: false, fromToken: null, @@ -95,6 +100,7 @@ const slice = createSlice({ clearSwapsState: () => initialState, navigatedBackToBuildQuote: (state) => { state.approveTxId = null; + state.tradeTxId = null; state.balanceError = false; state.fetchingQuotes = false; state.customGas.limit = null; @@ -437,7 +443,7 @@ export const fetchQuotesAndSetQuoteState = ( if ( toTokenAddress && toTokenSymbol !== swapsDefaultToken.symbol && - !contractExchangeRates[toTokenAddress] + contractExchangeRates[toTokenAddress] === undefined ) { destinationTokenAddedForSwap = true; await dispatch( @@ -479,6 +485,8 @@ export const fetchQuotesAndSetQuoteState = ( dispatch(setFromToken(selectedFromToken)); + const hardwareWalletUsed = isHardwareWallet(state); + const hardwareWalletType = getHardwareWalletType(state); metaMetricsEvent({ event: 'Quotes Requested', category: 'swaps', @@ -489,6 +497,8 @@ export const fetchQuotesAndSetQuoteState = ( request_type: balanceError ? 'Quote' : 'Order', slippage: maxSlippage, custom_slippage: maxSlippage !== 2, + is_hardware_wallet: hardwareWalletUsed, + hardware_wallet_type: hardwareWalletType, anonymizedData: true, }, }); @@ -536,6 +546,8 @@ export const fetchQuotesAndSetQuoteState = ( request_type: balanceError ? 'Quote' : 'Order', slippage: maxSlippage, custom_slippage: maxSlippage !== 2, + is_hardware_wallet: hardwareWalletUsed, + hardware_wallet_type: hardwareWalletType, }, }); dispatch(setSwapsErrorKey(QUOTES_NOT_AVAILABLE_ERROR)); @@ -559,6 +571,8 @@ export const fetchQuotesAndSetQuoteState = ( response_time: Date.now() - fetchStartTime, best_quote_source: newSelectedQuote.aggregator, available_quotes: Object.values(fetchedQuotes)?.length, + is_hardware_wallet: hardwareWalletUsed, + hardware_wallet_type: hardwareWalletType, anonymizedData: true, }, }); @@ -585,7 +599,7 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => { return async (dispatch, getState) => { const state = getState(); const chainId = getCurrentChainId(state); - + const hardwareWalletUsed = isHardwareWallet(state); let swapsFeatureIsLive = false; try { swapsFeatureIsLive = await fetchSwapsFeatureLiveness(chainId); @@ -605,7 +619,10 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => { const { sourceTokenInfo = {}, destinationTokenInfo = {} } = metaData; await dispatch(setBackgroundSwapRouteState('awaiting')); await dispatch(stopPollingForQuotes()); - history.push(AWAITING_SWAP_ROUTE); + + if (!hardwareWalletUsed) { + history.push(AWAITING_SWAP_ROUTE); + } const { fast: fastGasEstimate } = getSwapGasPriceEstimateData(state); @@ -671,6 +688,8 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => { performance_savings: usedQuote.savings?.performance, fee_savings: usedQuote.savings?.fee, median_metamask_fee: usedQuote.savings?.medianMetaMaskFee, + is_hardware_wallet: hardwareWalletUsed, + hardware_wallet_type: getHardwareWalletType(state), }; metaMetricsEvent({ @@ -694,6 +713,13 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => { let finalApproveTxMeta; const approveTxParams = getApproveTxParams(state); + + // For hardware wallets we go to the Awaiting Signatures page first and only after a user + // completes 1 or 2 confirmations, we redirect to the Awaiting Swap page. + if (hardwareWalletUsed) { + history.push(AWAITING_SIGNATURES_ROUTE); + } + if (approveTxParams) { const approveTxMeta = await dispatch( addUnapprovedTransaction( @@ -760,11 +786,20 @@ export const signAndSendTransactions = (history, metaMetricsEvent) => { try { await dispatch(updateAndApproveTx(finalTradeTxMeta, true)); } catch (e) { - await dispatch(setSwapsErrorKey(SWAP_FAILED_ERROR)); + const errorKey = e.message.includes('EthAppPleaseEnableContractData') + ? CONTRACT_DATA_DISABLED_ERROR + : SWAP_FAILED_ERROR; + await dispatch(setSwapsErrorKey(errorKey)); history.push(SWAPS_ERROR_ROUTE); return; } + // Only after a user confirms swapping on a hardware wallet (second `updateAndApproveTx` call above), + // we redirect to the Awaiting Swap page. + if (hardwareWalletUsed) { + history.push(AWAITING_SWAP_ROUTE); + } + await forceUpdateMetamaskState(dispatch); }; }; diff --git a/ui/app/ducks/swaps/swaps.test.js b/ui/ducks/swaps/swaps.test.js similarity index 98% rename from ui/app/ducks/swaps/swaps.test.js rename to ui/ducks/swaps/swaps.test.js index 585571d0e..a94869267 100644 --- a/ui/app/ducks/swaps/swaps.test.js +++ b/ui/ducks/swaps/swaps.test.js @@ -1,7 +1,7 @@ import nock from 'nock'; import { setSwapsLiveness } from '../../store/actions'; -import { setStorageItem } from '../../../lib/storage-helpers'; +import { setStorageItem } from '../../helpers/utils/storage-helpers'; import * as swaps from './swaps'; jest.mock('../../store/actions.js', () => ({ diff --git a/ui/app/helpers/constants/available-conversions.json b/ui/helpers/constants/available-conversions.json similarity index 100% rename from ui/app/helpers/constants/available-conversions.json rename to ui/helpers/constants/available-conversions.json diff --git a/ui/app/helpers/constants/common.js b/ui/helpers/constants/common.js similarity index 100% rename from ui/app/helpers/constants/common.js rename to ui/helpers/constants/common.js diff --git a/ui/app/helpers/constants/connected-sites.js b/ui/helpers/constants/connected-sites.js similarity index 100% rename from ui/app/helpers/constants/connected-sites.js rename to ui/helpers/constants/connected-sites.js diff --git a/ui/app/helpers/constants/design-system.js b/ui/helpers/constants/design-system.js similarity index 100% rename from ui/app/helpers/constants/design-system.js rename to ui/helpers/constants/design-system.js diff --git a/ui/app/helpers/constants/error-keys.js b/ui/helpers/constants/error-keys.js similarity index 55% rename from ui/app/helpers/constants/error-keys.js rename to ui/helpers/constants/error-keys.js index 85ce13d7d..bfdb7474f 100644 --- a/ui/app/helpers/constants/error-keys.js +++ b/ui/helpers/constants/error-keys.js @@ -2,3 +2,6 @@ export const INSUFFICIENT_FUNDS_ERROR_KEY = 'insufficientFunds'; export const GAS_LIMIT_TOO_LOW_ERROR_KEY = 'gasLimitTooLow'; export const TRANSACTION_ERROR_KEY = 'transactionError'; export const TRANSACTION_NO_CONTRACT_ERROR_KEY = 'transactionErrorNoContract'; +export const ETH_GAS_PRICE_FETCH_WARNING_KEY = 'ethGasPriceFetchWarning'; +export const GAS_PRICE_FETCH_FAILURE_ERROR_KEY = 'gasPriceFetchFailed'; +export const GAS_PRICE_EXCESSIVE_ERROR_KEY = 'gasPriceExcessive'; diff --git a/ui/app/helpers/constants/routes.js b/ui/helpers/constants/routes.js similarity index 92% rename from ui/app/helpers/constants/routes.js rename to ui/helpers/constants/routes.js index 1ed9a7f0d..781f51063 100644 --- a/ui/app/helpers/constants/routes.js +++ b/ui/helpers/constants/routes.js @@ -32,6 +32,7 @@ const SWAPS_ROUTE = '/swaps'; const BUILD_QUOTE_ROUTE = '/swaps/build-quote'; const VIEW_QUOTE_ROUTE = '/swaps/view-quote'; const LOADING_QUOTES_ROUTE = '/swaps/loading-quotes'; +const AWAITING_SIGNATURES_ROUTE = '/swaps/awaiting-signatures'; const AWAITING_SWAP_ROUTE = '/swaps/awaiting-swap'; const SWAPS_ERROR_ROUTE = '/swaps/swaps-error'; const SWAPS_MAINTENANCE_ROUTE = '/swaps/maintenance'; @@ -45,6 +46,7 @@ const INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE = const INITIALIZE_SELECT_ACTION_ROUTE = '/initialize/select-action'; const INITIALIZE_SEED_PHRASE_ROUTE = '/initialize/seed-phrase'; const INITIALIZE_BACKUP_SEED_PHRASE_ROUTE = '/initialize/backup-seed-phrase'; +const INITIALIZE_SEED_PHRASE_INTRO_ROUTE = '/initialize/seed-phrase-intro'; const INITIALIZE_END_OF_FLOW_ROUTE = '/initialize/end-of-flow'; const INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE = '/initialize/seed-phrase/confirm'; const INITIALIZE_METAMETRICS_OPT_IN_ROUTE = '/initialize/metametrics-opt-in'; @@ -80,7 +82,7 @@ const PATH_NAME_MAP = { [`${CONTACT_EDIT_ROUTE}/:address`]: 'Edit Contact Settings Page', [CONTACT_ADD_ROUTE]: 'Add Contact Settings Page', [`${CONTACT_VIEW_ROUTE}/:address`]: 'View Contact Settings Page', - [REVEAL_SEED_ROUTE]: 'Reveal Seed Page', + [REVEAL_SEED_ROUTE]: 'Reveal Secret Recovery Phrase Page', [MOBILE_SYNC_ROUTE]: 'Sync With Mobile Page', [RESTORE_VAULT_ROUTE]: 'Restore Vault Page', [ADD_TOKEN_ROUTE]: 'Add Token Page', @@ -112,15 +114,17 @@ const PATH_NAME_MAP = { [INITIALIZE_UNLOCK_ROUTE]: 'Initialization Unlock page', [INITIALIZE_CREATE_PASSWORD_ROUTE]: 'Initialization Create Password Page', [INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE]: - 'Initialization Import Account With Seed Phrase Page', + 'Initialization Import Account With Secret Recovery Phrase Page', [INITIALIZE_SELECT_ACTION_ROUTE]: 'Initialization Choose Restore or New Account Page', - [INITIALIZE_SEED_PHRASE_ROUTE]: 'Initialization Seed Phrase Page', + [INITIALIZE_SEED_PHRASE_ROUTE]: 'Initialization Secret Recovery Phrase Page', [INITIALIZE_BACKUP_SEED_PHRASE_ROUTE]: - 'Initialization Backup Seed Phrase Page', + 'Initialization Backup Secret Recovery Phrase Page', + [INITIALIZE_SEED_PHRASE_INTRO_ROUTE]: + 'Initialization Secret Recovery Phrase Intro Page', [INITIALIZE_END_OF_FLOW_ROUTE]: 'End of Initialization Page', [INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE]: - 'Initialization Confirm Seed Phrase Page', + 'Initialization Confirm Secret Recovery Phrase Page', [INITIALIZE_METAMETRICS_OPT_IN_ROUTE]: 'MetaMetrics Opt In Page', [BUILD_QUOTE_ROUTE]: 'Swaps Build Quote Page', [VIEW_QUOTE_ROUTE]: 'Swaps View Quotes Page', @@ -178,6 +182,7 @@ export { NETWORKS_ROUTE, NETWORKS_FORM_ROUTE, INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, + INITIALIZE_SEED_PHRASE_INTRO_ROUTE, CONNECT_ROUTE, CONNECT_CONFIRM_PERMISSIONS_ROUTE, CONNECTED_ROUTE, @@ -188,6 +193,7 @@ export { VIEW_QUOTE_ROUTE, LOADING_QUOTES_ROUTE, AWAITING_SWAP_ROUTE, + AWAITING_SIGNATURES_ROUTE, SWAPS_ERROR_ROUTE, SWAPS_MAINTENANCE_ROUTE, }; diff --git a/ui/app/helpers/constants/transactions.js b/ui/helpers/constants/transactions.js similarity index 91% rename from ui/app/helpers/constants/transactions.js rename to ui/helpers/constants/transactions.js index 288d497e2..614f0329d 100644 --- a/ui/app/helpers/constants/transactions.js +++ b/ui/helpers/constants/transactions.js @@ -1,7 +1,7 @@ import { TRANSACTION_TYPES, TRANSACTION_STATUSES, -} from '../../../../shared/constants/transaction'; +} from '../../../shared/constants/transaction'; export const PENDING_STATUS_HASH = { [TRANSACTION_STATUSES.UNAPPROVED]: true, diff --git a/ui/app/helpers/higher-order-components/authenticated/authenticated.component.js b/ui/helpers/higher-order-components/authenticated/authenticated.component.js similarity index 100% rename from ui/app/helpers/higher-order-components/authenticated/authenticated.component.js rename to ui/helpers/higher-order-components/authenticated/authenticated.component.js diff --git a/ui/app/helpers/higher-order-components/authenticated/authenticated.container.js b/ui/helpers/higher-order-components/authenticated/authenticated.container.js similarity index 100% rename from ui/app/helpers/higher-order-components/authenticated/authenticated.container.js rename to ui/helpers/higher-order-components/authenticated/authenticated.container.js diff --git a/ui/app/helpers/higher-order-components/authenticated/index.js b/ui/helpers/higher-order-components/authenticated/index.js similarity index 100% rename from ui/app/helpers/higher-order-components/authenticated/index.js rename to ui/helpers/higher-order-components/authenticated/index.js diff --git a/ui/app/helpers/higher-order-components/feature-toggled-route.js b/ui/helpers/higher-order-components/feature-toggled-route.js similarity index 100% rename from ui/app/helpers/higher-order-components/feature-toggled-route.js rename to ui/helpers/higher-order-components/feature-toggled-route.js diff --git a/ui/app/helpers/higher-order-components/initialized/index.js b/ui/helpers/higher-order-components/initialized/index.js similarity index 100% rename from ui/app/helpers/higher-order-components/initialized/index.js rename to ui/helpers/higher-order-components/initialized/index.js diff --git a/ui/app/helpers/higher-order-components/initialized/initialized.component.js b/ui/helpers/higher-order-components/initialized/initialized.component.js similarity index 100% rename from ui/app/helpers/higher-order-components/initialized/initialized.component.js rename to ui/helpers/higher-order-components/initialized/initialized.component.js diff --git a/ui/app/helpers/higher-order-components/initialized/initialized.container.js b/ui/helpers/higher-order-components/initialized/initialized.container.js similarity index 100% rename from ui/app/helpers/higher-order-components/initialized/initialized.container.js rename to ui/helpers/higher-order-components/initialized/initialized.container.js diff --git a/ui/app/helpers/higher-order-components/with-modal-props/index.js b/ui/helpers/higher-order-components/with-modal-props/index.js similarity index 100% rename from ui/app/helpers/higher-order-components/with-modal-props/index.js rename to ui/helpers/higher-order-components/with-modal-props/index.js diff --git a/ui/app/helpers/higher-order-components/with-modal-props/with-modal-props.js b/ui/helpers/higher-order-components/with-modal-props/with-modal-props.js similarity index 100% rename from ui/app/helpers/higher-order-components/with-modal-props/with-modal-props.js rename to ui/helpers/higher-order-components/with-modal-props/with-modal-props.js diff --git a/ui/app/helpers/higher-order-components/with-modal-props/with-modal-props.test.js b/ui/helpers/higher-order-components/with-modal-props/with-modal-props.test.js similarity index 100% rename from ui/app/helpers/higher-order-components/with-modal-props/with-modal-props.test.js rename to ui/helpers/higher-order-components/with-modal-props/with-modal-props.test.js diff --git a/ui/app/helpers/utils/common.util.js b/ui/helpers/utils/common.util.js similarity index 100% rename from ui/app/helpers/utils/common.util.js rename to ui/helpers/utils/common.util.js diff --git a/ui/app/helpers/utils/common.util.test.js b/ui/helpers/utils/common.util.test.js similarity index 100% rename from ui/app/helpers/utils/common.util.test.js rename to ui/helpers/utils/common.util.test.js diff --git a/ui/app/helpers/utils/confirm-tx.util.js b/ui/helpers/utils/confirm-tx.util.js similarity index 98% rename from ui/app/helpers/utils/confirm-tx.util.js rename to ui/helpers/utils/confirm-tx.util.js index 80fe2f3df..5ae5d13c3 100644 --- a/ui/app/helpers/utils/confirm-tx.util.js +++ b/ui/helpers/utils/confirm-tx.util.js @@ -1,7 +1,7 @@ import currencyFormatter from 'currency-formatter'; import currencies from 'currency-formatter/currencies'; import BigNumber from 'bignumber.js'; -import { addHexPrefix } from '../../../../app/scripts/lib/util'; +import { addHexPrefix } from '../../../app/scripts/lib/util'; import { unconfirmedTransactionsCountSelector } from '../../selectors'; import { diff --git a/ui/app/helpers/utils/confirm-tx.util.test.js b/ui/helpers/utils/confirm-tx.util.test.js similarity index 100% rename from ui/app/helpers/utils/confirm-tx.util.test.js rename to ui/helpers/utils/confirm-tx.util.test.js diff --git a/ui/app/helpers/utils/conversion-util.js b/ui/helpers/utils/conversion-util.js similarity index 100% rename from ui/app/helpers/utils/conversion-util.js rename to ui/helpers/utils/conversion-util.js diff --git a/ui/app/helpers/utils/conversion-util.test.js b/ui/helpers/utils/conversion-util.test.js similarity index 100% rename from ui/app/helpers/utils/conversion-util.test.js rename to ui/helpers/utils/conversion-util.test.js diff --git a/ui/app/helpers/utils/conversions.util.js b/ui/helpers/utils/conversions.util.js similarity index 98% rename from ui/app/helpers/utils/conversions.util.js rename to ui/helpers/utils/conversions.util.js index ce4fe8c51..b7c901d97 100644 --- a/ui/app/helpers/utils/conversions.util.js +++ b/ui/helpers/utils/conversions.util.js @@ -1,5 +1,5 @@ import { ETH, GWEI, WEI } from '../constants/common'; -import { addHexPrefix } from '../../../../app/scripts/lib/util'; +import { addHexPrefix } from '../../../app/scripts/lib/util'; import { conversionUtil, addCurrencies, diff --git a/ui/app/helpers/utils/conversions.util.test.js b/ui/helpers/utils/conversions.util.test.js similarity index 100% rename from ui/app/helpers/utils/conversions.util.test.js rename to ui/helpers/utils/conversions.util.test.js diff --git a/ui/app/helpers/utils/fetch-with-cache.js b/ui/helpers/utils/fetch-with-cache.js similarity index 90% rename from ui/app/helpers/utils/fetch-with-cache.js rename to ui/helpers/utils/fetch-with-cache.js index 6dc377593..f810864cc 100644 --- a/ui/app/helpers/utils/fetch-with-cache.js +++ b/ui/helpers/utils/fetch-with-cache.js @@ -1,5 +1,5 @@ -import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers'; -import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'; +import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'; +import { getStorageItem, setStorageItem } from './storage-helpers'; const fetchWithCache = async ( url, diff --git a/ui/app/helpers/utils/fetch-with-cache.test.js b/ui/helpers/utils/fetch-with-cache.test.js similarity index 97% rename from ui/app/helpers/utils/fetch-with-cache.test.js rename to ui/helpers/utils/fetch-with-cache.test.js index 76e295a77..7244e1d14 100644 --- a/ui/app/helpers/utils/fetch-with-cache.test.js +++ b/ui/helpers/utils/fetch-with-cache.test.js @@ -1,9 +1,9 @@ import nock from 'nock'; import sinon from 'sinon'; -import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers'; +import { getStorageItem, setStorageItem } from './storage-helpers'; -jest.mock('../../../lib/storage-helpers.js', () => ({ +jest.mock('./storage-helpers.js', () => ({ getStorageItem: jest.fn(), setStorageItem: jest.fn(), })); diff --git a/ui/app/helpers/utils/formatters.js b/ui/helpers/utils/formatters.js similarity index 100% rename from ui/app/helpers/utils/formatters.js rename to ui/helpers/utils/formatters.js diff --git a/ui/app/helpers/utils/i18n-helper.js b/ui/helpers/utils/i18n-helper.js similarity index 97% rename from ui/app/helpers/utils/i18n-helper.js rename to ui/helpers/utils/i18n-helper.js index ea2d7049f..611d1f665 100644 --- a/ui/app/helpers/utils/i18n-helper.js +++ b/ui/helpers/utils/i18n-helper.js @@ -3,7 +3,7 @@ import React from 'react'; import log from 'loglevel'; import * as Sentry from '@sentry/browser'; -import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'; +import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'; const fetchWithTimeout = getFetchWithTimeout(30000); diff --git a/ui/app/helpers/utils/i18n-helper.test.js b/ui/helpers/utils/i18n-helper.test.js similarity index 100% rename from ui/app/helpers/utils/i18n-helper.test.js rename to ui/helpers/utils/i18n-helper.test.js diff --git a/ui/lib/icon-factory.js b/ui/helpers/utils/icon-factory.js similarity index 97% rename from ui/lib/icon-factory.js rename to ui/helpers/utils/icon-factory.js index 132f5330d..5189dcfce 100644 --- a/ui/lib/icon-factory.js +++ b/ui/helpers/utils/icon-factory.js @@ -2,7 +2,7 @@ import contractMap from '@metamask/contract-metadata'; import { isValidHexAddress, toChecksumHexAddress, -} from '../../shared/modules/hexstring-utils'; +} from '../../../shared/modules/hexstring-utils'; let iconFactory; diff --git a/ui/lib/is-mobile-view.js b/ui/helpers/utils/is-mobile-view.js similarity index 100% rename from ui/lib/is-mobile-view.js rename to ui/helpers/utils/is-mobile-view.js diff --git a/ui/lib/storage-helpers.js b/ui/helpers/utils/storage-helpers.js similarity index 100% rename from ui/lib/storage-helpers.js rename to ui/helpers/utils/storage-helpers.js diff --git a/ui/app/helpers/utils/switch-direction.js b/ui/helpers/utils/switch-direction.js similarity index 100% rename from ui/app/helpers/utils/switch-direction.js rename to ui/helpers/utils/switch-direction.js diff --git a/ui/app/helpers/utils/token-util.js b/ui/helpers/utils/token-util.js similarity index 92% rename from ui/app/helpers/utils/token-util.js rename to ui/helpers/utils/token-util.js index 8811bec5d..4b6d5dd08 100644 --- a/ui/app/helpers/utils/token-util.js +++ b/ui/helpers/utils/token-util.js @@ -13,7 +13,6 @@ const casedContractMap = Object.keys(contractMap).reduce((acc, base) => { }, {}); const DEFAULT_SYMBOL = ''; -const DEFAULT_DECIMALS = '0'; async function getSymbolFromContract(tokenAddress) { const token = util.getContractAtAddress(tokenAddress); @@ -78,25 +77,6 @@ async function getDecimals(tokenAddress) { return decimals; } -export async function fetchSymbolAndDecimals(tokenAddress) { - let symbol, decimals; - - try { - symbol = await getSymbol(tokenAddress); - decimals = await getDecimals(tokenAddress); - } catch (error) { - log.warn( - `symbol() and decimal() calls for token at address ${tokenAddress} resulted in error:`, - error, - ); - } - - return { - symbol: symbol || DEFAULT_SYMBOL, - decimals: decimals || DEFAULT_DECIMALS, - }; -} - export async function getSymbolAndDecimals(tokenAddress, existingTokens = []) { const existingToken = existingTokens.find( ({ address }) => tokenAddress === address, @@ -123,7 +103,7 @@ export async function getSymbolAndDecimals(tokenAddress, existingTokens = []) { return { symbol: symbol || DEFAULT_SYMBOL, - decimals: decimals || DEFAULT_DECIMALS, + decimals, }; } diff --git a/ui/app/helpers/utils/transactions.util.js b/ui/helpers/utils/transactions.util.js similarity index 98% rename from ui/app/helpers/utils/transactions.util.js rename to ui/helpers/utils/transactions.util.js index 99ce94fe5..21a33112a 100644 --- a/ui/app/helpers/utils/transactions.util.js +++ b/ui/helpers/utils/transactions.util.js @@ -3,12 +3,12 @@ import abi from 'human-standard-token-abi'; import { ethers } from 'ethers'; import log from 'loglevel'; -import { addHexPrefix } from '../../../../app/scripts/lib/util'; +import { addHexPrefix } from '../../../app/scripts/lib/util'; import { TRANSACTION_TYPES, TRANSACTION_GROUP_STATUSES, TRANSACTION_STATUSES, -} from '../../../../shared/constants/transaction'; +} from '../../../shared/constants/transaction'; import fetchWithCache from './fetch-with-cache'; import { addCurrencies } from './conversion-util'; diff --git a/ui/app/helpers/utils/transactions.util.test.js b/ui/helpers/utils/transactions.util.test.js similarity index 97% rename from ui/app/helpers/utils/transactions.util.test.js rename to ui/helpers/utils/transactions.util.test.js index 9af77ef0f..a8663c3a6 100644 --- a/ui/app/helpers/utils/transactions.util.test.js +++ b/ui/helpers/utils/transactions.util.test.js @@ -2,7 +2,7 @@ import { TRANSACTION_TYPES, TRANSACTION_GROUP_STATUSES, TRANSACTION_STATUSES, -} from '../../../../shared/constants/transaction'; +} from '../../../shared/constants/transaction'; import * as utils from './transactions.util'; describe('Transactions utils', () => { diff --git a/ui/lib/tx-helper.js b/ui/helpers/utils/tx-helper.js similarity index 92% rename from ui/lib/tx-helper.js rename to ui/helpers/utils/tx-helper.js index 7585b33fe..bdfc576e9 100644 --- a/ui/lib/tx-helper.js +++ b/ui/helpers/utils/tx-helper.js @@ -1,6 +1,6 @@ import log from 'loglevel'; -import { transactionMatchesNetwork } from '../../shared/modules/transaction.utils'; -import { valuesFor } from '../app/helpers/utils/util'; +import { transactionMatchesNetwork } from '../../../shared/modules/transaction.utils'; +import { valuesFor } from './util'; export default function txHelper( unapprovedTxs, diff --git a/ui/lib/tx-helper.test.js b/ui/helpers/utils/tx-helper.test.js similarity index 92% rename from ui/lib/tx-helper.test.js rename to ui/helpers/utils/tx-helper.test.js index 502da54af..75565a2d9 100644 --- a/ui/lib/tx-helper.test.js +++ b/ui/helpers/utils/tx-helper.test.js @@ -1,7 +1,7 @@ import { MAINNET_CHAIN_ID, MAINNET_NETWORK_ID, -} from '../../shared/constants/network'; +} from '../../../shared/constants/network'; import txHelper from './tx-helper'; describe('txHelper', () => { diff --git a/ui/app/helpers/utils/util.js b/ui/helpers/utils/util.js similarity index 98% rename from ui/app/helpers/utils/util.js rename to ui/helpers/utils/util.js index 512acaef8..23e49d716 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/helpers/utils/util.js @@ -3,7 +3,7 @@ import abi from 'human-standard-token-abi'; import BigNumber from 'bignumber.js'; import * as ethUtil from 'ethereumjs-util'; import { DateTime } from 'luxon'; -import { addHexPrefix } from '../../../../app/scripts/lib/util'; +import { addHexPrefix } from '../../../app/scripts/lib/util'; import { GOERLI_CHAIN_ID, KOVAN_CHAIN_ID, @@ -11,8 +11,8 @@ import { MAINNET_CHAIN_ID, RINKEBY_CHAIN_ID, ROPSTEN_CHAIN_ID, -} from '../../../../shared/constants/network'; -import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; +} from '../../../shared/constants/network'; +import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils'; // formatData :: ( date: <Unix Timestamp> ) -> String export function formatDate(date, format = "M/d/y 'at' T") { diff --git a/ui/app/helpers/utils/util.test.js b/ui/helpers/utils/util.test.js similarity index 100% rename from ui/app/helpers/utils/util.test.js rename to ui/helpers/utils/util.test.js diff --git a/ui/lib/webcam-utils.js b/ui/helpers/utils/webcam-utils.js similarity index 90% rename from ui/lib/webcam-utils.js rename to ui/helpers/utils/webcam-utils.js index 7dd4dd499..ef7e80160 100644 --- a/ui/lib/webcam-utils.js +++ b/ui/helpers/utils/webcam-utils.js @@ -4,8 +4,8 @@ import { ENVIRONMENT_TYPE_POPUP, PLATFORM_BRAVE, PLATFORM_FIREFOX, -} from '../../shared/constants/app'; -import { getEnvironmentType, getPlatform } from '../../app/scripts/lib/util'; +} from '../../../shared/constants/app'; +import { getEnvironmentType, getPlatform } from '../../../app/scripts/lib/util'; class WebcamUtils { static async checkStatus() { diff --git a/ui/app/hooks/useCancelTransaction.js b/ui/hooks/useCancelTransaction.js similarity index 91% rename from ui/app/hooks/useCancelTransaction.js rename to ui/hooks/useCancelTransaction.js index 2e71c184b..03bad3c54 100644 --- a/ui/app/hooks/useCancelTransaction.js +++ b/ui/hooks/useCancelTransaction.js @@ -7,7 +7,11 @@ import { getHexGasTotal, increaseLastGasPrice, } from '../helpers/utils/confirm-tx.util'; -import { getConversionRate, getSelectedAccount } from '../selectors'; +import { + getConversionRate, + getSelectedAccount, + getIsMainnet, +} from '../selectors'; import { setCustomGasLimit, setCustomGasPriceForRetry, @@ -43,7 +47,8 @@ export function useCancelTransaction(transactionGroup) { multiplierBase: 10, }), ); - + const isMainnet = useSelector(getIsMainnet); + const hideBasic = !(isMainnet || process.env.IN_TEST); const cancelTransaction = useCallback( (event) => { event.stopPropagation(); @@ -62,6 +67,7 @@ export function useCancelTransaction(transactionGroup) { transitionName: 'sidebar-left', type: 'customize-gas', props: { + hideBasic, transaction: tx, onSubmit: (newGasLimit, newGasPrice) => { const userCustomizedGasTotal = getHexGasTotal({ @@ -82,7 +88,7 @@ export function useCancelTransaction(transactionGroup) { }), ); }, - [dispatch, transaction, defaultNewGasPrice], + [dispatch, transaction, defaultNewGasPrice, hideBasic], ); const hasEnoughCancelGas = diff --git a/ui/app/hooks/useCancelTransaction.test.js b/ui/hooks/useCancelTransaction.test.js similarity index 98% rename from ui/app/hooks/useCancelTransaction.test.js rename to ui/hooks/useCancelTransaction.test.js index 773f2dbb5..28453bc6c 100644 --- a/ui/app/hooks/useCancelTransaction.test.js +++ b/ui/hooks/useCancelTransaction.test.js @@ -1,7 +1,7 @@ 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'; +import transactions from '../../test/data/transaction-data.json'; import { getConversionRate, getSelectedAccount } from '../selectors'; import { showModal } from '../store/actions'; import { increaseLastGasPrice } from '../helpers/utils/confirm-tx.util'; diff --git a/ui/app/hooks/useCopyToClipboard.js b/ui/hooks/useCopyToClipboard.js similarity index 100% rename from ui/app/hooks/useCopyToClipboard.js rename to ui/hooks/useCopyToClipboard.js diff --git a/ui/app/hooks/useCurrencyDisplay.js b/ui/hooks/useCurrencyDisplay.js similarity index 100% rename from ui/app/hooks/useCurrencyDisplay.js rename to ui/hooks/useCurrencyDisplay.js diff --git a/ui/app/hooks/useCurrencyDisplay.test.js b/ui/hooks/useCurrencyDisplay.test.js similarity index 100% rename from ui/app/hooks/useCurrencyDisplay.test.js rename to ui/hooks/useCurrencyDisplay.test.js diff --git a/ui/app/hooks/useCurrentAsset.js b/ui/hooks/useCurrentAsset.js similarity index 96% rename from ui/app/hooks/useCurrentAsset.js rename to ui/hooks/useCurrentAsset.js index 832576a0c..068d076e7 100644 --- a/ui/app/hooks/useCurrentAsset.js +++ b/ui/hooks/useCurrentAsset.js @@ -6,7 +6,7 @@ import { ASSET_ROUTE } from '../helpers/constants/routes'; import { SWAPS_CHAINID_DEFAULT_TOKEN_MAP, ETH_SWAPS_TOKEN_OBJECT, -} from '../../../shared/constants/swaps'; +} from '../../shared/constants/swaps'; /** * Returns a token object for the asset that is currently being viewed. diff --git a/ui/app/hooks/useEqualityCheck.js b/ui/hooks/useEqualityCheck.js similarity index 100% rename from ui/app/hooks/useEqualityCheck.js rename to ui/hooks/useEqualityCheck.js diff --git a/ui/app/hooks/useEthFiatAmount.js b/ui/hooks/useEthFiatAmount.js similarity index 100% rename from ui/app/hooks/useEthFiatAmount.js rename to ui/hooks/useEthFiatAmount.js diff --git a/ui/app/hooks/useI18nContext.js b/ui/hooks/useI18nContext.js similarity index 100% rename from ui/app/hooks/useI18nContext.js rename to ui/hooks/useI18nContext.js diff --git a/ui/app/hooks/useMethodData.js b/ui/hooks/useMethodData.js similarity index 100% rename from ui/app/hooks/useMethodData.js rename to ui/hooks/useMethodData.js diff --git a/ui/app/hooks/useMetricEvent.js b/ui/hooks/useMetricEvent.js similarity index 92% rename from ui/app/hooks/useMetricEvent.js rename to ui/hooks/useMetricEvent.js index b30b37eb5..9ca7834f1 100644 --- a/ui/app/hooks/useMetricEvent.js +++ b/ui/hooks/useMetricEvent.js @@ -6,7 +6,7 @@ import { useEqualityCheck } from './useEqualityCheck'; // Type imports /** * @typedef {import('../contexts/metametrics.new').UIMetricsEventPayload} UIMetricsEventPayload - * @typedef {import('../../../shared/constants/metametrics').MetaMetricsEventOptions} MetaMetricsEventOptions + * @typedef {import('../../shared/constants/metametrics').MetaMetricsEventOptions} MetaMetricsEventOptions */ export function useMetricEvent(config = {}, overrides = {}) { diff --git a/ui/app/hooks/useOriginMetadata.js b/ui/hooks/useOriginMetadata.js similarity index 100% rename from ui/app/hooks/useOriginMetadata.js rename to ui/hooks/useOriginMetadata.js diff --git a/ui/app/hooks/usePrevious.js b/ui/hooks/usePrevious.js similarity index 100% rename from ui/app/hooks/usePrevious.js rename to ui/hooks/usePrevious.js diff --git a/ui/app/hooks/useRetryTransaction.js b/ui/hooks/useRetryTransaction.js similarity index 83% rename from ui/app/hooks/useRetryTransaction.js rename to ui/hooks/useRetryTransaction.js index 0f1532014..44fccb2f4 100644 --- a/ui/app/hooks/useRetryTransaction.js +++ b/ui/hooks/useRetryTransaction.js @@ -1,4 +1,5 @@ -import { useDispatch } from 'react-redux'; +import { useDispatch, useSelector } from 'react-redux'; + import { useCallback } from 'react'; import { showSidebar } from '../store/actions'; import { @@ -7,8 +8,8 @@ import { setCustomGasLimit, } from '../ducks/gas/gas.duck'; import { increaseLastGasPrice } from '../helpers/utils/confirm-tx.util'; +import { getIsMainnet } from '../selectors'; import { useMetricEvent } from './useMetricEvent'; - /** * Provides a reusable hook that, given a transactionGroup, will return * a method for beginning the retry process @@ -17,6 +18,8 @@ import { useMetricEvent } from './useMetricEvent'; */ export function useRetryTransaction(transactionGroup) { const { primaryTransaction } = transactionGroup; + const isMainnet = useSelector(getIsMainnet); + const hideBasic = !(isMainnet || process.env.IN_TEST); // Signature requests do not have a txParams, but this hook is called indiscriminately const gasPrice = primaryTransaction.txParams?.gasPrice; const trackMetricsEvent = useMetricEvent({ @@ -46,11 +49,11 @@ export function useRetryTransaction(transactionGroup) { showSidebar({ transitionName: 'sidebar-left', type: 'customize-gas', - props: { transaction }, + props: { transaction, hideBasic }, }), ); }, - [dispatch, trackMetricsEvent, gasPrice, primaryTransaction], + [dispatch, trackMetricsEvent, gasPrice, primaryTransaction, hideBasic], ); return retryTransaction; diff --git a/ui/app/hooks/useRetryTransaction.test.js b/ui/hooks/useRetryTransaction.test.js similarity index 83% rename from ui/app/hooks/useRetryTransaction.test.js rename to ui/hooks/useRetryTransaction.test.js index c32d98174..3c1f78401 100644 --- a/ui/app/hooks/useRetryTransaction.test.js +++ b/ui/hooks/useRetryTransaction.test.js @@ -1,25 +1,33 @@ 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'; +import transactions from '../../test/data/transaction-data.json'; import { showSidebar } from '../store/actions'; +import { getIsMainnet } from '../selectors'; import * as methodDataHook from './useMethodData'; import * as metricEventHook from './useMetricEvent'; import { useRetryTransaction } from './useRetryTransaction'; describe('useRetryTransaction', () => { describe('when transaction meets retry enabled criteria', () => { + let useSelector; const dispatch = sinon.spy(() => Promise.resolve({ blockTime: 0 })); const trackEvent = sinon.spy(); const event = { preventDefault: () => undefined, stopPropagation: () => undefined, }; - beforeAll(() => { sinon.stub(reactRedux, 'useDispatch').returns(dispatch); sinon.stub(methodDataHook, 'useMethodData').returns({}); sinon.stub(metricEventHook, 'useMetricEvent').returns(trackEvent); + useSelector = sinon.stub(reactRedux, 'useSelector'); + useSelector.callsFake((selector) => { + if (selector === getIsMainnet) { + return true; + } + return undefined; + }); }); afterEach(() => { @@ -61,7 +69,10 @@ describe('useRetryTransaction', () => { showSidebar({ transitionName: 'sidebar-left', type: 'customize-gas', - props: { transaction: retryEnabledTransaction.initialTransaction }, + props: { + transaction: retryEnabledTransaction.initialTransaction, + hideBasic: false, + }, }), ), ).toStrictEqual(true); @@ -104,7 +115,10 @@ describe('useRetryTransaction', () => { showSidebar({ transitionName: 'sidebar-left', type: 'customize-gas', - props: { transaction: cancelledTransaction.primaryTransaction }, + props: { + transaction: cancelledTransaction.primaryTransaction, + hideBasic: false, + }, }), ), ).toStrictEqual(true); diff --git a/ui/app/hooks/useShouldShowSpeedUp.js b/ui/hooks/useShouldShowSpeedUp.js similarity index 100% rename from ui/app/hooks/useShouldShowSpeedUp.js rename to ui/hooks/useShouldShowSpeedUp.js diff --git a/ui/app/hooks/useSwappedTokenValue.js b/ui/hooks/useSwappedTokenValue.js similarity index 96% rename from ui/app/hooks/useSwappedTokenValue.js rename to ui/hooks/useSwappedTokenValue.js index 6eff3726f..02a2a1a37 100644 --- a/ui/app/hooks/useSwappedTokenValue.js +++ b/ui/hooks/useSwappedTokenValue.js @@ -1,9 +1,9 @@ import { useSelector } from 'react-redux'; -import { TRANSACTION_TYPES } from '../../../shared/constants/transaction'; +import { TRANSACTION_TYPES } from '../../shared/constants/transaction'; import { isSwapsDefaultTokenAddress, isSwapsDefaultTokenSymbol, -} from '../../../shared/modules/swaps.utils'; +} from '../../shared/modules/swaps.utils'; import { getSwapsTokensReceivedFromTxMeta } from '../pages/swaps/swaps.util'; import { getCurrentChainId } from '../selectors'; import { useTokenFiatAmount } from './useTokenFiatAmount'; diff --git a/ui/app/hooks/useTimeout.js b/ui/hooks/useTimeout.js similarity index 100% rename from ui/app/hooks/useTimeout.js rename to ui/hooks/useTimeout.js diff --git a/ui/app/hooks/useTokenData.js b/ui/hooks/useTokenData.js similarity index 100% rename from ui/app/hooks/useTokenData.js rename to ui/hooks/useTokenData.js diff --git a/ui/app/hooks/useTokenData.test.js b/ui/hooks/useTokenData.test.js similarity index 96% rename from ui/app/hooks/useTokenData.test.js rename to ui/hooks/useTokenData.test.js index 7c5ed8572..1e80f5c9e 100644 --- a/ui/app/hooks/useTokenData.test.js +++ b/ui/hooks/useTokenData.test.js @@ -1,7 +1,7 @@ /* eslint-disable jest/no-conditional-expect */ import { ethers } from 'ethers'; import { renderHook } from '@testing-library/react-hooks'; -import { TRANSACTION_TYPES } from '../../../shared/constants/transaction'; +import { TRANSACTION_TYPES } from '../../shared/constants/transaction'; import { useTokenData } from './useTokenData'; const tests = [ diff --git a/ui/app/hooks/useTokenDisplayValue.js b/ui/hooks/useTokenDisplayValue.js similarity index 100% rename from ui/app/hooks/useTokenDisplayValue.js rename to ui/hooks/useTokenDisplayValue.js diff --git a/ui/app/hooks/useTokenDisplayValue.test.js b/ui/hooks/useTokenDisplayValue.test.js similarity index 100% rename from ui/app/hooks/useTokenDisplayValue.test.js rename to ui/hooks/useTokenDisplayValue.test.js diff --git a/ui/app/hooks/useTokenFiatAmount.js b/ui/hooks/useTokenFiatAmount.js similarity index 100% rename from ui/app/hooks/useTokenFiatAmount.js rename to ui/hooks/useTokenFiatAmount.js diff --git a/ui/app/hooks/useTokenTracker.js b/ui/hooks/useTokenTracker.js similarity index 100% rename from ui/app/hooks/useTokenTracker.js rename to ui/hooks/useTokenTracker.js diff --git a/ui/app/hooks/useTokensToSearch.js b/ui/hooks/useTokensToSearch.js similarity index 90% rename from ui/app/hooks/useTokensToSearch.js rename to ui/hooks/useTokensToSearch.js index e4bc6495e..02dd6097f 100644 --- a/ui/app/hooks/useTokensToSearch.js +++ b/ui/hooks/useTokensToSearch.js @@ -2,7 +2,7 @@ import { useMemo } from 'react'; import { useSelector } from 'react-redux'; import contractMap from '@metamask/contract-metadata'; import BigNumber from 'bignumber.js'; -import { isEqual, shuffle } from 'lodash'; +import { isEqual, shuffle, uniqBy } from 'lodash'; import { getTokenFiatAmount } from '../helpers/utils/token-util'; import { getTokenExchangeRates, @@ -12,8 +12,8 @@ import { getCurrentChainId, } from '../selectors'; import { getSwapsTokens } from '../ducks/swaps/swaps'; -import { isSwapsDefaultTokenSymbol } from '../../../shared/modules/swaps.utils'; -import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils'; +import { isSwapsDefaultTokenSymbol } from '../../shared/modules/swaps.utils'; +import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils'; import { useEqualityCheck } from './useEqualityCheck'; const tokenList = shuffle( @@ -119,7 +119,12 @@ export function useTokensToSearch({ usersTokens = [], topTokens = {} }) { others: [], }; - memoizedTokensToSearch.forEach((token) => { + const memoizedSwapsAndUserTokensWithoutDuplicities = uniqBy( + [...memoizedTokensToSearch, ...memoizedUsersToken], + 'address', + ); + + memoizedSwapsAndUserTokensWithoutDuplicities.forEach((token) => { const renderableDataToken = getRenderableTokenData( { ...usersTokensAddressMap[token.address], ...token }, tokenConversionRates, @@ -129,8 +134,7 @@ export function useTokensToSearch({ usersTokens = [], topTokens = {} }) { ); if ( isSwapsDefaultTokenSymbol(renderableDataToken.symbol, chainId) || - (usersTokensAddressMap[token.address] && - Number(renderableDataToken.balance ?? 0) !== 0) + usersTokensAddressMap[token.address] ) { tokensToSearchBuckets.owned.push(renderableDataToken); } else if (memoizedTopTokens[token.address]) { diff --git a/ui/app/hooks/useTransactionDisplayData.js b/ui/hooks/useTransactionDisplayData.js similarity index 99% rename from ui/app/hooks/useTransactionDisplayData.js rename to ui/hooks/useTransactionDisplayData.js index dc589f858..1fad5d2c7 100644 --- a/ui/app/hooks/useTransactionDisplayData.js +++ b/ui/hooks/useTransactionDisplayData.js @@ -22,7 +22,7 @@ import { TRANSACTION_TYPES, TRANSACTION_GROUP_CATEGORIES, TRANSACTION_STATUSES, -} from '../../../shared/constants/transaction'; +} from '../../shared/constants/transaction'; import { useI18nContext } from './useI18nContext'; import { useTokenFiatAmount } from './useTokenFiatAmount'; import { useUserPreferencedCurrency } from './useUserPreferencedCurrency'; diff --git a/ui/app/hooks/useTransactionDisplayData.test.js b/ui/hooks/useTransactionDisplayData.test.js similarity index 97% rename from ui/app/hooks/useTransactionDisplayData.test.js rename to ui/hooks/useTransactionDisplayData.test.js index aa0a9832d..e91566acf 100644 --- a/ui/app/hooks/useTransactionDisplayData.test.js +++ b/ui/hooks/useTransactionDisplayData.test.js @@ -3,7 +3,7 @@ import * as reactRedux from 'react-redux'; import { renderHook } from '@testing-library/react-hooks'; import sinon from 'sinon'; import { MemoryRouter } from 'react-router-dom'; -import transactions from '../../../test/data/transaction-data.json'; +import transactions from '../../test/data/transaction-data.json'; import { getPreferences, getShouldShowFiat, @@ -13,14 +13,14 @@ import { } from '../selectors'; import { getTokens } from '../ducks/metamask/metamask'; import { getMessage } from '../helpers/utils/i18n-helper'; -import messages from '../../../app/_locales/en/messages.json'; +import messages from '../../app/_locales/en/messages.json'; import { ASSET_ROUTE, DEFAULT_ROUTE } from '../helpers/constants/routes'; -import { MAINNET_CHAIN_ID } from '../../../shared/constants/network'; +import { MAINNET_CHAIN_ID } from '../../shared/constants/network'; import { TRANSACTION_TYPES, TRANSACTION_GROUP_CATEGORIES, TRANSACTION_STATUSES, -} from '../../../shared/constants/transaction'; +} from '../../shared/constants/transaction'; import * as i18nhooks from './useI18nContext'; import * as useTokenFiatAmountHooks from './useTokenFiatAmount'; import { useTransactionDisplayData } from './useTransactionDisplayData'; diff --git a/ui/app/hooks/useUserPreferencedCurrency.js b/ui/hooks/useUserPreferencedCurrency.js similarity index 100% rename from ui/app/hooks/useUserPreferencedCurrency.js rename to ui/hooks/useUserPreferencedCurrency.js diff --git a/ui/app/hooks/useUserPreferencedCurrency.test.js b/ui/hooks/useUserPreferencedCurrency.test.js similarity index 100% rename from ui/app/hooks/useUserPreferencedCurrency.test.js rename to ui/hooks/useUserPreferencedCurrency.test.js diff --git a/ui/index.js b/ui/index.js index 16a8f5c7d..4bc8409b0 100644 --- a/ui/index.js +++ b/ui/index.js @@ -7,24 +7,24 @@ import { getEnvironmentType } from '../app/scripts/lib/util'; import { ALERT_TYPES } from '../shared/constants/alerts'; import { SENTRY_STATE } from '../app/scripts/lib/setupSentry'; import { ENVIRONMENT_TYPE_POPUP } from '../shared/constants/app'; -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 * as actions from './store/actions'; +import configureStore from './store/store'; import { fetchLocale, loadRelativeTimeFormatLocaleData, -} from './app/helpers/utils/i18n-helper'; -import switchDirection from './app/helpers/utils/switch-direction'; +} from './helpers/utils/i18n-helper'; +import switchDirection from './helpers/utils/switch-direction'; import { getPermittedAccountsForCurrentTab, getSelectedAddress, -} from './app/selectors'; -import { ALERT_STATE } from './app/ducks/alerts'; +} from './selectors'; +import { ALERT_STATE } from './ducks/alerts'; import { getUnconnectedAccountAlertEnabledness, getUnconnectedAccountAlertShown, -} from './app/ducks/metamask/metamask'; +} from './ducks/metamask/metamask'; +import Root from './pages'; +import txHelper from './helpers/utils/tx-helper'; log.setLevel(global.METAMASK_DEBUG ? 'debug' : 'warn'); diff --git a/ui/lib/account-link.js b/ui/lib/account-link.js deleted file mode 100644 index 47d36908a..000000000 --- a/ui/lib/account-link.js +++ /dev/null @@ -1,12 +0,0 @@ -import { createAccountLinkForChain } from '@metamask/etherscan-link'; - -export default function getAccountLink(address, chainId, rpcPrefs) { - if (rpcPrefs && rpcPrefs.blockExplorerUrl) { - return `${rpcPrefs.blockExplorerUrl.replace( - /\/+$/u, - '', - )}/address/${address}`; - } - - return createAccountLinkForChain(address, chainId); -} diff --git a/ui/lib/account-link.test.js b/ui/lib/account-link.test.js deleted file mode 100644 index 4e464309f..000000000 --- a/ui/lib/account-link.test.js +++ /dev/null @@ -1,49 +0,0 @@ -import { - MAINNET_CHAIN_ID, - ROPSTEN_CHAIN_ID, -} from '../../shared/constants/network'; -import getAccountLink from './account-link'; - -describe('Account link', () => { - describe('getAccountLink', () => { - it('should return the correct block explorer url for an account', () => { - const tests = [ - { - expected: 'https://etherscan.io/address/0xabcd', - chainId: MAINNET_CHAIN_ID, - address: '0xabcd', - }, - { - expected: 'https://ropsten.etherscan.io/address/0xdef0', - chainId: ROPSTEN_CHAIN_ID, - address: '0xdef0', - rpcPrefs: {}, - }, - { - // test handling of `blockExplorerUrl` for a custom RPC - expected: 'https://block.explorer/address/0xabcd', - chainId: '0x21', - address: '0xabcd', - rpcPrefs: { - blockExplorerUrl: 'https://block.explorer', - }, - }, - { - // test handling of trailing `/` in `blockExplorerUrl` for a custom RPC - expected: 'https://another.block.explorer/address/0xdef0', - chainId: '0x1f', - address: '0xdef0', - rpcPrefs: { - blockExplorerUrl: 'https://another.block.explorer/', - }, - }, - ]; - - tests.forEach(({ expected, address, chainId, rpcPrefs }) => { - expect(getAccountLink(address, chainId, rpcPrefs)).toStrictEqual( - expected, - ); - }); - }); - }); -}); diff --git a/ui/lib/shallow-with-context.js b/ui/lib/shallow-with-context.js deleted file mode 100644 index 9cfb1bd75..000000000 --- a/ui/lib/shallow-with-context.js +++ /dev/null @@ -1,7 +0,0 @@ -import { shallow } from 'enzyme'; - -export default function shallowWithContext(jsxComponent) { - return shallow(jsxComponent, { - context: { t: (str1, str2) => (str2 ? str1 + str2 : str1) }, - }); -} diff --git a/ui/lib/test-timeout.js b/ui/lib/test-timeout.js deleted file mode 100644 index 8c29780a1..000000000 --- a/ui/lib/test-timeout.js +++ /dev/null @@ -1,5 +0,0 @@ -export default function timeout(time) { - return new Promise((resolve) => { - setTimeout(resolve, time || 1500); - }); -} diff --git a/ui/app/pages/add-token/add-token.component.js b/ui/pages/add-token/add-token.component.js similarity index 74% rename from ui/app/pages/add-token/add-token.component.js rename to ui/pages/add-token/add-token.component.js index cceeea624..36c215e2a 100644 --- a/ui/app/pages/add-token/add-token.component.js +++ b/ui/pages/add-token/add-token.component.js @@ -1,15 +1,20 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; +import { getTokenTrackerLink } from '@metamask/etherscan-link'; 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 PageContainer from '../../components/ui/page-container'; import { Tabs, Tab } from '../../components/ui/tabs'; -import { addHexPrefix } from '../../../../app/scripts/lib/util'; -import { isValidHexAddress } from '../../../../shared/modules/hexstring-utils'; -import TokenList from './token-list'; +import { addHexPrefix } from '../../../app/scripts/lib/util'; +import { isValidHexAddress } from '../../../shared/modules/hexstring-utils'; +import ActionableMessage from '../swaps/actionable-message'; +import Typography from '../../components/ui/typography'; +import { TYPOGRAPHY, FONT_WEIGHT } from '../../helpers/constants/design-system'; +import Button from '../../components/ui/button'; import TokenSearch from './token-search'; +import TokenList from './token-list'; const emptyAddr = '0x0000000000000000000000000000000000000000'; @@ -30,6 +35,8 @@ class AddToken extends Component { identities: PropTypes.object, showSearchTab: PropTypes.bool.isRequired, mostRecentOverviewPage: PropTypes.string.isRequired, + chainId: PropTypes.string, + rpcPrefs: PropTypes.object, }; state = { @@ -42,8 +49,9 @@ class AddToken extends Component { customAddressError: null, customSymbolError: null, customDecimalsError: null, - autoFilled: false, forceEditSymbol: false, + symbolAutoFilled: false, + decimalAutoFilled: false, }; componentDidMount() { @@ -148,10 +156,11 @@ class AddToken extends Component { } async attemptToAutoFillTokenParams(address) { - const { symbol = '', decimals = 0 } = await this.tokenInfoGetter(address); + const { symbol = '', decimals } = await this.tokenInfoGetter(address); - const autoFilled = Boolean(symbol && decimals); - this.setState({ autoFilled }); + const symbolAutoFilled = Boolean(symbol); + const decimalAutoFilled = Boolean(decimals); + this.setState({ symbolAutoFilled, decimalAutoFilled }); this.handleCustomSymbolChange(symbol || ''); this.handleCustomDecimalsChange(decimals); } @@ -162,7 +171,8 @@ class AddToken extends Component { customAddress, customAddressError: null, tokenSelectorError: null, - autoFilled: false, + symbolAutoFilled: false, + decimalAutoFilled: false, }); const addressIsValid = isValidHexAddress(customAddress, { @@ -213,16 +223,18 @@ class AddToken extends Component { } handleCustomDecimalsChange(value) { - const customDecimals = value.trim(); - const validDecimals = - customDecimals !== null && - customDecimals !== '' && - customDecimals >= MIN_DECIMAL_VALUE && - customDecimals <= MAX_DECIMAL_VALUE; + let customDecimals; let customDecimalsError = null; - if (!validDecimals) { - customDecimalsError = this.context.t('decimalsMustZerotoTen'); + if (value) { + customDecimals = Number(value.trim()); + customDecimalsError = + value < MIN_DECIMAL_VALUE || value > MAX_DECIMAL_VALUE + ? this.context.t('decimalsMustZerotoTen') + : null; + } else { + customDecimals = ''; + customDecimalsError = this.context.t('tokenDecimalFetchFailed'); } this.setState({ customDecimals, customDecimalsError }); @@ -236,10 +248,23 @@ class AddToken extends Component { customAddressError, customSymbolError, customDecimalsError, - autoFilled, forceEditSymbol, + symbolAutoFilled, + decimalAutoFilled, } = this.state; + const { chainId, rpcPrefs } = this.props; + const blockExplorerTokenLink = getTokenTrackerLink( + customAddress, + chainId, + null, + null, + { blockExplorerUrl: rpcPrefs?.blockExplorerUrl ?? null }, + ); + const blockExplorerLabel = rpcPrefs?.blockExplorerUrl + ? new URL(blockExplorerTokenLink).hostname + : this.context.t('etherscan'); + return ( <div className="add-token__custom-token-form"> <TextField @@ -260,7 +285,7 @@ class AddToken extends Component { <span className="add-token__custom-symbol__label"> {this.context.t('tokenSymbol')} </span> - {autoFilled && !forceEditSymbol && ( + {symbolAutoFilled && !forceEditSymbol && ( <div className="add-token__custom-symbol__edit" onClick={() => this.setState({ forceEditSymbol: true })} @@ -276,7 +301,7 @@ class AddToken extends Component { error={customSymbolError} fullWidth margin="normal" - disabled={autoFilled && !forceEditSymbol} + disabled={symbolAutoFilled && !forceEditSymbol} /> <TextField id="custom-decimals" @@ -284,13 +309,47 @@ class AddToken extends Component { type="number" value={customDecimals} onChange={(e) => this.handleCustomDecimalsChange(e.target.value)} - error={customDecimalsError} + error={customDecimals ? customDecimalsError : null} fullWidth margin="normal" - disabled={autoFilled} + disabled={decimalAutoFilled} min={MIN_DECIMAL_VALUE} max={MAX_DECIMAL_VALUE} /> + {customDecimals === '' && ( + <ActionableMessage + message={ + <> + <Typography + variant={TYPOGRAPHY.H7} + fontWeight={FONT_WEIGHT.BOLD} + > + {this.context.t('tokenDecimalFetchFailed')} + </Typography> + <Typography + variant={TYPOGRAPHY.H7} + fontWeight={FONT_WEIGHT.NORMAL} + > + {this.context.t('verifyThisTokenDecimalOn', [ + <Button + type="link" + key="add-token-verify-token-decimal" + className="add-token__link" + rel="noopener noreferrer" + target="_blank" + href={blockExplorerTokenLink} + > + {blockExplorerLabel} + </Button>, + ])} + </Typography> + </> + } + type="warning" + withRightButton + className="add-token__decimal-warning" + /> + )} </div> ); } diff --git a/ui/app/pages/add-token/add-token.container.js b/ui/pages/add-token/add-token.container.js similarity index 74% rename from ui/app/pages/add-token/add-token.container.js rename to ui/pages/add-token/add-token.container.js index ab8bf24c8..08f6505e3 100644 --- a/ui/app/pages/add-token/add-token.container.js +++ b/ui/pages/add-token/add-token.container.js @@ -2,12 +2,20 @@ import { connect } from 'react-redux'; import { setPendingTokens, clearPendingTokens } from '../../store/actions'; import { getMostRecentOverviewPage } from '../../ducks/history/history'; -import { getIsMainnet } from '../../selectors/selectors'; +import { + getIsMainnet, + getRpcPrefsForCurrentProvider, +} from '../../selectors/selectors'; import AddToken from './add-token.component'; const mapStateToProps = (state) => { const { - metamask: { identities, tokens, pendingTokens }, + metamask: { + identities, + tokens, + pendingTokens, + provider: { chainId }, + }, } = state; return { identities, @@ -15,6 +23,8 @@ const mapStateToProps = (state) => { tokens, pendingTokens, showSearchTab: getIsMainnet(state) || process.env.IN_TEST === 'true', + chainId, + rpcPrefs: getRpcPrefsForCurrentProvider(state), }; }; diff --git a/ui/app/pages/add-token/add-token.test.js b/ui/pages/add-token/add-token.test.js similarity index 96% rename from ui/app/pages/add-token/add-token.test.js rename to ui/pages/add-token/add-token.test.js index e91feafa7..4b36e7f39 100644 --- a/ui/app/pages/add-token/add-token.test.js +++ b/ui/pages/add-token/add-token.test.js @@ -2,7 +2,7 @@ import React from 'react'; import { Provider } from 'react-redux'; import sinon from 'sinon'; import configureMockStore from 'redux-mock-store'; -import { mountWithRouter } from '../../../../test/lib/render-helpers'; +import { mountWithRouter } from '../../../test/lib/render-helpers'; import AddToken from './add-token.container'; describe('Add Token', () => { @@ -82,7 +82,7 @@ describe('Add Token', () => { expect( wrapper.find('AddToken').instance().state.customDecimals, - ).toStrictEqual(tokenPrecision); + ).toStrictEqual(Number(tokenPrecision)); }); it('next', () => { diff --git a/ui/app/pages/add-token/index.js b/ui/pages/add-token/index.js similarity index 100% rename from ui/app/pages/add-token/index.js rename to ui/pages/add-token/index.js diff --git a/ui/app/pages/add-token/index.scss b/ui/pages/add-token/index.scss similarity index 80% rename from ui/app/pages/add-token/index.scss rename to ui/pages/add-token/index.scss index 5060a6348..581832ca4 100644 --- a/ui/app/pages/add-token/index.scss +++ b/ui/pages/add-token/index.scss @@ -1,6 +1,8 @@ @import 'token-list/index'; .add-token { + $self: &; + &__custom-token-form { padding: 8px 16px 16px; @@ -13,6 +15,9 @@ -webkit-appearance: none; display: none; } + & #{$self}__decimal-warning { + margin-top: 5px; + } } &__search-token { @@ -41,4 +46,12 @@ cursor: pointer; } } + + &__link { + @include H7; + + display: inline; + color: $primary-blue; + padding-left: 0; + } } diff --git a/ui/app/pages/add-token/token-list/index.js b/ui/pages/add-token/token-list/index.js similarity index 100% rename from ui/app/pages/add-token/token-list/index.js rename to ui/pages/add-token/token-list/index.js diff --git a/ui/app/pages/add-token/token-list/index.scss b/ui/pages/add-token/token-list/index.scss similarity index 100% rename from ui/app/pages/add-token/token-list/index.scss rename to ui/pages/add-token/token-list/index.scss diff --git a/ui/app/pages/add-token/token-list/token-list-placeholder/index.js b/ui/pages/add-token/token-list/token-list-placeholder/index.js similarity index 100% rename from ui/app/pages/add-token/token-list/token-list-placeholder/index.js rename to ui/pages/add-token/token-list/token-list-placeholder/index.js diff --git a/ui/app/pages/add-token/token-list/token-list-placeholder/index.scss b/ui/pages/add-token/token-list/token-list-placeholder/index.scss similarity index 100% rename from ui/app/pages/add-token/token-list/token-list-placeholder/index.scss rename to ui/pages/add-token/token-list/token-list-placeholder/index.scss diff --git a/ui/app/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js b/ui/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js similarity index 100% rename from ui/app/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js rename to ui/pages/add-token/token-list/token-list-placeholder/token-list-placeholder.component.js diff --git a/ui/app/pages/add-token/token-list/token-list.component.js b/ui/pages/add-token/token-list/token-list.component.js similarity index 100% rename from ui/app/pages/add-token/token-list/token-list.component.js rename to ui/pages/add-token/token-list/token-list.component.js diff --git a/ui/app/pages/add-token/token-list/token-list.container.js b/ui/pages/add-token/token-list/token-list.container.js similarity index 100% rename from ui/app/pages/add-token/token-list/token-list.container.js rename to ui/pages/add-token/token-list/token-list.container.js diff --git a/ui/app/pages/add-token/token-search/index.js b/ui/pages/add-token/token-search/index.js similarity index 100% rename from ui/app/pages/add-token/token-search/index.js rename to ui/pages/add-token/token-search/index.js diff --git a/ui/app/pages/add-token/token-search/token-search.component.js b/ui/pages/add-token/token-search/token-search.component.js similarity index 100% rename from ui/app/pages/add-token/token-search/token-search.component.js rename to ui/pages/add-token/token-search/token-search.component.js diff --git a/ui/app/pages/asset/asset.js b/ui/pages/asset/asset.js similarity index 100% rename from ui/app/pages/asset/asset.js rename to ui/pages/asset/asset.js diff --git a/ui/app/pages/asset/asset.scss b/ui/pages/asset/asset.scss similarity index 100% rename from ui/app/pages/asset/asset.scss rename to ui/pages/asset/asset.scss diff --git a/ui/app/pages/asset/components/asset-breadcrumb.js b/ui/pages/asset/components/asset-breadcrumb.js similarity index 100% rename from ui/app/pages/asset/components/asset-breadcrumb.js rename to ui/pages/asset/components/asset-breadcrumb.js diff --git a/ui/app/pages/asset/components/asset-navigation.js b/ui/pages/asset/components/asset-navigation.js similarity index 100% rename from ui/app/pages/asset/components/asset-navigation.js rename to ui/pages/asset/components/asset-navigation.js diff --git a/ui/app/pages/asset/components/asset-options.js b/ui/pages/asset/components/asset-options.js similarity index 90% rename from ui/app/pages/asset/components/asset-options.js rename to ui/pages/asset/components/asset-options.js index 3b3ee21c2..dbb4ba5c6 100644 --- a/ui/app/pages/asset/components/asset-options.js +++ b/ui/pages/asset/components/asset-options.js @@ -6,10 +6,11 @@ import { Menu, MenuItem } from '../../../components/ui/menu'; const AssetOptions = ({ onRemove, - onViewEtherscan, + onClickBlockExplorer, onViewAccountDetails, tokenSymbol, isNativeAsset, + isEthNetwork, }) => { const t = useContext(I18nContext); const [assetOptionsButtonElement, setAssetOptionsButtonElement] = useState( @@ -46,10 +47,10 @@ const AssetOptions = ({ data-testid="asset-options__etherscan" onClick={() => { setAssetOptionsOpen(false); - onViewEtherscan(); + onClickBlockExplorer(); }} > - {t('viewOnEtherscan')} + {isEthNetwork ? t('viewOnEtherscan') : t('viewinExplorer')} </MenuItem> {isNativeAsset ? null : ( <MenuItem @@ -70,9 +71,10 @@ const AssetOptions = ({ }; AssetOptions.propTypes = { + isEthNetwork: PropTypes.bool, isNativeAsset: PropTypes.bool, onRemove: PropTypes.func.isRequired, - onViewEtherscan: PropTypes.func.isRequired, + onClickBlockExplorer: PropTypes.func.isRequired, onViewAccountDetails: PropTypes.func.isRequired, tokenSymbol: PropTypes.string, }; diff --git a/ui/app/pages/asset/components/native-asset.js b/ui/pages/asset/components/native-asset.js similarity index 71% rename from ui/app/pages/asset/components/native-asset.js rename to ui/pages/asset/components/native-asset.js index f814c635a..6d17f512c 100644 --- a/ui/app/pages/asset/components/native-asset.js +++ b/ui/pages/asset/components/native-asset.js @@ -2,6 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { useSelector, useDispatch } from 'react-redux'; import { useHistory } from 'react-router-dom'; +import { getAccountLink } from '@metamask/etherscan-link'; import TransactionList from '../../../components/app/transaction-list'; import { EthOverview } from '../../../components/app/wallet-overview'; import { @@ -11,8 +12,8 @@ import { getSelectedAddress, } from '../../../selectors/selectors'; import { showModal } from '../../../store/actions'; -import getAccountLink from '../../../../lib/account-link'; import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; +import { useNewMetricEvent } from '../../../hooks/useMetricEvent'; import AssetNavigation from './asset-navigation'; import AssetOptions from './asset-options'; @@ -26,6 +27,17 @@ export default function NativeAsset({ nativeCurrency }) { const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); const address = useSelector(getSelectedAddress); const history = useHistory(); + const accountLink = getAccountLink(address, chainId, rpcPrefs); + + const blockExplorerLinkClickedEvent = useNewMetricEvent({ + category: 'Navigation', + event: 'Clicked Block Explorer Link', + properties: { + link_type: 'Account Tracker', + action: 'Asset Options', + block_explorer_domain: accountLink ? new URL(accountLink)?.hostname : '', + }, + }); return ( <> @@ -33,12 +45,14 @@ export default function NativeAsset({ nativeCurrency }) { accountName={selectedAccountName} assetName={nativeCurrency} onBack={() => history.push(DEFAULT_ROUTE)} + isEthNetwork={!rpcPrefs.blockExplorerUrl} optionsButton={ <AssetOptions isNativeAsset - onViewEtherscan={() => { + onClickBlockExplorer={() => { + blockExplorerLinkClickedEvent(); global.platform.openTab({ - url: getAccountLink(address, chainId, rpcPrefs), + url: accountLink, }); }} onViewAccountDetails={() => { diff --git a/ui/app/pages/asset/components/token-asset.js b/ui/pages/asset/components/token-asset.js similarity index 66% rename from ui/app/pages/asset/components/token-asset.js rename to ui/pages/asset/components/token-asset.js index 76566037e..c5b6410c0 100644 --- a/ui/app/pages/asset/components/token-asset.js +++ b/ui/pages/asset/components/token-asset.js @@ -2,16 +2,17 @@ import React from 'react'; import PropTypes from 'prop-types'; import { useDispatch, useSelector } from 'react-redux'; import { useHistory } from 'react-router-dom'; -import { createTokenTrackerLinkForChain } from '@metamask/etherscan-link'; - +import { getTokenTrackerLink } from '@metamask/etherscan-link'; import TransactionList from '../../../components/app/transaction-list'; import { TokenOverview } from '../../../components/app/wallet-overview'; import { getCurrentChainId, getSelectedIdentity, + getRpcPrefsForCurrentProvider, } from '../../../selectors/selectors'; import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; import { showModal } from '../../../store/actions'; +import { useNewMetricEvent } from '../../../hooks/useMetricEvent'; import AssetNavigation from './asset-navigation'; import AssetOptions from './asset-options'; @@ -19,10 +20,30 @@ import AssetOptions from './asset-options'; export default function TokenAsset({ token }) { const dispatch = useDispatch(); const chainId = useSelector(getCurrentChainId); + const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); const selectedIdentity = useSelector(getSelectedIdentity); const selectedAccountName = selectedIdentity.name; const selectedAddress = selectedIdentity.address; const history = useHistory(); + const tokenTrackerLink = getTokenTrackerLink( + token.address, + chainId, + null, + selectedAddress, + rpcPrefs, + ); + + const blockExplorerLinkClickedEvent = useNewMetricEvent({ + category: 'Navigation', + event: 'Clicked Block Explorer Link', + properties: { + link_type: 'Token Tracker', + action: 'Token Options', + block_explorer_domain: tokenTrackerLink + ? new URL(tokenTrackerLink)?.hostname + : '', + }, + }); return ( <> @@ -35,13 +56,10 @@ export default function TokenAsset({ token }) { onRemove={() => dispatch(showModal({ name: 'HIDE_TOKEN_CONFIRMATION', token })) } - onViewEtherscan={() => { - const url = createTokenTrackerLinkForChain( - token.address, - chainId, - selectedAddress, - ); - global.platform.openTab({ url }); + isEthNetwork={!rpcPrefs.blockExplorerUrl} + onClickBlockExplorer={() => { + blockExplorerLinkClickedEvent(); + global.platform.openTab({ url: tokenTrackerLink }); }} onViewAccountDetails={() => { dispatch(showModal({ name: 'ACCOUNT_DETAILS' })); diff --git a/ui/app/pages/asset/index.js b/ui/pages/asset/index.js similarity index 100% rename from ui/app/pages/asset/index.js rename to ui/pages/asset/index.js diff --git a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js b/ui/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js similarity index 97% rename from ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js rename to ui/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js index 5c8c0e1d6..41d506644 100644 --- a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js +++ b/ui/pages/confirm-add-suggested-token/confirm-add-suggested-token.component.js @@ -3,8 +3,8 @@ import PropTypes from 'prop-types'; import Button from '../../components/ui/button'; import Identicon from '../../components/ui/identicon'; import TokenBalance from '../../components/ui/token-balance'; -import { getEnvironmentType } from '../../../../app/scripts/lib/util'; -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../shared/constants/app'; export default class ConfirmAddSuggestedToken extends Component { static contextTypes = { diff --git a/ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js b/ui/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js similarity index 100% rename from ui/app/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js rename to ui/pages/confirm-add-suggested-token/confirm-add-suggested-token.container.js diff --git a/ui/app/pages/confirm-add-suggested-token/index.js b/ui/pages/confirm-add-suggested-token/index.js similarity index 100% rename from ui/app/pages/confirm-add-suggested-token/index.js rename to ui/pages/confirm-add-suggested-token/index.js diff --git a/ui/app/pages/confirm-add-token/confirm-add-token.component.js b/ui/pages/confirm-add-token/confirm-add-token.component.js similarity index 100% rename from ui/app/pages/confirm-add-token/confirm-add-token.component.js rename to ui/pages/confirm-add-token/confirm-add-token.component.js diff --git a/ui/app/pages/confirm-add-token/confirm-add-token.container.js b/ui/pages/confirm-add-token/confirm-add-token.container.js similarity index 100% rename from ui/app/pages/confirm-add-token/confirm-add-token.container.js rename to ui/pages/confirm-add-token/confirm-add-token.container.js diff --git a/ui/app/pages/confirm-add-token/index.js b/ui/pages/confirm-add-token/index.js similarity index 100% rename from ui/app/pages/confirm-add-token/index.js rename to ui/pages/confirm-add-token/index.js diff --git a/ui/app/pages/confirm-add-token/index.scss b/ui/pages/confirm-add-token/index.scss similarity index 100% rename from ui/app/pages/confirm-add-token/index.scss rename to ui/pages/confirm-add-token/index.scss diff --git a/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js b/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js similarity index 99% rename from ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js rename to ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js index 8f586d65e..05bb4c77b 100644 --- a/ui/app/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js +++ b/ui/pages/confirm-approve/confirm-approve-content/confirm-approve-content.component.js @@ -350,7 +350,7 @@ export default class ConfirmApproveContent extends Component { <div className="confirm-approve-content__full-tx-content"> <div className="confirm-approve-content__permission"> {this.renderApproveContentCard({ - symbol: <img src="/images/user-check.svg" alt="" />, + symbol: <img src="./images/user-check.svg" alt="" />, title: 'Permission', content: this.renderPermissionContent(), showEdit: true, diff --git a/ui/app/pages/confirm-approve/confirm-approve-content/index.js b/ui/pages/confirm-approve/confirm-approve-content/index.js similarity index 100% rename from ui/app/pages/confirm-approve/confirm-approve-content/index.js rename to ui/pages/confirm-approve/confirm-approve-content/index.js diff --git a/ui/app/pages/confirm-approve/confirm-approve-content/index.scss b/ui/pages/confirm-approve/confirm-approve-content/index.scss similarity index 100% rename from ui/app/pages/confirm-approve/confirm-approve-content/index.scss rename to ui/pages/confirm-approve/confirm-approve-content/index.scss diff --git a/ui/app/pages/confirm-approve/confirm-approve.js b/ui/pages/confirm-approve/confirm-approve.js similarity index 93% rename from ui/app/pages/confirm-approve/confirm-approve.js rename to ui/pages/confirm-approve/confirm-approve.js index 9eb51bd2a..a0257e7a4 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.js +++ b/ui/pages/confirm-approve/confirm-approve.js @@ -24,6 +24,9 @@ import { getUseNonceField, getCustomNonceValue, getNextSuggestedNonce, + getNoGasPriceFetched, + getIsEthGasPriceFetched, + getIsMainnet, } from '../../selectors'; import { currentNetworkTxListSelector } from '../../selectors/transactions'; import Loading from '../../components/ui/loading-screen'; @@ -116,7 +119,11 @@ export default function ConfirmApprove() { const customData = customPermissionAmount ? getCustomTxParamsData(data, { customPermissionAmount, decimals }) : null; - + const isEthGasPrice = useSelector(getIsEthGasPriceFetched); + const noGasPrice = useSelector(getNoGasPriceFetched); + const isMainnet = useSelector(getIsMainnet); + const hideBasic = + isEthGasPrice || noGasPrice || !(isMainnet || process.env.IN_TEST); return tokenSymbol === undefined ? ( <Loading /> ) : ( @@ -136,7 +143,13 @@ export default function ConfirmApprove() { tokenSymbol={tokenSymbol} tokenBalance={tokenBalance} showCustomizeGasModal={() => - dispatch(showModal({ name: 'CUSTOMIZE_GAS', txData })) + dispatch( + showModal({ + name: 'CUSTOMIZE_GAS', + txData, + hideBasic, + }), + ) } showEditApprovalPermissionModal={({ /* eslint-disable no-shadow */ diff --git a/ui/pages/confirm-approve/confirm-approve.stories.js b/ui/pages/confirm-approve/confirm-approve.stories.js new file mode 100644 index 000000000..35ee95e31 --- /dev/null +++ b/ui/pages/confirm-approve/confirm-approve.stories.js @@ -0,0 +1,67 @@ +/* eslint-disable react/prop-types */ +import React, { useEffect } from 'react'; +import { text } from '@storybook/addon-knobs'; +import { useParams } from 'react-router-dom'; +import { useSelector } from 'react-redux'; +import { updateMetamaskState } from '../../store/actions'; +import { currentNetworkTxListSelector } from '../../selectors/transactions'; +import { store } from '../../../.storybook/preview'; + +import { + currentNetworkTxListSample, + domainMetadata, +} from '../../../.storybook/initial-states/approval-screens/token-approval'; +import ConfirmApprove from '.'; + +export default { + title: 'Confirmation Screens', +}; + +// transaction ID, maps to entry in state.metamask.currentNetworkTxList +const txId = 7900715443136469; + +const PageSet = ({ children }) => { + const origin = text('Origin', 'https://metamask.github.io'); + const domainIconUrl = text( + 'Icon URL', + 'https://metamask.github.io/test-dapp/metamask-fox.svg', + ); + + const currentNetworkTxList = useSelector(currentNetworkTxListSelector); + const transaction = currentNetworkTxList.find(({ id }) => id === txId); + + useEffect(() => { + transaction.origin = origin; + store.dispatch( + updateMetamaskState({ currentNetworkTxList: [transaction] }), + ); + }, [origin, transaction]); + + useEffect(() => { + store.dispatch( + updateMetamaskState({ + domainMetadata: { + [origin]: { + icon: domainIconUrl, + }, + }, + }), + ); + }, [domainIconUrl, origin]); + + const params = useParams(); + params.id = txId; + return children; +}; + +export const ApproveTokens = () => { + store.dispatch( + updateMetamaskState({ currentNetworkTxList: [currentNetworkTxListSample] }), + ); + store.dispatch(updateMetamaskState({ domainMetadata })); + return ( + <PageSet> + <ConfirmApprove /> + </PageSet> + ); +}; diff --git a/ui/app/pages/confirm-approve/confirm-approve.util.js b/ui/pages/confirm-approve/confirm-approve.util.js similarity index 94% rename from ui/app/pages/confirm-approve/confirm-approve.util.js rename to ui/pages/confirm-approve/confirm-approve.util.js index 3345b0966..240925611 100644 --- a/ui/app/pages/confirm-approve/confirm-approve.util.js +++ b/ui/pages/confirm-approve/confirm-approve.util.js @@ -1,4 +1,4 @@ -import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; +import { TRANSACTION_TYPES } from '../../../shared/constants/transaction'; import { decimalToHex } from '../../helpers/utils/conversions.util'; import { calcTokenValue, diff --git a/ui/app/pages/confirm-approve/index.js b/ui/pages/confirm-approve/index.js similarity index 100% rename from ui/app/pages/confirm-approve/index.js rename to ui/pages/confirm-approve/index.js diff --git a/ui/app/pages/confirm-approve/index.scss b/ui/pages/confirm-approve/index.scss similarity index 100% rename from ui/app/pages/confirm-approve/index.scss rename to ui/pages/confirm-approve/index.scss diff --git a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js b/ui/pages/confirm-decrypt-message/confirm-decrypt-message.component.js similarity index 98% rename from ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js rename to ui/pages/confirm-decrypt-message/confirm-decrypt-message.component.js index 3ed8f67c2..ffbbccf19 100644 --- a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js +++ b/ui/pages/confirm-decrypt-message/confirm-decrypt-message.component.js @@ -9,8 +9,8 @@ import Identicon from '../../components/ui/identicon'; import Tooltip from '../../components/ui/tooltip'; import Copy from '../../components/ui/icon/copy-icon.component'; -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; -import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../shared/constants/app'; +import { getEnvironmentType } from '../../../app/scripts/lib/util'; import { conversionUtil } from '../../helpers/utils/conversion-util'; export default class ConfirmDecryptMessage extends Component { diff --git a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js b/ui/pages/confirm-decrypt-message/confirm-decrypt-message.container.js similarity index 100% rename from ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js rename to ui/pages/confirm-decrypt-message/confirm-decrypt-message.container.js diff --git a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.scss b/ui/pages/confirm-decrypt-message/confirm-decrypt-message.scss similarity index 100% rename from ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.scss rename to ui/pages/confirm-decrypt-message/confirm-decrypt-message.scss diff --git a/ui/app/pages/confirm-decrypt-message/index.js b/ui/pages/confirm-decrypt-message/index.js similarity index 100% rename from ui/app/pages/confirm-decrypt-message/index.js rename to ui/pages/confirm-decrypt-message/index.js diff --git a/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.component.js b/ui/pages/confirm-deploy-contract/confirm-deploy-contract.component.js similarity index 95% rename from ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.component.js rename to ui/pages/confirm-deploy-contract/confirm-deploy-contract.component.js index 231cd484a..63026bfaa 100644 --- a/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.component.js +++ b/ui/pages/confirm-deploy-contract/confirm-deploy-contract.component.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import ConfirmTransactionBase from '../confirm-transaction-base'; -import { toBuffer } from '../../../../shared/modules/buffer-utils'; +import { toBuffer } from '../../../shared/modules/buffer-utils'; export default class ConfirmDeployContract extends Component { static contextTypes = { diff --git a/ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.container.js b/ui/pages/confirm-deploy-contract/confirm-deploy-contract.container.js similarity index 100% rename from ui/app/pages/confirm-deploy-contract/confirm-deploy-contract.container.js rename to ui/pages/confirm-deploy-contract/confirm-deploy-contract.container.js diff --git a/ui/app/pages/confirm-deploy-contract/index.js b/ui/pages/confirm-deploy-contract/index.js similarity index 100% rename from ui/app/pages/confirm-deploy-contract/index.js rename to ui/pages/confirm-deploy-contract/index.js diff --git a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js b/ui/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js similarity index 97% rename from ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js rename to ui/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js index fb4100832..2382ea0bc 100644 --- a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js +++ b/ui/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js @@ -5,8 +5,8 @@ import AccountListItem from '../../components/app/account-list-item'; import Button from '../../components/ui/button'; import Identicon from '../../components/ui/identicon'; -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; -import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../shared/constants/app'; +import { getEnvironmentType } from '../../../app/scripts/lib/util'; import { conversionUtil } from '../../helpers/utils/conversion-util'; export default class ConfirmEncryptionPublicKey extends Component { diff --git a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js b/ui/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js similarity index 100% rename from ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js rename to ui/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js diff --git a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.scss b/ui/pages/confirm-encryption-public-key/confirm-encryption-public-key.scss similarity index 100% rename from ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.scss rename to ui/pages/confirm-encryption-public-key/confirm-encryption-public-key.scss diff --git a/ui/app/pages/confirm-encryption-public-key/index.js b/ui/pages/confirm-encryption-public-key/index.js similarity index 100% rename from ui/app/pages/confirm-encryption-public-key/index.js rename to ui/pages/confirm-encryption-public-key/index.js diff --git a/ui/app/pages/confirm-send-ether/confirm-send-ether.component.js b/ui/pages/confirm-send-ether/confirm-send-ether.component.js similarity index 100% rename from ui/app/pages/confirm-send-ether/confirm-send-ether.component.js rename to ui/pages/confirm-send-ether/confirm-send-ether.component.js diff --git a/ui/app/pages/confirm-send-ether/confirm-send-ether.container.js b/ui/pages/confirm-send-ether/confirm-send-ether.container.js similarity index 100% rename from ui/app/pages/confirm-send-ether/confirm-send-ether.container.js rename to ui/pages/confirm-send-ether/confirm-send-ether.container.js diff --git a/ui/app/pages/confirm-send-ether/index.js b/ui/pages/confirm-send-ether/index.js similarity index 100% rename from ui/app/pages/confirm-send-ether/index.js rename to ui/pages/confirm-send-ether/index.js diff --git a/ui/app/pages/confirm-send-token/confirm-send-token.component.js b/ui/pages/confirm-send-token/confirm-send-token.component.js similarity index 100% rename from ui/app/pages/confirm-send-token/confirm-send-token.component.js rename to ui/pages/confirm-send-token/confirm-send-token.component.js diff --git a/ui/app/pages/confirm-send-token/confirm-send-token.container.js b/ui/pages/confirm-send-token/confirm-send-token.container.js similarity index 100% rename from ui/app/pages/confirm-send-token/confirm-send-token.container.js rename to ui/pages/confirm-send-token/confirm-send-token.container.js diff --git a/ui/app/pages/confirm-send-token/index.js b/ui/pages/confirm-send-token/index.js similarity index 100% rename from ui/app/pages/confirm-send-token/index.js rename to ui/pages/confirm-send-token/index.js diff --git a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js b/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js similarity index 98% rename from ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js rename to ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js index a03cee3ef..b15a5f99e 100644 --- a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js +++ b/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.component.js @@ -86,7 +86,7 @@ export default function ConfirmTokenTransactionBase({ primaryTotalTextOverride={ <div> <span>{`${tokensText} + `}</span> - <img src="/images/eth.svg" height="18" alt="" /> + <img src="./images/eth.svg" height="18" alt="" /> <span>{ethTransactionTotal}</span> </div> } diff --git a/ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js b/ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js similarity index 100% rename from ui/app/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js rename to ui/pages/confirm-token-transaction-base/confirm-token-transaction-base.container.js diff --git a/ui/app/pages/confirm-token-transaction-base/index.js b/ui/pages/confirm-token-transaction-base/index.js similarity index 100% rename from ui/app/pages/confirm-token-transaction-base/index.js rename to ui/pages/confirm-token-transaction-base/index.js diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/pages/confirm-transaction-base/confirm-transaction-base.component.js similarity index 90% rename from ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js rename to ui/pages/confirm-transaction-base/confirm-transaction-base.component.js index e20efc83a..8a8e9e47e 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -1,16 +1,21 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; -import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../shared/constants/app'; +import { getEnvironmentType } from '../../../app/scripts/lib/util'; import ConfirmPageContainer, { ConfirmDetailRow, } from '../../components/app/confirm-page-container'; import { isBalanceSufficient } from '../send/send.utils'; -import { CONFIRM_TRANSACTION_ROUTE } from '../../helpers/constants/routes'; +import { + CONFIRM_TRANSACTION_ROUTE, + DEFAULT_ROUTE, +} from '../../helpers/constants/routes'; import { INSUFFICIENT_FUNDS_ERROR_KEY, TRANSACTION_ERROR_KEY, GAS_LIMIT_TOO_LOW_ERROR_KEY, + ETH_GAS_PRICE_FETCH_WARNING_KEY, + GAS_PRICE_FETCH_FAILURE_ERROR_KEY, } from '../../helpers/constants/error-keys'; import UserPreferencedCurrencyDisplay from '../../components/app/user-preferenced-currency-display'; import { PRIMARY, SECONDARY } from '../../helpers/constants/common'; @@ -20,9 +25,10 @@ import TextField from '../../components/ui/text-field'; import { TRANSACTION_TYPES, TRANSACTION_STATUSES, -} from '../../../../shared/constants/transaction'; +} from '../../../shared/constants/transaction'; import { getTransactionTypeTitle } from '../../helpers/utils/transactions.util'; -import { toBuffer } from '../../../../shared/modules/buffer-utils'; +import ErrorMessage from '../../components/ui/error-message'; +import { toBuffer } from '../../../shared/modules/buffer-utils'; export default class ConfirmTransactionBase extends Component { static contextTypes = { @@ -95,12 +101,16 @@ export default class ConfirmTransactionBase extends Component { showAccountInHeader: PropTypes.bool, mostRecentOverviewPage: PropTypes.string.isRequired, isMainnet: PropTypes.bool, + isEthGasPrice: PropTypes.bool, + noGasPrice: PropTypes.bool, + setDefaultHomeActiveTabName: PropTypes.func, }; state = { submitting: false, submitError: null, submitWarning: '', + ethGasPriceWarning: '', }; componentDidUpdate(prevProps) { @@ -109,17 +119,19 @@ export default class ConfirmTransactionBase extends Component { showTransactionConfirmedModal, history, clearConfirmTransaction, - mostRecentOverviewPage, nextNonce, customNonceValue, toAddress, tryReverseResolveAddress, + isEthGasPrice, + setDefaultHomeActiveTabName, } = this.props; const { customNonceValue: prevCustomNonceValue, nextNonce: prevNextNonce, toAddress: prevToAddress, transactionStatus: prevTxStatus, + isEthGasPrice: prevIsEthGasPrice, } = prevProps; const statusUpdated = transactionStatus !== prevTxStatus; const txDroppedOrConfirmed = @@ -143,7 +155,9 @@ export default class ConfirmTransactionBase extends Component { showTransactionConfirmedModal({ onSubmit: () => { clearConfirmTransaction(); - history.push(mostRecentOverviewPage); + setDefaultHomeActiveTabName('Activity').then(() => { + history.push(DEFAULT_ROUTE); + }); }, }); } @@ -151,6 +165,18 @@ export default class ConfirmTransactionBase extends Component { if (toAddress && toAddress !== prevToAddress) { tryReverseResolveAddress(toAddress); } + + if (isEthGasPrice !== prevIsEthGasPrice) { + if (isEthGasPrice) { + this.setState({ + ethGasPriceWarning: this.context.t(ETH_GAS_PRICE_FETCH_WARNING_KEY), + }); + } else { + this.setState({ + ethGasPriceWarning: '', + }); + } + } } getErrorKey() { @@ -160,6 +186,7 @@ export default class ConfirmTransactionBase extends Component { hexTransactionFee, txData: { simulationFails, txParams: { value: amount } = {} } = {}, customGas, + noGasPrice, } = this.props; const insufficientBalance = @@ -194,6 +221,13 @@ export default class ConfirmTransactionBase extends Component { }; } + if (noGasPrice) { + return { + valid: false, + errorKey: GAS_PRICE_FETCH_FAILURE_ERROR_KEY, + }; + } + return { valid: true, }; @@ -243,9 +277,12 @@ export default class ConfirmTransactionBase extends Component { nextNonce, getNextNonce, isMainnet, + isEthGasPrice, + noGasPrice, } = this.props; const notMainnetOrTest = !(isMainnet || process.env.IN_TEST); + const gasPriceFetchFailure = isEthGasPrice || noGasPrice; return ( <div className="confirm-page-container-content__details"> @@ -253,18 +290,26 @@ export default class ConfirmTransactionBase extends Component { <ConfirmDetailRow label="Gas Fee" value={hexTransactionFee} - headerText={notMainnetOrTest ? '' : 'Edit'} + headerText={notMainnetOrTest || gasPriceFetchFailure ? '' : 'Edit'} headerTextClassName={ - notMainnetOrTest ? '' : 'confirm-detail-row__header-text--edit' + notMainnetOrTest || gasPriceFetchFailure + ? '' + : 'confirm-detail-row__header-text--edit' + } + onHeaderClick={ + notMainnetOrTest || gasPriceFetchFailure + ? null + : () => this.handleEditGas() } - onHeaderClick={notMainnetOrTest ? null : () => this.handleEditGas()} secondaryText={ hideFiatConversion ? this.context.t('noConversionRateAvailable') : '' } /> - {advancedInlineGasShown || notMainnetOrTest ? ( + {advancedInlineGasShown || + notMainnetOrTest || + gasPriceFetchFailure ? ( <AdvancedGasInputs updateCustomGasPrice={(newGasPrice) => updateGasAndCalculate({ ...customGas, gasPrice: newGasPrice }) @@ -279,6 +324,11 @@ export default class ConfirmTransactionBase extends Component { isSpeedUp={false} /> ) : null} + {noGasPrice ? ( + <div className="confirm-page-container-content__error-container"> + <ErrorMessage errorKey={GAS_PRICE_FETCH_FAILURE_ERROR_KEY} /> + </div> + ) : null} </div> <div className={ @@ -672,7 +722,12 @@ export default class ConfirmTransactionBase extends Component { showAccountInHeader, txData, } = this.props; - const { submitting, submitError, submitWarning } = this.state; + const { + submitting, + submitError, + submitWarning, + ethGasPriceWarning, + } = this.state; const { name } = methodData; const { valid, errorKey } = this.getErrorKey(); @@ -696,7 +751,6 @@ export default class ConfirmTransactionBase extends Component { functionType = t('contractInteraction'); } } - return ( <ConfirmPageContainer fromName={fromName} @@ -739,6 +793,7 @@ export default class ConfirmTransactionBase extends Component { onSubmit={() => this.handleSubmit()} hideSenderToRecipient={hideSenderToRecipient} origin={txData.origin} + ethGasPriceWarning={ethGasPriceWarning} /> ); } diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.test.js b/ui/pages/confirm-transaction-base/confirm-transaction-base.component.test.js similarity index 100% rename from ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.test.js rename to ui/pages/confirm-transaction-base/confirm-transaction-base.component.test.js diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js similarity index 93% rename from ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js rename to ui/pages/confirm-transaction-base/confirm-transaction-base.container.js index 48d4ff814..6af7e49a9 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/pages/confirm-transaction-base/confirm-transaction-base.container.js @@ -14,6 +14,7 @@ import { updateTransaction, getNextNonce, tryReverseResolveAddress, + setDefaultHomeActiveTabName, } from '../../store/actions'; import { INSUFFICIENT_FUNDS_ERROR_KEY, @@ -33,10 +34,12 @@ import { getUseNonceField, getPreferences, transactionFeeSelector, + getNoGasPriceFetched, + getIsEthGasPriceFetched, } from '../../selectors'; import { getMostRecentOverviewPage } from '../../ducks/history/history'; -import { transactionMatchesNetwork } from '../../../../shared/modules/transaction.utils'; -import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils'; +import { transactionMatchesNetwork } from '../../../shared/modules/transaction.utils'; +import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils'; import ConfirmTransactionBase from './confirm-transaction-base.component'; const casedContractMap = Object.keys(contractMap).reduce((acc, base) => { @@ -147,6 +150,8 @@ const mapStateToProps = (state, ownProps) => { }; } customNonceValue = getCustomNonceValue(state); + const isEthGasPrice = getIsEthGasPriceFetched(state); + const noGasPrice = getNoGasPriceFetched(state); return { balance, @@ -186,6 +191,8 @@ const mapStateToProps = (state, ownProps) => { nextNonce, mostRecentOverviewPage: getMostRecentOverviewPage(state), isMainnet, + isEthGasPrice, + noGasPrice, }; }; @@ -204,7 +211,12 @@ export const mapDispatchToProps = (dispatch) => { }, showCustomizeGasModal: ({ txData, onSubmit, validate }) => { return dispatch( - showModal({ name: 'CUSTOMIZE_GAS', txData, onSubmit, validate }), + showModal({ + name: 'CUSTOMIZE_GAS', + txData, + onSubmit, + validate, + }), ); }, updateGasAndCalculate: (updatedTx) => { @@ -224,6 +236,8 @@ export const mapDispatchToProps = (dispatch) => { dispatch(updateAndApproveTx(customNonceMerge(txData))), setMetaMetricsSendCount: (val) => dispatch(setMetaMetricsSendCount(val)), getNextNonce: () => dispatch(getNextNonce()), + setDefaultHomeActiveTabName: (tabName) => + dispatch(setDefaultHomeActiveTabName(tabName)), }; }; @@ -275,6 +289,7 @@ const getValidateEditGas = ({ balance, conversionRate, txData }) => { const mergeProps = (stateProps, dispatchProps, ownProps) => { const { balance, conversionRate, txData, unapprovedTxs } = stateProps; + const { cancelAllTransactions: dispatchCancelAllTransactions, showCustomizeGasModal: dispatchShowCustomizeGasModal, diff --git a/ui/app/pages/confirm-transaction-base/index.js b/ui/pages/confirm-transaction-base/index.js similarity index 100% rename from ui/app/pages/confirm-transaction-base/index.js rename to ui/pages/confirm-transaction-base/index.js diff --git a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js b/ui/pages/confirm-transaction-switch/confirm-transaction-switch.component.js similarity index 95% rename from ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js rename to ui/pages/confirm-transaction-switch/confirm-transaction-switch.component.js index 83aa7cdbc..6a708e54d 100644 --- a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.component.js +++ b/ui/pages/confirm-transaction-switch/confirm-transaction-switch.component.js @@ -14,8 +14,8 @@ import { DECRYPT_MESSAGE_REQUEST_PATH, ENCRYPTION_PUBLIC_KEY_REQUEST_PATH, } from '../../helpers/constants/routes'; -import { MESSAGE_TYPE } from '../../../../shared/constants/app'; -import { TRANSACTION_TYPES } from '../../../../shared/constants/transaction'; +import { MESSAGE_TYPE } from '../../../shared/constants/app'; +import { TRANSACTION_TYPES } from '../../../shared/constants/transaction'; export default class ConfirmTransactionSwitch extends Component { static propTypes = { diff --git a/ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js b/ui/pages/confirm-transaction-switch/confirm-transaction-switch.container.js similarity index 100% rename from ui/app/pages/confirm-transaction-switch/confirm-transaction-switch.container.js rename to ui/pages/confirm-transaction-switch/confirm-transaction-switch.container.js diff --git a/ui/app/pages/confirm-transaction-switch/index.js b/ui/pages/confirm-transaction-switch/index.js similarity index 100% rename from ui/app/pages/confirm-transaction-switch/index.js rename to ui/pages/confirm-transaction-switch/index.js diff --git a/ui/app/pages/confirm-transaction/conf-tx.js b/ui/pages/confirm-transaction/conf-tx.js similarity index 97% rename from ui/app/pages/confirm-transaction/conf-tx.js rename to ui/pages/confirm-transaction/conf-tx.js index ef8657424..23f6e2375 100644 --- a/ui/app/pages/confirm-transaction/conf-tx.js +++ b/ui/pages/confirm-transaction/conf-tx.js @@ -5,13 +5,13 @@ 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 txHelper from '../../helpers/utils/tx-helper'; import SignatureRequest from '../../components/app/signature-request'; import SignatureRequestOriginal from '../../components/app/signature-request-original'; import Loading from '../../components/ui/loading-screen'; import { getMostRecentOverviewPage } from '../../ducks/history/history'; -import { MESSAGE_TYPE } from '../../../../shared/constants/app'; -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; +import { MESSAGE_TYPE } from '../../../shared/constants/app'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; function mapStateToProps(state) { const { metamask, appState } = state; diff --git a/ui/app/pages/confirm-transaction/confirm-transaction.component.js b/ui/pages/confirm-transaction/confirm-transaction.component.js similarity index 96% rename from ui/app/pages/confirm-transaction/confirm-transaction.component.js rename to ui/pages/confirm-transaction/confirm-transaction.component.js index c08b4f387..b88424cc7 100644 --- a/ui/app/pages/confirm-transaction/confirm-transaction.component.js +++ b/ui/pages/confirm-transaction/confirm-transaction.component.js @@ -23,6 +23,7 @@ import { SIGNATURE_REQUEST_PATH, DECRYPT_MESSAGE_REQUEST_PATH, ENCRYPTION_PUBLIC_KEY_REQUEST_PATH, + DEFAULT_ROUTE, } from '../../helpers/constants/routes'; import ConfTx from './conf-tx'; @@ -45,6 +46,7 @@ export default class ConfirmTransaction extends Component { paramsTransactionId: PropTypes.string, getTokenParams: PropTypes.func, isTokenMethodAction: PropTypes.bool, + setDefaultHomeActiveTabName: PropTypes.func, }; componentDidMount() { @@ -89,6 +91,7 @@ export default class ConfirmTransaction extends Component { history, mostRecentOverviewPage, totalUnapprovedCount, + setDefaultHomeActiveTabName, } = this.props; if ( @@ -104,7 +107,9 @@ export default class ConfirmTransaction extends Component { !transactionId && !totalUnapprovedCount ) { - history.replace(mostRecentOverviewPage); + setDefaultHomeActiveTabName('Activity').then(() => { + history.replace(DEFAULT_ROUTE); + }); } else if ( prevProps.transactionId && transactionId && diff --git a/ui/app/pages/confirm-transaction/confirm-transaction.container.js b/ui/pages/confirm-transaction/confirm-transaction.container.js similarity index 90% rename from ui/app/pages/confirm-transaction/confirm-transaction.container.js rename to ui/pages/confirm-transaction/confirm-transaction.container.js index 68ee7c3ed..21acaa7ff 100644 --- a/ui/app/pages/confirm-transaction/confirm-transaction.container.js +++ b/ui/pages/confirm-transaction/confirm-transaction.container.js @@ -8,7 +8,11 @@ import { import { isTokenMethodAction } from '../../helpers/utils/transactions.util'; import { fetchBasicGasEstimates } from '../../ducks/gas/gas.duck'; -import { getContractMethodData, getTokenParams } from '../../store/actions'; +import { + getContractMethodData, + getTokenParams, + setDefaultHomeActiveTabName, +} from '../../store/actions'; import { unconfirmedTransactionsListSelector } from '../../selectors'; import { getMostRecentOverviewPage } from '../../ducks/history/history'; import ConfirmTransaction from './confirm-transaction.component'; @@ -51,6 +55,8 @@ const mapDispatchToProps = (dispatch) => { fetchBasicGasEstimates: () => dispatch(fetchBasicGasEstimates()), getContractMethodData: (data) => dispatch(getContractMethodData(data)), getTokenParams: (tokenAddress) => dispatch(getTokenParams(tokenAddress)), + setDefaultHomeActiveTabName: (tabName) => + dispatch(setDefaultHomeActiveTabName(tabName)), }; }; diff --git a/ui/app/pages/confirm-transaction/index.js b/ui/pages/confirm-transaction/index.js similarity index 100% rename from ui/app/pages/confirm-transaction/index.js rename to ui/pages/confirm-transaction/index.js diff --git a/ui/app/pages/confirmation/components/confirmation-footer/confirmation-footer.js b/ui/pages/confirmation/components/confirmation-footer/confirmation-footer.js similarity index 100% rename from ui/app/pages/confirmation/components/confirmation-footer/confirmation-footer.js rename to ui/pages/confirmation/components/confirmation-footer/confirmation-footer.js diff --git a/ui/app/pages/confirmation/components/confirmation-footer/confirmation-footer.scss b/ui/pages/confirmation/components/confirmation-footer/confirmation-footer.scss similarity index 100% rename from ui/app/pages/confirmation/components/confirmation-footer/confirmation-footer.scss rename to ui/pages/confirmation/components/confirmation-footer/confirmation-footer.scss diff --git a/ui/app/pages/confirmation/components/confirmation-footer/index.js b/ui/pages/confirmation/components/confirmation-footer/index.js similarity index 100% rename from ui/app/pages/confirmation/components/confirmation-footer/index.js rename to ui/pages/confirmation/components/confirmation-footer/index.js diff --git a/ui/app/pages/confirmation/confirmation.js b/ui/pages/confirmation/confirmation.js similarity index 100% rename from ui/app/pages/confirmation/confirmation.js rename to ui/pages/confirmation/confirmation.js diff --git a/ui/app/pages/confirmation/confirmation.scss b/ui/pages/confirmation/confirmation.scss similarity index 100% rename from ui/app/pages/confirmation/confirmation.scss rename to ui/pages/confirmation/confirmation.scss diff --git a/ui/app/pages/confirmation/index.js b/ui/pages/confirmation/index.js similarity index 100% rename from ui/app/pages/confirmation/index.js rename to ui/pages/confirmation/index.js diff --git a/ui/app/pages/confirmation/templates/add-ethereum-chain.js b/ui/pages/confirmation/templates/add-ethereum-chain.js similarity index 100% rename from ui/app/pages/confirmation/templates/add-ethereum-chain.js rename to ui/pages/confirmation/templates/add-ethereum-chain.js diff --git a/ui/app/pages/confirmation/templates/index.js b/ui/pages/confirmation/templates/index.js similarity index 98% rename from ui/app/pages/confirmation/templates/index.js rename to ui/pages/confirmation/templates/index.js index 3c90a68fd..a4e873735 100644 --- a/ui/app/pages/confirmation/templates/index.js +++ b/ui/pages/confirmation/templates/index.js @@ -1,5 +1,5 @@ import { omit, pick } from 'lodash'; -import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; +import { MESSAGE_TYPE } from '../../../../shared/constants/app'; import { rejectPendingApproval, resolvePendingApproval, diff --git a/ui/app/pages/confirmation/templates/switch-ethereum-chain.js b/ui/pages/confirmation/templates/switch-ethereum-chain.js similarity index 86% rename from ui/app/pages/confirmation/templates/switch-ethereum-chain.js rename to ui/pages/confirmation/templates/switch-ethereum-chain.js index 4dc351027..08affd769 100644 --- a/ui/app/pages/confirmation/templates/switch-ethereum-chain.js +++ b/ui/pages/confirmation/templates/switch-ethereum-chain.js @@ -1,5 +1,8 @@ import { ethErrors } from 'eth-rpc-errors'; -import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; +import { + CHAIN_ID_TO_TYPE_MAP, + NETWORK_TYPE_RPC, +} from '../../../../shared/constants/network'; import { JUSTIFY_CONTENT, SEVERITIES, @@ -24,6 +27,14 @@ async function getAlerts() { return [PENDING_TX_DROP_NOTICE]; } +function getNetworkType(chainId) { + if (chainId in CHAIN_ID_TO_TYPE_MAP) { + return CHAIN_ID_TO_TYPE_MAP[chainId]; + } + + return NETWORK_TYPE_RPC; +} + function getValues(pendingApproval, t, actions) { return { content: [ @@ -65,7 +76,7 @@ function getValues(pendingApproval, t, actions) { colored: false, outline: true, targetNetwork: { - type: NETWORK_TYPE_RPC, + type: getNetworkType(pendingApproval.requestData.chainId), nickname: pendingApproval.requestData.nickname, }, }, diff --git a/ui/app/pages/connected-accounts/connected-accounts.component.js b/ui/pages/connected-accounts/connected-accounts.component.js similarity index 100% rename from ui/app/pages/connected-accounts/connected-accounts.component.js rename to ui/pages/connected-accounts/connected-accounts.component.js diff --git a/ui/app/pages/connected-accounts/connected-accounts.container.js b/ui/pages/connected-accounts/connected-accounts.container.js similarity index 100% rename from ui/app/pages/connected-accounts/connected-accounts.container.js rename to ui/pages/connected-accounts/connected-accounts.container.js diff --git a/ui/app/pages/connected-accounts/index.js b/ui/pages/connected-accounts/index.js similarity index 100% rename from ui/app/pages/connected-accounts/index.js rename to ui/pages/connected-accounts/index.js diff --git a/ui/app/pages/connected-accounts/index.scss b/ui/pages/connected-accounts/index.scss similarity index 100% rename from ui/app/pages/connected-accounts/index.scss rename to ui/pages/connected-accounts/index.scss diff --git a/ui/app/pages/connected-sites/connected-sites.component.js b/ui/pages/connected-sites/connected-sites.component.js similarity index 100% rename from ui/app/pages/connected-sites/connected-sites.component.js rename to ui/pages/connected-sites/connected-sites.component.js diff --git a/ui/app/pages/connected-sites/connected-sites.container.js b/ui/pages/connected-sites/connected-sites.container.js similarity index 100% rename from ui/app/pages/connected-sites/connected-sites.container.js rename to ui/pages/connected-sites/connected-sites.container.js diff --git a/ui/app/pages/connected-sites/index.js b/ui/pages/connected-sites/index.js similarity index 100% rename from ui/app/pages/connected-sites/index.js rename to ui/pages/connected-sites/index.js diff --git a/ui/app/pages/connected-sites/index.scss b/ui/pages/connected-sites/index.scss similarity index 100% rename from ui/app/pages/connected-sites/index.scss rename to ui/pages/connected-sites/index.scss diff --git a/ui/app/pages/create-account/connect-hardware/account-list.js b/ui/pages/create-account/connect-hardware/account-list.js similarity index 89% rename from ui/app/pages/create-account/connect-hardware/account-list.js rename to ui/pages/create-account/connect-hardware/account-list.js index 7449b0f19..a3bb775df 100644 --- a/ui/app/pages/create-account/connect-hardware/account-list.js +++ b/ui/pages/create-account/connect-hardware/account-list.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; -import getAccountLink from '../../../../lib/account-link'; +import { getAccountLink } from '@metamask/etherscan-link'; + import Button from '../../../components/ui/button'; import Checkbox from '../../../components/ui/check-box'; import Dropdown from '../../../components/ui/dropdown'; @@ -83,7 +84,7 @@ class AccountList extends Component { } renderAccounts() { - const { accounts, connectedAccounts } = this.props; + const { accounts, connectedAccounts, rpcPrefs, chainId } = this.props; return ( <div className="hw-account-list"> @@ -130,11 +131,27 @@ class AccountList extends Component { </div> <a className="hw-account-list__item__link" - href={getAccountLink( - account.address, - this.props.chainId, - this.props.rpcPrefs, - )} + onClick={() => { + const accountLink = getAccountLink( + account.address, + chainId, + rpcPrefs, + ); + this.context.trackEvent({ + category: 'Account', + event: 'Clicked Block Explorer Link', + properties: { + actions: 'Hardware Connect', + link_type: 'Account Tracker', + block_explorer_domain: accountLink + ? new URL(accountLink)?.hostname + : '', + }, + }); + global.platform.openTab({ + url: accountLink, + }); + }} target="_blank" rel="noopener noreferrer" title={this.context.t('etherscanView')} @@ -282,6 +299,7 @@ AccountList.propTypes = { AccountList.contextTypes = { t: PropTypes.func, + trackEvent: PropTypes.func, }; export default AccountList; diff --git a/ui/app/pages/create-account/connect-hardware/index.js b/ui/pages/create-account/connect-hardware/index.js similarity index 100% rename from ui/app/pages/create-account/connect-hardware/index.js rename to ui/pages/create-account/connect-hardware/index.js diff --git a/ui/app/pages/create-account/connect-hardware/index.scss b/ui/pages/create-account/connect-hardware/index.scss similarity index 100% rename from ui/app/pages/create-account/connect-hardware/index.scss rename to ui/pages/create-account/connect-hardware/index.scss diff --git a/ui/app/pages/create-account/connect-hardware/select-hardware.js b/ui/pages/create-account/connect-hardware/select-hardware.js similarity index 100% rename from ui/app/pages/create-account/connect-hardware/select-hardware.js rename to ui/pages/create-account/connect-hardware/select-hardware.js diff --git a/ui/app/pages/create-account/create-account.component.js b/ui/pages/create-account/create-account.component.js similarity index 100% rename from ui/app/pages/create-account/create-account.component.js rename to ui/pages/create-account/create-account.component.js diff --git a/ui/app/pages/create-account/import-account/index.js b/ui/pages/create-account/import-account/index.js similarity index 100% rename from ui/app/pages/create-account/import-account/index.js rename to ui/pages/create-account/import-account/index.js diff --git a/ui/app/pages/create-account/import-account/index.scss b/ui/pages/create-account/import-account/index.scss similarity index 100% rename from ui/app/pages/create-account/import-account/index.scss rename to ui/pages/create-account/import-account/index.scss diff --git a/ui/app/pages/create-account/import-account/json.js b/ui/pages/create-account/import-account/json.js similarity index 100% rename from ui/app/pages/create-account/import-account/json.js rename to ui/pages/create-account/import-account/json.js diff --git a/ui/app/pages/create-account/import-account/private-key.js b/ui/pages/create-account/import-account/private-key.js similarity index 100% rename from ui/app/pages/create-account/import-account/private-key.js rename to ui/pages/create-account/import-account/private-key.js diff --git a/ui/app/pages/create-account/index.js b/ui/pages/create-account/index.js similarity index 100% rename from ui/app/pages/create-account/index.js rename to ui/pages/create-account/index.js diff --git a/ui/app/pages/create-account/index.scss b/ui/pages/create-account/index.scss similarity index 100% rename from ui/app/pages/create-account/index.scss rename to ui/pages/create-account/index.scss diff --git a/ui/app/pages/create-account/new-account.component.js b/ui/pages/create-account/new-account.component.js similarity index 100% rename from ui/app/pages/create-account/new-account.component.js rename to ui/pages/create-account/new-account.component.js diff --git a/ui/app/pages/create-account/new-account.container.js b/ui/pages/create-account/new-account.container.js similarity index 100% rename from ui/app/pages/create-account/new-account.container.js rename to ui/pages/create-account/new-account.container.js diff --git a/ui/app/pages/error/error.component.js b/ui/pages/error/error.component.js similarity index 93% rename from ui/app/pages/error/error.component.js rename to ui/pages/error/error.component.js index 92fad5fa6..eedb1ad64 100644 --- a/ui/app/pages/error/error.component.js +++ b/ui/pages/error/error.component.js @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; -import { getEnvironmentType } from '../../../../app/scripts/lib/util'; -import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../shared/constants/app'; class ErrorPage extends PureComponent { static contextTypes = { diff --git a/ui/app/pages/error/index.js b/ui/pages/error/index.js similarity index 100% rename from ui/app/pages/error/index.js rename to ui/pages/error/index.js diff --git a/ui/app/pages/error/index.scss b/ui/pages/error/index.scss similarity index 100% rename from ui/app/pages/error/index.scss rename to ui/pages/error/index.scss diff --git a/ui/app/pages/first-time-flow/create-password/create-password.component.js b/ui/pages/first-time-flow/create-password/create-password.component.js similarity index 94% rename from ui/app/pages/first-time-flow/create-password/create-password.component.js rename to ui/pages/first-time-flow/create-password/create-password.component.js index 6913c10fa..357ce283b 100644 --- a/ui/app/pages/first-time-flow/create-password/create-password.component.js +++ b/ui/pages/first-time-flow/create-password/create-password.component.js @@ -5,7 +5,7 @@ import MetaFoxLogo from '../../../components/ui/metafox-logo'; import { INITIALIZE_CREATE_PASSWORD_ROUTE, INITIALIZE_IMPORT_WITH_SEED_PHRASE_ROUTE, - INITIALIZE_SEED_PHRASE_ROUTE, + INITIALIZE_SEED_PHRASE_INTRO_ROUTE, } from '../../../helpers/constants/routes'; import NewAccount from './new-account'; import ImportWithSeedPhrase from './import-with-seed-phrase'; @@ -22,7 +22,7 @@ export default class CreatePassword extends PureComponent { const { isInitialized, history } = this.props; if (isInitialized) { - history.push(INITIALIZE_SEED_PHRASE_ROUTE); + history.push(INITIALIZE_SEED_PHRASE_INTRO_ROUTE); } } diff --git a/ui/app/pages/first-time-flow/create-password/create-password.container.js b/ui/pages/first-time-flow/create-password/create-password.container.js similarity index 100% rename from ui/app/pages/first-time-flow/create-password/create-password.container.js rename to ui/pages/first-time-flow/create-password/create-password.container.js diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js b/ui/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js similarity index 100% rename from ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js rename to ui/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.js diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.test.js b/ui/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.test.js similarity index 89% rename from ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.test.js rename to ui/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.test.js index e26639c49..fd76283c7 100644 --- a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.test.js +++ b/ui/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.component.test.js @@ -23,7 +23,7 @@ describe('ImportWithSeedPhrase Component', () => { }); describe('parseSeedPhrase', () => { - it('should handle a regular seed phrase', () => { + it('should handle a regular Secret Recovery Phrase', () => { const root = shallowRender({ onSubmit: sinon.spy(), }); @@ -33,7 +33,7 @@ describe('ImportWithSeedPhrase Component', () => { expect(parseSeedPhrase('foo bar baz')).toStrictEqual('foo bar baz'); }); - it('should handle a mixed-case seed phrase', () => { + it('should handle a mixed-case Secret Recovery Phrase', () => { const root = shallowRender({ onSubmit: sinon.spy(), }); @@ -43,7 +43,7 @@ describe('ImportWithSeedPhrase Component', () => { expect(parseSeedPhrase('FOO bAr baZ')).toStrictEqual('foo bar baz'); }); - it('should handle an upper-case seed phrase', () => { + it('should handle an upper-case Secret Recovery Phrase', () => { const root = shallowRender({ onSubmit: sinon.spy(), }); @@ -53,7 +53,7 @@ describe('ImportWithSeedPhrase Component', () => { expect(parseSeedPhrase('FOO BAR BAZ')).toStrictEqual('foo bar baz'); }); - it('should trim extraneous whitespace from the given seed phrase', () => { + it('should trim extraneous whitespace from the given Secret Recovery Phrase', () => { const root = shallowRender({ onSubmit: sinon.spy(), }); diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js b/ui/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js similarity index 100% rename from ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js rename to ui/pages/first-time-flow/create-password/import-with-seed-phrase/import-with-seed-phrase.container.js diff --git a/ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/index.js b/ui/pages/first-time-flow/create-password/import-with-seed-phrase/index.js similarity index 100% rename from ui/app/pages/first-time-flow/create-password/import-with-seed-phrase/index.js rename to ui/pages/first-time-flow/create-password/import-with-seed-phrase/index.js diff --git a/ui/app/pages/first-time-flow/create-password/index.js b/ui/pages/first-time-flow/create-password/index.js similarity index 100% rename from ui/app/pages/first-time-flow/create-password/index.js rename to ui/pages/first-time-flow/create-password/index.js diff --git a/ui/app/pages/first-time-flow/create-password/new-account/index.js b/ui/pages/first-time-flow/create-password/new-account/index.js similarity index 100% rename from ui/app/pages/first-time-flow/create-password/new-account/index.js rename to ui/pages/first-time-flow/create-password/new-account/index.js diff --git a/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js b/ui/pages/first-time-flow/create-password/new-account/new-account.component.js similarity index 98% rename from ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js rename to ui/pages/first-time-flow/create-password/new-account/new-account.component.js index b74cce8a9..1e9417eb1 100644 --- a/ui/app/pages/first-time-flow/create-password/new-account/new-account.component.js +++ b/ui/pages/first-time-flow/create-password/new-account/new-account.component.js @@ -2,7 +2,7 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import Button from '../../../../components/ui/button'; import { - INITIALIZE_SEED_PHRASE_ROUTE, + INITIALIZE_SEED_PHRASE_INTRO_ROUTE, INITIALIZE_SELECT_ACTION_ROUTE, } from '../../../../helpers/constants/routes'; import TextField from '../../../../components/ui/text-field'; @@ -108,7 +108,7 @@ export default class NewAccount extends PureComponent { }, }); - history.push(INITIALIZE_SEED_PHRASE_ROUTE); + history.push(INITIALIZE_SEED_PHRASE_INTRO_ROUTE); } catch (error) { this.setState({ passwordError: error.message }); } diff --git a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js b/ui/pages/first-time-flow/end-of-flow/end-of-flow.component.js similarity index 100% rename from ui/app/pages/first-time-flow/end-of-flow/end-of-flow.component.js rename to ui/pages/first-time-flow/end-of-flow/end-of-flow.component.js diff --git a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js b/ui/pages/first-time-flow/end-of-flow/end-of-flow.container.js similarity index 100% rename from ui/app/pages/first-time-flow/end-of-flow/end-of-flow.container.js rename to ui/pages/first-time-flow/end-of-flow/end-of-flow.container.js diff --git a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.test.js b/ui/pages/first-time-flow/end-of-flow/end-of-flow.test.js similarity index 87% rename from ui/app/pages/first-time-flow/end-of-flow/end-of-flow.test.js rename to ui/pages/first-time-flow/end-of-flow/end-of-flow.test.js index 314025110..e3f04eaa5 100644 --- a/ui/app/pages/first-time-flow/end-of-flow/end-of-flow.test.js +++ b/ui/pages/first-time-flow/end-of-flow/end-of-flow.test.js @@ -1,7 +1,7 @@ import React from 'react'; import sinon from 'sinon'; -import { tick } from '../../../../../test/lib/tick'; -import { mountWithRouter } from '../../../../../test/lib/render-helpers'; +import { tick } from '../../../../test/lib/tick'; +import { mountWithRouter } from '../../../../test/lib/render-helpers'; import { DEFAULT_ROUTE } from '../../../helpers/constants/routes'; import EndOfFlowScreen from './end-of-flow.container'; diff --git a/ui/app/pages/first-time-flow/end-of-flow/index.js b/ui/pages/first-time-flow/end-of-flow/index.js similarity index 100% rename from ui/app/pages/first-time-flow/end-of-flow/index.js rename to ui/pages/first-time-flow/end-of-flow/index.js diff --git a/ui/app/pages/first-time-flow/end-of-flow/index.scss b/ui/pages/first-time-flow/end-of-flow/index.scss similarity index 100% rename from ui/app/pages/first-time-flow/end-of-flow/index.scss rename to ui/pages/first-time-flow/end-of-flow/index.scss diff --git a/ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.component.js b/ui/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.component.js similarity index 100% rename from ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.component.js rename to ui/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.component.js diff --git a/ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.container.js b/ui/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.container.js similarity index 100% rename from ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.container.js rename to ui/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.container.js diff --git a/ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.test.js b/ui/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.test.js similarity index 97% rename from ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.test.js rename to ui/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.test.js index ab057080d..e07331222 100644 --- a/ui/app/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.test.js +++ b/ui/pages/first-time-flow/first-time-flow-switch/first-time-flow-switch.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { mountWithRouter } from '../../../../../test/lib/render-helpers'; +import { mountWithRouter } from '../../../../test/lib/render-helpers'; import { DEFAULT_ROUTE, LOCK_ROUTE, diff --git a/ui/app/pages/first-time-flow/first-time-flow-switch/index.js b/ui/pages/first-time-flow/first-time-flow-switch/index.js similarity index 100% rename from ui/app/pages/first-time-flow/first-time-flow-switch/index.js rename to ui/pages/first-time-flow/first-time-flow-switch/index.js diff --git a/ui/app/pages/first-time-flow/first-time-flow.component.js b/ui/pages/first-time-flow/first-time-flow.component.js similarity index 93% rename from ui/app/pages/first-time-flow/first-time-flow.component.js rename to ui/pages/first-time-flow/first-time-flow.component.js index 5094fb2ba..974c37020 100644 --- a/ui/app/pages/first-time-flow/first-time-flow.component.js +++ b/ui/pages/first-time-flow/first-time-flow.component.js @@ -12,6 +12,7 @@ import { INITIALIZE_END_OF_FLOW_ROUTE, INITIALIZE_METAMETRICS_OPT_IN_ROUTE, INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, + INITIALIZE_SEED_PHRASE_INTRO_ROUTE, } from '../../helpers/constants/routes'; import FirstTimeFlowSwitch from './first-time-flow-switch'; import Welcome from './welcome'; @@ -125,6 +126,16 @@ export default class FirstTimeFlow extends PureComponent { /> )} /> + <Route + path={INITIALIZE_SEED_PHRASE_INTRO_ROUTE} + render={(routeProps) => ( + <SeedPhrase + {...routeProps} + seedPhrase={seedPhrase} + verifySeedPhrase={verifySeedPhrase} + /> + )} + /> <Route path={INITIALIZE_CREATE_PASSWORD_ROUTE} render={(routeProps) => ( diff --git a/ui/app/pages/first-time-flow/first-time-flow.container.js b/ui/pages/first-time-flow/first-time-flow.container.js similarity index 100% rename from ui/app/pages/first-time-flow/first-time-flow.container.js rename to ui/pages/first-time-flow/first-time-flow.container.js diff --git a/ui/app/pages/first-time-flow/index.js b/ui/pages/first-time-flow/index.js similarity index 100% rename from ui/app/pages/first-time-flow/index.js rename to ui/pages/first-time-flow/index.js diff --git a/ui/app/pages/first-time-flow/index.scss b/ui/pages/first-time-flow/index.scss similarity index 92% rename from ui/app/pages/first-time-flow/index.scss rename to ui/pages/first-time-flow/index.scss index 994d218d3..34a294019 100644 --- a/ui/app/pages/first-time-flow/index.scss +++ b/ui/pages/first-time-flow/index.scss @@ -143,3 +143,13 @@ color: $primary-blue; } } + +.first-time-flow__wrapper.intro { + @media screen and (min-width: $break-large) { + max-width: 1010px; + } + + @media screen and (max-width: 1010px) { + padding: 0 20px; + } +} diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/index.js b/ui/pages/first-time-flow/metametrics-opt-in/index.js similarity index 100% rename from ui/app/pages/first-time-flow/metametrics-opt-in/index.js rename to ui/pages/first-time-flow/metametrics-opt-in/index.js diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/index.scss b/ui/pages/first-time-flow/metametrics-opt-in/index.scss similarity index 100% rename from ui/app/pages/first-time-flow/metametrics-opt-in/index.scss rename to ui/pages/first-time-flow/metametrics-opt-in/index.scss diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js b/ui/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js similarity index 98% rename from ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js rename to ui/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js index 5e3be989b..4e13ca634 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js +++ b/ui/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.component.js @@ -77,7 +77,7 @@ export default class MetaMetricsOptIn extends Component { {t('metametricsCommitmentsNeverCollectIP', [ <span className="metametrics-opt-in__bold" - key="neverCollectKeys" + key="neverCollectIP" > {t('metametricsCommitmentsBoldNever')} </span>, @@ -90,7 +90,7 @@ export default class MetaMetricsOptIn extends Component { {t('metametricsCommitmentsNeverSellDataForProfit', [ <span className="metametrics-opt-in__bold" - key="neverCollectKeys" + key="neverSellData" > {t('metametricsCommitmentsBoldNever')} </span>, diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.container.js b/ui/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.container.js similarity index 100% rename from ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.container.js rename to ui/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.container.js diff --git a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.test.js b/ui/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.test.js similarity index 92% rename from ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.test.js rename to ui/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.test.js index fa1d61889..4a83441b0 100644 --- a/ui/app/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.test.js +++ b/ui/pages/first-time-flow/metametrics-opt-in/metametrics-opt-in.test.js @@ -1,7 +1,7 @@ import React from 'react'; import sinon from 'sinon'; import configureMockStore from 'redux-mock-store'; -import { mountWithRouter } from '../../../../../test/lib/render-helpers'; +import { mountWithRouter } from '../../../../test/lib/render-helpers'; import MetaMetricsOptIn from './metametrics-opt-in.container'; describe('MetaMetricsOptIn', () => { diff --git a/ui/app/pages/first-time-flow/onboarding-initiator-util.js b/ui/pages/first-time-flow/onboarding-initiator-util.js similarity index 100% rename from ui/app/pages/first-time-flow/onboarding-initiator-util.js rename to ui/pages/first-time-flow/onboarding-initiator-util.js diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase-component.test.js b/ui/pages/first-time-flow/seed-phrase/confirm-seed-phrase-component.test.js similarity index 100% rename from ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase-component.test.js rename to ui/pages/first-time-flow/seed-phrase/confirm-seed-phrase-component.test.js diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js b/ui/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js similarity index 100% rename from ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js rename to ui/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.component.js diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js b/ui/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js similarity index 100% rename from ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js rename to ui/pages/first-time-flow/seed-phrase/confirm-seed-phrase/confirm-seed-phrase.container.js diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js b/ui/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js similarity index 100% rename from ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js rename to ui/pages/first-time-flow/seed-phrase/confirm-seed-phrase/draggable-seed.component.js diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.js b/ui/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.js similarity index 100% rename from ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.js rename to ui/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.js diff --git a/ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss b/ui/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss similarity index 100% rename from ui/app/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss rename to ui/pages/first-time-flow/seed-phrase/confirm-seed-phrase/index.scss diff --git a/ui/app/pages/first-time-flow/seed-phrase/index.js b/ui/pages/first-time-flow/seed-phrase/index.js similarity index 100% rename from ui/app/pages/first-time-flow/seed-phrase/index.js rename to ui/pages/first-time-flow/seed-phrase/index.js diff --git a/ui/app/pages/first-time-flow/seed-phrase/index.scss b/ui/pages/first-time-flow/seed-phrase/index.scss similarity index 94% rename from ui/app/pages/first-time-flow/seed-phrase/index.scss rename to ui/pages/first-time-flow/seed-phrase/index.scss index b4a57912d..15f801632 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/index.scss +++ b/ui/pages/first-time-flow/seed-phrase/index.scss @@ -1,5 +1,6 @@ @import 'confirm-seed-phrase/index'; @import 'reveal-seed-phrase/index'; +@import 'seed-phrase-intro/index'; .seed-phrase { &__sections { diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.js b/ui/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.js similarity index 100% rename from ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.js rename to ui/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.js diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.scss b/ui/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.scss similarity index 100% rename from ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.scss rename to ui/pages/first-time-flow/seed-phrase/reveal-seed-phrase/index.scss diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js b/ui/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js similarity index 100% rename from ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js rename to ui/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.component.js diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.container.js b/ui/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.container.js similarity index 100% rename from ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.container.js rename to ui/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.container.js diff --git a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.test.js b/ui/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.test.js similarity index 93% rename from ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.test.js rename to ui/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.test.js index ba7191871..262b64f46 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.test.js +++ b/ui/pages/first-time-flow/seed-phrase/reveal-seed-phrase/reveal-seed-phrase.test.js @@ -3,7 +3,7 @@ import sinon from 'sinon'; import { mount } from 'enzyme'; import RevealSeedPhrase from './reveal-seed-phrase.container'; -describe('Reveal Seed Phrase', () => { +describe('Reveal Secret Recovery Phrase', () => { let wrapper; const TEST_SEED = @@ -27,7 +27,7 @@ describe('Reveal Seed Phrase', () => { }); }); - it('seed phrase', () => { + it('secret recovery phrase', () => { const seedPhrase = wrapper.find( '.reveal-seed-phrase__secret-words--hidden', ); diff --git a/ui/pages/first-time-flow/seed-phrase/seed-phrase-intro/index.js b/ui/pages/first-time-flow/seed-phrase/seed-phrase-intro/index.js new file mode 100644 index 000000000..c9d6bdbd6 --- /dev/null +++ b/ui/pages/first-time-flow/seed-phrase/seed-phrase-intro/index.js @@ -0,0 +1 @@ +export { default } from './seed-phrase-intro.component'; diff --git a/ui/pages/first-time-flow/seed-phrase/seed-phrase-intro/index.scss b/ui/pages/first-time-flow/seed-phrase/seed-phrase-intro/index.scss new file mode 100644 index 000000000..f0aeb8979 --- /dev/null +++ b/ui/pages/first-time-flow/seed-phrase/seed-phrase-intro/index.scss @@ -0,0 +1,44 @@ +.seed-phrase-intro { + &__sections { + display: flex; + + @media screen and (min-width: $break-large) { + flex-direction: row; + } + + @media screen and (max-width: 970px) { + flex-direction: column; + } + } + + &__left { + flex: 3; + min-width: 0; + } + + &__right { + flex: 1; + min-width: 0; + + @media screen and (max-width: 970px) { + margin-top: 24px; + } + } + + video { + border-radius: 8px; + + @media screen and (max-width: 970px) { + width: 95%; + } + } + + &__copy { + max-width: 696px; + } + + &__sidebar_list { + list-style: disc; + padding-left: 20px; + } +} diff --git a/ui/pages/first-time-flow/seed-phrase/seed-phrase-intro/seed-phrase-intro.component.js b/ui/pages/first-time-flow/seed-phrase/seed-phrase-intro/seed-phrase-intro.component.js new file mode 100644 index 000000000..304339967 --- /dev/null +++ b/ui/pages/first-time-flow/seed-phrase/seed-phrase-intro/seed-phrase-intro.component.js @@ -0,0 +1,121 @@ +import React from 'react'; +import { useHistory } from 'react-router-dom'; +import { useI18nContext } from '../../../../hooks/useI18nContext'; +// Components +import Box from '../../../../components/ui/box'; +import Button from '../../../../components/ui/button'; +import Typography from '../../../../components/ui/typography'; +import { + BLOCK_SIZES, + COLORS, + TYPOGRAPHY, + FONT_WEIGHT, + SIZES, + BORDER_STYLE, +} from '../../../../helpers/constants/design-system'; +// Routes +import { INITIALIZE_SEED_PHRASE_ROUTE } from '../../../../helpers/constants/routes'; + +export default function SeedPhraseIntro() { + const t = useI18nContext(); + const history = useHistory(); + + const handleNextStep = () => { + history.push(INITIALIZE_SEED_PHRASE_ROUTE); + }; + + return ( + <div className="seed-phrase-intro"> + <div className="seed-phrase-intro__sections"> + <div className="seed-phrase-intro__left"> + <Typography + color={COLORS.BLACK} + variant={TYPOGRAPHY.H1} + boxProps={{ marginTop: 0, marginBottom: 4 }} + > + {t('seedPhraseIntroTitle')} + </Typography> + <Typography + color={COLORS.BLACK} + boxProps={{ marginBottom: 4 }} + variant={TYPOGRAPHY.Paragraph} + className="seed-phrase-intro__copy" + > + {t('seedPhraseIntroTitleCopy')} + </Typography> + <Box marginBottom={4}> + <video controls> + <source + type="video/webm" + src="./images/videos/recovery-onboarding/video.webm" + /> + <track + default + srcLang="en" + label="English" + kind="subtitles" + src="./images/videos/recovery-onboarding/subtitles-en.vtt" + /> + </video> + </Box> + <Box width={BLOCK_SIZES.ONE_THIRD}> + <Button type="primary" onClick={handleNextStep}> + {t('next')} + </Button> + </Box> + </div> + <div className="seed-phrase-intro__right"> + <Box + padding={4} + borderWidth={1} + borderRadius={SIZES.MD} + borderColor={COLORS.UI2} + borderStyle={BORDER_STYLE.SOLID} + > + <Box marginBottom={4}> + <Typography + tag="span" + color={COLORS.BLACK} + fontWeight={FONT_WEIGHT.BOLD} + boxProps={{ display: 'block' }} + > + {t('seedPhraseIntroSidebarTitleOne')} + </Typography> + <span>{t('seedPhraseIntroSidebarCopyOne')}</span> + </Box> + <Box marginBottom={4}> + <Typography + tag="span" + color={COLORS.BLACK} + fontWeight={FONT_WEIGHT.BOLD} + boxProps={{ display: 'block' }} + > + {t('seedPhraseIntroSidebarTitleTwo')} + </Typography> + <ul className="seed-phrase-intro__sidebar_list"> + <li>{t('seedPhraseIntroSidebarBulletOne')}</li> + <li>{t('seedPhraseIntroSidebarBulletTwo')}</li> + <li>{t('seedPhraseIntroSidebarBulletThree')}</li> + <li>{t('seedPhraseIntroSidebarBulletFour')}</li> + </ul> + </Box> + <Box marginBottom={4}> + <Typography + tag="span" + color={COLORS.BLACK} + fontWeight={FONT_WEIGHT.BOLD} + boxProps={{ display: 'block' }} + > + {t('seedPhraseIntroSidebarTitleThree')} + </Typography> + <span>{t('seedPhraseIntroSidebarCopyTwo')}</span> + </Box> + <Box marginBottom={4}> + <span>{t('seedPhraseIntroSidebarCopyThree')}</span> + </Box> + </Box> + </div> + </div> + </div> + ); +} diff --git a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js b/ui/pages/first-time-flow/seed-phrase/seed-phrase.component.js similarity index 78% rename from ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js rename to ui/pages/first-time-flow/seed-phrase/seed-phrase.component.js index 97d27998a..612e86c77 100644 --- a/ui/app/pages/first-time-flow/seed-phrase/seed-phrase.component.js +++ b/ui/pages/first-time-flow/seed-phrase/seed-phrase.component.js @@ -7,11 +7,13 @@ import { INITIALIZE_SEED_PHRASE_ROUTE, INITIALIZE_CONFIRM_SEED_PHRASE_ROUTE, INITIALIZE_BACKUP_SEED_PHRASE_ROUTE, + INITIALIZE_SEED_PHRASE_INTRO_ROUTE, DEFAULT_ROUTE, } from '../../../helpers/constants/routes'; import MetaFoxLogo from '../../../components/ui/metafox-logo'; import ConfirmSeedPhrase from './confirm-seed-phrase'; import RevealSeedPhrase from './reveal-seed-phrase'; +import SeedPhraseIntro from './seed-phrase-intro'; export default class SeedPhrase extends PureComponent { static propTypes = { @@ -39,12 +41,15 @@ export default class SeedPhrase extends PureComponent { } render() { - const { seedPhrase } = this.props; + const { seedPhrase, history } = this.props; const { verifiedSeedPhrase } = this.state; + const pathname = history?.location?.pathname; + const introClass = + pathname === INITIALIZE_SEED_PHRASE_INTRO_ROUTE ? 'intro' : ''; return ( <DragDropContextProvider backend={HTML5Backend}> - <div className="first-time-flow__wrapper"> + <div className={`first-time-flow__wrapper ${introClass}`}> <MetaFoxLogo /> <Switch> <Route @@ -77,6 +82,16 @@ export default class SeedPhrase extends PureComponent { /> )} /> + <Route + exact + path={INITIALIZE_SEED_PHRASE_INTRO_ROUTE} + render={(routeProps) => ( + <SeedPhraseIntro + {...routeProps} + seedPhrase={seedPhrase || verifiedSeedPhrase} + /> + )} + /> </Switch> </div> </DragDropContextProvider> diff --git a/ui/app/pages/first-time-flow/select-action/index.js b/ui/pages/first-time-flow/select-action/index.js similarity index 100% rename from ui/app/pages/first-time-flow/select-action/index.js rename to ui/pages/first-time-flow/select-action/index.js diff --git a/ui/app/pages/first-time-flow/select-action/index.scss b/ui/pages/first-time-flow/select-action/index.scss similarity index 100% rename from ui/app/pages/first-time-flow/select-action/index.scss rename to ui/pages/first-time-flow/select-action/index.scss diff --git a/ui/app/pages/first-time-flow/select-action/select-action.component.js b/ui/pages/first-time-flow/select-action/select-action.component.js similarity index 95% rename from ui/app/pages/first-time-flow/select-action/select-action.component.js rename to ui/pages/first-time-flow/select-action/select-action.component.js index 2f02df189..7420b1333 100644 --- a/ui/app/pages/first-time-flow/select-action/select-action.component.js +++ b/ui/pages/first-time-flow/select-action/select-action.component.js @@ -50,7 +50,7 @@ export default class SelectAction extends PureComponent { <div className="select-action__select-button"> <div className="select-action__button-content"> <div className="select-action__button-symbol"> - <img src="/images/download-alt.svg" alt="" /> + <img src="./images/download-alt.svg" alt="" /> </div> <div className="select-action__button-text-big"> {t('noAlreadyHaveSeed')} @@ -70,7 +70,7 @@ export default class SelectAction extends PureComponent { <div className="select-action__select-button"> <div className="select-action__button-content"> <div className="select-action__button-symbol"> - <img src="/images/thin-plus.svg" alt="" /> + <img src="./images/thin-plus.svg" alt="" /> </div> <div className="select-action__button-text-big"> {t('letsGoSetUp')} diff --git a/ui/app/pages/first-time-flow/select-action/select-action.container.js b/ui/pages/first-time-flow/select-action/select-action.container.js similarity index 100% rename from ui/app/pages/first-time-flow/select-action/select-action.container.js rename to ui/pages/first-time-flow/select-action/select-action.container.js diff --git a/ui/app/pages/first-time-flow/select-action/select-action.test.js b/ui/pages/first-time-flow/select-action/select-action.test.js similarity index 95% rename from ui/app/pages/first-time-flow/select-action/select-action.test.js rename to ui/pages/first-time-flow/select-action/select-action.test.js index 013176b30..e0b79c789 100644 --- a/ui/app/pages/first-time-flow/select-action/select-action.test.js +++ b/ui/pages/first-time-flow/select-action/select-action.test.js @@ -1,6 +1,6 @@ import React from 'react'; import sinon from 'sinon'; -import { mountWithRouter } from '../../../../../test/lib/render-helpers'; +import { mountWithRouter } from '../../../../test/lib/render-helpers'; import SelectAction from './select-action.container'; describe('Selection Action', () => { diff --git a/ui/app/pages/first-time-flow/welcome/index.js b/ui/pages/first-time-flow/welcome/index.js similarity index 100% rename from ui/app/pages/first-time-flow/welcome/index.js rename to ui/pages/first-time-flow/welcome/index.js diff --git a/ui/app/pages/first-time-flow/welcome/index.scss b/ui/pages/first-time-flow/welcome/index.scss similarity index 100% rename from ui/app/pages/first-time-flow/welcome/index.scss rename to ui/pages/first-time-flow/welcome/index.scss diff --git a/ui/app/pages/first-time-flow/welcome/welcome.component.js b/ui/pages/first-time-flow/welcome/welcome.component.js similarity index 100% rename from ui/app/pages/first-time-flow/welcome/welcome.component.js rename to ui/pages/first-time-flow/welcome/welcome.component.js diff --git a/ui/app/pages/first-time-flow/welcome/welcome.container.js b/ui/pages/first-time-flow/welcome/welcome.container.js similarity index 100% rename from ui/app/pages/first-time-flow/welcome/welcome.container.js rename to ui/pages/first-time-flow/welcome/welcome.container.js diff --git a/ui/app/pages/first-time-flow/welcome/welcome.test.js b/ui/pages/first-time-flow/welcome/welcome.test.js similarity index 95% rename from ui/app/pages/first-time-flow/welcome/welcome.test.js rename to ui/pages/first-time-flow/welcome/welcome.test.js index 2d60b4d57..14d1a22cc 100644 --- a/ui/app/pages/first-time-flow/welcome/welcome.test.js +++ b/ui/pages/first-time-flow/welcome/welcome.test.js @@ -1,7 +1,7 @@ import React from 'react'; import sinon from 'sinon'; import configureMockStore from 'redux-mock-store'; -import { mountWithRouter } from '../../../../../test/lib/render-helpers'; +import { mountWithRouter } from '../../../../test/lib/render-helpers'; import Welcome from './welcome.container'; describe('Welcome', () => { diff --git a/ui/app/pages/home/home.component.js b/ui/pages/home/home.component.js similarity index 100% rename from ui/app/pages/home/home.component.js rename to ui/pages/home/home.component.js diff --git a/ui/app/pages/home/home.container.js b/ui/pages/home/home.container.js similarity index 93% rename from ui/app/pages/home/home.container.js rename to ui/pages/home/home.container.js index 6020c1510..f5ff5a966 100644 --- a/ui/app/pages/home/home.container.js +++ b/ui/pages/home/home.container.js @@ -29,15 +29,15 @@ import { import { setThreeBoxLastUpdated, hideWhatsNewPopup } from '../../ducks/app/app'; import { getWeb3ShimUsageAlertEnabledness } from '../../ducks/metamask/metamask'; import { getSwapsFeatureLiveness } from '../../ducks/swaps/swaps'; -import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { getEnvironmentType } from '../../../app/scripts/lib/util'; import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_POPUP, -} from '../../../../shared/constants/app'; +} from '../../../shared/constants/app'; import { ALERT_TYPES, WEB3_SHIM_USAGE_ALERT_STATES, -} from '../../../../shared/constants/alerts'; +} from '../../../shared/constants/alerts'; import Home from './home.component'; const mapStateToProps = (state) => { @@ -52,6 +52,7 @@ const mapStateToProps = (state) => { connectedStatusPopoverHasBeenShown, defaultHomeActiveTabName, swapsState, + dismissSeedBackUpReminder, } = metamask; const accountBalance = getCurrentEthBalance(state); const { forgottenPassword, threeBoxLastUpdated } = appState; @@ -84,7 +85,8 @@ const mapStateToProps = (state) => { unconfirmedTransactionsCount: unconfirmedTransactionsCountSelector(state), shouldShowSeedPhraseReminder: seedPhraseBackedUp === false && - (parseInt(accountBalance, 16) > 0 || tokens.length > 0), + (parseInt(accountBalance, 16) > 0 || tokens.length > 0) && + dismissSeedBackUpReminder === false, isPopup, isNotification, threeBoxSynced, diff --git a/ui/app/pages/home/index.js b/ui/pages/home/index.js similarity index 100% rename from ui/app/pages/home/index.js rename to ui/pages/home/index.js diff --git a/ui/app/pages/home/index.scss b/ui/pages/home/index.scss similarity index 100% rename from ui/app/pages/home/index.scss rename to ui/pages/home/index.scss diff --git a/ui/app/pages/index.js b/ui/pages/index.js similarity index 100% rename from ui/app/pages/index.js rename to ui/pages/index.js diff --git a/ui/app/pages/keychains/index.scss b/ui/pages/keychains/index.scss similarity index 100% rename from ui/app/pages/keychains/index.scss rename to ui/pages/keychains/index.scss diff --git a/ui/app/pages/keychains/restore-vault.js b/ui/pages/keychains/restore-vault.js similarity index 100% rename from ui/app/pages/keychains/restore-vault.js rename to ui/pages/keychains/restore-vault.js diff --git a/ui/app/pages/keychains/reveal-seed.js b/ui/pages/keychains/reveal-seed.js similarity index 100% rename from ui/app/pages/keychains/reveal-seed.js rename to ui/pages/keychains/reveal-seed.js diff --git a/ui/app/pages/keychains/reveal-seed.test.js b/ui/pages/keychains/reveal-seed.test.js similarity index 100% rename from ui/app/pages/keychains/reveal-seed.test.js rename to ui/pages/keychains/reveal-seed.test.js diff --git a/ui/app/pages/lock/index.js b/ui/pages/lock/index.js similarity index 100% rename from ui/app/pages/lock/index.js rename to ui/pages/lock/index.js diff --git a/ui/app/pages/lock/lock.component.js b/ui/pages/lock/lock.component.js similarity index 100% rename from ui/app/pages/lock/lock.component.js rename to ui/pages/lock/lock.component.js diff --git a/ui/app/pages/lock/lock.container.js b/ui/pages/lock/lock.container.js similarity index 100% rename from ui/app/pages/lock/lock.container.js rename to ui/pages/lock/lock.container.js diff --git a/ui/app/pages/lock/lock.test.js b/ui/pages/lock/lock.test.js similarity index 92% rename from ui/app/pages/lock/lock.test.js rename to ui/pages/lock/lock.test.js index 66de4a245..6f7d1def0 100644 --- a/ui/app/pages/lock/lock.test.js +++ b/ui/pages/lock/lock.test.js @@ -1,6 +1,6 @@ import React from 'react'; import sinon from 'sinon'; -import { mountWithRouter } from '../../../../test/lib/render-helpers'; +import { mountWithRouter } from '../../../test/lib/render-helpers'; import Lock from './lock.container'; describe('Lock', () => { diff --git a/ui/app/pages/mobile-sync/index.js b/ui/pages/mobile-sync/index.js similarity index 100% rename from ui/app/pages/mobile-sync/index.js rename to ui/pages/mobile-sync/index.js diff --git a/ui/app/pages/mobile-sync/mobile-sync.component.js b/ui/pages/mobile-sync/mobile-sync.component.js similarity index 100% rename from ui/app/pages/mobile-sync/mobile-sync.component.js rename to ui/pages/mobile-sync/mobile-sync.component.js diff --git a/ui/app/pages/mobile-sync/mobile-sync.container.js b/ui/pages/mobile-sync/mobile-sync.container.js similarity index 100% rename from ui/app/pages/mobile-sync/mobile-sync.container.js rename to ui/pages/mobile-sync/mobile-sync.container.js diff --git a/ui/app/pages/pages.scss b/ui/pages/pages.scss similarity index 100% rename from ui/app/pages/pages.scss rename to ui/pages/pages.scss diff --git a/ui/app/pages/permissions-connect/choose-account/choose-account.component.js b/ui/pages/permissions-connect/choose-account/choose-account.component.js similarity index 100% rename from ui/app/pages/permissions-connect/choose-account/choose-account.component.js rename to ui/pages/permissions-connect/choose-account/choose-account.component.js diff --git a/ui/app/pages/permissions-connect/choose-account/index.js b/ui/pages/permissions-connect/choose-account/index.js similarity index 100% rename from ui/app/pages/permissions-connect/choose-account/index.js rename to ui/pages/permissions-connect/choose-account/index.js diff --git a/ui/app/pages/permissions-connect/choose-account/index.scss b/ui/pages/permissions-connect/choose-account/index.scss similarity index 100% rename from ui/app/pages/permissions-connect/choose-account/index.scss rename to ui/pages/permissions-connect/choose-account/index.scss diff --git a/ui/app/pages/permissions-connect/index.js b/ui/pages/permissions-connect/index.js similarity index 100% rename from ui/app/pages/permissions-connect/index.js rename to ui/pages/permissions-connect/index.js diff --git a/ui/app/pages/permissions-connect/index.scss b/ui/pages/permissions-connect/index.scss similarity index 100% rename from ui/app/pages/permissions-connect/index.scss rename to ui/pages/permissions-connect/index.scss diff --git a/ui/app/pages/permissions-connect/permissions-connect.component.js b/ui/pages/permissions-connect/permissions-connect.component.js similarity index 98% rename from ui/app/pages/permissions-connect/permissions-connect.component.js rename to ui/pages/permissions-connect/permissions-connect.component.js index 1927af9ae..b9706faca 100644 --- a/ui/app/pages/permissions-connect/permissions-connect.component.js +++ b/ui/pages/permissions-connect/permissions-connect.component.js @@ -1,8 +1,8 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { Switch, Route } from 'react-router-dom'; -import { getEnvironmentType } from '../../../../app/scripts/lib/util'; -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../shared/constants/app'; import { DEFAULT_ROUTE } from '../../helpers/constants/routes'; import PermissionPageContainer from '../../components/app/permission-page-container'; import ChooseAccount from './choose-account'; diff --git a/ui/app/pages/permissions-connect/permissions-connect.container.js b/ui/pages/permissions-connect/permissions-connect.container.js similarity index 100% rename from ui/app/pages/permissions-connect/permissions-connect.container.js rename to ui/pages/permissions-connect/permissions-connect.container.js diff --git a/ui/app/pages/permissions-connect/redirect/index.js b/ui/pages/permissions-connect/redirect/index.js similarity index 100% rename from ui/app/pages/permissions-connect/redirect/index.js rename to ui/pages/permissions-connect/redirect/index.js diff --git a/ui/app/pages/permissions-connect/redirect/index.scss b/ui/pages/permissions-connect/redirect/index.scss similarity index 100% rename from ui/app/pages/permissions-connect/redirect/index.scss rename to ui/pages/permissions-connect/redirect/index.scss diff --git a/ui/app/pages/permissions-connect/redirect/permissions-redirect.component.js b/ui/pages/permissions-connect/redirect/permissions-redirect.component.js similarity index 100% rename from ui/app/pages/permissions-connect/redirect/permissions-redirect.component.js rename to ui/pages/permissions-connect/redirect/permissions-redirect.component.js diff --git a/ui/app/pages/routes/index.js b/ui/pages/routes/index.js similarity index 100% rename from ui/app/pages/routes/index.js rename to ui/pages/routes/index.js diff --git a/ui/app/pages/routes/routes.component.js b/ui/pages/routes/routes.component.js similarity index 96% rename from ui/app/pages/routes/routes.component.js rename to ui/pages/routes/routes.component.js index 5648e4e20..d70256e17 100644 --- a/ui/app/pages/routes/routes.component.js +++ b/ui/pages/routes/routes.component.js @@ -59,9 +59,9 @@ import { import { ENVIRONMENT_TYPE_NOTIFICATION, ENVIRONMENT_TYPE_POPUP, -} from '../../../../shared/constants/app'; -import { getEnvironmentType } from '../../../../app/scripts/lib/util'; -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; +} from '../../../shared/constants/app'; +import { getEnvironmentType } from '../../../app/scripts/lib/util'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; import ConfirmationPage from '../confirmation'; export default class Routes extends Component { @@ -90,6 +90,7 @@ export default class Routes extends Component { autoLockTimeLimit: PropTypes.number, pageChanged: PropTypes.func.isRequired, prepareToLeaveSwaps: PropTypes.func, + browserEnvironment: PropTypes.object, }; static contextTypes = { @@ -275,6 +276,7 @@ export default class Routes extends Component { submittedPendingTransactions, isMouseUser, prepareToLeaveSwaps, + browserEnvironment, } = this.props; const loadMessage = loadingMessage || isNetworkLoading @@ -296,9 +298,14 @@ export default class Routes extends Component { ({ id }) => id === sidebarTransaction.id, ); + const { os, browser } = browserEnvironment; return ( <div - className={classnames('app', { 'mouse-user-styles': isMouseUser })} + className={classnames('app', { + [`os-${os}`]: os, + [`browser-${browser}`]: browser, + 'mouse-user-styles': isMouseUser, + })} dir={textDirection} onClick={() => setMouseUserState(true)} onKeyDown={(e) => { diff --git a/ui/app/pages/routes/routes.container.js b/ui/pages/routes/routes.container.js similarity index 97% rename from ui/app/pages/routes/routes.container.js rename to ui/pages/routes/routes.container.js index 527f9791c..952e077d8 100644 --- a/ui/app/pages/routes/routes.container.js +++ b/ui/pages/routes/routes.container.js @@ -45,6 +45,7 @@ function mapStateToProps(state) { isMouseUser: state.appState.isMouseUser, providerId: getNetworkIdentifier(state), autoLockTimeLimit, + browserEnvironment: state.metamask.browserEnvironment, }; } diff --git a/ui/app/pages/send/index.js b/ui/pages/send/index.js similarity index 100% rename from ui/app/pages/send/index.js rename to ui/pages/send/index.js diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js b/ui/pages/send/send-content/add-recipient/add-recipient.component.js similarity index 99% rename from ui/app/pages/send/send-content/add-recipient/add-recipient.component.js rename to ui/pages/send/send-content/add-recipient/add-recipient.component.js index a7afd2141..da7999c94 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.js +++ b/ui/pages/send/send-content/add-recipient/add-recipient.component.js @@ -11,7 +11,7 @@ import Confusable from '../../../../components/ui/confusable'; import { isBurnAddress, isValidHexAddress, -} from '../../../../../../shared/modules/hexstring-utils'; +} from '../../../../../shared/modules/hexstring-utils'; export default class AddRecipient extends Component { static propTypes = { diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.component.test.js b/ui/pages/send/send-content/add-recipient/add-recipient.component.test.js similarity index 100% rename from ui/app/pages/send/send-content/add-recipient/add-recipient.component.test.js rename to ui/pages/send/send-content/add-recipient/add-recipient.component.test.js diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.container.js b/ui/pages/send/send-content/add-recipient/add-recipient.container.js similarity index 100% rename from ui/app/pages/send/send-content/add-recipient/add-recipient.container.js rename to ui/pages/send/send-content/add-recipient/add-recipient.container.js diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.container.test.js b/ui/pages/send/send-content/add-recipient/add-recipient.container.test.js similarity index 94% rename from ui/app/pages/send/send-content/add-recipient/add-recipient.container.test.js rename to ui/pages/send/send-content/add-recipient/add-recipient.container.test.js index 8e02da161..696ca926b 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.container.test.js +++ b/ui/pages/send/send-content/add-recipient/add-recipient.container.test.js @@ -13,7 +13,7 @@ jest.mock('react-redux', () => ({ }, })); -jest.mock('../../../../../app/selectors', () => ({ +jest.mock('../../../../selectors', () => ({ getSendEnsResolution: (s) => `mockSendEnsResolution:${s}`, getSendEnsResolutionError: (s) => `mockSendEnsResolutionError:${s}`, getAddressBook: (s) => [{ name: `mockAddressBook:${s}` }], @@ -24,7 +24,7 @@ jest.mock('../../../../../app/selectors', () => ({ ], })); -jest.mock('../../../../../app/store/actions', () => ({ +jest.mock('../../../../store/actions', () => ({ updateSendTo: jest.fn(), })); diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.js b/ui/pages/send/send-content/add-recipient/add-recipient.js similarity index 96% rename from ui/app/pages/send/send-content/add-recipient/add-recipient.js rename to ui/pages/send/send-content/add-recipient/add-recipient.js index 3124ccdb5..5141fda1d 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.js +++ b/ui/pages/send/send-content/add-recipient/add-recipient.js @@ -19,7 +19,7 @@ import { isBurnAddress, isValidHexAddress, toChecksumHexAddress, -} from '../../../../../../shared/modules/hexstring-utils'; +} from '../../../../../shared/modules/hexstring-utils'; export function getToErrorObject(to, sendTokenAddress, chainId) { let toError = null; diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.utils.test.js b/ui/pages/send/send-content/add-recipient/add-recipient.utils.test.js similarity index 91% rename from ui/app/pages/send/send-content/add-recipient/add-recipient.utils.test.js rename to ui/pages/send/send-content/add-recipient/add-recipient.utils.test.js index 33f70b876..4a9605d32 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.utils.test.js +++ b/ui/pages/send/send-content/add-recipient/add-recipient.utils.test.js @@ -7,18 +7,17 @@ import { } from '../../send.constants'; import { getToErrorObject, getToWarningObject } from './add-recipient'; -jest.mock('../../../../../app/helpers/utils/util', () => ({ +jest.mock('../../../../helpers/utils/util', () => ({ isDefaultMetaMaskChain: jest.fn().mockReturnValue(true), isEthNetwork: jest.fn().mockReturnValue(true), checkExistingAddresses: jest.fn().mockReturnValue(true), - isValidDomainName: jest.requireActual('../../../../../app/helpers/utils/util') + isValidDomainName: jest.requireActual('../../../../helpers/utils/util') .isValidDomainName, - isOriginContractAddress: jest.requireActual( - '../../../../../app/helpers/utils/util', - ).isOriginContractAddress, + isOriginContractAddress: jest.requireActual('../../../../helpers/utils/util') + .isOriginContractAddress, })); -jest.mock('../../../../../../shared/modules/hexstring-utils', () => ({ +jest.mock('../../../../../shared/modules/hexstring-utils', () => ({ isValidHexAddress: jest.fn((to) => Boolean(to.match(/^[0xabcdef123456798]+$/u)), ), diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js b/ui/pages/send/send-content/add-recipient/ens-input.component.js similarity index 98% rename from ui/app/pages/send/send-content/add-recipient/ens-input.component.js rename to ui/pages/send/send-content/add-recipient/ens-input.component.js index 9012ee643..658ac9bde 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.component.js +++ b/ui/pages/send/send-content/add-recipient/ens-input.component.js @@ -10,11 +10,11 @@ import log from 'loglevel'; import { isHexString } from 'ethereumjs-util'; import { ellipsify } from '../../send.utils'; import { isValidDomainName } from '../../../../helpers/utils/util'; -import { MAINNET_NETWORK_ID } from '../../../../../../shared/constants/network'; +import { MAINNET_NETWORK_ID } from '../../../../../shared/constants/network'; import { isBurnAddress, isValidHexAddress, -} from '../../../../../../shared/modules/hexstring-utils'; +} from '../../../../../shared/modules/hexstring-utils'; // Local Constants const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.container.js b/ui/pages/send/send-content/add-recipient/ens-input.container.js similarity index 85% rename from ui/app/pages/send/send-content/add-recipient/ens-input.container.js rename to ui/pages/send/send-content/add-recipient/ens-input.container.js index 42e75e501..90d2c3ff4 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.container.js +++ b/ui/pages/send/send-content/add-recipient/ens-input.container.js @@ -1,5 +1,5 @@ import { connect } from 'react-redux'; -import { CHAIN_ID_TO_NETWORK_ID_MAP } from '../../../../../../shared/constants/network'; +import { CHAIN_ID_TO_NETWORK_ID_MAP } from '../../../../../shared/constants/network'; import { getSendTo, getSendToNickname, diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.js b/ui/pages/send/send-content/add-recipient/ens-input.js similarity index 100% rename from ui/app/pages/send/send-content/add-recipient/ens-input.js rename to ui/pages/send/send-content/add-recipient/ens-input.js diff --git a/ui/app/pages/send/send-content/add-recipient/index.js b/ui/pages/send/send-content/add-recipient/index.js similarity index 100% rename from ui/app/pages/send/send-content/add-recipient/index.js rename to ui/pages/send/send-content/add-recipient/index.js diff --git a/ui/app/pages/send/send-content/index.js b/ui/pages/send/send-content/index.js similarity index 100% rename from ui/app/pages/send/send-content/index.js rename to ui/pages/send/send-content/index.js diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js b/ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js similarity index 100% rename from ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js rename to ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.js diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.test.js b/ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.test.js similarity index 100% rename from ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.test.js rename to ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.component.test.js diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.js b/ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.js similarity index 100% rename from ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.js rename to ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.js diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.test.js b/ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.test.js similarity index 93% rename from ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.test.js rename to ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.test.js index 4137ce0f2..90f95e6cb 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.test.js +++ b/ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.container.test.js @@ -15,7 +15,7 @@ jest.mock('react-redux', () => ({ }, })); -jest.mock('../../../../../../app/selectors', () => ({ +jest.mock('../../../../../selectors', () => ({ getGasTotal: (s) => `mockGasTotal:${s}`, getSendToken: (s) => `mockSendToken:${s}`, getSendFromBalance: (s) => `mockBalance:${s}`, @@ -28,11 +28,11 @@ jest.mock('./amount-max-button.utils.js', () => ({ calcMaxAmount: (mockObj) => mockObj.val + 1, })); -jest.mock('../../../../../../app/store/actions', () => ({ +jest.mock('../../../../../store/actions', () => ({ setMaxModeTo: jest.fn(), updateSendAmount: jest.fn(), })); -jest.mock('../../../../../../app/ducks/send/send.duck', () => ({ +jest.mock('../../../../../ducks/send/send.duck', () => ({ updateSendErrors: jest.fn(), })); diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js b/ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js similarity index 89% rename from ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js rename to ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js index 934e2fd0a..6826b5e39 100644 --- a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js +++ b/ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.js @@ -2,7 +2,7 @@ import { multiplyCurrencies, subtractCurrencies, } from '../../../../../helpers/utils/conversion-util'; -import { addHexPrefix } from '../../../../../../../app/scripts/lib/util'; +import { addHexPrefix } from '../../../../../../app/scripts/lib/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/amount-max-button.utils.test.js b/ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.test.js similarity index 100% rename from ui/app/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.test.js rename to ui/pages/send/send-content/send-amount-row/amount-max-button/amount-max-button.utils.test.js diff --git a/ui/app/pages/send/send-content/send-amount-row/amount-max-button/index.js b/ui/pages/send/send-content/send-amount-row/amount-max-button/index.js similarity index 100% rename from ui/app/pages/send/send-content/send-amount-row/amount-max-button/index.js rename to ui/pages/send/send-content/send-amount-row/amount-max-button/index.js diff --git a/ui/app/pages/send/send-content/send-amount-row/index.js b/ui/pages/send/send-content/send-amount-row/index.js similarity index 100% rename from ui/app/pages/send/send-content/send-amount-row/index.js rename to ui/pages/send/send-content/send-amount-row/index.js diff --git a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js b/ui/pages/send/send-content/send-amount-row/send-amount-row.component.js similarity index 100% rename from ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.js rename to ui/pages/send/send-content/send-amount-row/send-amount-row.component.js diff --git a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.test.js b/ui/pages/send/send-content/send-amount-row/send-amount-row.component.test.js similarity index 100% rename from ui/app/pages/send/send-content/send-amount-row/send-amount-row.component.test.js rename to ui/pages/send/send-content/send-amount-row/send-amount-row.component.test.js diff --git a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.container.js b/ui/pages/send/send-content/send-amount-row/send-amount-row.container.js similarity index 100% rename from ui/app/pages/send/send-content/send-amount-row/send-amount-row.container.js rename to ui/pages/send/send-content/send-amount-row/send-amount-row.container.js diff --git a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.container.test.js b/ui/pages/send/send-content/send-amount-row/send-amount-row.container.test.js similarity index 95% rename from ui/app/pages/send/send-content/send-amount-row/send-amount-row.container.test.js rename to ui/pages/send/send-content/send-amount-row/send-amount-row.container.test.js index 1e0979673..6d3b06aef 100644 --- a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.container.test.js +++ b/ui/pages/send/send-content/send-amount-row/send-amount-row.container.test.js @@ -28,12 +28,12 @@ jest.mock('../../send.utils', () => ({ }), })); -jest.mock('../../../../../app/store/actions', () => ({ +jest.mock('../../../../store/actions', () => ({ setMaxModeTo: jest.fn(), updateSendAmount: jest.fn(), })); -jest.mock('../../../../../app/ducks/send/send.duck', () => ({ +jest.mock('../../../../ducks/send/send.duck', () => ({ updateSendErrors: jest.fn(), })); diff --git a/ui/app/pages/send/send-content/send-amount-row/send-amount-row.scss b/ui/pages/send/send-content/send-amount-row/send-amount-row.scss similarity index 100% rename from ui/app/pages/send/send-content/send-amount-row/send-amount-row.scss rename to ui/pages/send/send-content/send-amount-row/send-amount-row.scss diff --git a/ui/app/pages/send/send-content/send-asset-row/index.js b/ui/pages/send/send-content/send-asset-row/index.js similarity index 100% rename from ui/app/pages/send/send-content/send-asset-row/index.js rename to ui/pages/send/send-content/send-asset-row/index.js diff --git a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js b/ui/pages/send/send-content/send-asset-row/send-asset-row.component.js similarity index 100% rename from ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js rename to ui/pages/send/send-content/send-asset-row/send-asset-row.component.js diff --git a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js b/ui/pages/send/send-content/send-asset-row/send-asset-row.container.js similarity index 100% rename from ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js rename to ui/pages/send/send-content/send-asset-row/send-asset-row.container.js diff --git a/ui/app/pages/send/send-content/send-content.component.js b/ui/pages/send/send-content/send-content.component.js similarity index 72% rename from ui/app/pages/send/send-content/send-content.component.js rename to ui/pages/send/send-content/send-content.component.js index 6f4fd7924..6f1a82b92 100644 --- a/ui/app/pages/send/send-content/send-content.component.js +++ b/ui/pages/send/send-content/send-content.component.js @@ -2,6 +2,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 { + ETH_GAS_PRICE_FETCH_WARNING_KEY, + GAS_PRICE_FETCH_FAILURE_ERROR_KEY, + GAS_PRICE_EXCESSIVE_ERROR_KEY, +} from '../../../helpers/constants/error-keys'; import SendAmountRow from './send-amount-row'; import SendGasRow from './send-gas-row'; import SendHexDataRow from './send-hex-data-row'; @@ -21,16 +26,30 @@ export default class SendContent extends Component { warning: PropTypes.string, error: PropTypes.string, gasIsExcessive: PropTypes.bool.isRequired, + isEthGasPrice: PropTypes.bool, + noGasPrice: PropTypes.bool, }; updateGas = (updateData) => this.props.updateGas(updateData); render() { - const { warning, error, gasIsExcessive } = this.props; + const { + warning, + error, + gasIsExcessive, + isEthGasPrice, + noGasPrice, + } = this.props; + + let gasError; + if (gasIsExcessive) gasError = GAS_PRICE_EXCESSIVE_ERROR_KEY; + else if (noGasPrice) gasError = GAS_PRICE_FETCH_FAILURE_ERROR_KEY; + return ( <PageContainerContent> <div className="send-v2__form"> - {gasIsExcessive && this.renderError(true)} + {gasError && this.renderError(gasError)} + {isEthGasPrice && this.renderWarning(ETH_GAS_PRICE_FETCH_WARNING_KEY)} {error && this.renderError()} {warning && this.renderWarning()} {this.maybeRenderAddContact()} @@ -68,24 +87,22 @@ export default class SendContent extends Component { ); } - renderWarning() { + renderWarning(gasWarning = '') { const { t } = this.context; const { warning } = this.props; - return ( <Dialog type="warning" className="send__error-dialog"> - {t(warning)} + {gasWarning === '' ? t(warning) : t(gasWarning)} </Dialog> ); } - renderError(gasError = false) { + renderError(gasError = '') { const { t } = this.context; const { error } = this.props; - return ( <Dialog type="error" className="send__error-dialog"> - {gasError ? t('gasPriceExcessive') : t(error)} + {gasError === '' ? t(error) : t(gasError)} </Dialog> ); } diff --git a/ui/app/pages/send/send-content/send-content.component.test.js b/ui/pages/send/send-content/send-content.component.test.js similarity index 97% rename from ui/app/pages/send/send-content/send-content.component.test.js rename to ui/pages/send/send-content/send-content.component.test.js index ed4485d76..0e4eb69d8 100644 --- a/ui/app/pages/send/send-content/send-content.component.test.js +++ b/ui/pages/send/send-content/send-content.component.test.js @@ -12,8 +12,13 @@ import SendAssetRow from './send-asset-row/send-asset-row.container'; describe('SendContent Component', () => { let wrapper; + const defaultProps = { + showHexData: true, + gasIsExcessive: false, + }; + beforeEach(() => { - wrapper = shallow(<SendContent showHexData />, { + wrapper = shallow(<SendContent {...defaultProps} />, { context: { t: (str) => `${str}_t` }, }); }); diff --git a/ui/app/pages/send/send-content/send-content.container.js b/ui/pages/send/send-content/send-content.container.js similarity index 88% rename from ui/app/pages/send/send-content/send-content.container.js rename to ui/pages/send/send-content/send-content.container.js index 42e115b94..3c99b3237 100644 --- a/ui/app/pages/send/send-content/send-content.container.js +++ b/ui/pages/send/send-content/send-content.container.js @@ -3,6 +3,8 @@ import { getSendTo, accountsWithSendEtherInfoSelector, getAddressBookEntry, + getIsEthGasPriceFetched, + getNoGasPriceFetched, } from '../../../selectors'; import * as actions from '../../../store/actions'; @@ -19,6 +21,8 @@ function mapStateToProps(state) { ), contact: getAddressBookEntry(state, to), to, + isEthGasPrice: getIsEthGasPriceFetched(state), + noGasPrice: getNoGasPriceFetched(state), }; } diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js b/ui/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js similarity index 100% rename from ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js rename to ui/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.js diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.test.js b/ui/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.test.js similarity index 100% rename from ui/app/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.test.js rename to ui/pages/send/send-content/send-gas-row/gas-fee-display/gas-fee-display.component.test.js diff --git a/ui/app/pages/send/send-content/send-gas-row/gas-fee-display/index.js b/ui/pages/send/send-content/send-gas-row/gas-fee-display/index.js similarity index 100% rename from ui/app/pages/send/send-content/send-gas-row/gas-fee-display/index.js rename to ui/pages/send/send-content/send-gas-row/gas-fee-display/index.js diff --git a/ui/app/pages/send/send-content/send-gas-row/index.js b/ui/pages/send/send-content/send-gas-row/index.js similarity index 100% rename from ui/app/pages/send/send-content/send-gas-row/index.js rename to ui/pages/send/send-content/send-gas-row/index.js diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js b/ui/pages/send/send-content/send-gas-row/send-gas-row.component.js similarity index 91% rename from ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js rename to ui/pages/send/send-content/send-gas-row/send-gas-row.component.js index cf74ee0f3..9cbe21629 100644 --- a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.js +++ b/ui/pages/send/send-content/send-gas-row/send-gas-row.component.js @@ -26,6 +26,8 @@ export default class SendGasRow extends Component { gasLimit: PropTypes.string, insufficientBalance: PropTypes.bool, isMainnet: PropTypes.bool, + isEthGasPrice: PropTypes.bool, + noGasPrice: PropTypes.bool, }; static contextTypes = { @@ -35,11 +37,19 @@ export default class SendGasRow extends Component { renderAdvancedOptionsButton() { const { metricsEvent } = this.context; - const { showCustomizeGasModal, isMainnet } = this.props; + const { + showCustomizeGasModal, + isMainnet, + isEthGasPrice, + noGasPrice, + } = this.props; // Tests should behave in same way as mainnet, but are using Localhost if (!isMainnet && !process.env.IN_TEST) { return null; } + if (isEthGasPrice || noGasPrice) { + return null; + } return ( <div className="advanced-gas-options-btn" @@ -92,8 +102,11 @@ export default class SendGasRow extends Component { gasLimit, insufficientBalance, isMainnet, + isEthGasPrice, + noGasPrice, } = this.props; const { metricsEvent } = this.context; + const gasPriceFetchFailure = isEthGasPrice || noGasPrice; const gasPriceButtonGroup = ( <div> @@ -148,7 +161,11 @@ export default class SendGasRow extends Component { </div> ); // Tests should behave in same way as mainnet, but are using Localhost - if (advancedInlineGasShown || (!isMainnet && !process.env.IN_TEST)) { + if ( + advancedInlineGasShown || + (!isMainnet && !process.env.IN_TEST) || + gasPriceFetchFailure + ) { return advancedGasInputs; } else if (gasButtonGroupShown) { return gasPriceButtonGroup; diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.test.js b/ui/pages/send/send-content/send-gas-row/send-gas-row.component.test.js similarity index 100% rename from ui/app/pages/send/send-content/send-gas-row/send-gas-row.component.test.js rename to ui/pages/send/send-content/send-gas-row/send-gas-row.component.test.js diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js b/ui/pages/send/send-content/send-gas-row/send-gas-row.container.js similarity index 95% rename from ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js rename to ui/pages/send/send-content/send-gas-row/send-gas-row.container.js index 210819f07..32b0529c4 100644 --- a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.js +++ b/ui/pages/send/send-content/send-gas-row/send-gas-row.container.js @@ -18,6 +18,8 @@ import { getRenderableEstimateDataForSmallButtonsFromGWEI, getDefaultActiveButtonIndex, getIsMainnet, + getIsEthGasPriceFetched, + getNoGasPriceFetched, } from '../../../../selectors'; import { isBalanceSufficient, calcGasTotal } from '../../send.utils'; import { calcMaxAmount } from '../send-amount-row/amount-max-button/amount-max-button.utils'; @@ -64,6 +66,8 @@ function mapStateToProps(state) { balance, conversionRate, }); + const isEthGasPrice = getIsEthGasPriceFetched(state); + const noGasPrice = getNoGasPriceFetched(state); return { balance: getSendFromBalance(state), @@ -85,6 +89,8 @@ function mapStateToProps(state) { sendToken: getSendToken(state), tokenBalance: getTokenBalance(state), isMainnet: getIsMainnet(state), + isEthGasPrice, + noGasPrice, }; } diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.test.js b/ui/pages/send/send-content/send-gas-row/send-gas-row.container.test.js similarity index 95% rename from ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.test.js rename to ui/pages/send/send-content/send-gas-row/send-gas-row.container.test.js index 6bd3b37cf..db322d25a 100644 --- a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.container.test.js +++ b/ui/pages/send/send-content/send-gas-row/send-gas-row.container.test.js @@ -26,7 +26,7 @@ jest.mock('react-redux', () => ({ }, })); -jest.mock('../../../../../app/selectors', () => ({ +jest.mock('../../../../selectors', () => ({ getSendMaxModeState: (s) => `mockMaxModeOn:${s}`, })); @@ -37,18 +37,18 @@ jest.mock('../../send.utils.js', () => ({ calcGasTotal: (gasLimit, gasPrice) => gasLimit + gasPrice, })); -jest.mock('../../../../../app/store/actions', () => ({ +jest.mock('../../../../store/actions', () => ({ showModal: jest.fn(), setGasPrice: jest.fn(), setGasTotal: jest.fn(), setGasLimit: jest.fn(), })); -jest.mock('../../../../../app/ducks/send/send.duck', () => ({ +jest.mock('../../../../ducks/send/send.duck', () => ({ showGasButtonGroup: jest.fn(), })); -jest.mock('../../../../../app/ducks/gas/gas.duck', () => ({ +jest.mock('../../../../ducks/gas/gas.duck', () => ({ resetCustomData: jest.fn(), setCustomGasPrice: jest.fn(), setCustomGasLimit: jest.fn(), diff --git a/ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss b/ui/pages/send/send-content/send-gas-row/send-gas-row.scss similarity index 100% rename from ui/app/pages/send/send-content/send-gas-row/send-gas-row.scss rename to ui/pages/send/send-content/send-gas-row/send-gas-row.scss diff --git a/ui/app/pages/send/send-content/send-hex-data-row/index.js b/ui/pages/send/send-content/send-hex-data-row/index.js similarity index 100% rename from ui/app/pages/send/send-content/send-hex-data-row/index.js rename to ui/pages/send/send-content/send-hex-data-row/index.js diff --git a/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js b/ui/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js similarity index 100% rename from ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js rename to ui/pages/send/send-content/send-hex-data-row/send-hex-data-row.component.js diff --git a/ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.container.js b/ui/pages/send/send-content/send-hex-data-row/send-hex-data-row.container.js similarity index 100% rename from ui/app/pages/send/send-content/send-hex-data-row/send-hex-data-row.container.js rename to ui/pages/send/send-content/send-hex-data-row/send-hex-data-row.container.js diff --git a/ui/app/pages/send/send-content/send-row-wrapper/index.js b/ui/pages/send/send-content/send-row-wrapper/index.js similarity index 100% rename from ui/app/pages/send/send-content/send-row-wrapper/index.js rename to ui/pages/send/send-content/send-row-wrapper/index.js diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/index.js b/ui/pages/send/send-content/send-row-wrapper/send-row-error-message/index.js similarity index 100% rename from ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/index.js rename to ui/pages/send/send-content/send-row-wrapper/send-row-error-message/index.js diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.js b/ui/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.js similarity index 100% rename from ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.js rename to ui/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.js diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.test.js b/ui/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.test.js similarity index 100% rename from ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.test.js rename to ui/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.component.test.js diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.container.js b/ui/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.container.js similarity index 100% rename from ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.container.js rename to ui/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.container.js diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.container.test.js b/ui/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.container.test.js similarity index 100% rename from ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.container.test.js rename to ui/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.container.test.js diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.scss b/ui/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.scss similarity index 100% rename from ui/app/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.scss rename to ui/pages/send/send-content/send-row-wrapper/send-row-error-message/send-row-error-message.scss diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-wrapper.component.js b/ui/pages/send/send-content/send-row-wrapper/send-row-wrapper.component.js similarity index 100% rename from ui/app/pages/send/send-content/send-row-wrapper/send-row-wrapper.component.js rename to ui/pages/send/send-content/send-row-wrapper/send-row-wrapper.component.js diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-wrapper.component.test.js b/ui/pages/send/send-content/send-row-wrapper/send-row-wrapper.component.test.js similarity index 100% rename from ui/app/pages/send/send-content/send-row-wrapper/send-row-wrapper.component.test.js rename to ui/pages/send/send-content/send-row-wrapper/send-row-wrapper.component.test.js diff --git a/ui/app/pages/send/send-content/send-row-wrapper/send-row-wrapper.scss b/ui/pages/send/send-content/send-row-wrapper/send-row-wrapper.scss similarity index 100% rename from ui/app/pages/send/send-content/send-row-wrapper/send-row-wrapper.scss rename to ui/pages/send/send-content/send-row-wrapper/send-row-wrapper.scss diff --git a/ui/app/pages/send/send-footer/index.js b/ui/pages/send/send-footer/index.js similarity index 100% rename from ui/app/pages/send/send-footer/index.js rename to ui/pages/send/send-footer/index.js diff --git a/ui/app/pages/send/send-footer/send-footer.component.js b/ui/pages/send/send-footer/send-footer.component.js similarity index 97% rename from ui/app/pages/send/send-footer/send-footer.component.js rename to ui/pages/send/send-footer/send-footer.component.js index 5956d9517..ef18f48b1 100644 --- a/ui/app/pages/send/send-footer/send-footer.component.js +++ b/ui/pages/send/send-footer/send-footer.component.js @@ -27,6 +27,7 @@ export default class SendFooter extends Component { gasEstimateType: PropTypes.string, gasIsLoading: PropTypes.bool, mostRecentOverviewPage: PropTypes.string.isRequired, + noGasPrice: PropTypes.bool, }; static contextTypes = { @@ -109,6 +110,7 @@ export default class SendFooter extends Component { to, gasLimit, gasIsLoading, + noGasPrice, } = this.props; const missingTokenBalance = sendToken && !tokenBalance; const gasLimitTooLow = gasLimit < 5208; // 5208 is hex value of 21000, minimum gas limit @@ -118,7 +120,8 @@ export default class SendFooter extends Component { missingTokenBalance || !(data || to) || gasLimitTooLow || - gasIsLoading; + gasIsLoading || + noGasPrice; return shouldBeDisabled; } diff --git a/ui/app/pages/send/send-footer/send-footer.component.test.js b/ui/pages/send/send-footer/send-footer.component.test.js similarity index 99% rename from ui/app/pages/send/send-footer/send-footer.component.test.js rename to ui/pages/send/send-footer/send-footer.component.test.js index cdcc06308..900c26b2a 100644 --- a/ui/app/pages/send/send-footer/send-footer.component.test.js +++ b/ui/pages/send/send-footer/send-footer.component.test.js @@ -49,6 +49,7 @@ describe('SendFooter Component', () => { update={propsMethodSpies.update} sendErrors={{}} mostRecentOverviewPage="mostRecentOverviewPage" + noGasPrice={false} />, { context: { t: (str) => str, metricsEvent: () => ({}) } }, ); diff --git a/ui/app/pages/send/send-footer/send-footer.container.js b/ui/pages/send/send-footer/send-footer.container.js similarity index 95% rename from ui/app/pages/send/send-footer/send-footer.container.js rename to ui/pages/send/send-footer/send-footer.container.js index ff7b475bc..e8ea039e1 100644 --- a/ui/app/pages/send/send-footer/send-footer.container.js +++ b/ui/pages/send/send-footer/send-footer.container.js @@ -24,9 +24,10 @@ import { getGasIsLoading, getRenderableEstimateDataForSmallButtonsFromGWEI, getDefaultActiveButtonIndex, + getNoGasPriceFetched, } from '../../../selectors'; import { getMostRecentOverviewPage } from '../../../ducks/history/history'; -import { addHexPrefix } from '../../../../../app/scripts/lib/util'; +import { addHexPrefix } from '../../../../app/scripts/lib/util'; import SendFooter from './send-footer.component'; import { addressIsNew, @@ -67,6 +68,7 @@ function mapStateToProps(state) { gasEstimateType, gasIsLoading: getGasIsLoading(state), mostRecentOverviewPage: getMostRecentOverviewPage(state), + noGasPrice: getNoGasPriceFetched(state), }; } diff --git a/ui/app/pages/send/send-footer/send-footer.container.test.js b/ui/pages/send/send-footer/send-footer.container.test.js similarity index 96% rename from ui/app/pages/send/send-footer/send-footer.container.test.js rename to ui/pages/send/send-footer/send-footer.container.test.js index 56e280b70..7fb79cbae 100644 --- a/ui/app/pages/send/send-footer/send-footer.container.test.js +++ b/ui/pages/send/send-footer/send-footer.container.test.js @@ -21,7 +21,7 @@ jest.mock('react-redux', () => ({ }, })); -jest.mock('../../../../app/store/actions.js', () => ({ +jest.mock('../../../store/actions.js', () => ({ addToAddressBook: jest.fn(), clearSend: jest.fn(), signTokenTx: jest.fn(), @@ -29,7 +29,7 @@ jest.mock('../../../../app/store/actions.js', () => ({ updateTransaction: jest.fn(), })); -jest.mock('../../../../app/selectors/send.js', () => ({ +jest.mock('../../../selectors/send.js', () => ({ getGasLimit: (s) => `mockGasLimit:${s}`, getGasPrice: (s) => `mockGasPrice:${s}`, getGasTotal: (s) => `mockGasTotal:${s}`, @@ -48,7 +48,7 @@ jest.mock('../../../../app/selectors/send.js', () => ({ getDefaultActiveButtonIndex: () => 0, })); -jest.mock('../../../../app/selectors/custom-gas.js', () => ({ +jest.mock('../../../selectors/custom-gas.js', () => ({ getRenderableEstimateDataForSmallButtonsFromGWEI: (s) => [ { gasEstimateType: `mockGasEstimateType:${s}` }, ], diff --git a/ui/app/pages/send/send-footer/send-footer.scss b/ui/pages/send/send-footer/send-footer.scss similarity index 100% rename from ui/app/pages/send/send-footer/send-footer.scss rename to ui/pages/send/send-footer/send-footer.scss diff --git a/ui/app/pages/send/send-footer/send-footer.utils.js b/ui/pages/send/send-footer/send-footer.utils.js similarity index 96% rename from ui/app/pages/send/send-footer/send-footer.utils.js rename to ui/pages/send/send-footer/send-footer.utils.js index 52be9143f..778b07867 100644 --- a/ui/app/pages/send/send-footer/send-footer.utils.js +++ b/ui/pages/send/send-footer/send-footer.utils.js @@ -1,6 +1,6 @@ import ethAbi from 'ethereumjs-abi'; import { TOKEN_TRANSFER_FUNCTION_SIGNATURE } from '../send.constants'; -import { addHexPrefix } from '../../../../../app/scripts/lib/util'; +import { addHexPrefix } from '../../../../app/scripts/lib/util'; import { addHexPrefixToObjectValues } from '../../../helpers/utils/util'; export function constructTxParams({ diff --git a/ui/app/pages/send/send-footer/send-footer.utils.test.js b/ui/pages/send/send-footer/send-footer.utils.test.js similarity index 100% rename from ui/app/pages/send/send-footer/send-footer.utils.test.js rename to ui/pages/send/send-footer/send-footer.utils.test.js diff --git a/ui/app/pages/send/send-header/index.js b/ui/pages/send/send-header/index.js similarity index 100% rename from ui/app/pages/send/send-header/index.js rename to ui/pages/send/send-header/index.js diff --git a/ui/app/pages/send/send-header/send-header.component.js b/ui/pages/send/send-header/send-header.component.js similarity index 100% rename from ui/app/pages/send/send-header/send-header.component.js rename to ui/pages/send/send-header/send-header.component.js diff --git a/ui/app/pages/send/send-header/send-header.component.test.js b/ui/pages/send/send-header/send-header.component.test.js similarity index 100% rename from ui/app/pages/send/send-header/send-header.component.test.js rename to ui/pages/send/send-header/send-header.component.test.js diff --git a/ui/app/pages/send/send-header/send-header.container.js b/ui/pages/send/send-header/send-header.container.js similarity index 100% rename from ui/app/pages/send/send-header/send-header.container.js rename to ui/pages/send/send-header/send-header.container.js diff --git a/ui/app/pages/send/send.component.js b/ui/pages/send/send.component.js similarity index 99% rename from ui/app/pages/send/send.component.js rename to ui/pages/send/send.component.js index 24bd3dc7a..6954f9cfc 100644 --- a/ui/app/pages/send/send.component.js +++ b/ui/pages/send/send.component.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { debounce } from 'lodash'; -import { isValidHexAddress } from '../../../../shared/modules/hexstring-utils'; +import { isValidHexAddress } from '../../../shared/modules/hexstring-utils'; import { getAmountErrorObject, getGasFeeErrorObject, diff --git a/ui/app/pages/send/send.component.test.js b/ui/pages/send/send.component.test.js similarity index 99% rename from ui/app/pages/send/send.component.test.js rename to ui/pages/send/send.component.test.js index bfceb20dd..5cc90307e 100644 --- a/ui/app/pages/send/send.component.test.js +++ b/ui/pages/send/send.component.test.js @@ -4,7 +4,7 @@ import sinon from 'sinon'; import { RINKEBY_CHAIN_ID, ROPSTEN_CHAIN_ID, -} from '../../../../shared/constants/network'; +} from '../../../shared/constants/network'; import SendTransactionScreen from './send.component'; import * as util from './send.utils'; diff --git a/ui/app/pages/send/send.constants.js b/ui/pages/send/send.constants.js similarity index 96% rename from ui/app/pages/send/send.constants.js rename to ui/pages/send/send.constants.js index 93b620d14..ffeaf0397 100644 --- a/ui/app/pages/send/send.constants.js +++ b/ui/pages/send/send.constants.js @@ -2,7 +2,7 @@ import { conversionUtil, multiplyCurrencies, } from '../../helpers/utils/conversion-util'; -import { addHexPrefix } from '../../../../app/scripts/lib/util'; +import { addHexPrefix } from '../../../app/scripts/lib/util'; const MIN_GAS_PRICE_DEC = '0'; const MIN_GAS_PRICE_HEX = parseInt(MIN_GAS_PRICE_DEC, 10).toString(16); diff --git a/ui/app/pages/send/send.container.js b/ui/pages/send/send.container.js similarity index 100% rename from ui/app/pages/send/send.container.js rename to ui/pages/send/send.container.js diff --git a/ui/app/pages/send/send.container.test.js b/ui/pages/send/send.container.test.js similarity index 97% rename from ui/app/pages/send/send.container.test.js rename to ui/pages/send/send.container.test.js index be7f137e9..bb2aca2dd 100644 --- a/ui/app/pages/send/send.container.test.js +++ b/ui/pages/send/send.container.test.js @@ -25,12 +25,12 @@ jest.mock('redux', () => ({ compose: (_, arg2) => () => arg2(), })); -jest.mock('../../../app/store/actions', () => ({ +jest.mock('../../store/actions', () => ({ updateSendTokenBalance: jest.fn(), updateGasData: jest.fn(), setGasTotal: jest.fn(), })); -jest.mock('../../../app/ducks/send/send.duck', () => ({ +jest.mock('../../ducks/send/send.duck', () => ({ updateSendErrors: jest.fn(), resetSendState: jest.fn(), })); diff --git a/ui/app/pages/send/send.scss b/ui/pages/send/send.scss similarity index 100% rename from ui/app/pages/send/send.scss rename to ui/pages/send/send.scss diff --git a/ui/app/pages/send/send.utils.js b/ui/pages/send/send.utils.js similarity index 99% rename from ui/app/pages/send/send.utils.js rename to ui/pages/send/send.utils.js index ffe76241d..1603061e2 100644 --- a/ui/app/pages/send/send.utils.js +++ b/ui/pages/send/send.utils.js @@ -9,7 +9,7 @@ import { } from '../../helpers/utils/conversion-util'; import { calcTokenAmount } from '../../helpers/utils/token-util'; -import { addHexPrefix } from '../../../../app/scripts/lib/util'; +import { addHexPrefix } from '../../../app/scripts/lib/util'; import { BASE_TOKEN_GAS_COST, diff --git a/ui/app/pages/send/send.utils.test.js b/ui/pages/send/send.utils.test.js similarity index 99% rename from ui/app/pages/send/send.utils.test.js rename to ui/pages/send/send.utils.test.js index f94c00fdc..06d3d8edc 100644 --- a/ui/app/pages/send/send.utils.test.js +++ b/ui/pages/send/send.utils.test.js @@ -29,7 +29,7 @@ import { INSUFFICIENT_TOKENS_ERROR, } from './send.constants'; -jest.mock('../../../app/helpers/utils/conversion-util', () => ({ +jest.mock('../../helpers/utils/conversion-util', () => ({ addCurrencies: jest.fn((a, b) => { let [a1, b1] = [a, b]; if (String(a).match(/^0x.+/u)) { @@ -47,7 +47,7 @@ jest.mock('../../../app/helpers/utils/conversion-util', () => ({ conversionLessThan: (obj1, obj2) => obj1.value < obj2.value, })); -jest.mock('../../../app/helpers/utils/token-util', () => ({ +jest.mock('../../helpers/utils/token-util', () => ({ calcTokenAmount: (a, d) => `calc:${a}${d}`, })); diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js b/ui/pages/settings/advanced-tab/advanced-tab.component.js similarity index 92% rename from ui/app/pages/settings/advanced-tab/advanced-tab.component.js rename to ui/pages/settings/advanced-tab/advanced-tab.component.js index ef95e84f2..09e70a303 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.component.js +++ b/ui/pages/settings/advanced-tab/advanced-tab.component.js @@ -7,8 +7,8 @@ import TextField from '../../../components/ui/text-field'; import Button from '../../../components/ui/button'; import { MOBILE_SYNC_ROUTE } from '../../../helpers/constants/routes'; -import { getPlatform } from '../../../../../app/scripts/lib/util'; -import { PLATFORM_FIREFOX } from '../../../../../shared/constants/app'; +import { getPlatform } from '../../../../app/scripts/lib/util'; +import { PLATFORM_FIREFOX } from '../../../../shared/constants/app'; export default class AdvancedTab extends PureComponent { static contextTypes = { @@ -38,6 +38,8 @@ export default class AdvancedTab extends PureComponent { ipfsGateway: PropTypes.string.isRequired, useLedgerLive: PropTypes.bool.isRequired, setLedgerLivePreference: PropTypes.func.isRequired, + setDismissSeedBackUpReminder: PropTypes.func.isRequired, + dismissSeedBackUpReminder: PropTypes.bool.isRequired, }; state = { @@ -258,7 +260,7 @@ export default class AdvancedTab extends PureComponent { data-testid="advanced-setting-custom-nonce" > <div className="settings-page__content-item"> - <span>{this.context.t('nonceField')}</span> + <span>{t('nonceField')}</span> <div className="settings-page__content-description"> {t('nonceFieldDescription')} </div> @@ -494,6 +496,38 @@ export default class AdvancedTab extends PureComponent { ); } + renderDismissSeedBackupReminderControl() { + const { t } = this.context; + const { + dismissSeedBackUpReminder, + setDismissSeedBackUpReminder, + } = this.props; + + return ( + <div + className="settings-page__content-row" + data-testid="advanced-setting-dismiss-reminder" + > + <div className="settings-page__content-item"> + <span>{t('dismissReminderField')}</span> + <div className="settings-page__content-description"> + {t('dismissReminderDescriptionField')} + </div> + </div> + <div className="settings-page__content-item"> + <div className="settings-page__content-item-col"> + <ToggleButton + value={dismissSeedBackUpReminder} + onToggle={(value) => setDismissSeedBackUpReminder(!value)} + offLabel={t('off')} + onLabel={t('on')} + /> + </div> + </div> + </div> + ); + } + render() { const { warning } = this.props; @@ -511,6 +545,7 @@ export default class AdvancedTab extends PureComponent { {this.renderThreeBoxControl()} {this.renderIpfsGatewayControl()} {this.renderLedgerLiveControl()} + {this.renderDismissSeedBackupReminderControl()} </div> ); } diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.component.test.js b/ui/pages/settings/advanced-tab/advanced-tab.component.test.js similarity index 82% rename from ui/app/pages/settings/advanced-tab/advanced-tab.component.test.js rename to ui/pages/settings/advanced-tab/advanced-tab.component.test.js index b73b90212..eb78d3c21 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.component.test.js +++ b/ui/pages/settings/advanced-tab/advanced-tab.component.test.js @@ -15,6 +15,10 @@ describe('AdvancedTab Component', () => { setThreeBoxSyncingPermission={() => undefined} threeBoxDisabled threeBoxSyncingAllowed={false} + useLedgerLive={false} + setLedgerLivePreference={() => undefined} + setDismissSeedBackUpReminder={() => undefined} + dismissSeedBackUpReminder={false} />, { context: { @@ -23,7 +27,7 @@ describe('AdvancedTab Component', () => { }, ); - expect(root.find('.settings-page__content-row')).toHaveLength(11); + expect(root.find('.settings-page__content-row')).toHaveLength(12); }); it('should update autoLockTimeLimit', () => { @@ -37,6 +41,10 @@ describe('AdvancedTab Component', () => { setThreeBoxSyncingPermission={() => undefined} threeBoxDisabled threeBoxSyncingAllowed={false} + useLedgerLive={false} + setLedgerLivePreference={() => undefined} + setDismissSeedBackUpReminder={() => undefined} + dismissSeedBackUpReminder={false} />, { context: { diff --git a/ui/app/pages/settings/advanced-tab/advanced-tab.container.js b/ui/pages/settings/advanced-tab/advanced-tab.container.js similarity index 88% rename from ui/app/pages/settings/advanced-tab/advanced-tab.container.js rename to ui/pages/settings/advanced-tab/advanced-tab.container.js index 2fe9eaf39..3ea88dc8d 100644 --- a/ui/app/pages/settings/advanced-tab/advanced-tab.container.js +++ b/ui/pages/settings/advanced-tab/advanced-tab.container.js @@ -12,6 +12,7 @@ import { setUseNonceField, setIpfsGateway, setLedgerLivePreference, + setDismissSeedBackUpReminder, } from '../../../store/actions'; import { getPreferences } from '../../../selectors'; import AdvancedTab from './advanced-tab.component'; @@ -28,6 +29,7 @@ export const mapStateToProps = (state) => { useNonceField, ipfsGateway, useLedgerLive, + dismissSeedBackUpReminder, } = metamask; const { showFiatInTestnets, autoLockTimeLimit } = getPreferences(state); @@ -42,6 +44,7 @@ export const mapStateToProps = (state) => { useNonceField, ipfsGateway, useLedgerLive, + dismissSeedBackUpReminder, }; }; @@ -71,8 +74,12 @@ export const mapDispatchToProps = (dispatch) => { setIpfsGateway: (value) => { return dispatch(setIpfsGateway(value)); }, - setLedgerLivePreference: (value) => - dispatch(setLedgerLivePreference(value)), + setLedgerLivePreference: (value) => { + return dispatch(setLedgerLivePreference(value)); + }, + setDismissSeedBackUpReminder: (value) => { + return dispatch(setDismissSeedBackUpReminder(value)); + }, }; }; diff --git a/ui/app/pages/settings/advanced-tab/index.js b/ui/pages/settings/advanced-tab/index.js similarity index 100% rename from ui/app/pages/settings/advanced-tab/index.js rename to ui/pages/settings/advanced-tab/index.js diff --git a/ui/app/pages/settings/alerts-tab/alerts-tab.js b/ui/pages/settings/alerts-tab/alerts-tab.js similarity index 96% rename from ui/app/pages/settings/alerts-tab/alerts-tab.js rename to ui/pages/settings/alerts-tab/alerts-tab.js index cdf77c7a5..c8d092470 100644 --- a/ui/app/pages/settings/alerts-tab/alerts-tab.js +++ b/ui/pages/settings/alerts-tab/alerts-tab.js @@ -2,7 +2,7 @@ import React from 'react'; import PropTypes from 'prop-types'; import { useSelector } from 'react-redux'; -import { ALERT_TYPES } from '../../../../../shared/constants/alerts'; +import { ALERT_TYPES } from '../../../../shared/constants/alerts'; import Tooltip from '../../../components/ui/tooltip'; import ToggleButton from '../../../components/ui/toggle-button'; import { setAlertEnabledness } from '../../../store/actions'; diff --git a/ui/app/pages/settings/alerts-tab/alerts-tab.scss b/ui/pages/settings/alerts-tab/alerts-tab.scss similarity index 100% rename from ui/app/pages/settings/alerts-tab/alerts-tab.scss rename to ui/pages/settings/alerts-tab/alerts-tab.scss diff --git a/ui/app/pages/settings/alerts-tab/index.js b/ui/pages/settings/alerts-tab/index.js similarity index 100% rename from ui/app/pages/settings/alerts-tab/index.js rename to ui/pages/settings/alerts-tab/index.js diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js b/ui/pages/settings/contact-list-tab/add-contact/add-contact.component.js similarity index 98% rename from ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js rename to ui/pages/settings/contact-list-tab/add-contact/add-contact.component.js index 8ddd29ac2..e454838d1 100644 --- a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.component.js +++ b/ui/pages/settings/contact-list-tab/add-contact/add-contact.component.js @@ -10,7 +10,7 @@ import PageContainerFooter from '../../../../components/ui/page-container/page-c import { isBurnAddress, isValidHexAddress, -} from '../../../../../../shared/modules/hexstring-utils'; +} from '../../../../../shared/modules/hexstring-utils'; export default class AddContact extends PureComponent { static contextTypes = { @@ -69,7 +69,6 @@ export default class AddContact extends PureComponent { renderInput() { return ( <EnsInput - className="send__to-row" scanQrCode={(_) => { this.props.scanQrCode(); }} diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js b/ui/pages/settings/contact-list-tab/add-contact/add-contact.container.js similarity index 100% rename from ui/app/pages/settings/contact-list-tab/add-contact/add-contact.container.js rename to ui/pages/settings/contact-list-tab/add-contact/add-contact.container.js diff --git a/ui/app/pages/settings/contact-list-tab/add-contact/index.js b/ui/pages/settings/contact-list-tab/add-contact/index.js similarity index 100% rename from ui/app/pages/settings/contact-list-tab/add-contact/index.js rename to ui/pages/settings/contact-list-tab/add-contact/index.js diff --git a/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js b/ui/pages/settings/contact-list-tab/contact-list-tab.component.js similarity index 97% rename from ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js rename to ui/pages/settings/contact-list-tab/contact-list-tab.component.js index 53e38c0a3..1c8e132a0 100644 --- a/ui/app/pages/settings/contact-list-tab/contact-list-tab.component.js +++ b/ui/pages/settings/contact-list-tab/contact-list-tab.component.js @@ -49,7 +49,7 @@ export default class ContactListTab extends Component { return ( <div className="address-book__container"> <div> - <img src="/images/address-book.svg" alt="Address book icon" /> + <img src="./images/address-book.svg" alt="Address book icon" /> <h4 className="address-book__title">{t('builContactList')}</h4> <p className="address-book__sub-title"> {t('addFriendsAndAddresses')} diff --git a/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js b/ui/pages/settings/contact-list-tab/contact-list-tab.container.js similarity index 89% rename from ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js rename to ui/pages/settings/contact-list-tab/contact-list-tab.container.js index 0d80480b5..60e760a11 100644 --- a/ui/app/pages/settings/contact-list-tab/contact-list-tab.container.js +++ b/ui/pages/settings/contact-list-tab/contact-list-tab.container.js @@ -2,8 +2,8 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { getAddressBook } from '../../../selectors'; -import { ENVIRONMENT_TYPE_POPUP } from '../../../../../shared/constants/app'; -import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { CONTACT_ADD_ROUTE, diff --git a/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js b/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js similarity index 98% rename from ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js rename to ui/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js index 00725f6ea..51419b302 100644 --- a/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js +++ b/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.component.js @@ -8,7 +8,7 @@ import PageContainerFooter from '../../../../components/ui/page-container/page-c import { isBurnAddress, isValidHexAddress, -} from '../../../../../../shared/modules/hexstring-utils'; +} from '../../../../../shared/modules/hexstring-utils'; export default class EditContact extends PureComponent { static contextTypes = { diff --git a/ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js b/ui/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js similarity index 100% rename from ui/app/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js rename to ui/pages/settings/contact-list-tab/edit-contact/edit-contact.container.js diff --git a/ui/app/pages/settings/contact-list-tab/edit-contact/index.js b/ui/pages/settings/contact-list-tab/edit-contact/index.js similarity index 100% rename from ui/app/pages/settings/contact-list-tab/edit-contact/index.js rename to ui/pages/settings/contact-list-tab/edit-contact/index.js diff --git a/ui/app/pages/settings/contact-list-tab/index.js b/ui/pages/settings/contact-list-tab/index.js similarity index 100% rename from ui/app/pages/settings/contact-list-tab/index.js rename to ui/pages/settings/contact-list-tab/index.js diff --git a/ui/app/pages/settings/contact-list-tab/index.scss b/ui/pages/settings/contact-list-tab/index.scss similarity index 100% rename from ui/app/pages/settings/contact-list-tab/index.scss rename to ui/pages/settings/contact-list-tab/index.scss diff --git a/ui/app/pages/settings/contact-list-tab/view-contact/index.js b/ui/pages/settings/contact-list-tab/view-contact/index.js similarity index 100% rename from ui/app/pages/settings/contact-list-tab/view-contact/index.js rename to ui/pages/settings/contact-list-tab/view-contact/index.js diff --git a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js b/ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js similarity index 100% rename from ui/app/pages/settings/contact-list-tab/view-contact/view-contact.component.js rename to ui/pages/settings/contact-list-tab/view-contact/view-contact.component.js diff --git a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js b/ui/pages/settings/contact-list-tab/view-contact/view-contact.container.js similarity index 92% rename from ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js rename to ui/pages/settings/contact-list-tab/view-contact/view-contact.container.js index 2ce020ffa..275273d0a 100644 --- a/ui/app/pages/settings/contact-list-tab/view-contact/view-contact.container.js +++ b/ui/pages/settings/contact-list-tab/view-contact/view-contact.container.js @@ -6,7 +6,7 @@ import { CONTACT_EDIT_ROUTE, CONTACT_LIST_ROUTE, } from '../../../../helpers/constants/routes'; -import { toChecksumHexAddress } from '../../../../../../shared/modules/hexstring-utils'; +import { toChecksumHexAddress } from '../../../../../shared/modules/hexstring-utils'; import ViewContact from './view-contact.component'; const mapStateToProps = (state, ownProps) => { diff --git a/ui/app/pages/settings/index.js b/ui/pages/settings/index.js similarity index 100% rename from ui/app/pages/settings/index.js rename to ui/pages/settings/index.js diff --git a/ui/app/pages/settings/index.scss b/ui/pages/settings/index.scss similarity index 100% rename from ui/app/pages/settings/index.scss rename to ui/pages/settings/index.scss diff --git a/ui/app/pages/settings/info-tab/index.js b/ui/pages/settings/info-tab/index.js similarity index 100% rename from ui/app/pages/settings/info-tab/index.js rename to ui/pages/settings/info-tab/index.js diff --git a/ui/app/pages/settings/info-tab/index.scss b/ui/pages/settings/info-tab/index.scss similarity index 100% rename from ui/app/pages/settings/info-tab/index.scss rename to ui/pages/settings/info-tab/index.scss diff --git a/ui/app/pages/settings/info-tab/info-tab.component.js b/ui/pages/settings/info-tab/info-tab.component.js similarity index 100% rename from ui/app/pages/settings/info-tab/info-tab.component.js rename to ui/pages/settings/info-tab/info-tab.component.js diff --git a/ui/app/pages/settings/networks-tab/index.js b/ui/pages/settings/networks-tab/index.js similarity index 100% rename from ui/app/pages/settings/networks-tab/index.js rename to ui/pages/settings/networks-tab/index.js diff --git a/ui/app/pages/settings/networks-tab/index.scss b/ui/pages/settings/networks-tab/index.scss similarity index 100% rename from ui/app/pages/settings/networks-tab/index.scss rename to ui/pages/settings/networks-tab/index.scss diff --git a/ui/app/pages/settings/networks-tab/network-form/index.js b/ui/pages/settings/networks-tab/network-form/index.js similarity index 100% rename from ui/app/pages/settings/networks-tab/network-form/index.js rename to ui/pages/settings/networks-tab/network-form/index.js diff --git a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js b/ui/pages/settings/networks-tab/network-form/network-form.component.js similarity index 91% rename from ui/app/pages/settings/networks-tab/network-form/network-form.component.js rename to ui/pages/settings/networks-tab/network-form/network-form.component.js index 58a3f5754..07163a6a8 100644 --- a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js +++ b/ui/pages/settings/networks-tab/network-form/network-form.component.js @@ -8,8 +8,8 @@ import Tooltip from '../../../../components/ui/tooltip'; import { isPrefixedFormattedHexString, isSafeChainId, -} from '../../../../../../shared/modules/network.utils'; -import { jsonRpcRequest } from '../../../../../../shared/modules/rpc.utils'; +} from '../../../../../shared/modules/network.utils'; +import { jsonRpcRequest } from '../../../../../shared/modules/rpc.utils'; const FORM_STATE_KEYS = [ 'rpcUrl', @@ -139,6 +139,20 @@ export default class NetworkForm extends PureComponent { return parseInt(chainId, 16).toString(10); } + /** + * Prefixes a given id with '0x' if the prefix does not exist + * + * @param {string} chainId - The chainId to prefix + * @returns {string} The chainId, prefixed with '0x' + */ + prefixChainId(chainId) { + let prefixedChainId = chainId; + if (!chainId.startsWith('0x')) { + prefixedChainId = `0x${parseInt(chainId, 10).toString(16)}`; + } + return prefixedChainId; + } + onSubmit = async () => { this.setState({ isSubmitting: true, @@ -162,11 +176,7 @@ export default class NetworkForm extends PureComponent { } = this.state; const formChainId = stateChainId.trim().toLowerCase(); - // Ensure chainId is a 0x-prefixed, lowercase hex string - let chainId = formChainId; - if (!chainId.startsWith('0x')) { - chainId = `0x${parseInt(chainId, 10).toString(16)}`; - } + const chainId = this.prefixChainId(formChainId); if (!(await this.validateChainIdOnSubmit(formChainId, chainId, rpcUrl))) { this.setState({ @@ -317,6 +327,10 @@ export default class NetworkForm extends PureComponent { }); }; + hasError = (errorKey, errorVal) => { + return this.state.errors[errorKey] === errorVal; + }; + validateChainIdOnChange = (chainIdArg = '') => { const chainId = chainIdArg.trim(); let errorMessage = ''; @@ -392,6 +406,8 @@ export default class NetworkForm extends PureComponent { this.setErrorTo('chainId', errorMessage); return false; } + + this.setErrorTo('chainId', ''); return true; }; @@ -416,9 +432,16 @@ export default class NetworkForm extends PureComponent { }; validateUrlRpcUrl = (url, stateKey) => { + const { t } = this.context; const { rpcUrls } = this.props; + const { chainId: stateChainId } = this.state; + const isValidUrl = validUrl.isWebUri(url) && url !== ''; + const chainIdFetchFailed = this.hasError( + 'chainId', + t('failedToFetchChainId'), + ); - if (!validUrl.isWebUri(url) && url !== '') { + if (!isValidUrl) { this.setErrorTo( stateKey, this.context.t( @@ -430,6 +453,13 @@ export default class NetworkForm extends PureComponent { } else { this.setErrorTo(stateKey, ''); } + + // Re-validate the chain id if it could not be found with previous rpc url + if (stateChainId && isValidUrl && chainIdFetchFailed) { + const formChainId = stateChainId.trim().toLowerCase(); + const chainId = this.prefixChainId(formChainId); + this.validateChainIdOnSubmit(formChainId, chainId, url); + } }; renderWarning() { diff --git a/ui/app/pages/settings/networks-tab/networks-tab.component.js b/ui/pages/settings/networks-tab/networks-tab.component.js similarity index 99% rename from ui/app/pages/settings/networks-tab/networks-tab.component.js rename to ui/pages/settings/networks-tab/networks-tab.component.js index f62a40790..e4fb230c7 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.component.js +++ b/ui/pages/settings/networks-tab/networks-tab.component.js @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; -import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; +import { NETWORK_TYPE_RPC } from '../../../../shared/constants/network'; import Button from '../../../components/ui/button'; import LockIcon from '../../../components/ui/lock-icon'; import { diff --git a/ui/app/pages/settings/networks-tab/networks-tab.constants.js b/ui/pages/settings/networks-tab/networks-tab.constants.js similarity index 96% rename from ui/app/pages/settings/networks-tab/networks-tab.constants.js rename to ui/pages/settings/networks-tab/networks-tab.constants.js index 52f6514d7..91fdbe251 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.constants.js +++ b/ui/pages/settings/networks-tab/networks-tab.constants.js @@ -9,7 +9,7 @@ import { RINKEBY_CHAIN_ID, ROPSTEN, ROPSTEN_CHAIN_ID, -} from '../../../../../shared/constants/network'; +} from '../../../../shared/constants/network'; const defaultNetworksData = [ { diff --git a/ui/app/pages/settings/networks-tab/networks-tab.container.js b/ui/pages/settings/networks-tab/networks-tab.container.js similarity index 93% rename from ui/app/pages/settings/networks-tab/networks-tab.container.js rename to ui/pages/settings/networks-tab/networks-tab.container.js index 75b637159..2878cbf11 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.container.js +++ b/ui/pages/settings/networks-tab/networks-tab.container.js @@ -10,9 +10,9 @@ import { showModal, } from '../../../store/actions'; import { NETWORKS_FORM_ROUTE } from '../../../helpers/constants/routes'; -import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app'; -import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; -import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../shared/constants/app'; +import { NETWORK_TYPE_RPC } from '../../../../shared/constants/network'; +import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import NetworksTab from './networks-tab.component'; import { defaultNetworksData } from './networks-tab.constants'; diff --git a/ui/app/pages/settings/security-tab/index.js b/ui/pages/settings/security-tab/index.js similarity index 100% rename from ui/app/pages/settings/security-tab/index.js rename to ui/pages/settings/security-tab/index.js diff --git a/ui/app/pages/settings/security-tab/security-tab.component.js b/ui/pages/settings/security-tab/security-tab.component.js similarity index 100% rename from ui/app/pages/settings/security-tab/security-tab.component.js rename to ui/pages/settings/security-tab/security-tab.component.js diff --git a/ui/app/pages/settings/security-tab/security-tab.container.js b/ui/pages/settings/security-tab/security-tab.container.js similarity index 100% rename from ui/app/pages/settings/security-tab/security-tab.container.js rename to ui/pages/settings/security-tab/security-tab.container.js diff --git a/ui/app/pages/settings/security-tab/security-tab.container.test.js b/ui/pages/settings/security-tab/security-tab.container.test.js similarity index 100% rename from ui/app/pages/settings/security-tab/security-tab.container.test.js rename to ui/pages/settings/security-tab/security-tab.container.test.js diff --git a/ui/app/pages/settings/settings-tab/index.js b/ui/pages/settings/settings-tab/index.js similarity index 100% rename from ui/app/pages/settings/settings-tab/index.js rename to ui/pages/settings/settings-tab/index.js diff --git a/ui/app/pages/settings/settings-tab/index.scss b/ui/pages/settings/settings-tab/index.scss similarity index 100% rename from ui/app/pages/settings/settings-tab/index.scss rename to ui/pages/settings/settings-tab/index.scss diff --git a/ui/app/pages/settings/settings-tab/settings-tab.component.js b/ui/pages/settings/settings-tab/settings-tab.component.js similarity index 99% rename from ui/app/pages/settings/settings-tab/settings-tab.component.js rename to ui/pages/settings/settings-tab/settings-tab.component.js index 71aae33a6..d40b446c2 100644 --- a/ui/app/pages/settings/settings-tab/settings-tab.component.js +++ b/ui/pages/settings/settings-tab/settings-tab.component.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import availableCurrencies from '../../../helpers/constants/available-conversions.json'; import Dropdown from '../../../components/ui/dropdown'; import ToggleButton from '../../../components/ui/toggle-button'; -import locales from '../../../../../app/_locales/index.json'; +import locales from '../../../../app/_locales/index.json'; const sortedCurrencies = availableCurrencies.sort((a, b) => { return a.name.toLocaleLowerCase().localeCompare(b.name.toLocaleLowerCase()); diff --git a/ui/app/pages/settings/settings-tab/settings-tab.container.js b/ui/pages/settings/settings-tab/settings-tab.container.js similarity index 100% rename from ui/app/pages/settings/settings-tab/settings-tab.container.js rename to ui/pages/settings/settings-tab/settings-tab.container.js diff --git a/ui/app/pages/settings/settings-tab/settings-tab.container.test.js b/ui/pages/settings/settings-tab/settings-tab.container.test.js similarity index 100% rename from ui/app/pages/settings/settings-tab/settings-tab.container.test.js rename to ui/pages/settings/settings-tab/settings-tab.container.test.js diff --git a/ui/app/pages/settings/settings.component.js b/ui/pages/settings/settings.component.js similarity index 100% rename from ui/app/pages/settings/settings.component.js rename to ui/pages/settings/settings.component.js diff --git a/ui/app/pages/settings/settings.container.js b/ui/pages/settings/settings.container.js similarity index 92% rename from ui/app/pages/settings/settings.container.js rename to ui/pages/settings/settings.container.js index 1121c4755..bf428c4fc 100644 --- a/ui/app/pages/settings/settings.container.js +++ b/ui/pages/settings/settings.container.js @@ -2,13 +2,13 @@ import { compose } from 'redux'; import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { getAddressBookEntryName } from '../../selectors'; -import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; -import { getEnvironmentType } from '../../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../shared/constants/app'; +import { getEnvironmentType } from '../../../app/scripts/lib/util'; import { getMostRecentOverviewPage } from '../../ducks/history/history'; import { isValidHexAddress, isBurnAddress, -} from '../../../../shared/modules/hexstring-utils'; +} from '../../../shared/modules/hexstring-utils'; import { ABOUT_US_ROUTE, diff --git a/ui/app/pages/swaps/__snapshots__/index.test.js.snap b/ui/pages/swaps/__snapshots__/index.test.js.snap similarity index 100% rename from ui/app/pages/swaps/__snapshots__/index.test.js.snap rename to ui/pages/swaps/__snapshots__/index.test.js.snap diff --git a/ui/app/pages/swaps/actionable-message/__snapshots__/actionable-message.test.js.snap b/ui/pages/swaps/actionable-message/__snapshots__/actionable-message.test.js.snap similarity index 100% rename from ui/app/pages/swaps/actionable-message/__snapshots__/actionable-message.test.js.snap rename to ui/pages/swaps/actionable-message/__snapshots__/actionable-message.test.js.snap diff --git a/ui/app/pages/swaps/actionable-message/actionable-message.js b/ui/pages/swaps/actionable-message/actionable-message.js similarity index 100% rename from ui/app/pages/swaps/actionable-message/actionable-message.js rename to ui/pages/swaps/actionable-message/actionable-message.js diff --git a/ui/app/pages/swaps/actionable-message/actionable-message.stories.js b/ui/pages/swaps/actionable-message/actionable-message.stories.js similarity index 100% rename from ui/app/pages/swaps/actionable-message/actionable-message.stories.js rename to ui/pages/swaps/actionable-message/actionable-message.stories.js diff --git a/ui/app/pages/swaps/actionable-message/actionable-message.test.js b/ui/pages/swaps/actionable-message/actionable-message.test.js similarity index 89% rename from ui/app/pages/swaps/actionable-message/actionable-message.test.js rename to ui/pages/swaps/actionable-message/actionable-message.test.js index 6074f4576..aeae55104 100644 --- a/ui/app/pages/swaps/actionable-message/actionable-message.test.js +++ b/ui/pages/swaps/actionable-message/actionable-message.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; +import { renderWithProvider } from '../../../../test/jest'; import ActionableMessage from '.'; const createProps = (customProps = {}) => { diff --git a/ui/app/pages/swaps/actionable-message/index.js b/ui/pages/swaps/actionable-message/index.js similarity index 100% rename from ui/app/pages/swaps/actionable-message/index.js rename to ui/pages/swaps/actionable-message/index.js diff --git a/ui/app/pages/swaps/actionable-message/index.scss b/ui/pages/swaps/actionable-message/index.scss similarity index 90% rename from ui/app/pages/swaps/actionable-message/index.scss rename to ui/pages/swaps/actionable-message/index.scss index 50e871613..4838489d4 100644 --- a/ui/app/pages/swaps/actionable-message/index.scss +++ b/ui/pages/swaps/actionable-message/index.scss @@ -51,12 +51,18 @@ } &--danger { - background: $Red-100; - border: 1px solid $Red-500; + background: $Red-000; + border: 1px solid $Red-300; justify-content: flex-start; .actionable-message__message { - color: $Red-500; + color: $Black-100; + text-align: left; + } + + button { + background: $Red-500; + color: #fff; } } diff --git a/ui/pages/swaps/awaiting-signatures/__snapshots__/awaiting-signatures.test.js.snap b/ui/pages/swaps/awaiting-signatures/__snapshots__/awaiting-signatures.test.js.snap new file mode 100644 index 000000000..a7b8b3546 --- /dev/null +++ b/ui/pages/swaps/awaiting-signatures/__snapshots__/awaiting-signatures.test.js.snap @@ -0,0 +1,26 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`AwaitingSignatures renders the component with initial props for 1 confirmation 1`] = ` +<div + class="swaps-footer" +> + <div + class="swaps-footer__buttons" + > + <div + class="page-container__footer swaps-footer__custom-page-container-footer-class" + > + <footer> + <button + class="button btn-primary page-container__footer-button swaps-footer__custom-page-container-footer-button-class swaps-footer__custom-page-container-footer-button-class--single" + data-testid="page-container-footer-next" + role="button" + tabindex="0" + > + Cancel + </button> + </footer> + </div> + </div> +</div> +`; diff --git a/ui/pages/swaps/awaiting-signatures/__snapshots__/swap-step-icon.test.js.snap b/ui/pages/swaps/awaiting-signatures/__snapshots__/swap-step-icon.test.js.snap new file mode 100644 index 000000000..681947428 --- /dev/null +++ b/ui/pages/swaps/awaiting-signatures/__snapshots__/swap-step-icon.test.js.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SwapStepIcon renders the component 1`] = ` +<div> + <svg + fill="none" + height="14" + viewBox="0 0 14 14" + width="14" + xmlns="http://www.w3.org/2000/svg" + > + <circle + cx="7" + cy="7" + r="6.25" + stroke="#037DD6" + stroke-width="1.5" + /> + <path + d="M6.50983 5.192H5.27783L6.14183 4H7.71783V9.68H6.50983V5.192Z" + fill="#037DD6" + /> + </svg> +</div> +`; diff --git a/ui/pages/swaps/awaiting-signatures/awaiting-signatures.js b/ui/pages/swaps/awaiting-signatures/awaiting-signatures.js new file mode 100644 index 000000000..784c990fb --- /dev/null +++ b/ui/pages/swaps/awaiting-signatures/awaiting-signatures.js @@ -0,0 +1,147 @@ +import React, { useContext, useEffect } from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { useHistory } from 'react-router-dom'; + +import { I18nContext } from '../../../contexts/i18n'; +import { useNewMetricEvent } from '../../../hooks/useMetricEvent'; +import { + getFetchParams, + getApproveTxParams, + prepareToLeaveSwaps, +} from '../../../ducks/swaps/swaps'; +import { + isHardwareWallet, + getHardwareWalletType, +} from '../../../selectors/selectors'; +import { + DEFAULT_ROUTE, + BUILD_QUOTE_ROUTE, +} from '../../../helpers/constants/routes'; +import PulseLoader from '../../../components/ui/pulse-loader'; +import Typography from '../../../components/ui/typography'; +import Box from '../../../components/ui/box'; +import { + BLOCK_SIZES, + COLORS, + TYPOGRAPHY, + FONT_WEIGHT, + JUSTIFY_CONTENT, + DISPLAY, +} from '../../../helpers/constants/design-system'; +import SwapsFooter from '../swaps-footer'; +import SwapStepIcon from './swap-step-icon'; + +export default function AwaitingSignatures() { + const t = useContext(I18nContext); + const history = useHistory(); + const dispatch = useDispatch(); + const fetchParams = useSelector(getFetchParams); + const { destinationTokenInfo, sourceTokenInfo } = fetchParams?.metaData || {}; + const approveTxParams = useSelector(getApproveTxParams); + const hardwareWalletUsed = useSelector(isHardwareWallet); + const hardwareWalletType = useSelector(getHardwareWalletType); + const needsTwoConfirmations = Boolean(approveTxParams); + + const awaitingSignaturesEvent = useNewMetricEvent({ + event: 'Awaiting Signature(s) on a HW wallet', + sensitiveProperties: { + needs_two_confirmations: needsTwoConfirmations, + token_from: sourceTokenInfo?.symbol, + token_from_amount: fetchParams?.value, + token_to: destinationTokenInfo?.symbol, + request_type: fetchParams?.balanceError ? 'Quote' : 'Order', + slippage: fetchParams?.slippage, + custom_slippage: fetchParams?.slippage === 2, + is_hardware_wallet: hardwareWalletUsed, + hardware_wallet_type: hardwareWalletType, + }, + category: 'swaps', + }); + + useEffect(() => { + awaitingSignaturesEvent(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const headerText = needsTwoConfirmations + ? t('swapTwoTransactions') + : t('swapConfirmWithHwWallet'); + + return ( + <div className="awaiting-signatures"> + <Box + paddingLeft={8} + paddingRight={8} + height={BLOCK_SIZES.FULL} + justifyContent={JUSTIFY_CONTENT.CENTER} + display={DISPLAY.FLEX} + className="awaiting-signatures__content" + > + <Box marginTop={3} marginBottom={4}> + <PulseLoader /> + </Box> + <Typography color={COLORS.BLACK} variant={TYPOGRAPHY.H3}> + {headerText} + </Typography> + {needsTwoConfirmations && ( + <> + <Typography + variant={TYPOGRAPHY.Paragraph} + boxProps={{ marginTop: 2 }} + fontWeight={FONT_WEIGHT.BOLD} + > + {t('swapToConfirmWithHwWallet')} + </Typography> + <ul className="awaiting-signatures__steps"> + <li> + <SwapStepIcon stepNumber={1} /> + {t('swapAllowSwappingOf', [ + <Typography + tag="span" + fontWeight={FONT_WEIGHT.BOLD} + key="allowToken" + > + {destinationTokenInfo?.symbol} + </Typography>, + ])} + </li> + <li> + <SwapStepIcon stepNumber={2} /> + {t('swapFromTo', [ + <Typography + tag="span" + fontWeight={FONT_WEIGHT.BOLD} + key="tokenFrom" + > + {sourceTokenInfo?.symbol} + </Typography>, + <Typography + tag="span" + fontWeight={FONT_WEIGHT.BOLD} + key="tokenTo" + > + {destinationTokenInfo?.symbol} + </Typography>, + ])} + </li> + </ul> + <Typography variant={TYPOGRAPHY.Paragraph}> + {t('swapGasFeesSplit')} + </Typography> + </> + )} + </Box> + <SwapsFooter + onSubmit={async () => { + await dispatch(prepareToLeaveSwaps()); + // Go to the default route and then to the build quote route in order to clean up + // the `inputValue` local state in `pages/swaps/index.js` + history.push(DEFAULT_ROUTE); + history.push(BUILD_QUOTE_ROUTE); + }} + submitText={t('cancel')} + hideCancel + /> + </div> + ); +} diff --git a/ui/pages/swaps/awaiting-signatures/awaiting-signatures.test.js b/ui/pages/swaps/awaiting-signatures/awaiting-signatures.test.js new file mode 100644 index 000000000..c8e466ec2 --- /dev/null +++ b/ui/pages/swaps/awaiting-signatures/awaiting-signatures.test.js @@ -0,0 +1,17 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; + +import { + renderWithProvider, + createSwapsMockStore, +} from '../../../../test/jest'; +import AwaitingSignatures from '.'; + +describe('AwaitingSignatures', () => { + it('renders the component with initial props for 1 confirmation', () => { + const store = configureMockStore()(createSwapsMockStore()); + const { getByText } = renderWithProvider(<AwaitingSignatures />, store); + expect(getByText('Confirm with your hardware wallet')).toBeInTheDocument(); + expect(document.querySelector('.swaps-footer')).toMatchSnapshot(); + }); +}); diff --git a/ui/pages/swaps/awaiting-signatures/index.js b/ui/pages/swaps/awaiting-signatures/index.js new file mode 100644 index 000000000..3950ca6bf --- /dev/null +++ b/ui/pages/swaps/awaiting-signatures/index.js @@ -0,0 +1 @@ +export { default } from './awaiting-signatures'; diff --git a/ui/pages/swaps/awaiting-signatures/index.scss b/ui/pages/swaps/awaiting-signatures/index.scss new file mode 100644 index 000000000..9c847236c --- /dev/null +++ b/ui/pages/swaps/awaiting-signatures/index.scss @@ -0,0 +1,34 @@ +.awaiting-signatures { + display: flex; + flex-flow: column; + align-items: center; + flex: 1; + width: 100%; + + &__content { + flex-flow: column; + } + + div { + text-align: center; + display: flex; + justify-content: center; + } + + &__steps { + display: flex; + flex-direction: column; + align-items: flex-start; + margin: 16px auto 12px auto; + + li { + margin-bottom: 4px; + display: flex; + align-items: center; + + svg { + margin-right: 4px; + } + } + } +} diff --git a/ui/pages/swaps/awaiting-signatures/swap-step-icon.js b/ui/pages/swaps/awaiting-signatures/swap-step-icon.js new file mode 100644 index 000000000..3e5d50665 --- /dev/null +++ b/ui/pages/swaps/awaiting-signatures/swap-step-icon.js @@ -0,0 +1,40 @@ +import React from 'react'; + +export default function SwapStepIcon({ stepNumber = 1 }) { + switch (stepNumber) { + case 1: + return ( + <svg + width="14" + height="14" + viewBox="0 0 14 14" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <circle cx="7" cy="7" r="6.25" stroke="#037DD6" strokeWidth="1.5" /> + <path + d="M6.50983 5.192H5.27783L6.14183 4H7.71783V9.68H6.50983V5.192Z" + fill="#037DD6" + /> + </svg> + ); + case 2: + return ( + <svg + width="14" + height="14" + viewBox="0 0 14 14" + fill="none" + xmlns="http://www.w3.org/2000/svg" + > + <circle cx="7" cy="7" r="6.25" stroke="#037DD6" strokeWidth="1.5" /> + <path + d="M8.92 9.776H5V9.368C5 9.048 5.056 8.77067 5.168 8.536C5.28 8.296 5.42133 8.08533 5.592 7.904C5.768 7.71733 5.96267 7.54933 6.176 7.4C6.39467 7.25067 6.608 7.10133 6.816 6.952C6.928 6.872 7.03467 6.78933 7.136 6.704C7.24267 6.61867 7.33333 6.53067 7.408 6.44C7.488 6.34933 7.552 6.256 7.6 6.16C7.648 6.064 7.672 5.96533 7.672 5.864C7.672 5.67733 7.616 5.52 7.504 5.392C7.39733 5.25867 7.22933 5.192 7 5.192C6.88267 5.192 6.776 5.21333 6.68 5.256C6.584 5.29333 6.50133 5.344 6.432 5.408C6.368 5.472 6.31733 5.54667 6.28 5.632C6.248 5.71733 6.232 5.808 6.232 5.904H5.024C5.024 5.62667 5.07467 5.37067 5.176 5.136C5.27733 4.90133 5.41867 4.70133 5.6 4.536C5.78133 4.36533 5.99467 4.23467 6.24 4.144C6.48533 4.048 6.752 4 7.04 4C7.28 4 7.50933 4.03733 7.728 4.112C7.952 4.18667 8.14933 4.29867 8.32 4.448C8.49067 4.59733 8.62667 4.784 8.728 5.008C8.82933 5.22667 8.88 5.48267 8.88 5.776C8.88 6.032 8.85067 6.25867 8.792 6.456C8.73333 6.648 8.65067 6.824 8.544 6.984C8.44267 7.13867 8.32 7.28 8.176 7.408C8.032 7.536 7.87733 7.66133 7.712 7.784C7.64267 7.832 7.55733 7.888 7.456 7.952C7.36 8.016 7.26133 8.08267 7.16 8.152C7.064 8.22133 6.97333 8.29333 6.888 8.368C6.80267 8.44267 6.74133 8.51467 6.704 8.584H8.92V9.776Z" + fill="#037DD6" + /> + </svg> + ); + default: + return undefined; // Don't return any SVG if a step number is not supported. + } +} diff --git a/ui/pages/swaps/awaiting-signatures/swap-step-icon.test.js b/ui/pages/swaps/awaiting-signatures/swap-step-icon.test.js new file mode 100644 index 000000000..47c92d7aa --- /dev/null +++ b/ui/pages/swaps/awaiting-signatures/swap-step-icon.test.js @@ -0,0 +1,11 @@ +import React from 'react'; + +import { renderWithProvider } from '../../../../test/jest'; +import SwapStepIcon from './swap-step-icon'; + +describe('SwapStepIcon', () => { + it('renders the component', () => { + const { container } = renderWithProvider(<SwapStepIcon />); + expect(container).toMatchSnapshot(); + }); +}); diff --git a/ui/app/pages/swaps/awaiting-swap/__snapshots__/awaiting-swap.test.js.snap b/ui/pages/swaps/awaiting-swap/__snapshots__/awaiting-swap.test.js.snap similarity index 100% rename from ui/app/pages/swaps/awaiting-swap/__snapshots__/awaiting-swap.test.js.snap rename to ui/pages/swaps/awaiting-swap/__snapshots__/awaiting-swap.test.js.snap diff --git a/ui/app/pages/swaps/awaiting-swap/__snapshots__/quotes-timeout-icon.test.js.snap b/ui/pages/swaps/awaiting-swap/__snapshots__/quotes-timeout-icon.test.js.snap similarity index 100% rename from ui/app/pages/swaps/awaiting-swap/__snapshots__/quotes-timeout-icon.test.js.snap rename to ui/pages/swaps/awaiting-swap/__snapshots__/quotes-timeout-icon.test.js.snap diff --git a/ui/app/pages/swaps/awaiting-swap/__snapshots__/swap-failure-icon.test.js.snap b/ui/pages/swaps/awaiting-swap/__snapshots__/swap-failure-icon.test.js.snap similarity index 100% rename from ui/app/pages/swaps/awaiting-swap/__snapshots__/swap-failure-icon.test.js.snap rename to ui/pages/swaps/awaiting-swap/__snapshots__/swap-failure-icon.test.js.snap diff --git a/ui/app/pages/swaps/awaiting-swap/__snapshots__/swap-success-icon.test.js.snap b/ui/pages/swaps/awaiting-swap/__snapshots__/swap-success-icon.test.js.snap similarity index 100% rename from ui/app/pages/swaps/awaiting-swap/__snapshots__/swap-success-icon.test.js.snap rename to ui/pages/swaps/awaiting-swap/__snapshots__/swap-success-icon.test.js.snap diff --git a/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js b/ui/pages/swaps/awaiting-swap/awaiting-swap.js similarity index 80% rename from ui/app/pages/swaps/awaiting-swap/awaiting-swap.js rename to ui/pages/swaps/awaiting-swap/awaiting-swap.js index af21ce29b..75f7a07b5 100644 --- a/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js +++ b/ui/pages/swaps/awaiting-swap/awaiting-swap.js @@ -3,7 +3,7 @@ import React, { useContext, useRef, useState } from 'react'; import { useDispatch, useSelector } from 'react-redux'; import PropTypes from 'prop-types'; import { useHistory } from 'react-router-dom'; -import { createCustomExplorerLink } from '@metamask/etherscan-link'; +import { getBlockExplorerLink } from '@metamask/etherscan-link'; import { I18nContext } from '../../../contexts/i18n'; import { useNewMetricEvent } from '../../../hooks/useMetricEvent'; import { MetaMetricsContext } from '../../../contexts/metametrics.new'; @@ -13,6 +13,8 @@ import { getCurrentCurrency, getRpcPrefsForCurrentProvider, getUSDConversionRate, + isHardwareWallet, + getHardwareWalletType, } from '../../../selectors'; import { @@ -26,23 +28,23 @@ import { prepareToLeaveSwaps, } from '../../../ducks/swaps/swaps'; import Mascot from '../../../components/ui/mascot'; +import Box from '../../../components/ui/box'; import { QUOTES_EXPIRED_ERROR, SWAP_FAILED_ERROR, ERROR_FETCHING_QUOTES, QUOTES_NOT_AVAILABLE_ERROR, + CONTRACT_DATA_DISABLED_ERROR, OFFLINE_FOR_MAINTENANCE, SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP, -} from '../../../../../shared/constants/swaps'; -import { CHAIN_ID_TO_TYPE_MAP as VALID_INFURA_CHAIN_IDS } from '../../../../../shared/constants/network'; -import { isSwapsDefaultTokenSymbol } from '../../../../../shared/modules/swaps.utils'; +} from '../../../../shared/constants/swaps'; +import { isSwapsDefaultTokenSymbol } from '../../../../shared/modules/swaps.utils'; import PulseLoader from '../../../components/ui/pulse-loader'; import { ASSET_ROUTE, DEFAULT_ROUTE } from '../../../helpers/constants/routes'; import { getRenderableNetworkFeesForQuote } from '../swaps.util'; import SwapsFooter from '../swaps-footer'; -import { getBlockExplorerUrlForTx } from '../../../../../shared/modules/transaction.utils'; import SwapFailureIcon from './swap-failure-icon'; import SwapSuccessIcon from './swap-success-icon'; @@ -95,31 +97,38 @@ export default function AwaitingSwap({ feeinUnformattedFiat = renderableNetworkFees.rawNetworkFees; } + const hardwareWalletUsed = useSelector(isHardwareWallet); + const hardwareWalletType = useSelector(getHardwareWalletType); + const sensitiveProperties = { + token_from: sourceTokenInfo?.symbol, + token_from_amount: fetchParams?.value, + token_to: destinationTokenInfo?.symbol, + request_type: fetchParams?.balanceError ? 'Quote' : 'Order', + slippage: fetchParams?.slippage, + custom_slippage: fetchParams?.slippage === 2, + gas_fees: feeinUnformattedFiat, + is_hardware_wallet: hardwareWalletUsed, + hardware_wallet_type: hardwareWalletType, + }; const quotesExpiredEvent = useNewMetricEvent({ event: 'Quotes Timed Out', - sensitiveProperties: { - token_from: sourceTokenInfo?.symbol, - token_from_amount: fetchParams?.value, - token_to: destinationTokenInfo?.symbol, - request_type: fetchParams?.balanceError ? 'Quote' : 'Order', - slippage: fetchParams?.slippage, - custom_slippage: fetchParams?.slippage === 2, - gas_fees: feeinUnformattedFiat, - }, + sensitiveProperties, + category: 'swaps', + }); + const makeAnotherSwapEvent = useNewMetricEvent({ + event: 'Make Another Swap', + sensitiveProperties, category: 'swaps', }); - let blockExplorerUrl; - if (txHash && rpcPrefs.blockExplorerUrl) { - blockExplorerUrl = getBlockExplorerUrlForTx({ hash: txHash }, rpcPrefs); - } else if (txHash && SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId]) { - blockExplorerUrl = createCustomExplorerLink( - txHash, - SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId], - ); - } else if (txHash && VALID_INFURA_CHAIN_IDS[chainId]) { - blockExplorerUrl = getBlockExplorerUrlForTx({ chainId, hash: txHash }); - } + const baseNetworkUrl = + rpcPrefs.blockExplorerUrl ?? + SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ?? + null; + const blockExplorerUrl = getBlockExplorerLink( + { hash: txHash, chainId }, + { blockExplorerUrl: baseNetworkUrl }, + ); const isCustomBlockExplorerUrl = SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] || @@ -178,6 +187,11 @@ export default function AwaitingSwap({ descriptionText = t('swapQuotesNotAvailableErrorDescription'); submitText = t('tryAgain'); statusImage = <SwapFailureIcon />; + } else if (errorKey === CONTRACT_DATA_DISABLED_ERROR) { + headerText = t('swapContractDataDisabledErrorTitle'); + descriptionText = t('swapContractDataDisabledErrorDescription'); + submitText = t('tryAgain'); + statusImage = <SwapFailureIcon />; } else if (!errorKey && !swapComplete) { headerText = t('swapProcessing'); statusImage = <PulseLoader />; @@ -200,7 +214,7 @@ export default function AwaitingSwap({ } else if (!errorKey && swapComplete) { headerText = t('swapTransactionComplete'); statusImage = <SwapSuccessIcon />; - submitText = t('swapViewToken', [destinationTokenInfo.symbol]); + submitText = t('close'); descriptionText = t('swapTokenAvailable', [ <span key="swapTokenAvailable-2" @@ -218,6 +232,22 @@ export default function AwaitingSwap({ ); } + const MakeAnotherSwap = () => { + return ( + <Box marginBottom={3}> + <a + href="#" + onClick={() => { + makeAnotherSwapEvent(); + dispatch(navigateBackToBuildQuote(history)); + }} + > + {t('makeAnotherSwap')} + </a> + </Box> + ); + }; + return ( <div className="awaiting-swap"> <div className="awaiting-swap__content"> @@ -233,6 +263,7 @@ export default function AwaitingSwap({ <div className="awaiting-swap__main-descrption">{descriptionText}</div> {content} </div> + {!errorKey && swapComplete && <MakeAnotherSwap />} <SwapsFooter onSubmit={async () => { if (errorKey === OFFLINE_FOR_MAINTENANCE) { @@ -251,7 +282,8 @@ export default function AwaitingSwap({ } else if (errorKey) { await dispatch(navigateBackToBuildQuote(history)); } else if ( - isSwapsDefaultTokenSymbol(destinationTokenInfo?.symbol, chainId) + isSwapsDefaultTokenSymbol(destinationTokenInfo?.symbol, chainId) || + swapComplete ) { history.push(DEFAULT_ROUTE); } else { @@ -277,6 +309,7 @@ AwaitingSwap.propTypes = { ERROR_FETCHING_QUOTES, QUOTES_NOT_AVAILABLE_ERROR, OFFLINE_FOR_MAINTENANCE, + CONTRACT_DATA_DISABLED_ERROR, ]), submittingSwap: PropTypes.bool, inputValue: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), diff --git a/ui/app/pages/swaps/awaiting-swap/awaiting-swap.test.js b/ui/pages/swaps/awaiting-swap/awaiting-swap.test.js similarity index 90% rename from ui/app/pages/swaps/awaiting-swap/awaiting-swap.test.js rename to ui/pages/swaps/awaiting-swap/awaiting-swap.test.js index 396bcfb51..bdd91c871 100644 --- a/ui/app/pages/swaps/awaiting-swap/awaiting-swap.test.js +++ b/ui/pages/swaps/awaiting-swap/awaiting-swap.test.js @@ -4,7 +4,7 @@ import configureMockStore from 'redux-mock-store'; import { renderWithProvider, createSwapsMockStore, -} from '../../../../../test/jest'; +} from '../../../../test/jest'; import AwaitingSwap from '.'; const createProps = (customProps = {}) => { @@ -27,7 +27,7 @@ describe('AwaitingSwap', () => { store, ); expect(getByText('Processing')).toBeInTheDocument(); - expect(getByText('View on Etherscan')).toBeInTheDocument(); + expect(getByText('ETH')).toBeInTheDocument(); expect(getByText('View in activity')).toBeInTheDocument(); expect( document.querySelector('.awaiting-swap__main-descrption'), diff --git a/ui/app/pages/swaps/awaiting-swap/index.js b/ui/pages/swaps/awaiting-swap/index.js similarity index 100% rename from ui/app/pages/swaps/awaiting-swap/index.js rename to ui/pages/swaps/awaiting-swap/index.js diff --git a/ui/app/pages/swaps/awaiting-swap/index.scss b/ui/pages/swaps/awaiting-swap/index.scss similarity index 97% rename from ui/app/pages/swaps/awaiting-swap/index.scss rename to ui/pages/swaps/awaiting-swap/index.scss index 0ad246934..f2792eb5a 100644 --- a/ui/app/pages/swaps/awaiting-swap/index.scss +++ b/ui/pages/swaps/awaiting-swap/index.scss @@ -20,6 +20,10 @@ justify-content: center; } + a { + color: $Blue-500; + } + &__status-image { margin-top: 12px; margin-bottom: 16px; diff --git a/ui/app/pages/swaps/awaiting-swap/quotes-timeout-icon.js b/ui/pages/swaps/awaiting-swap/quotes-timeout-icon.js similarity index 100% rename from ui/app/pages/swaps/awaiting-swap/quotes-timeout-icon.js rename to ui/pages/swaps/awaiting-swap/quotes-timeout-icon.js diff --git a/ui/app/pages/swaps/awaiting-swap/quotes-timeout-icon.test.js b/ui/pages/swaps/awaiting-swap/quotes-timeout-icon.test.js similarity index 81% rename from ui/app/pages/swaps/awaiting-swap/quotes-timeout-icon.test.js rename to ui/pages/swaps/awaiting-swap/quotes-timeout-icon.test.js index 6afc922ef..12f2adf45 100644 --- a/ui/app/pages/swaps/awaiting-swap/quotes-timeout-icon.test.js +++ b/ui/pages/swaps/awaiting-swap/quotes-timeout-icon.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; +import { renderWithProvider } from '../../../../test/jest'; import QuotesTimeoutIcon from './quotes-timeout-icon'; describe('QuotesTimeoutIcon', () => { diff --git a/ui/app/pages/swaps/awaiting-swap/swap-failure-icon.js b/ui/pages/swaps/awaiting-swap/swap-failure-icon.js similarity index 100% rename from ui/app/pages/swaps/awaiting-swap/swap-failure-icon.js rename to ui/pages/swaps/awaiting-swap/swap-failure-icon.js diff --git a/ui/app/pages/swaps/awaiting-swap/swap-failure-icon.test.js b/ui/pages/swaps/awaiting-swap/swap-failure-icon.test.js similarity index 81% rename from ui/app/pages/swaps/awaiting-swap/swap-failure-icon.test.js rename to ui/pages/swaps/awaiting-swap/swap-failure-icon.test.js index be75020f8..02af2db06 100644 --- a/ui/app/pages/swaps/awaiting-swap/swap-failure-icon.test.js +++ b/ui/pages/swaps/awaiting-swap/swap-failure-icon.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; +import { renderWithProvider } from '../../../../test/jest'; import SwapFailureIcon from './swap-failure-icon'; describe('SwapFailureIcon', () => { diff --git a/ui/app/pages/swaps/awaiting-swap/swap-success-icon.js b/ui/pages/swaps/awaiting-swap/swap-success-icon.js similarity index 100% rename from ui/app/pages/swaps/awaiting-swap/swap-success-icon.js rename to ui/pages/swaps/awaiting-swap/swap-success-icon.js diff --git a/ui/app/pages/swaps/awaiting-swap/swap-success-icon.test.js b/ui/pages/swaps/awaiting-swap/swap-success-icon.test.js similarity index 81% rename from ui/app/pages/swaps/awaiting-swap/swap-success-icon.test.js rename to ui/pages/swaps/awaiting-swap/swap-success-icon.test.js index 39d9eed12..4e735f158 100644 --- a/ui/app/pages/swaps/awaiting-swap/swap-success-icon.test.js +++ b/ui/pages/swaps/awaiting-swap/swap-success-icon.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; +import { renderWithProvider } from '../../../../test/jest'; import SwapSuccessIcon from './swap-success-icon'; describe('SwapSuccessIcon', () => { diff --git a/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/__snapshots__/view-on-ether-scan-link.test.js.snap b/ui/pages/swaps/awaiting-swap/view-on-ether-scan-link/__snapshots__/view-on-ether-scan-link.test.js.snap similarity index 100% rename from ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/__snapshots__/view-on-ether-scan-link.test.js.snap rename to ui/pages/swaps/awaiting-swap/view-on-ether-scan-link/__snapshots__/view-on-ether-scan-link.test.js.snap diff --git a/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/index.js b/ui/pages/swaps/awaiting-swap/view-on-ether-scan-link/index.js similarity index 100% rename from ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/index.js rename to ui/pages/swaps/awaiting-swap/view-on-ether-scan-link/index.js diff --git a/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js b/ui/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js similarity index 60% rename from ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js rename to ui/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js index 15fb7d081..ee11b2981 100644 --- a/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js +++ b/ui/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.js @@ -2,6 +2,7 @@ import React, { useContext } from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { I18nContext } from '../../../../contexts/i18n'; +import { useNewMetricEvent } from '../../../../hooks/useMetricEvent'; export default function ViewOnEtherScanLink({ txHash, @@ -9,13 +10,29 @@ export default function ViewOnEtherScanLink({ isCustomBlockExplorerUrl, }) { const t = useContext(I18nContext); + + const blockExplorerLinkClickedEvent = useNewMetricEvent({ + category: 'Swaps', + event: 'Clicked Block Explorer Link', + properties: { + link_type: 'Transaction Block Explorer', + action: 'Swap Transaction', + block_explorer_domain: blockExplorerUrl + ? new URL(blockExplorerUrl)?.hostname + : '', + }, + }); + return ( <div className={classnames('awaiting-swap__view-on-etherscan', { 'awaiting-swap__view-on-etherscan--visible': txHash, 'awaiting-swap__view-on-etherscan--invisible': !txHash, })} - onClick={() => global.platform.openTab({ url: blockExplorerUrl })} + onClick={() => { + blockExplorerLinkClickedEvent(); + global.platform.openTab({ url: blockExplorerUrl }); + }} > {isCustomBlockExplorerUrl ? t('viewOnCustomBlockExplorer', [new URL(blockExplorerUrl).hostname]) diff --git a/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.test.js b/ui/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.test.js similarity index 94% rename from ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.test.js rename to ui/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.test.js index 0eb8a4dc7..91e32b82c 100644 --- a/ui/app/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.test.js +++ b/ui/pages/swaps/awaiting-swap/view-on-ether-scan-link/view-on-ether-scan-link.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../../test/jest'; +import { renderWithProvider } from '../../../../../test/jest'; import ViewOnEtherScanLink from '.'; const createProps = (customProps = {}) => { diff --git a/ui/app/pages/swaps/build-quote/__snapshots__/build-quote.test.js.snap b/ui/pages/swaps/build-quote/__snapshots__/build-quote.test.js.snap similarity index 100% rename from ui/app/pages/swaps/build-quote/__snapshots__/build-quote.test.js.snap rename to ui/pages/swaps/build-quote/__snapshots__/build-quote.test.js.snap diff --git a/ui/app/pages/swaps/build-quote/build-quote.js b/ui/pages/swaps/build-quote/build-quote.js similarity index 87% rename from ui/app/pages/swaps/build-quote/build-quote.js rename to ui/pages/swaps/build-quote/build-quote.js index d93ab6a9b..a3ee1b047 100644 --- a/ui/app/pages/swaps/build-quote/build-quote.js +++ b/ui/pages/swaps/build-quote/build-quote.js @@ -4,11 +4,9 @@ import { useDispatch, useSelector } from 'react-redux'; import classnames from 'classnames'; import { uniqBy, isEqual } from 'lodash'; import { useHistory } from 'react-router-dom'; -import { - createCustomTokenTrackerLink, - createTokenTrackerLinkForChain, -} from '@metamask/etherscan-link'; +import { getTokenTrackerLink } from '@metamask/etherscan-link'; import { MetaMetricsContext } from '../../../contexts/metametrics.new'; +import { useNewMetricEvent } from '../../../hooks/useMetricEvent'; import { useTokensToSearch, getRenderableTokenData, @@ -53,8 +51,8 @@ import { useEthFiatAmount } from '../../../hooks/useEthFiatAmount'; import { isSwapsDefaultTokenAddress, isSwapsDefaultTokenSymbol, -} from '../../../../../shared/modules/swaps.utils'; -import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../../shared/constants/swaps'; +} from '../../../../shared/modules/swaps.utils'; +import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/swaps'; import { resetSwapsPostFetchState, removeToken } from '../../../store/actions'; import { fetchTokenPrice, fetchTokenBalance } from '../swaps.util'; @@ -223,29 +221,34 @@ export default function BuildQuote({ ); }; - let blockExplorerTokenLink; - let blockExplorerLabel; - if (rpcPrefs.blockExplorerUrl) { - blockExplorerTokenLink = createCustomTokenTrackerLink( - selectedToToken.address, - rpcPrefs.blockExplorerUrl, - ); - blockExplorerLabel = new URL(rpcPrefs.blockExplorerUrl).hostname; - } else if (SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId]) { - blockExplorerTokenLink = createCustomTokenTrackerLink( - selectedToToken.address, - SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId], - ); - blockExplorerLabel = new URL( - SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId], - ).hostname; - } else { - blockExplorerTokenLink = createTokenTrackerLinkForChain( - selectedToToken.address, - chainId, - ); - blockExplorerLabel = t('etherscan'); - } + const blockExplorerTokenLink = getTokenTrackerLink( + selectedToToken.address, + chainId, + null, // no networkId + null, // no holderAddress + { + blockExplorerUrl: + rpcPrefs.blockExplorerUrl ?? + SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ?? + null, + }, + ); + + const blockExplorerLabel = rpcPrefs.blockExplorerUrl + ? new URL(blockExplorerTokenLink).hostname + : t('etherscan'); + + const blockExplorerLinkClickedEvent = useNewMetricEvent({ + category: 'Swaps', + event: 'Clicked Block Explorer Link', + properties: { + link_type: 'Token Tracker', + action: 'Swaps Confirmation', + block_explorer_domain: blockExplorerTokenLink + ? new URL(blockExplorerTokenLink)?.hostname + : '', + }, + }); const { destinationTokenAddedForSwap } = fetchParams || {}; const { address: toAddress } = toToken || {}; @@ -330,6 +333,38 @@ export default function BuildQuote({ dispatch(resetSwapsPostFetchState()); }, [dispatch]); + const BlockExplorerLink = () => { + return ( + <a + className="build-quote__token-etherscan-link build-quote__underline" + key="build-quote-etherscan-link" + onClick={() => { + blockExplorerLinkClickedEvent(); + global.platform.openTab({ + url: blockExplorerTokenLink, + }); + }} + target="_blank" + rel="noopener noreferrer" + > + {blockExplorerLabel} + </a> + ); + }; + + let tokenVerificationDescription = ''; + if (blockExplorerTokenLink) { + if (occurances === 1) { + tokenVerificationDescription = t('verifyThisTokenOn', [ + <BlockExplorerLink key="block-explorer-link" />, + ]); + } else if (occurances === 0) { + tokenVerificationDescription = t('verifyThisUnconfirmedTokenOn', [ + <BlockExplorerLink key="block-explorer-link" />, + ]); + } + } + return ( <div className="build-quote"> <div className="build-quote__content"> @@ -401,7 +436,7 @@ export default function BuildQuote({ }} > <img - src="/images/icons/swap2.svg" + src="./images/icons/swap2.svg" alt={t('swapSwapSwitch')} width="12" height="16" @@ -431,32 +466,21 @@ export default function BuildQuote({ listContainerClassName="build-quote__open-to-dropdown" hideRightLabels defaultToAll + shouldSearchForImports /> </div> {toTokenIsNotDefault && (occurances < 2 ? ( <ActionableMessage + type={occurances === 1 ? 'warning' : 'danger'} message={ <div className="build-quote__token-verification-warning-message"> <div className="build-quote__bold"> {occurances === 1 ? t('swapTokenVerificationOnlyOneSource') - : t('swapTokenVerificationNoSource')} - </div> - <div> - {blockExplorerTokenLink && - t('verifyThisTokenOn', [ - <a - className="build-quote__token-etherscan-link build-quote__underline" - key="build-quote-etherscan-link" - href={blockExplorerTokenLink} - target="_blank" - rel="noopener noreferrer" - > - {blockExplorerLabel} - </a>, - ])} + : t('swapTokenVerificationAddedManually')} </div> + <div>{tokenVerificationDescription}</div> </div> } primaryAction={ @@ -467,7 +491,6 @@ export default function BuildQuote({ onClick: () => setVerificationClicked(true), } } - type="warning" withRightButton infoTooltipText={ blockExplorerTokenLink && @@ -488,7 +511,12 @@ export default function BuildQuote({ <a className="build-quote__token-etherscan-link" key="build-quote-etherscan-link" - href={blockExplorerTokenLink} + onClick={() => { + blockExplorerLinkClickedEvent(); + global.platform.openTab({ + url: blockExplorerTokenLink, + }); + }} target="_blank" rel="noopener noreferrer" > @@ -533,7 +561,7 @@ export default function BuildQuote({ !isFeatureFlagLoaded || !Number(inputValue) || !selectedToToken?.address || - Number(maxSlippage) === 0 || + Number(maxSlippage) < 0 || Number(maxSlippage) > MAX_ALLOWED_SLIPPAGE || (toTokenIsNotDefault && occurances < 2 && !verificationClicked) } diff --git a/ui/app/pages/swaps/build-quote/build-quote.stories.js b/ui/pages/swaps/build-quote/build-quote.stories.js similarity index 100% rename from ui/app/pages/swaps/build-quote/build-quote.stories.js rename to ui/pages/swaps/build-quote/build-quote.stories.js diff --git a/ui/app/pages/swaps/build-quote/build-quote.test.js b/ui/pages/swaps/build-quote/build-quote.test.js similarity index 97% rename from ui/app/pages/swaps/build-quote/build-quote.test.js rename to ui/pages/swaps/build-quote/build-quote.test.js index d27990687..960489281 100644 --- a/ui/app/pages/swaps/build-quote/build-quote.test.js +++ b/ui/pages/swaps/build-quote/build-quote.test.js @@ -6,7 +6,7 @@ import { renderWithProvider, createSwapsMockStore, setBackgroundConnection, -} from '../../../../../test/jest'; +} from '../../../../test/jest'; import BuildQuote from '.'; const middleware = [thunk]; diff --git a/ui/app/pages/swaps/build-quote/index.js b/ui/pages/swaps/build-quote/index.js similarity index 100% rename from ui/app/pages/swaps/build-quote/index.js rename to ui/pages/swaps/build-quote/index.js diff --git a/ui/app/pages/swaps/build-quote/index.scss b/ui/pages/swaps/build-quote/index.scss similarity index 91% rename from ui/app/pages/swaps/build-quote/index.scss rename to ui/pages/swaps/build-quote/index.scss index 325e795d6..1ebf6cab6 100644 --- a/ui/app/pages/swaps/build-quote/index.scss +++ b/ui/pages/swaps/build-quote/index.scss @@ -109,6 +109,22 @@ width: 100%; } + .dropdown-input-pair { + .searchable-item-list { + &__item--add-token { + display: none; + } + } + + &__to { + .searchable-item-list { + &__item--add-token { + display: flex; + } + } + } + } + &__open-to-dropdown { max-height: 194px; diff --git a/ui/app/pages/swaps/countdown-timer/countdown-timer.js b/ui/pages/swaps/countdown-timer/countdown-timer.js similarity index 100% rename from ui/app/pages/swaps/countdown-timer/countdown-timer.js rename to ui/pages/swaps/countdown-timer/countdown-timer.js diff --git a/ui/app/pages/swaps/countdown-timer/countdown-timer.stories.js b/ui/pages/swaps/countdown-timer/countdown-timer.stories.js similarity index 100% rename from ui/app/pages/swaps/countdown-timer/countdown-timer.stories.js rename to ui/pages/swaps/countdown-timer/countdown-timer.stories.js diff --git a/ui/app/pages/swaps/countdown-timer/countdown-timer.test.js b/ui/pages/swaps/countdown-timer/countdown-timer.test.js similarity index 95% rename from ui/app/pages/swaps/countdown-timer/countdown-timer.test.js rename to ui/pages/swaps/countdown-timer/countdown-timer.test.js index ad6697f3a..49f37dcd6 100644 --- a/ui/app/pages/swaps/countdown-timer/countdown-timer.test.js +++ b/ui/pages/swaps/countdown-timer/countdown-timer.test.js @@ -4,7 +4,7 @@ import configureMockStore from 'redux-mock-store'; import { renderWithProvider, createSwapsMockStore, -} from '../../../../../test/jest'; +} from '../../../../test/jest'; import CountdownTimer from '.'; const createProps = (customProps = {}) => { diff --git a/ui/app/pages/swaps/countdown-timer/index.js b/ui/pages/swaps/countdown-timer/index.js similarity index 100% rename from ui/app/pages/swaps/countdown-timer/index.js rename to ui/pages/swaps/countdown-timer/index.js diff --git a/ui/app/pages/swaps/countdown-timer/index.scss b/ui/pages/swaps/countdown-timer/index.scss similarity index 100% rename from ui/app/pages/swaps/countdown-timer/index.scss rename to ui/pages/swaps/countdown-timer/index.scss diff --git a/ui/app/pages/swaps/dropdown-input-pair/__snapshots__/dropdown-input-pair.test.js.snap b/ui/pages/swaps/dropdown-input-pair/__snapshots__/dropdown-input-pair.test.js.snap similarity index 100% rename from ui/app/pages/swaps/dropdown-input-pair/__snapshots__/dropdown-input-pair.test.js.snap rename to ui/pages/swaps/dropdown-input-pair/__snapshots__/dropdown-input-pair.test.js.snap diff --git a/ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.js b/ui/pages/swaps/dropdown-input-pair/dropdown-input-pair.js similarity index 100% rename from ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.js rename to ui/pages/swaps/dropdown-input-pair/dropdown-input-pair.js diff --git a/ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.stories.js b/ui/pages/swaps/dropdown-input-pair/dropdown-input-pair.stories.js similarity index 100% rename from ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.stories.js rename to ui/pages/swaps/dropdown-input-pair/dropdown-input-pair.stories.js diff --git a/ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.test.js b/ui/pages/swaps/dropdown-input-pair/dropdown-input-pair.test.js similarity index 71% rename from ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.test.js rename to ui/pages/swaps/dropdown-input-pair/dropdown-input-pair.test.js index 69420a56c..0f09cbf81 100644 --- a/ui/app/pages/swaps/dropdown-input-pair/dropdown-input-pair.test.js +++ b/ui/pages/swaps/dropdown-input-pair/dropdown-input-pair.test.js @@ -1,6 +1,10 @@ import React from 'react'; +import configureMockStore from 'redux-mock-store'; -import { renderWithProvider } from '../../../../../test/jest'; +import { + renderWithProvider, + createSwapsMockStore, +} from '../../../../test/jest'; import DropdownInputPair from '.'; const createProps = (customProps = {}) => { @@ -11,9 +15,11 @@ const createProps = (customProps = {}) => { describe('DropdownInputPair', () => { it('renders the component with initial props', () => { + const store = configureMockStore()(createSwapsMockStore()); const props = createProps(); const { getByPlaceholderText } = renderWithProvider( <DropdownInputPair {...props} />, + store, ); expect(getByPlaceholderText('0')).toBeInTheDocument(); expect( diff --git a/ui/app/pages/swaps/dropdown-input-pair/index.js b/ui/pages/swaps/dropdown-input-pair/index.js similarity index 100% rename from ui/app/pages/swaps/dropdown-input-pair/index.js rename to ui/pages/swaps/dropdown-input-pair/index.js diff --git a/ui/app/pages/swaps/dropdown-input-pair/index.scss b/ui/pages/swaps/dropdown-input-pair/index.scss similarity index 100% rename from ui/app/pages/swaps/dropdown-input-pair/index.scss rename to ui/pages/swaps/dropdown-input-pair/index.scss diff --git a/ui/app/pages/swaps/dropdown-search-list/__snapshots__/dropdown-search-list.test.js.snap b/ui/pages/swaps/dropdown-search-list/__snapshots__/dropdown-search-list.test.js.snap similarity index 100% rename from ui/app/pages/swaps/dropdown-search-list/__snapshots__/dropdown-search-list.test.js.snap rename to ui/pages/swaps/dropdown-search-list/__snapshots__/dropdown-search-list.test.js.snap diff --git a/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.js b/ui/pages/swaps/dropdown-search-list/dropdown-search-list.js similarity index 60% rename from ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.js rename to ui/pages/swaps/dropdown-search-list/dropdown-search-list.js index 005294a34..3f236ef2d 100644 --- a/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.js +++ b/ui/pages/swaps/dropdown-search-list/dropdown-search-list.js @@ -5,6 +5,7 @@ import React, { useContext, useRef, } from 'react'; +import { useSelector } from 'react-redux'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { isEqual } from 'lodash'; @@ -12,6 +13,16 @@ import { I18nContext } from '../../../contexts/i18n'; import SearchableItemList from '../searchable-item-list'; import PulseLoader from '../../../components/ui/pulse-loader'; import UrlIcon from '../../../components/ui/url-icon'; +import ActionableMessage from '../actionable-message'; +import ImportToken from '../import-token'; +import { useNewMetricEvent } from '../../../hooks/useMetricEvent'; +import { + isHardwareWallet, + getHardwareWalletType, + getCurrentChainId, + getRpcPrefsForCurrentProvider, +} from '../../../selectors/selectors'; +import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/swaps'; export default function DropdownSearchList({ searchListClassName, @@ -31,10 +42,31 @@ export default function DropdownSearchList({ hideRightLabels, hideItemIf, listContainerClassName, + shouldSearchForImports, }) { const t = useContext(I18nContext); const [isOpen, setIsOpen] = useState(false); + const [isImportTokenModalOpen, setIsImportTokenModalOpen] = useState(false); const [selectedItem, setSelectedItem] = useState(startingItem); + const [tokenForImport, setTokenForImport] = useState(null); + + const hardwareWalletUsed = useSelector(isHardwareWallet); + const hardwareWalletType = useSelector(getHardwareWalletType); + const chainId = useSelector(getCurrentChainId); + const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); + + const tokenImportedEvent = useNewMetricEvent({ + event: 'Token Imported', + sensitiveProperties: { + symbol: tokenForImport?.symbol, + address: tokenForImport?.address, + chain_id: chainId, + is_hardware_wallet: hardwareWalletUsed, + hardware_wallet_type: hardwareWalletType, + }, + category: 'swaps', + }); + const close = useCallback(() => { setIsOpen(false); onClose?.(); @@ -49,6 +81,25 @@ export default function DropdownSearchList({ [onSelect, close], ); + const onOpenImportTokenModalClick = (item) => { + setTokenForImport(item); + setIsImportTokenModalOpen(true); + }; + + const onImportTokenClick = () => { + tokenImportedEvent(); + // Only when a user confirms import of a token, we add it and show it in a dropdown. + onSelect?.(tokenForImport); + setSelectedItem(tokenForImport); + setTokenForImport(null); + close(); + }; + + const onImportTokenCloseClick = () => { + setIsImportTokenModalOpen(false); + close(); + }; + const onClickSelector = useCallback(() => { if (!isOpen) { setIsOpen(true); @@ -81,6 +132,34 @@ export default function DropdownSearchList({ } }; + const blockExplorerLink = + rpcPrefs.blockExplorerUrl ?? + SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ?? + null; + + const blockExplorerLabel = rpcPrefs.blockExplorerUrl + ? new URL(blockExplorerLink).hostname + : t('etherscan'); + + const blockExplorerLinkClickedEvent = useNewMetricEvent({ + category: 'Swaps', + event: 'Clicked Block Explorer Link', + properties: { + link_type: 'Token Tracker', + action: 'Verify Contract Address', + block_explorer_domain: blockExplorerLink + ? new URL(blockExplorerLink)?.hostname + : '', + }, + }); + + const importTokenProps = { + onImportTokenCloseClick, + onImportTokenClick, + setIsImportTokenModalOpen, + tokenForImport, + }; + return ( <div className={classnames('dropdown-search-list', className)} @@ -88,6 +167,9 @@ export default function DropdownSearchList({ onKeyUp={onKeyUp} tabIndex="0" > + {tokenForImport && isImportTokenModalOpen && ( + <ImportToken {...importTokenProps} /> + )} {!isOpen && ( <div className={classnames( @@ -141,6 +223,32 @@ export default function DropdownSearchList({ ) : ( <div className="dropdown-search-list__placeholder"> {t('swapBuildQuotePlaceHolderText', [searchQuery])} + <div + tabIndex="0" + className="searchable-item-list__item searchable-item-list__item--add-token" + key="searchable-item-list-item-last" + > + <ActionableMessage + message={ + blockExplorerLink && + t('addCustomTokenByContractAddress', [ + <a + key="dropdown-search-list__etherscan-link" + onClick={() => { + blockExplorerLinkClickedEvent(); + global.platform.openTab({ + url: blockExplorerLink, + }); + }} + target="_blank" + rel="noopener noreferrer" + > + {blockExplorerLabel} + </a>, + ]) + } + /> + </div> </div> ) } @@ -148,6 +256,7 @@ export default function DropdownSearchList({ fuseSearchKeys={fuseSearchKeys} defaultToAll={defaultToAll} onClickItem={onClickItem} + onOpenImportTokenModalClick={onOpenImportTokenModalClick} maxListItems={maxListItems} className={classnames( 'dropdown-search-list__token-container', @@ -159,6 +268,7 @@ export default function DropdownSearchList({ hideRightLabels={hideRightLabels} hideItemIf={hideItemIf} listContainerClassName={listContainerClassName} + shouldSearchForImports={shouldSearchForImports} /> <div className="dropdown-search-list__close-area" @@ -197,4 +307,5 @@ DropdownSearchList.propTypes = { hideRightLabels: PropTypes.bool, hideItemIf: PropTypes.func, listContainerClassName: PropTypes.string, + shouldSearchForImports: PropTypes.bool, }; diff --git a/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.stories.js b/ui/pages/swaps/dropdown-search-list/dropdown-search-list.stories.js similarity index 100% rename from ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.stories.js rename to ui/pages/swaps/dropdown-search-list/dropdown-search-list.stories.js diff --git a/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.test.js b/ui/pages/swaps/dropdown-search-list/dropdown-search-list.test.js similarity index 72% rename from ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.test.js rename to ui/pages/swaps/dropdown-search-list/dropdown-search-list.test.js index 70f0e6a68..47e9538f7 100644 --- a/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.test.js +++ b/ui/pages/swaps/dropdown-search-list/dropdown-search-list.test.js @@ -1,6 +1,10 @@ import React from 'react'; +import configureMockStore from 'redux-mock-store'; -import { renderWithProvider } from '../../../../../test/jest'; +import { + renderWithProvider, + createSwapsMockStore, +} from '../../../../test/jest'; import DropdownSearchList from '.'; const createProps = (customProps = {}) => { @@ -15,9 +19,11 @@ const createProps = (customProps = {}) => { describe('DropdownSearchList', () => { it('renders the component with initial props', () => { + const store = configureMockStore()(createSwapsMockStore()); const props = createProps(); const { container, getByText } = renderWithProvider( <DropdownSearchList {...props} />, + store, ); expect(container).toMatchSnapshot(); expect(getByText('symbol')).toBeInTheDocument(); diff --git a/ui/app/pages/swaps/dropdown-search-list/index.js b/ui/pages/swaps/dropdown-search-list/index.js similarity index 100% rename from ui/app/pages/swaps/dropdown-search-list/index.js rename to ui/pages/swaps/dropdown-search-list/index.js diff --git a/ui/app/pages/swaps/dropdown-search-list/index.scss b/ui/pages/swaps/dropdown-search-list/index.scss similarity index 96% rename from ui/app/pages/swaps/dropdown-search-list/index.scss rename to ui/pages/swaps/dropdown-search-list/index.scss index c75c22bbb..c8321e9df 100644 --- a/ui/app/pages/swaps/dropdown-search-list/index.scss +++ b/ui/pages/swaps/dropdown-search-list/index.scss @@ -63,7 +63,7 @@ cursor: pointer; position: relative; align-items: center; - width: 100%; + flex: 1; height: 60px; i { @@ -128,12 +128,16 @@ color: $Grey-500; min-height: 300px; position: relative; - z-index: 1; + z-index: 1002; background: white; border-radius: 6px; min-height: 194px; overflow: hidden; text-overflow: ellipsis; + + .searchable-item-list__item--add-token { + padding: 8px 0; + } } &__loading-item { diff --git a/ui/app/pages/swaps/exchange-rate-display/__snapshots__/exchange-rate-display.test.js.snap b/ui/pages/swaps/exchange-rate-display/__snapshots__/exchange-rate-display.test.js.snap similarity index 100% rename from ui/app/pages/swaps/exchange-rate-display/__snapshots__/exchange-rate-display.test.js.snap rename to ui/pages/swaps/exchange-rate-display/__snapshots__/exchange-rate-display.test.js.snap diff --git a/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.js b/ui/pages/swaps/exchange-rate-display/exchange-rate-display.js similarity index 100% rename from ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.js rename to ui/pages/swaps/exchange-rate-display/exchange-rate-display.js diff --git a/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.stories.js b/ui/pages/swaps/exchange-rate-display/exchange-rate-display.stories.js similarity index 100% rename from ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.stories.js rename to ui/pages/swaps/exchange-rate-display/exchange-rate-display.stories.js diff --git a/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.test.js b/ui/pages/swaps/exchange-rate-display/exchange-rate-display.test.js similarity index 92% rename from ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.test.js rename to ui/pages/swaps/exchange-rate-display/exchange-rate-display.test.js index b0aa8db60..9dc224206 100644 --- a/ui/app/pages/swaps/exchange-rate-display/exchange-rate-display.test.js +++ b/ui/pages/swaps/exchange-rate-display/exchange-rate-display.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; +import { renderWithProvider } from '../../../../test/jest'; import ExchangeRateDisplay from '.'; const createProps = (customProps = {}) => { diff --git a/ui/app/pages/swaps/exchange-rate-display/index.js b/ui/pages/swaps/exchange-rate-display/index.js similarity index 100% rename from ui/app/pages/swaps/exchange-rate-display/index.js rename to ui/pages/swaps/exchange-rate-display/index.js diff --git a/ui/app/pages/swaps/exchange-rate-display/index.scss b/ui/pages/swaps/exchange-rate-display/index.scss similarity index 100% rename from ui/app/pages/swaps/exchange-rate-display/index.scss rename to ui/pages/swaps/exchange-rate-display/index.scss diff --git a/ui/app/pages/swaps/fee-card/__snapshots__/fee-card.test.js.snap b/ui/pages/swaps/fee-card/__snapshots__/fee-card.test.js.snap similarity index 100% rename from ui/app/pages/swaps/fee-card/__snapshots__/fee-card.test.js.snap rename to ui/pages/swaps/fee-card/__snapshots__/fee-card.test.js.snap diff --git a/ui/app/pages/swaps/fee-card/fee-card.js b/ui/pages/swaps/fee-card/fee-card.js similarity index 99% rename from ui/app/pages/swaps/fee-card/fee-card.js rename to ui/pages/swaps/fee-card/fee-card.js index 23bb545f9..68ee4faec 100644 --- a/ui/app/pages/swaps/fee-card/fee-card.js +++ b/ui/pages/swaps/fee-card/fee-card.js @@ -6,7 +6,7 @@ import { MAINNET_CHAIN_ID, BSC_CHAIN_ID, LOCALHOST_CHAIN_ID, -} from '../../../../../shared/constants/network'; +} from '../../../../shared/constants/network'; export default function FeeCard({ primaryFee, diff --git a/ui/app/pages/swaps/fee-card/fee-card.stories.js b/ui/pages/swaps/fee-card/fee-card.stories.js similarity index 100% rename from ui/app/pages/swaps/fee-card/fee-card.stories.js rename to ui/pages/swaps/fee-card/fee-card.stories.js diff --git a/ui/app/pages/swaps/fee-card/fee-card.test.js b/ui/pages/swaps/fee-card/fee-card.test.js similarity index 92% rename from ui/app/pages/swaps/fee-card/fee-card.test.js rename to ui/pages/swaps/fee-card/fee-card.test.js index 15c8b0c33..7a81e4903 100644 --- a/ui/app/pages/swaps/fee-card/fee-card.test.js +++ b/ui/pages/swaps/fee-card/fee-card.test.js @@ -1,7 +1,7 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; -import { MAINNET_CHAIN_ID } from '../../../../../shared/constants/network'; +import { renderWithProvider } from '../../../../test/jest'; +import { MAINNET_CHAIN_ID } from '../../../../shared/constants/network'; import FeeCard from '.'; const createProps = (customProps = {}) => { diff --git a/ui/app/pages/swaps/fee-card/index.js b/ui/pages/swaps/fee-card/index.js similarity index 100% rename from ui/app/pages/swaps/fee-card/index.js rename to ui/pages/swaps/fee-card/index.js diff --git a/ui/app/pages/swaps/fee-card/index.scss b/ui/pages/swaps/fee-card/index.scss similarity index 100% rename from ui/app/pages/swaps/fee-card/index.scss rename to ui/pages/swaps/fee-card/index.scss diff --git a/ui/app/pages/swaps/fee-card/pig-icon.js b/ui/pages/swaps/fee-card/pig-icon.js similarity index 100% rename from ui/app/pages/swaps/fee-card/pig-icon.js rename to ui/pages/swaps/fee-card/pig-icon.js diff --git a/ui/app/pages/swaps/fee-card/pig-icon.test.js b/ui/pages/swaps/fee-card/pig-icon.test.js similarity index 80% rename from ui/app/pages/swaps/fee-card/pig-icon.test.js rename to ui/pages/swaps/fee-card/pig-icon.test.js index 7764681b8..6321b7dc6 100644 --- a/ui/app/pages/swaps/fee-card/pig-icon.test.js +++ b/ui/pages/swaps/fee-card/pig-icon.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; +import { renderWithProvider } from '../../../../test/jest'; import PigIcon from './pig-icon'; describe('PigIcon', () => { diff --git a/ui/pages/swaps/import-token/import-token.js b/ui/pages/swaps/import-token/import-token.js new file mode 100644 index 000000000..c0a967a9c --- /dev/null +++ b/ui/pages/swaps/import-token/import-token.js @@ -0,0 +1,89 @@ +import React, { useContext } from 'react'; +import PropTypes from 'prop-types'; +import { I18nContext } from '../../../contexts/i18n'; +import UrlIcon from '../../../components/ui/url-icon'; +import Popover from '../../../components/ui/popover'; +import Button from '../../../components/ui/button'; +import Box from '../../../components/ui/box'; +import Typography from '../../../components/ui/typography'; +import ActionableMessage from '../actionable-message'; +import { + TYPOGRAPHY, + FONT_WEIGHT, + ALIGN_ITEMS, + DISPLAY, +} from '../../../helpers/constants/design-system'; + +export default function ImportToken({ + onImportTokenCloseClick, + onImportTokenClick, + setIsImportTokenModalOpen, + tokenForImport, +}) { + const t = useContext(I18nContext); + const ImportTokenModalFooter = ( + <> + <Button + type="secondary" + className="page-container__footer-button" + onClick={onImportTokenCloseClick} + rounded + > + {t('cancel')} + </Button> + <Button + type="confirm" + className="page-container__footer-button" + onClick={onImportTokenClick} + rounded + > + {t('import')} + </Button> + </> + ); + + return ( + <Popover + title={t('importTokenQuestion')} + onClose={() => setIsImportTokenModalOpen(false)} + footer={ImportTokenModalFooter} + > + <Box + padding={[0, 6, 4, 6]} + alignItems={ALIGN_ITEMS.CENTER} + display={DISPLAY.FLEX} + className="import-token" + > + <ActionableMessage type="danger" message={t('importTokenWarning')} /> + <UrlIcon + url={tokenForImport.iconUrl} + className="import-token__token-icon" + fallbackClassName="import-token__token-icon" + name={tokenForImport.symbol} + /> + <Typography + ariant={TYPOGRAPHY.H4} + fontWeight={FONT_WEIGHT.BOLD} + boxProps={{ marginTop: 2, marginBottom: 3 }} + > + {tokenForImport.name} + </Typography> + <Typography variant={TYPOGRAPHY.H6}>{t('contract')}:</Typography> + <Typography + className="import-token__contract-address" + variant={TYPOGRAPHY.H7} + boxProps={{ marginBottom: 6 }} + > + {tokenForImport.address} + </Typography> + </Box> + </Popover> + ); +} + +ImportToken.propTypes = { + onImportTokenCloseClick: PropTypes.func, + onImportTokenClick: PropTypes.func, + setIsImportTokenModalOpen: PropTypes.func, + tokenForImport: PropTypes.object, +}; diff --git a/ui/pages/swaps/import-token/import-token.test.js b/ui/pages/swaps/import-token/import-token.test.js new file mode 100644 index 000000000..24616bdf9 --- /dev/null +++ b/ui/pages/swaps/import-token/import-token.test.js @@ -0,0 +1,27 @@ +import React from 'react'; + +import { renderWithProvider } from '../../../../test/jest'; +import ImportToken from '.'; + +const createProps = (customProps = {}) => { + return { + onImportTokenCloseClick: jest.fn(), + onImportTokenClick: jest.fn(), + setIsImportTokenModalOpen: jest.fn(), + tokenForImport: { + symbol: 'POS', + name: 'PoSToken', + address: '0xee609fe292128cad03b786dbb9bc2634ccdbe7fc', + }, + ...customProps, + }; +}; + +describe('ImportToken', () => { + it('renders the component with initial props', () => { + const props = createProps(); + const { getByText } = renderWithProvider(<ImportToken {...props} />); + expect(getByText(props.tokenForImport.name)).toBeInTheDocument(); + expect(getByText(props.tokenForImport.address)).toBeInTheDocument(); + }); +}); diff --git a/ui/pages/swaps/import-token/index.js b/ui/pages/swaps/import-token/index.js new file mode 100644 index 000000000..4196dce2c --- /dev/null +++ b/ui/pages/swaps/import-token/index.js @@ -0,0 +1 @@ +export { default } from './import-token'; diff --git a/ui/pages/swaps/import-token/index.scss b/ui/pages/swaps/import-token/index.scss new file mode 100644 index 000000000..28e7c396b --- /dev/null +++ b/ui/pages/swaps/import-token/index.scss @@ -0,0 +1,30 @@ +.import-token { + flex-direction: column; + + .actionable-message { + margin-top: 0; + + &--danger { + border-color: $Red-300; + background: $Red-000; + } + + &__message { + color: $Black-100; + text-align: left; + } + } + + &__contract-address { + border-radius: 8px; + background-color: $Grey-000; + padding: 5px 10px; + } + + &__token-icon { + font-size: $font-size-h2; + margin-top: 24px; + width: 69px; + height: 69px; + } +} diff --git a/ui/app/pages/swaps/index.js b/ui/pages/swaps/index.js similarity index 92% rename from ui/app/pages/swaps/index.js rename to ui/pages/swaps/index.js index 7af7b83b1..05a0d6d42 100644 --- a/ui/app/pages/swaps/index.js +++ b/ui/pages/swaps/index.js @@ -13,6 +13,8 @@ import { getSelectedAccount, getCurrentChainId, getIsSwapsChain, + isHardwareWallet, + getHardwareWalletType, } from '../../selectors/selectors'; import { getQuotes, @@ -33,6 +35,7 @@ import { fetchSwapsLiveness, } from '../../ducks/swaps/swaps'; import { + AWAITING_SIGNATURES_ROUTE, AWAITING_SWAP_ROUTE, BUILD_QUOTE_ROUTE, VIEW_QUOTE_ROUTE, @@ -45,8 +48,9 @@ import { ERROR_FETCHING_QUOTES, QUOTES_NOT_AVAILABLE_ERROR, SWAP_FAILED_ERROR, + CONTRACT_DATA_DISABLED_ERROR, OFFLINE_FOR_MAINTENANCE, -} from '../../../../shared/constants/swaps'; +} from '../../../shared/constants/swaps'; import { resetBackgroundSwapsState, @@ -59,13 +63,14 @@ import { currentNetworkTxListSelector } from '../../selectors'; import { useNewMetricEvent } from '../../hooks/useMetricEvent'; import FeatureToggledRoute from '../../helpers/higher-order-components/feature-toggled-route'; -import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; +import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; import { fetchTokens, fetchTopAssets, getSwapsTokensReceivedFromTxMeta, fetchAggregatorMetadata, } from './swaps.util'; +import AwaitingSignatures from './awaiting-signatures'; import AwaitingSwap from './awaiting-swap'; import LoadingQuote from './loading-swaps-quotes'; import BuildQuote from './build-quote'; @@ -78,6 +83,7 @@ export default function Swap() { const { pathname } = useLocation(); const isAwaitingSwapRoute = pathname === AWAITING_SWAP_ROUTE; + const isAwaitingSignaturesRoute = pathname === AWAITING_SIGNATURES_ROUTE; const isSwapsErrorRoute = pathname === SWAPS_ERROR_ROUTE; const isLoadingQuotesRoute = pathname === LOADING_QUOTES_ROUTE; @@ -131,7 +137,7 @@ export default function Swap() { tradeTxData?.txReceipt?.status === '0x0'; const conversionError = approveError || tradeError; - if (conversionError) { + if (conversionError && swapsErrorKey !== CONTRACT_DATA_DISABLED_ERROR) { swapsErrorKey = SWAP_FAILED_ERROR; } @@ -181,6 +187,8 @@ export default function Swap() { }; }, [dispatch, chainId]); + const hardwareWalletUsed = useSelector(isHardwareWallet); + const hardwareWalletType = useSelector(getHardwareWalletType); const exitedSwapsEvent = useNewMetricEvent({ event: 'Exited Swaps', category: 'swaps', @@ -192,6 +200,8 @@ export default function Swap() { slippage: fetchParams?.slippage, custom_slippage: fetchParams?.slippage !== 2, current_screen: pathname.match(/\/swaps\/(.+)/u)[1], + is_hardware_wallet: hardwareWalletUsed, + hardware_wallet_type: hardwareWalletType, }, }); const exitEventRef = useRef(); @@ -243,7 +253,7 @@ export default function Swap() { <div className="swaps__container"> <div className="swaps__header"> <div className="swaps__title">{t('swap')}</div> - {!isAwaitingSwapRoute && ( + {!isAwaitingSwapRoute && !isAwaitingSignaturesRoute && ( <div className="swaps__header-cancel" onClick={async () => { @@ -267,7 +277,7 @@ export default function Swap() { render={() => { if (tradeTxData && !conversionError) { return <Redirect to={{ pathname: AWAITING_SWAP_ROUTE }} />; - } else if (tradeTxData) { + } else if (tradeTxData && routeState) { return <Redirect to={{ pathname: SWAPS_ERROR_ROUTE }} />; } else if (routeState === 'loading' && aggregatorMetadata) { return <Redirect to={{ pathname: LOADING_QUOTES_ROUTE }} />; @@ -372,6 +382,13 @@ export default function Swap() { ); }} /> + <Route + path={AWAITING_SIGNATURES_ROUTE} + exact + render={() => { + return <AwaitingSignatures />; + }} + /> <Route path={AWAITING_SWAP_ROUTE} exact diff --git a/ui/app/pages/swaps/index.scss b/ui/pages/swaps/index.scss similarity index 94% rename from ui/app/pages/swaps/index.scss rename to ui/pages/swaps/index.scss index 7f1fe894a..358f0d7a5 100644 --- a/ui/app/pages/swaps/index.scss +++ b/ui/pages/swaps/index.scss @@ -1,5 +1,6 @@ @import 'actionable-message/index'; @import 'awaiting-swap/index'; +@import 'awaiting-signatures/index'; @import 'build-quote/index'; @import 'countdown-timer/index'; @import 'dropdown-input-pair/index'; @@ -13,6 +14,7 @@ @import 'slippage-buttons/index'; @import 'swaps-footer/index'; @import 'view-quote/index'; +@import 'import-token/index'; .swaps { display: flex; @@ -29,11 +31,8 @@ align-items: center; height: 100%; width: 100%; - overflow: hidden; - - &--scrollable { - overflow: auto; - } + overflow-x: hidden; + overflow-y: auto; @media screen and (min-width: 576px) { width: 460px; @@ -42,7 +41,6 @@ box-shadow: 0 0 7px 0 rgba(0, 0, 0, 0.08); border-radius: 8px; height: 620px; - overflow: hidden; } } diff --git a/ui/app/pages/swaps/index.test.js b/ui/pages/swaps/index.test.js similarity index 98% rename from ui/app/pages/swaps/index.test.js rename to ui/pages/swaps/index.test.js index fc47e01bf..a3162ae2a 100644 --- a/ui/app/pages/swaps/index.test.js +++ b/ui/pages/swaps/index.test.js @@ -10,7 +10,7 @@ import { setBackgroundConnection, MOCKS, CONSTANTS, -} from '../../../../test/jest'; +} from '../../../test/jest'; import Swap from '.'; const middleware = [thunk]; diff --git a/ui/app/pages/swaps/loading-swaps-quotes/__snapshots__/aggregator-logo.test.js.snap b/ui/pages/swaps/loading-swaps-quotes/__snapshots__/aggregator-logo.test.js.snap similarity index 100% rename from ui/app/pages/swaps/loading-swaps-quotes/__snapshots__/aggregator-logo.test.js.snap rename to ui/pages/swaps/loading-swaps-quotes/__snapshots__/aggregator-logo.test.js.snap diff --git a/ui/app/pages/swaps/loading-swaps-quotes/__snapshots__/loading-swaps-quotes-stories-metadata.test.js.snap b/ui/pages/swaps/loading-swaps-quotes/__snapshots__/loading-swaps-quotes-stories-metadata.test.js.snap similarity index 100% rename from ui/app/pages/swaps/loading-swaps-quotes/__snapshots__/loading-swaps-quotes-stories-metadata.test.js.snap rename to ui/pages/swaps/loading-swaps-quotes/__snapshots__/loading-swaps-quotes-stories-metadata.test.js.snap diff --git a/ui/app/pages/swaps/loading-swaps-quotes/aggregator-logo.js b/ui/pages/swaps/loading-swaps-quotes/aggregator-logo.js similarity index 100% rename from ui/app/pages/swaps/loading-swaps-quotes/aggregator-logo.js rename to ui/pages/swaps/loading-swaps-quotes/aggregator-logo.js diff --git a/ui/app/pages/swaps/loading-swaps-quotes/aggregator-logo.test.js b/ui/pages/swaps/loading-swaps-quotes/aggregator-logo.test.js similarity index 98% rename from ui/app/pages/swaps/loading-swaps-quotes/aggregator-logo.test.js rename to ui/pages/swaps/loading-swaps-quotes/aggregator-logo.test.js index fb81e33e6..3367316b6 100644 --- a/ui/app/pages/swaps/loading-swaps-quotes/aggregator-logo.test.js +++ b/ui/pages/swaps/loading-swaps-quotes/aggregator-logo.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; +import { renderWithProvider } from '../../../../test/jest'; import AggregatorLogo from './aggregator-logo'; const createProps = (customProps = {}) => { diff --git a/ui/app/pages/swaps/loading-swaps-quotes/background-animation.js b/ui/pages/swaps/loading-swaps-quotes/background-animation.js similarity index 100% rename from ui/app/pages/swaps/loading-swaps-quotes/background-animation.js rename to ui/pages/swaps/loading-swaps-quotes/background-animation.js diff --git a/ui/app/pages/swaps/loading-swaps-quotes/background-animation.test.js b/ui/pages/swaps/loading-swaps-quotes/background-animation.test.js similarity index 85% rename from ui/app/pages/swaps/loading-swaps-quotes/background-animation.test.js rename to ui/pages/swaps/loading-swaps-quotes/background-animation.test.js index 64e31843e..f4601ddc6 100644 --- a/ui/app/pages/swaps/loading-swaps-quotes/background-animation.test.js +++ b/ui/pages/swaps/loading-swaps-quotes/background-animation.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; +import { renderWithProvider } from '../../../../test/jest'; import BackgroundAnimation from './background-animation'; describe('BackgroundAnimation', () => { diff --git a/ui/app/pages/swaps/loading-swaps-quotes/index.js b/ui/pages/swaps/loading-swaps-quotes/index.js similarity index 100% rename from ui/app/pages/swaps/loading-swaps-quotes/index.js rename to ui/pages/swaps/loading-swaps-quotes/index.js diff --git a/ui/app/pages/swaps/loading-swaps-quotes/index.scss b/ui/pages/swaps/loading-swaps-quotes/index.scss similarity index 100% rename from ui/app/pages/swaps/loading-swaps-quotes/index.scss rename to ui/pages/swaps/loading-swaps-quotes/index.scss diff --git a/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes-stories-metadata.js b/ui/pages/swaps/loading-swaps-quotes/loading-swaps-quotes-stories-metadata.js similarity index 100% rename from ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes-stories-metadata.js rename to ui/pages/swaps/loading-swaps-quotes/loading-swaps-quotes-stories-metadata.js diff --git a/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes-stories-metadata.test.js b/ui/pages/swaps/loading-swaps-quotes/loading-swaps-quotes-stories-metadata.test.js similarity index 100% rename from ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes-stories-metadata.test.js rename to ui/pages/swaps/loading-swaps-quotes/loading-swaps-quotes-stories-metadata.test.js diff --git a/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js b/ui/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js similarity index 96% rename from ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js rename to ui/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js index 8835c372e..b0a5760f4 100644 --- a/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js +++ b/ui/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js @@ -10,6 +10,10 @@ import { getFetchParams, getQuotesFetchStartTime, } from '../../../ducks/swaps/swaps'; +import { + isHardwareWallet, + getHardwareWalletType, +} from '../../../selectors/selectors'; import { I18nContext } from '../../../contexts/i18n'; import { MetaMetricsContext } from '../../../contexts/metametrics.new'; import Mascot from '../../../components/ui/mascot'; @@ -67,6 +71,8 @@ export default function LoadingSwapsQuotes({ const fetchParams = useSelector(getFetchParams); const quotesFetchStartTime = useSelector(getQuotesFetchStartTime); + const hardwareWalletUsed = useSelector(isHardwareWallet); + const hardwareWalletType = useSelector(getHardwareWalletType); const quotesRequestCancelledEventConfig = { event: 'Quotes Request Cancelled', category: 'swaps', @@ -78,6 +84,8 @@ export default function LoadingSwapsQuotes({ slippage: fetchParams?.slippage, custom_slippage: fetchParams?.slippage !== 2, response_time: Date.now() - quotesFetchStartTime, + is_hardware_wallet: hardwareWalletUsed, + hardware_wallet_type: hardwareWalletType, }, }; diff --git a/ui/app/pages/swaps/main-quote-summary/__snapshots__/main-quote-summary.test.js.snap b/ui/pages/swaps/main-quote-summary/__snapshots__/main-quote-summary.test.js.snap similarity index 100% rename from ui/app/pages/swaps/main-quote-summary/__snapshots__/main-quote-summary.test.js.snap rename to ui/pages/swaps/main-quote-summary/__snapshots__/main-quote-summary.test.js.snap diff --git a/ui/app/pages/swaps/main-quote-summary/__snapshots__/quote-backdrop.test.js.snap b/ui/pages/swaps/main-quote-summary/__snapshots__/quote-backdrop.test.js.snap similarity index 100% rename from ui/app/pages/swaps/main-quote-summary/__snapshots__/quote-backdrop.test.js.snap rename to ui/pages/swaps/main-quote-summary/__snapshots__/quote-backdrop.test.js.snap diff --git a/ui/app/pages/swaps/main-quote-summary/index.js b/ui/pages/swaps/main-quote-summary/index.js similarity index 100% rename from ui/app/pages/swaps/main-quote-summary/index.js rename to ui/pages/swaps/main-quote-summary/index.js diff --git a/ui/app/pages/swaps/main-quote-summary/index.scss b/ui/pages/swaps/main-quote-summary/index.scss similarity index 100% rename from ui/app/pages/swaps/main-quote-summary/index.scss rename to ui/pages/swaps/main-quote-summary/index.scss diff --git a/ui/app/pages/swaps/main-quote-summary/main-quote-summary.js b/ui/pages/swaps/main-quote-summary/main-quote-summary.js similarity index 100% rename from ui/app/pages/swaps/main-quote-summary/main-quote-summary.js rename to ui/pages/swaps/main-quote-summary/main-quote-summary.js diff --git a/ui/app/pages/swaps/main-quote-summary/main-quote-summary.stories.js b/ui/pages/swaps/main-quote-summary/main-quote-summary.stories.js similarity index 100% rename from ui/app/pages/swaps/main-quote-summary/main-quote-summary.stories.js rename to ui/pages/swaps/main-quote-summary/main-quote-summary.stories.js diff --git a/ui/app/pages/swaps/main-quote-summary/main-quote-summary.test.js b/ui/pages/swaps/main-quote-summary/main-quote-summary.test.js similarity index 94% rename from ui/app/pages/swaps/main-quote-summary/main-quote-summary.test.js rename to ui/pages/swaps/main-quote-summary/main-quote-summary.test.js index cc1775363..85e17bd48 100644 --- a/ui/app/pages/swaps/main-quote-summary/main-quote-summary.test.js +++ b/ui/pages/swaps/main-quote-summary/main-quote-summary.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; +import { renderWithProvider } from '../../../../test/jest'; import MainQuoteSummary from '.'; const createProps = (customProps = {}) => { diff --git a/ui/app/pages/swaps/main-quote-summary/quote-backdrop.js b/ui/pages/swaps/main-quote-summary/quote-backdrop.js similarity index 100% rename from ui/app/pages/swaps/main-quote-summary/quote-backdrop.js rename to ui/pages/swaps/main-quote-summary/quote-backdrop.js diff --git a/ui/app/pages/swaps/main-quote-summary/quote-backdrop.test.js b/ui/pages/swaps/main-quote-summary/quote-backdrop.test.js similarity index 90% rename from ui/app/pages/swaps/main-quote-summary/quote-backdrop.test.js rename to ui/pages/swaps/main-quote-summary/quote-backdrop.test.js index caab811ca..00d23c265 100644 --- a/ui/app/pages/swaps/main-quote-summary/quote-backdrop.test.js +++ b/ui/pages/swaps/main-quote-summary/quote-backdrop.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; +import { renderWithProvider } from '../../../../test/jest'; import QuotesBackdrop from './quote-backdrop'; const createProps = (customProps = {}) => { diff --git a/ui/app/pages/swaps/searchable-item-list/__snapshots__/searchable-item-list.test.js.snap b/ui/pages/swaps/searchable-item-list/__snapshots__/searchable-item-list.test.js.snap similarity index 100% rename from ui/app/pages/swaps/searchable-item-list/__snapshots__/searchable-item-list.test.js.snap rename to ui/pages/swaps/searchable-item-list/__snapshots__/searchable-item-list.test.js.snap diff --git a/ui/app/pages/swaps/searchable-item-list/index.js b/ui/pages/swaps/searchable-item-list/index.js similarity index 100% rename from ui/app/pages/swaps/searchable-item-list/index.js rename to ui/pages/swaps/searchable-item-list/index.js diff --git a/ui/app/pages/swaps/searchable-item-list/index.scss b/ui/pages/swaps/searchable-item-list/index.scss similarity index 84% rename from ui/app/pages/swaps/searchable-item-list/index.scss rename to ui/pages/swaps/searchable-item-list/index.scss index 76b5e0578..85e4fb5a3 100644 --- a/ui/app/pages/swaps/searchable-item-list/index.scss +++ b/ui/pages/swaps/searchable-item-list/index.scss @@ -43,7 +43,7 @@ &__list-container { display: flex; flex-direction: column; - overflow-y: scroll; + overflow-y: auto; } &__item { @@ -63,7 +63,7 @@ } &:last-of-type { - border-bottom: 1px solid $Grey-100; + border-bottom: none; } &:hover, @@ -80,6 +80,38 @@ pointer-events: none; } + &--add-token { + min-height: auto; + opacity: 1; + pointer-events: none; + + &:hover { + background: none; + } + + .actionable-message { + margin: 0; + + &__message { + text-align: left; + color: $Black-100; + } + + a { + pointer-events: auto; + color: #037dd6; + cursor: pointer; + } + } + } + + .btn-primary { + @include H7; + + width: auto; + padding: 7px 11px; + } + > img { margin-top: -2px; } diff --git a/ui/app/pages/swaps/searchable-item-list/item-list/index.js b/ui/pages/swaps/searchable-item-list/item-list/index.js similarity index 100% rename from ui/app/pages/swaps/searchable-item-list/item-list/index.js rename to ui/pages/swaps/searchable-item-list/item-list/index.js diff --git a/ui/app/pages/swaps/searchable-item-list/item-list/item-list.component.js b/ui/pages/swaps/searchable-item-list/item-list/item-list.component.js similarity index 59% rename from ui/app/pages/swaps/searchable-item-list/item-list/item-list.component.js rename to ui/pages/swaps/searchable-item-list/item-list/item-list.component.js index 0601c7242..4c7442448 100644 --- a/ui/app/pages/swaps/searchable-item-list/item-list/item-list.component.js +++ b/ui/pages/swaps/searchable-item-list/item-list/item-list.component.js @@ -1,12 +1,23 @@ -import React from 'react'; +import React, { useContext } from 'react'; +import { useSelector } from 'react-redux'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import Identicon from '../../../../components/ui/identicon'; import UrlIcon from '../../../../components/ui/url-icon'; +import Button from '../../../../components/ui/button'; +import ActionableMessage from '../../actionable-message'; +import { I18nContext } from '../../../../contexts/i18n'; +import { + getCurrentChainId, + getRpcPrefsForCurrentProvider, +} from '../../../../selectors'; +import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../../shared/constants/swaps'; +import { useNewMetricEvent } from '../../../../hooks/useMetricEvent'; export default function ItemList({ results = [], onClickItem, + onOpenImportTokenModalClick, Placeholder, listTitle, maxListItems = 6, @@ -16,6 +27,32 @@ export default function ItemList({ hideItemIf, listContainerClassName, }) { + const t = useContext(I18nContext); + const chainId = useSelector(getCurrentChainId); + const rpcPrefs = useSelector(getRpcPrefsForCurrentProvider); + const blockExplorerLink = + rpcPrefs.blockExplorerUrl ?? + SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP[chainId] ?? + null; + + const blockExplorerLabel = rpcPrefs.blockExplorerUrl + ? new URL(blockExplorerLink).hostname + : t('etherscan'); + + const blockExplorerLinkClickedEvent = useNewMetricEvent({ + category: 'Swaps', + event: 'Clicked Block Explorer Link', + properties: { + link_type: 'Token Tracker', + action: 'Verify Contract Address', + block_explorer_domain: blockExplorerLink + ? new URL(blockExplorerLink)?.hostname + : '', + }, + }); + + // If there is a token for import based on a contract address, it's the only one in the list. + const hasTokenForImport = results.length === 1 && results[0].notImported; return results.length === 0 ? ( Placeholder && <Placeholder searchQuery={searchQuery} /> ) : ( @@ -35,7 +72,13 @@ export default function ItemList({ return null; } - const onClick = () => onClickItem?.(result); + const onClick = () => { + if (result.notImported) { + onOpenImportTokenModalClick(result); + } else { + onClickItem?.(result); + } + }; const { iconUrl, identiconAddress, @@ -96,9 +139,42 @@ export default function ItemList({ </div> )} </div> + {result.notImported && ( + <Button type="confirm" onClick={onClick} rounded> + {t('import')} + </Button> + )} </div> ); })} + {!hasTokenForImport && ( + <div + tabIndex="0" + className="searchable-item-list__item searchable-item-list__item--add-token" + key="searchable-item-list-item-last" + > + <ActionableMessage + message={ + blockExplorerLink && + t('addCustomTokenByContractAddress', [ + <a + key="searchable-item-list__etherscan-link" + onClick={() => { + blockExplorerLinkClickedEvent(); + global.platform.openTab({ + url: blockExplorerLink, + }); + }} + target="_blank" + rel="noopener noreferrer" + > + {blockExplorerLabel} + </a>, + ]) + } + /> + </div> + )} </div> </div> ); @@ -117,6 +193,7 @@ ItemList.propTypes = { }), ), onClickItem: PropTypes.func, + onOpenImportTokenModalClick: PropTypes.func, Placeholder: PropTypes.func, listTitle: PropTypes.string, maxListItems: PropTypes.number, diff --git a/ui/app/pages/swaps/searchable-item-list/list-item-search/index.js b/ui/pages/swaps/searchable-item-list/list-item-search/index.js similarity index 100% rename from ui/app/pages/swaps/searchable-item-list/list-item-search/index.js rename to ui/pages/swaps/searchable-item-list/list-item-search/index.js diff --git a/ui/app/pages/swaps/searchable-item-list/list-item-search/list-item-search.component.js b/ui/pages/swaps/searchable-item-list/list-item-search/list-item-search.component.js similarity index 59% rename from ui/app/pages/swaps/searchable-item-list/list-item-search/list-item-search.component.js rename to ui/pages/swaps/searchable-item-list/list-item-search/list-item-search.component.js index 1be3e3efe..26fbc0124 100644 --- a/ui/app/pages/swaps/searchable-item-list/list-item-search/list-item-search.component.js +++ b/ui/pages/swaps/searchable-item-list/list-item-search/list-item-search.component.js @@ -1,9 +1,14 @@ import React, { useState, useEffect, useRef } from 'react'; +import { useSelector } from 'react-redux'; import PropTypes from 'prop-types'; import Fuse from 'fuse.js'; +import log from 'loglevel'; import InputAdornment from '@material-ui/core/InputAdornment'; import TextField from '../../../../components/ui/text-field'; import { usePrevious } from '../../../../hooks/usePrevious'; +import { isValidHexAddress } from '../../../../../shared/modules/hexstring-utils'; +import { fetchToken } from '../../swaps.util'; +import { getCurrentChainId } from '../../../../selectors/selectors'; const renderAdornment = () => ( <InputAdornment position="start" style={{ marginRight: '12px' }}> @@ -18,17 +23,53 @@ export default function ListItemSearch({ fuseSearchKeys, searchPlaceholderText, defaultToAll, + shouldSearchForImports, }) { const fuseRef = useRef(); const [searchQuery, setSearchQuery] = useState(''); + const chainId = useSelector(getCurrentChainId); - const handleSearch = (newSearchQuery) => { - setSearchQuery(newSearchQuery); + /** + * Search a custom token for import based on a contract address. + * @param {String} contractAddress + */ + const handleSearchTokenForImport = async (contractAddress) => { + setSearchQuery(contractAddress); + try { + const token = await fetchToken(contractAddress, chainId); + if (token) { + token.primaryLabel = token.symbol; + token.secondaryLabel = token.name; + token.notImported = true; + onSearch({ + searchQuery: contractAddress, + results: [token], + }); + return; + } + } catch (e) { + log.error('Token not found, show 0 results.', e); + } + onSearch({ + searchQuery: contractAddress, + results: [], // No token for import found. + }); + }; + + const handleSearch = async (newSearchQuery) => { + const trimmedNewSearchQuery = newSearchQuery.trim(); + const validHexAddress = isValidHexAddress(trimmedNewSearchQuery); const fuseSearchResult = fuseRef.current.search(newSearchQuery); + const results = + defaultToAll && newSearchQuery === '' ? listToSearch : fuseSearchResult; + if (shouldSearchForImports && results.length === 0 && validHexAddress) { + await handleSearchTokenForImport(trimmedNewSearchQuery); + return; + } + setSearchQuery(newSearchQuery); onSearch({ searchQuery: newSearchQuery, - results: - defaultToAll && newSearchQuery === '' ? listToSearch : fuseSearchResult, + results, }); }; @@ -83,4 +124,5 @@ ListItemSearch.propTypes = { fuseSearchKeys: PropTypes.arrayOf(PropTypes.object).isRequired, searchPlaceholderText: PropTypes.string, defaultToAll: PropTypes.bool, + shouldSearchForImports: PropTypes.bool, }; diff --git a/ui/app/pages/swaps/searchable-item-list/searchable-item-list.js b/ui/pages/swaps/searchable-item-list/searchable-item-list.js similarity index 88% rename from ui/app/pages/swaps/searchable-item-list/searchable-item-list.js rename to ui/pages/swaps/searchable-item-list/searchable-item-list.js index ba871339e..318c2094e 100644 --- a/ui/app/pages/swaps/searchable-item-list/searchable-item-list.js +++ b/ui/pages/swaps/searchable-item-list/searchable-item-list.js @@ -12,11 +12,13 @@ export default function SearchableItemList({ listTitle, maxListItems, onClickItem, + onOpenImportTokenModalClick, Placeholder, searchPlaceholderText, hideRightLabels, hideItemIf, listContainerClassName, + shouldSearchForImports, }) { const itemListRef = useRef(); @@ -38,11 +40,13 @@ export default function SearchableItemList({ error={itemSelectorError} searchPlaceholderText={searchPlaceholderText} defaultToAll={defaultToAll} + shouldSearchForImports={shouldSearchForImports} /> <ItemList searchQuery={searchQuery} results={results} onClickItem={onClickItem} + onOpenImportTokenModalClick={onOpenImportTokenModalClick} Placeholder={Placeholder} listTitle={listTitle} maxListItems={maxListItems} @@ -59,6 +63,7 @@ SearchableItemList.propTypes = { itemSelectorError: PropTypes.string, itemsToSearch: PropTypes.array, onClickItem: PropTypes.func, + onOpenImportTokenModalClick: PropTypes.func, Placeholder: PropTypes.func, className: PropTypes.string, searchPlaceholderText: PropTypes.string, @@ -74,4 +79,5 @@ SearchableItemList.propTypes = { hideRightLabels: PropTypes.bool, hideItemIf: PropTypes.func, listContainerClassName: PropTypes.string, + shouldSearchForImports: PropTypes.bool, }; diff --git a/ui/app/pages/swaps/searchable-item-list/searchable-item-list.test.js b/ui/pages/swaps/searchable-item-list/searchable-item-list.test.js similarity index 82% rename from ui/app/pages/swaps/searchable-item-list/searchable-item-list.test.js rename to ui/pages/swaps/searchable-item-list/searchable-item-list.test.js index ef9a3a016..88641152f 100644 --- a/ui/app/pages/swaps/searchable-item-list/searchable-item-list.test.js +++ b/ui/pages/swaps/searchable-item-list/searchable-item-list.test.js @@ -1,6 +1,10 @@ import React from 'react'; +import configureMockStore from 'redux-mock-store'; -import { renderWithProvider } from '../../../../../test/jest'; +import { + renderWithProvider, + createSwapsMockStore, +} from '../../../../test/jest'; import SearchableItemList from '.'; const createProps = (customProps = {}) => { @@ -37,8 +41,12 @@ const createProps = (customProps = {}) => { describe('SearchableItemList', () => { it('renders the component with initial props', () => { + const store = configureMockStore()(createSwapsMockStore()); const props = createProps(); - const { getByText } = renderWithProvider(<SearchableItemList {...props} />); + const { getByText } = renderWithProvider( + <SearchableItemList {...props} />, + store, + ); expect(getByText(props.listTitle)).toBeInTheDocument(); expect(getByText(props.itemsToSearch[0].primaryLabel)).toBeInTheDocument(); expect( diff --git a/ui/app/pages/swaps/select-quote-popover/__snapshots__/select-quote-popover.test.js.snap b/ui/pages/swaps/select-quote-popover/__snapshots__/select-quote-popover.test.js.snap similarity index 100% rename from ui/app/pages/swaps/select-quote-popover/__snapshots__/select-quote-popover.test.js.snap rename to ui/pages/swaps/select-quote-popover/__snapshots__/select-quote-popover.test.js.snap diff --git a/ui/app/pages/swaps/select-quote-popover/index.js b/ui/pages/swaps/select-quote-popover/index.js similarity index 100% rename from ui/app/pages/swaps/select-quote-popover/index.js rename to ui/pages/swaps/select-quote-popover/index.js diff --git a/ui/app/pages/swaps/select-quote-popover/index.scss b/ui/pages/swaps/select-quote-popover/index.scss similarity index 100% rename from ui/app/pages/swaps/select-quote-popover/index.scss rename to ui/pages/swaps/select-quote-popover/index.scss diff --git a/ui/app/pages/swaps/select-quote-popover/mock-quote-data.js b/ui/pages/swaps/select-quote-popover/mock-quote-data.js similarity index 100% rename from ui/app/pages/swaps/select-quote-popover/mock-quote-data.js rename to ui/pages/swaps/select-quote-popover/mock-quote-data.js diff --git a/ui/app/pages/swaps/select-quote-popover/mock-quote-data.test.js b/ui/pages/swaps/select-quote-popover/mock-quote-data.test.js similarity index 100% rename from ui/app/pages/swaps/select-quote-popover/mock-quote-data.test.js rename to ui/pages/swaps/select-quote-popover/mock-quote-data.test.js diff --git a/ui/app/pages/swaps/select-quote-popover/quote-details/index.js b/ui/pages/swaps/select-quote-popover/quote-details/index.js similarity index 100% rename from ui/app/pages/swaps/select-quote-popover/quote-details/index.js rename to ui/pages/swaps/select-quote-popover/quote-details/index.js diff --git a/ui/app/pages/swaps/select-quote-popover/quote-details/index.scss b/ui/pages/swaps/select-quote-popover/quote-details/index.scss similarity index 100% rename from ui/app/pages/swaps/select-quote-popover/quote-details/index.scss rename to ui/pages/swaps/select-quote-popover/quote-details/index.scss diff --git a/ui/app/pages/swaps/select-quote-popover/quote-details/quote-details.js b/ui/pages/swaps/select-quote-popover/quote-details/quote-details.js similarity index 98% rename from ui/app/pages/swaps/select-quote-popover/quote-details/quote-details.js rename to ui/pages/swaps/select-quote-popover/quote-details/quote-details.js index 6d96123e0..86da97ca9 100644 --- a/ui/app/pages/swaps/select-quote-popover/quote-details/quote-details.js +++ b/ui/pages/swaps/select-quote-popover/quote-details/quote-details.js @@ -80,7 +80,7 @@ const QuoteDetails = ({ <div className="quote-details__row quote-details__row--high"> <div className="quote-details__detail-header"> <img - src="/images/logo/metamask-fox.svg" + src="./images/logo/metamask-fox.svg" className="quote-details__metafox-logo" alt="" /> diff --git a/ui/app/pages/swaps/select-quote-popover/select-quote-popover-constants.js b/ui/pages/swaps/select-quote-popover/select-quote-popover-constants.js similarity index 100% rename from ui/app/pages/swaps/select-quote-popover/select-quote-popover-constants.js rename to ui/pages/swaps/select-quote-popover/select-quote-popover-constants.js diff --git a/ui/app/pages/swaps/select-quote-popover/select-quote-popover.js b/ui/pages/swaps/select-quote-popover/select-quote-popover.js similarity index 100% rename from ui/app/pages/swaps/select-quote-popover/select-quote-popover.js rename to ui/pages/swaps/select-quote-popover/select-quote-popover.js diff --git a/ui/app/pages/swaps/select-quote-popover/select-quote-popover.stories.js b/ui/pages/swaps/select-quote-popover/select-quote-popover.stories.js similarity index 100% rename from ui/app/pages/swaps/select-quote-popover/select-quote-popover.stories.js rename to ui/pages/swaps/select-quote-popover/select-quote-popover.stories.js diff --git a/ui/app/pages/swaps/select-quote-popover/select-quote-popover.test.js b/ui/pages/swaps/select-quote-popover/select-quote-popover.test.js similarity index 89% rename from ui/app/pages/swaps/select-quote-popover/select-quote-popover.test.js rename to ui/pages/swaps/select-quote-popover/select-quote-popover.test.js index b23a35f68..1eaa99738 100644 --- a/ui/app/pages/swaps/select-quote-popover/select-quote-popover.test.js +++ b/ui/pages/swaps/select-quote-popover/select-quote-popover.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; +import { renderWithProvider } from '../../../../test/jest'; import SelectQuotePopover from '.'; const createProps = (customProps = {}) => { diff --git a/ui/app/pages/swaps/select-quote-popover/sort-list/__snapshots__/sort-list.test.js.snap b/ui/pages/swaps/select-quote-popover/sort-list/__snapshots__/sort-list.test.js.snap similarity index 100% rename from ui/app/pages/swaps/select-quote-popover/sort-list/__snapshots__/sort-list.test.js.snap rename to ui/pages/swaps/select-quote-popover/sort-list/__snapshots__/sort-list.test.js.snap diff --git a/ui/app/pages/swaps/select-quote-popover/sort-list/index.js b/ui/pages/swaps/select-quote-popover/sort-list/index.js similarity index 100% rename from ui/app/pages/swaps/select-quote-popover/sort-list/index.js rename to ui/pages/swaps/select-quote-popover/sort-list/index.js diff --git a/ui/app/pages/swaps/select-quote-popover/sort-list/sort-list.js b/ui/pages/swaps/select-quote-popover/sort-list/sort-list.js similarity index 100% rename from ui/app/pages/swaps/select-quote-popover/sort-list/sort-list.js rename to ui/pages/swaps/select-quote-popover/sort-list/sort-list.js diff --git a/ui/app/pages/swaps/select-quote-popover/sort-list/sort-list.test.js b/ui/pages/swaps/select-quote-popover/sort-list/sort-list.test.js similarity index 97% rename from ui/app/pages/swaps/select-quote-popover/sort-list/sort-list.test.js rename to ui/pages/swaps/select-quote-popover/sort-list/sort-list.test.js index 57896b8e0..99e5a19e5 100644 --- a/ui/app/pages/swaps/select-quote-popover/sort-list/sort-list.test.js +++ b/ui/pages/swaps/select-quote-popover/sort-list/sort-list.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../../test/jest'; +import { renderWithProvider } from '../../../../../test/jest'; import SortList from './sort-list'; const createProps = (customProps = {}) => { diff --git a/ui/app/pages/swaps/slippage-buttons/__snapshots__/slippage-buttons.test.js.snap b/ui/pages/swaps/slippage-buttons/__snapshots__/slippage-buttons.test.js.snap similarity index 100% rename from ui/app/pages/swaps/slippage-buttons/__snapshots__/slippage-buttons.test.js.snap rename to ui/pages/swaps/slippage-buttons/__snapshots__/slippage-buttons.test.js.snap diff --git a/ui/app/pages/swaps/slippage-buttons/index.js b/ui/pages/swaps/slippage-buttons/index.js similarity index 100% rename from ui/app/pages/swaps/slippage-buttons/index.js rename to ui/pages/swaps/slippage-buttons/index.js diff --git a/ui/app/pages/swaps/slippage-buttons/index.scss b/ui/pages/swaps/slippage-buttons/index.scss similarity index 99% rename from ui/app/pages/swaps/slippage-buttons/index.scss rename to ui/pages/swaps/slippage-buttons/index.scss index f9e2df7bc..fcfab7eb9 100644 --- a/ui/app/pages/swaps/slippage-buttons/index.scss +++ b/ui/pages/swaps/slippage-buttons/index.scss @@ -10,7 +10,6 @@ margin-bottom: 0; margin-left: auto; margin-right: auto; - cursor: pointer; background: unset; margin-bottom: 8px; } diff --git a/ui/app/pages/swaps/slippage-buttons/slippage-buttons.js b/ui/pages/swaps/slippage-buttons/slippage-buttons.js similarity index 90% rename from ui/app/pages/swaps/slippage-buttons/slippage-buttons.js rename to ui/pages/swaps/slippage-buttons/slippage-buttons.js index 83b230062..66a11f43b 100644 --- a/ui/app/pages/swaps/slippage-buttons/slippage-buttons.js +++ b/ui/pages/swaps/slippage-buttons/slippage-buttons.js @@ -13,8 +13,12 @@ export default function SlippageButtons({ }) { const t = useContext(I18nContext); const [customValue, setCustomValue] = useState(() => { - if (currentSlippage && currentSlippage !== 2 && currentSlippage !== 3) { - return currentSlippage; + if ( + typeof currentSlippage === 'number' && + currentSlippage !== 2 && + currentSlippage !== 3 + ) { + return currentSlippage.toString(); } return ''; }); @@ -24,7 +28,7 @@ export default function SlippageButtons({ return 1; } else if (currentSlippage === 2) { return 0; - } else if (currentSlippage) { + } else if (typeof currentSlippage === 'number') { return 2; } return 1; // Choose activeButtonIndex = 1 for 3% slippage by default. @@ -33,9 +37,12 @@ export default function SlippageButtons({ let errorText = ''; if (customValue) { - if (Number(customValue) <= 0) { - errorText = t('swapSlippageTooLow'); - } else if (Number(customValue) < 0.5) { + // customValue is a string, e.g. '0' + if (Number(customValue) < 0) { + errorText = t('swapSlippageNegative'); + } else if (Number(customValue) > 0 && Number(customValue) <= 1) { + // We will not show this warning for 0% slippage, because we will only + // return non-slippage quotes from off-chain makers. errorText = t('swapLowSlippageError'); } else if ( Number(customValue) >= 5 && @@ -136,10 +143,6 @@ export default function SlippageButtons({ ref={setInputRef} onBlur={() => { setEnteringCustomValue(false); - if (customValue === '0') { - setCustomValue(''); - setActiveButtonIndex(1); - } }} value={customValue || ''} /> diff --git a/ui/app/pages/swaps/slippage-buttons/slippage-buttons.stories.js b/ui/pages/swaps/slippage-buttons/slippage-buttons.stories.js similarity index 100% rename from ui/app/pages/swaps/slippage-buttons/slippage-buttons.stories.js rename to ui/pages/swaps/slippage-buttons/slippage-buttons.stories.js diff --git a/ui/app/pages/swaps/slippage-buttons/slippage-buttons.test.js b/ui/pages/swaps/slippage-buttons/slippage-buttons.test.js similarity index 93% rename from ui/app/pages/swaps/slippage-buttons/slippage-buttons.test.js rename to ui/pages/swaps/slippage-buttons/slippage-buttons.test.js index 0108f07d2..60ceeff4c 100644 --- a/ui/app/pages/swaps/slippage-buttons/slippage-buttons.test.js +++ b/ui/pages/swaps/slippage-buttons/slippage-buttons.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; +import { renderWithProvider } from '../../../../test/jest'; import SlippageButtons from '.'; const createProps = (customProps = {}) => { diff --git a/ui/app/pages/swaps/swaps-footer/__snapshots__/swaps-footer.test.js.snap b/ui/pages/swaps/swaps-footer/__snapshots__/swaps-footer.test.js.snap similarity index 100% rename from ui/app/pages/swaps/swaps-footer/__snapshots__/swaps-footer.test.js.snap rename to ui/pages/swaps/swaps-footer/__snapshots__/swaps-footer.test.js.snap diff --git a/ui/app/pages/swaps/swaps-footer/index.js b/ui/pages/swaps/swaps-footer/index.js similarity index 100% rename from ui/app/pages/swaps/swaps-footer/index.js rename to ui/pages/swaps/swaps-footer/index.js diff --git a/ui/app/pages/swaps/swaps-footer/index.scss b/ui/pages/swaps/swaps-footer/index.scss similarity index 100% rename from ui/app/pages/swaps/swaps-footer/index.scss rename to ui/pages/swaps/swaps-footer/index.scss diff --git a/ui/app/pages/swaps/swaps-footer/swaps-footer.js b/ui/pages/swaps/swaps-footer/swaps-footer.js similarity index 100% rename from ui/app/pages/swaps/swaps-footer/swaps-footer.js rename to ui/pages/swaps/swaps-footer/swaps-footer.js diff --git a/ui/app/pages/swaps/swaps-footer/swaps-footer.test.js b/ui/pages/swaps/swaps-footer/swaps-footer.test.js similarity index 91% rename from ui/app/pages/swaps/swaps-footer/swaps-footer.test.js rename to ui/pages/swaps/swaps-footer/swaps-footer.test.js index 4cff41083..17a2b3355 100644 --- a/ui/app/pages/swaps/swaps-footer/swaps-footer.test.js +++ b/ui/pages/swaps/swaps-footer/swaps-footer.test.js @@ -1,6 +1,6 @@ import React from 'react'; -import { renderWithProvider } from '../../../../../test/jest'; +import { renderWithProvider } from '../../../../test/jest'; import SwapsFooter from '.'; const createProps = (customProps = {}) => { diff --git a/ui/app/pages/swaps/swaps-gas-customization-modal/index.js b/ui/pages/swaps/swaps-gas-customization-modal/index.js similarity index 100% rename from ui/app/pages/swaps/swaps-gas-customization-modal/index.js rename to ui/pages/swaps/swaps-gas-customization-modal/index.js diff --git a/ui/app/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.component.js b/ui/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.component.js similarity index 100% rename from ui/app/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.component.js rename to ui/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.component.js diff --git a/ui/app/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.container.js b/ui/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.container.js similarity index 100% rename from ui/app/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.container.js rename to ui/pages/swaps/swaps-gas-customization-modal/swaps-gas-customization-modal.container.js diff --git a/ui/app/pages/swaps/swaps-util-test-constants.js b/ui/pages/swaps/swaps-util-test-constants.js similarity index 99% rename from ui/app/pages/swaps/swaps-util-test-constants.js rename to ui/pages/swaps/swaps-util-test-constants.js index cf54889b1..54c0b1e34 100644 --- a/ui/app/pages/swaps/swaps-util-test-constants.js +++ b/ui/pages/swaps/swaps-util-test-constants.js @@ -1,4 +1,4 @@ -import { ETH_SWAPS_TOKEN_OBJECT } from '../../../../shared/constants/swaps'; +import { ETH_SWAPS_TOKEN_OBJECT } from '../../../shared/constants/swaps'; export const TRADES_BASE_PROD_URL = 'https://api.metaswap.codefi.network/trades?'; diff --git a/ui/app/pages/swaps/swaps.util.js b/ui/pages/swaps/swaps.util.js similarity index 96% rename from ui/app/pages/swaps/swaps.util.js rename to ui/pages/swaps/swaps.util.js index 968802bb3..93788965f 100644 --- a/ui/app/pages/swaps/swaps.util.js +++ b/ui/pages/swaps/swaps.util.js @@ -6,16 +6,16 @@ import { METASWAP_CHAINID_API_HOST_MAP, SWAPS_CHAINID_CONTRACT_ADDRESS_MAP, ETH_WETH_CONTRACT_ADDRESS, -} from '../../../../shared/constants/swaps'; +} from '../../../shared/constants/swaps'; import { isSwapsDefaultTokenAddress, isSwapsDefaultTokenSymbol, -} from '../../../../shared/modules/swaps.utils'; +} from '../../../shared/modules/swaps.utils'; import { ETH_SYMBOL, WETH_SYMBOL, MAINNET_CHAIN_ID, -} from '../../../../shared/constants/network'; +} from '../../../shared/constants/network'; import { calcTokenValue, calcTokenAmount, @@ -34,7 +34,7 @@ import { formatCurrency } from '../../helpers/utils/confirm-tx.util'; import fetchWithCache from '../../helpers/utils/fetch-with-cache'; import { calcGasTotal } from '../send/send.utils'; -import { isValidHexAddress } from '../../../../shared/modules/hexstring-utils'; +import { isValidHexAddress } from '../../../shared/modules/hexstring-utils'; const TOKEN_TRANSFER_LOG_TOPIC_HASH = '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef'; @@ -47,6 +47,8 @@ const getBaseApi = function (type, chainId = MAINNET_CHAIN_ID) { return `${METASWAP_CHAINID_API_HOST_MAP[chainId]}/trades?`; case 'tokens': return `${METASWAP_CHAINID_API_HOST_MAP[chainId]}/tokens`; + case 'token': + return `${METASWAP_CHAINID_API_HOST_MAP[chainId]}/token`; case 'topAssets': return `${METASWAP_CHAINID_API_HOST_MAP[chainId]}/topAssets`; case 'featureFlag': @@ -290,10 +292,20 @@ export async function fetchTradesInfo( return newQuotes; } +export async function fetchToken(contractAddress, chainId) { + const tokenUrl = getBaseApi('token', chainId); + const token = await fetchWithCache( + `${tokenUrl}?address=${contractAddress}`, + { method: 'GET' }, + { cacheRefreshTime: CACHE_REFRESH_FIVE_MINUTES }, + ); + return token; +} + export async function fetchTokens(chainId) { - const tokenUrl = getBaseApi('tokens', chainId); + const tokensUrl = getBaseApi('tokens', chainId); const tokens = await fetchWithCache( - tokenUrl, + tokensUrl, { method: 'GET' }, { cacheRefreshTime: CACHE_REFRESH_FIVE_MINUTES }, ); @@ -301,7 +313,7 @@ export async function fetchTokens(chainId) { SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId], ...tokens.filter((token) => { return ( - validateData(TOKEN_VALIDATORS, token, tokenUrl) && + validateData(TOKEN_VALIDATORS, token, tokensUrl) && !( isSwapsDefaultTokenSymbol(token.symbol, chainId) || isSwapsDefaultTokenAddress(token.address, chainId) diff --git a/ui/app/pages/swaps/swaps.util.test.js b/ui/pages/swaps/swaps.util.test.js similarity index 98% rename from ui/app/pages/swaps/swaps.util.test.js rename to ui/pages/swaps/swaps.util.test.js index cc7f6d9fc..936864f0f 100644 --- a/ui/app/pages/swaps/swaps.util.test.js +++ b/ui/pages/swaps/swaps.util.test.js @@ -5,11 +5,11 @@ import { MAINNET_CHAIN_ID, BSC_CHAIN_ID, LOCALHOST_CHAIN_ID, -} from '../../../../shared/constants/network'; +} from '../../../shared/constants/network'; import { SWAPS_CHAINID_CONTRACT_ADDRESS_MAP, ETH_WETH_CONTRACT_ADDRESS, -} from '../../../../shared/constants/swaps'; +} from '../../../shared/constants/swaps'; import { TOKENS, EXPECTED_TOKENS_RESULT, @@ -26,7 +26,7 @@ import { isContractAddressValid, } from './swaps.util'; -jest.mock('../../../lib/storage-helpers.js', () => ({ +jest.mock('../../helpers/utils/storage-helpers.js', () => ({ getStorageItem: jest.fn(), setStorageItem: jest.fn(), })); diff --git a/ui/app/pages/swaps/view-quote/index.js b/ui/pages/swaps/view-quote/index.js similarity index 100% rename from ui/app/pages/swaps/view-quote/index.js rename to ui/pages/swaps/view-quote/index.js diff --git a/ui/app/pages/swaps/view-quote/index.scss b/ui/pages/swaps/view-quote/index.scss similarity index 76% rename from ui/app/pages/swaps/view-quote/index.scss rename to ui/pages/swaps/view-quote/index.scss index 20c2ea0b4..3e2e421bc 100644 --- a/ui/app/pages/swaps/view-quote/index.scss +++ b/ui/pages/swaps/view-quote/index.scss @@ -22,7 +22,7 @@ @media screen and (max-width: 576px) { overflow-y: auto; - max-height: 428px; + max-height: 420px; } } @@ -95,45 +95,52 @@ &-wrapper { width: 100%; - &.medium .actionable-message, - &.fiat-error .actionable-message { - border-color: $Yellow-500; - background: $Yellow-100; + &.low, + &.medium, + &.high { + .actionable-message { + .actionable-message__message { + color: inherit; + } - .actionable-message__message { - color: inherit; + button { + font-size: $font-size-h8; + padding: 4px 12px; + border-radius: 42px; + } } + } - button { - background: $Yellow-500; - border-radius: 42px; + &.low { + .actionable-message { + button { + background: $Blue-500; + color: #fff; + } + } + } + + &.medium { + .actionable-message { + border-color: $Yellow-500; + background: $Yellow-100; + + button { + background: $Yellow-500; + } } } &.high { .actionable-message { - border-color: $Red-500; - background: $Red-100; + border-color: $Red-300; + background: $Red-000; - .actionable-message__message { - color: $Red-500; + button { + background: $Red-500; + color: #fff; } } - - button { - background: $Red-500; - color: #fff; - border-radius: 42px; - - /* Offsets the width of ActionableMessage icon */ - margin-right: -22px; - } - } - - /* Hides info tooltip if there's a fiat error message */ - &.fiat-error div[data-tooltipped] { - /* !important overrides style being applied directly to tooltip by component */ - display: none !important; } } @@ -160,10 +167,9 @@ width: 100%; align-items: center; justify-content: center; - width: intrinsic; /* Safari/WebKit uses a non-standard name */ - width: max-content; max-width: 340px; margin-top: 8px; + margin-bottom: 28px; @media screen and (min-width: 576px) { &--thin { diff --git a/ui/app/pages/swaps/view-quote/view-quote-price-difference.js b/ui/pages/swaps/view-quote/view-quote-price-difference.js similarity index 77% rename from ui/app/pages/swaps/view-quote/view-quote-price-difference.js rename to ui/pages/swaps/view-quote/view-quote-price-difference.js index 61d1ad52b..327aaaf49 100644 --- a/ui/app/pages/swaps/view-quote/view-quote-price-difference.js +++ b/ui/pages/swaps/view-quote/view-quote-price-difference.js @@ -6,6 +6,11 @@ import { I18nContext } from '../../../contexts/i18n'; import ActionableMessage from '../actionable-message'; import Tooltip from '../../../components/ui/tooltip'; +import Box from '../../../components/ui/box'; +import { + JUSTIFY_CONTENT, + DISPLAY, +} from '../../../helpers/constants/design-system'; export default function ViewQuotePriceDifference(props) { const { @@ -28,9 +33,10 @@ export default function ViewQuotePriceDifference(props) { let priceDifferenceAcknowledgementText = ''; if (priceSlippageUnknownFiatValue) { // A calculation error signals we cannot determine dollar value - priceDifferenceMessage = t('swapPriceDifferenceUnavailable'); - priceDifferenceClass = 'fiat-error'; - priceDifferenceAcknowledgementText = t('continue'); + priceDifferenceTitle = t('swapPriceUnavailableTitle'); + priceDifferenceMessage = t('swapPriceUnavailableDescription'); + priceDifferenceClass = 'high'; + priceDifferenceAcknowledgementText = t('tooltipApproveButton'); } else { priceDifferenceTitle = t('swapPriceDifferenceTitle', [ priceDifferencePercentage, @@ -44,9 +50,7 @@ export default function ViewQuotePriceDifference(props) { priceSlippageFromDestination, // Destination tokens total value ]); priceDifferenceClass = usedQuote.priceSlippage.bucket; - priceDifferenceAcknowledgementText = t( - 'swapPriceDifferenceAcknowledgement', - ); + priceDifferenceAcknowledgementText = t('tooltipApproveButton'); } return ( @@ -60,11 +64,22 @@ export default function ViewQuotePriceDifference(props) { message={ <div className="view-quote__price-difference-warning-contents"> <div className="view-quote__price-difference-warning-contents-text"> - {priceDifferenceTitle && ( + <Box + display={DISPLAY.FLEX} + justifyContent={JUSTIFY_CONTENT.SPACE_BETWEEN} + paddingBottom={2} + > <div className="view-quote__price-difference-warning-contents-title"> {priceDifferenceTitle} </div> - )} + <Tooltip + position="bottom" + theme="white" + title={t('swapPriceImpactTooltip')} + > + <i className="fa fa-info-circle" /> + </Tooltip> + </Box> {priceDifferenceMessage} {!acknowledged && ( <div className="view-quote__price-difference-warning-contents-actions"> @@ -78,13 +93,6 @@ export default function ViewQuotePriceDifference(props) { </div> )} </div> - <Tooltip - position="bottom" - theme="white" - title={t('swapPriceDifferenceTooltip')} - > - <i className="fa fa-info-circle" /> - </Tooltip> </div> } /> diff --git a/ui/app/pages/swaps/view-quote/view-quote-price-difference.test.js b/ui/pages/swaps/view-quote/view-quote-price-difference.test.js similarity index 97% rename from ui/app/pages/swaps/view-quote/view-quote-price-difference.test.js rename to ui/pages/swaps/view-quote/view-quote-price-difference.test.js index c00322959..cd94ab4a0 100644 --- a/ui/app/pages/swaps/view-quote/view-quote-price-difference.test.js +++ b/ui/pages/swaps/view-quote/view-quote-price-difference.test.js @@ -2,7 +2,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { Provider } from 'react-redux'; import configureMockStore from 'redux-mock-store'; -import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; +import { NETWORK_TYPE_RPC } from '../../../../shared/constants/network'; import ViewQuotePriceDifference from './view-quote-price-difference'; describe('View Price Quote Difference', () => { @@ -144,6 +144,6 @@ describe('View Price Quote Difference', () => { 'Could not determine price.'; renderComponent(props); - expect(component.html()).toContain('fiat-error'); + expect(component.html()).toContain('high'); }); }); diff --git a/ui/app/pages/swaps/view-quote/view-quote.js b/ui/pages/swaps/view-quote/view-quote.js similarity index 96% rename from ui/app/pages/swaps/view-quote/view-quote.js rename to ui/pages/swaps/view-quote/view-quote.js index e20e806a0..c472f1f40 100644 --- a/ui/app/pages/swaps/view-quote/view-quote.js +++ b/ui/pages/swaps/view-quote/view-quote.js @@ -39,6 +39,8 @@ import { getSwapsDefaultToken, getCurrentChainId, getNativeCurrency, + isHardwareWallet, + getHardwareWalletType, } from '../../../selectors'; import { toPrecisionWithoutTrailingZeros } from '../../../helpers/utils/util'; import { getTokens } from '../../../ducks/metamask/metamask'; @@ -75,7 +77,7 @@ import { getRenderableNetworkFeesForQuote, } from '../swaps.util'; import { useTokenTracker } from '../../../hooks/useTokenTracker'; -import { QUOTES_EXPIRED_ERROR } from '../../../../../shared/constants/swaps'; +import { QUOTES_EXPIRED_ERROR } from '../../../../shared/constants/swaps'; import CountdownTimer from '../countdown-timer'; import SwapsFooter from '../swaps-footer'; import ViewQuotePriceDifference from './view-quote-price-difference'; @@ -330,6 +332,8 @@ export default function ViewQuote() { available_quotes: numberOfQuotes, }; + const hardwareWalletUsed = useSelector(isHardwareWallet); + const hardwareWalletType = useSelector(getHardwareWalletType); const allAvailableQuotesOpened = useNewMetricEvent({ event: 'All Available Quotes Opened', category: 'swaps', @@ -340,6 +344,8 @@ export default function ViewQuote() { usedQuote?.aggregator === topQuote?.aggregator ? null : usedQuote?.aggregator, + is_hardware_wallet: hardwareWalletUsed, + hardware_wallet_type: hardwareWalletType, }, }); const quoteDetailsOpened = useNewMetricEvent({ @@ -352,6 +358,8 @@ export default function ViewQuote() { usedQuote?.aggregator === topQuote?.aggregator ? null : usedQuote?.aggregator, + is_hardware_wallet: hardwareWalletUsed, + hardware_wallet_type: hardwareWalletType, }, }); const editSpendLimitOpened = useNewMetricEvent({ @@ -362,13 +370,20 @@ export default function ViewQuote() { custom_spend_limit_set: originalApproveAmount === approveAmount, custom_spend_limit_amount: originalApproveAmount === approveAmount ? null : approveAmount, + is_hardware_wallet: hardwareWalletUsed, + hardware_wallet_type: hardwareWalletType, }, }); const bestQuoteReviewedEvent = useNewMetricEvent({ event: 'Best Quote Reviewed', category: 'swaps', - sensitiveProperties: { ...eventObjectBase, network_fees: feeInFiat }, + sensitiveProperties: { + ...eventObjectBase, + network_fees: feeInFiat, + is_hardware_wallet: hardwareWalletUsed, + hardware_wallet_type: hardwareWalletType, + }, }); useEffect(() => { if ( diff --git a/ui/app/pages/unlock-page/index.js b/ui/pages/unlock-page/index.js similarity index 100% rename from ui/app/pages/unlock-page/index.js rename to ui/pages/unlock-page/index.js diff --git a/ui/app/pages/unlock-page/index.scss b/ui/pages/unlock-page/index.scss similarity index 100% rename from ui/app/pages/unlock-page/index.scss rename to ui/pages/unlock-page/index.scss diff --git a/ui/app/pages/unlock-page/unlock-page.component.js b/ui/pages/unlock-page/unlock-page.component.js similarity index 100% rename from ui/app/pages/unlock-page/unlock-page.component.js rename to ui/pages/unlock-page/unlock-page.component.js diff --git a/ui/app/pages/unlock-page/unlock-page.component.test.js b/ui/pages/unlock-page/unlock-page.component.test.js similarity index 84% rename from ui/app/pages/unlock-page/unlock-page.component.test.js rename to ui/pages/unlock-page/unlock-page.component.test.js index 412b7dc6f..5029f6a0e 100644 --- a/ui/app/pages/unlock-page/unlock-page.component.test.js +++ b/ui/pages/unlock-page/unlock-page.component.test.js @@ -2,7 +2,7 @@ import React from 'react'; import sinon from 'sinon'; import configureMockStore from 'redux-mock-store'; import { fireEvent } from '@testing-library/react'; -import { renderWithProvider } from '../../../../test/lib/render-helpers'; +import { renderWithProvider } from '../../../test/lib/render-helpers'; import UnlockPage from './unlock-page.component'; describe('Unlock Page Component', () => { @@ -23,7 +23,7 @@ describe('Unlock Page Component', () => { configureMockStore()({ metamask: { currentLocale: 'en' } }), ); - fireEvent.click(getByText('import using seed phrase')); + fireEvent.click(getByText('import using Secret Recovery Phrase')); expect(props.onRestore.calledOnce).toStrictEqual(true); }); }); diff --git a/ui/app/pages/unlock-page/unlock-page.container.js b/ui/pages/unlock-page/unlock-page.container.js similarity index 92% rename from ui/app/pages/unlock-page/unlock-page.container.js rename to ui/pages/unlock-page/unlock-page.container.js index 56da7e661..eb1be797a 100644 --- a/ui/app/pages/unlock-page/unlock-page.container.js +++ b/ui/pages/unlock-page/unlock-page.container.js @@ -1,8 +1,8 @@ import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { compose } from 'redux'; -import { getEnvironmentType } from '../../../../app/scripts/lib/util'; -import { ENVIRONMENT_TYPE_POPUP } from '../../../../shared/constants/app'; +import { getEnvironmentType } from '../../../app/scripts/lib/util'; +import { ENVIRONMENT_TYPE_POPUP } from '../../../shared/constants/app'; import { DEFAULT_ROUTE, RESTORE_VAULT_ROUTE, diff --git a/ui/app/pages/unlock-page/unlock-page.container.test.js b/ui/pages/unlock-page/unlock-page.container.test.js similarity index 100% rename from ui/app/pages/unlock-page/unlock-page.container.test.js rename to ui/pages/unlock-page/unlock-page.container.test.js diff --git a/ui/app/selectors/confirm-transaction.js b/ui/selectors/confirm-transaction.js similarity index 98% rename from ui/app/selectors/confirm-transaction.js rename to ui/selectors/confirm-transaction.js index 2ac609be7..ba837e8ab 100644 --- a/ui/app/selectors/confirm-transaction.js +++ b/ui/selectors/confirm-transaction.js @@ -1,5 +1,5 @@ import { createSelector } from 'reselect'; -import txHelper from '../../lib/tx-helper'; +import txHelper from '../helpers/utils/tx-helper'; import { calcTokenAmount } from '../helpers/utils/token-util'; import { roundExponential, @@ -10,7 +10,7 @@ import { addEth, } from '../helpers/utils/confirm-tx.util'; import { sumHexes } from '../helpers/utils/transactions.util'; -import { transactionMatchesNetwork } from '../../../shared/modules/transaction.utils'; +import { transactionMatchesNetwork } from '../../shared/modules/transaction.utils'; import { getCurrentChainId, deprecatedGetCurrentNetworkId } from './selectors'; import { getNativeCurrency } from '.'; diff --git a/ui/app/selectors/confirm-transaction.test.js b/ui/selectors/confirm-transaction.test.js similarity index 95% rename from ui/app/selectors/confirm-transaction.test.js rename to ui/selectors/confirm-transaction.test.js index 1f7acf158..9a899a523 100644 --- a/ui/app/selectors/confirm-transaction.test.js +++ b/ui/selectors/confirm-transaction.test.js @@ -2,8 +2,8 @@ import { KOVAN_CHAIN_ID, KOVAN_NETWORK_ID, MAINNET_CHAIN_ID, -} from '../../../shared/constants/network'; -import { TRANSACTION_TYPES } from '../../../shared/constants/transaction'; +} from '../../shared/constants/network'; +import { TRANSACTION_TYPES } from '../../shared/constants/transaction'; import { unconfirmedTransactionsCountSelector, sendTokenTokenAmountAndToAddressSelector, diff --git a/ui/app/selectors/custom-gas.js b/ui/selectors/custom-gas.js similarity index 89% rename from ui/app/selectors/custom-gas.js rename to ui/selectors/custom-gas.js index c84c48c71..4485c2086 100644 --- a/ui/app/selectors/custom-gas.js +++ b/ui/selectors/custom-gas.js @@ -1,4 +1,4 @@ -import { addHexPrefix } from '../../../app/scripts/lib/util'; +import { addHexPrefix } from '../../app/scripts/lib/util'; import { conversionUtil, conversionGreaterThan, @@ -9,6 +9,7 @@ import { formatETHFee } from '../helpers/utils/formatters'; import { calcGasTotal } from '../pages/send/send.utils'; import { GAS_ESTIMATE_TYPES } from '../helpers/constants/common'; +import { BASIC_ESTIMATE_STATES, GAS_SOURCE } from '../ducks/gas/gas.duck'; import { getCurrentCurrency, getIsMainnet, @@ -27,12 +28,14 @@ export function getCustomGasPrice(state) { } export function getBasicGasEstimateLoadingStatus(state) { - return state.gas.basicEstimateIsLoading; + return state.gas.basicEstimateStatus === 'LOADING'; } export function getAveragePriceEstimateInHexWEI(state) { - const averagePriceEstimate = state.gas.basicEstimates.average; - return getGasPriceInHexWei(averagePriceEstimate || '0x0'); + const averagePriceEstimate = state.gas.basicEstimates + ? state.gas.basicEstimates.average + : '0x0'; + return getGasPriceInHexWei(averagePriceEstimate); } export function getFastPriceEstimateInHexWEI(state) { @@ -355,3 +358,25 @@ export function getRenderableEstimateDataForSmallButtonsFromGWEI(state) { }, ]; } + +export function getIsEthGasPriceFetched(state) { + const gasState = state.gas; + return Boolean( + gasState.estimateSource === GAS_SOURCE.ETHGASPRICE && + gasState.basicEstimateStatus === BASIC_ESTIMATE_STATES.READY && + getIsMainnet(state), + ); +} + +export function getNoGasPriceFetched(state) { + const gasState = state.gas; + return Boolean(gasState.basicEstimateStatus === BASIC_ESTIMATE_STATES.FAILED); +} + +export function getIsGasEstimatesFetched(state) { + const gasState = state.gas; + return Boolean( + gasState.estimateSource === GAS_SOURCE.METASWAPS && + gasState.basicEstimateStatus === BASIC_ESTIMATE_STATES.READY, + ); +} diff --git a/ui/app/selectors/custom-gas.test.js b/ui/selectors/custom-gas.test.js similarity index 100% rename from ui/app/selectors/custom-gas.test.js rename to ui/selectors/custom-gas.test.js diff --git a/ui/app/selectors/first-time-flow.js b/ui/selectors/first-time-flow.js similarity index 100% rename from ui/app/selectors/first-time-flow.js rename to ui/selectors/first-time-flow.js diff --git a/ui/app/selectors/index.js b/ui/selectors/index.js similarity index 100% rename from ui/app/selectors/index.js rename to ui/selectors/index.js diff --git a/ui/app/selectors/permissions.js b/ui/selectors/permissions.js similarity index 99% rename from ui/app/selectors/permissions.js rename to ui/selectors/permissions.js index 8ac46cc96..788275179 100644 --- a/ui/app/selectors/permissions.js +++ b/ui/selectors/permissions.js @@ -1,5 +1,5 @@ import { forOwn } from 'lodash'; -import { CAVEAT_NAMES } from '../../../shared/constants/permissions'; +import { CAVEAT_NAMES } from '../../shared/constants/permissions'; import { getMetaMaskAccountsOrdered, getOriginOfCurrentTab, diff --git a/ui/app/selectors/permissions.test.js b/ui/selectors/permissions.test.js similarity index 99% rename from ui/app/selectors/permissions.test.js rename to ui/selectors/permissions.test.js index 3cebfd1a5..16d3057fc 100644 --- a/ui/app/selectors/permissions.test.js +++ b/ui/selectors/permissions.test.js @@ -1,4 +1,4 @@ -import { KOVAN_CHAIN_ID } from '../../../shared/constants/network'; +import { KOVAN_CHAIN_ID } from '../../shared/constants/network'; import { getConnectedDomainsForSelectedAddress, getOrderedConnectedAccountsForActiveTab, diff --git a/ui/app/selectors/selectors.js b/ui/selectors/selectors.js similarity index 92% rename from ui/app/selectors/selectors.js rename to ui/selectors/selectors.js index eed91f858..70c249ed1 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/selectors/selectors.js @@ -1,17 +1,18 @@ import { stripHexPrefix } from 'ethereumjs-util'; import { createSelector } from 'reselect'; -import { addHexPrefix } from '../../../app/scripts/lib/util'; +import { addHexPrefix } from '../../app/scripts/lib/util'; import { MAINNET_CHAIN_ID, + BSC_CHAIN_ID, TEST_CHAINS, NETWORK_TYPE_RPC, NATIVE_CURRENCY_TOKEN_IMAGE_MAP, -} from '../../../shared/constants/network'; +} from '../../shared/constants/network'; import { SWAPS_CHAINID_DEFAULT_TOKEN_MAP, ALLOWED_SWAPS_CHAIN_IDS, -} from '../../../shared/constants/swaps'; +} from '../../shared/constants/swaps'; import { shortenAddress, getAccountByAddress } from '../helpers/utils/util'; import { @@ -21,7 +22,7 @@ import { import { TEMPLATED_CONFIRMATION_MESSAGE_TYPES } from '../pages/confirmation/templates'; -import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils'; +import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils'; import { getNativeCurrency } from './send'; /** @@ -75,6 +76,26 @@ export function getCurrentKeyring(state) { return keyring; } +/** + * Checks if the current wallet is a hardware wallet. + * @param {Object} state + * @returns {Boolean} + */ +export function isHardwareWallet(state) { + const keyring = getCurrentKeyring(state); + return keyring.type.includes('Hardware'); +} + +/** + * Get a HW wallet type, e.g. "Ledger Hardware" + * @param {Object} state + * @returns {String|undefined} + */ +export function getHardwareWalletType(state) { + const keyring = getCurrentKeyring(state); + return keyring.type.includes('Hardware') ? keyring.type : undefined; +} + export function getAccountType(state) { const currentKeyring = getCurrentKeyring(state); const type = currentKeyring && currentKeyring.type; @@ -496,6 +517,22 @@ export function getShowWhatsNewPopup(state) { return state.appState.showWhatsNewPopup; } +/** + * Get an object of notification IDs and if they are allowed or not. + * @param {Object} state + * @returns {Object} + */ +function getAllowedNotificationIds(state) { + return { + 1: true, + 2: true, + 3: true, + 4: getCurrentChainId(state) === BSC_CHAIN_ID, + 5: true, + 6: true, + }; +} + /** * @typedef {Object} Notification * @property {number} id - A unique identifier for the notification @@ -516,8 +553,10 @@ export function getShowWhatsNewPopup(state) { export function getSortedNotificationsToShow(state) { const notifications = Object.values(state.metamask.notifications); + const allowedNotificationIds = getAllowedNotificationIds(state); const notificationsToShow = notifications.filter( - (notification) => !notification.isShown, + (notification) => + !notification.isShown && allowedNotificationIds[notification.id], ); const notificationsSortedByDate = notificationsToShow.sort( (a, b) => new Date(b.date) - new Date(a.date), diff --git a/ui/app/selectors/selectors.test.js b/ui/selectors/selectors.test.js similarity index 69% rename from ui/app/selectors/selectors.test.js rename to ui/selectors/selectors.test.js index 0b476f727..b83697ab3 100644 --- a/ui/app/selectors/selectors.test.js +++ b/ui/selectors/selectors.test.js @@ -1,4 +1,4 @@ -import mockState from '../../../test/data/mock-state.json'; +import mockState from '../../test/data/mock-state.json'; import * as selectors from './selectors'; describe('Selectors', () => { @@ -15,6 +15,44 @@ describe('Selectors', () => { }); }); + describe('#isHardwareWallet', () => { + it('returns false if it is not a HW wallet', () => { + mockState.metamask.keyrings[0].type = 'Simple Key Pair'; + expect(selectors.isHardwareWallet(mockState)).toBe(false); + }); + + it('returns true if it is a Ledger HW wallet', () => { + mockState.metamask.keyrings[0].type = 'Ledger Hardware'; + expect(selectors.isHardwareWallet(mockState)).toBe(true); + }); + + it('returns true if it is a Trezor HW wallet', () => { + mockState.metamask.keyrings[0].type = 'Trezor Hardware'; + expect(selectors.isHardwareWallet(mockState)).toBe(true); + }); + }); + + describe('#getHardwareWalletType', () => { + it('returns undefined if it is not a HW wallet', () => { + mockState.metamask.keyrings[0].type = 'Simple Key Pair'; + expect(selectors.getHardwareWalletType(mockState)).toBeUndefined(); + }); + + it('returns "Ledger Hardware" if it is a Ledger HW wallet', () => { + mockState.metamask.keyrings[0].type = 'Ledger Hardware'; + expect(selectors.getHardwareWalletType(mockState)).toBe( + 'Ledger Hardware', + ); + }); + + it('returns "Trezor Hardware" if it is a Trezor HW wallet', () => { + mockState.metamask.keyrings[0].type = 'Trezor Hardware'; + expect(selectors.getHardwareWalletType(mockState)).toBe( + 'Trezor Hardware', + ); + }); + }); + it('returns selected identity', () => { expect(selectors.getSelectedIdentity(mockState)).toStrictEqual({ address: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', diff --git a/ui/app/selectors/send-selectors-test-data.js b/ui/selectors/send-selectors-test-data.js similarity index 98% rename from ui/app/selectors/send-selectors-test-data.js rename to ui/selectors/send-selectors-test-data.js index f6c077798..e6c0d230c 100644 --- a/ui/app/selectors/send-selectors-test-data.js +++ b/ui/selectors/send-selectors-test-data.js @@ -1,4 +1,4 @@ -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; +import { TRANSACTION_STATUSES } from '../../shared/constants/transaction'; const state = { metamask: { diff --git a/ui/app/selectors/send.js b/ui/selectors/send.js similarity index 100% rename from ui/app/selectors/send.js rename to ui/selectors/send.js diff --git a/ui/app/selectors/send.test.js b/ui/selectors/send.test.js similarity index 99% rename from ui/app/selectors/send.test.js rename to ui/selectors/send.test.js index b4f94c56b..bab7b63fe 100644 --- a/ui/app/selectors/send.test.js +++ b/ui/selectors/send.test.js @@ -1,5 +1,5 @@ import sinon from 'sinon'; -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; +import { TRANSACTION_STATUSES } from '../../shared/constants/transaction'; import { getBlockGasLimit, getConversionRate, diff --git a/ui/app/selectors/transactions.js b/ui/selectors/transactions.js similarity index 98% rename from ui/app/selectors/transactions.js rename to ui/selectors/transactions.js index 628b856f0..e05d7f3fa 100644 --- a/ui/app/selectors/transactions.js +++ b/ui/selectors/transactions.js @@ -4,12 +4,12 @@ import { PENDING_STATUS_HASH, } from '../helpers/constants/transactions'; import { hexToDecimal } from '../helpers/utils/conversions.util'; -import txHelper from '../../lib/tx-helper'; +import txHelper from '../helpers/utils/tx-helper'; import { TRANSACTION_STATUSES, TRANSACTION_TYPES, -} from '../../../shared/constants/transaction'; -import { transactionMatchesNetwork } from '../../../shared/modules/transaction.utils'; +} from '../../shared/constants/transaction'; +import { transactionMatchesNetwork } from '../../shared/modules/transaction.utils'; import { getCurrentChainId, deprecatedGetCurrentNetworkId } from './selectors'; import { getSelectedAddress } from '.'; diff --git a/ui/app/selectors/transactions.test.js b/ui/selectors/transactions.test.js similarity index 98% rename from ui/app/selectors/transactions.test.js rename to ui/selectors/transactions.test.js index 4493c3e96..4f538e232 100644 --- a/ui/app/selectors/transactions.test.js +++ b/ui/selectors/transactions.test.js @@ -1,8 +1,8 @@ import { KOVAN_CHAIN_ID, MAINNET_CHAIN_ID, -} from '../../../shared/constants/network'; -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; +} from '../../shared/constants/network'; +import { TRANSACTION_STATUSES } from '../../shared/constants/transaction'; import { unapprovedMessagesSelector, transactionsSelector, diff --git a/ui/app/store/actionConstants.js b/ui/store/actionConstants.js similarity index 98% rename from ui/app/store/actionConstants.js rename to ui/store/actionConstants.js index 8613318c8..8a9f5cd84 100644 --- a/ui/app/store/actionConstants.js +++ b/ui/store/actionConstants.js @@ -29,7 +29,6 @@ export const HIDE_WARNING = 'HIDE_WARNING'; export const SHOW_ACCOUNT_DETAIL = 'SHOW_ACCOUNT_DETAIL'; export const SHOW_ACCOUNTS_PAGE = 'SHOW_ACCOUNTS_PAGE'; export const SHOW_CONF_TX_PAGE = 'SHOW_CONF_TX_PAGE'; -export const SET_CURRENT_FIAT = 'SET_CURRENT_FIAT'; // account detail screen export const SHOW_SEND_TOKEN_PAGE = 'SHOW_SEND_TOKEN_PAGE'; export const SHOW_PRIVATE_KEY = 'SHOW_PRIVATE_KEY'; @@ -72,6 +71,7 @@ export const BUY_ETH = 'BUY_ETH'; export const TOGGLE_ACCOUNT_MENU = 'TOGGLE_ACCOUNT_MENU'; +// preferences export const SET_USE_BLOCKIE = 'SET_USE_BLOCKIE'; export const SET_USE_NONCEFIELD = 'SET_USE_NONCEFIELD'; export const UPDATE_CUSTOM_NONCE = 'UPDATE_CUSTOM_NONCE'; diff --git a/ui/app/store/actionConstants.test.js b/ui/store/actionConstants.test.js similarity index 96% rename from ui/app/store/actionConstants.test.js rename to ui/store/actionConstants.test.js index 306704aea..7cfef827f 100644 --- a/ui/app/store/actionConstants.test.js +++ b/ui/store/actionConstants.test.js @@ -1,6 +1,6 @@ import freeze from 'deep-freeze-strict'; import reducers from '../ducks'; -import { NETWORK_TYPE_RPC } from '../../../shared/constants/network'; +import { NETWORK_TYPE_RPC } from '../../shared/constants/network'; import * as actionConstants from './actionConstants'; describe('Redux actionConstants', () => { diff --git a/ui/app/store/actions.js b/ui/store/actions.js similarity index 97% rename from ui/app/store/actions.js rename to ui/store/actions.js index f3c2c03ea..d701d20ad 100644 --- a/ui/app/store/actions.js +++ b/ui/store/actions.js @@ -2,31 +2,28 @@ import abi from 'human-standard-token-abi'; import pify from 'pify'; import log from 'loglevel'; import { capitalize } from 'lodash'; -import getBuyEthUrl from '../../../app/scripts/lib/buy-eth-url'; +import getBuyEthUrl from '../../app/scripts/lib/buy-eth-url'; import { calcTokenBalance, estimateGasForSend } from '../pages/send/send.utils'; import { fetchLocale, loadRelativeTimeFormatLocaleData, } from '../helpers/utils/i18n-helper'; import { getMethodDataAsync } from '../helpers/utils/transactions.util'; -import { fetchSymbolAndDecimals } from '../helpers/utils/token-util'; +import { getSymbolAndDecimals } from '../helpers/utils/token-util'; import switchDirection from '../helpers/utils/switch-direction'; -import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../../shared/constants/app'; +import { ENVIRONMENT_TYPE_NOTIFICATION } from '../../shared/constants/app'; import { hasUnconfirmedTransactions } from '../helpers/utils/confirm-tx.util'; import { setCustomGasLimit } from '../ducks/gas/gas.duck'; -import txHelper from '../../lib/tx-helper'; -import { - getEnvironmentType, - addHexPrefix, -} from '../../../app/scripts/lib/util'; +import txHelper from '../helpers/utils/tx-helper'; +import { getEnvironmentType, addHexPrefix } from '../../app/scripts/lib/util'; import { getPermittedAccountsForCurrentTab, getSelectedAddress, } from '../selectors'; import { switchedToUnconnectedAccount } from '../ducks/alerts/unconnected-account'; import { getUnconnectedAccountAlertEnabledness } from '../ducks/metamask/metamask'; -import { LISTED_CONTRACT_ADDRESSES } from '../../../shared/constants/tokens'; -import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils'; +import { LISTED_CONTRACT_ADDRESSES } from '../../shared/constants/tokens'; +import { toChecksumHexAddress } from '../../shared/modules/hexstring-utils'; import * as actionConstants from './actionConstants'; let background = null; @@ -473,25 +470,16 @@ export function setCurrentCurrency(currencyCode) { return async (dispatch) => { dispatch(showLoadingIndication()); log.debug(`background.setCurrentCurrency`); - let data; try { - data = await promisifiedBackground.setCurrentCurrency(currencyCode); + await promisifiedBackground.setCurrentCurrency(currencyCode); + await forceUpdateMetamaskState(dispatch); } catch (error) { - log.error(error.stack); + log.error(error); dispatch(displayWarning(error.message)); return; } finally { dispatch(hideLoadingIndication()); } - - dispatch({ - type: actionConstants.SET_CURRENT_FIAT, - value: { - currentCurrency: data.currentCurrency, - conversionRate: data.conversionRate, - conversionDate: data.conversionDate, - }, - }); }; } @@ -2050,8 +2038,9 @@ export function updatePreferences(value) { } export function setDefaultHomeActiveTabName(value) { - return async () => { + return async (dispatch) => { await promisifiedBackground.setDefaultHomeActiveTabName(value); + await forceUpdateMetamaskState(dispatch); }; } @@ -2262,7 +2251,7 @@ export function setPendingTokens(pendingTokens) { const { customToken = {}, selectedTokens = {} } = pendingTokens; const { address, symbol, decimals } = customToken; const tokens = - address && symbol && decimals + address && symbol && decimals >= 0 <= 36 ? { ...selectedTokens, [address]: { @@ -2563,6 +2552,14 @@ export function setLastActiveTime() { }; } +export function setDismissSeedBackUpReminder(value) { + return async (dispatch) => { + dispatch(showLoadingIndication()); + await promisifiedBackground.setDismissSeedBackUpReminder(value); + dispatch(hideLoadingIndication()); + }; +} + export function setConnectedStatusPopoverHasBeenShown() { return () => { background.setConnectedStatusPopoverHasBeenShown((err) => { @@ -2656,12 +2653,10 @@ export function getTokenParams(tokenAddress) { dispatch(loadingTokenParamsStarted()); log.debug(`loadingTokenParams`); - return fetchSymbolAndDecimals(tokenAddress, existingTokens).then( - ({ symbol, decimals }) => { - dispatch(addToken(tokenAddress, symbol, Number(decimals))); - dispatch(loadingTokenParamsFinished()); - }, - ); + return getSymbolAndDecimals(tokenAddress).then(({ symbol, decimals }) => { + dispatch(addToken(tokenAddress, symbol, Number(decimals))); + dispatch(loadingTokenParamsFinished()); + }); }; } @@ -2855,10 +2850,10 @@ export function setLedgerLivePreference(value) { // MetaMetrics /** - * @typedef {import('../../../shared/constants/metametrics').MetaMetricsEventPayload} MetaMetricsEventPayload - * @typedef {import('../../../shared/constants/metametrics').MetaMetricsEventOptions} MetaMetricsEventOptions - * @typedef {import('../../../shared/constants/metametrics').MetaMetricsPagePayload} MetaMetricsPagePayload - * @typedef {import('../../../shared/constants/metametrics').MetaMetricsPageOptions} MetaMetricsPageOptions + * @typedef {import('../../shared/constants/metametrics').MetaMetricsEventPayload} MetaMetricsEventPayload + * @typedef {import('../../shared/constants/metametrics').MetaMetricsEventOptions} MetaMetricsEventOptions + * @typedef {import('../../shared/constants/metametrics').MetaMetricsPagePayload} MetaMetricsPagePayload + * @typedef {import('../../shared/constants/metametrics').MetaMetricsPageOptions} MetaMetricsPageOptions */ /** diff --git a/ui/app/store/actions.test.js b/ui/store/actions.test.js similarity index 98% rename from ui/app/store/actions.test.js rename to ui/store/actions.test.js index d3281701e..73975843d 100644 --- a/ui/app/store/actions.test.js +++ b/ui/store/actions.test.js @@ -2,9 +2,9 @@ import sinon from 'sinon'; import configureStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import EthQuery from 'eth-query'; -import enLocale from '../../../app/_locales/en/messages.json'; -import MetaMaskController from '../../../app/scripts/metamask-controller'; -import { TRANSACTION_STATUSES } from '../../../shared/constants/transaction'; +import enLocale from '../../app/_locales/en/messages.json'; +import MetaMaskController from '../../app/scripts/metamask-controller'; +import { TRANSACTION_STATUSES } from '../../shared/constants/transaction'; import * as actions from './actions'; const middleware = [thunk]; @@ -618,28 +618,18 @@ describe('Actions', () => { it('calls setCurrentCurrency', async () => { const store = mockStore(); - const setCurrentCurrency = background.setCurrentCurrency.callsFake( - (_, cb) => - cb(null, { - currentCurrency: 'currency', - conversionRate: 100, - conversionDate: 1611839083653, - }), - ); - + background.setCurrentCurrency = sinon.stub().callsFake((_, cb) => cb()); actions._setBackgroundConnection(background); await store.dispatch(actions.setCurrentCurrency('jpy')); - expect(setCurrentCurrency.callCount).toStrictEqual(1); + expect(background.setCurrentCurrency.callCount).toStrictEqual(1); }); it('throws if setCurrentCurrency throws', async () => { const store = mockStore(); - - background.setCurrentCurrency.callsFake((_, cb) => - cb(new Error('error')), - ); - + background.setCurrentCurrency = sinon + .stub() + .callsFake((_, cb) => cb(new Error('error'))); actions._setBackgroundConnection(background); const expectedActions = [ diff --git a/ui/app/store/store.js b/ui/store/store.js similarity index 100% rename from ui/app/store/store.js rename to ui/store/store.js diff --git a/yarn.lock b/yarn.lock index 056b64bc2..620d82016 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2538,11 +2538,12 @@ "@types/yargs" "^15.0.0" chalk "^4.0.0" -"@lavamoat/allow-scripts@^1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@lavamoat/allow-scripts/-/allow-scripts-1.0.4.tgz#1804c552c40e522ad5210879181869030737321a" - integrity sha512-720ZQn/PGI1kOvO51I4bTknX3jhztbuytHSHh4i9D4fAqz4NHW14vLR6xbvyk8gh+QtbmsLloeulrA81+if1bw== +"@lavamoat/allow-scripts@^1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@lavamoat/allow-scripts/-/allow-scripts-1.0.6.tgz#fbdf7c35a5c2c2cff05ba002b7bc8f3355bda22c" + integrity sha512-bBUN2xuQEXWmWTJrfkwaM8Ige7TNfTTRodyW353VYnzX7kW866Tm/Ag0hdbukFvJfNjRHabVmLKxYYL8l/uyZQ== dependencies: + "@lavamoat/preinstall-always-fail" "^1.0.0" "@npmcli/run-script" "^1.8.1" "@yarnpkg/lockfile" "^1.1.0" npm-logical-tree "^1.2.1" @@ -2619,7 +2620,17 @@ prop-types "^15.7.2" react-is "^16.8.0" -"@metamask/contract-metadata@^1.19.0", "@metamask/contract-metadata@^1.22.0", "@metamask/contract-metadata@^1.23.0": +"@metamask/auto-changelog@^2.1.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@metamask/auto-changelog/-/auto-changelog-2.3.0.tgz#e8edf9210753b495d799b64af07de24ed0839004" + integrity sha512-l5Tk9Dx1+wF3L1ZvN+HObS7R077BDErRmElq5LckJTtAbAhEhg/MMD/6u2yZBmVIlPrint29BVt3tsqRp1GjIA== + dependencies: + cross-spawn "^7.0.3" + diff "^5.0.0" + semver "^7.3.5" + yargs "^17.0.1" + +"@metamask/contract-metadata@^1.19.0", "@metamask/contract-metadata@^1.22.0", "@metamask/contract-metadata@^1.25.0": version "1.25.0" resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.25.0.tgz#442ace91fb40165310764b68d8096d0017bb0492" integrity sha512-yhmYB9CQPv0dckNcPoWDcgtrdUp0OgK0uvkRE5QIBv4b3qENI1/03BztvK2ijbTuMlORUpjPq7/1MQDUPoRPVw== @@ -2652,20 +2663,20 @@ web3 "^0.20.7" web3-provider-engine "^16.0.1" -"@metamask/controllers@^6.2.1": - version "6.2.1" - resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-6.2.1.tgz#b7ca32011c814a3f629911cf455f02c609336dbf" - integrity sha512-ASysK0IJ/bBvI/C9htaupKYapN+Me7AkbR7xS9WTmoWNyf0mhMLvCtwVcYo34xPmzcnuTNA8huyfVHanEa1rXw== +"@metamask/controllers@^9.0.0": + version "9.1.0" + resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-9.1.0.tgz#4434f22eba2522889224b35aa08bc7b67d7248b7" + integrity sha512-jn/F0BNbaPsgEevHaPqk0lGAONKom4re1a4yBC67h7Vu6yu26CRi30SJl4xIh3IW4+ySbPhVLaiXFiXr3fESRQ== dependencies: - "@metamask/contract-metadata" "^1.23.0" + "@metamask/contract-metadata" "^1.25.0" "@types/uuid" "^8.3.0" async-mutex "^0.2.6" babel-runtime "^6.26.0" eth-ens-namehash "^2.0.8" eth-json-rpc-infura "^5.1.0" - eth-keyring-controller "^6.1.0" + eth-keyring-controller "^6.2.1" eth-method-registry "1.1.0" - eth-phishing-detect "^1.1.13" + eth-phishing-detect "^1.1.14" eth-query "^2.1.2" eth-rpc-errors "^4.0.0" eth-sig-util "^3.0.0" @@ -2679,6 +2690,7 @@ isomorphic-fetch "^3.0.0" jsonschema "^1.2.4" nanoid "^3.1.12" + punycode "^2.1.1" single-call-balance-checker-abi "^1.0.0" uuid "^8.3.2" web3 "^0.20.7" @@ -2704,12 +2716,12 @@ resolved "https://registry.yarnpkg.com/@metamask/eslint-config/-/eslint-config-6.0.0.tgz#ec53e8ab278073e882411ed89705bc7d06b78c81" integrity sha512-LyakGYGwM8UQOGhwWa+5erAI1hXuiTgf/y7USzOomX6H9KiuY09IAUYnPh7ToPG2sedD2F48UF1bUm8yvCoZOw== -"@metamask/eth-ledger-bridge-keyring@^0.4.0": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@metamask/eth-ledger-bridge-keyring/-/eth-ledger-bridge-keyring-0.4.0.tgz#764834adf146fc86ab7688a6c8f1e08708ed0d71" - integrity sha512-FkoAsP19YMKHNQzfPL5l9QJwp4YsEaN8d5pbJc+VcMzoC5rkt1iyDQdderERUV9DQlS3flBjxECCZ+QX54HD5w== +"@metamask/eth-ledger-bridge-keyring@^0.5.0": + version "0.5.0" + resolved "https://registry.yarnpkg.com/@metamask/eth-ledger-bridge-keyring/-/eth-ledger-bridge-keyring-0.5.0.tgz#c1ee89819c493239290a940da6285e6844240383" + integrity sha512-p7dvnAQ6n9AFf7JoJFwNsdIKoX5poP0bBwrgmCA/mLAdb5Z+bBAnHMSbKOZrH7rEsj7jExdbmUiJLI5qKnV0zA== dependencies: - eth-sig-util "^1.4.2" + eth-sig-util "^2.0.0" ethereumjs-tx "^1.3.4" ethereumjs-util "^7.0.9" events "^2.0.0" @@ -2728,30 +2740,16 @@ human-standard-token-abi "^1.0.2" safe-event-emitter "^1.0.1" -"@metamask/etherscan-link@^2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@metamask/etherscan-link/-/etherscan-link-2.0.0.tgz#89035736515a39532ba1142d87b9a8c2b4f920f1" - integrity sha512-/YS32hS2UTTxs0KyUmAgaDj1w4dzAvOrT+p4TJtpICeH3E/k51r2FO0Or7WJJI/mpzTqNKgcH5yyS2oCtupGiA== +"@metamask/etherscan-link@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@metamask/etherscan-link/-/etherscan-link-2.1.0.tgz#c0be8e68445b7b83cf85bcc03a56cdf8e256c973" + integrity sha512-ADuWlTUkFfN2vXlz81Bg/0BA+XRor+CdK1055p6k7H6BLIPoDKn9SBOFld9haQFuR9cKh/JYHcnlSIv5R4fUEw== "@metamask/forwarder@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@metamask/forwarder/-/forwarder-1.1.0.tgz#13829d8244bbf19ea658c0b20d21a77b67de0bdd" integrity sha512-Hggj4y0QIjDzKGTXzarhEPIQyFSB2bi2y6YLJNwaT4JmP30UB5Cj6gqoY0M4pj3QT57fzp0BUuGp7F/AUe28tw== -"@metamask/inpage-provider@^8.0.4": - version "8.0.4" - resolved "https://registry.yarnpkg.com/@metamask/inpage-provider/-/inpage-provider-8.0.4.tgz#6534fbdba4445a3aff639e32db66bb0ab5f0cd79" - integrity sha512-jdI0gVWW/0wQvKZe6shXl70cU+vIb8GpAimKFU4udc/HKtgp8tLd21ezq74RaMP/lHR+qq0coOQ2KnOnl8iNNg== - dependencies: - "@metamask/object-multiplex" "^1.1.0" - "@metamask/safe-event-emitter" "^2.0.0" - eth-rpc-errors "^4.0.2" - fast-deep-equal "^2.0.1" - is-stream "^2.0.0" - json-rpc-engine "^6.1.0" - json-rpc-middleware-stream "^3.0.0" - pump "^3.0.0" - "@metamask/jazzicon@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@metamask/jazzicon/-/jazzicon-2.0.0.tgz#5615528e91c0fc5c9d79202d1f0954a7922525a0" @@ -2786,6 +2784,31 @@ readable-stream "^2.2.2" through2 "^2.0.3" +"@metamask/post-message-stream@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@metamask/post-message-stream/-/post-message-stream-4.0.0.tgz#72f120e562346ca86ccc9b3684023ad44265f0df" + integrity sha512-r0JcoWXNuHycProx8ClxiIElJY/GVb/0/WWXTMsZu7qDejLo52VNXlwfydCdVjbMXeoT2nK1Yt3d5gjmHy5BWw== + dependencies: + readable-stream "2.3.3" + +"@metamask/providers@^8.1.1": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@metamask/providers/-/providers-8.1.1.tgz#7b0dbb54700c949aafba24c9b98e6f4e9d81f325" + integrity sha512-CG1sAuD6Mp4MZ5U90anf1FT0moDbStGXT+80TQFYXJbBeTQjhp321WgC/F2IgIJ3mFqOiByC3MQHLuunEVMQOA== + dependencies: + "@metamask/object-multiplex" "^1.1.0" + "@metamask/safe-event-emitter" "^2.0.0" + "@types/chrome" "^0.0.136" + detect-browser "^5.2.0" + eth-rpc-errors "^4.0.2" + extension-port-stream "^2.0.1" + fast-deep-equal "^2.0.1" + is-stream "^2.0.0" + json-rpc-engine "^6.1.0" + json-rpc-middleware-stream "^3.0.0" + pump "^3.0.0" + webextension-polyfill-ts "^0.25.0" + "@metamask/safe-event-emitter@^2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz#af577b477c683fad17c619a78208cede06f9605c" @@ -3655,11 +3678,31 @@ resolved "https://registry.yarnpkg.com/@types/braces/-/braces-3.0.0.tgz#7da1c0d44ff1c7eb660a36ec078ea61ba7eb42cb" integrity sha512-TbH79tcyi9FHwbyboOKeRachRq63mSuWYXOflsNO9ZyE5ClQ/JaozNKl+aWUq87qPNsXasXxi2AbgfwIJ+8GQw== +"@types/chrome@^0.0.136": + version "0.0.136" + resolved "https://registry.yarnpkg.com/@types/chrome/-/chrome-0.0.136.tgz#7c011b9f997b0156f25a140188a0c5689d3f368f" + integrity sha512-XDEiRhLkMd+SB7Iw3ZUIj/fov3wLd4HyTdLltVszkgl1dBfc3Rb7oPMVZ2Mz2TLqnF7Ow+StbR8E7r9lqpb4DA== + dependencies: + "@types/filesystem" "*" + "@types/har-format" "*" + "@types/color-name@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/filesystem@*": + version "0.0.30" + resolved "https://registry.yarnpkg.com/@types/filesystem/-/filesystem-0.0.30.tgz#a7373a2edf34d13e298baf7ee1101f738b2efb7e" + integrity sha512-NCoRgmGmLpTT9VFL6Bb6z0jQuqI3d0E5FGl7M0JOv/J5RQYo9s5aOItPYnpckx9MbYQk1APLXcF8f20Vqnf2yA== + dependencies: + "@types/filewriter" "*" + +"@types/filewriter@*": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/filewriter/-/filewriter-0.0.29.tgz#a48795ecadf957f6c0d10e0c34af86c098fa5bee" + integrity sha512-BsPXH/irW0ht0Ji6iw/jJaK8Lj3FJemon2gvEqHKpCdDCeemHa+rI3WBGq5z7cDMZgoLjY40oninGxqk+8NzNQ== + "@types/glob-base@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@types/glob-base/-/glob-base-0.3.0.tgz#a581d688347e10e50dd7c17d6f2880a10354319d" @@ -3680,6 +3723,11 @@ dependencies: "@types/node" "*" +"@types/har-format@*": + version "1.2.5" + resolved "https://registry.yarnpkg.com/@types/har-format/-/har-format-1.2.5.tgz#4f6648814d0fdcb6a510e3364a9db439a753c4b1" + integrity sha512-IG8AE1m2pWtPqQ7wXhFhy6Q59bwwnLwO36v5Rit2FrbXCIp8Sk8E2PfUCreyrdo17STwFSKDAkitVuVYbpEHvQ== + "@types/hast@^2.0.0": version "2.3.1" resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.1.tgz#b16872f2a6144c7025f296fb9636a667ebb79cd9" @@ -9051,6 +9099,11 @@ destroy@^1.0.4, destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= +detect-browser@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.2.0.tgz#c9cd5afa96a6a19fda0bbe9e9be48a6b6e1e9c97" + integrity sha512-tr7XntDAu50BVENgQfajMLzacmSe34D+qZc4zjnniz0ZVuw/TZcLcyxHQjYpJTM36sGEkZZlYLnIM1hH7alTMA== + detect-file@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/detect-file/-/detect-file-1.0.0.tgz#f0d66d03672a825cb1b73bdb3fe62310c8e552b7" @@ -9173,6 +9226,11 @@ diff@^4.0.2: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + diffie-hellman@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.2.tgz#b5835739270cfe26acf632099fded2a07f209e5e" @@ -10452,20 +10510,6 @@ eth-ens-namehash@^1.0.2: idna-uts46 "^1.0.1" js-sha3 "^0.5.7" -eth-hd-keyring@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/eth-hd-keyring/-/eth-hd-keyring-3.5.0.tgz#3976d83a27b24305481c389178f290d9264e839d" - integrity sha512-Ix1LcWYxHMxCCSIMz+TLXLtt50zF6ZDd/TRVXthdw91IwOk1ajuf7QHg3bCDcfeUpdf9oEpwIPbL3xjDqEEjYw== - dependencies: - bip39 "^2.2.0" - eth-sig-util "^2.4.4" - eth-simple-keyring "^3.5.0" - ethereumjs-abi "^0.6.5" - ethereumjs-util "^5.1.1" - ethereumjs-wallet "^0.6.0" - events "^1.1.1" - xtend "^4.0.1" - eth-hd-keyring@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/eth-hd-keyring/-/eth-hd-keyring-3.6.0.tgz#6835d30aa411b8d3ef098e82f6427b5325082abb" @@ -10546,25 +10590,10 @@ eth-json-rpc-middleware@^6.0.0: pify "^3.0.0" safe-event-emitter "^1.0.1" -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" - browser-passworder "^2.0.3" - eth-hd-keyring "^3.5.0" - eth-sig-util "^1.4.0" - eth-simple-keyring "^3.5.0" - ethereumjs-util "^5.1.2" - loglevel "^1.5.0" - obs-store "^4.0.3" - -eth-keyring-controller@^6.2.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-6.2.0.tgz#c649e7ced9bc9a11c2a6ab48234fae212569d390" - integrity sha512-UYYs+hTgrJNqy7xkI56QpekfsPuZw4kLxrFEUkHefCkBv9poSg/Abx4rvBsRwcj7yxXcxfgTNtoltJfR2we4uw== +eth-keyring-controller@^6.1.0, eth-keyring-controller@^6.2.0, eth-keyring-controller@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/eth-keyring-controller/-/eth-keyring-controller-6.2.1.tgz#61901071fc74059ed37cb5ae93870fdcae6e3781" + integrity sha512-x2gTM1iHp2Kbvdtd9Eslysw0qzVZiqOzpVB3AU/ni2Xiit+rlcv2H80zYKjrEwlfWFDj4YILD3bOqlnEMmRJOA== dependencies: bip39 "^2.4.0" bluebird "^3.5.0" @@ -10641,7 +10670,7 @@ eth-rpc-errors@^4.0.0, eth-rpc-errors@^4.0.2: dependencies: fast-safe-stringify "^2.0.6" -eth-sig-util@^1.4.0, eth-sig-util@^1.4.2: +eth-sig-util@^1.4.2: version "1.4.2" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" integrity sha1-jZWCAsftuq6Dlwf7pvCf8ydgYhA= @@ -10649,7 +10678,7 @@ eth-sig-util@^1.4.0, eth-sig-util@^1.4.2: ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" ethereumjs-util "^5.1.1" -eth-sig-util@^2.0.0, eth-sig-util@^2.4.4, eth-sig-util@^2.5.0: +eth-sig-util@^2.0.0: version "2.5.4" resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.5.4.tgz#577b01fe491b6bf59b0464be09633e20c1677bc5" integrity sha512-aCMBwp8q/4wrW4QLsF/HYBOSA7TpLKmkVwP3pYQNkEEseW2Rr8Z5Uxc9/h6HX+OG3tuHo+2bINVSihIeBfym6A== @@ -10669,18 +10698,6 @@ eth-sig-util@^3.0.0, eth-sig-util@^3.0.1: tweetnacl "^1.0.3" tweetnacl-util "^0.15.0" -eth-simple-keyring@^3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/eth-simple-keyring/-/eth-simple-keyring-3.5.0.tgz#c7fa285ca58d31ef44bc7db678b689f9ffd7b453" - integrity sha512-z9IPt9aoMWAw5Zc3Jk/HKbWPJNc7ivZ5ECNtl3ZoQUGRnwoWO71W5+liVPJtXFNacGOOGsBfqTqrXL9C4EnYYQ== - dependencies: - eth-sig-util "^2.5.0" - ethereumjs-abi "^0.6.5" - ethereumjs-util "^5.1.1" - ethereumjs-wallet "^0.6.0" - events "^1.1.1" - xtend "^4.0.1" - eth-simple-keyring@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/eth-simple-keyring/-/eth-simple-keyring-4.2.0.tgz#c197a4bd4cce7d701b5f3607d0b843112ddb17e3" @@ -10771,7 +10788,7 @@ ethereum-ens-network-map@^1.0.0, ethereum-ens-network-map@^1.0.2: resolved "https://registry.yarnpkg.com/ethereum-ens-network-map/-/ethereum-ens-network-map-1.0.2.tgz#4e27bad18dae7bd95d84edbcac2c9e739fc959b9" integrity sha512-5qwJ5n3YhjSpE6O/WEBXCAb2nagUgyagJ6C0lGUBWC4LjKp/rRzD+pwtDJ6KCiITFEAoX4eIrWOjRy0Sylq5Hg== -ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.4, ethereumjs-abi@^0.6.5, ethereumjs-abi@^0.6.8: +ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.4, ethereumjs-abi@^0.6.8: version "0.6.8" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== @@ -10894,19 +10911,7 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereum safe-buffer "^5.1.1" secp256k1 "^3.0.1" -ethereumjs-util@^7.0.2: - version "7.0.8" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.8.tgz#5258762b7b17e3d828e41834948363ff0a703ffd" - integrity sha512-JJt7tDpCAmDPw/sGoFYeq0guOVqT3pTE9xlEbBmc/nlCij3JRCoS2c96SQ6kXVHOT3xWUNLDm5QCJLQaUnVAtQ== - dependencies: - "@types/bn.js" "^4.11.3" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - ethjs-util "0.1.6" - rlp "^2.2.4" - -ethereumjs-util@^7.0.9: +ethereumjs-util@^7.0.2, ethereumjs-util@^7.0.9: version "7.0.9" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.9.tgz#2038baeb30f370a3e576ec175bd70bbbb6807d42" integrity sha512-cRqvYYKJoitq6vMKMf8pXeVwvTrX+dRD0JwHaYqm8jvogK14tqIoCWH/KUHcRwnVxVXEYF/o6pup5jRG4V0xzg== @@ -10969,7 +10974,7 @@ ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4, ethereumjs-vm@^2.6.0: rustbn.js "~0.2.0" safe-buffer "^5.1.1" -ethereumjs-wallet@0.6.5, ethereumjs-wallet@^0.6.0, ethereumjs-wallet@^0.6.4: +ethereumjs-wallet@0.6.5, ethereumjs-wallet@^0.6.4: version "0.6.5" resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.5.tgz#685e9091645cee230ad125c007658833991ed474" integrity sha512-MDwjwB9VQVnpp/Dc1XzA6J1a3wgHQ4hSvA1uWNatdpOrtCbPVuQSKSyRnjLvS0a+KKMw2pvQ9Ybqpb3+eW8oNA== @@ -11495,6 +11500,13 @@ extension-port-stream@^2.0.0: resolved "https://registry.yarnpkg.com/extension-port-stream/-/extension-port-stream-2.0.0.tgz#c52da241eef4643171b7c6d696baa4a3453c5a9a" integrity sha512-7ju8jisPXY8w8UiUczF61hRN6bpx/YTZYU9J901GnEqu7vQnweMAwS30k+SgXCcY9S38Zno+fhuu1iaxd+0swg== +extension-port-stream@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extension-port-stream/-/extension-port-stream-2.0.1.tgz#d374820c581418c2275d3c4439ade0b82c4cfac6" + integrity sha512-ltrv4Dh/979I04+D4Te6TFygfRSOc5EBzzlHRldWMS8v73V80qWluxH88hqF0qyUsBXTb8NmzlmSipcre6a+rg== + dependencies: + webextension-polyfill-ts "^0.22.0" + extensionizer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/extensionizer/-/extensionizer-1.0.1.tgz#504544239a7610ba8404b15c1832091a37768d09" @@ -11714,9 +11726,9 @@ fetch-ponyfill@^4.0.0: node-fetch "~1.7.1" figgy-pudding@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" - integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== + version "3.5.2" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.2.tgz#b4eee8148abb01dcf1d1ac34367d59e12fa61d6e" + integrity sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw== figures@^1.3.5: version "1.7.0" @@ -13469,6 +13481,13 @@ history@^4.9.0: tiny-warning "^1.0.0" value-equal "^1.0.1" +history@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/history/-/history-5.0.0.tgz#0cabbb6c4bbf835addb874f8259f6d25101efd08" + integrity sha512-3NyRMKIiFSJmIPdq7FxkNMJkQ7ZEtVblOQ38VtKaA0zZMW1Eo6Q6W8oDKEflr1kNNTItSnk4JMCO1deeSgbLLg== + dependencies: + "@babel/runtime" "^7.7.6" + hmac-drbg@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" @@ -13511,9 +13530,9 @@ homedir-polyfill@^1.0.1: parse-passwd "^1.0.0" hosted-git-info@^2.1.4: - version "2.5.0" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" - integrity sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg== + version "2.8.9" + resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" + integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== html-element-map@^1.0.0: version "1.2.0" @@ -20684,13 +20703,6 @@ posix-character-classes@^0.1.0: resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= -post-message-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/post-message-stream/-/post-message-stream-3.0.0.tgz#90d9f54bd209e6b6f5d74795b87588205b547048" - integrity sha1-kNn1S9IJ5rb110eVuHWIIFtUcEg= - dependencies: - readable-stream "^2.1.4" - postcss-flexbugs-fixes@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-4.1.0.tgz#e094a9df1783e2200b7b19f875dcad3b3aff8b20" @@ -21011,7 +21023,7 @@ probe-image-size@5.0.0: request "^2.83.0" stream-parser "~0.3.1" -process-nextick-args@^1.0.6, process-nextick-args@^1.0.7: +process-nextick-args@^1.0.6, process-nextick-args@^1.0.7, process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= @@ -22232,7 +22244,7 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.5, readable-stream@~2.3.6: +"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.5, readable-stream@~2.3.6: version "2.3.7" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== @@ -22264,6 +22276,19 @@ readable-stream@1.1.x, readable-stream@^1.0.33: string_decoder "^1.1.1" util-deprecate "^1.0.1" +readable-stream@2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" + integrity sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~1.0.6" + safe-buffer "~5.1.1" + string_decoder "~1.0.3" + 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" @@ -23478,14 +23503,7 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^7.2.1, semver@^7.3.2, semver@^7.3.4: - version "7.3.4" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" - integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== - dependencies: - lru-cache "^6.0.0" - -semver@^7.3.5: +semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5: version "7.3.5" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7" integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ== @@ -24219,9 +24237,9 @@ sshpk@^1.7.0: tweetnacl "~0.14.0" ssri@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" - integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== + version "6.0.2" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5" + integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q== dependencies: figgy-pudding "^3.5.1" @@ -24582,6 +24600,13 @@ string_decoder@^1.0.0, string_decoder@^1.1.1: dependencies: safe-buffer "~5.1.0" +string_decoder@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.0.3.tgz#0fc67d7c141825de94282dd536bec6b9bce860ab" + integrity sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ== + dependencies: + safe-buffer "~5.1.0" + string_decoder@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" @@ -26251,12 +26276,7 @@ uuid@^3.1.0, uuid@^3.2.1, uuid@^3.2.2, uuid@^3.3.2, uuid@^3.3.3: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.3.tgz#4568f0216e78760ee1dbf3a4d2cf53e224112866" integrity sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ== -uuid@^8.0.0: - version "8.3.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31" - integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg== - -uuid@^8.3.0, uuid@^8.3.2: +uuid@^8.0.0, uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -26848,6 +26868,25 @@ web3@^0.20.7: version "0.1.1" resolved "https://codeload.github.com/dignifiedquire/webcrypto-shim/tar.gz/190bc9ec341375df6025b17ae12ddb2428ea49c8" +webextension-polyfill-ts@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/webextension-polyfill-ts/-/webextension-polyfill-ts-0.22.0.tgz#86cfd7bab4d9d779d98c8340983f4b691b2343f3" + integrity sha512-3P33ClMwZ/qiAT7UH1ROrkRC1KM78umlnPpRhdC/292UyoTTW9NcjJEqDsv83HbibcTB6qCtpVeuB2q2/oniHQ== + dependencies: + webextension-polyfill "^0.7.0" + +webextension-polyfill-ts@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/webextension-polyfill-ts/-/webextension-polyfill-ts-0.25.0.tgz#fff041626365dbd0e29c40b197e989a55ec221ca" + integrity sha512-ikQhwwHYkpBu00pFaUzIKY26I6L87DeRI+Q6jBT1daZUNuu8dSrg5U9l/ZbqdaQ1M/TTSPKeAa3kolP5liuedw== + dependencies: + webextension-polyfill "^0.7.0" + +webextension-polyfill@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/webextension-polyfill/-/webextension-polyfill-0.7.0.tgz#0df1120ff0266056319ce1a622b09ad8d4a56505" + integrity sha512-su48BkMLxqzTTvPSE1eWxKToPS2Tv5DLGxKexLEVpwFd6Po6N8hhSLIvG6acPAg7qERoEaDL+Y5HQJeJeml5Aw== + webidl-conversions@^4.0.1, webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" @@ -27474,6 +27513,19 @@ yargs@^16.0.0, yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" +yargs@^17.0.1: + version "17.0.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.0.1.tgz#6a1ced4ed5ee0b388010ba9fd67af83b9362e0bb" + integrity sha512-xBBulfCc8Y6gLFcrPvtqKz9hz8SO0l1Ni8GgDekvBX2ro0HRQImDGnikfc33cgzcYUSncapnNcZDjVFIH3f6KQ== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yargs@^7.1.0: version "7.1.1" resolved "https://registry.yarnpkg.com/yargs/-/yargs-7.1.1.tgz#67f0ef52e228d4ee0d6311acede8850f53464df6"