diff --git a/.circleci/config.yml b/.circleci/config.yml index 973ee001a..a2ab03bfc 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -391,7 +391,7 @@ jobs: destination: test-artifacts test-e2e-firefox: - executor: node-browsers + executor: node-browsers-medium-plus steps: - checkout - run: diff --git a/.circleci/scripts/create-lavamoat-viz.sh b/.circleci/scripts/create-lavamoat-viz.sh index 53e520f27..db1dc3979 100755 --- a/.circleci/scripts/create-lavamoat-viz.sh +++ b/.circleci/scripts/create-lavamoat-viz.sh @@ -11,7 +11,7 @@ BUILD_DEST="./build-artifacts/build-viz/" mkdir -p "${BUILD_DEST}" # generate lavamoat debug config -yarn lavamoat:debug +yarn lavamoat:debug:build # generate viz npx lavamoat-viz --dest "${BUILD_DEST}" \ No newline at end of file diff --git a/.circleci/scripts/validate-allow-scripts.sh b/.circleci/scripts/validate-allow-scripts.sh index e466f039c..de45520ad 100755 --- a/.circleci/scripts/validate-allow-scripts.sh +++ b/.circleci/scripts/validate-allow-scripts.sh @@ -6,7 +6,7 @@ set -o pipefail yarn allow-scripts auto -if git diff --exit-code --quiet +if git diff --exit-code then echo "allow-scripts configuration is up-to-date" else diff --git a/.circleci/scripts/validate-lavamoat-policy.sh b/.circleci/scripts/validate-lavamoat-policy.sh index 4eab30b75..d674cd3f0 100755 --- a/.circleci/scripts/validate-lavamoat-policy.sh +++ b/.circleci/scripts/validate-lavamoat-policy.sh @@ -6,7 +6,7 @@ set -o pipefail yarn lavamoat:auto -if git diff --exit-code --quiet +if git diff --exit-code then echo "LavaMoat policy is up-to-date" else diff --git a/.eslintrc.js b/.eslintrc.js index ca9fe4677..4459124dd 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -134,6 +134,7 @@ module.exports = { 'shared/**/*.test.js', 'development/**/*.test.js', 'app/scripts/migrations/*.test.js', + 'app/scripts/platforms/*.test.js', ], extends: ['@metamask/eslint-config-mocha'], rules: { @@ -157,6 +158,7 @@ module.exports = { 'shared/**/*.test.js', 'development/**/*.test.js', 'app/scripts/migrations/*.test.js', + 'app/scripts/platforms/*.test.js', ], extends: ['@metamask/eslint-config-jest'], rules: { @@ -183,6 +185,7 @@ module.exports = { 'nyc.config.js', 'stylelint.config.js', 'app/scripts/lockdown-run.js', + 'app/scripts/lockdown-more.js', 'development/**/*.js', 'test/e2e/**/*.js', 'test/lib/wait-until-called.js', @@ -197,6 +200,7 @@ module.exports = { { files: [ 'app/scripts/lockdown-run.js', + 'app/scripts/lockdown-more.js', 'test/unit-global/protect-intrinsics.test.js', ], globals: { diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 5c0adaf12..68cad1c32 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -31,7 +31,7 @@ If applicable, add screenshots to help explain your problem. - OS: [e.g. OS X, Windows] - Hardware Wallet: [e.g. Trezor Firmware version 1.8.3, Ledger Nano S Firmware version 1.6.0] - Browser: [e.g. Chrome Version 79.0.3945.79 (Official Build) (64-bit), Firefox Browser 71.0 (64-bit)] - - MetaMask Version: [e.g. 5.0.2] + - MetaMask Version: [e.g. 5.0.2 - find it in Settings > About] **Additional context (Error Messages, etc.)** Add any other context about the problem here. diff --git a/.mocharc.js b/.mocharc.js new file mode 100644 index 000000000..83776be4f --- /dev/null +++ b/.mocharc.js @@ -0,0 +1,7 @@ +module.exports = { + // TODO: Remove the `exit` setting, it can hide broken tests. + exit: true, + ignore: ['./app/scripts/migrations/*.test.js', './app/scripts/platforms/*.test.js'], + recursive: true, + require: ['test/env.js', 'test/setup.js'], +} diff --git a/.mocharc.lax.js b/.mocharc.lax.js new file mode 100644 index 000000000..8921b4a3f --- /dev/null +++ b/.mocharc.lax.js @@ -0,0 +1,5 @@ +const baseConfig = require('./.mocharc'); + +module.exports = Object.assign({}, baseConfig, { + ignore: [...baseConfig.ignore, './app/scripts/controllers/permissions/*.test.js'] +}); diff --git a/.storybook/actions/sb-send-action.js b/.storybook/actions/sb-send-action.js new file mode 100644 index 000000000..c1e66e41c --- /dev/null +++ b/.storybook/actions/sb-send-action.js @@ -0,0 +1,9 @@ +export const updateSendAsset = (type) => ({ + type: 'send/updateSendAsset', + payload: type, +}); + +export const updateSendStage = (stage) => ({ + type: 'send/updateSendStage', + payload: stage, +}); diff --git a/.storybook/initial-states/approval-screens/add-suggested-token.js b/.storybook/initial-states/approval-screens/add-suggested-token.js index 0b623e3f7..5cd10451c 100644 --- a/.storybook/initial-states/approval-screens/add-suggested-token.js +++ b/.storybook/initial-states/approval-screens/add-suggested-token.js @@ -1,65 +1,83 @@ -export const suggestedTokens = { - "0x6b175474e89094c44da98b954eedeac495271d0f": { - "address": "0x6b175474e89094c44da98b954eedeac495271d0f", - "symbol": "META", - "decimals": 18, - "image": "metamark.svg", - "unlisted": false +export const suggestedAssets = [ + { + asset: { + address: '0x6b175474e89094c44da98b954eedeac495271d0f', + symbol: 'META', + decimals: 18, + image: 'metamark.svg', + unlisted: false }, - "0xB8c77482e45F1F44dE1745F52C74426C631bDD52": { - "address": "0xB8c77482e45F1F44dE1745F52C74426C631bDD52", - "symbol": "0X", - "decimals": 18, - "image": "0x.svg", - "unlisted": false + }, + { + asset: { + 'address': '0xB8c77482e45F1F44dE1745F52C74426C631bDD52', + 'symbol': '0X', + 'decimals': 18, + 'image': '0x.svg', + 'unlisted': false }, - "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984": { - "address": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984", - "symbol": "AST", - "decimals": 18, - "image": "ast.png", - "unlisted": false + }, + { + asset: { + 'address': '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', + 'symbol': 'AST', + 'decimals': 18, + 'image': 'ast.png', + 'unlisted': false }, - "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2": { - "address": "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2", - "symbol": "BAT", - "decimals": 18, - "image": "BAT_icon.svg", - "unlisted": false + }, + { + asset: { + 'address': '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2', + 'symbol': 'BAT', + 'decimals': 18, + 'image': 'BAT_icon.svg', + 'unlisted': false }, - "0xe83cccfabd4ed148903bf36d4283ee7c8b3494d1": { - "address": "0xe83cccfabd4ed148903bf36d4283ee7c8b3494d1", - "symbol": "CVL", - "decimals": 18, - "image": "CVL_token.svg", - "unlisted": false + }, + { + asset: { + 'address': '0xe83cccfabd4ed148903bf36d4283ee7c8b3494d1', + 'symbol': 'CVL', + 'decimals': 18, + 'image': 'CVL_token.svg', + 'unlisted': false }, - "0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e": { - "address": "0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e", - "symbol": "GLA", - "decimals": 18, - "image": "gladius.svg", - "unlisted": false + }, + { + asset: { + 'address': '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', + 'symbol': 'GLA', + 'decimals': 18, + 'image': 'gladius.svg', + 'unlisted': false }, - "0x467Bccd9d29f223BcE8043b84E8C8B282827790F": { - "address": "0x467Bccd9d29f223BcE8043b84E8C8B282827790F", - "symbol": "GNO", - "decimals": 18, - "image": "gnosis.svg", - "unlisted": false + }, + { + asset: { + 'address': '0x467Bccd9d29f223BcE8043b84E8C8B282827790F', + 'symbol': 'GNO', + 'decimals': 18, + 'image': 'gnosis.svg', + 'unlisted': false }, - "0xff20817765cb7f73d4bde2e66e067e58d11095c2": { - "address": "0xff20817765cb7f73d4bde2e66e067e58d11095c2", - "symbol": "OMG", - "decimals": 18, - "image": "omg.jpg", - "unlisted": false + }, + { + asset: { + 'address': '0xff20817765cb7f73d4bde2e66e067e58d11095c2', + 'symbol': 'OMG', + 'decimals': 18, + 'image': 'omg.jpg', + 'unlisted': false }, - "0x8e870d67f660d95d5be530380d0ec0bd388289e1": { - "address": "0x8e870d67f660d95d5be530380d0ec0bd388289e1", - "symbol": "WED", - "decimals": 18, - "image": "wed.png", - "unlisted": false + }, + { + asset: { + 'address': '0x8e870d67f660d95d5be530380d0ec0bd388289e1', + 'symbol': 'WED', + 'decimals': 18, + 'image': 'wed.png', + 'unlisted': false }, - } \ No newline at end of file + }, +] diff --git a/.storybook/reducers/sb-history-reducer.js b/.storybook/reducers/sb-history-reducer.js new file mode 100644 index 000000000..a3d282a27 --- /dev/null +++ b/.storybook/reducers/sb-history-reducer.js @@ -0,0 +1,9 @@ +import testData from '../test-data'; + +const initialState = { ...testData.history }; +export default function historySBReducer(state = initialState, action) { + switch (action.type) { + default: + return state; + } +} diff --git a/.storybook/reducers/sb-send-reducer.js b/.storybook/reducers/sb-send-reducer.js new file mode 100644 index 000000000..c53cd1bb7 --- /dev/null +++ b/.storybook/reducers/sb-send-reducer.js @@ -0,0 +1,19 @@ +import testData from '../test-data'; + +const initialState = { ...testData.send }; +export default function sendSBReducer(state = initialState, action) { + switch (action.type) { + case 'send/updateSendStage': + return { + ...state, + stage: action.payload, + }; + case 'send/updateSendAsset': + return { + ...state, + asset: { ...state.asset, type: action.payload }, + }; + default: + return state; + } +} diff --git a/.storybook/test-data.js b/.storybook/test-data.js index 766196d2f..28c5c15c8 100644 --- a/.storybook/test-data.js +++ b/.storybook/test-data.js @@ -1,5 +1,3 @@ -import { TRANSACTION_STATUSES } from '../shared/constants/transaction'; - const state = { invalidCustomNetwork: { state: 'CLOSED', @@ -16,11 +14,109 @@ const state = { url: 'https://metamask.github.io/test-dapp/', }, metamask: { + tokenList: { + '0x6b175474e89094c44da98b954eedeac495271d0f': { + address: '0x6b175474e89094c44da98b954eedeac495271d0f', + symbol: 'META', + decimals: 18, + image: 'metamark.svg', + unlisted: false + }, + '0xB8c77482e45F1F44dE1745F52C74426C631bDD52': { + address: '0xB8c77482e45F1F44dE1745F52C74426C631bDD52', + symbol: '0X', + decimals: 18, + image: '0x.svg', + unlisted: false + }, + '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984': { + address: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984', + symbol: 'AST', + decimals: 18, + image: 'ast.png', + unlisted: false + }, + '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2': { + address: '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2', + symbol: 'BAT', + decimals: 18, + image: 'BAT_icon.svg', + unlisted: false + }, + '0xe83cccfabd4ed148903bf36d4283ee7c8b3494d1': { + address: '0xe83cccfabd4ed148903bf36d4283ee7c8b3494d1', + symbol: 'CVL', + decimals: 18, + image: 'CVL_token.svg', + unlisted: false + }, + '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e': { + address: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', + symbol: 'GLA', + decimals: 18, + image: 'gladius.svg', + unlisted: false + }, + '0x467Bccd9d29f223BcE8043b84E8C8B282827790F': { + address: '0x467Bccd9d29f223BcE8043b84E8C8B282827790F', + symbol: 'GNO', + decimals: 18, + image: 'gnosis.svg', + unlisted: false + }, + '0xff20817765cb7f73d4bde2e66e067e58d11095c2': { + address: '0xff20817765cb7f73d4bde2e66e067e58d11095c2', + symbol: 'OMG', + decimals: 18, + image: 'omg.jpg', + unlisted: false + }, + '0x8e870d67f660d95d5be530380d0ec0bd388289e1': { + address: '0x8e870d67f660d95d5be530380d0ec0bd388289e1', + symbol: 'WED', + decimals: 18, + image: 'wed.png', + unlisted: false + }, + }, networkDetails: { EIPS: { 1559: true, }, }, + gasFeeEstimates: '0x5208', + 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, + }, + accountArray: [ + { + name: 'This is a Really Long Account Name', + address: '0x64a845a5b02460acf8a3d84503b0d68d028b4bb4', + index: 0, + balance: '0x176e5b6f173ebe66', + }, + { + name: 'Account 2', + address: '0xb19ac54efa18cc3a14a5b821bfec73d284bf0c5e', + index: 1, + balance: '0x2d3142f5000', + }, + ], + connectedAccounts: ['0x64a845a5b02460acf8a3d84503b0d68d028b4bb4'], isInitialized: true, isUnlocked: true, isAccountMenuOpen: false, @@ -103,12 +199,6 @@ const state = { }, }, }, - recipient: { - address: '0x39a4e4Af7cCB654dB9500F258c64781c8FbD39F0', - nickname: 'John Doe', - error: '', - warning: '', - }, addresses: [ { address: '0x39a4e4Af7cCB654dB9500F258c64781c8FbD39F0', @@ -126,8 +216,13 @@ const state = { }, tokens: [ { - address: '0xaD6D458402F60fD3Bd25163575031ACDce07538D', - symbol: 'DAI', + address: '0xaD6D458402F60fD3Bd25163575031ACDce07538A', + symbol: 'DAA', + decimals: 18, + }, + { + address: '0xaD6D458402F60fD3Bd25163575031ACDce07538U', + symbol: 'DAU', decimals: 18, }, ], @@ -366,6 +461,24 @@ const state = { value: '0x9c2686', }, ], + [ + { + note: 'transactions/pending-tx-tracker#event: tx:block-update', + op: 'add', + path: '/firstRetryBlockNumber', + timestamp: 1629582711878, + value: '0x9c2686', + }, + ], + [ + { + note: 'txStateManager: setting status to confirmed', + op: 'replace', + path: '/status', + timestamp: 1629582721178, + value: 'confirmed', + }, + ], [ { note: 'txStateManager: setting status to confirmed', @@ -794,7 +907,7 @@ const state = { '0xaD6D458402F60fD3Bd25163575031ACDce07538D': './sai.svg', }, hiddenTokens: [], - suggestedTokens: {}, + suggestedAssets: {}, useNonceField: false, usePhishDetect: true, lostIdentities: {}, @@ -1165,6 +1278,10 @@ const state = { balance: '0x0', details: null, }, + gas: { error: 'gas' }, + amount: { + error: 'amount', + }, }, confirmTransaction: { txData: { diff --git a/CHANGELOG.md b/CHANGELOG.md index 41ddfdf69..1cfc62b0c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [10.3.0] +### Added +- [#12252](https://github.com/MetaMask/metamask-extension/pull/12252): Support type "0" transactions on EIP-1559 networks + +### Changed +- [#12100](https://github.com/MetaMask/metamask-extension/pull/12100): Use more descriptive language for "View on Etherscan" links +- [#12279](https://github.com/MetaMask/metamask-extension/pull/12279): Remove autofocus from gas limit input in the advanced gas popup +- [#12096](https://github.com/MetaMask/metamask-extension/pull/12096): Standardize appearance of buttons across the extension +- [#12304](https://github.com/MetaMask/metamask-extension/pull/12304): Remove duplicate Cancel button on the Send screen +- [#12331](https://github.com/MetaMask/metamask-extension/pull/12331): Update "off" color for toggle buttons +- [#12330](https://github.com/MetaMask/metamask-extension/pull/12330): Standardize truncation for address display throughout the extension +- [#12384](https://github.com/MetaMask/metamask-extension/pull/12384): Move "View on Etherscan" link to the top of the account menu + +### Fixed +- [#12229](https://github.com/MetaMask/metamask-extension/pull/12229): Fix whitespace validation issue for seed phrase entry (Restore Your Account) +- [#12230](https://github.com/MetaMask/metamask-extension/pull/12230): Fix gas control flicker on send screen when switching between EIP-1559 networks +- [#12186](https://github.com/MetaMask/metamask-extension/pull/12186): Fix grammatical issue with "Not connected to this site" message +- [#12381](https://github.com/MetaMask/metamask-extension/pull/12381): Fix width and padding of the hide token modal while in the popup view +- [#12339](https://github.com/MetaMask/metamask-extension/pull/11996): Fix 'BigNumber' app error when '0x' is supplied as the transaction value +- [#12339](https://github.com/MetaMask/metamask-extension/pull/12339): Correctly notify the inpage provider of current selected account on "unlock" events +- [#12405](https://github.com/MetaMask/metamask-extension/pull/12405): Fix allowance issue with WETH -> ETH Swaps + ## [10.2.2] ### Changed - [#12256](https://github.com/MetaMask/metamask-extension/pull/12256): Updating instruction step when Ledger app has contract data or blind signing setting disabled @@ -178,6 +200,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - [#11210](https://github.com/MetaMask/metamask-extension/pull/11210): Disable sending ERC-721 assets (NFTs) - [#11418](https://github.com/MetaMask/metamask-extension/pull/11418): Use network gas estimate for gas limits of simple sends on custom networks +### Fixed +- [#11361](https://github.com/MetaMask/metamask-extension/pull/11361): Ensures custom network balance displays correctly when no ticker symbol is provided, and ensure ticker symbol displays correctly after all network switches. +- [#10965](https://github.com/MetaMask/metamask-extension/pull/10965): Fixed bug that resulted in sends to some contracts being disabled on custom networks. + ## [9.7.1] ### Fixed - [#11426](https://github.com/MetaMask/metamask-extension/pull/11426): Fixed bug that broke transaction speed up and cancel, when attempting those actions immediately after opening MetaMask @@ -2498,7 +2524,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Uncategorized - Added the ability to restore accounts from seed words. -[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.2.2...HEAD +[Unreleased]: https://github.com/MetaMask/metamask-extension/compare/v10.3.0...HEAD +[10.3.0]: https://github.com/MetaMask/metamask-extension/compare/v10.2.2...v10.3.0 [10.2.2]: https://github.com/MetaMask/metamask-extension/compare/v10.2.1...v10.2.2 [10.2.1]: https://github.com/MetaMask/metamask-extension/compare/v10.2.0...v10.2.1 [10.2.0]: https://github.com/MetaMask/metamask-extension/compare/v10.1.1...v10.2.0 diff --git a/README.md b/README.md index 395a2562b..03c04fd23 100644 --- a/README.md +++ b/README.md @@ -46,9 +46,7 @@ To start the [React DevTools](https://github.com/facebook/react-devtools) and [R ### Running Unit Tests and Linting -Run unit tests and the linter with `yarn test`. - -To run just unit tests, run `yarn test:unit`. To run unit tests continuously with a file watcher, run `yarn watch`. +Run unit tests and the linter with `yarn test`. To run just unit tests, run `yarn test:unit`. You can run the linter by itself with `yarn lint`, and you can automatically fix some lint problems with `yarn lint:fix`. You can also run these two commands just on your local changes to save time with `yarn lint:changed` and `yarn lint:changed:fix` respectively. diff --git a/app/_locales/am/messages.json b/app/_locales/am/messages.json index 50fa63a2e..cd4ff6d0d 100644 --- a/app/_locales/am/messages.json +++ b/app/_locales/am/messages.json @@ -796,9 +796,6 @@ "revealSeedWordsDescription": { "message": "ማሰሺያዎችን ከቀየሩ ወይም ኮምፒዩተሮቸን ከአንድ ቦታ ወደ ሌላ ቦታ ካንቀሳቀሱ፣ ወደ መለያዎችዎ ለመድረስ ይህ የዘር ሐረግ ያስፈልግዎታል። ደህንነቱና ሚስጥራዊነቱ በተጠበቀ ቦታ ያስቀምጧቸው።" }, - "revealSeedWordsTitle": { - "message": "የዘር ሐረግ" - }, "revealSeedWordsWarning": { "message": "እነዚህ ቃላት ሁሉንም መለያዎችዎን ለመስረቅ ሊውሉ ይችላሉ።" }, @@ -835,9 +832,6 @@ "searchTokens": { "message": "ተለዋጭ ስሞችን ፈልግ" }, - "secretBackupPhrase": { - "message": "ሚስጥራዊ የመጠባበቂያ ምዕራፍ" - }, "secretBackupPhraseDescription": { "message": "ሚስጥራዊ የመጠባበቂያ ሐረግዎ መለያዎን መጠባበቂያ ለመያዝና ወደነበረበት ለመመለስ ቀላል ያደርገዋል።" }, @@ -1124,21 +1118,9 @@ "viewContact": { "message": "ዕውቂያን ይመልከቱ" }, - "viewOnCustomBlockExplorer": { - "message": "በ $1ይመልከቱ" - }, - "viewOnEtherscan": { - "message": "በ Etherscan ላይ ይመልከቱ" - }, - "viewinExplorer": { - "message": "በኤክስፕሎረር ተመልከት" - }, "visitWebSite": { "message": "ድረ ገጻችንን ይጎብኙ" }, - "walletSeed": { - "message": "የቋት ዘር" - }, "welcome": { "message": "ወደ MetaMask እንኳን ደህና መጡ" }, diff --git a/app/_locales/ar/messages.json b/app/_locales/ar/messages.json index 5f37cb4e1..46f05e1ef 100644 --- a/app/_locales/ar/messages.json +++ b/app/_locales/ar/messages.json @@ -792,9 +792,6 @@ "revealSeedWordsDescription": { "message": "إذا كنت تنوي تغيير المتصفحات أو نقل أجهزة الكمبيوتر في أي وقت، فسوف تحتاج إلى عبارة الأمان هذه للوصول إلى حساباتك. احفظها في مكان آمن وسري." }, - "revealSeedWordsTitle": { - "message": "عبارة الأمان" - }, "revealSeedWordsWarning": { "message": "يمكن استخدام هذه الكلمات لسرقة جميع حساباتك." }, @@ -831,9 +828,6 @@ "searchTokens": { "message": "البحث عن العملات الرمزية" }, - "secretBackupPhrase": { - "message": "الجملة الاحتياطية السرية" - }, "secretBackupPhraseDescription": { "message": "تجعل عبارة النسخ الاحتياطي السرية الخاصة بك من السهل إجراء نسخ احتياطي واستعادة حسابك." }, @@ -1120,21 +1114,9 @@ "viewContact": { "message": "عرض جهة الاتصال" }, - "viewOnCustomBlockExplorer": { - "message": "عرض في $1" - }, - "viewOnEtherscan": { - "message": "عرضه على Etherscan" - }, - "viewinExplorer": { - "message": "عرض في متصفح Explorer" - }, "visitWebSite": { "message": "قم بزيارة موقعنا على الإنترنت" }, - "walletSeed": { - "message": "بذرة المحفظة" - }, "welcome": { "message": "مرحباً بك في MetaMask" }, diff --git a/app/_locales/bg/messages.json b/app/_locales/bg/messages.json index 57196e3b3..85db5cf66 100644 --- a/app/_locales/bg/messages.json +++ b/app/_locales/bg/messages.json @@ -795,9 +795,6 @@ "revealSeedWordsDescription": { "message": "Ако някога смените браузъра или компютъра си, тази ключова фраза ще Ви трябва за достъп до Вашите акаунти. Запазете я някъде на сигурно и тайно място." }, - "revealSeedWordsTitle": { - "message": "Фраза зародиш" - }, "revealSeedWordsWarning": { "message": "Тези думи могат да бъдат използвани за кражба на всички ваши акаунти." }, @@ -834,9 +831,6 @@ "searchTokens": { "message": "Търсене на маркери" }, - "secretBackupPhrase": { - "message": "Тайна резервна фраза" - }, "secretBackupPhraseDescription": { "message": "Вашата тайна резервна фраза улеснява архивирането и възстановяването на акаунта ви." }, @@ -1123,21 +1117,9 @@ "viewContact": { "message": "Преглед на контакта" }, - "viewOnCustomBlockExplorer": { - "message": "Преглед на $1" - }, - "viewOnEtherscan": { - "message": "Преглед на Etherscan" - }, - "viewinExplorer": { - "message": "Преглед в Explorer" - }, "visitWebSite": { "message": "Посетете нашият уеб сайт" }, - "walletSeed": { - "message": "Начална фраза за портфейл " - }, "welcome": { "message": "Добре дошли в MetaMask" }, diff --git a/app/_locales/bn/messages.json b/app/_locales/bn/messages.json index 19c45effd..92f31381d 100644 --- a/app/_locales/bn/messages.json +++ b/app/_locales/bn/messages.json @@ -799,9 +799,6 @@ "revealSeedWordsDescription": { "message": "আপনি কখনও ব্রাউজার পরিবর্তন করলে বা এক কম্পিউটার থেকে অন্য কম্পিউটারে গেলে, আপনাকে আপনার অ্যাকাউন্ট অ্যাক্সেস করার জন্য এই সীড ফ্রেজটি লাগবে। সেগুলি নিরাপদ ও গোপনীয় কোনো স্থানে সংরক্ষণ করুন। " }, - "revealSeedWordsTitle": { - "message": "সীড ফ্রেজ" - }, "revealSeedWordsWarning": { "message": "আপনার সমস্ত অ্যাকাউন্ট চুরি করতে এই শব্দগুলি ব্যবহার করা যাবে।" }, @@ -838,9 +835,6 @@ "searchTokens": { "message": "টোকেনগুলি অনুসন্ধান করুন" }, - "secretBackupPhrase": { - "message": "গোপন ব্যাকআপ ফ্রেজ" - }, "secretBackupPhraseDescription": { "message": "আপনার গোপন বাক্যাংশ আপনার অ্যাকাউন্ট ব্যাকআপ এবং রিস্টোর করা সহজতর করে তোলে।" }, @@ -1127,21 +1121,9 @@ "viewContact": { "message": "পরিচিতি দেখুন" }, - "viewOnCustomBlockExplorer": { - "message": "$1 এ দেখুন" - }, - "viewOnEtherscan": { - "message": "Etherscan দেখুন" - }, - "viewinExplorer": { - "message": "এক্সপ্লোরারে দেখুন" - }, "visitWebSite": { "message": "আমাদের ওয়েবসাইট দেখুন" }, - "walletSeed": { - "message": "ওয়ালেট সীড" - }, "welcome": { "message": "MetaMask এ স্বাগতম" }, diff --git a/app/_locales/ca/messages.json b/app/_locales/ca/messages.json index fe3311ead..f0c688d8d 100644 --- a/app/_locales/ca/messages.json +++ b/app/_locales/ca/messages.json @@ -777,9 +777,6 @@ "revealSeedWordsDescription": { "message": "Si mai canvies el navegador o l'ordinador, necessitaràs aquesta frase de recuperació per accedir als teus comptes. Guarda-la a un lloc segur i secret." }, - "revealSeedWordsTitle": { - "message": "Frase de Recuperació" - }, "revealSeedWordsWarning": { "message": "Aquestes paraules poden ser utilitzades per a robar tots els teus comptes." }, @@ -816,9 +813,6 @@ "searchTokens": { "message": "Tokens per cercar" }, - "secretBackupPhrase": { - "message": "Frase de recuperació secreta" - }, "secretBackupPhraseDescription": { "message": "La teva frase de recuperació secreta facilita la còpia de seguretat i la recuperació del teu compte." }, @@ -1096,21 +1090,9 @@ "viewContact": { "message": "Veure Contacte" }, - "viewOnCustomBlockExplorer": { - "message": "Mostra a $1" - }, - "viewOnEtherscan": { - "message": "Veure a Etherscan" - }, - "viewinExplorer": { - "message": "Mostra a Explorer" - }, "visitWebSite": { "message": "Visita el nostre lloc web" }, - "walletSeed": { - "message": "Cartera de seeds" - }, "welcome": { "message": "Benvingut a MetaMask" }, diff --git a/app/_locales/cs/messages.json b/app/_locales/cs/messages.json index 5ff4fa58b..8a9be7f3a 100644 --- a/app/_locales/cs/messages.json +++ b/app/_locales/cs/messages.json @@ -432,9 +432,6 @@ "visitWebSite": { "message": "Navštivte naši stránku" }, - "walletSeed": { - "message": "Klíčová fráze peněženky" - }, "welcome": { "message": "Vítejte v MetaMask" }, diff --git a/app/_locales/da/messages.json b/app/_locales/da/messages.json index c4c147bda..11b79bc9a 100644 --- a/app/_locales/da/messages.json +++ b/app/_locales/da/messages.json @@ -780,9 +780,6 @@ "revealSeedWordsDescription": { "message": "Hvis du nogensinde skifter browsere eller flytter computere, har du brug for denne backupsætning for at få adgang til dine konti. Gem den et sted sikkert og hemmeligt." }, - "revealSeedWordsTitle": { - "message": "Backupsætning" - }, "revealSeedWordsWarning": { "message": "Disse ord kan bruges til at stjæle alle dine konti." }, @@ -819,9 +816,6 @@ "searchTokens": { "message": "Søg efter tokens" }, - "secretBackupPhrase": { - "message": "Hemmelig backup-sætning" - }, "secretBackupPhraseDescription": { "message": "Din hemmelige backup-sætning gør det nemt at lave backup og gendanne din konto." }, @@ -1096,21 +1090,9 @@ "viewContact": { "message": "Vis kontakt" }, - "viewOnCustomBlockExplorer": { - "message": "Se på $1" - }, - "viewOnEtherscan": { - "message": "Se på Etherscan" - }, - "viewinExplorer": { - "message": "Vis i stifinder" - }, "visitWebSite": { "message": "Besøg vores webside" }, - "walletSeed": { - "message": "Tegnebogs-seed" - }, "welcome": { "message": "Velkommen til MetaMask" }, diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index d6e52d78b..f5dd97621 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -768,9 +768,6 @@ "revealSeedWordsDescription": { "message": "Wenn Sie einmal Ihren Browser oder Computer wechseln, benötigen Sie diesen Seed-Schlüssel, um auf Ihre Konten zuzugreifen. Bewahren Sie ihn an einem sicheren und geheimen Ort auf." }, - "revealSeedWordsTitle": { - "message": "Mnemonische Phrase" - }, "revealSeedWordsWarning": { "message": "Bitte niemals deine Seed-Wörterfolge an einem öffentlichen Ort kenntlich machen. Mit diesen Wörtern können alle deine Accounts gestohlen werden." }, @@ -807,9 +804,6 @@ "searchTokens": { "message": "Token suchen" }, - "secretBackupPhrase": { - "message": "Geheimer Backup-Schlüssel" - }, "secretBackupPhraseDescription": { "message": "Mit Ihrem geheimen Backup-Schlüssel können Sie Ihr Konto ganz einfach sichern und wiederherstellen." }, @@ -1087,15 +1081,6 @@ "viewContact": { "message": "Kontakt anzeigen" }, - "viewOnCustomBlockExplorer": { - "message": "Für $1 ansehen" - }, - "viewOnEtherscan": { - "message": "Auf Etherscan ansehen" - }, - "viewinExplorer": { - "message": "Im Explorer anzeigen" - }, "visitWebSite": { "message": "Gehe zu unserer Webseite" }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index e7239b9ae..15071eab3 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -796,9 +796,6 @@ "revealSeedWordsDescription": { "message": "Εάν αλλάξετε ποτέ προγράμματα περιήγησης ή μετακινήσετε υπολογιστές, θα χρειαστείτε αυτήν τη φράση φύτρου για να αποκτήσετε πρόσβαση στους λογαριασμούς σας. Αποθηκεύστε την κάπου με ασφάλεια και μυστικότητα." }, - "revealSeedWordsTitle": { - "message": "Φράση Επαναφοράς " - }, "revealSeedWordsWarning": { "message": "Αυτές οι λέξεις μπορούν να χρησιμοποιηθούν για να κλαπούν όλοι οι λογαριασμοί σας." }, @@ -835,9 +832,6 @@ "searchTokens": { "message": "Αναζήτηση Tokens" }, - "secretBackupPhrase": { - "message": "Μυστική Φράση Αντιγράφου Ασφαλείας" - }, "secretBackupPhraseDescription": { "message": "Η μυστική φράση δημιουργίας αντιγράφων ασφαλείας σας διευκολύνει να δημιουργήσετε αντίγραφα ασφαλείας και να επαναφέρετε τον λογαριασμού σας." }, @@ -1121,21 +1115,9 @@ "viewContact": { "message": "Εμφάνιση Επαφής" }, - "viewOnCustomBlockExplorer": { - "message": "Προβολή σε $1" - }, - "viewOnEtherscan": { - "message": "Προβολή στο Etherscan" - }, - "viewinExplorer": { - "message": "Προβολή στον Εξερευνητή" - }, "visitWebSite": { "message": "Επισκεφθείτε τον ιστότοπό μας" }, - "walletSeed": { - "message": "Σπόρος Πορτοφολιού" - }, "welcome": { "message": "Καλώς ήλθατε στο MetaMask" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index e892f5040..b7788b7fd 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -259,6 +259,22 @@ "betaWelcome": { "message": "Welcome to MetaMask Beta" }, + "blockExplorerAccountAction": { + "message": "Account", + "description": "This is used with viewOnEtherscan and viewInExplorer e.g View Account in Explorer" + }, + "blockExplorerAssetAction": { + "message": "Asset", + "description": "This is used with viewOnEtherscan and viewInExplorer e.g View Asset in Explorer" + }, + "blockExplorerSwapAction": { + "message": "Swap", + "description": "This is used with viewOnEtherscan e.g View Swap on Etherscan" + }, + "blockExplorerTransactionAction": { + "message": "Transaction", + "description": "This is used with viewOnCustomBlockExplorer and viewOnEtherscan e.g View Transaction on Etherscan" + }, "blockExplorerUrl": { "message": "Block Explorer URL" }, @@ -341,12 +357,12 @@ "confirmPassword": { "message": "Confirm password" }, + "confirmRecoveryPhrase": { + "message": "Confirm Secret Recovery Phrase" + }, "confirmSecretBackupPhrase": { "message": "Confirm your Secret Recovery Phrase" }, - "confirmSeedPhrase": { - "message": "Confirm Secret Recovery Phrase" - }, "confirmed": { "message": "Confirmed" }, @@ -405,7 +421,7 @@ "message": "You have 1 account connected to this site." }, "connectedAccountsEmptyDescription": { - "message": "MetaMask is not connected this site. To connect to a web3 site, find the connect button on their site." + "message": "MetaMask is not connected to this site. To connect to a web3 site, find and click the connect button." }, "connectedSites": { "message": "Connected sites" @@ -919,6 +935,9 @@ "message": "File import not working? Click here!", "description": "Helps user import their account from a JSON file" }, + "followUsOnTwitter": { + "message": "Follow us on Twitter" + }, "forbiddenIpfsGateway": { "message": "Forbidden IPFS Gateway: Please specify a CID gateway" }, @@ -1026,6 +1045,9 @@ "getStarted": { "message": "Get Started" }, + "goBack": { + "message": "Go Back" + }, "goerli": { "message": "Goerli Test Network" }, @@ -1097,6 +1119,16 @@ "message": "or $1", "description": "$1 represents the text from `importAccountLinkText` as a link" }, + "importExistingWalletDescription": { + "message": "Enter your Secret Recovery Phrase (aka Seed Phrase) that you were given when you created your wallet. $1", + "description": "$1 is the words 'Learn More' from key 'learnMore', separated here so that it can be added as a link" + }, + "importExistingWalletTitle": { + "message": "Import existing wallet with Secret Recovery Phrase" + }, + "importMyWallet": { + "message": "Import My Wallet" + }, "importTokenQuestion": { "message": "Import token?" }, @@ -1191,6 +1223,9 @@ "ipfsGatewayDescription": { "message": "Enter the URL of the IPFS CID gateway to use for ENS content resolution." }, + "jsDeliver": { + "message": "jsDeliver" + }, "jsonFile": { "message": "JSON File", "description": "format for importing an account" @@ -1597,10 +1632,24 @@ "on": { "message": "On" }, + "onboardingCreateWallet": { + "message": "Create a new wallet" + }, + "onboardingImportWallet": { + "message": "Import an existing wallet" + }, "onboardingReturnNotice": { "message": "\"$1\" will close this tab and direct back to $2", "description": "Return the user to the site that initiated onboarding" }, + "onboardingShowIncomingTransactionsDescription": { + "message": "Showing incoming transactions in your wallet relies on communication with $1. Etherscan will have access to your Ethereum address and your IP address. View $2.", + "description": "$1 is a clickable link with text defined by the 'etherscan' key. $2 is a clickable link with text defined by the 'privacyMsg' key." + }, + "onboardingUsePhishingDetectionDescription": { + "message": "Phishing detection alerts rely on communication with $1. jsDeliver will have access to your IP address. View $2.", + "description": "The $1 is the word 'jsDeliver', from key 'jsDeliver' and $2 is the words Privacy Policy from key 'privacyMsg', both separated here so that it can be wrapped as a link" + }, "onlyAddTrustedNetworks": { "message": "A malicious network provider can lie about the state of the blockchain and record your network activity. Only add custom networks you trust." }, @@ -1763,6 +1812,9 @@ "rejected": { "message": "Rejected" }, + "remember": { + "message": "Remember:" + }, "remindMeLater": { "message": "Remind me later" }, @@ -1812,9 +1864,6 @@ "revealSeedWordsDescription": { "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": "Secret Recovery Phrase" - }, "revealSeedWordsWarning": { "message": "These words can be used to steal all your accounts." }, @@ -1857,9 +1906,6 @@ "searchTokens": { "message": "Search Tokens" }, - "secretBackupPhrase": { - "message": "Secret Recovery Phrase" - }, "secretBackupPhraseDescription": { "message": "Your Secret Recovery Phrase makes it easy to back up and restore your account." }, @@ -1869,6 +1915,9 @@ "secretPhrase": { "message": "Only the first account on this wallet will auto load. After completing this process, to add additional accounts, click the drop down menu, then select Create Account." }, + "secretRecoveryPhrase": { + "message": "Secret Recovery Phrase" + }, "secureWallet": { "message": "Secure Wallet" }, @@ -1884,6 +1933,12 @@ "seedPhraseEnterMissingWords": { "message": "Confirm Secret Recovery Phrase" }, + "seedPhraseIntroNotRecommendedButtonCopy": { + "message": "Remind me later (not recommended)" + }, + "seedPhraseIntroRecommendedButtonCopy": { + "message": "Secure my wallet (recommended)" + }, "seedPhraseIntroSidebarBulletFour": { "message": "Write down and store in multiple secret places." }, @@ -1897,13 +1952,13 @@ "message": "Store in a bank vault." }, "seedPhraseIntroSidebarCopyOne": { - "message": "Your Secret Recovery Phrase is the “master key” to your wallet and funds." + "message": "Your Secret Recovery Phrase is a 12-word phrase that is the “master key” to your wallet and your funds" }, "seedPhraseIntroSidebarCopyThree": { - "message": "If someone asks for your Secret Recovery Phrase, they are most likely trying to scam you." + "message": "If someone asks for your recovery phrase they are likely trying to scam you and steal your wallet funds" }, "seedPhraseIntroSidebarCopyTwo": { - "message": "Never, ever share your Secret Recovery Phrase, even with MetaMask!" + "message": "Never, ever share your Secret Recovery Phrase, not even with MetaMask!" }, "seedPhraseIntroSidebarTitleOne": { "message": "What is a Secret Recovery Phrase?" @@ -1995,6 +2050,12 @@ "separateEachWord": { "message": "Separate each word with a single space" }, + "setAdvancedPrivacySettings": { + "message": "Set advanced privacy settings" + }, + "setAdvancedPrivacySettingsDetails": { + "message": "MetaMask uses these trusted third-party services to enhance product usability and safety." + }, "settings": { "message": "Settings" }, @@ -2055,6 +2116,15 @@ "signed": { "message": "Signed" }, + "skip": { + "message": "Skip" + }, + "skipAccountSecurity": { + "message": "Skip Account Security?" + }, + "skipAccountSecurityDetails": { + "message": "I understand that until I back up my Secret Recovery Phrase, I may lose my accounts and all of their assets." + }, "slow": { "message": "Slow" }, @@ -2684,6 +2754,9 @@ "tryAgain": { "message": "Try again" }, + "turnOnTokenDetection": { + "message": "Turn on Token Detection" + }, "typePassword": { "message": "Type your MetaMask password" }, @@ -2784,13 +2857,16 @@ "message": "View More" }, "viewOnCustomBlockExplorer": { - "message": "View at $1" + "message": "View $1 at $2", + "description": "$1 is the action type. e.g (Account, Transaction, Swap) and $2 is the Custom Block Exporer URL" }, "viewOnEtherscan": { - "message": "View on Etherscan" + "message": "View $1 on Etherscan", + "description": "$1 is the action type. e.g (Account, Transaction, Swap)" }, "viewinExplorer": { - "message": "View in Explorer" + "message": "View $1 in Explorer", + "description": "$1 is the action type. e.g (Account, Transaction, Swap)" }, "visitWebSite": { "message": "Visit our web site" @@ -2798,8 +2874,25 @@ "walletConnectionGuide": { "message": "our hardware wallet connection guide" }, - "walletSeed": { - "message": "Secret Recovery Phrase" + "walletCreationSuccessDetail": { + "message": "You’ve successfully protected your wallet. Keep your Secret Recovery Phrase safe and secret -- it’s your responsibility!" + }, + "walletCreationSuccessReminder1": { + "message": "MetaMask can’t recover your Secret Recovery Phrase." + }, + "walletCreationSuccessReminder2": { + "message": "MetaMask will never ask you for your Secret Recovery Phrase." + }, + "walletCreationSuccessReminder3": { + "message": "$1 with anyone or risk your funds being stolen", + "description": "$1 is separated as walletCreationSuccessReminder3BoldSection so that we can bold it" + }, + "walletCreationSuccessReminder3BoldSection": { + "message": "Never share your Secret Recovery Phrase", + "description": "This string is localized separately from walletCreationSuccessReminder3 so that we can bold it" + }, + "walletCreationSuccessTitle": { + "message": "Wallet creation successful" }, "walletSeedRestore": { "message": "Wallet Secret Recovery Phrase" @@ -2814,6 +2907,24 @@ "welcomeBack": { "message": "Welcome Back!" }, + "welcomeExploreDescription": { + "message": "Store, send and spend crypto currencies and assets." + }, + "welcomeExploreTitle": { + "message": "Explore decentralized apps" + }, + "welcomeLoginDescription": { + "message": "Use your MetaMask to login to decentralized apps - no signup needed." + }, + "welcomeLoginTitle": { + "message": "Say hello to your wallet" + }, + "welcomeToMetaMask": { + "message": "Let's get started" + }, + "welcomeToMetaMaskIntro": { + "message": "Trusted by millions, MetaMask is a secure wallet making the world of web3 accessible to all." + }, "whatsNew": { "message": "What's new", "description": "This is the title of a popup that gives users notifications about new features and updates to MetaMask." diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index b799d2d59..f98631f54 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -1527,9 +1527,6 @@ "revealSeedWordsDescription": { "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 secreta de recuperación" - }, "revealSeedWordsWarning": { "message": "Estas palabras pueden usarse para robar todas sus cuentas." }, @@ -1572,9 +1569,6 @@ "searchTokens": { "message": "Buscar tokens" }, - "secretBackupPhrase": { - "message": "Frase secreta de respaldo" - }, "secretBackupPhraseDescription": { "message": "La frase secreta de respaldo facilita la creación de una copia de seguridad y la restauración de su cuenta." }, @@ -2386,24 +2380,12 @@ "viewMore": { "message": "Ver más" }, - "viewOnCustomBlockExplorer": { - "message": "Ver en $1" - }, - "viewOnEtherscan": { - "message": "Ver en Etherscan" - }, - "viewinExplorer": { - "message": "Ver en el explorador" - }, "visitWebSite": { "message": "Visite nuestro sitio web" }, "walletConnectionGuide": { "message": "nuestra guía de conexión de la cartera de hardware" }, - "walletSeed": { - "message": "Frase secreta de recuperación" - }, "walletSeedRestore": { "message": "Frase secreta de recuperación de la cartera" }, diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index b799d2d59..f98631f54 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -1527,9 +1527,6 @@ "revealSeedWordsDescription": { "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 secreta de recuperación" - }, "revealSeedWordsWarning": { "message": "Estas palabras pueden usarse para robar todas sus cuentas." }, @@ -1572,9 +1569,6 @@ "searchTokens": { "message": "Buscar tokens" }, - "secretBackupPhrase": { - "message": "Frase secreta de respaldo" - }, "secretBackupPhraseDescription": { "message": "La frase secreta de respaldo facilita la creación de una copia de seguridad y la restauración de su cuenta." }, @@ -2386,24 +2380,12 @@ "viewMore": { "message": "Ver más" }, - "viewOnCustomBlockExplorer": { - "message": "Ver en $1" - }, - "viewOnEtherscan": { - "message": "Ver en Etherscan" - }, - "viewinExplorer": { - "message": "Ver en el explorador" - }, "visitWebSite": { "message": "Visite nuestro sitio web" }, "walletConnectionGuide": { "message": "nuestra guía de conexión de la cartera de hardware" }, - "walletSeed": { - "message": "Frase secreta de recuperación" - }, "walletSeedRestore": { "message": "Frase secreta de recuperación de la cartera" }, diff --git a/app/_locales/et/messages.json b/app/_locales/et/messages.json index f44cca3d0..de6d85299 100644 --- a/app/_locales/et/messages.json +++ b/app/_locales/et/messages.json @@ -789,9 +789,6 @@ "revealSeedWordsDescription": { "message": "Kui vahetate veebilehitsejat või arvutit, vajate oma kontodele ligipääsemiseks seemnefraasi. Hoidke seda turvalises ja salajases kohas." }, - "revealSeedWordsTitle": { - "message": "Seemnefraas" - }, "revealSeedWordsWarning": { "message": "Neid sõnu saab kasutada kõigi teie kontode tühjendamiseks." }, @@ -828,9 +825,6 @@ "searchTokens": { "message": "Lubade otsimine" }, - "secretBackupPhrase": { - "message": "Salajane varundusfraas" - }, "secretBackupPhraseDescription": { "message": "Teie salajane varundusfraas hõlbustab konto varundamist ja taastamist." }, @@ -1117,21 +1111,9 @@ "viewContact": { "message": "Kuva kontakt" }, - "viewOnCustomBlockExplorer": { - "message": "Vaata $1" - }, - "viewOnEtherscan": { - "message": "Kuva Etherscanil" - }, - "viewinExplorer": { - "message": "Kuva Exploreris" - }, "visitWebSite": { "message": "Külastage meie veebilehte" }, - "walletSeed": { - "message": "Rahakoti seeme" - }, "welcome": { "message": "Tere tulemast MetaMaski" }, diff --git a/app/_locales/fa/messages.json b/app/_locales/fa/messages.json index 96b9ece48..b22b198c5 100644 --- a/app/_locales/fa/messages.json +++ b/app/_locales/fa/messages.json @@ -799,9 +799,6 @@ "revealSeedWordsDescription": { "message": "در صورتیکه شما معمولًا براوزر ها را تغییر داده یا کمپیوتر ها را انتقال میدهید، شما این عبارت آغازین را نیاز خواهید داشت تا به حساب های تان دسترسی داشته باشید. آنها را در یکجای مصؤن و مخفی نگهدارید." }, - "revealSeedWordsTitle": { - "message": "عبارت بازیاب" - }, "revealSeedWordsWarning": { "message": "این کلمات را میتوان جهت سرقت همه حساب های تان استفاده نمود." }, @@ -838,9 +835,6 @@ "searchTokens": { "message": "رمزیاب های جستجو" }, - "secretBackupPhrase": { - "message": "عبارت مخفی پشتیبان" - }, "secretBackupPhraseDescription": { "message": "عبارت مخفی پشتیبان تان نسخه پشتیبان و دوباره سازی حساب را تسهیل میسازد." }, @@ -1127,21 +1121,9 @@ "viewContact": { "message": "مشاهده تماس" }, - "viewOnCustomBlockExplorer": { - "message": "مشاهده در 1$1" - }, - "viewOnEtherscan": { - "message": "مشاهده در ایترسکن" - }, - "viewinExplorer": { - "message": "مشاهده در براوزر" - }, "visitWebSite": { "message": "از وب سایت ما دیدن نمایید" }, - "walletSeed": { - "message": "بازیاب کیف" - }, "welcome": { "message": "به MetaMask خوش آمدید" }, diff --git a/app/_locales/fi/messages.json b/app/_locales/fi/messages.json index 2baae1b63..857e496e2 100644 --- a/app/_locales/fi/messages.json +++ b/app/_locales/fi/messages.json @@ -796,9 +796,6 @@ "revealSeedWordsDescription": { "message": "Mikäli vaihdat jossakin vaiheessa selainta tai tietokonetta, tarvitset tämän salaustekstin tiliesi käyttämiseen. Tallenna se johonkin turvalliseen ja salaiseen paikkaan." }, - "revealSeedWordsTitle": { - "message": "Juurilause" - }, "revealSeedWordsWarning": { "message": "Näitä sanoja voidaan käyttää kaikkien tiliesi ryöstämiseen." }, @@ -835,9 +832,6 @@ "searchTokens": { "message": "Hae tietueita" }, - "secretBackupPhrase": { - "message": "Salainen varmuuskopiolause" - }, "secretBackupPhraseDescription": { "message": "Salainen varmistuslauseesi tekee varmuuskopioinnista ja tilisi palauttamisesta helppoa." }, @@ -1124,21 +1118,9 @@ "viewContact": { "message": "Näytä yhteyshenkilö" }, - "viewOnCustomBlockExplorer": { - "message": "Tarkastele kohdassa $1" - }, - "viewOnEtherscan": { - "message": "Näytä Etherscanissa" - }, - "viewinExplorer": { - "message": "Tarkastele Explorerissa" - }, "visitWebSite": { "message": "Vieraile verkkosivustollamme" }, - "walletSeed": { - "message": "Lompakon siemen" - }, "welcome": { "message": "Tervetuloa MetaMaskiin" }, diff --git a/app/_locales/fil/messages.json b/app/_locales/fil/messages.json index a472c8bd0..235694a2f 100644 --- a/app/_locales/fil/messages.json +++ b/app/_locales/fil/messages.json @@ -1021,15 +1021,6 @@ "viewContact": { "message": "Tingnan ang Contact" }, - "viewOnCustomBlockExplorer": { - "message": "Tingnan sa $1" - }, - "viewOnEtherscan": { - "message": "Tingnan sa Etherscan" - }, - "viewinExplorer": { - "message": "Tingnan sa Explorer" - }, "visitWebSite": { "message": "Bisitahin ang aming web site" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index f43a8f73f..709ecbd83 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -781,9 +781,6 @@ "revealSeedWordsDescription": { "message": "Si jamais vous changez de navigateur ou d'ordinateur, vos aurez besoin de cette phrase seed pour accéder à vos comptes. Sauvegardez la quelque part de sûr et secret." }, - "revealSeedWordsTitle": { - "message": "Phrase Seed" - }, "revealSeedWordsWarning": { "message": "Ces mots peuvent être utilisés pour voler tous vos comptes." }, @@ -820,9 +817,6 @@ "searchTokens": { "message": "Rechercher des jetons" }, - "secretBackupPhrase": { - "message": "Phrase de sauvegarde secrète" - }, "secretBackupPhraseDescription": { "message": "Votre phrase de sauvegarde secrète facilite la sauvegarde et la restauration de votre compte." }, @@ -1103,21 +1097,9 @@ "viewContact": { "message": "Voir contact" }, - "viewOnCustomBlockExplorer": { - "message": "Afficher sur $1" - }, - "viewOnEtherscan": { - "message": "Voir sur Etherscan" - }, - "viewinExplorer": { - "message": "Afficher dans Explorer" - }, "visitWebSite": { "message": "Visitez notre site web" }, - "walletSeed": { - "message": "Seed du portefeuille" - }, "welcome": { "message": "Bienvenue dans la Beta de MetaMask" }, diff --git a/app/_locales/he/messages.json b/app/_locales/he/messages.json index 3ddc4e4fb..f080f1e66 100644 --- a/app/_locales/he/messages.json +++ b/app/_locales/he/messages.json @@ -796,9 +796,6 @@ "revealSeedWordsDescription": { "message": "אם בעתיד תחליף/י דפדפנים או תעביר/י מחשבים, תצטרך/י seed phrase זה כדי לקבל גישה לחשבונות שלך. יש לשמור אותם במקום בטוח וסודי." }, - "revealSeedWordsTitle": { - "message": "צירוף גרעין (Seed Phrase)" - }, "revealSeedWordsWarning": { "message": "במילים אלה עלול להיעשות שימוש כדי לגנוב את כל חשבונותיך." }, @@ -832,9 +829,6 @@ "searchTokens": { "message": "חיפוש טוקנים" }, - "secretBackupPhrase": { - "message": "צירוף מילים סודי לגיבוי" - }, "secretBackupPhraseDescription": { "message": "עם צירוף מילים סודי לגיבוי קל יותר לגבות ולשחזר את החשבון שלך." }, @@ -1121,21 +1115,9 @@ "viewContact": { "message": "הצג איש קשר" }, - "viewOnCustomBlockExplorer": { - "message": "הצג ב- $1" - }, - "viewOnEtherscan": { - "message": "הצג ב-Etherscan" - }, - "viewinExplorer": { - "message": "הצג באקספלורר" - }, "visitWebSite": { "message": "בקר/י באתר שלנו" }, - "walletSeed": { - "message": "גרעין (Seed) ארנק" - }, "welcome": { "message": "ברוכים הבאים ל- MetaMask" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index de8052516..18147a08b 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -1527,9 +1527,6 @@ "revealSeedWordsDescription": { "message": "यदि आप कभी ब्राउज़र बदलते हैं या कंप्यूटर को स्थानांतरित करते हैं, तो आपको अपने खातों तक पहुँचने के लिए इस गुप्त रिकवरी फ्रेज़ की आवश्यकता होगी। उन्हें कहीं सुरक्षित और गोपनीय तरीके से सहेजें।" }, - "revealSeedWordsTitle": { - "message": "गुप्त रिकवरी फ्रेज़" - }, "revealSeedWordsWarning": { "message": "इन शब्दों का उपयोग आपके सभी खातों को चुराने के लिए किया जा सकता है।" }, @@ -1572,9 +1569,6 @@ "searchTokens": { "message": "टोकन खोजें" }, - "secretBackupPhrase": { - "message": "गुप्त बैकअप वाक्यांश" - }, "secretBackupPhraseDescription": { "message": "आपका गुप्त बैकअप वाक्यांश आपके खाते का बैकअप लेना और पुनर्स्थापित करना आसान बनाता है।" }, @@ -2386,24 +2380,12 @@ "viewMore": { "message": "और देखें" }, - "viewOnCustomBlockExplorer": { - "message": "$1 पर देखें" - }, - "viewOnEtherscan": { - "message": "Etherscan पर देखें" - }, - "viewinExplorer": { - "message": "एक्सप्लोरर में देखें" - }, "visitWebSite": { "message": "हमारी वेबसाइट पर जाएँ" }, "walletConnectionGuide": { "message": "हमारी हार्डवेयर वॉलेट कनेक्शन गाइड" }, - "walletSeed": { - "message": "गुप्त रिकवरी फ्रेज़" - }, "walletSeedRestore": { "message": "वॉलेट का गुप्त रिकवरी फ्रेज़" }, diff --git a/app/_locales/hr/messages.json b/app/_locales/hr/messages.json index 656fd84f9..5a629159f 100644 --- a/app/_locales/hr/messages.json +++ b/app/_locales/hr/messages.json @@ -792,9 +792,6 @@ "revealSeedWordsDescription": { "message": "Ako ikada promijenite preglednike ili računala, trebate ovu početnu rečenicu za pristupanje svojim računima. Spremite ih negdje na sigurno i tajno mjesto." }, - "revealSeedWordsTitle": { - "message": "Početna rečenica" - }, "revealSeedWordsWarning": { "message": "Ove se riječi mogu upotrijebiti za krađu vaših računa." }, @@ -831,9 +828,6 @@ "searchTokens": { "message": "Pretraži tokene" }, - "secretBackupPhrase": { - "message": "Alternativna tajna rečenica" - }, "secretBackupPhraseDescription": { "message": "Vašom se alternativnom tajnom rečenicom jednostavno sigurnosno kopira i obnavlja vaš račun." }, @@ -1117,21 +1111,9 @@ "viewContact": { "message": "Prikaži kontakt" }, - "viewOnCustomBlockExplorer": { - "message": "Prikaži u $1" - }, - "viewOnEtherscan": { - "message": "Prikaži na Etherscanu" - }, - "viewinExplorer": { - "message": "Prikaži u Exploreru" - }, "visitWebSite": { "message": "Posjetite naše mrežno mjesto" }, - "walletSeed": { - "message": "Početni novčanik" - }, "welcome": { "message": "Dobro došli u uslugu MetaMask" }, diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json index 6cab69c61..dc3b8b90c 100644 --- a/app/_locales/ht/messages.json +++ b/app/_locales/ht/messages.json @@ -492,9 +492,6 @@ "revealSeedWordsDescription": { "message": "Si ou pa janm chanje navigatè ou deplase òdinatè, ou pral bezwen fraz seed la pou ka gen aksè a kont ou. Sere yo on kote an sekirite e an sekrè." }, - "revealSeedWordsTitle": { - "message": "Seed Fraz" - }, "revealSeedWordsWarning": { "message": "Yo ka itilize mo sa pou vòlè kont ou." }, @@ -688,15 +685,9 @@ "viewAccount": { "message": "Wè Kont" }, - "viewOnEtherscan": { - "message": "Wè sou Etherscan" - }, "visitWebSite": { "message": "Vizite sit entènèt nou an" }, - "walletSeed": { - "message": "Bous Seed" - }, "welcome": { "message": "Byenveni nan MetaMask" }, diff --git a/app/_locales/hu/messages.json b/app/_locales/hu/messages.json index 7e8cec14b..4f99006d6 100644 --- a/app/_locales/hu/messages.json +++ b/app/_locales/hu/messages.json @@ -792,9 +792,6 @@ "revealSeedWordsDescription": { "message": "Ha valamikor böngészőt váltasz, vagy számítógépet cserélsz, a fiókjaid használatához szükséged lesz erre a kulcsszóláncra. Őrizd őket egy biztonságos és titkos helyen." }, - "revealSeedWordsTitle": { - "message": "Kulcsszólánc" - }, "revealSeedWordsWarning": { "message": "Ezekkel a szavakkal ellophatóak a fiókjai." }, @@ -831,9 +828,6 @@ "searchTokens": { "message": "Keresés a tokenek között" }, - "secretBackupPhrase": { - "message": "Titkos biztonsági kifejezés " - }, "secretBackupPhraseDescription": { "message": "Titkos biztonsági szókapcsolatoddal könnyedén készíthetsz biztonsági mentést és helyreállíthatod fiókodat." }, @@ -1117,21 +1111,9 @@ "viewContact": { "message": "Névjegy megtekintése" }, - "viewOnCustomBlockExplorer": { - "message": "Megtekintés $1-kor" - }, - "viewOnEtherscan": { - "message": "Nézze meg Etherscanen" - }, - "viewinExplorer": { - "message": "Megtekintés Explorerben" - }, "visitWebSite": { "message": "Látogass el weboldalunkra" }, - "walletSeed": { - "message": "Pénztárca kulcsszólánca" - }, "welcome": { "message": "Üdvözöljük a MetaMaskban" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index 80f539ad7..529c98ed1 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -1527,9 +1527,6 @@ "revealSeedWordsDescription": { "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 Rahasia" - }, "revealSeedWordsWarning": { "message": "Kata-kata ini dapat digunakan untuk mencuri semua akun Anda." }, @@ -1572,9 +1569,6 @@ "searchTokens": { "message": "Cari Token" }, - "secretBackupPhrase": { - "message": "Frasa Cadangan Rahasia" - }, "secretBackupPhraseDescription": { "message": "Frasa cadangan rahasia Anda memudahkan untuk mencadangkan dan memulihkan akun Anda." }, @@ -2386,24 +2380,12 @@ "viewMore": { "message": "Lihat Selengkapnya" }, - "viewOnCustomBlockExplorer": { - "message": "Lihat di $1" - }, - "viewOnEtherscan": { - "message": "Lihat di Etherscan" - }, - "viewinExplorer": { - "message": "Lihat di Explorer" - }, "visitWebSite": { "message": "Kunjungi situs web kami" }, "walletConnectionGuide": { "message": "panduan koneksi dompet perangkat keras kami" }, - "walletSeed": { - "message": "Frasa Pemulihan Rahasia" - }, "walletSeedRestore": { "message": "Frasa Pemulihan Rahasia Dompet" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index 57122608d..0cd8bf51c 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -1253,9 +1253,6 @@ "revealSeedWordsDescription": { "message": "Se cambierai browser o computer, ti servirà questa frase seed per accedere ai tuoi account. Salvala in un posto sicuro e segreto." }, - "revealSeedWordsTitle": { - "message": "Frase Seed" - }, "revealSeedWordsWarning": { "message": "Non ripristinare la tua frase seed in pubblico!. Queste parole possono essere usate per rubare il tuo account." }, @@ -1298,9 +1295,6 @@ "searchTokens": { "message": "Cerca Tokens" }, - "secretBackupPhrase": { - "message": "Frase di Backup Segreta" - }, "secretBackupPhraseDescription": { "message": "La tua frase di backup segreta rende facile fare il backup e ripristinare il tuo account." }, @@ -1947,24 +1941,12 @@ "viewContact": { "message": "Visualizza contatto" }, - "viewOnCustomBlockExplorer": { - "message": "Vedi su $1" - }, - "viewOnEtherscan": { - "message": "Vedi su Etherscan" - }, - "viewinExplorer": { - "message": "Vista in Explorer" - }, "visitWebSite": { "message": "Visita il nostro sito web" }, "walletConnectionGuide": { "message": "la nostra guida al collegamento del portafoglio hardware" }, - "walletSeed": { - "message": "Seed del Portafoglio" - }, "web3ShimUsageNotification": { "message": "Abbiamo notato che il sito corrente ha provato ad usare la API window.web3 rimossa. Se il sito ti sembra non funzionare, clicca $1 per più informazioni.", "description": "$1 is a clickable link." diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index e6f295cc6..f9e1d125a 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -1527,9 +1527,6 @@ "revealSeedWordsDescription": { "message": "ブラウザーを変更した場合や、コンピューターを移動した場合は、自分のアカウントにアクセスするためにこのシークレット リカバリー フレーズが必要になります。安全で秘密の場所に保管してください。" }, - "revealSeedWordsTitle": { - "message": "シークレット リカバリー フレーズ" - }, "revealSeedWordsWarning": { "message": "これらの単語を使用すると、すべてのアカウントを窃取することができます。" }, @@ -1572,9 +1569,6 @@ "searchTokens": { "message": "トークンの検索" }, - "secretBackupPhrase": { - "message": "秘密のバックアップ フレーズ" - }, "secretBackupPhraseDescription": { "message": "秘密のバックアップ フレーズを使用すると、アカウントのバックアップと復元が容易になります。" }, @@ -2386,24 +2380,12 @@ "viewMore": { "message": "詳細を表示" }, - "viewOnCustomBlockExplorer": { - "message": "$1 に表示" - }, - "viewOnEtherscan": { - "message": "Etherscan で表示" - }, - "viewinExplorer": { - "message": "Explorer で表示" - }, "visitWebSite": { "message": "当社の Web サイトにアクセス" }, "walletConnectionGuide": { "message": "当社のハードウェア ウォレット接続ガイド" }, - "walletSeed": { - "message": "シークレット リカバリー フレーズ" - }, "walletSeedRestore": { "message": "ウォレット シークレット リカバリー フレーズ" }, diff --git a/app/_locales/kn/messages.json b/app/_locales/kn/messages.json index 7aad7aed4..0cdbcab35 100644 --- a/app/_locales/kn/messages.json +++ b/app/_locales/kn/messages.json @@ -799,9 +799,6 @@ "revealSeedWordsDescription": { "message": "ನೀವು ಬ್ರೌಸರ್‌ಗಳನ್ನು ಬದಲಾಯಿಸಿದರೆ ಅಥವಾ ಕಂಪ್ಯೂಟರ್‌ಗಳನ್ನು ಸರಿಸಿದರೆ, ನಿಮ್ಮ ಖಾತೆಗಳನ್ನು ಪ್ರವೇಶಿಸಲು ನಿಮಗೆ ಈ ಸೀಡ್ ಫ್ರೇಸ್‌ಗಳ ಅಗತ್ಯವಿರುತ್ತದೆ. ಅವುಗಳನ್ನು ಎಲ್ಲಿಯಾದರೂ ಸುರಕ್ಷಿತವಾಗಿ ಮತ್ತು ರಹಸ್ಯವಾಗಿ ಉಳಿಸಿ." }, - "revealSeedWordsTitle": { - "message": "ಸೀಡ್ ಫ್ರೇಸ್" - }, "revealSeedWordsWarning": { "message": "ಈ ಪದಗಳನ್ನು ನಿಮ್ಮ ಎಲ್ಲಾ ಖಾತೆಗಳನ್ನು ಕದಿಯಲು ಬಳಸಬಹುದು." }, @@ -838,9 +835,6 @@ "searchTokens": { "message": "ಟೋಕನ್‌ಗಳನ್ನು ಹುಡುಕಿ" }, - "secretBackupPhrase": { - "message": "ರಹಸ್ಯ ಬ್ಯಾಕಪ್ ಫ್ರೇಸ್" - }, "secretBackupPhraseDescription": { "message": "ನಿಮ್ಮ ಖಾತೆಯನ್ನು ಬ್ಯಾಕ್ ಅಪ್ ಮತ್ತು ಮರುಸ್ಥಾಪಿಸುವುದನ್ನು ನಿಮ್ಮ ರಹಸ್ಯ ಬ್ಯಾಕಪ್ ಫ್ರೇಸ್ ಸುಲಭವಾಗಿಸುತ್ತದೆ." }, @@ -1127,21 +1121,9 @@ "viewContact": { "message": "ಸಂಪರ್ಕವನ್ನು ವೀಕ್ಷಿಸಿ" }, - "viewOnCustomBlockExplorer": { - "message": "$1 ನಲ್ಲಿ ವೀಕ್ಷಿಸಿ" - }, - "viewOnEtherscan": { - "message": "ಎಥೆರ್‌ಸ್ಕ್ಯಾನ್‌ನಲ್ಲಿ ವೀಕ್ಷಿಸಿ" - }, - "viewinExplorer": { - "message": "ಎಕ್ಸ್‌ಪ್ಲೋರರ್‌ನಲ್ಲಿ ವೀಕ್ಷಿಸಿ" - }, "visitWebSite": { "message": "ನಮ್ಮ ವೆಬ್ ಸೈಟ್ ಅನ್ನು ಭೇಟಿ ಮಾಡಿ" }, - "walletSeed": { - "message": "ವ್ಯಾಲೆಟ್ ಸೀಡ್" - }, "welcome": { "message": "MetaMask ಗೆ ಸ್ವಾಗತ" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index d62801f6a..96ad9f3fa 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -1527,9 +1527,6 @@ "revealSeedWordsDescription": { "message": "브라우저를 변경하거나 컴퓨터를 옮긴 경우, 계정에 액세스하려면 이 비밀 복구 구문이 필요합니다. 기밀이 보장된 안전한 곳에 보관하세요." }, - "revealSeedWordsTitle": { - "message": "비밀 복구 구문" - }, "revealSeedWordsWarning": { "message": "이 구문은 계정 전체를 도용하는 데 사용될 수 있습니다." }, @@ -1572,9 +1569,6 @@ "searchTokens": { "message": "토큰 검색" }, - "secretBackupPhrase": { - "message": "비밀 백업 구문" - }, "secretBackupPhraseDescription": { "message": "비밀 백업 구문을 이용하면 계정을 쉽게 백업하고 복구할 수 있습니다." }, @@ -2386,24 +2380,12 @@ "viewMore": { "message": "더 보기" }, - "viewOnCustomBlockExplorer": { - "message": "$1에서 보기" - }, - "viewOnEtherscan": { - "message": "Etherscan에서 보기" - }, - "viewinExplorer": { - "message": "탐색기에서 보기" - }, "visitWebSite": { "message": "당사 웹사이트 방문하기" }, "walletConnectionGuide": { "message": "당사의 하드웨어 지갑 연결 가이드" }, - "walletSeed": { - "message": "비밀 복구 구문" - }, "walletSeedRestore": { "message": "지갑 비밀 복구 구문" }, diff --git a/app/_locales/lt/messages.json b/app/_locales/lt/messages.json index f315161d8..01670c783 100644 --- a/app/_locales/lt/messages.json +++ b/app/_locales/lt/messages.json @@ -799,9 +799,6 @@ "revealSeedWordsDescription": { "message": "Jei imsite naudotis kita naršykle arba kitu kompiuteriu, šios atkūrimo frazės jums reikės paskyroms pasiekti. Saugokite ją saugioje ir slaptoje vietoje." }, - "revealSeedWordsTitle": { - "message": "Atkūrimo frazė" - }, "revealSeedWordsWarning": { "message": "Šiuos žodžius galima panaudoti visoms jūsų paskyroms pavogti." }, @@ -838,9 +835,6 @@ "searchTokens": { "message": "Ieškoti žetonų" }, - "secretBackupPhrase": { - "message": "Slapta atsarginė frazė" - }, "secretBackupPhraseDescription": { "message": "Jūsų slapta atsarginė frazė leidžia paprastai padaryti paskyros atsarginę kopiją ir ją atkurti," }, @@ -1127,21 +1121,9 @@ "viewContact": { "message": "Peržiūrėti kontaktą" }, - "viewOnCustomBlockExplorer": { - "message": "Peržiūrėti $1" - }, - "viewOnEtherscan": { - "message": "Peržiūrėti „Etherscan“" - }, - "viewinExplorer": { - "message": "Peržiūrėti naršyklėje" - }, "visitWebSite": { "message": "Apsilankykite mūsų svetainėje" }, - "walletSeed": { - "message": "Slaptažodinės atkūrimo frazė" - }, "welcome": { "message": "Sveiki, tai „MetaMask“" }, diff --git a/app/_locales/lv/messages.json b/app/_locales/lv/messages.json index 3fdcc90a0..ad541d917 100644 --- a/app/_locales/lv/messages.json +++ b/app/_locales/lv/messages.json @@ -795,9 +795,6 @@ "revealSeedWordsDescription": { "message": "Ja mainīsiet pārlūku vai datoru, jūsu kontu piekļuvei būs nepieciešama šī atkopšanas frāze. Saglabājiet to drošā un slepenā vietā!" }, - "revealSeedWordsTitle": { - "message": "Atkopšanas frāze" - }, "revealSeedWordsWarning": { "message": "Šos vārdus var izmantot visu jūsu kontu nolaupīšanai." }, @@ -834,9 +831,6 @@ "searchTokens": { "message": "Meklēt marķierus" }, - "secretBackupPhrase": { - "message": "Slepenā rezerves frāze" - }, "secretBackupPhraseDescription": { "message": "Ar slepeno atgūšanas frāzi ir vieglāk dublēt un atjaunot kontu." }, @@ -1123,21 +1117,9 @@ "viewContact": { "message": "Skatīt līgumu" }, - "viewOnCustomBlockExplorer": { - "message": "Skatīt $1" - }, - "viewOnEtherscan": { - "message": "Skatīt Etherscan" - }, - "viewinExplorer": { - "message": "Skatīt Explorer" - }, "visitWebSite": { "message": "Apmeklējiet mūsu tīmekļa vietni" }, - "walletSeed": { - "message": "Maka atkopšanas frāze" - }, "welcome": { "message": "Laipni lūgti MetaMask" }, diff --git a/app/_locales/ms/messages.json b/app/_locales/ms/messages.json index 38f440b04..f58cb95ba 100644 --- a/app/_locales/ms/messages.json +++ b/app/_locales/ms/messages.json @@ -776,9 +776,6 @@ "revealSeedWordsDescription": { "message": "Jika anda pernah menukar pelayar atau berpindah komputer, anda memerlukan ungkapan benih ini untuk mengakses akaun anda. Simpan ungkapan di tempat yang selamat dan rahsia." }, - "revealSeedWordsTitle": { - "message": "Frasa Benih" - }, "revealSeedWordsWarning": { "message": "Perkataan ini boleh digunakan untuk mencuri kesemua akaun anda." }, @@ -815,9 +812,6 @@ "searchTokens": { "message": "Cari Token" }, - "secretBackupPhrase": { - "message": "Ungkapan Sandaran Rahsia" - }, "secretBackupPhraseDescription": { "message": "Ungkapan rahsia sandaran anda memudahkan membuat sandaran dan memulihkan akaun anda." }, @@ -1101,21 +1095,9 @@ "viewContact": { "message": "Lihat Kenalan" }, - "viewOnCustomBlockExplorer": { - "message": "Lihat pada $1" - }, - "viewOnEtherscan": { - "message": "Lihat di Etherscan" - }, - "viewinExplorer": { - "message": "Lihat di Explorer" - }, "visitWebSite": { "message": "Kunjungi laman web kami" }, - "walletSeed": { - "message": "Benih Dompet" - }, "welcome": { "message": "Selamat datang ke MetaMask" }, diff --git a/app/_locales/no/messages.json b/app/_locales/no/messages.json index c63a23962..e04e6a42c 100644 --- a/app/_locales/no/messages.json +++ b/app/_locales/no/messages.json @@ -786,9 +786,6 @@ "revealSeedWordsDescription": { "message": "Hvis du noen gang bytter nettlesere eller flytter datamaskiner, trenger du denne mnemoniske gjenopprettingsfrasen for å få tilgang til kontoene dine. Lagre dem på et trygt og hemmelig sted." }, - "revealSeedWordsTitle": { - "message": "Mnemonisk gjenopprettingsfrase" - }, "revealSeedWordsWarning": { "message": "Disse ordene kan brukes for å stjele alle kontoene dine. " }, @@ -822,9 +819,6 @@ "searchTokens": { "message": "Søk i sjetonger" }, - "secretBackupPhrase": { - "message": "Hemmelig sikkerhetskopifrase " - }, "secretBackupPhraseDescription": { "message": "Den hemmelige gjenopprettingsfrasen din gjør det enkelt å sikkerhetskopiere og gjenopprette kontoen din." }, @@ -1102,21 +1096,9 @@ "viewContact": { "message": "Se kontrakt" }, - "viewOnCustomBlockExplorer": { - "message": "Vis ved $1 " - }, - "viewOnEtherscan": { - "message": "Vis på Etherscan " - }, - "viewinExplorer": { - "message": "Se i Explorer" - }, "visitWebSite": { "message": "Besøk nettsiden vår " }, - "walletSeed": { - "message": "Lommebok med mnemonisk gjenopprettingsfrase" - }, "welcome": { "message": "Velkommen til MetaMask" }, diff --git a/app/_locales/ph/messages.json b/app/_locales/ph/messages.json index b4c123481..d42c1aa80 100644 --- a/app/_locales/ph/messages.json +++ b/app/_locales/ph/messages.json @@ -1527,9 +1527,6 @@ "revealSeedWordsDescription": { "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": "Secret Recovery Phrase" - }, "revealSeedWordsWarning": { "message": "Magagamit ang mga salitang ito para manakaw ang lahat ng iyong account." }, @@ -1572,9 +1569,6 @@ "searchTokens": { "message": "Maghanap ng Mga Token" }, - "secretBackupPhrase": { - "message": "Lihim na Phrase sa Pag-back up" - }, "secretBackupPhraseDescription": { "message": "Pinapadali ng iyong lihim na phrase sa pag-back up na i-back up at i-restore ang iyong account." }, @@ -2386,24 +2380,12 @@ "viewMore": { "message": "Tumingin Pa" }, - "viewOnCustomBlockExplorer": { - "message": "Tingnan sa $1" - }, - "viewOnEtherscan": { - "message": "Tingnan sa Etherscan" - }, - "viewinExplorer": { - "message": "Tingnan sa Explorer" - }, "visitWebSite": { "message": "Bisitahin ang aming website" }, "walletConnectionGuide": { "message": "ang aming gabay sa pagkonekta ng hardware wallet" }, - "walletSeed": { - "message": "Secret Recovery Phrase" - }, "walletSeedRestore": { "message": "Recovery Phrase ng Wallet Secret" }, diff --git a/app/_locales/pl/messages.json b/app/_locales/pl/messages.json index 4c7b7383d..1d415a675 100644 --- a/app/_locales/pl/messages.json +++ b/app/_locales/pl/messages.json @@ -793,9 +793,6 @@ "revealSeedWordsDescription": { "message": "Jeśli kiedyś zmienisz przeglądarkę lub komputer, będziesz potrzebować tej frazy seed, żeby dostać się do swoich kont. Zapisz ją w bezpiecznym miejscu." }, - "revealSeedWordsTitle": { - "message": "Fraza seed" - }, "revealSeedWordsWarning": { "message": "Te słowa mogą być użyte żeby ukraść Twoje konta." }, @@ -832,9 +829,6 @@ "searchTokens": { "message": "Szukaj tokenów" }, - "secretBackupPhrase": { - "message": "Tajna fraza zapasowa" - }, "secretBackupPhraseDescription": { "message": "Twoja tajna fraza zapasowa ułatwia tworzenie kopii zapasowych i przywracanie konta." }, @@ -1115,21 +1109,9 @@ "viewContact": { "message": "Wyświetl kontakt" }, - "viewOnCustomBlockExplorer": { - "message": "Wyświetl w $1" - }, - "viewOnEtherscan": { - "message": "Zobacz na Etherscan" - }, - "viewinExplorer": { - "message": "Wyświetl w przeglądarce" - }, "visitWebSite": { "message": "Odwiedź naszą stronę" }, - "walletSeed": { - "message": "Seed portfela" - }, "welcome": { "message": "Witaj w MetaMask" }, diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index 79879c23f..9e326c99f 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -1527,9 +1527,6 @@ "revealSeedWordsDescription": { "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 de recuperação secreta" - }, "revealSeedWordsWarning": { "message": "Essas palavras podem ser usadas para roubar todas as suas contas." }, @@ -1572,9 +1569,6 @@ "searchTokens": { "message": "Buscar tokens" }, - "secretBackupPhrase": { - "message": "Frase secreta de backup" - }, "secretBackupPhraseDescription": { "message": "Sua frase secreta de backup facilita fazer o backup e a restauração da sua conta." }, @@ -2386,24 +2380,12 @@ "viewMore": { "message": "Exibir Mais" }, - "viewOnCustomBlockExplorer": { - "message": "Exibir em $1" - }, - "viewOnEtherscan": { - "message": "Exibir no Etherscan" - }, - "viewinExplorer": { - "message": "Exibir no Explorer" - }, "visitWebSite": { "message": "Visite nosso website" }, "walletConnectionGuide": { "message": "nosso guia de conexão com a carteira de hardware" }, - "walletSeed": { - "message": "Frase de recuperação secreta" - }, "walletSeedRestore": { "message": "Frase de recuperação secreta da carteira" }, diff --git a/app/_locales/ro/messages.json b/app/_locales/ro/messages.json index 9e934ab69..97f49a7a5 100644 --- a/app/_locales/ro/messages.json +++ b/app/_locales/ro/messages.json @@ -786,9 +786,6 @@ "revealSeedWordsDescription": { "message": "Dacă schimbați vreodată browserele sau vă mutați la alt computer, veți avea nevoie de această expresie sursă pentru a vă accesa conturile. Salvați-o într-un loc sigur și secret." }, - "revealSeedWordsTitle": { - "message": "Expresie sursă" - }, "revealSeedWordsWarning": { "message": "Aceste cuvinte pot fi folosite pentru a vă fura toate conturile." }, @@ -825,9 +822,6 @@ "searchTokens": { "message": "Căutați token-uri" }, - "secretBackupPhrase": { - "message": "Expresia secretă de rezervă" - }, "secretBackupPhraseDescription": { "message": "Expresia dvs. secretă de rezervă înlesnește crearea unei copii de rezervă a contului dvs. și restabilirea acestuia." }, @@ -1108,21 +1102,9 @@ "viewContact": { "message": "Vizualizare contact" }, - "viewOnCustomBlockExplorer": { - "message": "Vizualizați la $1" - }, - "viewOnEtherscan": { - "message": "Vizualizați pe Etherscan" - }, - "viewinExplorer": { - "message": "Vizualizare în Explorator" - }, "visitWebSite": { "message": "Accesați site-ul nostru" }, - "walletSeed": { - "message": "Sursă portofel" - }, "welcome": { "message": "Bun venit la MetaMask" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index 4d7457124..054f5e100 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -1527,9 +1527,6 @@ "revealSeedWordsDescription": { "message": "Если вы меняете браузер или переходите на другой компьютер, вам понадобится эта секретная фраза восстановления для доступа к своим счетам. Сохраните ее в безопасном секретном месте." }, - "revealSeedWordsTitle": { - "message": "Секретная фраза восстановления" - }, "revealSeedWordsWarning": { "message": "Эти слова можно использовать для кражи всех ваших счетов." }, @@ -1572,9 +1569,6 @@ "searchTokens": { "message": "Поиск токенов" }, - "secretBackupPhrase": { - "message": "Секретная резервная фраза" - }, "secretBackupPhraseDescription": { "message": "Ваша секретная резервная фраза упрощает резервное копирование и восстановление вашего счета." }, @@ -2386,24 +2380,12 @@ "viewMore": { "message": "Посмотреть больше" }, - "viewOnCustomBlockExplorer": { - "message": "Посмотреть на $1" - }, - "viewOnEtherscan": { - "message": "Посмотреть на Etherscan" - }, - "viewinExplorer": { - "message": "Проводник в проводнике" - }, "visitWebSite": { "message": "Посетите наш веб-сайт" }, "walletConnectionGuide": { "message": "наше руководство по подключению аппаратного кошелька" }, - "walletSeed": { - "message": "Секретная фраза восстановления" - }, "walletSeedRestore": { "message": "Секретная фраза восстановления кошелька" }, diff --git a/app/_locales/sk/messages.json b/app/_locales/sk/messages.json index 0a5af86c0..aefb96bd1 100644 --- a/app/_locales/sk/messages.json +++ b/app/_locales/sk/messages.json @@ -768,9 +768,6 @@ "revealSeedWordsDescription": { "message": "Ak niekedy zmeníte prehliadač alebo presuniete počítače, budete potrebovať túto seed frázu na prístup k svojim účtom. Uložte ich niekde v bezpečí a v tajnosti." }, - "revealSeedWordsTitle": { - "message": "Seed fráza" - }, "revealSeedWordsWarning": { "message": "Nebnovujte slova klíčové fráze na veřejnosti! Tato slova mohou být použita k odcizení veškerých vyašich účtů." }, @@ -801,9 +798,6 @@ "searchTokens": { "message": "Hledat tokeny" }, - "secretBackupPhrase": { - "message": "Tajná backup fráza" - }, "secretBackupPhraseDescription": { "message": "Vaša tajná backup fráza uľahčuje zálohovanie a obnovenie vášho účtu." }, @@ -1084,21 +1078,9 @@ "viewContact": { "message": "Zobraziť kontakt" }, - "viewOnCustomBlockExplorer": { - "message": "Zobraziť na $1" - }, - "viewOnEtherscan": { - "message": "Zobraziť na Etherscan" - }, - "viewinExplorer": { - "message": "Zobraziť v Exploreri" - }, "visitWebSite": { "message": "Navštivte naši stránku" }, - "walletSeed": { - "message": "Klíčová fráze peněženky" - }, "welcome": { "message": "Vitajte v MetaMask" }, diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json index 2aa7c40d3..d9173c49a 100644 --- a/app/_locales/sl/messages.json +++ b/app/_locales/sl/messages.json @@ -823,9 +823,6 @@ "searchTokens": { "message": "Iskanje žetonov" }, - "secretBackupPhrase": { - "message": "Skrivno geslo za varnostno kopiranje" - }, "secretBackupPhraseDescription": { "message": "Vaše skrivno geslo za varnostno kopiranje olajša varnostno kopiranje in obnovitev računa." }, @@ -1112,15 +1109,6 @@ "viewContact": { "message": "Ogled stika" }, - "viewOnCustomBlockExplorer": { - "message": "Ogled na $1 " - }, - "viewOnEtherscan": { - "message": "Poglej na Etherscan" - }, - "viewinExplorer": { - "message": "Ogled v Explorerju" - }, "visitWebSite": { "message": "Obiščite našo spletno stran" }, diff --git a/app/_locales/sr/messages.json b/app/_locales/sr/messages.json index 5a21f3df1..1bcfee19a 100644 --- a/app/_locales/sr/messages.json +++ b/app/_locales/sr/messages.json @@ -790,9 +790,6 @@ "revealSeedWordsDescription": { "message": "Ukoliko ikad promenite pregledač ili kompjuter, trebaće vam ova šifra za oporavak naloga (seed phrase) kako biste pristupili svojim nalozima. Čuvajte je na bezbednom i tajnom mestu." }, - "revealSeedWordsTitle": { - "message": "Seed fraza" - }, "revealSeedWordsWarning": { "message": "Ove reči se mogu iskoristiti za krađu svih vaših naloga." }, @@ -829,9 +826,6 @@ "searchTokens": { "message": "Pretražite tokene" }, - "secretBackupPhrase": { - "message": "Tajna rezervna kopija fraze" - }, "secretBackupPhraseDescription": { "message": "Vaša tajna fraza za rezervnu kopiju olakšava pravljenje rezervne kopije i vraćanje naloga u prethodno stanje." }, @@ -1112,21 +1106,9 @@ "viewContact": { "message": "Pogledaj kontakt" }, - "viewOnCustomBlockExplorer": { - "message": "Pogledaj na $1" - }, - "viewOnEtherscan": { - "message": "Pogledaj na Etherscan-u" - }, - "viewinExplorer": { - "message": "Pogledati u Explorer-u" - }, "visitWebSite": { "message": "Posetite našu veb lokaciju" }, - "walletSeed": { - "message": "Šifra za oporavak novčanika" - }, "welcome": { "message": "Dobro došli na MetaMask" }, diff --git a/app/_locales/sv/messages.json b/app/_locales/sv/messages.json index 790027eda..a49e35d41 100644 --- a/app/_locales/sv/messages.json +++ b/app/_locales/sv/messages.json @@ -783,9 +783,6 @@ "revealSeedWordsDescription": { "message": "Om du någonsin byter webbläsare eller dator kommer du behöva denna" }, - "revealSeedWordsTitle": { - "message": "Seed phrase" - }, "revealSeedWordsWarning": { "message": "De här orden kan användas för att stjäla alla dina konton." }, @@ -822,9 +819,6 @@ "searchTokens": { "message": "Sök tokens" }, - "secretBackupPhrase": { - "message": "Hemlig återställningsfras" - }, "secretBackupPhraseDescription": { "message": "Din hemliga backup-fras gör det enkelt att säkerhetskopiera och återställa ditt konto." }, @@ -1102,21 +1096,9 @@ "viewContact": { "message": "Visa kontakt" }, - "viewOnCustomBlockExplorer": { - "message": "Visa vid $1" - }, - "viewOnEtherscan": { - "message": "Visa på Etherscan" - }, - "viewinExplorer": { - "message": "Visa i Utforskaren" - }, "visitWebSite": { "message": "Besök vår hemsida" }, - "walletSeed": { - "message": "Plånboksseed" - }, "welcome": { "message": "Välkommen till MetaMask" }, diff --git a/app/_locales/sw/messages.json b/app/_locales/sw/messages.json index 79c583c7b..e9eed3a4b 100644 --- a/app/_locales/sw/messages.json +++ b/app/_locales/sw/messages.json @@ -777,9 +777,6 @@ "revealSeedWordsDescription": { "message": "Ikiwa utabadilisha kisakuzi au kuhamisha kompyuta, utahitaji kirai hiki kianzio ili kufikia akaunti zako. Vihifadhi mahali fulani ambapo ni salamana pa siri." }, - "revealSeedWordsTitle": { - "message": "Kiari Kianzio" - }, "revealSeedWordsWarning": { "message": "Maneno haya yanaweza kutumika kuiba akanti zako zote." }, @@ -816,9 +813,6 @@ "searchTokens": { "message": "Tafuta Vianzio" }, - "secretBackupPhrase": { - "message": "Kirai cha Siri cha Hifadhi Mbadala" - }, "secretBackupPhraseDescription": { "message": "Kirai chako cha siri cha hifadhi mbadala kinafanya iwe rahisi kuhifadhi kwa njia mbadala na kurejesha akaunti yako." }, @@ -1105,21 +1099,9 @@ "viewContact": { "message": "Tazama Mawasiliano" }, - "viewOnCustomBlockExplorer": { - "message": "Tazama kwenye $1" - }, - "viewOnEtherscan": { - "message": "Tazama kwenye Etherscan" - }, - "viewinExplorer": { - "message": "Tazama kwenye Explorer" - }, "visitWebSite": { "message": "Tembelea Tovuti yetu" }, - "walletSeed": { - "message": "Kianzio cha Waleti" - }, "welcome": { "message": "Karibu kwenye MetaMask" }, diff --git a/app/_locales/ta/messages.json b/app/_locales/ta/messages.json index be36f14c0..f754b0532 100644 --- a/app/_locales/ta/messages.json +++ b/app/_locales/ta/messages.json @@ -520,9 +520,6 @@ "visitWebSite": { "message": "எங்கள் வலைத்தளத்தைப் பார்வையிடவும்" }, - "walletSeed": { - "message": "வால்ட் விதை" - }, "welcome": { "message": "மெட்டாமாஸ்க் பீட்டாவுக்கு வருக" }, diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json index c65591572..55e6587b5 100644 --- a/app/_locales/tl/messages.json +++ b/app/_locales/tl/messages.json @@ -1244,9 +1244,6 @@ "revealSeedWordsDescription": { "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": "Secret Recovery Phrase" - }, "revealSeedWordsWarning": { "message": "Magagamit ang mga salitang ito para manakaw ang lahat ng iyong account." }, @@ -1289,9 +1286,6 @@ "searchTokens": { "message": "Maghanap ng Mga Token" }, - "secretBackupPhrase": { - "message": "Lihim na Phrase sa Pag-back up" - }, "secretBackupPhraseDescription": { "message": "Pinapadali ng iyong lihim na phrase sa pag-back up na i-back up at i-restore ang iyong account." }, @@ -1900,24 +1894,12 @@ "viewContact": { "message": "Tingnan ang Contact" }, - "viewOnCustomBlockExplorer": { - "message": "Tingnan sa $1" - }, - "viewOnEtherscan": { - "message": "Tingnan sa Etherscan" - }, - "viewinExplorer": { - "message": "Tingnan sa Explorer" - }, "visitWebSite": { "message": "Bisitahin ang aming website" }, "walletConnectionGuide": { "message": "ang aming gabay sa pagkonekta ng hardware wallet" }, - "walletSeed": { - "message": "Secret Recovery Phrase" - }, "walletSeedRestore": { "message": "Recovery Phrase ng Wallet Secret" }, diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index 15723d6ed..977162984 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -454,9 +454,6 @@ "visitWebSite": { "message": "Web sitemizi ziyaret edin" }, - "walletSeed": { - "message": "Cüzdan Kaynağı" - }, "welcome": { "message": "MetaMask'ya Hoşgeldiniz" }, diff --git a/app/_locales/uk/messages.json b/app/_locales/uk/messages.json index a9d372722..fe88a0e32 100644 --- a/app/_locales/uk/messages.json +++ b/app/_locales/uk/messages.json @@ -799,9 +799,6 @@ "revealSeedWordsDescription": { "message": "При зміні браузера або комп'ютера, вам знадобиться seed-фраза для отримання доступу до ваших облікових записів. Збережіть її у надійному місці." }, - "revealSeedWordsTitle": { - "message": "Мнемонічна фраза" - }, "revealSeedWordsWarning": { "message": "Ці слова можуть бути використані, щоб вкрасти всі ваші облікові записи." }, @@ -838,9 +835,6 @@ "searchTokens": { "message": "Шукати токени" }, - "secretBackupPhrase": { - "message": "Секретна резервна фраза" - }, "secretBackupPhraseDescription": { "message": "Ваша секретна резервна фраза дозволяє легко створити резервну копію та відновити обліковий запис." }, @@ -1127,21 +1121,9 @@ "viewContact": { "message": "Переглянути контакт" }, - "viewOnCustomBlockExplorer": { - "message": "Дивитись на $1" - }, - "viewOnEtherscan": { - "message": "Дивитись на Etherscan" - }, - "viewinExplorer": { - "message": "Дивитись в Explorer" - }, "visitWebSite": { "message": "Відвідайте наш веб-сайт" }, - "walletSeed": { - "message": "Seed гаманця" - }, "welcome": { "message": "Ласкаво просимо до MetaMask" }, diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index 1553f11ee..56ed93266 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -1527,9 +1527,6 @@ "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 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 khôi phục bí mật này ở nơi an toàn và bí mật." }, - "revealSeedWordsTitle": { - "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." }, @@ -1572,9 +1569,6 @@ "searchTokens": { "message": "Tìm kiếm token" }, - "secretBackupPhrase": { - "message": "Cụm mật khẩu sao lưu bí mật" - }, "secretBackupPhraseDescription": { "message": "Cụm mật khẩu sao lưu bí mật giúp việc sao lưu và khôi phục tài khoản trở nên dễ dàng." }, @@ -2386,24 +2380,12 @@ "viewMore": { "message": "Xem thêm" }, - "viewOnCustomBlockExplorer": { - "message": "Xem tại $1" - }, - "viewOnEtherscan": { - "message": "Xem trên Etherscan" - }, - "viewinExplorer": { - "message": "Xem trên trình khám phá" - }, "visitWebSite": { "message": "Truy cập trang web của chúng tôi" }, "walletConnectionGuide": { "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 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í" }, diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index 1a83650d4..bbd980f1d 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -1247,9 +1247,6 @@ "revealSeedWordsDescription": { "message": "如果您更换浏览器或计算机,则需要使用此账户助记词访问您的帐户。请将它们保存在安全秘密的地方。" }, - "revealSeedWordsTitle": { - "message": "账户助记词" - }, "revealSeedWordsWarning": { "message": "该账户助记词可以用来窃取您的所有帐户" }, @@ -1292,9 +1289,6 @@ "searchTokens": { "message": "搜索代币" }, - "secretBackupPhrase": { - "message": "账户助记词" - }, "secretBackupPhraseDescription": { "message": "您的账户助记词可以帮助您轻松备份和恢复个人账户。" }, @@ -1924,24 +1918,12 @@ "viewContact": { "message": "查看联系人" }, - "viewOnCustomBlockExplorer": { - "message": "在 $1 查看" - }, - "viewOnEtherscan": { - "message": "在 Etherscan(以太坊浏览器)上查看" - }, - "viewinExplorer": { - "message": "在浏览器中查看" - }, "visitWebSite": { "message": "访问我们的网站" }, "walletConnectionGuide": { "message": "我们的硬件钱包连接指南" }, - "walletSeed": { - "message": "账户助记词" - }, "web3ShimUsageNotification": { "message": "我们发现当前的网站尝试使用已经删除的 window.web3 API。如果这个网站网站已经无法正常使用,请点击 $1 获取更多信息。", "description": "$1 is a clickable link." diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json index 045826588..82035e758 100644 --- a/app/_locales/zh_TW/messages.json +++ b/app/_locales/zh_TW/messages.json @@ -793,9 +793,6 @@ "revealSeedWordsDescription": { "message": "若想在不同瀏覽器或電腦登入,將需要使用助憶詞還原帳戶資訊。請妥善並安全的保管您的助憶詞。" }, - "revealSeedWordsTitle": { - "message": "助憶詞" - }, "revealSeedWordsWarning": { "message": "絕對不要在公共場合輸入助憶詞!這可被用來竊取您的帳戶。" }, @@ -832,9 +829,6 @@ "searchTokens": { "message": "搜尋代幣" }, - "secretBackupPhrase": { - "message": "助憶詞" - }, "secretBackupPhraseDescription": { "message": "助憶詞將可協助您用更簡單的方式備份帳戶資訊。" }, @@ -1115,21 +1109,9 @@ "viewContact": { "message": "觀看聯絡資訊" }, - "viewOnCustomBlockExplorer": { - "message": "在 $1 瀏覽" - }, - "viewOnEtherscan": { - "message": "在 Etherscan 上瀏覽" - }, - "viewinExplorer": { - "message": "在 Explorer 上瀏覽" - }, "visitWebSite": { "message": "造訪我們的網站" }, - "walletSeed": { - "message": "助憶詞" - }, "welcome": { "message": "歡迎來到 MetaMask" }, diff --git a/app/background.html b/app/background.html index 2faa31411..447efa60e 100644 --- a/app/background.html +++ b/app/background.html @@ -6,11 +6,18 @@ - - - + {{@if(it.useLavamoat)}} + + + + {{#else}} + + + + + {{/if}} {{@each(it.jsBundles) => val}} - + {{/each}} diff --git a/app/home.html b/app/home.html index 5350b31dd..d44eb6663 100644 --- a/app/home.html +++ b/app/home.html @@ -12,11 +12,18 @@
- - - + {{@if(it.useLavamoat)}} + + + + {{#else}} + + + + + {{/if}} {{@each(it.jsBundles) => val}} - + {{/each}} diff --git a/app/images/onboarding-welcome-decentralised-apps.svg b/app/images/onboarding-welcome-decentralised-apps.svg new file mode 100644 index 000000000..c07f2dae7 --- /dev/null +++ b/app/images/onboarding-welcome-decentralised-apps.svg @@ -0,0 +1,218 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/images/onboarding-welcome-say-hello.svg b/app/images/onboarding-welcome-say-hello.svg new file mode 100644 index 000000000..1c34835f0 --- /dev/null +++ b/app/images/onboarding-welcome-say-hello.svg @@ -0,0 +1,335 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/images/tada.png b/app/images/tada.png new file mode 100644 index 000000000..6ddcf2f89 Binary files /dev/null and b/app/images/tada.png differ diff --git a/app/images/twitter-icon.png b/app/images/twitter-icon.png new file mode 100644 index 000000000..a71ad381f Binary files /dev/null and b/app/images/twitter-icon.png differ diff --git a/app/images/warning-icon.png b/app/images/warning-icon.png new file mode 100644 index 000000000..06b4be332 Binary files /dev/null and b/app/images/warning-icon.png differ diff --git a/app/manifest/_base.json b/app/manifest/_base.json index 6c328d0c6..e4f55da26 100644 --- a/app/manifest/_base.json +++ b/app/manifest/_base.json @@ -35,6 +35,7 @@ "globalthis.js", "lockdown-install.js", "lockdown-run.js", + "lockdown-more.js", "contentscript.js" ], "run_at": "document_start", diff --git a/app/manifest/_beta_modifications.json b/app/manifest/_beta_modifications.json index a505eb7f4..33a2da321 100644 --- a/app/manifest/_beta_modifications.json +++ b/app/manifest/_beta_modifications.json @@ -22,6 +22,5 @@ "512": "images/icon-512.png" }, "name": "__MSG_appName__ Beta", - "short_name": "__MSG_appName__ Beta", - "version": "" + "short_name": "__MSG_appName__ Beta" } diff --git a/app/notification.html b/app/notification.html index 55b98c960..1002a37ef 100644 --- a/app/notification.html +++ b/app/notification.html @@ -35,11 +35,18 @@
- - - + {{@if(it.useLavamoat)}} + + + + {{#else}} + + + + + {{/if}} {{@each(it.jsBundles) => val}} - + {{/each}} diff --git a/app/phishing.html b/app/phishing.html index dd180fb77..30accb9bf 100644 --- a/app/phishing.html +++ b/app/phishing.html @@ -5,6 +5,7 @@ + diff --git a/app/popup.html b/app/popup.html index c94b82df8..e24978ad7 100644 --- a/app/popup.html +++ b/app/popup.html @@ -12,11 +12,18 @@
- - - + {{@if(it.useLavamoat)}} + + + + {{#else}} + + + + + {{/if}} {{@each(it.jsBundles) => val}} - + {{/each}} diff --git a/app/scripts/controllers/onboarding.js b/app/scripts/controllers/onboarding.js index 5e55d0e0f..25ae2968a 100644 --- a/app/scripts/controllers/onboarding.js +++ b/app/scripts/controllers/onboarding.js @@ -4,12 +4,12 @@ import log from 'loglevel'; /** * @typedef {Object} InitState * @property {Boolean} seedPhraseBackedUp Indicates whether the user has completed the seed phrase backup challenge + * @property {Boolean} completedOnboarding Indicates whether the user has completed the onboarding flow */ /** * @typedef {Object} OnboardingOptions * @property {InitState} initState The initial controller state - * @property {PreferencesController} preferencesController Controller for managing user perferences */ /** @@ -28,21 +28,12 @@ export default class OnboardingController { }; const initState = { seedPhraseBackedUp: null, + firstTimeFlowType: null, + completedOnboarding: false, ...opts.initState, ...initialTransientState, }; this.store = new ObservableStore(initState); - this.preferencesController = opts.preferencesController; - this.completedOnboarding = this.preferencesController.store.getState().completedOnboarding; - - this.preferencesController.store.subscribe(({ completedOnboarding }) => { - if (completedOnboarding !== this.completedOnboarding) { - this.completedOnboarding = completedOnboarding; - if (completedOnboarding) { - this.store.updateState(initialTransientState); - } - } - }); } setSeedPhraseBackedUp(newSeedPhraseBackUpState) { @@ -51,6 +42,27 @@ export default class OnboardingController { }); } + // /** + // * Sets the completedOnboarding state to true, indicating that the user has completed the + // * onboarding process. + // */ + completeOnboarding() { + this.store.updateState({ + completedOnboarding: true, + }); + return Promise.resolve(true); + } + + /** + * Setter for the `firstTimeFlowType` property + * + * @param {string} type - Indicates the type of first time flow - create or import - the user wishes to follow + * + */ + setFirstTimeFlowType(type) { + this.store.updateState({ firstTimeFlowType: type }); + } + /** * Registering a site as having initiated onboarding * diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index 60607d602..7f5d59ba6 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -45,7 +45,6 @@ export default class PreferencesController { showIncomingTransactions: true, }, knownMethodData: {}, - firstTimeFlowType: null, currentLocale: opts.initLangCode, identities: {}, lostIdentities: {}, @@ -56,7 +55,6 @@ export default class PreferencesController { useNativeCurrencyAsPrimaryCurrency: true, hideZeroBalanceTokens: false, }, - completedOnboarding: false, // ENS decentralized website resolution ipfsGateway: 'dweb.link', infuraBlocked: null, @@ -127,16 +125,6 @@ export default class PreferencesController { this.store.updateState({ useTokenDetection: val }); } - /** - * Setter for the `firstTimeFlowType` property - * - * @param {string} type - Indicates the type of first time flow - create or import - the user wishes to follow - * - */ - setFirstTimeFlowType(type) { - this.store.updateState({ firstTimeFlowType: type }); - } - /** * Add new methodData to state, to avoid requesting this information again through Infura * @@ -509,15 +497,6 @@ export default class PreferencesController { return this.store.getState().preferences; } - /** - * Sets the completedOnboarding state to true, indicating that the user has completed the - * onboarding process. - */ - completeOnboarding() { - this.store.updateState({ completedOnboarding: true }); - return Promise.resolve(true); - } - /** * A getter for the `ipfsGateway` property * @returns {string} The current IPFS gateway domain diff --git a/app/scripts/controllers/swaps.js b/app/scripts/controllers/swaps.js index 5f3ec9851..d48eea028 100644 --- a/app/scripts/controllers/swaps.js +++ b/app/scripts/controllers/swaps.js @@ -277,7 +277,9 @@ export default class SwapsController { // _getERC20Allowance() returns the amount of the token they have approved for withdrawal. If that amount is greater // than 0, it means that approval has already occured and is not needed. Otherwise, for tokens to be swapped, a new // call of the ERC-20 approve method is required. - approvalRequired = allowance.eq(0); + approvalRequired = + allowance.eq(0) && + Object.values(newQuotes)[0].aggregator !== 'wrappedNative'; if (!approvalRequired) { newQuotes = mapValues(newQuotes, (quote) => ({ ...quote, diff --git a/app/scripts/controllers/token-rates-controller.test.js b/app/scripts/controllers/token-rates-controller.test.js deleted file mode 100644 index 31032495e..000000000 --- a/app/scripts/controllers/token-rates-controller.test.js +++ /dev/null @@ -1,68 +0,0 @@ -import { strict as assert } from 'assert'; -import sinon from 'sinon'; -import { TokensController } from '@metamask/controllers'; -import TokenRatesController from './token-rates'; -import NetworkController from './network'; -import PreferencesController from './preferences'; - -const networkControllerProviderConfig = { - getAccounts: () => undefined, -}; - -describe('TokenRatesController', function () { - let nativeCurrency, - getNativeCurrency, - network, - provider, - preferences, - tokensController; - beforeEach(function () { - nativeCurrency = 'ETH'; - getNativeCurrency = () => nativeCurrency; - network = new NetworkController(); - network.setInfuraProjectId('foo'); - network.initializeProvider(networkControllerProviderConfig); - provider = network.getProviderAndBlockTracker().provider; - preferences = new PreferencesController({ network, provider }); - tokensController = new TokensController({ - onPreferencesStateChange: preferences.store.subscribe.bind( - preferences.store, - ), - onNetworkStateChange: network.store.subscribe.bind(network.store), - }); - sinon.stub(network, 'getLatestBlock').callsFake(() => Promise.resolve({})); - sinon.stub(tokensController, '_instantiateNewEthersProvider').returns(null); - sinon - .stub(tokensController, '_detectIsERC721') - .returns(Promise.resolve(false)); - }); - it('should listen for tokenControllers state updates', async function () { - const controller = new TokenRatesController({ - tokensController, - getNativeCurrency, - }); - await tokensController.addToken('0x1', 'TEST', 1); - assert.deepEqual(controller._tokens, [ - { - address: '0x1', - decimals: 1, - symbol: 'TEST', - image: undefined, - isERC721: false, - }, - ]); - }); - - it('should poll on correct interval', async function () { - const stub = sinon.stub(global, 'setInterval'); - const controller = new TokenRatesController({ - tokensController, - getNativeCurrency, - }); - controller.start(1337); - - assert.strictEqual(stub.getCall(0).args[1], 1337); - stub.restore(); - controller.stop(); - }); -}); diff --git a/app/scripts/controllers/token-rates.js b/app/scripts/controllers/token-rates.js deleted file mode 100644 index 319265593..000000000 --- a/app/scripts/controllers/token-rates.js +++ /dev/null @@ -1,88 +0,0 @@ -import { ObservableStore } from '@metamask/obs-store'; -import log from 'loglevel'; -import { normalize as normalizeAddress } from 'eth-sig-util'; -import getFetchWithTimeout from '../../../shared/modules/fetch-with-timeout'; -import { toChecksumHexAddress } from '../../../shared/modules/hexstring-utils'; -import { MINUTE, SECOND } from '../../../shared/constants/time'; - -const fetchWithTimeout = getFetchWithTimeout(SECOND * 30); - -// By default, poll every 3 minutes -const DEFAULT_INTERVAL = MINUTE * 3; - -/** - * A controller that polls for token exchange - * rates based on a user's current token list - */ -export default class TokenRatesController { - /** - * Creates a TokenRatesController - * - * @param {Object} [config] - Options to configure controller - */ - constructor({ tokensController, getNativeCurrency } = {}) { - this.store = new ObservableStore(); - this.getNativeCurrency = getNativeCurrency; - this.tokens = tokensController.state.tokens; - tokensController.subscribe(({ tokens = [] }) => { - this.tokens = tokens; - }); - } - - /** - * Updates exchange rates for all tokens - */ - async updateExchangeRates() { - const contractExchangeRates = {}; - const nativeCurrency = this.getNativeCurrency().toLowerCase(); - const pairs = this._tokens.map((token) => token.address).join(','); - const query = `contract_addresses=${pairs}&vs_currencies=${nativeCurrency}`; - if (this._tokens.length > 0) { - try { - const response = await fetchWithTimeout( - `https://api.coingecko.com/api/v3/simple/token_price/ethereum?${query}`, - ); - const prices = await response.json(); - this._tokens.forEach((token) => { - const price = - prices[token.address.toLowerCase()] || - prices[toChecksumHexAddress(token.address)]; - contractExchangeRates[normalizeAddress(token.address)] = price - ? price[nativeCurrency] - : 0; - }); - } catch (error) { - log.warn( - `MetaMask - TokenRatesController exchange rate fetch failed.`, - error, - ); - } - } - this.store.putState({ contractExchangeRates }); - } - - /* eslint-disable accessor-pairs */ - /** - * @type {Array} - */ - set tokens(tokens) { - this._tokens = tokens; - this.updateExchangeRates(); - } - /* eslint-enable accessor-pairs */ - - start(interval = DEFAULT_INTERVAL) { - this._handle && clearInterval(this._handle); - if (!interval) { - return; - } - this._handle = setInterval(() => { - this.updateExchangeRates(); - }, interval); - this.updateExchangeRates(); - } - - stop() { - this._handle && clearInterval(this._handle); - } -} diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 0aa43d339..82131dee0 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -405,8 +405,9 @@ export default class TransactionController extends EventEmitter { * @returns {Promise} resolves with txMeta */ async addTxGasDefaults(txMeta, getCodeResponse) { - const eip1559Compatibility = await this.getEIP1559Compatibility(); - + const eip1559Compatibility = + txMeta.txParams.type !== TRANSACTION_ENVELOPE_TYPES.LEGACY && + (await this.getEIP1559Compatibility()); const { gasPrice: defaultGasPrice, maxFeePerGas: defaultMaxFeePerGas, diff --git a/app/scripts/controllers/transactions/index.test.js b/app/scripts/controllers/transactions/index.test.js index 56669d267..e4bc6ca20 100644 --- a/app/scripts/controllers/transactions/index.test.js +++ b/app/scripts/controllers/transactions/index.test.js @@ -525,6 +525,58 @@ describe('Transaction Controller', function () { stub2.restore(); }); + it('should not add maxFeePerGas and maxPriorityFeePerGas to type-0 transactions', async function () { + const TEST_GASPRICE = '0x12a05f200'; + + const stub1 = sinon + .stub(txController, 'getEIP1559Compatibility') + .returns(true); + + const stub2 = sinon + .stub(txController, '_getDefaultGasFees') + .callsFake(() => ({ gasPrice: TEST_GASPRICE })); + + txController.txStateManager._addTransactionsToState([ + { + id: 1, + status: TRANSACTION_STATUSES.UNAPPROVED, + metamaskNetworkId: currentNetworkId, + txParams: { + to: VALID_ADDRESS, + from: VALID_ADDRESS_TWO, + type: '0x0', + }, + history: [{}], + }, + ]); + const txMeta = { + id: 1, + txParams: { + from: '0xc684832530fcbddae4b4230a47e991ddcec2831d', + to: '0xc684832530fcbddae4b4230a47e991ddcec2831d', + type: '0x0', + }, + history: [{}], + }; + providerResultStub.eth_getBlockByNumber = { gasLimit: '47b784' }; + providerResultStub.eth_estimateGas = '5209'; + + const txMetaWithDefaults = await txController.addTxGasDefaults(txMeta); + + assert.equal( + txMetaWithDefaults.txParams.maxFeePerGas, + undefined, + 'should not have maxFeePerGas', + ); + assert.equal( + txMetaWithDefaults.txParams.maxPriorityFeePerGas, + undefined, + 'should not have max priority fee per gas', + ); + stub1.restore(); + stub2.restore(); + }); + it('should not add gasPrice if the fee data is available from the dapp', async function () { const TEST_GASPRICE = '0x12a05f200'; const TEST_MAX_FEE_PER_GAS = '0x12a05f200'; diff --git a/app/scripts/controllers/transactions/lib/util.js b/app/scripts/controllers/transactions/lib/util.js index 7e4e0f4fb..79336d369 100644 --- a/app/scripts/controllers/transactions/lib/util.js +++ b/app/scripts/controllers/transactions/lib/util.js @@ -197,6 +197,12 @@ export function validateTxParams(txParams, eip1559Compatibility = true) { `Invalid transaction value of "${value}": number must be in wei.`, ); } + + if (!value.match(/^0x[a-fA-F0-9]+$/u)) { + throw ethErrors.rpc.invalidParams( + `Invalid transaction value of "${value}": not a valid hex string.`, + ); + } break; case 'chainId': if (typeof value !== 'number' && typeof value !== 'string') { diff --git a/app/scripts/lockdown-more.js b/app/scripts/lockdown-more.js new file mode 100644 index 000000000..7db50e43f --- /dev/null +++ b/app/scripts/lockdown-more.js @@ -0,0 +1,91 @@ +// Make all "object" and "function" own properties of globalThis +// non-configurable and non-writable, when possible. +// We call a property that is non-configurable and non-writable, +// "non-modifiable". +try { + /** + * `lockdown` only hardens the properties enumerated by the + * universalPropertyNames constant specified in 'ses/src/whitelist'. This + * function makes all function and object properties on the start compartment + * global non-configurable and non-writable, unless they are already + * non-configurable. + * + * It is critical that this function runs at the right time during + * initialization, which should always be immediately after `lockdown` has been + * called. At the time of writing, the modifications this function makes to the + * runtime environment appear to be non-breaking, but that could change with + * the addition of dependencies, or the order of our scripts in our HTML files. + * Exercise caution. + * + * See inline comments for implementation details. + * + * We write this function in IIFE format to avoid polluting global scope. + */ + (function protectIntrinsics() { + const namedIntrinsics = Reflect.ownKeys(new Compartment().globalThis); + + // These named intrinsics are not automatically hardened by `lockdown` + const shouldHardenManually = new Set(['eval', 'Function']); + + const globalProperties = new Set([ + // universalPropertyNames is a constant added by lockdown to global scope + // at the time of writing, it is initialized in 'ses/src/whitelist'. + // These properties tend to be non-enumerable. + ...namedIntrinsics, + + // TODO: Also include the named platform globals + // This grabs every enumerable property on globalThis. + // ...Object.keys(globalThis), + ]); + + globalProperties.forEach((propertyName) => { + const descriptor = Reflect.getOwnPropertyDescriptor( + globalThis, + propertyName, + ); + + if (descriptor) { + if (descriptor.configurable) { + // If the property on globalThis is configurable, make it + // non-configurable. If it has no accessor properties, also make it + // non-writable. + if (hasAccessor(descriptor)) { + Object.defineProperty(globalThis, propertyName, { + configurable: false, + }); + } else { + Object.defineProperty(globalThis, propertyName, { + configurable: false, + writable: false, + }); + } + } + + if (shouldHardenManually.has(propertyName)) { + harden(globalThis[propertyName]); + } + } + }); + + /** + * Checks whether the given propertyName descriptor has any accessors, i.e. the + * properties `get` or `set`. + * + * We want to make globals non-writable, and we can't set the `writable` + * property and accessor properties at the same time. + * + * @param {Object} descriptor - The propertyName descriptor to check. + * @returns {boolean} Whether the propertyName descriptor has any accessors. + */ + function hasAccessor(descriptor) { + return 'set' in descriptor || 'get' in descriptor; + } + })(); +} catch (error) { + console.error('Protecting intrinsics failed:', error); + if (globalThis?.sentry.captureException) { + globalThis.sentry.captureException( + new Error(`Protecting intrinsics failed: ${error.message}`), + ); + } +} diff --git a/app/scripts/lockdown-run.js b/app/scripts/lockdown-run.js index 3c7276fdf..0d869cc7f 100644 --- a/app/scripts/lockdown-run.js +++ b/app/scripts/lockdown-run.js @@ -20,95 +20,3 @@ try { ); } } - -// Make all "object" and "function" own properties of globalThis -// non-configurable and non-writable, when possible. -// We call the a property that is non-configurable and non-writable, -// "non-modifiable". -try { - /** - * `lockdown` only hardens the properties enumerated by the - * universalPropertyNames constant specified in 'ses/src/whitelist'. This - * function makes all function and object properties on the start compartment - * global non-configurable and non-writable, unless they are already - * non-configurable. - * - * It is critical that this function runs at the right time during - * initialization, which should always be immediately after `lockdown` has been - * called. At the time of writing, the modifications this function makes to the - * runtime environment appear to be non-breaking, but that could change with - * the addition of dependencies, or the order of our scripts in our HTML files. - * Exercise caution. - * - * See inline comments for implementation details. - * - * We write this function in IIFE format to avoid polluting global scope. - */ - (function protectIntrinsics() { - const namedIntrinsics = Reflect.ownKeys(new Compartment().globalThis); - - // These named intrinsics are not automatically hardened by `lockdown` - const shouldHardenManually = new Set(['eval', 'Function']); - - const globalProperties = new Set([ - // universalPropertyNames is a constant added by lockdown to global scope - // at the time of writing, it is initialized in 'ses/src/whitelist'. - // These properties tend to be non-enumerable. - ...namedIntrinsics, - - // TODO: Also include the named platform globals - // This grabs every enumerable property on globalThis. - // ...Object.keys(globalThis), - ]); - - globalProperties.forEach((propertyName) => { - const descriptor = Reflect.getOwnPropertyDescriptor( - globalThis, - propertyName, - ); - - if (descriptor) { - if (descriptor.configurable) { - // If the property on globalThis is configurable, make it - // non-configurable. If it has no accessor properties, also make it - // non-writable. - if (hasAccessor(descriptor)) { - Object.defineProperty(globalThis, propertyName, { - configurable: false, - }); - } else { - Object.defineProperty(globalThis, propertyName, { - configurable: false, - writable: false, - }); - } - } - - if (shouldHardenManually.has(propertyName)) { - harden(globalThis[propertyName]); - } - } - }); - - /** - * Checks whether the given propertyName descriptor has any accessors, i.e. the - * properties `get` or `set`. - * - * We want to make globals non-writable, and we can't set the `writable` - * property and accessor properties at the same time. - * - * @param {Object} descriptor - The propertyName descriptor to check. - * @returns {boolean} Whether the propertyName descriptor has any accessors. - */ - function hasAccessor(descriptor) { - return 'set' in descriptor || 'get' in descriptor; - } - })(); -} catch (error) { - console.error('Protecting intrinsics failed:', error); - if (globalThis.sentry && globalThis.sentry.captureException) { - globalThis.sentry.captureException( - new Error(`Protecting intrinsics failed: ${error.message}`), - ); - } -} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index ae05d10d8..f28c16bf3 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -32,6 +32,7 @@ import { TRANSACTION_STATUSES } from '../../shared/constants/transaction'; import { GAS_API_BASE_URL, GAS_DEV_API_BASE_URL, + SWAPS_CLIENT_ID, } from '../../shared/constants/swaps'; import { MAINNET_CHAIN_ID } from '../../shared/constants/network'; import { KEYRING_TYPES } from '../../shared/constants/hardware-wallets'; @@ -201,6 +202,7 @@ export default class MetamaskController extends EventEmitter { this.gasFeeController = new GasFeeController({ interval: 10000, messenger: gasFeeMessenger, + clientId: SWAPS_CLIENT_ID, getProvider: () => this.networkController.getProviderAndBlockTracker().provider, onNetworkStateChange: this.networkController.on.bind( @@ -362,7 +364,6 @@ export default class MetamaskController extends EventEmitter { this.onboardingController = new OnboardingController({ initState: initState.OnboardingController, - preferencesController: this.preferencesController, }); this.tokensController.hub.on('pendingSuggestedAsset', async () => { @@ -378,7 +379,7 @@ export default class MetamaskController extends EventEmitter { this.keyringController.memStore.subscribe((state) => this._onKeyringControllerUpdate(state), ); - this.keyringController.on('unlock', () => this.emit('unlock')); + this.keyringController.on('unlock', () => this._onUnlock()); this.keyringController.on('lock', () => this._onLock()); this.permissionsController = new PermissionsController( @@ -627,7 +628,7 @@ export default class MetamaskController extends EventEmitter { if ( password && !this.isUnlocked() && - this.onboardingController.completedOnboarding + this.onboardingController.store.getState().completedOnboarding ) { this.submitPassword(password); } @@ -818,7 +819,6 @@ export default class MetamaskController extends EventEmitter { ), setIpfsGateway: this.setIpfsGateway.bind(this), setParticipateInMetaMetrics: this.setParticipateInMetaMetrics.bind(this), - setFirstTimeFlowType: this.setFirstTimeFlowType.bind(this), setCurrentLocale: this.setCurrentLocale.bind(this), markPasswordForgotten: this.markPasswordForgotten.bind(this), unMarkPasswordForgotten: this.unMarkPasswordForgotten.bind(this), @@ -897,10 +897,7 @@ export default class MetamaskController extends EventEmitter { preferencesController.setPreference, preferencesController, ), - completeOnboarding: nodeify( - preferencesController.completeOnboarding, - preferencesController, - ), + addKnownMethodData: nodeify( preferencesController.addKnownMethodData, preferencesController, @@ -1001,6 +998,14 @@ export default class MetamaskController extends EventEmitter { onboardingController.setSeedPhraseBackedUp, onboardingController, ), + completeOnboarding: nodeify( + onboardingController.completeOnboarding, + onboardingController, + ), + setFirstTimeFlowType: nodeify( + onboardingController.setFirstTimeFlowType, + onboardingController, + ), // alert controller setAlertEnabledness: nodeify( @@ -2624,10 +2629,10 @@ export default class MetamaskController extends EventEmitter { ? (origin) => payload(origin) : () => payload; - Object.values(this.connections).forEach((origin) => { - Object.values(origin).forEach((conn) => { + Object.keys(this.connections).forEach((origin) => { + Object.values(this.connections[origin]).forEach(async (conn) => { if (conn.engine) { - conn.engine.emit('notification', getPayload(origin)); + conn.engine.emit('notification', await getPayload(origin)); } }); }); @@ -2662,12 +2667,12 @@ export default class MetamaskController extends EventEmitter { * Notifies all connections that the extension is unlocked. */ _onUnlock() { - this.notifyAllConnections((origin) => { + this.notifyAllConnections(async (origin) => { return { method: NOTIFICATION_NAMES.unlockStateChanged, params: { isUnlocked: true, - accounts: this.permissionsController.getAccounts(origin), + accounts: await this.permissionsController.getAccounts(origin), }, }; }); @@ -3015,23 +3020,6 @@ export default class MetamaskController extends EventEmitter { } } - /** - * Sets the type of first time flow the user wishes to follow: create or import - * @param {string} type - Indicates the type of first time flow the user wishes to follow - * @param {Function} cb - A callback function called when complete. - */ - setFirstTimeFlowType(type, cb) { - try { - this.preferencesController.setFirstTimeFlowType(type); - cb(null); - return; - } catch (err) { - cb(err); - // eslint-disable-next-line no-useless-return - return; - } - } - /** * A method for setting a user's current locale, affecting the language rendered. * @param {string} key - Locale identifier. diff --git a/app/scripts/metamask-controller.test.js b/app/scripts/metamask-controller.test.js index 61995363e..f91176858 100644 --- a/app/scripts/metamask-controller.test.js +++ b/app/scripts/metamask-controller.test.js @@ -9,6 +9,7 @@ import proxyquire from 'proxyquire'; import { TRANSACTION_STATUSES } from '../../shared/constants/transaction'; import createTxMeta from '../../test/lib/createTxMeta'; import { NETWORK_TYPE_RPC } from '../../shared/constants/network'; +import { KEYRING_TYPES } from '../../shared/constants/hardware-wallets'; import { addHexPrefix } from './lib/util'; const Ganache = require('../../test/e2e/ganache'); @@ -506,11 +507,11 @@ describe('MetaMaskController', function () { sinon.spy(metamaskController.keyringController, 'addNewKeyring'); await metamaskController.connectHardware('trezor', 0).catch(() => null); const keyrings = await metamaskController.keyringController.getKeyringsByType( - 'Trezor Hardware', + KEYRING_TYPES.TREZOR, ); assert.deepEqual( metamaskController.keyringController.addNewKeyring.getCall(0).args, - ['Trezor Hardware'], + [KEYRING_TYPES.TREZOR], ); assert.equal(keyrings.length, 1); }); @@ -519,11 +520,11 @@ describe('MetaMaskController', function () { sinon.spy(metamaskController.keyringController, 'addNewKeyring'); await metamaskController.connectHardware('ledger', 0).catch(() => null); const keyrings = await metamaskController.keyringController.getKeyringsByType( - 'Ledger Hardware', + KEYRING_TYPES.LEDGER, ); assert.deepEqual( metamaskController.keyringController.addNewKeyring.getCall(0).args, - ['Ledger Hardware'], + [KEYRING_TYPES.LEDGER], ); assert.equal(keyrings.length, 1); }); @@ -567,7 +568,7 @@ describe('MetaMaskController', function () { await metamaskController.connectHardware('trezor', 0).catch(() => null); await metamaskController.forgetDevice('trezor'); const keyrings = await metamaskController.keyringController.getKeyringsByType( - 'Trezor Hardware', + KEYRING_TYPES.TREZOR, ); assert.deepEqual(keyrings[0].accounts, []); @@ -626,7 +627,7 @@ describe('MetaMaskController', function () { it('should set unlockedAccount in the keyring', async function () { const keyrings = await metamaskController.keyringController.getKeyringsByType( - 'Trezor Hardware', + KEYRING_TYPES.TREZOR, ); assert.equal(keyrings[0].unlockedAccount, accountToUnlock); }); diff --git a/app/scripts/migrations/065.js b/app/scripts/migrations/065.js new file mode 100644 index 000000000..96e9820e1 --- /dev/null +++ b/app/scripts/migrations/065.js @@ -0,0 +1,39 @@ +import { cloneDeep } from 'lodash'; + +const version = 65; + +/** + * Removes metaMetricsSendCount from MetaMetrics controller + */ +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) { + if (state.PreferencesController) { + const { + completedOnboarding, + firstTimeFlowType, + } = state.PreferencesController; + state.OnboardingController = state.OnboardingController ?? {}; + + if (completedOnboarding !== undefined) { + state.OnboardingController.completedOnboarding = completedOnboarding; + delete state.PreferencesController.completedOnboarding; + } + if (firstTimeFlowType !== undefined) { + state.OnboardingController.firstTimeFlowType = firstTimeFlowType; + delete state.PreferencesController.firstTimeFlowType; + } + } + + return state; +} diff --git a/app/scripts/migrations/065.test.js b/app/scripts/migrations/065.test.js new file mode 100644 index 000000000..712e90e49 --- /dev/null +++ b/app/scripts/migrations/065.test.js @@ -0,0 +1,145 @@ +import migration65 from './065'; + +describe('migration #65', () => { + it('should update the version metadata', async () => { + const oldStorage = { + meta: { + version: 64, + }, + data: {}, + }; + + const newStorage = await migration65.migrate(oldStorage); + expect(newStorage.meta).toStrictEqual({ + version: 65, + }); + }); + + it('should move completedOnboarding from PreferencesController to OnboardingController when completedOnboarding is true', async () => { + const oldStorage = { + meta: {}, + data: { + PreferencesController: { + completedOnboarding: true, + bar: 'baz', + }, + OnboardingController: { + foo: 'bar', + }, + }, + }; + + const newStorage = await migration65.migrate(oldStorage); + expect(newStorage.data).toStrictEqual({ + PreferencesController: { + bar: 'baz', + }, + OnboardingController: { + completedOnboarding: true, + foo: 'bar', + }, + }); + }); + + it('should move completedOnboarding from PreferencesController to OnboardingController when completedOnboarding is false', async () => { + const oldStorage = { + meta: {}, + data: { + PreferencesController: { + completedOnboarding: false, + bar: 'baz', + }, + OnboardingController: { + foo: 'bar', + }, + }, + }; + + const newStorage = await migration65.migrate(oldStorage); + expect(newStorage.data).toStrictEqual({ + PreferencesController: { + bar: 'baz', + }, + OnboardingController: { + completedOnboarding: false, + foo: 'bar', + }, + }); + }); + + it('should move firstTimeFlowType from PreferencesController to OnboardingController when firstTimeFlowType is truthy', async () => { + const oldStorage = { + meta: {}, + data: { + PreferencesController: { + firstTimeFlowType: 'create', + bar: 'baz', + }, + OnboardingController: { + foo: 'bar', + }, + }, + }; + + const newStorage = await migration65.migrate(oldStorage); + expect(newStorage.data).toStrictEqual({ + PreferencesController: { + bar: 'baz', + }, + OnboardingController: { + firstTimeFlowType: 'create', + foo: 'bar', + }, + }); + }); + + it('should move firstTimeFlowType from PreferencesController to OnboardingController when firstTimeFlowType is falsy', async () => { + const oldStorage = { + meta: {}, + data: { + PreferencesController: { + firstTimeFlowType: null, + bar: 'baz', + }, + OnboardingController: { + foo: 'bar', + }, + }, + }; + + const newStorage = await migration65.migrate(oldStorage); + expect(newStorage.data).toStrictEqual({ + PreferencesController: { + bar: 'baz', + }, + OnboardingController: { + firstTimeFlowType: null, + foo: 'bar', + }, + }); + }); + + it('should not modify PreferencesController or OnboardingController when completedOnboarding and firstTimeFlowType are undefined', async () => { + const oldStorage = { + meta: {}, + data: { + PreferencesController: { + bar: 'baz', + }, + OnboardingController: { + foo: 'bar', + }, + }, + }; + + const newStorage = await migration65.migrate(oldStorage); + expect(newStorage.data).toStrictEqual({ + PreferencesController: { + bar: 'baz', + }, + OnboardingController: { + foo: 'bar', + }, + }); + }); +}); diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 8798a0529..6ca02a881 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -68,6 +68,7 @@ import m061 from './061'; import m062 from './062'; import m063 from './063'; import m064 from './064'; +import m065 from './065'; const migrations = [ m002, @@ -133,6 +134,7 @@ const migrations = [ m062, m063, m064, + m065, ]; export default migrations; diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index e8820d602..145e04c88 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -79,7 +79,36 @@ export default class ExtensionPlatform { } getVersion() { - return extension.runtime.getManifest().version; + const { + version, + version_name: versionName, + } = extension.runtime.getManifest(); + + const versionParts = version.split('.'); + if (versionName) { + // On Chrome, the build type is stored as `version_name` in the manifest, and the fourth part + // of the version is the build version. + const buildType = versionName; + if (versionParts.length < 4) { + throw new Error(`Version missing build number: '${version}'`); + } + const [major, minor, patch, buildVersion] = versionParts; + + return `${major}.${minor}.${patch}-${buildType}.${buildVersion}`; + } else if (versionParts.length === 4) { + // On Firefox, the build type and build version are in the fourth part of the version. + const [major, minor, patch, prerelease] = versionParts; + const matches = prerelease.match(/^(\w+)(\d)+$/u); + if (matches === null) { + throw new Error(`Version contains invalid prerelease: ${version}`); + } + const [, buildType, buildVersion] = matches; + return `${major}.${minor}.${patch}-${buildType}.${buildVersion}`; + } + + // If there is no `version_name` and there are only 3 version parts, then this is not a + // prerelease and the version requires no modification. + return version; } openExtensionInBrowser(route = null, queryString = null) { diff --git a/app/scripts/platforms/extension.test.js b/app/scripts/platforms/extension.test.js new file mode 100644 index 000000000..ea0b9914d --- /dev/null +++ b/app/scripts/platforms/extension.test.js @@ -0,0 +1,96 @@ +import extension from 'extensionizer'; +import ExtensionPlatform from './extension'; + +jest.mock('extensionizer', () => { + return { + runtime: { + getManifest: jest.fn(), + }, + }; +}); + +describe('extension platform', () => { + beforeEach(() => { + // TODO: Delete this an enable 'resetMocks' in `jest.config.js` instead + jest.resetAllMocks(); + }); + + describe('getVersion', () => { + it('should return non-prerelease version', () => { + extension.runtime.getManifest.mockReturnValue({ version: '1.2.3' }); + const extensionPlatform = new ExtensionPlatform(); + + const version = extensionPlatform.getVersion(); + + expect(version).toBe('1.2.3'); + }); + + it('should return SemVer-formatted version for Chrome style manifest of prerelease', () => { + extension.runtime.getManifest.mockReturnValue({ + version: '1.2.3.0', + version_name: 'beta', + }); + const extensionPlatform = new ExtensionPlatform(); + + const version = extensionPlatform.getVersion(); + + expect(version).toBe('1.2.3-beta.0'); + }); + + it('should return SemVer-formatted version for Firefox style manifest of prerelease', () => { + extension.runtime.getManifest.mockReturnValue({ + version: '1.2.3.beta0', + }); + const extensionPlatform = new ExtensionPlatform(); + + const version = extensionPlatform.getVersion(); + + expect(version).toBe('1.2.3-beta.0'); + }); + + it('should throw error if build version is missing from Chrome style prerelease manifest', () => { + extension.runtime.getManifest.mockReturnValue({ + version: '1.2.3', + version_name: 'beta', + }); + const extensionPlatform = new ExtensionPlatform(); + + expect(() => extensionPlatform.getVersion()).toThrow( + 'Version missing build number:', + ); + }); + + it('should throw error if build type is missing from Chrome style prerelease manifest', () => { + extension.runtime.getManifest.mockReturnValue({ + version: '1.2.3.0', + }); + const extensionPlatform = new ExtensionPlatform(); + + expect(() => extensionPlatform.getVersion()).toThrow( + 'Version contains invalid prerelease:', + ); + }); + + it('should throw error if build version is missing from Firefox style prerelease manifest', () => { + extension.runtime.getManifest.mockReturnValue({ + version: '1.2.3.beta', + }); + const extensionPlatform = new ExtensionPlatform(); + + expect(() => extensionPlatform.getVersion()).toThrow( + 'Version contains invalid prerelease:', + ); + }); + + it('should throw error if build type is missing from Firefox style prerelease manifest', () => { + extension.runtime.getManifest.mockReturnValue({ + version: '1.2.3.0', + }); + const extensionPlatform = new ExtensionPlatform(); + + expect(() => extensionPlatform.getVersion()).toThrow( + 'Version contains invalid prerelease:', + ); + }); + }); +}); diff --git a/development/build/README.md b/development/build/README.md index 6c671be27..0e29f78ec 100644 --- a/development/build/README.md +++ b/development/build/README.md @@ -40,8 +40,6 @@ Commands: e2e tests. Options: - --beta-version If the build type is "beta", the beta version number. - [number] [default: 0] --build-type The "type" of build to create. One of: "beta", "main" [string] [default: "main"] --lint-fence-files Whether files with code fences should be linted after diff --git a/development/build/etc.js b/development/build/etc.js index c30bbe9b8..f68da192a 100644 --- a/development/build/etc.js +++ b/development/build/etc.js @@ -5,17 +5,12 @@ const del = require('del'); const pify = require('pify'); const pump = pify(require('pump')); const { version } = require('../../package.json'); - const { createTask, composeParallel } = require('./task'); +const { BuildTypes } = require('./utils'); module.exports = createEtcTasks; -function createEtcTasks({ - betaVersionsMap, - browserPlatforms, - isBeta, - livereload, -}) { +function createEtcTasks({ browserPlatforms, buildType, livereload }) { const clean = createTask('clean', async function clean() { await del(['./dist/*']); await Promise.all( @@ -33,20 +28,19 @@ function createEtcTasks({ const zip = createTask( 'zip', composeParallel( - ...browserPlatforms.map((platform) => - createZipTask(platform, isBeta ? betaVersionsMap[platform] : undefined), - ), + ...browserPlatforms.map((platform) => createZipTask(platform, buildType)), ), ); return { clean, reload, zip }; } -function createZipTask(platform, betaVersion) { +function createZipTask(platform, buildType) { return async () => { - const path = betaVersion - ? `metamask-BETA-${platform}-${betaVersion}` - : `metamask-${platform}-${version}`; + const path = + buildType === BuildTypes.main + ? `metamask-${platform}-${version}` + : `metamask-${buildType}-${platform}-${version}`; await pump( gulp.src(`dist/${platform}/**`), gulpZip(`${path}.zip`), diff --git a/development/build/index.js b/development/build/index.js index 01c9b50da..cbea6e799 100755 --- a/development/build/index.js +++ b/development/build/index.js @@ -5,7 +5,6 @@ // const livereload = require('gulp-livereload'); const minimist = require('minimist'); -const { version } = require('../../package.json'); const { createTask, composeSeries, @@ -17,7 +16,7 @@ const createScriptTasks = require('./scripts'); const createStyleTasks = require('./styles'); const createStaticAssetTasks = require('./static'); const createEtcTasks = require('./etc'); -const { BuildTypes, getNextBetaVersionMap } = require('./utils'); +const { BuildTypes, getBrowserVersionMap } = require('./utils'); // packages required dynamically via browserify configuration in dependencies require('loose-envify'); @@ -34,10 +33,8 @@ defineAndRunBuildTasks(); function defineAndRunBuildTasks() { const { - betaVersion, buildType, entryTask, - isBeta, isLavaMoat, shouldIncludeLockdown, shouldLintFenceFiles, @@ -46,26 +43,19 @@ function defineAndRunBuildTasks() { const browserPlatforms = ['firefox', 'chrome', 'brave', 'opera']; - let betaVersionsMap; - if (isBeta) { - betaVersionsMap = getNextBetaVersionMap( - version, - betaVersion, - browserPlatforms, - ); - } + const browserVersionMap = getBrowserVersionMap(browserPlatforms); const staticTasks = createStaticAssetTasks({ livereload, browserPlatforms, shouldIncludeLockdown, - isBeta, + buildType, }); const manifestTasks = createManifestTasks({ browserPlatforms, - betaVersionsMap, - isBeta, + browserVersionMap, + buildType, }); const styleTasks = createStyleTasks({ livereload }); @@ -81,8 +71,7 @@ function defineAndRunBuildTasks() { const { clean, reload, zip } = createEtcTasks({ livereload, browserPlatforms, - betaVersionsMap, - isBeta, + buildType, }); // build for development (livereload) @@ -146,7 +135,6 @@ function defineAndRunBuildTasks() { function parseArgv() { const NamedArgs = { - BetaVersion: 'beta-version', BuildType: 'build-type', LintFenceFiles: 'lint-fence-files', OmitLockdown: 'omit-lockdown', @@ -161,7 +149,6 @@ function parseArgv() { ], string: [NamedArgs.BuildType], default: { - [NamedArgs.BetaVersion]: 0, [NamedArgs.BuildType]: BuildTypes.main, [NamedArgs.LintFenceFiles]: true, [NamedArgs.OmitLockdown]: false, @@ -180,11 +167,6 @@ function parseArgv() { throw new Error('MetaMask build: No entry task specified.'); } - const betaVersion = argv[NamedArgs.BetaVersion]; - if (!Number.isInteger(betaVersion) || betaVersion < 0) { - throw new Error(`MetaMask build: Invalid beta version: "${betaVersion}"`); - } - const buildType = argv[NamedArgs.BuildType]; if (!(buildType in BuildTypes)) { throw new Error(`MetaMask build: Invalid build type: "${buildType}"`); @@ -198,10 +180,8 @@ function parseArgv() { : !/dev/iu.test(entryTask); return { - betaVersion: String(betaVersion), buildType, entryTask, - isBeta: argv[NamedArgs.BuildType] === BuildTypes.beta, isLavaMoat: process.argv[0].includes('lavamoat'), shouldIncludeLockdown: argv[NamedArgs.OmitLockdown], shouldLintFenceFiles, diff --git a/development/build/manifest.js b/development/build/manifest.js index 3e80ea5b5..e14c3d786 100644 --- a/development/build/manifest.js +++ b/development/build/manifest.js @@ -3,14 +3,18 @@ const path = require('path'); const { merge, cloneDeep } = require('lodash'); const baseManifest = require('../../app/manifest/_base.json'); -const { version } = require('../../package.json'); const betaManifestModifications = require('../../app/manifest/_beta_modifications.json'); const { createTask, composeSeries } = require('./task'); +const { BuildTypes } = require('./utils'); module.exports = createManifestTasks; -function createManifestTasks({ betaVersionsMap, browserPlatforms, isBeta }) { +function createManifestTasks({ + browserPlatforms, + browserVersionMap, + buildType, +}) { // merge base manifest with per-platform manifests const prepPlatforms = async () => { return Promise.all( @@ -28,9 +32,8 @@ function createManifestTasks({ betaVersionsMap, browserPlatforms, isBeta }) { const result = merge( cloneDeep(baseManifest), platformModifications, - isBeta - ? getBetaModifications(platform, betaVersionsMap) - : { version }, + browserVersionMap[platform], + getBuildModifications(buildType), ); const dir = path.join('.', 'dist', platform); await fs.mkdir(dir, { recursive: true }); @@ -109,16 +112,10 @@ async function writeJson(obj, file) { return fs.writeFile(file, JSON.stringify(obj, null, 2)); } -function getBetaModifications(platform, betaVersionsMap) { - if (!betaVersionsMap || typeof betaVersionsMap !== 'object') { - throw new Error('MetaMask build: Expected object beta versions map.'); +function getBuildModifications(buildType) { + const buildModifications = {}; + if (buildType === BuildTypes.beta) { + Object.assign(buildModifications, betaManifestModifications); } - - const betaVersion = betaVersionsMap[platform]; - - return { - ...betaManifestModifications, - version: betaVersion, - ...(platform === 'firefox' ? {} : { version_name: 'beta' }), - }; + return buildModifications; } diff --git a/development/build/scripts.js b/development/build/scripts.js index da7e73e26..e681be02f 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -4,6 +4,7 @@ const { writeFileSync, readFileSync } = require('fs'); const EventEmitter = require('events'); const gulp = require('gulp'); const watch = require('gulp-watch'); +const Vinyl = require('vinyl'); const source = require('vinyl-source-stream'); const buffer = require('vinyl-buffer'); const log = require('fancy-log'); @@ -20,13 +21,15 @@ const endOfStream = pify(require('end-of-stream')); const labeledStreamSplicer = require('labeled-stream-splicer').obj; const wrapInStream = require('pumpify').obj; const Sqrl = require('squirrelly'); -const lavaPack = require('@lavamoat/lavapack'); +const lavapack = require('@lavamoat/lavapack'); +const lavamoatBrowserify = require('lavamoat-browserify'); const terser = require('terser'); const bifyModuleGroups = require('bify-module-groups'); const metamaskrc = require('rc')('metamask', { INFURA_PROJECT_ID: process.env.INFURA_PROJECT_ID, + ONBOARDING_V2: process.env.ONBOARDING_V2, SEGMENT_HOST: process.env.SEGMENT_HOST, SEGMENT_WRITE_KEY: process.env.SEGMENT_WRITE_KEY, SEGMENT_LEGACY_WRITE_KEY: process.env.SEGMENT_LEGACY_WRITE_KEY, @@ -259,7 +262,22 @@ function createFactoredBuild({ // set bundle entries bundlerOpts.entries = [...entryFiles]; + // setup lavamoat + // lavamoat will add lavapack but it will be removed by bify-module-groups + // we will re-add it later by installing a lavapack runtime + const lavamoatOpts = { + policy: path.resolve(__dirname, '../../lavamoat/browserify/policy.json'), + policyOverride: path.resolve( + __dirname, + '../../lavamoat/browserify/policy-override.json', + ), + writeAutoPolicy: process.env.WRITE_AUTO_POLICY, + }; + Object.assign(bundlerOpts, lavamoatBrowserify.args); + bundlerOpts.plugin.push([lavamoatBrowserify, lavamoatOpts]); + // setup bundle factoring with bify-module-groups plugin + // note: this will remove lavapack, but its ok bc we manually readd it later Object.assign(bundlerOpts, bifyModuleGroups.plugin.args); bundlerOpts.plugin = [...bundlerOpts.plugin, [bifyModuleGroups.plugin]]; @@ -281,18 +299,24 @@ function createFactoredBuild({ groupingMap: sizeGroupMap, }), ); - pipeline.get('vinyl').unshift( - // convert each module group into a stream with a single vinyl file - streamFlatMap((moduleGroup) => { - const filename = `${moduleGroup.label}.js`; - const childStream = wrapInStream( - moduleGroup.stream, - lavaPack({ raw: true, hasExports: true, includePrelude: false }), - source(filename), - ); - return childStream; + // converts each module group into a single vinyl file containing its bundle + const moduleGroupPackerStream = streamFlatMap((moduleGroup) => { + const filename = `${moduleGroup.label}.js`; + const childStream = wrapInStream( + moduleGroup.stream, + // we manually readd lavapack here bc bify-module-groups removes it + lavapack({ raw: true, hasExports: true, includePrelude: false }), + source(filename), + ); + return childStream; + }); + pipeline.get('vinyl').unshift(moduleGroupPackerStream, buffer()); + // add lavamoat policy loader file to packer output + moduleGroupPackerStream.push( + new Vinyl({ + path: 'policy-load.js', + contents: lavapack.makePolicyLoaderStream(lavamoatOpts), }), - buffer(), ); // setup bundle destination browserPlatforms.forEach((platform) => { @@ -306,36 +330,58 @@ function createFactoredBuild({ const commonSet = sizeGroupMap.get('common'); // create entry points for each file for (const [groupLabel, groupSet] of sizeGroupMap.entries()) { - // skip "common" group, they are added tp all other groups + // skip "common" group, they are added to all other groups if (groupSet === commonSet) continue; switch (groupLabel) { case 'ui': { - renderHtmlFile('popup', groupSet, commonSet, browserPlatforms); - renderHtmlFile( - 'notification', + renderHtmlFile({ + htmlName: 'popup', groupSet, commonSet, browserPlatforms, - ); - renderHtmlFile('home', groupSet, commonSet, browserPlatforms); + useLavamoat: false, + }); + renderHtmlFile({ + htmlName: 'notification', + groupSet, + commonSet, + browserPlatforms, + useLavamoat: false, + }); + renderHtmlFile({ + htmlName: 'home', + groupSet, + commonSet, + browserPlatforms, + useLavamoat: false, + }); break; } case 'background': { - renderHtmlFile('background', groupSet, commonSet, browserPlatforms); + renderHtmlFile({ + htmlName: 'background', + groupSet, + commonSet, + browserPlatforms, + useLavamoat: false, + }); break; } case 'content-script': { - renderHtmlFile( - 'trezor-usb-permissions', + renderHtmlFile({ + htmlName: 'trezor-usb-permissions', groupSet, commonSet, browserPlatforms, - ); + useLavamoat: false, + }); break; } default: { - throw new Error(`buildsys - unknown groupLabel "${groupLabel}"`); + throw new Error( + `build/scripts - unknown groupLabel "${groupLabel}"`, + ); } } } @@ -612,6 +658,7 @@ function getEnvironmentVariables({ buildType, devMode, testing }) { ? process.env.SEGMENT_PROD_LEGACY_WRITE_KEY : metamaskrc.SEGMENT_LEGACY_WRITE_KEY, SWAPS_USE_DEV_APIS: process.env.SWAPS_USE_DEV_APIS === '1', + ONBOARDING_V2: metamaskrc.ONBOARDING_V2 === '1', }; } @@ -635,13 +682,24 @@ function getEnvironment({ devMode, testing }) { return 'other'; } -function renderHtmlFile(htmlName, groupSet, commonSet, browserPlatforms) { +function renderHtmlFile({ + htmlName, + groupSet, + commonSet, + browserPlatforms, + useLavamoat, +}) { + if (useLavamoat === undefined) { + throw new Error( + 'build/scripts/renderHtmlFile - must specify "useLavamoat" option', + ); + } const htmlFilePath = `./app/${htmlName}.html`; const htmlTemplate = readFileSync(htmlFilePath, 'utf8'); const jsBundles = [...commonSet.values(), ...groupSet.values()].map( (label) => `./${label}.js`, ); - const htmlOutput = Sqrl.render(htmlTemplate, { jsBundles }); + const htmlOutput = Sqrl.render(htmlTemplate, { jsBundles, useLavamoat }); browserPlatforms.forEach((platform) => { const dest = `./dist/${platform}/${htmlName}.html`; // we dont have a way of creating async events atm diff --git a/development/build/static.js b/development/build/static.js index 341b7d56b..ecc12b249 100644 --- a/development/build/static.js +++ b/development/build/static.js @@ -6,6 +6,7 @@ const glob = require('fast-glob'); const locales = require('../../app/_locales/index.json'); const { createTask, composeSeries } = require('./task'); +const { BuildTypes } = require('./utils'); const EMPTY_JS_FILE = './development/empty.js'; @@ -13,26 +14,30 @@ module.exports = function createStaticAssetTasks({ livereload, browserPlatforms, shouldIncludeLockdown = true, - isBeta, + buildType, }) { const [copyTargetsProd, copyTargetsDev] = getCopyTargets( shouldIncludeLockdown, ); - const copyTargetsBeta = [ - ...copyTargetsProd, - { - src: './app/build-types/beta/', - dest: `images`, - }, - ]; - - const targets = isBeta ? copyTargetsBeta : copyTargetsProd; + const additionalBuildTargets = { + [BuildTypes.beta]: [ + { + src: './app/build-types/beta/', + dest: `images`, + }, + ], + }; + + if (Object.keys(additionalBuildTargets).includes(buildType)) { + copyTargetsProd.push(...additionalBuildTargets[buildType]); + copyTargetsDev.push(...additionalBuildTargets[buildType]); + } const prod = createTask( 'static:prod', composeSeries( - ...targets.map((target) => { + ...copyTargetsProd.map((target) => { return async function copyStaticAssets() { await performCopy(target); }; @@ -118,6 +123,10 @@ function getCopyTargets(shouldIncludeLockdown) { src: `./node_modules/@fortawesome/fontawesome-free/webfonts/`, dest: `fonts/fontawesome`, }, + { + src: `./node_modules/react-responsive-carousel/lib/styles`, + dest: 'react-gallery/', + }, { src: `./ui/css/output/`, pattern: `*.css`, @@ -143,11 +152,22 @@ function getCopyTargets(shouldIncludeLockdown) { : EMPTY_JS_FILE, dest: `lockdown-run.js`, }, + { + src: shouldIncludeLockdown + ? `./app/scripts/lockdown-more.js` + : EMPTY_JS_FILE, + dest: `lockdown-more.js`, + }, { // eslint-disable-next-line node/no-extraneous-require src: require.resolve('@lavamoat/lavapack/src/runtime-cjs.js'), dest: `runtime-cjs.js`, }, + { + // eslint-disable-next-line node/no-extraneous-require + src: require.resolve('@lavamoat/lavapack/src/runtime.js'), + dest: `runtime-lavamoat.js`, + }, { src: `./app/phishing.html`, dest: `phishing.html`, diff --git a/development/build/utils.js b/development/build/utils.js index 0b8503d19..4413ab899 100644 --- a/development/build/utils.js +++ b/development/build/utils.js @@ -1,32 +1,63 @@ +const semver = require('semver'); +const { version } = require('../../package.json'); + +const BuildTypes = { + beta: 'beta', + flask: 'flask', + main: 'main', +}; + /** - * @returns {Object} An object with browser as key and next version of beta - * as the value. E.g. { firefox: '9.6.0.beta0', chrome: '9.6.0.1' } + * Map the current version to a format that is compatible with each browser. + * + * The given version number is assumed to be a SemVer version number. Additionally, if the version + * has a prerelease component, it is assumed to have the format ". { - platformMap[platform] = [ - // Keeps the current major - major, - // Bump the minor version - Number(minor) + 1, - // This isn't typically used - 0, - // The beta number - `${platform === 'firefox' ? 'beta' : ''}${betaVersion}`, - ].join('.'); + const versionParts = [major, minor, patch]; + const browserSpecificVersion = {}; + if (prerelease) { + if (platform === 'firefox') { + versionParts.push(`${buildType}${buildVersion}`); + } else { + versionParts.push(buildVersion); + browserSpecificVersion.version_name = buildType; + } + } + browserSpecificVersion.version = versionParts.join('.'); + platformMap[platform] = browserSpecificVersion; return platformMap; }, {}); } -const BuildTypes = { - beta: 'beta', - flask: 'flask', - main: 'main', -}; - module.exports = { BuildTypes, - getNextBetaVersionMap, + getBrowserVersionMap, }; diff --git a/jest.config.js b/jest.config.js index 9c15faa41..9f87eb4d9 100644 --- a/jest.config.js +++ b/jest.config.js @@ -20,6 +20,7 @@ module.exports = { '/ui/**/*.test.js', '/shared/**/*.test.js', '/app/scripts/migrations/*.test.js', + '/app/scripts/platforms/*.test.js', ], testTimeout: 2500, }; diff --git a/lavamoat/browserify/policy-override.json b/lavamoat/browserify/policy-override.json new file mode 100644 index 000000000..71fd98f61 --- /dev/null +++ b/lavamoat/browserify/policy-override.json @@ -0,0 +1,55 @@ +{ + "resources": { + "browser-resolve": { + "packages": { + "core-js": true + } + }, + "babel-runtime": { + "packages": { + "@babel/runtime": true + } + }, + "node-fetch": { + "globals": { + "fetch": true + } + }, + "lodash": { + "globals": { + "setTimeout": true, + "clearTimeout": true + } + }, + "@ethersproject/random": { + "globals": { + "crypto.getRandomValues": true + } + }, + "browser-passworder": { + "globals": { + "crypto": true + } + }, + "randombytes": { + "globals": { + "crypto.getRandomValues": true + } + }, + "extensionizer": { + "globals": { + "console": true + } + }, + "web3": { + "globals": { + "XMLHttpRequest": true + } + }, + "storage": { + "globals": { + "localStorage": true + } + } + } +} diff --git a/lavamoat/browserify/policy.json b/lavamoat/browserify/policy.json new file mode 100644 index 000000000..b920f9059 --- /dev/null +++ b/lavamoat/browserify/policy.json @@ -0,0 +1,4688 @@ +{ + "resources": { + "3box": { + "globals": { + "console.error": true, + "console.log": true, + "console.warn": true, + "fetch": true, + "setTimeout": true + }, + "packages": { + "3box-orbitdb-plugins": true, + "3id-resolver": true, + "@babel/runtime": true, + "buffer": true, + "did-jwt": true, + "elliptic": true, + "ethers": true, + "graphql-request": true, + "https-did-resolver": true, + "ipfs": true, + "ipfs-did-document": true, + "ipfs-log": true, + "ipfs-mini": true, + "is-ipfs": true, + "js-sha256": true, + "multihashes": true, + "muport-did-resolver": true, + "node-fetch": true, + "orbit-db": true, + "orbit-db-access-controllers": true, + "orbit-db-identity-provider": true, + "orbit-db-pubsub": true, + "process": true, + "store": true, + "tweetnacl": true, + "tweetnacl-util": true + } + }, + "3box-orbitdb-plugins": { + "globals": { + "console.log": true + }, + "packages": { + "base64url": true, + "did-jwt": true, + "did-resolver": true, + "events": true, + "ipfs-log": true, + "is-ipfs": true, + "orbit-db-access-controllers": true, + "orbit-db-io": true, + "safe-buffer": true + } + }, + "3id-resolver": { + "packages": { + "@babel/runtime": true, + "base64url": true, + "did-jwt": true, + "did-resolver": true, + "ipfs-did-document": true + } + }, + "@babel/runtime": { + "packages": { + "regenerator-runtime": true + } + }, + "@download/blockies": { + "globals": { + "document.createElement": true + } + }, + "@ensdomains/content-hash": { + "globals": { + "console.warn": true + }, + "packages": { + "buffer": true, + "cids": true, + "js-base64": true, + "multicodec": true, + "multihashes": true + } + }, + "@ethereumjs/common": { + "packages": { + "buffer": true, + "crc-32": true, + "ethereumjs-util": true, + "events": true + } + }, + "@ethereumjs/tx": { + "packages": { + "@ethereumjs/common": true, + "buffer": true, + "ethereumjs-util": true, + "is-buffer": true + } + }, + "@ethersproject/abi": { + "globals": { + "console.log": true + }, + "packages": { + "@ethersproject/address": true, + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/constants": true, + "@ethersproject/hash": true, + "@ethersproject/keccak256": true, + "@ethersproject/logger": true, + "@ethersproject/properties": true, + "@ethersproject/strings": true + } + }, + "@ethersproject/abstract-provider": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/logger": true, + "@ethersproject/properties": true + } + }, + "@ethersproject/abstract-signer": { + "packages": { + "@ethersproject/logger": true, + "@ethersproject/properties": true + } + }, + "@ethersproject/address": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/keccak256": true, + "@ethersproject/logger": true, + "@ethersproject/rlp": true + } + }, + "@ethersproject/base64": { + "globals": { + "atob": true, + "btoa": true + }, + "packages": { + "@ethersproject/bytes": true + } + }, + "@ethersproject/basex": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/properties": true + } + }, + "@ethersproject/bignumber": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/logger": true, + "bn.js": true + } + }, + "@ethersproject/bytes": { + "packages": { + "@ethersproject/logger": true + } + }, + "@ethersproject/constants": { + "packages": { + "@ethersproject/bignumber": true + } + }, + "@ethersproject/contracts": { + "globals": { + "setTimeout": true + }, + "packages": { + "@ethersproject/abi": true, + "@ethersproject/abstract-provider": true, + "@ethersproject/abstract-signer": true, + "@ethersproject/address": true, + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/logger": true, + "@ethersproject/properties": true, + "@ethersproject/transactions": true + } + }, + "@ethersproject/hash": { + "packages": { + "@ethersproject/address": true, + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/keccak256": true, + "@ethersproject/logger": true, + "@ethersproject/properties": true, + "@ethersproject/strings": true + } + }, + "@ethersproject/hdnode": { + "packages": { + "@ethersproject/basex": true, + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/logger": true, + "@ethersproject/pbkdf2": true, + "@ethersproject/properties": true, + "@ethersproject/sha2": true, + "@ethersproject/signing-key": true, + "@ethersproject/strings": true, + "@ethersproject/transactions": true, + "@ethersproject/wordlists": true + } + }, + "@ethersproject/json-wallets": { + "packages": { + "@ethersproject/address": true, + "@ethersproject/bytes": true, + "@ethersproject/hdnode": true, + "@ethersproject/keccak256": true, + "@ethersproject/logger": true, + "@ethersproject/pbkdf2": true, + "@ethersproject/properties": true, + "@ethersproject/random": true, + "@ethersproject/strings": true, + "@ethersproject/transactions": true, + "aes-js": true, + "scrypt-js": true + } + }, + "@ethersproject/keccak256": { + "packages": { + "@ethersproject/bytes": true, + "js-sha3": true + } + }, + "@ethersproject/logger": { + "globals": { + "console": true + } + }, + "@ethersproject/networks": { + "packages": { + "@ethersproject/logger": true + } + }, + "@ethersproject/pbkdf2": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/sha2": true + } + }, + "@ethersproject/properties": { + "packages": { + "@ethersproject/logger": true + } + }, + "@ethersproject/providers": { + "globals": { + "WebSocket": true, + "clearInterval": true, + "clearTimeout": true, + "console.log": true, + "console.warn": true, + "name": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/abstract-provider": true, + "@ethersproject/abstract-signer": true, + "@ethersproject/address": true, + "@ethersproject/basex": true, + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/constants": true, + "@ethersproject/hash": true, + "@ethersproject/logger": true, + "@ethersproject/networks": true, + "@ethersproject/properties": true, + "@ethersproject/random": true, + "@ethersproject/sha2": true, + "@ethersproject/strings": true, + "@ethersproject/transactions": true, + "@ethersproject/web": true, + "bech32": true + } + }, + "@ethersproject/random": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/logger": true + } + }, + "@ethersproject/rlp": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/logger": true + } + }, + "@ethersproject/sha2": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/logger": true, + "hash.js": true + } + }, + "@ethersproject/signing-key": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/logger": true, + "@ethersproject/properties": true, + "elliptic": true + } + }, + "@ethersproject/solidity": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/keccak256": true, + "@ethersproject/sha2": true, + "@ethersproject/strings": true + } + }, + "@ethersproject/strings": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/constants": true, + "@ethersproject/logger": true + } + }, + "@ethersproject/transactions": { + "globals": { + "console.log": true + }, + "packages": { + "@ethersproject/address": true, + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/constants": true, + "@ethersproject/keccak256": true, + "@ethersproject/logger": true, + "@ethersproject/properties": true, + "@ethersproject/rlp": true, + "@ethersproject/signing-key": true + } + }, + "@ethersproject/units": { + "packages": { + "@ethersproject/bignumber": true, + "@ethersproject/logger": true + } + }, + "@ethersproject/wallet": { + "packages": { + "@ethersproject/abstract-provider": true, + "@ethersproject/abstract-signer": true, + "@ethersproject/address": true, + "@ethersproject/bytes": true, + "@ethersproject/hash": true, + "@ethersproject/hdnode": true, + "@ethersproject/json-wallets": true, + "@ethersproject/keccak256": true, + "@ethersproject/logger": true, + "@ethersproject/properties": true, + "@ethersproject/random": true, + "@ethersproject/signing-key": true, + "@ethersproject/transactions": true + } + }, + "@ethersproject/web": { + "globals": { + "clearTimeout": true, + "fetch": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/base64": true, + "@ethersproject/bytes": true, + "@ethersproject/logger": true, + "@ethersproject/properties": true, + "@ethersproject/strings": true + } + }, + "@ethersproject/wordlists": { + "packages": { + "@ethersproject/bytes": true, + "@ethersproject/hash": true, + "@ethersproject/logger": true, + "@ethersproject/properties": true, + "@ethersproject/strings": true + } + }, + "@formatjs/intl-relativetimeformat": { + "globals": { + "Intl": true + }, + "packages": { + "@formatjs/intl-utils": true + } + }, + "@formatjs/intl-utils": { + "globals": { + "Intl.getCanonicalLocales": true + } + }, + "@material-ui/core": { + "globals": { + "Image": true, + "_formatMuiErrorMessage": true, + "addEventListener": true, + "clearInterval": true, + "clearTimeout": true, + "console.error": true, + "console.warn": true, + "document": true, + "getComputedStyle": true, + "getSelection": true, + "innerHeight": true, + "innerWidth": true, + "matchMedia": true, + "navigator": true, + "performance.now": true, + "removeEventListener": true, + "requestAnimationFrame": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "@babel/runtime": true, + "@material-ui/styles": true, + "@material-ui/system": true, + "@material-ui/utils": true, + "clsx": true, + "hoist-non-react-statics": true, + "popper.js": true, + "prop-types": true, + "react": true, + "react-dom": true, + "react-is": true, + "react-transition-group": true + } + }, + "@material-ui/styles": { + "globals": { + "console.error": true, + "console.warn": true, + "document.createComment": true, + "document.head": true + }, + "packages": { + "@babel/runtime": true, + "@material-ui/utils": true, + "clsx": true, + "hoist-non-react-statics": true, + "jss": true, + "jss-plugin-camel-case": true, + "jss-plugin-default-unit": true, + "jss-plugin-global": true, + "jss-plugin-nested": true, + "jss-plugin-props-sort": true, + "jss-plugin-rule-value-function": true, + "jss-plugin-vendor-prefixer": true, + "prop-types": true, + "react": true + } + }, + "@material-ui/system": { + "globals": { + "console.error": true + }, + "packages": { + "@babel/runtime": true, + "@material-ui/utils": true, + "prop-types": true + } + }, + "@material-ui/utils": { + "packages": { + "@babel/runtime": true, + "prop-types": true, + "react-is": true + } + }, + "@metamask/controllers": { + "globals": { + "Headers": true, + "clearInterval": true, + "clearTimeout": true, + "console.error": true, + "console.log": true, + "fetch": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "@ethereumjs/common": true, + "@ethereumjs/tx": true, + "@metamask/contract-metadata": true, + "abort-controller": true, + "async-mutex": true, + "await-semaphore": true, + "buffer": true, + "eth-ens-namehash": true, + "eth-json-rpc-infura": true, + "eth-keyring-controller": true, + "eth-method-registry": true, + "eth-phishing-detect": true, + "eth-query": true, + "eth-rpc-errors": true, + "eth-sig-util": true, + "ethereumjs-tx": true, + "ethereumjs-util": true, + "ethereumjs-wallet": true, + "ethers": true, + "ethjs-query": true, + "ethjs-unit": true, + "ethjs-util": true, + "events": true, + "human-standard-collectible-abi": true, + "human-standard-token-abi": true, + "immer": true, + "isomorphic-fetch": true, + "jsonschema": true, + "nanoid": true, + "punycode": true, + "single-call-balance-checker-abi": true, + "uuid": true, + "web3": true, + "web3-provider-engine": true + } + }, + "@metamask/eth-ledger-bridge-keyring": { + "globals": { + "addEventListener": true, + "console.log": true, + "document.createElement": true, + "document.head.appendChild": true, + "fetch": true, + "removeEventListener": true + }, + "packages": { + "@ethereumjs/tx": true, + "buffer": true, + "eth-sig-util": true, + "ethereumjs-util": true, + "events": true, + "hdkey": true + } + }, + "@metamask/eth-token-tracker": { + "globals": { + "console.warn": true + }, + "packages": { + "@babel/runtime": true, + "deep-equal": true, + "eth-block-tracker": true, + "ethjs": true, + "ethjs-contract": true, + "ethjs-query": true, + "human-standard-token-abi": true, + "safe-event-emitter": true + } + }, + "@metamask/etherscan-link": { + "globals": { + "URL": true + } + }, + "@metamask/jazzicon": { + "globals": { + "document.createElement": true, + "document.createElementNS": true + }, + "packages": { + "color": true, + "mersenne-twister": true + } + }, + "@metamask/logo": { + "globals": { + "addEventListener": true, + "document.body.appendChild": true, + "document.createElementNS": true, + "innerHeight": true, + "innerWidth": true, + "requestAnimationFrame": true + }, + "packages": { + "gl-mat4": true, + "gl-vec3": true + } + }, + "@metamask/obs-store": { + "globals": { + "localStorage": true + }, + "packages": { + "@metamask/safe-event-emitter": true, + "stream-browserify": true, + "through2": true + } + }, + "@metamask/safe-event-emitter": { + "globals": { + "setTimeout": true + }, + "packages": { + "events": true + } + }, + "@popperjs/core": { + "globals": { + "Element": true, + "HTMLElement": true, + "ShadowRoot": true, + "console.error": true, + "console.warn": true, + "document": true, + "navigator.userAgent": true + } + }, + "@reduxjs/toolkit": { + "globals": { + "AbortController": true, + "__REDUX_DEVTOOLS_EXTENSION_COMPOSE__": true, + "__REDUX_DEVTOOLS_EXTENSION__": true, + "console.error": true, + "console.info": true, + "console.warn": true + }, + "packages": { + "immer": true, + "redux": true, + "redux-thunk": true, + "reselect": true + } + }, + "@segment/loosely-validate-event": { + "packages": { + "assert": true, + "buffer": true, + "component-type": true, + "join-component": true + } + }, + "@sentry/browser": { + "globals": { + "XMLHttpRequest": true, + "document.body": true, + "document.createElement": true, + "document.head": true, + "setTimeout": true + }, + "packages": { + "@sentry/core": true, + "@sentry/types": true, + "@sentry/utils": true, + "tslib": true + } + }, + "@sentry/core": { + "globals": { + "clearInterval": true, + "setInterval": true + }, + "packages": { + "@sentry/hub": true, + "@sentry/minimal": true, + "@sentry/types": true, + "@sentry/utils": true, + "tslib": true + } + }, + "@sentry/hub": { + "globals": { + "setTimeout": true + }, + "packages": { + "@sentry/utils": true, + "tslib": true + } + }, + "@sentry/integrations": { + "globals": { + "clearTimeout": true, + "console.error": true, + "console.log": true, + "setTimeout": true + }, + "packages": { + "@sentry/types": true, + "@sentry/utils": true, + "localforage": true, + "tslib": true + } + }, + "@sentry/minimal": { + "packages": { + "@sentry/hub": true, + "tslib": true + } + }, + "@sentry/utils": { + "globals": { + "CustomEvent": true, + "DOMError": true, + "DOMException": true, + "Element": true, + "ErrorEvent": true, + "Event": true, + "Headers": true, + "Request": true, + "Response": true, + "XMLHttpRequest.prototype": true, + "clearTimeout": true, + "console.error": true, + "document": true, + "setTimeout": true + }, + "packages": { + "process": true, + "tslib": true + } + }, + "@sindresorhus/is": { + "packages": { + "is-buffer": true, + "util": true + } + }, + "@zxing/library": { + "globals": { + "TextDecoder": true, + "TextEncoder": true, + "btoa": true, + "clearTimeout": true, + "define": true, + "document.createElement": true, + "document.createElementNS": true, + "document.getElementById": true, + "navigator.mediaDevices.enumerateDevices": true, + "navigator.mediaDevices.getUserMedia": true, + "setTimeout": true + } + }, + "abort-controller": { + "globals": { + "AbortController": true + } + }, + "abstract-leveldown": { + "packages": { + "is-buffer": true, + "process": true, + "xtend": true + } + }, + "accounting": { + "globals": { + "define": true + } + }, + "aes-js": { + "globals": { + "define": true + } + }, + "analytics-node": { + "globals": { + "clearTimeout": true, + "console.log": true, + "setImmediate": true, + "setTimeout": true + }, + "packages": { + "@segment/loosely-validate-event": true, + "assert": true, + "axios": true, + "axios-retry": true, + "lodash.isstring": true, + "md5": true, + "ms": true, + "process": true, + "remove-trailing-slash": true, + "uuid": true + } + }, + "asap": { + "globals": { + "clearInterval": true, + "clearTimeout": true, + "document.createTextNode": true, + "setInterval": true, + "setTimeout": true + } + }, + "asn1.js": { + "packages": { + "bn.js": true, + "buffer": true, + "inherits": true, + "minimalistic-assert": true, + "vm-browserify": true + } + }, + "assemblyscript": { + "globals": { + "WebAssembly.Instance": true, + "WebAssembly.Module": true, + "WebAssembly.instantiateStreaming": true, + "console.log": true + } + }, + "assert": { + "globals": { + "Buffer": true + }, + "packages": { + "object-assign": true, + "util": true + } + }, + "async": { + "globals": { + "clearTimeout": true, + "setTimeout": true + }, + "packages": { + "lodash": true, + "process": true, + "timers-browserify": true + } + }, + "async-iterator-to-pull-stream": { + "packages": { + "get-iterator": true, + "pull-stream-to-async-iterator": true + } + }, + "async-iterator-to-stream": { + "packages": { + "process": true, + "readable-stream": true + } + }, + "async-mutex": { + "globals": { + "setTimeout": true + }, + "packages": { + "tslib": true + } + }, + "await-semaphore": { + "packages": { + "process": true, + "timers-browserify": true + } + }, + "axios": { + "globals": { + "FormData": true, + "URLSearchParams": true, + "XMLHttpRequest": true, + "btoa": true, + "console.warn": true, + "document": true, + "location.href": true, + "navigator": true, + "setTimeout": true + }, + "packages": { + "process": true + } + }, + "axios-retry": { + "globals": { + "setTimeout": true + }, + "packages": { + "is-retry-allowed": true + } + }, + "babel-runtime": { + "packages": { + "core-js": true, + "regenerator-runtime": true + } + }, + "backoff": { + "globals": { + "clearTimeout": true, + "setTimeout": true + }, + "packages": { + "events": true, + "precond": true, + "util": true + } + }, + "base-x": { + "packages": { + "safe-buffer": true + } + }, + "base32-encode": { + "packages": { + "to-data-view": true + } + }, + "base64url": { + "packages": { + "buffer": true + } + }, + "bignumber.js": { + "globals": { + "crypto": true, + "define": true + }, + "packages": { + "crypto-browserify": true + } + }, + "bip39": { + "packages": { + "create-hash": true, + "pbkdf2": true, + "randombytes": true, + "safe-buffer": true, + "unorm": true + } + }, + "bip66": { + "packages": { + "safe-buffer": true + } + }, + "bl": { + "packages": { + "buffer": true, + "readable-stream": true, + "util": true + } + }, + "blakejs": { + "globals": { + "console.log": true + }, + "packages": { + "buffer": true + } + }, + "blob": { + "globals": { + "Blob": true, + "MSBlobBuilder": true, + "MozBlobBuilder": true, + "WebKitBlobBuilder": true + } + }, + "bn.js": { + "packages": { + "browser-resolve": true + } + }, + "borc": { + "globals": { + "console": true + }, + "packages": { + "bignumber.js": true, + "buffer": true, + "ieee754": true, + "iso-url": true + } + }, + "brorand": { + "globals": { + "crypto": true, + "msCrypto": true + }, + "packages": { + "browser-resolve": true + } + }, + "browser-passworder": { + "globals": { + "btoa": true, + "crypto.getRandomValues": true, + "crypto.subtle.decrypt": true, + "crypto.subtle.deriveKey": true, + "crypto.subtle.encrypt": true, + "crypto.subtle.importKey": true + }, + "packages": { + "browserify-unibabel": true + } + }, + "browserify-aes": { + "packages": { + "buffer": true, + "buffer-xor": true, + "cipher-base": true, + "evp_bytestokey": true, + "inherits": true, + "safe-buffer": true + } + }, + "browserify-cipher": { + "packages": { + "browserify-aes": true, + "browserify-des": true, + "evp_bytestokey": true + } + }, + "browserify-des": { + "packages": { + "buffer": true, + "cipher-base": true, + "des.js": true, + "inherits": true + } + }, + "browserify-rsa": { + "packages": { + "bn.js": true, + "buffer": true, + "randombytes": true + } + }, + "browserify-sign": { + "packages": { + "bn.js": true, + "browserify-rsa": true, + "buffer": true, + "create-hash": true, + "create-hmac": true, + "elliptic": true, + "inherits": true, + "parse-asn1": true, + "stream-browserify": true + } + }, + "browserify-unibabel": { + "globals": { + "atob": true, + "btoa": true + } + }, + "bs58": { + "packages": { + "base-x": true + } + }, + "bs58check": { + "packages": { + "bs58": true, + "create-hash": true, + "safe-buffer": true + } + }, + "btoa": { + "packages": { + "buffer": true + } + }, + "buffer": { + "globals": { + "console": true + }, + "packages": { + "base64-js": true, + "ieee754": true + } + }, + "buffer-split": { + "packages": { + "buffer-indexof": true + } + }, + "buffer-xor": { + "packages": { + "buffer": true + } + }, + "cids": { + "packages": { + "buffer": true, + "class-is": true, + "is-buffer": true, + "multibase": true, + "multicodec": true, + "multihashes": true, + "uint8arrays": true + } + }, + "cipher-base": { + "packages": { + "inherits": true, + "safe-buffer": true, + "stream-browserify": true, + "string_decoder": true + } + }, + "classnames": { + "globals": { + "classNames": "write", + "define": true + } + }, + "clone": { + "packages": { + "buffer": true + } + }, + "coinstring": { + "packages": { + "bs58": true, + "buffer": true, + "create-hash": true + } + }, + "color": { + "packages": { + "clone": true, + "color-convert": true, + "color-string": true + } + }, + "color-convert": { + "packages": { + "color-name": true + } + }, + "color-string": { + "packages": { + "color-name": true + } + }, + "cookiejar": { + "globals": { + "console.warn": true + } + }, + "copy-to-clipboard": { + "globals": { + "clipboardData.setData": true, + "console.error": true, + "console.warn": true, + "document.body.appendChild": true, + "document.body.removeChild": true, + "document.createElement": true, + "document.createRange": true, + "document.execCommand": true, + "document.getSelection": true, + "navigator.userAgent": true, + "prompt": true + }, + "packages": { + "toggle-selection": true + } + }, + "core-js": { + "globals": { + "PromiseRejectionEvent": true, + "__e": "write", + "__g": "write", + "document.createTextNode": true, + "postMessage": true, + "setTimeout": true + } + }, + "core-util-is": { + "packages": { + "is-buffer": true + } + }, + "crc-32": { + "globals": { + "DO_NOT_EXPORT_CRC": true, + "define": true + } + }, + "create-ecdh": { + "packages": { + "bn.js": true, + "buffer": true, + "elliptic": true + } + }, + "create-hash": { + "packages": { + "cipher-base": true, + "inherits": true, + "md5.js": true, + "ripemd160": true, + "sha.js": true + } + }, + "create-hmac": { + "packages": { + "cipher-base": true, + "create-hash": true, + "inherits": true, + "ripemd160": true, + "safe-buffer": true, + "sha.js": true + } + }, + "cross-fetch": { + "globals": { + "Blob": true, + "FileReader": true, + "FormData": true, + "URLSearchParams.prototype.isPrototypeOf": true, + "XMLHttpRequest": true + } + }, + "crypto-browserify": { + "packages": { + "browserify-cipher": true, + "browserify-sign": true, + "create-ecdh": true, + "create-hash": true, + "create-hmac": true, + "diffie-hellman": true, + "pbkdf2": true, + "public-encrypt": true, + "randombytes": true, + "randomfill": true + } + }, + "crypto-js": { + "globals": { + "define": true + } + }, + "css-vendor": { + "globals": { + "document.createElement": true, + "document.documentElement": true, + "getComputedStyle": true + }, + "packages": { + "@babel/runtime": true, + "is-in-browser": true + } + }, + "currency-formatter": { + "packages": { + "accounting": true, + "locale-currency": true, + "object-assign": true + } + }, + "data-queue": { + "packages": { + "events": true + } + }, + "datastore-core": { + "packages": { + "async": true, + "buffer": true, + "interface-datastore": true, + "pull-many": true, + "pull-stream": true + } + }, + "datastore-level": { + "packages": { + "buffer": true, + "encoding-down": true, + "interface-datastore": true, + "level-js": true, + "levelup": true, + "pull-stream": true + } + }, + "datastore-pubsub": { + "packages": { + "assert": true, + "buffer": true, + "debug": true, + "err-code": true, + "interface-datastore": true, + "multibase": true + } + }, + "debounce": { + "globals": { + "clearTimeout": true, + "setTimeout": true + } + }, + "debounce-stream": { + "packages": { + "debounce": true, + "duplexer": true, + "through": true + } + }, + "debug": { + "globals": { + "chrome": true, + "console": true, + "document": true, + "localStorage": true, + "navigator": true, + "process": true + }, + "packages": { + "ms": true, + "process": true + } + }, + "deep-equal": { + "packages": { + "is-arguments": true, + "is-date-object": true, + "is-regex": true, + "object-is": true, + "object-keys": true, + "regexp.prototype.flags": true + } + }, + "deep-extend": { + "packages": { + "buffer": true + } + }, + "deferred-leveldown": { + "packages": { + "abstract-leveldown": true, + "inherits": true + } + }, + "define-properties": { + "packages": { + "object-keys": true + } + }, + "des.js": { + "packages": { + "inherits": true, + "minimalistic-assert": true + } + }, + "did-jwt": { + "packages": { + "@babel/runtime": true, + "@stablelib/utf8": true, + "base64url": true, + "buffer": true, + "did-resolver": true, + "elliptic": true, + "js-sha256": true, + "js-sha3": true, + "tweetnacl": true, + "tweetnacl-util": true, + "uport-base64url": true + } + }, + "diffie-hellman": { + "packages": { + "bn.js": true, + "buffer": true, + "miller-rabin": true, + "randombytes": true + } + }, + "dlv": { + "globals": { + "define": true + } + }, + "dnd-core": { + "packages": { + "asap": true, + "invariant": true, + "lodash": true, + "redux": true + } + }, + "dom-helpers": { + "globals": { + "document": true, + "setTimeout": true + }, + "packages": { + "@babel/runtime": true + } + }, + "drbg.js": { + "packages": { + "buffer": true, + "create-hmac": true + } + }, + "duplexer": { + "packages": { + "stream-browserify": true + } + }, + "elliptic": { + "packages": { + "bn.js": true, + "brorand": true, + "hash.js": true, + "hmac-drbg": true, + "inherits": true, + "minimalistic-assert": true, + "minimalistic-crypto-utils": true + } + }, + "encoding-down": { + "packages": { + "abstract-leveldown": true, + "inherits": true, + "level-codec": true, + "level-errors": true + } + }, + "end-of-stream": { + "packages": { + "once": true, + "process": true + } + }, + "engine.io-client": { + "globals": { + "MozWebSocket": true, + "WebSocket": true, + "XDomainRequest": true, + "XMLHttpRequest": true, + "addEventListener": true, + "attachEvent": true, + "clearTimeout": true, + "document": true, + "location": true, + "navigator": true, + "setTimeout": true + }, + "packages": { + "browser-resolve": true, + "buffer": true, + "component-emitter": true, + "component-inherit": true, + "debug": true, + "engine.io-parser": true, + "has-cors": true, + "indexof": true, + "parseqs": true, + "parseuri": true, + "yeast": true + } + }, + "engine.io-parser": { + "globals": { + "FileReader": true, + "btoa": true, + "navigator": true + }, + "packages": { + "after": true, + "arraybuffer.slice": true, + "base64-arraybuffer": true, + "blob": true, + "has-binary2": true + } + }, + "errno": { + "packages": { + "prr": true + } + }, + "es-abstract": { + "packages": { + "function-bind": true, + "has-symbols": true + } + }, + "eth-block-tracker": { + "globals": { + "clearTimeout": true, + "console.error": true, + "setTimeout": true + }, + "packages": { + "@metamask/safe-event-emitter": true, + "eth-query": true, + "json-rpc-random-id": true, + "pify": true, + "safe-event-emitter": true + } + }, + "eth-ens-namehash": { + "globals": { + "name": "write" + }, + "packages": { + "buffer": true, + "idna-uts46": true, + "idna-uts46-hx": true, + "js-sha3": true + } + }, + "eth-hd-keyring": { + "packages": { + "bip39": true, + "eth-sig-util": true, + "eth-simple-keyring": true, + "ethereumjs-wallet": true + } + }, + "eth-json-rpc-filters": { + "globals": { + "console.error": true, + "results": "write" + }, + "packages": { + "await-semaphore": true, + "eth-json-rpc-middleware": true, + "eth-query": true, + "json-rpc-engine": true, + "lodash.flatmap": true, + "pify": true, + "safe-event-emitter": true + } + }, + "eth-json-rpc-infura": { + "globals": { + "setTimeout": true + }, + "packages": { + "eth-json-rpc-middleware": true, + "eth-rpc-errors": true, + "json-rpc-engine": true, + "node-fetch": true + } + }, + "eth-json-rpc-middleware": { + "globals": { + "console.error": true, + "fetch": true, + "setTimeout": true + }, + "packages": { + "btoa": true, + "clone": true, + "eth-rpc-errors": true, + "eth-sig-util": true, + "json-rpc-engine": true, + "json-stable-stringify": true, + "node-fetch": true, + "pify": true, + "safe-event-emitter": true, + "url": true + } + }, + "eth-keyring-controller": { + "packages": { + "bip39": true, + "browser-passworder": true, + "eth-hd-keyring": true, + "eth-sig-util": true, + "eth-simple-keyring": true, + "ethereumjs-util": true, + "events": true, + "loglevel": true, + "obs-store": true + } + }, + "eth-method-registry": { + "packages": { + "ethjs": true + } + }, + "eth-phishing-detect": { + "packages": { + "fast-levenshtein": true + } + }, + "eth-query": { + "packages": { + "json-rpc-random-id": true, + "xtend": true + } + }, + "eth-rpc-errors": { + "packages": { + "fast-safe-stringify": true + } + }, + "eth-sig-util": { + "packages": { + "buffer": true, + "ethereumjs-abi": true, + "ethereumjs-util": true, + "tweetnacl": true, + "tweetnacl-util": true + } + }, + "eth-simple-keyring": { + "packages": { + "buffer": true, + "eth-sig-util": true, + "ethereumjs-util": true, + "ethereumjs-wallet": true, + "events": true + } + }, + "eth-trezor-keyring": { + "globals": { + "setTimeout": true + }, + "packages": { + "@ethereumjs/tx": true, + "buffer": true, + "ethereumjs-util": true, + "events": true, + "hdkey": true, + "trezor-connect": true + } + }, + "ethereum-cryptography": { + "packages": { + "assert": true, + "bs58check": true, + "buffer": true, + "create-hmac": true, + "hash.js": true, + "keccak": true, + "randombytes": true, + "safe-buffer": true, + "secp256k1": true + } + }, + "ethereumjs-abi": { + "packages": { + "bn.js": true, + "buffer": true, + "ethereumjs-util": true + } + }, + "ethereumjs-tx": { + "packages": { + "buffer": true, + "ethereum-common": true, + "ethereumjs-util": true + } + }, + "ethereumjs-util": { + "packages": { + "assert": true, + "bn.js": true, + "buffer": true, + "create-hash": true, + "elliptic": true, + "ethereum-cryptography": true, + "ethjs-util": true, + "is-buffer": true, + "keccak": true, + "rlp": true, + "safe-buffer": true, + "secp256k1": true + } + }, + "ethereumjs-wallet": { + "packages": { + "aes-js": true, + "bs58check": true, + "buffer": true, + "crypto-browserify": true, + "ethereum-cryptography": true, + "ethereumjs-util": true, + "randombytes": true, + "safe-buffer": true, + "scrypt-js": true, + "scryptsy": true, + "utf8": true, + "uuid": true + } + }, + "ethers": { + "globals": { + "MessageChannel": true, + "XMLHttpRequest": true, + "atob": true, + "btoa": true, + "clearInterval": true, + "clearTimeout": true, + "console": true, + "crypto.getRandomValues": true, + "define": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "@ethersproject/abi": true, + "@ethersproject/abstract-signer": true, + "@ethersproject/address": true, + "@ethersproject/base64": true, + "@ethersproject/basex": true, + "@ethersproject/bignumber": true, + "@ethersproject/bytes": true, + "@ethersproject/constants": true, + "@ethersproject/contracts": true, + "@ethersproject/hash": true, + "@ethersproject/hdnode": true, + "@ethersproject/json-wallets": true, + "@ethersproject/keccak256": true, + "@ethersproject/logger": true, + "@ethersproject/properties": true, + "@ethersproject/providers": true, + "@ethersproject/random": true, + "@ethersproject/rlp": true, + "@ethersproject/sha2": true, + "@ethersproject/signing-key": true, + "@ethersproject/solidity": true, + "@ethersproject/strings": true, + "@ethersproject/transactions": true, + "@ethersproject/units": true, + "@ethersproject/wallet": true, + "@ethersproject/web": true, + "@ethersproject/wordlists": true + } + }, + "ethjs": { + "globals": { + "clearInterval": true, + "setInterval": true + }, + "packages": { + "bn.js": true, + "buffer": true, + "ethjs-abi": true, + "ethjs-contract": true, + "ethjs-filter": true, + "ethjs-provider-http": true, + "ethjs-query": true, + "ethjs-unit": true, + "ethjs-util": true, + "js-sha3": true, + "number-to-bn": true + } + }, + "ethjs-abi": { + "packages": { + "bn.js": true, + "buffer": true, + "js-sha3": true, + "number-to-bn": true + } + }, + "ethjs-contract": { + "packages": { + "babel-runtime": true, + "ethjs-abi": true, + "ethjs-filter": true, + "ethjs-util": true, + "js-sha3": true, + "promise-to-callback": true + } + }, + "ethjs-ens": { + "packages": { + "eth-ens-namehash": true, + "ethereum-ens-network-map": true, + "ethjs-contract": true, + "ethjs-query": true + } + }, + "ethjs-filter": { + "globals": { + "clearInterval": true, + "setInterval": true + } + }, + "ethjs-format": { + "packages": { + "ethjs-schema": true, + "ethjs-util": true, + "number-to-bn": true, + "strip-hex-prefix": true + } + }, + "ethjs-provider-http": { + "packages": { + "xhr2": true + } + }, + "ethjs-query": { + "globals": { + "console": true + }, + "packages": { + "babel-runtime": true, + "ethjs-format": true, + "ethjs-rpc": true, + "promise-to-callback": true + } + }, + "ethjs-rpc": { + "packages": { + "promise-to-callback": true + } + }, + "ethjs-unit": { + "packages": { + "bn.js": true, + "number-to-bn": true + } + }, + "ethjs-util": { + "packages": { + "buffer": true, + "is-hex-prefixed": true, + "strip-hex-prefix": true + } + }, + "events": { + "globals": { + "console": true + } + }, + "evp_bytestokey": { + "packages": { + "md5.js": true, + "safe-buffer": true + } + }, + "extension-port-stream": { + "packages": { + "buffer": true, + "stream-browserify": true + } + }, + "extensionizer": { + "globals": { + "browser": true, + "chrome": true + } + }, + "fast-json-patch": { + "globals": { + "addEventListener": true, + "clearTimeout": true, + "removeEventListener": true, + "setTimeout": true + }, + "packages": { + "fast-deep-equal": true + } + }, + "fast-levenshtein": { + "globals": { + "Intl": true, + "Levenshtein": "write", + "console.log": true, + "define": true, + "importScripts": true, + "postMessage": true + } + }, + "fsm-event": { + "packages": { + "assert": true, + "events": true, + "fsm": true + } + }, + "fuse.js": { + "globals": { + "console": true, + "define": true + } + }, + "get-browser-rtc": { + "globals": { + "RTCIceCandidate": true, + "RTCPeerConnection": true, + "RTCSessionDescription": true, + "mozRTCIceCandidate": true, + "mozRTCPeerConnection": true, + "mozRTCSessionDescription": true, + "webkitRTCIceCandidate": true, + "webkitRTCPeerConnection": true, + "webkitRTCSessionDescription": true + } + }, + "get-params": { + "globals": { + "GetParams": "write" + } + }, + "graphql-request": { + "globals": { + "fetch": true + }, + "packages": { + "cross-fetch": true + } + }, + "hamt-sharding": { + "packages": { + "is-buffer": true, + "sparse-array": true + } + }, + "has-binary2": { + "globals": { + "Blob": true, + "File": true + }, + "packages": { + "buffer": true, + "isarray": true + } + }, + "has-cors": { + "globals": { + "XMLHttpRequest": true + } + }, + "hash-base": { + "packages": { + "inherits": true, + "safe-buffer": true, + "stream-browserify": true + } + }, + "hash.js": { + "packages": { + "inherits": true, + "minimalistic-assert": true + } + }, + "hdkey": { + "packages": { + "assert": true, + "coinstring": true, + "crypto-browserify": true, + "safe-buffer": true, + "secp256k1": true + } + }, + "heap": { + "globals": { + "define": true + } + }, + "hi-base32": { + "globals": { + "define": true + }, + "packages": { + "process": true + } + }, + "history": { + "globals": { + "addEventListener": true, + "confirm": true, + "document": true, + "history": true, + "location": true, + "navigator.userAgent": true, + "removeEventListener": true + }, + "packages": { + "resolve-pathname": true, + "tiny-invariant": true, + "tiny-warning": true, + "value-equal": true + } + }, + "hmac-drbg": { + "packages": { + "hash.js": true, + "minimalistic-assert": true, + "minimalistic-crypto-utils": true + } + }, + "hoist-non-react-statics": { + "packages": { + "react-is": true + } + }, + "https-browserify": { + "packages": { + "stream-http": true, + "url": true + } + }, + "https-did-resolver": { + "globals": { + "XMLHttpRequest": true + }, + "packages": { + "browser-resolve": true, + "did-resolver": true + } + }, + "human-to-milliseconds": { + "packages": { + "promisify-es6": true + } + }, + "idb-readable-stream": { + "globals": { + "IDBKeyRange.bound": true, + "IDBKeyRange.lowerBound": true, + "IDBKeyRange.upperBound": true + }, + "packages": { + "stream-browserify": true, + "xtend": true + } + }, + "idna-uts46": { + "globals": { + "define": true + }, + "packages": { + "punycode": true + } + }, + "idna-uts46-hx": { + "globals": { + "define": true + }, + "packages": { + "punycode": true + } + }, + "immediate": { + "globals": { + "MessageChannel": true, + "MutationObserver": true, + "WebKitMutationObserver": true, + "clearTimeout": true, + "document.createElement": true, + "document.createTextNode": true, + "document.documentElement.appendChild": true, + "setImmediate": true, + "setTimeout": true + }, + "packages": { + "process": true + } + }, + "interface-connection": { + "packages": { + "pull-defer": true + } + }, + "interface-datastore": { + "packages": { + "async": true, + "buffer": true, + "class-is": true, + "err-code": true, + "os-browserify": true, + "path-browserify": true, + "pull-defer": true, + "pull-stream": true, + "uuid": true + } + }, + "ip": { + "packages": { + "buffer": true, + "os-browserify": true + } + }, + "ipfs": { + "globals": { + "AbortController": true, + "clearInterval": true, + "clearTimeout": true, + "console.log": true, + "fetch": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "async": true, + "async-iterator-all": true, + "async-iterator-to-pull-stream": true, + "async-iterator-to-stream": true, + "base32.js": true, + "bignumber.js": true, + "browser-resolve": true, + "buffer": true, + "callbackify": true, + "cids": true, + "class-is": true, + "datastore-core": true, + "datastore-pubsub": true, + "debug": true, + "dlv": true, + "err-code": true, + "events": true, + "fnv1a": true, + "fsm-event": true, + "human-to-milliseconds": true, + "interface-datastore": true, + "ipfs-bitswap": true, + "ipfs-block": true, + "ipfs-block-service": true, + "ipfs-mfs": true, + "ipfs-repo": true, + "ipfs-unixfs": true, + "ipfs-unixfs-exporter": true, + "ipfs-unixfs-importer": true, + "ipfs-utils": true, + "ipld": true, + "ipld-dag-cbor": true, + "ipld-dag-pb": true, + "ipld-raw": true, + "ipns": true, + "is-buffer": true, + "is-ipfs": true, + "is-pull-stream": true, + "is-stream": true, + "iso-url": true, + "just-flatten-it": true, + "kind-of": true, + "libp2p": true, + "libp2p-bootstrap": true, + "libp2p-crypto": true, + "libp2p-kad-dht": true, + "libp2p-keychain": true, + "libp2p-record": true, + "libp2p-secio": true, + "libp2p-webrtc-star": true, + "libp2p-websocket-star-multi": true, + "libp2p-websockets": true, + "mafmt": true, + "merge-options": true, + "multiaddr": true, + "multiaddr-to-uri": true, + "multibase": true, + "multicodec": true, + "multihashes": true, + "multihashing-async": true, + "peer-book": true, + "peer-id": true, + "peer-info": true, + "promisify-es6": true, + "protons": true, + "pull-cat": true, + "pull-defer": true, + "pull-mplex": true, + "pull-pushable": true, + "pull-sort": true, + "pull-stream": true, + "pull-stream-to-async-iterator": true, + "pull-stream-to-stream": true, + "pull-traverse": true, + "readable-stream": true, + "receptacle": true, + "stream-to-pull-stream": true, + "superstruct": true, + "timers-browserify": true, + "varint": true + } + }, + "ipfs-bitswap": { + "globals": { + "clearInterval": true, + "clearTimeout": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "assert": true, + "async": true, + "bignumber.js": true, + "cids": true, + "debug": true, + "events": true, + "ipfs-block": true, + "just-debounce-it": true, + "lodash.isequalwith": true, + "moving-average": true, + "multicodec": true, + "multihashing-async": true, + "protons": true, + "pull-length-prefixed": true, + "pull-stream": true, + "varint-decoder": true + } + }, + "ipfs-block": { + "packages": { + "cids": true, + "class-is": true, + "is-buffer": true + } + }, + "ipfs-block-service": { + "packages": { + "async": true + } + }, + "ipfs-log": { + "globals": { + "clearTimeout": true, + "console.warn": true, + "setTimeout": true + }, + "packages": { + "buffer": true, + "json-stringify-deterministic": true, + "orbit-db-io": true, + "p-each-series": true, + "p-map": true, + "p-whilst": true + } + }, + "ipfs-mfs": { + "globals": { + "Blob": true, + "FileReader": true + }, + "packages": { + "assert": true, + "async-iterator-last": true, + "browser-resolve": true, + "buffer": true, + "cids": true, + "debug": true, + "err-code": true, + "hamt-sharding": true, + "interface-datastore": true, + "ipfs-unixfs": true, + "ipfs-unixfs-exporter": true, + "ipfs-unixfs-importer": true, + "ipld-dag-pb": true, + "mortice": true, + "multicodec": true, + "multihashes": true, + "promisify-es6": true + } + }, + "ipfs-mini": { + "globals": { + "XMLHttpRequest": true + } + }, + "ipfs-pubsub-1on1": { + "globals": { + "clearInterval": true, + "setInterval": true + }, + "packages": { + "events": true, + "path-browserify": true, + "safe-buffer": true + } + }, + "ipfs-pubsub-peer-monitor": { + "globals": { + "clearInterval": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "events": true + } + }, + "ipfs-repo": { + "packages": { + "assert": true, + "async": true, + "base32.js": true, + "bignumber.js": true, + "buffer": true, + "cids": true, + "datastore-core": true, + "datastore-level": true, + "debug": true, + "dlv": true, + "interface-datastore": true, + "ipfs-block": true, + "just-safe-set": true, + "path-browserify": true, + "pull-stream": true, + "sort-keys": true, + "timers-browserify": true + } + }, + "ipfs-unixfs": { + "packages": { + "protons": true + } + }, + "ipfs-unixfs-exporter": { + "packages": { + "async-iterator-last": true, + "buffer": true, + "cids": true, + "err-code": true, + "hamt-sharding": true, + "ipfs-unixfs": true, + "ipfs-unixfs-importer": true, + "is-buffer": true + } + }, + "ipfs-unixfs-importer": { + "packages": { + "async-iterator-all": true, + "async-iterator-batch": true, + "async-iterator-first": true, + "bl": true, + "buffer": true, + "deep-extend": true, + "err-code": true, + "hamt-sharding": true, + "ipfs-unixfs": true, + "ipld-dag-pb": true, + "multicodec": true, + "multihashes": true, + "multihashing-async": true, + "rabin-wasm": true, + "superstruct": true + } + }, + "ipfs-utils": { + "globals": { + "FileReader": true + }, + "packages": { + "is-buffer": true, + "is-pull-stream": true, + "is-stream": true, + "kind-of": true, + "readable-stream": true + } + }, + "ipld": { + "packages": { + "cids": true, + "ipfs-block": true, + "ipld-dag-cbor": true, + "ipld-dag-pb": true, + "ipld-raw": true, + "is-buffer": true, + "merge-options": true, + "multicodec": true, + "promisify-es6": true, + "typical": true + } + }, + "ipld-dag-cbor": { + "packages": { + "borc": true, + "buffer": true, + "cids": true, + "is-buffer": true, + "is-circular": true, + "multicodec": true, + "multihashing-async": true + } + }, + "ipld-dag-pb": { + "packages": { + "assert": true, + "buffer": true, + "cids": true, + "class-is": true, + "is-buffer": true, + "multicodec": true, + "multihashing-async": true, + "protons": true, + "stable": true + } + }, + "ipld-raw": { + "packages": { + "cids": true, + "multicodec": true, + "multihashing-async": true + } + }, + "ipns": { + "packages": { + "base32-encode": true, + "buffer": true, + "debug": true, + "interface-datastore": true, + "libp2p-crypto": true, + "multihashes": true, + "peer-id": true, + "protons": true, + "timestamp-nano": true + } + }, + "is-dom": { + "globals": { + "Node": true + }, + "packages": { + "is-object": true, + "is-window": true + } + }, + "is-in-browser": { + "globals": { + "document": true + } + }, + "is-ip": { + "packages": { + "ip-regex": true + } + }, + "is-ipfs": { + "packages": { + "bs58": true, + "buffer": true, + "cids": true, + "mafmt": true, + "multiaddr": true, + "multibase": true, + "multihashes": true + } + }, + "is-regex": { + "packages": { + "has-symbols": true + } + }, + "iso-random-stream": { + "globals": { + "crypto": true, + "msCrypto": true + }, + "packages": { + "buffer": true + } + }, + "iso-url": { + "globals": { + "URL": true, + "URLSearchParams": true, + "location": true + } + }, + "isomorphic-fetch": { + "globals": { + "fetch.bind": true + }, + "packages": { + "whatwg-fetch": true + } + }, + "js-base64": { + "globals": { + "Base64": "write", + "TextDecoder": true, + "TextEncoder": true, + "atob": true, + "btoa": true, + "define": true + }, + "packages": { + "buffer": true + } + }, + "js-sha256": { + "globals": { + "define": true + }, + "packages": { + "process": true + } + }, + "js-sha3": { + "globals": { + "define": true + }, + "packages": { + "process": true + } + }, + "jsan": { + "globals": { + "console.warn": true + } + }, + "json-rpc-engine": { + "packages": { + "@metamask/safe-event-emitter": true, + "eth-rpc-errors": true, + "safe-event-emitter": true + } + }, + "json-rpc-middleware-stream": { + "packages": { + "readable-stream": true + } + }, + "json-stable-stringify": { + "packages": { + "jsonify": true + } + }, + "jsonschema": { + "packages": { + "url": true + } + }, + "jss": { + "globals": { + "CSS": true, + "document.createElement": true, + "document.querySelector": true + }, + "packages": { + "@babel/runtime": true, + "is-in-browser": true, + "tiny-warning": true + } + }, + "jss-plugin-camel-case": { + "packages": { + "hyphenate-style-name": true + } + }, + "jss-plugin-default-unit": { + "globals": { + "CSS": true + }, + "packages": { + "jss": true + } + }, + "jss-plugin-global": { + "packages": { + "@babel/runtime": true, + "jss": true + } + }, + "jss-plugin-nested": { + "packages": { + "@babel/runtime": true, + "tiny-warning": true + } + }, + "jss-plugin-rule-value-function": { + "packages": { + "jss": true, + "tiny-warning": true + } + }, + "jss-plugin-vendor-prefixer": { + "packages": { + "css-vendor": true, + "jss": true + } + }, + "just-debounce-it": { + "globals": { + "clearTimeout": true, + "setTimeout": true + } + }, + "k-bucket": { + "packages": { + "events": true, + "randombytes": true + } + }, + "keccak": { + "packages": { + "buffer": true, + "inherits": true, + "safe-buffer": true, + "stream-browserify": true + } + }, + "latency-monitor": { + "globals": { + "clearInterval": true, + "clearTimeout": true, + "document": true, + "performance": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "debug": true, + "events": true, + "lodash": true, + "process": true + } + }, + "level-codec": { + "packages": { + "buffer": true + } + }, + "level-errors": { + "packages": { + "errno": true + } + }, + "level-iterator-stream": { + "packages": { + "inherits": true, + "readable-stream": true, + "xtend": true + } + }, + "level-js": { + "globals": { + "IDBKeyRange.bound": true, + "IDBKeyRange.lowerBound": true, + "IDBKeyRange.only": true, + "IDBKeyRange.upperBound": true, + "indexedDB": true + }, + "packages": { + "abstract-leveldown": true, + "buffer": true, + "idb-readable-stream": true, + "immediate": true, + "inherits": true, + "is-buffer": true, + "ltgt": true, + "process": true, + "stream-browserify": true, + "typedarray-to-buffer": true, + "util": true, + "xtend": true + } + }, + "levelup": { + "packages": { + "assert": true, + "deferred-leveldown": true, + "events": true, + "level-errors": true, + "level-iterator-stream": true, + "process": true, + "util": true, + "xtend": true + } + }, + "libp2p": { + "packages": { + "async": true, + "debug": true, + "err-code": true, + "events": true, + "fsm-event": true, + "is-buffer": true, + "libp2p-connection-manager": true, + "libp2p-floodsub": true, + "libp2p-ping": true, + "libp2p-switch": true, + "libp2p-websockets": true, + "multiaddr": true, + "once": true, + "peer-book": true, + "peer-id": true, + "peer-info": true, + "process": true, + "superstruct": true + } + }, + "libp2p-bootstrap": { + "globals": { + "clearInterval": true, + "setInterval": true + }, + "packages": { + "async": true, + "debug": true, + "events": true, + "mafmt": true, + "multiaddr": true, + "peer-id": true, + "peer-info": true + } + }, + "libp2p-circuit": { + "packages": { + "async": true, + "debug": true, + "events": true, + "interface-connection": true, + "mafmt": true, + "multiaddr": true, + "once": true, + "peer-id": true, + "peer-info": true, + "protons": true, + "pull-handshake": true, + "pull-length-prefixed": true, + "pull-stream": true + } + }, + "libp2p-connection-manager": { + "packages": { + "debug": true, + "events": true, + "latency-monitor": true + } + }, + "libp2p-crypto": { + "globals": { + "crypto": true, + "msCrypto": true + }, + "packages": { + "asn1.js": true, + "async": true, + "browserify-aes": true, + "bs58": true, + "buffer": true, + "iso-random-stream": true, + "libp2p-crypto-secp256k1": true, + "multihashing-async": true, + "node-forge": true, + "protons": true, + "tweetnacl": true + } + }, + "libp2p-crypto-secp256k1": { + "packages": { + "async": true, + "bs58": true, + "multihashing-async": true, + "secp256k1": true + } + }, + "libp2p-floodsub": { + "packages": { + "assert": true, + "async": true, + "debug": true, + "libp2p-pubsub": true, + "pull-length-prefixed": true, + "pull-stream": true + } + }, + "libp2p-identify": { + "globals": { + "console.warn": true + }, + "packages": { + "buffer": true, + "multiaddr": true, + "peer-id": true, + "peer-info": true, + "protons": true, + "pull-length-prefixed": true, + "pull-stream": true + } + }, + "libp2p-kad-dht": { + "globals": { + "clearInterval": true, + "clearTimeout": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "abort-controller": true, + "assert": true, + "async": true, + "base32.js": true, + "buffer": true, + "cids": true, + "debug": true, + "err-code": true, + "events": true, + "hashlru": true, + "heap": true, + "interface-datastore": true, + "is-buffer": true, + "k-bucket": true, + "libp2p-crypto": true, + "libp2p-record": true, + "multihashes": true, + "multihashing-async": true, + "p-queue": true, + "p-times": true, + "peer-id": true, + "peer-info": true, + "promise-to-callback": true, + "promisify-es6": true, + "protons": true, + "pull-length-prefixed": true, + "pull-stream": true, + "pull-stream-to-async-iterator": true, + "varint": true, + "xor-distance": true + } + }, + "libp2p-keychain": { + "globals": { + "setTimeout": true + }, + "packages": { + "async": true, + "buffer": true, + "err-code": true, + "interface-datastore": true, + "libp2p-crypto": true, + "merge-options": true, + "node-forge": true, + "pull-stream": true, + "sanitize-filename": true + } + }, + "libp2p-ping": { + "packages": { + "debug": true, + "events": true, + "libp2p-crypto": true, + "pull-handshake": true, + "pull-stream": true + } + }, + "libp2p-pubsub": { + "packages": { + "async": true, + "bs58": true, + "buffer": true, + "debug": true, + "err-code": true, + "events": true, + "is-buffer": true, + "libp2p-crypto": true, + "protons": true, + "pull-length-prefixed": true, + "pull-pushable": true, + "pull-stream": true, + "time-cache": true + } + }, + "libp2p-record": { + "packages": { + "assert": true, + "async": true, + "buffer": true, + "buffer-split": true, + "err-code": true, + "is-buffer": true, + "multihashing-async": true, + "protons": true + } + }, + "libp2p-secio": { + "packages": { + "assert": true, + "async": true, + "buffer": true, + "debug": true, + "interface-connection": true, + "libp2p-crypto": true, + "multihashing-async": true, + "once": true, + "peer-id": true, + "peer-info": true, + "protons": true, + "pull-defer": true, + "pull-handshake": true, + "pull-length-prefixed": true, + "pull-stream": true + } + }, + "libp2p-switch": { + "packages": { + "assert": true, + "async": true, + "bignumber.js": true, + "class-is": true, + "debug": true, + "err-code": true, + "events": true, + "fsm-event": true, + "hashlru": true, + "interface-connection": true, + "libp2p-circuit": true, + "libp2p-identify": true, + "moving-average": true, + "multiaddr": true, + "multistream-select": true, + "once": true, + "peer-id": true, + "peer-info": true, + "pull-stream": true, + "retimer": true + } + }, + "libp2p-webrtc-star": { + "packages": { + "async": true, + "class-is": true, + "debug": true, + "events": true, + "interface-connection": true, + "mafmt": true, + "multiaddr": true, + "once": true, + "peer-id": true, + "peer-info": true, + "simple-peer": true, + "socket.io-client": true, + "stream-to-pull-stream": true, + "webrtcsupport": true + } + }, + "libp2p-websocket-star": { + "globals": { + "console.error": true + }, + "packages": { + "async": true, + "buffer": true, + "class-is": true, + "debug": true, + "events": true, + "interface-connection": true, + "libp2p-crypto": true, + "mafmt": true, + "multiaddr": true, + "once": true, + "peer-id": true, + "peer-info": true, + "pull-stream": true, + "socket.io-client": true, + "socket.io-pull-stream": true, + "uuid": true + } + }, + "libp2p-websocket-star-multi": { + "globals": { + "setTimeout": true + }, + "packages": { + "async": true, + "debug": true, + "events": true, + "libp2p-websocket-star": true, + "mafmt": true, + "multiaddr": true, + "once": true + } + }, + "libp2p-websockets": { + "packages": { + "class-is": true, + "debug": true, + "interface-connection": true, + "mafmt": true, + "multiaddr": true, + "multiaddr-to-uri": true, + "os-browserify": true, + "pull-ws": true + } + }, + "locale-currency": { + "globals": { + "countryCode": true + } + }, + "localforage": { + "globals": { + "Blob": true, + "BlobBuilder": true, + "FileReader": true, + "IDBKeyRange": true, + "MSBlobBuilder": true, + "MozBlobBuilder": true, + "OIndexedDB": true, + "WebKitBlobBuilder": true, + "atob": true, + "btoa": true, + "console.error": true, + "console.info": true, + "console.warn": true, + "define": true, + "fetch": true, + "indexedDB": true, + "localStorage": true, + "mozIndexedDB": true, + "msIndexedDB": true, + "navigator.platform": true, + "navigator.userAgent": true, + "openDatabase": true, + "setTimeout": true, + "webkitIndexedDB": true + } + }, + "lodash": { + "globals": { + "define": true + } + }, + "lodash.throttle": { + "globals": { + "clearTimeout": true, + "setTimeout": true + } + }, + "loglevel": { + "globals": { + "console": true, + "define": true, + "document.cookie": true, + "localStorage": true, + "log": "write" + } + }, + "logplease": { + "globals": { + "LOG": true, + "console.error": true, + "console.log": true + }, + "packages": { + "browser-resolve": true, + "events": true, + "process": true, + "util": true + } + }, + "lru": { + "packages": { + "events": true, + "inherits": true + } + }, + "ltgt": { + "packages": { + "is-buffer": true + } + }, + "luxon": { + "globals": { + "Intl": true + } + }, + "mafmt": { + "packages": { + "multiaddr": true + } + }, + "md5": { + "packages": { + "charenc": true, + "crypt": true, + "is-buffer": true + } + }, + "md5.js": { + "packages": { + "hash-base": true, + "inherits": true, + "safe-buffer": true + } + }, + "merge-options": { + "packages": { + "is-plain-obj": true + } + }, + "miller-rabin": { + "packages": { + "bn.js": true, + "brorand": true + } + }, + "mini-create-react-context": { + "packages": { + "@babel/runtime": true, + "gud": true, + "prop-types": true, + "react": true, + "tiny-warning": true + } + }, + "mortice": { + "globals": { + "Worker": true + }, + "packages": { + "browser-resolve": true, + "events": true, + "observable-webworkers": true, + "p-queue": true, + "process": true, + "promise-timeout": true, + "shortid": true + } + }, + "multiaddr": { + "packages": { + "bs58": true, + "buffer": true, + "class-is": true, + "hi-base32": true, + "ip": true, + "is-ip": true, + "varint": true + } + }, + "multiaddr-to-uri": { + "packages": { + "multiaddr": true + } + }, + "multibase": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "@multiformats/base-x": true, + "base-x": true, + "buffer": true, + "web-encoding": true + } + }, + "multicodec": { + "packages": { + "buffer": true, + "uint8arrays": true, + "varint": true + } + }, + "multihashes": { + "packages": { + "bs58": true, + "buffer": true, + "multibase": true, + "uint8arrays": true, + "varint": true, + "web-encoding": true + } + }, + "multihashing-async": { + "globals": { + "crypto": true, + "msCrypto": true + }, + "packages": { + "blakejs": true, + "buffer": true, + "err-code": true, + "js-sha3": true, + "multihashes": true, + "murmurhash3js": true, + "murmurhash3js-revisited": true, + "nodeify": true, + "process": true + } + }, + "multistream-select": { + "packages": { + "assert": true, + "async": true, + "buffer": true, + "debug": true, + "err-code": true, + "interface-connection": true, + "once": true, + "pull-handshake": true, + "pull-length-prefixed": true, + "pull-stream": true, + "semver": true, + "varint": true + } + }, + "muport-did-resolver": { + "packages": { + "@babel/runtime": true, + "did-resolver": true, + "node-fetch": true + } + }, + "murmurhash3js": { + "globals": { + "define": true + } + }, + "murmurhash3js-revisited": { + "globals": { + "define": true + } + }, + "nanoid": { + "globals": { + "crypto": true, + "msCrypto": true, + "navigator": true + }, + "packages": { + "buffer": true, + "crypto-browserify": true + } + }, + "node-forge": { + "globals": { + "Blob": true, + "MutationObserver": true, + "QuotaExceededError": true, + "URL.createObjectURL": true, + "URL.revokeObjectURL": true, + "Worker": true, + "addEventListener": true, + "document": true, + "jQuery": true, + "localStorage": true, + "location": true, + "navigator": true, + "postMessage": true, + "removeEventListener": true, + "setTimeout": true + }, + "packages": { + "browser-resolve": true, + "process": true, + "timers-browserify": true + } + }, + "nodeify": { + "globals": { + "setTimeout": true + }, + "packages": { + "is-promise": true, + "process": true, + "promise": true, + "timers-browserify": true + } + }, + "nonce-tracker": { + "packages": { + "assert": true, + "await-semaphore": true, + "ethjs-query": true + } + }, + "number-to-bn": { + "packages": { + "bn.js": true, + "strip-hex-prefix": true + } + }, + "obj-multiplex": { + "globals": { + "console.warn": true + }, + "packages": { + "end-of-stream": true, + "once": true, + "readable-stream": true + } + }, + "obs-store": { + "packages": { + "safe-event-emitter": true, + "xtend": true + } + }, + "once": { + "packages": { + "wrappy": true + } + }, + "orbit-db": { + "globals": { + "console.log": true + }, + "packages": { + "cids": true, + "ipfs-pubsub-1on1": true, + "logplease": true, + "multihashes": true, + "orbit-db-access-controllers": true, + "orbit-db-cache": true, + "orbit-db-counterstore": true, + "orbit-db-docstore": true, + "orbit-db-eventstore": true, + "orbit-db-feedstore": true, + "orbit-db-identity-provider": true, + "orbit-db-io": true, + "orbit-db-keystore": true, + "orbit-db-kvstore": true, + "orbit-db-pubsub": true, + "path-browserify": true + } + }, + "orbit-db-access-controllers": { + "globals": { + "console.log": true + }, + "packages": { + "events": true, + "orbit-db-io": true, + "p-map-series": true, + "path-browserify": true, + "safe-buffer": true + } + }, + "orbit-db-cache": { + "packages": { + "level-js": true, + "logplease": true, + "path-browserify": true + } + }, + "orbit-db-counterstore": { + "packages": { + "crdts": true, + "orbit-db-store": true + } + }, + "orbit-db-docstore": { + "packages": { + "orbit-db-store": true, + "p-map": true, + "readable-stream": true + } + }, + "orbit-db-eventstore": { + "packages": { + "orbit-db-store": true + } + }, + "orbit-db-feedstore": { + "packages": { + "orbit-db-eventstore": true + } + }, + "orbit-db-identity-provider": { + "packages": { + "orbit-db-keystore": true + } + }, + "orbit-db-io": { + "packages": { + "buffer": true, + "cids": true, + "ipld-dag-pb": true + } + }, + "orbit-db-keystore": { + "globals": { + "console.error": true, + "console.log": true + }, + "packages": { + "elliptic": true, + "level-js": true, + "levelup": true, + "libp2p-crypto": true, + "lru": true, + "safe-buffer": true, + "secp256k1": true + } + }, + "orbit-db-kvstore": { + "packages": { + "orbit-db-store": true + } + }, + "orbit-db-pubsub": { + "packages": { + "buffer": true, + "ipfs-pubsub-peer-monitor": true, + "logplease": true, + "p-series": true + } + }, + "orbit-db-store": { + "globals": { + "clearInterval": true, + "console.error": true, + "console.warn": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "buffer": true, + "events": true, + "ipfs-log": true, + "logplease": true, + "orbit-db-io": true, + "p-each-series": true, + "p-map": true, + "readable-stream": true + } + }, + "os-browserify": { + "globals": { + "location": true, + "navigator": true + } + }, + "p-each-series": { + "packages": { + "p-reduce": true + } + }, + "p-map-series": { + "packages": { + "p-reduce": true + } + }, + "p-queue": { + "globals": { + "clearInterval": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "eventemitter3": true + } + }, + "p-series": { + "packages": { + "@sindresorhus/is": true, + "p-reduce": true + } + }, + "p-times": { + "packages": { + "p-map": true + } + }, + "parse-asn1": { + "packages": { + "asn1.js": true, + "browserify-aes": true, + "buffer": true, + "evp_bytestokey": true, + "pbkdf2": true + } + }, + "path-browserify": { + "packages": { + "process": true + } + }, + "path-to-regexp": { + "packages": { + "isarray": true + } + }, + "pbkdf2": { + "globals": { + "crypto": true, + "process": true + }, + "packages": { + "create-hash": true, + "process": true, + "ripemd160": true, + "safe-buffer": true, + "sha.js": true + } + }, + "peer-book": { + "packages": { + "bs58": true, + "is-buffer": true, + "peer-id": true, + "peer-info": true + } + }, + "peer-id": { + "packages": { + "assert": true, + "async": true, + "buffer": true, + "class-is": true, + "libp2p-crypto": true, + "multihashes": true + } + }, + "peer-info": { + "packages": { + "assert": true, + "multiaddr": true, + "peer-id": true, + "unique-by": true + } + }, + "popper.js": { + "globals": { + "MSInputMethodContext": true, + "Node.DOCUMENT_POSITION_FOLLOWING": true, + "cancelAnimationFrame": true, + "console.warn": true, + "define": true, + "devicePixelRatio": true, + "document": true, + "getComputedStyle": true, + "innerHeight": true, + "innerWidth": true, + "navigator": true, + "requestAnimationFrame": true, + "setTimeout": true + } + }, + "precond": { + "packages": { + "util": true + } + }, + "process": { + "globals": { + "clearTimeout": true, + "setTimeout": true + } + }, + "process-nextick-args": { + "packages": { + "process": true + } + }, + "promise": { + "globals": { + "setImediate": true, + "setTimeout": true + }, + "packages": { + "is-promise": true, + "process": true + } + }, + "promise-timeout": { + "globals": { + "clearTimeout": true, + "setTimeout": true + } + }, + "promise-to-callback": { + "packages": { + "is-fn": true, + "set-immediate-shim": true + } + }, + "prop-types": { + "globals": { + "console": true + }, + "packages": { + "object-assign": true, + "react-is": true + } + }, + "protons": { + "packages": { + "buffer": true, + "is-buffer": true, + "protocol-buffers-schema": true, + "safe-buffer": true, + "signed-varint": true, + "varint": true + } + }, + "public-encrypt": { + "packages": { + "bn.js": true, + "browserify-rsa": true, + "buffer": true, + "create-hash": true, + "parse-asn1": true, + "randombytes": true + } + }, + "pubnub": { + "globals": { + "ActiveXObject": true, + "XMLHttpRequest": true, + "addEventListener": true, + "btoa": true, + "clearInterval": true, + "clearTimeout": true, + "console": true, + "define": true, + "localStorage.getItem": true, + "localStorage.setItem": true, + "location": true, + "navigator": true, + "setInterval": true, + "setTimeout": true + } + }, + "pull-handshake": { + "packages": { + "pull-cat": true, + "pull-pair": true, + "pull-pushable": true, + "pull-reader": true + } + }, + "pull-length-prefixed": { + "packages": { + "pull-pushable": true, + "pull-reader": true, + "safe-buffer": true, + "varint": true + } + }, + "pull-mplex": { + "packages": { + "async": true, + "buffer": true, + "debug": true, + "events": true, + "interface-connection": true, + "looper": true, + "pull-abortable": true, + "pull-pushable": true, + "pull-stream": true, + "pull-through": true, + "varint": true + } + }, + "pull-reader": { + "globals": { + "cb": true, + "clearTimeout": true, + "setTimeout": true + }, + "packages": { + "buffer": true + } + }, + "pull-sort": { + "packages": { + "pull-defer": true, + "pull-stream": true + } + }, + "pull-stream": { + "globals": { + "console.log": true + } + }, + "pull-stream-to-async-iterator": { + "packages": { + "pull-stream": true + } + }, + "pull-stream-to-stream": { + "packages": { + "process": true, + "stream-browserify": true, + "timers-browserify": true + } + }, + "pull-through": { + "packages": { + "looper": true + } + }, + "pull-ws": { + "globals": { + "WebSocket": true, + "location": true + }, + "packages": { + "browser-resolve": true, + "events": true, + "https-browserify": true, + "process": true, + "relative-url": true, + "safe-buffer": true, + "stream-http": true, + "timers-browserify": true, + "url": true + } + }, + "pump": { + "packages": { + "browser-resolve": true, + "end-of-stream": true, + "once": true, + "process": true + } + }, + "punycode": { + "globals": { + "define": true + } + }, + "qrcode-generator": { + "globals": { + "define": true + } + }, + "rabin-wasm": { + "globals": { + "Blob": true, + "Response": true, + "WebAssembly": true + }, + "packages": { + "assemblyscript": true + } + }, + "randombytes": { + "globals": { + "crypto": true, + "msCrypto": true + }, + "packages": { + "process": true, + "safe-buffer": true + } + }, + "randomfill": { + "globals": { + "crypto": true, + "msCrypto": true + }, + "packages": { + "process": true, + "randombytes": true, + "safe-buffer": true + } + }, + "react": { + "globals": { + "console": true + }, + "packages": { + "object-assign": true, + "prop-types": true + } + }, + "react-dnd": { + "globals": { + "console.error": true + }, + "packages": { + "disposables": true, + "dnd-core": true, + "hoist-non-react-statics": true, + "invariant": true, + "lodash": true, + "prop-types": true, + "react": true, + "shallowequal": true + } + }, + "react-dnd-html5-backend": { + "globals": { + "Image": true, + "console.warn": true, + "devicePixelRatio": true, + "document": true, + "navigator.userAgent": true, + "safari": true, + "setTimeout": true + } + }, + "react-dom": { + "globals": { + "MSApp": true, + "__REACT_DEVTOOLS_GLOBAL_HOOK__": true, + "addEventListener": true, + "clearTimeout": true, + "clipboardData": true, + "console": true, + "dispatchEvent": true, + "document": true, + "event": "write", + "jest": true, + "location.protocol": true, + "navigator.userAgent.indexOf": true, + "performance": true, + "removeEventListener": true, + "self": true, + "setTimeout": true, + "top": true, + "trustedTypes": true + }, + "packages": { + "object-assign": true, + "prop-types": true, + "react": true, + "scheduler": true + } + }, + "react-easy-swipe": { + "globals": { + "addEventListener": true, + "define": true, + "document.addEventListener": true, + "document.removeEventListener": true + }, + "packages": { + "prop-types": true, + "react": true + } + }, + "react-fast-compare": { + "globals": { + "Element": true, + "console.warn": true + } + }, + "react-idle-timer": { + "globals": { + "clearTimeout": true, + "document": true, + "setTimeout": true + }, + "packages": { + "prop-types": true, + "react": true + } + }, + "react-inspector": { + "globals": { + "Node.CDATA_SECTION_NODE": true, + "Node.COMMENT_NODE": true, + "Node.DOCUMENT_FRAGMENT_NODE": true, + "Node.DOCUMENT_NODE": true, + "Node.DOCUMENT_TYPE_NODE": true, + "Node.ELEMENT_NODE": true, + "Node.PROCESSING_INSTRUCTION_NODE": true, + "Node.TEXT_NODE": true + }, + "packages": { + "babel-runtime": true, + "is-dom": true, + "prop-types": true, + "react": true + } + }, + "react-is": { + "globals": { + "console": true + } + }, + "react-popper": { + "globals": { + "document": true + }, + "packages": { + "@popperjs/core": true, + "react": true, + "react-fast-compare": true, + "warning": true + } + }, + "react-redux": { + "globals": { + "console": true, + "document": true + }, + "packages": { + "@babel/runtime": true, + "hoist-non-react-statics": true, + "prop-types": true, + "react": true, + "react-dom": true, + "react-is": true, + "redux": true + } + }, + "react-responsive-carousel": { + "globals": { + "HTMLElement": true, + "clearTimeout": true, + "console.warn": true, + "document": true, + "getComputedStyle": true, + "setTimeout": true + }, + "packages": { + "classnames": true, + "react": true, + "react-dom": true, + "react-easy-swipe": true + } + }, + "react-router": { + "packages": { + "history": true, + "hoist-non-react-statics": true, + "mini-create-react-context": true, + "path-to-regexp": true, + "prop-types": true, + "react": true, + "react-is": true, + "tiny-invariant": true, + "tiny-warning": true + } + }, + "react-router-dom": { + "packages": { + "history": true, + "prop-types": true, + "react": true, + "react-router": true, + "tiny-invariant": true, + "tiny-warning": true + } + }, + "react-simple-file-input": { + "globals": { + "File": true, + "FileReader": true, + "console.warn": true + }, + "packages": { + "prop-types": true, + "react": true + } + }, + "react-tippy": { + "globals": { + "Element": true, + "MSStream": true, + "MutationObserver": true, + "addEventListener": true, + "clearTimeout": true, + "console.error": true, + "console.warn": true, + "define": true, + "document": true, + "getComputedStyle": true, + "innerHeight": true, + "innerWidth": true, + "navigator.maxTouchPoints": true, + "navigator.msMaxTouchPoints": true, + "navigator.userAgent": true, + "performance": true, + "requestAnimationFrame": true, + "setTimeout": true + }, + "packages": { + "popper.js": true, + "react": true, + "react-dom": true + } + }, + "react-toggle-button": { + "globals": { + "clearTimeout": true, + "console.warn": true, + "define": true, + "performance": true, + "setTimeout": true + }, + "packages": { + "react": true + } + }, + "react-transition-group": { + "globals": { + "Element": true, + "clearTimeout": true, + "setTimeout": true + }, + "packages": { + "chain-function": true, + "dom-helpers": true, + "prop-types": true, + "react": true, + "react-dom": true, + "warning": true + } + }, + "readable-stream": { + "packages": { + "browser-resolve": true, + "buffer": true, + "core-util-is": true, + "events": true, + "inherits": true, + "isarray": true, + "process": true, + "process-nextick-args": true, + "safe-buffer": true, + "string_decoder": true, + "timers-browserify": true, + "util-deprecate": true + } + }, + "receptacle": { + "globals": { + "clearTimeout": true, + "setTimeout": true + }, + "packages": { + "ms": true + } + }, + "redux": { + "globals": { + "console": true + }, + "packages": { + "@babel/runtime": true, + "symbol-observable": true + } + }, + "redux-devtools-core": { + "globals": { + "ErrorUtils": true, + "console": true, + "devToolsOptions": true, + "onerror": "write", + "serializeState": true + }, + "packages": { + "get-params": true, + "jsan": true, + "lodash": true, + "nanoid": true, + "remotedev-serialize": true + } + }, + "redux-devtools-instrument": { + "globals": { + "chrome": true, + "console.error": true, + "process": true, + "setTimeout": true + }, + "packages": { + "lodash": true, + "process": true, + "symbol-observable": true + } + }, + "regenerator-runtime": { + "globals": { + "regeneratorRuntime": "write" + } + }, + "regexp.prototype.flags": { + "packages": { + "define-properties": true, + "es-abstract": true + } + }, + "relative-url": { + "packages": { + "url": true + } + }, + "remote-redux-devtools": { + "globals": { + "console.log": true, + "console.warn": true, + "fetch": true, + "setTimeout": true + }, + "packages": { + "jsan": true, + "redux-devtools-core": true, + "redux-devtools-instrument": true, + "rn-host-detect": true, + "socketcluster-client": true + } + }, + "retimer": { + "globals": { + "clearTimeout": true, + "setTimeout": true + } + }, + "ripemd160": { + "packages": { + "buffer": true, + "hash-base": true, + "inherits": true + } + }, + "rlp": { + "packages": { + "bn.js": true, + "buffer": true + } + }, + "rn-host-detect": { + "globals": { + "__DEV__": true, + "__fbBatchedBridgeConfig": true, + "console": true + } + }, + "rpc-cap": { + "packages": { + "@metamask/controllers": true, + "eth-rpc-errors": true, + "is-subset": true, + "json-rpc-engine": true, + "uuid": true + } + }, + "safe-buffer": { + "packages": { + "buffer": true + } + }, + "safe-event-emitter": { + "globals": { + "setTimeout": true + }, + "packages": { + "events": true, + "util": true + } + }, + "sanitize-filename": { + "packages": { + "truncate-utf8-bytes": true + } + }, + "sc-channel": { + "packages": { + "component-emitter": true + } + }, + "sc-formatter": { + "globals": { + "Buffer": true + } + }, + "scheduler": { + "globals": { + "MessageChannel": true, + "cancelAnimationFrame": true, + "clearTimeout": true, + "console": true, + "navigator": true, + "performance": true, + "requestAnimationFrame": true, + "setTimeout": true + } + }, + "scrypt-js": { + "globals": { + "define": true, + "setTimeout": true + }, + "packages": { + "timers-browserify": true + } + }, + "scryptsy": { + "packages": { + "buffer": true, + "pbkdf2": true + } + }, + "secp256k1": { + "packages": { + "bip66": true, + "bn.js": true, + "create-hash": true, + "drbg.js": true, + "elliptic": true, + "is-buffer": true, + "safe-buffer": true + } + }, + "semaphore": { + "globals": { + "define": true, + "setTimeout": true + }, + "packages": { + "process": true + } + }, + "semver": { + "globals": { + "console": true + }, + "packages": { + "process": true + } + }, + "set-immediate-shim": { + "globals": { + "setTimeout.apply": true + }, + "packages": { + "timers-browserify": true + } + }, + "sha.js": { + "packages": { + "inherits": true, + "safe-buffer": true + } + }, + "shortid": { + "globals": { + "crypto": true, + "msCrypto": true + }, + "packages": { + "nanoid": true + } + }, + "signed-varint": { + "packages": { + "varint": true + } + }, + "simple-peer": { + "globals": { + "clearInterval": true, + "console.warn": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "buffer": true, + "debug": true, + "get-browser-rtc": true, + "inherits": true, + "randombytes": true, + "readable-stream": true + } + }, + "socket.io-client": { + "globals": { + "clearTimeout": true, + "location": true, + "setTimeout": true + }, + "packages": { + "backo2": true, + "component-bind": true, + "component-emitter": true, + "debug": true, + "engine.io-client": true, + "has-binary2": true, + "indexof": true, + "parseqs": true, + "parseuri": true, + "socket.io-parser": true, + "to-array": true + } + }, + "socket.io-parser": { + "globals": { + "Blob": true, + "File": true, + "FileReader": true + }, + "packages": { + "buffer": true, + "component-emitter": true, + "debug": true, + "isarray": true + } + }, + "socket.io-pull-stream": { + "globals": { + "console.error": true + }, + "packages": { + "buffer": true, + "data-queue": true, + "debug": true, + "pull-stream": true, + "uuid": true + } + }, + "socketcluster-client": { + "globals": { + "WebSocket": true, + "WorkerGlobalScope": true, + "addEventListener": true, + "clearTimeout": true, + "localStorage": true, + "location": true, + "removeEventListener": true, + "setTimeout": true + }, + "packages": { + "buffer": true, + "clone": true, + "component-emitter": true, + "linked-list": true, + "querystring-es3": true, + "sc-channel": true, + "sc-errors": true, + "sc-formatter": true, + "uuid": true + } + }, + "sort-keys": { + "packages": { + "is-plain-obj": true + } + }, + "stable": { + "globals": { + "define": true + } + }, + "store": { + "globals": { + "ActiveXObject": true, + "console": true + } + }, + "stream-browserify": { + "packages": { + "events": true, + "inherits": true, + "readable-stream": true + } + }, + "stream-http": { + "globals": { + "AbortController": true, + "Blob": true, + "MSStreamReader": true, + "ReadableStream": true, + "WritableStream": true, + "XDomainRequest": true, + "XMLHttpRequest": true, + "clearTimeout": true, + "fetch": true, + "location.protocol.search": true, + "setTimeout": true + }, + "packages": { + "buffer": true, + "builtin-status-codes": true, + "inherits": true, + "process": true, + "readable-stream": true, + "url": true, + "xtend": true + } + }, + "stream-to-pull-stream": { + "globals": { + "console.error": true + }, + "packages": { + "looper": true, + "process": true, + "pull-stream": true + } + }, + "string_decoder": { + "packages": { + "safe-buffer": true + } + }, + "strip-hex-prefix": { + "packages": { + "is-hex-prefixed": true + } + }, + "textarea-caret": { + "globals": { + "document.body.appendChild": true, + "document.body.removeChild": true, + "document.createElement": true, + "document.querySelector": true, + "getCaretCoordinates": "write", + "getComputedStyle": true, + "mozInnerScreenX": true + } + }, + "through": { + "packages": { + "process": true, + "stream-browserify": true + } + }, + "through2": { + "packages": { + "process": true, + "readable-stream": true, + "util": true, + "xtend": true + } + }, + "time-cache": { + "packages": { + "lodash.throttle": true + } + }, + "timers-browserify": { + "globals": { + "clearInterval": true, + "clearTimeout": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "process": true + } + }, + "tiny-warning": { + "globals": { + "console": true + } + }, + "toggle-selection": { + "globals": { + "document.activeElement": true, + "document.getSelection": true + } + }, + "trezor-connect": { + "globals": { + "__TREZOR_CONNECT_SRC": true, + "addEventListener": true, + "btoa": true, + "chrome": true, + "clearInterval": true, + "clearTimeout": true, + "console": true, + "document.body": true, + "document.createElement": true, + "document.createTextNode": true, + "document.getElementById": true, + "document.querySelectorAll": true, + "fetch": true, + "location": true, + "navigator": true, + "open": true, + "removeEventListener": true, + "setInterval": true, + "setTimeout": true + }, + "packages": { + "@babel/runtime": true, + "events": true, + "whatwg-fetch": true + } + }, + "truncate-utf8-bytes": { + "packages": { + "utf8-byte-length": true + } + }, + "tslib": { + "globals": { + "define": true + } + }, + "tweetnacl": { + "globals": { + "crypto": true, + "msCrypto": true, + "nacl": "write" + }, + "packages": { + "browser-resolve": true + } + }, + "tweetnacl-util": { + "globals": { + "atob": true, + "btoa": true + }, + "packages": { + "browser-resolve": true + } + }, + "typedarray-to-buffer": { + "packages": { + "buffer": true, + "is-typedarray": true + } + }, + "typical": { + "globals": { + "define": true + } + }, + "uint8arrays": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "multibase": true, + "web-encoding": true + } + }, + "unorm": { + "globals": { + "define": true + } + }, + "uport-base64url": { + "packages": { + "buffer": true + } + }, + "url": { + "packages": { + "punycode": true, + "querystring-es3": true + } + }, + "utf8": { + "globals": { + "define": true + } + }, + "util": { + "globals": { + "console.error": true, + "console.log": true, + "console.trace": true, + "process": true + }, + "packages": { + "inherits": true, + "process": true + } + }, + "util-deprecate": { + "globals": { + "console.trace": true, + "console.warn": true, + "localStorage": true + } + }, + "uuid": { + "globals": { + "crypto": true, + "msCrypto": true + } + }, + "varint-decoder": { + "packages": { + "is-buffer": true, + "varint": true + } + }, + "vm-browserify": { + "globals": { + "document.body.appendChild": true, + "document.body.removeChild": true, + "document.createElement": true + } + }, + "warning": { + "globals": { + "console": true + } + }, + "web-encoding": { + "globals": { + "TextDecoder": true, + "TextEncoder": true + }, + "packages": { + "util": true + } + }, + "web3": { + "globals": { + "Web3": "write", + "XMLHttpRequest": "write", + "clearTimeout": true, + "console.error": true, + "setTimeout": true + }, + "packages": { + "bignumber.js": true, + "buffer": true, + "crypto-js": true, + "utf8": true, + "xhr2-cookies": true + } + }, + "web3-provider-engine": { + "globals": { + "WebSocket": true, + "console": true, + "setTimeout": true + }, + "packages": { + "@ethereumjs/tx": true, + "async": true, + "backoff": true, + "browser-resolve": true, + "buffer": true, + "eth-block-tracker": true, + "eth-json-rpc-filters": true, + "eth-json-rpc-infura": true, + "eth-json-rpc-middleware": true, + "eth-sig-util": true, + "ethereumjs-util": true, + "events": true, + "json-stable-stringify": true, + "semaphore": true, + "util": true, + "xtend": true + } + }, + "web3-stream-provider": { + "globals": { + "setTimeout": true + }, + "packages": { + "readable-stream": true, + "util": true, + "uuid": true + } + }, + "webrtcsupport": { + "globals": { + "AudioContext": true, + "MediaStream": true, + "RTCIceCandidate": true, + "RTCPeerConnection": true, + "RTCSessionDescription": true, + "document": true, + "location.protocol": true, + "mozRTCIceCandidate": true, + "mozRTCPeerConnection": true, + "mozRTCSessionDescription": true, + "navigator.getUserMedia": true, + "navigator.mozGetUserMedia": true, + "navigator.msGetUserMedia": true, + "navigator.userAgent.match": true, + "navigator.webkitGetUserMedia": true, + "webkitAudioContext": true, + "webkitMediaStream": true, + "webkitRTCPeerConnection": true + } + }, + "whatwg-fetch": { + "globals": { + "Blob": true, + "FileReader": true, + "FormData": true, + "URLSearchParams.prototype.isPrototypeOf": true, + "XMLHttpRequest": true, + "define": true, + "setTimeout": true + } + }, + "xhr2": { + "globals": { + "XMLHttpRequest": true + } + }, + "xhr2-cookies": { + "globals": { + "console.warn": true + }, + "packages": { + "buffer": true, + "cookiejar": true, + "https-browserify": true, + "os-browserify": true, + "process": true, + "stream-http": true, + "url": true + } + }, + "xor-distance": { + "packages": { + "buffer": true + } + } + } +} \ No newline at end of file diff --git a/lavamoat/node/policy.json b/lavamoat/node/policy.json index 8fc5fcd16..f12ad2325 100644 --- a/lavamoat/node/policy.json +++ b/lavamoat/node/policy.json @@ -824,8 +824,8 @@ "@gulp-sourcemaps/identity-map": { "packages": { "acorn": true, - "css": true, "normalize-path": true, + "postcss": true, "source-map": true, "through2": true } @@ -840,18 +840,22 @@ "builtin": { "assert": true, "buffer.Buffer.from": true, + "fs.readFileSync": true, "path.join": true, "path.relative": true }, "globals": { "__dirname": true, - "process.cwd": true + "process.cwd": true, + "setTimeout": true }, "packages": { "JSONStream": true, "combine-source-map": true, "convert-source-map": true, "json-stable-stringify": true, + "lavamoat-core": true, + "readable-stream": true, "through2": true, "umd": true } @@ -962,15 +966,6 @@ "uri-js": true } }, - "amdefine": { - "builtin": { - "path.dirname": true - }, - "globals": { - "__filename": true, - "process.nextTick": true - } - }, "ansi-colors": { "packages": { "ansi-wrap": true @@ -1407,6 +1402,15 @@ "buffer.Buffer": true } }, + "clone-deep": { + "packages": { + "for-own": true, + "is-plain-object": true, + "kind-of": true, + "lazy-cache": true, + "shallow-clone": true + } + }, "clone-regexp": { "packages": { "is-regexp": true @@ -1465,6 +1469,7 @@ "concat-stream": { "globals": { "Buffer.concat": true, + "Buffer.from": true, "Buffer.isBuffer": true }, "packages": { @@ -1481,7 +1486,7 @@ "path.resolve": true }, "globals": { - "Buffer": true + "Buffer.from": true }, "packages": { "safe-buffer": true @@ -1540,13 +1545,13 @@ "css": { "builtin": { "fs.readFileSync": true, - "path.dirname": true + "path.dirname": true, + "path.sep": true }, "packages": { "inherits": true, "source-map": true, - "source-map-resolve": true, - "urix": true + "source-map-resolve": true } }, "d": { @@ -2436,7 +2441,8 @@ "path.sep": true }, "globals": { - "Buffer": true + "Buffer.concat": true, + "Buffer.from": true }, "packages": { "@gulp-sourcemaps/identity-map": true, @@ -2595,7 +2601,7 @@ }, "inline-source-map": { "globals": { - "Buffer": true + "Buffer.from": true }, "packages": { "source-map": true @@ -2820,6 +2826,70 @@ "es6-weak-map": true } }, + "lavamoat-browserify": { + "builtin": { + "fs.existsSync": true, + "fs.mkdirSync": true, + "fs.readFileSync": true, + "fs.writeFileSync": true, + "path.dirname": true, + "path.extname": true, + "path.resolve": true, + "util.callbackify": true + }, + "globals": { + "console.warn": true, + "process.cwd": true + }, + "packages": { + "@lavamoat/lavapack": true, + "concat-stream": true, + "duplexify": true, + "json-stable-stringify": true, + "lavamoat-core": true, + "readable-stream": true, + "through2": true + } + }, + "lavamoat-core": { + "builtin": { + "events": true, + "fs.existsSync": true, + "fs.readFileSync": true, + "module.createRequire": true, + "module.createRequireFromPath": true, + "path.extname": true, + "path.join": true, + "path.sep": true + }, + "globals": { + "__dirname": true, + "console.warn": true, + "define": true + }, + "packages": { + "fromentries": true, + "json-stable-stringify": true, + "lavamoat-tofu": true, + "merge-deep": true, + "resolve": true + } + }, + "lavamoat-tofu": { + "globals": { + "console.log": true + }, + "packages": { + "@babel/parser": true, + "@babel/traverse": true + } + }, + "lazy-cache": { + "globals": { + "process.env.TRAVIS": true, + "process.env.UNLAZY": true + } + }, "lazystream": { "builtin": { "util.inherits": true @@ -2870,6 +2940,11 @@ "js-tokens": true } }, + "lru-cache": { + "packages": { + "yallist": true + } + }, "lru-queue": { "packages": { "es5-ext": true @@ -2936,6 +3011,13 @@ "timers-ext": true } }, + "merge-deep": { + "packages": { + "arr-union": true, + "clone-deep": true, + "kind-of": true + } + }, "merge-source-map": { "packages": { "source-map": true @@ -3000,6 +3082,12 @@ "is-extendable": true } }, + "mixin-object": { + "packages": { + "for-in": true, + "is-extendable": true + } + }, "mkdirp": { "builtin": { "fs": true, @@ -3732,6 +3820,9 @@ "globals": { "console": true, "process": true + }, + "packages": { + "lru-cache": true } }, "set-value": { @@ -3742,6 +3833,14 @@ "split-string": true } }, + "shallow-clone": { + "packages": { + "is-extendable": true, + "kind-of": true, + "lazy-cache": true, + "mixin-object": true + } + }, "shasum": { "builtin": { "buffer.Buffer.isBuffer": true, @@ -3816,16 +3915,15 @@ "console.time": true, "console.timeEnd": true, "fetch": true - }, - "packages": { - "amdefine": true } }, "source-map-resolve": { "builtin": { + "path.sep": true, "url.resolve": true }, "globals": { + "TextDecoder": true, "setImmediate": true }, "packages": { diff --git a/package.json b/package.json index 3dc9c235d..a633ffc44 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "metamask-crx", - "version": "10.2.2", + "version": "10.3.0", "private": true, "repository": { "type": "git", @@ -24,12 +24,12 @@ "dapp-chain": "GANACHE_ARGS='-b 2' concurrently -k -n ganache,dapp -p '[{time}][{name}]' 'yarn ganache:start' 'sleep 5 && yarn dapp'", "forwarder": "node ./development/static-server.js ./node_modules/@metamask/forwarder/dist/ --port 9010", "dapp-forwarder": "concurrently -k -n forwarder,dapp -p '[{time}][{name}]' 'yarn forwarder' 'yarn dapp'", - "test:unit": "mocha --exit --require test/env.js --require test/setup.js --recursive './app/**/*.test.js'", - "test:unit:global": "mocha --exit --require test/env.js --require test/setup.js --recursive test/unit-global/*.test.js", - "test:unit:jest": "./test/run-jest.sh", - "test:unit:lax": "mocha --exit --require test/env.js --require test/setup.js --ignore './app/scripts/controllers/permissions/*.test.js' --ignore './app/scripts/migrations/*.test.js' --recursive './app/**/*.test.js'", - "test:unit:strict": "mocha --exit --require test/env.js --require test/setup.js --recursive './app/scripts/controllers/permissions/*.test.js'", - "test:unit:path": "mocha --exit --require test/env.js --require test/setup.js --recursive", + "test:unit": "./test/test-unit-combined.sh", + "test:unit:jest": "./test/test-unit-jest.sh", + "test:unit:global": "mocha test/unit-global/*.test.js", + "test:unit:mocha": "mocha './app/**/*.test.js'", + "test:unit:lax": "mocha --config '.mocharc.lax.js' './app/**/*.test.js'", + "test:unit:strict": "mocha './app/scripts/controllers/permissions/*.test.js'", "test:e2e:chrome": "SELENIUM_BROWSER=chrome node test/e2e/run-all.js", "test:e2e:chrome:metrics": "SELENIUM_BROWSER=chrome node test/e2e/run-e2e-test.js test/e2e/metrics.spec.js", "test:e2e:firefox": "SELENIUM_BROWSER=firefox node test/e2e/run-all.js", @@ -54,7 +54,6 @@ "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/**/*.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", @@ -64,11 +63,14 @@ "storybook:deploy": "storybook-to-ghpages --existing-output-dir storybook-build --remote storybook --branch master", "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" + "lavamoat:build:auto": "lavamoat ./development/build/index.js --writeAutoPolicy", + "lavamoat:debug:build": "lavamoat ./development/build/index.js --writeAutoPolicyDebug", + "lavamoat:background:auto": "WRITE_AUTO_POLICY=1 yarn build prod", + "lavamoat:auto": "yarn lavamoat:build:auto && yarn lavamoat:background:auto" }, "resolutions": { "**/regenerator-runtime": "^0.13.7", + "**/caniuse-lite": "1.0.30001265", "**/configstore/dot-prop": "^5.1.1", "**/ethers/elliptic": "^6.5.4", "**/knex/minimist": "^1.2.5", @@ -102,7 +104,7 @@ "@fortawesome/fontawesome-free": "^5.13.0", "@material-ui/core": "^4.11.0", "@metamask/contract-metadata": "^1.28.0", - "@metamask/controllers": "^16.0.0", + "@metamask/controllers": "^17.0.0", "@metamask/eth-ledger-bridge-keyring": "^0.7.0", "@metamask/eth-token-tracker": "^3.0.1", "@metamask/etherscan-link": "^2.1.0", @@ -182,6 +184,7 @@ "react-inspector": "^2.3.0", "react-popper": "^2.2.3", "react-redux": "^7.2.0", + "react-responsive-carousel": "^3.2.21", "react-router-dom": "^5.1.2", "react-simple-file-input": "^2.0.0", "react-tippy": "^1.2.2", @@ -216,7 +219,7 @@ "@babel/preset-react": "^7.0.0", "@babel/register": "^7.5.5", "@lavamoat/allow-scripts": "^1.0.6", - "@lavamoat/lavapack": "^1.0.4", + "@lavamoat/lavapack": "^2.0.3", "@metamask/auto-changelog": "^2.1.0", "@metamask/eslint-config": "^6.0.0", "@metamask/eslint-config-jest": "^6.0.0", @@ -278,7 +281,7 @@ "gulp-livereload": "4.0.0", "gulp-rename": "^2.0.0", "gulp-rtlcss": "^1.4.0", - "gulp-sourcemaps": "^2.6.0", + "gulp-sourcemaps": "^3.0.0", "gulp-stylelint": "^13.0.0", "gulp-watch": "^5.0.1", "gulp-zip": "^4.0.0", @@ -287,7 +290,8 @@ "jest": "^26.6.3", "jsdom": "^11.2.0", "koa": "^2.7.0", - "lavamoat": "^5.3.1", + "lavamoat": "^5.3.4", + "lavamoat-browserify": "^14.0.3", "lavamoat-viz": "^6.0.9", "lockfile-lint": "^4.0.0", "loose-envify": "^1.4.0", @@ -312,6 +316,7 @@ "sass": "^1.32.4", "sass-loader": "^10.1.1", "selenium-webdriver": "4.0.0-alpha.7", + "semver": "^7.3.5", "serve-handler": "^6.1.2", "sinon": "^9.0.0", "source-map": "^0.7.2", @@ -323,6 +328,7 @@ "terser": "^5.7.0", "through2": "^4.0.2", "ttest": "^2.1.1", + "vinyl": "^2.2.1", "vinyl-buffer": "^1.0.1", "vinyl-source-stream": "^2.0.0", "vinyl-sourcemaps-apply": "^0.2.1", diff --git a/patches/abort-controller+3.0.0.patch b/patches/abort-controller+3.0.0.patch new file mode 100644 index 000000000..2210446d2 --- /dev/null +++ b/patches/abort-controller+3.0.0.patch @@ -0,0 +1,18 @@ +diff --git a/node_modules/abort-controller/browser.js b/node_modules/abort-controller/browser.js +index b0c5ec3..c8c8018 100644 +--- a/node_modules/abort-controller/browser.js ++++ b/node_modules/abort-controller/browser.js +@@ -2,12 +2,7 @@ + "use strict" + + /*eslint-disable @mysticatea/prettier */ +-const { AbortController, AbortSignal } = +- typeof self !== "undefined" ? self : +- typeof window !== "undefined" ? window : +- /* otherwise */ undefined ++const { AbortController } = globalThis; + /*eslint-enable @mysticatea/prettier */ + + module.exports = AbortController +-module.exports.AbortSignal = AbortSignal +-module.exports.default = AbortController diff --git a/patches/combine-source-map++convert-source-map+1.1.3.patch b/patches/combine-source-map++convert-source-map+1.1.3.patch new file mode 100644 index 000000000..c24f12817 --- /dev/null +++ b/patches/combine-source-map++convert-source-map+1.1.3.patch @@ -0,0 +1,22 @@ +diff --git a/node_modules/combine-source-map/node_modules/convert-source-map/index.js b/node_modules/combine-source-map/node_modules/convert-source-map/index.js +index bfe92d1..bee1ffe 100644 +--- a/node_modules/combine-source-map/node_modules/convert-source-map/index.js ++++ b/node_modules/combine-source-map/node_modules/convert-source-map/index.js +@@ -9,7 +9,7 @@ var mapFileCommentRx = + /(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"]+?)[ \t]*$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^\*]+?)[ \t]*(?:\*\/){1}[ \t]*$)/mg + + function decodeBase64(base64) { +- return new Buffer(base64, 'base64').toString(); ++ return Buffer.from(base64, 'base64').toString(); + } + + function stripComment(sm) { +@@ -60,7 +60,7 @@ Converter.prototype.toJSON = function (space) { + + Converter.prototype.toBase64 = function () { + var json = this.toJSON(); +- return new Buffer(json).toString('base64'); ++ return Buffer.from(json).toString('base64'); + }; + + Converter.prototype.toComment = function (options) { diff --git a/patches/gulp-sourcemaps+3.0.0.patch b/patches/gulp-sourcemaps+3.0.0.patch new file mode 100644 index 000000000..056bcb8e2 --- /dev/null +++ b/patches/gulp-sourcemaps+3.0.0.patch @@ -0,0 +1,44 @@ +diff --git a/node_modules/gulp-sourcemaps/src/init/index.internals.js b/node_modules/gulp-sourcemaps/src/init/index.internals.js +index 7104555..7dfe218 100644 +--- a/node_modules/gulp-sourcemaps/src/init/index.internals.js ++++ b/node_modules/gulp-sourcemaps/src/init/index.internals.js +@@ -72,7 +72,7 @@ module.exports = function(options, file, fileContent) { + + }); + // remove source map comment from source +- file.contents = new Buffer(sources.content, 'utf8'); ++ file.contents = Buffer.from(sources.content, 'utf8'); + } + + } +diff --git a/node_modules/gulp-sourcemaps/src/write/index.internals.js b/node_modules/gulp-sourcemaps/src/write/index.internals.js +index 89cee60..adfe8d1 100644 +--- a/node_modules/gulp-sourcemaps/src/write/index.internals.js ++++ b/node_modules/gulp-sourcemaps/src/write/index.internals.js +@@ -99,7 +99,7 @@ module.exports = function(destPath, options) { + + if (destPath === undefined || destPath === null) { + // encode source map into comment +- var base64Map = new Buffer(JSON.stringify(sourceMap)).toString('base64'); ++ var base64Map = Buffer.from(JSON.stringify(sourceMap)).toString('base64'); + comment = commentFormatter('data:application/json;charset=' + options.charset + ';base64,' + base64Map); + } else { + var mapFile = path.join(destPath, file.relative) + '.map'; +@@ -130,7 +130,7 @@ module.exports = function(destPath, options) { + + var sourceMapFile = file.clone(options.clone || { deep: false, contents: false }); + sourceMapFile.path = sourceMapPath; +- sourceMapFile.contents = new Buffer(JSON.stringify(sourceMap)); ++ sourceMapFile.contents = Buffer.from(JSON.stringify(sourceMap)); + sourceMapFile.stat = { + isFile: function() { return true; }, + isDirectory: function() { return false; }, +@@ -164,7 +164,7 @@ module.exports = function(destPath, options) { + + // append source map comment + if (options.addComment) { +- file.contents = Buffer.concat([file.contents, new Buffer(comment)]); ++ file.contents = Buffer.concat([file.contents, Buffer.from(comment)]); + } + } + diff --git a/patches/inline-source-map+0.6.2.patch b/patches/inline-source-map+0.6.2.patch new file mode 100644 index 000000000..5e5ae09a0 --- /dev/null +++ b/patches/inline-source-map+0.6.2.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/inline-source-map/index.js b/node_modules/inline-source-map/index.js +index df74d61..7641aad 100644 +--- a/node_modules/inline-source-map/index.js ++++ b/node_modules/inline-source-map/index.js +@@ -91,7 +91,7 @@ Generator.prototype.addSourceContent = function (sourceFile, sourcesContent) { + */ + Generator.prototype.base64Encode = function () { + var map = this.toString(); +- return new Buffer(map).toString('base64'); ++ return Buffer.from(map).toString('base64'); + }; + + /** diff --git a/patches/regenerator-runtime+0.13.7.patch b/patches/regenerator-runtime+0.13.7.patch index 1710d779a..778bc62ca 100644 --- a/patches/regenerator-runtime+0.13.7.patch +++ b/patches/regenerator-runtime+0.13.7.patch @@ -1,5 +1,5 @@ diff --git a/node_modules/regenerator-runtime/runtime.js b/node_modules/regenerator-runtime/runtime.js -index 547b8c6..c53a471 100644 +index 547b8c6..885626e 100644 --- a/node_modules/regenerator-runtime/runtime.js +++ b/node_modules/regenerator-runtime/runtime.js @@ -5,7 +5,7 @@ @@ -65,3 +65,12 @@ index 547b8c6..c53a471 100644 function pushTryEntry(locs) { var entry = { tryLoc: locs[0] }; +@@ -733,7 +734,7 @@ var runtime = (function (exports) { + )); + + try { +- regeneratorRuntime = runtime; ++ globalThis.regeneratorRuntime = runtime; + } catch (accidentalStrictMode) { + // This module should not be running in strict mode, so the above + // assignment should always work unless something is misconfigured. Just diff --git a/shared/constants/labels.js b/shared/constants/labels.js new file mode 100644 index 000000000..ab03c4eb0 --- /dev/null +++ b/shared/constants/labels.js @@ -0,0 +1,10 @@ +// The character limit on ENS names, nicknames and addresses before we truncate +export const TRUNCATED_NAME_CHAR_LIMIT = 11; + +// The number of characters to slice from the beginning of an address for truncated format: +// `${TRUNCATED_ADDRESS_START_CHARS}...${TRUNCATED_ADDRESS_END_CHARS}` +export const TRUNCATED_ADDRESS_START_CHARS = 5; + +// The number of characters to slice from the end of an address for truncated format: +// `${TRUNCATED_ADDRESS_START_CHARS}...${TRUNCATED_ADDRESS_END_CHARS}` +export const TRUNCATED_ADDRESS_END_CHARS = 4; diff --git a/shared/constants/swaps.js b/shared/constants/swaps.js index 5da0d08d8..2b1c9cbbf 100644 --- a/shared/constants/swaps.js +++ b/shared/constants/swaps.js @@ -114,7 +114,7 @@ export const ALLOWED_SWAPS_CHAIN_IDS = { // This is mapping for v1 URLs and will be removed once we migrate to v2. export const METASWAP_CHAINID_API_HOST_MAP = { [MAINNET_CHAIN_ID]: METASWAP_ETH_API_HOST, - [SWAPS_TESTNET_CHAIN_ID]: SWAPS_TESTNET_HOST, + [SWAPS_TESTNET_CHAIN_ID]: `${SWAPS_API_V2_BASE_URL}/networks/1`, [BSC_CHAIN_ID]: METASWAP_BSC_API_HOST, [RINKEBY_CHAIN_ID]: SWAPS_TESTNET_HOST, }; @@ -177,3 +177,5 @@ export const ETHEREUM = 'ethereum'; export const POLYGON = 'polygon'; export const BSC = 'bsc'; export const RINKEBY = 'rinkeby'; + +export const SWAPS_CLIENT_ID = 'extension'; diff --git a/shared/notifications/index.js b/shared/notifications/index.js index 4649fce00..da7c2f410 100644 --- a/shared/notifications/index.js +++ b/shared/notifications/index.js @@ -67,7 +67,7 @@ export const getTranslatedUINoficiations = (t, locale) => { }, 5: { ...UI_NOTIFICATIONS[5], - title: t('walletSeed'), + title: t('secretRecoveryPhrase'), description: t('notifications5Description'), actionText: t('notifications3ActionText'), date: new Intl.DateTimeFormat(formattedLocale).format( diff --git a/test/data/mock-state.json b/test/data/mock-state.json index 8b6171339..e8c979fd1 100644 --- a/test/data/mock-state.json +++ b/test/data/mock-state.json @@ -31,6 +31,11 @@ "name": "Test Account 2" } }, + "networkDetails": { + "EIPS": { + "1559": true + } + }, "cachedBalances": {}, "incomingTransactions": {}, "unapprovedTxs": { diff --git a/test/e2e/helpers.js b/test/e2e/helpers.js index dca25366a..5eb5ad8fb 100644 --- a/test/e2e/helpers.js +++ b/test/e2e/helpers.js @@ -130,7 +130,7 @@ async function withFixtures(options, testSuite) { if (webDriver) { await webDriver.quit(); } - if (dappServer) { + if (dappServer && dappServer.listening) { await new Promise((resolve, reject) => { dappServer.close((error) => { if (error) { diff --git a/test/e2e/metamask-ui.spec.js b/test/e2e/metamask-ui.spec.js index 74ea431f2..3f57d00ae 100644 --- a/test/e2e/metamask-ui.spec.js +++ b/test/e2e/metamask-ui.spec.js @@ -100,7 +100,7 @@ describe('MetaMask', function () { }); it('clicks the "No thanks" option on the metametrics opt-in screen', async function () { - await driver.clickElement('.btn-default'); + await driver.clickElement('.btn-secondary'); await driver.delay(largeDelayMs); }); diff --git a/test/e2e/run-all.sh b/test/e2e/run-all.sh deleted file mode 100755 index 88cc695d8..000000000 --- a/test/e2e/run-all.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env bash - -set -x -set -e -set -u -set -o pipefail - -readonly __DIR__=$( cd "${BASH_SOURCE[0]%/*}" && pwd ) - -for spec in "${__DIR__}"/tests/*.spec.js -do - node "${__DIR__}/run-e2e-test.js" "${spec}" -done - -node "${__DIR__}/run-e2e-test.js" "${__DIR__}/metamask-ui.spec.js" diff --git a/test/e2e/run-e2e-test.js b/test/e2e/run-e2e-test.js index c732de709..0a8b5e37c 100644 --- a/test/e2e/run-e2e-test.js +++ b/test/e2e/run-e2e-test.js @@ -74,7 +74,12 @@ async function main() { } await retry({ retries }, async () => { - await runInShell('yarn', ['mocha', '--no-timeouts', e2eTestPath]); + await runInShell('yarn', [ + 'mocha', + '--no-config', + '--no-timeouts', + e2eTestPath, + ]); }); } diff --git a/test/e2e/tests/contract-interactions.spec.js b/test/e2e/tests/contract-interactions.spec.js index e94c18f0a..6ef4cc4fb 100644 --- a/test/e2e/tests/contract-interactions.spec.js +++ b/test/e2e/tests/contract-interactions.spec.js @@ -1,5 +1,5 @@ const { strict: assert } = require('assert'); -const { withFixtures } = require('../helpers'); +const { withFixtures, regularDelayMs } = require('../helpers'); describe('Deploy contract and call contract methods', function () { let windowHandles; @@ -32,6 +32,7 @@ describe('Deploy contract and call contract methods', function () { await driver.openNewPage('http://127.0.0.1:8080/'); await driver.clickElement({ text: 'Connect', tag: 'button' }); await driver.waitUntilXWindowHandles(3); + await driver.delay(5000); windowHandles = await driver.getAllWindowHandles(); extension = windowHandles[0]; dapp = await driver.switchToWindowWithTitle( @@ -86,11 +87,13 @@ describe('Deploy contract and call contract methods', function () { await driver.switchToWindow(dapp); await driver.clickElement('#depositButton'); await driver.waitUntilXWindowHandles(3); + await driver.delay(5000); windowHandles = await driver.getAllWindowHandles(); await driver.switchToWindowWithTitle( 'MetaMask Notification', windowHandles, ); + await driver.delay(regularDelayMs); await driver.clickElement({ text: 'Confirm', tag: 'button' }); await driver.waitUntilXWindowHandles(2); await driver.switchToWindow(extension); @@ -110,11 +113,13 @@ describe('Deploy contract and call contract methods', function () { await driver.switchToWindow(dapp); await driver.clickElement('#withdrawButton'); await driver.waitUntilXWindowHandles(3); + await driver.delay(5000); windowHandles = await driver.getAllWindowHandles(); await driver.switchToWindowWithTitle( 'MetaMask Notification', windowHandles, ); + await driver.delay(regularDelayMs); await driver.clickElement({ text: 'Confirm', tag: 'button' }); await driver.waitUntilXWindowHandles(2); await driver.switchToWindow(extension); diff --git a/test/e2e/tests/custom-rpc-history.spec.js b/test/e2e/tests/custom-rpc-history.spec.js index 08a2bdd31..078cb124f 100644 --- a/test/e2e/tests/custom-rpc-history.spec.js +++ b/test/e2e/tests/custom-rpc-history.spec.js @@ -48,7 +48,7 @@ describe('Stores custom RPC history', function () { await chainIdInput.clear(); await chainIdInput.sendKeys(chainId.toString()); - await driver.clickElement('.network-form__footer .btn-secondary'); + await driver.clickElement('.network-form__footer .btn-primary'); await driver.findElement({ text: networkName, tag: 'span' }); }, ); @@ -192,7 +192,7 @@ describe('Stores custom RPC history', function () { await driver.clickElement({ text: 'Custom RPC', tag: 'span' }); // cancel new custom rpc - await driver.clickElement('.network-form__footer button.btn-default'); + await driver.clickElement('.network-form__footer button.btn-secondary'); const networkListItems = await driver.findClickableElements( '.networks-tab__networks-list-name', @@ -209,7 +209,7 @@ describe('Stores custom RPC history', function () { ); await driver.clickElement( - '.button.btn-danger.modal-container__footer-button', + '.button.btn-danger-primary.modal-container__footer-button', ); // wait for confirm delete modal to be removed from DOM. diff --git a/test/e2e/tests/from-import-ui.spec.js b/test/e2e/tests/from-import-ui.spec.js index 176b51e48..ad97bb257 100644 --- a/test/e2e/tests/from-import-ui.spec.js +++ b/test/e2e/tests/from-import-ui.spec.js @@ -38,7 +38,7 @@ describe('Metamask Import UI', function () { await driver.clickElement({ text: 'Import wallet', tag: 'button' }); // clicks the "No thanks" option on the metametrics opt-in screen - await driver.clickElement('.btn-default'); + await driver.clickElement('.btn-secondary'); // Import Secret Recovery Phrase await driver.fill( @@ -76,8 +76,9 @@ describe('Metamask Import UI', function () { // shows a QR code for the account const detailsModal = await driver.findVisibleElement('span .modal'); // shows the correct account address - const [address] = await driver.findElements('.readonly-input__input'); - assert.equal(await address.getAttribute('value'), testAddress); + const address = await driver.findElement('.qr-code__address'); + + assert.equal(await address.getText(), testAddress); await driver.clickElement('.account-modal__close'); await detailsModal.waitForElementState('hidden'); diff --git a/test/e2e/tests/incremental-security.spec.js b/test/e2e/tests/incremental-security.spec.js index 185a0d8c0..e000e9817 100644 --- a/test/e2e/tests/incremental-security.spec.js +++ b/test/e2e/tests/incremental-security.spec.js @@ -42,7 +42,7 @@ describe('Incremental Security', function () { await driver.clickElement({ text: 'Create a Wallet', tag: 'button' }); // clicks the "No thanks" option on the metametrics opt-in screen - await driver.clickElement('.btn-default'); + await driver.clickElement('.btn-secondary'); // accepts a secure password await driver.fill( @@ -80,8 +80,8 @@ describe('Incremental Security', function () { ); // gets the current accounts address - const addressInput = await driver.findElement('.readonly-input__input'); - const publicAddress = await addressInput.getAttribute('value'); + const address = await driver.findElement('.qr-code__address'); + const publicAddress = await address.getText(); // wait for account modal to be visible const accountModal = await driver.findVisibleElement('span .modal'); diff --git a/test/e2e/webdriver/chrome.js b/test/e2e/webdriver/chrome.js index bf3c2d023..9a1e1294b 100644 --- a/test/e2e/webdriver/chrome.js +++ b/test/e2e/webdriver/chrome.js @@ -16,13 +16,10 @@ class ChromeDriver { .setChromeOptions(options); const service = new chrome.ServiceBuilder(); - // Enables Chrome logging. + // Enables Chrome logging. Default: enabled // Especially useful for discovering why Chrome has crashed, but can also // be useful for revealing console errors (from the page or background). - if ( - process.env.ENABLE_CHROME_LOGGING && - process.env.ENABLE_CHROME_LOGGING !== 'false' - ) { + if (process.env.ENABLE_CHROME_LOGGING !== 'false') { service.setStdio('inherit').enableChromeLogging(); } if (port) { diff --git a/test/e2e/webdriver/driver.js b/test/e2e/webdriver/driver.js index d7a742399..ad8430794 100644 --- a/test/e2e/webdriver/driver.js +++ b/test/e2e/webdriver/driver.js @@ -277,13 +277,13 @@ class Driver { async switchToWindowWithTitle( title, - windowHandles, + initialWindowHandles, delayStep = 1000, timeout = 5000, ) { + let windowHandles = + initialWindowHandles || (await this.driver.getAllWindowHandles()); let timeElapsed = 0; - // eslint-disable-next-line no-param-reassign - windowHandles = windowHandles || (await this.driver.getAllWindowHandles()); while (timeElapsed <= timeout) { for (const handle of windowHandles) { await this.driver.switchTo().window(handle); @@ -294,6 +294,8 @@ class Driver { } await this.delay(delayStep); timeElapsed += delayStep; + // refresh the window handles + windowHandles = await this.driver.getAllWindowHandles(); } throw new Error(`No window with title: ${title}`); diff --git a/test/test-unit-combined.sh b/test/test-unit-combined.sh new file mode 100755 index 000000000..d793ba752 --- /dev/null +++ b/test/test-unit-combined.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +set -x +set -e +set -u +set -o pipefail + +concurrently --raw -n mocha,jest,global \ + "yarn test:unit:mocha" \ + "yarn test:unit:jest" \ + "yarn test:unit:global" diff --git a/test/run-jest.sh b/test/test-unit-jest.sh similarity index 78% rename from test/run-jest.sh rename to test/test-unit-jest.sh index 40b208732..384124920 100755 --- a/test/run-jest.sh +++ b/test/test-unit-jest.sh @@ -5,6 +5,6 @@ set -e set -u set -o pipefail -concurrently \ +concurrently -n production,development \ "jest --config=./jest.config.js $*" \ "jest --config=./development/jest.config.js $*" diff --git a/test/unit-global/protect-intrinsics.test.js b/test/unit-global/protect-intrinsics.test.js index 5075080f9..3958d7762 100644 --- a/test/unit-global/protect-intrinsics.test.js +++ b/test/unit-global/protect-intrinsics.test.js @@ -1,5 +1,6 @@ import 'ses/lockdown'; import '../../app/scripts/lockdown-run'; +import '../../app/scripts/lockdown-more'; import { strict as assert } from 'assert'; // These are Agoric inventions, and we don't care about them. diff --git a/ui/components/app/account-menu/account-menu.component.js b/ui/components/app/account-menu/account-menu.component.js index 41c809be8..c644a2176 100644 --- a/ui/components/app/account-menu/account-menu.component.js +++ b/ui/components/app/account-menu/account-menu.component.js @@ -10,6 +10,7 @@ import Identicon from '../../ui/identicon'; import SiteIcon from '../../ui/site-icon'; import UserPreferencedCurrencyDisplay from '../user-preferenced-currency-display'; import { PRIMARY } from '../../../helpers/constants/common'; +import { KEYRING_TYPES } from '../../../../shared/constants/hardware-wallets'; import { SETTINGS_ROUTE, NEW_ACCOUNT_ROUTE, @@ -19,6 +20,7 @@ import { } from '../../../helpers/constants/routes'; import TextField from '../../ui/text-field'; import SearchIcon from '../../ui/search-icon'; +import Button from '../../ui/button'; import { isBeta } from '../../../helpers/utils/build-types'; @@ -232,8 +234,8 @@ export default class AccountMenu extends Component { let label; switch (type) { - case 'Trezor Hardware': - case 'Ledger Hardware': + case KEYRING_TYPES.TREZOR: + case KEYRING_TYPES.LEDGER: label = t('hardware'); break; case 'Simple Key Pair': @@ -324,7 +326,7 @@ export default class AccountMenu extends Component {
{t('myAccounts')} - +
diff --git a/ui/components/app/account-menu/account-menu.test.js b/ui/components/app/account-menu/account-menu.test.js index fc715ead1..501c187dd 100644 --- a/ui/components/app/account-menu/account-menu.test.js +++ b/ui/components/app/account-menu/account-menu.test.js @@ -3,6 +3,7 @@ import sinon from 'sinon'; import configureMockStore from 'redux-mock-store'; import { Provider } from 'react-redux'; import { mountWithRouter } from '../../../../test/lib/render-helpers'; +import Button from '../../ui/button'; import AccountMenu from '.'; describe('Account Menu', () => { @@ -103,7 +104,7 @@ describe('Account Menu', () => { let logout; it('logout', () => { - logout = wrapper.find('.account-menu__lock-button'); + logout = wrapper.find(Button); expect(logout).toHaveLength(1); }); diff --git a/ui/components/app/account-menu/index.scss b/ui/components/app/account-menu/index.scss index 8f1f5c8c8..18059a7e8 100644 --- a/ui/components/app/account-menu/index.scss +++ b/ui/components/app/account-menu/index.scss @@ -97,14 +97,14 @@ align-items: center; } - &__lock-button { + & &__lock-button { @include H7; - border: 1px solid $dusty-gray; + border: 1px solid $ui-white; background-color: transparent; color: $white; - border-radius: 4px; padding: 3.5px 24px; + width: 59px; } &__item-icon { diff --git a/ui/components/app/advanced-gas-controls/advanced-gas-controls.component.js b/ui/components/app/advanced-gas-controls/advanced-gas-controls.component.js index 93f3e5ee3..e9e3117ac 100644 --- a/ui/components/app/advanced-gas-controls/advanced-gas-controls.component.js +++ b/ui/components/app/advanced-gas-controls/advanced-gas-controls.component.js @@ -6,7 +6,6 @@ import { I18nContext } from '../../../contexts/i18n'; import FormField from '../../ui/form-field'; import { GAS_ESTIMATE_TYPES } from '../../../../shared/constants/gas'; import { getGasFormErrorText } from '../../../helpers/constants/gas'; -import { checkNetworkAndAccountSupports1559 } from '../../../selectors'; import { getIsGasEstimatesLoading } from '../../../ducks/metamask/metamask'; export default function AdvancedGasControls({ @@ -24,15 +23,13 @@ export default function AdvancedGasControls({ maxFeeFiat, gasErrors, minimumGasLimit, + supportsEIP1559, }) { const t = useContext(I18nContext); - const networkAndAccountSupport1559 = useSelector( - checkNetworkAndAccountSupports1559, - ); const isGasEstimatesLoading = useSelector(getIsGasEstimatesLoading); const showFeeMarketFields = - networkAndAccountSupport1559 && + supportsEIP1559 && (gasEstimateType === GAS_ESTIMATE_TYPES.FEE_MARKET || gasEstimateType === GAS_ESTIMATE_TYPES.ETH_GASPRICE || isGasEstimatesLoading); @@ -54,7 +51,6 @@ export default function AdvancedGasControls({ value={gasLimit} allowDecimals={false} numeric - autoFocus /> {showFeeMarketFields ? ( <> @@ -132,4 +128,5 @@ AdvancedGasControls.propTypes = { maxFeeFiat: PropTypes.string, gasErrors: PropTypes.object, minimumGasLimit: PropTypes.string, + supportsEIP1559: PropTypes.bool, }; diff --git a/ui/components/app/advanced-gas-controls/advanced-gas-controls.test.js b/ui/components/app/advanced-gas-controls/advanced-gas-controls.test.js new file mode 100644 index 000000000..f99cd1618 --- /dev/null +++ b/ui/components/app/advanced-gas-controls/advanced-gas-controls.test.js @@ -0,0 +1,39 @@ +import React from 'react'; +import configureMockStore from 'redux-mock-store'; + +import { GAS_ESTIMATE_TYPES } from '../../../../shared/constants/gas'; +import { renderWithProvider } from '../../../../test/jest/rendering'; + +import AdvancedGasControls from './advanced-gas-controls.component'; + +const renderComponent = (props) => { + const store = configureMockStore([])({ metamask: { identities: [] } }); + return renderWithProvider(, store); +}; + +describe('AdvancedGasControls Component', () => { + it('should render correctly', () => { + expect(() => { + renderComponent(); + }).not.toThrow(); + }); + + it('should not render maxFee and maxPriorityFee inputs if supportsEIP1559 is false', () => { + const { queryByText } = renderComponent({ supportsEIP1559: false }); + expect(queryByText('Gas Limit')).toBeInTheDocument(); + expect(queryByText('Gas price')).toBeInTheDocument(); + expect(queryByText('Max fee')).not.toBeInTheDocument(); + expect(queryByText('Max priority fee')).not.toBeInTheDocument(); + }); + + it('should render maxFee and maxPriorityFee inputs if supportsEIP1559 is true', () => { + const { queryByText } = renderComponent({ + gasEstimateType: GAS_ESTIMATE_TYPES.FEE_MARKET, + supportsEIP1559: true, + }); + expect(queryByText('Gas price')).not.toBeInTheDocument(); + expect(queryByText('Gas Limit')).toBeInTheDocument(); + expect(queryByText('Max fee')).toBeInTheDocument(); + expect(queryByText('Max priority fee')).toBeInTheDocument(); + }); +}); diff --git a/ui/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 index de7010883..a1a170466 100644 --- a/ui/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 @@ -37,7 +37,6 @@ & &-button { height: 40px; width: 50%; - border-radius: 100px; margin-right: 24px; &:last-of-type { diff --git a/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js b/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js index 1b887bba4..cbcac50eb 100644 --- a/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js +++ b/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.js @@ -76,7 +76,6 @@ const UnconnectedAccountAlert = () => { disabled={alertState === LOADING} onClick={onClose} type="primary" - rounded className="unconnected-account-alert__dismiss-button" > {t('dismiss')} diff --git a/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.scss b/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.scss index 11c12f420..cedd14617 100644 --- a/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.scss +++ b/ui/components/app/alerts/unconnected-account-alert/unconnected-account-alert.scss @@ -22,7 +22,6 @@ height: 40px; width: 100px; border: 0; - border-radius: 100px; } &__error { diff --git a/ui/components/app/app-components.scss b/ui/components/app/app-components.scss index aabadf245..d76c2998f 100644 --- a/ui/components/app/app-components.scss +++ b/ui/components/app/app-components.scss @@ -46,3 +46,4 @@ @import 'transaction-total-banner/index'; @import 'wallet-overview/index'; @import 'whats-new-popup/index'; +@import 'loading-network-screen/index' diff --git a/ui/components/app/cancel-button/cancel-button.js b/ui/components/app/cancel-button/cancel-button.js index bef23f98c..0efce2212 100644 --- a/ui/components/app/cancel-button/cancel-button.js +++ b/ui/components/app/cancel-button/cancel-button.js @@ -33,11 +33,10 @@ export default function CancelButton({ const btn = (
- {networkAndAccountSupport1559 && - !requireDappAcknowledgement && - showEducationButton && ( -
- -
- )} + {supportsEIP1559 && !requireDappAcknowledgement && showEducationButton && ( +
+ +
+ )}
); diff --git a/ui/components/app/edit-gas-popover/edit-gas-popover.component.js b/ui/components/app/edit-gas-popover/edit-gas-popover.component.js index 64280984c..5825143bc 100644 --- a/ui/components/app/edit-gas-popover/edit-gas-popover.component.js +++ b/ui/components/app/edit-gas-popover/edit-gas-popover.component.js @@ -29,6 +29,7 @@ import { import LoadingHeartBeat from '../../ui/loading-heartbeat'; import { checkNetworkAndAccountSupports1559 } from '../../../selectors'; import { useIncrementedGasFees } from '../../../hooks/useIncrementedGasFees'; +import { isLegacyTransaction } from '../../../helpers/utils/transactions.util'; export default function EditGasPopover({ popoverTitle = '', @@ -42,9 +43,9 @@ export default function EditGasPopover({ }) { const t = useContext(I18nContext); const dispatch = useDispatch(); - const networkAndAccountSupport1559 = useSelector( - checkNetworkAndAccountSupports1559, - ); + const supportsEIP1559 = + useSelector(checkNetworkAndAccountSupports1559) && + !isLegacyTransaction(transaction?.txParams); const gasLoadingAnimationIsShowing = useSelector( getGasLoadingAnimationIsShowing, ); @@ -52,7 +53,7 @@ export default function EditGasPopover({ const showEducationButton = (mode === EDIT_GAS_MODES.MODIFY_IN_PLACE || mode === EDIT_GAS_MODES.SWAPS) && - networkAndAccountSupport1559; + supportsEIP1559; const [showEducationContent, setShowEducationContent] = useState(false); const [warning] = useState(null); @@ -132,7 +133,7 @@ export default function EditGasPopover({ closePopover(); } - const newGasSettings = networkAndAccountSupport1559 + const newGasSettings = supportsEIP1559 ? { gas: decimalToHex(gasLimit), gasLimit: decimalToHex(gasLimit), @@ -149,7 +150,7 @@ export default function EditGasPopover({ const cleanTransactionParams = { ...updatedTransaction.txParams }; - if (networkAndAccountSupport1559) { + if (supportsEIP1559) { delete cleanTransactionParams.gasPrice; } @@ -182,7 +183,7 @@ export default function EditGasPopover({ break; case EDIT_GAS_MODES.SWAPS: // This popover component should only be used for the "FEE_MARKET" type in Swaps. - if (networkAndAccountSupport1559) { + if (supportsEIP1559) { dispatch(updateSwapsUserFeeLevel(estimateToUse || 'custom')); dispatch(updateCustomSwapsEIP1559GasParams(newGasSettings)); } @@ -201,7 +202,7 @@ export default function EditGasPopover({ gasPrice, maxFeePerGas, maxPriorityFeePerGas, - networkAndAccountSupport1559, + supportsEIP1559, estimateToUse, estimatedBaseFee, ]); diff --git a/ui/components/app/edit-gas-popover/edit-gas-popover.stories.js b/ui/components/app/edit-gas-popover/edit-gas-popover.stories.js index 93d7cc830..b18d834be 100644 --- a/ui/components/app/edit-gas-popover/edit-gas-popover.stories.js +++ b/ui/components/app/edit-gas-popover/edit-gas-popover.stories.js @@ -1,31 +1,89 @@ import React from 'react'; +import { Provider } from 'react-redux'; +import { action } from '@storybook/addon-actions'; +import { boolean } from '@storybook/addon-knobs'; +import { decGWEIToHexWEI } from '../../../helpers/utils/conversions.util'; +import configureStore from '../../../store/store'; +import testData from '../../../../.storybook/test-data'; +import { EDIT_GAS_MODES } from '../../../../shared/constants/gas'; import EditGasPopover from '.'; +const store = configureStore(testData); + export default { title: 'Edit Gas Display Popover', + decorators: [(story) => {story()}], id: __filename, }; -export const basic = () => { +export const Basic = () => { return (
- + action(`Close Edit Gas Popover`)()} + minimumGasLimit="5700" + />
); }; -export const basicWithDifferentButtonText = () => { +export const BasicWithDifferentButtonText = () => { return (
- + action(`Close Edit Gas Popover`)()} + minimumGasLimit="5700" + />
); }; -export const educationalContentFlow = () => { +export const EducationalContentFlow = () => { return (
- + action(`Close Edit Gas Popover`)()} + minimumGasLimit="5700" + />
); }; diff --git a/ui/components/app/home-notification/index.scss b/ui/components/app/home-notification/index.scss index 8d522a0e4..62a556fbb 100644 --- a/ui/components/app/home-notification/index.scss +++ b/ui/components/app/home-notification/index.scss @@ -71,7 +71,6 @@ & &__ignore-button { border-color: #6a737d; box-sizing: border-box; - border-radius: 6px; color: $white; background-color: inherit; height: 34px; @@ -95,7 +94,6 @@ & &__accept-button { border-color: #6a737d; box-sizing: border-box; - border-radius: 6px; color: $white; background-color: inherit; height: 34px; diff --git a/ui/components/app/loading-network-screen/index.scss b/ui/components/app/loading-network-screen/index.scss new file mode 100644 index 000000000..95039f422 --- /dev/null +++ b/ui/components/app/loading-network-screen/index.scss @@ -0,0 +1,6 @@ +.loading-overlay__error-buttons { + button { + margin: 5px; + padding: 5px 30px; + } +} diff --git a/ui/components/app/loading-network-screen/loading-network-screen.component.js b/ui/components/app/loading-network-screen/loading-network-screen.component.js index 7f2f2df48..0b3f05229 100644 --- a/ui/components/app/loading-network-screen/loading-network-screen.component.js +++ b/ui/components/app/loading-network-screen/loading-network-screen.component.js @@ -71,7 +71,7 @@ export default class LoadingNetworkScreen extends PureComponent { {this.context.t('somethingWentWrong')}
{exportPrivateKeyFeatureEnabled ? ( diff --git a/ui/components/app/modals/account-modal-container/index.scss b/ui/components/app/modals/account-modal-container/index.scss index bfb0c37a8..149a4de96 100644 --- a/ui/components/app/modals/account-modal-container/index.scss +++ b/ui/components/app/modals/account-modal-container/index.scss @@ -31,7 +31,7 @@ @include H1; background-color: transparent; - color: $dusty-gray; + color: $ui-black; position: absolute; cursor: pointer; top: -10px; diff --git a/ui/components/app/modals/cancel-transaction/cancel-transaction.component.js b/ui/components/app/modals/cancel-transaction/cancel-transaction.component.js index 9b436f7d9..f98ce7c7b 100644 --- a/ui/components/app/modals/cancel-transaction/cancel-transaction.component.js +++ b/ui/components/app/modals/cancel-transaction/cancel-transaction.component.js @@ -55,7 +55,6 @@ export default class CancelTransaction extends PureComponent { onCancel={this.handleCancel} submitText={t('yesLetsTry')} cancelText={t('nevermind')} - submitType="secondary" submitDisabled={busy} >
diff --git a/ui/components/app/modals/confirm-delete-network/confirm-delete-network.component.js b/ui/components/app/modals/confirm-delete-network/confirm-delete-network.component.js index a8be936a5..74b48bb85 100644 --- a/ui/components/app/modals/confirm-delete-network/confirm-delete-network.component.js +++ b/ui/components/app/modals/confirm-delete-network/confirm-delete-network.component.js @@ -30,7 +30,7 @@ export default class ConfirmDeleteNetwork extends PureComponent { onCancel={() => this.props.hideModal()} submitText={t('delete')} cancelText={t('cancel')} - submitType="danger" + submitType="danger-primary" > { it('clicks cancel to hide modal', () => { const cancelButton = wrapper.find( - '.button.btn-default.modal-container__footer-button', + '.button.btn-secondary.modal-container__footer-button', ); cancelButton.simulate('click'); @@ -43,7 +43,7 @@ describe('Confirm Delete Network', () => { it('clicks delete to delete the target and hides modal', async () => { const deleteButton = wrapper.find( - '.button.btn-danger.modal-container__footer-button', + '.button.btn-danger-primary.modal-container__footer-button', ); deleteButton.simulate('click'); diff --git a/ui/components/app/modals/confirm-remove-account/confirm-remove-account.component.js b/ui/components/app/modals/confirm-remove-account/confirm-remove-account.component.js index e7bfd69cd..891e40f87 100644 --- a/ui/components/app/modals/confirm-remove-account/confirm-remove-account.component.js +++ b/ui/components/app/modals/confirm-remove-account/confirm-remove-account.component.js @@ -95,7 +95,6 @@ export default class ConfirmRemoveAccount extends Component { onCancel={this.handleCancel} submitText={t('remove')} cancelText={t('nevermind')} - submitType="secondary" >
{this.renderSelectedAccount()} diff --git a/ui/components/app/modals/confirm-remove-account/confirm-remove-account.test.js b/ui/components/app/modals/confirm-remove-account/confirm-remove-account.test.js index da59aeffa..f55fec4be 100644 --- a/ui/components/app/modals/confirm-remove-account/confirm-remove-account.test.js +++ b/ui/components/app/modals/confirm-remove-account/confirm-remove-account.test.js @@ -51,14 +51,14 @@ describe('Confirm Remove Account', () => { }); it('nevermind', () => { - const nevermind = wrapper.find({ type: 'default' }); + const nevermind = wrapper.find({ type: 'secondary' }); nevermind.simulate('click'); expect(props.hideModal.calledOnce).toStrictEqual(true); }); it('remove', async () => { - const remove = wrapper.find({ type: 'secondary' }); + const remove = wrapper.find({ type: 'primary' }); remove.simulate('click'); expect(await props.removeAccount.calledOnce).toStrictEqual(true); diff --git a/ui/components/app/modals/confirm-reset-account/confirm-reset-account.component.js b/ui/components/app/modals/confirm-reset-account/confirm-reset-account.component.js index c4e5a9a17..f9c4fe8fb 100644 --- a/ui/components/app/modals/confirm-reset-account/confirm-reset-account.component.js +++ b/ui/components/app/modals/confirm-reset-account/confirm-reset-account.component.js @@ -25,7 +25,7 @@ export default class ConfirmResetAccount extends PureComponent { onCancel={() => this.props.hideModal()} submitText={t('reset')} cancelText={t('nevermind')} - submitType="danger" + submitType="danger-primary" > { it('hides modal when nevermind button is clicked', () => { const nevermind = wrapper.find( - '.btn-default.modal-container__footer-button', + '.btn-secondary.modal-container__footer-button', ); nevermind.simulate('click'); @@ -33,7 +33,9 @@ describe('Confirm Reset Account', () => { }); it('resets account and hides modal when reset button is clicked', async () => { - const reset = wrapper.find('.btn-danger.modal-container__footer-button'); + const reset = wrapper.find( + '.btn-danger-primary.modal-container__footer-button', + ); reset.simulate('click'); expect(await props.resetAccount.calledOnce).toStrictEqual(true); diff --git a/ui/components/app/modals/customize-nonce/customize-nonce.component.js b/ui/components/app/modals/customize-nonce/customize-nonce.component.js index d2cacc816..91357d89e 100644 --- a/ui/components/app/modals/customize-nonce/customize-nonce.component.js +++ b/ui/components/app/modals/customize-nonce/customize-nonce.component.js @@ -37,11 +37,8 @@ const CustomizeNonce = ({ hideModal(); }} submitText={t('save')} - submitType="primary" onCancel={() => hideModal()} cancelText={t('cancel')} - cancelType="secondary" - rounded contentClass="customize-nonce-modal-content" containerClass="customize-nonce-modal-container" > diff --git a/ui/components/app/modals/edit-approval-permission/edit-approval-permission.component.js b/ui/components/app/modals/edit-approval-permission/edit-approval-permission.component.js index 2e100353f..b6cfec569 100644 --- a/ui/components/app/modals/edit-approval-permission/edit-approval-permission.component.js +++ b/ui/components/app/modals/edit-approval-permission/edit-approval-permission.component.js @@ -226,7 +226,6 @@ export default class EditApprovalPermission extends PureComponent { hideModal(); }} submitText={t('save')} - submitType="primary" contentClass="edit-approval-permission-modal-content" containerClass="edit-approval-permission-modal-container" submitDisabled={disabled} diff --git a/ui/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 index ba6e4ca8b..ae378f3ce 100644 --- a/ui/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 @@ -93,7 +93,7 @@ export default class ExportPrivateKeyModal extends Component {
{!privateKey && (
diff --git a/ui/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 index 7b90b24ff..ff6650652 100644 --- a/ui/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 @@ -28,7 +28,9 @@ describe('MetaMetrics Opt In', () => { }); it('passes false to setParticipateInMetaMetrics and hides modal', async () => { - const noThanks = wrapper.find('.btn-default.page-container__footer-button'); + const noThanks = wrapper.find( + '.btn-secondary.page-container__footer-button', + ); noThanks.simulate('click'); expect(await props.setParticipateInMetaMetrics.calledOnce).toStrictEqual( diff --git a/ui/components/app/modals/modal.js b/ui/components/app/modals/modal.js index cd1d4c3ab..16a5d4807 100644 --- a/ui/components/app/modals/modal.js +++ b/ui/components/app/modals/modal.js @@ -184,8 +184,13 @@ const MODALS = { top: getEnvironmentType() === ENVIRONMENT_TYPE_POPUP ? '52vh' : '36.5vh', }, laptopModalStyle: { - width: '449px', + width: + getEnvironmentType() === ENVIRONMENT_TYPE_POPUP ? '357px' : '449px', top: 'calc(33% + 45px)', + paddingLeft: + getEnvironmentType() === ENVIRONMENT_TYPE_POPUP ? '16px' : null, + paddingRight: + getEnvironmentType() === ENVIRONMENT_TYPE_POPUP ? '16px' : null, }, }, diff --git a/ui/components/app/modals/qr-scanner/qr-scanner.component.js b/ui/components/app/modals/qr-scanner/qr-scanner.component.js index fac593717..610c2631b 100644 --- a/ui/components/app/modals/qr-scanner/qr-scanner.component.js +++ b/ui/components/app/modals/qr-scanner/qr-scanner.component.js @@ -221,7 +221,6 @@ export default class QrScanner extends Component { onSubmit={this.tryAgain} cancelText={t('cancel')} submitText={t('tryAgain')} - submitButtonType="confirm" /> ); diff --git a/ui/components/app/modals/reject-transactions/reject-transactions.component.js b/ui/components/app/modals/reject-transactions/reject-transactions.component.js index 3bb4cd9d9..6ef0daa91 100644 --- a/ui/components/app/modals/reject-transactions/reject-transactions.component.js +++ b/ui/components/app/modals/reject-transactions/reject-transactions.component.js @@ -32,7 +32,6 @@ export default class RejectTransactionsModal extends PureComponent { onCancel={hideModal} submitText={t('rejectAll')} cancelText={t('cancel')} - submitType="secondary" >
diff --git a/ui/components/app/modals/reject-transactions/reject-transactions.test.js b/ui/components/app/modals/reject-transactions/reject-transactions.test.js index 043f9bab7..e8ec7a7b5 100644 --- a/ui/components/app/modals/reject-transactions/reject-transactions.test.js +++ b/ui/components/app/modals/reject-transactions/reject-transactions.test.js @@ -26,7 +26,7 @@ describe('Reject Transactions Model', () => { it('hides modal when cancel button is clicked', () => { const cancelButton = wrapper.find( - '.btn-default.modal-container__footer-button', + '.btn-secondary.modal-container__footer-button', ); cancelButton.simulate('click'); @@ -35,7 +35,7 @@ describe('Reject Transactions Model', () => { it('onSubmit is called and hides modal when reject all clicked', async () => { const rejectAllButton = wrapper.find( - '.btn-secondary.modal-container__footer-button', + '.btn-primary.modal-container__footer-button', ); rejectAllButton.simulate('click'); diff --git a/ui/components/app/modals/transaction-confirmed/transaction-confirmed.test.js b/ui/components/app/modals/transaction-confirmed/transaction-confirmed.test.js index 84111a9ee..0e1658242 100644 --- a/ui/components/app/modals/transaction-confirmed/transaction-confirmed.test.js +++ b/ui/components/app/modals/transaction-confirmed/transaction-confirmed.test.js @@ -17,9 +17,7 @@ describe('Transaction Confirmed', () => { }, }, ); - const submit = wrapper.find( - '.btn-secondary.modal-container__footer-button', - ); + const submit = wrapper.find('.btn-primary.modal-container__footer-button'); submit.simulate('click'); expect(props.onSubmit.calledOnce).toStrictEqual(true); diff --git a/ui/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 index 3213e896b..7cacc40c8 100644 --- a/ui/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 @@ -70,12 +70,6 @@ export default class PermissionPageContainerContent extends PureComponent { ); } - getAccountDescriptor(identity) { - return `${identity.label} (...${identity.address.slice( - identity.address.length - 4, - )})`; - } - renderAccountTooltip(textContent) { const { selectedIdentities } = this.props; const { t } = this.context; @@ -90,7 +84,7 @@ export default class PermissionPageContainerContent extends PureComponent { {selectedIdentities.slice(0, 6).map((identity, index) => { return (
- {this.getAccountDescriptor(identity)} + {identity.addressLabel}
); })} @@ -126,7 +120,7 @@ export default class PermissionPageContainerContent extends PureComponent { ), ]); } - return t('connectTo', [this.getAccountDescriptor(selectedIdentities[0])]); + return t('connectTo', [selectedIdentities[0]?.addressLabel]); } render() { diff --git a/ui/components/app/permission-page-container/permission-page-container.component.js b/ui/components/app/permission-page-container/permission-page-container.component.js index a8378f746..2a8daa2f6 100644 --- a/ui/components/app/permission-page-container/permission-page-container.component.js +++ b/ui/components/app/permission-page-container/permission-page-container.component.js @@ -141,7 +141,6 @@ export default class PermissionPageContainer extends Component { cancelText={this.context.t('cancel')} onSubmit={() => this.onSubmit()} submitText={this.context.t('connect')} - submitButtonType="confirm" buttonSizeLarge={false} />
diff --git a/ui/components/app/recovery-phrase-reminder/recovery-phrase-reminder.js b/ui/components/app/recovery-phrase-reminder/recovery-phrase-reminder.js index 1b8b66ba3..23dd36442 100644 --- a/ui/components/app/recovery-phrase-reminder/recovery-phrase-reminder.js +++ b/ui/components/app/recovery-phrase-reminder/recovery-phrase-reminder.js @@ -75,7 +75,7 @@ export default function RecoveryPhraseReminder({ onConfirm, hasBackedUp }) { - diff --git a/ui/components/app/selected-account/selected-account-component.test.js b/ui/components/app/selected-account/selected-account-component.test.js index d50bd34f2..bc55c7e7e 100644 --- a/ui/components/app/selected-account/selected-account-component.test.js +++ b/ui/components/app/selected-account/selected-account-component.test.js @@ -15,7 +15,7 @@ describe('SelectedAccount Component', () => { ); // Checksummed version of address is displayed expect(wrapper.find('.selected-account__address').text()).toStrictEqual( - '0x1B82...5C9D', + '0x1B8...5C9D', ); expect(wrapper.find('.selected-account__name').text()).toStrictEqual( 'testName', diff --git a/ui/components/app/signature-request-original/signature-request-original.component.js b/ui/components/app/signature-request-original/signature-request-original.component.js index c999cf282..ec3baf497 100644 --- a/ui/components/app/signature-request-original/signature-request-original.component.js +++ b/ui/components/app/signature-request-original/signature-request-original.component.js @@ -285,50 +285,58 @@ export default class SignatureRequestOriginal extends Component { history, mostRecentOverviewPage, sign, + txData: { type }, } = this.props; + const { metricsEvent, t } = this.context; return (
); diff --git a/ui/components/app/signature-request/signature-request-footer/index.scss b/ui/components/app/signature-request/signature-request-footer/index.scss index b0c07f0b1..b1470d3e3 100644 --- a/ui/components/app/signature-request/signature-request-footer/index.scss +++ b/ui/components/app/signature-request/signature-request-footer/index.scss @@ -6,7 +6,6 @@ text-transform: uppercase; flex: 1; margin: 1rem 0.5rem; - border-radius: 3px; } button:first-child { diff --git a/ui/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 index c0a08812b..0ca254079 100644 --- a/ui/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 @@ -16,7 +16,7 @@ export default class SignatureRequestFooter extends PureComponent { const { cancelAction, signAction } = this.props; return (
- @@ -181,8 +181,13 @@ export default class TransactionListItemDetails extends PureComponent { containerClassName="transaction-list-item-details__header-button-tooltip-container" title={ blockExplorerUrl - ? t('viewOnCustomBlockExplorer', [blockExplorerUrl]) - : t('viewOnEtherscan') + ? t('viewOnCustomBlockExplorer', [ + t('blockExplorerTransactionAction'), + blockExplorerUrl, + ]) + : t('viewOnEtherscan', [ + t('blockExplorerTransactionAction'), + ]) } > + ) + ); + } + + return ( + onClose && ( +
onClose()} + /> + ) + ); + } + renderHeaderRow() { const { showBackButton, @@ -47,14 +79,7 @@ export default class PageContainerHeader extends Component { } render() { - const { - title, - subtitle, - onClose, - tabs, - headerCloseText, - className, - } = this.props; + const { title, subtitle, tabs, className, hideClose } = this.props; return (
{this.renderHeaderRow()} - {title &&
{title}
} - - {subtitle &&
{subtitle}
} - - {onClose && headerCloseText ? ( - - ) : ( - onClose && ( -
onClose()} - /> - ) + {title} +
)} + {subtitle &&
{subtitle}
} + + {this.renderCloseAction()} {this.renderTabs()}
diff --git a/ui/components/ui/page-container/page-container.component.js b/ui/components/ui/page-container/page-container.component.js index 28b5f75b0..a7bee1fe6 100644 --- a/ui/components/ui/page-container/page-container.component.js +++ b/ui/components/ui/page-container/page-container.component.js @@ -143,7 +143,6 @@ export default class PageContainer extends PureComponent { onSubmit={onSubmit} submitText={tabSubmitText || submitText} disabled={disabled} - submitButtonType="primary" />
diff --git a/ui/components/ui/popover/popover.component.js b/ui/components/ui/popover/popover.component.js index c4bae4ffc..637f07528 100644 --- a/ui/components/ui/popover/popover.component.js +++ b/ui/components/ui/popover/popover.component.js @@ -20,6 +20,7 @@ const Popover = ({ centerTitle, }) => { const t = useI18nContext(); + const showHeader = title || onBack || subtitle || onClose; return (
{CustomBackground ? ( @@ -32,36 +33,38 @@ const Popover = ({ ref={popoverRef} > {showArrow ?
: null} -
-
-

- {onBack ? ( + {showHeader && ( +
+
+

+ {onBack ? ( +

+ {onClose ? (

- {onClose ? ( -
+ {subtitle ? ( +

{subtitle}

) : null} -
- {subtitle ? ( -

{subtitle}

- ) : null} - + + )} {children ? (
{children} @@ -78,7 +81,7 @@ const Popover = ({ }; Popover.propTypes = { - title: PropTypes.string.isRequired, + title: PropTypes.string, subtitle: PropTypes.string, children: PropTypes.node, footer: PropTypes.node, diff --git a/ui/components/ui/qr-code/index.scss b/ui/components/ui/qr-code/index.scss index 521075f64..c228ffeda 100644 --- a/ui/components/ui/qr-code/index.scss +++ b/ui/components/ui/qr-code/index.scss @@ -24,4 +24,11 @@ color: #f7861c; margin-bottom: 9px; } + + &__address { + @include H7; + + background-color: $ui-1; + padding: 12px; + } } diff --git a/ui/components/ui/qr-code/qr-code.js b/ui/components/ui/qr-code/qr-code.js index db0eeed2c..84f40836b 100644 --- a/ui/components/ui/qr-code/qr-code.js +++ b/ui/components/ui/qr-code/qr-code.js @@ -3,7 +3,6 @@ import React from 'react'; 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'; export default connect(mapStateToProps)(QrCodeView); @@ -47,11 +46,7 @@ function QrCodeView(props) { __html: qrImage.createTableTag(4), }} /> - +
{toChecksumHexAddress(data)}
); } diff --git a/ui/components/ui/radio-group/radio-group.component.js b/ui/components/ui/radio-group/radio-group.component.js index 7bc0dae6b..90c136fb9 100644 --- a/ui/components/ui/radio-group/radio-group.component.js +++ b/ui/components/ui/radio-group/radio-group.component.js @@ -24,8 +24,8 @@ function Connector({ isFirst, isLast }) { } Connector.propTypes = { - isFirst: PropTypes.boolean, - isLast: PropTypes.boolean, + isFirst: PropTypes.bool, + isLast: PropTypes.bool, }; export default function RadioGroup({ options, name, selectedValue, onChange }) { diff --git a/ui/components/ui/sender-to-recipient/index.scss b/ui/components/ui/sender-to-recipient/index.scss index 5c2c3cf5e..edd50cd4a 100644 --- a/ui/components/ui/sender-to-recipient/index.scss +++ b/ui/components/ui/sender-to-recipient/index.scss @@ -178,6 +178,7 @@ overflow: hidden; text-overflow: ellipsis; white-space: nowrap; + margin-inline-start: 8px; [dir='rtl'] & { /*rtl:ignore*/ diff --git a/ui/components/ui/sender-to-recipient/sender-to-recipient.component.js b/ui/components/ui/sender-to-recipient/sender-to-recipient.component.js index 635687053..fe6655cc8 100644 --- a/ui/components/ui/sender-to-recipient/sender-to-recipient.component.js +++ b/ui/components/ui/sender-to-recipient/sender-to-recipient.component.js @@ -55,14 +55,12 @@ function SenderAddress({ } }} > - {!addressOnly && ( -
- -
- )} +
+ +
{addressOnly ? ( - {`${t('from')}: ${senderName || checksummedSenderAddress}`} + {`${t('from')}: ${ + senderName || shortenAddress(checksummedSenderAddress) + }`} ) : ( senderName @@ -132,11 +132,9 @@ function RecipientWithAddress({ } }} > - {!addressOnly && ( -
- -
- )} +
+ +
{addressOnly ? `${t('to')}: ` : ''} {addressOnly - ? recipientNickname || recipientEns || checksummedRecipientAddress + ? recipientNickname || + recipientEns || + shortenAddress(checksummedRecipientAddress) : recipientNickname || recipientEns || recipientName || @@ -225,7 +225,7 @@ export default function SenderToRecipient({ /> ) : (
- {!addressOnly && } +
{t('newContract')}
)} diff --git a/ui/components/ui/slider/index.js b/ui/components/ui/slider/index.js new file mode 100644 index 000000000..52e836261 --- /dev/null +++ b/ui/components/ui/slider/index.js @@ -0,0 +1,3 @@ +import Slider from './slider.component'; + +export default Slider; diff --git a/ui/components/ui/slider/index.scss b/ui/components/ui/slider/index.scss new file mode 100644 index 000000000..00ff33766 --- /dev/null +++ b/ui/components/ui/slider/index.scss @@ -0,0 +1,48 @@ +.slider { + display: inline-block; + width: 100%; + + &__heading, + &__footer { + display: flex; + justify-content: space-between; + } + + &__heading-title { + display: flex; + align-items: center; + + > p { + margin-left: 10px; + font-size: 14px; + } + } + + &__heading-detail > p { + font-size: 14px; + } + + &__footer-info { + display: flex; + align-items: center; + + > p { + font-size: 12px; + } + } + + &__footer-edit > button { + border: none; + background: none; + font-size: 12px; + color: $Blue-500; + + &:focus { + outline: none; + } + } + + h6 { + margin-inline-end: 6px; + } +} diff --git a/ui/components/ui/slider/slider.component.js b/ui/components/ui/slider/slider.component.js new file mode 100644 index 000000000..9bdb7309b --- /dev/null +++ b/ui/components/ui/slider/slider.component.js @@ -0,0 +1,135 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import MaterialSlider from '@material-ui/core/Slider'; +import { withStyles } from '@material-ui/core/styles'; + +import { + COLORS, + FONT_WEIGHT, + TYPOGRAPHY, +} from '../../../helpers/constants/design-system'; + +import InfoTooltip from '../info-tooltip/info-tooltip'; +import Typography from '../typography/typography'; + +const styles = { + root: { + height: 6, + padding: '6px 0', + }, + rail: { + borderRadius: 50, + background: '#D6D9DC', + height: 6, + }, + track: { + borderRadius: 50, + background: '#037DD6', + height: 6, + }, + thumb: { + 'height': 20, + 'width': 20, + 'marginTop': -7, + 'marginLeft': -7, + 'backgroundColor': '#037DD6', + 'border': '1px solid #EAF6FF', + 'boxSizing': 'border-box', + 'boxShadow': '0px 0px 14px 0px rgba(0, 0, 0, 0.18)', + '&:focus, &$active': { + height: 20, + width: 20, + marginTop: -7, + marginLeft: -7, + boxShadow: '0px 0px 14px 0px rgba(0, 0, 0, 0.18)', + }, + '&:hover': { + height: 22, + width: 22, + marginTop: -8, + marginLeft: -8, + border: 'none', + boxShadow: '0px 0px 14px 0px rgba(0, 0, 0, 0.18)', + }, + }, +}; + +const Slider = ({ + editText, + infoText, + onEdit, + titleDetail, + titleText, + tooltipText, + valueText, + ...rest +}) => ( +
+
+
+ {titleText && ( + + {titleText} + + )} + {tooltipText && ( + + )} + {valueText && ( + + {valueText} + + )} +
+ {titleDetail && ( +
+ + {titleDetail} + +
+ )} +
+ +
+
+ {infoText && ( + + {infoText} + + )} +
+
+ {onEdit && ( + + )} +
+
+
+); + +Slider.defaultProps = { + editText: 'Edit', +}; + +Slider.propTypes = { + editText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), + infoText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), + titleDetail: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), + titleText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), + tooltipText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), + valueText: PropTypes.oneOfType([PropTypes.string, PropTypes.node]), + max: PropTypes.number, + min: PropTypes.number, + onChange: PropTypes.func, + onEdit: PropTypes.func, + step: PropTypes.number, + value: PropTypes.number, +}; + +export default withStyles(styles)(Slider); diff --git a/ui/components/ui/slider/slider.component.test.js b/ui/components/ui/slider/slider.component.test.js new file mode 100644 index 000000000..d28e2adca --- /dev/null +++ b/ui/components/ui/slider/slider.component.test.js @@ -0,0 +1,58 @@ +import React from 'react'; +import { fireEvent, render } from '@testing-library/react'; + +import Slider from './slider.component'; + +describe('Slider Component', () => { + describe('rendering', () => { + it('should render properly', () => { + expect(() => { + render(); + }).not.toThrow(); + }); + + it('should contain passed header props', () => { + const wrapper = render( + , + ); + + expect(wrapper.getAllByText('Slider Title Text')).toBeDefined(); + expect(wrapper.getAllByText('$ 00.00')).toBeDefined(); + expect(wrapper.getAllByText('100 GWEI')).toBeDefined(); + }); + + it('should contain passed footer props', () => { + const wrapper = render( + { + console.log('on edit click'); + }} + />, + ); + + expect(wrapper.getAllByText('Footer Info Text')).toBeDefined(); + expect( + wrapper.getByRole('button', { name: 'edit as numeric input' }), + ).toBeDefined(); + expect(wrapper.getAllByText('Edit GWEI')).toBeDefined(); + }); + + it('should call onEdit callback when edit button is clicked', () => { + const mockEditFn = jest.fn(); + const wrapper = render( + , + ); + + const editButton = wrapper.getByRole('button'); + fireEvent.click(editButton); + expect(mockEditFn).toHaveBeenCalledTimes(1); + }); + }); +}); diff --git a/ui/components/ui/slider/slider.stories.js b/ui/components/ui/slider/slider.stories.js new file mode 100644 index 000000000..316ae3929 --- /dev/null +++ b/ui/components/ui/slider/slider.stories.js @@ -0,0 +1,33 @@ +import React from 'react'; +import Slider from '.'; + +export default { + title: 'Slider', + id: __filename, +}; + +export const slider = () => ; + +export const sliderWithSteps = () => ; + +export const sliderWithHeader = () => ( + +); + +export const sliderWithFooter = () => ( + { + console.log('on edit click'); + }} + /> +); diff --git a/ui/components/ui/toggle-button/toggle-button.component.js b/ui/components/ui/toggle-button/toggle-button.component.js index 2c935ad90..0acdd2ab4 100644 --- a/ui/components/ui/toggle-button/toggle-button.component.js +++ b/ui/components/ui/toggle-button/toggle-button.component.js @@ -34,7 +34,7 @@ const colors = { base: '#037DD6', }, inactiveThumb: { - base: '#037DD6', + base: '#6A737D', }, active: { base: '#ffffff', diff --git a/ui/components/ui/toggle-button/toggle-button.stories.js b/ui/components/ui/toggle-button/toggle-button.stories.js new file mode 100644 index 000000000..64f1a7acb --- /dev/null +++ b/ui/components/ui/toggle-button/toggle-button.stories.js @@ -0,0 +1,32 @@ +import React, { useState } from 'react'; +import { action } from '@storybook/addon-actions'; +import { boolean, text } from '@storybook/addon-knobs'; + +import ToggleButton from './toggle-button.component'; + +export default { + title: 'ToggleButton', + component: ToggleButton, + id: __filename, +}; + +export const DefaultStory = () => { + const [checked, setChecked] = useState(false); + const handleOnToggle = (e) => { + action('onToggle')(e); + setChecked(!checked); + }; + return ( + + ); +}; + +DefaultStory.story = { + name: 'Default', +}; diff --git a/ui/components/ui/truncated-definition-list/truncated-definition-list.js b/ui/components/ui/truncated-definition-list/truncated-definition-list.js index 2382b045b..f7354cffd 100644 --- a/ui/components/ui/truncated-definition-list/truncated-definition-list.js +++ b/ui/components/ui/truncated-definition-list/truncated-definition-list.js @@ -49,7 +49,6 @@ export default function TruncatedDefinitionList({ -
diff --git a/ui/pages/create-account/connect-hardware/account-list.js b/ui/pages/create-account/connect-hardware/account-list.js index 96a31bd05..29922fcd2 100644 --- a/ui/pages/create-account/connect-hardware/account-list.js +++ b/ui/pages/create-account/connect-hardware/account-list.js @@ -194,7 +194,7 @@ class AccountList extends Component { return (