diff --git a/.circleci/config.yml b/.circleci/config.yml index 9ebde782f..908ef7722 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -26,6 +26,13 @@ workflows: - /^Version-v(\d+)[.](\d+)[.](\d+)/ - prep-deps - test-deps + - validate-lavamoat-config: + filters: + branches: + only: + - /^Version-v(\d+)[.](\d+)[.](\d+)|master/ + requires: + - prep-deps - prep-build: requires: - prep-deps @@ -72,6 +79,7 @@ workflows: - prep-build - all-tests-pass: requires: + - validate-lavamoat-config - test-lint - test-lint-shellcheck - test-lint-lockfile @@ -118,9 +126,9 @@ jobs: - run: name: Create GitHub Pull Request for version command: | - .circleci/scripts/release-bump-changelog-version - .circleci/scripts/release-bump-manifest-version - .circleci/scripts/release-create-release-pr + .circleci/scripts/release-bump-changelog-version.sh + .circleci/scripts/release-bump-manifest-version.sh + .circleci/scripts/release-create-release-pr.sh prep-deps: executor: node-browsers @@ -143,6 +151,21 @@ jobs: - node_modules - build-artifacts + validate-lavamoat-config: + executor: node-browsers + steps: + - checkout + - attach_workspace: + at: . + - run: + name: Validate allow-scripts config + command: | + .circleci/scripts/validate-allow-scripts.sh + - run: + name: Validate LavaMoat policy + command: | + .circleci/scripts/validate-lavamoat-policy.sh + prep-build: executor: node-browsers-medium-plus steps: @@ -257,7 +280,7 @@ jobs: at: . - run: name: yarn audit - command: .circleci/scripts/yarn-audit + command: .circleci/scripts/yarn-audit.sh test-e2e-chrome: executor: node-browsers @@ -277,7 +300,7 @@ jobs: - run: name: test:e2e:chrome command: | - if .circleci/scripts/test-run-e2e + if .circleci/scripts/test-run-e2e.sh then yarn test:e2e:chrome fi @@ -304,7 +327,7 @@ jobs: - run: name: test:e2e:chrome:metrics command: | - if .circleci/scripts/test-run-e2e + if .circleci/scripts/test-run-e2e.sh then yarn test:e2e:chrome:metrics fi @@ -319,7 +342,7 @@ jobs: - checkout - run: name: Install Firefox - command: ./.circleci/scripts/firefox-install + command: ./.circleci/scripts/firefox-install.sh - attach_workspace: at: . - run: @@ -331,7 +354,7 @@ jobs: - run: name: test:e2e:firefox command: | - if .circleci/scripts/test-run-e2e + if .circleci/scripts/test-run-e2e.sh then yarn test:e2e:firefox fi @@ -346,7 +369,7 @@ jobs: - checkout - run: name: Install Firefox - command: ./.circleci/scripts/firefox-install + command: ./.circleci/scripts/firefox-install.sh - attach_workspace: at: . - run: @@ -358,7 +381,7 @@ jobs: - run: name: test:e2e:firefox:metrics command: | - if .circleci/scripts/test-run-e2e + if .circleci/scripts/test-run-e2e.sh then yarn test:e2e:firefox:metrics fi @@ -414,6 +437,12 @@ jobs: - store_artifacts: path: test-artifacts destination: test-artifacts + # important: generate lavamoat viz AFTER uploading builds as artifacts + # Temporarily disabled until we can update to a version of `sesify` with + # this fix included: https://github.com/LavaMoat/LavaMoat/pull/121 + - run: + name: build:lavamoat-viz + command: ./.circleci/scripts/create-lavamoat-viz.sh - store_artifacts: path: build-artifacts destination: build-artifacts @@ -436,10 +465,10 @@ jobs: - run: name: Create GitHub release command: | - .circleci/scripts/release-create-gh-release + .circleci/scripts/release-create-gh-release.sh - run: name: Create GitHub Pull Request to sync master with develop - command: .circleci/scripts/release-create-master-pr + command: .circleci/scripts/release-create-master-pr.sh job-publish-storybook: executor: node-browsers diff --git a/.circleci/scripts/create-lavamoat-viz.sh b/.circleci/scripts/create-lavamoat-viz.sh new file mode 100755 index 000000000..53e520f27 --- /dev/null +++ b/.circleci/scripts/create-lavamoat-viz.sh @@ -0,0 +1,17 @@ +#!/usr/bin/env bash + +set -x +set -e +set -u +set -o pipefail + +BUILD_DEST="./build-artifacts/build-viz/" + +# prepare artifacts dir +mkdir -p "${BUILD_DEST}" + +# generate lavamoat debug config +yarn lavamoat:debug + +# generate viz +npx lavamoat-viz --dest "${BUILD_DEST}" \ No newline at end of file diff --git a/.circleci/scripts/deps-install.sh b/.circleci/scripts/deps-install.sh index cba42c416..eaab9f2de 100755 --- a/.circleci/scripts/deps-install.sh +++ b/.circleci/scripts/deps-install.sh @@ -5,7 +5,7 @@ set -x # Exit immediately if a command exits with a non-zero status. set -e -yarn --frozen-lockfile --har +yarn setup-ci # Move HAR file into directory with consistent name so that we can cache it mkdir -p build-artifacts/yarn-install-har @@ -13,7 +13,4 @@ har_files=(./*.har) if [[ -f "${har_files[0]}" ]] then mv ./*.har build-artifacts/yarn-install-har/ -fi - -# use @lavamoat/allow-scripts instead of manually running install scripts so directory change does not persist -yarn allow-scripts +fi \ No newline at end of file diff --git a/.circleci/scripts/firefox-install b/.circleci/scripts/firefox-install.sh similarity index 100% rename from .circleci/scripts/firefox-install rename to .circleci/scripts/firefox-install.sh diff --git a/.circleci/scripts/release-bump-changelog-version b/.circleci/scripts/release-bump-changelog-version.sh similarity index 100% rename from .circleci/scripts/release-bump-changelog-version rename to .circleci/scripts/release-bump-changelog-version.sh diff --git a/.circleci/scripts/release-bump-manifest-version b/.circleci/scripts/release-bump-manifest-version.sh similarity index 100% rename from .circleci/scripts/release-bump-manifest-version rename to .circleci/scripts/release-bump-manifest-version.sh diff --git a/.circleci/scripts/release-create-gh-release b/.circleci/scripts/release-create-gh-release.sh similarity index 100% rename from .circleci/scripts/release-create-gh-release rename to .circleci/scripts/release-create-gh-release.sh diff --git a/.circleci/scripts/release-create-master-pr b/.circleci/scripts/release-create-master-pr.sh similarity index 100% rename from .circleci/scripts/release-create-master-pr rename to .circleci/scripts/release-create-master-pr.sh diff --git a/.circleci/scripts/release-create-release-pr b/.circleci/scripts/release-create-release-pr.sh similarity index 100% rename from .circleci/scripts/release-create-release-pr rename to .circleci/scripts/release-create-release-pr.sh diff --git a/.circleci/scripts/test-run-e2e b/.circleci/scripts/test-run-e2e.sh similarity index 100% rename from .circleci/scripts/test-run-e2e rename to .circleci/scripts/test-run-e2e.sh diff --git a/.circleci/scripts/validate-allow-scripts.sh b/.circleci/scripts/validate-allow-scripts.sh new file mode 100755 index 000000000..e466f039c --- /dev/null +++ b/.circleci/scripts/validate-allow-scripts.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + +yarn allow-scripts auto + +if git diff --exit-code --quiet +then + echo "allow-scripts configuration is up-to-date" +else + echo "allow-scripts configuration requires updates" + exit 1 +fi diff --git a/.circleci/scripts/validate-lavamoat-policy.sh b/.circleci/scripts/validate-lavamoat-policy.sh new file mode 100755 index 000000000..4eab30b75 --- /dev/null +++ b/.circleci/scripts/validate-lavamoat-policy.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -e +set -u +set -o pipefail + +yarn lavamoat:auto + +if git diff --exit-code --quiet +then + echo "LavaMoat policy is up-to-date" +else + echo "LavaMoat policy requires updates" + exit 1 +fi diff --git a/.circleci/scripts/yarn-audit b/.circleci/scripts/yarn-audit.sh similarity index 100% rename from .circleci/scripts/yarn-audit rename to .circleci/scripts/yarn-audit.sh diff --git a/.eslintrc.js b/.eslintrc.js index 5bebbe073..322d41a5e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -31,6 +31,7 @@ module.exports = { 'test/e2e/send-eth-with-private-key-test/**', 'nyc_output/**', '.vscode/**', + 'lavamoat/*/policy.json', ], extends: [ diff --git a/.prettierignore b/.prettierignore index f1835d8dc..3059730e1 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ node_modules/** +lavamoat/*/policy.json dist/** builds/** test-*/** diff --git a/.storybook/i18n-party-addon/register.js b/.storybook/i18n-party-addon/register.js new file mode 100644 index 000000000..20175a80e --- /dev/null +++ b/.storybook/i18n-party-addon/register.js @@ -0,0 +1,37 @@ +// import { useGlobals } from '@storybook/api'; +const { useGlobals } = require('@storybook/api') +const React = require("react") +const { addons, types } = require("@storybook/addons") +const { Icons, IconButton } = require('@storybook/components') +const localeList = require('../../app/_locales/index.json') +const { useEffect } = React + +addons.register("i18n-party", () => { + + addons.add("i18n-party", { + title: "rotates through every i18n locale", + //👇 Sets the type of UI element in Storybook + type: types.TOOL, + match: () => true, + render: (...args) => { + // https://github.com/storybookjs/storybook/blob/6490a0d646dbaa293b76bbde477daca615efe789/addons/toolbars/src/components/MenuToolbar.tsx#L2 + const [globals, updateGlobals] = useGlobals() + useEffect(() => { + if (!globals.localeParty) return + const interval = setInterval((...args) => { + const currentIndex = localeList.findIndex(({ code }) => code === globals.locale) + const nextIndex = (currentIndex + 1) % localeList.length + const nextLocale = localeList[nextIndex].code + updateGlobals({ locale: nextLocale }) + }, 2000) + return () => clearInterval(interval) + }) + + return ( + updateGlobals({ localeParty: !globals.localeParty })}> + + + ) + }, + }) +}) diff --git a/.storybook/main.js b/.storybook/main.js index b2ff41a8e..2e708e264 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -9,6 +9,7 @@ module.exports = { '@storybook/addon-actions', '@storybook/addon-backgrounds', '@storybook/addon-toolbars', + './i18n-party-addon/register.js', ], webpackFinal: async (config) => { config.module.strictExportPresence = true diff --git a/.storybook/preview.js b/.storybook/preview.js index 8c6c910cf..112c8f16e 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -1,22 +1,24 @@ -import React from 'react' -import { addDecorator, addParameters } from '@storybook/react' -import { withKnobs } from '@storybook/addon-knobs' -import { Provider } from 'react-redux' -import configureStore from '../ui/app/store/store' -import '../ui/app/css/index.scss' -import localeList from '../app/_locales/index.json' -import * as allLocales from './locales' -import { I18nProvider, LegacyI18nProvider } from './i18n' +import React, { useEffect } from 'react'; +import { addDecorator, addParameters } from '@storybook/react'; +import { useGlobals } from '@storybook/api'; +import { withKnobs } from '@storybook/addon-knobs'; +import { Provider } from 'react-redux'; +import configureStore from '../ui/app/store/store'; +import '../ui/app/css/index.scss'; +import localeList from '../app/_locales/index.json'; +import * as allLocales from './locales'; +import { I18nProvider, LegacyI18nProvider } from './i18n'; +import testData from './test-data.js' addParameters({ backgrounds: { default: 'light', values: [ - { name: 'light', value: '#FFFFFF'}, + { name: 'light', value: '#FFFFFF' }, { name: 'dark', value: '#333333' }, ], - } -}) + }, +}); export const globalTypes = { locale: { @@ -26,8 +28,8 @@ export const globalTypes = { toolbar: { icon: 'globe', items: localeList.map(({ code, name }) => { - return { value: code, right: code, title: name } - }) + return { value: code, right: code, title: name }; + }), }, }, }; @@ -37,15 +39,13 @@ const styles = { display: 'flex', justifyContent: 'center', alignItems: 'center', -} +}; -const store = configureStore({ - metamask: { metamask: { } }, -}) +const store = configureStore(testData) const metamaskDecorator = (story, context) => { - const currentLocale = context.globals.locale - const current = allLocales[currentLocale] + const currentLocale = context.globals.locale; + const current = allLocales[currentLocale]; return ( { en={allLocales.en} > -
- { story() } -
+
{story()}
- ) -} + ); +}; -addDecorator(withKnobs) -addDecorator(metamaskDecorator) +addDecorator(withKnobs); +addDecorator(metamaskDecorator); diff --git a/.storybook/test-data.js b/.storybook/test-data.js new file mode 100644 index 000000000..99295cab0 --- /dev/null +++ b/.storybook/test-data.js @@ -0,0 +1,218 @@ +import { TRANSACTION_STATUSES } from '../shared/constants/transaction'; + +const state = { + metamask: { + isInitialized: true, + isUnlocked: true, + featureFlags: { sendHexData: true }, + rpcUrl: 'https://rawtestrpc.metamask.io/', + identities: { + '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825': { + address: '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825', + name: 'Send Account 1', + }, + '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb': { + address: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb', + name: 'Send Account 2', + }, + '0x2f8d4a878cfa04a6e60d46362f5644deab66572d': { + address: '0x2f8d4a878cfa04a6e60d46362f5644deab66572d', + name: 'Send Account 3', + }, + '0xd85a4b6a394794842887b8284293d69163007bbb': { + address: '0xd85a4b6a394794842887b8284293d69163007bbb', + name: 'Send Account 4', + }, + }, + cachedBalances: {}, + currentBlockGasLimit: '0x4c1878', + currentCurrency: 'USD', + conversionRate: 1200.88200327, + conversionDate: 1489013762, + nativeCurrency: 'ETH', + frequentRpcList: [], + network: '3', + provider: { + type: 'ropsten', + chainId: '0x3', + }, + accounts: { + '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825': { + code: '0x', + balance: '0x47c9d71831c76efe', + nonce: '0x1b', + address: '0xfdea65c8e26263f6d9a1b5de9555d2931a33b825', + }, + '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb': { + code: '0x', + balance: '0x37452b1315889f80', + nonce: '0xa', + address: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb', + }, + '0x2f8d4a878cfa04a6e60d46362f5644deab66572d': { + code: '0x', + balance: '0x30c9d71831c76efe', + nonce: '0x1c', + address: '0x2f8d4a878cfa04a6e60d46362f5644deab66572d', + }, + '0xd85a4b6a394794842887b8284293d69163007bbb': { + code: '0x', + balance: '0x0', + nonce: '0x0', + address: '0xd85a4b6a394794842887b8284293d69163007bbb', + }, + }, + addressBook: { + '0x3': { + '0x06195827297c7a80a443b6894d3bdb8824b43896': { + address: '0x06195827297c7a80a443b6894d3bdb8824b43896', + name: 'Address Book Account 1', + chainId: '0x3', + }, + }, + }, + tokens: [ + { + address: '0x1a195821297c7a80a433b6894d3bdb8824b43896', + decimals: 18, + symbol: 'ABC', + }, + { + address: '0x8d6b81208414189a58339873ab429b6c47ab92d3', + decimals: 4, + symbol: 'DEF', + }, + { + address: '0xa42084c8d1d9a2198631988579bb36b48433a72b', + decimals: 18, + symbol: 'GHI', + }, + ], + transactions: {}, + currentNetworkTxList: [ + { + id: 'mockTokenTx1', + txParams: { + to: '0x8d6b81208414189a58339873ab429b6c47ab92d3', + from: '0xd85a4b6a394794842887b8284293d69163007bbb', + }, + time: 1700000000000, + }, + { + id: 'mockTokenTx2', + txParams: { + to: '0xafaketokenaddress', + from: '0xd85a4b6a394794842887b8284293d69163007bbb', + }, + time: 1600000000000, + }, + { + id: 'mockTokenTx3', + txParams: { + to: '0x8d6b81208414189a58339873ab429b6c47ab92d3', + from: '0xd85a4b6a394794842887b8284293d69163007bbb', + }, + time: 1500000000000, + }, + { + id: 'mockEthTx1', + txParams: { + to: '0xd85a4b6a394794842887b8284293d69163007bbb', + from: '0xd85a4b6a394794842887b8284293d69163007bbb', + }, + time: 1400000000000, + }, + ], + unapprovedMsgs: { + '0xabc': { id: 'unapprovedMessage1', time: 1650000000000 }, + '0xdef': { id: 'unapprovedMessage2', time: 1550000000000 }, + '0xghi': { id: 'unapprovedMessage3', time: 1450000000000 }, + }, + unapprovedMsgCount: 0, + unapprovedPersonalMsgs: {}, + unapprovedPersonalMsgCount: 0, + unapprovedDecryptMsgs: {}, + unapprovedDecryptMsgCount: 0, + unapprovedEncryptionPublicKeyMsgs: {}, + unapprovedEncryptionPublicKeyMsgCount: 0, + keyringTypes: ['Simple Key Pair', 'HD Key Tree'], + keyrings: [ + { + type: 'HD Key Tree', + accounts: [ + 'fdea65c8e26263f6d9a1b5de9555d2931a33b825', + 'c5b8dbac4c1d3f152cdeb400e2313f309c410acb', + '2f8d4a878cfa04a6e60d46362f5644deab66572d', + ], + }, + { + type: 'Simple Key Pair', + accounts: ['0xd85a4b6a394794842887b8284293d69163007bbb'], + }, + ], + selectedAddress: '0xd85a4b6a394794842887b8284293d69163007bbb', + send: { + gasLimit: '0xFFFF', + gasPrice: '0xaa', + gasTotal: '0xb451dc41b578', + tokenBalance: 3434, + from: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb', + to: '0x987fedabc', + amount: '0x080', + memo: '', + errors: { + someError: null, + }, + maxModeOn: false, + editingTransactionId: 97531, + }, + unapprovedTxs: { + 4768706228115573: { + id: 4768706228115573, + time: 1487363153561, + status: TRANSACTION_STATUSES.UNAPPROVED, + gasMultiplier: 1, + metamaskNetworkId: '3', + txParams: { + from: '0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb', + to: '0x18a3462427bcc9133bb46e88bcbe39cd7ef0e761', + value: '0xde0b6b3a7640000', + metamaskId: 4768706228115573, + metamaskNetworkId: '3', + gas: '0x5209', + }, + txFee: '17e0186e60800', + txValue: 'de0b6b3a7640000', + maxCost: 'de234b52e4a0800', + gasPrice: '4a817c800', + }, + }, + currentLocale: 'en', + }, + appState: { + menuOpen: false, + currentView: { + name: 'accountDetail', + detailView: null, + context: '0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc', + }, + accountDetail: { + subview: 'transactions', + }, + modal: { + modalState: {}, + previousModalState: {}, + }, + isLoading: false, + warning: null, + scrollToBottom: false, + forgottenPassword: null, + }, + send: { + fromDropdownOpen: false, + toDropdownOpen: false, + errors: { someError: null }, + }, +}; + +export default state; diff --git a/CHANGELOG.md b/CHANGELOG.md index 508b8416e..088caecb7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,41 @@ ## Current Develop Branch +## 9.1.0 Mon Mar 01 2021 +- [#10265](https://github.com/MetaMask/metamask-extension/pull/10265): Update Japanese translations. +- [#9388](https://github.com/MetaMask/metamask-extension/pull/9388): Update Chinese(Simplified) translations. +- [#10270](https://github.com/MetaMask/metamask-extension/pull/10270): Update Vietnamese translations. +- [#10258](https://github.com/MetaMask/metamask-extension/pull/10258): Update Spanish and Spanish(Latin American and Carribean) translations. +- [#10268](https://github.com/MetaMask/metamask-extension/pull/10268): Update Russian translations. +- [#10269](https://github.com/MetaMask/metamask-extension/pull/10269): Update Tagalog localized messages. +- [#10448](https://github.com/MetaMask/metamask-extension/pull/10448): Fix 'imported' translation use case for Dutch. +- [#10391](https://github.com/MetaMask/metamask-extension/pull/10391): Use translated transaction category for confirmations. +- [#10357](https://github.com/MetaMask/metamask-extension/pull/10357): Cancel unapproved confirmations on network change +- [#10413](https://github.com/MetaMask/metamask-extension/pull/10413): Use native currency in asset row. +- [#10421](https://github.com/MetaMask/metamask-extension/pull/10421): Fix color indicator size on connected site indicator. +- [#10423](https://github.com/MetaMask/metamask-extension/pull/10423): Fix multiple notification window prompts. +- [#10424](https://github.com/MetaMask/metamask-extension/pull/10424): Fix icons on token options menu. +- [#10414](https://github.com/MetaMask/metamask-extension/pull/10414): Fix token fiat conversion rates when switching from certain custom networks. +- [#10453](https://github.com/MetaMask/metamask-extension/pull/10453): Disable BUY button from home screen when not on Ethereum Mainnet. +- [#10465](https://github.com/MetaMask/metamask-extension/pull/10465): Fixes gas selection check mark on the notification view. +- [#10467](https://github.com/MetaMask/metamask-extension/pull/10467): Fix confirm page header with from/to addresses in fullscreen for tx confirmations. +- [#10455](https://github.com/MetaMask/metamask-extension/pull/10455): Hide links to etherscan when no block explorer is specified for a custom network for notifications. +- [#10456](https://github.com/MetaMask/metamask-extension/pull/10456): Fix swap insufficient balance error message. +- [#10350](https://github.com/MetaMask/metamask-extension/pull/10350): Fix encypt/decrypt tx queueing. +- [#10473](https://github.com/MetaMask/metamask-extension/pull/10473): Improve autofocus in the add network form. +- [#10444](https://github.com/MetaMask/metamask-extension/pull/10444): Use eth_gasprice for tx gas price estimation on non-Mainnet networks. +- [#10477](https://github.com/MetaMask/metamask-extension/pull/10477): Fix accountsChanged event not triggering when manually connecting. +- [#10471](https://github.com/MetaMask/metamask-extension/pull/10471): Fix navigation from jumping vertically when clicking into token. +- [#9724](https://github.com/MetaMask/metamask-extension/pull/9724): Add custom network RPC method. +- [#10496](https://github.com/MetaMask/metamask-extension/pull/10496): Eliminate artificial delay in swaps loading screen after request loading is complete. +- [#10501](https://github.com/MetaMask/metamask-extension/pull/10501): Ensure that swap approve tx and swap tx always have the same gas price. +- [#10485](https://github.com/MetaMask/metamask-extension/pull/10485): Fixes signTypedData message overflow. +- [#10525](https://github.com/MetaMask/metamask-extension/pull/10525): Update swaps failure message to include a support link. +- [#10521](https://github.com/MetaMask/metamask-extension/pull/10521): Accommodate for 0 sources verifying swap token +- [#10530](https://github.com/MetaMask/metamask-extension/pull/10530): Show warnings on Add Recipient page of Send flow +- [#9187](https://github.com/MetaMask/metamask-extension/pull/9187): Warn users when an ENS name contains 'confusable' characters +- [#10507](https://github.com/MetaMask/metamask-extension/pull/10507): Fixes ENS IPFS resolution on custom networks with the chainID of 1. + ## 9.0.5 Mon Feb 08 2021 - [#10278](https://github.com/MetaMask/metamask-extension/pull/10278): Allow editing transaction amount after clicking max - [#10214](https://github.com/MetaMask/metamask-extension/pull/10214): Standardize size, shape and color of network color indicators @@ -19,6 +54,7 @@ ## 9.0.4 Fri Jan 22 2021 - [#10285](https://github.com/MetaMask/metamask-extension/pull/10285): Update @metamask/contract-metadata from v1.21.0 to 1.22.0 +- [#10264](https://github.com/MetaMask/metamask-extension/pull/10264): Update `hi` localized messages - [#10174](https://github.com/MetaMask/metamask-extension/pull/10174): Move fox to bottom of 'About' page - [#10198](https://github.com/MetaMask/metamask-extension/pull/10198): Fix hardware account selection - [#10101](https://github.com/MetaMask/metamask-extension/pull/10101): Add a timeout to all network requests diff --git a/README.md b/README.md index 6ea6e204c..cc546cd93 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ For [general questions](https://metamask.zendesk.com/hc/en-us/community/topics/3 MetaMask supports Firefox, Google Chrome, and Chromium-based browsers. We recommend using the latest available browser version. -For up to the minute news, follow our [Twitter](https://twitter.com/metamask_io) or [Medium](https://medium.com/metamask) pages. +For up to the minute news, follow our [Twitter](https://twitter.com/metamask) or [Medium](https://medium.com/metamask) pages. To learn how to develop MetaMask-compatible applications, visit our [Developer Docs](https://metamask.github.io/metamask-docs/). @@ -25,24 +25,49 @@ To learn how to contribute to the MetaMask project itself, visit our [Internal D - Replace the `INFURA_PROJECT_ID` value with your own personal [Infura Project ID](https://infura.io/docs). - If debugging MetaMetrics, you'll need to add a value for `SEGMENT_WRITE_KEY` [Segment write key](https://segment.com/docs/connections/find-writekey/). - Build the project to the `./dist/` folder with `yarn dist`. -- Optionally, to start a development build (e.g. with logging and file watching) run `yarn start` instead. - - To start the [React DevTools](https://github.com/facebook/react-devtools) and [Redux DevTools Extension](http://extension.remotedev.io) - alongside the app, use `yarn start:dev`. - - React DevTools will open in a separate window; no browser extension is required - - Redux DevTools will need to be installed as a browser extension. Open the Redux Remote Devtools to access Redux state logs. This can be done by either right clicking within the web browser to bring up the context menu, expanding the Redux DevTools panel and clicking Open Remote DevTools OR clicking the Redux DevTools extension icon and clicking Open Remote DevTools. - - You will also need to check the "Use custom (local) server" checkbox in the Remote DevTools Settings, using the default server configuration (host `localhost`, port `8000`, secure connection checkbox unchecked) Uncompressed builds can be found in `/dist`, compressed builds can be found in `/builds` once they're built. ## Contributing -### Running Tests +### Development builds -Run tests with `yarn test`. +To start a development build (e.g. with logging and file watching) run `yarn start`. -You can also test with a continuously watching process, via `yarn watch`. +To start the [React DevTools](https://github.com/facebook/react-devtools) and [Redux DevTools Extension](http://extension.remotedev.io) + alongside the app, use `yarn start:dev`. + - React DevTools will open in a separate window; no browser extension is required + - Redux DevTools will need to be installed as a browser extension. Open the Redux Remote Devtools to access Redux state logs. This can be done by either right clicking within the web browser to bring up the context menu, expanding the Redux DevTools panel and clicking Open Remote DevTools OR clicking the Redux DevTools extension icon and clicking Open Remote DevTools. + - You will also need to check the "Use custom (local) server" checkbox in the Remote DevTools Settings, using the default server configuration (host `localhost`, port `8000`, secure connection checkbox unchecked) -You can run the linter by itself with `yarn lint`. +### 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`. + +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. + +### Running E2E Tests + +Our e2e test suite can be run on either Firefox or Chrome. In either case, start by creating a test build by running `yarn build:test`. + +Firefox e2e tests can be run with `yarn test:e2e:firefox`. + +Chrome e2e tests can be run with `yarn test:e2e:chrome`, but they will only work if you have Chrome v79 installed. Update the `chromedriver` package to a version matching your local Chrome installation to run e2e tests on newer Chrome versions. + +### Changing dependencies + +Whenever you change dependencies (adding, removing, or updating, either in `package.json` or `yarn.lock`), there are various files that must be kept up-to-date. + +* `yarn.lock`: + * Run `yarn setup` again after your changes to ensure `yarn.lock` has been properly updated. +* The `allow-scripts` configuration in `package.json` + * Run `yarn allow-scripts auto` to update the `allow-scripts` configuration automatically. This config determines whether the package's install/postinstall scripts are allowed to run. Review each new package to determine whether the install script needs to run or not, testing if necessary. + * Unfortunately, `yarn allow-scripts auto` will behave inconsistently on different platforms. macOS and Windows users may see extraneous changes relating to optional dependencies. +* The LavaMoat auto-generated policy in `lavamoat/node/policy.json` + * Run `yarn lavamoat:auto` to re-generate this policy file. Review the changes to determine whether the access granted to each package seems appropriate. + * Unfortunately, `yarn lavamoat:auto` will behave inconsistently on different platforms. macOS and Windows users may see extraneous changes relating to optional dependencies. ## Architecture diff --git a/app/_locales/am/messages.json b/app/_locales/am/messages.json index af0f3c78c..9b9444dbd 100644 --- a/app/_locales/am/messages.json +++ b/app/_locales/am/messages.json @@ -928,18 +928,12 @@ "selectAnAccountHelp": { "message": "መለያውን በ MetaMask ለማየት ይምረጡ" }, - "selectCurrency": { - "message": "የገንዘብ ዓይነት ይምረጡ" - }, "selectEachPhrase": { "message": "እባክዎ እያንዳንዱን ሐረግ በመምረጥ ትክክለኛነቱን ያረጋግጡ።" }, "selectHdPath": { "message": "የ HD ዱካ ይምረጡ" }, - "selectLocale": { - "message": "አካባቢ ይምረጡ" - }, "selectPathHelp": { "message": "ነባር የሌጄር መለያዎችን ከታች ካላዩ፣ ዱካዎችን ወደ \"Legacy (MEW / MyCrypto)\" ለመቀየር ይሞክሩ" }, diff --git a/app/_locales/ar/messages.json b/app/_locales/ar/messages.json index 8edd9482f..cdc187925 100644 --- a/app/_locales/ar/messages.json +++ b/app/_locales/ar/messages.json @@ -924,18 +924,12 @@ "selectAnAccountHelp": { "message": "حدد الحساب لعرضه في MetaMask" }, - "selectCurrency": { - "message": "تحديد العملة" - }, "selectEachPhrase": { "message": "يُرجى تحديد كل عبارة للتأكد من صحتها." }, "selectHdPath": { "message": "حدد مسار HD " }, - "selectLocale": { - "message": "تحديد الموقع المحلي" - }, "selectPathHelp": { "message": "إذا لم تشاهد حسابات Ledger الحالية الخاصة بك أدناه، فحاول تبديل المسارات \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/bg/messages.json b/app/_locales/bg/messages.json index f06f2e39e..0d5f8dfc5 100644 --- a/app/_locales/bg/messages.json +++ b/app/_locales/bg/messages.json @@ -927,18 +927,12 @@ "selectAnAccountHelp": { "message": "Изберете акаунта за преглед в MetaMask" }, - "selectCurrency": { - "message": "Изберете валута" - }, "selectEachPhrase": { "message": "Моля, изберете всяка фраза, за да се уверите, че е правилна." }, "selectHdPath": { "message": "Изберете HD Path" }, - "selectLocale": { - "message": "Изберете местоположение" - }, "selectPathHelp": { "message": "Ако не виждате съществуващите си акаунти в Ledger по-долу, опитайте да превключите пътеки към „Legacy (MEW / MyCrypto)“" }, diff --git a/app/_locales/bn/messages.json b/app/_locales/bn/messages.json index fc2b72108..c01b44a0e 100644 --- a/app/_locales/bn/messages.json +++ b/app/_locales/bn/messages.json @@ -931,18 +931,12 @@ "selectAnAccountHelp": { "message": "MetaMask এ দেখতে অ্যাকাউন্টটি নির্বাচন করুন" }, - "selectCurrency": { - "message": "কারেন্সি নির্বাচন করুন" - }, "selectEachPhrase": { "message": "ফ্রেজগুলি সঠিক তা নিশ্চিত করতে অনুগ্রহ করে প্রতিটি ফ্রেজ নির্বাচন করুন।" }, "selectHdPath": { "message": "HD পাথ নির্বাচন করুন" }, - "selectLocale": { - "message": "স্থানীয় নির্বাচন করুন" - }, "selectPathHelp": { "message": "আপনি নিচে আপনার বিদ্যমান লেজার ব্যালেন্স না দেখলে, \"Legacy (MEW / MyCrypto)\" পাথগুলিতে সুইচ করার চেষ্টা করুন " }, diff --git a/app/_locales/ca/messages.json b/app/_locales/ca/messages.json index f8bd80055..3d9c73237 100644 --- a/app/_locales/ca/messages.json +++ b/app/_locales/ca/messages.json @@ -909,18 +909,12 @@ "selectAnAccountHelp": { "message": "Selecciona el compte que vols veure a MetaMask" }, - "selectCurrency": { - "message": "Selecciona divisa" - }, "selectEachPhrase": { "message": "Si us plau selecciona cada frase per a assegurar-te que és correcta." }, "selectHdPath": { "message": "Selecciona Ruta HD" }, - "selectLocale": { - "message": "Selecciona Configuració Regional" - }, "selectPathHelp": { "message": "Si no veus els teus comptes Ledger a sota, prova canviant la ruta a \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/cs/messages.json b/app/_locales/cs/messages.json index 0fe5b7b48..3ccfc0089 100644 --- a/app/_locales/cs/messages.json +++ b/app/_locales/cs/messages.json @@ -350,9 +350,6 @@ "seedPhraseReq": { "message": "klíčové fráze mají 12 slov" }, - "selectCurrency": { - "message": "Vybrat měnu" - }, "selectType": { "message": "Vybrat typ" }, diff --git a/app/_locales/da/messages.json b/app/_locales/da/messages.json index 99f0df45b..db9091c0a 100644 --- a/app/_locales/da/messages.json +++ b/app/_locales/da/messages.json @@ -912,18 +912,12 @@ "selectAnAccountHelp": { "message": "Vælg kontoen der skal vises i MetaMask" }, - "selectCurrency": { - "message": "Vælg valuta" - }, "selectEachPhrase": { "message": "Vælg venligst hver sætning, for at sikre at de er korrekte." }, "selectHdPath": { "message": "Vælg HD-Sti" }, - "selectLocale": { - "message": "Vælg Lokalitet" - }, "selectPathHelp": { "message": "Hvis du ikke ser dine eksisterende Ledger-konti nedenfor, kan du prøve at skifte til \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/de/messages.json b/app/_locales/de/messages.json index 1bc83610d..0ff63d570 100644 --- a/app/_locales/de/messages.json +++ b/app/_locales/de/messages.json @@ -900,18 +900,12 @@ "selectAnAccountHelp": { "message": "Wählen Sie das Konto aus, das in MetaMask angezeigt werden soll." }, - "selectCurrency": { - "message": "Währung auswählen" - }, "selectEachPhrase": { "message": "Bitte wählen Sie jede Phrase aus, um sicherzustellen, dass sie korrekt ist." }, "selectHdPath": { "message": "HD-Pfad auswählen" }, - "selectLocale": { - "message": "Gebietsschema auswählen" - }, "selectPathHelp": { "message": "Wenn Sie Ihre bestehenden Ledger-Konten nachfolgend nicht sehen, versuchen Sie, die Pfade zu \"Legacy (MEW / MyCrypto)\" zu ändern" }, diff --git a/app/_locales/el/messages.json b/app/_locales/el/messages.json index 5b7e9e6b4..ae30afdce 100644 --- a/app/_locales/el/messages.json +++ b/app/_locales/el/messages.json @@ -928,18 +928,12 @@ "selectAnAccountHelp": { "message": "Επιλέξτε τον λογαριασμό για προβολή στο MetaMask" }, - "selectCurrency": { - "message": "Επιλέξτε Νόμισμα" - }, "selectEachPhrase": { "message": "Παρακαλούμε επιλέξτε κάθε φράση, για να βεβαιωθείτε ότι είναι σωστή." }, "selectHdPath": { "message": "Επιλέξτε Διαδρομή HD" }, - "selectLocale": { - "message": "Επιλέξτε Τοπικές Ρυθμίσεις" - }, "selectPathHelp": { "message": "Εάν δεν βλέπετε τους υπάρχοντες λογαριασμούς σας Καθολικού παρακάτω, προσπαθήστε να αλλάξετε τις διαδρομές σε \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index 2b10de408..99789f491 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -52,6 +52,23 @@ "addAlias": { "message": "Add alias" }, + "addEthereumChainConfirmationDescription": { + "message": "This will allow this network to be used within MetaMask." + }, + "addEthereumChainConfirmationRisks": { + "message": "MetaMask does not verify custom networks." + }, + "addEthereumChainConfirmationRisksLearnMore": { + "message": "Learn about $1.", + "description": "$1 is a link with text that is provided by the 'addEthereumChainConfirmationRisksLearnMoreLink' key" + }, + "addEthereumChainConfirmationRisksLearnMoreLink": { + "message": "scams and network security risks", + "description": "Link text for the 'addEthereumChainConfirmationRisksLearnMore' translation key" + }, + "addEthereumChainConfirmationTitle": { + "message": "Allow this site to add a network?" + }, "addNetwork": { "message": "Add Network" }, @@ -150,6 +167,9 @@ "approve": { "message": "Approve spend limit" }, + "approveButtonText": { + "message": "Approve" + }, "approveSpendLimit": { "message": "Approve $1 spend limit", "description": "The token symbol that is being approved" @@ -212,7 +232,10 @@ "message": "Basic" }, "blockExplorerUrl": { - "message": "Block Explorer" + "message": "Block Explorer URL" + }, + "blockExplorerUrlDefinition": { + "message": "The URL used as the block explorer for this network." }, "blockExplorerView": { "message": "View account at $1", @@ -254,6 +277,9 @@ "chainId": { "message": "Chain ID" }, + "chainIdDefinition": { + "message": "The chain ID used to sign transactions for this network." + }, "chromeRequiredForHardwareWallets": { "message": "You need to use MetaMask on Google Chrome in order to connect to your Hardware Wallet." }, @@ -275,6 +301,15 @@ "confirmed": { "message": "Confirmed" }, + "confusableUnicode": { + "message": "'$1' is similar to '$2'." + }, + "confusableZeroWidthUnicode": { + "message": "Zero-width character found." + }, + "confusingEnsDomain": { + "message": "We have detected a confusable character in the ENS name. Check the ENS name to avoid a potential scam." + }, "congratulations": { "message": "Congratulations" }, @@ -409,6 +444,12 @@ "currencyConversion": { "message": "Currency Conversion" }, + "currencySymbol": { + "message": "Currency Symbol" + }, + "currencySymbolDefinition": { + "message": "The ticker symbol displayed for this network’s currency." + }, "currentAccountNotConnected": { "message": "Your current account is not connected" }, @@ -1005,6 +1046,14 @@ "metametricsOptInDescription": { "message": "MetaMask would like to gather usage data to better understand how our users interact with the extension. This data will be used to continually improve the usability and user experience of our product and the Ethereum ecosystem." }, + "mismatchedChain": { + "message": "This network details for this Chain ID do not match our records. We recommend that you $1 before proceeding.", + "description": "$1 is a clickable link with text defined by the 'mismatchedChainLinkText' key" + }, + "mismatchedChainLinkText": { + "message": "verify the network details", + "description": "Serves as link text for the 'mismatchedChain' key. This text will be embedded inside the translation for that key." + }, "mobileSyncText": { "message": "Please enter your password to confirm it's you!" }, @@ -1030,15 +1079,27 @@ "negativeETH": { "message": "Can not send negative amounts of ETH." }, + "networkDetails": { + "message": "Network Details" + }, "networkName": { "message": "Network Name" }, + "networkNameDefinition": { + "message": "The name associated with this network." + }, "networkSettingsChainIdDescription": { "message": "The chain ID is used for signing transactions. It must match the chain ID returned by the network. You can enter a decimal or '0x'-prefixed hexadecimal number, but we will display the number in decimal." }, "networkSettingsDescription": { "message": "Add and edit custom RPC networks" }, + "networkURL": { + "message": "Network URL" + }, + "networkURLDefinition": { + "message": "The URL used to access this network." + }, "networks": { "message": "Networks" }, @@ -1418,18 +1479,12 @@ "selectAnAccountHelp": { "message": "Select the account to view in MetaMask" }, - "selectCurrency": { - "message": "Select Currency" - }, "selectEachPhrase": { "message": "Please select each phrase in order to make sure it is correct." }, "selectHdPath": { "message": "Select HD Path" }, - "selectLocale": { - "message": "Select Locale" - }, "selectPathHelp": { "message": "If you don't see your existing Ledger accounts below, try switching paths to \"Legacy (MEW / MyCrypto)\"" }, @@ -1657,8 +1712,9 @@ "swapEstimatedNetworkFeesInfo": { "message": "This is an estimate of the network fee that will be used to complete your swap. The actual amount may change according to network conditions." }, - "swapFailedErrorDescription": { - "message": "Your funds are safe and still available in your wallet." + "swapFailedErrorDescriptionWithSupportLink": { + "message": "Transaction failures happen and we are here to help. If this issue persists, you can reach our customer support at $1 for further assistance.", + "description": "This message is shown to a user if their swap fails. The $1 will be replaced by support.metamask.io" }, "swapFailedErrorTitle": { "message": "Swap failed" @@ -1841,6 +1897,10 @@ "message": "Your $1 has been added to your account.", "description": "This message is shown after a swap is successful and communicates the exact amount of tokens the user has received for a swap. The $1 is a decimal number of tokens followed by the token symbol." }, + "swapTokenBalanceUnavailable": { + "message": "We were unable to retrieve your $1 balance", + "description": "This message communicates to the user that their balance of a given token is currently unavailable. $1 will be replaced by a token symbol" + }, "swapTokenToToken": { "message": "Swap $1 to $2", "description": "Used in the transaction display list to describe a swap. $1 and $2 are the symbols of tokens in involved in a swap." @@ -1849,6 +1909,9 @@ "message": "Always confirm the token address on $1.", "description": "Points the user to Etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"Etherscan\" followed by an info icon that shows more info on hover." }, + "swapTokenVerificationNoSource": { + "message": "This token has not been verified." + }, "swapTokenVerificationOnlyOneSource": { "message": "Only verified on 1 source." }, @@ -1894,12 +1957,24 @@ "swapsViewInActivity": { "message": "View in activity" }, + "switchEthereumChainConfirmationDescription": { + "message": "This will switch the selected network within MetaMask to a previously added network:" + }, + "switchEthereumChainConfirmationTitle": { + "message": "Allow this site to switch the network?" + }, + "switchNetwork": { + "message": "Switch network" + }, "switchNetworks": { "message": "Switch Networks" }, "switchToThisAccount": { "message": "Switch to this account" }, + "switchingNetworksCancelsPendingConfirmations": { + "message": "Switching networks will cancel all pending confirmations" + }, "symbol": { "message": "Symbol" }, @@ -2075,6 +2150,14 @@ "unlockMessage": { "message": "The decentralized web awaits" }, + "unrecognizedChain": { + "message": "This custom network is not recognized. We recommend that you $1 before proceeding", + "description": "$1 is a clickable link with text defined by the 'unrecognizedChanLinkText' key. The link will open to instructions for users to validate custom network details." + }, + "unrecognizedChainLinkText": { + "message": "verify the network details", + "description": "Serves as link text for the 'unrecognizedChain' key. This text will be embedded inside the translation for that key." + }, "updatedWithDate": { "message": "Updated $1" }, @@ -2147,6 +2230,10 @@ "message": "$1 of $2", "description": "$1 and $2 are intended to be two numbers, where $2 is a total, and $1 is a count towards that total" }, + "xOfYPending": { + "message": "$1 of $2 pending", + "description": "$1 and $2 are intended to be two numbers, where $2 is a total number of pending confirmations, and $1 is a count towards that total" + }, "yesLetsTry": { "message": "Yes, let's try" }, diff --git a/app/_locales/es/messages.json b/app/_locales/es/messages.json index 20b7ef950..3188d5ef8 100644 --- a/app/_locales/es/messages.json +++ b/app/_locales/es/messages.json @@ -1,6 +1,6 @@ { "about": { - "message": "Acerca" + "message": "Acerca de" }, "aboutSettingsDescription": { "message": "Versión, centro de soporte e información de contacto" @@ -8,6 +8,14 @@ "acceleratingATransaction": { "message": "* Agilizar a una transacción al usar un precio de gas más alto aumenta las probabilidades que que la red lo procese más rápidamente, pero eso no siempre está garantizado." }, + "acceptTermsOfUse": { + "message": "Leí y acepto $1", + "description": "$1 is the `terms` message" + }, + "accessAndSpendNotice": { + "message": "$1 puede acceder y gastar hasta este monto máximo", + "description": "$1 is the url of the site requesting ability to spend" + }, "accessingYourCamera": { "message": "Accediendo a tu cámara..." }, @@ -26,9 +34,18 @@ "accountSelectionRequired": { "message": "¡Necesitas elegir una cuenta!" }, + "active": { + "message": "Activo" + }, + "activity": { + "message": "Actividad" + }, "activityLog": { "message": "registro de actividades" }, + "addAccount": { + "message": "Agregar una cuenta" + }, "addAcquiredTokens": { "message": "Agregar los tokens que has adquirido usando MetaMask" }, @@ -42,19 +59,19 @@ "message": "Añadir destinatario" }, "addSuggestedTokens": { - "message": "Agregar tokens propuestos" + "message": "Añadir tokens sugeridos" }, "addToAddressBook": { - "message": "Añadir al libro de direcciones" + "message": "Añadir a la libreta de direcciones" }, "addToAddressBookModalPlaceholder": { - "message": "p. ej. John D." + "message": "ej: Juan García" }, "addToken": { - "message": "Agregar token" + "message": "Añadir token" }, "addTokens": { - "message": "Agregar tokens" + "message": "Añadir tokens" }, "advanced": { "message": "Avanzado" @@ -62,28 +79,92 @@ "advancedOptions": { "message": "Opciones Avanzadas" }, + "advancedSettingsDescription": { + "message": "Acceder a funcionalidades para desarrolladores, descargar Logs de Estado, Resetear Cuenta, configurar redes de prueba y RPC personalizado" + }, + "affirmAgree": { + "message": "Estoy de acuerdo" + }, + "aggregatorFeeCost": { + "message": "Tarifa de red del agregador" + }, + "alertDisableTooltip": { + "message": "Esto se puede cambiar en \"Configuración > Alertas\"" + }, + "alertSettingsUnconnectedAccount": { + "message": "Navegando un sitio web con una cuenta desconectada seleccionada" + }, + "alertSettingsUnconnectedAccountDescription": { + "message": "Esta alerta se muestra en un popup cuando está navegando un sitio Web3, pero la cuenta seleccionada actualmente no está conectada." + }, + "alertSettingsWeb3ShimUsage": { + "message": "Cuando un sitio intenta usar la window.web3 API eliminada" + }, + "alertSettingsWeb3ShimUsageDescription": { + "message": "Esta alerta se muestra en un popup cuando está navegando un sitio que intenta usar la window.web3 API eliminada y puede estar roto como resultado" + }, + "alerts": { + "message": "Alertas" + }, + "alertsSettingsDescription": { + "message": "Habilitar o deshabilitar cada alerta" + }, + "allowExternalExtensionTo": { + "message": "Habilitar esta extensión externa a:" + }, + "allowOriginSpendToken": { + "message": "¿Habilitar a $1 gastar sus $2?", + "description": "$1 is the url of the site and $2 is the symbol of the token they are requesting to spend" + }, + "allowThisSiteTo": { + "message": "Habilitar a este sitio a:" + }, + "allowWithdrawAndSpend": { + "message": "Habilitar a $1 retirar y gastar hasta el siguiente monto:", + "description": "The url of the site that requested permission to 'withdraw and spend'" + }, "amount": { "message": "Cantidad" }, + "amountInEth": { + "message": "$1 ETH", + "description": "Displays an eth amount to the user. $1 is a decimal number" + }, + "amountWithColon": { + "message": "Cantidad:" + }, "appDescription": { - "message": "Extensión del navegador para Ethereum", + "message": "Un Monedero de Ethereum para su Navegador", "description": "The description of the application" }, "appName": { "message": "MetaMask", "description": "The name of the application" }, + "approvalAndAggregatorTxFeeCost": { + "message": "Tarifa de la red de aprobación y agregación" + }, + "approvalTxGasCost": { + "message": "Aprobación del Costo del Gas para la Tx" + }, "approve": { "message": "Aprobar" }, + "approveSpendLimit": { + "message": "Aprobar $1", + "description": "The token symbol that is being approved" + }, "approved": { "message": "Aprobado" }, "asset": { "message": "Activo" }, + "assets": { + "message": "Activos" + }, "attemptToCancel": { - "message": "¿Intentar cancelar?" + "message": "¿Intenta cancelar?" }, "attemptToCancelDescription": { "message": "El intentar cancelar la transacción no garantiza la cancelación de la misma. Si el intento de cancelación tiene éxito, se le cobrará la comisión de transacción indicada arriba." @@ -94,8 +175,11 @@ "attributions": { "message": "Atribuciones" }, + "authorizedPermissions": { + "message": "Has autorizado los siguientes permisos" + }, "autoLockTimeLimit": { - "message": "Temporizador Auto-Cierre (minutos)" + "message": "Temporizador de cierre de sesión automático (minutos)" }, "autoLockTimeLimitDescription": { "message": "Establece el tiempo de inactividad en minutos antes de que MetaMask cierre la sesión automáticamente." @@ -109,15 +193,31 @@ "backToAll": { "message": "Volver a Todo" }, + "backupApprovalInfo": { + "message": "Este código secreto es requerido para recuperar tu monedero en caso de que pierdas tu dispositivo, olvides tu contraseña, tengas que re-instalar MetaMask, o quieras acceder a tu monedero en otro dispositivo." + }, "backupApprovalNotice": { - "message": "Haz un respaldo de tu código de Recuperación Secreta para mantener tu Wallet y tus fondos seguros." + "message": "Haz un respaldo de tu código de Recuperación Secreto para mantener tu monedero y tus fondos seguros." + }, + "backupNow": { + "message": "Haz un respaldo ahora" }, "balance": { "message": "Saldo" }, + "balanceOutdated": { + "message": "El saldo puede estar desactualizado" + }, "basic": { "message": "Básico" }, + "blockExplorerUrl": { + "message": "Explorador de Bloques" + }, + "blockExplorerView": { + "message": "Ver la cuenta en $1", + "description": "$1 replaced by URL for custom block explorer" + }, "blockiesIdenticon": { "message": "Usar Blockies Identicon (Iconos)" }, @@ -127,6 +227,21 @@ "builtInCalifornia": { "message": "MetaMask fue diseñado y construido en California" }, + "buy": { + "message": "Comprar" + }, + "buyWithWyre": { + "message": "Comprar ETH con Wyre" + }, + "buyWithWyreDescription": { + "message": "Wyre permite usar una tarjeta de débito para depositar ETH directo en su cuenta MetaMask." + }, + "bytes": { + "message": "Bytes" + }, + "canToggleInSettings": { + "message": "Puede volver a habilitar esta notificación en Configuración -> Alertas." + }, "cancel": { "message": "Cancelar" }, @@ -137,7 +252,7 @@ "message": "Cancelado" }, "chainId": { - "message": "ID Cadena" + "message": "ID de Cadena" }, "chromeRequiredForHardwareWallets": { "message": "Hay que usar MetaMask en Google Chrome para poder conectarse con tu Monedero Físico." @@ -154,6 +269,9 @@ "confirmPassword": { "message": "Confirmar contraseña" }, + "confirmSecretBackupPhrase": { + "message": "Confime su Frase de Respaldo Secreta" + }, "confirmed": { "message": "Confirmado" }, @@ -163,32 +281,94 @@ "connect": { "message": "Conectar" }, + "connectAccountOrCreate": { + "message": "Conectar una cuenta o crear una nueva" + }, "connectHardwareWallet": { "message": "Conectar Monedero Físico" }, + "connectManually": { + "message": "Conectar manualmente al sitio actual" + }, + "connectTo": { + "message": "Conectar a $1", + "description": "$1 is the name/origin of a web3 site/application that the user can connect to metamask" + }, + "connectToAll": { + "message": "Conectar a todos sus $1", + "description": "$1 will be replaced by the translation of connectToAllAccounts" + }, + "connectToAllAccounts": { + "message": "cuentas", + "description": "will replace $1 in connectToAll, completing the sentence 'connect to all of your accounts', will be text that shows list of accounts on hover" + }, + "connectToMultiple": { + "message": "Conectar a $1", + "description": "$1 will be replaced by the translation of connectToMultipleNumberOfAccounts" + }, + "connectToMultipleNumberOfAccounts": { + "message": "$1 cuentas", + "description": "$1 is the number of accounts to which the web3 site/application is asking to connect; this will substitute $1 in connectToMultiple" + }, + "connectWithMetaMask": { + "message": "Conectar Con MetaMask" + }, + "connectedAccountsDescriptionPlural": { + "message": "Tiene $1 cuentas conectadas con este sitio.", + "description": "$1 is the number of accounts" + }, + "connectedAccountsDescriptionSingular": { + "message": "Tiene 1 cuenta conectada con este sitio." + }, + "connectedAccountsEmptyDescription": { + "message": "MetaMask no está conectado a este sitio. Para conectarse a un sitio web3, busque el botón de conexión en su sitio." + }, + "connectedSites": { + "message": "Sitios conectados" + }, + "connectedSitesDescription": { + "message": "$1 está conectado a estos sitios. Ellos pueden ver la dirección de tu cuenta.", + "description": "$1 is the account name" + }, + "connectedSitesEmptyDescription": { + "message": "$1 no está conetado a ningún sitio.", + "description": "$1 is the account name" + }, + "connecting": { + "message": "Conectándose..." + }, "connectingTo": { - "message": "Conectánodse a $1" + "message": "Conectándose a $1" }, "connectingToGoerli": { - "message": "Conectando al Test de Red Goerli" + "message": "Conectando a la red de pruebas Goerli" }, "connectingToKovan": { - "message": "Conectando a la red de test Kovan" + "message": "Conectando a la red de pruebas Kovan" }, "connectingToMainnet": { "message": "Conectando a la red principal de Ethereum (Main Net)" }, "connectingToRinkeby": { - "message": "Conectando a la red de test Rinkeby" + "message": "Conectando a la red de pruebas Rinkeby" }, "connectingToRopsten": { - "message": "Conectando a la red de test Ropsten" + "message": "Conectando a la red de pruebas Ropsten" + }, + "contactUs": { + "message": "Contacta con nosotros" + }, + "contacts": { + "message": "Contactos" + }, + "contactsSettingsDescription": { + "message": "Agregar, editar, eliminar y administrar contactos" }, "continueToWyre": { "message": "Continuar a Wyre" }, "contractDeployment": { - "message": "Desplegar (Deploy) contrato" + "message": "Despliegue de contratos" }, "contractInteraction": { "message": "Interacción con contrato" @@ -197,25 +377,25 @@ "message": "¡Copiado!" }, "copiedTransactionId": { - "message": "ID Transacción copiado" + "message": "ID de la Transacción copiado" }, "copyAddress": { "message": "Copiar la dirección al portapapeles" }, "copyPrivateKey": { - "message": "Ésta es tu clave privada (haz click para copiar)" + "message": "Ésta es tu clave privada (haz clic para copiar)" }, "copyToClipboard": { "message": "Copiar al portapapeles" }, "copyTransactionId": { - "message": "Copiar ID Transacción" + "message": "Copiar ID de la Transacción" }, "create": { "message": "Crear" }, "createAWallet": { - "message": "Crear Wallet" + "message": "Crear Monedero" }, "createAccount": { "message": "Crear cuenta" @@ -226,6 +406,12 @@ "currencyConversion": { "message": "Cambio de Monedas" }, + "currentAccountNotConnected": { + "message": "Tu cuenta actual no está conectada" + }, + "currentExtension": { + "message": "Página de la extensión actual" + }, "currentLanguage": { "message": "Idioma Actual" }, @@ -238,17 +424,43 @@ "customRPC": { "message": "RPC personalizado" }, + "customSpendLimit": { + "message": "Límite de Gasto Personalizado" + }, "customToken": { "message": "Token Personalizado" }, + "dataBackupFoundInfo": { + "message": "Se hizo una copia de seguridad de algunos de los datos de su cuenta durante una instalación anterior de MetaMask. Esto podría incluir su configuración, contactos y tokens. ¿Le gustaría restaurar estos datos ahora?" + }, "decimal": { "message": "Decimales de precisión" }, "decimalsMustZerotoTen": { "message": "Los decimales deben ser al menos 0 y no más de 36" }, + "decrypt": { + "message": "Descifrar" + }, + "decryptCopy": { + "message": "Copiar mensaje cifrado" + }, + "decryptInlineError": { + "message": "Este mensaje no puede ser descifrado debido al error: $1", + "description": "$1 is error message" + }, + "decryptMessageNotice": { + "message": "$1 quiere leer este mensaje para completar su acción", + "description": "$1 is the web3 site name" + }, + "decryptMetamask": { + "message": "Descifrar mensaje" + }, + "decryptRequest": { + "message": "Descifrar petición" + }, "defaultNetwork": { - "message": "La red por defecto para las transacciones de Ether es MainNet (red principal)" + "message": "La red por defecto para las transacciones de Ether es la red principal de Ethereum (Main Net)" }, "delete": { "message": "Eliminar" @@ -256,6 +468,12 @@ "deleteAccount": { "message": "Eliminar Cuenta" }, + "deleteNetwork": { + "message": "¿Eliminar Red?" + }, + "deleteNetworkDescription": { + "message": "¿Está seguro de querer eliminar esta red?" + }, "depositEther": { "message": "Depositar Ether" }, @@ -266,7 +484,25 @@ "message": "Depositar Ether directamente" }, "directDepositEtherExplainer": { - "message": "Si posees Ether, la forma más rápida de transferirlo a tu nueva billetera es depositándolo directamente" + "message": "Si posees Ether, la forma más rápida de transferirlos a tu nuevo monedero es depositándolos directamente" + }, + "disconnect": { + "message": "Desconectar" + }, + "disconnectAllAccounts": { + "message": "Desconectar todas las cuentas" + }, + "disconnectAllAccountsConfirmationDescription": { + "message": "¿Seguro que quieres desconectarte? Puede perder la funcionalidad del sitio." + }, + "disconnectPrompt": { + "message": "Desconectar $1" + }, + "disconnectThisAccount": { + "message": "Desconectar esta cuenta" + }, + "dismiss": { + "message": "Descartar" }, "done": { "message": "Completo" @@ -274,9 +510,15 @@ "dontHaveAHardwareWallet": { "message": "¿No tienes un monedero físico?" }, + "dontShowThisAgain": { + "message": "No mostrar esto de nuevo" + }, "downloadGoogleChrome": { "message": "Descargar Google Chrome" }, + "downloadSecretBackup": { + "message": "Descargue esta Frase de Respaldo Secreta y guárdela almacenada de manera segura en un disco duro o medio de almacenamiento externo cifrado." + }, "downloadStateLogs": { "message": "Descargar logs de estado" }, @@ -289,20 +531,112 @@ "editContact": { "message": "Editar Contacto" }, + "editPermission": { + "message": "Editar Permiso" + }, + "encryptionPublicKeyNotice": { + "message": "$1 desea su clave de cifrado pública. Al dar su consentimiento, este sitio podrá redactar mensajes cifrados para usted.", + "description": "$1 is the web3 site name" + }, + "encryptionPublicKeyRequest": { + "message": "Solicitar clave pública de cifrado" + }, + "endOfFlowMessage1": { + "message": "Pasó la prueba - mantenga su frase semilla segura, ¡es su responsabilidad!" + }, + "endOfFlowMessage10": { + "message": "Todo Listo" + }, + "endOfFlowMessage2": { + "message": "Consejos para almacenarlo de forma segura" + }, + "endOfFlowMessage3": { + "message": "Guarde una copia de seguridad en varios lugares." + }, + "endOfFlowMessage4": { + "message": "Nunca comparta la frase con nadie." + }, + "endOfFlowMessage5": { + "message": "¡Cuidado con el phishing! MetaMask nunca le pedirá espontáneamente su frase semilla." + }, + "endOfFlowMessage6": { + "message": "Si necesita hacer una copia de seguridad de su frase semilla nuevamente, puede encontrarla en Configuración -> Seguridad." + }, + "endOfFlowMessage7": { + "message": "Si alguna vez tiene preguntas o ve algo sospechoso, envíe un correo electrónico a support@metamask.io." + }, "endOfFlowMessage8": { - "message": "MetaMask no puede recuperar tu seedphrase. Saber más." + "message": "MetaMask no puede recuperar tu frase semilla. Saber más." }, "endOfFlowMessage9": { "message": "Saber más." }, + "endpointReturnedDifferentChainId": { + "message": "El endpoint devolvió un ID de cadena diferente: $1", + "description": "$1 is the return value of eth_chainId from an RPC endpoint" + }, + "ensNotFoundOnCurrentNetwork": { + "message": "El nombre de ENS no se encuentra en la red actual. Intente cambiar a la red principal de Ethereum (Main Net)." + }, + "ensRegistrationError": { + "message": "Error en el registro de nombres de ENS" + }, + "enterAnAlias": { + "message": "Ingrese un alias" + }, + "enterMaxSpendLimit": { + "message": "Ingrese el Límite de Gasto Máximo" + }, "enterPassword": { "message": "Ingresa contraseña" }, "enterPasswordContinue": { "message": "Introducir contraseña para seguir" }, + "errorCode": { + "message": "Código: $1", + "description": "Displayed error code for debugging purposes. $1 is the error code" + }, + "errorDetails": { + "message": "Detalles del Error", + "description": "Title for collapsible section that displays error details for debugging purposes" + }, + "errorMessage": { + "message": "Mensaje: $1", + "description": "Displayed error message for debugging purposes. $1 is the error message" + }, + "errorName": { + "message": "Código: $1", + "description": "Displayed error name for debugging purposes. $1 is the error name" + }, + "errorPageMessage": { + "message": "Vuelva a intentarlo recargando la página o póngase en contacto con el soporte en support@metamask.io", + "description": "Message displayed on generic error page in the fullscreen or notification UI" + }, + "errorPagePopupMessage": { + "message": "Vuelva a intentarlo cerrando y volviendo a abrir la ventana emergente, o comuníquese con el soporte en support@metamask.io", + "description": "Message displayed on generic error page in the popup UI" + }, + "errorPageTitle": { + "message": "MetaMask encontró un error", + "description": "Title of generic error page" + }, + "errorStack": { + "message": "Pila:", + "description": "Title for error stack, which is displayed for debugging purposes" + }, "estimatedProcessingTimes": { - "message": "Tiempo Previsto de procesamiento" + "message": "Tiempo Previsto de Procesamiento" + }, + "eth_accounts": { + "message": "Ver las direcciones de sus cuentas permitidas (obligatorio)", + "description": "The description for the `eth_accounts` permission" + }, + "ethereumPublicAddress": { + "message": "Dirección Pública de Ethereum" + }, + "etherscan": { + "message": "Etherscan" }, "etherscanView": { "message": "Ver la cuenta en Etherscan" @@ -311,46 +645,96 @@ "message": "Ampliar Vista" }, "exportPrivateKey": { - "message": "Exportar clave privada" + "message": "Exportar Clave Privada" + }, + "externalExtension": { + "message": "Extensión Externa" + }, + "extraApprovalGas": { + "message": "+$1 gas de aprobación", + "description": "Expresses an additional gas amount the user will have to pay, on top of some other displayed amount. $1 is a decimal amount of gas" }, "failed": { "message": "Fallo" }, + "failedToFetchChainId": { + "message": "No se pudo obtener el ID de la cadena. ¿Es correcta su URL de RPC?" + }, + "failureMessage": { + "message": "Algo salió mal y no pudimos completar la acción" + }, "fast": { "message": "Rápido" }, + "fastest": { + "message": "Más rápido" + }, + "feeAssociatedRequest": { + "message": "Hay una tarifa asociada con esta solicitud." + }, "fiat": { "message": "FIAT", "description": "Exchange type" }, "fileImportFail": { - "message": "¿La importación no funcionó? ¡Haz click aquí!", + "message": "¿La importación no funcionó? ¡Haz clic aquí!", "description": "Helps user import their account from a JSON file" }, + "forbiddenIpfsGateway": { + "message": "Puerta de enlace IPFS prohibida: Por favor, especifique una puerta de enlace CID" + }, "forgetDevice": { "message": "Olvidar a este dispositivo" }, "from": { "message": "De:" }, + "fromAddress": { + "message": "Desde: $1", + "description": "$1 is the address to include in the From label. It is typically shortened first using shortenAddress" + }, + "functionApprove": { + "message": "Función: Aprobar" + }, "functionType": { "message": "Tipo de función" }, "gasLimit": { "message": "Límite de gas" }, + "gasLimitInfoTooltipContent": { + "message": "El límite de gas es la cantidad máxima de unidades de gas que está dispuesto a gastar." + }, "gasLimitTooLow": { "message": "El límite de gas debe ser de al menos 21000" }, + "gasLimitTooLowWithDynamicFee": { + "message": "El límite de gas debe ser de al menos $1", + "description": "$1 is the custom gas limit, in decimal." + }, "gasPrice": { "message": "Precio del Gas (GWEI)" }, "gasPriceExtremelyLow": { "message": "Precio de Gas excesivamente bajo" }, + "gasPriceInfoTooltipContent": { + "message": "El precio del gas especifica la cantidad de Ether que está dispuesto a pagar por cada unidad de gas." + }, "gasUsed": { "message": "Gas usado" }, + "gdprMessage": { + "message": "Estos datos son agregados y, por lo tanto, son anónimos a los efectos del Reglamento General de Protección de Datos (EU) 2016/679. Para obtener más información sobre nuestras prácticas de privacidad, consulte nuestro $1.", + "description": "$1 refers to the gdprMessagePrivacyPolicy message, the translation of which is meant to be used exclusively in the context of gdprMessage" + }, + "gdprMessagePrivacyPolicy": { + "message": "Política de privacidad aquí", + "description": "this translation is intended to be exclusively used as the replacement for the $1 in the gdprMessage translation" + }, + "general": { + "message": "General" + }, "generalSettingsDescription": { "message": "Conversión de divisas, divisa principal, idioma, blockies identicon" }, @@ -364,6 +748,18 @@ "getHelp": { "message": "Pedir ayuda." }, + "getStarted": { + "message": "Empezar" + }, + "goerli": { + "message": "Red de pruebas Goerli" + }, + "happyToSeeYou": { + "message": "Estamos felices de verte." + }, + "hardware": { + "message": "Físico" + }, "hardwareWalletConnected": { "message": "Se ha conectado el monedero físico" }, @@ -374,14 +770,14 @@ "message": "Seleccionar un monedero físico que quieres usar con MetaMask" }, "havingTroubleConnecting": { - "message": "¿Tienes problemas para hacer la conexión?" + "message": "¿Tienes problemas de conexión?" }, "here": { "message": "Aquí", "description": "as in -click here- for more information (goes with troubleTokenBalances)" }, "hexData": { - "message": "Datos de formato Hex" + "message": "Datos hexadecimales" }, "hide": { "message": "Ocultar" @@ -389,6 +785,10 @@ "hideTokenPrompt": { "message": "¿Ocultar token?" }, + "hideTokenSymbol": { + "message": "Ocultar $1", + "description": "$1 is the symbol for a token (e.g. 'DAI')" + }, "history": { "message": "Historial" }, @@ -400,23 +800,29 @@ "message": "Importar cuenta" }, "importAccountMsg": { - "message": "Las cuentas importadas no serán asociadas con tu cuenta original creada con tu MetaMask. Aprende más acerca de importar cuentas." + "message": "Las cuentas importadas no serán asociadas con tu cuenta original creada con tu MetaMask. Aprende más acerca de importar cuentas " + }, + "importAccountSeedPhrase": { + "message": "Importar una cuenta con la frase semilla" }, "importUsingSeed": { "message": "Importar usando la frase semilla de la cuenta" }, "importWallet": { - "message": "Importar Wallet" + "message": "Importar Monedero" + }, + "importYourExisting": { + "message": "Importa tu monedero existente usando la frase semilla de 12 palabras" }, "imported": { "message": "Importado", "description": "status showing that an account has been fully loaded into the keyring" }, "infoHelp": { - "message": "Informacion y ayuda" + "message": "Información y ayuda" }, "initialTransactionConfirmed": { - "message": "La red confirmó tu transacción inicial. Hazle clic en OK para volver." + "message": "La red confirmó tu transacción inicial. Hazle clic en Ok para volver." }, "insufficientBalance": { "message": "Saldo insuficiente." @@ -431,33 +837,80 @@ "message": "Dirección inválida" }, "invalidAddressRecipient": { - "message": "Dirección del destinatario invalida" + "message": "Dirección del destinatario inválida" }, "invalidAddressRecipientNotEthNetwork": { "message": "No es una red ETH, convertirlo a minúscula" }, "invalidBlockExplorerURL": { - "message": "Invalida URL del Block Explorer" + "message": "URL Inválida del Explorador de Bloques" + }, + "invalidCustomNetworkAlertContent1": { + "message": "El ID de la cadena para la red personalizada '$1' tiene que ser re-ingresada.", + "description": "$1 is the name/identifier of the network." + }, + "invalidCustomNetworkAlertContent2": { + "message": "Para protegerlo de proveedores de red maliciosos o con fallas, los IDs de cadenas son ahora requeridos para todas las redes personalizadas." + }, + "invalidCustomNetworkAlertContent3": { + "message": "Vaya a Configuración > Redes e ingrese el ID de la cadena. Puede obtener los IDs de las cadens más populares en $1.", + "description": "$1 is a link to https://chainid.network" + }, + "invalidCustomNetworkAlertTitle": { + "message": "Red Personalizada Inválida" + }, + "invalidHexNumber": { + "message": "Número hexadecimal inválido." + }, + "invalidHexNumberLeadingZeros": { + "message": "Número hexadecimal inválido. Elimine los ceros iniciales." + }, + "invalidIpfsGateway": { + "message": "Puerta de enlace IPFS inválida: El valor debe ser una URL válida" + }, + "invalidNumber": { + "message": "Número inválido. Ingrese un número decimal o un hexadecimal con prefijo '0x'." + }, + "invalidNumberLeadingZeros": { + "message": "Número inválido. Elimine los ceros iniciales." }, "invalidRPC": { - "message": "Invalida URL del RPC" + "message": "URL del RPC inválida " }, "invalidSeedPhrase": { - "message": "Frase semilla no válida." + "message": "Frase semilla inválida." + }, + "ipfsGateway": { + "message": "Puerta de enlace IPFS" + }, + "ipfsGatewayDescription": { + "message": "Ingrese la URL de la puerta de enlace IPFS CID para usar resolución de contenido ENS." }, "jsonFile": { "message": "Archivo JSON", "description": "format for importing an account" }, + "knownAddressRecipient": { + "message": "Dirección de contrato conocida." + }, + "knownTokenWarning": { + "message": "Esta acción editará los tokens que ya están listados en su monedero, que se pueden usar para suplantarlo. Apruebe solo si está seguro de que quiere cambiar lo que representan estos tokens." + }, "kovan": { "message": "Red de pruebas Kovan" }, + "lastConnected": { + "message": "Última vez Conectado" + }, "learnMore": { "message": "Más información" }, "ledgerAccountRestriction": { "message": "Hay que hacer uso de tu última cuenta antes de agregarle una nueva." }, + "letsGoSetUp": { + "message": "Sí, ¡preparémonos!" + }, "likeToAddTokens": { "message": "¿Te gustaría agregar estos tokens?" }, @@ -473,29 +926,96 @@ "loadingTokens": { "message": "Cargando tokens..." }, + "localhost": { + "message": "Localhost 8545" + }, "lock": { "message": "Cerrar sesión" }, + "lockTimeTooGreat": { + "message": "El tiempo para cerrar sesión es demasiado grande" + }, "mainnet": { "message": "Red principal de Ethereum (Main Net)" }, + "max": { + "message": "Máximo" + }, + "memo": { + "message": "memo" + }, + "memorizePhrase": { + "message": "Memoriza esta frase." + }, "message": { "message": "Mensaje" }, + "metaMaskConnectStatusParagraphOne": { + "message": "Ahora tienes más control sobre tus conexiones a la cuenta en MetaMask." + }, + "metaMaskConnectStatusParagraphThree": { + "message": "Clic para administrar tus cuentas conectadas." + }, + "metaMaskConnectStatusParagraphTwo": { + "message": "El botón de estado de conexión muestra si el sitio que está visitando se encuentra conectado a tu cuenta actualmente seleccionada." + }, "metamaskDescription": { - "message": "MetaMask es una identidad segura en Ethereum" + "message": "Conectándote a Ethereum y la Web Descentralizada." + }, + "metamaskSwapsOfflineDescription": { + "message": "Intercambios MetaMask está en mantenimiento. Por favor intente más tarde." }, "metamaskVersion": { "message": "Versión de MetaMask" }, + "metametricsCommitmentsAllowOptOut": { + "message": "Siempre permitir optar por no participar a través de Configuración" + }, + "metametricsCommitmentsBoldNever": { + "message": "Nunca", + "description": "This string is localized separately from some of the commitments so that we can bold it" + }, + "metametricsCommitmentsIntro": { + "message": "MetaMask va a.." + }, + "metametricsCommitmentsNeverCollectIP": { + "message": "$1 recolecta tu dirección IP completa", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverCollectKeysEtc": { + "message": "$1 recolecta llaves, direcciones, transaccinoes, balances, hashes, o cualquier información personal", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverSellDataForProfit": { + "message": "$1 vende datos para lucrar. ¡Nunca!", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsSendAnonymizedEvents": { + "message": "Enviar eventos de vista de página y clics anónimos" + }, + "metametricsHelpImproveMetaMask": { + "message": "Ayúdanos a mejorar MetaMask" + }, + "metametricsOptInDescription": { + "message": "A MetaMask le gustaría recopilar datos de uso para entender mejor cómo interactúan nuestros usuarios con la extensión. Estos datos van a ser usados, de forma continua, para mejorar la usabilidad y experiencia de uso de nuestro producto y el ecosistema Ethereum." + }, + "mobileSyncText": { + "message": "Por favor, ingrese su contraseña ¡para confirmar que es usted!" + }, "mustSelectOne": { "message": "Debe seleccionar al menos un (1) token" }, "myAccounts": { "message": "Mis cuentas" }, + "myWalletAccounts": { + "message": "Mis cuentas de monedero" + }, + "myWalletAccountsDescription": { + "message": "Todas tus cuentas creadas con MetaMask serán automáticamente agregadas a esta sección." + }, "needEtherInWallet": { - "message": "Para interactuar con una aplicación descentralizada usando MetaMask, necesitas tener Ether en tu billetera" + "message": "Para interactuar con una aplicación descentralizada usando MetaMask, necesitas tener Ether en tu monedero" }, "needImportFile": { "message": "Debes seleccionar un archivo para importar", @@ -504,6 +1024,15 @@ "negativeETH": { "message": "No se pueden mandar cantidades negativas de ETH" }, + "networkName": { + "message": "Nombre de la Red" + }, + "networkSettingsChainIdDescription": { + "message": "El ID de la cadena es utilizado para firmar transacciones. Debe coincidir con el ID de la cadena devuelto por la red. Puede ingresar un número decimal o hexadecimal con prefijo '0x', pero se mostrará el número en decimal." + }, + "networkSettingsDescription": { + "message": "Agregue y edite redes RPC personalizadas" + }, "networks": { "message": "Redes" }, @@ -513,6 +1042,9 @@ "newAccount": { "message": "Nueva cuenta" }, + "newAccountDetectedDialogMessage": { + "message": "¡Nueva dirección detectada! Clic aquí para agregar a su libreta de direcciones." + }, "newAccountNumberName": { "message": "Cuenta $1", "description": "Default name of next account to be created on create account screen" @@ -529,6 +1061,9 @@ "newPassword": { "message": "Nueva contraseña (mínimo [8] caracteres)" }, + "newToMetaMask": { + "message": "¿Es nuevo en MetaMask?" + }, "newTotal": { "message": "Nuevo total" }, @@ -538,11 +1073,24 @@ "next": { "message": "Siguiente" }, + "nextNonceWarning": { + "message": "El nonce es más alto que el sugerido de $1", + "description": "The next nonce according to MetaMask's internal logic" + }, + "noAccountsFound": { + "message": "No se encontraron cuentas para su búsqueda" + }, "noAddressForName": { - "message": "No se ha establecido ninguna dirección para este nombre" + "message": "No se ha establecido ninguna dirección para este nombre." + }, + "noAlreadyHaveSeed": { + "message": "No, ya tengo una frase semilla" }, "noConversionRateAvailable": { - "message": "No hay tasa de conversión" + "message": "No hay ninguna Tasa de Conversión Disponible" + }, + "noThanks": { + "message": "No Gracias" }, "noTransactions": { "message": "Sin transacciones" @@ -553,21 +1101,70 @@ "noWebcamFoundTitle": { "message": "No se encontró a la webcam" }, + "nonceField": { + "message": "Personalizar el nonce de la transacción" + }, + "nonceFieldDescription": { + "message": "Habilite esto para cambiar el nonce (número de transacción) en las pantallas de confirmación. Esto es una funcionalidad avanzada, úsela con precaución." + }, + "nonceFieldHeading": { + "message": "Nonce Personalizado" + }, + "notCurrentAccount": { + "message": "¿Es esta la cuenta correcta? Es diferente de la cuenta actualmente seleccionada en su monedero" + }, + "notEnoughGas": { + "message": "No hay suficiente gas" + }, "ofTextNofM": { "message": "de" }, + "off": { + "message": "Apagado" + }, + "offlineForMaintenance": { + "message": "Fuera de línea por mantenimiento" + }, + "ok": { + "message": "Ok" + }, + "on": { + "message": "Encendido" + }, + "onboardingReturnNotice": { + "message": "\"$1\" cerrará esta pestaña y volverá directamente a $2", + "description": "Return the user to the site that initiated onboarding" + }, + "onlyAddTrustedNetworks": { + "message": "Un proveedor de red de Ethereum malintencionado puede mentir sobre el estado de la cadena de bloques y registrar la actividad de su red. Solo agregue redes personalizadas en las que confíe." + }, + "onlyAvailableOnMainnet": { + "message": "Solo disponible en la red principal de Ethereum (Main Net)" + }, + "onlyConnectTrust": { + "message": "Conéctese solo con sitios en los que confíe." + }, + "optionalBlockExplorerUrl": { + "message": "URL del Explorador de bloques (opcional)" + }, "optionalCurrencySymbol": { "message": "Símbolo (opcional)" }, "orderOneHere": { - "message": "Comprate un Trezor o Ledger y guarda tus fondos en almacenamiento frío" + "message": "Cómprate un Trezor o Ledger y guarda tus fondos en almacenamiento frío" }, "origin": { - "message": "Orígen" + "message": "Origen" }, "parameters": { "message": "Parámetros" }, + "participateInMetaMetrics": { + "message": "Participa en MetaMetrics" + }, + "participateInMetaMetricsDescription": { + "message": "Participa en MetaMetrics para ayudarnos a mejorar MetaMask" + }, "password": { "message": "Contraseña" }, @@ -584,14 +1181,30 @@ "pending": { "message": "pendiente" }, + "permissionCheckedIconDescription": { + "message": "Has aprobado este permiso" + }, + "permissionUncheckedIconDescription": { + "message": "No has aprobado este permiso" + }, + "permissions": { + "message": "Permisos" + }, "personalAddressDetected": { "message": "Dirección personal detectada. Ingresa la dirección del contrato del token" }, + "plusXMore": { + "message": "+ $1 más", + "description": "$1 is a number of additional but unshown items in a list- this message will be shown in place of those items" + }, + "prev": { + "message": "Prev" + }, "primaryCurrencySetting": { "message": "Moneda principal" }, "primaryCurrencySettingDescription": { - "message": "Seleccionar nativa para prioritizar el que se muestren los valores en la moneda nativa de la cadena (p.ej. ETH). Seleccionar Fíat para prioritzar el que se muestren los valores en la moneda fíat seleccionada." + "message": "Seleccionar nativa para priorizar el que se muestren los valores en la moneda nativa de la cadena (p.ej. ETH). Seleccionar Fíat para priorizar el que se muestren los valores en la moneda fíat seleccionada." }, "privacyMsg": { "message": "Política de privacidad" @@ -601,43 +1214,70 @@ "description": "select this type of file to use to import an account" }, "privateKeyWarning": { - "message": "Advertencia: NUNCA reveles esta clave. Cualquier persona con tus claves privadas puede robar los activos retenidos en tu cuenta" + "message": "Advertencia: Nunca reveles esta clave. Cualquier persona con tus claves privadas puede robar los activos retenidos en tu cuenta" }, "privateNetwork": { "message": "Red privada" }, + "proposedApprovalLimit": { + "message": "Límite de aprobación propuesto" + }, + "protectYourKeys": { + "message": "¡Proteja sus llaves!" + }, + "protectYourKeysMessage1": { + "message": "Tenga cuidado con su frase semilla — ha habido informes de sitios web que intentan imitar MetaMask. ¡MetaMask nunca le pedirá su frase semilla!" + }, + "protectYourKeysMessage2": { + "message": "Mantenga su frase a salvo. Si ve algo sospechoso o no está seguro acerca de un sitio web, envíe un correo electrónico a support@metamask.io" + }, + "provide": { + "message": "Proveer" + }, "queue": { "message": "Cola" }, + "queued": { + "message": "Encolado" + }, "readdToken": { "message": "Puedes volver a agregar este token en el futuro pinchando sobre 'Agregar token' en el menú de opciones de tu cuenta" }, "readyToConnect": { "message": "¿Listo/a para conectar?" }, + "receive": { + "message": "Recibir" + }, "recents": { "message": "Recientes" }, "recipientAddress": { - "message": "Dirección del receptor" + "message": "Dirección del destinatario" + }, + "recipientAddressPlaceholder": { + "message": "Buscar, dirección pública (0x) o ENS" }, "reject": { "message": "Rechazar" }, "rejectAll": { - "message": "Rechazar todas" + "message": "Rechazar todo" }, "rejectTxsDescription": { - "message": "Está al punto de rechazar transacciones de $1 en lote." + "message": "Está a punto de rechazar transacciones de $1 en lote." }, "rejectTxsN": { "message": "Rechazar transacciones de $1" }, "rejected": { - "message": "Rechazado" + "message": "Rechazada" + }, + "remindMeLater": { + "message": "Recordarme más tarde" }, "remove": { - "message": "borrar" + "message": "Borrar" }, "removeAccount": { "message": "Borrar cuenta" @@ -664,31 +1304,44 @@ "message": "Restaurar" }, "restoreAccountWithSeed": { - "message": "Restaurar tu Cuenta con Frase Semilla" + "message": "Restaurar tu Cuenta con la Frase Semilla" }, "restoreFromSeed": { - "message": "Restaurar desde semilla" + "message": "¿Restaurar cuenta?" + }, + "restoreWalletPreferences": { + "message": "Se ha encontrado una copia de seguridad de sus datos de $1. ¿Le gustaría restaurar sus preferencias de monedero?", + "description": "$1 is the date at which the data was backed up" + }, + "retryTransaction": { + "message": "Reintentar Transacción" + }, + "reusedTokenNameWarning": { + "message": "Un token aquí reutiliza un símbolo de otro token que está observando, esto puede ser confuso o engañoso." }, "revealSeedWords": { - "message": "Revelar palabras de semilla" + "message": "Revelar Frase Semilla" }, "revealSeedWordsDescription": { "message": "Si en algún momento cambias de navegador o de ordenador, necesitarás esta frase semilla para acceder a tus cuentas. Guárdatela en un lugar seguro y secreto." }, "revealSeedWordsTitle": { - "message": "Frase semilla" + "message": "Frase Semilla" }, "revealSeedWordsWarning": { - "message": "¡No recuperes tu semilla en un lugar pública! Esas palabras pueden ser usadas para robarte todas tus cuentas" + "message": "¡No recuperes tu semilla en un lugar público! Esas palabras pueden ser usadas para robarte todas tus cuentas" }, "revealSeedWordsWarningTitle": { - "message": "NO compartas esta frase con nadie!" + "message": "¡NO compartas esta frase con nadie!" }, "rinkeby": { - "message": "Red privada Rinkeby" + "message": "Red de prueba Rinkeby" }, "ropsten": { - "message": "Red privada Ropsten" + "message": "Red de prueba Ropsten" + }, + "rpcUrl": { + "message": "Nueva URL RPC" }, "save": { "message": "Guardar" @@ -702,62 +1355,96 @@ "scanQrCode": { "message": "Escanear código QR" }, + "scrollDown": { + "message": "Desplazarse hacia abajo" + }, "search": { "message": "Buscar" }, + "searchAccounts": { + "message": "Buscar Cuentas" + }, "searchResults": { "message": "Resultados de la Búsqueda" }, "searchTokens": { "message": "Buscar Tokens" }, + "secretBackupPhrase": { + "message": "Frase de Respaldo Secreta" + }, + "secretBackupPhraseDescription": { + "message": "Su frase de respaldo secreta facilita la realización de copias de seguridad y la restauración de su cuenta." + }, + "secretBackupPhraseWarning": { + "message": "ADVERTENCIA: Nunca revele su frase de respaldo. Cualquiera con esta frase puede tomar su Ether para siempre." + }, "secretPhrase": { - "message": "Ingresa tu frase de doce (12) palabras para restaurar tu bóveda" + "message": "Ingresa tu frase de doce (12) palabras para restaurar tu bóveda." + }, + "securityAndPrivacy": { + "message": "Seguridad y Privacidad" + }, + "securitySettingsDescription": { + "message": "Configuración de privacidad y frase semilla de monedero" }, "seedPhrasePlaceholder": { "message": "Separar a cada palabra con un sólo espacio" }, + "seedPhrasePlaceholderPaste": { + "message": "Pegar la frase semilla del portapapeles" + }, "seedPhraseReq": { - "message": "las frases semilla tienen doce (12) palabras de largo" + "message": "Las frases semilla contienen 12, 15, 18, 21 oo 24 palabras" }, "selectAHigherGasFee": { "message": "Seleccione una comisión de gas más elevada para agilizar el procesamiento de tu transacción.*" }, + "selectAccounts": { + "message": "Selecciona cuenta(s)" + }, + "selectAll": { + "message": "Seleccionar todo" + }, "selectAnAccount": { - "message": "Seleccionar una Cuenta" + "message": "Selecciona una Cuenta" }, "selectAnAccountHelp": { - "message": "Seleccionar la cuenta que quiere ver en MetaMask" + "message": "Selecciona la cuenta que quiere ver en MetaMask" }, - "selectCurrency": { - "message": "Seleccionar moneda" + "selectEachPhrase": { + "message": "Selecciona cada frase para asegurarse de que sea correcta." }, "selectHdPath": { - "message": "Seleccionar la ruta HD (jerárquica determinista)" - }, - "selectLocale": { - "message": "Seleccionar local" + "message": "Selecciona la ruta HD (jerárquica determinista)" }, "selectPathHelp": { "message": "Si no ves tus cuentas actuales de Ledger abajo, prueba cambiando la ruta a \"Legacy (MEW / MyCrypto)\"" }, "selectType": { - "message": "Seleccionar tipo" + "message": "Selecciona tipo" + }, + "selectingAllWillAllow": { + "message": "Seleccionar todo permitirá que este sitio vea todas sus cuentas actuales. Asegúrate de confiar en este sitio." }, "send": { "message": "Enviar" }, "sendAmount": { - "message": "Mandar cantidad" + "message": "Enviar cantidad" }, "sendETH": { - "message": "Enviar Ether" + "message": "Enviar ETH" + }, + "sendSpecifiedTokens": { + "message": "Enviar $1", + "description": "Symbol of the specified token" }, "sendTokens": { "message": "Enviar tokens" }, "sentEther": { - "message": "se mandó ether" + "message": "Ether enviado" }, "separateEachWord": { "message": "Separar a cada palabra con un sólo espacio" @@ -765,15 +1452,39 @@ "settings": { "message": "Configuración" }, + "showAdvancedGasInline": { + "message": "Controles de gas avanzados" + }, + "showAdvancedGasInlineDescription": { + "message": "Seleccione esto para mostrar el precio del gas y los controles de límite directamente en las pantallas de envío y confirmación." + }, + "showFiatConversionInTestnets": { + "message": "Mostrar Conversión en redes de prueba" + }, + "showFiatConversionInTestnetsDescription": { + "message": "Seleccione esto para mostrar la conversión fiat en redes de prueba" + }, "showHexData": { "message": "Mostrar Datos en formato Hex" }, "showHexDataDescription": { "message": "Seleccionar esto para mostrar el campo de los datos en formato hex en la pantalla de mandar" }, + "showIncomingTransactions": { + "message": "Mostrar transacciones entrantes" + }, + "showIncomingTransactionsDescription": { + "message": "Seleccione esto para usar Etherscan para mostrar las transacciones entrantes en la lista de transacciones" + }, + "showPermissions": { + "message": "Mostrar permisos" + }, "showPrivateKeys": { "message": "Mostrar claves privadas" }, + "showSeedPhrase": { + "message": "Mostrar frase semilla" + }, "sigRequest": { "message": "Solicitud de firma" }, @@ -786,6 +1497,9 @@ "signatureRequest": { "message": "Petición de Firma" }, + "signatureRequest1": { + "message": "Mensaje" + }, "signed": { "message": "Firmado" }, @@ -804,14 +1518,42 @@ "speedUpTransaction": { "message": "Agilizar esta transacción" }, + "spendLimitAmount": { + "message": "Monto límite de gasto" + }, + "spendLimitInsufficient": { + "message": "Límite de gasto insuficiente" + }, + "spendLimitInvalid": { + "message": "Límite de gasto inválido, debe ser un número positivo" + }, + "spendLimitPermission": { + "message": "Permiso de límite de gasto" + }, + "spendLimitRequestedBy": { + "message": "Límite de gasto solicitado por $1", + "description": "Origin of the site requesting the spend limit" + }, + "spendLimitTooLarge": { + "message": "Límite de gasto demasiado grande" + }, "stateLogError": { - "message": "Error en la recogida de logs de estado" + "message": "Error al recuperar los logs de estado" + }, + "stateLogFileName": { + "message": "Logs de Estado MetaMask" }, "stateLogs": { - "message": "Logs de estado" + "message": "Logs de Estado" }, "stateLogsDescription": { - "message": "Los logs de estado contienen tus direcciones de cuentas públicas y transacciones envíadas" + "message": "Los logs de estado contienen sus direcciones de cuentas públicas y transacciones enviadas" + }, + "statusConnected": { + "message": "Conectado" + }, + "statusNotConnected": { + "message": "No conectado" }, "step1HardwareWallet": { "message": "1. Conectar monedero físico." @@ -826,44 +1568,385 @@ "message": "Seleccione la cuenta que quieres ver. Sólo se puede eligir una a la vez." }, "step3HardwareWallet": { - "message": "3. Empezar a usar dApps y más!" + "message": "3. Empezar a usar dApps ¡y más!" }, "step3HardwareWalletMsg": { "message": "Usa tu cuenta física igual que harías con cualquier cuenta de Ethereum. Regístrate con dApps, manda Eth, compra y almacena tokens de ERC20 y otros tokens no-fungibles, como CryptoKitties." }, + "storePhrase": { + "message": "Guarde esta frase en un administrador de contraseñas como 1Password." + }, + "submit": { + "message": "Enviar" + }, "submitted": { "message": "Enviado" }, "supportCenter": { "message": "Visita nuestro centro de atención" }, + "swap": { + "message": "Intercambiar" + }, + "swapAdvancedSlippageInfo": { + "message": "Si el precio cambia entre el momento en que se realiza el pedido y el momento en que se confirma, se denomina \"deslizamiento\". Su intercambio se cancelará automáticamente si el deslizamiento excede su configuración de \"deslizamiento máximo\"." + }, + "swapAggregator": { + "message": "Agregador" + }, + "swapAmountReceived": { + "message": "Cantidad garantizada" + }, + "swapAmountReceivedInfo": { + "message": "Esta es la cantidad mínima que recibirá. Puede recibir más dependiendo del deslizamiento." + }, + "swapApproval": { + "message": "Aprobar $1 para intercambios", + "description": "Used in the transaction display list to describe a transaction that is an approve call on a token that is to be swapped.. $1 is the symbol of a token that has been approved." + }, + "swapApproveNeedMoreTokens": { + "message": "Necesita $1 más de $2 para completar este intercambio", + "description": "Tells the user how many more of a given token they need for a specific swap. $1 is an amount of tokens and $2 is the token symbol." + }, + "swapBetterQuoteAvailable": { + "message": "Hay una mejor cotización disponible" + }, + "swapBuildQuotePlaceHolderText": { + "message": "No hay tokens disponibles que coincidan con $1", + "description": "Tells the user that a given search string does not match any tokens in our token lists. $1 can be any string of text" + }, + "swapCheckingQuote": { + "message": "Comprobando $1", + "description": "Shown to the user during quote loading. $1 is the name of an aggregator. The message indicates that metamask is currently checking if that aggregator has a trade/quote for their requested swap." + }, + "swapCustom": { + "message": "personalizado" + }, + "swapDecentralizedExchange": { + "message": "Exchange descentralizado" + }, + "swapEditLimit": { + "message": "Editar límite" + }, + "swapEnableDescription": { + "message": "Esto es obligatorio y le da permiso a MetaMask para intercambiar su $1.", + "description": "Gives the user info about the required approval transaction for swaps. $1 will be the symbol of a token being approved for swaps." + }, + "swapEstimatedNetworkFee": { + "message": "Tarifa de red estimada" + }, + "swapEstimatedNetworkFeeSummary": { + "message": "La “$1“ es lo que esperamos que sea la tarifa real. La cantidad exacta depende de las condiciones de la red.", + "description": "$1 will be the translation of swapEstimatedNetworkFee, with the font bolded" + }, + "swapEstimatedNetworkFees": { + "message": "Tarifas de red estimadas" + }, + "swapEstimatedNetworkFeesInfo": { + "message": "Esta es una estimación de la tarifa de red que se utilizará para completar su intercambio. La cantidad real puede cambiar según las condiciones de la red." + }, + "swapFailedErrorTitle": { + "message": "Intercambio fallido" + }, + "swapFetchingQuotesErrorDescription": { + "message": "Hmmm... algo salió mal. Vuelva a intentarlo o, si los errores persisten, póngase en contacto con el servicio de atención al cliente." + }, + "swapFetchingQuotesErrorTitle": { + "message": "Error al obtener cotizaciones" + }, + "swapFetchingTokens": { + "message": "Obteniendo tokens..." + }, + "swapFinalizing": { + "message": "Finalizando..." + }, + "swapHighSlippageWarning": { + "message": "La cantidad de deslizamiento es muy alta. ¡Asegúrate de saber lo que estás haciendo!" + }, + "swapIntroLearnMoreHeader": { + "message": "¿Quiere aprender más?" + }, + "swapIntroLearnMoreLink": { + "message": "Más información sobre los Intercambios MetaMask" + }, + "swapIntroLiquiditySourcesLabel": { + "message": "Las fuentes de liquidez incluyen:" + }, + "swapIntroPopupSubTitle": { + "message": "Ahora puede intercambiar tokens directamente en su monedero MetaMask. Intercambios MetaMask combina múltiples agregadores de intercambio descentralizados, creadores de mercado profesionales y DEX individuales para garantizar que los usuarios de MetaMask siempre obtengan el mejor precio con las tarifas de red más bajas." + }, + "swapIntroPopupTitle": { + "message": "¡El intercambio de tokens está aquí!" + }, + "swapLearnMoreContractsAuditReview": { + "message": "Revise nuestra auditoría de contratos oficiales" + }, + "swapLowSlippageError": { + "message": "La transacción puede fallar, el deslizamiento máximo es demasiado bajo." + }, + "swapMaxNetworkFeeInfo": { + "message": "“$1” es lo máximo que gastará. Cuando la red es volátil, esto puede ser una gran cantidad.", + "description": "$1 will be the translation of swapMaxNetworkFees, with the font bolded" + }, + "swapMaxNetworkFees": { + "message": "Tarifa de red máxima" + }, + "swapMaxSlippage": { + "message": "Deslizamiento máximo" + }, + "swapMetaMaskFee": { + "message": "Tarifa de MetaMask" + }, + "swapMetaMaskFeeDescription": { + "message": "Siempre encontramos el mejor precio de las principales fuentes de liquidez. Una tarifa de $1% se incluye automáticamente en cada cotización, lo que respalda el desarrollo continuo para hacer que MetaMask sea aún mejor.", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapNQuotes": { + "message": "$1 cotizaciones", + "description": "$1 is the number of quotes that the user can select from when opening the list of quotes on the 'view quote' screen" + }, + "swapNetworkFeeSummary": { + "message": "La tarifa de la red cubre el costo de procesar su intercambio y almacenarlo en la red Ethereum. MetaMask no se beneficia de esta tarifa." + }, + "swapNewQuoteIn": { + "message": "Nuevas cotizaciones en $1", + "description": "Tells the user the amount of time until the currently displayed quotes are update. $1 is a time that is counting down from 1:00 to 0:00" + }, + "swapOnceTransactionHasProcess": { + "message": "Su $1 se agregará a su cuenta una vez que se haya procesado esta transacción.", + "description": "This message communicates the token that is being transferred. It is shown on the awaiting swap screen. The $1 will be a token symbol." + }, + "swapPriceDifference": { + "message": "Está poor interccambiar $1 $2 (~$3) por $4 $5 (~$6).", + "description": "This message represents the price slippage for the swap. $1 and $4 are a number (ex: 2.89), $2 and $5 are symbols (ex: ETH), and $3 and $6 are fiat currency amounts." + }, + "swapPriceDifferenceTitle": { + "message": "Diferencia de precio de ~$1%", + "description": "$1 is a number (ex: 1.23) that represents the price difference." + }, + "swapPriceDifferenceTooltip": { + "message": "La diferencia en los precios de mercado puede verse afectada por las tarifas cobradas por los intermediarios, el tamaño del mercado, el tamaño del comercio o las ineficiencias del mercado." + }, + "swapPriceDifferenceUnavailable": { + "message": "El precio de mercado no está disponible. Asegúrese de sentirse cómodo con el monto devuelto antes de continuar." + }, + "swapProcessing": { + "message": "Procesando" + }, + "swapQuoteDetails": { + "message": "Detalles de cotización" + }, + "swapQuoteDetailsSlippageInfo": { + "message": "Si el precio cambia entre el momento en que se realiza el pedido y se confirma, se denomina \"deslizamiento\". Su intercambio se cancelará automáticamente si el deslizamiento excede su configuración de \"tolerancia de deslizamiento\"." + }, + "swapQuoteIncludesRate": { + "message": "La cotización incluye una tarifa de MetaMask de $1%", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapQuoteNofN": { + "message": "Cotización $1 de $2", + "description": "A count of loaded quotes shown to the user while they are waiting for quotes to be fetched. $1 is the number of quotes already loaded, and $2 is the total number of quotes to load." + }, + "swapQuoteSource": { + "message": "Fuente de cotización" + }, + "swapQuotesAreRefreshed": { + "message": "Las cotizaciones se actualizan a menudo para reflejar las condiciones actuales del mercado." + }, + "swapQuotesExpiredErrorDescription": { + "message": "Solicite nuevas cotizaciones para obtener las últimas tarifas." + }, + "swapQuotesExpiredErrorTitle": { + "message": "El tiempo de espera caducó obteniendo cotizaciones" + }, + "swapQuotesNotAvailableErrorDescription": { + "message": "Intente ajustar la configuración de cantidad o deslizamiento y vuelva a intentarlo." + }, + "swapQuotesNotAvailableErrorTitle": { + "message": "No hay cotizaciones disponibles" + }, + "swapRate": { + "message": "Tasa de intercambio" + }, + "swapReceiving": { + "message": "Recibiendo" + }, + "swapReceivingInfoTooltip": { + "message": "Esta es una estimación. La cantidad exacta depende del deslizamiento." + }, + "swapRequestForQuotation": { + "message": "Solicitud de presupuesto" + }, + "swapSearchForAToken": { + "message": "Buscar un token" + }, + "swapSelect": { + "message": "Seleccionar" + }, + "swapSelectAQuote": { + "message": "Seleccionar una cotización" + }, + "swapSelectAToken": { + "message": "Seleccionar un token" + }, + "swapSelectQuotePopoverDescription": { + "message": "A continuación se muestran todas las cotizaciones recopiladas de múltiples fuentes de liquidez." + }, + "swapSlippageTooLow": { + "message": "El deslizamiento debe ser mayor que cero" + }, + "swapSource": { + "message": "Fuente de liquidez" + }, + "swapSourceInfo": { + "message": "Buscamos múltiples fuentes de liquidez (exchanges, agregadores y creadores de mercado profesionales) para encontrar las mejores tarifas y las tarifas de red más bajas." + }, + "swapStartSwapping": { + "message": "Comenzar intercambio" + }, + "swapSwapFrom": { + "message": "Intercambiar desde" + }, + "swapSwapSwitch": { + "message": "Intercambiar de y a tokens" + }, + "swapSwapTo": { + "message": "Intercambiar a" + }, + "swapThisWillAllowApprove": { + "message": "Esto permitirá que se intercambie $1." + }, + "swapTokenAvailable": { + "message": "Su $1 se ha agregado a su cuenta.", + "description": "This message is shown after a swap is successful and communicates the exact amount of tokens the user has received for a swap. The $1 is a decimal number of tokens followed by the token symbol." + }, + "swapTokenToToken": { + "message": "Intercambiar $1 a $2", + "description": "Used in the transaction display list to describe a swap. $1 and $2 are the symbols of tokens in involved in a swap." + }, + "swapTransactionComplete": { + "message": "Transacción completada" + }, + "swapUnknown": { + "message": "Desconocido" + }, + "swapUsingBestQuote": { + "message": "Utilizando la mejor cotización" + }, + "swapVerifyTokenExplanation": { + "message": "Varios tokens pueden usar el mismo nombre y símbolo. Verifique Etherscan para verificar que este es el token que está buscando." + }, + "swapViewToken": { + "message": "Ver $1" + }, + "swapYourTokenBalance": { + "message": "$1 $2 están disponibles para intercambiar", + "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" + }, + "swapZeroSlippage": { + "message": "Deslizamiento 0%" + }, + "swapsAdvancedOptions": { + "message": "Opciones Avanzadas" + }, + "swapsExcessiveSlippageWarning": { + "message": "La cantidad de deslizamiento es demasiado alta y resultará en una mala tasa. Reduzca su tolerancia al deslizamiento a un valor inferior al 15%." + }, + "swapsMaxSlippage": { + "message": "Tolerancia al Deslizamiento" + }, + "swapsNotEnoughForTx": { + "message": "No hay suficiente $1 para completar esta transacción", + "description": "Tells the user that they don't have enough of a token for a proposed swap. $1 is a token symbol" + }, + "swapsViewInActivity": { + "message": "Ver en actividad" + }, "switchNetworks": { "message": "Cambiar de Red" }, + "switchToThisAccount": { + "message": "Cambiar a esta cuenta" + }, + "symbol": { + "message": "Símbolo" + }, "symbolBetweenZeroTwelve": { "message": "El símbolo debe tener 11 caracteres o menos." }, "syncWithMobile": { "message": "Sincronizar con el móvil" }, + "syncWithMobileBeCareful": { + "message": "Asegúrese de que nadie más esté mirando su pantalla cuando escanee este código" + }, + "syncWithMobileComplete": { + "message": "Tus datos se han sincronizado correctamente. ¡Disfruta de la aplicación móvil MetaMask!" + }, + "syncWithMobileDesc": { + "message": "Puede sincronizar sus cuentas e información con su dispositivo móvil. Abra la aplicación móvil MetaMask, vaya a \"Configuración\" y toque \"Sincronizar desde la extensión del navegador\"" + }, + "syncWithMobileDescNewUsers": { + "message": "Si acaba de abrir la aplicación móvil MetaMask por primera vez, simplemente siga los pasos en su teléfono." + }, + "syncWithMobileScanThisCode": { + "message": "Escanee este código con su aplicación móvil MetaMask" + }, "syncWithMobileTitle": { "message": "Sincronizar con el móvil" }, + "syncWithThreeBox": { + "message": "Sincronizar datos con 3Box (experimental)" + }, + "syncWithThreeBoxDescription": { + "message": "Actívelo para hacer una copia de seguridad de su configuración con 3Box. Esta característica es actualmente experimental, úselo bajo su propio riesgo." + }, + "syncWithThreeBoxDisabled": { + "message": "3Box se ha desactivado debido a un error durante la sincronización inicial" + }, "terms": { - "message": "Términos de uso" + "message": "Términos de Uso" + }, + "termsOfService": { + "message": "Términos del Servicio" }, "testFaucet": { - "message": "Probar Faucet" + "message": "Grifo de prueba" + }, + "thisWillCreate": { + "message": "Esto creará un nuevo monedero y frase semilla" + }, + "tips": { + "message": "Consejos" }, "to": { "message": "Para" }, + "toAddress": { + "message": "Para: $1", + "description": "$1 is the address to include in the To label. It is typically shortened first using shortenAddress" + }, + "toWithColon": { + "message": "Para:" + }, + "token": { + "message": "Token" + }, "tokenAlreadyAdded": { "message": "El token está actualmente agregado" }, + "tokenContractAddress": { + "message": "Dirección del contrato de token" + }, + "tokenOptions": { + "message": "Opciones del Token" + }, "tokenSymbol": { "message": "Símbolo del token" }, + "total": { + "message": "Total" + }, "transaction": { "message": "transacción" }, @@ -874,13 +1957,13 @@ "message": "La transacción se canceló con éxito en $2" }, "transactionConfirmed": { - "message": "Se confirmó la transacción a $2." + "message": "Se confirmó la transacción en $2." }, "transactionCreated": { - "message": "Se creó una transacción con un valor de $1, a $2." + "message": "Se creó una transacción con un valor de $1 en $2." }, "transactionDropped": { - "message": "Transacción se cayó en $2." + "message": "Transacción se redujo en $2." }, "transactionError": { "message": "Error en transacción. Se produjo una excepción en el código del contrato." @@ -904,15 +1987,26 @@ "message": "Se actualizó la transacción en $2." }, "transfer": { - "message": "Traspasar" + "message": "Transferir" + }, + "transferBetweenAccounts": { + "message": "Transferir entre mis cuentas" }, "transferFrom": { - "message": "Traspasar de" + "message": "Transferir Desde" + }, + "troubleConnectingToWallet": { + "message": "Tuvimos problemas para conectarnos con su $1, intente revisar $2 y vuelva a intentarlo.", + "description": "$1 is the wallet device name; $2 is a link to wallet connection guide" }, "troubleTokenBalances": { "message": "Tuvimos problemas para cargar tus saldos de tokens. Puedes verlos ", "description": "Followed by a link (here) to view token balances" }, + "trustSiteApprovePermission": { + "message": "¿Confías en este sitio? Al otorgar este permiso, permite que $1 retire sus $2 y automatice las transacciones por usted.", + "description": "$1 is the url requesting permission and $2 is the symbol of the currency that the request is for" + }, "tryAgain": { "message": "Vuelve a intentar" }, @@ -926,7 +2020,7 @@ "message": "unidades" }, "unknown": { - "message": "Desconocido (a)" + "message": "Desconocido/a" }, "unknownCameraError": { "message": "Hubo un error al intentar acceder a la cámara. Por favor, vuelve a intentar..." @@ -940,6 +2034,9 @@ "unknownQrCode": { "message": "Error: No pudimos identificar ese código QR" }, + "unlimited": { + "message": "Ilimitado" + }, "unlock": { "message": "Desbloquear" }, @@ -952,20 +2049,52 @@ "urlErrorMsg": { "message": "URI necesita el prefijo HTTP/HTTPS apropiado" }, + "urlExistsErrorMsg": { + "message": "La URL ya está presente en la lista existente de redes" + }, + "usePhishingDetection": { + "message": "Usar la detección de phishing" + }, + "usePhishingDetectionDescription": { + "message": "Mostrar una advertencia para los dominios de phishing dirigidos a los usuarios de Ethereum" + }, "usedByClients": { "message": "Utilizado por una variedad de clientes diferentes" }, + "userName": { + "message": "Nombre de usuario" + }, + "verifyThisTokenOn": { + "message": "Verifica este token en $1", + "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" + }, "viewAccount": { - "message": "Mirar cuenta" + "message": "Ver cuenta" + }, + "viewContact": { + "message": "Ver Contacto" + }, + "viewOnCustomBlockExplorer": { + "message": "Ver en $1" }, "viewOnEtherscan": { "message": "Ver en Etherscan" }, + "viewinExplorer": { + "message": "Ver en el Explorador" + }, "visitWebSite": { "message": "Visita nuestro sitio web" }, + "walletConnectionGuide": { + "message": "nuestra guía de monedero físico" + }, "walletSeed": { - "message": "Semilla de la billetera" + "message": "Semilla del monedero" + }, + "web3ShimUsageNotification": { + "message": "Notamos que el sitio web actual intentó utilizar la API window.web3 eliminada. Si el sitio parece estar roto, haga clic en $1 para obtener más información.", + "description": "$1 is a clickable link." }, "welcome": { "message": "Bienvenido a MetaMask" @@ -973,6 +2102,16 @@ "welcomeBack": { "message": "¡Bienvenido de nuevo!" }, + "whatsThis": { + "message": "¿Qué es esto?" + }, + "writePhrase": { + "message": "Escriba esta frase en una hoja de papel y guárdela en un lugar seguro. Si desea aún más seguridad, anótelo en varias hojas de papel y guárdelas en 2 o 3 ubicaciones diferentes." + }, + "xOfY": { + "message": "$1 de $2", + "description": "$1 and $2 are intended to be two numbers, where $2 is a total, and $1 is a count towards that total" + }, "yesLetsTry": { "message": "Sí, probemos" }, diff --git a/app/_locales/es_419/messages.json b/app/_locales/es_419/messages.json index 1cf13ed44..1dccd990a 100644 --- a/app/_locales/es_419/messages.json +++ b/app/_locales/es_419/messages.json @@ -6,10 +6,18 @@ "message": "Versión, centro de soporte técnico e información de contacto" }, "acceleratingATransaction": { - "message": "* Aumentar una transacción utilizando un precio de gas más alto aumenta sus posibilidades de ser procesada más rápido por la red, pero esto no siempre está garantizado." + "message": "* Acelerar una transacción utilizando un precio de gas más alto aumenta sus posibilidades de ser procesada más rápido por la red, pero esto no siempre está garantizado." + }, + "acceptTermsOfUse": { + "message": "Leí y acepto $1", + "description": "$1 is the `terms` message" + }, + "accessAndSpendNotice": { + "message": "$1 puede acceder y gastar hasta este monto máximo", + "description": "$1 is the url of the site requesting ability to spend" }, "accessingYourCamera": { - "message": "Accediendo a la cámara…" + "message": "Accediendo a la cámara..." }, "account": { "message": "Cuenta" @@ -26,9 +34,18 @@ "accountSelectionRequired": { "message": "¡Tienes que seleccionar una cuenta!" }, + "active": { + "message": "Activo" + }, + "activity": { + "message": "Actividad" + }, "activityLog": { "message": "registro de actividad" }, + "addAccount": { + "message": "Agregar una cuenta" + }, "addAcquiredTokens": { "message": "Agrega los tokens adquiridos con MetaMask" }, @@ -36,7 +53,7 @@ "message": "Agregar alias" }, "addNetwork": { - "message": "Añadir red" + "message": "Agregar Red" }, "addRecipient": { "message": "Agregar destinatario" @@ -48,7 +65,7 @@ "message": "Agregar a la libreta de direcciones" }, "addToAddressBookModalPlaceholder": { - "message": "P. ej.: Juan García" + "message": "ej: Juan García" }, "addToken": { "message": "Agregar token" @@ -60,31 +77,92 @@ "message": "Avanzada" }, "advancedOptions": { - "message": "Opciones avanzadas" + "message": "Opciones Avanzadas" }, "advancedSettingsDescription": { - "message": "Accede a las funciones de desarrollador, descarga los registros de estado, restablece la cuenta, y configura las redes Testnet y el RPC personalizado" + "message": "Accede a las funciones de desarrollador, descarga los Registros de Estado, Restablece la Cuenta, y configura las redes de prueba y el RPC personalizado" + }, + "affirmAgree": { + "message": "Estoy de acuerdo" + }, + "aggregatorFeeCost": { + "message": "Tarifa de red del agregador" + }, + "alertDisableTooltip": { + "message": "Esto se puede cambiar en \"Configuración > Alertas\"" + }, + "alertSettingsUnconnectedAccount": { + "message": "Navegando un sitio web con una cuenta desconectada seleccionada" + }, + "alertSettingsUnconnectedAccountDescription": { + "message": "Esta alerta se muestra en un popup cuando está navegando un sitio Web3, pero la cuenta seleccionada actualmente no está conectada." + }, + "alertSettingsWeb3ShimUsage": { + "message": "Cuando un sitio intenta usar la window.web3 API eliminada" + }, + "alertSettingsWeb3ShimUsageDescription": { + "message": "Esta alerta se muestra en un popup cuando está navegando un sitio que intenta usar la window.web3 API eliminada y puede estar roto como resultado" + }, + "alerts": { + "message": "Alertas" + }, + "alertsSettingsDescription": { + "message": "Habilitar o deshabilitar cada alerta" + }, + "allowExternalExtensionTo": { + "message": "Habilitar esta extensión externa a:" + }, + "allowOriginSpendToken": { + "message": "¿Habilitar a $1 gastar sus $2?", + "description": "$1 is the url of the site and $2 is the symbol of the token they are requesting to spend" + }, + "allowThisSiteTo": { + "message": "Habilitar a este sitio a:" + }, + "allowWithdrawAndSpend": { + "message": "Habilitar a $1 retirar y gastar hasta el siguiente monto:", + "description": "The url of the site that requested permission to 'withdraw and spend'" }, "amount": { "message": "Monto" }, + "amountInEth": { + "message": "$1 ETH", + "description": "Displays an eth amount to the user. $1 is a decimal number" + }, + "amountWithColon": { + "message": "Monto:" + }, "appDescription": { - "message": "Una billetera de Ethereum en tu navegador", + "message": "Una Billetera de Ethereum en tu navegador", "description": "The description of the application" }, "appName": { "message": "MetaMask", "description": "The name of the application" }, + "approvalAndAggregatorTxFeeCost": { + "message": "Tarifa de la red de aprobación y agregación" + }, + "approvalTxGasCost": { + "message": "Aprobación del Costo del Gas para la Tx" + }, "approve": { "message": "Aprobar" }, + "approveSpendLimit": { + "message": "Aprobar $1", + "description": "The token symbol that is being approved" + }, "approved": { "message": "Aprobados" }, "asset": { "message": "Activo" }, + "assets": { + "message": "Activos" + }, "attemptToCancel": { "message": "¿Intentas cancelar?" }, @@ -92,11 +170,14 @@ "message": "Este intento no garantiza que se cancele tu transacción original. Si el intento de cancelación es exitoso, se te cobrará la tasa de transacción que se muestra arriba." }, "attemptingConnect": { - "message": "Tratar de conectarse a blockchain." + "message": "Tratando de conectar a la Blockchain." }, "attributions": { "message": "Atribuciones" }, + "authorizedPermissions": { + "message": "Has autorizado los siguientes permisos" + }, "autoLockTimeLimit": { "message": "Temporizador de cierre de sesión automático (minutos)" }, @@ -125,44 +206,53 @@ "message": "Saldo" }, "balanceOutdated": { - "message": "El saldo puede estar anticuado" + "message": "El saldo puede estar desactualizado" }, "basic": { "message": "Básicas" }, "blockExplorerUrl": { - "message": "Bloquear Explorer" + "message": "Explorador de Bloques" }, "blockExplorerView": { "message": "Ver cuenta en $1", "description": "$1 replaced by URL for custom block explorer" }, "blockiesIdenticon": { - "message": "Utilizar blockies identicon" + "message": "Utilizar Blockies Identicon" }, "browserNotSupported": { - "message": "Tu navegador no es compatible…" + "message": "Tu navegador no es compatible..." }, "builtInCalifornia": { "message": "MetaMask se diseñó y creó en California." }, + "buy": { + "message": "Comprar" + }, "buyWithWyre": { "message": "Comprar ETH con Wyre" }, "buyWithWyreDescription": { - "message": "Wyre te permite utilizar una tarjeta de crédito para depositar ETH directamente en su cuenta de MetaMask." + "message": "Wyre te permite utilizar una tarjeta de débito para depositar ETH directamente en su cuenta de MetaMask." + }, + "bytes": { + "message": "Bytes" + }, + "canToggleInSettings": { + "message": "Puede volver a habilitar esta notificación en Configuración -> Alertas." }, "cancel": { "message": "Cancelar" }, "cancellationGasFee": { - "message": "Tasa de cancelación de gas" + "message": "Tasa de Cancelación de Gas" }, "cancelled": { "message": "Cancelado" }, "chainId": { - "message": "ID de cadena" + "message": "ID de Cadena" }, "chromeRequiredForHardwareWallets": { "message": "Debes utilizar MetaMask en Google Chrome para poder conectarte a tu billetera de hardware." @@ -180,7 +270,7 @@ "message": "Confirmar contraseña" }, "confirmSecretBackupPhrase": { - "message": "Confirma tu frase de copia de seguridad secreta" + "message": "Confirma tu Frase de Respaldo Secreta" }, "confirmed": { "message": "Confirmado" @@ -191,26 +281,88 @@ "connect": { "message": "Conectar" }, + "connectAccountOrCreate": { + "message": "Conectar una cuenta o crear una nueva" + }, "connectHardwareWallet": { - "message": "Conectar billetera de hardware" + "message": "Conectar Billetera de Hardware" + }, + "connectManually": { + "message": "Conectar manualmente al sitio actual" + }, + "connectTo": { + "message": "Conectar a $1", + "description": "$1 is the name/origin of a web3 site/application that the user can connect to metamask" + }, + "connectToAll": { + "message": "Conectar a todos sus $1", + "description": "$1 will be replaced by the translation of connectToAllAccounts" + }, + "connectToAllAccounts": { + "message": "cuentas", + "description": "will replace $1 in connectToAll, completing the sentence 'connect to all of your accounts', will be text that shows list of accounts on hover" + }, + "connectToMultiple": { + "message": "Conectar a $1", + "description": "$1 will be replaced by the translation of connectToMultipleNumberOfAccounts" + }, + "connectToMultipleNumberOfAccounts": { + "message": "$1 cuentas", + "description": "$1 is the number of accounts to which the web3 site/application is asking to connect; this will substitute $1 in connectToMultiple" + }, + "connectWithMetaMask": { + "message": "Conectar Con MetaMask" + }, + "connectedAccountsDescriptionPlural": { + "message": "Tiene $1 cuentas conectadas con este sitio.", + "description": "$1 is the number of accounts" + }, + "connectedAccountsDescriptionSingular": { + "message": "Tiene 1 cuenta conectada con este sitio." + }, + "connectedAccountsEmptyDescription": { + "message": "MetaMask no está conectado a este sitio. Para conectarse a un sitio web3, busque el botón de conexión en su sitio." + }, + "connectedSites": { + "message": "Sitios conectados" + }, + "connectedSitesDescription": { + "message": "$1 está conectado a estos sitios. Ellos pueden ver la dirección de tu cuenta.", + "description": "$1 is the account name" + }, + "connectedSitesEmptyDescription": { + "message": "$1 no está conetado a ningún sitio.", + "description": "$1 is the account name" + }, + "connecting": { + "message": "Conectándose..." }, "connectingTo": { "message": "Conexión con $1" }, "connectingToGoerli": { - "message": "Conexión con la red de prueba Goerli" + "message": "Conectando con la red de prueba Goerli" }, "connectingToKovan": { - "message": "Conexión con la red de prueba Kovan" + "message": "Conectando con la red de prueba Kovan" }, "connectingToMainnet": { - "message": "Conexión con la red principal de Ethereum" + "message": "Conectando con la red principal de Ethereum (Main Net)" }, "connectingToRinkeby": { - "message": "Conexión con la red de prueba Rinkeby" + "message": "Conectando con la red de prueba Rinkeby" }, "connectingToRopsten": { - "message": "Conexión con la red de prueba Ropsten" + "message": "Conectando con la red de prueba Ropsten" + }, + "contactUs": { + "message": "Contacta con nosotros" + }, + "contacts": { + "message": "Contactos" + }, + "contactsSettingsDescription": { + "message": "Agregar, editar, eliminar y administrar contactos" }, "continueToWyre": { "message": "Continuar a Wyre" @@ -219,43 +371,49 @@ "message": "Despliegue de contratos" }, "contractInteraction": { - "message": "Interacción contractual" + "message": "Interacción con contrato" }, "copiedExclamation": { - "message": "Copiado" + "message": "¡Copiado!" }, "copiedTransactionId": { - "message": "Se ha copiado la ID de transacción" + "message": "Se ha copiado el ID de la transacción" }, "copyAddress": { "message": "Copiar la dirección al portapapeles" }, "copyPrivateKey": { - "message": "Esta es tu clave privada (haz clic para copiar)" + "message": "Ésta es tu clave privada (haz clic para copiar)" }, "copyToClipboard": { "message": "Copiar al portapapeles" }, "copyTransactionId": { - "message": "Copiar ID de transacción" + "message": "Copiar ID de la transacción" }, "create": { "message": "Crear" }, "createAWallet": { - "message": "Crear una billetera" + "message": "Crear una Billetera" }, "createAccount": { "message": "Crear cuenta" }, "createPassword": { - "message": "Crear contraseña" + "message": "Crear Contraseña" }, "currencyConversion": { - "message": "Conversión de moneda" + "message": "Conversión de Moneda" + }, + "currentAccountNotConnected": { + "message": "Tu cuenta actual no está conectada" + }, + "currentExtension": { + "message": "Página de la extensión actual" }, "currentLanguage": { - "message": "Idioma actual" + "message": "Idioma Actual" }, "customGas": { "message": "Personalizar gas" @@ -266,41 +424,85 @@ "customRPC": { "message": "RPC personalizado" }, + "customSpendLimit": { + "message": "Límite de Gasto Personalizado" + }, "customToken": { - "message": "Token personalizado" + "message": "Token Personalizado" + }, + "dataBackupFoundInfo": { + "message": "Se hizo una copia de seguridad de algunos de los datos de su cuenta durante una instalación anterior de MetaMask. Esto podría incluir su configuración, contactos y tokens. ¿Le gustaría restaurar estos datos ahora?" }, "decimal": { "message": "Decimales de precisión" }, "decimalsMustZerotoTen": { - "message": "Los decimales deben ser mayores a 0 y menores a 36." + "message": "Los decimales deben ser al menos 0 y no más de 36" + }, + "decrypt": { + "message": "Desencriptar" + }, + "decryptCopy": { + "message": "Copiar mensaje encriptado" + }, + "decryptInlineError": { + "message": "Este mensaje no puede ser desencriptado debido al error: $1", + "description": "$1 is error message" + }, + "decryptMessageNotice": { + "message": "$1 quiere leer este mensaje para completar su acción", + "description": "$1 is the web3 site name" + }, + "decryptMetamask": { + "message": "Desencriptar mensaje" + }, + "decryptRequest": { + "message": "Desencriptar petición" }, "defaultNetwork": { - "message": "La red predeterminada para las transacciones de Ethers es Main Net." + "message": "La red predeterminada para las transacciones de Ether es la red principal de Ethereum (Main Net)." }, "delete": { "message": "Borrar" }, "deleteAccount": { - "message": "Borrar cuenta" + "message": "Borrar Cuenta" }, "deleteNetwork": { - "message": "¿Eliminar red?" + "message": "¿Borrar Red?" }, "deleteNetworkDescription": { "message": "¿Estás seguro de que deseas borrar esta red?" }, "depositEther": { - "message": "Depositar Ethers" + "message": "Depositar Ether" }, "details": { "message": "Detalles" }, "directDepositEther": { - "message": "Depósito directo de Ethers" + "message": "Depósito directo de Ether" }, "directDepositEtherExplainer": { - "message": "Si ya tienes algunos Ethers, la forma más rápida de ingresarlos en tu nueva billetera es a través de un depósito directo." + "message": "Si ya tienes algunos Ether, la forma más rápida de ingresarlos en tu nueva billetera es a través de un depósito directo." + }, + "disconnect": { + "message": "Desconectar" + }, + "disconnectAllAccounts": { + "message": "Desconectar todas las cuentas" + }, + "disconnectAllAccountsConfirmationDescription": { + "message": "¿Seguro que quieres desconectarte? Puede perder la funcionalidad del sitio." + }, + "disconnectPrompt": { + "message": "Desconectar $1" + }, + "disconnectThisAccount": { + "message": "Desconectar esta cuenta" + }, + "dismiss": { + "message": "Descartar" }, "done": { "message": "Listo" @@ -308,11 +510,14 @@ "dontHaveAHardwareWallet": { "message": "¿No tienes una billetera de hardware?" }, + "dontShowThisAgain": { + "message": "No mostrar esto de nuevo" + }, "downloadGoogleChrome": { "message": "Descargar Google Chrome" }, "downloadSecretBackup": { - "message": "Descarga esta frase de copia de seguridad secreta y guárdala de forma segura en un disco duro externo cifrado o en algún medio de almacenamiento." + "message": "Descarga esta Frase de Respaldo Secreta y guárdala de forma segura en un disco duro externo encriptado o en algún medio de almacenamiento." }, "downloadStateLogs": { "message": "Descargar registros de estado" @@ -324,13 +529,23 @@ "message": "Editar" }, "editContact": { - "message": "Editar contacto" + "message": "Editar Contacto" + }, + "editPermission": { + "message": "Editar Permiso" + }, + "encryptionPublicKeyNotice": { + "message": "$1 desea su clave de encriptación pública. Al dar su consentimiento, este sitio podrá redactar mensajes encriptados para usted.", + "description": "$1 is the web3 site name" + }, + "encryptionPublicKeyRequest": { + "message": "Solicitar clave pública de encriptación" }, "endOfFlowMessage1": { - "message": "Pasaste la prueba. Es responsabilidad tuya mantener la frase de inicialización segura." + "message": "Pasaste la prueba. Es responsabilidad tuya mantener la frase semilla segura." }, "endOfFlowMessage10": { - "message": "Todo listo" + "message": "Todo Listo" }, "endOfFlowMessage2": { "message": "Consejos para almacenar de forma segura" @@ -342,20 +557,24 @@ "message": "Nunca compartas tu frase con nadie." }, "endOfFlowMessage5": { - "message": "¡Cuidado con las suplantaciones de identidad! MetaMask no te pedirá nunca tu frase de inicialización de forma espontánea." + "message": "¡Cuidado con las suplantaciones de identidad! MetaMask no te pedirá nunca tu frase semilla de forma espontánea." }, "endOfFlowMessage6": { - "message": "Si necesitas otra copia de seguridad de tu frase de inicialización, puedes encontrarla en Configuración -> Seguridad." + "message": "Si necesitas otro respaldo de tu frase semilla, puedes encontrarla en Configuración -> Seguridad." }, "endOfFlowMessage7": { "message": "Si tienes preguntas o ves algo sospechoso, envía un correo electrónico a support@metamask.io." }, "endOfFlowMessage8": { - "message": "MetaMask no puede recuperar tu frase de inicialización. Obtén más información." + "message": "MetaMask no puede recuperar tu frase semilla. Obtén más información." }, "endOfFlowMessage9": { "message": "Más información." }, + "endpointReturnedDifferentChainId": { + "message": "El endpoint devolvió un ID de cadena diferente: $1", + "description": "$1 is the return value of eth_chainId from an RPC endpoint" + }, "ensNotFoundOnCurrentNetwork": { "message": "No se pudo encontrar el nombre de ENS en la red actual. Intenta cambiar a la red principal de Ethereum." }, @@ -365,33 +584,94 @@ "enterAnAlias": { "message": "Ingresa un alias" }, + "enterMaxSpendLimit": { + "message": "Ingrese el Límite de Gasto Máximo" + }, "enterPassword": { "message": "Ingresa la contraseña" }, "enterPasswordContinue": { "message": "Ingresa tu contraseña para continuar" }, + "errorCode": { + "message": "Código: $1", + "description": "Displayed error code for debugging purposes. $1 is the error code" + }, + "errorDetails": { + "message": "Detalles del Error", + "description": "Title for collapsible section that displays error details for debugging purposes" + }, + "errorMessage": { + "message": "Mensaje: $1", + "description": "Displayed error message for debugging purposes. $1 is the error message" + }, + "errorName": { + "message": "Código: $1", + "description": "Displayed error name for debugging purposes. $1 is the error name" + }, + "errorPageMessage": { + "message": "Vuelva a intentarlo recargando la página o póngase en contacto con el soporte en support@metamask.io", + "description": "Message displayed on generic error page in the fullscreen or notification UI" + }, + "errorPagePopupMessage": { + "message": "Vuelva a intentarlo cerrando y volviendo a abrir la ventana emergente, o comuníquese con el soporte en support@metamask.io", + "description": "Message displayed on generic error page in the popup UI" + }, + "errorPageTitle": { + "message": "MetaMask encontró un error", + "description": "Title of generic error page" + }, + "errorStack": { + "message": "Pila:", + "description": "Title for error stack, which is displayed for debugging purposes" + }, "estimatedProcessingTimes": { - "message": "Tiempo estimado de procesamiento" + "message": "Tiempo Estimado de Procesamiento" + }, + "eth_accounts": { + "message": "Ver las direcciones de sus cuentas permitidas (obligatorio)", + "description": "The description for the `eth_accounts` permission" }, "ethereumPublicAddress": { - "message": "Dirección pública de Ethereum" + "message": "Dirección Pública de Ethereum" + }, + "etherscan": { + "message": "Etherscan" }, "etherscanView": { "message": "Ver cuenta en Etherscan" }, "expandView": { - "message": "Expandir vista" + "message": "Expandir Vista" }, "exportPrivateKey": { - "message": "Exportar clave privada" + "message": "Exportar Clave Privada" + }, + "externalExtension": { + "message": "Extensión Externa" + }, + "extraApprovalGas": { + "message": "+$1 gas de aprobación", + "description": "Expresses an additional gas amount the user will have to pay, on top of some other displayed amount. $1 is a decimal amount of gas" }, "failed": { "message": "Error" }, + "failedToFetchChainId": { + "message": "No se pudo obtener el ID de la cadena. ¿Es correcta su URL de RPC?" + }, + "failureMessage": { + "message": "Algo salió mal y no pudimos completar la acción" + }, "fast": { "message": "Rápido" }, + "fastest": { + "message": "Más rápido" + }, + "feeAssociatedRequest": { + "message": "Hay una tarifa asociada con esta solicitud." + }, "fiat": { "message": "Dinero fiduciario", "description": "Exchange type" @@ -400,44 +680,69 @@ "message": "¿No puedes importar archivos? ¡Haz clic aquí!", "description": "Helps user import their account from a JSON file" }, + "forbiddenIpfsGateway": { + "message": "Puerta de enlace IPFS prohibida: Por favor, especifique una puerta de enlace CID" + }, "forgetDevice": { "message": "Olvidar este dispositivo" }, "from": { - "message": "De" + "message": "De:" + }, + "fromAddress": { + "message": "Desde: $1", + "description": "$1 is the address to include in the From label. It is typically shortened first using shortenAddress" + }, + "functionApprove": { + "message": "Función: Aprobar" }, "functionType": { "message": "Tipo de función" }, "gasLimit": { - "message": "Limite de gas" + "message": "Límite de gas" }, "gasLimitInfoTooltipContent": { "message": "El límite de gas es la cantidad máxima de unidades de gas que estás dispuesto a gastar." }, "gasLimitTooLow": { - "message": "El límite de gas debe ser de al menos 21 000" + "message": "El límite de gas debe ser de al menos 21000" + }, + "gasLimitTooLowWithDynamicFee": { + "message": "El límite de gas debe ser de al menos $1", + "description": "$1 is the custom gas limit, in decimal." }, "gasPrice": { - "message": "Precio del gas (GWEI)" + "message": "Precio del Gas (GWEI)" }, "gasPriceExtremelyLow": { - "message": "El precio del gas es extremadamente bajo" + "message": "El Precio del Gas es extremadamente bajo" }, "gasPriceInfoTooltipContent": { - "message": "El precio del gas especifica la cantidad de Ethers que estás dispuesto a pagar por cada unidad de gas." + "message": "El precio del gas especifica la cantidad de Ether que está dispuesto a pagar por cada unidad de gas." }, "gasUsed": { "message": "Gas usado" }, + "gdprMessage": { + "message": "Estos datos son agregados y, por lo tanto, son anónimos a los efectos del Reglamento General de Protección de Datos (EU) 2016/679. Para obtener más información sobre nuestras prácticas de privacidad, consulte nuestro $1.", + "description": "$1 refers to the gdprMessagePrivacyPolicy message, the translation of which is meant to be used exclusively in the context of gdprMessage" + }, + "gdprMessagePrivacyPolicy": { + "message": "Política de privacidad aquí", + "description": "this translation is intended to be exclusively used as the replacement for the $1 in the gdprMessage translation" + }, + "general": { + "message": "General" + }, "generalSettingsDescription": { "message": "Conversión de moneda, moneda principal, idioma, blockies identicon" }, "getEther": { - "message": "Obtener Ethers" + "message": "Obtener Ether" }, "getEtherFromFaucet": { - "message": "Obtener Ethers a partir de un grifo para $1", + "message": "Obtener Ether a partir de un grifo para $1", "description": "Displays network name for Ether faucet" }, "getHelp": { @@ -452,6 +757,9 @@ "happyToSeeYou": { "message": "Estamos encantados de verte." }, + "hardware": { + "message": "Hardware" + }, "hardwareWalletConnected": { "message": "Billetera de hardware conectada" }, @@ -465,7 +773,7 @@ "message": "¿Problemas de conexión?" }, "here": { - "message": "aquí", + "message": "Aquí", "description": "as in -click here- for more information (goes with troubleTokenBalances)" }, "hexData": { @@ -477,6 +785,10 @@ "hideTokenPrompt": { "message": "¿Ocultar token?" }, + "hideTokenSymbol": { + "message": "Ocultar $1", + "description": "$1 is the symbol for a token (e.g. 'DAI')" + }, "history": { "message": "Historial" }, @@ -488,19 +800,19 @@ "message": "Importar cuenta" }, "importAccountMsg": { - "message": "Las cuentas importadas no estarán asociadas a la frase de inicialización que se creó en un principio para tu cuenta de MetaMask. Obtén más información sobre las cuentas importadas" + "message": "Las cuentas importadas no estarán asociadas a la frase semilla que se creó en un principio para tu cuenta de MetaMask. Obtén más información sobre las cuentas importadas " }, "importAccountSeedPhrase": { - "message": "Importar una cuenta con frase de inicialización" + "message": "Importar una cuenta con frase semilla" }, "importUsingSeed": { - "message": "Importar usando la frase de inicialización de la cuenta" + "message": "Importar usando la frase semilla de la cuenta" }, "importWallet": { "message": "Importar billetera" }, "importYourExisting": { - "message": "Importa tu billetera existente con una frase de inicialización de 12 palabras" + "message": "Importa tu billetera existente con una frase semilla de 12 palabras" }, "imported": { "message": "Importado", @@ -522,7 +834,7 @@ "message": "Tokens insuficientes." }, "invalidAddress": { - "message": "Dirección no válida" + "message": "Dirección inválida" }, "invalidAddressRecipient": { "message": "La dirección del destinatario no es válida" @@ -531,13 +843,48 @@ "message": "No existe la red ETH, utilice minúsculas" }, "invalidBlockExplorerURL": { - "message": "Block Explorer de URL no válido" + "message": "URL Inválida del Explorador de Bloques" + }, + "invalidCustomNetworkAlertContent1": { + "message": "El ID de la cadena para la red personalizada '$1' tiene que ser re-ingresada.", + "description": "$1 is the name/identifier of the network." + }, + "invalidCustomNetworkAlertContent2": { + "message": "Para protegerlo de proveedores de red maliciosos o con fallas, los IDs de cadenas son ahora requeridos para todas las redes personalizadas." + }, + "invalidCustomNetworkAlertContent3": { + "message": "Vaya a Configuración > Redes e ingrese el ID de la cadena. Puede obtener los IDs de las cadens más populares en $1.", + "description": "$1 is a link to https://chainid.network" + }, + "invalidCustomNetworkAlertTitle": { + "message": "Red Personalizada Inválida" + }, + "invalidHexNumber": { + "message": "Número hexadecimal inválido." + }, + "invalidHexNumberLeadingZeros": { + "message": "Número hexadecimal inválido. Elimine los ceros iniciales." + }, + "invalidIpfsGateway": { + "message": "Puerta de enlace IPFS inválida: El valor debe ser una URL válida" + }, + "invalidNumber": { + "message": "Número inválido. Ingrese un número decimal o un hexadecimal con prefijo '0x'." + }, + "invalidNumberLeadingZeros": { + "message": "Número inválido. Elimine los ceros iniciales." }, "invalidRPC": { - "message": "RPC de URL no válido" + "message": "URL del RPC inválida " }, "invalidSeedPhrase": { - "message": "Frase de inicialización no válida" + "message": "Frase semilla inválida." + }, + "ipfsGateway": { + "message": "Puerta de enlace IPFS" + }, + "ipfsGatewayDescription": { + "message": "Ingrese la URL de la puerta de enlace IPFS CID para usar resolución de contenido ENS." }, "jsonFile": { "message": "Archivo JSON", @@ -546,9 +893,15 @@ "knownAddressRecipient": { "message": "Dirección de contrato conocida." }, + "knownTokenWarning": { + "message": "Esta acción editará los tokens que ya están listados en su billetera, que se pueden usar para suplantarlo. Apruebe solo si está seguro de que quiere cambiar lo que representan estos tokens." + }, "kovan": { "message": "Red de prueba Kovan" }, + "lastConnected": { + "message": "Última vez Conectado" + }, "learnMore": { "message": "Más información" }, @@ -565,37 +918,89 @@ "message": "Enlaces" }, "loadMore": { - "message": "Cargar más" + "message": "Cargar Más" }, "loading": { "message": "Cargando..." }, "loadingTokens": { - "message": "Cargando tokens…" + "message": "Cargando tokens..." + }, + "localhost": { + "message": "Localhost 8545" }, "lock": { "message": "Cerrar sesión" }, + "lockTimeTooGreat": { + "message": "El tiempo para cerrar sesión es demasiado grande" + }, "mainnet": { - "message": "Red principal de Ethereum" + "message": "Red principal de Ethereum (Main Net)" }, "max": { "message": "Máx." }, + "memo": { + "message": "memo" + }, "memorizePhrase": { "message": "Memoriza esta frase." }, "message": { "message": "Mensaje" }, + "metaMaskConnectStatusParagraphOne": { + "message": "Ahora tienes más control sobre tus conexiones a la cuenta en MetaMask." + }, + "metaMaskConnectStatusParagraphThree": { + "message": "Clic para administrar tus cuentas conectadas." + }, + "metaMaskConnectStatusParagraphTwo": { + "message": "El botón de estado de conexión muestra si el sitio que está visitando se encuentra conectado a tu cuenta actualmente seleccionada." + }, "metamaskDescription": { "message": "Te estamos conectando a Ethereum y a la web descentralizada." }, + "metamaskSwapsOfflineDescription": { + "message": "Intercambios MetaMask está en mantenimiento. Por favor intente más tarde." + }, "metamaskVersion": { "message": "Versión de MetaMask" }, + "metametricsCommitmentsAllowOptOut": { + "message": "Siempre permitir optar por no participar a través de Configuración" + }, + "metametricsCommitmentsBoldNever": { + "message": "Nunca", + "description": "This string is localized separately from some of the commitments so that we can bold it" + }, + "metametricsCommitmentsIntro": { + "message": "MetaMask va a.." + }, + "metametricsCommitmentsNeverCollectIP": { + "message": "$1 recolecta tu dirección IP completa", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverCollectKeysEtc": { + "message": "$1 recolecta llaves, direcciones, transaccinoes, balances, hashes, o cualquier información personal", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverSellDataForProfit": { + "message": "$1 vende datos para lucrar. ¡Nunca!", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsSendAnonymizedEvents": { + "message": "Enviar eventos de vista de página y clics anónimos" + }, + "metametricsHelpImproveMetaMask": { + "message": "Ayúdanos a mejorar MetaMask" + }, + "metametricsOptInDescription": { + "message": "A MetaMask le gustaría recopilar datos de uso para entender mejor cómo interactúan nuestros usuarios con la extensión. Estos datos van a ser usados, de forma continua, para mejorar la usabilidad y experiencia de uso de nuestro producto y el ecosistema Ethereum." + }, "mobileSyncText": { - "message": "Ingresa tu contraseña para confirmar que eres tú." + "message": "Por favor, ingrese su contraseña ¡para confirmar que es usted!" }, "mustSelectOne": { "message": "Se debe seleccionar al menos 1 token." @@ -610,7 +1015,7 @@ "message": "Todas tus cuentas creadas en MetaMask se agregarán automáticamente a esta sección." }, "needEtherInWallet": { - "message": "Necesitarás tener Ethers en tu billetera para poder interactuar con aplicaciones descentralizadas a través de MetaMask." + "message": "Necesitarás tener Ether en tu billetera para poder interactuar con aplicaciones descentralizadas a través de MetaMask." }, "needImportFile": { "message": "Selecciona un archivo para importar.", @@ -622,8 +1027,11 @@ "networkName": { "message": "Nombre de la red" }, + "networkSettingsChainIdDescription": { + "message": "El ID de la cadena es utilizado para firmar transacciones. Debe coincidir con el ID de la cadena devuelto por la red. Puede ingresar un número decimal o hexadecimal con prefijo '0x', pero se mostrará el número en decimal." + }, "networkSettingsDescription": { - "message": "Agregar y editar redes RPC personalizadas" + "message": "Agregue y edite redes RPC personalizadas" }, "networks": { "message": "Redes" @@ -642,13 +1050,13 @@ "description": "Default name of next account to be created on create account screen" }, "newContact": { - "message": "Nuevo contacto" + "message": "Nuevo Contacto" }, "newContract": { "message": "Nuevo contrato" }, "newNetwork": { - "message": "Nueva red" + "message": "Nueva Red" }, "newPassword": { "message": "Nueva contraseña (mín. 8 caracteres)" @@ -660,19 +1068,29 @@ "message": "Nuevo total" }, "newTransactionFee": { - "message": "Nueva tasa de transacción" + "message": "Nueva Comisión por transacción" }, "next": { "message": "Siguiente" }, + "nextNonceWarning": { + "message": "El nonce es más alto que el sugerido de $1", + "description": "The next nonce according to MetaMask's internal logic" + }, + "noAccountsFound": { + "message": "No se encontraron cuentas para su búsqueda" + }, "noAddressForName": { "message": "No se ha establecido ninguna dirección para este nombre." }, "noAlreadyHaveSeed": { - "message": "No, ya tengo una frase de inicialización" + "message": "No, ya tengo una frase semilla" }, "noConversionRateAvailable": { - "message": "No hay ninguna tasa de conversión disponible" + "message": "No hay ninguna Tasa de Conversión Disponible" + }, + "noThanks": { + "message": "No Gracias" }, "noTransactions": { "message": "No tienes transacciones" @@ -683,6 +1101,18 @@ "noWebcamFoundTitle": { "message": "No se encuentra la cámara web" }, + "nonceField": { + "message": "Personalizar el nonce de la transacción" + }, + "nonceFieldDescription": { + "message": "Habilite esto para cambiar el nonce (número de transacción) en las pantallas de confirmación. Esto es una funcionalidad avanzada, úsela con precaución." + }, + "nonceFieldHeading": { + "message": "Nonce Personalizado" + }, + "notCurrentAccount": { + "message": "¿Es esta la cuenta correcta? Es diferente de la cuenta actualmente seleccionada en su billetera" + }, "notEnoughGas": { "message": "No tienes suficiente gas" }, @@ -692,14 +1122,30 @@ "off": { "message": "Desactivado" }, + "offlineForMaintenance": { + "message": "Fuera de línea por mantenimiento" + }, "ok": { "message": "Aceptar" }, "on": { - "message": "Activada" + "message": "Activado" + }, + "onboardingReturnNotice": { + "message": "\"$1\" cerrará esta pestaña y volverá directamente a $2", + "description": "Return the user to the site that initiated onboarding" + }, + "onlyAddTrustedNetworks": { + "message": "Un proveedor de red de Ethereum malintencionado puede mentir sobre el estado de la cadena de bloques y registrar la actividad de su red. Solo agregue redes personalizadas en las que confíe." + }, + "onlyAvailableOnMainnet": { + "message": "Solo disponible en la red principal de Ethereum (Main Net)" + }, + "onlyConnectTrust": { + "message": "Conéctese solo con sitios en los que confíe." }, "optionalBlockExplorerUrl": { - "message": "Bloquear la URL de Explorer (opcional)" + "message": "URL del Explorador de bloques (opcional)" }, "optionalCurrencySymbol": { "message": "Símbolo (opcional)" @@ -729,15 +1175,28 @@ "message": "Las contraseñas no coinciden" }, "pastePrivateKey": { - "message": "Copia y pega tu cadena de claves privada aquí:", + "message": "Copia y pega tu clave privada aquí:", "description": "For importing an account from a private key" }, "pending": { "message": "pendiente" }, + "permissionCheckedIconDescription": { + "message": "Has aprobado este permiso" + }, + "permissionUncheckedIconDescription": { + "message": "No has aprobado este permiso" + }, + "permissions": { + "message": "Permisos" + }, "personalAddressDetected": { "message": "Dirección personal detectada. Ingresa la dirección de contrato del token." }, + "plusXMore": { + "message": "+ $1 más", + "description": "$1 is a number of additional but unshown items in a list- this message will be shown in place of those items" + }, "prev": { "message": "Ant" }, @@ -745,7 +1204,7 @@ "message": "Moneda principal" }, "primaryCurrencySettingDescription": { - "message": "Selecciona \"moneda nativa\" para que se muestren primero los valores en la moneda nativa de la cadena (p. ej., ETH). Selecciona \"dinero fiduciario\" para que se muestren primero los valores en la moneda fiduciaria que seleccionaste." + "message": "Selecciona \"moneda nativa\" para que se muestren primero los valores en la moneda nativa de la cadena (p. ej., ETH). Selecciona \"dinero fiduciario\" para que se muestren primero los valores en la moneda fiduciaria que seleccionaste." }, "privacyMsg": { "message": "Política de privacidad" @@ -760,23 +1219,35 @@ "privateNetwork": { "message": "Red privada" }, + "proposedApprovalLimit": { + "message": "Límite de aprobación propuesto" + }, "protectYourKeys": { "message": "¡Protege tus claves!" }, "protectYourKeysMessage1": { - "message": "Ten cuidado con tu frase de inicialización: hay informes sobre sitios web que intentan hacerse pasar por MetaMask. ¡MetaMask no te pedirá nunca tu frase de inicialización!" + "message": "Ten cuidado con tu frase semilla — hay informes sobre sitios web que intentan hacerse pasar por MetaMask. ¡MetaMask no te pedirá nunca tu frase semilla!" }, "protectYourKeysMessage2": { "message": "Mantén tu frase segura. Si notas algo raro o si no está seguro sobre si usar algún sitio web en específico, envíanos un correo electrónico a support@metamask.io" }, + "provide": { + "message": "Proveer" + }, "queue": { "message": "Cola" }, + "queued": { + "message": "Encolado" + }, "readdToken": { "message": "Puedes volver a agregar este token a través de la opción \"Agregar token\" en el menú de opciones de tus cuentas." }, "readyToConnect": { - "message": "¿Listo para conectarte?" + "message": "¿Listo/a para conectarte?" + }, + "receive": { + "message": "Recibir" }, "recents": { "message": "Recientes" @@ -806,13 +1277,13 @@ "message": "Recordármelo más tarde" }, "remove": { - "message": "Quitar" + "message": "Eliminar" }, "removeAccount": { "message": "Eliminar cuenta" }, "removeAccountDescription": { - "message": "Esta cuenta se eliminará de tu billetera. Asegúrate de tener la frase de inicialización original o clave privada de esta cuenta importada para poder continuar. Puedes volver a importar o crear cuentas desde el menú desplegable de la cuenta." + "message": "Esta cuenta se eliminará de tu billetera. Asegúrate de tener la frase semilla original o clave privada de esta cuenta importada para poder continuar. Puedes volver a importar o crear cuentas desde el menú desplegable de la cuenta." }, "requestsAwaitingAcknowledgement": { "message": "solicitudes pendientes de reconocimiento" @@ -833,25 +1304,35 @@ "message": "Restaurar" }, "restoreAccountWithSeed": { - "message": "Restaura tu cuenta con la frase de inicialización" + "message": "Restaura tu Cuenta con la Frase Semilla" }, "restoreFromSeed": { "message": "¿Restaurar cuenta?" }, + "restoreWalletPreferences": { + "message": "Se ha encontrado una copia de seguridad de sus datos de $1. ¿Le gustaría restaurar sus preferencias de billetera?", + "description": "$1 is the date at which the data was backed up" + }, + "retryTransaction": { + "message": "Reintentar Transacción" + }, + "reusedTokenNameWarning": { + "message": "Un token aquí reutiliza un símbolo de otro token que está observando, esto puede ser confuso o engañoso." + }, "revealSeedWords": { - "message": "Mostrar las palabras de inicialización" + "message": "Mostrar la Frase Semilla" }, "revealSeedWordsDescription": { - "message": "Si cambias de navegador o computadora, necesitarás esta frase de inicialización para acceder a tus cuentas. Guárdalas en un lugar seguro y secreto." + "message": "Si cambias de navegador o computadora, necesitarás esta frase semilla para acceder a tus cuentas. Guárdalas en un lugar seguro y secreto." }, "revealSeedWordsTitle": { - "message": "Frase de inicialización" + "message": "Frase Semilla" }, "revealSeedWordsWarning": { - "message": "Alguien podría utilizar estas palabras para robar todas tus cuentas." + "message": "¡No recuperes tu semilla en un lugar público! Alguien podría utilizar estas palabras para robar todas tus cuentas." }, "revealSeedWordsWarningTitle": { - "message": "¡No comparta esta frase con nadie!" + "message": "¡NO comparta esta frase con nadie!" }, "rinkeby": { "message": "Red de prueba Rinkeby" @@ -874,23 +1355,29 @@ "scanQrCode": { "message": "Escanear el código QR" }, + "scrollDown": { + "message": "Desplazarse hacia abajo" + }, "search": { "message": "Buscar" }, + "searchAccounts": { + "message": "Buscar Cuentas" + }, "searchResults": { - "message": "Resultados de la búsqueda" + "message": "Resultados de la Búsqueda" }, "searchTokens": { - "message": "Buscar tokens" + "message": "Buscar Tokens" }, "secretBackupPhrase": { - "message": "Frase de copia de seguridad secreta" + "message": "Frase de Respaldo Secreta" }, "secretBackupPhraseDescription": { - "message": "Tu frase de copia de seguridad secreta facilita que se pueda respaldar y restaurar tu cuenta." + "message": "Tu frase de respaldo secreta facilita que se pueda respaldar y restaurar tu cuenta." }, "secretBackupPhraseWarning": { - "message": "ADVERTENCIA: Nunca reveles tu frase de copia de seguridad. Cualquier persona que tenga acceso a esta frase puede llevarse tus Ethers permanentemente." + "message": "ADVERTENCIA: Nunca reveles tu frase de respaldo. Cualquier persona que tenga acceso a esta frase puede llevarse tus Ether permanentemente." }, "secretPhrase": { "message": "Ingresa tu frase secreta de doce palabras para restaurar tu almacén." @@ -899,41 +1386,47 @@ "message": "Seguridad y privacidad" }, "securitySettingsDescription": { - "message": "Configuración de privacidad y frase de inicialización de la billetera" + "message": "Configuración de privacidad y frase semilla de la billetera" }, "seedPhrasePlaceholder": { "message": "Separa cada palabra con un solo espacio" }, + "seedPhrasePlaceholderPaste": { + "message": "Pegar la frase semilla del portapapeles" + }, "seedPhraseReq": { - "message": "Las frases de inicialización tienen una longitud de 12 palabras" + "message": "Las frases de inicialización tienen una longitud de 12 palabras" }, "selectAHigherGasFee": { "message": "Selecciona una tasa de gas más alta para acelerar el procesamiento de tu transacción.*" }, + "selectAccounts": { + "message": "Seleccionar cuenta(s)" + }, + "selectAll": { + "message": "Seleccionar todo" + }, "selectAnAccount": { - "message": "Selecciona una cuenta" + "message": "Selecciona una Cuenta" }, "selectAnAccountHelp": { "message": "Selecciona la cuenta que deseas ver en MetaMask" }, - "selectCurrency": { - "message": "Seleccionar moneda" - }, "selectEachPhrase": { "message": "Selecciona todas las frases para asegurarte de que son correctas." }, "selectHdPath": { "message": "Selecciona la ruta HD" }, - "selectLocale": { - "message": "Selecciona la configuración regional" - }, "selectPathHelp": { "message": "Si no ves tus cuentas existentes de Ledger más abajo, intenta cambiar la ruta a \"Legacy (MEW / MyCrypto)\"" }, "selectType": { "message": "Seleccionar tipo" }, + "selectingAllWillAllow": { + "message": "Seleccionar todo permitirá que este sitio vea todas sus cuentas actuales. Asegúrate de confiar en este sitio." + }, "send": { "message": "Enviar" }, @@ -943,11 +1436,15 @@ "sendETH": { "message": "Enviar ETH" }, + "sendSpecifiedTokens": { + "message": "Enviar $1", + "description": "Symbol of the specified token" + }, "sendTokens": { "message": "Enviar tokens" }, "sentEther": { - "message": "Ethers enviados" + "message": "Ether enviado" }, "separateEachWord": { "message": "Separa cada palabra con un solo espacio" @@ -962,10 +1459,10 @@ "message": "Selecciona esto para mostrar el precio del gas y limitar los controles directamente en las pantallas de envío y confirmación." }, "showFiatConversionInTestnets": { - "message": "Mostrar conversión en redes Testnet" + "message": "Mostrar conversión en redes de prueba" }, "showFiatConversionInTestnetsDescription": { - "message": "Selecciona esto para mostrar la conversión de dinero fiduciario en redes Testnet" + "message": "Selecciona esto para mostrar la conversión de dinero fiduciario en redes de prueba" }, "showHexData": { "message": "Mostrar datos hexadecimales" @@ -973,9 +1470,21 @@ "showHexDataDescription": { "message": "Selecciona esto para mostrar el campo de datos hexadecimales en la pantalla de envío" }, + "showIncomingTransactions": { + "message": "Mostrar transacciones entrantes" + }, + "showIncomingTransactionsDescription": { + "message": "Seleccione esto para usar Etherscan para mostrar las transacciones entrantes en la lista de transacciones" + }, + "showPermissions": { + "message": "Mostrar permisos" + }, "showPrivateKeys": { "message": "Mostrar claves privadas" }, + "showSeedPhrase": { + "message": "Mostrar frase semilla" + }, "sigRequest": { "message": "Solicitud de firma" }, @@ -988,6 +1497,9 @@ "signatureRequest": { "message": "Solicitud de firma" }, + "signatureRequest1": { + "message": "Mensaje" + }, "signed": { "message": "Firmado" }, @@ -1006,15 +1518,43 @@ "speedUpTransaction": { "message": "Acelerar esta transacción" }, + "spendLimitAmount": { + "message": "Monto límite de gasto" + }, + "spendLimitInsufficient": { + "message": "Límite de gasto insuficiente" + }, + "spendLimitInvalid": { + "message": "Límite de gasto inválido, debe ser un número positivo" + }, + "spendLimitPermission": { + "message": "Permiso de límite de gasto" + }, + "spendLimitRequestedBy": { + "message": "Límite de gasto solicitado por $1", + "description": "Origin of the site requesting the spend limit" + }, + "spendLimitTooLarge": { + "message": "Límite de gasto demasiado grande" + }, "stateLogError": { "message": "Error al recuperar los registros de estado." }, + "stateLogFileName": { + "message": "Registros de Estado MetaMask" + }, "stateLogs": { - "message": "Registros de estado" + "message": "Registros de Estado" }, "stateLogsDescription": { "message": "Los registros de estado contienen las direcciones de sus cuentas públicas y transacciones enviadas." }, + "statusConnected": { + "message": "Conectado" + }, + "statusNotConnected": { + "message": "No conectado" + }, "step1HardwareWallet": { "message": "1. Conecta la billetera de hardware" }, @@ -1036,14 +1576,297 @@ "storePhrase": { "message": "Almacena esta frase en un administrador de contraseñas como 1Password." }, + "submit": { + "message": "Enviar" + }, "submitted": { "message": "Enviado" }, "supportCenter": { "message": "Visita nuestro Centro de soporte técnico" }, + "swap": { + "message": "Intercambiar" + }, + "swapAdvancedSlippageInfo": { + "message": "Si el precio cambia entre el momento en que se realiza el pedido y el momento en que se confirma, se denomina \"deslizamiento\". Su intercambio se cancelará automáticamente si el deslizamiento excede su configuración de \"deslizamiento máximo\"." + }, + "swapAggregator": { + "message": "Agregador" + }, + "swapAmountReceived": { + "message": "Cantidad garantizada" + }, + "swapAmountReceivedInfo": { + "message": "Esta es la cantidad mínima que recibirá. Puede recibir más dependiendo del deslizamiento." + }, + "swapApproval": { + "message": "Aprobar $1 para intercambios", + "description": "Used in the transaction display list to describe a transaction that is an approve call on a token that is to be swapped.. $1 is the symbol of a token that has been approved." + }, + "swapApproveNeedMoreTokens": { + "message": "Necesita $1 más de $2 para completar este intercambio", + "description": "Tells the user how many more of a given token they need for a specific swap. $1 is an amount of tokens and $2 is the token symbol." + }, + "swapBetterQuoteAvailable": { + "message": "Hay una mejor cotización disponible" + }, + "swapBuildQuotePlaceHolderText": { + "message": "No hay tokens disponibles que coincidan con $1", + "description": "Tells the user that a given search string does not match any tokens in our token lists. $1 can be any string of text" + }, + "swapCheckingQuote": { + "message": "Comprobando $1", + "description": "Shown to the user during quote loading. $1 is the name of an aggregator. The message indicates that metamask is currently checking if that aggregator has a trade/quote for their requested swap." + }, + "swapCustom": { + "message": "personalizado" + }, + "swapDecentralizedExchange": { + "message": "Exchange descentralizado" + }, + "swapEditLimit": { + "message": "Editar límite" + }, + "swapEnableDescription": { + "message": "Esto es obligatorio y le da permiso a MetaMask para intercambiar su $1.", + "description": "Gives the user info about the required approval transaction for swaps. $1 will be the symbol of a token being approved for swaps." + }, + "swapEstimatedNetworkFee": { + "message": "Tarifa de red estimada" + }, + "swapEstimatedNetworkFeeSummary": { + "message": "La “$1“ es lo que esperamos que sea la tarifa real. La cantidad exacta depende de las condiciones de la red.", + "description": "$1 will be the translation of swapEstimatedNetworkFee, with the font bolded" + }, + "swapEstimatedNetworkFees": { + "message": "Tarifas de red estimadas" + }, + "swapEstimatedNetworkFeesInfo": { + "message": "Esta es una estimación de la tarifa de red que se utilizará para completar su intercambio. La cantidad real puede cambiar según las condiciones de la red." + }, + "swapFailedErrorTitle": { + "message": "Intercambio fallido" + }, + "swapFetchingQuotesErrorDescription": { + "message": "Hmmm... algo salió mal. Vuelva a intentarlo o, si los errores persisten, póngase en contacto con el servicio de atención al cliente." + }, + "swapFetchingQuotesErrorTitle": { + "message": "Error al obtener cotizaciones" + }, + "swapFetchingTokens": { + "message": "Obteniendo tokens..." + }, + "swapFinalizing": { + "message": "Finalizando..." + }, + "swapHighSlippageWarning": { + "message": "La cantidad de deslizamiento es muy alta. ¡Asegúrate de saber lo que estás haciendo!" + }, + "swapIntroLearnMoreHeader": { + "message": "¿Quiere aprender más?" + }, + "swapIntroLearnMoreLink": { + "message": "Más información sobre los Intercambios MetaMask" + }, + "swapIntroLiquiditySourcesLabel": { + "message": "Las fuentes de liquidez incluyen:" + }, + "swapIntroPopupSubTitle": { + "message": "Ahora puede intercambiar tokens directamente en su billetera MetaMask. Intercambios MetaMask combina múltiples agregadores de intercambio descentralizados, creadores de mercado profesionales y DEX individuales para garantizar que los usuarios de MetaMask siempre obtengan el mejor precio con las tarifas de red más bajas." + }, + "swapIntroPopupTitle": { + "message": "¡El intercambio de tokens está aquí!" + }, + "swapLearnMoreContractsAuditReview": { + "message": "Revise nuestra auditoría de contratos oficiales" + }, + "swapLowSlippageError": { + "message": "La transacción puede fallar, el deslizamiento máximo es demasiado bajo." + }, + "swapMaxNetworkFeeInfo": { + "message": "“$1” es lo máximo que gastará. Cuando la red es volátil, esto puede ser una gran cantidad.", + "description": "$1 will be the translation of swapMaxNetworkFees, with the font bolded" + }, + "swapMaxNetworkFees": { + "message": "Tarifa de red máxima" + }, + "swapMaxSlippage": { + "message": "Deslizamiento máximo" + }, + "swapMetaMaskFee": { + "message": "Tarifa de MetaMask" + }, + "swapMetaMaskFeeDescription": { + "message": "Siempre encontramos el mejor precio de las principales fuentes de liquidez. Una tarifa de $1% se incluye automáticamente en cada cotización, lo que respalda el desarrollo continuo para hacer que MetaMask sea aún mejor.", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapNQuotes": { + "message": "$1 cotizaciones", + "description": "$1 is the number of quotes that the user can select from when opening the list of quotes on the 'view quote' screen" + }, + "swapNetworkFeeSummary": { + "message": "La tarifa de la red cubre el costo de procesar su intercambio y almacenarlo en la red Ethereum. MetaMask no se beneficia de esta tarifa." + }, + "swapNewQuoteIn": { + "message": "Nuevas cotizaciones en $1", + "description": "Tells the user the amount of time until the currently displayed quotes are update. $1 is a time that is counting down from 1:00 to 0:00" + }, + "swapOnceTransactionHasProcess": { + "message": "Su $1 se agregará a su cuenta una vez que se haya procesado esta transacción.", + "description": "This message communicates the token that is being transferred. It is shown on the awaiting swap screen. The $1 will be a token symbol." + }, + "swapPriceDifference": { + "message": "Está poor interccambiar $1 $2 (~$3) por $4 $5 (~$6).", + "description": "This message represents the price slippage for the swap. $1 and $4 are a number (ex: 2.89), $2 and $5 are symbols (ex: ETH), and $3 and $6 are fiat currency amounts." + }, + "swapPriceDifferenceTitle": { + "message": "Diferencia de precio de ~$1%", + "description": "$1 is a number (ex: 1.23) that represents the price difference." + }, + "swapPriceDifferenceTooltip": { + "message": "La diferencia en los precios de mercado puede verse afectada por las tarifas cobradas por los intermediarios, el tamaño del mercado, el tamaño del comercio o las ineficiencias del mercado." + }, + "swapPriceDifferenceUnavailable": { + "message": "El precio de mercado no está disponible. Asegúrese de sentirse cómodo con el monto devuelto antes de continuar." + }, + "swapProcessing": { + "message": "Procesando" + }, + "swapQuoteDetails": { + "message": "Detalles de cotización" + }, + "swapQuoteDetailsSlippageInfo": { + "message": "Si el precio cambia entre el momento en que se realiza el pedido y se confirma, se denomina \"deslizamiento\". Su intercambio se cancelará automáticamente si el deslizamiento excede su configuración de \"tolerancia de deslizamiento\"." + }, + "swapQuoteIncludesRate": { + "message": "La cotización incluye una tarifa de MetaMask de $1%", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapQuoteNofN": { + "message": "Cotización $1 de $2", + "description": "A count of loaded quotes shown to the user while they are waiting for quotes to be fetched. $1 is the number of quotes already loaded, and $2 is the total number of quotes to load." + }, + "swapQuoteSource": { + "message": "Fuente de cotización" + }, + "swapQuotesAreRefreshed": { + "message": "Las cotizaciones se actualizan a menudo para reflejar las condiciones actuales del mercado." + }, + "swapQuotesExpiredErrorDescription": { + "message": "Solicite nuevas cotizaciones para obtener las últimas tarifas." + }, + "swapQuotesExpiredErrorTitle": { + "message": "El tiempo de espera caducó obteniendo cotizaciones" + }, + "swapQuotesNotAvailableErrorDescription": { + "message": "Intente ajustar la configuración de cantidad o deslizamiento y vuelva a intentarlo." + }, + "swapQuotesNotAvailableErrorTitle": { + "message": "No hay cotizaciones disponibles" + }, + "swapRate": { + "message": "Tasa de intercambio" + }, + "swapReceiving": { + "message": "Recibiendo" + }, + "swapReceivingInfoTooltip": { + "message": "Esta es una estimación. La cantidad exacta depende del deslizamiento." + }, + "swapRequestForQuotation": { + "message": "Solicitud de presupuesto" + }, + "swapSearchForAToken": { + "message": "Buscar un token" + }, + "swapSelect": { + "message": "Seleccionar" + }, + "swapSelectAQuote": { + "message": "Seleccionar una cotización" + }, + "swapSelectAToken": { + "message": "Seleccionar un token" + }, + "swapSelectQuotePopoverDescription": { + "message": "A continuación se muestran todas las cotizaciones recopiladas de múltiples fuentes de liquidez." + }, + "swapSlippageTooLow": { + "message": "El deslizamiento debe ser mayor que cero" + }, + "swapSource": { + "message": "Fuente de liquidez" + }, + "swapSourceInfo": { + "message": "Buscamos múltiples fuentes de liquidez (exchanges, agregadores y creadores de mercado profesionales) para encontrar las mejores tarifas y las tarifas de red más bajas." + }, + "swapStartSwapping": { + "message": "Comenzar intercambio" + }, + "swapSwapFrom": { + "message": "Intercambiar desde" + }, + "swapSwapSwitch": { + "message": "Intercambiar de y a tokens" + }, + "swapSwapTo": { + "message": "Intercambiar a" + }, + "swapThisWillAllowApprove": { + "message": "Esto permitirá que se intercambie $1." + }, + "swapTokenAvailable": { + "message": "Su $1 se ha agregado a su cuenta.", + "description": "This message is shown after a swap is successful and communicates the exact amount of tokens the user has received for a swap. The $1 is a decimal number of tokens followed by the token symbol." + }, + "swapTokenToToken": { + "message": "Intercambiar $1 a $2", + "description": "Used in the transaction display list to describe a swap. $1 and $2 are the symbols of tokens in involved in a swap." + }, + "swapTransactionComplete": { + "message": "Transacción completada" + }, + "swapUnknown": { + "message": "Desconocido" + }, + "swapUsingBestQuote": { + "message": "Utilizando la mejor cotización" + }, + "swapVerifyTokenExplanation": { + "message": "Varios tokens pueden usar el mismo nombre y símbolo. Verifique Etherscan para verificar que este es el token que está buscando." + }, + "swapViewToken": { + "message": "Ver $1" + }, + "swapYourTokenBalance": { + "message": "$1 $2 están disponibles para intercambiar", + "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" + }, + "swapZeroSlippage": { + "message": "Deslizamiento 0%" + }, + "swapsAdvancedOptions": { + "message": "Opciones Avanzadas" + }, + "swapsExcessiveSlippageWarning": { + "message": "La cantidad de deslizamiento es demasiado alta y resultará en una mala tasa. Reduzca su tolerancia al deslizamiento a un valor inferior al 15%." + }, + "swapsMaxSlippage": { + "message": "Tolerancia al Deslizamiento" + }, + "swapsNotEnoughForTx": { + "message": "No hay suficiente $1 para completar esta transacción", + "description": "Tells the user that they don't have enough of a token for a proposed swap. $1 is a token symbol" + }, + "swapsViewInActivity": { + "message": "Ver en actividad" + }, "switchNetworks": { - "message": "Cambiar redes" + "message": "Cambiar de Red" + }, + "switchToThisAccount": { + "message": "Cambiar a esta cuenta" }, "symbol": { "message": "Símbolo" @@ -1072,14 +1895,26 @@ "syncWithMobileTitle": { "message": "Sincronizar con un dispositivo móvil" }, + "syncWithThreeBox": { + "message": "Sincronizar datos con 3Box (experimental)" + }, + "syncWithThreeBoxDescription": { + "message": "Actívelo para hacer una copia de seguridad de su configuración con 3Box. Esta característica es actualmente experimental, úselo bajo su propio riesgo." + }, + "syncWithThreeBoxDisabled": { + "message": "3Box se ha desactivado debido a un error durante la sincronización inicial" + }, "terms": { "message": "Condiciones de uso" }, + "termsOfService": { + "message": "Términos del Servicio" + }, "testFaucet": { "message": "Grifo de prueba" }, "thisWillCreate": { - "message": "Esto creará una billetera y una frase de inicialización nuevas" + "message": "Esto creará una billetera y una frase semilla nuevas" }, "tips": { "message": "Consejos" @@ -1087,15 +1922,31 @@ "to": { "message": "A" }, + "toAddress": { + "message": "A: $1", + "description": "$1 is the address to include in the To label. It is typically shortened first using shortenAddress" + }, + "toWithColon": { + "message": "A:" + }, + "token": { + "message": "Token" + }, "tokenAlreadyAdded": { "message": "El token ya se ha agregado." }, "tokenContractAddress": { "message": "Dirección de contrato del token" }, + "tokenOptions": { + "message": "Opciones del Token" + }, "tokenSymbol": { "message": "Símbolo del token" }, + "total": { + "message": "Total" + }, "transaction": { "message": "transacción" }, @@ -1118,7 +1969,7 @@ "message": "Error de transacción. Se dio una excepción en el código de contrato." }, "transactionErrorNoContract": { - "message": "Se está intentando llamar una función en una dirección no contractual." + "message": "Se está intentando llamar una función en una dirección no es del contrato." }, "transactionErrored": { "message": "Error en la transacción." @@ -1142,12 +1993,20 @@ "message": "Transferir entre mis cuentas" }, "transferFrom": { - "message": "Transferir desde" + "message": "Transferir Desde" + }, + "troubleConnectingToWallet": { + "message": "Tuvimos problemas para conectarnos con su $1, intente revisar $2 y vuelva a intentarlo.", + "description": "$1 is the wallet device name; $2 is a link to wallet connection guide" }, "troubleTokenBalances": { - "message": "Hubo un problema al cargar tus saldos de tokens. Puedes verlos", + "message": "Hubo un problema al cargar tus saldos de tokens. Puedes verlos ", "description": "Followed by a link (here) to view token balances" }, + "trustSiteApprovePermission": { + "message": "¿Confías en este sitio? Al otorgar este permiso, permite que $1 retire sus $2 y automatice las transacciones por usted.", + "description": "$1 is the url requesting permission and $2 is the symbol of the currency that the request is for" + }, "tryAgain": { "message": "Reintentar" }, @@ -1161,13 +2020,13 @@ "message": "unidades" }, "unknown": { - "message": "Desconocido" + "message": "Desconocido/a" }, "unknownCameraError": { - "message": "Hubo un error al intentar acceder a tu cámara. Vuelve a intentarlo…" + "message": "Hubo un error al intentar acceder a tu cámara. Vuelve a intentarlo..." }, "unknownCameraErrorTitle": { - "message": "¡Vaya! Se produjo un error…" + "message": "¡Vaya! Se produjo un error..." }, "unknownNetwork": { "message": "Red privada desconocida" @@ -1175,6 +2034,9 @@ "unknownQrCode": { "message": "Error: No se pudo identificar el código QR" }, + "unlimited": { + "message": "Ilimitado" + }, "unlock": { "message": "Desbloquear" }, @@ -1187,17 +2049,30 @@ "urlErrorMsg": { "message": "Los URI deben tener el prefijo HTTP/HTTPS apropiado." }, + "urlExistsErrorMsg": { + "message": "La URL ya está presente en la lista existente de redes" + }, + "usePhishingDetection": { + "message": "Usar la detección de phishing" + }, + "usePhishingDetectionDescription": { + "message": "Mostrar una advertencia para los dominios de phishing dirigidos a los usuarios de Ethereum" + }, "usedByClients": { "message": "Utilizado por una gran variedad de clientes distintos" }, "userName": { "message": "Nombre de usuario" }, + "verifyThisTokenOn": { + "message": "Verifica este token en $1", + "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" + }, "viewAccount": { "message": "Ver cuenta" }, "viewContact": { - "message": "Ver contacto" + "message": "Ver Contacto" }, "viewOnCustomBlockExplorer": { "message": "Ver en $1" @@ -1206,13 +2081,20 @@ "message": "Ver en Etherscan" }, "viewinExplorer": { - "message": "Ver en Explorer" + "message": "Ver en el Explorador" }, "visitWebSite": { "message": "Visita nuestro sitio web" }, + "walletConnectionGuide": { + "message": "nuestra guía de billetera física" + }, "walletSeed": { - "message": "Inicialización de la billetera" + "message": "Semilla de la billetera" + }, + "web3ShimUsageNotification": { + "message": "Notamos que el sitio web actual intentó utilizar la API window.web3 eliminada. Si el sitio parece estar roto, haga clic en $1 para obtener más información.", + "description": "$1 is a clickable link." }, "welcome": { "message": "Bienvenido a MetaMask" @@ -1220,9 +2102,16 @@ "welcomeBack": { "message": "¡Hola de nuevo!" }, + "whatsThis": { + "message": "¿Qué es esto?" + }, "writePhrase": { "message": "Escribe esta frase en un papel y guárdalo en un lugar seguro. Si deseas una seguridad incluso mejor, escríbela en varios trozos de papel y guárdalos en dos o tres lugares distintos." }, + "xOfY": { + "message": "$1 de $2", + "description": "$1 and $2 are intended to be two numbers, where $2 is a total, and $1 is a count towards that total" + }, "yesLetsTry": { "message": "Sí, intentémoslo" }, @@ -1233,9 +2122,9 @@ "message": "Estás firmando" }, "yourPrivateSeedPhrase": { - "message": "Tu frase de inicialización privada" + "message": "Tu frase semilla privada" }, "zeroGasPriceOnSpeedUpError": { - "message": "El precio del gas es cero en aceleración" + "message": "No hubo precio de gas al acelerar" } } diff --git a/app/_locales/et/messages.json b/app/_locales/et/messages.json index 1fc296d7c..8064a0e0c 100644 --- a/app/_locales/et/messages.json +++ b/app/_locales/et/messages.json @@ -921,18 +921,12 @@ "selectAnAccountHelp": { "message": "Valige konto, mida MetaMaskis vaadata" }, - "selectCurrency": { - "message": "Valitud valuuta" - }, "selectEachPhrase": { "message": "Valige iga fraas, veendumaks, et see on õige." }, "selectHdPath": { "message": "Valige HD-teekond" }, - "selectLocale": { - "message": "Valige Lokaat" - }, "selectPathHelp": { "message": "Kui te ei näe allpool oma olemasolevaid pearaamatu kontosid, vahetage tee kohta \"Legacy (MEW/MyCrypto)\"" }, diff --git a/app/_locales/fa/messages.json b/app/_locales/fa/messages.json index 2a95dd796..da5872eee 100644 --- a/app/_locales/fa/messages.json +++ b/app/_locales/fa/messages.json @@ -931,18 +931,12 @@ "selectAnAccountHelp": { "message": "برای مشاهده MetaMask حساب را انتخاب نمایید" }, - "selectCurrency": { - "message": "واحد پول را انتخاب کنید" - }, "selectEachPhrase": { "message": "لطفًا جهت اطمینان از درستی، هر عبارت را انتخاب کنید." }, "selectHdPath": { "message": "انتخاب مسیر HD" }, - "selectLocale": { - "message": "محل را انتخاب کنید" - }, "selectPathHelp": { "message": "در صورتیکه شما حساب های موجود دفتر حساب را در ذیل نمیبینید، مسیر ها به \"Legacy (MEW / MyCrypto)\"  تغییر دهید" }, diff --git a/app/_locales/fi/messages.json b/app/_locales/fi/messages.json index 5f96b1c77..97ec89982 100644 --- a/app/_locales/fi/messages.json +++ b/app/_locales/fi/messages.json @@ -928,18 +928,12 @@ "selectAnAccountHelp": { "message": "Valitse MetaMaskissa näytettävä tili" }, - "selectCurrency": { - "message": "Valitse valuutta" - }, "selectEachPhrase": { "message": "Ole hyvä ja valitse jokainen teksti järjestyksessä varmistaaksesi, että se on oikein." }, "selectHdPath": { "message": "Valitse HD-polku" }, - "selectLocale": { - "message": "Valitse kielialue" - }, "selectPathHelp": { "message": "Jos et näe nykyisiä Ledger-tilejäsi tämän alla, koeta vaihtaa poluksi ”Vanha (MEW / MyCrypto)”" }, diff --git a/app/_locales/fil/messages.json b/app/_locales/fil/messages.json index 0b4123370..09f8c2bc4 100644 --- a/app/_locales/fil/messages.json +++ b/app/_locales/fil/messages.json @@ -843,18 +843,12 @@ "selectAnAccountHelp": { "message": "Piliin ang account na titingnan sa MetaMask" }, - "selectCurrency": { - "message": "Pumili ng Currency" - }, "selectEachPhrase": { "message": "Pakipili ang bawat parirala para tiyaking tama ito." }, "selectHdPath": { "message": "Piliin ang HD Path" }, - "selectLocale": { - "message": "Pumili ng Locale" - }, "selectPathHelp": { "message": "Kung hindi mo makita ang kasalukuyan mong mga Ledger account sa ibaba, subukang ilipat ang mga path sa \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/fr/messages.json b/app/_locales/fr/messages.json index 19c613762..22a15af1c 100644 --- a/app/_locales/fr/messages.json +++ b/app/_locales/fr/messages.json @@ -913,18 +913,12 @@ "selectAnAccountHelp": { "message": "Selectionner le compte à afficher dans MetaMask" }, - "selectCurrency": { - "message": "Selectionner Devise" - }, "selectEachPhrase": { "message": "Veuillez sélectionner chaque phrase afin de vous assurer qu'elle est correcte." }, "selectHdPath": { "message": "Selectioner le \"Path HD\"" }, - "selectLocale": { - "message": "Selectionner la localisation" - }, "selectPathHelp": { "message": "Si vos comptes Ledger n'apparaissent pas ci-dessous, essayez de selectionner le path \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/he/messages.json b/app/_locales/he/messages.json index b53fc791a..d5e148bf8 100644 --- a/app/_locales/he/messages.json +++ b/app/_locales/he/messages.json @@ -925,18 +925,12 @@ "selectAnAccountHelp": { "message": "בחר את החשבון לצפייה ב- MetaMask" }, - "selectCurrency": { - "message": "בחר מטבע" - }, "selectEachPhrase": { "message": "נא לבחור כל צירוף מילים כדי להבטיח שהוא נכון." }, "selectHdPath": { "message": "בחר/י נתיב HD" }, - "selectLocale": { - "message": "בחר/י מיקום" - }, "selectPathHelp": { "message": "אם אינך רואה את חשבונות ה-Ledger הקיימים שלך בהמשך, נסה/י להחליף נתיב ל-Legacy (MEW / MyCrypto)" }, diff --git a/app/_locales/hi/messages.json b/app/_locales/hi/messages.json index 6e8e48288..5eb356e15 100644 --- a/app/_locales/hi/messages.json +++ b/app/_locales/hi/messages.json @@ -1403,18 +1403,12 @@ "selectAnAccountHelp": { "message": "MetaMask में देखने के लिए खाते का चयन करें" }, - "selectCurrency": { - "message": "मुद्रा का चयन करें" - }, "selectEachPhrase": { "message": "कृपया प्रत्येक वाक्यांश का चयन करें, ताकि यह सुनिश्चित हो सके कि यह सही है।" }, "selectHdPath": { "message": "HD पथ का चयन करें" }, - "selectLocale": { - "message": "लोकेल का चयन करें" - }, "selectPathHelp": { "message": "यदि आपको अपने मौजूदा लेजर खाते नीचे नहीं दिखाई देते हैं, तो पथ को \"Legacy (MEW / MyCrypto)\" पर स्विच करने का प्रयास करें" }, @@ -1639,9 +1633,6 @@ "swapEstimatedNetworkFeesInfo": { "message": "यह नेटवर्क शुल्क का एक अनुमान है, जिसे आपके स्वैप को पूरा करने के लिए उपयोग किया जाएगा। नेटवर्क की स्थितियों के अनुसार वास्तविक राशि बदल सकती है।" }, - "swapFailedErrorDescription": { - "message": "आपका धन सुरक्षित है और अभी भी आपके वॉलेट में उपलब्ध है।" - }, "swapFailedErrorTitle": { "message": "स्वैप विफल रहा" }, diff --git a/app/_locales/hn/messages.json b/app/_locales/hn/messages.json index 106db04cb..0dac2b285 100644 --- a/app/_locales/hn/messages.json +++ b/app/_locales/hn/messages.json @@ -330,9 +330,6 @@ "seedPhraseReq": { "message": "बीज वाक्यांश 12 शब्द लंबा हैं" }, - "selectCurrency": { - "message": "मुद्रा चुनें" - }, "selectType": { "message": "प्रकार चुनें" }, diff --git a/app/_locales/hr/messages.json b/app/_locales/hr/messages.json index 72e6f3945..9ffa140c1 100644 --- a/app/_locales/hr/messages.json +++ b/app/_locales/hr/messages.json @@ -924,18 +924,12 @@ "selectAnAccountHelp": { "message": "Odaberi račun za prikaz u usluzi MetaMask" }, - "selectCurrency": { - "message": "Odaberite valutu" - }, "selectEachPhrase": { "message": "Odaberite svaku rečenicu kako biste provjerili je li točna." }, "selectHdPath": { "message": "Odaberi put HD-a" }, - "selectLocale": { - "message": "Odaberi lokalnu postavku" - }, "selectPathHelp": { "message": "Ako ne vidite u nastavku postojeće račune Ledger, pokušajte promijeniti puteve na „Nasljeđe (MEW / MyCrypto)”" }, diff --git a/app/_locales/ht/messages.json b/app/_locales/ht/messages.json index 289501561..40d8d73bb 100644 --- a/app/_locales/ht/messages.json +++ b/app/_locales/ht/messages.json @@ -573,15 +573,9 @@ "selectAnAccountHelp": { "message": "Chwazi kont pou wè nan MetaMask" }, - "selectCurrency": { - "message": "Chwazi Lajan" - }, "selectHdPath": { "message": "Chwazi chemen HD" }, - "selectLocale": { - "message": "Chwazi Lokasyon" - }, "selectPathHelp": { "message": "Si ou pa wè kont Ledger ou te genyen an anba a, eseye chanje chemen an \"Eritaj (MEW / MyCrypto)\"" }, diff --git a/app/_locales/hu/messages.json b/app/_locales/hu/messages.json index ce3ae6148..3d41627db 100644 --- a/app/_locales/hu/messages.json +++ b/app/_locales/hu/messages.json @@ -924,18 +924,12 @@ "selectAnAccountHelp": { "message": "Válássza ki a MetaMask-ban megtekinteni kívánt fiókot" }, - "selectCurrency": { - "message": "Válasszon valutát" - }, "selectEachPhrase": { "message": "Kérjük, válassza ki az egyes mondatokat, hogy meggyőződjön azok helyességéről. " }, "selectHdPath": { "message": "Válassz HD elérési útvonalat" }, - "selectLocale": { - "message": "Válaszd ki a területi beállítást" - }, "selectPathHelp": { "message": "Ha nem láthatók alább Ledger számláid, próbáld kicserélni az elérési útvonalat: „Legacy (MEW / MyCypto)”" }, diff --git a/app/_locales/id/messages.json b/app/_locales/id/messages.json index b8119c448..480e63e20 100644 --- a/app/_locales/id/messages.json +++ b/app/_locales/id/messages.json @@ -1403,18 +1403,12 @@ "selectAnAccountHelp": { "message": "Pilih akun untuk dilihat di MetaMask" }, - "selectCurrency": { - "message": "Pilih Mata Uang" - }, "selectEachPhrase": { "message": "Pilih masing-masing frasa untuk memastikan kebenarannya." }, "selectHdPath": { "message": "Pilih Jalur HD" }, - "selectLocale": { - "message": "Pilih Lokal" - }, "selectPathHelp": { "message": "Jika Anda tidak melihat akun Ledger Anda yang ada di bawah, coba untuk beralih jalur ke \"Warisan (MEW / MyCrypto)\"" }, @@ -1639,9 +1633,6 @@ "swapEstimatedNetworkFeesInfo": { "message": "Ini adalah perkiraan biaya jaringan yang akan digunakan untuk menyelesaikan penukaran Anda. Jumlah aktual dapat berubah sesuai dengan kondisi jaringan." }, - "swapFailedErrorDescription": { - "message": "Dana Anda aman dan masih tersedia di dompet Anda." - }, "swapFailedErrorTitle": { "message": "Penukaran gagal" }, diff --git a/app/_locales/index.json b/app/_locales/index.json index 31199dcab..0e17dfbc9 100644 --- a/app/_locales/index.json +++ b/app/_locales/index.json @@ -50,6 +50,7 @@ { "code": "ta", "name": "தமிழ்" }, { "code": "te", "name": "తెలుగు" }, { "code": "th", "name": "ไทย" }, + { "code": "tl", "name": "Wikang Tagalog" }, { "code": "tr", "name": "Türkçe" }, { "code": "uk", "name": "Українська мова" }, { "code": "vi", "name": "Tiếng Việt" }, diff --git a/app/_locales/it/messages.json b/app/_locales/it/messages.json index daff32d6d..f1d13d7c8 100644 --- a/app/_locales/it/messages.json +++ b/app/_locales/it/messages.json @@ -1294,18 +1294,12 @@ "selectAnAccountHelp": { "message": "Selezione l'account da visualizzare in MetaMask" }, - "selectCurrency": { - "message": "Seleziona Moneta" - }, "selectEachPhrase": { "message": "Per favore seleziona ogni frase in ordine per assicurarti che sia corretta." }, "selectHdPath": { "message": "Seleziona Percorso HD" }, - "selectLocale": { - "message": "Selezione Lingua" - }, "selectPathHelp": { "message": "Se non vedi il tuo account Ledger esistente di seguito, prova a cambiare il percorso in \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/ja/messages.json b/app/_locales/ja/messages.json index a8cfd9bbe..556ba6fff 100644 --- a/app/_locales/ja/messages.json +++ b/app/_locales/ja/messages.json @@ -1,9 +1,20 @@ { + "about": { + "message": "バージョン情報" + }, "aboutSettingsDescription": { - "message": "バージョンやサポート、問合せ先など" + "message": "バージョン、サポートセンター、問い合わせ情報" }, "acceleratingATransaction": { - "message": "*より高いガス価格を使用すると、ネットワークでより速く処理され、トランザクションを高速化できる可能性が高くなりますが、常に保証されるとは限りません。" + "message": "* より高いGas料金を支払うと、トランザクションはより早くネットワークで処理される可能性が高くなります。ただし、これは常に保証されるとは限りません。" + }, + "acceptTermsOfUse": { + "message": "$1 の内容を確認し、同意します", + "description": "$1 is the `terms` message" + }, + "accessAndSpendNotice": { + "message": "$1 はアクセスしてこの最大量まで使用する可能性があります", + "description": "$1 is the url of the site requesting ability to spend" }, "accessingYourCamera": { "message": "カメラにアクセスしています..." @@ -12,7 +23,7 @@ "message": "アカウント" }, "accountDetails": { - "message": "アカウント詳細" + "message": "アカウントの詳細" }, "accountName": { "message": "アカウント名" @@ -21,28 +32,37 @@ "message": "アカウント設定" }, "accountSelectionRequired": { - "message": "アカウントを選択してください。" + "message": "アカウントを選択する必要があります!" + }, + "active": { + "message": "アクティブ" + }, + "activity": { + "message": "アクティビティ" }, "activityLog": { - "message": "アクティビティログ" + "message": "アクティビティのログ" + }, + "addAccount": { + "message": "アカウントの追加" }, "addAcquiredTokens": { - "message": "MetaMaskで獲得したトークンを追加する" + "message": "MetaMaskで取得したトークンを追加する" }, "addAlias": { - "message": "エイリアスを追加" + "message": "エイリアスの追加" }, "addNetwork": { - "message": "ネットワーク追加" + "message": "ネットワークの追加" }, "addRecipient": { - "message": "受取人追加" + "message": "受取人を追加" }, "addSuggestedTokens": { - "message": "推奨トークンを追加" + "message": "推奨されたトークンを追加" }, "addToAddressBook": { - "message": "アドレス帳に追加" + "message": "アドレス帳へ追加" }, "addToAddressBookModalPlaceholder": { "message": "例: John D" @@ -62,19 +82,77 @@ "advancedSettingsDescription": { "message": "開発者向け機能では、状態ログのダウンロード、アカウントリセットし、テストネットやカスタムRPCの設定が可能です。" }, + "affirmAgree": { + "message": "同意します" + }, + "aggregatorFeeCost": { + "message": "アグリゲータのネットワーク手数料" + }, + "alertDisableTooltip": { + "message": "\"設定 > 警告の設定\"で変更できます" + }, + "alertSettingsUnconnectedAccount": { + "message": "未接続のアカウントを選択してWebサイト閲覧した時に警告する" + }, + "alertSettingsUnconnectedAccountDescription": { + "message": "この警告は、選択中のアカウントが未接続のままWeb3サイトを閲覧しているときにポップアップ表示されます。" + }, + "alertSettingsWeb3ShimUsage": { + "message": "廃止されたwindow.web3 APIの使用を警告する" + }, + "alertSettingsWeb3ShimUsageDescription": { + "message": "この警告は、選択中のアカウントが廃止されたwindow.web3 APIを使用してサイトを閲覧したときにポップアップ表示されます。サイトは恐らく機能しません。" + }, + "alerts": { + "message": "警告の設定" + }, + "alertsSettingsDescription": { + "message": "警告を有効化または無効化" + }, + "allowExternalExtensionTo": { + "message": "外部拡張機能に次の操作を許可します:" + }, + "allowOriginSpendToken": { + "message": "$1 に $2 の使用を許可しますか?", + "description": "$1 is the url of the site and $2 is the symbol of the token they are requesting to spend" + }, + "allowThisSiteTo": { + "message": "このサイトに次の操作を許可します:" + }, + "allowWithdrawAndSpend": { + "message": "$1 に以下の額までの引き出しと使用を許可します。", + "description": "The url of the site that requested permission to 'withdraw and spend'" + }, "amount": { "message": "金額" }, + "amountInEth": { + "message": "$1 ETH", + "description": "Displays an eth amount to the user. $1 is a decimal number" + }, + "amountWithColon": { + "message": "金額:" + }, "appDescription": { - "message": "Ethereumのブラウザ・エクステンション", + "message": "Ethereumウォレットのブラウザ・エクステンション", "description": "The description of the application" }, "appName": { "message": "MetaMask", "description": "The name of the application" }, + "approvalAndAggregatorTxFeeCost": { + "message": "承認とアグリゲータのネットワーク手数料" + }, + "approvalTxGasCost": { + "message": "承認のトランザクションGas料金" + }, "approve": { - "message": "承認する" + "message": "使用限度額の承認" + }, + "approveSpendLimit": { + "message": "使用限度額 $1 を承認", + "description": "The token symbol that is being approved" }, "approved": { "message": "承認済み" @@ -82,23 +160,29 @@ "asset": { "message": "アセット" }, + "assets": { + "message": "アセット" + }, "attemptToCancel": { - "message": "キャンセルを試みますか?" + "message": "キャンセルを要求しますか?" }, "attemptToCancelDescription": { - "message": "このキャンセルを送信しても、元のトランザクションがキャンセルされることは保証されません。キャンセルが成功した場合、上記の取引手数料が請求されます。" + "message": "キャンセルを要求しても、取引のキャンセルは保証されません。キャンセルが成功した場合、上記の取引手数料が請求されます。" }, "attemptingConnect": { "message": "ブロックチェーンに接続中" }, "attributions": { - "message": "属性" + "message": "ソフトウェアの著作権告知" + }, + "authorizedPermissions": { + "message": "以下の権限を許可しました" }, "autoLockTimeLimit": { - "message": "自動ログアウト(分)" + "message": "自動ロック(分)" }, "autoLockTimeLimitDescription": { - "message": "MetaMaskが自動的にログアウトするまでのアイドル時間を分単位で設定します。" + "message": "MetaMaskが自動的にロックするまでのアイドル時間を分単位で設定します。" }, "average": { "message": "平均" @@ -106,59 +190,292 @@ "back": { "message": "戻る" }, + "backToAll": { + "message": "一覧に戻る" + }, + "backupApprovalInfo": { + "message": "シードフレーズはウォレットの復旧に必要です。デバイスやパスワードの紛失、MetaMaskの再インストール時、または別のデバイスでウォレットを使用する時に必要です。" + }, + "backupApprovalNotice": { + "message": "シードフレーズをバックアップして、ウォレットと資金の安全を確保してください。" + }, + "backupNow": { + "message": "今すぐバックアップ" + }, "balance": { - "message": "残高:" + "message": "残高" + }, + "balanceOutdated": { + "message": "残高情報は最新ではない可能性があります" + }, + "basic": { + "message": "基本" + }, + "blockExplorerUrl": { + "message": "ブロックエクスプローラ" + }, + "blockExplorerView": { + "message": "$1 のアカウントを表示", + "description": "$1 replaced by URL for custom block explorer" }, "blockiesIdenticon": { - "message": "Blockies Identicon を使用" + "message": "Blockies Identiconを使用" + }, + "browserNotSupported": { + "message": "このブラウザーはサポートしていません。" + }, + "builtInCalifornia": { + "message": "MetaMaskはカリフォルニアで設計、作成されました。" + }, + "buy": { + "message": "入金" + }, + "buyWithWyre": { + "message": "WyreでETHを購入" + }, + "buyWithWyreDescription": { + "message": "Wyreでは、デビットカードを使用してETHをMetaMaskアカウントに直接入金できます。" + }, + "bytes": { + "message": "バイト" + }, + "canToggleInSettings": { + "message": "通知は設定->警告の設定で再度有効にできます。" }, "cancel": { "message": "キャンセル" }, + "cancellationGasFee": { + "message": "キャンセルのGas料金" + }, + "cancelled": { + "message": "キャンセル済み" + }, + "chainId": { + "message": "チェーンID" + }, + "chromeRequiredForHardwareWallets": { + "message": "ハードウェアウォレットへ接続するには、MetaMask on Google Chrome を使用する必要があります。" + }, + "clickToRevealSeed": { + "message": "シードフレーズを表示するにはここをクリックします" + }, + "close": { + "message": "閉じる" + }, "confirm": { "message": "確認" }, "confirmPassword": { "message": "パスワードの確認" }, + "confirmSecretBackupPhrase": { + "message": "シードフレーズの確認" + }, + "confirmed": { + "message": "確認しました" + }, + "congratulations": { + "message": "おめでとうございます" + }, + "connect": { + "message": "接続" + }, + "connectAccountOrCreate": { + "message": "アカウントを接続するか、または新規に作成します" + }, + "connectHardwareWallet": { + "message": "ハードウェアウォレットの接続" + }, + "connectManually": { + "message": "手動で現在のサイトに接続します" + }, + "connectTo": { + "message": "接続先 $1", + "description": "$1 is the name/origin of a web3 site/application that the user can connect to metamask" + }, + "connectToAll": { + "message": "全ての $1 に接続", + "description": "$1 will be replaced by the translation of connectToAllAccounts" + }, + "connectToAllAccounts": { + "message": "アカウント", + "description": "will replace $1 in connectToAll, completing the sentence 'connect to all of your accounts', will be text that shows list of accounts on hover" + }, + "connectToMultiple": { + "message": "$1 に接続", + "description": "$1 will be replaced by the translation of connectToMultipleNumberOfAccounts" + }, + "connectToMultipleNumberOfAccounts": { + "message": "$1個のアカウント", + "description": "$1 is the number of accounts to which the web3 site/application is asking to connect; this will substitute $1 in connectToMultiple" + }, + "connectWithMetaMask": { + "message": "MetaMaskをサイトに接続する" + }, + "connectedAccountsDescriptionPlural": { + "message": "このサイトに接続されたアカウントは $1個あります。", + "description": "$1 is the number of accounts" + }, + "connectedAccountsDescriptionSingular": { + "message": "このサイトに接続されたアカウントは $1個あります。" + }, + "connectedAccountsEmptyDescription": { + "message": "MetaMaskはこのサイトに接続されていません。Web3サイトに接続するには、サイト内にある接続ボタンを使用します。" + }, + "connectedSites": { + "message": "接続済みのサイト" + }, + "connectedSitesDescription": { + "message": "$1 はサイトに接続されています。サイトはアカウントアドレスを見ることができます。", + "description": "$1 is the account name" + }, + "connectedSitesEmptyDescription": { + "message": "$1 はどのサイトとも接続されていません。", + "description": "$1 is the account name" + }, + "connecting": { + "message": "接続しています..." + }, + "connectingTo": { + "message": "$1 への接続" + }, + "connectingToGoerli": { + "message": "Goerliテストネットワークへの接続" + }, + "connectingToKovan": { + "message": "Kovanテストネットワークへの接続" + }, + "connectingToMainnet": { + "message": "Ethereumメインネットへの接続" + }, + "connectingToRinkeby": { + "message": "Rinkebyテストネットワークへの接続" + }, + "connectingToRopsten": { + "message": "Ropstenテストネットワークへ接続" + }, + "contactUs": { + "message": "問い合わせ" + }, + "contacts": { + "message": "アドレス帳" + }, + "contactsSettingsDescription": { + "message": "アドレス帳の追加、編集、削除、管理" + }, + "continueToWyre": { + "message": "Wyreへ進む" + }, "contractDeployment": { "message": "コントラクトのデプロイ" }, "contractInteraction": { - "message": "コントラクトへのアクセス" + "message": "コントラクトのインタラクション" }, "copiedExclamation": { "message": "コピー完了!" }, + "copiedTransactionId": { + "message": "コピーしたトランザクションID" + }, + "copyAddress": { + "message": "アドレスをクリップボードにコピーしました" + }, "copyPrivateKey": { "message": "これはあなたの秘密鍵です(クリックでコピー)" }, "copyToClipboard": { "message": "クリップボードへコピー" }, + "copyTransactionId": { + "message": "トランザクションIDをコピー" + }, "create": { "message": "作成" }, + "createAWallet": { + "message": "ウォレットの作成" + }, "createAccount": { "message": "アカウント作成" }, + "createPassword": { + "message": "パスワードの作成" + }, + "currencyConversion": { + "message": "通貨換算" + }, + "currentAccountNotConnected": { + "message": "現在のアカウントは接続されていません" + }, + "currentExtension": { + "message": "現在のエクステンションページ" + }, + "currentLanguage": { + "message": "現在の言語" + }, "customGas": { - "message": "ガスのカスタマイズ" + "message": "Gasのカスタマイズ" + }, + "customGasSubTitle": { + "message": "手数料を増やすと処理までの時間が短縮できます。(短縮できない場合もあります。)" }, "customRPC": { "message": "カスタムRPC" }, + "customSpendLimit": { + "message": "カスタム使用限度額" + }, "customToken": { "message": "カスタムトークン" }, + "dataBackupFoundInfo": { + "message": "一部のアカウントデータはMetaMaskの前回のインストール時にバックアップされました。これには、設定、アドレス帳、トークンが含まれます。データを今すぐ復元しますか?" + }, "decimal": { "message": "小数点桁数" }, + "decimalsMustZerotoTen": { + "message": "小数桁数は、0 以上 36 以下の範囲にする必要があります。" + }, + "decrypt": { + "message": "復号" + }, + "decryptCopy": { + "message": "暗号化したメッセージをコピー" + }, + "decryptInlineError": { + "message": "エラーです。メッセージを復号できません:$1", + "description": "$1 is error message" + }, + "decryptMessageNotice": { + "message": "$1 はメッセージを読み取ってアクションを完了しようとしています", + "description": "$1 is the web3 site name" + }, + "decryptMetamask": { + "message": "メッセージを復号" + }, + "decryptRequest": { + "message": "復号のリクエスト" + }, "defaultNetwork": { - "message": "デフォルトのEther送受信ネットワークはメインネットです。" + "message": "デフォルトのEther取引ネットワークはメインネットです。" + }, + "delete": { + "message": "削除" + }, + "deleteAccount": { + "message": "アカウントの削除" + }, + "deleteNetwork": { + "message": "ネットワークを削除しますか?" + }, + "deleteNetworkDescription": { + "message": "本当にこのネットワークを削除しますか?" }, "depositEther": { - "message": "Etherを振込" + "message": "Etherを入金" }, "details": { "message": "詳細" @@ -167,68 +484,316 @@ "message": "Etherを直接入金" }, "directDepositEtherExplainer": { - "message": "既にEtherをお持ちなら、MetaMaskの新しいウォレットにEtherを送信することができます。" + "message": "Etherが既にあるなら、MetaMaskの新しいウォレットにEtherを送金することができます。" + }, + "disconnect": { + "message": "切断" + }, + "disconnectAllAccounts": { + "message": "すべてのアカウントを切断する" + }, + "disconnectAllAccountsConfirmationDescription": { + "message": "本当に切断しますか?サイトの機能を失う可能性があります。" + }, + "disconnectPrompt": { + "message": "$1 を切断" + }, + "disconnectThisAccount": { + "message": "このアカウントを切断" + }, + "dismiss": { + "message": "却下" }, "done": { "message": "完了" }, + "dontHaveAHardwareWallet": { + "message": "ハードウェアウォレットをお持ちではありませんか?" + }, + "dontShowThisAgain": { + "message": "再度表示しない" + }, + "downloadGoogleChrome": { + "message": "Google Chromeのダウンロード" + }, + "downloadSecretBackup": { + "message": "シードフレーズをダウンロードして、外部の暗号化されたハードウェアドライブまたはストレージ媒体に安全に保管してください。" + }, + "downloadStateLogs": { + "message": "状態ログのダウンロード" + }, + "dropped": { + "message": "削除済" + }, "edit": { "message": "編集" }, + "editContact": { + "message": "連絡先の編集" + }, + "editPermission": { + "message": "アクセス許可の編集" + }, + "encryptionPublicKeyNotice": { + "message": "$1 は公開暗号鍵を使用しようとしています。同意すると、このサイトは暗号化されたメッセージを作成できます。", + "description": "$1 is the web3 site name" + }, + "encryptionPublicKeyRequest": { + "message": "公開暗号鍵の要求" + }, + "endOfFlowMessage1": { + "message": "テストに合格しました。シードフレーズを安全に保管してください。これは利用者の責務です。" + }, "endOfFlowMessage10": { "message": "全て完了" }, + "endOfFlowMessage2": { + "message": "安全に保管するためのヒント" + }, + "endOfFlowMessage3": { + "message": "バックアップは複数の場所に保管してください。" + }, + "endOfFlowMessage4": { + "message": "シードフレーズは絶対に誰にも教えないでください。" + }, + "endOfFlowMessage5": { + "message": "フィッシング詐欺に注意してください!MetaMaskは自発的にシードフレーズを絶対に要求しません。" + }, + "endOfFlowMessage6": { + "message": "シードフレーズを再度バックアップする場合は、[設定] -> [セキュリティとプライバシー] で見つけることができます。" + }, + "endOfFlowMessage7": { + "message": "問題や不審な点がある場合は、support@metamask.io 宛に電子メールをお送りください。" + }, + "endOfFlowMessage8": { + "message": "MetaMaskはシードフレーズを復元できません。" + }, + "endOfFlowMessage9": { + "message": "詳細を表示。" + }, + "endpointReturnedDifferentChainId": { + "message": "エンドポイントは別のチェーンID:$1 を返してきました", + "description": "$1 is the return value of eth_chainId from an RPC endpoint" + }, + "ensNotFoundOnCurrentNetwork": { + "message": "ENS名が現在のネットワーク上で見つかりません。Ethereumメインネットへの切り替えを試みてください。" + }, + "ensRegistrationError": { + "message": "ENS名の登録のエラーです" + }, + "enterAnAlias": { + "message": "エイリアスを入力してください" + }, + "enterMaxSpendLimit": { + "message": "使用限度額の最大値を入力してください" + }, "enterPassword": { - "message": "パスワードを入力" + "message": "パスワードを入力してください" + }, + "enterPasswordContinue": { + "message": "続行するには、パスワードを入力してください" + }, + "errorCode": { + "message": "コード:$1", + "description": "Displayed error code for debugging purposes. $1 is the error code" + }, + "errorDetails": { + "message": "エラーの詳細", + "description": "Title for collapsible section that displays error details for debugging purposes" + }, + "errorMessage": { + "message": "メッセージ:$1", + "description": "Displayed error message for debugging purposes. $1 is the error message" + }, + "errorName": { + "message": "エラー名:$1", + "description": "Displayed error name for debugging purposes. $1 is the error name" + }, + "errorPageMessage": { + "message": "ページをリロードして再試行するか、サポート(support@metamask.io)までお問い合わせください", + "description": "Message displayed on generic error page in the fullscreen or notification UI" + }, + "errorPagePopupMessage": { + "message": "ポップアップを閉じてから再び開いてもう一度実行するか、サポート(support@metamask.io)までお問い合わせください", + "description": "Message displayed on generic error page in the popup UI" + }, + "errorPageTitle": { + "message": "MetaMaskにエラーが発生しました", + "description": "Title of generic error page" + }, + "errorStack": { + "message": "スタック:", + "description": "Title for error stack, which is displayed for debugging purposes" + }, + "estimatedProcessingTimes": { + "message": "推定処理時間" + }, + "eth_accounts": { + "message": "許可したアカウントのアドレスの読み取り(必須)", + "description": "The description for the `eth_accounts` permission" + }, + "ethereumPublicAddress": { + "message": "パブリックEthereumアドレス" + }, + "etherscan": { + "message": "Etherscan" }, "etherscanView": { - "message": "Etherscanでアカウントを確認" + "message": "Etherscanでアカウントを表示" + }, + "expandView": { + "message": "ウインドウで表示" }, "exportPrivateKey": { "message": "秘密鍵のエクスポート" }, + "externalExtension": { + "message": "外部拡張機能" + }, + "extraApprovalGas": { + "message": "+$1 承認Gas", + "description": "Expresses an additional gas amount the user will have to pay, on top of some other displayed amount. $1 is a decimal amount of gas" + }, "failed": { "message": "失敗" }, + "failedToFetchChainId": { + "message": "チェーンIDを取り込むことができませんでした。RPCのURLが正しいか確認してください。" + }, + "failureMessage": { + "message": "問題が発生しました。アクションを完了することができません" + }, + "fast": { + "message": "高速" + }, + "fastest": { + "message": "最高速" + }, + "feeAssociatedRequest": { + "message": "このリクエストにかかる手数料です。" + }, "fiat": { "message": "法定通貨", "description": "Exchange type" }, "fileImportFail": { - "message": "ファイルがインポートされなければ、ここをクリック!", + "message": "ファイルのインポート方法について", "description": "Helps user import their account from a JSON file" }, + "forbiddenIpfsGateway": { + "message": "IPFSゲートウェイの使用は禁止されています:CID ゲートウェイを指定してください" + }, + "forgetDevice": { + "message": "このデバイスを無視する" + }, "from": { "message": "送信元" }, + "fromAddress": { + "message": "送信元:$1", + "description": "$1 is the address to include in the From label. It is typically shortened first using shortenAddress" + }, + "functionApprove": { + "message": "機能:承認" + }, + "functionType": { + "message": "機能の種類" + }, "gasLimit": { - "message": "ガスリミット" + "message": "Gasリミット" + }, + "gasLimitInfoTooltipContent": { + "message": "Gasリミットは、使用するガスの最大量です。" }, "gasLimitTooLow": { - "message": "ガスリミットは最低21000です。" + "message": "Gasリミットは21000以上にする必要があります" + }, + "gasLimitTooLowWithDynamicFee": { + "message": "Gasリミットは $1 以上にする必要があります", + "description": "$1 is the custom gas limit, in decimal." }, "gasPrice": { - "message": "ガスプライス (GWEI)" + "message": "Gas価格 (GWEI)" + }, + "gasPriceExtremelyLow": { + "message": "Gas価格が安すぎます" + }, + "gasPriceInfoTooltipContent": { + "message": "Gas価格は1Gas当たりのEther価格です。" + }, + "gasUsed": { + "message": "Gas使用量" + }, + "gdprMessage": { + "message": "このデータは、General Data Protection Regulation (EU) 2016/679 のため、匿名で収集されます。個人情報の取り扱いに関する詳細については、$1 をご覧ください。", + "description": "$1 refers to the gdprMessagePrivacyPolicy message, the translation of which is meant to be used exclusively in the context of gdprMessage" + }, + "gdprMessagePrivacyPolicy": { + "message": "プライバシーポリシーはこちら", + "description": "this translation is intended to be exclusively used as the replacement for the $1 in the gdprMessage translation" + }, + "general": { + "message": "一般" + }, + "generalSettingsDescription": { + "message": "通貨換算、通貨単位、言語、アカウントのidenticon" }, "getEther": { "message": "Etherを取得する" }, "getEtherFromFaucet": { - "message": "フォーセットで $1のEtherを得ることができます。", + "message": "$1 のFaucetでEtherを得ることができます。", "description": "Displays network name for Ether faucet" }, + "getHelp": { + "message": "サポートを受ける。" + }, + "getStarted": { + "message": "はじめる" + }, + "goerli": { + "message": "Goerliテストネットワーク" + }, + "happyToSeeYou": { + "message": "また会えましたね!" + }, + "hardware": { + "message": "ハードウェア" + }, + "hardwareWalletConnected": { + "message": "ハードウェアウォレットが接続されました" + }, + "hardwareWallets": { + "message": "ハードウェアウォレットの接続" + }, + "hardwareWalletsMsg": { + "message": "MetaMaskに接続するハードウェアウォレットを選択してください" + }, + "havingTroubleConnecting": { + "message": "接続に問題がありますか?" + }, "here": { - "message": "ここ", + "message": "こちら", "description": "as in -click here- for more information (goes with troubleTokenBalances)" }, + "hexData": { + "message": "16進数データ" + }, "hide": { - "message": "隠す" + "message": "非表示" }, "hideTokenPrompt": { - "message": "トークンを隠しますか?" + "message": "トークンを非表示にしますか?" + }, + "hideTokenSymbol": { + "message": "$1 を非表示にする", + "description": "$1 is the symbol for a token (e.g. 'DAI')" + }, + "history": { + "message": "履歴" }, "import": { - "message": "追加", + "message": "インポート", "description": "Button to import an account from a selected file" }, "importAccount": { @@ -237,137 +802,540 @@ "importAccountMsg": { "message": "追加したアカウントはMetaMaskのアカウントパスフレーズとは関連付けられません。インポートしたアカウントについての詳細は" }, + "importAccountSeedPhrase": { + "message": "シードフレーズを使用してアカウントをインポート" + }, + "importUsingSeed": { + "message": "アカウントのシードフレーズから復元する" + }, + "importWallet": { + "message": "ウォレットのインポート" + }, + "importYourExisting": { + "message": "12単語のシードフレーズを使用して既存のウォレットをインポートします" + }, "imported": { - "message": "インポート完了", + "message": "インポート済", "description": "status showing that an account has been fully loaded into the keyring" }, "infoHelp": { "message": "情報とヘルプ" }, + "initialTransactionConfirmed": { + "message": "最初のトランザクションがネットワークに確認されました。戻るにはOKをクリックします。" + }, + "insufficientBalance": { + "message": "残高不足です。" + }, "insufficientFunds": { "message": "残高不足" }, + "insufficientTokens": { + "message": "トークンが不足しています。" + }, "invalidAddress": { - "message": "アドレスが無効です。" + "message": "無効なアドレスです" + }, + "invalidAddressRecipient": { + "message": "無効な送金先アドレスです" + }, + "invalidAddressRecipientNotEthNetwork": { + "message": "ETH ネットワークではなく、小文字を設定してください" + }, + "invalidBlockExplorerURL": { + "message": "無効なブロックエクスプローラURLです。" + }, + "invalidChainIdTooBig": { + "message": "無効なチェーンIDです。チェーンIDが大きすぎます。" + }, + "invalidCustomNetworkAlertContent1": { + "message": "カスタムネットワーク'$1'のチェーンIDを再入力してください。", + "description": "$1 is the name/identifier of the network." + }, + "invalidCustomNetworkAlertContent2": { + "message": "悪意や欠陥のあるネットワークプロバイダから利用者を保護するため、すべてのカスタムネットワークにチェーンIDが必要です" + }, + "invalidCustomNetworkAlertContent3": { + "message": "設定 > ネットワーク を選択して、チェーンIDを入力してください。よく使用されるネットワークのチェーンIDは $1 にあります。", + "description": "$1 is a link to https://chainid.network" + }, + "invalidCustomNetworkAlertTitle": { + "message": "無効なカスタムネットワークです" + }, + "invalidHexNumber": { + "message": "無効な10進数です。" + }, + "invalidHexNumberLeadingZeros": { + "message": "無効な10進数です。先頭の0を削除してください。" + }, + "invalidIpfsGateway": { + "message": "無効なIPFSゲートウェイです:正しいURLを設定してください。" + }, + "invalidNumber": { + "message": "無効な数値です。10進数、または'0x'を付けた16進数を入力します。" + }, + "invalidNumberLeadingZeros": { + "message": "無効な数値です。先頭の 0 を削除してください。" + }, + "invalidRPC": { + "message": "無効な RPC URL" + }, + "invalidSeedPhrase": { + "message": "無効なシードフレーズ" + }, + "ipfsGateway": { + "message": "IPFSゲートウェイ" + }, + "ipfsGatewayDescription": { + "message": "ENSコンテンツレゾリューションに使用する、IPFS CIDゲートウェイのURLを設定します" }, "jsonFile": { "message": "JSONファイル", "description": "format for importing an account" }, + "knownAddressRecipient": { + "message": "既知のコントラクトアドレスです。" + }, + "knownTokenWarning": { + "message": "このアクションは既にウォレット一覧に表示あるトークンを編集します。これは、フィッシング詐欺の手段として指示されることがあります。変更の意図が明確な場合にのみ実施してください。" + }, "kovan": { "message": "Kovanテストネットワーク" }, + "lastConnected": { + "message": "最後の接続" + }, "learnMore": { - "message": "詳細" + "message": "詳しい使用手順" + }, + "ledgerAccountRestriction": { + "message": "新しいアカウントを追加するには、その前に使用した最後のアカウントが必要です。" + }, + "letsGoSetUp": { + "message": "セットアップを始めましょう!" }, "likeToAddTokens": { - "message": "トークンを追加しますか?" + "message": "これらのトークンを追加しますか?" }, "links": { "message": "リンク" }, + "loadMore": { + "message": "続きをロード" + }, "loading": { - "message": "ロード中..." + "message": "ロードしています..." }, "loadingTokens": { - "message": "トークンをロード中..." + "message": "トークンをロードしています..." + }, + "localhost": { + "message": "Localhost 8545" }, "lock": { - "message": "ログアウト" + "message": "ロック" + }, + "lockTimeTooGreat": { + "message": "ロック時間が長すぎます" }, "mainnet": { - "message": "Ethereumメインネットワーク" + "message": "Ethereumメインネット" }, "max": { "message": "最大" }, + "memo": { + "message": "メモ" + }, + "memorizePhrase": { + "message": "このフレーズを記録してください。" + }, "message": { "message": "メッセージ" }, + "metaMaskConnectStatusParagraphOne": { + "message": "アカウントの接続をMetaMaskで詳細に制御できるようになりました。" + }, + "metaMaskConnectStatusParagraphThree": { + "message": "接続しているアカウントを管理するにはクリックしてください。" + }, + "metaMaskConnectStatusParagraphTwo": { + "message": "現在選択しているアカウントが訪問中のWebサイトに接続されている場合、接続ステータスボタンが表示されます。" + }, + "metamaskDescription": { + "message": "Ethereumの分散型Webに接続しています。" + }, + "metamaskSwapsOfflineDescription": { + "message": "MetaMask Swapsはメンテナンス中です。後でもう一度確認してください。" + }, + "metamaskVersion": { + "message": "MetaMaskのバージョン" + }, + "metametricsCommitmentsAllowOptOut": { + "message": "設定からいつでも離脱できます" + }, + "metametricsCommitmentsBoldNever": { + "message": "実行しない", + "description": "This string is localized separately from some of the commitments so that we can bold it" + }, + "metametricsCommitmentsIntro": { + "message": "MetaMaskが実行する内容は…" + }, + "metametricsCommitmentsNeverCollectIP": { + "message": "$1 が識別可能なIPアドレスを収集することはありません", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverCollectKeysEtc": { + "message": "$1 は、キー、アドレス、トランザクション、残高、ハッシュなど、いかなる個人情報も収集しません", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverSellDataForProfit": { + "message": "$1 が営利目的でデータを販売することは'永遠に'ありません。", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsSendAnonymizedEvents": { + "message": "匿名化されたクリックイベントとページビューイベントを送信する" + }, + "metametricsHelpImproveMetaMask": { + "message": "MetaMaskの品質向上へのご協力のお願い" + }, + "metametricsOptInDescription": { + "message": "MetaMaskでは、ユーザーによる拡張機能の操作方法をより理解するため、基本的な使用状況データを収集させて頂きたいと考えています。このデータは、我々の製品およびEthereumエコシステムの使いやすさとユーザーエクスペリエンスを継続的に改善するために使用されます。" + }, + "mobileSyncText": { + "message": "本人認証のため、パスワードを入力してください!" + }, "mustSelectOne": { - "message": "一つ以上のトークンを選択してください。" + "message": "1つ以上のトークンを選択してください。" }, "myAccounts": { "message": "マイアカウント" }, + "myWalletAccounts": { + "message": "このウォレットのアカウント" + }, + "myWalletAccountsDescription": { + "message": "MetaMaskで作成したすべてのアカウントは、このセクションに自動的に追加されます。" + }, "needEtherInWallet": { - "message": "MetaMaskで分散型アプリケーションを使用するためには、このウォレットにEtherが必要です。" + "message": "MetaMaskで分散型アプリケーションを操作するには、ウォレットにEtherが必要です。" }, "needImportFile": { "message": "インポートするファイルを選択してください。", "description": "User is important an account and needs to add a file to continue" }, + "negativeETH": { + "message": "マイナス額のETHを送付することはできません。" + }, + "networkName": { + "message": "ネットワーク名" + }, + "networkSettingsChainIdDescription": { + "message": "チェーンIDはトランザクションの署名に使用します。チェーンIDはネットワークのチェーンIDと一致する必要があります。10進数、または'0x'を付けた16進数を入力します。表示は10進数です。" + }, + "networkSettingsDescription": { + "message": "カスタムRPCネットワークの追加と編集" + }, "networks": { "message": "ネットワーク" }, + "nevermind": { + "message": "後で試す" + }, "newAccount": { - "message": "新規アカウント" + "message": "新しいアカウント" + }, + "newAccountDetectedDialogMessage": { + "message": "新しいアカウントを検出しました!アドレス帳に追加するにはここをクリックします。" }, "newAccountNumberName": { "message": "アカウント $1", "description": "Default name of next account to be created on create account screen" }, + "newContact": { + "message": "新しい連絡先" + }, "newContract": { - "message": "新規コントラクト" + "message": "新しいコントラクト" + }, + "newNetwork": { + "message": "新しいネットワーク" }, "newPassword": { - "message": "新規パスワード(最低8文字)" + "message": "新しいパスワード(最低 8文字)" + }, + "newToMetaMask": { + "message": "MetaMaskは初めてですか?" + }, + "newTotal": { + "message": "新しい合計" + }, + "newTransactionFee": { + "message": "新しいトランザクション手数料" }, "next": { "message": "次へ" }, + "nextNonceWarning": { + "message": "Nonce $1 は提案された値より大きいです", + "description": "The next nonce according to MetaMask's internal logic" + }, + "noAccountsFound": { + "message": "指定された検索クエリでアカウントは見つかりませんでした" + }, "noAddressForName": { "message": "この名前にはアドレスが設定されていません。" }, "noAlreadyHaveSeed": { - "message": "すでにシードを持っています" + "message": "いいえ、既にシードフレーズがあります" + }, + "noConversionRateAvailable": { + "message": "どの換算レートも利用できません" + }, + "noThanks": { + "message": "やめておく" }, "noTransactions": { - "message": "トランザクションがありません。" + "message": "トランザクションがありません" }, - "password": { - "message": "パスワード" + "noWebcamFound": { + "message": "このコンピューターのウェブカメラが見つかりません。もう一度実行してください。" }, - "pastePrivateKey": { - "message": "秘密鍵をここにペーストして下さい:", - "description": "For importing an account from a private key" + "noWebcamFoundTitle": { + "message": "ウェブカメラが見つかりません" }, - "privacyMsg": { - "message": "プライバシーポリシー" + "nonceField": { + "message": "トランザクションNonceのカスタマイズ" }, - "privateKey": { - "message": "秘密鍵", - "description": "select this type of file to use to import an account" + "nonceFieldDescription": { + "message": "オンにすると、確認画面上でNonce(トランザクション番号)を変更できます。これは高度な機能です。慎重に使用してください。" }, - "privateKeyWarning": { - "message": "警告: この鍵は絶対に公開しないで下さい。公開すると、誰でもあなたのアカウント内の資産を盗むことができてしまいます。" + "nonceFieldHeading": { + "message": "カスタムNonce" + }, + "notCurrentAccount": { + "message": "これは正しいアカウントですか?現在ウォレットで選択中のアカウントと異なります" + }, + "notEnoughGas": { + "message": "Gasが不足しています" + }, + "ofTextNofM": { + "message": "of" + }, + "off": { + "message": "オフ" + }, + "offlineForMaintenance": { + "message": "メンテナンスのためにオフラインです" + }, + "ok": { + "message": "OK" + }, + "on": { + "message": "オン" + }, + "onboardingReturnNotice": { + "message": "\"$1\" はこのタブを閉じます。 $2 に戻ってください。", + "description": "Return the user to the site that initiated onboarding" + }, + "onlyAddTrustedNetworks": { + "message": "悪意のあるEthereumネットワークプロバイダは、不正なブロックチェーンによりネットワーク行動を記録することがあります。信頼できるカスタムネットワークのみを追加してください。" + }, + "onlyAvailableOnMainnet": { + "message": "メインネットのみ使用可能です" + }, + "onlyConnectTrust": { + "message": "信頼するサイトにのみ接続してください。" + }, + "optionalBlockExplorerUrl": { + "message": "ブロックエクスプローラのURL(オプション)" + }, + "optionalCurrencySymbol": { + "message": "通貨シンボル(オプション)" + }, + "orderOneHere": { + "message": "Trezor又はLedgerを注文して資金をコールドストレージに保管できます" + }, + "origin": { + "message": "要求元" + }, + "parameters": { + "message": "パラメータ" + }, + "participateInMetaMetrics": { + "message": "MetaMetricsに参加" + }, + "participateInMetaMetricsDescription": { + "message": "MetaMaskの改善のため、MetaMetricsに参加します" + }, + "password": { + "message": "パスワード" + }, + "passwordNotLongEnough": { + "message": "パスワードの長さが足りません" + }, + "passwordsDontMatch": { + "message": "パスワードが一致しません" + }, + "pastePrivateKey": { + "message": "秘密鍵をペーストして下さい:", + "description": "For importing an account from a private key" + }, + "pending": { + "message": "保留中" + }, + "permissionCheckedIconDescription": { + "message": "この許可を承認しました。" + }, + "permissionUncheckedIconDescription": { + "message": "この許可は承認を完了していません。" + }, + "permissions": { + "message": "権限" + }, + "personalAddressDetected": { + "message": "個人アドレスが検出されました。トークンコントラクトのアドレスを入力してください。" + }, + "plusXMore": { + "message": "+$1 以上", + "description": "$1 is a number of additional but unshown items in a list- this message will be shown in place of those items" + }, + "prev": { + "message": "戻る" + }, + "primaryCurrencySetting": { + "message": "基準通貨" + }, + "primaryCurrencySettingDescription": { + "message": "値の表示をチェーンの通貨(ETHなど)で優先するには、通貨(ETHなど)を選択します。選択した基準通貨を優先するには、[法定通貨] を選択します。" + }, + "privacyMsg": { + "message": "プライバシーポリシー" + }, + "privateKey": { + "message": "秘密鍵", + "description": "select this type of file to use to import an account" + }, + "privateKeyWarning": { + "message": "警告: この鍵は絶対に公開しないで下さい。公開すると、アカウント内の資産を盗まれます。" }, "privateNetwork": { - "message": "プライベート・ネットワーク" + "message": "プライベートネットワーク" + }, + "proposedApprovalLimit": { + "message": "承認限度額の提案" + }, + "protectYourKeys": { + "message": "キーを保護してください!" + }, + "protectYourKeysMessage1": { + "message": "シードフレーズは厳重に取り扱ってください。MetaMaskの偽物がWebサイトで報告されています。MetaMaskがシードフレーズを要求することは絶対にありえません!" + }, + "protectYourKeysMessage2": { + "message": "シードフレーズを厳重に保管してください。不審な点がやWebサイトについて不明確な場合は、support@metamask.io まで電子メールでお問い合わせください" + }, + "provide": { + "message": "提供する" + }, + "queue": { + "message": "保留中" + }, + "queued": { + "message": "追加済" }, "readdToken": { - "message": "アカウントのオプションメニューから「トークンを追加」すれば、将来このトークンを追加し直すことができます。" + "message": "アカウントオプションのメニューで\"トークンの追加\"を選択すると、後でこのトークンを戻すことができます。" + }, + "readyToConnect": { + "message": "接続準備はよろしいですか?" + }, + "receive": { + "message": "受け取る" + }, + "recents": { + "message": "最近の履歴" }, "recipientAddress": { - "message": "受取人アドレス" + "message": "受取アドレス" + }, + "recipientAddressPlaceholder": { + "message": "パブリックアドレス(0x)、またはENSを検索" }, "reject": { "message": "拒否" }, + "rejectAll": { + "message": "すべて拒否" + }, + "rejectTxsDescription": { + "message": "$1個のトランザクションを一括拒否しようとしています。" + }, + "rejectTxsN": { + "message": "$1個のトランザクションを拒否" + }, "rejected": { - "message": "拒否されました" + "message": "拒否しました" + }, + "remindMeLater": { + "message": "後で通知" + }, + "remove": { + "message": "削除" + }, + "removeAccount": { + "message": "アカウントの削除" + }, + "removeAccountDescription": { + "message": "このアカウントはウォレットから削除されます。続行する前に、ウォレットにインポートしたアカウントのシードフレーズか秘密鍵を保管してください。アカウントは、アカウントのドロップダウンから再度インポート、または作成できます。" + }, + "requestsAwaitingAcknowledgement": { + "message": "承認されるまで待機する" }, "required": { - "message": "必要です。" + "message": "必須" + }, + "reset": { + "message": "リセット" }, "resetAccount": { "message": "アカウントをリセット" }, + "resetAccountDescription": { + "message": "アカウントをリセットするとトランザクション履歴がクリアされます。シードフレーズの再入力は不要です。これによりアカウント内の残高が変更されることはありません。" + }, + "restore": { + "message": "復元" + }, + "restoreAccountWithSeed": { + "message": "シードフレーズでアカウントを復元" + }, "restoreFromSeed": { - "message": "パスフレーズから復元する" + "message": "アカウントを復元しますか?" + }, + "restoreWalletPreferences": { + "message": "$1 のデータバックアップが見つかりました。ウォレットの基本設定を復元しますか?", + "description": "$1 is the date at which the data was backed up" + }, + "retryTransaction": { + "message": "トランザクションを再試行" + }, + "reusedTokenNameWarning": { + "message": "既に登録されているトークンシンボルと同じシンボルの登録はお勧めしません。混乱や操作ミスの原因になります。" }, "revealSeedWords": { - "message": "パスフレーズを表示" + "message": "シードフレーズを表示" + }, + "revealSeedWordsDescription": { + "message": "ブラウザを変更したりコンピュータを変更した場合は、アカウントにアクセスするためにシードフレーズが必要になります。安全で秘密の場所に保管してください。" + }, + "revealSeedWordsTitle": { + "message": "シードフレーズ" + }, + "revealSeedWordsWarning": { + "message": "シードフレーズは全てのアカウントを盗む手段にも使えます。" + }, + "revealSeedWordsWarningTitle": { + "message": "シードフレーズは誰にも教えないでください。" }, "rinkeby": { "message": "Rinkebyテストネットワーク" @@ -375,38 +1343,150 @@ "ropsten": { "message": "Ropstenテストネットワーク" }, + "rpcUrl": { + "message": "RPC URL" + }, "save": { "message": "保存" }, + "saveAsCsvFile": { + "message": "CSVファイルとして保存" + }, + "scanInstructions": { + "message": "カメラでQRコードを置いてください" + }, + "scanQrCode": { + "message": "QRコードのスキャン" + }, + "scrollDown": { + "message": "下へスクロール" + }, "search": { "message": "検索" }, + "searchAccounts": { + "message": "アカウントの検索" + }, "searchResults": { "message": "検索結果" }, "searchTokens": { "message": "トークンの検索" }, - "selectCurrency": { - "message": "通貨を選択" + "secretBackupPhrase": { + "message": "シードフレーズのバックアップ" + }, + "secretBackupPhraseDescription": { + "message": "シードフレーズを使用すると、アカウントのバックアップと復元が簡単になります。" + }, + "secretBackupPhraseWarning": { + "message": "警告:シードフレーズは絶対に公開しないでください。シードフレーズを使うと、誰でもアカウントからETHを盗み出せます。" + }, + "secretPhrase": { + "message": "アカウント情報を復元するには、12単語で構成されたシードフレーズを入力してください。" + }, + "securityAndPrivacy": { + "message": "セキュリティとプライバシー" + }, + "securitySettingsDescription": { + "message": "プライバシーの設定とウォレットのシードフレーズ" + }, + "seedPhrasePlaceholder": { + "message": "シードフレーズを単語ごとに半角スペースで分割して入力して下さい" + }, + "seedPhrasePlaceholderPaste": { + "message": "シードフレーズをクリップボードからペーストして下さい" + }, + "seedPhraseReq": { + "message": "シードフレーズには、12,15,18,21、または24単語が含まれます" + }, + "selectAHigherGasFee": { + "message": "トランザクションの処理を早めるには、より高いガス料金を選択してください。" + }, + "selectAccounts": { + "message": "アカウントを選択してください" + }, + "selectAll": { + "message": "すべて選択" + }, + "selectAnAccount": { + "message": "アカウントを1個選択" + }, + "selectAnAccountHelp": { + "message": "MetaMaskで表示するアカウントを選択してください" + }, + "selectEachPhrase": { + "message": "単語を選択して、各フレーズが正しいことを確認してください。" + }, + "selectHdPath": { + "message": "HDパスの選択" + }, + "selectPathHelp": { + "message": "既存のLedgerのアカウントが以下に表示されない場合は、パスを \"Legacy (MEW / MyCrypto)\" に変えてください。" }, "selectType": { - "message": "キーの種類" + "message": "形式の選択" + }, + "selectingAllWillAllow": { + "message": "すべてを選択すると、このサイトは現在の全アカウントを見ることができます。サイトが信頼できるか確認してください。" }, "send": { - "message": "送信" + "message": "送る" + }, + "sendAmount": { + "message": "送金額" }, "sendETH": { - "message": "ETHの送信" + "message": "ETHの送金" + }, + "sendSpecifiedTokens": { + "message": "$1 を送る", + "description": "Symbol of the specified token" }, "sendTokens": { - "message": "トークンを送信" + "message": "トークンを送る" + }, + "sentEther": { + "message": "Etherの送金" + }, + "separateEachWord": { + "message": "単語ごとに1文字のスペースで分離してください" }, "settings": { "message": "設定" }, + "showAdvancedGasInline": { + "message": "高度なGasの設定" + }, + "showAdvancedGasInlineDescription": { + "message": "オンにするとGas価格とGasリミットが送金画面と確認画面に直接表示されます。" + }, + "showFiatConversionInTestnets": { + "message": "テストネットで法定通貨換算額を表示" + }, + "showFiatConversionInTestnetsDescription": { + "message": "オンにすると、テストネットで法定通貨換算額を表示します" + }, + "showHexData": { + "message": "16進データの表示" + }, + "showHexDataDescription": { + "message": "オンにすると、送金画面に16進データフィールドを表示します" + }, + "showIncomingTransactions": { + "message": "着信したトランザクションの表示" + }, + "showIncomingTransactionsDescription": { + "message": "オンにすると、Etherscanを使用して、着信トランザクションをトランザクションリストに表示します" + }, + "showPermissions": { + "message": "権限の表示" + }, "showPrivateKeys": { - "message": "秘密鍵を表示" + "message": "秘密鍵の表示" + }, + "showSeedPhrase": { + "message": "シードフレーズの表示" }, "sigRequest": { "message": "署名リクエスト" @@ -415,64 +1495,639 @@ "message": "署名" }, "signNotice": { - "message": "このメッセージへの署名は危険となる可能性があります。\n完全に信頼するサイトからのメッセージのみ、\nあなたのアカウントで署名して下さい。今後のバージョンでは、\nこの危険なメソッドは削除される予定です。" + "message": "メッセージへの署名は、アカウント全体に対して危険な副作用を起こす可能性があります。\n完全に信頼できるサイトからのメッセージのみに署名してください。\nこの方法は危険です。将来のバージョンでは削除されます。" }, "signatureRequest": { "message": "署名リクエスト" }, + "signatureRequest1": { + "message": "メッセージ" + }, + "signed": { + "message": "署名が完了しました" + }, + "slow": { + "message": "低速" + }, + "somethingWentWrong": { + "message": "おおぅ!問題が発生しました。" + }, + "speedUp": { + "message": "高速化" + }, + "speedUpCancellation": { + "message": "キャンセルを高速化" + }, + "speedUpTransaction": { + "message": "トランザクションを高速化" + }, + "spendLimitAmount": { + "message": "使用限度額" + }, + "spendLimitInsufficient": { + "message": "使用限度額が不十分です" + }, + "spendLimitInvalid": { + "message": "使用限度額が無効です。正の数値をである必要があります" + }, + "spendLimitPermission": { + "message": "使用限度額の許可" + }, + "spendLimitRequestedBy": { + "message": "使用限度額が $1 によって要求されました", + "description": "Origin of the site requesting the spend limit" + }, + "spendLimitTooLarge": { + "message": "使用限度額が多すぎます" + }, + "stateLogError": { + "message": "状態ログの検索中にエラーが発生しました。" + }, + "stateLogFileName": { + "message": "MetaMask State Logs" + }, + "stateLogs": { + "message": "状態ログ" + }, + "stateLogsDescription": { + "message": "状態ログには、アカウントアドレスと送信済みトランザクションが含まれています。" + }, + "statusConnected": { + "message": "接続済" + }, + "statusNotConnected": { + "message": "未接続" + }, + "step1HardwareWallet": { + "message": "1.ハードウェア ウォレットの接続" + }, + "step1HardwareWalletMsg": { + "message": "コンピューターに直接ハードウェアウォレットを接続してください。" + }, + "step2HardwareWallet": { + "message": "2.アカウントを選択" + }, + "step2HardwareWalletMsg": { + "message": "読取るアカウントを1つ選択します。" + }, + "step3HardwareWallet": { + "message": "3.web3を使用してサイトに接続しましょう!" + }, + "step3HardwareWalletMsg": { + "message": "Ethereumアカウントと同じように、ハードウェアアカウントを使用します。web3サイトに接続してETH を送金し、ERC20トークンやCryptoKittiesのようなトークンを購入して保管できます。" + }, + "storePhrase": { + "message": "このフレーズを1Passwordのようなパスワードマネージャーに保管てください。" + }, + "submit": { + "message": "送信" + }, + "submitted": { + "message": "送信済み" + }, + "supportCenter": { + "message": "サポートセンターへ移動" + }, + "swap": { + "message": "スワップ" + }, + "swapAdvancedSlippageInfo": { + "message": "注文した時点と注文が承認された時点で価格が変わることをスリッページと呼びます。スリッページが最大スリッページ設定を超えると、スワップは自動的にキャンセルされます。" + }, + "swapAggregator": { + "message": "アグリゲータ" + }, + "swapAmountReceived": { + "message": "受け取り保証額" + }, + "swapAmountReceivedInfo": { + "message": "これは受け取る最低額です。スリッページに基づいて、それ以上の額を受け取ることができます。" + }, + "swapApproval": { + "message": "$1 のスワップを承認", + "description": "Used in the transaction display list to describe a transaction that is an approve call on a token that is to be swapped.. $1 is the symbol of a token that has been approved." + }, + "swapApproveNeedMoreTokens": { + "message": "このスワップを完了するには、さらに $1 の $2 が必要です。", + "description": "Tells the user how many more of a given token they need for a specific swap. $1 is an amount of tokens and $2 is the token symbol." + }, + "swapBetterQuoteAvailable": { + "message": "より良い見積があります。" + }, + "swapBuildQuotePlaceHolderText": { + "message": "$1 と一致するトークンがありません", + "description": "Tells the user that a given search string does not match any tokens in our token lists. $1 can be any string of text" + }, + "swapCheckingQuote": { + "message": "$1 をチェック中", + "description": "Shown to the user during quote loading. $1 is the name of an aggregator. The message indicates that metamask is currently checking if that aggregator has a trade/quote for their requested swap." + }, + "swapCustom": { + "message": "カスタム" + }, + "swapDecentralizedExchange": { + "message": "分散型取引所" + }, + "swapEditLimit": { + "message": "限度額の変更" + }, + "swapEnableDescription": { + "message": "MetaMaskで $1 のスワップを許可します。(必須)", + "description": "Gives the user info about the required approval transaction for swaps. $1 will be the symbol of a token being approved for swaps." + }, + "swapEstimatedNetworkFee": { + "message": "推定のネットワーク手数料" + }, + "swapEstimatedNetworkFeeSummary": { + "message": "“$1”は現状から予測された手数料です。正確な額はネットワーク状態によって変わります。", + "description": "$1 will be the translation of swapEstimatedNetworkFee, with the font bolded" + }, + "swapEstimatedNetworkFees": { + "message": "推定のネットワーク手数料" + }, + "swapEstimatedNetworkFeesInfo": { + "message": "これは、スワップを完了するために使用されるネットワーク手数料の推定値です。実際の額はネットワークの状態によって変わる可能性があります。" + }, + "swapFailedErrorTitle": { + "message": "スワップに失敗しました" + }, + "swapFetchingQuotesErrorDescription": { + "message": "ぐぬぬ...問題が発生しました。もう一度実行してください。エラーが解決しななければ、カスタマサポート担当者へお問い合わせください。" + }, + "swapFetchingQuotesErrorTitle": { + "message": "見積の取得エラー" + }, + "swapFetchingTokens": { + "message": "トークンを取り出し中..." + }, + "swapFinalizing": { + "message": "終了中..." + }, + "swapHighSlippageWarning": { + "message": "非常に大きいスリッページ額です。本当に実行するか確認してください。" + }, + "swapIntroLearnMoreHeader": { + "message": "詳細を表示しますか?" + }, + "swapIntroLearnMoreLink": { + "message": "MetaMask Swapsの詳細" + }, + "swapIntroLiquiditySourcesLabel": { + "message": "流動性ソースには以下が含まれます。" + }, + "swapIntroPopupSubTitle": { + "message": "トークンをMetaMaskで直接スワップできるようになりました。MetaMask Swapsは、多数の分散型取引所アグリゲーター、専門のマーケットメーカー、DEX取引所を統合し、ユーザーは常に最低のネットワーク手数料、最適な価格で取引できます。" + }, + "swapIntroPopupTitle": { + "message": "トークンのスワップはこちら!" + }, + "swapLearnMoreContractsAuditReview": { + "message": "MetaSwapのコントラクト監査のレビュー" + }, + "swapLowSlippageError": { + "message": "トランザクションが失敗する可能性があります。最大スリッページが少なすぎます。" + }, + "swapMaxNetworkFeeInfo": { + "message": " $1 は最大支払額です。ネットワークのボラビリティが高いと、大きな値になることがあります。", + "description": "$1 will be the translation of swapMaxNetworkFees, with the font bolded" + }, + "swapMaxNetworkFees": { + "message": "最大ネットワーク手数料" + }, + "swapMaxSlippage": { + "message": "最大スリッページ" + }, + "swapMetaMaskFee": { + "message": "MetaMask手数料" + }, + "swapMetaMaskFeeDescription": { + "message": "MetaMaskは取引毎に最上位の流動性の供給者から最良価格を探します。見積には $1% の手数料が自動的に組み込まれ、MetaMaskの将来の開発をサポートします。", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapNQuotes": { + "message": "$1個の見積", + "description": "$1 is the number of quotes that the user can select from when opening the list of quotes on the 'view quote' screen" + }, + "swapNetworkFeeSummary": { + "message": "ネットワーク手数料には、スワップの結果をEthereumネットワークに保管する費用も含まれています。MetaMaskは手数料から利益を得ません。" + }, + "swapNewQuoteIn": { + "message": "見積の有効期限 $1", + "description": "Tells the user the amount of time until the currently displayed quotes are update. $1 is a time that is counting down from 1:00 to 0:00" + }, + "swapOnceTransactionHasProcess": { + "message": "このトランザクション処理を完了すると、$1 がアカウントに追加されます。", + "description": "This message communicates the token that is being transferred. It is shown on the awaiting swap screen. The $1 will be a token symbol." + }, + "swapPriceDifference": { + "message": "$1 $2 ($3) を $4 $5 ($6)にスワップします。", + "description": "This message represents the price slippage for the swap. $1 and $4 are a number (ex: 2.89), $2 and $5 are symbols (ex: ETH), and $3 and $6 are fiat currency amounts." + }, + "swapPriceDifferenceTitle": { + "message": "価格差は $1% です", + "description": "$1 is a number (ex: 1.23) that represents the price difference." + }, + "swapPriceDifferenceTooltip": { + "message": "市場価格の違いは、仲介業者が負担する手数料、市場規模、取引量、または取引価格差の影響を受けることがあります。" + }, + "swapPriceDifferenceUnavailable": { + "message": "マーケット価格は利用できません。続行する前に、返金額に問題がないことを確認してください。" + }, + "swapProcessing": { + "message": "処理中" + }, + "swapQuoteDetails": { + "message": "見積の詳細" + }, + "swapQuoteDetailsSlippageInfo": { + "message": "注文した時点と注文が承認された時点で価格が変わることを\"スリッページ\"と呼びます。スリッページが\"最大スリッページ\"設定を超える場合、スワップは自動的にキャンセルされます。" + }, + "swapQuoteIncludesRate": { + "message": "見積には $1% のMetaMask手数料が含まれています", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapQuoteNofN": { + "message": "$2個中の $1個の見積", + "description": "A count of loaded quotes shown to the user while they are waiting for quotes to be fetched. $1 is the number of quotes already loaded, and $2 is the total number of quotes to load." + }, + "swapQuoteSource": { + "message": "取引ソース" + }, + "swapQuotesAreRefreshed": { + "message": "現在のマーケット状態を反映して、見積はリアルタイム更新されます。" + }, + "swapQuotesExpiredErrorDescription": { + "message": "最新のレートで見積を取得するには再試行してください。" + }, + "swapQuotesExpiredErrorTitle": { + "message": "見積のタイムアウト" + }, + "swapQuotesNotAvailableErrorDescription": { + "message": "取引額を調整するかスリッページを再設定して、もう一度実行してください。" + }, + "swapQuotesNotAvailableErrorTitle": { + "message": "見積を取得できません" + }, + "swapRate": { + "message": "レート" + }, + "swapReceiving": { + "message": "受取額" + }, + "swapReceivingInfoTooltip": { + "message": "これは推定値です。正確な額はスリッページによって異なります。" + }, + "swapRequestForQuotation": { + "message": "見積の要求" + }, + "swapSearchForAToken": { + "message": "トークンを検索" + }, + "swapSelect": { + "message": "選択" + }, + "swapSelectAQuote": { + "message": "見積の選択" + }, + "swapSelectAToken": { + "message": "トークンの選択" + }, + "swapSelectQuotePopoverDescription": { + "message": "以下は複数の流動性ソースから収集したすべての見積です。" + }, + "swapSlippageTooLow": { + "message": "スリッページは 0 より多くする必要があります。" + }, + "swapSource": { + "message": "流動性ソース" + }, + "swapSourceInfo": { + "message": "最良のレートと最小のネットワーク手数料を探すため、複数の流動性ソース(取引所、アグリゲーター、専門のマーケットメーカー)を検索します。" + }, + "swapStartSwapping": { + "message": "スワップの開始" + }, + "swapSwapFrom": { + "message": "スワップ元" + }, + "swapSwapSwitch": { + "message": "スワップ先と元の交換" + }, + "swapSwapTo": { + "message": "スワップ先" + }, + "swapThisWillAllowApprove": { + "message": "$1 のスワップが可能になります。" + }, + "swapTokenAvailable": { + "message": "$1 がアカウントに追加されました。", + "description": "This message is shown after a swap is successful and communicates the exact amount of tokens the user has received for a swap. The $1 is a decimal number of tokens followed by the token symbol." + }, + "swapTokenToToken": { + "message": "$1 を $2 にスワップ", + "description": "Used in the transaction display list to describe a swap. $1 and $2 are the symbols of tokens in involved in a swap." + }, + "swapTransactionComplete": { + "message": "トランザクションが完了しました" + }, + "swapUnknown": { + "message": "不明" + }, + "swapUsingBestQuote": { + "message": "最適な見積を使用する" + }, + "swapVerifyTokenExplanation": { + "message": "複数のトークンが同じ名前とシンボルであることがあります。Etherscanで実際のトークンでを確認してください。" + }, + "swapViewToken": { + "message": "$1 を表示" + }, + "swapYourTokenBalance": { + "message": "$1 $2 はスワップに使用できます", + "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" + }, + "swapZeroSlippage": { + "message": "0% スリッページ" + }, + "swapsAdvancedOptions": { + "message": "詳細オプション" + }, + "swapsExcessiveSlippageWarning": { + "message": "スリッページが大きすぎてレートが悪化しています。スリッページ最大値を 15% 未満にしてください。" + }, + "swapsMaxSlippage": { + "message": "最大スリッページ" + }, + "swapsNotEnoughForTx": { + "message": "トランザクションを完了するには $1 は不十分です。", + "description": "Tells the user that they don't have enough of a token for a proposed swap. $1 is a token symbol" + }, + "swapsViewInActivity": { + "message": "アクティビティの表示" + }, + "switchNetworks": { + "message": "ネットワークを切替え" + }, + "switchToThisAccount": { + "message": "このアカウントへ切替え" + }, + "symbol": { + "message": "シンボル" + }, + "symbolBetweenZeroTwelve": { + "message": "シンボルは11文字以下にする必要があります。" + }, + "syncWithMobile": { + "message": "モバイルアプリと同期" + }, + "syncWithMobileBeCareful": { + "message": "コードをスキャンする前に、誰にも画面を見られていないことを確認してください" + }, + "syncWithMobileComplete": { + "message": "データの同期に成功しました。MetaMaskモバイルアプリを利用できます!" + }, + "syncWithMobileDesc": { + "message": "アカウントと情報をスマートフォンアプリと同期させることができます。MetaMaskモバイルアプリを開き、\"設定\" に進み、\"ブラウザー拡張機能から同期\" をタップします。" + }, + "syncWithMobileDescNewUsers": { + "message": "MetaMaskモバイルアプリを初めて使用する場合は、スマートフォンを以下のステップに従って操作してください。" + }, + "syncWithMobileScanThisCode": { + "message": "MetaMaskモバイルアプリでこのコードをスキャンしてください" + }, + "syncWithMobileTitle": { + "message": "モバイルアプリとの同期" + }, + "syncWithThreeBox": { + "message": "データを3Boxと同期(試験中)" + }, + "syncWithThreeBoxDescription": { + "message": "オンにすると、設定が3Box でバックアップされます。この機能は試験中です。ご自身の責任で使用してください。" + }, + "syncWithThreeBoxDisabled": { + "message": "3Boxは、初期同期のエラーにより、使用不能です。" + }, "terms": { "message": "利用規約" }, + "termsOfService": { + "message": "サービス利用規約" + }, "testFaucet": { - "message": "Faucetをテスト" + "message": "テストFaucet" + }, + "thisWillCreate": { + "message": "新しいウォレットとシードフレーズが作成されます" + }, + "tips": { + "message": "ヒント" }, "to": { - "message": "送信先" + "message": "受信先" + }, + "toAddress": { + "message": "受信先:$1", + "description": "$1 is the address to include in the To label. It is typically shortened first using shortenAddress" + }, + "toWithColon": { + "message": "受信先:" }, "token": { "message": "トークン" }, + "tokenAlreadyAdded": { + "message": "トークンは既に追加されています。" + }, + "tokenContractAddress": { + "message": "トークンコントラクトのアドレス" + }, + "tokenOptions": { + "message": "トークンのオプション" + }, "tokenSymbol": { "message": "トークンシンボル" }, "total": { "message": "合計" }, + "transaction": { + "message": "トランザクション" + }, + "transactionCancelAttempted": { + "message": "トランザクションのキャンセルをGas料金 $1 で試みました。$2" + }, + "transactionCancelSuccess": { + "message": "トランザクションのキャンセルが成功しました。$2" + }, + "transactionConfirmed": { + "message": "トランザクションが確定しました。$2" + }, + "transactionCreated": { + "message": "トランザクションは $1 の値を作成しました。$2" + }, + "transactionDropped": { + "message": "トランザクションは削除されました。$2" + }, + "transactionError": { + "message": "トランザクションエラー。コントラクトコードで例外がスローされました。" + }, + "transactionErrorNoContract": { + "message": "コントラクト外アドレスに対して関数呼出を試みています。" + }, + "transactionErrored": { + "message": "トランザクションでエラーが発生しました。" + }, + "transactionFee": { + "message": "トランザクション手数料" + }, + "transactionResubmitted": { + "message": "トランザクションを追加Gas料金: $1 で再送信しました。$2" + }, + "transactionSubmitted": { + "message": "トランザクションがGas料金 $1 で送信されました。$2" + }, + "transactionUpdated": { + "message": "トランザクションが更新されました。$2" + }, + "transfer": { + "message": "転送" + }, + "transferBetweenAccounts": { + "message": "自分のアカウント間での移動" + }, + "transferFrom": { + "message": "転送元" + }, + "troubleConnectingToWallet": { + "message": "$1 への接続に失敗しました。 $2 を再確認して、もう一度実行してください。", + "description": "$1 is the wallet device name; $2 is a link to wallet connection guide" + }, "troubleTokenBalances": { "message": "トークン残高を取得できません。こちらでご確認ください。", "description": "Followed by a link (here) to view token balances" }, + "trustSiteApprovePermission": { + "message": "このサイトを信頼しますか?許可を与えることにより、$1 は $2 の支払トランザクションを自動化します。", + "description": "$1 is the url requesting permission and $2 is the symbol of the currency that the request is for" + }, + "tryAgain": { + "message": "再試行" + }, "typePassword": { - "message": "パスワードの入力" + "message": "MetaMaskのパスワードを入力" + }, + "unapproved": { + "message": "未承認" + }, + "units": { + "message": "単位" }, "unknown": { "message": "不明" }, + "unknownCameraError": { + "message": "カメラにアクセスしているときにエラーが発生しました。もう一度実行してください。" + }, + "unknownCameraErrorTitle": { + "message": "おおぅ!問題が発生しました。" + }, "unknownNetwork": { "message": "不明なプライベートネットワーク" }, + "unknownQrCode": { + "message": "エラー:QRコードを識別できませんでした" + }, + "unlimited": { + "message": "無制限" + }, "unlock": { - "message": "ログイン" + "message": "ロック解除" + }, + "unlockMessage": { + "message": "分散型Webが待っています" + }, + "updatedWithDate": { + "message": "$1 に更新しました" + }, + "urlErrorMsg": { + "message": "URLには適切なHTTP/HTTPSプレフィックスが必要です。" + }, + "urlExistsErrorMsg": { + "message": "URLはネットワークリストに既に存在します" + }, + "usePhishingDetection": { + "message": "フィッシング検出を使用" + }, + "usePhishingDetectionDescription": { + "message": "Ethereumユーザーを対象としたドメインのフィッシングに対して警告を表示します" }, "usedByClients": { - "message": "様々なクライアントによって使用されています。" + "message": "Ethereumクライアントなどで使用されています。" + }, + "userName": { + "message": "ユーザー名" + }, + "verifyThisTokenOn": { + "message": "トークンを $1 で検証する", + "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" }, "viewAccount": { - "message": "アカウントを見る" + "message": "アカウントを表示" + }, + "viewContact": { + "message": "連絡先を表示" + }, + "viewOnCustomBlockExplorer": { + "message": "$1 で表示" }, "viewOnEtherscan": { - "message": "Etherscan で見る" + "message": "Etherscanで表示" + }, + "viewinExplorer": { + "message": "Explorerで表示" + }, + "visitWebSite": { + "message": "ウェブサイト" + }, + "walletConnectionGuide": { + "message": "ハードウェアウォレット接続ガイド" }, "walletSeed": { - "message": "ウォレットのパスフレーズ" + "message": "シードフレーズ" + }, + "web3ShimUsageNotification": { + "message": "このサイトは削除されたwindow.web3 APIを使用します。サイトに問題が発生しているなら、$1 で詳細を見ることができます。", + "description": "$1 is a clickable link." }, "welcome": { - "message": "MetaMask ベータ版へようこそ!" + "message": "MetaMaskへようこそ!" }, "welcomeBack": { "message": "おかえりなさい!" }, + "whatsThis": { + "message": "これは何ですか?" + }, + "writePhrase": { + "message": "このパスフレーズを紙に書いて、安全な場所に保管してください。セキュリティが必要な場合は、フレーズを分割して複数の紙に書き、それぞれを別の場所に保管します。" + }, + "xOfY": { + "message": "$1 / $2", + "description": "$1 and $2 are intended to be two numbers, where $2 is a total, and $1 is a count towards that total" + }, + "yesLetsTry": { + "message": "試す" + }, + "youNeedToAllowCameraAccess": { + "message": "この機能を使用するには、カメラへのアクセスを許可が必要です。" + }, "youSign": { - "message": "署名しています。" + "message": "署名しています" + }, + "yourPrivateSeedPhrase": { + "message": "秘密のシードフレーズ" + }, + "zeroGasPriceOnSpeedUpError": { + "message": "追加のGas価格を0にできません" } } diff --git a/app/_locales/kn/messages.json b/app/_locales/kn/messages.json index 4c3a9add5..66c6b4358 100644 --- a/app/_locales/kn/messages.json +++ b/app/_locales/kn/messages.json @@ -931,18 +931,12 @@ "selectAnAccountHelp": { "message": "MetaMask ನಲ್ಲಿ ವೀಕ್ಷಿಸಲು ಖಾತೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ" }, - "selectCurrency": { - "message": "ಕರೆನ್ಸಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ" - }, "selectEachPhrase": { "message": "ಅದು ಸರಿಯಾಗಿದೆಯೆ ಎಂಬುದನ್ನು ಖಚಿತಪಡಿಸಿಕೊಳ್ಳಲು ದಯವಿಟ್ಟು ಪ್ರತಿ ಫ್ರೇಸ್ ಅನ್ನು ಆಯ್ಕೆಮಾಡಿ." }, "selectHdPath": { "message": "HD ಪಾತ್ ಆಯ್ಕೆಮಾಡಿ" }, - "selectLocale": { - "message": "ಪ್ರದೇಶವನ್ನು ಆಯ್ಕೆಮಾಡಿ" - }, "selectPathHelp": { "message": "ನಿಮ್ಮ ಅಸ್ತಿತ್ವದಲ್ಲಿರುವ ಲೆಡ್ಜರ್ ಖಾತೆಗಳನ್ನು ನೀವು ಕೆಳಗೆ ನೋಡದಿದ್ದರೆ, ಪಾತ್‌ಗಳನ್ನು \"ಲೆಗಸಿ (MEW / MyCrypto)\" ಗೆ ಬದಲಾಯಿಸಲು ಪ್ರಯತ್ನಿಸಿ" }, diff --git a/app/_locales/ko/messages.json b/app/_locales/ko/messages.json index 5e0e307ac..e389148ed 100644 --- a/app/_locales/ko/messages.json +++ b/app/_locales/ko/messages.json @@ -1403,18 +1403,12 @@ "selectAnAccountHelp": { "message": "MetaMask에서 확인할 계정 선택" }, - "selectCurrency": { - "message": "통화 선택" - }, "selectEachPhrase": { "message": "각 구문을 선택하여 구문이 올바른지 확인하세요." }, "selectHdPath": { "message": "HD 경로 선택" }, - "selectLocale": { - "message": "로캘 선택" - }, "selectPathHelp": { "message": "아래에 기존 Ledger 계정이 표시되지 않는다면 경로를 \"Legacy(MEW / MyCrypto)\"로 변경해 보세요." }, @@ -1639,9 +1633,6 @@ "swapEstimatedNetworkFeesInfo": { "message": "스왑을 완료하는 데 사용할 네트워크 요금 예상치입니다. 실제 금액은 네트워크 조건에 따라 달라질 수 있습니다." }, - "swapFailedErrorDescription": { - "message": "자금은 안전하며 지갑에서 계속 사용할 수 있습니다." - }, "swapFailedErrorTitle": { "message": "스왑 실패" }, diff --git a/app/_locales/lt/messages.json b/app/_locales/lt/messages.json index 062f00060..f6bf6ef41 100644 --- a/app/_locales/lt/messages.json +++ b/app/_locales/lt/messages.json @@ -931,18 +931,12 @@ "selectAnAccountHelp": { "message": "Pasirinkite paskyrą peržiūrėti „MetaMask“" }, - "selectCurrency": { - "message": "Pasirinkite valiutą" - }, "selectEachPhrase": { "message": "Pasirinkite kiekvieną frazę, kad patikrintumėte, ar ji tinkama" }, "selectHdPath": { "message": "Pasirinkite HD kelią" }, - "selectLocale": { - "message": "Pasirinkite lokalę" - }, "selectPathHelp": { "message": "Jeigu toliau nematote savo esamų operacijų sąskaitų, mėginkite pakeisti kelius į „Legacy (MEW / MyCrypto)“" }, diff --git a/app/_locales/lv/messages.json b/app/_locales/lv/messages.json index f0000fadc..73497939b 100644 --- a/app/_locales/lv/messages.json +++ b/app/_locales/lv/messages.json @@ -927,18 +927,12 @@ "selectAnAccountHelp": { "message": "Atlasiet kontu, ko skatīt MetaMask" }, - "selectCurrency": { - "message": "Atlasiet valūtu" - }, "selectEachPhrase": { "message": "Lūdzu, atlasiet katru frāzi, lai pārliecinātos par tās pareizību." }, "selectHdPath": { "message": "Atlasīt HD ceļu" }, - "selectLocale": { - "message": "Izvēlieties lokalizāciju" - }, "selectPathHelp": { "message": "Ja zemāk neredzat savus esošos žurnāla kontus, mēģiniet pārslēgt ceļus uz \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/ms/messages.json b/app/_locales/ms/messages.json index 5c1c373ef..a3e9b340c 100644 --- a/app/_locales/ms/messages.json +++ b/app/_locales/ms/messages.json @@ -908,18 +908,12 @@ "selectAnAccountHelp": { "message": "Pilih akaun untuk dilihat dalam MetaMask" }, - "selectCurrency": { - "message": "Pilih Mata Wang" - }, "selectEachPhrase": { "message": "Sila pilih setiap ungkapan untuk memastikan ia betul." }, "selectHdPath": { "message": "Pilih Laluan HD" }, - "selectLocale": { - "message": "Pilih Penempatan" - }, "selectPathHelp": { "message": "Jika anda tidak melihat akaun Ledger sedia ada anda di bawah, cuba tukar laluan kepada \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/nl/messages.json b/app/_locales/nl/messages.json index 3ed69643b..1c20ec2f5 100644 --- a/app/_locales/nl/messages.json +++ b/app/_locales/nl/messages.json @@ -56,7 +56,7 @@ "message": "Contractimplementatie" }, "copiedExclamation": { - "message": "Gekopieerde!" + "message": "Gekopieerd!" }, "copyPrivateKey": { "message": "Dit is uw privésleutel (klik om te kopiëren)" @@ -163,7 +163,7 @@ "message": " Geïmporteerde accounts worden niet gekoppeld aan de seedphrase van uw oorspronkelijk gemaakte MetaMask-account. Meer informatie over geïmporteerde accounts" }, "imported": { - "message": "geïmporteerde", + "message": "geïmporteerd", "description": "status showing that an account has been fully loaded into the keyring" }, "infoHelp": { @@ -317,9 +317,6 @@ "seedPhraseReq": { "message": "Back-up woorden zijn 12 woorden lang" }, - "selectCurrency": { - "message": "selecteer valuta" - }, "selectType": { "message": "Selecteer type" }, diff --git a/app/_locales/no/messages.json b/app/_locales/no/messages.json index 8beaa8933..936ffbb5a 100644 --- a/app/_locales/no/messages.json +++ b/app/_locales/no/messages.json @@ -915,18 +915,12 @@ "selectAnAccountHelp": { "message": "Velg konto for å vise i MetaMask" }, - "selectCurrency": { - "message": "Velg valuta" - }, "selectEachPhrase": { "message": "Velg hver frase for å kontrollere at den er riktig." }, "selectHdPath": { "message": "Velg HD-bane" }, - "selectLocale": { - "message": "Velg plassering" - }, "selectPathHelp": { "message": "Hvis du ikke ser de eksisterende Ledger-kontoene nedenfor, kan du prøve å bytte baner til «Legacy (MEW/MyCrypto)»" }, diff --git a/app/_locales/pl/messages.json b/app/_locales/pl/messages.json index ac2c8d18b..f45639fc4 100644 --- a/app/_locales/pl/messages.json +++ b/app/_locales/pl/messages.json @@ -925,18 +925,12 @@ "selectAnAccountHelp": { "message": "Wybierz konto do przeglądania w MetaMask" }, - "selectCurrency": { - "message": "Wybierz walutę" - }, "selectEachPhrase": { "message": "Wybierz każdą frazę, aby upewnić się, że jest poprawna." }, "selectHdPath": { "message": "Wybierz ścieżkę HD" }, - "selectLocale": { - "message": "Wybierz lokalizację" - }, "selectPathHelp": { "message": "Jeśli nie widzisz poniżej swoich kont Ledger, spróbuj przełączyć się na \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/pt/messages.json b/app/_locales/pt/messages.json index 1e3d1e63b..ca1cca50f 100644 --- a/app/_locales/pt/messages.json +++ b/app/_locales/pt/messages.json @@ -327,9 +327,6 @@ "seedPhraseReq": { "message": "seed phrases are 12 words long" }, - "selectCurrency": { - "message": "Selecionar Moeda" - }, "selectType": { "message": "Selecionar Tipo" }, diff --git a/app/_locales/pt_BR/messages.json b/app/_locales/pt_BR/messages.json index e61b29f4b..e09fd0861 100644 --- a/app/_locales/pt_BR/messages.json +++ b/app/_locales/pt_BR/messages.json @@ -919,18 +919,12 @@ "selectAnAccountHelp": { "message": "Selecione a conta para ver no MetaMask" }, - "selectCurrency": { - "message": "Selecione a Moeda" - }, "selectEachPhrase": { "message": "Selecione cada frase para se certificar de que esteja correta." }, "selectHdPath": { "message": "Selecione o caminho no HD" }, - "selectLocale": { - "message": "Selecionar Local" - }, "selectPathHelp": { "message": "Se não conseguir ver as contas da Ledger existentes abaixo, experimente alternar os caminhos para \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/ro/messages.json b/app/_locales/ro/messages.json index efa1eed9b..7a8ce67d5 100644 --- a/app/_locales/ro/messages.json +++ b/app/_locales/ro/messages.json @@ -918,18 +918,12 @@ "selectAnAccountHelp": { "message": "Selectați contul de vizualizat în MetaMask" }, - "selectCurrency": { - "message": "Selectați moneda" - }, "selectEachPhrase": { "message": "Vă rugăm să selectați fiecare expresie pentru a vă asigura că este corectă." }, "selectHdPath": { "message": "Selectare cale HD" }, - "selectLocale": { - "message": "Alegeți setările regionale" - }, "selectPathHelp": { "message": "Dacă nu vedeți mai jos conturile dvs. Ledger existente, încercați să comutați calea la „Legacy (MEW / MyCrypto)”" }, diff --git a/app/_locales/ru/messages.json b/app/_locales/ru/messages.json index 8d354ea34..37a32d357 100644 --- a/app/_locales/ru/messages.json +++ b/app/_locales/ru/messages.json @@ -1,33 +1,50 @@ { "about": { - "message": "О нас" + "message": "Общие сведения" }, "aboutSettingsDescription": { - "message": "О выпуске, поддержка и контакты" + "message": "Версия, центр поддержки и контактная информация" }, "acceleratingATransaction": { - "message": "* Увеличение цены газа повышает шансы на более быструю обработку в сети, но это не гарантируется." + "message": "* Ускорение транзакции за счет более высокой цены на топливо увеличивает ее шансы на более быструю обработку в сети, но это не всегда гарантируется." + }, + "acceptTermsOfUse": { + "message": "Я прочитал и согласен с $1", + "description": "$1 is the `terms` message" + }, + "accessAndSpendNotice": { + "message": "$1 может получить доступ и потратить до этой максимальной суммы", + "description": "$1 is the url of the site requesting ability to spend" }, "accessingYourCamera": { - "message": "Доступ к вашей камере ..." + "message": "Доступ к камере..." }, "account": { "message": "Счет" }, "accountDetails": { - "message": "Детали счета" + "message": "Реквизиты счета" }, "accountName": { "message": "Название счета" }, "accountOptions": { - "message": "Настройки аккаунта" + "message": "Опции счета" }, "accountSelectionRequired": { - "message": "Вам необходимо выбрать учетную запись!" + "message": "Вам необходимо выбрать счет!" + }, + "active": { + "message": "Активный" + }, + "activity": { + "message": "Активность" }, "activityLog": { - "message": "Журнал событий" + "message": "Журнал активности" + }, + "addAccount": { + "message": "Добавить счет" }, "addAcquiredTokens": { "message": "Добавьте токены, которые вы приобрели с помощью MetaMask" @@ -48,7 +65,7 @@ "message": "Добавить в адресную книгу" }, "addToAddressBookModalPlaceholder": { - "message": "например, Джон Д." + "message": "напр., Джон Д." }, "addToken": { "message": "Добавить токен" @@ -57,51 +74,109 @@ "message": "Добавить токены" }, "advanced": { - "message": "Продвинутый" + "message": "Дополнительно" }, "advancedOptions": { - "message": "Расширенные настройки" + "message": "Расширенные опции" }, "advancedSettingsDescription": { - "message": "Получите доступ к функциям разработчика, журналу событий, сбросу учетной записи, настройке тестовых сетей и пользовательский RPC." + "message": "Доступ к функциям разработчика, загрузка журналов состояния, сброс счета, настройка тестовых сетей и настраиваемый RPC" + }, + "affirmAgree": { + "message": "Я согласен" + }, + "aggregatorFeeCost": { + "message": "Комиссия сети агрегатора" + }, + "alertDisableTooltip": { + "message": "Это можно изменить в \"Настройки > Оповещения\"" + }, + "alertSettingsUnconnectedAccount": { + "message": "Просмотр веб-сайта с выбранным неподключенным счетом" + }, + "alertSettingsUnconnectedAccountDescription": { + "message": "Это предупреждение отображается во всплывающем окне, когда вы просматриваете подключенный сайт Web3, но текущий выбранный счет не подключен." + }, + "alerts": { + "message": "Предупреждения" + }, + "alertsSettingsDescription": { + "message": "Включение или отключение каждого предупреждения" + }, + "allowExternalExtensionTo": { + "message": "Разрешить этому внешнему расширению:" + }, + "allowOriginSpendToken": { + "message": "Разрешить $1 потратить ваши $2?", + "description": "$1 is the url of the site and $2 is the symbol of the token they are requesting to spend" + }, + "allowThisSiteTo": { + "message": "Разрешить этому сайту:" + }, + "allowWithdrawAndSpend": { + "message": "Разрешить $1 снять и потратить до следующей суммы:", + "description": "The url of the site that requested permission to 'withdraw and spend'" }, "amount": { "message": "Сумма" }, + "amountInEth": { + "message": "$1 ETH", + "description": "Displays an eth amount to the user. $1 is a decimal number" + }, + "amountWithColon": { + "message": "Сумма:" + }, "appDescription": { - "message": "Расширение браузера для Ethereum", + "message": "Кошелек Ethereum в вашем браузере", "description": "The description of the application" }, "appName": { "message": "MetaMask", "description": "The name of the application" }, + "approvalAndAggregatorTxFeeCost": { + "message": "Комиссия сети одобрения и агрегатора" + }, + "approvalTxGasCost": { + "message": "Утвержденная стоимость Tx топлива" + }, "approve": { - "message": "Одобрить" + "message": "Утвердить предел расходов" + }, + "approveSpendLimit": { + "message": "Утвердить предел расходов $1", + "description": "The token symbol that is being approved" }, "approved": { - "message": "Одобрена" + "message": "Утвержден" }, "asset": { "message": "Актив" }, + "assets": { + "message": "Активы" + }, "attemptToCancel": { - "message": "Попытаться отменить?" + "message": "Попытка отменить?" }, "attemptToCancelDescription": { - "message": "Отправка этой попытки не гарантирует отмену вашей первоначальной транзакции. Если попытка отмены окажется успешной комиссия за исходную транзакцию будет возвращена." + "message": "Отправка этой попытки не гарантирует, что ваша первоначальная транзакция будет отменена. Если попытка отмены будет успешной, с вас будет взята комиссия за транзакцию, указанная выше." }, "attemptingConnect": { - "message": "Попытка подключиться к блокчейн сети." + "message": "Попытка подключиться к блокчейну." }, "attributions": { - "message": "Атрибуция" + "message": "Авторство" + }, + "authorizedPermissions": { + "message": "Вы авторизовали следующие разрешения" }, "autoLockTimeLimit": { - "message": "Таймер автоматического выхода из кошелька (минуты)" + "message": "Таймер автоблокировки (минуты)" }, "autoLockTimeLimitDescription": { - "message": "Установите время простоя в минутах, прежде чем MetaMask автоматически заблокирует кошелек" + "message": "Установите время простоя в минутах, прежде чем MetaMask будет заблокирован." }, "average": { "message": "Средний" @@ -110,19 +185,19 @@ "message": "Назад" }, "backToAll": { - "message": "На главную" + "message": "Вернуться ко всем" }, "backupApprovalInfo": { - "message": "Этот секретный код необходим для восстановления вашего кошелька в случае, если вы потеряете свое устройство, забудете пароль, придется переустановить MetaMask или захотите получить доступ к своему кошельку на другом устройстве." + "message": "Этот секретный код необходим для восстановления вашего кошелька в случае, если вы потеряете свое устройство, забудете пароль, вам придется переустановить MetaMask или захотите получить доступ к своему кошельку на другом устройстве." }, "backupApprovalNotice": { - "message": "Сделайте резервную копию секретного кода восстановления, чтобы сохранить свой кошелек и средства в безопасности." + "message": "Сделайте копию своего секретного кода восстановления, чтобы обезопасить свой кошелек и средства." }, "backupNow": { - "message": "Создать копию сейчас" + "message": "Сделайте резервную копию сейчас" }, "balance": { - "message": "Баланс:" + "message": "Баланс" }, "balanceOutdated": { "message": "Баланс может быть устаревшим" @@ -131,26 +206,29 @@ "message": "Базовый" }, "blockExplorerUrl": { - "message": "Блок-эксплорер" + "message": "Проводник блока" }, "blockExplorerView": { - "message": "Посмотреть аккаунт на $1", + "message": "Посмотреть счет на $1", "description": "$1 replaced by URL for custom block explorer" }, "blockiesIdenticon": { - "message": "Использовать Blockies Identicon" + "message": "Использовать идентикон Blockies" }, "browserNotSupported": { "message": "Ваш браузер не поддерживается..." }, "builtInCalifornia": { - "message": "MetaMask спроектирован и разработан в Калифорнии." + "message": "MetaMask разработан и построен в Калифорнии." + }, + "buy": { + "message": "Купить" }, "buyWithWyre": { - "message": "Купить ETH на Wyre" + "message": "Купить ETH с Wyre" }, "buyWithWyreDescription": { - "message": "Wyre позволяет вам покупать ETH использую кредитную карту, прямо на ваш счет в MetaMask." + "message": "Wyre позволяет использовать дебетовую карту для внесения ETH прямо на ваш счет MetaMask." }, "bytes": { "message": "Байт" @@ -159,19 +237,19 @@ "message": "Отмена" }, "cancellationGasFee": { - "message": "Комиссия за газ на отмену" + "message": "Комиссия за отмену топлива" }, "cancelled": { - "message": "Отменена" + "message": "Отменено" }, "chainId": { - "message": "ID сети" + "message": "Идентификатор цепи" }, "chromeRequiredForHardwareWallets": { - "message": "Вам необходимо использовать MetaMask в Google Chrome, чтобы подключиться к своему аппаратному кошельку." + "message": "Вам необходимо использовать MetaMask в Google Chrome, чтобы подключиться к аппаратному кошельку." }, "clickToRevealSeed": { - "message": "Нажмите здесь, чтобы показать секретную фразу (сид)" + "message": "Нажмите здесь, чтобы раскрыть секретные слова" }, "close": { "message": "Закрыть" @@ -180,22 +258,75 @@ "message": "Подтвердить" }, "confirmPassword": { - "message": "Подтвердите пароль" + "message": "Подтвердить пароль" }, "confirmSecretBackupPhrase": { - "message": "Подтвердите вашу резервную секретную фразу" + "message": "Подтвердите свою секретную резервную фразу" }, "confirmed": { - "message": "Подтверждена" + "message": "Подтверждено" }, "congratulations": { - "message": "Поздравляю!" + "message": "Поздравляем" }, "connect": { "message": "Подключиться" }, + "connectAccountOrCreate": { + "message": "Подключите счет или создайте новый" + }, "connectHardwareWallet": { - "message": "Подключите аппаратный кошелек" + "message": "Подключить аппаратный кошелек" + }, + "connectManually": { + "message": "Подключиться к текущему сайту вручную" + }, + "connectTo": { + "message": "Подключиться к $1", + "description": "$1 is the name/origin of a web3 site/application that the user can connect to metamask" + }, + "connectToAll": { + "message": "Подключиться ко всем своим $1", + "description": "$1 will be replaced by the translation of connectToAllAccounts" + }, + "connectToAllAccounts": { + "message": "счета", + "description": "will replace $1 in connectToAll, completing the sentence 'connect to all of your accounts', will be text that shows list of accounts on hover" + }, + "connectToMultiple": { + "message": "Подключиться к $1", + "description": "$1 will be replaced by the translation of connectToMultipleNumberOfAccounts" + }, + "connectToMultipleNumberOfAccounts": { + "message": "$1 счета/счетов", + "description": "$1 is the number of accounts to which the web3 site/application is asking to connect; this will substitute $1 in connectToMultiple" + }, + "connectWithMetaMask": { + "message": "Подключиться к MetaMask" + }, + "connectedAccountsDescriptionPlural": { + "message": "К этому сайту подключено $1 ваших счетов.", + "description": "$1 is the number of accounts" + }, + "connectedAccountsDescriptionSingular": { + "message": "К этому сайту подключен 1 ваш счет." + }, + "connectedAccountsEmptyDescription": { + "message": "MetaMask не подключен к этому сайту. Чтобы подключиться к сайту web3, найдите кнопку подключения на их сайте." + }, + "connectedSites": { + "message": "Подключенный сайты" + }, + "connectedSitesDescription": { + "message": "$1 подключен к этим сайтам. Они могут видеть адрес вашего счета.", + "description": "$1 is the account name" + }, + "connectedSitesEmptyDescription": { + "message": "$1 не подключен ни к каким сайтам.", + "description": "$1 is the account name" + }, + "connecting": { + "message": "Подключение..." }, "connectingTo": { "message": "Подключение к $1" @@ -204,31 +335,40 @@ "message": "Подключение к тестовой сети Goerli" }, "connectingToKovan": { - "message": "Соединение с тестовой сетью Kovan" + "message": "Подключение к тестовой сети Kovan" }, "connectingToMainnet": { - "message": "Соединение с основной сетью Ethereum" + "message": "Подключение к сети Ethereum Mainnet" }, "connectingToRinkeby": { - "message": "Соединение с тестовой сетью Rinkeby" + "message": "Подключение к тестовой сети Rinkeby" }, "connectingToRopsten": { - "message": "Соединение с тестовой сетью Ropsten" + "message": "Подключение к тестовой сети Ropsten" + }, + "contactUs": { + "message": "Свяжитесь с нами" + }, + "contacts": { + "message": "Контактная информация" + }, + "contactsSettingsDescription": { + "message": "Добавляйте, редактируйте, удаляйте и управляйте своими контактами" }, "continueToWyre": { - "message": "Продолжить на Wyre" + "message": "Продолжить к Wyre" }, "contractDeployment": { "message": "Развертывание контракта" }, "contractInteraction": { - "message": "Взаимодействие с контрактом" + "message": "Контрактное взаимодействие" }, "copiedExclamation": { "message": "Скопировано!" }, "copiedTransactionId": { - "message": "Идентификатор транзакции скопирован" + "message": "Скопированный идентификатор транзакции" }, "copyAddress": { "message": "Скопировать адрес в буфер обмена" @@ -252,63 +392,72 @@ "message": "Создать счет" }, "createPassword": { - "message": "Придумайте пароль" + "message": "Создать пароль" }, "currencyConversion": { - "message": "Конвертация валюты" + "message": "Обмен валюты" + }, + "currentAccountNotConnected": { + "message": "Ваша текущий счет не подключен" + }, + "currentExtension": { + "message": "Страница текущего расширения" }, "currentLanguage": { "message": "Текущий язык" }, "customGas": { - "message": "Настроить газ" + "message": "Настроить топливо" }, "customGasSubTitle": { - "message": "Увеличение платы может сократить время обработки, но это не гарантируется." + "message": "Увеличение комиссии может сократить время обработки, но это не гарантируется." }, "customRPC": { "message": "Пользовательский RPC" }, + "customSpendLimit": { + "message": "Пользовательский предел расходов" + }, "customToken": { "message": "Пользовательский токен" }, "dataBackupFoundInfo": { - "message": "Некоторые данные вашей учетной записи были экспортированы во время предыдущей установки MetaMask. Это может включать ваши настройки, контакты и токены. Вы хотите импортировать эти данные сейчас?" + "message": "Некоторые данные вашего счета были скопированы во время предыдущей установки MetaMask. Они могли включать ваши настройки, контакты и токены. Хотите восстановить эти данные сейчас?" }, "decimal": { - "message": "Количество десятичных разрядов" + "message": "Десятичных знаков точности" }, "decimalsMustZerotoTen": { - "message": "Количество десятичных разрядов должно быть минимум 0 и максимум 36." + "message": "Число десятичных знаков должно быть не менее 0, но не более 36." }, "decrypt": { "message": "Расшифровать" }, "decryptCopy": { - "message": "Скопировать расшифрованное сообщение" + "message": "Скопировать зашифрованное сообщение" }, "decryptInlineError": { - "message": "Это сообщение не может быть дешифровано из-за ошибки: $1", + "message": "Это сообщение невозможно расшифровать из-за ошибки: $1", "description": "$1 is error message" }, "decryptMessageNotice": { - "message": "Для $1 необходимо прочитать это сообщение, чтобы завершить Ваше действие", + "message": "$1 необходимо прочитать это сообщение, чтобы завершить свое действие", "description": "$1 is the web3 site name" }, "decryptMetamask": { "message": "Расшифровать сообщение" }, "decryptRequest": { - "message": "Запрос расшифровки" + "message": "Расшифровать запрос" }, "defaultNetwork": { - "message": "Основная сеть Ethereum – это сеть по умолчанию для Ether транзакций." + "message": "Сетью по умолчанию для транзакций Ether является Main Net." }, "delete": { "message": "Удалить" }, "deleteAccount": { - "message": "Удалить аккаунт" + "message": "Удалить счет" }, "deleteNetwork": { "message": "Удалить сеть?" @@ -317,34 +466,55 @@ "message": "Вы уверены, что хотите удалить эту сеть?" }, "depositEther": { - "message": "Пополнить Ether" + "message": "Внести Ether" }, "details": { "message": "Детали" }, "directDepositEther": { - "message": "Прямое пополнение Ether" + "message": "Напрямую внести Ether" }, "directDepositEtherExplainer": { - "message": "Если у вас уже есть Ether, то самый быстрый способ получить Ether в ваш новый кошелек – это прямое пополнение." + "message": "Если у вас уже есть Ether, то это самый быстрый способ получить Ether в свой новый кошелек путем прямого депозита." + }, + "disconnect": { + "message": "Отключить" + }, + "disconnectAllAccounts": { + "message": "Отключить все счета" + }, + "disconnectAllAccountsConfirmationDescription": { + "message": "Вы уверены, что хотите отключить? Вы можете потерять функциональность сайта." + }, + "disconnectPrompt": { + "message": "Отключить $1" + }, + "disconnectThisAccount": { + "message": "Отключить этот счет" + }, + "dismiss": { + "message": "Отклонить" }, "done": { - "message": "Готово" + "message": "Выполнено" }, "dontHaveAHardwareWallet": { - "message": "Нет аппаратного кошелька?" + "message": "У вас нет аппаратного кошелька?" + }, + "dontShowThisAgain": { + "message": "Больше не показывать это сообщение" }, "downloadGoogleChrome": { - "message": "Скачать Google Chrome" + "message": "Загрузить Google Chrome" }, "downloadSecretBackup": { - "message": "Загрузите секретную резервную фразу и сохраните ее в безопасном месте на внешнем зашифрованном жестком диске или ином носителе." + "message": "Загрузите эту секретную фразу резервного копирования и храните ее в надежном месте на внешнем зашифрованном жестком диске или носителе." }, "downloadStateLogs": { - "message": "Скачать журнал состояния" + "message": "Скачать журналы состояния" }, "dropped": { - "message": "Отброшена" + "message": "Удалено" }, "edit": { "message": "Редактировать" @@ -352,159 +522,249 @@ "editContact": { "message": "Изменить контакт" }, + "editPermission": { + "message": "Изменить разрешение" + }, "encryptionPublicKeyNotice": { - "message": "$1 запрашивает ваш открытый ключ шифрования. По согласованию, этот сайт сможет создавать для Вас зашифрованные сообщения.", + "message": "$1 хотел бы получить ваш открытый ключ шифрования. После вашего согласия этот сайт сможет создавать вам зашифрованные сообщения.", "description": "$1 is the web3 site name" }, "encryptionPublicKeyRequest": { - "message": "Запрос публичного ключа шифрования" + "message": "Запросить открытый ключ шифрования." }, "endOfFlowMessage1": { - "message": "Вы прошли тестирование - сохраняйте свою исходную фразу в безопасности, это ваша ответственность!" + "message": "Вы прошли тест — храните свою исходную фразу в безопасности, это ваша ответственность!" }, "endOfFlowMessage10": { - "message": "Завершено" + "message": "Выполнено" }, "endOfFlowMessage2": { - "message": "Советы по безопасному хранению активов" + "message": "Советы по безопасному хранению" }, "endOfFlowMessage3": { - "message": "Сохраните резервную копию в нескольких местах." + "message": "Сохраните копию в нескольких местах." }, "endOfFlowMessage4": { - "message": "Никогда не делись фразой ни с кем." + "message": "Никогда не говорите никому эту фразу." }, "endOfFlowMessage5": { - "message": "Будьте осторожны с фишингом! MetaMask никогда не будет самопроизвольно запрашивать вашу начальную фразу." + "message": "Остерегайтесь фишинга! MetaMask никогда неожиданно не запросит вашу исходную фразу." }, "endOfFlowMessage6": { - "message": "Если вам нужно снова создать резервную копию исходной фразы, вы можете найти ее в «Настройки» -> «Безопасность»." + "message": "Если вам нужно снова создать резервную копию исходной фразы, вы можете найти ее в Настройки -> Безопасность." }, "endOfFlowMessage7": { - "message": "Если у вас есть вопросы или вы видите что-то подозрительное, пишите на support@metamask.io." + "message": "Если у вас возникнут вопросы или вы увидите что-то подозрительное, напишите на support@metamask.io." }, "endOfFlowMessage8": { - "message": "MetaMask не может восстановить вашу начальную фразу. Узнать больше." + "message": "Просто помните, что MetaMask не может восстановить исходную фразу." }, "endOfFlowMessage9": { - "message": "Узнать больше" + "message": "Дополнительная информация" + }, + "endpointReturnedDifferentChainId": { + "message": "Конечная точка вернула другой идентификатор цепочки: $1", + "description": "$1 is the return value of eth_chainId from an RPC endpoint" }, "ensNotFoundOnCurrentNetwork": { - "message": "Имя ENS не найдено в текущей сети. Попробуйте переключиться на основную сеть Ethereum" + "message": "Имя ENS не найдено в текущей сети. Попробуйте переключиться на сеть Ethereum Mainnet." }, "ensRegistrationError": { - "message": "Ошибка в регистрации имени ENS" + "message": "Ошибка при регистрации имени ENS" }, "enterAnAlias": { - "message": "Введите алиас" + "message": "Ввести псевдоним" + }, + "enterMaxSpendLimit": { + "message": "Введите максимальный лимит расходов" }, "enterPassword": { "message": "Введите пароль" }, "enterPasswordContinue": { - "message": "Введите пароль для продолжения" + "message": "Введите пароль, чтобы продолжить" + }, + "errorCode": { + "message": "Код: $1", + "description": "Displayed error code for debugging purposes. $1 is the error code" + }, + "errorDetails": { + "message": "Детали ошибки", + "description": "Title for collapsible section that displays error details for debugging purposes" + }, + "errorMessage": { + "message": "Сообщение: $1", + "description": "Displayed error message for debugging purposes. $1 is the error message" + }, + "errorName": { + "message": "Код: $1", + "description": "Displayed error name for debugging purposes. $1 is the error name" + }, + "errorPageMessage": { + "message": "Повторите попытку, перезагрузив страницу, или обратитесь в службу поддержки по адресу support@metamask.io", + "description": "Message displayed on generic error page in the fullscreen or notification UI" + }, + "errorPagePopupMessage": { + "message": "Повторите попытку, закрыв и вновь открыв всплывающее окно, или обратитесь в службу поддержки по адресу support@metamask.io", + "description": "Message displayed on generic error page in the popup UI" + }, + "errorPageTitle": { + "message": "MetaMask обнаружил ошибку", + "description": "Title of generic error page" + }, + "errorStack": { + "message": "Стек:", + "description": "Title for error stack, which is displayed for debugging purposes" }, "estimatedProcessingTimes": { - "message": "Ожидаемое время обработки" + "message": "Расчетное время обработки" + }, + "eth_accounts": { + "message": "Просмотр адресов ваших разрешенных счетов (обязательно)", + "description": "The description for the `eth_accounts` permission" }, "ethereumPublicAddress": { "message": "Публичный адрес Ethereum" }, + "etherscan": { + "message": "Etherscan" + }, "etherscanView": { - "message": "Просмотреть счет на Etherscan" + "message": "Посмотреть счет на Etherscan" }, "expandView": { - "message": "Развернуть" + "message": "Развернуть вид" }, "exportPrivateKey": { "message": "Экспортировать закрытый ключ" }, + "externalExtension": { + "message": "Внешнее расширение" + }, + "extraApprovalGas": { + "message": "+$1 утверждение топлива", + "description": "Expresses an additional gas amount the user will have to pay, on top of some other displayed amount. $1 is a decimal amount of gas" + }, "failed": { - "message": "Неудачна" + "message": "Не удалось" + }, + "failedToFetchChainId": { + "message": "Не удалось получить идентификатор цепочки. Ваш URL-адрес RPC правильный?" + }, + "failureMessage": { + "message": "Что-то пошло не так, и мы не смогли завершить действие" }, "fast": { - "message": "Быстро" + "message": "Быстрый" + }, + "fastest": { + "message": "Самый быстрый" + }, + "feeAssociatedRequest": { + "message": "С этим запросом связана комиссия." }, "fiat": { - "message": "Валюта", + "message": "Конвертированная валюта", "description": "Exchange type" }, "fileImportFail": { - "message": "Не работает импорт файла? Нажмите тут!", + "message": "Импорт файлов не работает? Нажмите здесь!", "description": "Helps user import their account from a JSON file" }, + "forbiddenIpfsGateway": { + "message": "Запрещенный шлюз IPFS: Укажите шлюз CID" + }, "forgetDevice": { - "message": "Забыть устройство" + "message": "Забудь это устройство" }, "from": { - "message": "Отправитель" + "message": "От" + }, + "fromAddress": { + "message": "От: $1", + "description": "$1 is the address to include in the From label. It is typically shortened first using shortenAddress" + }, + "functionApprove": { + "message": "Функция: Одобрить" }, "functionType": { "message": "Тип функции" }, "gasLimit": { - "message": "Лимит газа" + "message": "Предел топлива" }, "gasLimitInfoTooltipContent": { - "message": "Лимит газа - это максимальное количество единиц газа, которое вы готовы потратить." + "message": "Лимит топлива — это максимальное количество единиц топлива, которое вы готовы потратить." }, "gasLimitTooLow": { - "message": "Лимит газа должен быть как минимум 21000" + "message": "Лимит топлива должен быть не менее 21 000" + }, + "gasLimitTooLowWithDynamicFee": { + "message": "Лимит топлива должен быть не менее $1", + "description": "$1 is the custom gas limit, in decimal." }, "gasPrice": { - "message": "Цена за газ (GWEI)" + "message": "Цена топлива (GWEI)" }, "gasPriceExtremelyLow": { - "message": "Цена на газ слишком низкая" + "message": "Цена топлива очень низкая" }, "gasPriceInfoTooltipContent": { - "message": "Цена на газ указывает количество эфира, которое вы готовы платить за каждую единицу газа." + "message": "Цена топлива указывает количество Ether, которое вы готовы платить за каждую единицу топлива." }, "gasUsed": { - "message": "Газа использовано" + "message": "Использовано топлива" + }, + "gdprMessage": { + "message": "Эти данные агрегированы и поэтому анонимны для целей Общего регламента по защите данных (ЕС) 2016/679. Для получения дополнительной информации о нашей политике конфиденциальности ознакомьтесь с нашей $1.", + "description": "$1 refers to the gdprMessagePrivacyPolicy message, the translation of which is meant to be used exclusively in the context of gdprMessage" + }, + "gdprMessagePrivacyPolicy": { + "message": "Политика конфиденциальности здесь", + "description": "this translation is intended to be exclusively used as the replacement for the $1 in the gdprMessage translation" }, "general": { - "message": "Основное" + "message": "Общий" }, "generalSettingsDescription": { - "message": "Конвертация валюты, основная валюта, язык, идентификаторы блоков" + "message": "Обмен валюты, основная валюта, язык, идентикон blockies" }, "getEther": { "message": "Получить Ether" }, "getEtherFromFaucet": { - "message": "Получить Ether из крана для $1", + "message": "Получите Ether из крана для $1", "description": "Displays network name for Ether faucet" }, "getHelp": { - "message": "Получить помощь." + "message": "Получить справку." }, "getStarted": { - "message": "Начать" + "message": "Начать работу" }, "goerli": { "message": "Тестовая сеть Goerli" }, "happyToSeeYou": { - "message": "Мы рады видеть вас." + "message": "Мы рады вас видеть." }, "hardware": { - "message": "Аппаратные кошельки" + "message": "Аппаратное обеспечение" }, "hardwareWalletConnected": { "message": "Аппаратный кошелек подключен" }, "hardwareWallets": { - "message": "Подключите аппаратный кошелек" + "message": "Подключить аппаратный кошелек" }, "hardwareWalletsMsg": { "message": "Выберите аппаратный кошелек, который вы хотите использовать с MetaMask" }, "havingTroubleConnecting": { - "message": "Возникли проблемы с подключением?" + "message": "Проблемы с подключением?" }, "here": { - "message": "тут", + "message": "здесь", "description": "as in -click here- for more information (goes with troubleTokenBalances)" }, "hexData": { @@ -516,40 +776,44 @@ "hideTokenPrompt": { "message": "Скрыть токен?" }, + "hideTokenSymbol": { + "message": "Скрыть $1", + "description": "$1 is the symbol for a token (e.g. 'DAI')" + }, "history": { "message": "История" }, "import": { - "message": "Импортировать", + "message": "Импорт", "description": "Button to import an account from a selected file" }, "importAccount": { "message": "Импортировать счет" }, "importAccountMsg": { - "message": " Импортированные счета не будут ассоциированы с вашей ключевой фразой, созданной MetaMask. Узнать больше про импорт счетов " + "message": " Импортированные счета не будут связаны с исходной фразой вашей изначально созданного счета MetaMask. Узнайте больше об импортированных счетах " }, "importAccountSeedPhrase": { - "message": "Импортировать аккаунт с помощью секретной фразы (сида)" + "message": "Импортировать счет с исходной фразой" }, "importUsingSeed": { - "message": "Импортировать используя секретную фразу (сид)" + "message": "Импортировать с использованием исходной фразы счета" }, "importWallet": { "message": "Импортировать кошелек" }, "importYourExisting": { - "message": "Импортируйте существующий кошелек, используя секретную фразу из 12 слов" + "message": "Импортируйте существующий кошелек, используя начальную фразу из 12 слов" }, "imported": { - "message": "Импортирован", + "message": "Импортированный", "description": "status showing that an account has been fully loaded into the keyring" }, "infoHelp": { - "message": "Информация и помощь" + "message": "Информация и справка" }, "initialTransactionConfirmed": { - "message": "Ваша первоначальная транзакция была подтверждена сетью. Нажмите OK, чтобы вернуться." + "message": "Ваша первоначальная транзакция была подтверждена сетью. Нажмите ОК, чтобы вернуться." }, "insufficientBalance": { "message": "Недостаточный баланс." @@ -567,38 +831,79 @@ "message": "Неверный адрес получателя" }, "invalidAddressRecipientNotEthNetwork": { - "message": "Адрес получателя не принадлежит сети Eth" + "message": "Не сеть ETH, задана в нижнем регистре" }, "invalidBlockExplorerURL": { - "message": "Неверный Block Explorer URI" + "message": "Недействительный URL-адрес проводника блока" + }, + "invalidCustomNetworkAlertContent1": { + "message": "Необходимо повторно ввести идентификатор цепочки для пользовательской сети «$1».", + "description": "$1 is the name/identifier of the network." + }, + "invalidCustomNetworkAlertContent2": { + "message": "Чтобы защитить вас от злонамеренных или ошибочных сетевых провайдеров, идентификаторы цепочек теперь требуются для всех настраиваемых сетей." + }, + "invalidCustomNetworkAlertContent3": { + "message": "Перейдите в Настройки > Сеть и введите идентификатор цепочки. Вы можете найти идентификаторы наиболее популярных сетей на $1.", + "description": "$1 is a link to https://chainid.network" + }, + "invalidCustomNetworkAlertTitle": { + "message": "Недействительная пользовательская сеть" + }, + "invalidHexNumber": { + "message": "Недействительное шестнадцатеричное число." + }, + "invalidHexNumberLeadingZeros": { + "message": "Недействительное шестнадцатеричное число. Удалите все начальные нули." + }, + "invalidIpfsGateway": { + "message": "Неверный шлюз IPFS: Значение должно быть действительным URL" + }, + "invalidNumber": { + "message": "Недопустимое число. Введите десятичное число или шестнадцатеричное число с префиксом \"0x\"." + }, + "invalidNumberLeadingZeros": { + "message": "Недопустимое число. Удалите все начальные нули." }, "invalidRPC": { - "message": "Неверный RPC URI" + "message": "Недействительный URL-адрес RPC" }, "invalidSeedPhrase": { - "message": "Неверная начальная фраза" + "message": "Неверная исходная фраза" + }, + "ipfsGateway": { + "message": "Шлюз IPFS" + }, + "ipfsGatewayDescription": { + "message": "Введите URL-адрес шлюза IPFS CID, который будет использоваться для разрешения содержимого ENS." }, "jsonFile": { - "message": "JSON файл", + "message": "Файл JSON", "description": "format for importing an account" }, "knownAddressRecipient": { - "message": "Известный адрес контракта" + "message": "Известный адрес контракта." + }, + "knownTokenWarning": { + "message": "Это действие изменит токены, уже указанные в вашем кошельке, которые можно использовать для фишинга. Утверждайте, только если вы уверены, что хотите изменить то, что представляют эти токены." }, "kovan": { "message": "Тестовая сеть Kovan" }, + "lastConnected": { + "message": "Последнее подключение" + }, "learnMore": { - "message": "Узнать больше." + "message": "Дополнительная информация" }, "ledgerAccountRestriction": { - "message": "Вам нужно использовать свой последний аккаунт, прежде чем вы сможете добавить новый." + "message": "Вам необходимо использовать свой последний счет, прежде чем вы сможете добавить новый." }, "letsGoSetUp": { - "message": "Да, давайте приступим!" + "message": "Да, давайте настроим!" }, "likeToAddTokens": { - "message": "Вы хотите добавить эти токены?" + "message": "Вы хотели бы добавить эти токены?" }, "links": { "message": "Ссылки" @@ -612,17 +917,23 @@ "loadingTokens": { "message": "Загрузка токенов..." }, + "localhost": { + "message": "Локальный хост 8545" + }, "lock": { - "message": "Выход" + "message": "Заблокировать" + }, + "lockTimeTooGreat": { + "message": "Время блокировки слишком велико" }, "mainnet": { - "message": "Основная сеть Ethereum" + "message": "Сеть Ethereum Mainnet" }, "max": { - "message": "Максимум" + "message": "Макс." }, "memo": { - "message": "Мнемотик" + "message": "памятка" }, "memorizePhrase": { "message": "Запомните эту фразу." @@ -630,54 +941,100 @@ "message": { "message": "Сообщение" }, + "metaMaskConnectStatusParagraphOne": { + "message": "Теперь у вас есть больший контроль над подключениями к вашим счетам в MetaMask." + }, + "metaMaskConnectStatusParagraphThree": { + "message": "Нажмите на него, чтобы управлять подключенными счетами." + }, + "metaMaskConnectStatusParagraphTwo": { + "message": "Кнопка статуса подключения показывает, подключен ли веб-сайт, который вы посещаете, к вашей выбранному в нестоящее врем счету." + }, "metamaskDescription": { - "message": "MetaMask – безопасный кошелек для Ethereum." + "message": "Подключение вас к Ethereum и децентрализованной сети." + }, + "metamaskSwapsOfflineDescription": { + "message": "Свопы MetaMask Swaps находятся на техническом обслуживании. Зайдите позже." }, "metamaskVersion": { "message": "Версия MetaMask" }, + "metametricsCommitmentsAllowOptOut": { + "message": "Всегда разрешать вам отказаться через настройки" + }, + "metametricsCommitmentsBoldNever": { + "message": "Никогда", + "description": "This string is localized separately from some of the commitments so that we can bold it" + }, + "metametricsCommitmentsIntro": { + "message": "MetaMask не будет..." + }, + "metametricsCommitmentsNeverCollectIP": { + "message": "$1 не сохранять ваш полный IP-адрес", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverCollectKeysEtc": { + "message": "$1 не хранить ключи, адреса, транзакции, балансы, хэши или любую персональную информацию", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverSellDataForProfit": { + "message": "$1 не продавать данные для прибыли. Никогда!", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsSendAnonymizedEvents": { + "message": "Отправлять анонимизированные события кликов и просмотров страниц" + }, + "metametricsHelpImproveMetaMask": { + "message": "Помогите нам улучшить MetaMask" + }, + "metametricsOptInDescription": { + "message": "MetaMask хотел бы собрать основные данные об использовании, чтобы лучше понять, как наши пользователи взаимодействуют с расширением. Эти данные будут использоваться для постоянного улучшения удобства и опыта использования нашего продукта и экосистемы Ethereum." + }, "mobileSyncText": { - "message": "Пожалуйста, введите ваш пароль, чтобы подтвердить, что это вы!" + "message": "Введите свой пароль, чтобы подтвердить ваш личность!" }, "mustSelectOne": { - "message": "Необходимо выбрать как минимум 1 токен." + "message": "Необходимо выбрать хотя бы 1 токен." }, "myAccounts": { "message": "Мои счета" }, "myWalletAccounts": { - "message": "Мои кошельки" + "message": "Счета моего кошелька" }, "myWalletAccountsDescription": { - "message": "Все ваши учетные записи, созданные в MetaMask, будут автоматически добавлены в этот раздел." + "message": "Все ваши счета, созданные в MetaMask, будут автоматически добавлены в этот раздел." }, "needEtherInWallet": { - "message": "Для взаимодействия с децентрализованными приложениями с помощью MetaMask нужен Ether в вашем кошельке." + "message": "Для взаимодействия с децентрализованными приложениями с помощью MetaMask вам понадобится Ether в вашем кошельке." }, "needImportFile": { "message": "Вы должны выбрать файл для импорта.", "description": "User is important an account and needs to add a file to continue" }, "negativeETH": { - "message": "Невозможно отправить отрицательную сумму ETH." + "message": "Невозможно отправить отрицательное количество ETH." }, "networkName": { "message": "Имя сети" }, + "networkSettingsChainIdDescription": { + "message": "Идентификатор цепочки используется для подписания транзакций. Он должен соответствовать идентификатору цепочки, возвращаемому сетью. Вы можете ввести десятичное число или шестнадцатеричное число с префиксом «0x», но мы будем отображать число в десятичном виде." + }, "networkSettingsDescription": { - "message": "Добавить и редактировать пользовательские сети RPC" + "message": "Добавление и редактирование пользовательских сетей RPC" }, "networks": { "message": "Сети" }, "nevermind": { - "message": "Не берите в голову" + "message": "Неважно" }, "newAccount": { "message": "Новый счет" }, "newAccountDetectedDialogMessage": { - "message": "Обнаружен новый адрес. Нажмите здесь, чтобы добавить в вашу адресную книгу." + "message": "Обнаружен новый адрес! Нажмите здесь, чтобы добавить этот адрес в свою адресную книгу." }, "newAccountNumberName": { "message": "Счет $1", @@ -693,76 +1050,111 @@ "message": "Новая сеть" }, "newPassword": { - "message": "Новый пароль (мин. 8 символов)" + "message": "Новый пароль (мин.8 знаков)" }, "newToMetaMask": { "message": "Впервые в MetaMask?" }, "newTotal": { - "message": "Итого" + "message": "Новая сумма" }, "newTransactionFee": { - "message": "Плата за новую транзакцию" + "message": "Новые комиссии за транзакцию" }, "next": { "message": "Далее" }, + "nextNonceWarning": { + "message": "Одноразовый номер больше, чем предложенный одноразовый номер $1", + "description": "The next nonce according to MetaMask's internal logic" + }, + "noAccountsFound": { + "message": "По данному поисковому запросу счетов не найдено" + }, "noAddressForName": { - "message": "Дла этого названия не установлен адрес." + "message": "Для этого имени не задан адрес." }, "noAlreadyHaveSeed": { - "message": "Нет, у меня уже есть начальная фраза" + "message": "Нет, у меня уже есть исходная фраза" }, "noConversionRateAvailable": { - "message": "Курсы валют недоступны" + "message": "Нет доступного курса обмена" }, "noThanks": { "message": "Нет, спасибо" }, "noTransactions": { - "message": "Нет транзакций" + "message": "У вас нет транзакций" }, "noWebcamFound": { - "message": "Веб-камера вашего компьютера не была найдена. Пожалуйста, попробуйте еще раз." + "message": "Веб-камера вашего компьютера не найдена. Попробуйте еще раз." }, "noWebcamFoundTitle": { "message": "Веб-камера не найдена" }, + "nonceField": { + "message": "Настроить одноразовый номер транзакции" + }, + "nonceFieldDescription": { + "message": "Включите это, чтобы изменить одноразовый номер (номер транзакции) на экранах подтверждения. Это расширенная функция, используйте ее с осторожностью." + }, + "nonceFieldHeading": { + "message": "Индивидуальные одноразовый номер" + }, + "notCurrentAccount": { + "message": "Это правильный счет? Он отличается от выбранного в настоящее время счета в вашем кошельке." + }, "notEnoughGas": { - "message": "Не хватает газа" + "message": "Недостаточно топлива" }, "ofTextNofM": { "message": "из" }, "off": { - "message": "Откл" + "message": "С" + }, + "offlineForMaintenance": { + "message": "Не в сети для обслуживания" }, "ok": { "message": "ОК" }, "on": { - "message": "Вкл" + "message": "Вкл." + }, + "onboardingReturnNotice": { + "message": "\"$1\" закроет эту вкладку и вернется к $2", + "description": "Return the user to the site that initiated onboarding" + }, + "onlyAddTrustedNetworks": { + "message": "Вредоносный сетевой провайдер Ethereum может дезинформировать о состоянии блокчейн и записывать ваши действия в сети. Добавляйте только те пользовательские сети, которым доверяете." + }, + "onlyAvailableOnMainnet": { + "message": "Доступно только в mainnet" + }, + "onlyConnectTrust": { + "message": "Подключайтесь только к сайтам, которым доверяете." }, "optionalBlockExplorerUrl": { - "message": "URL блок-эксплорера (необязательно)" + "message": "URL-адрес проводника блока (необязательно)" }, "optionalCurrencySymbol": { - "message": "Символ (необязательно)" + "message": "Символ валюты (необязательно)" }, "orderOneHere": { - "message": "Закажите Trezor или Ledger и храните свои средства в холодном кошельке" + "message": "Закажите Trezor или Ledger и храните свои средства в холодном хранилище" }, "origin": { - "message": "происхождения" + "message": "Источник" }, "parameters": { - "message": "параметры" + "message": "Параметры" }, "participateInMetaMetrics": { - "message": "Участвовать в MetaMetrics" + "message": "Участвуйте в MetaMetrics" }, "participateInMetaMetricsDescription": { - "message": "Участвуйте в MetaMetrics, чтобы помочь нам сделать MetaMask лучше" + "message": "Участвуйте в MetaMetrics, чтобы помочь нам улучшить его" }, "password": { "message": "Пароль" @@ -774,45 +1166,61 @@ "message": "Пароли не совпадают" }, "pastePrivateKey": { - "message": "Вставьте ваш закрытый ключ тут:", + "message": "Вставьте строку вашего закрытого ключа сюда:", "description": "For importing an account from a private key" }, "pending": { - "message": "В обработке" + "message": "В ожидании" + }, + "permissionCheckedIconDescription": { + "message": "Вы одобрили это разрешение" + }, + "permissionUncheckedIconDescription": { + "message": "Вы не одобрили это разрешение" + }, + "permissions": { + "message": "Разрешения" }, "personalAddressDetected": { - "message": "Обнаружен персональный адрес. Введите адрес контракта токена." + "message": "Обнаружен личный адрес. Введите адрес контракта токена." + }, + "plusXMore": { + "message": "+ $1 еще", + "description": "$1 is a number of additional but unshown items in a list- this message will be shown in place of those items" }, "prev": { - "message": "Предыдущая" + "message": "Предыдущее" }, "primaryCurrencySetting": { "message": "Основная валюта" }, "primaryCurrencySettingDescription": { - "message": "Выберите «Собственный», чтобы установить приоритет отображения сумм в валюте сети(например, ETH).выберите Фиат, чтобы установить приоритет отображения значений в выбранной вами фиатной валюте." + "message": "Выберите Native, чтобы установить приоритет отображения значений в собственной валюте цепи (например, ETH). Выберите Fiat, чтобы установить приоритет отображения значений в выбранной валюте конвертации." }, "privacyMsg": { - "message": "Политика конфиденциальности" + "message": "Политикой конфиденциальности" }, "privateKey": { "message": "Закрытый ключ", "description": "select this type of file to use to import an account" }, "privateKeyWarning": { - "message": "Предупреждение: Никогда не раскрывайте этот ключ. Любой, у кого есть ваши закрытые ключи, может украсть любые активы, хранящиеся на счету." + "message": "Предупреждение: Никогда не раскрывайте этот ключ. Любой, у кого есть ваши закрытые ключи, может украсть любые активы, хранящиеся на вашем счете." }, "privateNetwork": { - "message": "Частная сеть" + "message": "Закрытая сеть" + }, + "proposedApprovalLimit": { + "message": "Предлагаемый предел утверждения" }, "protectYourKeys": { "message": "Защитите свои ключи!" }, "protectYourKeysMessage1": { - "message": "Будьте осторожны с исходной фразой - были сообщения о сайтах, которые пытаются подражать MetaMask. MetaMask никогда не запрашивает секретную фразу (сид)!" + "message": "Будьте осторожны с исходной фразой — были сообщения о веб-сайтах, которые пытались имитировать MetaMask. MetaMask никогда не запросит вашу исходную фразу!" }, "protectYourKeysMessage2": { - "message": "Держите вашу фразу в безопасности. Если вы видите что-то подозрительное или сомневаетесь в веб-сайте, напишите support@metamask.io" + "message": "Храните свою исходную фразу в безопасности. Если вы увидите что-то подозрительное или вы не уверены в сайте, напишите на support@metamask.io" }, "provide": { "message": "Предоставить" @@ -820,12 +1228,18 @@ "queue": { "message": "Очередь" }, + "queued": { + "message": "В очереди" + }, "readdToken": { - "message": "Вы можете в будущем добавить обратно этот токен, выбрав пункт меню “Добавить токен”." + "message": "Вы можете снова добавить этот токен в будущем, выбрав «Добавить токен» в меню опций вашего счета." }, "readyToConnect": { "message": "Готовы подключиться?" }, + "receive": { + "message": "Получить" + }, "recents": { "message": "Недавние" }, @@ -833,7 +1247,7 @@ "message": "Адрес получателя" }, "recipientAddressPlaceholder": { - "message": "Поиск, публичный адрес (0x)или ENS" + "message": "Поиск, публичный адрес (0x) или ENS" }, "reject": { "message": "Отклонить" @@ -842,68 +1256,74 @@ "message": "Отклонить все" }, "rejectTxsDescription": { - "message": "Вы собираетесь отклонить $1 транзакций" + "message": "Вы собираетесь пакетно отклонить $1 транзакций." }, "rejectTxsN": { - "message": "Отклонить транзакции $1" + "message": "Отклонить $1 транзакций" }, "rejected": { - "message": "Отклонена" + "message": "Отклонены" }, "remindMeLater": { - "message": "Напомнить позже" + "message": "Напомните мне позже" }, "remove": { "message": "Удалить" }, "removeAccount": { - "message": "Удалить учетную запись" + "message": "Удалить счет" }, "removeAccountDescription": { - "message": "Эта учетная запись будет удалена из вашего кошелька. Прежде чем продолжить, убедитесь, что у вас есть исходная фраза или закрытый ключ для этой импортированной учетной записи. Вы можете импортировать или создать учетные записи снова из раскрывающегося списка." + "message": "Этот счет будет удален из вашего кошелька. Перед продолжением убедитесь, что у вас есть исходная фраза или закрытый ключ для этой импортированного счета. Вы можете импортировать или снова создать счета из раскрывающегося списка. " }, "requestsAwaitingAcknowledgement": { "message": "запросы, ожидающие подтверждения" }, "required": { - "message": "Обязательное поле" + "message": "Требуется" }, "reset": { - "message": "Сброс" + "message": "Сбросить" }, "resetAccount": { - "message": "Сбросить аккаунт" + "message": "Сбросить счет" }, "resetAccountDescription": { - "message": "Сброс вашей учетной записи очистит вашу историю транзакций." + "message": "Сброс вашего счета удалит историю транзакций. Это не изменит остатки на ваших счетах и не потребует повторного ввода исходной фразы." }, "restore": { "message": "Восстановить" }, "restoreAccountWithSeed": { - "message": "Восстановите свой аккаунт с помощью секретной фразы" + "message": "Восстановите свой счет с помощью исходной фразы" }, "restoreFromSeed": { - "message": "Восстановить из ключевой фразы" + "message": "Восстановить счет?" }, "restoreWalletPreferences": { - "message": "Были найдены данные экспортированные от $1. Вы желаете восстановить настройки вашего кошелька?", + "message": "Найдена резервная копия ваших данных из $1. Хотите восстановить настройки кошелька?", "description": "$1 is the date at which the data was backed up" }, + "retryTransaction": { + "message": "Повторить попытку транзакции" + }, + "reusedTokenNameWarning": { + "message": "Токен здесь повторно использует символ из другого токена, который вы смотрите, это может запутать или ввести в заблуждение." + }, "revealSeedWords": { - "message": "Показать ключевую фразу" + "message": "Раскрыть исходную фразу" }, "revealSeedWordsDescription": { - "message": "Если вы когда-либо меняете браузеры или перемещаете компьютеры, вам понадобится эта начальная фраза для доступа к вашим учетным записям. Сохраните их где-нибудь в безопасном хранилище." + "message": "Если вы меняете браузер или переходите на другой компьютер, вам понадобится эта исходная фраза для доступа к своим счетам. Сохраните ее в безопасном секретном месте." }, "revealSeedWordsTitle": { - "message": "Сид-фраза" + "message": "Исходная фраза" }, "revealSeedWordsWarning": { - "message": "Не восстанавливайте ключевую фразу в общественном месте! Она может быть использована для кражи всех ваших счетов." + "message": "Эти слова можно использовать для кражи всех ваших счетов." }, "revealSeedWordsWarningTitle": { - "message": "НЕ делитесь этой фразой ни с кем!" + "message": "НЕ говорите никому эту фразу!" }, "rinkeby": { "message": "Тестовая сеть Rinkeby" @@ -912,79 +1332,91 @@ "message": "Тестовая сеть Ropsten" }, "rpcUrl": { - "message": "Новый RPC URL" + "message": "Новый URL RPC" }, "save": { - "message": "Сохранить" + "message": "«»Сохранить" }, "saveAsCsvFile": { "message": "Сохранить как файл CSV" }, "scanInstructions": { - "message": "Поместите QR-код перед вашей камерой" + "message": "Поместите QR-код перед камерой" }, "scanQrCode": { "message": "Сканировать QR-код" }, + "scrollDown": { + "message": "Прокрутить вниз" + }, "search": { "message": "Поиск" }, + "searchAccounts": { + "message": "Поиск счетов" + }, "searchResults": { - "message": "Результат поиска" + "message": "Поиск результатов" }, "searchTokens": { "message": "Поиск токенов" }, "secretBackupPhrase": { - "message": "Резервная копия секретной фразы" + "message": "Секретная резервная фраза" }, "secretBackupPhraseDescription": { - "message": "Ваша секретная резервная фраза облегчает резервное копирование и восстановление вашей учетной записи." + "message": "Ваша секретная резервная фраза упрощает резервное копирование и восстановление вашего счета." }, "secretBackupPhraseWarning": { - "message": "ВНИМАНИЕ. Никогда не раскрывайте свою резервную фразу. Любой, у кого есть эта фраза, может завладеть вашими средствами безвозвратно" + "message": "ПРЕДУПРЕЖДЕНИЕ: Никогда не разглашайте резервную фразу. Любой, у кого есть эта фраза, может забрать ваш Ether навсегда." }, "secretPhrase": { - "message": "Введите вашу ключевую фразу из 12 слов, чтобы восстановить кошелек." + "message": "Введите здесь свою секретную фразу из двенадцати слов, чтобы восстановить свой сейф." }, "securityAndPrivacy": { "message": "Безопасность и конфиденциальность" }, "securitySettingsDescription": { - "message": "Настройки конфиденциальности и фраза кошелька" + "message": "Настройки конфиденциальности и исходная фраза кошелька" }, "seedPhrasePlaceholder": { - "message": "Разделяйте каждое слово одним пробелом" + "message": "Отделяйте каждое слово одним пробелом" + }, + "seedPhrasePlaceholderPaste": { + "message": "Вставить исходную фразу из буфера обмена" }, "seedPhraseReq": { - "message": "ключевые фразы имеют длину 12 слов" + "message": "Исходные фразы содержат 12, 15, 18, 21 или 24 слова" }, "selectAHigherGasFee": { - "message": "Установите более высокую плату за газ, чтобы ускорить обработку вашей транзакции.*" + "message": "Выберите более высокую плату за топливо, чтобы ускорить обработку транзакции. *" + }, + "selectAccounts": { + "message": "Выберите счет(а)" + }, + "selectAll": { + "message": "Выбрать все" }, "selectAnAccount": { - "message": "Выберите аккаунт" + "message": "Выберите счет" }, "selectAnAccountHelp": { - "message": "Выберите учетную запись для просмотра в MetaMask" - }, - "selectCurrency": { - "message": "Выберите валюту" + "message": "Выберите счет для просмотра в MetaMask" }, "selectEachPhrase": { - "message": "Пожалуйста, выберите каждую фразу, чтобы убедиться, что она правильная." + "message": "Выберите каждую фразу, чтобы убедиться, что она верна." }, "selectHdPath": { - "message": "Выберите HD путь" - }, - "selectLocale": { - "message": "Выберите язык" + "message": "Выберите путь HD" }, "selectPathHelp": { - "message": "Если вы не видите свои существующие учетные записи Ledger ниже, попробуйте sw" + "message": "Если вы не видите свои существующие книги счетов ниже, попробуйте переключить проход на \"Legacy (MEW / MyCrypto)\"" }, "selectType": { - "message": "Выберите тип" + "message": "Выбрать тип" + }, + "selectingAllWillAllow": { + "message": "Выбор всех позволит этому сайту просматривать все ваши текущие счета. Убедитесь, что вы доверяете этому сайту." }, "send": { "message": "Отправить" @@ -995,137 +1427,452 @@ "sendETH": { "message": "Отправить ETH" }, + "sendSpecifiedTokens": { + "message": "Отправить $1", + "description": "Symbol of the specified token" + }, "sendTokens": { "message": "Отправить токены" }, "sentEther": { - "message": "Отправить Ether" + "message": "отправленный Ether" }, "separateEachWord": { - "message": "Разделяйте каждое слово одним пробелом" + "message": "Отделяйте каждое слово одним пробелом" }, "settings": { "message": "Настройки" }, "showAdvancedGasInline": { - "message": "Продвинутый контроль газа" + "message": "Расширенное управление топливом" }, "showAdvancedGasInlineDescription": { - "message": "Выберите этот параметр, чтобы отобразить параметры контроля цены и лимита газа непосредственно на экранах отправки и подтверждения." + "message": "Выберите это, чтобы отображать цену топлива и лимиты управления непосредственно на экранах отправки и подтверждения." }, "showFiatConversionInTestnets": { - "message": "Конвертировать значения в тестовых сетях" + "message": "Показать конвертацию в Testnets" }, "showFiatConversionInTestnetsDescription": { - "message": "Выберите это, чтобы отобразить конвертацию в фиат в тестовых сетях" + "message": "Выберите это, чтобы показывать конвертацию fiat в Testnets" }, "showHexData": { - "message": "Показать HEX-значение" + "message": "Показать шестнадцатеричные данные" }, "showHexDataDescription": { - "message": "Выберите это, чтобы показать шестнадцатеричное поле данных на экране отправки" + "message": "Выберите эту опцию, чтобы отобразить поле шестнадцатеричных данных на экране отправки" + }, + "showIncomingTransactions": { + "message": "Показать входящие транзакции" + }, + "showIncomingTransactionsDescription": { + "message": "Выберите это, чтобы использовать Etherscan для отображения входящих транзакций в списке транзакций" + }, + "showPermissions": { + "message": "Показать разрешения" }, "showPrivateKeys": { "message": "Показать закрытые ключи" }, + "showSeedPhrase": { + "message": "Показать исходную фразу" + }, "sigRequest": { - "message": "Запрос подписи" + "message": "Запрос на подпись" }, "sign": { - "message": "Подпись" + "message": "Подписать" }, "signNotice": { - "message": "Подпись этого сообщения может иметь \nопасные побочные эффекты. Подписывайте только сообщения \nс сайтов, которым вы полностью доверяете свой аккаунт. Этот опасный метод будет удален в будущей версии." + "message": "Подписание этого сообщения может иметь \nопасные побочные эффекты. Подписывайте сообщения только с \nсайтов, которым вы полностью доверяете всем своим счетом.\n Этот опасный метод будет удален в будущей версии. " }, "signatureRequest": { - "message": "Запрос подписи" + "message": "Запрос на подпись" + }, + "signatureRequest1": { + "message": "Сообщение" }, "signed": { - "message": "Подписана" + "message": "Подписан" }, "slow": { - "message": "Медленно" + "message": "Медленный" }, "somethingWentWrong": { - "message": "Опс! Что-то пошло не так." + "message": "Упс! Что-то пошло не так." }, "speedUp": { "message": "Ускорить" }, "speedUpCancellation": { - "message": "Ускорить отмену транзакции" + "message": "Ускорить эту отмену" }, "speedUpTransaction": { "message": "Ускорить эту транзакцию" }, + "spendLimitAmount": { + "message": "Сумма лимита расходов" + }, + "spendLimitInsufficient": { + "message": "Лимит расходов недостаточен" + }, + "spendLimitInvalid": { + "message": "Лимит расходов недействителен; должно быть положительное число" + }, + "spendLimitPermission": { + "message": "Разрешение на предел расходов" + }, + "spendLimitRequestedBy": { + "message": "Предел расходов затребован $1", + "description": "Origin of the site requesting the spend limit" + }, + "spendLimitTooLarge": { + "message": "Лимит расходов слишком велик" + }, "stateLogError": { - "message": "Ошибка при получении журнала состояния." + "message": "Ошибка при получении журналов состояния." + }, + "stateLogFileName": { + "message": "Журналы состояния MetaMask" }, "stateLogs": { - "message": "Журнал состояния" + "message": "Журналы состояний" }, "stateLogsDescription": { - "message": "Журнал состояния содержит ваши публичные адреса счетов и совершенные транзакции." + "message": "Журналы состояния содержат открытые адреса ваших счетов и отправленные транзакции." + }, + "statusConnected": { + "message": "Подключен" + }, + "statusNotConnected": { + "message": "Не подключен" }, "step1HardwareWallet": { - "message": "1. Подключите аппаратный кошелек" + "message": "1. Подключить аппаратный кошелек" }, "step1HardwareWalletMsg": { - "message": "Подключите аппаратный кошелек напрямую к компьютеру." + "message": "Подключите свой аппаратный кошелек напрямую к компьютеру." }, "step2HardwareWallet": { - "message": "2. Выберите учетную запись" + "message": "2. Выберите счет" }, "step2HardwareWalletMsg": { - "message": "Выберите учетную запись, которую вы хотите просмотреть. Вы можете выбрать только один за раз." + "message": "Выберите желаемый счет для просмотра. Вы можете выбирать только по одному." }, "step3HardwareWallet": { - "message": "3. Начните использовать dApps и многое другое!" + "message": "3. Начните использовать сайты web3 и другое!" }, "step3HardwareWalletMsg": { - "message": "Используйте свою учетную запись аппаратного обеспечения, как и любую учетную запись Ethereum. Войдите в dApps, отправьте Eth, купите и сохраните токены ERC20 и уникальные токены, такие как CryptoKitties." + "message": "Используйте свой аппаратный счет, как обычный счет Ethereum. Подключайтесь к сайтам web3, отправляйте ETH, покупайте и храните токены ERC20 и незаменяемые токены, такие как CryptoKitties." }, "storePhrase": { - "message": "Сохраните эту фразу в менеджере паролей, например 1Password." + "message": "Сохраните эту фразу в диспетчере паролей, например в 1Password." + }, + "submit": { + "message": "Отправить" }, "submitted": { - "message": "Отправлена" + "message": "Отправлено" }, "supportCenter": { - "message": "Перейти в наш Центр поддержки" + "message": "Посетите наш центр поддержки" + }, + "swap": { + "message": "Своп" + }, + "swapAdvancedSlippageInfo": { + "message": "Если цена меняется в период между размещением вашего заказа и подтверждением, это называется «проскальзыванием». Ваш своп будет автоматически отменен, если проскальзывание превысит вашу настройку «максимального проскальзывания»." + }, + "swapAggregator": { + "message": "Агрегатор" + }, + "swapAmountReceived": { + "message": "Гарантированная сумма" + }, + "swapAmountReceivedInfo": { + "message": "Это минимальная сумма, которую вы получите. Вы можете получить больше в зависимости от проскальзывания." + }, + "swapApproval": { + "message": "Одобрить $1 на свопы", + "description": "Used in the transaction display list to describe a transaction that is an approve call on a token that is to be swapped.. $1 is the symbol of a token that has been approved." + }, + "swapApproveNeedMoreTokens": { + "message": "Вам нужно еще $1 $2 для завершения этого свопа", + "description": "Tells the user how many more of a given token they need for a specific swap. $1 is an amount of tokens and $2 is the token symbol." + }, + "swapBuildQuotePlaceHolderText": { + "message": "Нет доступных токенов соответствующих $1", + "description": "Tells the user that a given search string does not match any tokens in our token lists. $1 can be any string of text" + }, + "swapCheckingQuote": { + "message": "Проверка $1", + "description": "Shown to the user during quote loading. $1 is the name of an aggregator. The message indicates that metamask is currently checking if that aggregator has a trade/quote for their requested swap." + }, + "swapCustom": { + "message": "специальный" + }, + "swapDecentralizedExchange": { + "message": "Децентрализованная обмен" + }, + "swapEditLimit": { + "message": "Изменить лимит" + }, + "swapEnableDescription": { + "message": "Это необходимо и дает MetaMask разрешение на своп вашего $1.", + "description": "Gives the user info about the required approval transaction for swaps. $1 will be the symbol of a token being approved for swaps." + }, + "swapEstimatedNetworkFee": { + "message": "Ориентировочная комиссия сети" + }, + "swapEstimatedNetworkFeeSummary": { + "message": "«$1» — это ожидаемая нами реальная комиссия. Точная сумма зависит от условий сети.", + "description": "$1 will be the translation of swapEstimatedNetworkFee, with the font bolded" + }, + "swapEstimatedNetworkFees": { + "message": "Ориентировочные комиссии сети" + }, + "swapEstimatedNetworkFeesInfo": { + "message": "Это оценочная сетевая комиссия, которая будет использована для завершения вашего свопа. Фактическая сумма может меняться в зависимости от условий сети." + }, + "swapFailedErrorTitle": { + "message": "Своп не удался" + }, + "swapFetchingQuotesErrorDescription": { + "message": "Хмм... Что-то пошло не так. Повторите попытку или, если ошибка не исчезнет, обратитесь в службу поддержки." + }, + "swapFetchingQuotesErrorTitle": { + "message": "Ошибка при получении котировок" + }, + "swapFetchingTokens": { + "message": "Получение токенов..." + }, + "swapFinalizing": { + "message": "Завершение..." + }, + "swapHighSlippageWarning": { + "message": "Величина проскальзывания очень велика. Убедитесь, что вы знаете, что делаете!" + }, + "swapIntroLearnMoreHeader": { + "message": "Хотите узнать больше?" + }, + "swapIntroLearnMoreLink": { + "message": "Подробнее о свопах MetaMask" + }, + "swapIntroLiquiditySourcesLabel": { + "message": "Источники ликвидности включают:" + }, + "swapIntroPopupSubTitle": { + "message": "Теперь вы можете обменивать токены прямо в кошельке MetaMask. MetaMask Swaps объединяет несколько децентрализованных агрегаторов обменов, профессиональных торговцев и отдельные DEX, чтобы пользователи MetaMask всегда получали лучшую цену с минимальными комиссиями сети." + }, + "swapIntroPopupTitle": { + "message": "Обмен токенов здесь!" + }, + "swapLearnMoreContractsAuditReview": { + "message": "Ознакомьтесь с нашим официальным аудитом контрактов" + }, + "swapLowSlippageError": { + "message": "Транзакции могут завершиться неудачей, максимальное проскальзывание слишком мало." + }, + "swapMaxNetworkFeeInfo": { + "message": "«$1» — это максимальная сумма, которую вы потратите. Когда сеть нестабильна, это может быть большая сумма.", + "description": "$1 will be the translation of swapMaxNetworkFees, with the font bolded" + }, + "swapMaxNetworkFees": { + "message": "Максимальная комиссия за сеть" + }, + "swapMaxSlippage": { + "message": "Максимальное проскальзывание" + }, + "swapMetaMaskFee": { + "message": "Комиссия MetaMask" + }, + "swapMetaMaskFeeDescription": { + "message": "Мы всегда находим лучшую цену из лучших источников ликвидности. Комиссия в размере $1% автоматически включается в каждую котировку на поддержку текущих разработок, чтобы сделать MetaMask еще лучше.", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapNetworkFeeSummary": { + "message": "Сетевая комиссия покрывает стоимость обработки вашего свопа и его хранения в сети Ethereum. MetaMask не получает прибыли от этой комиссии." + }, + "swapNewQuoteIn": { + "message": "Новые котировки в $1", + "description": "Tells the user the amount of time until the currently displayed quotes are update. $1 is a time that is counting down from 1:00 to 0:00" + }, + "swapOnceTransactionHasProcess": { + "message": "Ваш $1 будет добавлен к вашему счету после обработки этой транзакции.", + "description": "This message communicates the token that is being transferred. It is shown on the awaiting swap screen. The $1 will be a token symbol." + }, + "swapProcessing": { + "message": "Обработка" + }, + "swapQuoteDetails": { + "message": "Детали котировки" + }, + "swapQuoteDetailsSlippageInfo": { + "message": "Если цена меняется в период между размещением вашего заказа и подтверждением, это называется \"проскальзыванием\". Ваш своп будет автоматически отменен, если проскальзывание превысит вашу настройку \"максимального проскальзывания\"." + }, + "swapQuoteIncludesRate": { + "message": "Котировка включает $1% MetaMask fee", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapQuoteNofN": { + "message": "Котировка $1 из $2", + "description": "A count of loaded quotes shown to the user while they are waiting for quotes to be fetched. $1 is the number of quotes already loaded, and $2 is the total number of quotes to load." + }, + "swapQuoteSource": { + "message": "Источник котировки" + }, + "swapQuotesAreRefreshed": { + "message": "Котировки часто обновляются, чтобы отражать текущие рыночные условия." + }, + "swapQuotesExpiredErrorDescription": { + "message": "Запрашивайте новые котировки, чтобы узнать последние цены." + }, + "swapQuotesExpiredErrorTitle": { + "message": "Таймаут котировок" + }, + "swapQuotesNotAvailableErrorDescription": { + "message": "Попробуйте изменить настройки суммы или проскальзывания и повторите попытку." + }, + "swapQuotesNotAvailableErrorTitle": { + "message": "Не имеется доступных котировок" + }, + "swapRate": { + "message": "Цена" + }, + "swapReceiving": { + "message": "Полученный" + }, + "swapReceivingInfoTooltip": { + "message": "Это оценка. Точная сумма зависит от проскальзывания." + }, + "swapRequestForQuotation": { + "message": "Запрос котировки" + }, + "swapSearchForAToken": { + "message": "Поиск токена" + }, + "swapSelect": { + "message": "Выбрать" + }, + "swapSelectAQuote": { + "message": "Выбрать котировку" + }, + "swapSelectAToken": { + "message": "Выбрать токен" + }, + "swapSelectQuotePopoverDescription": { + "message": "Ниже приведены все котировки, собранные из нескольких источников ликвидности." + }, + "swapSlippageTooLow": { + "message": "Проскальзывание должно быть больше нуля" + }, + "swapSource": { + "message": "Источник ликвидности" + }, + "swapSourceInfo": { + "message": "Мы ищем несколько источников ликвидности (биржи, агрегаторы и профессиональные продавцы), чтобы найти лучшие цены и самые низкие сетевые комиссии." + }, + "swapStartSwapping": { + "message": "Начать обмен" + }, + "swapSwapFrom": { + "message": "Своп с" + }, + "swapSwapSwitch": { + "message": "Переход с токенов и на токены" + }, + "swapSwapTo": { + "message": "Своп на" + }, + "swapThisWillAllowApprove": { + "message": "Это позволит обмен $1." + }, + "swapTokenAvailable": { + "message": "Ваш $1 был добавлен в ваш счет.", + "description": "This message is shown after a swap is successful and communicates the exact amount of tokens the user has received for a swap. The $1 is a decimal number of tokens followed by the token symbol." + }, + "swapTokenToToken": { + "message": "Своп $1 на $2", + "description": "Used in the transaction display list to describe a swap. $1 and $2 are the symbols of tokens in involved in a swap." + }, + "swapTransactionComplete": { + "message": "Транзакция завершена" + }, + "swapUnknown": { + "message": "Неизвестный" + }, + "swapVerifyTokenExplanation": { + "message": "Несколько токенов могут использовать одно и то же имя и символ. Проверьте Etherscan, чтобы убедиться, что это именно тот токен, который вы ищете." + }, + "swapViewToken": { + "message": "Просмотреть $1" + }, + "swapYourTokenBalance": { + "message": "$1 $2 доступны для свопа", + "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" + }, + "swapZeroSlippage": { + "message": "0% проскальзывания" + }, + "swapsAdvancedOptions": { + "message": "Расширенные опции" + }, + "swapsMaxSlippage": { + "message": "Максимальное проскальзывание" + }, + "swapsNotEnoughForTx": { + "message": "Недостаточно $1 для завершения этой транзакции", + "description": "Tells the user that they don't have enough of a token for a proposed swap. $1 is a token symbol" + }, + "swapsViewInActivity": { + "message": "Посмотреть в журнале активности" }, "switchNetworks": { "message": "Переключить сети" }, + "switchToThisAccount": { + "message": "Переключить на этот счет" + }, "symbol": { "message": "Символ" }, "symbolBetweenZeroTwelve": { - "message": "Символ должен быть не более 11 символов." + "message": "Символ должен состоять из 11 или менее знаков." }, "syncWithMobile": { - "message": "Синхронизация с мобильным" + "message": "Синхронизировать с мобильным приложением" }, "syncWithMobileBeCareful": { - "message": "Убедитесь, что никто не смотрит на ваш экран при сканировании этого кода" + "message": "Убедитесь, что никто не смотрит на ваш экран, когда вы сканируете этот код" }, "syncWithMobileComplete": { "message": "Ваши данные были успешно синхронизированы. Наслаждайтесь мобильным приложением MetaMask!" }, "syncWithMobileDesc": { - "message": "Вы можете синхронизировать свои учетные записи и информацию с вашим мобильным устройством. Откройте мобильное приложение MetaMask, перейдите в «Настройки» и нажмите «Синхронизировать с расширением браузера»." + "message": "Вы можете синхронизировать свои счета и информацию со своим мобильным устройством. Откройте мобильное приложение MetaMask, перейдите в \"Настройки\" и нажмите \"Синхронизировать из расширения браузера\"" }, "syncWithMobileDescNewUsers": { - "message": "Если вы впервые открываете приложение MetaMask Mobile, просто следуйте инструкциям на телефоне." + "message": "Если вы открываете приложение MetaMask Mobile в первый раз, просто следуйте инструкциям на телефоне." }, "syncWithMobileScanThisCode": { - "message": "Сканируйте этот код с помощью мобильного приложения MetaMask." + "message": "Отсканируйте этот код с помощью мобильного приложения MetaMask" }, "syncWithMobileTitle": { - "message": "Синхронизация с мобильным" + "message": "Синхронизировать с мобильным приложением" + }, + "syncWithThreeBox": { + "message": "Синхронизация данных с 3Box (экспериментальная)" + }, + "syncWithThreeBoxDescription": { + "message": "Включите, чтобы скопировать ваши настройки с помощью 3Box. Эта функция в настоящее время является экспериментальной; Используйте на свой риск." + }, + "syncWithThreeBoxDisabled": { + "message": "3Box был отключен из-за ошибки во время начальной синхронизации" }, "terms": { - "message": "Условия пользования" + "message": "Условия использования" + }, + "termsOfService": { + "message": "Условия обслуживания" }, "testFaucet": { "message": "Тестовый кран" @@ -1134,128 +1881,162 @@ "message": "Это создаст новый кошелек и начальную фразу" }, "tips": { - "message": "Подсказки" + "message": "Советы" }, "to": { - "message": "Получатель" + "message": "Адресат" + }, + "toAddress": { + "message": "Адресат $1", + "description": "$1 is the address to include in the To label. It is typically shortened first using shortenAddress" + }, + "toWithColon": { + "message": "Адресат" }, "token": { "message": "Токен" }, "tokenAlreadyAdded": { - "message": "Токен уже был добавлен." + "message": "Токен уже добавлен." }, "tokenContractAddress": { "message": "Адрес контракта токена" }, + "tokenOptions": { + "message": "Опции токена" + }, "tokenSymbol": { "message": "Символ токена" }, "total": { - "message": "Всего" + "message": "Итого" }, "transaction": { - "message": "Транзакция" + "message": "транзакция" }, "transactionCancelAttempted": { - "message": "Предпринята попытка отмены транзакции при оплате за бензин в размере 1$ за 2$" + "message": "Попытка отменить транзакцию с платой за топливо в размере $1 в $2" }, "transactionCancelSuccess": { - "message": "Транзакция успешно отменена $2" + "message": "Транзакция успешно отменена в $2" }, "transactionConfirmed": { - "message": "Сделка подтверждена на $2." + "message": "Подтверждение транзакции в $2." }, "transactionCreated": { - "message": "Транзакция создана со значением $1 в $2." + "message": "Сделка создана со стоимостью $1 в $2." }, "transactionDropped": { - "message": "Транзакция отброшена $2." + "message": "Транзакция прекращена в $2." }, "transactionError": { - "message": "Ошибка транзакции. Исключение, указанное в коде контракта." + "message": "Ошибка транзакции. Исключение в коде контракта." }, "transactionErrorNoContract": { - "message": "Попытка вызова функции у адреса не являющегося контрактом." + "message": "Попытка вызвать функцию на неконтрактном адресе." }, "transactionErrored": { - "message": "Транзакция завершилась с ошибкой." + "message": "Транзакция обнаружила ошибку." }, "transactionFee": { - "message": "Комиссия на перевод" + "message": "Комиссия за транзакцию" }, "transactionResubmitted": { - "message": "Повторная транзакция с платой за газ увеличена до 1$ за 2$." + "message": "Попытка повторно отправить транзакцию с платой за топливо, увеличенной до $1 в $2" }, "transactionSubmitted": { - "message": "Сделка подана с оплатой за газ в размере 1$ за 2$." + "message": "Транзакция отправлена с платой за топливо в размере $1 в $2." }, "transactionUpdated": { - "message": "Транзакция обновлена до $2." + "message": "Транзакция обновлена в $2." }, "transfer": { "message": "Перевести" }, "transferBetweenAccounts": { - "message": "Перевод между моими аккаунтами" + "message": "Перевод между моими счетами" }, "transferFrom": { - "message": "Перевод из" + "message": "Перевести с" + }, + "troubleConnectingToWallet": { + "message": "Не удалось подключиться к вашему $1, попробуйте проверить $2 и повторите попытку.", + "description": "$1 is the wallet device name; $2 is a link to wallet connection guide" }, "troubleTokenBalances": { - "message": "Возникли проблемы при загрузке балансов токенов. Вы можете посмотреть их ", + "message": "У нас возникли проблемы с загрузкой вашего баланса токенов. Вы можете просмотреть их ", "description": "Followed by a link (here) to view token balances" }, + "trustSiteApprovePermission": { + "message": "Вы доверяете этому сайту? Предоставляя это разрешение, вы разрешаете $1 вывести ваши $2 и автоматизировать транзакции для вас.", + "description": "$1 is the url requesting permission and $2 is the symbol of the currency that the request is for" + }, "tryAgain": { - "message": "Попробуйте снова" + "message": "Попробуйте еще раз" }, "typePassword": { - "message": "Введите пароль" + "message": "Введите свой пароль MetaMask" }, "unapproved": { - "message": "Не одобрена" + "message": "Одобрение снято" }, "units": { - "message": "единицы" + "message": "единиц" }, "unknown": { - "message": "Неизвестно" + "message": "Неизвестный" }, "unknownCameraError": { - "message": "При попытке доступа к камере произошла ошибка. Пожалуйста, попробуйте еще раз..." + "message": "При попытке получить доступ к вашей камере произошла ошибка. Попробуйте еще раз..." }, "unknownCameraErrorTitle": { - "message": "Ой! Что-то пошло не так...." + "message": "Упс! Что-то пошло не так..." }, "unknownNetwork": { - "message": "Неизвестная частная сеть" + "message": "Неизвестная закрытая сеть" }, "unknownQrCode": { - "message": "Ошибка. Мы не смогли идентифицировать этот QR-код" + "message": "Ошибка: Мы не смогли идентифицировать этот QR-код" + }, + "unlimited": { + "message": "Неограниченное" }, "unlock": { "message": "Разблокировать" }, "unlockMessage": { - "message": "Децентрализованная сеть ждет" + "message": "Ожидание децентрализованной сети" }, "updatedWithDate": { "message": "Обновлено $1" }, "urlErrorMsg": { - "message": "Для URI требуется соответствующий префикс HTTP/HTTPS." + "message": "Для URL требуется соответствующий префикс HTTP/HTTPS." + }, + "urlExistsErrorMsg": { + "message": "URL уже присутствует в имеющемся списке сетей" + }, + "usePhishingDetection": { + "message": "Использовать обнаружение фишинга" + }, + "usePhishingDetectionDescription": { + "message": "Показывать предупреждение для фишинговых доменов, нацеленных на пользователей Ethereum" }, "usedByClients": { - "message": "Используется различными клиентами" + "message": "Используется множеством разных клиентов" }, "userName": { "message": "Имя пользователя" }, + "verifyThisTokenOn": { + "message": "Проверить этот токен на $1", + "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" + }, "viewAccount": { "message": "Посмотреть счет" }, "viewContact": { - "message": "Просмотреть контракт" + "message": "Посмотреть контакт" }, "viewOnCustomBlockExplorer": { "message": "Посмотреть на $1" @@ -1264,33 +2045,46 @@ "message": "Посмотреть на Etherscan" }, "viewinExplorer": { - "message": "Просмотреть в блок-экплорере" + "message": "Проводник в проводнике" }, "visitWebSite": { - "message": "Перейти на наш сайт" + "message": "Посетите наш веб-сайт" + }, + "walletConnectionGuide": { + "message": "наше руководство по подключению аппаратного кошелька" }, "walletSeed": { - "message": "Ключевая фраза кошелька" + "message": "Исходная фраза" }, "welcome": { "message": "Добро пожаловать в MetaMask" }, "welcomeBack": { - "message": "Рад видеть вас снова!" + "message": "Добро пожаловать обратно!" + }, + "whatsThis": { + "message": "Что это?" }, "writePhrase": { - "message": "Напишите эту фразу на листе бумаги и храните в надежном месте. Если вы хотите еще большей безопасности, запишите это на нескольких листах бумаги и храните каждый в 2 - 3 разных местах." + "message": "Запишите эту фразу на листе бумаги и храните в надежном месте. Если вы хотите дополнительную безопасность, запишите ее на нескольких листах бумаги и храните в 2–3 разных местах." + }, + "xOfY": { + "message": "$1 из $2", + "description": "$1 and $2 are intended to be two numbers, where $2 is a total, and $1 is a count towards that total" }, "yesLetsTry": { - "message": "Да, давайте начнем" + "message": "Да, давайте попробуем" }, "youNeedToAllowCameraAccess": { - "message": "Вы должны разрешить доступ к камере, чтобы использовать эту функцию." + "message": "Для использования этой функции вам необходимо разрешить доступ к камере." }, "youSign": { "message": "Вы подписываете" }, "yourPrivateSeedPhrase": { - "message": "Ваша сид-фраза" + "message": "Ваша личная исходная фраза" + }, + "zeroGasPriceOnSpeedUpError": { + "message": "Нулевая цена на топливо при ускорении" } } diff --git a/app/_locales/sk/messages.json b/app/_locales/sk/messages.json index ff375b586..29254b61a 100644 --- a/app/_locales/sk/messages.json +++ b/app/_locales/sk/messages.json @@ -894,18 +894,12 @@ "selectAnAccountHelp": { "message": "Vyberte účet, ktorý chcete zobraziť v MetaMask" }, - "selectCurrency": { - "message": "Vybrat měnu" - }, "selectEachPhrase": { "message": "Vyberte každú frázu, aby ste sa uistili, že je správna." }, "selectHdPath": { "message": "Vyberte cestu HD" }, - "selectLocale": { - "message": "Vybrať miestne nastavenia" - }, "selectPathHelp": { "message": "Ak nevidíte svoje existujúce účty v Hlavnej knihe dole, skúste prepnúť cesty na „Odkaz (MEW/MyCrypto)“" }, diff --git a/app/_locales/sl/messages.json b/app/_locales/sl/messages.json index 024cdfe6d..81ada8e54 100644 --- a/app/_locales/sl/messages.json +++ b/app/_locales/sl/messages.json @@ -913,18 +913,12 @@ "selectAnAccountHelp": { "message": "Izberi račun za prikaz v MetaMask" }, - "selectCurrency": { - "message": "Izberi valuto" - }, "selectEachPhrase": { "message": "Izberite vsako geslo ter se prepričajte, da je pravilno." }, "selectHdPath": { "message": "Izberi HD Path" }, - "selectLocale": { - "message": "Izberi jezik" - }, "selectPathHelp": { "message": "Če obstoječih Ledger ne vidite, poskusite izbrati \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/sr/messages.json b/app/_locales/sr/messages.json index e356d79a5..64a26aa38 100644 --- a/app/_locales/sr/messages.json +++ b/app/_locales/sr/messages.json @@ -922,18 +922,12 @@ "selectAnAccountHelp": { "message": "Izaberite nalog za prikaz u MetaMask-u" }, - "selectCurrency": { - "message": "Izaberite valutu" - }, "selectEachPhrase": { "message": "Molimo vas izaberite svaki izraz kako biste proverili da je tačan." }, "selectHdPath": { "message": "Izaberite HD Path" }, - "selectLocale": { - "message": "Izaberite lokalni standard" - }, "selectPathHelp": { "message": "Ako ne vidite svoje postojeće Ledger naloge dole, pokušajte prebaciti putanje na „Legacy (MEW / MyCrypto)”" }, diff --git a/app/_locales/sv/messages.json b/app/_locales/sv/messages.json index 9dd41a7ff..bf41b49e9 100644 --- a/app/_locales/sv/messages.json +++ b/app/_locales/sv/messages.json @@ -915,18 +915,12 @@ "selectAnAccountHelp": { "message": "Välj konto att visa i MetaMask" }, - "selectCurrency": { - "message": "Välj valuta" - }, "selectEachPhrase": { "message": "Välj varje fras för att säkerställa att den är korrekt." }, "selectHdPath": { "message": "Välj HD-sökväg" }, - "selectLocale": { - "message": "Välj plats" - }, "selectPathHelp": { "message": "Om du inte ser dina befintliga Ledger-konton nedan, prova att byta sökväg till \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/sw/messages.json b/app/_locales/sw/messages.json index f807fbcc1..0124d0782 100644 --- a/app/_locales/sw/messages.json +++ b/app/_locales/sw/messages.json @@ -909,18 +909,12 @@ "selectAnAccountHelp": { "message": "Chagua akaunti kuangalia kwenye MetaMask" }, - "selectCurrency": { - "message": "Chagua Sarafu" - }, "selectEachPhrase": { "message": "Tafadhali chagua kila kirai ili kuhakikisha kuwa hii ni sahihi." }, "selectHdPath": { "message": "Chagua Njia ya HD" }, - "selectLocale": { - "message": "Chagua Lugha" - }, "selectPathHelp": { "message": "Ikiwa huoni akaunti zako za Leja za sasa hapa chini, charibu kubadilisha njia kwenda \"Legacy (MEW / MyCrypto)\"  " }, diff --git a/app/_locales/ta/messages.json b/app/_locales/ta/messages.json index 1b305017a..09b0b87bb 100644 --- a/app/_locales/ta/messages.json +++ b/app/_locales/ta/messages.json @@ -432,9 +432,6 @@ "seedPhraseReq": { "message": "விதை வாக்கியங்கள் 12 வார்த்தைகள் நீண்டவை" }, - "selectCurrency": { - "message": "நாணயத்தைத் தேர்ந்தெடு" - }, "selectType": { "message": "வகை தேர்ந்தெடு" }, diff --git a/app/_locales/th/messages.json b/app/_locales/th/messages.json index 5135a467f..b0df95826 100644 --- a/app/_locales/th/messages.json +++ b/app/_locales/th/messages.json @@ -429,9 +429,6 @@ "selectAnAccount": { "message": "เลือกบัญชี" }, - "selectCurrency": { - "message": "เลือกสกุลเงิน" - }, "selectHdPath": { "message": "เลือกเส้นทาง HD" }, diff --git a/app/_locales/tl/messages.json b/app/_locales/tl/messages.json new file mode 100644 index 000000000..239c54195 --- /dev/null +++ b/app/_locales/tl/messages.json @@ -0,0 +1,2090 @@ +{ + "about": { + "message": "Tungkol Dito" + }, + "aboutSettingsDescription": { + "message": "Bersyon, support center, at impormasyon sa pakikipag-ugnayan" + }, + "acceleratingATransaction": { + "message": "* Kapag in-accelerate ang transaksyon sa pamamagitan ng paggamit ng mas mataas na presyo ng gasolina, mas magiging malaki ang tsansang mas mabilis na maproseso ng network, pero hindi ito palaging ginagarantiya." + }, + "acceptTermsOfUse": { + "message": "Nabasa ko at sumasang-ayon ako sa $1", + "description": "$1 is the `terms` message" + }, + "accessAndSpendNotice": { + "message": "Maaaring i-access ng $1 ang max na halagang ito at gumastos hanggang sa max na halagang ito", + "description": "$1 is the url of the site requesting ability to spend" + }, + "accessingYourCamera": { + "message": "Ina-access ang iyong camera..." + }, + "account": { + "message": "Account" + }, + "accountDetails": { + "message": "Mga detalye ng account" + }, + "accountName": { + "message": "Pangalan ng Account" + }, + "accountOptions": { + "message": "Mga Opsyon sa Account" + }, + "accountSelectionRequired": { + "message": "Kailangan mong pumili ng account!" + }, + "active": { + "message": "Aktibo" + }, + "activity": { + "message": "Aktibidad" + }, + "activityLog": { + "message": "log ng aktibidad" + }, + "addAccount": { + "message": "Magdagdag ng account" + }, + "addAcquiredTokens": { + "message": "Idagdag ang mga token na nakuha mo gamit ang MetaMask" + }, + "addAlias": { + "message": "Magdagdag ng alias" + }, + "addNetwork": { + "message": "Magdagdag ng Network" + }, + "addRecipient": { + "message": "Magdagdag ng Recipient" + }, + "addSuggestedTokens": { + "message": "Magdagdag ng Mga Iminumungkahing Token" + }, + "addToAddressBook": { + "message": "Idagdag sa address book" + }, + "addToAddressBookModalPlaceholder": { + "message": "hal. John D." + }, + "addToken": { + "message": "Magdagdag ng Token" + }, + "addTokens": { + "message": "Magdagdag ng Mga Token" + }, + "advanced": { + "message": "Advanced" + }, + "advancedOptions": { + "message": "Mga Advanced na Opsyon" + }, + "advancedSettingsDescription": { + "message": "I-access ang mga pang-developer na feature, i-download ang Mga Log ng Estado, I-reset ang Account, i-set up ang mga testnet at custom na RPC" + }, + "affirmAgree": { + "message": "Sang-ayon Ako" + }, + "aggregatorFeeCost": { + "message": "Bayarin sa aggregator network" + }, + "alertDisableTooltip": { + "message": "Puwede itong baguhin sa \"Mga Setting > Mga Alerto\"" + }, + "alertSettingsUnconnectedAccount": { + "message": "Napili ang pag-browse ng website nang may hindi nakakonektang account" + }, + "alertSettingsUnconnectedAccountDescription": { + "message": "Makikita ang alertong ito sa popup kapag nagba-browse ka sa isang nakakonektang Web3 site, pero hindi nakakonekta ang kasalukuyang napiling account." + }, + "alerts": { + "message": "Mga Alerto" + }, + "alertsSettingsDescription": { + "message": "I-enable o i-disable ang bawat alerto" + }, + "allowExternalExtensionTo": { + "message": "Payagan ang external extension na ito na:" + }, + "allowOriginSpendToken": { + "message": "Payagan ang $1 na gastusin ang iyong $2?", + "description": "$1 is the url of the site and $2 is the symbol of the token they are requesting to spend" + }, + "allowThisSiteTo": { + "message": "Payagan ang site na ito na:" + }, + "allowWithdrawAndSpend": { + "message": "Payagan ang $1 na mag-withdraw at gastusin ang sumusunod na halaga:", + "description": "The url of the site that requested permission to 'withdraw and spend'" + }, + "amount": { + "message": "Halaga" + }, + "amountInEth": { + "message": "$1 ETH", + "description": "Displays an eth amount to the user. $1 is a decimal number" + }, + "amountWithColon": { + "message": "Halaga:" + }, + "appDescription": { + "message": "Ethereum Wallet sa iyong Browser", + "description": "The description of the application" + }, + "appName": { + "message": "MetaMask", + "description": "The name of the application" + }, + "approvalAndAggregatorTxFeeCost": { + "message": "Bayarin sa pag-apruba at aggregator network" + }, + "approvalTxGasCost": { + "message": "Approval Tx Gas Cost" + }, + "approve": { + "message": "Aprubahan ang limitasyon sa paggastos" + }, + "approveSpendLimit": { + "message": "Aprubahan ang limitasyon sa paggastos na $1", + "description": "The token symbol that is being approved" + }, + "approved": { + "message": "Inaprubahan" + }, + "asset": { + "message": "Asset" + }, + "assets": { + "message": "Mga Asset" + }, + "attemptToCancel": { + "message": "Subukang Kanselahin?" + }, + "attemptToCancelDescription": { + "message": "Kapag isinumite ang pagsubok na ito, hindi nito magagarantiyang makakansela ang iyong orihinal na transaksyon. Kung magiging matagumpay ang pagsubok na magkansela, sisingilin ka para sa bayarin sa transaksyon sa itaas." + }, + "attemptingConnect": { + "message": "Sinusubukang kumonekta sa blockchain." + }, + "attributions": { + "message": "Mga Attribution" + }, + "authorizedPermissions": { + "message": "Inawtorisahan mo ang mga sumusunod na pahintulot" + }, + "autoLockTimeLimit": { + "message": "Timer sa Awtomatikong Pag-lock (minuto)" + }, + "autoLockTimeLimitDescription": { + "message": "Itakda ang oras ng pag-idle sa ilang minuto bago ma-lock ang MetaMask." + }, + "average": { + "message": "Average" + }, + "back": { + "message": "Bumalik" + }, + "backToAll": { + "message": "Bumalik sa Lahat" + }, + "backupApprovalInfo": { + "message": "Ang lihim na code na ito ay kinakailangan para ma-recover ang iyong wallet sakaling maiwala mo ang iyong device, makalimutan ang iyong password, kailanganin mong i-install ulit ang MetaMask, o gusto mong i-access ang iyong wallet sa ibang device." + }, + "backupApprovalNotice": { + "message": "I-back up ang iyong Lihim na Code sa Pag-recover para mapanatiling secure ang iyong wallet at mga pondo." + }, + "backupNow": { + "message": "I-back up na" + }, + "balance": { + "message": "Balanse" + }, + "balanceOutdated": { + "message": "Maaaring hindi updated ang balanse" + }, + "basic": { + "message": "Basic" + }, + "blockExplorerUrl": { + "message": "Block Explorer" + }, + "blockExplorerView": { + "message": "Tingnan ang account sa $1", + "description": "$1 replaced by URL for custom block explorer" + }, + "blockiesIdenticon": { + "message": "Gumamit ng Blockies Identicon" + }, + "browserNotSupported": { + "message": "Hindi sinusuportahan ang iyong Browser..." + }, + "builtInCalifornia": { + "message": "Ang MetaMask ay idinisenyo at binuo sa California." + }, + "buy": { + "message": "Bilhin" + }, + "buyWithWyre": { + "message": "Bumili ng ETH gamit ang Wyre" + }, + "buyWithWyreDescription": { + "message": "Nagbibigay-daan sa iyo ang Wyre na gumamit ng debit card para mag-deposit ng ETH sa mismong MetaMask account mo." + }, + "bytes": { + "message": "Bytes" + }, + "cancel": { + "message": "Kanselahin" + }, + "cancellationGasFee": { + "message": "Bayarin sa Gasolina para sa Pagkansela" + }, + "cancelled": { + "message": "Nakansela" + }, + "chainId": { + "message": "Chain ID" + }, + "chromeRequiredForHardwareWallets": { + "message": "Kailangan mong gamitin ang MetaMask sa Google Chrome para maikonekta sa iyong Hardware Wallet." + }, + "clickToRevealSeed": { + "message": "Mag-click dito para ipakita ang mga lihim na salita" + }, + "close": { + "message": "Isara" + }, + "confirm": { + "message": "Kumpirmahin" + }, + "confirmPassword": { + "message": "Kumpirmahin ang password" + }, + "confirmSecretBackupPhrase": { + "message": "Kumpirmahin ang iyong Lihim na Parirala sa Pag-back up" + }, + "confirmed": { + "message": "Nakumpirma" + }, + "congratulations": { + "message": "Congratulations" + }, + "connect": { + "message": "Kumonekta" + }, + "connectAccountOrCreate": { + "message": "Ikonekta ang account o gumawa ng bago" + }, + "connectHardwareWallet": { + "message": "Ikonekta ang Hardware Wallet" + }, + "connectManually": { + "message": "Manu-manong kumonekta sa kasalukuyang site" + }, + "connectTo": { + "message": "Kumonekta sa $1", + "description": "$1 is the name/origin of a web3 site/application that the user can connect to metamask" + }, + "connectToAll": { + "message": "Ikonekta sa lahat ng iyong $1", + "description": "$1 will be replaced by the translation of connectToAllAccounts" + }, + "connectToAllAccounts": { + "message": "mga account", + "description": "will replace $1 in connectToAll, completing the sentence 'connect to all of your accounts', will be text that shows list of accounts on hover" + }, + "connectToMultiple": { + "message": "Kumonekta sa $1", + "description": "$1 will be replaced by the translation of connectToMultipleNumberOfAccounts" + }, + "connectToMultipleNumberOfAccounts": { + "message": "Mga $1 account", + "description": "$1 is the number of accounts to which the web3 site/application is asking to connect; this will substitute $1 in connectToMultiple" + }, + "connectWithMetaMask": { + "message": "Kumonekta sa MetaMask" + }, + "connectedAccountsDescriptionPlural": { + "message": "Mayroon kang $1 (na) account na nakakonekta sa site na ito.", + "description": "$1 is the number of accounts" + }, + "connectedAccountsDescriptionSingular": { + "message": "Mayroon kang 1 account na nakakonekta sa site na ito." + }, + "connectedAccountsEmptyDescription": { + "message": "Ang MetaMask ay hindi nakakonekta sa site na ito. Para kumonekta sa isang web3 site, hanapin ang button na kumonekta sa site nila." + }, + "connectedSites": { + "message": "Mga nakakonektang site" + }, + "connectedSitesDescription": { + "message": "Ang $1 ay nakakonekta sa mga site na ito. Matitingnan nila ang address ng iyong account.", + "description": "$1 is the account name" + }, + "connectedSitesEmptyDescription": { + "message": "Ang $1 ay hindi nakakonekta sa anumang site.", + "description": "$1 is the account name" + }, + "connecting": { + "message": "Kumokonekta..." + }, + "connectingTo": { + "message": "Kumokonekta sa $1" + }, + "connectingToGoerli": { + "message": "Kumokonekta sa Goerli Test Network" + }, + "connectingToKovan": { + "message": "Kumokonekta sa Kovan Test Network" + }, + "connectingToMainnet": { + "message": "Kumokonekta sa Ethereum Mainnet" + }, + "connectingToRinkeby": { + "message": "Kumokonekta sa Rinkeby Test Network" + }, + "connectingToRopsten": { + "message": "Kumokonekta sa Ropsten Test Network" + }, + "contactUs": { + "message": "Makipag-ugnayan sa amin" + }, + "contacts": { + "message": "Mga Contact" + }, + "contactsSettingsDescription": { + "message": "Magdagdag, mag-edit, magtanggal, at mamahala ng iyong mga contact" + }, + "continueToWyre": { + "message": "Magpatuloy sa Wyre" + }, + "contractDeployment": { + "message": "Deployment ng Kontrata" + }, + "contractInteraction": { + "message": "Interaksyon ng Kontrata" + }, + "copiedExclamation": { + "message": "Nakopya na!" + }, + "copiedTransactionId": { + "message": "Nakopya ang ID ng Transaksyon" + }, + "copyAddress": { + "message": "Kopyahin ang address sa clipboard" + }, + "copyPrivateKey": { + "message": "Ito ang iyong pribadong key (i-click para kopyahin)" + }, + "copyToClipboard": { + "message": "Kopyahin sa clipboard" + }, + "copyTransactionId": { + "message": "Kopyahin ang ID ng Transaksyon" + }, + "create": { + "message": "Gumawa" + }, + "createAWallet": { + "message": "Gumawa ng Wallet" + }, + "createAccount": { + "message": "Gumawa ng Account" + }, + "createPassword": { + "message": "Gumawa ng Password" + }, + "currencyConversion": { + "message": "Conversion ng Currency" + }, + "currentAccountNotConnected": { + "message": "Hindi nakakonekta ang kasalukuyan mong account" + }, + "currentExtension": { + "message": "Kasalukuyang extension page" + }, + "currentLanguage": { + "message": "Kasalukuyang Wika" + }, + "customGas": { + "message": "I-customize ang Gasolina" + }, + "customGasSubTitle": { + "message": "Kapag dinagdagan ang bayarin, mababawasan ang mga oras ng pagproseso, pero hindi ito garantisado." + }, + "customRPC": { + "message": "Custom na RPC" + }, + "customSpendLimit": { + "message": "Custom na Limitasyon sa Paggastos" + }, + "customToken": { + "message": "Custom na Token" + }, + "dataBackupFoundInfo": { + "message": "Ang ilan sa data ng iyong account ay na-back up sa nakaraang pag-install ng MetaMask. Maaaring kasama rito ang iyong mga setting, contact, at token. Gusto mo bang i-restore na ang data na ito?" + }, + "decimal": { + "message": "Mga Decimal ng Katumpakan" + }, + "decimalsMustZerotoTen": { + "message": "Ang mga decimal ay dapat na hindi bababa sa 0, at hihigit sa 36." + }, + "decrypt": { + "message": "I-decrypt" + }, + "decryptCopy": { + "message": "Kopyahin ang naka-encrypt na mensahe" + }, + "decryptInlineError": { + "message": "Hindi made-decrypt ang mensaheng ito dahil sa error: $1", + "description": "$1 is error message" + }, + "decryptMessageNotice": { + "message": "Gusto ng $1 na basahin ang mensaheng ito para makumpleto ang iyong aksyon", + "description": "$1 is the web3 site name" + }, + "decryptMetamask": { + "message": "I-decrypt ang mensahe" + }, + "decryptRequest": { + "message": "I-decrypt ang request" + }, + "defaultNetwork": { + "message": "Ang default na network para sa mga transaksyon ng Ether ay ang Main Net." + }, + "delete": { + "message": "I-delete" + }, + "deleteAccount": { + "message": "I-delete ang Account" + }, + "deleteNetwork": { + "message": "I-delete ang Network?" + }, + "deleteNetworkDescription": { + "message": "Sigurado ka bang gusto mong i-delete ang network na ito?" + }, + "depositEther": { + "message": "Mag-deposit ng Ether" + }, + "details": { + "message": "Mga Detalye" + }, + "directDepositEther": { + "message": "Direktang Mag-deposit ng Ether" + }, + "directDepositEtherExplainer": { + "message": "Kung mayroon ka nang ilang Ether, ang pinakamabilis na paraan para makakuha ng Ether sa bago mong wallet ay sa pamamagitan ng direktang pag-deposit." + }, + "disconnect": { + "message": "Idiskonekta" + }, + "disconnectAllAccounts": { + "message": "Idiskonekta ang lahat ng account" + }, + "disconnectAllAccountsConfirmationDescription": { + "message": "Sigurado ka bang gusto mong idiskonekta? Maaaring mawala ang functionality ng site." + }, + "disconnectPrompt": { + "message": "Idiskonekta $1" + }, + "disconnectThisAccount": { + "message": "Idiskonekta ang account na ito" + }, + "dismiss": { + "message": "I-dismiss" + }, + "done": { + "message": "Tapos na" + }, + "dontHaveAHardwareWallet": { + "message": "Wala ka bang hardware wallet?" + }, + "dontShowThisAgain": { + "message": "Huwag itong ipaklita ulit" + }, + "downloadGoogleChrome": { + "message": "I-download ang Google Chrome" + }, + "downloadSecretBackup": { + "message": "I-download ang Lihim na Parirala sa Pag-back up na ito at panatilihin itong naka-store nang ligtas sa isang external na naka-encrypt na hard drive o storage medium." + }, + "downloadStateLogs": { + "message": "I-download ang Mga Log ng Estado" + }, + "dropped": { + "message": "Binitawan" + }, + "edit": { + "message": "I-edit" + }, + "editContact": { + "message": "I-edit ang Contact" + }, + "editPermission": { + "message": "Pahintulot sa Pag-edit" + }, + "encryptionPublicKeyNotice": { + "message": "Kailangan ng $1 ang iyong pampublikong encryption key. Sa pamamagitan ng pagbibigay ng pahintulot, makakagawa ang site na ito ng mga naka-encrypt na mensahe para sa iyo.", + "description": "$1 is the web3 site name" + }, + "encryptionPublicKeyRequest": { + "message": "Mag-request ng pampublikong encryption key" + }, + "endOfFlowMessage1": { + "message": "Naipasa mo ang pagsusulit - panatilihing ligtas ang iyong seedphrase, responsibilidad mo ito!" + }, + "endOfFlowMessage10": { + "message": "Tapos Na Lahat" + }, + "endOfFlowMessage2": { + "message": "Mga tip sa ligtas na pag-store nito" + }, + "endOfFlowMessage3": { + "message": "Mag-save ng backup sa maraming lugar." + }, + "endOfFlowMessage4": { + "message": "Huwag kailanmang ibahagi ang parirala sa sinuman." + }, + "endOfFlowMessage5": { + "message": "Mag-ingat sa phishing! Hindi kailanman basta na lang hihingin ng MetaMask ang iyong seed phrase." + }, + "endOfFlowMessage6": { + "message": "Kung kailangan mong i-back up ulit ang iyong seed phrase, makikita mo ito sa Mga Setting -> Seguridad." + }, + "endOfFlowMessage7": { + "message": "Sakaling mayroon kang mga tanong o may nakita kang kahina-hinalang bagay, mag-email sa support@metamask.io." + }, + "endOfFlowMessage8": { + "message": "Hindi mababawi ng MetaMask ang iyong seedphrase." + }, + "endOfFlowMessage9": { + "message": "Matuto pa." + }, + "endpointReturnedDifferentChainId": { + "message": "Nagbalik ang endpoint ng ibang chain ID: $1", + "description": "$1 is the return value of eth_chainId from an RPC endpoint" + }, + "ensNotFoundOnCurrentNetwork": { + "message": "Hindi nahanapa ang ENS name sa kasalukuyang network. Subukang lumipat sa Ethereum Mainnet." + }, + "ensRegistrationError": { + "message": "Nagka-error sa pag-register ng ENS name" + }, + "enterAnAlias": { + "message": "Maglagay ng alias" + }, + "enterMaxSpendLimit": { + "message": "Ilagay ang Max na Limitasyon sa Paggastos" + }, + "enterPassword": { + "message": "Ilagay ang password" + }, + "enterPasswordContinue": { + "message": "Ilagay ang password para magpatuloy" + }, + "errorCode": { + "message": "Code: $1", + "description": "Displayed error code for debugging purposes. $1 is the error code" + }, + "errorDetails": { + "message": "Mga Detalye ng Error", + "description": "Title for collapsible section that displays error details for debugging purposes" + }, + "errorMessage": { + "message": "Mensahe: $1", + "description": "Displayed error message for debugging purposes. $1 is the error message" + }, + "errorName": { + "message": "Code: $1", + "description": "Displayed error name for debugging purposes. $1 is the error name" + }, + "errorPageMessage": { + "message": "Subukan ulit sa pamamagitan ng pag-reload ng page, o makipag-ugnayan sa suporta sa support@metamask.io", + "description": "Message displayed on generic error page in the fullscreen or notification UI" + }, + "errorPagePopupMessage": { + "message": "Subukan ulit sa pamamagitan ng pagsara at muling pagbukas ng popup, o makipag-ugnayan sa suporta sa support@metamask.io", + "description": "Message displayed on generic error page in the popup UI" + }, + "errorPageTitle": { + "message": "Nagkaroon ng error sa MetaMask", + "description": "Title of generic error page" + }, + "errorStack": { + "message": "Stack:", + "description": "Title for error stack, which is displayed for debugging purposes" + }, + "estimatedProcessingTimes": { + "message": "Mga Tinatantyang Tagal ng Pagproseso" + }, + "eth_accounts": { + "message": "Tingnan ang mga address ng iyong mga pinapayagang account (kinakailangan)", + "description": "The description for the `eth_accounts` permission" + }, + "ethereumPublicAddress": { + "message": "Pampublikong Address ng Ethereum" + }, + "etherscan": { + "message": "Etherscan" + }, + "etherscanView": { + "message": "Tingnan ang account sa Etherscan" + }, + "expandView": { + "message": "I-expand ang view" + }, + "exportPrivateKey": { + "message": "I-export ang Pribadong Key" + }, + "externalExtension": { + "message": "External Extension" + }, + "extraApprovalGas": { + "message": "+$1 na pag-apruba sa gas", + "description": "Expresses an additional gas amount the user will have to pay, on top of some other displayed amount. $1 is a decimal amount of gas" + }, + "failed": { + "message": "Hindi matagumpay" + }, + "failedToFetchChainId": { + "message": "Hindi makuha ang chain ID. Tama ba ang URL ng iyong RPC?" + }, + "failureMessage": { + "message": "Nagkaproblema, at hindi namin makumpleto ang aksyon" + }, + "fast": { + "message": "Mabilis" + }, + "fastest": { + "message": "Pinakamabilis" + }, + "feeAssociatedRequest": { + "message": "May nauugnay na bayarin para sa request na ito." + }, + "fiat": { + "message": "Fiat", + "description": "Exchange type" + }, + "fileImportFail": { + "message": "Hindi gumagana ang pag-import ng file? Mag-click dito!", + "description": "Helps user import their account from a JSON file" + }, + "forbiddenIpfsGateway": { + "message": "Forbidden IPFS Gateway: Tumukoy ng CID gateway" + }, + "forgetDevice": { + "message": "Kalimutan ang device na ito" + }, + "from": { + "message": "Mula kay/sa" + }, + "fromAddress": { + "message": "Mula kay/sa: $1", + "description": "$1 is the address to include in the From label. It is typically shortened first using shortenAddress" + }, + "functionApprove": { + "message": "Function: Aprubahan" + }, + "functionType": { + "message": "Uri ng Function" + }, + "gasLimit": { + "message": "Limitasyon sa Gas" + }, + "gasLimitInfoTooltipContent": { + "message": "Ang limitasyon sa gas ay ang maximum na halaga ng mga unit ng gas na handa mong gastusin." + }, + "gasLimitTooLow": { + "message": "Ang limitasyon sa gas ay dapat na hindi bababa sa 21000" + }, + "gasLimitTooLowWithDynamicFee": { + "message": "Ang limitasyon sa gas ay dapat na hindi bababa sa $1", + "description": "$1 is the custom gas limit, in decimal." + }, + "gasPrice": { + "message": "Presyo ng Gas (GWEI)" + }, + "gasPriceExtremelyLow": { + "message": "Sobrang Baba ng Presyo ng Gas" + }, + "gasPriceInfoTooltipContent": { + "message": "Tinutukoy ng presyo ng gas ang halaga ng Ether na handa mong bayaran para sa bawat unit ng gas." + }, + "gasUsed": { + "message": "Nagamit na Gas" + }, + "gdprMessage": { + "message": "Ang data na ito ay pinagsama-sama at ginawang anonymous para sa mga layunin ng General Data Protection Regulation (EU) 2016/679. Para sa higit pang impormasyon kaugnay ng aming mga kagawian sa pagkapribado, pakitingnan ang aming $1.", + "description": "$1 refers to the gdprMessagePrivacyPolicy message, the translation of which is meant to be used exclusively in the context of gdprMessage" + }, + "gdprMessagePrivacyPolicy": { + "message": "Patakaran sa Pagkapribado rito", + "description": "this translation is intended to be exclusively used as the replacement for the $1 in the gdprMessage translation" + }, + "general": { + "message": "Pangkalahatan" + }, + "generalSettingsDescription": { + "message": "Conversion ng currency, pangunahing currency, wika, blockies identicon" + }, + "getEther": { + "message": "Kunin ang Ether" + }, + "getEtherFromFaucet": { + "message": "Kunin ang Ether mula sa isang faucet sa halagang $1", + "description": "Displays network name for Ether faucet" + }, + "getHelp": { + "message": "Humingi ng Tulong." + }, + "getStarted": { + "message": "Magsimula" + }, + "goerli": { + "message": "Goerli Test Network" + }, + "happyToSeeYou": { + "message": "Nagagalak kaming makilala ka." + }, + "hardware": { + "message": "Hardware" + }, + "hardwareWalletConnected": { + "message": "Nakakonekta ang hardware wallet" + }, + "hardwareWallets": { + "message": "Magkonekta ng hardware wallet" + }, + "hardwareWalletsMsg": { + "message": "Pumili ng hardware wallet na gusto mong gamitin kasama ng MetaMask" + }, + "havingTroubleConnecting": { + "message": "Nagkakaproblema ka ba sa pagkonekta?" + }, + "here": { + "message": "dito", + "description": "as in -click here- for more information (goes with troubleTokenBalances)" + }, + "hexData": { + "message": "Hex Data" + }, + "hide": { + "message": "Itago" + }, + "hideTokenPrompt": { + "message": "Itago ang Token?" + }, + "hideTokenSymbol": { + "message": "Itago $1", + "description": "$1 is the symbol for a token (e.g. 'DAI')" + }, + "history": { + "message": "History" + }, + "import": { + "message": "Mag-import", + "description": "Button to import an account from a selected file" + }, + "importAccount": { + "message": "Mag-import ng Account" + }, + "importAccountMsg": { + "message": " Ang mga na-import na account ay hindi mauugnay sa orihinal mong nagawang seedphrase ng MetaMask account. Matuto pa tungkol sa mga na-import account " + }, + "importAccountSeedPhrase": { + "message": "Mag-import ng account gamit ang seed phrase" + }, + "importUsingSeed": { + "message": "I-import gamit ang seed phrase ng account" + }, + "importWallet": { + "message": "I-import ang wallet" + }, + "importYourExisting": { + "message": "I-import ang iyong kasalukuyang wallet gamit ang 12 salita na seed phrase" + }, + "imported": { + "message": "Na-import", + "description": "status showing that an account has been fully loaded into the keyring" + }, + "infoHelp": { + "message": "Impormasyon at Tulong" + }, + "initialTransactionConfirmed": { + "message": "Nakumpirma na ng network ang iyong inisyal na transaksyon. I-click ang OK para bumalik." + }, + "insufficientBalance": { + "message": "Hindi sapat ang balanse." + }, + "insufficientFunds": { + "message": "Hindi sapat ang pondo." + }, + "insufficientTokens": { + "message": "Hindi sapat ang token." + }, + "invalidAddress": { + "message": "Hindi valid ang address" + }, + "invalidAddressRecipient": { + "message": "Hindi valid ang address ng tatanggap" + }, + "invalidAddressRecipientNotEthNetwork": { + "message": "Hindi ETH network, itakda sa maliliit na letra" + }, + "invalidBlockExplorerURL": { + "message": "Hindi Valid ang URL ng Block Explorer" + }, + "invalidCustomNetworkAlertContent1": { + "message": "Kailangang ilagay ulit ang chain ID para sa custom na network na '$1'.", + "description": "$1 is the name/identifier of the network." + }, + "invalidCustomNetworkAlertContent2": { + "message": "Para maprotektahan ka sa mga nakakahamak o palyadong network provider, kinakailangan na ngayon ang mga chain ID para sa lahat ng custom na network." + }, + "invalidCustomNetworkAlertContent3": { + "message": "Pumunta sa Mga Setting > Network at ilagay ang chain ID. Makikita mo ang mga chain ID ng mga pinakasikat na network sa $1.", + "description": "$1 is a link to https://chainid.network" + }, + "invalidCustomNetworkAlertTitle": { + "message": "Hindi Valid ang Custom na Network" + }, + "invalidHexNumber": { + "message": "Hindi valid ang hexadecimal number." + }, + "invalidHexNumberLeadingZeros": { + "message": "Hindi valid ang hexadecimal number. Tanggalin ang anumang zero sa unahan." + }, + "invalidIpfsGateway": { + "message": "Hindi Valid ang IPFS Gateway: Dapat ay valid na URL ang value" + }, + "invalidNumber": { + "message": "Hindi valid ang numero. Maglagay ng decimal o '0x'-prefixed hexadecimal number." + }, + "invalidNumberLeadingZeros": { + "message": "Hindi valid ang numero. Tanggalin ang anumang zero sa unahan." + }, + "invalidRPC": { + "message": "Hindi valid ang RPC URL" + }, + "invalidSeedPhrase": { + "message": "Hindi valid ang seed phrase" + }, + "ipfsGateway": { + "message": "IPFS Gateway" + }, + "ipfsGatewayDescription": { + "message": "Ilagay ang URL ng IPFS CID gateway para magamit para sa resolusyon ng content ng ENS." + }, + "jsonFile": { + "message": "JSON File", + "description": "format for importing an account" + }, + "knownAddressRecipient": { + "message": "Kilalang address ng kontrata." + }, + "knownTokenWarning": { + "message": "Mae-edit ng aksyong ito ang mga token na nakalista na sa iyong wallet, na puwedeng gamitin para i-phish ka. Aprubahan lang kung sigurado kang gusto mong baguhin kung ano ang kinakatawan ng mga token na ito." + }, + "kovan": { + "message": "Kovan Test Network" + }, + "lastConnected": { + "message": "Huling Kumonekta" + }, + "learnMore": { + "message": "Matuto pa" + }, + "ledgerAccountRestriction": { + "message": "Kailangan mong gamitin ang huli mong account bago ka magdagdag ng panibago." + }, + "letsGoSetUp": { + "message": "Sige, simulan na nating mag-set up!" + }, + "likeToAddTokens": { + "message": "Gusto mo bang idagdag ang mga token na ito?" + }, + "links": { + "message": "Mga Link" + }, + "loadMore": { + "message": "Matuto Pa" + }, + "loading": { + "message": "Nilo-load..." + }, + "loadingTokens": { + "message": "Nilo-load ang Mga Token..." + }, + "localhost": { + "message": "Localhost 8545" + }, + "lock": { + "message": "I-lock" + }, + "lockTimeTooGreat": { + "message": "Masyadong matagal ang oras ng pag-lock" + }, + "mainnet": { + "message": "Ethereum Mainnet" + }, + "max": { + "message": "Max" + }, + "memo": { + "message": "memo" + }, + "memorizePhrase": { + "message": "Tandaan ang phrase na ito." + }, + "message": { + "message": "Mensahe" + }, + "metaMaskConnectStatusParagraphOne": { + "message": "Mas may kontrol ka na ngayon sa mga koneksyon ng iyong account sa MetaMask." + }, + "metaMaskConnectStatusParagraphThree": { + "message": "I-click ito para pamahalaan ang mga nakakonekta mong account." + }, + "metaMaskConnectStatusParagraphTwo": { + "message": "Makikita sa button ng status ng koneksyon kung nakakonekta ang website na binibisita mo sa kasalukuyan mong napiling account." + }, + "metamaskDescription": { + "message": "Ikinokonekta ka sa Ethereum at sa Decentralized Web." + }, + "metamaskSwapsOfflineDescription": { + "message": "Kasalukuyang minementina ang MetaMask Swaps. Bumalik sa ibang pagkakataon." + }, + "metamaskVersion": { + "message": "Bersyon ng MetaMask" + }, + "metametricsCommitmentsAllowOptOut": { + "message": "Palagi kang papayagang mag-opt out sa pamamagitan ng Mga Setting" + }, + "metametricsCommitmentsBoldNever": { + "message": "Huwag Kailanman", + "description": "This string is localized separately from some of the commitments so that we can bold it" + }, + "metametricsCommitmentsIntro": { + "message": "Gagawin ng MetaMask ang sumusunod..." + }, + "metametricsCommitmentsNeverCollectIP": { + "message": "$1 kolektahin ang iyong IP address", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverCollectKeysEtc": { + "message": "$1 nangongolekta ng mga key, address, transaksyon, balanse, hash, o anumang personal na impormasyon", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverSellDataForProfit": { + "message": "$1 nagbebenta ng data para pagkakitaan. Kahit kailan!", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsSendAnonymizedEvents": { + "message": "Magpapadala ng mga anonymous na kaganapang pag-click at pagtingin sa page" + }, + "metametricsHelpImproveMetaMask": { + "message": "Tulungan Kaming Mapahusay ang MetaMask" + }, + "metametricsOptInDescription": { + "message": "Gustong kunin ng MetaMask ang data ng paggamit para mas maunawaan kung paano ginagamit ng mga user namin ang extension. Gagamitin ang data na ito para patuloy na mapahusay ang kakayahang magamit at karanasan ng user sa paggamit ng produkto namin at Ethereum ecosystem." + }, + "mobileSyncText": { + "message": "Pakilagay ang iyong password para makumpirmang ikaw nga ito!" + }, + "mustSelectOne": { + "message": "Dapat pumili ng kahit 1 token lang." + }, + "myAccounts": { + "message": "Mga Account Ko" + }, + "myWalletAccounts": { + "message": "Mga Wallet Account Ko" + }, + "myWalletAccountsDescription": { + "message": "Ang lahat ng iyong ginawang account sa MetaMask ay awtomatikong maidaragdag sa seksyong ito." + }, + "needEtherInWallet": { + "message": "Para makaugnayan ang mga decentralized ma application gamit ang MetaMask, kakailanganin mo ang Ether sa iyong wallet." + }, + "needImportFile": { + "message": "Dapat kang pumili ng file na ii-import.", + "description": "User is important an account and needs to add a file to continue" + }, + "negativeETH": { + "message": "Hindi makakapagpadala ng mga negatibong halaga ng ETH." + }, + "networkName": { + "message": "Pangalan ng Network" + }, + "networkSettingsChainIdDescription": { + "message": "Ginagaamit ang chain ID sa paglagda ng mga transaksyon. Dapat itong tumugma sa chain ID na ibinalik ng network. Puwede kang maglagay ng decimal o '0x'-prefixed hexadecimal number, pero ipapakita namin ang numero sa decimal." + }, + "networkSettingsDescription": { + "message": "Magdagdag at mag-edit ng mga custom na RPC network" + }, + "networks": { + "message": "Mga Network" + }, + "nevermind": { + "message": "Huwag na" + }, + "newAccount": { + "message": "Bagong Account" + }, + "newAccountDetectedDialogMessage": { + "message": "May natukoy na bagong address! Mag-click dito para idagdag sa iyong address book." + }, + "newAccountNumberName": { + "message": "Account $1", + "description": "Default name of next account to be created on create account screen" + }, + "newContact": { + "message": "Bagong Contact" + }, + "newContract": { + "message": "Bagong Kontrata" + }, + "newNetwork": { + "message": "Bagong Network" + }, + "newPassword": { + "message": "Bagong password (min na 8 char)" + }, + "newToMetaMask": { + "message": "Bago ka ba sa MetaMask?" + }, + "newTotal": { + "message": "Bagong Kabuuan" + }, + "newTransactionFee": { + "message": "Bagong Bayarin sa Transaksyon" + }, + "next": { + "message": "Susunod" + }, + "nextNonceWarning": { + "message": "Mas mataas ang noncesa iminumungkahing nonce na $1", + "description": "The next nonce according to MetaMask's internal logic" + }, + "noAccountsFound": { + "message": "Walang nakitang account para sa ibinigay na query sa paghahanap" + }, + "noAddressForName": { + "message": "Walang naitakdang address para sa pangalang ito." + }, + "noAlreadyHaveSeed": { + "message": "May seed phrase na ako" + }, + "noConversionRateAvailable": { + "message": "Hindi Available ang Rate ng Conversion" + }, + "noThanks": { + "message": "Huwag na lang" + }, + "noTransactions": { + "message": "Wala kang transaksyon" + }, + "noWebcamFound": { + "message": "Hindi nakita ang webcam ng iyong computer. Pakisubukan ulit." + }, + "noWebcamFoundTitle": { + "message": "Hindi nakita ang webcam" + }, + "nonceField": { + "message": "I-customize ang transaksyon nang isang beses" + }, + "nonceFieldDescription": { + "message": "I-on ito para baguhin ang nonce (numero ng transaksyon) sa mga screen ng kumpirmasyon. Isa itong advanced na feature, gamitin nang may pag-iingat." + }, + "nonceFieldHeading": { + "message": "Custom na Nonce" + }, + "notCurrentAccount": { + "message": "Ito ba ang tamang account? Iba ito sa kasalukuyang napiling account sa iyong wallet" + }, + "notEnoughGas": { + "message": "Hindi Sapat ang Gas" + }, + "ofTextNofM": { + "message": "ng" + }, + "off": { + "message": "Naka-off" + }, + "offlineForMaintenance": { + "message": "Offline para sa pagmementina" + }, + "ok": { + "message": "Ok" + }, + "on": { + "message": "Naka-on" + }, + "onboardingReturnNotice": { + "message": "Isasara ng \"$1\" ang tab na ito at ididirekta ka pabalik sa $2", + "description": "Return the user to the site that initiated onboarding" + }, + "onlyAddTrustedNetworks": { + "message": "Maaaring magsinungaling ang nakakahamak na Ethereum network providertungkol sa estado ng blockchain at i-record ang aktibidad ng iyong network. Magdagdag lang ng mga custom na network na pinagkakatiwalaan mo." + }, + "onlyAvailableOnMainnet": { + "message": "Available lang sa mainnet" + }, + "onlyConnectTrust": { + "message": "Kumonekta lang sa mga site na pinagkakatiwalaan mo." + }, + "optionalBlockExplorerUrl": { + "message": "URL ng Block Explorer (opsyonal)" + }, + "optionalCurrencySymbol": { + "message": "Simbolo ng Currency (opsyonal)" + }, + "orderOneHere": { + "message": "Mag-order ng Trezor o Ledger at itabi ang mga pondo mo sa malamig na storage" + }, + "origin": { + "message": "Pinagmulan" + }, + "parameters": { + "message": "Mga Parameter" + }, + "participateInMetaMetrics": { + "message": "Sumali sa MetaMetrics" + }, + "participateInMetaMetricsDescription": { + "message": "Sumali sa MetaMetrics para mas mapahusay namin ang MetaMask" + }, + "password": { + "message": "Password" + }, + "passwordNotLongEnough": { + "message": "Hindi sapat ang haba ng password" + }, + "passwordsDontMatch": { + "message": "Hindi Magkatugma ang Mga Password" + }, + "pastePrivateKey": { + "message": "I-paste ang string ng iyong pribadong key dito:", + "description": "For importing an account from a private key" + }, + "pending": { + "message": "Nakabinbin" + }, + "permissionCheckedIconDescription": { + "message": "Inaprubahan mo ang pahintulot na ito" + }, + "permissionUncheckedIconDescription": { + "message": "Hindi mo inaprubahan ang pahintulot na ito" + }, + "permissions": { + "message": "Mga Pahintulot" + }, + "personalAddressDetected": { + "message": "Natukoy ang personal na address. Ilagay ang address ng kontrata ng token." + }, + "plusXMore": { + "message": "+ $1 pa", + "description": "$1 is a number of additional but unshown items in a list- this message will be shown in place of those items" + }, + "prev": { + "message": "Nakaraan" + }, + "primaryCurrencySetting": { + "message": "Pangunahing Currency" + }, + "primaryCurrencySettingDescription": { + "message": "Piliin ang native para maisapriyoridad ang pagpapakita ng mga value sa native na currency ng chain (hal. ETH). Piliin ang Fiat para maisapriyoridad ang pagpapakita ng mga value sa napili mong fiat currency." + }, + "privacyMsg": { + "message": "Patakaran sa Pagkapribado" + }, + "privateKey": { + "message": "Pribadong Key", + "description": "select this type of file to use to import an account" + }, + "privateKeyWarning": { + "message": "Babala: Huwag ipaalam ang key na ito. Ang sinumang mayroon ng iyong mga pribadong key ay maaaring magnakaw ng anumang asset sa iyong account." + }, + "privateNetwork": { + "message": "Pribadong Network" + }, + "proposedApprovalLimit": { + "message": "Iminumungkahing Limitasyon sa Pag-apruba" + }, + "protectYourKeys": { + "message": "Protektahan ang Iyong Mga Key!" + }, + "protectYourKeysMessage1": { + "message": "Ingatan ang iyong seed phrase — may mga naiulat na website na sinusubukang gayahin ang MetaMask. Hindi kailanman hihingin ng MetaMask ang iyong seed phrase!" + }, + "protectYourKeysMessage2": { + "message": "Ingatan ang iyong phrase. Kung may makikita kang kahina-hinalang bagay, o hindi ka sigurado sa isang website, mag-email sa support@metamask.io" + }, + "provide": { + "message": "Ibigay" + }, + "queue": { + "message": "Queue" + }, + "queued": { + "message": "Naka-queue" + }, + "readdToken": { + "message": "Puwede mong ibalik ang token na ito sa hinaharap sa pamamagitan ng pagpunta sa “Magdagdag ng token” sa menu ng mga opsyon sa iyong account." + }, + "readyToConnect": { + "message": "Handa ka na bang kumonekta?" + }, + "receive": { + "message": "Tumanggap" + }, + "recents": { + "message": "Mga Kamakailan" + }, + "recipientAddress": { + "message": "Address ng Tatanggap" + }, + "recipientAddressPlaceholder": { + "message": "Maghanap, pampublikong address (0x), o ENS" + }, + "reject": { + "message": "Tanggihan" + }, + "rejectAll": { + "message": "Tanggihan Lahat" + }, + "rejectTxsDescription": { + "message": "Maramihan mong tatanggihan ang $1 (na) transaksyon." + }, + "rejectTxsN": { + "message": "Tanggihan ang $1 transaksyon" + }, + "rejected": { + "message": "Tinanggihan" + }, + "remindMeLater": { + "message": "Paalalahanan ako mamaya" + }, + "remove": { + "message": "Tanggalin" + }, + "removeAccount": { + "message": "Tanggalin ang account" + }, + "removeAccountDescription": { + "message": "Tatanggalin ang account na ito sa iyong wallet. Tiyaking nasa iyo ang orihinal na seed phrase o pribadong key para sa na-import na account na ito bago magpatuloy. Puwede kang mag-import o gumawa ulit ng mga account mula sa drop-down ng account. " + }, + "requestsAwaitingAcknowledgement": { + "message": "mga request na hinihintay na tanggapin" + }, + "required": { + "message": "Kinakailangan" + }, + "reset": { + "message": "I-reset" + }, + "resetAccount": { + "message": "I-reset ang Account" + }, + "resetAccountDescription": { + "message": "Kapag ni-reset ang iyong account, maki-clear ang history ng iyong transaksyon. Hindi nito babaguhin ang mga balanse sa iyong mga account o hindi mo kakailanganing ilagay ulit ang iyong seed phrase." + }, + "restore": { + "message": "I-restore" + }, + "restoreAccountWithSeed": { + "message": "I-restore ang iyong Account gamit ang Seed Phrase" + }, + "restoreFromSeed": { + "message": "I-restore ang account?" + }, + "restoreWalletPreferences": { + "message": "Nakita ang backup ng iyong data mula sa $1. Gusto mo bang i-restore ang mga kagustuhan mo sa wallet?", + "description": "$1 is the date at which the data was backed up" + }, + "retryTransaction": { + "message": "Subukan Ulit ang Transaksyon" + }, + "reusedTokenNameWarning": { + "message": "Ang isang token dito ay muling ginagamit ang isang simbolo mula sa ibang token na tinitingnan mo, maaari itong maging nakakalito." + }, + "revealSeedWords": { + "message": "Ipakita ang Seed Phrase" + }, + "revealSeedWordsDescription": { + "message": "Kung papalitan mo ang iyong browser o ililipat ang mga computer, kakailanganin mo ang seed phrase na ito para ma-access ang iyong mga account. I-save ang mga iyon sa isang ligtas at sikretong lugar." + }, + "revealSeedWordsTitle": { + "message": "Seed Phrase" + }, + "revealSeedWordsWarning": { + "message": "Magagamit ang mga salitang ito para manakaw ang lahat ng iyong account." + }, + "revealSeedWordsWarningTitle": { + "message": "Huwag ibahagi ang phrase na ito sa sinuman!" + }, + "rinkeby": { + "message": "Rinkeby Test Network" + }, + "ropsten": { + "message": "Ropsten Test Network" + }, + "rpcUrl": { + "message": "Bagong RPC URL" + }, + "save": { + "message": "I-save" + }, + "saveAsCsvFile": { + "message": "I-save bilang CSV File" + }, + "scanInstructions": { + "message": "Itapat ang QR code sa iyong camera" + }, + "scanQrCode": { + "message": "Mag-scan ng QR Code" + }, + "scrollDown": { + "message": "Mag-scroll pababa" + }, + "search": { + "message": "Maghanap" + }, + "searchAccounts": { + "message": "Maghanap ng Account" + }, + "searchResults": { + "message": "Mga Resulta ng Paghahanap" + }, + "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." + }, + "secretBackupPhraseWarning": { + "message": "BABALA: Huwag kailanman ipaalam ang iyong phrase sa pag-back up. Ang sinumang may phrase na ito ay maaaring angkinin ang iyong Ether." + }, + "secretPhrase": { + "message": "Ilagay ang iyong labindalawang lihim na phrase dito para ma-restore ang iyong vault." + }, + "securityAndPrivacy": { + "message": "Seguridad at Pagkapribado" + }, + "securitySettingsDescription": { + "message": "Mga setting ng pagkapribado at seed phrase ng wallet" + }, + "seedPhrasePlaceholder": { + "message": "Paghiwa-hiwalayin ang bawat salita gamit ang espasyo" + }, + "seedPhrasePlaceholderPaste": { + "message": "I-paste ang seed phrase mula sa clipboard" + }, + "seedPhraseReq": { + "message": "Ang mga seed phrase ay naglalaman ng 12, 15, 18, 21, o 24 na salita" + }, + "selectAHigherGasFee": { + "message": "Pumili ng mas malaking bayarin sa gas para mapabilis ang pagproseso ng iyong transaksyon.*" + }, + "selectAccounts": { + "message": "Pumili ng (mga) account" + }, + "selectAll": { + "message": "Piliin lahat" + }, + "selectAnAccount": { + "message": "Pumili ng Account" + }, + "selectAnAccountHelp": { + "message": "Piliin ang account na titingnan sa MetaMask" + }, + "selectEachPhrase": { + "message": "Pakipili ang bawat phrase para matiyak na tama ito." + }, + "selectHdPath": { + "message": "Pumili ng HD Path" + }, + "selectPathHelp": { + "message": "Kung hindi mo makita ang mga kasalukuyan mong Ledger account sa ibaba, subukang ilipat ang path sa \"Legacy (MEW / MyCrypto)\"" + }, + "selectType": { + "message": "Pumili ng Uri" + }, + "selectingAllWillAllow": { + "message": "Kapag pinili lahat, mabibigyang-daan ang site na ito na makita ang lahat ng kasalukuyan mong account. Tiyaking pinagkakatiwalaan mo ang site na ito." + }, + "send": { + "message": "Magpadala" + }, + "sendAmount": { + "message": "Halaga ng Ipapadala" + }, + "sendETH": { + "message": "Magpadala ng ETH" + }, + "sendSpecifiedTokens": { + "message": "Magpadala ng $1", + "description": "Symbol of the specified token" + }, + "sendTokens": { + "message": "Magpadala ng Mga Token" + }, + "sentEther": { + "message": "nagpadala ng ether" + }, + "separateEachWord": { + "message": "Paghiwa-hiwalayin ang bawat salita gamit ang espasyo" + }, + "settings": { + "message": "Mga Setting" + }, + "showAdvancedGasInline": { + "message": "Mga advanced na kontrol sa gas" + }, + "showAdvancedGasInlineDescription": { + "message": "Piliin ito para direktang maipakita ang presyo ng gas at mga kontrol sa limitasyon sa mga screen ng pagpapadala at pagkumpirma." + }, + "showFiatConversionInTestnets": { + "message": "Ipakita ang Conversion sa Testnets" + }, + "showFiatConversionInTestnetsDescription": { + "message": "Piliin ito para ipakita ang fiat conversion sa Testnets" + }, + "showHexData": { + "message": "Ipakita ang Hex Data" + }, + "showHexDataDescription": { + "message": "Piliin ito para ipakita ang field ng hex data sa screen ng pagpapadala" + }, + "showIncomingTransactions": { + "message": "Ipakita ang Mga Papasok na Transaksyon" + }, + "showIncomingTransactionsDescription": { + "message": "Piliin ito para gamitin ang Etherscan sa pagpapakita ng mga papasok na transaksyon sa listahan ng mga transaksyon" + }, + "showPermissions": { + "message": "Ipakita ang mga pahintulot" + }, + "showPrivateKeys": { + "message": "Ipakita ang Mga Pribadong Key" + }, + "showSeedPhrase": { + "message": "Ipakita ang seed phrase" + }, + "sigRequest": { + "message": "Request na Paglagda" + }, + "sign": { + "message": "Lumagda" + }, + "signNotice": { + "message": "Maaaring may mga \nmapanganib na side effect ang paglagda sa mensaheng ito. Lagdaan lang ang mga mensahe mula sa \nmga site na pinagkakatiwalaan mo para sa buong account mo.\n Tatanggalin ang mapanganib na paraang ito sa bersyon sa hinaharap. " + }, + "signatureRequest": { + "message": "Request na Paglagda" + }, + "signatureRequest1": { + "message": "Mensahe" + }, + "signed": { + "message": "Nilagdaan" + }, + "slow": { + "message": "Mabagal" + }, + "somethingWentWrong": { + "message": "Oops! Nagkaproblema." + }, + "speedUp": { + "message": "Pabilisin" + }, + "speedUpCancellation": { + "message": "Pabilisin ang pagkanselang ito" + }, + "speedUpTransaction": { + "message": "Pabilisin ang transaksyong ito" + }, + "spendLimitAmount": { + "message": "Halaga ng limitasyon sa paggastos" + }, + "spendLimitInsufficient": { + "message": "Hindi sapat ang limitasyon sa paggastos" + }, + "spendLimitInvalid": { + "message": "Hindi valid ang limitasyon sa paggastos; dapat ay positibong numero" + }, + "spendLimitPermission": { + "message": "Pahintulot sa limitasyon sa paggastos" + }, + "spendLimitRequestedBy": { + "message": "Limitasyon sa paggastos ayon sa inire-request ng $1", + "description": "Origin of the site requesting the spend limit" + }, + "spendLimitTooLarge": { + "message": "Masyadong malaki ang limitasyon sa paggastos" + }, + "stateLogError": { + "message": "Error sa pagkuha ng mga log ng estado." + }, + "stateLogFileName": { + "message": "Mga Log ng Estado ng MetaMask" + }, + "stateLogs": { + "message": "Mga Log ng Estado" + }, + "stateLogsDescription": { + "message": "Naglalaman ang mga log ng estado ng iyong mga address ng pampublikong account at ipinadalang transaksyon." + }, + "statusConnected": { + "message": "Nakakonekta" + }, + "statusNotConnected": { + "message": "Hindi nakakonekta" + }, + "step1HardwareWallet": { + "message": "1. Ikonekta ang Hardware Wallet" + }, + "step1HardwareWalletMsg": { + "message": "Direktang ikonekta ang wallet ng iyong hardware sa computer mo." + }, + "step2HardwareWallet": { + "message": "2. Pumili ng Account" + }, + "step2HardwareWalletMsg": { + "message": "Piliin ang account na gusto mong tingnan. Puwede ka lang pumili ng isa sa isang pagkakataon." + }, + "step3HardwareWallet": { + "message": "3. Simulang gamitin ang mga web3 site at higit pa!" + }, + "step3HardwareWalletMsg": { + "message": "Gamitin ang account ng iyong hardware sa parehong paraan ng paggamit mo sa Ethereum account. Kumonekta sa mga web3 site, magpadala ng ETH, bumili at mag-store ng mga ERC20 token at non-fungible token gaya ng CryptoKitties." + }, + "storePhrase": { + "message": "I-store ang phrase na ito sa isang password manager gaya ng 1Password." + }, + "submit": { + "message": "Isumite" + }, + "submitted": { + "message": "Isinumite" + }, + "supportCenter": { + "message": "Bisitahin ang aming Support Center" + }, + "swap": { + "message": "I-swap" + }, + "swapAdvancedSlippageInfo": { + "message": "Kung magbabago ang presyo sa pagitan ng oras ng pag-order mo at sa oras na nakumpirma ito, tinatawag itong “slippage”. Awtomatikong makakansela ang iyong pag-swap kung lalampas ang slippage sa iyong setting na “max slippage”." + }, + "swapAggregator": { + "message": "Aggregator" + }, + "swapAmountReceived": { + "message": "Garantisadong halaga" + }, + "swapAmountReceivedInfo": { + "message": "Ito ang minimum na halagang matatanggap mo. Maaari kang makatanggap ng mas malaki depende sa slippage." + }, + "swapApproval": { + "message": "Aprubahan ang $1 para sa mga pagpapalit", + "description": "Used in the transaction display list to describe a transaction that is an approve call on a token that is to be swapped.. $1 is the symbol of a token that has been approved." + }, + "swapApproveNeedMoreTokens": { + "message": "Kailangan mo ng $1 pa $2 para makumpleto ang pag-swap na ito", + "description": "Tells the user how many more of a given token they need for a specific swap. $1 is an amount of tokens and $2 is the token symbol." + }, + "swapBuildQuotePlaceHolderText": { + "message": "Walang available na token na tumutugma sa $1", + "description": "Tells the user that a given search string does not match any tokens in our token lists. $1 can be any string of text" + }, + "swapCheckingQuote": { + "message": "Sinusuri ang $1", + "description": "Shown to the user during quote loading. $1 is the name of an aggregator. The message indicates that metamask is currently checking if that aggregator has a trade/quote for their requested swap." + }, + "swapCustom": { + "message": "custom" + }, + "swapDecentralizedExchange": { + "message": "Decentralized exchange" + }, + "swapEditLimit": { + "message": "I-edit ang limitasyon" + }, + "swapEnableDescription": { + "message": "Kinakailangan ito at nagbibigay ito ng pahintulot sa MetaMask na i-swap ang iyong $1.", + "description": "Gives the user info about the required approval transaction for swaps. $1 will be the symbol of a token being approved for swaps." + }, + "swapEstimatedNetworkFee": { + "message": "Tinatayang bayarin sa network" + }, + "swapEstimatedNetworkFeeSummary": { + "message": "Ang “$1” ay ang inaasahan naming magiging aktuwal na bayarin. Ang eksaktong halaga ay nakadepende sa mga kundisyon ng network.", + "description": "$1 will be the translation of swapEstimatedNetworkFee, with the font bolded" + }, + "swapEstimatedNetworkFees": { + "message": "Mga tinatayang bayarin sa network" + }, + "swapEstimatedNetworkFeesInfo": { + "message": "Ito ay pagtatantya ng bayarin sa network na gagamitin para kumpletuhin ang iyong pag-swap. Maaaring magbago ang aktuwal na halaga ayon sa mga kundisyon ng network." + }, + "swapFailedErrorTitle": { + "message": "Hindi matagumpay ang pag-swap" + }, + "swapFetchingQuotesErrorDescription": { + "message": "Hmmm... nagkaproblema. Subukan ulit, o kung magpapatuloy ang mga error, makipag-ugnayan sa customer support." + }, + "swapFetchingQuotesErrorTitle": { + "message": "Nagka-error sa pagkuha ng mga quote" + }, + "swapFetchingTokens": { + "message": "Kinukuha ang mga token..." + }, + "swapFinalizing": { + "message": "Isinasapinal..." + }, + "swapHighSlippageWarning": { + "message": "Sobrang laki ng halaga ng slippage. Tiyaking alam mo ang ginagawa mo!" + }, + "swapIntroLearnMoreHeader": { + "message": "Gusto mo bang matuto pa?" + }, + "swapIntroLearnMoreLink": { + "message": "Matuto pa tungkol sa MetaMask Swaps" + }, + "swapIntroLiquiditySourcesLabel": { + "message": "Kasama sa mga pinagkunan ng liquidity ang:" + }, + "swapIntroPopupSubTitle": { + "message": "Puwede mo nang direktang i-swap ang mga token sa iyong MetaMask wallet. Pinagsasama-sama ng MetaMask Swaps ang maraming decentralized exchange aggregator, propesyonal na market maker, at indibidwal na DEX para matiyak na makukuha palagi ng mga user ng MetaMask ang pinakasulit na presyo nang may pinakamababang bayarin sa network." + }, + "swapIntroPopupTitle": { + "message": "Ito na ang pag-swap ng token!" + }, + "swapLearnMoreContractsAuditReview": { + "message": "Suriin ang aming audit ng mga opisyal na kontrata" + }, + "swapLowSlippageError": { + "message": "Maaaring hindi magtagumpay ang transaksyon, masyadong mababa ang max na slippage." + }, + "swapMaxNetworkFeeInfo": { + "message": "Aang “$1” ay ang pinakamalaking gagastusin mo. Kapag volatile ang network, maaaring malaking halaga ito.", + "description": "$1 will be the translation of swapMaxNetworkFees, with the font bolded" + }, + "swapMaxNetworkFees": { + "message": "Max na bayarin sa network" + }, + "swapMaxSlippage": { + "message": "Max na slippage" + }, + "swapMetaMaskFee": { + "message": "Bayarin sa MetaMask" + }, + "swapMetaMaskFeeDescription": { + "message": "Hinahanap namin ang pinakasulit na presyo mula sa mga nangungunang pinagkukunan ng liquidity, sa lahat ng pagkakataon. Ang bayarin na $1% ay awtomatikong fina-factor sa bawat quote, na sumusuporta sa kasalukuyang development para mas mapahusay ang MetaMask.", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapNetworkFeeSummary": { + "message": "Kasama sa bayarin sa network ang gastusin sa pagproseso ng iyong pag-swap at pag-store nito sa Ethereum network. Hindi kumikita ang MetaMask mula sa bayaring ito." + }, + "swapNewQuoteIn": { + "message": "Mga bagong quote sa $1", + "description": "Tells the user the amount of time until the currently displayed quotes are update. $1 is a time that is counting down from 1:00 to 0:00" + }, + "swapOnceTransactionHasProcess": { + "message": "Idaragdag ang iyong $1 sa account mo sa oras na maiproseso ang transaksyong ito.", + "description": "This message communicates the token that is being transferred. It is shown on the awaiting swap screen. The $1 will be a token symbol." + }, + "swapProcessing": { + "message": "Pagproseso" + }, + "swapQuoteDetails": { + "message": "Mga detalye ng quote" + }, + "swapQuoteDetailsSlippageInfo": { + "message": "Kung magbabago ang presyo sa pagitan ng oras ng pag-order mo at sa oras na nakumpirma ito, tinatawag itong \"slippage\". Awtomatikong makakansela ang iyong Pag-swap kung lalampas ang slippage sa iyong setting na \"max slippage\"." + }, + "swapQuoteIncludesRate": { + "message": "Kasama sa quote ang $1% bayarin sa MetaMask", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapQuoteNofN": { + "message": "Quote $1 ng $2", + "description": "A count of loaded quotes shown to the user while they are waiting for quotes to be fetched. $1 is the number of quotes already loaded, and $2 is the total number of quotes to load." + }, + "swapQuoteSource": { + "message": "Pinagkunan ng quote" + }, + "swapQuotesAreRefreshed": { + "message": "Madalas na nire-refresh ang mga quote para maipakita ang mga kasalukuyang kundisyon ng market." + }, + "swapQuotesExpiredErrorDescription": { + "message": "Mag-request ng mga bagong quote para makuha ang mga pinakabagong rate." + }, + "swapQuotesExpiredErrorTitle": { + "message": "Pag-timeout ng mga quote" + }, + "swapQuotesNotAvailableErrorDescription": { + "message": "Subukang i-adjust ang halaga o mga setting ng slippage at subukan ulit." + }, + "swapQuotesNotAvailableErrorTitle": { + "message": "Walang available na quote" + }, + "swapRate": { + "message": "Rate" + }, + "swapReceiving": { + "message": "Pagtanggap" + }, + "swapReceivingInfoTooltip": { + "message": "Isang itong pagtatantya. Ang eksaktong halaga ay nakadepende sa slippage." + }, + "swapRequestForQuotation": { + "message": "Mag-request ng quotation" + }, + "swapSearchForAToken": { + "message": "Maghanap ng token" + }, + "swapSelect": { + "message": "Piliin" + }, + "swapSelectAQuote": { + "message": "Pumili ng quote" + }, + "swapSelectAToken": { + "message": "Pumili ng token" + }, + "swapSelectQuotePopoverDescription": { + "message": "Makikita sa ibaba ang lahat ng quote na nakuha mula sa maraming pinagkukunan ng liquidity." + }, + "swapSlippageTooLow": { + "message": "Dapat ay mas malaki sa zero ang slippage" + }, + "swapSource": { + "message": "Pinagkunan ng liquidity" + }, + "swapSourceInfo": { + "message": "Naghahanap kami ng maraming pinagkukunan ng liquidity (mga exchange, aggregator at propesyonal na market maker) para mahanap ang mga pinakasulit na rate at pinakamababang bayarin sa network." + }, + "swapStartSwapping": { + "message": "Simulang mag-swap" + }, + "swapSwapFrom": { + "message": "Ipalit mula sa" + }, + "swapSwapSwitch": { + "message": "Mga token na papalitan o ipapalit" + }, + "swapSwapTo": { + "message": "Palitan ng" + }, + "swapThisWillAllowApprove": { + "message": "Mabibigyang-daan nito ang $1 na ma-swap." + }, + "swapTokenAvailable": { + "message": "Naidagdag na ang $1 sa iyong account.", + "description": "This message is shown after a swap is successful and communicates the exact amount of tokens the user has received for a swap. The $1 is a decimal number of tokens followed by the token symbol." + }, + "swapTokenToToken": { + "message": "I-swap ang $1 sa $2", + "description": "Used in the transaction display list to describe a swap. $1 and $2 are the symbols of tokens in involved in a swap." + }, + "swapTransactionComplete": { + "message": "Nakumpleto ang transaksyon" + }, + "swapUnknown": { + "message": "Hindi Alam" + }, + "swapVerifyTokenExplanation": { + "message": "Maaaring gamitin ng maraming token ang iisang pangalan at simbolo. Suriin ang Etherscan para ma-verify na ito ang token na hinahanap mo." + }, + "swapViewToken": { + "message": "Tingnan ang $1" + }, + "swapYourTokenBalance": { + "message": "Available ang $1 $2 na i-swap", + "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" + }, + "swapZeroSlippage": { + "message": "0% Slippage" + }, + "swapsAdvancedOptions": { + "message": "Mga Advanced na Opsyon" + }, + "swapsMaxSlippage": { + "message": "Max na slippage" + }, + "swapsNotEnoughForTx": { + "message": "Hindi sapat ang $1 para makumpleto ang transaksyong ito", + "description": "Tells the user that they don't have enough of a token for a proposed swap. $1 is a token symbol" + }, + "swapsViewInActivity": { + "message": "Tingnan sa aktibidad" + }, + "switchNetworks": { + "message": "Lumipat ng Network" + }, + "switchToThisAccount": { + "message": "Lumipat sa account na ito" + }, + "symbol": { + "message": "Simbolo" + }, + "symbolBetweenZeroTwelve": { + "message": "Dapat ay 11 character o mas kaunti ang simbolo." + }, + "syncWithMobile": { + "message": "I-sync sa mobile" + }, + "syncWithMobileBeCareful": { + "message": "Tiyaking walang ibang nakakakita sa iyong screen kapag na-scan mo ang code na ito" + }, + "syncWithMobileComplete": { + "message": "Matagumpay na na-sync ang iyong data. I-enjoy ang MetaMask mobile app!" + }, + "syncWithMobileDesc": { + "message": "Puwede mong i-sync ang iyong mga account at impormasyon sa mobile device mo. Buksan ang MetaMask mobile app, pumunta sa \"Mga Setting\" at i-tap ang \"I-sync mula sa Browser Extension\"" + }, + "syncWithMobileDescNewUsers": { + "message": "Kung unang pagkakataon mong bubuksan ang MetaMask Mobile app, sundin lang ang mga hakbang sa iyong telepono." + }, + "syncWithMobileScanThisCode": { + "message": "I-scan ang code na ito gamit ang iyong MetaMask mobile app" + }, + "syncWithMobileTitle": { + "message": "I-sync sa mobile" + }, + "syncWithThreeBox": { + "message": "I-sync ang data sa 3Box (pinag-eeksperimentuhan)" + }, + "syncWithThreeBoxDescription": { + "message": "I-on para ma-back up ang iyong mga setting sa 3Box. Kasalukuyang pinag-eeksperimentuhan ang feature na ito; gamitin sa sarili mong pagpapasya." + }, + "syncWithThreeBoxDisabled": { + "message": "Na-disable ang 3Box dahil sa isang error sa unang pag-sync" + }, + "terms": { + "message": "Mga Tuntunin ng Paggamit" + }, + "termsOfService": { + "message": "Mga Tuntunin ng Serbisyo" + }, + "testFaucet": { + "message": "Test Faucet" + }, + "thisWillCreate": { + "message": "Gagawa ito ng bagong wallet at seed phrase" + }, + "tips": { + "message": "Mga Tip" + }, + "to": { + "message": "Para kay/sa" + }, + "toAddress": { + "message": "Para kay/sa: $1", + "description": "$1 is the address to include in the To label. It is typically shortened first using shortenAddress" + }, + "toWithColon": { + "message": "Para kay/sa:" + }, + "token": { + "message": "Token" + }, + "tokenAlreadyAdded": { + "message": "Naidagdag na ang token." + }, + "tokenContractAddress": { + "message": "Address ng Kontrata ng Token" + }, + "tokenOptions": { + "message": "Mga opsyon ng token" + }, + "tokenSymbol": { + "message": "Simbolo ng Token" + }, + "total": { + "message": "Kabuuan" + }, + "transaction": { + "message": "transaksyon" + }, + "transactionCancelAttempted": { + "message": "Sinubukang kanselahin ang transaksyon sa bayarin sa gas na $1 sa $2" + }, + "transactionCancelSuccess": { + "message": "Matagumpay na nakansela ang transaksyon sa $2" + }, + "transactionConfirmed": { + "message": "Nakumpirma ang transaksyon sa $2." + }, + "transactionCreated": { + "message": "Nagawa ang transaksyon na nagkakahalagang $1 sa $2." + }, + "transactionDropped": { + "message": "Tinanggihan ang transaksyon sa $2." + }, + "transactionError": { + "message": "Error sa Transaksyon. Nagkaroon ng exception sa code ng kontrata." + }, + "transactionErrorNoContract": { + "message": "Sinusubukang i-call ang isang function sa isang address na hindi kontrata." + }, + "transactionErrored": { + "message": "Nagkaroon ng error sa transaksyon." + }, + "transactionFee": { + "message": "Bayarin sa Transaksyon" + }, + "transactionResubmitted": { + "message": "Isinumite ulit ang transaksyon nang may bayarin sa gas na tumaas at naging $1 sa $2" + }, + "transactionSubmitted": { + "message": "Isinumite ang transaksyon nang may bayarin sa gas na $1 sa $2." + }, + "transactionUpdated": { + "message": "Na-update ang transaksyon sa $2." + }, + "transfer": { + "message": "Mag-transfer" + }, + "transferBetweenAccounts": { + "message": "Mag-transfer sa iba't ibang account ko" + }, + "transferFrom": { + "message": "Mag-transfer Mula Kay/Sa" + }, + "troubleConnectingToWallet": { + "message": "Nagkaproblema kami sa pagkonekta sa iyong $1, subukang suriin ang $2 at subukan ulit.", + "description": "$1 is the wallet device name; $2 is a link to wallet connection guide" + }, + "troubleTokenBalances": { + "message": "Nagkaproblema kami sa pag-load ng mga balanse ng iyong token. Puwede mong tingnan ang mga iyon ", + "description": "Followed by a link (here) to view token balances" + }, + "trustSiteApprovePermission": { + "message": "Pinagkakatiwalaan mo ba ang site na ito? Sa pamamagitan ng pagbibigay ng pahintulot na ito, pinapayagan mo ang $1 na i-withdraw ang iyong $2 at i-automate ang mga transaksyon para sa iyo.", + "description": "$1 is the url requesting permission and $2 is the symbol of the currency that the request is for" + }, + "tryAgain": { + "message": "Subukan ulit" + }, + "typePassword": { + "message": "Uri ng password ng iyong MetaMask" + }, + "unapproved": { + "message": "Hindi inaprubahan" + }, + "units": { + "message": "mga unit" + }, + "unknown": { + "message": "Hindi Alam" + }, + "unknownCameraError": { + "message": "Nagkaroon ng error habang sinusubukang i-access ang iyong camera. Pakisubukan ulit..." + }, + "unknownCameraErrorTitle": { + "message": "Ooops! Nagkaproblema...." + }, + "unknownNetwork": { + "message": "Hindi Alam na Pribadong Network" + }, + "unknownQrCode": { + "message": "Error: Hindi namin matukoy ang QR code na iyon" + }, + "unlimited": { + "message": "Walang Limitasyon" + }, + "unlock": { + "message": "I-unlock" + }, + "unlockMessage": { + "message": "Naghihintay ang decentralized web" + }, + "updatedWithDate": { + "message": "Na-update noong $1" + }, + "urlErrorMsg": { + "message": "Kinakailangan ng mga URL ang naaangkop na HTTP/HTTPS prefix." + }, + "urlExistsErrorMsg": { + "message": "Nasa kasalukuyang listahan ng mga network na ang URL" + }, + "usePhishingDetection": { + "message": "Gumamit ng Pag-detect ng Phishing" + }, + "usePhishingDetectionDescription": { + "message": "Magpakita ng babala para sa mga phishing domain na nagta-target sa mga user ng Ethereum" + }, + "usedByClients": { + "message": "Ginagamit ng iba't ibang client" + }, + "userName": { + "message": "Username" + }, + "verifyThisTokenOn": { + "message": "I-verify ang token na ito sa $1", + "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" + }, + "viewAccount": { + "message": "Tingnan ang Account" + }, + "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": "Seed phrase" + }, + "welcome": { + "message": "Welcome sa MetaMask" + }, + "welcomeBack": { + "message": "Welcome Back!" + }, + "whatsThis": { + "message": "Ano ito?" + }, + "writePhrase": { + "message": "Isulat ang phrase na ito sa papel at itabi sa ligtas na lugar. Kung gusto mo ng mas maigting na seguridad, isulat ito sa maraming piraso ng papel at itabi ang bawat isa sa 2 - 3 magkakaibang lokasyon." + }, + "xOfY": { + "message": "$1 ng $2", + "description": "$1 and $2 are intended to be two numbers, where $2 is a total, and $1 is a count towards that total" + }, + "yesLetsTry": { + "message": "Oo, subukan natin" + }, + "youNeedToAllowCameraAccess": { + "message": "Kailangan mong payagan ang pag-access sa camera para magamit ang feature na ito." + }, + "youSign": { + "message": "Nilalagdaan mo ang" + }, + "yourPrivateSeedPhrase": { + "message": "Ang iyong pribadong seed phrase" + }, + "zeroGasPriceOnSpeedUpError": { + "message": "Walang presyo ng gas sa pagpapabilis" + } +} diff --git a/app/_locales/tr/messages.json b/app/_locales/tr/messages.json index a2471b68f..4b71110d0 100644 --- a/app/_locales/tr/messages.json +++ b/app/_locales/tr/messages.json @@ -372,9 +372,6 @@ "seedPhraseReq": { "message": "Kaynak ifadeleri 12 kelimedir." }, - "selectCurrency": { - "message": "Döviz Seç" - }, "selectType": { "message": "Tip Seç" }, diff --git a/app/_locales/uk/messages.json b/app/_locales/uk/messages.json index 0a659eb40..11029c216 100644 --- a/app/_locales/uk/messages.json +++ b/app/_locales/uk/messages.json @@ -931,18 +931,12 @@ "selectAnAccountHelp": { "message": "Оберіть обліковий запис для перегляду в MetaMask" }, - "selectCurrency": { - "message": "Виберіть валюту" - }, "selectEachPhrase": { "message": "Виберіть кожну фразу, щоб переконатися, що вона правильна." }, "selectHdPath": { "message": "Виберіть шлях до HD-гаманця" }, - "selectLocale": { - "message": "Оберіть локаль" - }, "selectPathHelp": { "message": "Якщо ви не бачите ваш обліковий запис Ledger, який існує, спробуйте переключити шляхи на \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/_locales/vi/messages.json b/app/_locales/vi/messages.json index 815e46881..d24e310d4 100644 --- a/app/_locales/vi/messages.json +++ b/app/_locales/vi/messages.json @@ -1,4 +1,24 @@ { + "about": { + "message": "Giới thiệu" + }, + "aboutSettingsDescription": { + "message": "Phiên bản, trung tâm trợ giúp và thông tin liên hệ" + }, + "acceleratingATransaction": { + "message": "* Việc đẩy nhanh giao dịch bằng cách sử dụng giá gas cao hơn sẽ tăng khả năng được mạng xử lý nhanh hơn, nhưng không phải lúc nào điều này cũng được đảm bảo." + }, + "acceptTermsOfUse": { + "message": "Tôi đã đọc và đồng ý với $1", + "description": "$1 is the `terms` message" + }, + "accessAndSpendNotice": { + "message": "$1 có thể truy cập và chi tiêu đến số tiền tối đa", + "description": "$1 is the url of the site requesting ability to spend" + }, + "accessingYourCamera": { + "message": "Đang truy cập camera..." + }, "account": { "message": "Tài khoản" }, @@ -8,134 +28,760 @@ "accountName": { "message": "Tên tài khoản" }, + "accountOptions": { + "message": "Tùy chọn tài khoản" + }, + "accountSelectionRequired": { + "message": "Bạn cần chọn một tài khoản!" + }, + "active": { + "message": "Đang hoạt động" + }, + "activity": { + "message": "Hoạt động" + }, + "activityLog": { + "message": "nhật ký hoạt động" + }, + "addAccount": { + "message": "Thêm tài khoản" + }, + "addAcquiredTokens": { + "message": "Thêm token mà bạn đã mua bằng MetaMask" + }, + "addAlias": { + "message": "Thêm biệt danh" + }, + "addNetwork": { + "message": "Thêm mạng" + }, + "addRecipient": { + "message": "Thêm người nhận" + }, + "addSuggestedTokens": { + "message": "Thêm token được đề xuất" + }, + "addToAddressBook": { + "message": "Thêm vào sổ địa chỉ" + }, + "addToAddressBookModalPlaceholder": { + "message": "ví dụ: John D." + }, "addToken": { - "message": "Thêm mã Token" + "message": "Thêm token" + }, + "addTokens": { + "message": "Thêm token" + }, + "advanced": { + "message": "Nâng cao" + }, + "advancedOptions": { + "message": "Tùy chọn nâng cao" + }, + "advancedSettingsDescription": { + "message": "Truy cập các tính năng dành cho nhà phát triển, tải Nhật ký trạng thái xuống, Đặt lại tài khoản, thiết lập mạng thử nghiệm và RPC tùy chỉnh" + }, + "affirmAgree": { + "message": "Tôi đồng ý" + }, + "aggregatorFeeCost": { + "message": "Phí mạng cho trình tổng hợp" + }, + "alertDisableTooltip": { + "message": "Bạn có thể thay đổi tùy chọn này trong phần \"Cài đặt > Cảnh báo\"" + }, + "alertSettingsUnconnectedAccount": { + "message": "Đang duyệt trang web khi chọn một tài khoản không được kết nối" + }, + "alertSettingsUnconnectedAccountDescription": { + "message": "Cảnh báo này hiển thị trong cửa sổ bật lên khi bạn đang duyệt một trang web đã được kết nối trên Web3, nhưng tài khoản đang chọn không được kết nối." + }, + "alerts": { + "message": "Cảnh báo" + }, + "alertsSettingsDescription": { + "message": "Bật hoặc tắt từng cảnh báo" + }, + "allowExternalExtensionTo": { + "message": "Cho phép tiện ích bên ngoài này:" + }, + "allowOriginSpendToken": { + "message": "Cho phép $1 chi tiêu $2 của bạn?", + "description": "$1 is the url of the site and $2 is the symbol of the token they are requesting to spend" + }, + "allowThisSiteTo": { + "message": "Cho phép trang web này:" + }, + "allowWithdrawAndSpend": { + "message": "Cho phép $1 rút và chi tiêu tối đa số tiền sau đây:", + "description": "The url of the site that requested permission to 'withdraw and spend'" }, "amount": { - "message": "Số lượng" + "message": "Số tiền" + }, + "amountInEth": { + "message": "$1 ETH", + "description": "Displays an eth amount to the user. $1 is a decimal number" + }, + "amountWithColon": { + "message": "Số tiền:" }, "appDescription": { - "message": "Tính năng Ethereum cho trình duyệt", + "message": "Ví Ethereum trên trình duyệt của bạn", "description": "The description of the application" }, "appName": { "message": "MetaMask", "description": "The name of the application" }, + "approvalAndAggregatorTxFeeCost": { + "message": "Phí mạng cho trình tổng hợp và việc phê duyệt" + }, + "approvalTxGasCost": { + "message": "Chi phí gas cho giao dịch phê duyệt" + }, "approve": { - "message": "Phê duyệt" + "message": "Phê duyệt giới hạn chi tiêu" + }, + "approveSpendLimit": { + "message": "Phê duyệt giới hạn chi tiêu $1", + "description": "The token symbol that is being approved" + }, + "approved": { + "message": "Đã phê duyệt" + }, + "asset": { + "message": "Tài sản" + }, + "assets": { + "message": "Tài sản" + }, + "attemptToCancel": { + "message": "Cố gắng hủy?" + }, + "attemptToCancelDescription": { + "message": "Việc gửi lần thử này không đảm bảo rằng giao dịch gốc của bạn sẽ được hủy. Nếu lần hủy này thành công, bạn sẽ chịu phí giao dịch nêu ở trên." }, "attemptingConnect": { - "message": "Đang kết nối đến blockchain." + "message": "Đang cố gắng kết nối với chuỗi khối." + }, + "attributions": { + "message": "Ghi nhận đóng góp" + }, + "authorizedPermissions": { + "message": "Bạn đã cấp các quyền sau đây" + }, + "autoLockTimeLimit": { + "message": "Hẹn giờ tự động khóa (phút)" + }, + "autoLockTimeLimitDescription": { + "message": "Đặt khoảng thời gian không hoạt động tính bằng phút trước khi MetaMask khóa." + }, + "average": { + "message": "Trung bình" }, "back": { "message": "Quay lại" }, + "backToAll": { + "message": "Quay lại toàn bộ danh sách" + }, + "backupApprovalInfo": { + "message": "Đây là mã bí mật bắt buộc phải dùng để khôi phục ví trong trường hợp bạn bị mất thiết bị, quên mật khẩu, phải cài đặt lại MetaMask hoặc muốn truy cập ví của mình trên một thiết bị khác." + }, + "backupApprovalNotice": { + "message": "Sao lưu Mã khôi phục bí mật để đảm bảo an toàn cho ví và tiền của bạn." + }, + "backupNow": { + "message": "Sao lưu ngay" + }, "balance": { - "message": "Số dư:" + "message": "Số dư" + }, + "balanceOutdated": { + "message": "Số dư có thể đã cũ" + }, + "basic": { + "message": "Cơ bản" + }, + "blockExplorerUrl": { + "message": "Trình khám phá khối" + }, + "blockExplorerView": { + "message": "Xem tài khoản tại $1", + "description": "$1 replaced by URL for custom block explorer" + }, + "blockiesIdenticon": { + "message": "Dùng biểu tượng nhận dạng kiểu Blockies" + }, + "browserNotSupported": { + "message": "Trình duyệt của bạn không được hỗ trợ..." + }, + "builtInCalifornia": { + "message": "MetaMask được thiết kế và phát triển tại California." + }, + "buy": { + "message": "Mua" + }, + "buyWithWyre": { + "message": "Mua ETH qua Wyre" + }, + "buyWithWyreDescription": { + "message": "Wyre cho phép bạn dùng thẻ ghi nợ để nộp ETH trực tiếp vào tài khoản MetaMask của mình." + }, + "bytes": { + "message": "Byte" }, "cancel": { "message": "Hủy" }, + "cancellationGasFee": { + "message": "Phí gas hủy" + }, + "cancelled": { + "message": "Đã hủy" + }, + "chainId": { + "message": "Mã chuỗi" + }, + "chromeRequiredForHardwareWallets": { + "message": "Bạn cần sử dụng MetaMask trên Google Chrome để kết nối với Ví cứng của bạn." + }, + "clickToRevealSeed": { + "message": "Nhấp vào đây để hiện các từ bí mật" + }, + "close": { + "message": "Đóng" + }, "confirm": { "message": "Xác nhận" }, "confirmPassword": { "message": "Xác nhận mật khẩu" }, + "confirmSecretBackupPhrase": { + "message": "Xác nhận Cụm mật khẩu sao lưu bí mật" + }, + "confirmed": { + "message": "Đã xác nhận" + }, + "congratulations": { + "message": "Chúc mừng bạn" + }, + "connect": { + "message": "Kết nối" + }, + "connectAccountOrCreate": { + "message": "Tạo tài khoản hoặc tạo tài khoản mới" + }, + "connectHardwareWallet": { + "message": "Kết nối với ví cứng" + }, + "connectManually": { + "message": "Kết nối thủ công với trang web hiện tại" + }, + "connectTo": { + "message": "Kết nối với $1", + "description": "$1 is the name/origin of a web3 site/application that the user can connect to metamask" + }, + "connectToAll": { + "message": "Kết nối với tất cả các $1 của bạn", + "description": "$1 will be replaced by the translation of connectToAllAccounts" + }, + "connectToAllAccounts": { + "message": "tài khoản", + "description": "will replace $1 in connectToAll, completing the sentence 'connect to all of your accounts', will be text that shows list of accounts on hover" + }, + "connectToMultiple": { + "message": "Kết nối với $1", + "description": "$1 will be replaced by the translation of connectToMultipleNumberOfAccounts" + }, + "connectToMultipleNumberOfAccounts": { + "message": "$1 tài khoản", + "description": "$1 is the number of accounts to which the web3 site/application is asking to connect; this will substitute $1 in connectToMultiple" + }, + "connectWithMetaMask": { + "message": "Kết nối với MetaMask" + }, + "connectedAccountsDescriptionPlural": { + "message": "Bạn có $1 tài khoản kết nối với trang web này.", + "description": "$1 is the number of accounts" + }, + "connectedAccountsDescriptionSingular": { + "message": "Bạn có 1 tài khoản kết nối với trang web này." + }, + "connectedAccountsEmptyDescription": { + "message": "MetaMask chưa kết nối với trang web này. Để kết nối với một trang web trên web3, hãy tìm nút kết nối trên trang web của họ." + }, + "connectedSites": { + "message": "Trang web đã kết nối" + }, + "connectedSitesDescription": { + "message": "$1 đã kết nối với các trang web này. Các trang web này có thể xem địa chỉ tài khoản của bạn.", + "description": "$1 is the account name" + }, + "connectedSitesEmptyDescription": { + "message": "$1 chưa kết nối với bất kỳ trang web nào.", + "description": "$1 is the account name" + }, + "connecting": { + "message": "Đang kết nối..." + }, + "connectingTo": { + "message": "Đang kết nối với $1" + }, + "connectingToGoerli": { + "message": "Đang kết nối với mạng thử nghiệm Goerli" + }, + "connectingToKovan": { + "message": "Đang kết nối với mạng thử nghiệm Kovan" + }, + "connectingToMainnet": { + "message": "Đang kết nối với mạng chính thức của Ethereum" + }, + "connectingToRinkeby": { + "message": "Đang kết nối với mạng thử nghiệm Rinkeby" + }, + "connectingToRopsten": { + "message": "Đang kết nối với mạng thử nghiệm Ropsten" + }, + "contactUs": { + "message": "Liên hệ với chúng tôi" + }, + "contacts": { + "message": "Danh bạ" + }, + "contactsSettingsDescription": { + "message": "Thêm, chỉnh sửa, xóa và quản lý danh bạ của bạn" + }, + "continueToWyre": { + "message": "Tiếp tục chuyển đến Wyre" + }, "contractDeployment": { "message": "Triển khai hợp đồng" }, + "contractInteraction": { + "message": "Tương tác với hợp đồng" + }, "copiedExclamation": { "message": "Đã sao chép!" }, + "copiedTransactionId": { + "message": "Đã sao chép mã giao dịch" + }, + "copyAddress": { + "message": "Sao chép địa chỉ vào khay nhớ tạm" + }, "copyPrivateKey": { - "message": "Đây là Khoá Bí Mật của bạn (nhấp vào để sao chép)" + "message": "Đây là khóa riêng tư của bạn (hãy nhấp vào để sao chép)" }, "copyToClipboard": { - "message": "Đã sao chép vào clipboard" + "message": "Sao chép vào khay nhớ tạm" + }, + "copyTransactionId": { + "message": "Sao chép mã giao dịch" }, "create": { "message": "Tạo" }, + "createAWallet": { + "message": "Tạo ví" + }, "createAccount": { "message": "Tạo tài khoản" }, + "createPassword": { + "message": "Tạo mật khẩu" + }, + "currencyConversion": { + "message": "Quy đổi tiền" + }, + "currentAccountNotConnected": { + "message": "Tài khoản hiện tại của bạn chưa được kết nối" + }, + "currentExtension": { + "message": "Trang tiện ích hiện tại" + }, + "currentLanguage": { + "message": "Ngôn ngữ hiện tại" + }, "customGas": { "message": "Tùy chỉnh gas" }, + "customGasSubTitle": { + "message": "Việc tăng phí có thể giúp giảm thời gian xử lý, nhưng điều này không được đảm bảo." + }, "customRPC": { - "message": "Tùy chỉnh RPC" + "message": "RPC tùy chỉnh" + }, + "customSpendLimit": { + "message": "Giới hạn chi tiêu tùy chỉnh" + }, + "customToken": { + "message": "Token tùy chỉnh" + }, + "dataBackupFoundInfo": { + "message": "Một số dữ liệu tài khoản của bạn đã được sao lưu trong lần cài đặt MetaMask trước đó. Dữ liệu này có thể bao gồm các tùy chọn cài đặt, danh bạ và token. Bạn có muốn khôi phục dữ liệu này bây giờ không?" + }, + "decimal": { + "message": "Số vị trí thập phân của độ chính xác" + }, + "decimalsMustZerotoTen": { + "message": "Số vị trí thập phân ít nhất phải bằng 0 và không được quá 36." + }, + "decrypt": { + "message": "Decrypt" + }, + "decryptCopy": { + "message": "Sao chép thông báo đã mã hóa" + }, + "decryptInlineError": { + "message": "Không thể giải mã thông báo này do lỗi: $1", + "description": "$1 is error message" + }, + "decryptMessageNotice": { + "message": "$1 muốn đọc thông báo này để hoàn tất hành động của bạn", + "description": "$1 is the web3 site name" + }, + "decryptMetamask": { + "message": "Thông báo của Decrypt" + }, + "decryptRequest": { + "message": "Yêu cầu của Decrypt" }, "defaultNetwork": { - "message": "Mạng lưới mặc định dùng cho các giao dịch Ether là Main Net (tiền ETH thật)." + "message": "Mạng mặc định cho các giao dịch Ether là Mạng chính thức." + }, + "delete": { + "message": "Xóa" + }, + "deleteAccount": { + "message": "Xóa tài khoản" + }, + "deleteNetwork": { + "message": "Xóa mạng?" + }, + "deleteNetworkDescription": { + "message": "Bạn có chắc chắn muốn xóa mạng này không?" }, "depositEther": { - "message": "Ký gửi Ether" + "message": "Nộp Ether" }, "details": { "message": "Chi tiết" }, "directDepositEther": { - "message": "Ký gửi Ether trực tiếp" + "message": "Nộp trực tiếp Ether" }, "directDepositEtherExplainer": { - "message": "Nếu bạn đã có sẵn vài Ether, cách nhanh nhất để thêm Ether vào ví tiền mới của bạn là bằng ký gửi trực tiếp." + "message": "Nếu bạn đã có một lượng Ether, cách nhanh nhất để chuyển Ether vào ví mới của bạn là nộp trực tiếp." + }, + "disconnect": { + "message": "Ngắt kết nối" + }, + "disconnectAllAccounts": { + "message": "Ngắt kết nối tất cả các tài khoản" + }, + "disconnectAllAccountsConfirmationDescription": { + "message": "Bạn có chắc chắn muốn ngắt kết nối không? Bạn có thể bị mất chức năng của trang web." + }, + "disconnectPrompt": { + "message": "Ngắt kết nối $1" + }, + "disconnectThisAccount": { + "message": "Ngắt kết nối tài khoản này" + }, + "dismiss": { + "message": "Đóng" }, "done": { "message": "Hoàn tất" }, + "dontHaveAHardwareWallet": { + "message": "Bạn không có ví cứng?" + }, + "dontShowThisAgain": { + "message": "Không hiển thị lại" + }, + "downloadGoogleChrome": { + "message": "Tải Google Chrome xuống" + }, + "downloadSecretBackup": { + "message": "Tải Cụm mật khẩu sao lưu bí mật này xuống và lưu giữ trên một ổ đĩa cứng hoặc môi trường lưu trữ bên ngoài được mã hóa." + }, + "downloadStateLogs": { + "message": "Tải nhật ký trạng thái xuống" + }, + "dropped": { + "message": "Đã ngừng" + }, "edit": { "message": "Chỉnh sửa" }, + "editContact": { + "message": "Chỉnh sửa người liên hệ" + }, + "editPermission": { + "message": "Chỉnh sửa quyền" + }, + "encryptionPublicKeyNotice": { + "message": "$1 muốn biết khóa mã hóa công khai của bạn. Bằng việc đồng ý, trang web này sẽ có thể gửi thông báo được mã hóa cho bạn.", + "description": "$1 is the web3 site name" + }, + "encryptionPublicKeyRequest": { + "message": "Yêu cầu khóa mã hóa công khai" + }, + "endOfFlowMessage1": { + "message": "Bạn đã vượt qua bài kiểm tra. Hãy lưu giữ cụm mật khẩu gốc của bạn an toàn, đó là trách nhiệm của bạn!" + }, + "endOfFlowMessage10": { + "message": "Tất cả đã hoàn tất" + }, + "endOfFlowMessage2": { + "message": "Mẹo lưu trữ an toàn" + }, + "endOfFlowMessage3": { + "message": "Lưu bản sao lưu ở nhiều nơi." + }, + "endOfFlowMessage4": { + "message": "Tuyệt đối không chia sẻ cụm mật khẩu với bất kỳ ai." + }, + "endOfFlowMessage5": { + "message": "Hãy cẩn thận với hoạt động lừa đảo! MetaMask sẽ không bao giờ tự ý hỏi cụm mật khẩu gốc của bạn." + }, + "endOfFlowMessage6": { + "message": "Nếu cần sao lưu lại cụm mật khẩu gốc của mình, bạn có thể tìm thấy cụm mật khẩu này trong phần Cài đặt -> Bảo mật." + }, + "endOfFlowMessage7": { + "message": "Nếu bạn có câu hỏi hoặc nhận thấy điều gì đó đáng ngờ, hãy gửi email đến support@metamask.io." + }, + "endOfFlowMessage8": { + "message": "MetaMask không thể khôi phục cụm mật khẩu gốc của bạn." + }, + "endOfFlowMessage9": { + "message": "Tìm hiểu thêm." + }, + "endpointReturnedDifferentChainId": { + "message": "Điểm cuối đã trả về một mã chuỗi khác: $1", + "description": "$1 is the return value of eth_chainId from an RPC endpoint" + }, + "ensNotFoundOnCurrentNetwork": { + "message": "Không tìm thấy tên ENS trên mạng hiện tại. Đang chuyển sang mạng chính thức của Ethereum." + }, + "ensRegistrationError": { + "message": "Lỗi khi đăng ký tên ENS" + }, + "enterAnAlias": { + "message": "Nhập một biệt danh" + }, + "enterMaxSpendLimit": { + "message": "Nhập giới hạn chi tiêu tối đa" + }, "enterPassword": { "message": "Nhập mật khẩu" }, + "enterPasswordContinue": { + "message": "Nhập mật khẩu để tiếp tục" + }, + "errorCode": { + "message": "Mã: $1", + "description": "Displayed error code for debugging purposes. $1 is the error code" + }, + "errorDetails": { + "message": "Chi tiết về lỗi", + "description": "Title for collapsible section that displays error details for debugging purposes" + }, + "errorMessage": { + "message": "Thông báo: $1", + "description": "Displayed error message for debugging purposes. $1 is the error message" + }, + "errorName": { + "message": "Mã: $1", + "description": "Displayed error name for debugging purposes. $1 is the error name" + }, + "errorPageMessage": { + "message": "Hãy thử lại bằng cách tải lại trang hoặc liên hệ với bộ phận hỗ trợ theo địa chỉ support@metamask.io", + "description": "Message displayed on generic error page in the fullscreen or notification UI" + }, + "errorPagePopupMessage": { + "message": "Hãy thử lại bằng cách đóng và mở lại cửa sổ bật lên hoặc liên hệ với bộ phận hỗ trợ theo địa chỉ support@metamask.io", + "description": "Message displayed on generic error page in the popup UI" + }, + "errorPageTitle": { + "message": "MetaMask đã gặp lỗi", + "description": "Title of generic error page" + }, + "errorStack": { + "message": "Cụm:", + "description": "Title for error stack, which is displayed for debugging purposes" + }, + "estimatedProcessingTimes": { + "message": "Thời gian xử lý ước tính" + }, + "eth_accounts": { + "message": "Xem địa chỉ của các tài khoản được cho phép của bạn (bắt buộc)", + "description": "The description for the `eth_accounts` permission" + }, + "ethereumPublicAddress": { + "message": "Địa chỉ công khai trên Ethereum" + }, + "etherscan": { + "message": "Etherscan" + }, "etherscanView": { "message": "Xem tài khoản trên Etherscan" }, + "expandView": { + "message": "Mở rộng cửa sổ xem" + }, "exportPrivateKey": { - "message": "Xuất mã khóa cá nhân" + "message": "Xuất khóa riêng tư" + }, + "externalExtension": { + "message": "Tiện ích bên ngoài" + }, + "extraApprovalGas": { + "message": "+$1 gas phê duyệt", + "description": "Expresses an additional gas amount the user will have to pay, on top of some other displayed amount. $1 is a decimal amount of gas" }, "failed": { "message": "Không thành công" }, + "failedToFetchChainId": { + "message": "Không thể tìm nạp mã chuỗi. URL RPC của bạn có chính xác không?" + }, + "failureMessage": { + "message": "Đã xảy ra sự cố và chúng tôi không thể hoàn tất hành động" + }, + "fast": { + "message": "Nhanh" + }, + "fastest": { + "message": "Nhanh nhất" + }, + "feeAssociatedRequest": { + "message": "Yêu cầu này có kèm theo một khoản phí." + }, "fiat": { - "message": "FIAT", + "message": "Pháp định", "description": "Exchange type" }, "fileImportFail": { - "message": "Tập tin đã nhập không hoạt động? Nhấp vào đây!", + "message": "Tính năng nhập tệp không hoạt động? Nhấp vào đây!", "description": "Helps user import their account from a JSON file" }, + "forbiddenIpfsGateway": { + "message": "Cổng kết nối IPFS không được phép: Vui lòng chỉ định một cổng kết nối CID" + }, + "forgetDevice": { + "message": "Quên thiết bị này" + }, "from": { "message": "Từ" }, + "fromAddress": { + "message": "Từ: $1", + "description": "$1 is the address to include in the From label. It is typically shortened first using shortenAddress" + }, + "functionApprove": { + "message": "Chức năng: Phê duyệt" + }, + "functionType": { + "message": "Loại chức năng" + }, "gasLimit": { - "message": "Hạn mức ga" + "message": "Giới hạn gas" + }, + "gasLimitInfoTooltipContent": { + "message": "Giới hạn gas là số lượng đơn vị gas tối đa mà bạn sẵn sàng chi tiêu." }, "gasLimitTooLow": { - "message": "Hạn mức ga phải đạt tối thiểu 21000" + "message": "Giới hạn gas ít nhất phải là 21000" + }, + "gasLimitTooLowWithDynamicFee": { + "message": "Giới hạn gas ít nhất phải là $1", + "description": "$1 is the custom gas limit, in decimal." }, "gasPrice": { - "message": "Giá ga (GWEI)" + "message": "Giá gas (GWEI)" + }, + "gasPriceExtremelyLow": { + "message": "Giá gas cực kỳ thấp" + }, + "gasPriceInfoTooltipContent": { + "message": "Giá gas xác định khoản Ether mà bạn sẵn sàng thanh toán cho mỗi đơn vị gas." + }, + "gasUsed": { + "message": "Đã dùng gas" + }, + "gdprMessage": { + "message": "Đây là dữ liệu tổng hợp, do đó ở trạng thái ẩn danh để phục vụ cho mục đích của Quy định chung về bảo vệ dữ liệu (Liên minh Châu Âu) 2016/679. Để biết thêm thông tin liên quan đến các phương thức bảo vệ quyền riêng tư của chúng tôi, vui lòng xem $1 của chúng tôi.", + "description": "$1 refers to the gdprMessagePrivacyPolicy message, the translation of which is meant to be used exclusively in the context of gdprMessage" + }, + "gdprMessagePrivacyPolicy": { + "message": "Chính sách quyền riêng tư tại đây", + "description": "this translation is intended to be exclusively used as the replacement for the $1 in the gdprMessage translation" + }, + "general": { + "message": "Chung" + }, + "generalSettingsDescription": { + "message": "Quy đổi tiền, đơn vị tiền chính, ngôn ngữ, biểu tượng nhận dạng kiểu blockies" }, "getEther": { - "message": "Lấy Ether" + "message": "Nhận Ether" }, "getEtherFromFaucet": { - "message": "Lấy Ether từ vòi với giá $1", + "message": "Nhận Ether từ một vòi dành cho $1", "description": "Displays network name for Ether faucet" }, + "getHelp": { + "message": "Nhận trợ giúp." + }, + "getStarted": { + "message": "Bắt đầu" + }, + "goerli": { + "message": "Mạng thử nghiệm Goerli" + }, + "happyToSeeYou": { + "message": "Chúng tôi rất vui khi được gặp bạn." + }, + "hardware": { + "message": "Phần cứng" + }, + "hardwareWalletConnected": { + "message": "Đã kết nối với ví cứng" + }, + "hardwareWallets": { + "message": "Kết nối với một ví cứng" + }, + "hardwareWalletsMsg": { + "message": "Chọn một ví cứng mà bạn muốn sử dụng với MetaMask" + }, + "havingTroubleConnecting": { + "message": "Bạn đang gặp sự cố với việc kết nối?" + }, "here": { "message": "tại đây", "description": "as in -click here- for more information (goes with troubleTokenBalances)" }, + "hexData": { + "message": "Dữ liệu thập lục phân" + }, "hide": { "message": "Ẩn" }, "hideTokenPrompt": { - "message": "Ẩn mã token?" + "message": "Ẩn token?" + }, + "hideTokenSymbol": { + "message": "Ẩn $1", + "description": "$1 is the symbol for a token (e.g. 'DAI')" + }, + "history": { + "message": "Lịch sử" }, "import": { "message": "Nhập", @@ -144,101 +790,540 @@ "importAccount": { "message": "Nhập tài khoản" }, + "importAccountMsg": { + "message": " Tài khoản đã nhập sẽ không được liên kết với cụm mật khẩu gốc cho tài khoản MetaMask đã tạo ban đầu của bạn. Tìm hiểu thêm về các tài khoản đã nhập " + }, + "importAccountSeedPhrase": { + "message": "Nhập một tài khoản bằng cụm mật khẩu gốc" + }, + "importUsingSeed": { + "message": "Nhập bằng cách sử dụng cụm mật khẩu gốc của tài khoản" + }, + "importWallet": { + "message": "Nhập ví" + }, + "importYourExisting": { + "message": "Nhập ví hiện có của bạn bằng cụm mật khẩu gốc gồm 12 từ" + }, "imported": { "message": "Đã nhập", "description": "status showing that an account has been fully loaded into the keyring" }, "infoHelp": { - "message": "Thông tin & Trợ giúp" + "message": "Thông tin và trợ giúp" + }, + "initialTransactionConfirmed": { + "message": "Mạng đã xác nhận giao dịch ban đầu của bạn. Nhấp vào OK để quay lại." + }, + "insufficientBalance": { + "message": "Không đủ số dư." + }, + "insufficientFunds": { + "message": "Không đủ tiền." + }, + "insufficientTokens": { + "message": "Không đủ token." }, "invalidAddress": { "message": "Địa chỉ không hợp lệ" }, - "jsonFile": { - "message": "Tập tin JSON", - "description": "format for importing an account" + "invalidAddressRecipient": { + "message": "Địa chỉ người nhận không hợp lệ" }, - "kovan": { - "message": "Mạng thử nghiệm Kovan" + "invalidAddressRecipientNotEthNetwork": { + "message": "Không phải mạng ETH, hãy đặt ở chữ viết thường" }, - "loading": { - "message": "Đang tải..." + "invalidBlockExplorerURL": { + "message": "URL trình khám phá khối không hợp lệ" }, - "loadingTokens": { - "message": "Đang tải mã token..." + "invalidCustomNetworkAlertContent1": { + "message": "Phải nhập lại mã chuỗi cho mạng tùy chỉnh “$1”.", + "description": "$1 is the name/identifier of the network." }, - "lock": { - "message": "Thoát" + "invalidCustomNetworkAlertContent2": { + "message": "Để bảo vệ bạn khỏi các nhà cung cấp mạng độc hại hoặc bị lỗi, mã chuỗi giờ đây là yêu cầu bắt buộc đối với tất cả các mạng tùy chỉnh." }, - "mainnet": { - "message": "Mạng Ethereum MainNet (tiền ETH thật)" + "invalidCustomNetworkAlertContent3": { + "message": "Chuyển đến phần Cài đặt > Mạng, rồi nhập mã chuỗi. Bạn có thể tìm được mã chuỗi của hầu hết các mạng phổ biến trên $1.", + "description": "$1 is a link to https://chainid.network" }, - "message": { - "message": "Tin nhắn" + "invalidCustomNetworkAlertTitle": { + "message": "Mạng tùy chỉnh không hợp lệ" }, - "myAccounts": { - "message": "Tài khoản của tôi" + "invalidHexNumber": { + "message": "Số thập lục phân không hợp lệ." }, - "needEtherInWallet": { - "message": "Để tương tác với các ứng dụng phân tán bằng MetaMask, bạn sẽ phải cần có Ether trong ví của bạn." + "invalidHexNumberLeadingZeros": { + "message": "Số thập lục phân không hợp lệ. Xóa mọi chữ số 0 ở đầu." }, - "needImportFile": { - "message": "Bạn phải chọn một tập tin để nhập.", - "description": "User is important an account and needs to add a file to continue" + "invalidIpfsGateway": { + "message": "Cổng kết nối IPFS không hợp lệ. Giá trị phải là URL hợp lệ" }, - "networks": { - "message": "Các mạng lưới" + "invalidNumber": { + "message": "Số không hợp lệ. Hãy nhập một số thập phân hoặc số thập lục phân bắt đầu bằng “0x”." }, - "newAccount": { - "message": "Tài khoản mới" + "invalidNumberLeadingZeros": { + "message": "Số không hợp lệ. Xóa mọi chữ số 0 ở đầu." }, - "newAccountNumberName": { - "message": "Tài khoản $1", - "description": "Default name of next account to be created on create account screen" + "invalidRPC": { + "message": "URL RPC không hợp lệ" }, - "newContract": { - "message": "Hợp đồng mới" + "invalidSeedPhrase": { + "message": "Cụm mật khẩu gốc không hợp lệ" }, - "newPassword": { - "message": "Mật khẩu mới (tối thiểu 8 ký tự)" + "ipfsGateway": { + "message": "Cổng kết nối IPFS" }, - "next": { - "message": "Kế tiếp" + "ipfsGatewayDescription": { + "message": "Nhập URL của cổng kết nối IPFS CID để dùng cho quá trình phân giải nội dung ENS." }, - "noAddressForName": { - "message": "Không có địa chỉ nào được ấn định cho tên này." + "jsonFile": { + "message": "Tệp JSON", + "description": "format for importing an account" }, - "noTransactions": { - "message": "Không có giao dịch" + "knownAddressRecipient": { + "message": "Địa chỉ hợp đồng đã biết." }, - "pastePrivateKey": { - "message": "Dán dãy khóa cá nhân của bạn tại đây:", - "description": "For importing an account from a private key" + "knownTokenWarning": { + "message": "Hành động này sẽ chỉnh sửa các token đã niêm yết trong ví của bạn, kẻ xấu có thể lợi dụng việc này để lừa đảo bạn. Chỉ phê duyệt nếu bạn chắc chắn rằng bạn muốn thay đổi giá trị mà những token này đại diện cho." }, - "privateKey": { - "message": "Khóa Bí Mật", - "description": "select this type of file to use to import an account" + "kovan": { + "message": "Mạng thử nghiệm Kovan" }, - "privateKeyWarning": { - "message": "Cảnh báo: Không bao giờ được tiết lộ khóa này. Bất kỳ ai có Khóa Bí Mật của bạn đều có thể đánh cắp tài sản được giữ trong tài khoản của bạn." + "lastConnected": { + "message": "Đã kết nối lần gần đây nhất" }, - "privateNetwork": { - "message": "Mạng lưới riêng" + "learnMore": { + "message": "Tìm hiểu thêm" }, - "readdToken": { - "message": "Bạn có thể thêm trở lại mã token này bằng cách nhấn \"Thêm mã token\" trong menu tùy chọn trong tài khoản của bạn." + "ledgerAccountRestriction": { + "message": "Bạn cần sử dụng tài khoản gần đây nhất thì mới có thể thêm một tài khoản mới." }, - "recipientAddress": { - "message": "Địa chỉ người nhận" + "letsGoSetUp": { + "message": "Có, hãy thiết lập!" }, - "reject": { - "message": "Từ chối" + "likeToAddTokens": { + "message": "Bạn có muốn thêm những token này không?" + }, + "links": { + "message": "Đường liên kết" + }, + "loadMore": { + "message": "Nạp thêm" + }, + "loading": { + "message": "Đang tải..." + }, + "loadingTokens": { + "message": "Đang nạp token..." + }, + "localhost": { + "message": "Máy chủ cục bộ 8545" + }, + "lock": { + "message": "Khóa" + }, + "lockTimeTooGreat": { + "message": "Thời gian khóa quá lớn" + }, + "mainnet": { + "message": "Mạng chính thức của Ethereum" + }, + "max": { + "message": "Tối đa" + }, + "memo": { + "message": "memo" + }, + "memorizePhrase": { + "message": "Lưu cụm mật khẩu này." + }, + "message": { + "message": "Thông báo" + }, + "metaMaskConnectStatusParagraphOne": { + "message": "Giờ đây bạn có thể kiểm soát chi tiết hơn đối với các mối liên kết với tài khoản của mình trong MetaMask." + }, + "metaMaskConnectStatusParagraphThree": { + "message": "Nhấp vào đó để quản lý các tài khoản bạn đã kết nối." + }, + "metaMaskConnectStatusParagraphTwo": { + "message": "Nút trạng thái kết nối sẽ hiển thị nếu trang web mà bạn đang truy cập được kết nối với tài khoản bạn đang chọn." + }, + "metamaskDescription": { + "message": "Kết nối bạn với Ethereum và Web phi tập trung." + }, + "metamaskSwapsOfflineDescription": { + "message": "Tính năng Hoán đổi trên MetaMask đang được bảo trì. Vui lòng kiểm tra lại sau." + }, + "metamaskVersion": { + "message": "Phiên bản MetaMask" + }, + "metametricsCommitmentsAllowOptOut": { + "message": "Luôn cho phép bạn chọn không tham gia thông qua phần Cài đặt" + }, + "metametricsCommitmentsBoldNever": { + "message": "Không bao giờ", + "description": "This string is localized separately from some of the commitments so that we can bold it" + }, + "metametricsCommitmentsIntro": { + "message": "MetaMask sẽ.." + }, + "metametricsCommitmentsNeverCollectIP": { + "message": "$1 thu thập địa chỉ IP đầy đủ của bạn", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverCollectKeysEtc": { + "message": "$1 thu thập mã khóa, địa chỉ, giao dịch, số dư, mã băm hoặc bất kỳ thông tin cá nhân nào", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverSellDataForProfit": { + "message": "$1 bán dữ liệu để thu lợi. Tuyệt đối không bao giờ!", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsSendAnonymizedEvents": { + "message": "Gửi các lượt nhấp và xem trang đã được ẩn danh" + }, + "metametricsHelpImproveMetaMask": { + "message": "Giúp chúng tôi cải thiện MetaMask" + }, + "metametricsOptInDescription": { + "message": "MetaMask muốn thu thập dữ liệu sử dụng để hiểu rõ hơn về cách người dùng tương tác với tiện ích. Chúng tôi sẽ dùng dữ liệu này để liên tục cải thiện độ hữu ích và trải nghiệm người dùng trên sản phẩm của mình và hệ sinh thái Ethereum." + }, + "mobileSyncText": { + "message": "Vui lòng nhập mật khẩu để xác nhận đây là bạn!" + }, + "mustSelectOne": { + "message": "Phải chọn ít nhất 1 token." + }, + "myAccounts": { + "message": "Tài khoản của tôi" + }, + "myWalletAccounts": { + "message": "Các tài khoản trong ví của tôi" + }, + "myWalletAccountsDescription": { + "message": "Tất cả các tài khoản đã tạo của bạn trong MetaMask sẽ tự động được thêm vào phần này." + }, + "needEtherInWallet": { + "message": "Để tương tác với các ứng dụng phi tập trung bằng MetaMask, bạn sẽ cần phải có Ether trong ví của mình." + }, + "needImportFile": { + "message": "Bạn phải chọn tệp để nhập.", + "description": "User is important an account and needs to add a file to continue" + }, + "negativeETH": { + "message": "Không thể gửi khoản ETH âm." + }, + "networkName": { + "message": "Tên mạng" + }, + "networkSettingsChainIdDescription": { + "message": "Mã chuỗi được dùng để ký các giao dịch. Giá trị này phải khớp với mã chuỗi do mạng trả về. Bạn có thể nhập một số thập phân hoặc số thập lục phân bắt đầu bằng “0x” nhưng chúng tôi sẽ hiển thị số ở dạng thập phân." + }, + "networkSettingsDescription": { + "message": "Thêm và chỉnh sửa mạng RPC tùy chỉnh" + }, + "networks": { + "message": "Mạng" + }, + "nevermind": { + "message": "Bỏ qua" + }, + "newAccount": { + "message": "Tài khoản mới" + }, + "newAccountDetectedDialogMessage": { + "message": "Đã tìm thấy địa chỉ mới! Nhấp vào đây để thêm địa chỉ này vào sổ địa chỉ của bạn." + }, + "newAccountNumberName": { + "message": "Tài khoản $1", + "description": "Default name of next account to be created on create account screen" + }, + "newContact": { + "message": "Người liên hệ mới" + }, + "newContract": { + "message": "Hợp đồng mới" + }, + "newNetwork": { + "message": "Mạng mới" + }, + "newPassword": { + "message": "Mật khẩu mới (tối thiểu 8 ký tự)" + }, + "newToMetaMask": { + "message": "Bạn mới sử dụng MetaMask?" + }, + "newTotal": { + "message": "Tổng mới" + }, + "newTransactionFee": { + "message": "Phí giao dịch mới" + }, + "next": { + "message": "Tiếp theo" + }, + "nextNonceWarning": { + "message": "Số chỉ dùng một lần lớn hơn số chỉ dùng một lần gợi ý là $1", + "description": "The next nonce according to MetaMask's internal logic" + }, + "noAccountsFound": { + "message": "Không tìm thấy tài khoản nào cho cụm từ tìm kiếm đã đưa ra" + }, + "noAddressForName": { + "message": "Chưa có địa chỉ nào được đặt cho tên này." + }, + "noAlreadyHaveSeed": { + "message": "Không, tôi đã có cụm mật khẩu gốc" + }, + "noConversionRateAvailable": { + "message": "Không có sẵn tỷ lệ quy đổi nào" + }, + "noThanks": { + "message": "Không, cảm ơn" + }, + "noTransactions": { + "message": "Bạn không có giao dịch nào" + }, + "noWebcamFound": { + "message": "Không tìm thấy webcam trên máy tính của bạn. Vui lòng thử lại." + }, + "noWebcamFoundTitle": { + "message": "Không tìm thấy webcam" + }, + "nonceField": { + "message": "Tùy chỉnh số chỉ dùng một lần của giao dịch" + }, + "nonceFieldDescription": { + "message": "Bật tùy chọn này để thay đổi số dùng một lần (số giao dịch) trên màn hình xác nhận. Đây là tính năng nâng cao, hãy dùng một cách thận trọng." + }, + "nonceFieldHeading": { + "message": "Số dùng một lần tùy chỉnh" + }, + "notCurrentAccount": { + "message": "Tài khoản này có chính xác không? Tài khoản này khác với tài khoản bạn đang chọn trong ví của mình" + }, + "notEnoughGas": { + "message": "Không đủ gas" + }, + "ofTextNofM": { + "message": "trên" + }, + "off": { + "message": "Tắt" + }, + "offlineForMaintenance": { + "message": "Ngoại tuyến để bảo trì" + }, + "ok": { + "message": "Ok" + }, + "on": { + "message": "Bật" + }, + "onboardingReturnNotice": { + "message": "\"$1\" sẽ đóng tab này và chuyển về $2", + "description": "Return the user to the site that initiated onboarding" + }, + "onlyAddTrustedNetworks": { + "message": "Một nhà cung cấp mạng Ethereum độc hại có thể nói dối về trạng thái của chuỗi khối và ghi lại hoạt động của bạn trên mạng. Chỉ thêm các mạng tùy chỉnh mà bạn tin tưởng." + }, + "onlyAvailableOnMainnet": { + "message": "Chỉ có trên mạng chính thức" + }, + "onlyConnectTrust": { + "message": "Chỉ kết nối với các trang web mà bạn tin tưởng." + }, + "optionalBlockExplorerUrl": { + "message": "URL trình khám phá khối (không bắt buộc)" + }, + "optionalCurrencySymbol": { + "message": "Ký hiệu tiền tệ (không bắt buộc)" + }, + "orderOneHere": { + "message": "Đặt mua một ví Trezor hoặc Ledger và giữ tiền của bạn trong ví lưu trữ lạnh" + }, + "origin": { + "message": "Nguồn gốc" + }, + "parameters": { + "message": "Tham số" + }, + "participateInMetaMetrics": { + "message": "Tham gia MetaMetrics" + }, + "participateInMetaMetricsDescription": { + "message": "Tham gia MetaMetrics để giúp chúng tôi cải thiện MetaMask" + }, + "password": { + "message": "Mật khẩu" + }, + "passwordNotLongEnough": { + "message": "Mật khẩu không đủ dài" + }, + "passwordsDontMatch": { + "message": "Mật khẩu không khớp" + }, + "pastePrivateKey": { + "message": "Dán chuỗi khóa riêng tư của bạn vào đây:", + "description": "For importing an account from a private key" + }, + "pending": { + "message": "Đang chờ xử lý" + }, + "permissionCheckedIconDescription": { + "message": "Bạn đã phê duyệt quyền này" + }, + "permissionUncheckedIconDescription": { + "message": "Bạn chưa phê duyệt quyền này" + }, + "permissions": { + "message": "Quyền" + }, + "personalAddressDetected": { + "message": "Đã tìm thấy địa chỉ cá nhân. Nhập địa chỉ hợp đồng token." + }, + "plusXMore": { + "message": "+ $1 khác", + "description": "$1 is a number of additional but unshown items in a list- this message will be shown in place of those items" + }, + "prev": { + "message": "Trước" + }, + "primaryCurrencySetting": { + "message": "Đơn vị tiền chính" + }, + "primaryCurrencySettingDescription": { + "message": "Chọn Gốc để ưu tiên hiển thị giá trị bằng đơn vị tiền gốc của chuỗi (ví dụ: ETH). Chọn Pháp định để ưu tiên hiển thị giá trị bằng đơn vị tiền pháp định mà bạn chọn." + }, + "privacyMsg": { + "message": "Chính sách quyền riêng tư" + }, + "privateKey": { + "message": "Khóa riêng tư", + "description": "select this type of file to use to import an account" + }, + "privateKeyWarning": { + "message": "Cảnh báo: Tuyệt đối không để lộ mã khóa này. Bất kỳ ai có mã khóa riêng tư của bạn cũng có thể đánh cắp tài sản được giữ trong tài khoản của bạn." + }, + "privateNetwork": { + "message": "Mạng riêng" + }, + "proposedApprovalLimit": { + "message": "Giới hạn phê duyệt đề xuất" + }, + "protectYourKeys": { + "message": "Bảo vệ khóa của bạn!" + }, + "protectYourKeysMessage1": { + "message": "Hãy cẩn với cụm mật khẩu gốc của bạn, đã có báo cáo về các trang web cố tình giả mạo MetaMask. MetaMask sẽ không bao giờ hỏi cụm mật khẩu gốc của bạn!" + }, + "protectYourKeysMessage2": { + "message": "Hãy lưu giữ cụm mật khẩu của bạn an toàn. Nếu bạn nhận thấy điều gì đó đáng ngờ hoặc không chắc chắn về một trang web, hãy gửi email đến support@metamask.io" + }, + "provide": { + "message": "Cung cấp" + }, + "queue": { + "message": "Hàng đợi" + }, + "queued": { + "message": "Đã đưa vào hàng đợi" + }, + "readdToken": { + "message": "Bạn có thể thêm lại token này trong tương lai bằng cách chuyển đến mục “Thêm token” trong trình đơn tùy chọn tài khoản." + }, + "readyToConnect": { + "message": "Bạn đã sẵn sàng kết nối chưa?" + }, + "receive": { + "message": "Nhận" + }, + "recents": { + "message": "Gần đây" + }, + "recipientAddress": { + "message": "Địa chỉ người nhận" + }, + "recipientAddressPlaceholder": { + "message": "Tìm kiếm, địa chỉ công khai (0x) hoặc ENS" + }, + "reject": { + "message": "Từ chối" + }, + "rejectAll": { + "message": "Từ chối tất cả" + }, + "rejectTxsDescription": { + "message": "Bạn chuẩn bị từ chối hàng loạt $1 giao dịch." + }, + "rejectTxsN": { + "message": "Từ chối $1 giao dịch" }, "rejected": { - "message": "Không chấp thuận/Bị từ chối" + "message": "Đã từ chối" + }, + "remindMeLater": { + "message": "Nhắc tôi sau" + }, + "remove": { + "message": "Xóa" + }, + "removeAccount": { + "message": "Xóa tài khoản" + }, + "removeAccountDescription": { + "message": "Tài khoản này sẽ được xóa khỏi ví của bạn. Xin đảm bảo rằng bạn có cụm mật khẩu gốc ban đầu hoặc khóa riêng tư cho tài khoản được nhập trước khi tiếp tục. Bạn có thể nhập hoặc tạo lại tài khoản từ trình đơn tài khoản thả xuống. " + }, + "requestsAwaitingAcknowledgement": { + "message": "yêu cầu đang chờ xác nhận" }, "required": { - "message": "Yêu cầu" + "message": "Bắt buộc" + }, + "reset": { + "message": "Đặt lại" + }, + "resetAccount": { + "message": "Đặt lại tài khoản" + }, + "resetAccountDescription": { + "message": "Nếu đặt lại tài khoản của bạn, toàn bộ lịch sử giao dịch sẽ bị xóa. Việc này sẽ không làm thay đổi số dư trong tài khoản của bạn hoặc yêu cầu bạn phải nhập lại cụm mật khẩu gốc." + }, + "restore": { + "message": "Khôi phục" + }, + "restoreAccountWithSeed": { + "message": "Khôi phục tài khoản của bạn bằng cụm mật khẩu gốc" + }, + "restoreFromSeed": { + "message": "Khôi phục tài khoản?" + }, + "restoreWalletPreferences": { + "message": "Đã tìm thấy bản sao lưu dữ liệu của bạn từ $1. Bạn có muốn khôi phục các tùy chọn ưu tiên trong ví của mình không?", + "description": "$1 is the date at which the data was backed up" + }, + "retryTransaction": { + "message": "Thử lại giao dịch" + }, + "reusedTokenNameWarning": { + "message": "Một token trong đây sử dụng lại ký hiệu của một token khác mà bạn thấy, điều này có thể gây nhầm lẫn hoặc mang tính lừa dối." + }, + "revealSeedWords": { + "message": "Hiện cụm mật khẩu gốc" + }, + "revealSeedWordsDescription": { + "message": "Nếu thay đổi trình duyệt hoặc chuyển máy tính, bạn sẽ cần cụm mật khẩu gốc này để truy cập tài khoản của mình. Hãy lưu cụm mật khẩu gốc này ở nơi an toàn và bí mật." + }, + "revealSeedWordsTitle": { + "message": "Cụm mật khẩu gốc" + }, + "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." + }, + "revealSeedWordsWarningTitle": { + "message": "KHÔNG chia sẻ cụm mật khẩu này với bất kỳ ai!" }, "rinkeby": { "message": "Mạng thử nghiệm Rinkeby" @@ -246,62 +1331,760 @@ "ropsten": { "message": "Mạng thử nghiệm Ropsten" }, + "rpcUrl": { + "message": "URL RPC mới" + }, "save": { "message": "Lưu" }, + "saveAsCsvFile": { + "message": "Lưu dưới dạng tệp CSV" + }, + "scanInstructions": { + "message": "Đặt mã QR vào trước máy ảnh" + }, + "scanQrCode": { + "message": "Quét mã QR" + }, + "scrollDown": { + "message": "Cuộn xuống" + }, + "search": { + "message": "Tìm kiếm" + }, + "searchAccounts": { + "message": "Tìm kiếm tài khoản" + }, + "searchResults": { + "message": "Kết quả tìm kiếm" + }, + "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." + }, + "secretBackupPhraseWarning": { + "message": "CẢNH BÁO: Tuyệt đối không để lộ cụm mật khẩu sao lưu của bạn. Bất kỳ ai có cụm mật khẩu này cũng có thể lấy Ether của bạn vĩnh viễn." + }, + "secretPhrase": { + "message": "Nhập cụm mật khẩu bí mật gồm 12 từ vào đây để khôi phục két của bạn." + }, + "securityAndPrivacy": { + "message": "Bảo mật và quyền riêng tư" + }, + "securitySettingsDescription": { + "message": "Cụm mật khẩu gốc của ví và các tùy chọn cài đặt quyền riêng tư" + }, + "seedPhrasePlaceholder": { + "message": "Phân tách mỗi từ bằng một dấu cách" + }, + "seedPhrasePlaceholderPaste": { + "message": "Dán cụm mật khẩu gốc từ khay nhớ tạm" + }, + "seedPhraseReq": { + "message": "Cụm mật khẩu gốc gồm 12, 15, 18, 21 hoặc 24 từ" + }, + "selectAHigherGasFee": { + "message": "Chọn phí gas cao hơn để tăng tốc quá trình xử lý giao dịch của bạn.*" + }, + "selectAccounts": { + "message": "Chọn (các) tài khoản" + }, + "selectAll": { + "message": "Chọn tất cả" + }, + "selectAnAccount": { + "message": "Chọn một tài khoản" + }, + "selectAnAccountHelp": { + "message": "Chọn tài khoản để xem trong MetaMask" + }, + "selectEachPhrase": { + "message": "Vui lòng chọn từng cụm mật khẩu theo thứ tự để đảm bảo sự chính xác." + }, + "selectHdPath": { + "message": "Chọn đường dẫn phân cấp xác định" + }, + "selectPathHelp": { + "message": "Nếu bạn không thấy các tài khoản Ledger hiện có của bạn dưới đây, hãy thử chuyển đường dẫn thành \"Legacy (MEW / MyCrypto)\"" + }, + "selectType": { + "message": "Chọn loại" + }, + "selectingAllWillAllow": { + "message": "Việc chọn tất cả sẽ cho phép trang này xem tất cả các tài khoản hiện tại của bạn. Đảm bảo rằng bạn tin tưởng trang web này." + }, "send": { "message": "Gửi" }, + "sendAmount": { + "message": "Gửi khoản tiền" + }, + "sendETH": { + "message": "Gửi ETH" + }, + "sendSpecifiedTokens": { + "message": "Gửi $1", + "description": "Symbol of the specified token" + }, "sendTokens": { - "message": "Gửi mã token" + "message": "Gửi token" + }, + "sentEther": { + "message": "đã gửi ether" + }, + "separateEachWord": { + "message": "Phân tách mỗi từ bằng một dấu cách" }, "settings": { "message": "Cài đặt" }, + "showAdvancedGasInline": { + "message": "Quyền kiểm soát gas nâng cao" + }, + "showAdvancedGasInlineDescription": { + "message": "Chọn tùy chọn này để hiển thị các quyền kiểm soát giá và giới hạn ngay trên màn hình gửi và xác nhận." + }, + "showFiatConversionInTestnets": { + "message": "Hiển thị tỷ lệ quy đổi trên các mạng thử nghiệm" + }, + "showFiatConversionInTestnetsDescription": { + "message": "Chọn tùy chọn này để hiển thị tỷ lệ quy đổi pháp định trên Mạng thử nghiệm" + }, + "showHexData": { + "message": "Hiển thị dữ liệu thập lục phân" + }, + "showHexDataDescription": { + "message": "Chọn tùy chọn này để hiển thị trường dữ liệu thập lục phân trên màn hình gửi" + }, + "showIncomingTransactions": { + "message": "Hiển thị các giao dịch đến" + }, + "showIncomingTransactionsDescription": { + "message": "Chọn tùy chọn này nếu bạn muốn dùng Etherscan để hiển thị các giao dịch đến trong danh sách giao dịch" + }, + "showPermissions": { + "message": "Hiển thị quyền" + }, "showPrivateKeys": { - "message": "Hiển thị khóa cá nhân" + "message": "Hiện khóa riêng tư" + }, + "showSeedPhrase": { + "message": "Hiển thị cụm mật khẩu gốc" }, "sigRequest": { "message": "Yêu cầu chữ ký" }, "sign": { - "message": "Ký nhận" + "message": "Ký" }, "signNotice": { - "message": "Ký nhận vào tin nhắn này có thể gây nguy hiểm. Chỉ nên ký nhận tin nhắn từ những nguồn bạn hoàn toàn tin tưởng có thể dùng với tài khoản của bạn. Cách thức nguy hiểm này sẽ bị xóa trong phiên bản sắp tới." + "message": "Việc ký thông báo này có thể gây ra \nảnh hưởng nguy hiểm ngoài ý muốn. Chỉ ký những thông báo từ \ncác trang web mà bạn hoàn toàn tin tưởng bằng toàn bộ tài khoản của mình.\n Chúng tôi sẽ loại bỏ phương thức nguy hiểm này trong phiên bản sau này. " }, "signatureRequest": { "message": "Yêu cầu chữ ký" }, + "signatureRequest1": { + "message": "Thông báo" + }, + "signed": { + "message": "Đã ký" + }, + "slow": { + "message": "Chậm" + }, + "somethingWentWrong": { + "message": "Rất tiếc! Đã xảy ra sự cố." + }, + "speedUp": { + "message": "Tăng tốc" + }, + "speedUpCancellation": { + "message": "Tăng tốc lệnh hủy này" + }, + "speedUpTransaction": { + "message": "Tăng tốc giao dịch này" + }, + "spendLimitAmount": { + "message": "Khoản tiền giới hạn chi tiêu" + }, + "spendLimitInsufficient": { + "message": "Giới hạn chi tiêu không đủ" + }, + "spendLimitInvalid": { + "message": "Giới hạn chi tiêu không hợp lệ; giá trị này phải là số dương." + }, + "spendLimitPermission": { + "message": "Quyền đối với giới hạn chi tiêu" + }, + "spendLimitRequestedBy": { + "message": "Bên yêu cầu giới hạn chi tiêu: $1", + "description": "Origin of the site requesting the spend limit" + }, + "spendLimitTooLarge": { + "message": "Giới hạn chi tiêu quá lớn" + }, + "stateLogError": { + "message": "Lỗi khi truy xuất nhật ký trạng thái." + }, + "stateLogFileName": { + "message": "Nhật ký trạng thái của MetaMask" + }, + "stateLogs": { + "message": "Nhật ký trạng thái" + }, + "stateLogsDescription": { + "message": "Nhật ký trạng thái có chứa các địa chỉ tài khoản công khai của bạn và các giao dịch đã gửi." + }, + "statusConnected": { + "message": "Đã kết nối" + }, + "statusNotConnected": { + "message": "Chưa kết nối" + }, + "step1HardwareWallet": { + "message": "1. Kết nối với ví cứng" + }, + "step1HardwareWalletMsg": { + "message": "Kết nối ví cứng của bạn trực tiếp với máy tính." + }, + "step2HardwareWallet": { + "message": "2. Chọn một tài khoản" + }, + "step2HardwareWalletMsg": { + "message": "Chọn tài khoản bạn muốn xem. Bạn chỉ chọn được một tài khoản tại một thời điểm." + }, + "step3HardwareWallet": { + "message": "3. Bắt đầu sử dụng các trang web trên web3 và nhiều hơn thế!" + }, + "step3HardwareWalletMsg": { + "message": "Sử dụng cùng một tài khoản ví cứng mà bạn sẽ dùng với mọi tài khoản Ethereum của mình. Kết nối với các trang web trên web3, gửi ETH, mua và lưu trữ token ERC20 cũng như token không thể thay thế, chẳng hạn như CryptoKitties." + }, + "storePhrase": { + "message": "Lưu cụm mật khẩu này trong trình quản lý mật khẩu chẳng hạn như 1Password." + }, + "submit": { + "message": "Gửi" + }, + "submitted": { + "message": "Đã gửi" + }, + "supportCenter": { + "message": "Truy cập Trung tâm hỗ trợ của chúng tôi" + }, + "swap": { + "message": "Hoán đổi" + }, + "swapAdvancedSlippageInfo": { + "message": "Giá thay đổi giữa thời điểm đặt và xác nhận lệnh, việc này được gọi là “trượt giá”. Giao dịch hoán đổi của bạn sẽ tự động hủy nếu mức trượt giá vượt quá “mức trượt giá tối đa” đã cài đặt." + }, + "swapAggregator": { + "message": "Trình tổng hợp" + }, + "swapAmountReceived": { + "message": "Số tiền được đảm bảo" + }, + "swapAmountReceivedInfo": { + "message": "Đây là số tiền tối thiểu mà bạn sẽ nhận được. Bạn sẽ nhận được nhiều hơn tùy thuộc vào mức trượt giá." + }, + "swapApproval": { + "message": "Phê duyệt $1 cho các giao dịch hoán đổi", + "description": "Used in the transaction display list to describe a transaction that is an approve call on a token that is to be swapped.. $1 is the symbol of a token that has been approved." + }, + "swapApproveNeedMoreTokens": { + "message": "Bạn cần $1 $2 nữa để hoàn tất giao dịch hoán đổi này", + "description": "Tells the user how many more of a given token they need for a specific swap. $1 is an amount of tokens and $2 is the token symbol." + }, + "swapBuildQuotePlaceHolderText": { + "message": "Không có token nào khớp với $1", + "description": "Tells the user that a given search string does not match any tokens in our token lists. $1 can be any string of text" + }, + "swapCheckingQuote": { + "message": "Đang kiểm tra $1", + "description": "Shown to the user during quote loading. $1 is the name of an aggregator. The message indicates that metamask is currently checking if that aggregator has a trade/quote for their requested swap." + }, + "swapCustom": { + "message": "tùy chỉnh" + }, + "swapDecentralizedExchange": { + "message": "Sàn giao dịch phi tập trung" + }, + "swapEditLimit": { + "message": "Chỉnh sửa giới hạn" + }, + "swapEnableDescription": { + "message": "Thao tác này là bắt buộc và cấp cho MetaMask quyền hoán đổi $1 của bạn.", + "description": "Gives the user info about the required approval transaction for swaps. $1 will be the symbol of a token being approved for swaps." + }, + "swapEstimatedNetworkFee": { + "message": "Phí mạng ước tính" + }, + "swapEstimatedNetworkFeeSummary": { + "message": "“$1” là giá trị mà chúng tôi dự kiến sẽ là khoản phí thực sự. Số tiền chính xác phụ thuộc vào tình trạng mạng.", + "description": "$1 will be the translation of swapEstimatedNetworkFee, with the font bolded" + }, + "swapEstimatedNetworkFees": { + "message": "Phí mạng ước tính" + }, + "swapEstimatedNetworkFeesInfo": { + "message": "Đây là giá trị ước tính của phí mạng sẽ dùng để hoàn thành giao dịch hoán đổi của bạn. Số tiền thực tế có thể thay đổi tùy theo tình trạng mạng." + }, + "swapFailedErrorTitle": { + "message": "Hoán đổi không thành công" + }, + "swapFetchingQuotesErrorDescription": { + "message": "Rất tiếc... đã xảy ra sự cố. Hãy thử lại. Nếu lỗi vẫn tiếp diễn, hãy liên hệ với bộ phận hỗ trợ khách hàng." + }, + "swapFetchingQuotesErrorTitle": { + "message": "Lỗi tìm nạp báo giá" + }, + "swapFetchingTokens": { + "message": "Đang tìm nạp token..." + }, + "swapFinalizing": { + "message": "Đang hoàn tất..." + }, + "swapHighSlippageWarning": { + "message": "Số tiền trượt giá rất cao. Hãy chắc chắn rằng bạn hiểu những gì mình đang làm!" + }, + "swapIntroLearnMoreHeader": { + "message": "Bạn muốn tìm hiểu thêm?" + }, + "swapIntroLearnMoreLink": { + "message": "Tìm hiểu thêm về MetaMask Swaps" + }, + "swapIntroLiquiditySourcesLabel": { + "message": "Các nguồn thanh khoản bao gồm:" + }, + "swapIntroPopupSubTitle": { + "message": "Giờ đây bạn có thể hoán đổi token ngay trong ví MetaMask của mình. MetaMask Swaps quy tụ nhiều trình tổng hợp sàn giao dịch phi tập trung, các nhà tạo lập thị trường chuyên nghiệp và các sàn giao dịch phi tập trung dành cho cá nhân nhằm đảm bảo người dùng MetaMask luôn nhận được mức giá tốt nhất với phí mạng thấp nhất." + }, + "swapIntroPopupTitle": { + "message": "Tính năng hoán đổi token đã sẵn sàng!" + }, + "swapLearnMoreContractsAuditReview": { + "message": "Xem xét quy trình kiểm tra hợp đồng chính thức của chúng tôi" + }, + "swapLowSlippageError": { + "message": "Giao dịch có thể không thành công, mức trượt giá tối đa quá thấp." + }, + "swapMaxNetworkFeeInfo": { + "message": "“$1” là mức chi tiêu cao nhất của bạn. Khi mạng không ổn định, đây có thể là số tiền lớn.", + "description": "$1 will be the translation of swapMaxNetworkFees, with the font bolded" + }, + "swapMaxNetworkFees": { + "message": "Phí mạng tối đa" + }, + "swapMaxSlippage": { + "message": "Mức trượt giá tối đa" + }, + "swapMetaMaskFee": { + "message": "Phí của MetaMask" + }, + "swapMetaMaskFeeDescription": { + "message": "Chúng tôi luôn tìm giá tốt nhất từ các nguồn thanh khoản hàng đầu. Khoản phí $1% tự động được tính vào mỗi báo giá để hỗ trợ sự phát triển liên tục và giúp MetaMask hoàn thiện hơn nữa.", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapNetworkFeeSummary": { + "message": "Phí mạng dùng để chi trả chi phí xử lý giao dịch hoán đổi của bạn và lưu trữ giao dịch đó trên mạng Ethereum. MetaMask không thu lợi từ khoản phí này." + }, + "swapNewQuoteIn": { + "message": "Báo giá mới sẽ có sau $1", + "description": "Tells the user the amount of time until the currently displayed quotes are update. $1 is a time that is counting down from 1:00 to 0:00" + }, + "swapOnceTransactionHasProcess": { + "message": "$1 của bạn sẽ được thêm vào tài khoản sau khi xử lý xong giao dịch.", + "description": "This message communicates the token that is being transferred. It is shown on the awaiting swap screen. The $1 will be a token symbol." + }, + "swapProcessing": { + "message": "Đang xử lý" + }, + "swapQuoteDetails": { + "message": "Chi tiết báo giá" + }, + "swapQuoteDetailsSlippageInfo": { + "message": "Giá thay đổi giữa thời điểm đặt và xác nhận lệnh, việc này được gọi là \"trượt giá\". Giao dịch Hoán đổi của bạn sẽ tự động hủy nếu mức trượt giá vượt quá \"mức trượt giá tối đa\" đã cài đặt." + }, + "swapQuoteIncludesRate": { + "message": "Báo giá có bao gồm khoản phí $1% cho MetaMask", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapQuoteNofN": { + "message": "Báo giá $1/$2", + "description": "A count of loaded quotes shown to the user while they are waiting for quotes to be fetched. $1 is the number of quotes already loaded, and $2 is the total number of quotes to load." + }, + "swapQuoteSource": { + "message": "Nguồn báo giá" + }, + "swapQuotesAreRefreshed": { + "message": "Báo giá được làm mới thường xuyên để thể hiện tình trạng hiện tại của thị trường." + }, + "swapQuotesExpiredErrorDescription": { + "message": "Vui lòng yêu cầu báo giá mới để biết các mức tỷ lệ mới nhất." + }, + "swapQuotesExpiredErrorTitle": { + "message": "Hết thời gian chờ báo giá" + }, + "swapQuotesNotAvailableErrorDescription": { + "message": "Hãy thử điều chỉnh số tiền hoặc tùy chọn cài đặt mức trượt giá và thử lại." + }, + "swapQuotesNotAvailableErrorTitle": { + "message": "Không có báo giá" + }, + "swapRate": { + "message": "Tỷ lệ" + }, + "swapReceiving": { + "message": "Đang nhận" + }, + "swapReceivingInfoTooltip": { + "message": "Đây là giá trị ước tính. Số tiền chính xác phụ thuộc vào mức trượt giá." + }, + "swapRequestForQuotation": { + "message": "Yêu cầu báo giá" + }, + "swapSearchForAToken": { + "message": "Tìm kiếm token" + }, + "swapSelect": { + "message": "Chọn" + }, + "swapSelectAQuote": { + "message": "Chọn một báo giá" + }, + "swapSelectAToken": { + "message": "Chọn một token" + }, + "swapSelectQuotePopoverDescription": { + "message": "Dưới đây là tất cả các báo giá thu thập từ nhiều nguồn thanh khoản." + }, + "swapSlippageTooLow": { + "message": "Mức trượt giá phải lớn hơn 0" + }, + "swapSource": { + "message": "Nguồn thanh khoản" + }, + "swapSourceInfo": { + "message": "Chúng tôi tìm kiếm nhiều nguồn thanh khoản (các sàn giao dịch, trình tổng hợp và nhà tạo lập thị trường) để tìm được mức tỷ lệ tốt nhất và phí mạng thấp nhất." + }, + "swapStartSwapping": { + "message": "Bắt đầu hoán đổi" + }, + "swapSwapFrom": { + "message": "Hoán đổi từ" + }, + "swapSwapSwitch": { + "message": "Chuyển từ và chuyển sang token khác" + }, + "swapSwapTo": { + "message": "Hoán đổi sang" + }, + "swapThisWillAllowApprove": { + "message": "Thao tác này sẽ cho phép hoán đổi $1" + }, + "swapTokenAvailable": { + "message": "Đã thêm $1 vào tài khoản của bạn.", + "description": "This message is shown after a swap is successful and communicates the exact amount of tokens the user has received for a swap. The $1 is a decimal number of tokens followed by the token symbol." + }, + "swapTokenToToken": { + "message": "Hoán đổi $1 sang $2", + "description": "Used in the transaction display list to describe a swap. $1 and $2 are the symbols of tokens in involved in a swap." + }, + "swapTransactionComplete": { + "message": "Đã hoàn tất giao dịch" + }, + "swapUnknown": { + "message": "Không xác định" + }, + "swapVerifyTokenExplanation": { + "message": "Nhiều token có thể dùng cùng một tên và ký hiệu. Hãy kiểm tra trên Etherscan để xác minh xem đây có phải là token bạn đang tìm kiếm không." + }, + "swapViewToken": { + "message": "Xem $1" + }, + "swapYourTokenBalance": { + "message": "Có sẵn $1 $2 để hoán đổi", + "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" + }, + "swapZeroSlippage": { + "message": "Mức trượt giá 0%" + }, + "swapsAdvancedOptions": { + "message": "Tùy chọn nâng cao" + }, + "swapsMaxSlippage": { + "message": "Mức trượt giá tối đa" + }, + "swapsNotEnoughForTx": { + "message": "Không đủ $1 để hoàn thành giao dịch này", + "description": "Tells the user that they don't have enough of a token for a proposed swap. $1 is a token symbol" + }, + "swapsViewInActivity": { + "message": "Xem hoạt động" + }, + "switchNetworks": { + "message": "Thay đổi mạng" + }, + "switchToThisAccount": { + "message": "Chuyển sang tài khoản này" + }, + "symbol": { + "message": "Ký hiệu" + }, + "symbolBetweenZeroTwelve": { + "message": "Ký hiệu không được dài quá 11 ký tự." + }, + "syncWithMobile": { + "message": "Đồng bộ hóa với thiết bị di động" + }, + "syncWithMobileBeCareful": { + "message": "Đảm bảo rằng không có ai nhìn vào màn hình của bạn khi quét mã này" + }, + "syncWithMobileComplete": { + "message": "Đã đồng bộ hóa thành công dữ liệu của bạn. Tận hưởng ứng dụng MetaMask trên thiết bị di động!" + }, + "syncWithMobileDesc": { + "message": "Bạn có thể đồng bộ hóa tài khoản và thông tin của mình với thiết bị di động. Mở ứng dụng MetaMask trên thiết bị di động, chuyển đến phần \"Cài đặt\" và nhấn vào \"Đồng bộ hóa với tiện ích trình duyệt\"" + }, + "syncWithMobileDescNewUsers": { + "message": "Nếu mới mở ứng dụng MetaMask trên thiết bị di động lần đầu tiên, bạn chỉ cần làm theo các bước hướng dẫn trên điện thoại." + }, + "syncWithMobileScanThisCode": { + "message": "Quét mã này bằng ứng dụng MetaMask trên thiết bị di động" + }, + "syncWithMobileTitle": { + "message": "Đồng bộ hóa với thiết bị di động" + }, + "syncWithThreeBox": { + "message": "Đồng bộ hóa dữ liệu với 3Box (thử nghiệm)" + }, + "syncWithThreeBoxDescription": { + "message": "Bật để sao lưu các tùy chọn cài đặt của bạn với 3Box. Tính năng này hiện đang trong giai đoạn thử nghiệm; bạn tự chịu rủi ro khi sử dụng." + }, + "syncWithThreeBoxDisabled": { + "message": "Đã tắt 3Box do có lỗi xảy ra trong quá trình đồng bộ hóa ban đầu" + }, + "terms": { + "message": "Điều khoản sử dụng" + }, + "termsOfService": { + "message": "Điều khoản dịch vụ" + }, "testFaucet": { - "message": "Vòi nhận tiền ETH ảo để thử nghiệm" + "message": "Vòi thử nghiệm" + }, + "thisWillCreate": { + "message": "Thao tác này sẽ tạo một ví mới và cụm mật khẩu gốc" + }, + "tips": { + "message": "Mẹo" }, "to": { "message": "Đến" }, + "toAddress": { + "message": "Đến: $1", + "description": "$1 is the address to include in the To label. It is typically shortened first using shortenAddress" + }, + "toWithColon": { + "message": "Đến:" + }, + "token": { + "message": "Token" + }, + "tokenAlreadyAdded": { + "message": "Đã thêm token." + }, + "tokenContractAddress": { + "message": "Địa chỉ hợp đồng token" + }, + "tokenOptions": { + "message": "Tùy chọn token" + }, + "tokenSymbol": { + "message": "Ký hiệu token" + }, "total": { - "message": "Tổng cộng" + "message": "Tổng" + }, + "transaction": { + "message": "giao dịch" + }, + "transactionCancelAttempted": { + "message": "Đã cố gắng hủy giao dịch với mức phí gas $1 lúc $2" + }, + "transactionCancelSuccess": { + "message": "Đã hủy thành công giao dịch lúc $2" + }, + "transactionConfirmed": { + "message": "Đã xác nhận giao dịch lúc $2." + }, + "transactionCreated": { + "message": "Đã tạo giao dịch với giá trị $1 lúc $2" + }, + "transactionDropped": { + "message": "Đã ngừng giao dịch lúc $2." + }, + "transactionError": { + "message": "Lỗi giao dịch. Đã xảy ra ngoại lệ trong mã hợp đồng." + }, + "transactionErrorNoContract": { + "message": "Đang cố gắng gọi một hàm trên địa chỉ không có hợp đồng." + }, + "transactionErrored": { + "message": "Giao dịch đã gặp lỗi." + }, + "transactionFee": { + "message": "Phí giao dịch" + }, + "transactionResubmitted": { + "message": "Đã gửi lại giao dịch với mức phí gas tăng lên $1 lúc $2" + }, + "transactionSubmitted": { + "message": "Đã gửi giao dịch với mức phí gas $1 lúc $2." + }, + "transactionUpdated": { + "message": "Đã cập nhật giao dịch lúc $2." + }, + "transfer": { + "message": "Chuyển" + }, + "transferBetweenAccounts": { + "message": "Chuyển giữa các tài khoản của tôi" + }, + "transferFrom": { + "message": "Chuyển từ" + }, + "troubleConnectingToWallet": { + "message": "Chúng tôi đã gặp phải sự cố khi kết nối với $1 của bạn, hãy thử xem lại $2 và thử lại.", + "description": "$1 is the wallet device name; $2 is a link to wallet connection guide" }, "troubleTokenBalances": { - "message": "Chúng tôi gặp sự cố khi tải số dư token của bạn. Xin vui lòng xem lại", + "message": "Chúng tôi đã gặp phải vấn đề khi tải số dư token của bạn. Bạn có thể xem số dư ", "description": "Followed by a link (here) to view token balances" }, + "trustSiteApprovePermission": { + "message": "Bạn có tin tưởng trang web này không? Bằng việc cấp quyền này, bạn sẽ cho phép $1 rút $2 của bạn và tự động thực hiện các giao dịch cho bạn.", + "description": "$1 is the url requesting permission and $2 is the symbol of the currency that the request is for" + }, + "tryAgain": { + "message": "Thử lại" + }, "typePassword": { - "message": "Điền mật khẩu của bạn" + "message": "Nhập mật khẩu MetaMask của bạn" + }, + "unapproved": { + "message": "Chưa phê duyệt" + }, + "units": { + "message": "đơn vị" }, "unknown": { "message": "Không xác định" }, + "unknownCameraError": { + "message": "Đã xảy ra lỗi khi cố gắng truy cập máy ảnh của bạn. Vui lòng thử lại..." + }, + "unknownCameraErrorTitle": { + "message": "Rất tiếc! Đã xảy ra sự cố...." + }, "unknownNetwork": { - "message": "Mạng lưới riêng không xác định" + "message": "Mạng riêng không xác định" + }, + "unknownQrCode": { + "message": "Lỗi: Chúng tôi không thể xác định mã QR đó" + }, + "unlimited": { + "message": "Không giới hạn" + }, + "unlock": { + "message": "Mở khóa" + }, + "unlockMessage": { + "message": "Web phi tập trung đang chờ đón bạn" + }, + "updatedWithDate": { + "message": "Đã cập nhật vào $1" + }, + "urlErrorMsg": { + "message": "URL phải có tiền tố HTTP/HTTPS phù hợp." + }, + "urlExistsErrorMsg": { + "message": "URL đã có trong danh sách mạng hiện tại" + }, + "usePhishingDetection": { + "message": "Sử dụng tính năng Phát hiện lừa đảo" + }, + "usePhishingDetectionDescription": { + "message": "Hiển thị cảnh báo đối với các miền lừa đảo nhắm đến người dùng Ethereum" }, "usedByClients": { - "message": "Được sử dụng bởi nhiều khách hàng khác nhau" + "message": "Được nhiều ví khác nhau sử dụng" + }, + "userName": { + "message": "Tên người dùng" + }, + "verifyThisTokenOn": { + "message": "Xác minh token này trên $1", + "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" }, "viewAccount": { "message": "Xem tài khoản" }, + "viewContact": { + "message": "Xem người liên hệ" + }, + "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 gốc" + }, + "welcome": { + "message": "Chào mừng bạn đến với MetaMask" + }, + "welcomeBack": { + "message": "Chào mừng bạn trở lại!" + }, + "whatsThis": { + "message": "Đây là gì?" + }, + "writePhrase": { + "message": "Ghi cụm mật khẩu này ra giấy và lưu giữ ở một nơi an toàn. Nếu bạn cần độ bảo mật cao hơn nữa, hãy ghi ra nhiều tờ giấy và lưu giữ ở 2 đến 3 nơi khác nhau." + }, + "xOfY": { + "message": "$1/$2", + "description": "$1 and $2 are intended to be two numbers, where $2 is a total, and $1 is a count towards that total" + }, + "yesLetsTry": { + "message": "Có, hãy thử" + }, + "youNeedToAllowCameraAccess": { + "message": "Bạn cần cho phép truy cập vào camera để sử dụng tính năng này." + }, "youSign": { - "message": "Bạn đang ký nhận" + "message": "Bạn đang ký" + }, + "yourPrivateSeedPhrase": { + "message": "Cụm mật khẩu gốc riêng tư của bạn" + }, + "zeroGasPriceOnSpeedUpError": { + "message": "Giá gas bằng 0 khi tăng tốc" } } diff --git a/app/_locales/zh_CN/messages.json b/app/_locales/zh_CN/messages.json index c584e0fc3..cef95ab7e 100644 --- a/app/_locales/zh_CN/messages.json +++ b/app/_locales/zh_CN/messages.json @@ -3,13 +3,21 @@ "message": "关于" }, "aboutSettingsDescription": { - "message": "版本、技术支持中心和联系方式。" + "message": "版本、支持中心和联系方式。" }, "acceleratingATransaction": { - "message": "* 设定更高的 Gas 价格,加快交易的完成进度,提高网络快速处理机率,但无法保证每次均能够实现提速。" + "message": "* 设定更高燃料价格,可以加快交易完成进度,提高网络快速处理机率,但无法保证每次均能够实现提速。" + }, + "acceptTermsOfUse": { + "message": "我已阅读并同意 $1", + "description": "$1 is the `terms` message" + }, + "accessAndSpendNotice": { + "message": "$1 可以访问并使用此最大数额", + "description": "$1 is the url of the site requesting ability to spend" }, "accessingYourCamera": { - "message": "正在获取相机使用权限..." + "message": "正在获取您的相机……" }, "account": { "message": "账户" @@ -26,11 +34,20 @@ "accountSelectionRequired": { "message": "您需要选择一个账户 !" }, + "active": { + "message": "当前" + }, + "activity": { + "message": "活动" + }, "activityLog": { "message": "活动日志" }, + "addAccount": { + "message": "添加一个账户" + }, "addAcquiredTokens": { - "message": "在MetaMask上添加已用的代币" + "message": "在 MetaMask 上添加获得的代币" }, "addAlias": { "message": "添加别名" @@ -39,7 +56,7 @@ "message": "添加网络" }, "addRecipient": { - "message": "添加接受人" + "message": "添加接收方" }, "addSuggestedTokens": { "message": "添加推荐代币" @@ -63,10 +80,58 @@ "message": "高级选项" }, "advancedSettingsDescription": { - "message": "访问开发者功能,下载状态日志,重置账户,安排测试网络和自定义 RPC 。" + "message": "访问开发者功能,下载状态日志,重置账户,设置测试网和自定义 RPC。" + }, + "affirmAgree": { + "message": "我同意" + }, + "aggregatorFeeCost": { + "message": "聚集器网络手续费" + }, + "alertDisableTooltip": { + "message": "这个可以在“设置 > 提醒”中进行更改" + }, + "alertSettingsUnconnectedAccount": { + "message": "选择了未连接的账户时浏览网站" + }, + "alertSettingsUnconnectedAccountDescription": { + "message": "当您在浏览已连接的 Web3 网站,但当前选择的账户没有连接时,该提醒会在弹出的窗口中显示。" + }, + "alertSettingsWeb3ShimUsage": { + "message": "当网站尝试使用已经删除的 window.web3 API" + }, + "alertSettingsWeb3ShimUsageDescription": { + "message": "当您在浏览的网站尝试使用已经删除的 window.web3 API 时,该提醒会在弹出的窗口中显示。" + }, + "alerts": { + "message": "提醒" + }, + "alertsSettingsDescription": { + "message": "启用或禁用每个提醒" + }, + "allowExternalExtensionTo": { + "message": "允许这个外部扩展到:" + }, + "allowOriginSpendToken": { + "message": "允许 $1 使用您的 $2?", + "description": "$1 is the url of the site and $2 is the symbol of the token they are requesting to spend" + }, + "allowThisSiteTo": { + "message": "允许本网站:" + }, + "allowWithdrawAndSpend": { + "message": "允许 $1 提取和最多消费以下数额:", + "description": "The url of the site that requested permission to 'withdraw and spend'" }, "amount": { - "message": "数量" + "message": "数额" + }, + "amountInEth": { + "message": "$1 ETH", + "description": "Displays an eth amount to the user. $1 is a decimal number" + }, + "amountWithColon": { + "message": "数额:" }, "appDescription": { "message": "以太坊浏览器插件", @@ -76,8 +141,18 @@ "message": "MetaMask", "description": "The name of the application" }, + "approvalAndAggregatorTxFeeCost": { + "message": "批准聚合商网络手续费" + }, + "approvalTxGasCost": { + "message": "批准交易燃料成本" + }, "approve": { - "message": "批准" + "message": "批准消费限额" + }, + "approveSpendLimit": { + "message": "批准 $1 消费限额", + "description": "The token symbol that is being approved" }, "approved": { "message": "已批准" @@ -85,23 +160,29 @@ "asset": { "message": "资产" }, + "assets": { + "message": "资产" + }, "attemptToCancel": { "message": "想要取消吗?" }, "attemptToCancelDescription": { - "message": "确认提交该操作无法保证能够成功取消您的原始交易。如果取消成功,您将被收取上述交易费用。" + "message": "确认提交该操作无法保证能够成功取消您的原始交易。如取消成功,您将被收取上述交易费。" }, "attemptingConnect": { - "message": "正在尝试连接区块链。" + "message": "正在尝试连接到区块链。" }, "attributions": { "message": "来源" }, + "authorizedPermissions": { + "message": "您已授权以下权限" + }, "autoLockTimeLimit": { - "message": "自动注销计时器(分钟)" + "message": "自动锁定定时(分钟)" }, "autoLockTimeLimitDescription": { - "message": "请设置 MetaMask 自动注销前的空闲时间(以分钟为单位)" + "message": "请设置 MetaMask 自动锁定前的空闲时间(单位:分钟)" }, "average": { "message": "平均值" @@ -110,19 +191,19 @@ "message": "返回" }, "backToAll": { - "message": "恢复所有设置" + "message": "返回全部" }, "backupApprovalInfo": { "message": "如果不慎丢失个人设备,忘记密码,或者需要重新安装 MetaMask,亦或是需在另一台设备上打开钱包,请使用该保密码恢复个人钱包数据。" }, "backupApprovalNotice": { - "message": "请备份您的私密恢复代码,保证个人钱包和资金安全。" + "message": "请备份您的账户助记词,保证您的钱包和资金安全。" }, "backupNow": { "message": "立即备份" }, "balance": { - "message": "余额:" + "message": "余额 " }, "balanceOutdated": { "message": "余额可能已过期" @@ -131,21 +212,24 @@ "message": "基本" }, "blockExplorerUrl": { - "message": "屏蔽管理器" + "message": "区块浏览器" }, "blockExplorerView": { "message": "通过 $1 查看账户", "description": "$1 replaced by URL for custom block explorer" }, "blockiesIdenticon": { - "message": "使用区块Identicon" + "message": "使用 Blockies Identicon 图标头像" }, "browserNotSupported": { - "message": "您的浏览器不支持该功能…" + "message": "您的浏览器不支持该功能……" }, "builtInCalifornia": { "message": "MetaMask在加利福尼亚设计和制造。" }, + "buy": { + "message": "购买" + }, "buyWithWyre": { "message": "使用 Wyre 购买 ETH" }, @@ -155,11 +239,14 @@ "bytes": { "message": "字节" }, + "canToggleInSettings": { + "message": "您可以在 设置 -> 提醒 中重新启用该提醒通知。" + }, "cancel": { "message": "取消" }, "cancellationGasFee": { - "message": "取消 Gas 费" + "message": "取消交易燃料费用" }, "cancelled": { "message": "已取消" @@ -168,7 +255,7 @@ "message": "链 ID" }, "chromeRequiredForHardwareWallets": { - "message": "您需要通过 Google Chrome 浏览器使用 MetaMask ,连接个人硬件钱包。" + "message": "您需要在谷歌浏览器(Google Chrome)上使用 MetaMask 才能连接到您的硬件钱包。" }, "clickToRevealSeed": { "message": "点击此处显示密语" @@ -183,7 +270,7 @@ "message": "确认密码" }, "confirmSecretBackupPhrase": { - "message": "请确认您的私密备份密语" + "message": "请确认您的账户助记词" }, "confirmed": { "message": "确认" @@ -194,8 +281,61 @@ "connect": { "message": "连接" }, + "connectAccountOrCreate": { + "message": "连接账户或创建新账户" + }, "connectHardwareWallet": { - "message": "链接硬件钱包" + "message": "连接硬件钱包" + }, + "connectManually": { + "message": "手动连接到当前站点" + }, + "connectTo": { + "message": "连接到 $1", + "description": "$1 is the name/origin of a web3 site/application that the user can connect to metamask" + }, + "connectToAll": { + "message": "连接到您的全部$1", + "description": "$1 will be replaced by the translation of connectToAllAccounts" + }, + "connectToAllAccounts": { + "message": "账户", + "description": "will replace $1 in connectToAll, completing the sentence 'connect to all of your accounts', will be text that shows list of accounts on hover" + }, + "connectToMultiple": { + "message": "连接到 $1", + "description": "$1 will be replaced by the translation of connectToMultipleNumberOfAccounts" + }, + "connectToMultipleNumberOfAccounts": { + "message": "$1 个账户", + "description": "$1 is the number of accounts to which the web3 site/application is asking to connect; this will substitute $1 in connectToMultiple" + }, + "connectWithMetaMask": { + "message": "使用 MetaMask 连接" + }, + "connectedAccountsDescriptionPlural": { + "message": "您有 $1 个账户连接到了该网站。", + "description": "$1 is the number of accounts" + }, + "connectedAccountsDescriptionSingular": { + "message": "您有 1 个账户连接到了该网站。" + }, + "connectedAccountsEmptyDescription": { + "message": "MetaMask 没有连接这个网站。要连接到 web3 网站,请在他们的网站上找到连接按钮。" + }, + "connectedSites": { + "message": "已连接的网站" + }, + "connectedSitesDescription": { + "message": "$1 已连接到这些网站。他们可以查看您的账户地址。", + "description": "$1 is the account name" + }, + "connectedSitesEmptyDescription": { + "message": "$1 还没连接任何网站。", + "description": "$1 is the account name" + }, + "connecting": { + "message": "连接中……" }, "connectingTo": { "message": "正在连接 $1" @@ -204,16 +344,25 @@ "message": "正在连接 Goerli 测试网络" }, "connectingToKovan": { - "message": "正在连接到Kovan测试网络" + "message": "正在连接到 Kovan 测试网络" }, "connectingToMainnet": { - "message": "正在连接到以太坊主网" + "message": "正在连接到以太坊 Ethereum 主网" }, "connectingToRinkeby": { - "message": "正在连接到Rinkeby测试网络" + "message": "正在连接到 Rinkeby 测试网络" }, "connectingToRopsten": { - "message": "正在连接到Ropsten测试网络" + "message": "正在连接到 Ropsten 测试网络" + }, + "contactUs": { + "message": "联系我们" + }, + "contacts": { + "message": "联系人" + }, + "contactsSettingsDescription": { + "message": "添加、编辑、删除和管理您的联系人。" }, "continueToWyre": { "message": "继续前往 Wyre" @@ -231,10 +380,10 @@ "message": "交易 ID 复制成功" }, "copyAddress": { - "message": "将地址复制到剪贴板" + "message": "复制地址到剪贴板" }, "copyPrivateKey": { - "message": "这是你的私钥(点击复制)" + "message": "这是您的私钥(点击复制)" }, "copyToClipboard": { "message": "复制到剪贴板" @@ -255,13 +404,19 @@ "message": "创建密码" }, "currencyConversion": { - "message": "货币兑换" + "message": "货币转换" + }, + "currentAccountNotConnected": { + "message": "您的当前账户没有连接" + }, + "currentExtension": { + "message": "当前扩展页" }, "currentLanguage": { "message": "当前语言" }, "customGas": { - "message": "自定义 Gas" + "message": "自定义燃料" }, "customGasSubTitle": { "message": "提升费用可能会缩短处理时间,但不保证绝对有效。" @@ -269,17 +424,43 @@ "customRPC": { "message": "自定义 RPC" }, + "customSpendLimit": { + "message": "自定义消费限额" + }, "customToken": { "message": "自定义代币" }, + "dataBackupFoundInfo": { + "message": "您的部分账户数据已在之前安装的 MetaMask 时备份。其中可能包括您的设置、联系人和代币。您现在想恢复这些数据吗?" + }, "decimal": { - "message": "精确小数点" + "message": "小数精度" }, "decimalsMustZerotoTen": { "message": "小数位最小为0并且不超过36位." }, + "decrypt": { + "message": "解密" + }, + "decryptCopy": { + "message": "复制加密信息" + }, + "decryptInlineError": { + "message": "无法解密此消息,错误:$1", + "description": "$1 is error message" + }, + "decryptMessageNotice": { + "message": "$1 希望阅读此信息来完成您的操作。", + "description": "$1 is the web3 site name" + }, + "decryptMetamask": { + "message": "解密信息" + }, + "decryptRequest": { + "message": "解密请求" + }, "defaultNetwork": { - "message": "默认以太坊交易网络为主网。" + "message": "默认以太坊(Ether)交易网络为主网。" }, "delete": { "message": "删除" @@ -288,10 +469,10 @@ "message": "删除账户" }, "deleteNetwork": { - "message": "是否删除网络?" + "message": "删除网络?" }, "deleteNetworkDescription": { - "message": "您是否确认要删除该网络?" + "message": "是否确认要删除该网络?" }, "depositEther": { "message": "存入 Ether" @@ -303,7 +484,25 @@ "message": "直接存入 Ether" }, "directDepositEtherExplainer": { - "message": "如果你已经有了一些 Ether,通过直接转入是你的新钱包获取 Ether 的最快捷方式。" + "message": "如果您已经有了一些 Ether,最快捷的方法就是直接向新钱包存入 Ether。" + }, + "disconnect": { + "message": "断开" + }, + "disconnectAllAccounts": { + "message": "断开所有账户" + }, + "disconnectAllAccountsConfirmationDescription": { + "message": "您确定要断开连接吗?您可能会失去网站功能。" + }, + "disconnectPrompt": { + "message": "断开 $1" + }, + "disconnectThisAccount": { + "message": "断开此账户的连接" + }, + "dismiss": { + "message": "关闭" }, "done": { "message": "完成" @@ -311,14 +510,17 @@ "dontHaveAHardwareWallet": { "message": "没有硬件钱包?" }, + "dontShowThisAgain": { + "message": "不再显示" + }, "downloadGoogleChrome": { "message": "下载 Google Chrome 浏览器" }, "downloadSecretBackup": { - "message": "下载私密备份密语,并使用外部加密硬盘或存储媒介妥善保管。" + "message": "下载账户助记词,并将其安全保存在外部加密硬盘或存储介质上。" }, "downloadStateLogs": { - "message": "下载日志" + "message": "下载状态日志" }, "dropped": { "message": "丢弃" @@ -329,36 +531,50 @@ "editContact": { "message": "编辑联系人" }, + "editPermission": { + "message": "编辑权限" + }, + "encryptionPublicKeyNotice": { + "message": "$1 希望得到您的加密公钥。同意后该网站将可以想您发送加密信息。", + "description": "$1 is the web3 site name" + }, + "encryptionPublicKeyRequest": { + "message": "申请加密公钥" + }, "endOfFlowMessage1": { - "message": "您已通过测试 - 请妥善保管你的种子密语。这是您的责任!" + "message": "您通过了测试—— 保管好您的账户助记词,这是您的责任!" }, "endOfFlowMessage10": { "message": "全部完成" }, "endOfFlowMessage2": { - "message": "安全保存小技巧" + "message": "安全保存技巧" }, "endOfFlowMessage3": { "message": "在多处保存备份数据。" }, "endOfFlowMessage4": { - "message": "绝不向任何分享该密语。" + "message": "不向任何任何人分享该账户助记词。" }, "endOfFlowMessage5": { - "message": "谨防网络钓鱼!MetaMask 绝不会主动要求您提供个人种子密语。" + "message": "谨防网络钓鱼!MetaMask 绝不会主动要求您提供个人账户助记词。" }, "endOfFlowMessage6": { - "message": "如果您需要再次备份个人种子密语,请通过设置 -> 安全选项完成该操作。" + "message": "如果您需要再次备份账户助记词,请通过设置 -> 安全选项完成该操作。" }, "endOfFlowMessage7": { "message": "如果您仍存有疑问或发现任何可疑的地方,请发送电子邮件至 support@metamask.io 进行咨询。" }, "endOfFlowMessage8": { - "message": "MetaMask 无法恢复您的种子密语。了解更多。" + "message": "MetaMask 无法恢复您的账户助记词。" }, "endOfFlowMessage9": { "message": "了解详情。" }, + "endpointReturnedDifferentChainId": { + "message": "RPC 端点使用链不同的链 ID: $1", + "description": "$1 is the return value of eth_chainId from an RPC endpoint" + }, "ensNotFoundOnCurrentNetwork": { "message": "未在当前网络找到 ENS 名称。请尝试切换至主以太坊网络。" }, @@ -368,20 +584,62 @@ "enterAnAlias": { "message": "输入别名" }, + "enterMaxSpendLimit": { + "message": "输入最高消费额度" + }, "enterPassword": { - "message": "请输入密码" + "message": "输入密码" }, "enterPasswordContinue": { - "message": "请输入密码以继续" + "message": "输入密码以继续" + }, + "errorCode": { + "message": "代码:$1", + "description": "Displayed error code for debugging purposes. $1 is the error code" + }, + "errorDetails": { + "message": "错误详情", + "description": "Title for collapsible section that displays error details for debugging purposes" + }, + "errorMessage": { + "message": "信息:$1", + "description": "Displayed error message for debugging purposes. $1 is the error message" + }, + "errorName": { + "message": "代码:$1", + "description": "Displayed error name for debugging purposes. $1 is the error name" + }, + "errorPageMessage": { + "message": "请重新加载页面重试,或通过 support@metamask.io 联系支持。", + "description": "Message displayed on generic error page in the fullscreen or notification UI" + }, + "errorPagePopupMessage": { + "message": "请关闭并重新打开弹窗再试一次,或通过 support@metamask.io 联系支持。", + "description": "Message displayed on generic error page in the popup UI" + }, + "errorPageTitle": { + "message": "MetaMask 遇到了一个错误", + "description": "Title of generic error page" + }, + "errorStack": { + "message": "栈:", + "description": "Title for error stack, which is displayed for debugging purposes" }, "estimatedProcessingTimes": { - "message": "预估处理时间" + "message": "预计处理时间" + }, + "eth_accounts": { + "message": "查看您允许的账户的地址(必填)", + "description": "The description for the `eth_accounts` permission" }, "ethereumPublicAddress": { - "message": "以太坊公共地址" + "message": "以太坊 Ethereum 公开地址" + }, + "etherscan": { + "message": "Etherscan(以太坊浏览器)" }, "etherscanView": { - "message": "在 Etherscan 上查看账户" + "message": "在 Etherscan(以太坊浏览器)上查看账户" }, "expandView": { "message": "展开视图" @@ -389,12 +647,31 @@ "exportPrivateKey": { "message": "导出私钥" }, + "externalExtension": { + "message": "外部扩展" + }, + "extraApprovalGas": { + "message": "+$1 批准燃料", + "description": "Expresses an additional gas amount the user will have to pay, on top of some other displayed amount. $1 is a decimal amount of gas" + }, "failed": { "message": "失败" }, + "failedToFetchChainId": { + "message": "无法获取链 IC,您的 RPC URL 地址是正确的么?" + }, + "failureMessage": { + "message": "出了点问题,我们无法完成这个操作。" + }, "fast": { "message": "快" }, + "fastest": { + "message": "最快" + }, + "feeAssociatedRequest": { + "message": "此请求需要支付一定的费用。" + }, "fiat": { "message": "FIAT", "description": "Exchange type" @@ -403,47 +680,69 @@ "message": "文件导入失败? 点击这里!", "description": "Helps user import their account from a JSON file" }, + "forbiddenIpfsGateway": { + "message": "禁用的 IPFS 网关:请指定一个 CID 网关" + }, "forgetDevice": { - "message": "取消保存此设备" + "message": "忘记此设备" }, "from": { - "message": "来自" + "message": "从" + }, + "fromAddress": { + "message": "从:$1", + "description": "$1 is the address to include in the From label. It is typically shortened first using shortenAddress" + }, + "functionApprove": { + "message": "功能:同意" }, "functionType": { "message": "功能类型" }, "gasLimit": { - "message": "Gas 上限" + "message": "燃料限制" }, "gasLimitInfoTooltipContent": { - "message": "Gas 上限是您个人希望付出的 Gas 数量上限。" + "message": "燃料限制是指您愿意花费的最燃料量单位。" }, "gasLimitTooLow": { - "message": "Gas 上限至少要 21000" + "message": "燃料限制至少要 21000" + }, + "gasLimitTooLowWithDynamicFee": { + "message": "燃料限制至少要 $1", + "description": "$1 is the custom gas limit, in decimal." }, "gasPrice": { - "message": "Gas 价格 (gwei)" + "message": "燃料价格(GWEI)" }, "gasPriceExtremelyLow": { - "message": "Gas 价格极低" + "message": "燃料价格极低" }, "gasPriceInfoTooltipContent": { - "message": "Gas 价格将详细列明每个付费 Gas 单位的以太币金额。" + "message": "燃料价格规定了您愿意为每单位燃料支付的 Ether 数量。" }, "gasUsed": { - "message": "已使用 Gas 量" + "message": "燃料使用" + }, + "gdprMessage": { + "message": "这些数据是汇总的,因此,根据《GDPR 通用数据保护条例》(EU)2016/679,这些数据是匿名的。有关我们隐私惯例的更多信息,请参见我们的 $1。", + "description": "$1 refers to the gdprMessagePrivacyPolicy message, the translation of which is meant to be used exclusively in the context of gdprMessage" + }, + "gdprMessagePrivacyPolicy": { + "message": "隐私政策", + "description": "this translation is intended to be exclusively used as the replacement for the $1 in the gdprMessage translation" }, "general": { "message": "通用" }, "generalSettingsDescription": { - "message": "货币兑换、主要货币、语言和块状身份头像" + "message": "货币转换、主要价格单位、语言和 Blockies Identicon 图标头像" }, "getEther": { "message": "获取 Ether" }, "getEtherFromFaucet": { - "message": "从水管获取$1网络的 Ether", + "message": "从水管获取 $1 网络的 Ether", "description": "Displays network name for Ether faucet" }, "getHelp": { @@ -456,19 +755,19 @@ "message": "Goerli 测试网络" }, "happyToSeeYou": { - "message": "我们很高兴与您见面。" + "message": "我们很高兴见到您。" }, "hardware": { "message": "硬件" }, "hardwareWalletConnected": { - "message": "已连接硬件钱包" + "message": "已连接的硬件钱包" }, "hardwareWallets": { "message": "连接硬件钱包" }, "hardwareWalletsMsg": { - "message": "请选择希望用于 MetaMask 的硬件钱包" + "message": "选择希望用于 MetaMask 的硬件钱包" }, "havingTroubleConnecting": { "message": "连接出现问题?" @@ -486,6 +785,10 @@ "hideTokenPrompt": { "message": "隐藏代币?" }, + "hideTokenSymbol": { + "message": "隐藏 $1", + "description": "$1 is the symbol for a token (e.g. 'DAI')" + }, "history": { "message": "历史记录" }, @@ -496,17 +799,20 @@ "importAccount": { "message": "导入账户" }, + "importAccountMsg": { + "message": "导入的账户将不会与最初创建的 MetaMask 账户助记词相关联。了解更多有关导入账户的信息 。" + }, "importAccountSeedPhrase": { - "message": "使用种子密语导入账户" + "message": "使用账户助记词导入账户" }, "importUsingSeed": { - "message": "使用帐号种子密语导入" + "message": "使用账户助记词导入" }, "importWallet": { "message": "导入钱包" }, "importYourExisting": { - "message": "请使用 12 字种子密语导入现有钱包" + "message": "使用 12 个单词的账户助记词导入您现有的钱包账户。" }, "imported": { "message": "已导入", @@ -516,56 +822,100 @@ "message": "信息 & 帮助" }, "initialTransactionConfirmed": { - "message": "您的首次交易已通过网络完成确认。请点击“确定”返回。" + "message": "您的初始交易已通过网络确认。请点击“确定”返回。" }, "insufficientBalance": { "message": "余额不足。" }, "insufficientFunds": { - "message": "余额不足." + "message": "余额不足。" }, "insufficientTokens": { - "message": "代币余额不足." + "message": "代币余额不足。" }, "invalidAddress": { "message": "无效地址" }, "invalidAddressRecipient": { - "message": "收款地址不合法" + "message": "接收方地址无效" }, "invalidAddressRecipientNotEthNetwork": { - "message": "非 ETH 网络,设置为小写" + "message": "非 ETH 网络,请使用小写" }, "invalidBlockExplorerURL": { - "message": "无效 Block Explorer URI" + "message": "无效的区块浏览器 URL" + }, + "invalidChainIdTooBig": { + "message": "无效的链 ID,该链 ID 数字过大。" + }, + "invalidCustomNetworkAlertContent1": { + "message": "需要重新输入自定义网络'$1'的链 ID。", + "description": "$1 is the name/identifier of the network." + }, + "invalidCustomNetworkAlertContent2": { + "message": "为了保护您免受恶意或有问题的网络提供商的侵害,现在所有的自定义网络都需要提供链 ID。" + }, + "invalidCustomNetworkAlertContent3": { + "message": "进入设置 > 网络并输入链 ID。您可以通过 $1 查找常用的链 ID。", + "description": "$1 is a link to https://chainid.network" + }, + "invalidCustomNetworkAlertTitle": { + "message": "无效的自定义网络" + }, + "invalidHexNumber": { + "message": "无效的十六进制数。" + }, + "invalidHexNumberLeadingZeros": { + "message": "无效的十六进制数。去除任何开头的零。" + }, + "invalidIpfsGateway": { + "message": "无效的 IPFS 网关。该值必须是一个有效的 URL" + }, + "invalidNumber": { + "message": "无效的数字。输入一个数字或‘0x’开头的十六进制数。" + }, + "invalidNumberLeadingZeros": { + "message": "无效的数字。去除任何开头的零。" }, "invalidRPC": { - "message": "无效 RPC URI" + "message": "无效 RPC URL" }, "invalidSeedPhrase": { - "message": "无效种子密语" + "message": "无效的账户助记词" + }, + "ipfsGateway": { + "message": "IPFS 网关" + }, + "ipfsGatewayDescription": { + "message": "输入用于 ENS 内容解析的 IPFS CID 网关的 URL。" }, "jsonFile": { "message": "JSON 文件", "description": "format for importing an account" }, "knownAddressRecipient": { - "message": "已知联系人地址。" + "message": "已知接收方地址。" + }, + "knownTokenWarning": { + "message": "此操作将编辑已经在您的钱包中列出的代币,有肯能被用来欺骗您。只有确定要更改这些代币的内容时,才通过此操作。" }, "kovan": { "message": "Kovan 测试网络" }, + "lastConnected": { + "message": "最后连接" + }, "learnMore": { - "message": "查看更多." + "message": "查看更多" }, "ledgerAccountRestriction": { - "message": "请在新增账户前,确认添加上一个账户。" + "message": "在添加新的账户之前,需要使用您的最后一个账户。" }, "letsGoSetUp": { - "message": "是的。立即开始设置!" + "message": "第一次,立即开始设置!" }, "likeToAddTokens": { - "message": "你想添加这些代币吗?" + "message": "您想添加这些代币吗?" }, "links": { "message": "链接" @@ -574,57 +924,115 @@ "message": "加载更多" }, "loading": { - "message": "加载中..." + "message": "加载中……" }, "loadingTokens": { - "message": "加载代币中..." + "message": "加载代币中……" + }, + "localhost": { + "message": "Localhost 8545" }, "lock": { "message": "锁定" }, + "lockTimeTooGreat": { + "message": "锁定时间过长" + }, "mainnet": { - "message": "以太坊主网络" + "message": "以太坊 Ethereum 主网络" }, "max": { "message": "最大" }, "memo": { - "message": "备忘录" + "message": "备忘" }, "memorizePhrase": { - "message": "记住该密语。" + "message": "记住该账户助记词。" }, "message": { "message": "消息" }, + "metaMaskConnectStatusParagraphOne": { + "message": "现在您可在 MetaMask 中对账户连接进行更多的控制。" + }, + "metaMaskConnectStatusParagraphThree": { + "message": "点击管理连接的账户。" + }, + "metaMaskConnectStatusParagraphTwo": { + "message": "连接状态按钮显示所访问的网站是否与您当前选择的账户连接。" + }, "metamaskDescription": { - "message": "MetaMask is a secure identity vault for Ethereum." + "message": "将您与 Ethereum 和去中心化网络连接起来。" + }, + "metamaskSwapsOfflineDescription": { + "message": "MetaMask Swaps 正在进行维护。请稍后访问。" }, "metamaskVersion": { "message": "MetaMask 版本" }, + "metametricsCommitmentsAllowOptOut": { + "message": "始终允许您通过设置选择退出" + }, + "metametricsCommitmentsBoldNever": { + "message": "从不", + "description": "This string is localized separately from some of the commitments so that we can bold it" + }, + "metametricsCommitmentsIntro": { + "message": "MetaMask……" + }, + "metametricsCommitmentsNeverCollectIP": { + "message": "$1收集您的完整IP地址", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverCollectKeysEtc": { + "message": "$1收集密钥、地址、交易记录、余额、哈希或任何个人信息", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsNeverSellDataForProfit": { + "message": "$1为利益而出售您的数据,永远不会!", + "description": "The $1 is the bolded word 'Never', from 'metametricsCommitmentsBoldNever'" + }, + "metametricsCommitmentsSendAnonymizedEvents": { + "message": "发送匿名的点击和页面浏览事件信息" + }, + "metametricsHelpImproveMetaMask": { + "message": "帮助我们让 MetaMask 变得更好" + }, + "metametricsOptInDescription": { + "message": "MetaMask 希望收集使用数据,以更好地了解我们的用户如何与扩展进行互动。这些数据将被用于持续改进我们产品和 Ethereum 生态系统的可用性和用户体验。" + }, "mobileSyncText": { "message": "请输入密码确认个人身份!" }, "mustSelectOne": { - "message": "至少选择一种代币." + "message": "至少选择 1 种代币。" + }, + "myAccounts": { + "message": "我的账户" }, "myWalletAccounts": { "message": "我的钱包账户" }, "myWalletAccountsDescription": { - "message": "所有已创建的 MetaMask 账户将自动添加到该部分。" + "message": "所有创建的 MetaMask 账户将自动添加到此部分。" }, "needEtherInWallet": { - "message": "使用 MetaMask 与 DAPP 交互,需要你的钱包里有 Ether。" + "message": "使用 MetaMask 与分布式应用交互,需要您的钱包里需要有 Ether。" }, "needImportFile": { - "message": "必须选择导入一个文件。", + "message": "必须选择一个文件来导入。", "description": "User is important an account and needs to add a file to continue" }, + "negativeETH": { + "message": "不能发负值的 ETH。" + }, "networkName": { "message": "网络名称" }, + "networkSettingsChainIdDescription": { + "message": "链 ID 用于签署交易。它必须与网络返回的链 ID 相匹配。您可以输入十进制或'0x'前缀的十六进制数字,但我们将以十进制显示。" + }, "networkSettingsDescription": { "message": "添加和编辑自定义 RPC 网络" }, @@ -638,14 +1046,14 @@ "message": "新账户" }, "newAccountDetectedDialogMessage": { - "message": "检测到新地址!请点击此处添加至您的地址簿。" + "message": "检测到新地址!点击添加至地址簿。" }, "newAccountNumberName": { "message": "账户 $1", "description": "Default name of next account to be created on create account screen" }, "newContact": { - "message": "新增联系人" + "message": "新联系人" }, "newContract": { "message": "新合约" @@ -657,37 +1065,59 @@ "message": "新密码(至少 8 个字符)" }, "newToMetaMask": { - "message": "新增至 MetaMask?" + "message": "第一次使用 MetaMask?" }, "newTotal": { - "message": "新增合计" + "message": "新总额" }, "newTransactionFee": { - "message": "新增交易费用" + "message": "新交易费用" }, "next": { "message": "下一步" }, + "nextNonceWarning": { + "message": "Nonce 高于建议的 nouce 值 $1", + "description": "The next nonce according to MetaMask's internal logic" + }, + "noAccountsFound": { + "message": "没找到查询的账户" + }, "noAddressForName": { - "message": "此 ENS 名字还没有指定地址。" + "message": "这个名字还没有设置地址。" }, "noAlreadyHaveSeed": { - "message": "不,我已经有一个种子密语了。" + "message": "不,我已经有一个账户助记词了。" }, "noConversionRateAvailable": { - "message": "无可用兑换率" + "message": "无可用转换率" + }, + "noThanks": { + "message": "不,谢谢" }, "noTransactions": { "message": "没有交易" }, "noWebcamFound": { - "message": "找不到您的个人电脑网络摄像头,请重试。" + "message": "未找到您的电脑摄像头。请重试。" }, "noWebcamFoundTitle": { - "message": "未找到网络摄像头" + "message": "未找到摄像头" + }, + "nonceField": { + "message": "自定义交易 nonce" + }, + "nonceFieldDescription": { + "message": "开启此功能可以改变确认屏幕上的 nonce(交易号)。此为高级功能,请谨慎使用。" + }, + "nonceFieldHeading": { + "message": "自定义 Nonce" + }, + "notCurrentAccount": { + "message": "这是正确的账户吗?这与您钱包中当前选择的账户不同。" }, "notEnoughGas": { - "message": "Gas 不足" + "message": "燃料不足" }, "ofTextNofM": { "message": "/" @@ -695,14 +1125,30 @@ "off": { "message": "关" }, + "offlineForMaintenance": { + "message": "脱机维护" + }, "ok": { - "message": "确认" + "message": "确定" }, "on": { "message": "启用" }, + "onboardingReturnNotice": { + "message": "“$1”会关闭此标签,直接回到 $2", + "description": "Return the user to the site that initiated onboarding" + }, + "onlyAddTrustedNetworks": { + "message": "恶意的 Ethereum 以太坊网络提供商可以伪造区块链状态,并记录您的网络活动。只添加您信任的自定义网络。" + }, + "onlyAvailableOnMainnet": { + "message": "仅在主网(mainnet)上提供" + }, + "onlyConnectTrust": { + "message": "只连接您信任的网站。" + }, "optionalBlockExplorerUrl": { - "message": "屏蔽管理器 URL(选填)" + "message": "区块浏览器 URL(选填)" }, "optionalCurrencySymbol": { "message": "符号(选填)" @@ -732,15 +1178,28 @@ "message": "密码不匹配" }, "pastePrivateKey": { - "message": "请粘贴你的私钥:", + "message": "请粘贴您的私钥:", "description": "For importing an account from a private key" }, "pending": { "message": "待处理" }, + "permissionCheckedIconDescription": { + "message": "您已同意该权限" + }, + "permissionUncheckedIconDescription": { + "message": "您还未同意该权限" + }, + "permissions": { + "message": "权限" + }, "personalAddressDetected": { "message": "检测到个人地址。请输入代币合约地址。" }, + "plusXMore": { + "message": "+ $1", + "description": "$1 is a number of additional but unshown items in a list- this message will be shown in place of those items" + }, "prev": { "message": "上一个" }, @@ -748,7 +1207,7 @@ "message": "主要货币" }, "primaryCurrencySettingDescription": { - "message": "请选择“本地”,优先显示当地货币链价值(如 ETH )。请选择“法定”,优先显示选定法定货币价值。" + "message": "请选择“本地”,优先显示当地货币链价值(如 ETH )。选择“货币”则优先以所选货币作为价值显示单位。" }, "privacyMsg": { "message": "隐私政策" @@ -758,29 +1217,41 @@ "description": "select this type of file to use to import an account" }, "privateKeyWarning": { - "message": "注意:永远不要公开这个私钥。任何拥有你的私钥的人都可以窃取你帐户中的任何资产。" + "message": "注意:永远不要公开这个私钥。任何拥有您的私钥的人都可以窃取您帐户中的任何资产。" }, "privateNetwork": { "message": "私有网络" }, + "proposedApprovalLimit": { + "message": "拟议的审批上限" + }, "protectYourKeys": { "message": "妥善保管您的密钥!" }, "protectYourKeysMessage1": { - "message": "请注意个人种子密语安全。报告显示有多个网站企图伪造 MetaMask。MetaMask 绝不会要求您提供个人种子密语!" + "message": "请注意个人账户助记词的安全。报告显示有多个网站企图伪造 MetaMask。MetaMask 绝不会要求您提供个人账户助记词!" }, "protectYourKeysMessage2": { - "message": "请妥善保管您的密语。如果您发现任何可疑的地方,或无法确认网络安全性,请发送电子邮件至 support@metamask.io 进行咨询" + "message": "请妥善保管您的账户助记词。如果您发现任何可疑的地方,或无法确认网络安全性,请发送电子邮件至 support@metamask.io 进行咨询" + }, + "provide": { + "message": "提供" }, "queue": { "message": "队列" }, + "queued": { + "message": "队列中" + }, "readdToken": { - "message": "之后你还可以通过帐户选项菜单中的“添加代币”来添加此代币。" + "message": "之后您还可以通过帐户选项菜单中的“添加代币”来添加此代币。" }, "readyToConnect": { "message": "是否准备连接?" }, + "receive": { + "message": "接收" + }, "recents": { "message": "最近记录" }, @@ -794,10 +1265,10 @@ "message": "拒绝" }, "rejectAll": { - "message": "拒绝所有" + "message": "拒绝全部" }, "rejectTxsDescription": { - "message": "您将指拒绝 $1 笔交易。" + "message": "您将批量拒绝 $1 笔交易。" }, "rejectTxsN": { "message": "拒绝 $1 笔交易" @@ -809,16 +1280,16 @@ "message": "稍后提醒" }, "remove": { - "message": "移除" + "message": "删除" }, "removeAccount": { - "message": "移除帐号" + "message": "删除账户" }, "removeAccountDescription": { - "message": "该账户已从您的钱包中删除。请在继续后续操作前,确认您是否已拥有该导入账户的原始种子密语或个人密钥。您可以通过账户下拉菜单再次导入或创建账户。" + "message": "该账户已从您的钱包中删除。请在继续后续操作前,确认您是否已拥有该导入账户的原始账户助记词或账户密钥。您可以通过账户下拉菜单再次导入或创建账户。" }, "requestsAwaitingAcknowledgement": { - "message": "等待确认的请求" + "message": "待确认的请求" }, "required": { "message": "必填" @@ -830,31 +1301,41 @@ "message": "重设账户" }, "resetAccountDescription": { - "message": "重置账户后,将清除您的个人交易历史记录。" + "message": "重置账户将清除您的交易历史记录。这不会改变您账户中的余额,也不会要求您重新输入账户助记词。" }, "restore": { "message": "恢复" }, "restoreAccountWithSeed": { - "message": "使用种子密语恢复个人账户" + "message": "使用账户助记词恢复您的账户" }, "restoreFromSeed": { "message": "从助记词还原" }, + "restoreWalletPreferences": { + "message": "已找到于 $1 的数据备份。您想恢复您的钱包设置吗?", + "description": "$1 is the date at which the data was backed up" + }, + "retryTransaction": { + "message": "重试交易" + }, + "reusedTokenNameWarning": { + "message": "此处的一个代币使用了与您关注的另一个代币的相同符号,这可能会让人感到困惑或欺骗。" + }, "revealSeedWords": { - "message": "显示助记词" + "message": "显示账户助记词" }, "revealSeedWordsDescription": { - "message": "如果您更换浏览器或计算机,则需要使用此助记词访问您的帐户。请将它们保存在安全秘密的地方。" + "message": "如果您更换浏览器或计算机,则需要使用此账户助记词访问您的帐户。请将它们保存在安全秘密的地方。" }, "revealSeedWordsTitle": { - "message": "助记词" + "message": "账户助记词" }, "revealSeedWordsWarning": { - "message": "助记词可以用来窃取您的所有帐户." + "message": "该账户助记词可以用来窃取您的所有帐户" }, "revealSeedWordsWarningTitle": { - "message": "不要对任何人展示助记词!" + "message": "不要对任何人展示此账户助记词!" }, "rinkeby": { "message": "Rinkeby 测试网络" @@ -869,17 +1350,23 @@ "message": "保存" }, "saveAsCsvFile": { - "message": "另存为CSV文件" + "message": "保存为 CSV 文件" }, "scanInstructions": { - "message": "请将二维码置于镜头前" + "message": "将二维码放在相机前" }, "scanQrCode": { "message": "扫描二维码" }, + "scrollDown": { + "message": "向下滚动" + }, "search": { "message": "搜索" }, + "searchAccounts": { + "message": "搜索账户" + }, "searchResults": { "message": "搜索结果" }, @@ -887,70 +1374,80 @@ "message": "搜索代币" }, "secretBackupPhrase": { - "message": "私密备份密语" + "message": "账户助记词" }, "secretBackupPhraseDescription": { - "message": "您的个人私密备份密语可以帮助您轻松备份和恢复个人账户。" + "message": "您的账户助记词可以帮助您轻松备份和恢复个人账户。" }, "secretBackupPhraseWarning": { - "message": "警告:切勿向他人透露您的备份密语。任何人一旦持有该密语,即可取走您的以太币。" + "message": "警告:切勿向他人透露您的账户助记词。任何人一旦持有该账户助记词,即可控制您的 Ether。" }, "secretPhrase": { - "message": "输入12位助记词以恢复金库." + "message": "输入 12 个单词组成的账户助记词恢复您的账户。" }, "securityAndPrivacy": { "message": "安全与隐私" }, "securitySettingsDescription": { - "message": "隐私设置和钱包种子密语" + "message": "隐私设置和账户助记词" }, "seedPhrasePlaceholder": { "message": "用空格分隔每个单词" }, + "seedPhrasePlaceholderPaste": { + "message": "从剪贴板粘贴账户助记词" + }, "seedPhraseReq": { - "message": "助记词为12个单词" + "message": "账户助记词由 12、15、18、21 或 24 个单词组成" }, "selectAHigherGasFee": { - "message": "请选择价格稍高的 Gas 费,以加快交易处理速度。*" + "message": "选择更高的燃料费用,提高交易处理速度。*" }, - "selectAnAccount": { + "selectAccounts": { "message": "选择账户" }, - "selectAnAccountHelp": { - "message": "请通过 MetaMask 选择需要查看的账户" + "selectAll": { + "message": "全部选择" }, - "selectCurrency": { - "message": "选择货币" + "selectAnAccount": { + "message": "选择一个账户" + }, + "selectAnAccountHelp": { + "message": "选择在 MetaMask 中查看的账户" }, "selectEachPhrase": { - "message": "请选择每一个单词,以确保单词正确性。" + "message": "请选择每个单词,以确保其正确性。" }, "selectHdPath": { "message": "选择 HD 路径" }, - "selectLocale": { - "message": "选择语言区域" - }, "selectPathHelp": { "message": "如果下列账户中没有您当前所持有的 Ledger 账户,请将路径切换至“Legacy (MEW / MyCrypto)”" }, "selectType": { "message": "选择类型" }, + "selectingAllWillAllow": { + "message": "选择全部将允许本网站查看您当前的所有账户。确保您信任这个网站。" + }, "send": { "message": "发送" }, "sendAmount": { - "message": "发送金额" + "message": "发送数额" }, "sendETH": { "message": "发送 ETH" }, + "sendSpecifiedTokens": { + "message": "发送 $1", + "description": "Symbol of the specified token" + }, "sendTokens": { "message": "发送代币" }, "sentEther": { - "message": "以太币已发送" + "message": "发送 Ether" }, "separateEachWord": { "message": "用空格分隔每个单词" @@ -959,10 +1456,10 @@ "message": "设置" }, "showAdvancedGasInline": { - "message": "高级 Gas 控制" + "message": "高级燃料控制" }, "showAdvancedGasInlineDescription": { - "message": "请选择该选项,直接在发送和确认页面显示 Gas 价格和限制管理。" + "message": "在发送和确认界面显示燃料价格和燃料限制设置选项。" }, "showFiatConversionInTestnets": { "message": "在 Testnets 上显示兑换率" @@ -976,9 +1473,21 @@ "showHexDataDescription": { "message": "请选择该选项,在发送页面显示十六进制数据字域" }, + "showIncomingTransactions": { + "message": "显示收到的交易" + }, + "showIncomingTransactionsDescription": { + "message": "选择该选项可使用 Etherscan(以太坊浏览器)(以太坊浏览器)在交易列表中显示收到的交易。" + }, + "showPermissions": { + "message": "显示权限" + }, "showPrivateKeys": { "message": "显示私钥" }, + "showSeedPhrase": { + "message": "显示账户助记词" + }, "sigRequest": { "message": "请求签名" }, @@ -986,11 +1495,14 @@ "message": "签名" }, "signNotice": { - "message": "签署此消息可能会产生危险的副作用。 \n只从你完全信任的网站上签名。 未来的版本将移除这种危险的方法。" + "message": "签署此消息可能会产生危险的副作用。 \n只从您完全信任的网站上签名。 未来的版本将移除这种危险的方法。" }, "signatureRequest": { "message": "请求签名" }, + "signatureRequest1": { + "message": "信息" + }, "signed": { "message": "已签名" }, @@ -998,7 +1510,7 @@ "message": "慢" }, "somethingWentWrong": { - "message": "哎呀!出问题了。" + "message": "糟糕!出问题了。" }, "speedUp": { "message": "加速" @@ -1009,35 +1521,66 @@ "speedUpTransaction": { "message": "加速该交易操作" }, + "spendLimitAmount": { + "message": "消费限额数量" + }, + "spendLimitInsufficient": { + "message": "消费限额不足" + }, + "spendLimitInvalid": { + "message": "消费限制无效,必须是正数。" + }, + "spendLimitPermission": { + "message": "消费限制权限" + }, + "spendLimitRequestedBy": { + "message": "消费限制申请来自 $1", + "description": "Origin of the site requesting the spend limit" + }, + "spendLimitTooLarge": { + "message": "消费限制过大" + }, "stateLogError": { "message": "检索状态日志时出错。" }, + "stateLogFileName": { + "message": "MetaMask 状态日志" + }, "stateLogs": { "message": "状态日志" }, "stateLogsDescription": { "message": "状态日志包含您的账户地址和已发送的交易。" }, + "statusConnected": { + "message": "已连接" + }, + "statusNotConnected": { + "message": "未连接" + }, "step1HardwareWallet": { "message": "1. 连接硬件钱包" }, "step1HardwareWalletMsg": { - "message": "直接将您的硬件钱包与个人电脑相连。" + "message": "将您的硬件钱包直接连接到电脑上。" }, "step2HardwareWallet": { "message": "2. 选择账户" }, "step2HardwareWalletMsg": { - "message": "请选择您想查看的账户。每次仅限选择一个。" + "message": "请选择您想查看的账户。每次只能选择一个账户。" }, "step3HardwareWallet": { - "message": "3. 开始体验 dApps 和更多功能!" + "message": "3. 开始使用 web3 站点和更多功能!" }, "step3HardwareWalletMsg": { - "message": "使用您的硬件钱包,操作与以太坊账户制作相同。登录 dApps,发送 ETH ,购买和保存 ERC20 代币和非同质化代币如 CryptoKitties。" + "message": "使用您的硬件钱包,操作与以太坊账户制作相同。登录 dApps,发送 ETH ,购买和保存 ERC20 代币和诸如 CryptoKitties 等不可替代代币。" }, "storePhrase": { - "message": "通过如 1Password 等密码管家保存该密语。" + "message": "通过如 1Password 等密码管理工具保存该账户助记词。" + }, + "submit": { + "message": "提交" }, "submitted": { "message": "已提交" @@ -1045,20 +1588,300 @@ "supportCenter": { "message": "访问我们的支持中心" }, + "swap": { + "message": "兑换 Swap" + }, + "swapAdvancedSlippageInfo": { + "message": "如果价格在您下单和确认之间发生变化,这就叫做“滑点”。如果滑点超过您的“最大滑点”设置,您的的兑换将自动取消。" + }, + "swapAggregator": { + "message": "聚合商" + }, + "swapAmountReceived": { + "message": "保证数额" + }, + "swapAmountReceivedInfo": { + "message": "这是您将收到的最低数额。根据滑点值, 您可能会收到更多。" + }, + "swapApproval": { + "message": "批准 $1 的兑换 ", + "description": "Used in the transaction display list to describe a transaction that is an approve call on a token that is to be swapped.. $1 is the symbol of a token that has been approved." + }, + "swapApproveNeedMoreTokens": { + "message": "您还需 $1 $2 来完成这笔兑换", + "description": "Tells the user how many more of a given token they need for a specific swap. $1 is an amount of tokens and $2 is the token symbol." + }, + "swapBetterQuoteAvailable": { + "message": "有一个可用的更优报价" + }, + "swapBuildQuotePlaceHolderText": { + "message": "没有匹配的代币符合 $1", + "description": "Tells the user that a given search string does not match any tokens in our token lists. $1 can be any string of text" + }, + "swapCheckingQuote": { + "message": "正在检查 $1", + "description": "Shown to the user during quote loading. $1 is the name of an aggregator. The message indicates that metamask is currently checking if that aggregator has a trade/quote for their requested swap." + }, + "swapCustom": { + "message": "自定义" + }, + "swapDecentralizedExchange": { + "message": "去中心化交易所" + }, + "swapEditLimit": { + "message": "修改限制" + }, + "swapEnableDescription": { + "message": "这是必须的,并且允许 MetaMask 兑换您的 $1。", + "description": "Gives the user info about the required approval transaction for swaps. $1 will be the symbol of a token being approved for swaps." + }, + "swapEstimatedNetworkFee": { + "message": "预计网络手续费" + }, + "swapEstimatedNetworkFeeSummary": { + "message": "“$1”是我们预计的实际产生费用。具体数额视网络情况而定。", + "description": "$1 will be the translation of swapEstimatedNetworkFee, with the font bolded" + }, + "swapEstimatedNetworkFees": { + "message": "预计网络手续费" + }, + "swapEstimatedNetworkFeesInfo": { + "message": "这是预估的用于完成您的兑换所使用的网络手续费。实际数额可能会根据网络条件而变化。" + }, + "swapFailedErrorTitle": { + "message": "兑换失败" + }, + "swapFetchingQuotesErrorDescription": { + "message": "呃……出错了。再试一次,如果错误仍存在,请联系客户支持。" + }, + "swapFetchingQuotesErrorTitle": { + "message": "获取报价出错" + }, + "swapFetchingTokens": { + "message": "获取代币中……" + }, + "swapFinalizing": { + "message": "确定中……" + }, + "swapHighSlippageWarning": { + "message": "滑点数量非常大。确保您知道您的操作!" + }, + "swapIntroLearnMoreHeader": { + "message": "想了解更多信息?" + }, + "swapIntroLearnMoreLink": { + "message": "了解更多关于 MetaMask Swap(兑换)" + }, + "swapIntroLiquiditySourcesLabel": { + "message": "流动资金来源包括:" + }, + "swapIntroPopupSubTitle": { + "message": "现在您可以直接在 MetaMask 钱包中兑换代币。MetaMask Swaps(兑换)结合了多个去中心化交易所聚合商、专业做市商和个人 DEX,确保 MetaMask 用户始终以最低的网络费用获得最佳价格。" + }, + "swapIntroPopupTitle": { + "message": "代币兑换来了!" + }, + "swapLearnMoreContractsAuditReview": { + "message": "查看我们的官方合约审计" + }, + "swapLowSlippageError": { + "message": "交易可能失败,最大滑点过低。" + }, + "swapMaxNetworkFeeInfo": { + "message": "“$1”是您最多所话费的数量,当网络不稳定时,这可能是一个大的数额。", + "description": "$1 will be the translation of swapMaxNetworkFees, with the font bolded" + }, + "swapMaxNetworkFees": { + "message": "最大网络手续费" + }, + "swapMaxSlippage": { + "message": "最大滑点" + }, + "swapMetaMaskFee": { + "message": "MetaMask 手续费" + }, + "swapMetaMaskFeeDescription": { + "message": "我们每次都能从顶级流动性资源中找到最好的价格。每次报价都会自动收取1%的手续费用,以支持 MetaMask 的持续发展,使其更加完善。", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapNQuotes": { + "message": "$1 个报价", + "description": "$1 is the number of quotes that the user can select from when opening the list of quotes on the 'view quote' screen" + }, + "swapNetworkFeeSummary": { + "message": "网络手续费包括处理您的兑换和在以太坊(Ethereum)网络上存储的成本。MetaMask 不从这笔费用中获利。" + }, + "swapNewQuoteIn": { + "message": "$1 后更新报价", + "description": "Tells the user the amount of time until the currently displayed quotes are update. $1 is a time that is counting down from 1:00 to 0:00" + }, + "swapOnceTransactionHasProcess": { + "message": "一旦交易完成,您的 $1 将被添加到您的账户中。", + "description": "This message communicates the token that is being transferred. It is shown on the awaiting swap screen. The $1 will be a token symbol." + }, + "swapPriceDifference": { + "message": "您将兑换 $1 $2(~$3)为 $4 $5(~$6)。", + "description": "This message represents the price slippage for the swap. $1 and $4 are a number (ex: 2.89), $2 and $5 are symbols (ex: ETH), and $3 and $6 are fiat currency amounts." + }, + "swapPriceDifferenceTitle": { + "message": "价格差异 ~$1%", + "description": "$1 is a number (ex: 1.23) that represents the price difference." + }, + "swapPriceDifferenceTooltip": { + "message": "市场价格的差异可能受到中介机构收取的费用、市场规模、交易规模或市场效率低下的影响。" + }, + "swapPriceDifferenceUnavailable": { + "message": "市场价格不可用。 请确认您对退回的数额感到满意后再继续。" + }, + "swapProcessing": { + "message": "处理中" + }, + "swapQuoteDetails": { + "message": "报价详情" + }, + "swapQuoteDetailsSlippageInfo": { + "message": "如果在您下订单和确认订单之间的价格发生了变化,这就叫做\"滑点\"。如果滑点超过您的\"最大滑点\"设置,您的兑换将自动取消。" + }, + "swapQuoteIncludesRate": { + "message": "报价包含 $1% MetaMask 手续费", + "description": "Provides information about the fee that metamask takes for swaps. $1 is a decimal number." + }, + "swapQuoteNofN": { + "message": "报价 $1 / $2", + "description": "A count of loaded quotes shown to the user while they are waiting for quotes to be fetched. $1 is the number of quotes already loaded, and $2 is the total number of quotes to load." + }, + "swapQuoteSource": { + "message": "报价来源" + }, + "swapQuotesAreRefreshed": { + "message": "报价会经常刷新,以反映当前的市场状况。" + }, + "swapQuotesExpiredErrorDescription": { + "message": "请请求新的报价,以获得最新的价格。" + }, + "swapQuotesExpiredErrorTitle": { + "message": "报价超时" + }, + "swapQuotesNotAvailableErrorDescription": { + "message": "尝试调整滑点数量设置,并再试一次。" + }, + "swapQuotesNotAvailableErrorTitle": { + "message": "无可用报价" + }, + "swapRate": { + "message": "费率" + }, + "swapReceiving": { + "message": "接收" + }, + "swapReceivingInfoTooltip": { + "message": "这是一个预估数额。确切的数额取决于滑点。" + }, + "swapRequestForQuotation": { + "message": "请求报价" + }, + "swapSearchForAToken": { + "message": "搜索代币" + }, + "swapSelect": { + "message": "选择" + }, + "swapSelectAQuote": { + "message": "选择一个报价" + }, + "swapSelectAToken": { + "message": "选择一个代币" + }, + "swapSelectQuotePopoverDescription": { + "message": "以下是从多个流动资金来源收集到的所有报价。" + }, + "swapSlippageTooLow": { + "message": "滑点必须大于零" + }, + "swapSource": { + "message": "流动资金来源" + }, + "swapSourceInfo": { + "message": "我们搜索多个流动性来源(交易所、聚合商和专业做市商),以找到最好的利率和最低的网络手续费。" + }, + "swapStartSwapping": { + "message": "开始兑换" + }, + "swapSwapFrom": { + "message": "兑换自" + }, + "swapSwapSwitch": { + "message": "切换兑换代币方向" + }, + "swapSwapTo": { + "message": "兑换到" + }, + "swapThisWillAllowApprove": { + "message": "这样将允许 $1 用于兑换。" + }, + "swapTokenAvailable": { + "message": "您的 $1 已添加到您的账户。", + "description": "This message is shown after a swap is successful and communicates the exact amount of tokens the user has received for a swap. The $1 is a decimal number of tokens followed by the token symbol." + }, + "swapTokenToToken": { + "message": "兑换 $1 到 $2", + "description": "Used in the transaction display list to describe a swap. $1 and $2 are the symbols of tokens in involved in a swap." + }, + "swapTransactionComplete": { + "message": "交易完成" + }, + "swapUnknown": { + "message": "未知的" + }, + "swapUsingBestQuote": { + "message": "使用最好的报价" + }, + "swapVerifyTokenExplanation": { + "message": "多个代币可以使用相同的名称和符号。检查 Etherscan(以太坊浏览器)以确认这是您正在寻找的代币。" + }, + "swapViewToken": { + "message": "查看 $1" + }, + "swapYourTokenBalance": { + "message": "$1 $2 可用", + "description": "Tells the user how much of a token they have in their balance. $1 is a decimal number amount of tokens, and $2 is a token symbol" + }, + "swapZeroSlippage": { + "message": "0% 滑点" + }, + "swapsAdvancedOptions": { + "message": "高级选项" + }, + "swapsExcessiveSlippageWarning": { + "message": "滑点数额太高,会导致不良率。请将滑点设置降低到 15% 以下。" + }, + "swapsMaxSlippage": { + "message": "最大滑点" + }, + "swapsNotEnoughForTx": { + "message": "没有足够的 $1 来完成此交易", + "description": "Tells the user that they don't have enough of a token for a proposed swap. $1 is a token symbol" + }, + "swapsViewInActivity": { + "message": "在活动中查看" + }, "switchNetworks": { "message": "切换网络" }, + "switchToThisAccount": { + "message": "切换到该账户" + }, "symbol": { "message": "符号" }, "symbolBetweenZeroTwelve": { - "message": "符号不得超过11个字符。" + "message": "符号不得超过 11 个字符。" }, "syncWithMobile": { - "message": "使用移动设备进行同步" + "message": "使用移动设备同步" }, "syncWithMobileBeCareful": { - "message": "扫描编码时,请确保身边无其他人正在查看您的显示页面" + "message": "扫描这个代码时,请确保附近没有其他人在看您的屏幕。" }, "syncWithMobileComplete": { "message": "您的数据已同步成功。尽情体验 MetaMask 应用程序!" @@ -1070,134 +1893,183 @@ "message": "如果您是首次启用 MetaMask 移动应用程序,请通过个人手机完成如下操作。" }, "syncWithMobileScanThisCode": { - "message": "使用 MetaMask 应用程序扫描编码" + "message": "使用 MetaMask 应用程序扫描代码" }, "syncWithMobileTitle": { "message": "使用移动设备进行同步" }, + "syncWithThreeBox": { + "message": "使用 3Box 同步数据(实验功能)" + }, + "syncWithThreeBoxDescription": { + "message": "开启后可以用 3Box 备份您的设置。此功能目前是实验功能,使用时风险自负。" + }, + "syncWithThreeBoxDisabled": { + "message": "由于初始同步过程中出现错误,3Box 已被禁用。" + }, "terms": { "message": "使用条款" }, + "termsOfService": { + "message": "服务条款" + }, "testFaucet": { "message": "测试水管" }, "thisWillCreate": { - "message": "该操作将为您创建新钱包和种子密语" + "message": "将为您创建新的钱包账户和账户助记词" }, "tips": { - "message": "赏金" + "message": "小贴士" }, "to": { "message": "至" }, + "toAddress": { + "message": "至:$1", + "description": "$1 is the address to include in the To label. It is typically shortened first using shortenAddress" + }, + "toWithColon": { + "message": "至:" + }, "token": { "message": "代币" }, "tokenAlreadyAdded": { - "message": "代币已经被添加." + "message": "代币已添加。" }, "tokenContractAddress": { "message": "代币合约地址" }, + "tokenOptions": { + "message": "代币选项" + }, "tokenSymbol": { "message": "代币符号" }, "total": { - "message": "总量" + "message": "总额" }, "transaction": { "message": "交易" }, "transactionCancelAttempted": { - "message": "在 $2 尝试取消交易,其 Gas 费为 $1" + "message": "尝试取消交易 $2,燃料费用:$1。" }, "transactionCancelSuccess": { - "message": "成功在 $2 取消交易单" + "message": "取消交易成功 $2。" }, "transactionConfirmed": { - "message": "交易已通过 $2 确认。" + "message": "交易已确认 $2。" }, "transactionCreated": { - "message": "在 $2 生成的交易单,其交易额为 $1 。" + "message": "交易已创建 $2,交易数额:$1。" }, "transactionDropped": { - "message": "在 $2 终止的交易单。" + "message": "交易终止 $2。" }, "transactionError": { - "message": "交易出错. 合约代码执行异常." + "message": "交易出错。合约代码执行异常。" }, "transactionErrorNoContract": { - "message": "正在尝试调用非联系人地址功能。" + "message": "试图在一个非合约地址上调用一个函数。" }, "transactionErrored": { - "message": "交易报错。" + "message": "交易出现错误。" }, "transactionFee": { "message": "交易费" }, "transactionResubmitted": { - "message": "在 $2 重新提交的交易单,其 Gas 费用增加至 $1" + "message": "重新提交交易 $2,交易费升至:$1。" }, "transactionSubmitted": { - "message": "在 $2 提交的交易单,其 Gas 费用为 $1 。" + "message": "交易已提交 $2,交易费:$1。" }, "transactionUpdated": { - "message": "交易单已于 $2 更新。" + "message": "交易更新时间 $2。" }, "transfer": { "message": "转账" }, "transferBetweenAccounts": { - "message": "在个人账户间转账" + "message": "在我的账户间转账" }, "transferFrom": { - "message": "转出" + "message": "转自" + }, + "troubleConnectingToWallet": { + "message": "我们在连接您的 $1 遇到问题,尝试检查 $2 并重试。", + "description": "$1 is the wallet device name; $2 is a link to wallet connection guide" }, "troubleTokenBalances": { - "message": "我们无法加载您的代币余额。你可以查看它们", + "message": "我们无法加载您的代币余额。您可以查看它们", "description": "Followed by a link (here) to view token balances" }, + "trustSiteApprovePermission": { + "message": "您信任这个网站吗?授权即表示您允许 $1 提取您的 $2,并为您自动进行交易。", + "description": "$1 is the url requesting permission and $2 is the symbol of the currency that the request is for" + }, "tryAgain": { "message": "重试" }, "typePassword": { - "message": "输入你的密码" + "message": "输入您的 MetaMask 密码" }, "unapproved": { "message": "未批准" }, "units": { - "message": "单位" + "message": "数量" }, "unknown": { "message": "未知" }, "unknownCameraError": { - "message": "尝试获取相机使用权限时报错。请重试…" + "message": "尝试获取相机使用权限时报错。请重试……" }, "unknownCameraErrorTitle": { - "message": "哎呀!出问题了…" + "message": "哎呀!出问题了……" }, "unknownNetwork": { - "message": "未知私有网络" + "message": "未知的私有网络" }, "unknownQrCode": { - "message": "错误:我们无法识别该二维码" + "message": "错误:无法识别该二维码" + }, + "unlimited": { + "message": "无限制" }, "unlock": { "message": "解锁" }, "unlockMessage": { - "message": "分散网络待命中" + "message": "即将进入去中心化网络" }, "updatedWithDate": { "message": "已更新 $1" }, + "urlErrorMsg": { + "message": "URL 需要相应的 HTTP/HTTPS 前缀。" + }, + "urlExistsErrorMsg": { + "message": "URL 已经存在于现有的网络列表中" + }, + "usePhishingDetection": { + "message": "使用网络钓鱼检测" + }, + "usePhishingDetectionDescription": { + "message": "显示针对 Ethereum 用户钓鱼域名的警告。" + }, "usedByClients": { "message": "可用于各种不同的客户端" }, "userName": { - "message": "用户名" + "message": "名称" + }, + "verifyThisTokenOn": { + "message": "在 $1 上验证此代币", + "description": "Points the user to etherscan as a place they can verify information about a token. $1 is replaced with the translation for \"etherscan\"" }, "viewAccount": { "message": "查看账户" @@ -1209,39 +2081,53 @@ "message": "在 $1 查看" }, "viewOnEtherscan": { - "message": "在 Etherscan 上查看" + "message": "在 Etherscan(以太坊浏览器)上查看" }, "viewinExplorer": { - "message": "在管理器中查看" + "message": "在浏览器中查看" }, "visitWebSite": { "message": "访问我们的网站" }, + "walletConnectionGuide": { + "message": "我们的硬件钱包连接指南" + }, "walletSeed": { - "message": "钱包助记词" + "message": "账户助记词" + }, + "web3ShimUsageNotification": { + "message": "我们发现当前的网站尝试使用已经删除的 window.web3 API。如果这个网站网站已经无法正常使用,请点击 $1 获取更多信息。", + "description": "$1 is a clickable link." }, "welcome": { - "message": "欢迎使用 MetaMask 测试版" + "message": "欢迎使用 MetaMask" }, "welcomeBack": { "message": "欢迎回来!" }, + "whatsThis": { + "message": "这是什么?" + }, "writePhrase": { - "message": "请将该密语记录在纸上,并保存在安全的地方。如果希望提升信息安全性,请将信息记录在多张纸上,并分别保存在 2 - 3 个不同的地方。" + "message": "请将该账户助记词记录在纸上,并保存在安全的地方。如果希望提升信息安全性,请将信息记录在多张纸上,并分别保存在 2 - 3 个不同的地方。" + }, + "xOfY": { + "message": "$1 / $2", + "description": "$1 and $2 are intended to be two numbers, where $2 is a total, and $1 is a count towards that total" }, "yesLetsTry": { - "message": "没错。不妨一试" + "message": "是的,尝试下" }, "youNeedToAllowCameraAccess": { - "message": "您需要开启相机访问权限,才能使用该功能。" + "message": "需要开启相机访问权限,才能使用该功能。" }, "youSign": { "message": "正在签名" }, "yourPrivateSeedPhrase": { - "message": "你的私有助记词" + "message": "您的账户助记词" }, "zeroGasPriceOnSpeedUpError": { - "message": "Gas 价格加速上涨" + "message": "加速时无燃料价格" } } diff --git a/app/_locales/zh_TW/messages.json b/app/_locales/zh_TW/messages.json index 819e80f22..c62c3677f 100644 --- a/app/_locales/zh_TW/messages.json +++ b/app/_locales/zh_TW/messages.json @@ -922,15 +922,9 @@ "selectAnAccount": { "message": "選擇帳戶" }, - "selectCurrency": { - "message": "選擇幣別" - }, "selectEachPhrase": { "message": "請依照正確順序點選助憶詞" }, - "selectLocale": { - "message": "選擇地區" - }, "selectPathHelp": { "message": "若看不到您已經擁有的 Ledger 帳戶,請嘗試切換路徑為 \"Legacy (MEW / MyCrypto)\"" }, diff --git a/app/manifest/_base.json b/app/manifest/_base.json index 3d2edff7f..2e0a5d625 100644 --- a/app/manifest/_base.json +++ b/app/manifest/_base.json @@ -78,6 +78,6 @@ "notifications" ], "short_name": "__MSG_appName__", - "version": "9.0.5", + "version": "9.1.0", "web_accessible_resources": ["inpage.js", "phishing.html"] } diff --git a/app/scripts/background.js b/app/scripts/background.js index 55a8f5a63..44bcab288 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -32,7 +32,9 @@ import LocalStore from './lib/local-store'; import ReadOnlyNetworkStore from './lib/network-store'; import createStreamSink from './lib/createStreamSink'; import NotificationManager from './lib/notification-manager'; -import MetamaskController from './metamask-controller'; +import MetamaskController, { + METAMASK_CONTROLLER_EVENTS, +} from './metamask-controller'; import rawFirstTimeState from './first-time-state'; import getFirstPreferredLangCode from './lib/get-first-preferred-lang-code'; import getObjStructure from './lib/getObjStructure'; @@ -51,6 +53,7 @@ global.METAMASK_NOTIFIER = notificationManager; let popupIsOpen = false; let notificationIsOpen = false; +let uiIsTriggering = false; const openMetamaskTabsIDs = {}; const requestAccountTabIds = {}; @@ -240,7 +243,9 @@ function setupController(initState, initLangCode) { }); setupEnsIpfsResolver({ - getCurrentNetwork: controller.getCurrentNetwork, + getCurrentChainId: controller.networkController.getCurrentChainId.bind( + controller.networkController, + ), getIpfsGateway: controller.preferencesController.getIpfsGateway.bind( controller.preferencesController, ), @@ -396,14 +401,35 @@ function setupController(initState, initLangCode) { // updateBadge(); - controller.txController.on('update:badge', updateBadge); - controller.messageManager.on('updateBadge', updateBadge); - controller.personalMessageManager.on('updateBadge', updateBadge); - controller.decryptMessageManager.on('updateBadge', updateBadge); - controller.encryptionPublicKeyManager.on('updateBadge', updateBadge); - controller.typedMessageManager.on('updateBadge', updateBadge); + controller.txController.on( + METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE, + updateBadge, + ); + controller.messageManager.on( + METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE, + updateBadge, + ); + controller.personalMessageManager.on( + METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE, + updateBadge, + ); + controller.decryptMessageManager.on( + METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE, + updateBadge, + ); + controller.encryptionPublicKeyManager.on( + METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE, + updateBadge, + ); + controller.typedMessageManager.on( + METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE, + updateBadge, + ); controller.approvalController.subscribe(updateBadge); - controller.appStateController.on('updateBadge', updateBadge); + controller.appStateController.on( + METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE, + updateBadge, + ); /** * Updates the Web Extension's "badge" number, on the little fox in the toolbar. @@ -459,8 +485,17 @@ async function triggerUi() { tabs.length > 0 && tabs[0].extData && tabs[0].extData.indexOf('vivaldi_tab') > -1; - if ((isVivaldi || !popupIsOpen) && !currentlyActiveMetamaskTab) { - await notificationManager.showPopup(); + if ( + !uiIsTriggering && + (isVivaldi || !popupIsOpen) && + !currentlyActiveMetamaskTab + ) { + uiIsTriggering = true; + try { + await notificationManager.showPopup(); + } finally { + uiIsTriggering = false; + } } } diff --git a/app/scripts/controllers/app-state.js b/app/scripts/controllers/app-state.js index 0bf791821..73173bf68 100644 --- a/app/scripts/controllers/app-state.js +++ b/app/scripts/controllers/app-state.js @@ -1,5 +1,6 @@ import EventEmitter from 'events'; import { ObservableStore } from '@metamask/obs-store'; +import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller'; export default class AppStateController extends EventEmitter { /** @@ -74,7 +75,7 @@ export default class AppStateController extends EventEmitter { */ waitForUnlock(resolve, shouldShowUnlockRequest) { this.waitingForUnlock.push({ resolve }); - this.emit('updateBadge'); + this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE); if (shouldShowUnlockRequest) { this._showUnlockRequest(); } @@ -88,7 +89,7 @@ export default class AppStateController extends EventEmitter { while (this.waitingForUnlock.length > 0) { this.waitingForUnlock.shift().resolve(); } - this.emit('updateBadge'); + this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE); } } diff --git a/app/scripts/controllers/ens/index.js b/app/scripts/controllers/ens/index.js index 05d531103..015c3ee0a 100644 --- a/app/scripts/controllers/ens/index.js +++ b/app/scripts/controllers/ens/index.js @@ -2,20 +2,22 @@ import punycode from 'punycode/punycode'; import ethUtil from 'ethereumjs-util'; import { ObservableStore } from '@metamask/obs-store'; import log from 'loglevel'; +import { CHAIN_ID_TO_NETWORK_ID_MAP } from '../../../../shared/constants/network'; import Ens from './ens'; const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; const ZERO_X_ERROR_ADDRESS = '0x'; export default class EnsController { - constructor({ ens, provider, networkStore } = {}) { + constructor({ ens, provider, onNetworkDidChange, getCurrentChainId } = {}) { const initState = { ensResolutionsByAddress: {}, }; this._ens = ens; if (!this._ens) { - const network = networkStore.getState(); + const chainId = getCurrentChainId(); + const network = CHAIN_ID_TO_NETWORK_ID_MAP[chainId]; if (Ens.getNetworkEnsSupport(network)) { this._ens = new Ens({ network, @@ -25,8 +27,10 @@ export default class EnsController { } this.store = new ObservableStore(initState); - networkStore.subscribe((network) => { + onNetworkDidChange(() => { this.store.putState(initState); + const chainId = getCurrentChainId(); + const network = CHAIN_ID_TO_NETWORK_ID_MAP[chainId]; if (Ens.getNetworkEnsSupport(network)) { this._ens = new Ens({ network, diff --git a/app/scripts/controllers/incoming-transactions.js b/app/scripts/controllers/incoming-transactions.js index 481810ec1..b6227d984 100644 --- a/app/scripts/controllers/incoming-transactions.js +++ b/app/scripts/controllers/incoming-transactions.js @@ -23,6 +23,7 @@ import { ROPSTEN, ROPSTEN_CHAIN_ID, } from '../../../shared/constants/network'; +import { NETWORK_EVENTS } from './network'; const fetchWithTimeout = getFetchWithTimeout(30000); @@ -111,7 +112,7 @@ export default class IncomingTransactionsController { }), ); - this.networkController.on('networkDidChange', async () => { + this.networkController.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, async () => { const address = this.preferencesController.getSelectedAddress(); await this._update({ address, @@ -282,6 +283,7 @@ export default class IncomingTransactionsController { return { blockNumber: txMeta.blockNumber, id: createId(), + chainId, metamaskNetworkId: CHAIN_ID_TO_NETWORK_ID_MAP[chainId], status, time, diff --git a/app/scripts/controllers/metametrics.js b/app/scripts/controllers/metametrics.js index 4bb1c4f46..00e07009f 100644 --- a/app/scripts/controllers/metametrics.js +++ b/app/scripts/controllers/metametrics.js @@ -200,9 +200,9 @@ export default class MetaMetricsController { value, currency, category, - network: this.network, + network: properties?.network ?? this.network, locale: this.locale, - chain_id: this.chainId, + chain_id: properties?.chain_id ?? this.chainId, environment_type: environmentType, }, context: this._buildContext(referrer, page), diff --git a/app/scripts/controllers/network/index.js b/app/scripts/controllers/network/index.js index a0a43faa5..fa027c5ab 100644 --- a/app/scripts/controllers/network/index.js +++ b/app/scripts/controllers/network/index.js @@ -1 +1 @@ -export { default } from './network'; +export { default, NETWORK_EVENTS } from './network'; diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index 605b0063a..1c9c80600 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -21,7 +21,7 @@ import { import { isPrefixedFormattedHexString, isSafeChainId, -} from '../../../../shared/modules/utils'; +} from '../../../../shared/modules/network.utils'; import createMetamaskMiddleware from './createMetamaskMiddleware'; import createInfuraClient from './createInfuraClient'; import createJsonRpcClient from './createJsonRpcClient'; @@ -47,6 +47,13 @@ const defaultProviderConfig = { ...defaultProviderConfigOpts, }; +export const NETWORK_EVENTS = { + // Fired after the actively selected network is changed + NETWORK_DID_CHANGE: 'networkDidChange', + // Fired when the actively selected network *will* change + NETWORK_WILL_CHANGE: 'networkWillChange', +}; + export default class NetworkController extends EventEmitter { constructor(opts = {}) { super(); @@ -73,7 +80,7 @@ export default class NetworkController extends EventEmitter { this._providerProxy = null; this._blockTrackerProxy = null; - this.on('networkDidChange', this.lookupNetwork); + this.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, this.lookupNetwork); } /** @@ -229,9 +236,10 @@ export default class NetworkController extends EventEmitter { // _switchNetwork(opts) { + this.emit(NETWORK_EVENTS.NETWORK_WILL_CHANGE); this.setNetworkState('loading'); this._configureProvider(opts); - this.emit('networkDidChange', opts.type); + this.emit(NETWORK_EVENTS.NETWORK_DID_CHANGE, opts.type); } _configureProvider({ type, rpcUrl, chainId }) { diff --git a/app/scripts/controllers/permissions/index.js b/app/scripts/controllers/permissions/index.js index c10a950cb..c4b6eae79 100644 --- a/app/scripts/controllers/permissions/index.js +++ b/app/scripts/controllers/permissions/index.js @@ -126,7 +126,12 @@ export class PermissionsController { */ async requestAccountsPermissionWithId(origin) { const id = nanoid(); - this._requestPermissions({ origin }, { eth_accounts: {} }, id); + this._requestPermissions({ origin }, { eth_accounts: {} }, id).then( + async () => { + const permittedAccounts = await this.getAccounts(origin); + this.notifyAccountsChanged(origin, permittedAccounts); + }, + ); return id; } diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index fc02a317f..539978bca 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -7,7 +7,8 @@ import ethers from 'ethers'; import log from 'loglevel'; import { LISTED_CONTRACT_ADDRESSES } from '../../../shared/constants/tokens'; import { NETWORK_TYPE_TO_ID_MAP } from '../../../shared/constants/network'; -import { isPrefixedFormattedHexString } from '../../../shared/modules/utils'; +import { isPrefixedFormattedHexString } from '../../../shared/modules/network.utils'; +import { NETWORK_EVENTS } from './network'; export default class PreferencesController { /** @@ -72,7 +73,7 @@ export default class PreferencesController { this.store.setMaxListeners(12); this.openPopup = opts.openPopup; this.migrateAddressBookState = opts.migrateAddressBookState; - this._subscribeProviderType(); + this._subscribeToNetworkDidChange(); global.setPreference = (key, value) => { return this.setFeatureFlag(key, value); @@ -667,12 +668,11 @@ export default class PreferencesController { // /** - * Subscription to network provider type. - * - * + * Handle updating token list to reflect current network by listening for the + * NETWORK_DID_CHANGE event. */ - _subscribeProviderType() { - this.network.providerStore.subscribe(() => { + _subscribeToNetworkDidChange() { + this.network.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, () => { const { tokens, hiddenTokens } = this._getTokenRelatedStates(); this._updateAccountTokens(tokens, this.getAssetImages(), hiddenTokens); }); @@ -689,12 +689,12 @@ export default class PreferencesController { _updateAccountTokens(tokens, assetImages, hiddenTokens) { const { accountTokens, - providerType, + chainId, selectedAddress, accountHiddenTokens, } = this._getTokenRelatedStates(); - accountTokens[selectedAddress][providerType] = tokens; - accountHiddenTokens[selectedAddress][providerType] = hiddenTokens; + accountTokens[selectedAddress][chainId] = tokens; + accountHiddenTokens[selectedAddress][chainId] = hiddenTokens; this.store.updateState({ accountTokens, tokens, @@ -730,27 +730,27 @@ export default class PreferencesController { // eslint-disable-next-line no-param-reassign selectedAddress = this.store.getState().selectedAddress; } - const providerType = this.network.providerStore.getState().type; + const chainId = this.network.getCurrentChainId(); if (!(selectedAddress in accountTokens)) { accountTokens[selectedAddress] = {}; } if (!(selectedAddress in accountHiddenTokens)) { accountHiddenTokens[selectedAddress] = {}; } - if (!(providerType in accountTokens[selectedAddress])) { - accountTokens[selectedAddress][providerType] = []; + if (!(chainId in accountTokens[selectedAddress])) { + accountTokens[selectedAddress][chainId] = []; } - if (!(providerType in accountHiddenTokens[selectedAddress])) { - accountHiddenTokens[selectedAddress][providerType] = []; + if (!(chainId in accountHiddenTokens[selectedAddress])) { + accountHiddenTokens[selectedAddress][chainId] = []; } - const tokens = accountTokens[selectedAddress][providerType]; - const hiddenTokens = accountHiddenTokens[selectedAddress][providerType]; + const tokens = accountTokens[selectedAddress][chainId]; + const hiddenTokens = accountHiddenTokens[selectedAddress][chainId]; return { tokens, accountTokens, hiddenTokens, accountHiddenTokens, - providerType, + chainId, selectedAddress, }; } diff --git a/app/scripts/controllers/swaps.js b/app/scripts/controllers/swaps.js index 992af5578..d82ac305f 100644 --- a/app/scripts/controllers/swaps.js +++ b/app/scripts/controllers/swaps.js @@ -19,6 +19,7 @@ import { fetchSwapsFeatureLiveness as defaultFetchSwapsFeatureLiveness, fetchSwapsQuoteRefreshTime as defaultFetchSwapsQuoteRefreshTime, } from '../../../ui/app/pages/swaps/swaps.util'; +import { NETWORK_EVENTS } from './network'; const METASWAP_ADDRESS = '0x881d40237659c251811cec9c364ef91dc08d300c'; @@ -103,7 +104,7 @@ export default class SwapsController { this.ethersProvider = new ethers.providers.Web3Provider(provider); this._currentNetwork = networkController.store.getState().network; - networkController.on('networkDidChange', (network) => { + networkController.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, (network) => { if (network !== 'loading' && network !== this._currentNetwork) { this._currentNetwork = network; this.ethersProvider = new ethers.providers.Web3Provider(provider); diff --git a/app/scripts/controllers/token-rates.js b/app/scripts/controllers/token-rates.js index a3f0f6710..9d597ce1b 100644 --- a/app/scripts/controllers/token-rates.js +++ b/app/scripts/controllers/token-rates.js @@ -19,10 +19,13 @@ export default class TokenRatesController { * * @param {Object} [config] - Options to configure controller */ - constructor({ currency, preferences } = {}) { + constructor({ preferences, getNativeCurrency } = {}) { this.store = new ObservableStore(); - this.currency = currency; - this.preferences = preferences; + this.getNativeCurrency = getNativeCurrency; + this.tokens = preferences.getState().tokens; + preferences.subscribe(({ tokens = [] }) => { + this.tokens = tokens; + }); } /** @@ -30,9 +33,7 @@ export default class TokenRatesController { */ async updateExchangeRates() { const contractExchangeRates = {}; - const nativeCurrency = this.currency - ? this.currency.state.nativeCurrency.toLowerCase() - : 'eth'; + 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) { @@ -60,21 +61,6 @@ export default class TokenRatesController { } /* eslint-disable accessor-pairs */ - /** - * @type {Object} - */ - set preferences(preferences) { - this._preferences && this._preferences.unsubscribe(); - if (!preferences) { - return; - } - this._preferences = preferences; - this.tokens = preferences.getState().tokens; - preferences.subscribe(({ tokens = [] }) => { - this.tokens = tokens; - }); - } - /** * @type {Array} */ diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index 36864c509..f153558d3 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -23,6 +23,7 @@ import { TRANSACTION_STATUSES, TRANSACTION_TYPES, } from '../../../../shared/constants/transaction'; +import { METAMASK_CONTROLLER_EVENTS } from '../../metamask-controller'; import TransactionStateManager from './tx-state-manager'; import TxGasUtil from './tx-gas-utils'; import PendingTransactionTracker from './pending-tx-tracker'; @@ -83,6 +84,7 @@ export default class TransactionController extends EventEmitter { initState: opts.initState, txHistoryLimit: opts.txHistoryLimit, getNetwork: this.getNetwork.bind(this), + getCurrentChainId: opts.getCurrentChainId, }); this._onBootCleanUp(); @@ -113,7 +115,9 @@ export default class TransactionController extends EventEmitter { ), }); - this.txStateManager.store.subscribe(() => this.emit('update:badge')); + this.txStateManager.store.subscribe(() => + this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE), + ); this._setupListeners(); // memstore is computed from a few different stores this._updateMemstore(); diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index 492ea4dde..c62a97d1e 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -3,6 +3,8 @@ import { ObservableStore } from '@metamask/obs-store'; import log from 'loglevel'; import createId from '../../lib/random-id'; import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; +import { METAMASK_CONTROLLER_EVENTS } from '../../metamask-controller'; +import { transactionMatchesNetwork } from '../../../../shared/modules/transaction.utils'; import { generateHistoryEntry, replayHistory, @@ -27,12 +29,13 @@ import { getFinalStates, normalizeTxParams } from './lib/util'; * @class */ export default class TransactionStateManager extends EventEmitter { - constructor({ initState, txHistoryLimit, getNetwork }) { + constructor({ initState, txHistoryLimit, getNetwork, getCurrentChainId }) { super(); this.store = new ObservableStore({ transactions: [], ...initState }); this.txHistoryLimit = txHistoryLimit; this.getNetwork = getNetwork; + this.getCurrentChainId = getCurrentChainId; } /** @@ -41,6 +44,7 @@ export default class TransactionStateManager extends EventEmitter { */ generateTxMeta(opts) { const netId = this.getNetwork(); + const chainId = this.getCurrentChainId(); if (netId === 'loading') { throw new Error('MetaMask is having trouble connecting to the network'); } @@ -49,6 +53,7 @@ export default class TransactionStateManager extends EventEmitter { time: new Date().getTime(), status: TRANSACTION_STATUSES.UNAPPROVED, metamaskNetworkId: netId, + chainId, loadingDefaults: true, ...opts, }; @@ -64,13 +69,14 @@ export default class TransactionStateManager extends EventEmitter { */ getTxList(limit) { const network = this.getNetwork(); + const chainId = this.getCurrentChainId(); const fullTxList = this.getFullTxList(); const nonces = new Set(); const txs = []; for (let i = fullTxList.length - 1; i > -1; i--) { const txMeta = fullTxList[i]; - if (txMeta.metamaskNetworkId !== network) { + if (transactionMatchesNetwork(txMeta, chainId, network) === false) { continue; } @@ -451,13 +457,14 @@ export default class TransactionStateManager extends EventEmitter { // network only tx const txs = this.getFullTxList(); const network = this.getNetwork(); + const chainId = this.getCurrentChainId(); // Filter out the ones from the current account and network const otherAccountTxs = txs.filter( (txMeta) => !( txMeta.txParams.from === address && - txMeta.metamaskNetworkId === network + transactionMatchesNetwork(txMeta, chainId, network) ), ); @@ -474,7 +481,7 @@ export default class TransactionStateManager extends EventEmitter { * @param {TransactionStatuses[keyof TransactionStatuses]} status - the status to set on the txMeta * @emits tx:status-update - passes txId and status * @emits ${txMeta.id}:finished - if it is a finished state. Passes the txMeta - * @emits update:badge + * @emits 'updateBadge' */ _setTxStatus(txId, status) { const txMeta = this.getTx(txId); @@ -497,7 +504,7 @@ export default class TransactionStateManager extends EventEmitter { ) { this.emit(`${txMeta.id}:finished`, txMeta); } - this.emit('update:badge'); + this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE); } catch (error) { log.error(error); } diff --git a/app/scripts/lib/decrypt-message-manager.js b/app/scripts/lib/decrypt-message-manager.js index 39f2a0e42..32ae13626 100644 --- a/app/scripts/lib/decrypt-message-manager.js +++ b/app/scripts/lib/decrypt-message-manager.js @@ -4,6 +4,7 @@ import ethUtil from 'ethereumjs-util'; import { ethErrors } from 'eth-rpc-errors'; import log from 'loglevel'; import { MESSAGE_TYPE } from '../../../shared/constants/app'; +import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller'; import { addHexPrefix } from './util'; import createId from './random-id'; @@ -253,6 +254,14 @@ export default class DecryptMessageManager extends EventEmitter { this._setMsgStatus(msgId, 'errored'); } + /** + * Clears all unapproved messages from memory. + */ + clearUnapproved() { + this.messages = this.messages.filter((msg) => msg.status !== 'unapproved'); + this._saveMsgList(); + } + /** * Updates the status of a DecryptMessage in this.messages via a call to this._updateMsg * @@ -316,7 +325,7 @@ export default class DecryptMessageManager extends EventEmitter { unapprovedDecryptMsgs, unapprovedDecryptMsgCount, }); - this.emit('updateBadge'); + this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE); } /** diff --git a/app/scripts/lib/encryption-public-key-manager.js b/app/scripts/lib/encryption-public-key-manager.js index 6fc213b19..e29723b5b 100644 --- a/app/scripts/lib/encryption-public-key-manager.js +++ b/app/scripts/lib/encryption-public-key-manager.js @@ -3,6 +3,7 @@ import { ObservableStore } from '@metamask/obs-store'; import { ethErrors } from 'eth-rpc-errors'; import log from 'loglevel'; import { MESSAGE_TYPE } from '../../../shared/constants/app'; +import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller'; import createId from './random-id'; /** @@ -242,6 +243,14 @@ export default class EncryptionPublicKeyManager extends EventEmitter { this._setMsgStatus(msgId, 'errored'); } + /** + * Clears all unapproved messages from memory. + */ + clearUnapproved() { + this.messages = this.messages.filter((msg) => msg.status !== 'unapproved'); + this._saveMsgList(); + } + /** * Updates the status of a EncryptionPublicKey in this.messages via a call to this._updateMsg * @@ -303,6 +312,6 @@ export default class EncryptionPublicKeyManager extends EventEmitter { unapprovedEncryptionPublicKeyMsgs, unapprovedEncryptionPublicKeyMsgCount, }); - this.emit('updateBadge'); + this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE); } } diff --git a/app/scripts/lib/ens-ipfs/setup.js b/app/scripts/lib/ens-ipfs/setup.js index 51b740301..8c30de975 100644 --- a/app/scripts/lib/ens-ipfs/setup.js +++ b/app/scripts/lib/ens-ipfs/setup.js @@ -8,7 +8,7 @@ const supportedTopLevelDomains = ['eth']; export default function setupEnsIpfsResolver({ provider, - getCurrentNetwork, + getCurrentChainId, getIpfsGateway, }) { // install listener @@ -30,7 +30,7 @@ export default function setupEnsIpfsResolver({ const { tabId, url } = details; // ignore requests that are not associated with tabs // only attempt ENS resolution on mainnet - if (tabId === -1 || getCurrentNetwork() !== '1') { + if (tabId === -1 || getCurrentChainId() !== '0x1') { return; } // parse ens name diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index 796971208..7f4218f8b 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -3,6 +3,7 @@ import { ObservableStore } from '@metamask/obs-store'; import ethUtil from 'ethereumjs-util'; import { ethErrors } from 'eth-rpc-errors'; import { MESSAGE_TYPE } from '../../../shared/constants/app'; +import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller'; import createId from './random-id'; /** @@ -220,6 +221,14 @@ export default class MessageManager extends EventEmitter { this._setMsgStatus(msgId, 'rejected'); } + /** + * Clears all unapproved messages from memory. + */ + clearUnapproved() { + this.messages = this.messages.filter((msg) => msg.status !== 'unapproved'); + this._saveMsgList(); + } + /** * Updates the status of a Message in this.messages via a call to this._updateMsg * @@ -272,7 +281,7 @@ export default class MessageManager extends EventEmitter { const unapprovedMsgs = this.getUnapprovedMsgs(); const unapprovedMsgCount = Object.keys(unapprovedMsgs).length; this.memStore.updateState({ unapprovedMsgs, unapprovedMsgCount }); - this.emit('updateBadge'); + this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE); } } diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index 66474c8c4..1fb59144b 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -4,6 +4,7 @@ import ethUtil from 'ethereumjs-util'; import { ethErrors } from 'eth-rpc-errors'; import log from 'loglevel'; import { MESSAGE_TYPE } from '../../../shared/constants/app'; +import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller'; import { addHexPrefix } from './util'; import createId from './random-id'; @@ -241,6 +242,14 @@ export default class PersonalMessageManager extends EventEmitter { this._setMsgStatus(msgId, 'rejected'); } + /** + * Clears all unapproved messages from memory. + */ + clearUnapproved() { + this.messages = this.messages.filter((msg) => msg.status !== 'unapproved'); + this._saveMsgList(); + } + /** * Updates the status of a PersonalMessage in this.messages via a call to this._updateMsg * @@ -301,7 +310,7 @@ export default class PersonalMessageManager extends EventEmitter { unapprovedPersonalMsgs, unapprovedPersonalMsgCount, }); - this.emit('updateBadge'); + this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE); } /** diff --git a/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js b/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js new file mode 100644 index 000000000..ac170b399 --- /dev/null +++ b/app/scripts/lib/rpc-method-middleware/handlers/add-ethereum-chain.js @@ -0,0 +1,272 @@ +import { ethErrors } from 'eth-rpc-errors'; +import validUrl from 'valid-url'; +import { omit } from 'lodash'; +import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; +import { + isPrefixedFormattedHexString, + isSafeChainId, +} from '../../../../../shared/modules/network.utils'; +import { jsonRpcRequest } from '../../../../../shared/modules/rpc.utils'; +import { CHAIN_ID_TO_NETWORK_ID_MAP } from '../../../../../shared/constants/network'; + +const addEthereumChain = { + methodNames: [MESSAGE_TYPE.ADD_ETHEREUM_CHAIN], + implementation: addEthereumChainHandler, +}; +export default addEthereumChain; + +async function addEthereumChainHandler( + req, + res, + _next, + end, + { + addCustomRpc, + getCurrentChainId, + findCustomRpcBy, + updateRpcTarget, + requestUserApproval, + sendMetrics, + }, +) { + if (!req.params?.[0] || typeof req.params[0] !== 'object') { + return end( + ethErrors.rpc.invalidParams({ + message: `Expected single, object parameter. Received:\n${JSON.stringify( + req.params, + )}`, + }), + ); + } + + const { origin } = req; + + const { + chainId, + chainName = null, + blockExplorerUrls = null, + nativeCurrency = null, + rpcUrls, + } = req.params[0]; + + const otherKeys = Object.keys( + omit(req.params[0], [ + 'chainId', + 'chainName', + 'blockExplorerUrls', + 'iconUrls', + 'rpcUrls', + 'nativeCurrency', + ]), + ); + + if (otherKeys.length > 0) { + return end( + ethErrors.rpc.invalidParams({ + message: `Received unexpected keys on object parameter. Unsupported keys:\n${otherKeys}`, + }), + ); + } + + const firstValidRPCUrl = Array.isArray(rpcUrls) + ? rpcUrls.find((rpcUrl) => validUrl.isHttpsUri(rpcUrl)) + : null; + + const firstValidBlockExplorerUrl = + blockExplorerUrls !== null && Array.isArray(blockExplorerUrls) + ? blockExplorerUrls.find((blockExplorerUrl) => + validUrl.isHttpsUri(blockExplorerUrl), + ) + : null; + + if (!firstValidRPCUrl) { + return end( + ethErrors.rpc.invalidParams({ + message: `Expected an array with at least one valid string HTTPS url 'rpcUrls', Received:\n${rpcUrls}`, + }), + ); + } + + if (blockExplorerUrls !== null && !firstValidBlockExplorerUrl) { + return end( + ethErrors.rpc.invalidParams({ + message: `Expected null or array with at least one valid string HTTPS URL 'blockExplorerUrl'. Received: ${blockExplorerUrls}`, + }), + ); + } + + const _chainId = typeof chainId === 'string' && chainId.toLowerCase(); + + if (!isPrefixedFormattedHexString(_chainId)) { + return end( + ethErrors.rpc.invalidParams({ + message: `Expected 0x-prefixed, unpadded, non-zero hexadecimal string 'chainId'. Received:\n${chainId}`, + }), + ); + } + + if (!isSafeChainId(parseInt(_chainId, 16))) { + return end( + ethErrors.rpc.invalidParams({ + message: `Invalid chain ID "${_chainId}": numerical value greater than max safe value. Received:\n${chainId}`, + }), + ); + } + + if (CHAIN_ID_TO_NETWORK_ID_MAP[_chainId]) { + return end( + ethErrors.rpc.invalidParams({ + message: `May not specify default MetaMask chain.`, + }), + ); + } + + const existingNetwork = findCustomRpcBy({ chainId: _chainId }); + + if (existingNetwork !== null) { + const currentChainId = getCurrentChainId(); + if (currentChainId === _chainId) { + res.result = null; + return end(); + } + try { + await updateRpcTarget( + await requestUserApproval({ + origin, + type: MESSAGE_TYPE.SWITCH_ETHEREUM_CHAIN, + requestData: { + rpcUrl: existingNetwork.rpcUrl, + chainId: existingNetwork.chainId, + nickname: existingNetwork.nickname, + ticker: existingNetwork.ticker, + }, + }), + ); + res.result = null; + } catch (error) { + return end(error); + } + return end(); + } + + let endpointChainId; + + try { + endpointChainId = await jsonRpcRequest(firstValidRPCUrl, 'eth_chainId'); + } catch (err) { + return end( + ethErrors.rpc.internal({ + message: `Request for method 'eth_chainId on ${firstValidRPCUrl} failed`, + data: { networkErr: err }, + }), + ); + } + + if (_chainId !== endpointChainId) { + return end( + ethErrors.rpc.invalidParams({ + message: `Chain ID returned by RPC URL ${firstValidRPCUrl} does not match ${_chainId}`, + data: { chainId: endpointChainId }, + }), + ); + } + + if (typeof chainName !== 'string' || !chainName) { + return end( + ethErrors.rpc.invalidParams({ + message: `Expected non-empty string 'chainName'. Received:\n${chainName}`, + }), + ); + } + const _chainName = + chainName.length > 100 ? chainName.substring(0, 100) : chainName; + + if (nativeCurrency !== null) { + if (typeof nativeCurrency !== 'object' || Array.isArray(nativeCurrency)) { + return end( + ethErrors.rpc.invalidParams({ + message: `Expected null or object 'nativeCurrency'. Received:\n${nativeCurrency}`, + }), + ); + } + if (nativeCurrency.decimals !== 18) { + return end( + ethErrors.rpc.invalidParams({ + message: `Expected the number 18 for 'nativeCurrency.decimals' when 'nativeCurrency' is provided. Received: ${nativeCurrency.decimals}`, + }), + ); + } + + if (!nativeCurrency.symbol || typeof nativeCurrency.symbol !== 'string') { + return end( + ethErrors.rpc.invalidParams({ + message: `Expected a string 'nativeCurrency.symbol'. Received: ${nativeCurrency.symbol}`, + }), + ); + } + } + const ticker = nativeCurrency?.symbol || 'ETH'; + + if (typeof ticker !== 'string' || ticker.length < 2 || ticker.length > 6) { + return end( + ethErrors.rpc.invalidParams({ + message: `Expected 2-6 character string 'nativeCurrency.symbol'. Received:\n${ticker}`, + }), + ); + } + + try { + await addCustomRpc( + await requestUserApproval({ + origin, + type: MESSAGE_TYPE.ADD_ETHEREUM_CHAIN, + requestData: { + chainId: _chainId, + blockExplorerUrl: firstValidBlockExplorerUrl, + chainName: _chainName, + rpcUrl: firstValidRPCUrl, + ticker, + }, + }), + ); + + sendMetrics({ + event: 'Custom Network Added', + category: 'Network', + referrer: { + url: origin, + }, + sensitiveProperties: { + chain_id: _chainId, + rpc_url: firstValidRPCUrl, + network_name: _chainName, + // Including network to override the default network + // property included in all events. For RPC type networks + // the MetaMetrics controller uses the rpcUrl for the network + // property. + network: firstValidRPCUrl, + symbol: ticker, + block_explorer_url: firstValidBlockExplorerUrl, + source: 'dapp', + }, + }); + + await updateRpcTarget( + await requestUserApproval({ + origin, + type: MESSAGE_TYPE.SWITCH_ETHEREUM_CHAIN, + requestData: { + rpcUrl: firstValidRPCUrl, + chainId: _chainId, + nickname: _chainName, + ticker, + }, + }), + ); + + res.result = null; + } catch (error) { + return end(error); + } + return end(); +} diff --git a/app/scripts/lib/rpc-method-middleware/handlers/index.js b/app/scripts/lib/rpc-method-middleware/handlers/index.js index e292e0cdd..541256a1c 100644 --- a/app/scripts/lib/rpc-method-middleware/handlers/index.js +++ b/app/scripts/lib/rpc-method-middleware/handlers/index.js @@ -1,6 +1,12 @@ +import addEthereumChain from './add-ethereum-chain'; import getProviderState from './get-provider-state'; import logWeb3ShimUsage from './log-web3-shim-usage'; import watchAsset from './watch-asset'; -const handlers = [getProviderState, logWeb3ShimUsage, watchAsset]; +const handlers = [ + addEthereumChain, + getProviderState, + logWeb3ShimUsage, + watchAsset, +]; export default handlers; diff --git a/app/scripts/lib/typed-message-manager.js b/app/scripts/lib/typed-message-manager.js index 630e6029c..d1ea6491b 100644 --- a/app/scripts/lib/typed-message-manager.js +++ b/app/scripts/lib/typed-message-manager.js @@ -7,6 +7,7 @@ import { isValidAddress } from 'ethereumjs-util'; import log from 'loglevel'; import jsonschema from 'jsonschema'; import { MESSAGE_TYPE } from '../../../shared/constants/app'; +import { METAMASK_CONTROLLER_EVENTS } from '../metamask-controller'; import createId from './random-id'; /** @@ -313,6 +314,14 @@ export default class TypedMessageManager extends EventEmitter { this._setMsgStatus(msgId, 'errored'); } + /** + * Clears all unapproved messages from memory. + */ + clearUnapproved() { + this.messages = this.messages.filter((msg) => msg.status !== 'unapproved'); + this._saveMsgList(); + } + // // PRIVATE METHODS // @@ -377,6 +386,6 @@ export default class TypedMessageManager extends EventEmitter { unapprovedTypedMessages, unapprovedTypedMessagesCount, }); - this.emit('updateBadge'); + this.emit(METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE); } } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 2eff30355..a71ad26d2 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -35,7 +35,7 @@ import createTabIdMiddleware from './lib/createTabIdMiddleware'; import createOnboardingMiddleware from './lib/createOnboardingMiddleware'; import { setupMultiplex } from './lib/stream-utils'; import EnsController from './controllers/ens'; -import NetworkController from './controllers/network'; +import NetworkController, { NETWORK_EVENTS } from './controllers/network'; import PreferencesController from './controllers/preferences'; import AppStateController from './controllers/app-state'; import CachedBalancesController from './controllers/cached-balances'; @@ -61,6 +61,12 @@ import seedPhraseVerifier from './lib/seed-phrase-verifier'; import MetaMetricsController from './controllers/metametrics'; import { segment, segmentLegacy } from './lib/segment'; +export const METAMASK_CONTROLLER_EVENTS = { + // Fired after state changes that impact the extension badge (unapproved msg count) + // The process of updating the badge happens in app/scripts/background.js. + UPDATE_BADGE: 'updateBadge', +}; + export default class MetamaskController extends EventEmitter { /** * @constructor @@ -127,7 +133,7 @@ export default class MetamaskController extends EventEmitter { preferencesStore: this.preferencesController.store, onNetworkDidChange: this.networkController.on.bind( this.networkController, - 'networkDidChange', + NETWORK_EVENTS.NETWORK_DID_CHANGE, ), getNetworkIdentifier: this.networkController.getNetworkIdentifier.bind( this.networkController, @@ -163,13 +169,22 @@ export default class MetamaskController extends EventEmitter { // token exchange rate tracker this.tokenRatesController = new TokenRatesController({ - currency: this.currencyRateController, preferences: this.preferencesController.store, + getNativeCurrency: () => { + const { ticker } = this.networkController.getProviderConfig(); + return ticker ?? 'ETH'; + }, }); this.ensController = new EnsController({ provider: this.provider, - networkStore: this.networkController.networkStore, + getCurrentChainId: this.networkController.getCurrentChainId.bind( + this.networkController, + ), + onNetworkDidChange: this.networkController.on.bind( + this.networkController, + NETWORK_EVENTS.NETWORK_DID_CHANGE, + ), }); this.incomingTransactionsController = new IncomingTransactionsController({ @@ -214,11 +229,6 @@ export default class MetamaskController extends EventEmitter { preferencesController: this.preferencesController, }); - // ensure accountTracker updates balances after network change - this.networkController.on('networkDidChange', () => { - this.accountTracker._updateAccounts(); - }); - const additionalKeyrings = [TrezorKeyring, LedgerBridgeKeyring]; this.keyringController = new KeyringController({ keyringTypes: additionalKeyrings, @@ -245,7 +255,6 @@ export default class MetamaskController extends EventEmitter { notifyDomain: this.notifyConnections.bind(this), notifyAllDomains: this.notifyAllConnections.bind(this), preferences: this.preferencesController.store, - showPermissionRequest: opts.showUserConfirmation, }, initState.PermissionsController, initState.PermissionsMetadata, @@ -290,7 +299,6 @@ export default class MetamaskController extends EventEmitter { ), preferencesStore: this.preferencesController.store, txHistoryLimit: 40, - getNetwork: this.networkController.getNetworkState.bind(this), signTransaction: this.keyringController.signTransaction.bind( this.keyringController, ), @@ -323,7 +331,7 @@ export default class MetamaskController extends EventEmitter { } }); - this.networkController.on('networkDidChange', () => { + this.networkController.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, () => { this.setCurrentCurrency( this.currencyRateController.state.currentCurrency, (error) => { @@ -333,7 +341,8 @@ export default class MetamaskController extends EventEmitter { }, ); }); - + const { ticker } = this.networkController.getProviderConfig(); + this.currencyRateController.configure({ nativeCurrency: ticker ?? 'ETH' }); this.networkController.lookupNetwork(); this.messageManager = new MessageManager(); this.personalMessageManager = new PersonalMessageManager(); @@ -357,6 +366,21 @@ export default class MetamaskController extends EventEmitter { tokenRatesStore: this.tokenRatesController.store, }); + // ensure accountTracker updates balances after network change + this.networkController.on(NETWORK_EVENTS.NETWORK_DID_CHANGE, () => { + this.accountTracker._updateAccounts(); + }); + + // clear unapproved transactions and messages when the network will change + this.networkController.on(NETWORK_EVENTS.NETWORK_WILL_CHANGE, () => { + this.txController.txStateManager.clearUnapprovedTxs(); + this.encryptionPublicKeyManager.clearUnapproved(); + this.personalMessageManager.clearUnapproved(); + this.typedMessageManager.clearUnapproved(); + this.decryptMessageManager.clearUnapproved(); + this.messageManager.clearUnapproved(); + }); + // ensure isClientOpenAndUnlocked is updated when memState updates this.on('update', (memState) => this._onStateUpdate(memState)); @@ -559,6 +583,7 @@ export default class MetamaskController extends EventEmitter { getApi() { const { alertController, + approvalController, keyringController, metaMetricsController, networkController, @@ -883,6 +908,16 @@ export default class MetamaskController extends EventEmitter { metaMetricsController.trackPage, metaMetricsController, ), + + // approval controller + resolvePendingApproval: nodeify( + approvalController.resolve, + approvalController, + ), + rejectPendingApproval: nodeify( + approvalController.reject, + approvalController, + ), }; } @@ -2078,6 +2113,38 @@ export default class MetamaskController extends EventEmitter { setWeb3ShimUsageRecorded: this.alertController.setWeb3ShimUsageRecorded.bind( this.alertController, ), + findCustomRpcBy: this.findCustomRpcBy.bind(this), + getCurrentChainId: this.networkController.getCurrentChainId.bind( + this.networkController, + ), + requestUserApproval: this.approvalController.addAndShowApprovalRequest.bind( + this.approvalController, + ), + updateRpcTarget: ({ rpcUrl, chainId, ticker, nickname }) => { + this.networkController.setRpcTarget( + rpcUrl, + chainId, + ticker, + nickname, + ); + }, + addCustomRpc: async ({ + chainId, + blockExplorerUrl, + ticker, + chainName, + rpcUrl, + } = {}) => { + await this.preferencesController.addToFrequentRpcList( + rpcUrl, + chainId, + ticker, + chainName, + { + blockExplorerUrl, + }, + ); + }, }), ); // filter and subscription polyfills @@ -2431,8 +2498,10 @@ export default class MetamaskController extends EventEmitter { * @param {string} rpcUrl - A URL for a valid Ethereum RPC API. * @param {string} chainId - The chainId of the selected network. * @param {string} ticker - The ticker symbol of the selected network. - * @param {string} nickname - Optional nickname of the selected network. - * @returns {Promise} The RPC Target URL confirmed. + * @param {string} [nickname] - Nickname of the selected network. + * @param {Object} [rpcPrefs] - RPC preferences. + * @param {string} [rpcPrefs.blockExplorerUrl] - URL of block explorer for the chain. + * @returns {Promise} - The RPC Target URL confirmed. */ async updateAndSetCustomRpc( rpcUrl, @@ -2513,6 +2582,25 @@ export default class MetamaskController extends EventEmitter { await this.preferencesController.removeFromFrequentRpcList(rpcUrl); } + /** + * Returns the first RPC info object that matches at least one field of the + * provided search criteria. Returns null if no match is found + * + * @param {Object} rpcInfo - The RPC endpoint properties and values to check. + * @returns {Object} rpcInfo found in the frequentRpcList + */ + findCustomRpcBy(rpcInfo) { + const frequentRpcListDetail = this.preferencesController.getFrequentRpcListDetail(); + for (const existingRpcInfo of frequentRpcListDetail) { + for (const key of Object.keys(rpcInfo)) { + if (existingRpcInfo[key] === rpcInfo[key]) { + return existingRpcInfo; + } + } + } + return null; + } + async initializeThreeBox() { await this.threeBoxController.init(); } diff --git a/app/scripts/migrations/052.js b/app/scripts/migrations/052.js new file mode 100644 index 000000000..4b5de7d22 --- /dev/null +++ b/app/scripts/migrations/052.js @@ -0,0 +1,125 @@ +import { cloneDeep } from 'lodash'; +import { + GOERLI, + GOERLI_CHAIN_ID, + KOVAN, + KOVAN_CHAIN_ID, + MAINNET, + MAINNET_CHAIN_ID, + NETWORK_TYPE_RPC, + RINKEBY, + RINKEBY_CHAIN_ID, + ROPSTEN, + ROPSTEN_CHAIN_ID, +} from '../../../shared/constants/network'; + +const version = 52; + +/** + * Migrate tokens in Preferences to be keyed by chainId instead of + * providerType. To prevent breaking user's MetaMask and selected + * tokens, this migration copies the RPC entry into *every* custom RPC + * chainId. + */ +export default { + version, + async migrate(originalVersionedData) { + const versionedData = cloneDeep(originalVersionedData); + versionedData.meta.version = version; + const state = versionedData.data; + versionedData.data = transformState(state); + return versionedData; + }, +}; + +function transformState(state = {}) { + if (state.PreferencesController) { + const { + accountTokens, + accountHiddenTokens, + frequentRpcListDetail, + } = state.PreferencesController; + + const newAccountTokens = {}; + const newAccountHiddenTokens = {}; + + if (accountTokens && Object.keys(accountTokens).length > 0) { + for (const address of Object.keys(accountTokens)) { + newAccountTokens[address] = {}; + if (accountTokens[address][NETWORK_TYPE_RPC]) { + frequentRpcListDetail.forEach((detail) => { + newAccountTokens[address][detail.chainId] = + accountTokens[address][NETWORK_TYPE_RPC]; + }); + } + for (const providerType of Object.keys(accountTokens[address])) { + switch (providerType) { + case MAINNET: + newAccountTokens[address][MAINNET_CHAIN_ID] = + accountTokens[address][MAINNET]; + break; + case ROPSTEN: + newAccountTokens[address][ROPSTEN_CHAIN_ID] = + accountTokens[address][ROPSTEN]; + break; + case RINKEBY: + newAccountTokens[address][RINKEBY_CHAIN_ID] = + accountTokens[address][RINKEBY]; + break; + case GOERLI: + newAccountTokens[address][GOERLI_CHAIN_ID] = + accountTokens[address][GOERLI]; + break; + case KOVAN: + newAccountTokens[address][KOVAN_CHAIN_ID] = + accountTokens[address][KOVAN]; + break; + default: + break; + } + } + } + state.PreferencesController.accountTokens = newAccountTokens; + } + + if (accountHiddenTokens && Object.keys(accountHiddenTokens).length > 0) { + for (const address of Object.keys(accountHiddenTokens)) { + newAccountHiddenTokens[address] = {}; + if (accountHiddenTokens[address][NETWORK_TYPE_RPC]) { + frequentRpcListDetail.forEach((detail) => { + newAccountHiddenTokens[address][detail.chainId] = + accountHiddenTokens[address][NETWORK_TYPE_RPC]; + }); + } + for (const providerType of Object.keys(accountHiddenTokens[address])) { + switch (providerType) { + case MAINNET: + newAccountHiddenTokens[address][MAINNET_CHAIN_ID] = + accountHiddenTokens[address][MAINNET]; + break; + case ROPSTEN: + newAccountHiddenTokens[address][ROPSTEN_CHAIN_ID] = + accountHiddenTokens[address][ROPSTEN]; + break; + case RINKEBY: + newAccountHiddenTokens[address][RINKEBY_CHAIN_ID] = + accountHiddenTokens[address][RINKEBY]; + break; + case GOERLI: + newAccountHiddenTokens[address][GOERLI_CHAIN_ID] = + accountHiddenTokens[address][GOERLI]; + break; + case KOVAN: + newAccountHiddenTokens[address][KOVAN_CHAIN_ID] = + accountHiddenTokens[address][KOVAN]; + break; + default: + break; + } + } + } + state.PreferencesController.accountHiddenTokens = newAccountHiddenTokens; + } + } + return state; +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 5fe85ae74..b4368c1b5 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -56,6 +56,7 @@ const migrations = [ require('./049').default, require('./050').default, require('./051').default, + require('./052').default, ]; export default migrations; diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index 8c43a343b..98196c946 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -196,7 +196,9 @@ export default class ExtensionPlatform { const nonce = parseInt(txMeta.txParams.nonce, 16); const title = 'Confirmed transaction'; - const message = `Transaction ${nonce} confirmed! View on Etherscan`; + const message = `Transaction ${nonce} confirmed! ${ + url.length ? 'View on Etherscan' : '' + }`; this._showNotification(title, message, url); } diff --git a/development/build/index.js b/development/build/index.js index c6ce884f5..9a60ead28 100755 --- a/development/build/index.js +++ b/development/build/index.js @@ -16,6 +16,17 @@ const createStyleTasks = require('./styles'); const createStaticAssetTasks = require('./static'); const createEtcTasks = require('./etc'); +// packages required dynamically via browserify configuration in dependencies +require('loose-envify'); +require('@babel/plugin-proposal-object-rest-spread'); +require('@babel/plugin-transform-runtime'); +require('@babel/plugin-proposal-class-properties'); +require('@babel/plugin-proposal-optional-chaining'); +require('@babel/plugin-proposal-nullish-coalescing-operator'); +require('@babel/preset-env'); +require('@babel/preset-react'); +require('@babel/core'); + const browserPlatforms = ['firefox', 'chrome', 'brave', 'opera']; defineAllTasks(); diff --git a/development/build/sass-compiler.js b/development/build/sass-compiler.js new file mode 100644 index 000000000..7ed069f8a --- /dev/null +++ b/development/build/sass-compiler.js @@ -0,0 +1,12 @@ +const sass = require('sass'); + +module.exports = { + render: (opts, callback) => { + // sass wants its arguments to come from the same Realm as itself + // bridgeJson and bridgeFn are added via patch-package to make this possible + sass.render(sass.bridgeJson(opts), sass.bridgeFn(callback)); + }, + renderSync: () => { + throw new Error('sass-wrapper - renderSync not supported'); + }, +}; diff --git a/development/build/scripts.js b/development/build/scripts.js index 57bbbcc6d..f3dcc8de0 100644 --- a/development/build/scripts.js +++ b/development/build/scripts.js @@ -11,6 +11,8 @@ const browserify = require('browserify'); const envify = require('loose-envify/custom'); const sourcemaps = require('gulp-sourcemaps'); const terser = require('gulp-terser-js'); +const babelify = require('babelify'); +const brfs = require('brfs'); const conf = require('rc')('metamask', { INFURA_PROJECT_ID: process.env.INFURA_PROJECT_ID, @@ -294,8 +296,8 @@ function createScriptTasks({ browserPlatforms, livereload }) { } let bundler = browserify(browserifyOpts) - .transform('babelify') - .transform('brfs'); + .transform(babelify) + .transform(brfs); if (opts.buildLib) { bundler = bundler.require(opts.dependenciesToBundle); diff --git a/development/build/styles.js b/development/build/styles.js index b1b31fbef..52490f6fd 100644 --- a/development/build/styles.js +++ b/development/build/styles.js @@ -1,7 +1,5 @@ const pify = require('pify'); const gulp = require('gulp'); -const sass = require('gulp-sass'); -sass.compiler = require('sass'); const autoprefixer = require('gulp-autoprefixer'); const gulpStylelint = require('gulp-stylelint'); const watch = require('gulp-watch'); @@ -11,6 +9,8 @@ const rename = require('gulp-rename'); const pump = pify(require('pump')); const { createTask } = require('./task'); +let sass; + // scss compilation and autoprefixing tasks module.exports = createStyleTasks; @@ -66,6 +66,14 @@ function createStyleTasks({ livereload }) { } async function buildScssPipeline(src, dest, devMode, rtl) { + if (!sass) { + // eslint-disable-next-line node/global-require + sass = require('gulp-sass'); + // use our own compiler which runs sass in its own process + // in order to not pollute the intrinsics + // eslint-disable-next-line node/global-require + sass.compiler = require('./sass-compiler.js'); + } await pump( ...[ // pre-process diff --git a/development/build/task.js b/development/build/task.js index e4de01ef6..2651b470a 100644 --- a/development/build/task.js +++ b/development/build/task.js @@ -23,7 +23,7 @@ function detectAndRunEntryTask() { if (!taskName) { throw new Error(`MetaMask build: No task name specified`); } - const skipStats = process.argv[3] === '--skip-stats'; + const skipStats = process.argv.includes('--skip-stats'); runTask(taskName, { skipStats }); } diff --git a/development/metamaskbot-build-announce.js b/development/metamaskbot-build-announce.js index f0fd33260..d4cda2e65 100755 --- a/development/metamaskbot-build-announce.js +++ b/development/metamaskbot-build-announce.js @@ -61,12 +61,17 @@ async function start() { const storybookUrl = `${BUILD_LINK_BASE}/storybook/index.html`; const storybookLink = `Storybook`; + // links to bundle browser builds + const depVizUrl = `${BUILD_LINK_BASE}/build-artifacts/build-viz/index.html`; + const depVizLink = `Build System`; + // link to artifacts const allArtifactsUrl = `https://circleci.com/gh/MetaMask/metamask-extension/${CIRCLE_BUILD_NUM}#artifacts/containers/0`; const contentRows = [ `builds: ${buildLinks}`, `bundle viz: ${bundleLinks}`, + `build viz: ${depVizLink}`, `code coverage: ${coverageLink}`, `storybook: ${storybookLink}`, `all artifacts`, diff --git a/development/run-ganache b/development/run-ganache.sh similarity index 100% rename from development/run-ganache rename to development/run-ganache.sh diff --git a/development/source-map-explorer.sh b/development/source-map-explorer.sh index 2a2ec6120..a4130d0f0 100755 --- a/development/source-map-explorer.sh +++ b/development/source-map-explorer.sh @@ -1,10 +1,15 @@ -#! /bin/bash +#!/usr/bin/env bash + set -x +set -e +set -u +set -o pipefail mkdir -p build-artifacts/source-map-explorer -npx source-map-explorer dist/chrome/inpage.js --html build-artifacts/source-map-explorer/inpage.html -npx source-map-explorer dist/chrome/contentscript.js --html build-artifacts/source-map-explorer/contentscript.html -npx source-map-explorer dist/chrome/background.js --html build-artifacts/source-map-explorer/background.html -npx source-map-explorer dist/chrome/ui.js --html build-artifacts/source-map-explorer/ui.html -npx source-map-explorer dist/chrome/libs.js --html build-artifacts/source-map-explorer/libs.html -npx source-map-explorer dist/chrome/phishing-detect.js --html build-artifacts/source-map-explorer/phishing-detect.html +yarn source-map-explorer dist/chrome/inpage.js --html build-artifacts/source-map-explorer/inpage.html +yarn source-map-explorer dist/chrome/contentscript.js --html build-artifacts/source-map-explorer/contentscript.html +yarn source-map-explorer dist/chrome/background.js --html build-artifacts/source-map-explorer/background.html +yarn source-map-explorer dist/chrome/bg-libs.js --html build-artifacts/source-map-explorer/bg-libs.html +yarn source-map-explorer dist/chrome/ui.js --html build-artifacts/source-map-explorer/ui.html +yarn source-map-explorer dist/chrome/ui-libs.js --html build-artifacts/source-map-explorer/ui-libs.html +yarn source-map-explorer dist/chrome/phishing-detect.js --html build-artifacts/source-map-explorer/phishing-detect.html diff --git a/development/verify-locale-strings.js b/development/verify-locale-strings.js index d49b60095..2e7b7584b 100644 --- a/development/verify-locale-strings.js +++ b/development/verify-locale-strings.js @@ -22,9 +22,9 @@ // ////////////////////////////////////////////////////////////////////////////// const fs = require('fs'); -const path = require('path'); const { promisify } = require('util'); const log = require('loglevel'); +const glob = require('fast-glob'); const matchAll = require('string.prototype.matchall').getPolyfill(); const localeIndex = require('../app/_locales/index.json'); const { @@ -34,7 +34,6 @@ const { getLocalePath, } = require('./lib/locales'); -const readdir = promisify(fs.readdir); const readFile = promisify(fs.readFile); const writeFile = promisify(fs.writeFile); @@ -168,15 +167,22 @@ async function verifyLocale(code) { async function verifyEnglishLocale() { const englishLocale = await getLocale('en'); - const uiJSFiles = await findJavascriptFiles( - path.resolve(__dirname, '..', 'ui'), - ); - const sharedJSFiles = await findJavascriptFiles( - path.resolve(__dirname, '..', 'shared'), - ); - - const javascriptFiles = sharedJSFiles.concat(uiJSFiles); + // As time allows we'll switch to only performing the strict search. + // In the meantime we'll use glob to specify which paths can be strict searched + // and gradually phase out the key based search + const globsToStrictSearch = [ + 'ui/app/components/app/metamask-translation/*.js', + 'ui/app/pages/confirmation/templates/*.js', + ]; + const testGlob = '**/*.test.js'; + const javascriptFiles = await glob(['ui/**/*.js', 'shared/**/*.js'], { + ignore: [...globsToStrictSearch, testGlob], + }); + const javascriptFilesToStrictSearch = await glob(globsToStrictSearch, { + ignore: [testGlob], + }); + const strictSearchRegex = /\bt\(\s*'(\w+)'\s*\)|\btranslationKey:\s*'(\w+)'/gu; // match "t(`...`)" because constructing message keys from template strings // prevents this script from finding the messages, and then inappropriately // deletes them @@ -190,10 +196,21 @@ async function verifyEnglishLocale() { for (const match of matchAll.call(fileContents, keyRegex)) { usedMessages.add(match[1] || match[2]); } + const templateMatches = fileContents.match(templateStringRegex); + if (templateMatches) { + templateMatches.forEach((match) => templateUsage.push(match)); + } + } + + for await (const fileContents of getFileContents( + javascriptFilesToStrictSearch, + )) { + for (const match of matchAll.call(fileContents, strictSearchRegex)) { + usedMessages.add(match[1] || match[2] || match[3] || match[4]); + } const templateMatches = fileContents.match(templateStringRegex); if (templateMatches) { - // concat doesn't work here for some reason templateMatches.forEach((match) => templateUsage.push(match)); } } @@ -237,21 +254,6 @@ async function verifyEnglishLocale() { return true; // failed === true } -async function findJavascriptFiles(rootDir) { - const javascriptFiles = []; - const contents = await readdir(rootDir, { withFileTypes: true }); - for (const file of contents) { - if (file.isDirectory()) { - javascriptFiles.push( - ...(await findJavascriptFiles(path.join(rootDir, file.name))), - ); - } else if (file.isFile() && file.name.endsWith('.js')) { - javascriptFiles.push(path.join(rootDir, file.name)); - } - } - return javascriptFiles; -} - async function* getFileContents(filenames) { for (const filename of filenames) { yield readFile(filename, 'utf8'); diff --git a/lavamoat/node/policy-override.json b/lavamoat/node/policy-override.json new file mode 100644 index 000000000..85e84f001 --- /dev/null +++ b/lavamoat/node/policy-override.json @@ -0,0 +1,33 @@ +{ + "resources": { + "node-sass": { + "native": true + }, + "module-deps": { + "packages": { + "loose-envify": true + } + }, + "@babel/core": { + "packages": { + "": true, + "@babel/preset-env": true, + "@babel/preset-react": true, + "@babel/plugin-transform-runtime": true, + "@babel/plugin-proposal-class-properties": true, + "@babel/plugin-proposal-object-rest-spread": true, + "@babel/plugin-proposal-optional-chaining": true, + "@babel/plugin-proposal-nullish-coalescing-operator": true + } + }, + "sass": { + "env": "unfrozen", + "builtin": { + "url": true + }, + "globals": { + "Buffer": true + } + } + } +} diff --git a/lavamoat/node/policy.json b/lavamoat/node/policy.json new file mode 100644 index 000000000..123dee86c --- /dev/null +++ b/lavamoat/node/policy.json @@ -0,0 +1,4471 @@ +{ + "resources": { + "@babel/code-frame": { + "globals": { + "console.warn": true, + "process.emitWarning": true + }, + "packages": { + "@babel/highlight": true + } + }, + "@babel/core": { + "builtin": { + "fs": true, + "path": true, + "url": true + }, + "globals": { + "console.log": true, + "process.cwd": true, + "process.env.BABEL_ENV": true, + "process.env.BABEL_SHOW_CONFIG_FOR": true, + "process.env.NODE_ENV": true + }, + "packages": { + "@babel/code-frame": true, + "@babel/generator": true, + "@babel/helper-module-transforms": true, + "@babel/helpers": true, + "@babel/parser": true, + "@babel/template": true, + "@babel/traverse": true, + "@babel/types": true, + "convert-source-map": true, + "debug": true, + "gensync": true, + "json5": true, + "lodash": true, + "resolve": true, + "semver": true, + "source-map": true + } + }, + "@babel/generator": { + "globals": { + "console.error": true + }, + "packages": { + "@babel/types": true, + "jsesc": true, + "source-map": true + } + }, + "@babel/helper-annotate-as-pure": { + "packages": { + "@babel/types": true + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "packages": { + "@babel/helper-explode-assignable-expression": true, + "@babel/types": true + } + }, + "@babel/helper-builder-react-jsx": { + "packages": { + "@babel/helper-annotate-as-pure": true, + "@babel/types": true + } + }, + "@babel/helper-builder-react-jsx-experimental": { + "packages": { + "@babel/helper-annotate-as-pure": true, + "@babel/helper-module-imports": true, + "@babel/types": true + } + }, + "@babel/helper-compilation-targets": { + "globals": { + "console.log": true, + "process.versions.node": true + }, + "packages": { + "@babel/compat-data": true, + "@babel/helper-validator-option": true, + "browserslist": true, + "semver": true + } + }, + "@babel/helper-create-class-features-plugin": { + "globals": { + "console.warn": true + }, + "packages": { + "@babel/core": true, + "@babel/helper-function-name": true, + "@babel/helper-member-expression-to-functions": true, + "@babel/helper-optimise-call-expression": true, + "@babel/helper-replace-supers": true, + "@babel/helper-split-export-declaration": true + } + }, + "@babel/helper-create-regexp-features-plugin": { + "packages": { + "@babel/core": true, + "@babel/helper-annotate-as-pure": true, + "regexpu-core": true + } + }, + "@babel/helper-define-map": { + "packages": { + "@babel/helper-function-name": true, + "@babel/types": true, + "lodash": true + } + }, + "@babel/helper-explode-assignable-expression": { + "packages": { + "@babel/types": true + } + }, + "@babel/helper-function-name": { + "packages": { + "@babel/helper-get-function-arity": true, + "@babel/template": true, + "@babel/types": true + } + }, + "@babel/helper-get-function-arity": { + "packages": { + "@babel/types": true + } + }, + "@babel/helper-hoist-variables": { + "packages": { + "@babel/types": true + } + }, + "@babel/helper-member-expression-to-functions": { + "packages": { + "@babel/types": true + } + }, + "@babel/helper-module-imports": { + "builtin": { + "assert": true + }, + "packages": { + "@babel/types": true + } + }, + "@babel/helper-module-transforms": { + "builtin": { + "assert": true, + "path.basename": true, + "path.extname": true + }, + "packages": { + "@babel/helper-module-imports": true, + "@babel/helper-replace-supers": true, + "@babel/helper-simple-access": true, + "@babel/helper-split-export-declaration": true, + "@babel/helper-validator-identifier": true, + "@babel/template": true, + "@babel/traverse": true, + "@babel/types": true, + "lodash": true + } + }, + "@babel/helper-optimise-call-expression": { + "packages": { + "@babel/types": true + } + }, + "@babel/helper-remap-async-to-generator": { + "packages": { + "@babel/helper-annotate-as-pure": true, + "@babel/helper-wrap-function": true, + "@babel/types": true + } + }, + "@babel/helper-replace-supers": { + "packages": { + "@babel/helper-member-expression-to-functions": true, + "@babel/helper-optimise-call-expression": true, + "@babel/traverse": true, + "@babel/types": true + } + }, + "@babel/helper-simple-access": { + "packages": { + "@babel/types": true + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "packages": { + "@babel/types": true + } + }, + "@babel/helper-split-export-declaration": { + "packages": { + "@babel/types": true + } + }, + "@babel/helper-wrap-function": { + "packages": { + "@babel/helper-function-name": true, + "@babel/template": true, + "@babel/types": true + } + }, + "@babel/helpers": { + "packages": { + "@babel/template": true, + "@babel/traverse": true, + "@babel/types": true + } + }, + "@babel/highlight": { + "packages": { + "@babel/helper-validator-identifier": true, + "chalk": true, + "js-tokens": true + } + }, + "@babel/parser": { + "globals": { + "BigInt": true + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true, + "@babel/helper-remap-async-to-generator": true, + "@babel/plugin-syntax-async-generators": true + } + }, + "@babel/plugin-proposal-class-properties": { + "packages": { + "@babel/helper-create-class-features-plugin": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-proposal-dynamic-import": { + "packages": { + "@babel/helper-plugin-utils": true, + "@babel/plugin-syntax-dynamic-import": true + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true, + "@babel/plugin-syntax-export-namespace-from": true + } + }, + "@babel/plugin-proposal-json-strings": { + "packages": { + "@babel/helper-plugin-utils": true, + "@babel/plugin-syntax-json-strings": true + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true, + "@babel/plugin-syntax-logical-assignment-operators": true + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true, + "@babel/plugin-syntax-nullish-coalescing-operator": true + } + }, + "@babel/plugin-proposal-numeric-separator": { + "packages": { + "@babel/helper-plugin-utils": true, + "@babel/plugin-syntax-numeric-separator": true + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true, + "@babel/plugin-syntax-object-rest-spread": true, + "@babel/plugin-transform-parameters": true + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "packages": { + "@babel/helper-plugin-utils": true, + "@babel/plugin-syntax-optional-catch-binding": true + } + }, + "@babel/plugin-proposal-optional-chaining": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true, + "@babel/helper-skip-transparent-expression-wrappers": true, + "@babel/plugin-syntax-optional-chaining": true + } + }, + "@babel/plugin-proposal-private-methods": { + "packages": { + "@babel/helper-create-class-features-plugin": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "packages": { + "@babel/helper-create-regexp-features-plugin": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-syntax-async-generators": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-syntax-class-properties": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-syntax-dynamic-import": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-syntax-json-strings": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-syntax-jsx": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-syntax-numeric-separator": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-syntax-optional-chaining": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-syntax-top-level-await": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-arrow-functions": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-async-to-generator": { + "packages": { + "@babel/core": true, + "@babel/helper-module-imports": true, + "@babel/helper-plugin-utils": true, + "@babel/helper-remap-async-to-generator": true + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-block-scoping": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-classes": { + "packages": { + "@babel/core": true, + "@babel/helper-annotate-as-pure": true, + "@babel/helper-define-map": true, + "@babel/helper-function-name": true, + "@babel/helper-optimise-call-expression": true, + "@babel/helper-plugin-utils": true, + "@babel/helper-replace-supers": true, + "@babel/helper-split-export-declaration": true, + "globals": true + } + }, + "@babel/plugin-transform-computed-properties": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-destructuring": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-dotall-regex": { + "packages": { + "@babel/helper-create-regexp-features-plugin": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-duplicate-keys": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "packages": { + "@babel/core": true, + "@babel/helper-builder-binary-assignment-operator-visitor": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-for-of": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-function-name": { + "packages": { + "@babel/helper-function-name": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-literals": { + "packages": { + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-member-expression-literals": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-modules-amd": { + "packages": { + "@babel/core": true, + "@babel/helper-module-transforms": true, + "@babel/helper-plugin-utils": true, + "babel-plugin-dynamic-import-node": true + } + }, + "@babel/plugin-transform-modules-commonjs": { + "packages": { + "@babel/core": true, + "@babel/helper-module-transforms": true, + "@babel/helper-plugin-utils": true, + "@babel/helper-simple-access": true, + "babel-plugin-dynamic-import-node": true + } + }, + "@babel/plugin-transform-modules-systemjs": { + "globals": { + "console.warn": true + }, + "packages": { + "@babel/core": true, + "@babel/helper-hoist-variables": true, + "@babel/helper-module-transforms": true, + "@babel/helper-plugin-utils": true, + "@babel/helper-validator-identifier": true, + "babel-plugin-dynamic-import-node": true + } + }, + "@babel/plugin-transform-modules-umd": { + "builtin": { + "path.basename": true, + "path.extname": true + }, + "packages": { + "@babel/core": true, + "@babel/helper-module-transforms": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "packages": { + "@babel/helper-create-regexp-features-plugin": true + } + }, + "@babel/plugin-transform-new-target": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-object-super": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true, + "@babel/helper-replace-supers": true + } + }, + "@babel/plugin-transform-parameters": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-property-literals": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-react-display-name": { + "builtin": { + "path": true + }, + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-react-jsx": { + "packages": { + "@babel/core": true, + "@babel/helper-builder-react-jsx": true, + "@babel/helper-builder-react-jsx-experimental": true, + "@babel/helper-plugin-utils": true, + "@babel/plugin-syntax-jsx": true + } + }, + "@babel/plugin-transform-react-jsx-development": { + "packages": { + "@babel/core": true, + "@babel/helper-builder-react-jsx-experimental": true, + "@babel/helper-plugin-utils": true, + "@babel/plugin-syntax-jsx": true + } + }, + "@babel/plugin-transform-react-jsx-self": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-react-jsx-source": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-react-pure-annotations": { + "packages": { + "@babel/core": true, + "@babel/helper-annotate-as-pure": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-regenerator": { + "packages": { + "regenerator-transform": true + } + }, + "@babel/plugin-transform-reserved-words": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-runtime": { + "builtin": { + "path": true + }, + "packages": { + "@babel/core": true, + "@babel/helper-module-imports": true, + "@babel/helper-plugin-utils": true, + "resolve": true, + "semver": true + } + }, + "@babel/plugin-transform-shorthand-properties": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-spread": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true, + "@babel/helper-skip-transparent-expression-wrappers": true + } + }, + "@babel/plugin-transform-sticky-regex": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-template-literals": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-typeof-symbol": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-unicode-escapes": { + "packages": { + "@babel/core": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/plugin-transform-unicode-regex": { + "packages": { + "@babel/helper-create-regexp-features-plugin": true, + "@babel/helper-plugin-utils": true + } + }, + "@babel/preset-env": { + "globals": { + "console.log": true, + "console.warn": true, + "process.cwd": true, + "process.env.BABEL_ENV": true + }, + "packages": { + "@babel/compat-data": true, + "@babel/helper-compilation-targets": true, + "@babel/helper-module-imports": true, + "@babel/helper-plugin-utils": true, + "@babel/helper-validator-option": true, + "@babel/plugin-proposal-async-generator-functions": true, + "@babel/plugin-proposal-class-properties": true, + "@babel/plugin-proposal-dynamic-import": true, + "@babel/plugin-proposal-export-namespace-from": true, + "@babel/plugin-proposal-json-strings": true, + "@babel/plugin-proposal-logical-assignment-operators": true, + "@babel/plugin-proposal-nullish-coalescing-operator": true, + "@babel/plugin-proposal-numeric-separator": true, + "@babel/plugin-proposal-object-rest-spread": true, + "@babel/plugin-proposal-optional-catch-binding": true, + "@babel/plugin-proposal-optional-chaining": true, + "@babel/plugin-proposal-private-methods": true, + "@babel/plugin-proposal-unicode-property-regex": true, + "@babel/plugin-syntax-async-generators": true, + "@babel/plugin-syntax-class-properties": true, + "@babel/plugin-syntax-dynamic-import": true, + "@babel/plugin-syntax-export-namespace-from": true, + "@babel/plugin-syntax-json-strings": true, + "@babel/plugin-syntax-logical-assignment-operators": true, + "@babel/plugin-syntax-nullish-coalescing-operator": true, + "@babel/plugin-syntax-numeric-separator": true, + "@babel/plugin-syntax-object-rest-spread": true, + "@babel/plugin-syntax-optional-catch-binding": true, + "@babel/plugin-syntax-optional-chaining": true, + "@babel/plugin-syntax-top-level-await": true, + "@babel/plugin-transform-arrow-functions": true, + "@babel/plugin-transform-async-to-generator": true, + "@babel/plugin-transform-block-scoped-functions": true, + "@babel/plugin-transform-block-scoping": true, + "@babel/plugin-transform-classes": true, + "@babel/plugin-transform-computed-properties": true, + "@babel/plugin-transform-destructuring": true, + "@babel/plugin-transform-dotall-regex": true, + "@babel/plugin-transform-duplicate-keys": true, + "@babel/plugin-transform-exponentiation-operator": true, + "@babel/plugin-transform-for-of": true, + "@babel/plugin-transform-function-name": true, + "@babel/plugin-transform-literals": true, + "@babel/plugin-transform-member-expression-literals": true, + "@babel/plugin-transform-modules-amd": true, + "@babel/plugin-transform-modules-commonjs": true, + "@babel/plugin-transform-modules-systemjs": true, + "@babel/plugin-transform-modules-umd": true, + "@babel/plugin-transform-named-capturing-groups-regex": true, + "@babel/plugin-transform-new-target": true, + "@babel/plugin-transform-object-super": true, + "@babel/plugin-transform-parameters": true, + "@babel/plugin-transform-property-literals": true, + "@babel/plugin-transform-regenerator": true, + "@babel/plugin-transform-reserved-words": true, + "@babel/plugin-transform-shorthand-properties": true, + "@babel/plugin-transform-spread": true, + "@babel/plugin-transform-sticky-regex": true, + "@babel/plugin-transform-template-literals": true, + "@babel/plugin-transform-typeof-symbol": true, + "@babel/plugin-transform-unicode-escapes": true, + "@babel/plugin-transform-unicode-regex": true, + "@babel/preset-modules": true, + "@babel/types": true, + "core-js-compat": true, + "semver": true + } + }, + "@babel/preset-react": { + "packages": { + "@babel/helper-plugin-utils": true, + "@babel/plugin-transform-react-display-name": true, + "@babel/plugin-transform-react-jsx": true, + "@babel/plugin-transform-react-jsx-development": true, + "@babel/plugin-transform-react-jsx-self": true, + "@babel/plugin-transform-react-jsx-source": true, + "@babel/plugin-transform-react-pure-annotations": true + } + }, + "@babel/template": { + "packages": { + "@babel/code-frame": true, + "@babel/parser": true, + "@babel/types": true + } + }, + "@babel/traverse": { + "globals": { + "console.log": true, + "console.trace": true, + "process.env.NODE_ENV": true + }, + "packages": { + "@babel/code-frame": true, + "@babel/generator": true, + "@babel/helper-function-name": true, + "@babel/helper-split-export-declaration": true, + "@babel/parser": true, + "@babel/types": true, + "debug": true, + "globals": true + } + }, + "@babel/types": { + "globals": { + "console.trace": true, + "process.env.BABEL_TYPES_8_BREAKING": true + }, + "packages": { + "@babel/helper-validator-identifier": true, + "lodash": true, + "to-fast-properties": true + } + }, + "@choojs/findup": { + "builtin": { + "events.EventEmitter": true, + "fs.access": true, + "fs.accessSync": true, + "fs.exists": true, + "fs.existsSync": true, + "path.join": true, + "util.inherits": true + }, + "globals": { + "console.log": true + } + }, + "@gulp-sourcemaps/identity-map": { + "packages": { + "acorn": true, + "css": true, + "normalize-path": true, + "source-map": true, + "through2": true + } + }, + "@gulp-sourcemaps/map-sources": { + "packages": { + "normalize-path": true, + "through2": true + } + }, + "@nodelib/fs.scandir": { + "builtin": { + "fs.lstat": true, + "fs.lstatSync": true, + "fs.readdir": true, + "fs.readdirSync": true, + "fs.stat": true, + "fs.statSync": true, + "path.sep": true + }, + "globals": { + "process.versions.node.split": true + }, + "packages": { + "@nodelib/fs.stat": true, + "run-parallel": true + } + }, + "@nodelib/fs.stat": { + "builtin": { + "fs.lstat": true, + "fs.lstatSync": true, + "fs.stat": true, + "fs.statSync": true + } + }, + "@nodelib/fs.walk": { + "builtin": { + "events.EventEmitter": true, + "path.sep": true, + "stream.Readable": true + }, + "globals": { + "setImmediate": true + }, + "packages": { + "@nodelib/fs.scandir": true, + "fastq": true + } + }, + "@stylelint/postcss-css-in-js": { + "globals": { + "__dirname": true + }, + "packages": { + "@babel/core": true, + "postcss": true, + "postcss-syntax": true + } + }, + "@stylelint/postcss-markdown": { + "packages": { + "postcss-html": true, + "postcss-syntax": true, + "remark": true, + "unist-util-find-all-after": true + } + }, + "JSONStream": { + "globals": { + "Buffer": true + }, + "packages": { + "jsonparse": true, + "through": true + } + }, + "acorn": { + "globals": { + "BigInt": true, + "define": true + } + }, + "acorn-dynamic-import": { + "packages": { + "acorn": true + } + }, + "acorn-node": { + "globals": { + "BigInt": true + }, + "packages": { + "acorn": true, + "acorn-dynamic-import": true, + "acorn-walk": true, + "xtend": true + } + }, + "acorn-walk": { + "globals": { + "define": true + } + }, + "ajv": { + "packages": { + "fast-deep-equal": true + } + }, + "amdefine": { + "builtin": { + "path.dirname": true + }, + "globals": { + "__filename": true, + "process.nextTick": true + } + }, + "ansi-colors": { + "packages": { + "ansi-wrap": true + } + }, + "ansi-cyan": { + "packages": { + "ansi-wrap": true + } + }, + "ansi-gray": { + "packages": { + "ansi-wrap": true + } + }, + "ansi-red": { + "packages": { + "ansi-wrap": true + } + }, + "ansi-styles": { + "packages": { + "color-convert": true + } + }, + "anymatch": { + "builtin": { + "path.sep": true + }, + "packages": { + "micromatch": true, + "normalize-path": true, + "picomatch": true + } + }, + "append-buffer": { + "builtin": { + "os.EOL": true + }, + "globals": { + "Buffer": true + }, + "packages": { + "buffer-equal": true + } + }, + "arr-diff": { + "packages": { + "arr-flatten": true, + "array-slice": true + } + }, + "arr-filter": { + "packages": { + "make-iterator": true + } + }, + "arr-map": { + "packages": { + "make-iterator": true + } + }, + "array-initial": { + "packages": { + "array-slice": true, + "is-number": true + } + }, + "array-last": { + "packages": { + "is-number": true + } + }, + "array-union": { + "packages": { + "array-uniq": true + } + }, + "async-done": { + "builtin": { + "domain.create": true + }, + "globals": { + "process.nextTick": true + }, + "packages": { + "end-of-stream": true, + "once": true, + "process-nextick-args": true, + "stream-exhaust": true + } + }, + "async-each": { + "globals": { + "define": true + } + }, + "async-settle": { + "packages": { + "async-done": true + } + }, + "atob": { + "globals": { + "Buffer.from": true + } + }, + "autoprefixer": { + "globals": { + "console": true, + "process.cwd": true, + "process.env.AUTOPREFIXER_GRID": true + }, + "packages": { + "browserslist": true, + "caniuse-lite": true, + "colorette": true, + "normalize-range": true, + "num2fraction": true, + "postcss": true, + "postcss-value-parser": true + } + }, + "babelify": { + "builtin": { + "path.extname": true, + "path.resolve": true, + "stream.PassThrough": true, + "stream.Transform": true, + "util": true + }, + "globals": { + "Buffer.concat": true + }, + "packages": { + "@babel/core": true + } + }, + "bach": { + "builtin": { + "assert.ok": true + }, + "packages": { + "arr-filter": true, + "arr-flatten": true, + "arr-map": true, + "array-each": true, + "array-initial": true, + "array-last": true, + "async-done": true, + "async-settle": true, + "now-and-later": true + } + }, + "base": { + "builtin": { + "util.inherits": true + }, + "packages": { + "cache-base": true, + "class-utils": true, + "component-emitter": true, + "define-property": true, + "isobject": true, + "mixin-deep": true, + "pascalcase": true + } + }, + "bl": { + "builtin": { + "util.inherits": true + }, + "packages": { + "readable-stream": true, + "safe-buffer": true + } + }, + "body": { + "builtin": { + "querystring.parse": true + }, + "packages": { + "continuable-cache": true, + "error": true, + "raw-body": true, + "safe-json-parse": true + } + }, + "brace-expansion": { + "packages": { + "balanced-match": true, + "concat-map": true + } + }, + "braces": { + "packages": { + "arr-flatten": true, + "array-unique": true, + "expand-range": true, + "extend-shallow": true, + "fill-range": true, + "isobject": true, + "preserve": true, + "repeat-element": true, + "snapdragon": true, + "snapdragon-node": true, + "split-string": true, + "to-regex": true + } + }, + "brfs": { + "builtin": { + "fs.createReadStream": true, + "fs.readdir": true, + "path": true + }, + "packages": { + "quote-stream": true, + "resolve": true, + "static-module": true, + "through2": true + } + }, + "browser-pack": { + "builtin": { + "fs.readFileSync": true, + "path.join": true, + "path.relative": true + }, + "globals": { + "__dirname": true, + "process.cwd": true + }, + "packages": { + "JSONStream": true, + "combine-source-map": true, + "defined": true, + "safe-buffer": true, + "through2": true, + "umd": true + } + }, + "browser-resolve": { + "builtin": { + "fs.readFile": true, + "fs.readFileSync": true, + "path": true + }, + "globals": { + "__dirname": true, + "process.platform": true + }, + "packages": { + "resolve": true + } + }, + "browserify": { + "builtin": { + "events.EventEmitter": true, + "fs.realpath": true, + "path.dirname": true, + "path.join": true, + "path.relative": true, + "path.resolve": true, + "path.sep": true + }, + "globals": { + "__dirname": true, + "process.cwd": true, + "process.nextTick": true, + "process.platform": true + }, + "packages": { + "browser-pack": true, + "browser-resolve": true, + "cached-path-relative": true, + "concat-stream": true, + "defined": true, + "deps-sort": true, + "has": true, + "htmlescape": true, + "inherits": true, + "insert-module-globals": true, + "labeled-stream-splicer": true, + "module-deps": true, + "read-only-stream": true, + "resolve": true, + "shasum": true, + "syntax-error": true, + "through2": true, + "xtend": true + } + }, + "browserslist": { + "builtin": { + "fs.existsSync": true, + "fs.readFileSync": true, + "fs.statSync": true, + "path.basename": true, + "path.dirname": true, + "path.join": true, + "path.resolve": true + }, + "globals": { + "console.warn": true, + "process.env.BROWSERSLIST": true, + "process.env.BROWSERSLIST_CONFIG": true, + "process.env.BROWSERSLIST_DANGEROUS_EXTEND": true, + "process.env.BROWSERSLIST_DISABLE_CACHE": true, + "process.env.BROWSERSLIST_ENV": true, + "process.env.BROWSERSLIST_IGNORE_OLD_DATA": true, + "process.env.BROWSERSLIST_STATS": true, + "process.env.NODE_ENV": true, + "process.versions.node": true + }, + "packages": { + "caniuse-lite": true, + "electron-to-chromium": true, + "node-releases": true + } + }, + "buffer-crc32": { + "builtin": { + "buffer.Buffer": true + } + }, + "buffer-equal": { + "builtin": { + "buffer.Buffer.isBuffer": true + } + }, + "buffer-from": { + "globals": { + "Buffer": true + } + }, + "cache-base": { + "packages": { + "collection-visit": true, + "component-emitter": true, + "get-value": true, + "has-value": true, + "isobject": true, + "set-value": true, + "to-object-path": true, + "union-value": true, + "unset-value": true + } + }, + "cached-path-relative": { + "builtin": { + "path": true + }, + "globals": { + "process.cwd": true + } + }, + "chalk": { + "globals": { + "process.env.TERM": true, + "process.platform": true + }, + "packages": { + "ansi-styles": true, + "escape-string-regexp": true, + "supports-color": true + } + }, + "chokidar": { + "builtin": { + "events.EventEmitter": true, + "fs": true, + "path.basename": true, + "path.dirname": true, + "path.extname": true, + "path.isAbsolute": true, + "path.join": true, + "path.normalize": true, + "path.relative": true, + "path.resolve": true, + "path.sep": true, + "util.promisify": true + }, + "globals": { + "clearTimeout": true, + "console.error": true, + "process.env.CHOKIDAR_INTERVAL": true, + "process.env.CHOKIDAR_PRINT_FSEVENTS_REQUIRE_ERROR": true, + "process.env.CHOKIDAR_USEPOLLING": true, + "process.nextTick": true, + "process.platform": true, + "process.version.match": true, + "setTimeout": true + }, + "packages": { + "anymatch": true, + "async-each": true, + "braces": true, + "glob-parent": true, + "inherits": true, + "is-binary-path": true, + "is-glob": true, + "normalize-path": true, + "path-is-absolute": true, + "readdirp": true, + "upath": true + } + }, + "class-utils": { + "builtin": { + "util": true + }, + "packages": { + "arr-union": true, + "define-property": true, + "isobject": true, + "static-extend": true + } + }, + "clone": { + "globals": { + "Buffer": true + } + }, + "clone-buffer": { + "builtin": { + "buffer.Buffer": true + } + }, + "clone-regexp": { + "packages": { + "is-regexp": true + } + }, + "clone-stats": { + "builtin": { + "fs.Stats": true + } + }, + "cloneable-readable": { + "packages": { + "inherits": true, + "process-nextick-args": true, + "through2": true + } + }, + "collection-map": { + "packages": { + "arr-map": true, + "for-own": true, + "make-iterator": true + } + }, + "collection-visit": { + "packages": { + "map-visit": true, + "object-visit": true + } + }, + "color-convert": { + "packages": { + "color-name": true + } + }, + "color-support": { + "globals": { + "process": true + } + }, + "combine-source-map": { + "builtin": { + "path.dirname": true, + "path.join": true + }, + "globals": { + "process.platform": true + }, + "packages": { + "convert-source-map": true, + "inline-source-map": true, + "lodash.memoize": true, + "source-map": true + } + }, + "concat-stream": { + "globals": { + "Buffer.concat": true, + "Buffer.isBuffer": true + }, + "packages": { + "buffer-from": true, + "inherits": true, + "readable-stream": true, + "typedarray": true + } + }, + "convert-source-map": { + "builtin": { + "fs.readFileSync": true, + "path.join": true, + "path.resolve": true + }, + "globals": { + "Buffer": true + }, + "packages": { + "safe-buffer": true + } + }, + "core-js-compat": { + "packages": { + "semver": true + } + }, + "core-util-is": { + "globals": { + "Buffer.isBuffer": true + } + }, + "cosmiconfig": { + "builtin": { + "fs": true, + "os": true, + "path": true + }, + "globals": { + "process.cwd": true + }, + "packages": { + "import-fresh": true, + "parse-json": true, + "path-type": true, + "yaml": true + } + }, + "cross-spawn": { + "builtin": { + "child_process.spawn": true, + "child_process.spawnSync": true, + "fs.closeSync": true, + "fs.openSync": true, + "fs.readSync": true, + "path.delimiter": true, + "path.normalize": true, + "path.resolve": true + }, + "globals": { + "Buffer.alloc": true, + "process.chdir": true, + "process.cwd": true, + "process.env": true, + "process.platform": true + }, + "packages": { + "path-key": true, + "shebang-command": true, + "which": true + } + }, + "css": { + "builtin": { + "fs.readFileSync": true, + "path.dirname": true + }, + "packages": { + "inherits": true, + "source-map": true, + "source-map-resolve": true, + "urix": true + } + }, + "d": { + "packages": { + "es5-ext": true + } + }, + "dash-ast": { + "builtin": { + "assert": true + } + }, + "debug": { + "builtin": { + "fs.SyncWriteStream": true, + "net.Socket": true, + "tty.WriteStream": true, + "tty.isatty": true, + "util": true + }, + "globals": { + "chrome": true, + "console": true, + "document": true, + "localStorage": true, + "navigator": true, + "process": true + }, + "packages": { + "ms": true, + "supports-color": true + } + }, + "debug-fabulous": { + "packages": { + "debug": true, + "memoizee": true, + "object-assign": true + } + }, + "deep-extend": { + "globals": { + "Buffer": true + } + }, + "default-resolution": { + "globals": { + "process.version.match": true + } + }, + "define-properties": { + "packages": { + "object-keys": true + } + }, + "define-property": { + "packages": { + "is-descriptor": true, + "isobject": true + } + }, + "del": { + "builtin": { + "path.resolve": true + }, + "packages": { + "globby": true, + "is-path-cwd": true, + "is-path-in-cwd": true, + "p-map": true, + "pify": true, + "rimraf": true + } + }, + "deps-sort": { + "packages": { + "shasum": true, + "through2": true + } + }, + "detective": { + "packages": { + "acorn-node": true, + "defined": true + } + }, + "dir-glob": { + "builtin": { + "path.extname": true, + "path.isAbsolute": true, + "path.join": true, + "path.posix.join": true + }, + "globals": { + "process.cwd": true + }, + "packages": { + "path-type": true + } + }, + "dom-serializer": { + "packages": { + "domelementtype": true, + "entities": true + } + }, + "domhandler": { + "packages": { + "domelementtype": true + } + }, + "domutils": { + "packages": { + "dom-serializer": true, + "domelementtype": true + } + }, + "duplexer": { + "builtin": { + "stream": true + } + }, + "duplexer2": { + "packages": { + "readable-stream": true + } + }, + "duplexify": { + "globals": { + "Buffer": true, + "process.nextTick": true + }, + "packages": { + "end-of-stream": true, + "inherits": true, + "readable-stream": true, + "stream-shift": true + } + }, + "end-of-stream": { + "globals": { + "process.nextTick": true + }, + "packages": { + "once": true + } + }, + "error": { + "builtin": { + "assert": true + }, + "packages": { + "string-template": true, + "xtend": true + } + }, + "error-ex": { + "builtin": { + "util.inherits": true + }, + "packages": { + "is-arrayish": true + } + }, + "es-abstract": { + "globals": { + "AggregateError": true, + "Atomics": true, + "BigInt": true, + "FinalizationRegistry": true, + "SharedArrayBuffer": true, + "WeakRef": true + }, + "packages": { + "function-bind": true, + "has": true, + "has-symbols": true + } + }, + "es5-ext": { + "packages": { + "es6-symbol": true + } + }, + "es6-iterator": { + "packages": { + "d": true, + "es5-ext": true, + "es6-symbol": true + } + }, + "es6-map": { + "packages": { + "d": true, + "es5-ext": true, + "es6-iterator": true, + "es6-symbol": true, + "event-emitter": true + } + }, + "es6-set": { + "packages": { + "d": true, + "es5-ext": true, + "es6-iterator": true, + "es6-symbol": true, + "event-emitter": true + } + }, + "es6-symbol": { + "packages": { + "d": true + } + }, + "es6-weak-map": { + "packages": { + "d": true, + "es5-ext": true, + "es6-iterator": true, + "es6-symbol": true + } + }, + "escodegen": { + "globals": { + "sourceMap.SourceNode": true + }, + "packages": { + "estraverse": true, + "esutils": true, + "source-map": true + } + }, + "event-emitter": { + "packages": { + "d": true, + "es5-ext": true + } + }, + "event-stream": { + "builtin": { + "buffer.Buffer.isBuffer": true, + "stream.Stream": true + }, + "globals": { + "Buffer.concat": true, + "Buffer.isBuffer": true, + "console.error": true, + "process.nextTick": true, + "setImmediate": true + }, + "packages": { + "duplexer": true, + "from": true, + "map-stream": true, + "pause-stream": true, + "split": true, + "stream-combiner": true, + "through": true + } + }, + "execall": { + "packages": { + "clone-regexp": true + } + }, + "expand-brackets": { + "globals": { + "__filename": true + }, + "packages": { + "debug": true, + "define-property": true, + "extend-shallow": true, + "is-posix-bracket": true, + "posix-character-classes": true, + "regex-not": true, + "snapdragon": true, + "to-regex": true + } + }, + "expand-range": { + "packages": { + "fill-range": true + } + }, + "extend-shallow": { + "packages": { + "assign-symbols": true, + "is-extendable": true, + "kind-of": true + } + }, + "extglob": { + "packages": { + "array-unique": true, + "define-property": true, + "expand-brackets": true, + "extend-shallow": true, + "fragment-cache": true, + "is-extglob": true, + "regex-not": true, + "snapdragon": true, + "to-regex": true + } + }, + "fancy-log": { + "builtin": { + "console.Console": true + }, + "globals": { + "console": true, + "process.argv.indexOf": true, + "process.platform": true, + "process.stderr": true, + "process.stdout": true, + "process.version": true + }, + "packages": { + "ansi-gray": true, + "color-support": true, + "parse-node-version": true, + "time-stamp": true + } + }, + "fast-glob": { + "builtin": { + "fs.lstat": true, + "fs.lstatSync": true, + "fs.readdir": true, + "fs.readdirSync": true, + "fs.stat": true, + "fs.statSync": true, + "os.cpus": true, + "path.basename": true, + "path.resolve": true, + "stream.PassThrough": true, + "stream.Readable": true + }, + "globals": { + "process.cwd": true + }, + "packages": { + "@nodelib/fs.stat": true, + "@nodelib/fs.walk": true, + "glob-parent": true, + "merge2": true, + "micromatch": true, + "picomatch": true + } + }, + "fastq": { + "packages": { + "reusify": true + } + }, + "faye-websocket": { + "builtin": { + "net.connect": true, + "stream.Stream": true, + "tls.connect": true, + "url.parse": true, + "util.inherits": true + }, + "globals": { + "Buffer": true, + "clearInterval": true, + "process.nextTick": true, + "setInterval": true + }, + "packages": { + "websocket-driver": true + } + }, + "file-entry-cache": { + "builtin": { + "crypto.createHash": true, + "fs.readFileSync": true, + "fs.statSync": true, + "path.basename": true, + "path.dirname": true + }, + "packages": { + "flat-cache": true + } + }, + "fill-range": { + "builtin": { + "util.inspect": true + }, + "packages": { + "extend-shallow": true, + "is-number": true, + "isobject": true, + "randomatic": true, + "repeat-element": true, + "repeat-string": true, + "to-regex-range": true + } + }, + "first-chunk-stream": { + "builtin": { + "util.inherits": true + }, + "globals": { + "Buffer.concat": true, + "setImmediate": true + }, + "packages": { + "readable-stream": true + } + }, + "flat-cache": { + "builtin": { + "fs.existsSync": true, + "fs.readFileSync": true, + "path.basename": true, + "path.dirname": true, + "path.resolve": true + }, + "globals": { + "__dirname": true + }, + "packages": { + "flatted": true, + "rimraf": true, + "write": true + } + }, + "flush-write-stream": { + "globals": { + "Buffer": true + }, + "packages": { + "inherits": true, + "readable-stream": true + } + }, + "for-own": { + "packages": { + "for-in": true + } + }, + "fragment-cache": { + "packages": { + "map-cache": true + } + }, + "from": { + "builtin": { + "stream": true + }, + "globals": { + "process.nextTick": true + } + }, + "fs-extra": { + "builtin": { + "assert": true, + "fs": true, + "os.tmpdir": true, + "path.dirname": true, + "path.isAbsolute": true, + "path.join": true, + "path.normalize": true, + "path.parse": true, + "path.relative": true, + "path.resolve": true, + "path.sep": true + }, + "globals": { + "Buffer": true, + "console.warn": true, + "process.arch": true, + "process.cwd": true, + "process.platform": true, + "process.umask": true, + "process.versions.node.split": true, + "setTimeout": true + }, + "packages": { + "graceful-fs": true, + "jsonfile": true, + "universalify": true + } + }, + "fs-mkdirp-stream": { + "builtin": { + "path.dirname": true, + "path.resolve": true + }, + "globals": { + "process.umask": true + }, + "packages": { + "graceful-fs": true, + "through2": true + } + }, + "fs.realpath": { + "builtin": { + "fs.lstat": true, + "fs.lstatSync": true, + "fs.readlink": true, + "fs.readlinkSync": true, + "fs.realpath": true, + "fs.realpathSync": true, + "fs.stat": true, + "fs.statSync": true, + "path.normalize": true, + "path.resolve": true + }, + "globals": { + "console.error": true, + "console.trace": true, + "process.env.NODE_DEBUG": true, + "process.nextTick": true, + "process.noDeprecation": true, + "process.platform": true, + "process.throwDeprecation": true, + "process.traceDeprecation": true, + "process.version": true + } + }, + "get-assigned-identifiers": { + "builtin": { + "assert.equal": true + } + }, + "get-stream": { + "builtin": { + "stream.PassThrough": true + }, + "globals": { + "Buffer.concat": true + } + }, + "glob": { + "builtin": { + "assert": true, + "events.EventEmitter": true, + "fs.lstat": true, + "fs.lstatSync": true, + "fs.readdir": true, + "fs.readdirSync": true, + "fs.realpath": true, + "fs.realpathSync": true, + "fs.stat": true, + "fs.statSync": true, + "path.join": true, + "path.resolve": true, + "util": true + }, + "globals": { + "console.error": true, + "process.cwd": true, + "process.nextTick": true, + "process.platform": true + }, + "packages": { + "fs.realpath": true, + "inflight": true, + "inherits": true, + "minimatch": true, + "once": true, + "path-is-absolute": true + } + }, + "glob-base": { + "builtin": { + "path.dirname": true + }, + "packages": { + "glob-parent": true, + "is-glob": true + } + }, + "glob-parent": { + "builtin": { + "os.platform": true, + "path": true + }, + "packages": { + "is-glob": true, + "path-dirname": true + } + }, + "glob-stream": { + "builtin": { + "util.inherits": true + }, + "globals": { + "process.cwd": true, + "process.nextTick": true + }, + "packages": { + "extend": true, + "glob": true, + "glob-parent": true, + "is-negated-glob": true, + "ordered-read-streams": true, + "pumpify": true, + "readable-stream": true, + "remove-trailing-separator": true, + "to-absolute-glob": true, + "unique-stream": true + } + }, + "glob-watcher": { + "packages": { + "anymatch": true, + "async-done": true, + "chokidar": true, + "is-negated-glob": true, + "just-debounce": true, + "object.defaults": true + } + }, + "global-modules": { + "builtin": { + "path.resolve": true + }, + "globals": { + "process.env.OSTYPE": true, + "process.platform": true + }, + "packages": { + "global-prefix": true + } + }, + "global-prefix": { + "builtin": { + "fs.readFileSync": true, + "fs.realpathSync": true, + "os.homedir": true, + "path.dirname": true, + "path.join": true, + "path.resolve": true + }, + "globals": { + "process.env.APPDATA": true, + "process.env.DESTDIR": true, + "process.env.OSTYPE": true, + "process.env.PREFIX": true, + "process.execPath": true, + "process.platform": true + }, + "packages": { + "ini": true, + "which": true + } + }, + "globby": { + "builtin": { + "fs.Stats": true, + "fs.readFile": true, + "fs.readFileSync": true, + "fs.statSync": true, + "path.dirname": true, + "path.isAbsolute": true, + "path.join": true, + "path.posix.join": true, + "path.relative": true, + "stream.Transform": true, + "util.promisify": true + }, + "globals": { + "process.cwd": true + }, + "packages": { + "array-union": true, + "dir-glob": true, + "fast-glob": true, + "glob": true, + "ignore": true, + "merge2": true, + "object-assign": true, + "pify": true, + "pinkie-promise": true, + "slash": true + } + }, + "globjoin": { + "builtin": { + "path.join": true + } + }, + "gonzales-pe": { + "globals": { + "console.error": true, + "define": true + } + }, + "graceful-fs": { + "builtin": { + "assert.equal": true, + "constants.O_SYMLINK": true, + "constants.O_WRONLY": true, + "constants.hasOwnProperty": true, + "fs": true, + "stream.Stream.call": true, + "util": true + }, + "globals": { + "console.error": true, + "process": true, + "setTimeout": true + } + }, + "gulp": { + "builtin": { + "util.inherits": true + }, + "packages": { + "glob-watcher": true, + "undertaker": true, + "vinyl-fs": true + } + }, + "gulp-autoprefixer": { + "globals": { + "Buffer.from": true, + "setImmediate": true + }, + "packages": { + "autoprefixer": true, + "fancy-log": true, + "plugin-error": true, + "postcss": true, + "through2": true, + "vinyl-sourcemaps-apply": true + } + }, + "gulp-livereload": { + "builtin": { + "path.relative": true + }, + "packages": { + "chalk": true, + "debug": true, + "event-stream": true, + "fancy-log": true, + "lodash.assign": true, + "tiny-lr": true + } + }, + "gulp-rename": { + "builtin": { + "path.basename": true, + "path.dirname": true, + "path.extname": true, + "path.join": true, + "stream.Transform": true + } + }, + "gulp-rtlcss": { + "globals": { + "Buffer.from": true + }, + "packages": { + "plugin-error": true, + "rtlcss": true, + "through2": true, + "vinyl-sourcemaps-apply": true + } + }, + "gulp-sass": { + "builtin": { + "path.basename": true, + "path.dirname": true, + "path.extname": true, + "path.join": true, + "path.relative": true + }, + "globals": { + "process.cwd": true, + "process.stderr.write": true + }, + "packages": { + "chalk": true, + "lodash": true, + "node-sass": true, + "plugin-error": true, + "replace-ext": true, + "strip-ansi": true, + "through2": true, + "vinyl-sourcemaps-apply": true + } + }, + "gulp-sourcemaps": { + "builtin": { + "path.dirname": true, + "path.extname": true, + "path.join": true, + "path.relative": true, + "path.resolve": true, + "path.sep": true + }, + "globals": { + "Buffer": true + }, + "packages": { + "@gulp-sourcemaps/identity-map": true, + "@gulp-sourcemaps/map-sources": true, + "acorn": true, + "convert-source-map": true, + "css": true, + "debug-fabulous": true, + "detect-newline": true, + "graceful-fs": true, + "source-map": true, + "strip-bom-string": true, + "through2": true + } + }, + "gulp-stylelint": { + "builtin": { + "fs.mkdir": true, + "fs.writeFile": true, + "path.dirname": true, + "path.resolve": true + }, + "globals": { + "Buffer.from": true, + "process.cwd": true, + "process.nextTick": true + }, + "packages": { + "fancy-log": true, + "plugin-error": true, + "source-map": true, + "strip-ansi": true, + "stylelint": true, + "through2": true + } + }, + "gulp-terser-js": { + "builtin": { + "fs.readFileSync": true, + "path.basename": true, + "path.resolve": true + }, + "globals": { + "Buffer.from": true, + "console.error": true, + "console.log": true, + "process.stdout.columns": true + }, + "packages": { + "plugin-error": true, + "source-map": true, + "terser": true, + "through2": true, + "vinyl-sourcemaps-apply": true + } + }, + "gulp-watch": { + "builtin": { + "path.dirname": true, + "path.normalize": true, + "path.resolve": true + }, + "globals": { + "process.arch": true, + "process.cwd": true, + "process.platform": true, + "process.version": true, + "setTimeout": true + }, + "packages": { + "ansi-colors": true, + "anymatch": true, + "chokidar": true, + "fancy-log": true, + "glob-parent": true, + "object-assign": true, + "path-is-absolute": true, + "plugin-error": true, + "readable-stream": true, + "slash": true, + "vinyl": true, + "vinyl-file": true + } + }, + "gulp-zip": { + "builtin": { + "path.join": true + }, + "packages": { + "get-stream": true, + "plugin-error": true, + "through2": true, + "vinyl": true, + "yazl": true + } + }, + "has": { + "packages": { + "function-bind": true + } + }, + "has-flag": { + "globals": { + "process.argv": true + } + }, + "has-value": { + "packages": { + "get-value": true, + "has-values": true, + "isobject": true + } + }, + "has-values": { + "packages": { + "is-number": true, + "kind-of": true + } + }, + "htmlparser2": { + "builtin": { + "buffer.Buffer": true, + "events.EventEmitter": true, + "string_decoder.StringDecoder": true + }, + "packages": { + "domelementtype": true, + "domhandler": true, + "domutils": true, + "entities": true, + "inherits": true, + "readable-stream": true + } + }, + "http-parser-js": { + "builtin": { + "assert.equal": true, + "assert.ok": true + } + }, + "ignore": { + "globals": { + "process": true + } + }, + "import-fresh": { + "builtin": { + "path.dirname": true + }, + "globals": { + "__filename": true + }, + "packages": { + "parent-module": true, + "resolve-from": true + } + }, + "inflight": { + "globals": { + "process.nextTick": true + }, + "packages": { + "once": true, + "wrappy": true + } + }, + "inherits": { + "builtin": { + "util.inherits": true + } + }, + "ini": { + "globals": { + "process": true + } + }, + "inline-source-map": { + "globals": { + "Buffer": true + }, + "packages": { + "source-map": true + } + }, + "insert-module-globals": { + "builtin": { + "path.dirname": true, + "path.isAbsolute": true, + "path.relative": true, + "path.sep": true + }, + "globals": { + "Buffer.concat": true, + "Buffer.isBuffer": true + }, + "packages": { + "acorn-node": true, + "combine-source-map": true, + "path-is-absolute": true, + "through2": true, + "undeclared-identifiers": true, + "xtend": true + } + }, + "is-absolute": { + "packages": { + "is-relative": true, + "is-windows": true + } + }, + "is-accessor-descriptor": { + "packages": { + "kind-of": true + } + }, + "is-alphanumerical": { + "packages": { + "is-alphabetical": true, + "is-decimal": true + } + }, + "is-binary-path": { + "builtin": { + "path.extname": true + }, + "packages": { + "binary-extensions": true + } + }, + "is-core-module": { + "globals": { + "process.versions": true + }, + "packages": { + "has": true + } + }, + "is-data-descriptor": { + "packages": { + "kind-of": true + } + }, + "is-descriptor": { + "packages": { + "is-accessor-descriptor": true, + "is-data-descriptor": true, + "kind-of": true + } + }, + "is-equal-shallow": { + "packages": { + "is-primitive": true + } + }, + "is-extendable": { + "packages": { + "is-plain-object": true + } + }, + "is-glob": { + "packages": { + "is-extglob": true + } + }, + "is-number": { + "packages": { + "kind-of": true + } + }, + "is-odd": { + "packages": { + "is-number": true + } + }, + "is-path-cwd": { + "builtin": { + "path.resolve": true + }, + "globals": { + "process.cwd": true + } + }, + "is-path-in-cwd": { + "globals": { + "process.cwd": true + }, + "packages": { + "is-path-inside": true + } + }, + "is-path-inside": { + "builtin": { + "path.resolve": true + }, + "packages": { + "path-is-inside": true + } + }, + "is-plain-object": { + "packages": { + "isobject": true + } + }, + "is-relative": { + "packages": { + "is-unc-path": true + } + }, + "is-unc-path": { + "packages": { + "unc-path-regex": true + } + }, + "is-windows": { + "globals": { + "define": true, + "isWindows": "write", + "process": true + } + }, + "isexe": { + "builtin": { + "fs": true + }, + "globals": { + "TESTING_WINDOWS": true, + "process.env.PATHEXT": true, + "process.getgid": true, + "process.getuid": true, + "process.platform": true + } + }, + "isobject": { + "packages": { + "isarray": true + } + }, + "jsesc": { + "globals": { + "Buffer.isBuffer": true + } + }, + "json-stable-stringify": { + "packages": { + "jsonify": true + } + }, + "json5": { + "globals": { + "console.warn": true + } + }, + "jsonfile": { + "builtin": { + "fs": true + }, + "globals": { + "Buffer.isBuffer": true + }, + "packages": { + "graceful-fs": true + } + }, + "jsonparse": { + "globals": { + "Buffer": true + } + }, + "just-debounce": { + "globals": { + "clearTimeout": true, + "setTimeout": true + } + }, + "kind-of": { + "globals": { + "Buffer": true + }, + "packages": { + "is-buffer": true + } + }, + "labeled-stream-splicer": { + "packages": { + "inherits": true, + "isarray": true, + "stream-splicer": true + } + }, + "last-run": { + "builtin": { + "assert": true + }, + "packages": { + "default-resolution": true, + "es6-weak-map": true + } + }, + "lazystream": { + "builtin": { + "util.inherits": true + }, + "packages": { + "readable-stream": true + } + }, + "lead": { + "globals": { + "process.nextTick": true + }, + "packages": { + "flush-write-stream": true + } + }, + "lodash": { + "globals": { + "define": true + } + }, + "log-symbols": { + "globals": { + "process.env.CI": true, + "process.env.TERM": true, + "process.platform": true + }, + "packages": { + "chalk": true + } + }, + "loose-envify": { + "builtin": { + "stream.PassThrough": true, + "stream.Transform": true, + "util.inherits": true + }, + "globals": { + "process.env": true + }, + "packages": { + "js-tokens": true + } + }, + "lru-queue": { + "packages": { + "es5-ext": true + } + }, + "magic-string": { + "globals": { + "Buffer": true, + "btoa": true, + "console.warn": true + }, + "packages": { + "sourcemap-codec": true + } + }, + "make-iterator": { + "packages": { + "kind-of": true + } + }, + "map-stream": { + "builtin": { + "stream.Stream": true + }, + "globals": { + "process.nextTick": true + } + }, + "map-visit": { + "builtin": { + "util.inspect": true + }, + "packages": { + "object-visit": true + } + }, + "markdown-table": { + "packages": { + "repeat-string": true + } + }, + "math-random": { + "builtin": { + "crypto.randomBytes": true + } + }, + "mdast-util-compact": { + "packages": { + "unist-util-visit": true + } + }, + "memoizee": { + "globals": { + "clearTimeout": true, + "setTimeout": true + }, + "packages": { + "d": true, + "es5-ext": true, + "event-emitter": true, + "is-promise": true, + "lru-queue": true, + "next-tick": true, + "timers-ext": true + } + }, + "merge-source-map": { + "packages": { + "source-map": true + } + }, + "merge2": { + "builtin": { + "stream.PassThrough": true + }, + "globals": { + "process.nextTick": true + } + }, + "micromatch": { + "builtin": { + "path.basename": true, + "path.sep": true, + "util.inspect": true + }, + "globals": { + "process": true + }, + "packages": { + "arr-diff": true, + "array-unique": true, + "braces": true, + "define-property": true, + "expand-brackets": true, + "extend-shallow": true, + "extglob": true, + "filename-regex": true, + "fragment-cache": true, + "is-extglob": true, + "is-glob": true, + "kind-of": true, + "nanomatch": true, + "normalize-path": true, + "object.omit": true, + "object.pick": true, + "parse-glob": true, + "picomatch": true, + "regex-cache": true, + "regex-not": true, + "snapdragon": true, + "to-regex": true + } + }, + "minimatch": { + "builtin": { + "path": true + }, + "globals": { + "console.error": true + }, + "packages": { + "brace-expansion": true + } + }, + "mixin-deep": { + "packages": { + "for-in": true, + "is-extendable": true + } + }, + "mkdirp": { + "builtin": { + "fs": true, + "path.dirname": true, + "path.resolve": true + } + }, + "module-deps": { + "builtin": { + "fs.createReadStream": true, + "fs.readFile": true, + "path.delimiter": true, + "path.dirname": true, + "path.join": true, + "path.resolve": true + }, + "globals": { + "process.cwd": true, + "process.env.NODE_PATH": true, + "process.nextTick": true, + "process.platform": true, + "setTimeout": true, + "tr": true + }, + "packages": { + "browser-resolve": true, + "cached-path-relative": true, + "concat-stream": true, + "defined": true, + "detective": true, + "duplexer2": true, + "inherits": true, + "parents": true, + "readable-stream": true, + "resolve": true, + "stream-combiner2": true, + "through2": true, + "xtend": true + } + }, + "nanomatch": { + "builtin": { + "path.basename": true, + "path.sep": true, + "util.inspect": true + }, + "packages": { + "arr-diff": true, + "array-unique": true, + "define-property": true, + "extend-shallow": true, + "fragment-cache": true, + "is-odd": true, + "is-windows": true, + "kind-of": true, + "object.pick": true, + "regex-not": true, + "snapdragon": true, + "to-regex": true + } + }, + "next-tick": { + "globals": { + "MutationObserver": true, + "WebKitMutationObserver": true, + "document": true, + "process": true, + "setImmediate": true, + "setTimeout": true + } + }, + "node-sass": { + "builtin": { + "fs.existsSync": true, + "fs.readFileSync": true, + "fs.readdirSync": true, + "os.EOL": true, + "path.delimiter": true, + "path.join": true, + "path.resolve": true + }, + "globals": { + "__dirname": true, + "console.log": true, + "process.arch": true, + "process.argv.slice": true, + "process.cwd": true, + "process.env.SASS_BINARY_DIR": true, + "process.env.SASS_BINARY_NAME": true, + "process.env.SASS_BINARY_PATH": true, + "process.env.SASS_BINARY_SITE": true, + "process.env.SASS_PATH.split": true, + "process.env.hasOwnProperty": true, + "process.env.npm_config_cache": true, + "process.env.npm_config_sass_binary_cache": true, + "process.env.npm_config_sass_binary_dir": true, + "process.env.npm_config_sass_binary_name": true, + "process.env.npm_config_sass_binary_path": true, + "process.env.npm_config_sass_binary_site": true, + "process.execPath": true, + "process.platform": true, + "process.sass": "write", + "process.versions.modules": true + }, + "packages": { + "lodash": true, + "mkdirp": true, + "true-case-path": true + } + }, + "normalize-path": { + "packages": { + "remove-trailing-separator": true + } + }, + "normalize-selector": { + "globals": { + "define": true + } + }, + "now-and-later": { + "packages": { + "once": true + } + }, + "object-copy": { + "packages": { + "copy-descriptor": true, + "define-property": true, + "kind-of": true + } + }, + "object-inspect": { + "builtin": { + "util.inspect": true + }, + "globals": { + "BigInt": true, + "HTMLElement": true + } + }, + "object-visit": { + "packages": { + "isobject": true + } + }, + "object.assign": { + "packages": { + "define-properties": true, + "es-abstract": true, + "has-symbols": true, + "object-keys": true + } + }, + "object.defaults": { + "packages": { + "array-each": true, + "array-slice": true, + "for-own": true, + "isobject": true + } + }, + "object.omit": { + "packages": { + "for-own": true, + "is-extendable": true + } + }, + "object.pick": { + "packages": { + "isobject": true + } + }, + "object.reduce": { + "packages": { + "for-own": true, + "make-iterator": true + } + }, + "once": { + "packages": { + "wrappy": true + } + }, + "ordered-read-streams": { + "builtin": { + "util.inherits": true + }, + "packages": { + "readable-stream": true + } + }, + "parent-module": { + "packages": { + "callsites": true + } + }, + "parents": { + "globals": { + "process.cwd": true, + "process.platform": true + }, + "packages": { + "path-platform": true + } + }, + "parse-entities": { + "packages": { + "character-entities": true, + "character-entities-legacy": true, + "character-reference-invalid": true, + "is-alphanumerical": true, + "is-decimal": true, + "is-hexadecimal": true + } + }, + "parse-glob": { + "packages": { + "glob-base": true, + "is-dotfile": true, + "is-extglob": true, + "is-glob": true + } + }, + "parse-json": { + "packages": { + "@babel/code-frame": true, + "error-ex": true, + "json-parse-better-errors": true, + "lines-and-columns": true + } + }, + "path-dirname": { + "builtin": { + "path": true, + "util.inspect": true + }, + "globals": { + "process.platform": true + } + }, + "path-is-absolute": { + "globals": { + "process.platform": true + } + }, + "path-is-inside": { + "builtin": { + "path.sep": true + }, + "globals": { + "process.platform": true + } + }, + "path-key": { + "globals": { + "process.env": true, + "process.platform": true + } + }, + "path-parse": { + "globals": { + "process.platform": true + } + }, + "path-platform": { + "builtin": { + "path": true, + "util.isObject": true, + "util.isString": true + }, + "globals": { + "process.cwd": true, + "process.env": true, + "process.platform": true + } + }, + "path-type": { + "builtin": { + "fs": true, + "util.promisify": true + } + }, + "pause-stream": { + "packages": { + "through": true + } + }, + "picomatch": { + "builtin": { + "path.basename": true, + "path.sep": true + }, + "globals": { + "process.platform": true, + "process.version.slice": true + } + }, + "pinkie": { + "globals": { + "process": true, + "setImmediate": true, + "setTimeout": true + } + }, + "pinkie-promise": { + "packages": { + "pinkie": true + } + }, + "plugin-error": { + "builtin": { + "util.inherits": true + }, + "packages": { + "ansi-colors": true, + "ansi-cyan": true, + "ansi-red": true, + "arr-diff": true, + "arr-union": true, + "extend-shallow": true + } + }, + "postcss": { + "builtin": { + "fs": true, + "path": true + }, + "globals": { + "Buffer": true, + "atob": true, + "btoa": true, + "console": true, + "process.env.NODE_ENV": true + }, + "packages": { + "chalk": true, + "source-map": true, + "supports-color": true + } + }, + "postcss-html": { + "globals": { + "__dirname": true + }, + "packages": { + "htmlparser2": true, + "postcss-syntax": true + } + }, + "postcss-less": { + "packages": { + "postcss": true + } + }, + "postcss-reporter": { + "packages": { + "lodash": true + } + }, + "postcss-safe-parser": { + "packages": { + "postcss": true + } + }, + "postcss-sass": { + "packages": { + "gonzales-pe": true, + "postcss": true + } + }, + "postcss-scss": { + "packages": { + "postcss": true + } + }, + "postcss-selector-parser": { + "builtin": { + "util.deprecate": true + }, + "packages": { + "cssesc": true, + "indexes-of": true, + "uniq": true + } + }, + "postcss-syntax": { + "builtin": { + "path.isAbsolute": true, + "path.resolve": true, + "path.sep": true + }, + "packages": { + "postcss": true + } + }, + "process-nextick-args": { + "globals": { + "process": true + } + }, + "pump": { + "builtin": { + "fs": true + }, + "globals": { + "process.version": true + }, + "packages": { + "end-of-stream": true, + "once": true + } + }, + "pumpify": { + "packages": { + "duplexify": true, + "inherits": true, + "pump": true + } + }, + "quote-stream": { + "globals": { + "Buffer": true + }, + "packages": { + "buffer-equal": true, + "through2": true + } + }, + "randomatic": { + "packages": { + "is-number": true, + "kind-of": true, + "math-random": true + } + }, + "randomcolor": { + "globals": { + "define": true + } + }, + "raw-body": { + "globals": { + "Buffer.concat": true, + "process.nextTick": true + }, + "packages": { + "bytes": true, + "string_decoder": true + } + }, + "rc": { + "builtin": { + "fs.readFileSync": true, + "fs.statSync": true, + "path.dirname": true, + "path.join": true + }, + "globals": { + "process.argv.slice": true, + "process.cwd": true, + "process.env": true, + "process.platform": true + }, + "packages": { + "deep-extend": true, + "ini": true, + "minimist": true, + "strip-json-comments": true + } + }, + "read-only-stream": { + "packages": { + "readable-stream": true + } + }, + "readable-stream": { + "builtin": { + "buffer.Buffer": true, + "events.EventEmitter": true, + "stream": true, + "util": true + }, + "globals": { + "process.browser": true, + "process.env.READABLE_STREAM": true, + "process.nextTick": true, + "process.stderr": true, + "process.stdout": true, + "process.version.slice": true, + "setImmediate": true + }, + "packages": { + "core-util-is": true, + "inherits": true, + "isarray": true, + "process-nextick-args": true, + "safe-buffer": true, + "string_decoder": true, + "util-deprecate": true + } + }, + "readdirp": { + "builtin": { + "fs": true, + "path.join": true, + "path.relative": true, + "path.resolve": true, + "path.sep": true, + "stream.Readable": true, + "util.inherits": true, + "util.promisify": true + }, + "globals": { + "process.platform": true, + "setImmediate": true + }, + "packages": { + "graceful-fs": true, + "micromatch": true, + "picomatch": true, + "readable-stream": true + } + }, + "regenerate": { + "globals": { + "define": true + } + }, + "regenerator-transform": { + "builtin": { + "assert": true, + "util.inherits": true + }, + "packages": { + "@babel/runtime": true + } + }, + "regex-cache": { + "packages": { + "is-equal-shallow": true + } + }, + "regex-not": { + "packages": { + "extend-shallow": true, + "safe-regex": true + } + }, + "regexpu-core": { + "packages": { + "regenerate": true, + "regjsgen": true, + "regjsparser": true, + "unicode-match-property-ecmascript": true, + "unicode-match-property-value-ecmascript": true + } + }, + "regjsgen": { + "globals": { + "define": true + } + }, + "regjsparser": { + "globals": { + "regjsparser": "write" + } + }, + "remark": { + "packages": { + "remark-parse": true, + "remark-stringify": true, + "unified": true + } + }, + "remark-parse": { + "packages": { + "ccount": true, + "collapse-white-space": true, + "is-alphabetical": true, + "is-decimal": true, + "is-whitespace-character": true, + "is-word-character": true, + "markdown-escapes": true, + "parse-entities": true, + "repeat-string": true, + "state-toggle": true, + "trim": true, + "trim-trailing-lines": true, + "unherit": true, + "unist-util-remove-position": true, + "vfile-location": true, + "xtend": true + } + }, + "remark-stringify": { + "packages": { + "ccount": true, + "is-alphanumeric": true, + "is-decimal": true, + "is-whitespace-character": true, + "longest-streak": true, + "markdown-escapes": true, + "markdown-table": true, + "mdast-util-compact": true, + "parse-entities": true, + "repeat-string": true, + "state-toggle": true, + "stringify-entities": true, + "unherit": true, + "xtend": true + } + }, + "remove-bom-buffer": { + "packages": { + "is-buffer": true, + "is-utf8": true + } + }, + "remove-bom-stream": { + "packages": { + "remove-bom-buffer": true, + "safe-buffer": true, + "through2": true + } + }, + "remove-trailing-separator": { + "globals": { + "process.platform": true + } + }, + "replace-ext": { + "builtin": { + "path.basename": true, + "path.dirname": true, + "path.extname": true, + "path.join": true + } + }, + "resolve": { + "builtin": { + "fs.readFile": true, + "fs.readFileSync": true, + "fs.realpath": true, + "fs.realpathSync": true, + "fs.stat": true, + "fs.statSync": true, + "path": true + }, + "globals": { + "process.nextTick": true, + "process.platform": true, + "process.versions": true + }, + "packages": { + "is-core-module": true, + "path-parse": true + } + }, + "resolve-from": { + "builtin": { + "fs.realpathSync": true, + "module._nodeModulePaths": true, + "module._resolveFilename": true, + "path.join": true, + "path.resolve": true + } + }, + "resolve-options": { + "packages": { + "value-or-function": true + } + }, + "rimraf": { + "builtin": { + "assert": true, + "fs": true, + "path.join": true + }, + "globals": { + "process.platform": true, + "setTimeout": true + }, + "packages": { + "glob": true + } + }, + "rtlcss": { + "builtin": { + "fs.readFileSync": true, + "path.join": true, + "path.normalize": true + }, + "globals": { + "process.cwd": true, + "process.env.HOME": true, + "process.env.HOMEPATH": true, + "process.env.USERPROFILE": true + }, + "packages": { + "@choojs/findup": true, + "postcss": true, + "strip-json-comments": true + } + }, + "run-parallel": { + "globals": { + "process.nextTick": true + } + }, + "safe-buffer": { + "builtin": { + "buffer": true + } + }, + "safe-regex": { + "packages": { + "ret": true + } + }, + "sass": { + "builtin": { + "fs": true, + "readline": true + }, + "globals": { + "HTMLElement": true, + "InternalError": true, + "TextDecoder": true, + "WorkerGlobalScope": true, + "__dirname": true, + "__filename": true, + "__non_webpack_require__": true, + "__webpack_require__": true, + "console": true, + "dartExperimentalFixupGetTag": true, + "dartMainRunner": true, + "dartNativeDispatchHooksTransformer": true, + "dartPrint": true, + "document": true, + "load": true, + "navigator": true, + "print": true, + "process": true, + "setTimeout": true, + "version": true + }, + "packages": { + "chokidar": true + } + }, + "scope-analyzer": { + "builtin": { + "assert.ok": true, + "assert.strictEqual": true + }, + "packages": { + "array-from": true, + "dash-ast": true, + "es6-map": true, + "es6-set": true, + "es6-symbol": true, + "estree-is-function": true, + "get-assigned-identifiers": true + } + }, + "semver": { + "globals": { + "console": true, + "process": true + } + }, + "set-value": { + "packages": { + "extend-shallow": true, + "is-extendable": true, + "is-plain-object": true, + "split-string": true + } + }, + "shasum": { + "builtin": { + "buffer.Buffer.isBuffer": true, + "crypto.createHash": true + }, + "packages": { + "json-stable-stringify": true + } + }, + "shebang-command": { + "packages": { + "shebang-regex": true + } + }, + "signal-exit": { + "builtin": { + "assert.equal": true, + "events": true + }, + "globals": { + "process": true + } + }, + "slice-ansi": { + "packages": { + "ansi-styles": true, + "astral-regex": true, + "is-fullwidth-code-point": true + } + }, + "snapdragon": { + "builtin": { + "fs.readFileSync": true, + "path.dirname": true, + "util.inspect": true + }, + "globals": { + "__filename": true + }, + "packages": { + "base": true, + "debug": true, + "define-property": true, + "extend-shallow": true, + "map-cache": true, + "source-map": true, + "source-map-resolve": true, + "use": true + } + }, + "snapdragon-node": { + "packages": { + "define-property": true, + "isobject": true, + "snapdragon-util": true + } + }, + "snapdragon-util": { + "packages": { + "kind-of": true + } + }, + "source-map": { + "builtin": { + "fs.readFile": true, + "path.join": true + }, + "globals": { + "WebAssembly.instantiate": true, + "__dirname": true, + "console.debug": true, + "console.time": true, + "console.timeEnd": true, + "fetch": true + }, + "packages": { + "amdefine": true + } + }, + "source-map-resolve": { + "builtin": { + "url.resolve": true + }, + "globals": { + "setImmediate": true + }, + "packages": { + "atob": true, + "decode-uri-component": true, + "source-map-url": true, + "urix": true + } + }, + "source-map-url": { + "globals": { + "define": true + } + }, + "sourcemap-codec": { + "globals": { + "define": true + } + }, + "specificity": { + "globals": { + "define": true + } + }, + "split": { + "builtin": { + "string_decoder.StringDecoder": true + }, + "packages": { + "through": true + } + }, + "split-string": { + "packages": { + "extend-shallow": true + } + }, + "static-eval": { + "packages": { + "escodegen": true + } + }, + "static-extend": { + "builtin": { + "util.inherits": true + }, + "packages": { + "define-property": true, + "object-copy": true + } + }, + "static-module": { + "packages": { + "acorn-node": true, + "concat-stream": true, + "convert-source-map": true, + "duplexer2": true, + "escodegen": true, + "has": true, + "magic-string": true, + "merge-source-map": true, + "object-inspect": true, + "readable-stream": true, + "scope-analyzer": true, + "shallow-copy": true, + "static-eval": true, + "through2": true + } + }, + "stream-combiner": { + "packages": { + "duplexer": true + } + }, + "stream-combiner2": { + "packages": { + "duplexer2": true, + "readable-stream": true + } + }, + "stream-exhaust": { + "builtin": { + "stream.Writable": true, + "util.inherits": true + }, + "globals": { + "setImmediate": true + } + }, + "stream-splicer": { + "globals": { + "process.nextTick": true, + "setImmediate": true + }, + "packages": { + "inherits": true, + "readable-stream": true + } + }, + "string-width": { + "packages": { + "emoji-regex": true, + "is-fullwidth-code-point": true, + "strip-ansi": true + } + }, + "string_decoder": { + "builtin": { + "buffer.Buffer": true + }, + "packages": { + "safe-buffer": true + } + }, + "stringify-entities": { + "packages": { + "character-entities-html4": true, + "character-entities-legacy": true, + "is-alphanumerical": true, + "is-decimal": true, + "is-hexadecimal": true + } + }, + "strip-ansi": { + "packages": { + "ansi-regex": true + } + }, + "strip-bom": { + "globals": { + "Buffer.isBuffer": true + }, + "packages": { + "is-utf8": true + } + }, + "strip-bom-stream": { + "packages": { + "first-chunk-stream": true, + "strip-bom": true + } + }, + "stylelint": { + "builtin": { + "fs.lstatSync": true, + "fs.readFile": true, + "fs.readFileSync": true, + "fs.stat": true, + "os.EOL": true, + "path.dirname": true, + "path.isAbsolute": true, + "path.join": true, + "path.normalize": true, + "path.relative": true, + "path.resolve": true, + "path.sep": true, + "url.URL": true + }, + "globals": { + "__dirname": true, + "assert": true, + "console.warn": true, + "process.cwd": true, + "process.env.NODE_ENV": true, + "process.stdout.columns": true, + "process.stdout.isTTY": true + }, + "packages": { + "@stylelint/postcss-css-in-js": true, + "@stylelint/postcss-markdown": true, + "autoprefixer": true, + "balanced-match": true, + "chalk": true, + "cosmiconfig": true, + "debug": true, + "execall": true, + "file-entry-cache": true, + "global-modules": true, + "globby": true, + "globjoin": true, + "html-tags": true, + "ignore": true, + "import-lazy": true, + "imurmurhash": true, + "known-css-properties": true, + "leven": true, + "lodash": true, + "log-symbols": true, + "mathml-tag-names": true, + "micromatch": true, + "normalize-selector": true, + "postcss": true, + "postcss-html": true, + "postcss-less": true, + "postcss-media-query-parser": true, + "postcss-reporter": true, + "postcss-resolve-nested-selector": true, + "postcss-safe-parser": true, + "postcss-sass": true, + "postcss-scss": true, + "postcss-selector-parser": true, + "postcss-syntax": true, + "postcss-value-parser": true, + "resolve-from": true, + "slash": true, + "specificity": true, + "string-width": true, + "style-search": true, + "sugarss": true, + "svg-tags": true, + "table": true, + "write-file-atomic": true + } + }, + "sugarss": { + "packages": { + "postcss": true + } + }, + "supports-color": { + "builtin": { + "os.release": true, + "tty.isatty": true + }, + "globals": { + "process.env": true, + "process.platform": true, + "process.stderr": true, + "process.stdout": true, + "process.versions.node.split": true + }, + "packages": { + "has-flag": true + } + }, + "syntax-error": { + "packages": { + "acorn-node": true + } + }, + "table": { + "globals": { + "process.stdout.write": true + }, + "packages": { + "ajv": true, + "lodash": true, + "slice-ansi": true, + "string-width": true + } + }, + "terser": { + "globals": { + "Buffer.from": true, + "atob": true, + "btoa": true, + "define": true + }, + "packages": { + "source-map": true + } + }, + "through": { + "builtin": { + "stream": true + }, + "globals": { + "process.nextTick": true + } + }, + "through2": { + "builtin": { + "util.inherits": true + }, + "globals": { + "process.nextTick": true + }, + "packages": { + "readable-stream": true, + "xtend": true + } + }, + "through2-filter": { + "packages": { + "through2": true, + "xtend": true + } + }, + "timers-ext": { + "packages": { + "es5-ext": true + } + }, + "tiny-lr": { + "builtin": { + "events": true, + "fs": true, + "http": true, + "https": true, + "url.parse": true + }, + "globals": { + "console.error": true + }, + "packages": { + "body": true, + "debug": true, + "faye-websocket": true, + "object-assign": true, + "qs": true + } + }, + "to-absolute-glob": { + "builtin": { + "path.resolve": true + }, + "globals": { + "process.cwd": true, + "process.platform": true + }, + "packages": { + "is-absolute": true, + "is-negated-glob": true + } + }, + "to-object-path": { + "packages": { + "kind-of": true + } + }, + "to-regex": { + "packages": { + "define-property": true, + "extend-shallow": true, + "regex-not": true, + "safe-regex": true + } + }, + "to-regex-range": { + "packages": { + "is-number": true, + "repeat-string": true + } + }, + "to-through": { + "packages": { + "through2": true + } + }, + "true-case-path": { + "builtin": { + "path.normalize": true, + "path.parse": true + }, + "globals": { + "process.platform": true + }, + "packages": { + "glob": true + } + }, + "typedarray-to-buffer": { + "globals": { + "Buffer.from": true + }, + "packages": { + "is-typedarray": true + } + }, + "undeclared-identifiers": { + "packages": { + "acorn-node": true, + "get-assigned-identifiers": true, + "xtend": true + } + }, + "undertaker": { + "builtin": { + "assert": true, + "events.EventEmitter": true, + "util.inherits": true + }, + "globals": { + "process.env.UNDERTAKER_SETTLE": true, + "process.env.UNDERTAKER_TIME_RESOLUTION": true, + "process.hrtime": true + }, + "packages": { + "arr-flatten": true, + "arr-map": true, + "bach": true, + "collection-map": true, + "es6-weak-map": true, + "last-run": true, + "object.defaults": true, + "object.reduce": true, + "undertaker-registry": true + } + }, + "unherit": { + "packages": { + "inherits": true, + "xtend": true + } + }, + "unicode-match-property-ecmascript": { + "packages": { + "unicode-canonical-property-names-ecmascript": true, + "unicode-property-aliases-ecmascript": true + } + }, + "unified": { + "packages": { + "bail": true, + "extend": true, + "is-buffer": true, + "is-plain-obj": true, + "trough": true, + "vfile": true + } + }, + "union-value": { + "packages": { + "arr-union": true, + "get-value": true, + "is-extendable": true, + "set-value": true + } + }, + "unique-stream": { + "packages": { + "json-stable-stringify": true, + "through2-filter": true + } + }, + "unist-util-find-all-after": { + "packages": { + "unist-util-is": true + } + }, + "unist-util-remove-position": { + "packages": { + "unist-util-visit": true + } + }, + "unist-util-visit": { + "packages": { + "unist-util-visit-parents": true + } + }, + "unist-util-visit-parents": { + "packages": { + "unist-util-is": true + } + }, + "unset-value": { + "packages": { + "has-value": true, + "isobject": true + } + }, + "upath": { + "builtin": { + "path": true + } + }, + "urix": { + "builtin": { + "path.sep": true + } + }, + "use": { + "packages": { + "kind-of": true + } + }, + "util-deprecate": { + "builtin": { + "util.deprecate": true + } + }, + "vfile": { + "builtin": { + "path.basename": true, + "path.dirname": true, + "path.extname": true, + "path.join": true, + "path.sep": true + }, + "globals": { + "process.cwd": true + }, + "packages": { + "is-buffer": true, + "replace-ext": true, + "vfile-message": true + } + }, + "vfile-message": { + "packages": { + "unist-util-stringify-position": true + } + }, + "vinyl": { + "builtin": { + "buffer.Buffer": true, + "path.basename": true, + "path.dirname": true, + "path.extname": true, + "path.join": true, + "path.normalize": true, + "path.relative": true, + "stream.PassThrough": true, + "stream.Stream": true, + "util.inspect.custom": true + }, + "globals": { + "process.cwd": true + }, + "packages": { + "clone": true, + "clone-buffer": true, + "clone-stats": true, + "cloneable-readable": true, + "remove-trailing-separator": true, + "replace-ext": true + } + }, + "vinyl-buffer": { + "packages": { + "bl": true, + "through2": true + } + }, + "vinyl-file": { + "builtin": { + "path.resolve": true + }, + "globals": { + "process.cwd": true + }, + "packages": { + "graceful-fs": true, + "pify": true, + "pinkie-promise": true, + "strip-bom": true, + "strip-bom-stream": true, + "vinyl": true + } + }, + "vinyl-fs": { + "builtin": { + "os.platform": true, + "path.relative": true, + "path.resolve": true, + "util.inherits": true + }, + "globals": { + "Buffer.isBuffer": true, + "process.cwd": true, + "process.geteuid": true, + "process.getuid": true, + "process.nextTick": true + }, + "packages": { + "fs-mkdirp-stream": true, + "glob-stream": true, + "graceful-fs": true, + "is-valid-glob": true, + "lazystream": true, + "lead": true, + "object.assign": true, + "pumpify": true, + "readable-stream": true, + "remove-bom-buffer": true, + "remove-bom-stream": true, + "resolve-options": true, + "through2": true, + "to-through": true, + "value-or-function": true, + "vinyl": true, + "vinyl-sourcemap": true + } + }, + "vinyl-source-stream": { + "builtin": { + "path.resolve": true + }, + "globals": { + "process.cwd": true + }, + "packages": { + "through2": true, + "vinyl": true + } + }, + "vinyl-sourcemap": { + "builtin": { + "path.dirname": true, + "path.join": true, + "path.relative": true, + "path.resolve": true + }, + "globals": { + "Buffer": true + }, + "packages": { + "append-buffer": true, + "convert-source-map": true, + "graceful-fs": true, + "normalize-path": true, + "now-and-later": true, + "remove-bom-buffer": true, + "vinyl": true + } + }, + "vinyl-sourcemaps-apply": { + "packages": { + "source-map": true + } + }, + "watchify": { + "builtin": { + "path.join": true + }, + "globals": { + "clearTimeout": true, + "setTimeout": true + }, + "packages": { + "anymatch": true, + "chokidar": true, + "through2": true, + "xtend": true + } + }, + "websocket-driver": { + "builtin": { + "crypto.createHash": true, + "crypto.randomBytes": true, + "events.EventEmitter": true, + "stream.Stream": true, + "url.parse": true, + "util.inherits": true + }, + "globals": { + "Buffer": true, + "process.version.match": true + }, + "packages": { + "http-parser-js": true, + "websocket-extensions": true + } + }, + "which": { + "builtin": { + "path.join": true + }, + "globals": { + "process.cwd": true, + "process.env.OSTYPE": true, + "process.env.PATH": true, + "process.env.PATHEXT": true, + "process.platform": true + }, + "packages": { + "isexe": true + } + }, + "write": { + "builtin": { + "fs.createWriteStream": true, + "fs.writeFile": true, + "fs.writeFileSync": true, + "path.dirname": true + }, + "packages": { + "mkdirp": true + } + }, + "write-file-atomic": { + "builtin": { + "fs.chmod": true, + "fs.chmodSync": true, + "fs.chown": true, + "fs.chownSync": true, + "fs.close": true, + "fs.closeSync": true, + "fs.fsync": true, + "fs.fsyncSync": true, + "fs.open": true, + "fs.openSync": true, + "fs.realpath": true, + "fs.realpathSync": true, + "fs.rename": true, + "fs.renameSync": true, + "fs.stat": true, + "fs.statSync": true, + "fs.unlink": true, + "fs.unlinkSync": true, + "fs.write": true, + "fs.writeSync": true, + "path.resolve": true, + "util.promisify": true, + "worker_threads.threadId": true + }, + "globals": { + "Buffer.isBuffer": true, + "__filename": true, + "process.getuid": true, + "process.pid": true + }, + "packages": { + "imurmurhash": true, + "is-typedarray": true, + "signal-exit": true, + "typedarray-to-buffer": true + } + }, + "yaml": { + "globals": { + "Buffer": true, + "_YAML_SILENCE_DEPRECATION_WARNINGS": true, + "_YAML_SILENCE_WARNINGS": true, + "atob": true, + "btoa": true, + "console.warn": true, + "process": true + } + }, + "yazl": { + "builtin": { + "events.EventEmitter": true, + "fs.createReadStream": true, + "fs.stat": true, + "stream.PassThrough": true, + "stream.Transform": true, + "util.inherits": true, + "zlib.DeflateRaw": true, + "zlib.deflateRaw": true + }, + "globals": { + "Buffer": true, + "setImmediate": true, + "utf8FileName.length": true + }, + "packages": { + "buffer-crc32": true + } + } + } +} \ No newline at end of file diff --git a/package.json b/package.json index 08dbb9fb9..dfc829560 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,11 @@ "version": "0.0.0", "private": true, "scripts": { - "setup": "yarn install && yarn allow-scripts", + "setup": "yarn install && yarn patch-package && yarn allow-scripts", + "setup-ci": "yarn install --frozen-lockfile --har && yarn patch-package && yarn allow-scripts", "start": "yarn build dev", "dist": "yarn build prod", - "build": "node development/build/index.js", + "build": "lavamoat development/build/index.js", "start:test": "yarn build testDev", "benchmark:chrome": "SELENIUM_BROWSER=chrome node test/e2e/benchmark.js", "benchmark:firefox": "SELENIUM_BROWSER=firefox node test/e2e/benchmark.js", @@ -30,7 +31,7 @@ "test:coverage": "nyc --silent --check-coverage yarn test:unit:strict && nyc --silent --no-clean yarn test:unit:lax && nyc report --reporter=text --reporter=html", "test:coverage:strict": "nyc --check-coverage yarn test:unit:strict", "test:coverage:path": "nyc --check-coverage yarn test:unit:path", - "ganache:start": "./development/run-ganache", + "ganache:start": "./development/run-ganache.sh", "sentry:publish": "node ./development/sentry-publish.js", "lint": "prettier --check ./**/*.json && eslint . --ext js && yarn lint:styles", "lint:fix": "prettier --write ./**/*.json && eslint . --ext js --fix", @@ -52,7 +53,9 @@ "storybook:build": "build-storybook -c .storybook -o storybook-build --static-dir ./app ./storybook/images", "storybook:deploy": "storybook-to-ghpages --existing-output-dir storybook-build --remote storybook --branch master", "update-changelog": "./development/auto-changelog.sh", - "generate:migration": "./development/generate-migration.sh" + "generate:migration": "./development/generate-migration.sh", + "lavamoat:auto": "lavamoat ./development/build/index.js --writeAutoPolicy", + "lavamoat:debug": "lavamoat ./development/build/index.js --writeAutoPolicyDebug" }, "resolutions": { "**/configstore/dot-prop": "^5.1.1", @@ -67,7 +70,6 @@ "3box/ipfs/ipld-zcash/zcash-bitcore-lib/elliptic": "^6.5.3", "3box/**/libp2p-crypto/node-forge": "^0.10.0", "3box/**/libp2p-keychain/node-forge": "^0.10.0", - "browserify-derequire/derequire": "^2.1.1", "analytics-node/axios": "^0.21.1" }, "dependencies": { @@ -82,7 +84,7 @@ "@metamask/controllers": "^5.1.0", "@metamask/eth-ledger-bridge-keyring": "^0.2.6", "@metamask/eth-token-tracker": "^3.0.1", - "@metamask/etherscan-link": "^1.4.0", + "@metamask/etherscan-link": "^1.4.1", "@metamask/inpage-provider": "^8.0.4", "@metamask/jazzicon": "^2.0.0", "@metamask/logo": "^2.5.0", @@ -133,6 +135,7 @@ "fuse.js": "^3.2.0", "globalthis": "^1.0.1", "human-standard-token-abi": "^2.0.0", + "immer": "^8.0.1", "json-rpc-engine": "^6.1.0", "json-rpc-middleware-stream": "^2.1.1", "jsonschema": "^1.2.4", @@ -140,7 +143,6 @@ "lodash": "^4.17.19", "loglevel": "^1.4.1", "luxon": "^1.24.1", - "multihashes": "^0.4.12", "nanoid": "^2.1.6", "nonce-tracker": "^1.0.0", "obj-multiplex": "^1.0.0", @@ -161,7 +163,6 @@ "react-popper": "^2.2.3", "react-redux": "^7.2.0", "react-router-dom": "^5.1.2", - "react-select": "^1.0.0", "react-simple-file-input": "^2.0.0", "react-tippy": "^1.2.2", "react-toggle-button": "^2.2.0", @@ -176,6 +177,7 @@ "single-call-balance-checker-abi": "^1.0.0", "swappable-obj-proxy": "^1.1.0", "textarea-caret": "^3.0.1", + "unicode-confusables": "^0.1.1", "valid-url": "^1.0.9", "web3": "^0.20.7", "web3-stream-provider": "^4.0.0" @@ -197,23 +199,20 @@ "@metamask/forwarder": "^1.1.0", "@metamask/test-dapp": "^4.0.1", "@sentry/cli": "^1.58.0", - "@storybook/addon-actions": "^6.1.9", - "@storybook/addon-backgrounds": "^6.1.9", - "@storybook/addon-knobs": "^6.1.9", + "@storybook/addon-actions": "^6.1.17", + "@storybook/addon-backgrounds": "^6.1.17", + "@storybook/addon-knobs": "^6.1.17", "@storybook/addon-toolbars": "^6.1.17", - "@storybook/core": "^6.1.9", - "@storybook/react": "^6.1.9", - "@storybook/storybook-deployer": "^2.8.6", + "@storybook/core": "^6.1.17", + "@storybook/react": "^6.1.17", + "@storybook/storybook-deployer": "^2.8.7", "@testing-library/react": "^10.4.8", "@testing-library/react-hooks": "^3.2.1", "@types/react": "^16.9.53", "addons-linter": "1.14.0", - "babel-loader": "^8.0.6", "babelify": "^10.0.0", "brfs": "^2.0.2", "browserify": "^16.5.1", - "browserify-derequire": "^1.0.1", - "chai": "^4.1.0", "chalk": "^3.0.0", "chromedriver": "^79.0.0", "concurrently": "^5.2.0", @@ -221,7 +220,6 @@ "cross-spawn": "^7.0.3", "css-loader": "^2.1.1", "del": "^3.0.0", - "deps-dump": "^1.1.0", "enzyme": "^3.10.0", "enzyme-adapter-react-16": "^1.15.1", "eslint": "^7.7.0", @@ -233,7 +231,6 @@ "eslint-plugin-react-hooks": "^4.0.4", "fancy-log": "^1.3.3", "fast-glob": "^3.2.2", - "file-loader": "^1.1.11", "fs-extra": "^8.1.0", "ganache-cli": "^6.12.1", "ganache-core": "^2.13.1", @@ -241,13 +238,8 @@ "get-port": "^5.1.0", "gulp": "^4.0.2", "gulp-autoprefixer": "^5.0.0", - "gulp-babel": "^8.0.0", - "gulp-debug": "^3.2.0", - "gulp-imagemin": "^6.1.0", "gulp-livereload": "4.0.0", - "gulp-multi-process": "^1.3.1", "gulp-rename": "^2.0.0", - "gulp-replace": "^1.0.0", "gulp-rtlcss": "^1.4.0", "gulp-sass": "^4.1.0", "gulp-sourcemaps": "^2.6.0", @@ -257,23 +249,24 @@ "gulp-zip": "^4.0.0", "jsdom": "^11.2.0", "koa": "^2.7.0", + "lavamoat": "^5.1.4", + "lavamoat-viz": "^6.0.4", "lockfile-lint": "^4.0.0", "loose-envify": "^1.4.0", "mocha": "^7.2.0", "nock": "^9.0.14", "node-fetch": "^2.6.1", "nyc": "^15.0.0", + "patch-package": "^6.2.2", "polyfill-crypto.getrandomvalues": "^1.0.0", "prettier": "^2.1.1", "prettier-plugin-sort-json": "^0.0.1", "proxyquire": "^2.1.3", "randomcolor": "^0.5.4", "rc": "^1.2.8", - "react-devtools": "^4.8.0", - "react-test-renderer": "^16.12.0", + "react-devtools": "^4.10.1", "read-installed": "^4.0.3", "redux-mock-store": "^1.5.4", - "regenerator-runtime": "^0.13.3", "remote-redux-devtools": "^0.5.16", "remotedev-server": "^0.3.1", "resolve-url-loader": "^3.1.2", @@ -302,12 +295,11 @@ "lavamoat": { "allowScripts": { "node-sass": true, - "optipng-bin": true, - "gifsicle": true, - "jpegtran-bin": true, "chromedriver": true, "geckodriver": true, "@sentry/cli": true, + "electron": true, + "sqlite3": true, "core-js": false, "core-js-pure": false, "keccak": false, @@ -316,17 +308,14 @@ "sha3": false, "bufferutil": false, "utf-8-validate": false, - "electron": false, "ejs": false, "sc-uws": false, - "sqlite3": false, "leveldown": false, "ursa-optional": false, "gc-stats": false, "github:assemblyscript/assemblyscript": false, "tiny-secp256k1": false, - "@lavamoat/preinstall-always-fail": false, - "fsevents": false + "@lavamoat/preinstall-always-fail": false } } } diff --git a/patches/error+7.0.2.patch b/patches/error+7.0.2.patch new file mode 100644 index 000000000..9ade384e1 --- /dev/null +++ b/patches/error+7.0.2.patch @@ -0,0 +1,16 @@ +diff --git a/node_modules/error/typed.js b/node_modules/error/typed.js +index fe9effd..e554568 100644 +--- a/node_modules/error/typed.js ++++ b/node_modules/error/typed.js +@@ -22,8 +22,10 @@ function TypedError(args) { + args.name = errorName[0].toUpperCase() + errorName.substr(1); + } + +- extend(createError, args); + createError._name = args.name; ++ //remove args.name, name is not extensible under strict mode (lavamoat) ++ delete args.name ++ extend(createError, args); + + return createError; + diff --git a/patches/node-sass+4.14.1.patch b/patches/node-sass+4.14.1.patch new file mode 100644 index 000000000..bcc3054f3 --- /dev/null +++ b/patches/node-sass+4.14.1.patch @@ -0,0 +1,13 @@ +diff --git a/node_modules/node-sass/lib/index.js b/node_modules/node-sass/lib/index.js +index 3f20708..425e97c 100644 +--- a/node_modules/node-sass/lib/index.js ++++ b/node_modules/node-sass/lib/index.js +@@ -166,6 +166,8 @@ function buildIncludePaths(options) { + options.includePaths = options.includePaths || []; + + if (process.env.hasOwnProperty('SASS_PATH')) { ++ //quick workaround for SASS_PATH.split undefined under lavamoat ++ process.env.SASS_PATH.split = String.prototype.split + options.includePaths = options.includePaths.concat( + process.env.SASS_PATH.split(path.delimiter) + ); diff --git a/patches/plugin-error+1.0.1.patch b/patches/plugin-error+1.0.1.patch new file mode 100644 index 000000000..dec4ceffa --- /dev/null +++ b/patches/plugin-error+1.0.1.patch @@ -0,0 +1,12 @@ +diff --git a/node_modules/plugin-error/index.js b/node_modules/plugin-error/index.js +index a4d360d..d2be4a2 100644 +--- a/node_modules/plugin-error/index.js ++++ b/node_modules/plugin-error/index.js +@@ -54,7 +54,6 @@ function PluginError(plugin, message, options) { + return this._messageWithDetails() + '\nStack:'; + }.bind(this); + +- Error.captureStackTrace(safety, arguments.callee || this.constructor); + this.__safety = safety; + } + if (!this.plugin) { diff --git a/patches/sass+1.32.4.patch b/patches/sass+1.32.4.patch new file mode 100644 index 000000000..6939fd235 --- /dev/null +++ b/patches/sass+1.32.4.patch @@ -0,0 +1,25 @@ +diff --git a/node_modules/sass/sass.dart.js b/node_modules/sass/sass.dart.js +index fedd867..fef6a8f 100644 +--- a/node_modules/sass/sass.dart.js ++++ b/node_modules/sass/sass.dart.js +@@ -16,6 +16,9 @@ self.scheduleImmediate = self.setImmediate + // CommonJS globals. + self.exports = exports; + ++exports.bridgeJson = (target) => JSON.parse(JSON.stringify(target)) ++exports.bridgeFn = (target) => ((...args) => target(...args)) ++ + // Node.js specific exports, check to see if they exist & or polyfilled + + if (typeof process !== "undefined") { +@@ -3616,10 +3619,6 @@ self.fs = require("fs"); + return C.PlainJavaScriptObject_methods; + if (proto === Object.prototype) + return C.PlainJavaScriptObject_methods; +- if (typeof $constructor == "function") { +- Object.defineProperty($constructor, J.JS_INTEROP_INTERCEPTOR_TAG(), {value: C.UnknownJavaScriptObject_methods, enumerable: false, writable: true, configurable: true}); +- return C.UnknownJavaScriptObject_methods; +- } + return C.UnknownJavaScriptObject_methods; + }, + JS_INTEROP_INTERCEPTOR_TAG: function() { diff --git a/patches/stylelint+13.6.1.patch b/patches/stylelint+13.6.1.patch new file mode 100644 index 000000000..8683fb39e --- /dev/null +++ b/patches/stylelint+13.6.1.patch @@ -0,0 +1,28 @@ +diff --git a/node_modules/stylelint/lib/syntaxes/index.js b/node_modules/stylelint/lib/syntaxes/index.js +index 7afa0c3..73eaa00 100644 +--- a/node_modules/stylelint/lib/syntaxes/index.js ++++ b/node_modules/stylelint/lib/syntaxes/index.js +@@ -1,16 +1,13 @@ + 'use strict'; + +-// Use this require pattern so that syntaxes can be bundled separately +-const importLazy = require('import-lazy')(require); +- + /** @typedef {import('../getPostcssResult').Syntax} Syntax */ + /** @type {{[k: string]: Syntax}} */ + module.exports = { +- 'css-in-js': importLazy('./syntax-css-in-js'), +- html: importLazy('./syntax-html'), +- less: importLazy('./syntax-less'), +- markdown: importLazy('./syntax-markdown'), +- sass: importLazy('./syntax-sass'), +- scss: importLazy('./syntax-scss'), +- sugarss: importLazy('./syntax-sugarss'), ++ 'css-in-js': require('./syntax-css-in-js'), ++ html: require('./syntax-html'), ++ less: require('./syntax-less'), ++ markdown: require('./syntax-markdown'), ++ sass: require('./syntax-sass'), ++ scss: require('./syntax-scss'), ++ sugarss: require('./syntax-sugarss'), + }; diff --git a/shared/constants/app.js b/shared/constants/app.js index d0369cd82..93c843846 100644 --- a/shared/constants/app.js +++ b/shared/constants/app.js @@ -27,4 +27,6 @@ export const MESSAGE_TYPE = { PERSONAL_SIGN: 'personal_sign', WATCH_ASSET: 'wallet_watchAsset', WATCH_ASSET_LEGACY: 'metamask_watchAsset', + ADD_ETHEREUM_CHAIN: 'wallet_addEthereumChain', + SWITCH_ETHEREUM_CHAIN: 'metamask_switchEthereumChain', }; diff --git a/shared/constants/network.js b/shared/constants/network.js index d3a53e519..a3cb2e7c9 100644 --- a/shared/constants/network.js +++ b/shared/constants/network.js @@ -31,6 +31,13 @@ export const GOERLI_DISPLAY_NAME = 'Goerli'; export const INFURA_PROVIDER_TYPES = [ROPSTEN, RINKEBY, KOVAN, MAINNET, GOERLI]; +export const TEST_CHAINS = [ + ROPSTEN_CHAIN_ID, + RINKEBY_CHAIN_ID, + GOERLI_CHAIN_ID, + KOVAN_CHAIN_ID, +]; + export const NETWORK_TYPE_TO_ID_MAP = { [ROPSTEN]: { networkId: ROPSTEN_NETWORK_ID, chainId: ROPSTEN_CHAIN_ID }, [RINKEBY]: { networkId: RINKEBY_NETWORK_ID, chainId: RINKEBY_CHAIN_ID }, diff --git a/shared/modules/utils.js b/shared/modules/network.utils.js similarity index 100% rename from shared/modules/utils.js rename to shared/modules/network.utils.js diff --git a/shared/modules/rpc.utils.js b/shared/modules/rpc.utils.js new file mode 100644 index 000000000..7d4d51318 --- /dev/null +++ b/shared/modules/rpc.utils.js @@ -0,0 +1,54 @@ +import getFetchWithTimeout from './fetch-with-timeout'; + +const fetchWithTimeout = getFetchWithTimeout(30000); + +/** + * Makes a JSON RPC request to the given URL, with the given RPC method and params. + * + * @param {string} rpcUrl - The RPC endpoint URL to target. + * @param {string} rpcMethod - The RPC method to request. + * @param {Array} [rpcParams] - The RPC method params. + * @returns {Promise} Returns the result of the RPC method call, + * or throws an error in case of failure. + */ +export async function jsonRpcRequest(rpcUrl, rpcMethod, rpcParams = []) { + let fetchUrl = rpcUrl; + const headers = { + 'Content-Type': 'application/json', + }; + // Convert basic auth URL component to Authorization header + const { origin, pathname, username, password, search } = new URL(rpcUrl); + // URLs containing username and password needs special processing + if (username && password) { + const encodedAuth = Buffer.from(`${username}:${password}`).toString( + 'base64', + ); + headers.Authorization = `Basic ${encodedAuth}`; + fetchUrl = `${origin}${pathname}${search}`; + } + const jsonRpcResponse = await fetchWithTimeout(fetchUrl, { + method: 'POST', + body: JSON.stringify({ + id: Date.now().toString(), + jsonrpc: '2.0', + method: rpcMethod, + params: rpcParams, + }), + headers, + cache: 'default', + }).then((httpResponse) => httpResponse.json()); + + if ( + !jsonRpcResponse || + Array.isArray(jsonRpcResponse) || + typeof jsonRpcResponse !== 'object' + ) { + throw new Error(`RPC endpoint ${rpcUrl} returned non-object response.`); + } + const { error, result } = jsonRpcResponse; + + if (error) { + throw new Error(error?.message || error); + } + return result; +} diff --git a/shared/modules/transaction.utils.js b/shared/modules/transaction.utils.js new file mode 100644 index 000000000..9e89679f8 --- /dev/null +++ b/shared/modules/transaction.utils.js @@ -0,0 +1,6 @@ +export function transactionMatchesNetwork(transaction, chainId, networkId) { + if (typeof transaction.chainId !== 'undefined') { + return transaction.chainId === chainId; + } + return transaction.metamaskNetworkId === networkId; +} diff --git a/test/unit/actions/tx_test.js b/test/unit/actions/tx_test.js index c1a969b75..120fcdb73 100644 --- a/test/unit/actions/tx_test.js +++ b/test/unit/actions/tx_test.js @@ -3,6 +3,7 @@ import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import * as actions from '../../../ui/app/store/actions'; import * as actionConstants from '../../../ui/app/store/actionConstants'; +import { ROPSTEN_CHAIN_ID } from '../../../shared/constants/network'; const middlewares = [thunk]; const mockStore = configureMockStore(middlewares); @@ -19,6 +20,9 @@ describe('tx confirmation screen', function () { time: 1457634084250, }, }, + provider: { + chainId: ROPSTEN_CHAIN_ID, + }, }, }; diff --git a/test/unit/app/controllers/ens-controller-test.js b/test/unit/app/controllers/ens-controller-test.js index c210fa3f8..d21a723e1 100644 --- a/test/unit/app/controllers/ens-controller-test.js +++ b/test/unit/app/controllers/ens-controller-test.js @@ -1,31 +1,38 @@ import assert from 'assert'; import sinon from 'sinon'; -import { ObservableStore } from '@metamask/obs-store'; import EnsController from '../../../../app/scripts/controllers/ens'; const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000'; const ZERO_X_ERROR_ADDRESS = '0x'; describe('EnsController', function () { + let currentChainId; + let getCurrentChainId; + let onNetworkDidChange; + beforeEach(function () { + currentChainId = '0x3'; + getCurrentChainId = () => currentChainId; + onNetworkDidChange = sinon.spy(); + }); + afterEach(function () { + sinon.restore(); + }); describe('#constructor', function () { it('should construct the controller given a provider and a network', async function () { - const currentNetworkId = '3'; - const networkStore = new ObservableStore(currentNetworkId); const ens = new EnsController({ provider: {}, - networkStore, + getCurrentChainId, + onNetworkDidChange, }); assert.ok(ens._ens); }); it('should construct the controller given an existing ENS instance', async function () { - const networkStore = { - subscribe: sinon.spy(), - }; const ens = new EnsController({ ens: {}, - networkStore, + getCurrentChainId, + onNetworkDidChange, }); assert.ok(ens._ens); @@ -35,15 +42,13 @@ describe('EnsController', function () { describe('#reverseResolveName', function () { it('should resolve to an ENS name', async function () { const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'; - const networkStore = { - subscribe: sinon.spy(), - }; const ens = new EnsController({ ens: { reverse: sinon.stub().withArgs(address).returns('peaksignal.eth'), lookup: sinon.stub().withArgs('peaksignal.eth').returns(address), }, - networkStore, + onNetworkDidChange, + getCurrentChainId, }); const name = await ens.reverseResolveAddress(address); @@ -54,15 +59,13 @@ describe('EnsController', function () { const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'; const reverse = sinon.stub().withArgs(address).returns('peaksignal.eth'); const lookup = sinon.stub().withArgs('peaksignal.eth').returns(address); - const networkStore = { - subscribe: sinon.spy(), - }; const ens = new EnsController({ ens: { reverse, lookup, }, - networkStore, + getCurrentChainId, + onNetworkDidChange, }); assert.equal(await ens.reverseResolveAddress(address), 'peaksignal.eth'); @@ -73,15 +76,13 @@ describe('EnsController', function () { it('should fail if the name is registered to a different address than the reverse-resolved', async function () { const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'; - const networkStore = { - subscribe: sinon.spy(), - }; const ens = new EnsController({ ens: { reverse: sinon.stub().withArgs(address).returns('peaksignal.eth'), lookup: sinon.stub().withArgs('peaksignal.eth').returns('0xfoo'), }, - networkStore, + onNetworkDidChange, + getCurrentChainId, }); const name = await ens.reverseResolveAddress(address); @@ -90,15 +91,13 @@ describe('EnsController', function () { it('should throw an error when the lookup resolves to the zero address', async function () { const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'; - const networkStore = { - subscribe: sinon.spy(), - }; const ens = new EnsController({ ens: { reverse: sinon.stub().withArgs(address).returns('peaksignal.eth'), lookup: sinon.stub().withArgs('peaksignal.eth').returns(ZERO_ADDRESS), }, - networkStore, + getCurrentChainId, + onNetworkDidChange, }); try { @@ -111,9 +110,6 @@ describe('EnsController', function () { it('should throw an error the lookup resolves to the zero x address', async function () { const address = '0x8e5d75d60224ea0c33d0041e75de68b1c3cb6dd5'; - const networkStore = { - subscribe: sinon.spy(), - }; const ens = new EnsController({ ens: { reverse: sinon.stub().withArgs(address).returns('peaksignal.eth'), @@ -122,7 +118,8 @@ describe('EnsController', function () { .withArgs('peaksignal.eth') .returns(ZERO_X_ERROR_ADDRESS), }, - networkStore, + onNetworkDidChange, + getCurrentChainId, }); try { diff --git a/test/unit/app/controllers/incoming-transactions-test.js b/test/unit/app/controllers/incoming-transactions-test.js index 86e629609..d476d18cb 100644 --- a/test/unit/app/controllers/incoming-transactions-test.js +++ b/test/unit/app/controllers/incoming-transactions-test.js @@ -19,6 +19,7 @@ import { TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, } from '../../../../shared/constants/transaction'; +import { NETWORK_EVENTS } from '../../../../app/scripts/controllers/network'; const IncomingTransactionsController = proxyquire( '../../../../app/scripts/controllers/incoming-transactions', @@ -161,7 +162,7 @@ describe('IncomingTransactionsController', function () { assert(incomingTransactionsController.networkController.on.calledOnce); assert.equal( incomingTransactionsController.networkController.on.getCall(0).args[0], - 'networkDidChange', + NETWORK_EVENTS.NETWORK_DID_CHANGE, ); const networkControllerListenerCallback = incomingTransactionsController.networkController.on.getCall( 0, @@ -271,7 +272,8 @@ describe('IncomingTransactionsController', function () { '0xfake': { blockNumber: '10', hash: '0xfake', - metamaskNetworkId: '3', + metamaskNetworkId: ROPSTEN_NETWORK_ID, + chainId: ROPSTEN_CHAIN_ID, status: TRANSACTION_STATUSES.CONFIRMED, time: 16000000000000000, transactionCategory: TRANSACTION_CATEGORIES.INCOMING, @@ -614,7 +616,8 @@ describe('IncomingTransactionsController', function () { '0xfake': { blockNumber: '10', hash: '0xfake', - metamaskNetworkId: '3', + metamaskNetworkId: ROPSTEN_NETWORK_ID, + chainId: ROPSTEN_CHAIN_ID, status: TRANSACTION_STATUSES.CONFIRMED, time: 16000000000000000, transactionCategory: TRANSACTION_CATEGORIES.INCOMING, @@ -768,7 +771,8 @@ describe('IncomingTransactionsController', function () { '0xfake': { blockNumber: '10', hash: '0xfake', - metamaskNetworkId: '3', + metamaskNetworkId: ROPSTEN_NETWORK_ID, + chainId: ROPSTEN_CHAIN_ID, status: TRANSACTION_STATUSES.CONFIRMED, time: 16000000000000000, transactionCategory: TRANSACTION_CATEGORIES.INCOMING, @@ -1346,6 +1350,7 @@ describe('IncomingTransactionsController', function () { blockNumber: 333, id: 54321, metamaskNetworkId: ROPSTEN_NETWORK_ID, + chainId: ROPSTEN_CHAIN_ID, status: TRANSACTION_STATUSES.FAILED, time: 4444000, txParams: { @@ -1391,6 +1396,7 @@ describe('IncomingTransactionsController', function () { blockNumber: 333, id: 54321, metamaskNetworkId: ROPSTEN_NETWORK_ID, + chainId: ROPSTEN_CHAIN_ID, status: TRANSACTION_STATUSES.CONFIRMED, time: 4444000, txParams: { diff --git a/test/unit/app/controllers/metametrics-test.js b/test/unit/app/controllers/metametrics-test.js index 8f2de0c02..839b323c4 100644 --- a/test/unit/app/controllers/metametrics-test.js +++ b/test/unit/app/controllers/metametrics-test.js @@ -8,6 +8,7 @@ import { METAMETRICS_BACKGROUND_PAGE_OBJECT, } from '../../../../shared/constants/metametrics'; import waitUntilCalled from '../../../lib/wait-until-called'; +import { NETWORK_EVENTS } from '../../../../app/scripts/controllers/network'; const segment = createSegmentMock(2, 10000); const segmentLegacy = createSegmentMock(2, 10000); @@ -49,7 +50,7 @@ function getMockNetworkController( provider = { type: NETWORK }, ) { let networkStore = { chainId, provider }; - const on = sinon.stub().withArgs('networkDidChange'); + const on = sinon.stub().withArgs(NETWORK_EVENTS.NETWORK_DID_CHANGE); const updateState = (newState) => { networkStore = { ...networkStore, ...newState }; on.getCall(0).args[1](); @@ -99,7 +100,7 @@ function getMetaMetricsController({ ), onNetworkDidChange: networkController.on.bind( networkController, - 'networkDidChange', + NETWORK_EVENTS.NETWORK_DID_CHANGE, ), preferencesStore, version: '0.0.1', diff --git a/test/unit/app/controllers/permissions/permissions-controller-test.js b/test/unit/app/controllers/permissions/permissions-controller-test.js index 9fb2529a4..b36467566 100644 --- a/test/unit/app/controllers/permissions/permissions-controller-test.js +++ b/test/unit/app/controllers/permissions/permissions-controller-test.js @@ -1519,20 +1519,46 @@ describe('permissions controller', function () { }); describe('miscellanea and edge cases', function () { - it('requestAccountsPermissionWithId calls _requestAccountsPermission with an explicit request ID', async function () { + it('requestAccountsPermissionWithId calls _requestPermissions and notifyAccounts', function (done) { + const notifications = initNotifications(); + const permController = initPermController(notifications); + const _requestPermissions = sinon + .stub(permController, '_requestPermissions') + .resolves(); + const notifyAccountsChanged = sinon + .stub(permController, 'notifyAccountsChanged') + .callsFake(() => { + assert.ok( + notifyAccountsChanged.calledOnceWithExactly('example.com', []), + ); + notifyAccountsChanged.restore(); + _requestPermissions.restore(); + done(); + }); + permController.requestAccountsPermissionWithId('example.com'); + }); + it('requestAccountsPermissionWithId calls _requestAccountsPermission with an explicit request ID', function (done) { const permController = initPermController(); const _requestPermissions = sinon .stub(permController, '_requestPermissions') .resolves(); - await permController.requestAccountsPermissionWithId('example.com'); - assert.ok( - _requestPermissions.calledOnceWithExactly( - sinon.match.object.and(sinon.match.has('origin')), - { eth_accounts: {} }, - sinon.match.string.and(sinon.match.truthy), - ), - ); - _requestPermissions.restore(); + const onResolved = async () => { + assert.ok( + _requestPermissions.calledOnceWithExactly( + sinon.match.object.and(sinon.match.has('origin')), + { eth_accounts: {} }, + sinon.match.string.and(sinon.match.truthy), + ), + ); + _requestPermissions.restore(); + // eslint-disable-next-line no-use-before-define + notifyAccountsChanged.restore(); + done(); + }; + const notifyAccountsChanged = sinon + .stub(permController, 'notifyAccountsChanged') + .callsFake(onResolved); + permController.requestAccountsPermissionWithId('example.com'); }); }); }); diff --git a/test/unit/app/controllers/preferences-controller-test.js b/test/unit/app/controllers/preferences-controller-test.js index d2a85d12c..b56a6d65c 100644 --- a/test/unit/app/controllers/preferences-controller-test.js +++ b/test/unit/app/controllers/preferences-controller-test.js @@ -1,19 +1,39 @@ import assert from 'assert'; -import { ObservableStore } from '@metamask/obs-store'; import sinon from 'sinon'; import PreferencesController from '../../../../app/scripts/controllers/preferences'; +import { + MAINNET_CHAIN_ID, + RINKEBY_CHAIN_ID, +} from '../../../../shared/constants/network'; describe('preferences controller', function () { let preferencesController; let network; + let currentChainId; + let triggerNetworkChange; + let switchToMainnet; + let switchToRinkeby; const migrateAddressBookState = sinon.stub(); beforeEach(function () { - network = { providerStore: new ObservableStore({ type: 'mainnet' }) }; + currentChainId = MAINNET_CHAIN_ID; + network = { + getCurrentChainId: () => currentChainId, + on: sinon.spy(), + }; preferencesController = new PreferencesController({ migrateAddressBookState, network, }); + triggerNetworkChange = network.on.firstCall.args[1]; + switchToMainnet = () => { + currentChainId = MAINNET_CHAIN_ID; + triggerNetworkChange(); + }; + switchToRinkeby = () => { + currentChainId = RINKEBY_CHAIN_ID; + triggerNetworkChange(); + }; }); afterEach(function () { @@ -230,12 +250,10 @@ describe('preferences controller', function () { const symbolFirst = 'ABBR'; const symbolSecond = 'ABBB'; const decimals = 5; - - network.providerStore.updateState({ type: 'mainnet' }); await preferencesController.addToken(addressFirst, symbolFirst, decimals); const tokensFirstAddress = preferencesController.getTokens(); - network.providerStore.updateState({ type: 'rinkeby' }); + switchToRinkeby(); await preferencesController.addToken( addressSecond, symbolSecond, @@ -304,14 +322,13 @@ describe('preferences controller', function () { }); it('should remove a token from its state on corresponding network', async function () { - network.providerStore.updateState({ type: 'mainnet' }); await preferencesController.addToken('0xa', 'A', 4); await preferencesController.addToken('0xb', 'B', 5); - network.providerStore.updateState({ type: 'rinkeby' }); + switchToRinkeby(); await preferencesController.addToken('0xa', 'A', 4); await preferencesController.addToken('0xb', 'B', 5); const initialTokensSecond = preferencesController.getTokens(); - network.providerStore.updateState({ type: 'mainnet' }); + switchToMainnet(); await preferencesController.removeToken('0xa'); const tokensFirst = preferencesController.getTokens(); @@ -320,7 +337,7 @@ describe('preferences controller', function () { const [token1] = tokensFirst; assert.deepEqual(token1, { address: '0xb', symbol: 'B', decimals: 5 }); - network.providerStore.updateState({ type: 'rinkeby' }); + switchToRinkeby(); const tokensSecond = preferencesController.getTokens(); assert.deepEqual( tokensSecond, @@ -371,11 +388,10 @@ describe('preferences controller', function () { describe('on updateStateNetworkType', function () { it('should remove a token from its state on corresponding network', async function () { - network.providerStore.updateState({ type: 'mainnet' }); await preferencesController.addToken('0xa', 'A', 4); await preferencesController.addToken('0xb', 'B', 5); const initialTokensFirst = preferencesController.getTokens(); - network.providerStore.updateState({ type: 'rinkeby' }); + switchToRinkeby(); await preferencesController.addToken('0xa', 'C', 4); await preferencesController.addToken('0xb', 'D', 5); const initialTokensSecond = preferencesController.getTokens(); @@ -386,9 +402,9 @@ describe('preferences controller', function () { 'tokens not equal for different networks and tokens', ); - network.providerStore.updateState({ type: 'mainnet' }); + switchToMainnet(); const tokensFirst = preferencesController.getTokens(); - network.providerStore.updateState({ type: 'rinkeby' }); + switchToRinkeby(); const tokensSecond = preferencesController.getTokens(); assert.deepEqual( tokensFirst, diff --git a/test/unit/app/controllers/swaps-test.js b/test/unit/app/controllers/swaps-test.js index 5bd1c8529..299f99229 100644 --- a/test/unit/app/controllers/swaps-test.js +++ b/test/unit/app/controllers/swaps-test.js @@ -14,6 +14,7 @@ import { createTestProviderTools } from '../../../stub/provider'; import SwapsController, { utils, } from '../../../../app/scripts/controllers/swaps'; +import { NETWORK_EVENTS } from '../../../../app/scripts/controllers/network'; const MOCK_FETCH_PARAMS = { slippage: 3, @@ -101,7 +102,10 @@ function getMockNetworkController() { }; }, }, - on: sinon.stub().withArgs('networkDidChange').callsArgAsync(1), + on: sinon + .stub() + .withArgs(NETWORK_EVENTS.NETWORK_DID_CHANGE) + .callsArgAsync(1), }; } diff --git a/test/unit/app/controllers/token-rates-controller.js b/test/unit/app/controllers/token-rates-controller.js index c1f69d54f..6c23abbaf 100644 --- a/test/unit/app/controllers/token-rates-controller.js +++ b/test/unit/app/controllers/token-rates-controller.js @@ -4,10 +4,19 @@ import { ObservableStore } from '@metamask/obs-store'; import TokenRatesController from '../../../../app/scripts/controllers/token-rates'; describe('TokenRatesController', function () { + let nativeCurrency; + let getNativeCurrency; + beforeEach(function () { + nativeCurrency = 'ETH'; + getNativeCurrency = () => nativeCurrency; + }); it('should listen for preferences store updates', function () { const preferences = new ObservableStore({ tokens: [] }); preferences.putState({ tokens: ['foo'] }); - const controller = new TokenRatesController({ preferences }); + const controller = new TokenRatesController({ + preferences, + getNativeCurrency, + }); assert.deepEqual(controller._tokens, ['foo']); }); @@ -15,7 +24,10 @@ describe('TokenRatesController', function () { const stub = sinon.stub(global, 'setInterval'); const preferences = new ObservableStore({ tokens: [] }); preferences.putState({ tokens: ['foo'] }); - const controller = new TokenRatesController({ preferences }); + const controller = new TokenRatesController({ + preferences, + getNativeCurrency, + }); controller.start(1337); assert.strictEqual(stub.getCall(0).args[1], 1337); diff --git a/test/unit/app/controllers/transactions/tx-controller-test.js b/test/unit/app/controllers/transactions/tx-controller-test.js index ca7bfede6..d8b362555 100644 --- a/test/unit/app/controllers/transactions/tx-controller-test.js +++ b/test/unit/app/controllers/transactions/tx-controller-test.js @@ -15,6 +15,7 @@ import { TRANSACTION_STATUSES, TRANSACTION_TYPES, } from '../../../../../shared/constants/transaction'; +import { METAMASK_CONTROLLER_EVENTS } from '../../../../../app/scripts/metamask-controller'; const noop = () => true; const currentNetworkId = '42'; @@ -395,7 +396,10 @@ describe('Transaction Controller', function () { txParams: {}, }; - const eventNames = ['update:badge', '1:unapproved']; + const eventNames = [ + METAMASK_CONTROLLER_EVENTS.UPDATE_BADGE, + '1:unapproved', + ]; const listeners = []; eventNames.forEach((eventName) => { listeners.push( @@ -860,6 +864,7 @@ describe('Transaction Controller', function () { return '0xee6b2800'; }, networkStore: new ObservableStore(currentNetworkId), + getCurrentChainId: () => currentChainId, txHistoryLimit: 10, blockTracker: _blockTrackerStub, signTransaction: (ethTx) => @@ -899,6 +904,7 @@ describe('Transaction Controller', function () { return '0xee6b2800'; }, networkStore: new ObservableStore(currentNetworkId), + getCurrentChainId: () => currentChainId, txHistoryLimit: 10, blockTracker: _blockTrackerStub, signTransaction: (ethTx) => diff --git a/test/unit/app/controllers/transactions/tx-helper-test.js b/test/unit/app/controllers/transactions/tx-helper-test.js index c2b13af4c..246f9a46c 100644 --- a/test/unit/app/controllers/transactions/tx-helper-test.js +++ b/test/unit/app/controllers/transactions/tx-helper-test.js @@ -1,16 +1,21 @@ import { strict as assert } from 'assert'; +import { + MAINNET_CHAIN_ID, + MAINNET_NETWORK_ID, +} from '../../../../../shared/constants/network'; import txHelper from '../../../../../ui/lib/tx-helper'; describe('txHelper', function () { it('always shows the oldest tx first', function () { - const metamaskNetworkId = '1'; + const metamaskNetworkId = MAINNET_NETWORK_ID; + const chainId = MAINNET_CHAIN_ID; const txs = { a: { metamaskNetworkId, time: 3 }, b: { metamaskNetworkId, time: 1 }, c: { metamaskNetworkId, time: 2 }, }; - const sorted = txHelper(txs, null, null, metamaskNetworkId); + const sorted = txHelper(txs, null, null, metamaskNetworkId, chainId); assert.equal(sorted[0].time, 1, 'oldest tx first'); assert.equal(sorted[2].time, 3, 'newest tx last'); }); diff --git a/test/unit/app/controllers/transactions/tx-state-manager-test.js b/test/unit/app/controllers/transactions/tx-state-manager-test.js index 6efafb693..db9a4bdbc 100644 --- a/test/unit/app/controllers/transactions/tx-state-manager-test.js +++ b/test/unit/app/controllers/transactions/tx-state-manager-test.js @@ -3,12 +3,17 @@ import sinon from 'sinon'; import TxStateManager from '../../../../../app/scripts/controllers/transactions/tx-state-manager'; import { snapshotFromTxMeta } from '../../../../../app/scripts/controllers/transactions/lib/tx-state-history-helpers'; import { TRANSACTION_STATUSES } from '../../../../../shared/constants/transaction'; +import { + KOVAN_CHAIN_ID, + KOVAN_NETWORK_ID, +} from '../../../../../shared/constants/network'; const noop = () => true; describe('TransactionStateManager', function () { let txStateManager; - const currentNetworkId = '42'; + const currentNetworkId = KOVAN_NETWORK_ID; + const currentChainId = KOVAN_CHAIN_ID; const otherNetworkId = '2'; beforeEach(function () { @@ -18,6 +23,7 @@ describe('TransactionStateManager', function () { }, txHistoryLimit: 10, getNetwork: () => currentNetworkId, + getCurrentChainId: () => currentChainId, }); }); @@ -137,6 +143,7 @@ describe('TransactionStateManager', function () { transactions: [submittedTx, confirmedTx], }, getNetwork: () => currentNetworkId, + getCurrentChainId: () => currentChainId, }); assert.deepEqual(txm.getTxList(), [submittedTx, confirmedTx]); @@ -201,6 +208,7 @@ describe('TransactionStateManager', function () { ], }, getNetwork: () => currentNetworkId, + getCurrentChainId: () => currentChainId, }); assert.deepEqual(txm.getTxList(2), [approvedTx2, confirmedTx3]); @@ -235,6 +243,7 @@ describe('TransactionStateManager', function () { const unapprovedTx1 = { id: 1, metamaskNetworkId: currentNetworkId, + chainId: currentChainId, time: 1, txParams: { from: '0xAddress', @@ -259,6 +268,7 @@ describe('TransactionStateManager', function () { { id: 2, metamaskNetworkId: currentNetworkId, + chainId: currentChainId, time: 2, txParams: { from: '0xAddress', @@ -284,6 +294,7 @@ describe('TransactionStateManager', function () { { id: 3, metamaskNetworkId: currentNetworkId, + chainId: currentChainId, time: 3, txParams: { from: '0xAddress', @@ -304,6 +315,7 @@ describe('TransactionStateManager', function () { ], }, getNetwork: () => currentNetworkId, + getCurrentChainId: () => currentChainId, }); assert.deepEqual(txm.getTxList(2), [...approvedTx2s, ...failedTx3s]); diff --git a/test/unit/app/util-test.js b/test/unit/app/util-test.js index a6d2783f1..7f9a285ff 100644 --- a/test/unit/app/util-test.js +++ b/test/unit/app/util-test.js @@ -3,7 +3,7 @@ import { getEnvironmentType, sufficientBalance, } from '../../../app/scripts/lib/util'; -import { isPrefixedFormattedHexString } from '../../../shared/modules/utils'; +import { isPrefixedFormattedHexString } from '../../../shared/modules/network.utils'; import { ENVIRONMENT_TYPE_POPUP, diff --git a/test/unit/migrations/052-test.js b/test/unit/migrations/052-test.js new file mode 100644 index 000000000..23dc7c603 --- /dev/null +++ b/test/unit/migrations/052-test.js @@ -0,0 +1,424 @@ +import assert from 'assert'; +import migration52 from '../../../app/scripts/migrations/052'; +import { + GOERLI, + GOERLI_CHAIN_ID, + KOVAN, + KOVAN_CHAIN_ID, + MAINNET, + MAINNET_CHAIN_ID, + NETWORK_TYPE_RPC, + RINKEBY, + RINKEBY_CHAIN_ID, + ROPSTEN, + ROPSTEN_CHAIN_ID, +} from '../../../shared/constants/network'; + +const TOKEN1 = { symbol: 'TST', address: '0x10', decimals: 18 }; +const TOKEN2 = { symbol: 'TXT', address: '0x11', decimals: 18 }; +const TOKEN3 = { symbol: 'TVT', address: '0x12', decimals: 18 }; +const TOKEN4 = { symbol: 'TAT', address: '0x13', decimals: 18 }; + +describe('migration #52', function () { + it('should update the version metadata', async function () { + const oldStorage = { + meta: { + version: 52, + }, + data: {}, + }; + + const newStorage = await migration52.migrate(oldStorage); + assert.deepStrictEqual(newStorage.meta, { + version: 52, + }); + }); + + it(`should move ${MAINNET} tokens and hidden tokens to be keyed by ${MAINNET_CHAIN_ID} for each address`, async function () { + const oldStorage = { + meta: {}, + data: { + PreferencesController: { + accountHiddenTokens: { + '0x1111': { + [MAINNET]: [TOKEN1], + }, + '0x1112': { + [MAINNET]: [TOKEN3], + }, + }, + accountTokens: { + '0x1111': { + [MAINNET]: [TOKEN1, TOKEN2], + }, + '0x1112': { + [MAINNET]: [TOKEN1, TOKEN3], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }, + }; + + const newStorage = await migration52.migrate(oldStorage); + assert.deepStrictEqual(newStorage.data, { + PreferencesController: { + accountHiddenTokens: { + '0x1111': { + [MAINNET_CHAIN_ID]: [TOKEN1], + }, + '0x1112': { + [MAINNET_CHAIN_ID]: [TOKEN3], + }, + }, + accountTokens: { + '0x1111': { + [MAINNET_CHAIN_ID]: [TOKEN1, TOKEN2], + }, + '0x1112': { + [MAINNET_CHAIN_ID]: [TOKEN1, TOKEN3], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }); + }); + + it(`should move ${RINKEBY} tokens and hidden tokens to be keyed by ${RINKEBY_CHAIN_ID} for each address`, async function () { + const oldStorage = { + meta: {}, + data: { + PreferencesController: { + accountHiddenTokens: { + '0x1111': { + [RINKEBY]: [TOKEN1], + }, + '0x1112': { + [RINKEBY]: [TOKEN3], + }, + }, + accountTokens: { + '0x1111': { + [RINKEBY]: [TOKEN1, TOKEN2], + }, + '0x1112': { + [RINKEBY]: [TOKEN1, TOKEN3], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }, + }; + + const newStorage = await migration52.migrate(oldStorage); + assert.deepStrictEqual(newStorage.data, { + PreferencesController: { + accountHiddenTokens: { + '0x1111': { + [RINKEBY_CHAIN_ID]: [TOKEN1], + }, + '0x1112': { + [RINKEBY_CHAIN_ID]: [TOKEN3], + }, + }, + accountTokens: { + '0x1111': { + [RINKEBY_CHAIN_ID]: [TOKEN1, TOKEN2], + }, + '0x1112': { + [RINKEBY_CHAIN_ID]: [TOKEN1, TOKEN3], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }); + }); + + it(`should move ${KOVAN} tokens and hidden tokens to be keyed by ${KOVAN_CHAIN_ID} for each address`, async function () { + const oldStorage = { + meta: {}, + data: { + PreferencesController: { + accountHiddenTokens: { + '0x1111': { + [KOVAN]: [TOKEN1], + }, + '0x1112': { + [KOVAN]: [TOKEN3], + }, + }, + accountTokens: { + '0x1111': { + [KOVAN]: [TOKEN1, TOKEN2], + }, + '0x1112': { + [KOVAN]: [TOKEN1, TOKEN3], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }, + }; + + const newStorage = await migration52.migrate(oldStorage); + assert.deepStrictEqual(newStorage.data, { + PreferencesController: { + accountHiddenTokens: { + '0x1111': { + [KOVAN_CHAIN_ID]: [TOKEN1], + }, + '0x1112': { + [KOVAN_CHAIN_ID]: [TOKEN3], + }, + }, + accountTokens: { + '0x1111': { + [KOVAN_CHAIN_ID]: [TOKEN1, TOKEN2], + }, + '0x1112': { + [KOVAN_CHAIN_ID]: [TOKEN1, TOKEN3], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }); + }); + + it(`should move ${GOERLI} tokens and hidden tokens to be keyed by ${GOERLI_CHAIN_ID} for each address`, async function () { + const oldStorage = { + meta: {}, + data: { + PreferencesController: { + accountHiddenTokens: { + '0x1111': { + [GOERLI]: [TOKEN1], + }, + '0x1112': { + [GOERLI]: [TOKEN3], + }, + }, + accountTokens: { + '0x1111': { + [GOERLI]: [TOKEN1, TOKEN2], + }, + '0x1112': { + [GOERLI]: [TOKEN1, TOKEN3], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }, + }; + + const newStorage = await migration52.migrate(oldStorage); + assert.deepStrictEqual(newStorage.data, { + PreferencesController: { + accountHiddenTokens: { + '0x1111': { + [GOERLI_CHAIN_ID]: [TOKEN1], + }, + '0x1112': { + [GOERLI_CHAIN_ID]: [TOKEN3], + }, + }, + accountTokens: { + '0x1111': { + [GOERLI_CHAIN_ID]: [TOKEN1, TOKEN2], + }, + '0x1112': { + [GOERLI_CHAIN_ID]: [TOKEN1, TOKEN3], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }); + }); + + it(`should move ${ROPSTEN} tokens and hidden tokens to be keyed by ${ROPSTEN_CHAIN_ID} for each address`, async function () { + const oldStorage = { + meta: {}, + data: { + PreferencesController: { + accountHiddenTokens: { + '0x1111': { + [ROPSTEN]: [TOKEN1], + }, + '0x1112': { + [ROPSTEN]: [TOKEN3], + }, + }, + accountTokens: { + '0x1111': { + [ROPSTEN]: [TOKEN1, TOKEN2], + }, + '0x1112': { + [ROPSTEN]: [TOKEN1, TOKEN3], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }, + }; + + const newStorage = await migration52.migrate(oldStorage); + assert.deepStrictEqual(newStorage.data, { + PreferencesController: { + accountHiddenTokens: { + '0x1111': { + [ROPSTEN_CHAIN_ID]: [TOKEN1], + }, + '0x1112': { + [ROPSTEN_CHAIN_ID]: [TOKEN3], + }, + }, + accountTokens: { + '0x1111': { + [ROPSTEN_CHAIN_ID]: [TOKEN1, TOKEN2], + }, + '0x1112': { + [ROPSTEN_CHAIN_ID]: [TOKEN1, TOKEN3], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }); + }); + + it(`should duplicate ${NETWORK_TYPE_RPC} tokens and hidden tokens to all custom networks for each address`, async function () { + const oldStorage = { + meta: {}, + data: { + PreferencesController: { + frequentRpcListDetail: [ + { chainId: '0xab' }, + { chainId: '0x12' }, + { chainId: '0xfa' }, + ], + accountHiddenTokens: { + '0x1111': { + [NETWORK_TYPE_RPC]: [TOKEN1], + }, + '0x1112': { + [NETWORK_TYPE_RPC]: [TOKEN3], + }, + }, + accountTokens: { + '0x1111': { + [NETWORK_TYPE_RPC]: [TOKEN1, TOKEN2], + }, + '0x1112': { + [NETWORK_TYPE_RPC]: [TOKEN1, TOKEN3], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }, + }; + + const newStorage = await migration52.migrate(oldStorage); + assert.deepStrictEqual(newStorage.data, { + PreferencesController: { + frequentRpcListDetail: [ + { chainId: '0xab' }, + { chainId: '0x12' }, + { chainId: '0xfa' }, + ], + accountHiddenTokens: { + '0x1111': { + '0xab': [TOKEN1], + '0x12': [TOKEN1], + '0xfa': [TOKEN1], + }, + '0x1112': { + '0xab': [TOKEN3], + '0x12': [TOKEN3], + '0xfa': [TOKEN3], + }, + }, + accountTokens: { + '0x1111': { + '0xab': [TOKEN1, TOKEN2], + '0x12': [TOKEN1, TOKEN2], + '0xfa': [TOKEN1, TOKEN2], + }, + '0x1112': { + '0xab': [TOKEN1, TOKEN3], + '0x12': [TOKEN1, TOKEN3], + '0xfa': [TOKEN1, TOKEN3], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }); + }); + + it(`should overwrite ${NETWORK_TYPE_RPC} tokens with built in networks if chainIds match`, async function () { + const oldStorage = { + meta: {}, + data: { + PreferencesController: { + frequentRpcListDetail: [{ chainId: '0x1' }], + accountHiddenTokens: { + '0x1111': { + [NETWORK_TYPE_RPC]: [TOKEN3], + [MAINNET]: [TOKEN1], + }, + }, + accountTokens: { + '0x1111': { + [NETWORK_TYPE_RPC]: [TOKEN1, TOKEN2], + [MAINNET]: [TOKEN3, TOKEN4], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }, + }; + + const newStorage = await migration52.migrate(oldStorage); + assert.deepStrictEqual(newStorage.data, { + PreferencesController: { + frequentRpcListDetail: [{ chainId: '0x1' }], + accountHiddenTokens: { + '0x1111': { + '0x1': [TOKEN1], + }, + }, + accountTokens: { + '0x1111': { + '0x1': [TOKEN3, TOKEN4], + }, + }, + bar: 'baz', + }, + foo: 'bar', + }); + }); + + it('should do nothing if no PreferencesController key', async function () { + const oldStorage = { + meta: {}, + data: { + foo: 'bar', + }, + }; + + const newStorage = await migration52.migrate(oldStorage); + assert.deepStrictEqual(newStorage.data, { + foo: 'bar', + }); + }); +}); diff --git a/ui/app/components/app/app-header/app-header.container.js b/ui/app/components/app/app-header/app-header.container.js index d1751c67a..a7d632b6d 100644 --- a/ui/app/components/app/app-header/app-header.container.js +++ b/ui/app/components/app/app-header/app-header.container.js @@ -8,18 +8,10 @@ import AppHeader from './app-header.component'; const mapStateToProps = (state) => { const { appState, metamask } = state; const { networkDropdownOpen } = appState; - const { - network, - provider, - selectedAddress, - isUnlocked, - isAccountMenuOpen, - } = metamask; + const { selectedAddress, isUnlocked, isAccountMenuOpen } = metamask; return { networkDropdownOpen, - network, - provider, selectedAddress, isUnlocked, isAccountMenuOpen, diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js b/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js index 0c17f41fa..2054f7daa 100644 --- a/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-header/confirm-page-container-header.component.js @@ -25,7 +25,7 @@ export default function ConfirmPageContainerHeader({ windowType !== ENVIRONMENT_TYPE_POPUP; if (!showEdit && isFullScreen) { - return null; + return children; } return (
diff --git a/ui/app/components/app/confirm-page-container/confirm-page-container-header/tests/confirm-page-container-header.component.test.js b/ui/app/components/app/confirm-page-container/confirm-page-container-header/tests/confirm-page-container-header.component.test.js new file mode 100644 index 000000000..24da85a38 --- /dev/null +++ b/ui/app/components/app/confirm-page-container/confirm-page-container-header/tests/confirm-page-container-header.component.test.js @@ -0,0 +1,63 @@ +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import sinon from 'sinon'; +import { Provider } from 'react-redux'; +import ConfirmPageContainerHeader from '../confirm-page-container-header.component'; +import configureStore from '../../../../../store/store'; +import testData from '../../../../../../../.storybook/test-data'; + +const util = require('../../../../../../../app/scripts/lib/util'); + +describe('Confirm Detail Row Component', function () { + describe('render', function () { + it('should render a div with a confirm-page-container-header class', function () { + const stub = sinon + .stub(util, 'getEnvironmentType') + .callsFake(() => 'popup'); + const wrapper = shallow( + + { + // noop + }} + showAccountInHeader={false} + accountAddress="0xmockAccountAddress" + /> + , + ); + assert.strictEqual( + wrapper.html().includes('confirm-page-container-header'), + true, + ); + stub.restore(); + }); + + it('should only render children when fullscreen and showEdit is false', function () { + const stub = sinon + .stub(util, 'getEnvironmentType') + .callsFake(() => 'fullscreen'); + const wrapper = shallow( + + { + // noop + }} + showAccountInHeader={false} + accountAddress="0xmockAccountAddress" + > +
+ + , + ); + assert.strictEqual(wrapper.html().includes('nested-test-class'), true); + assert.strictEqual( + wrapper.html().includes('confirm-page-container-header'), + false, + ); + stub.restore(); + }); + }); +}); diff --git a/ui/app/components/app/dropdowns/network-dropdown.js b/ui/app/components/app/dropdowns/network-dropdown.js index d01c71ba9..c0d010517 100644 --- a/ui/app/components/app/dropdowns/network-dropdown.js +++ b/ui/app/components/app/dropdowns/network-dropdown.js @@ -11,7 +11,7 @@ import { } from '../../../helpers/constants/routes'; import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../../shared/constants/app'; import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; -import { isPrefixedFormattedHexString } from '../../../../../shared/modules/utils'; +import { isPrefixedFormattedHexString } from '../../../../../shared/modules/network.utils'; import { getEnvironmentType } from '../../../../../app/scripts/lib/util'; import ColorIndicator from '../../ui/color-indicator'; diff --git a/ui/app/components/app/dropdowns/simple-dropdown.js b/ui/app/components/app/dropdowns/simple-dropdown.js deleted file mode 100644 index cafaa4e62..000000000 --- a/ui/app/components/app/dropdowns/simple-dropdown.js +++ /dev/null @@ -1,89 +0,0 @@ -import classnames from 'classnames'; -import PropTypes from 'prop-types'; -import React, { Component } from 'react'; - -class SimpleDropdown extends Component { - static propTypes = { - options: PropTypes.array.isRequired, - placeholder: PropTypes.string, - onSelect: PropTypes.func, - selectedOption: PropTypes.string, - }; - - state = { - isOpen: false, - }; - - getDisplayValue() { - const { selectedOption, options } = this.props; - const matchesOption = (option) => option.value === selectedOption; - const matchingOption = options.find(matchesOption); - return matchingOption - ? matchingOption.displayValue || matchingOption.value - : selectedOption; - } - - handleClose() { - this.setState({ isOpen: false }); - } - - toggleOpen() { - this.setState((prevState) => ({ - isOpen: !prevState.isOpen, - })); - } - - renderOptions() { - const { options, onSelect, selectedOption } = this.props; - - return ( -
-
{ - event.stopPropagation(); - this.handleClose(); - }} - /> -
- {options.map((option) => ( -
{ - event.stopPropagation(); - if (option.value !== selectedOption) { - onSelect(option.value); - } - - this.handleClose(); - }} - > - {option.displayValue || option.value} -
- ))} -
-
- ); - } - - render() { - const { placeholder } = this.props; - const { isOpen } = this.state; - - return ( -
this.toggleOpen()}> -
- {this.getDisplayValue() || placeholder || 'Select'} -
- - {isOpen && this.renderOptions()} -
- ); - } -} - -export default SimpleDropdown; diff --git a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js index ac355d656..100e30780 100644 --- a/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js +++ b/ui/app/components/app/gas-customization/gas-modal-page-container/tests/gas-modal-page-container-container.test.js @@ -19,10 +19,6 @@ const gasActionSpies = { resetCustomData: sinon.spy(), }; -const confirmTransactionActionSpies = { - updateGasAndCalculate: sinon.spy(), -}; - const sendActionSpies = { hideGasButtonGroup: sinon.spy(), }; @@ -48,7 +44,6 @@ proxyquire('../gas-modal-page-container.container.js', { }, '../../../../store/actions': actionSpies, '../../../../ducks/gas/gas.duck': gasActionSpies, - '../../../../ducks/confirm-transaction/confirm-transaction.duck': confirmTransactionActionSpies, '../../../../ducks/send/send.duck': sendActionSpies, }); @@ -83,6 +78,7 @@ describe('gas-modal-page-container container', function () { }, provider: { type: 'mainnet', + chainId: '0x1', }, currentNetworkTxList: [ { @@ -205,6 +201,7 @@ describe('gas-modal-page-container container', function () { provider: { ...baseMockState.metamask.provider, type: 'rinkeby', + chainId: '0x4', }, }, }, @@ -230,6 +227,7 @@ describe('gas-modal-page-container container', function () { provider: { ...baseMockState.metamask.provider, type: 'rinkeby', + chainId: '0x4', }, }, }, @@ -251,6 +249,7 @@ describe('gas-modal-page-container container', function () { provider: { ...baseMockState.metamask.provider, type: 'mainnet', + chainId: '0x1', }, }, }, diff --git a/ui/app/components/app/gas-customization/gas-price-button-group/index.scss b/ui/app/components/app/gas-customization/gas-price-button-group/index.scss index 4db9a19fc..06d59e74f 100644 --- a/ui/app/components/app/gas-customization/gas-price-button-group/index.scss +++ b/ui/app/components/app/gas-customization/gas-price-button-group/index.scss @@ -243,8 +243,6 @@ } i { - @include H7; - display: flex; color: $primary-blue; font-weight: 900; diff --git a/ui/app/components/app/menu-bar/index.scss b/ui/app/components/app/menu-bar/index.scss index 673b219c3..b70403115 100644 --- a/ui/app/components/app/menu-bar/index.scss +++ b/ui/app/components/app/menu-bar/index.scss @@ -4,6 +4,7 @@ column-gap: 5px; padding: 0 8px; border-bottom: 1px solid $Grey-100; + height: 64px; .menu-bar__account-options { background: none; diff --git a/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js b/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js index 30e4b6b30..6aaca546b 100644 --- a/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js +++ b/ui/app/components/app/metamask-template-renderer/metamask-template-renderer.js @@ -77,7 +77,7 @@ const MetaMaskTemplateRenderer = ({ sections }) => { ); }; -const SectionShape = { +export const SectionShape = { props: PropTypes.object, element: PropTypes.oneOf(Object.keys(safeComponentList)).isRequired, key: PropTypes.string, diff --git a/ui/app/components/app/metamask-template-renderer/safe-component-list.js b/ui/app/components/app/metamask-template-renderer/safe-component-list.js index 9e8c22991..72571832b 100644 --- a/ui/app/components/app/metamask-template-renderer/safe-component-list.js +++ b/ui/app/components/app/metamask-template-renderer/safe-component-list.js @@ -5,8 +5,12 @@ import TruncatedDefinitionList from '../../ui/truncated-definition-list'; import Popover from '../../ui/popover'; import Typography from '../../ui/typography'; import Box from '../../ui/box'; +import MetaMaskTranslation from '../metamask-translation'; +import NetworkDisplay from '../network-display'; export const safeComponentList = { + MetaMaskTranslation, + a: 'a', b: 'b', p: 'p', div: 'div', @@ -18,4 +22,5 @@ export const safeComponentList = { Button, Popover, Box, + NetworkDisplay, }; diff --git a/ui/app/components/app/metamask-translation/index.js b/ui/app/components/app/metamask-translation/index.js new file mode 100644 index 000000000..53548cbb0 --- /dev/null +++ b/ui/app/components/app/metamask-translation/index.js @@ -0,0 +1 @@ +export { default } from './metamask-translation'; diff --git a/ui/app/components/app/metamask-translation/metamask-translation.js b/ui/app/components/app/metamask-translation/metamask-translation.js new file mode 100644 index 000000000..b0df34155 --- /dev/null +++ b/ui/app/components/app/metamask-translation/metamask-translation.js @@ -0,0 +1,80 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { useI18nContext } from '../../../hooks/useI18nContext'; +import MetaMaskTemplateRenderer, { + SectionShape, +} from '../metamask-template-renderer/metamask-template-renderer'; + +/** + * MetaMaskTranslation is a simple helper Component for adding full translation + * support to the template system. We do pass the translation function to the + * template getValues function, but passing it React components as variables + * would require React to be in scope, and breaks the object pattern paradigm. + * + * This component gets around that by converting variables that are templates + * themselves into tiny React trees. This component does additional validation + * to make sure that the tree has a single root node, with maximum two leaves. + * Each subnode can have a maximum of one child that must be a string. + * + * This enforces a maximum recursion depth of 2, preventing translation strings + * from being performance hogs. We could further limit this, and also attenuate + * the safeComponentList for what kind of components we allow these special + * trees to contain. + */ +export default function MetaMaskTranslation({ translationKey, variables }) { + const t = useI18nContext(); + + return t( + translationKey, + variables?.map((variable) => { + if ( + typeof variable === 'object' && + !Array.isArray(variable) && + variable.element + ) { + if (!variable.key) { + throw new Error( + `When using MetaMask Template Language in a MetaMaskTranslation variable, you must provide a key for the section regardless of syntax. + Section with element '${variable.element}' for translationKey: '${translationKey}' has no key property`, + ); + } + if ( + variable.children && + Array.isArray(variable.children) && + variable.children.length > 2 + ) { + throw new Error( + 'MetaMaskTranslation only renders templates with a single section and maximum two children', + ); + } else if ( + (variable.children?.[0]?.children !== undefined && + typeof variable.children[0].children !== 'string') || + (variable.children?.[1]?.children !== undefined && + typeof variable.children[1].children !== 'string') + ) { + throw new Error( + 'MetaMaskTranslation does not allow for component trees of non trivial depth', + ); + } + return ( + + ); + } + return variable; + }), + ); +} + +MetaMaskTranslation.propTypes = { + translationKey: PropTypes.string.isRequired, + variables: PropTypes.arrayOf( + PropTypes.oneOfType([ + PropTypes.string, + PropTypes.number, + PropTypes.shape(SectionShape), + ]), + ), +}; diff --git a/ui/app/components/app/metamask-translation/metamask-translation.stories.js b/ui/app/components/app/metamask-translation/metamask-translation.stories.js new file mode 100644 index 000000000..21d321ccc --- /dev/null +++ b/ui/app/components/app/metamask-translation/metamask-translation.stories.js @@ -0,0 +1,66 @@ +import React from 'react'; +import { select, object } from '@storybook/addon-knobs'; +import { groupBy } from 'lodash'; +import en from '../../../../../app/_locales/en/messages.json'; +import MetaMaskTranslation from './metamask-translation'; + +export default { + title: 'MetaMaskTranslation', +}; + +const { keysWithSubstitution, keysWithoutSubstitution } = groupBy( + Object.keys(en), + (key) => { + if (en[key].message.includes('$1')) { + return 'keysWithSubstitution'; + } + return 'keysWithoutSubstitution'; + }, +); + +export const withoutSubstitutions = () => ( + +); + +export const withSubstitutions = () => ( + +); + +export const withTemplate = () => ( + +); diff --git a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js index 59522154c..9b86e2b51 100644 --- a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js +++ b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.component.js @@ -11,6 +11,8 @@ export default class DepositEtherModal extends Component { static propTypes = { network: PropTypes.string.isRequired, + isTestnet: PropTypes.bool.isRequired, + isMainnet: PropTypes.bool.isRequired, toWyre: PropTypes.func.isRequired, address: PropTypes.string.isRequired, toFaucet: PropTypes.func.isRequired, @@ -86,9 +88,14 @@ export default class DepositEtherModal extends Component { } render() { - const { network, toWyre, address, toFaucet } = this.props; - - const isTestNetwork = ['3', '4', '5', '42'].find((n) => n === network); + const { + network, + toWyre, + address, + toFaucet, + isTestnet, + isMainnet, + } = this.props; const networkName = getNetworkDisplayName(network); return ( @@ -133,7 +140,7 @@ export default class DepositEtherModal extends Component { }); toWyre(address); }, - hide: isTestNetwork, + hide: !isMainnet, })} {this.renderRow({ logo: ( @@ -158,7 +165,7 @@ export default class DepositEtherModal extends Component { text: this.faucetRowText(networkName), buttonLabel: this.context.t('getEther'), onButtonClick: () => toFaucet(network), - hide: !isTestNetwork, + hide: !isTestnet, })}
diff --git a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js index 8e324c5b2..f4f5713c9 100644 --- a/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js +++ b/ui/app/components/app/modals/deposit-ether-modal/deposit-ether-modal.container.js @@ -5,11 +5,14 @@ import { showModal, hideWarning, } from '../../../../store/actions'; +import { getIsTestnet, getIsMainnet } from '../../../../selectors/selectors'; import DepositEtherModal from './deposit-ether-modal.component'; function mapStateToProps(state) { return { network: state.metamask.network, + isTestnet: getIsTestnet(state), + isMainnet: getIsMainnet(state), address: state.metamask.selectedAddress, }; } diff --git a/ui/app/components/app/modals/tests/account-details-modal.test.js b/ui/app/components/app/modals/tests/account-details-modal.test.js index f4da817e4..304b76d7c 100644 --- a/ui/app/components/app/modals/tests/account-details-modal.test.js +++ b/ui/app/components/app/modals/tests/account-details-modal.test.js @@ -70,11 +70,8 @@ describe('Account Details Modal', function () { wrapper.setProps({ rpcPrefs: { blockExplorerUrl } }); const modalButton = wrapper.find('.account-details-modal__button'); - const blockExplorerLink = modalButton.first(); + const blockExplorerLink = modalButton.first().shallow(); - assert.strictEqual( - blockExplorerLink.html(), - '', - ); + assert.strictEqual(blockExplorerLink.text(), 'blockExplorerView'); }); }); diff --git a/ui/app/components/app/network-display/network-display.js b/ui/app/components/app/network-display/network-display.js index beda83498..65060abdf 100644 --- a/ui/app/components/app/network-display/network-display.js +++ b/ui/app/components/app/network-display/network-display.js @@ -2,7 +2,10 @@ import React from 'react'; import PropTypes from 'prop-types'; import classnames from 'classnames'; import { useSelector } from 'react-redux'; -import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; +import { + NETWORK_TYPE_RPC, + NETWORK_TYPE_TO_ID_MAP, +} from '../../../../../shared/constants/network'; import LoadingIndicator from '../../ui/loading-indicator'; import ColorIndicator from '../../ui/color-indicator'; @@ -21,15 +24,19 @@ export default function NetworkDisplay({ indicatorSize, disabled, labelProps, + targetNetwork, onClick, }) { - const { network, networkNickname, networkType } = useSelector((state) => ({ + const currentNetwork = useSelector((state) => ({ network: state.metamask.network, - networkNickname: state.metamask.provider.nickname, - networkType: state.metamask.provider.type, + nickname: state.metamask.provider.nickname, + type: state.metamask.provider.type, })); const t = useI18nContext(); + const { network = '', nickname: networkNickname, type: networkType } = + targetNetwork ?? currentNetwork; + return ( @@ -75,8 +84,13 @@ export default function NetworkDisplay({ NetworkDisplay.propTypes = { colored: PropTypes.bool, indicatorSize: PropTypes.oneOf(Object.values(SIZES)), - labelProps: PropTypes.shape({ - ...Chip.propTypes.labelProps, + labelProps: Chip.propTypes.labelProps, + targetNetwork: PropTypes.shape({ + type: PropTypes.oneOf([ + ...Object.values(NETWORK_TYPE_TO_ID_MAP), + NETWORK_TYPE_RPC, + ]), + nickname: PropTypes.string, }), outline: PropTypes.bool, disabled: PropTypes.bool, diff --git a/ui/app/components/app/signature-request-original/signature-request-original.component.js b/ui/app/components/app/signature-request-original/signature-request-original.component.js index ab7bd6c50..5dbcf9eb7 100644 --- a/ui/app/components/app/signature-request-original/signature-request-original.component.js +++ b/ui/app/components/app/signature-request-original/signature-request-original.component.js @@ -166,7 +166,7 @@ export default class SignatureRequestOriginal extends Component { {originMetadata?.icon ? ( ) : null} diff --git a/ui/app/components/app/signature-request/signature-request-header/index.scss b/ui/app/components/app/signature-request/signature-request-header/index.scss index b4f3b5479..beaa5a92c 100644 --- a/ui/app/components/app/signature-request/signature-request-header/index.scss +++ b/ui/app/components/app/signature-request/signature-request-header/index.scss @@ -9,12 +9,11 @@ &--account, &--network { flex: 1; - } - - &--account { display: flex; align-items: center; + } + &--account { .account-list-item { &__top-row { display: flex; diff --git a/ui/app/components/app/signature-request/signature-request-message/index.scss b/ui/app/components/app/signature-request/signature-request-message/index.scss index fbddf241e..9b03134c7 100644 --- a/ui/app/components/app/signature-request/signature-request-message/index.scss +++ b/ui/app/components/app/signature-request/signature-request-message/index.scss @@ -29,35 +29,27 @@ overflow: auto; padding-left: 12px; padding-right: 12px; - width: 360px; @media screen and (min-width: 576px) { width: auto; } } - &__type-title { - @include H6; - - margin-left: 12px; - margin-top: 6px; - margin-bottom: 10px; - } - &--node, &--node-leaf { - padding-left: 0.8rem; + padding-left: 0.3rem; &-label { color: #5b5d67; + margin-left: 0.5rem; } &-value { color: black; margin-left: 0.5rem; - text-overflow: ellipsis; - white-space: nowrap; + white-space: pre-line; overflow: hidden; + word-wrap: break-word; } } diff --git a/ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js b/ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js index 7802fd591..ca1056718 100644 --- a/ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js +++ b/ui/app/components/app/signature-request/signature-request-message/signature-request-message.component.js @@ -47,9 +47,6 @@ export default class SignatureRequestMessage extends PureComponent { {this.context.t('signatureRequest1')}
-
- {this.context.t('signatureRequest1')} -
{this.renderNode(data)}
diff --git a/ui/app/components/app/signature-request/signature-request.stories.js b/ui/app/components/app/signature-request/signature-request.stories.js new file mode 100644 index 000000000..fd121cc86 --- /dev/null +++ b/ui/app/components/app/signature-request/signature-request.stories.js @@ -0,0 +1,37 @@ +import React from 'react'; +import testData from '../../../../../.storybook/test-data'; +import SignatureRequest from './signature-request.component'; + +const primaryIdentity = Object.values(testData.metamask.identities)[0]; + +const containerStyle = { + width: '357px', +}; + +export default { + title: 'Signature Request', +}; + +export const FirstLook = () => { + return ( +
+ +
+ ); +}; diff --git a/ui/app/components/app/token-cell/token-cell.test.js b/ui/app/components/app/token-cell/token-cell.test.js index 677102418..9694e188c 100644 --- a/ui/app/components/app/token-cell/token-cell.test.js +++ b/ui/app/components/app/token-cell/token-cell.test.js @@ -23,7 +23,7 @@ describe('Token Cell', function () { conversionRate: 7.0, preferences: {}, provider: { - chainId: '1', + chainId: '0x1', ticker: 'ETH', type: 'mainnet', }, diff --git a/ui/app/components/app/wallet-overview/eth-overview.js b/ui/app/components/app/wallet-overview/eth-overview.js index 17bcb8673..d1de6730b 100644 --- a/ui/app/components/app/wallet-overview/eth-overview.js +++ b/ui/app/components/app/wallet-overview/eth-overview.js @@ -23,7 +23,8 @@ import { isBalanceCached, getSelectedAccount, getShouldShowFiat, - getCurrentChainId, + getIsMainnet, + getIsTestnet, getCurrentKeyring, } from '../../../selectors/selectors'; import SwapIcon from '../../ui/icon/swap-icon.component'; @@ -34,7 +35,6 @@ import { setSwapsFromToken, } from '../../../ducks/swaps/swaps'; import IconButton from '../../ui/icon-button'; -import { MAINNET_CHAIN_ID } from '../../../../../shared/constants/network'; import WalletOverview from './wallet-overview'; const EthOverview = ({ className }) => { @@ -61,7 +61,8 @@ const EthOverview = ({ className }) => { const showFiat = useSelector(getShouldShowFiat); const selectedAccount = useSelector(getSelectedAccount); const { balance } = selectedAccount; - const chainId = useSelector(getCurrentChainId); + const isMainnetChain = useSelector(getIsMainnet); + const isTestnetChain = useSelector(getIsTestnet); const enteredSwapsEvent = useNewMetricEvent({ event: 'Swaps Opened', properties: { source: 'Main View', active_currency: 'ETH' }, @@ -115,6 +116,7 @@ const EthOverview = ({ className }) => { { depositEvent(); @@ -134,10 +136,10 @@ const EthOverview = ({ className }) => { {swapsEnabled ? ( { - if (chainId === MAINNET_CHAIN_ID) { + if (isMainnetChain) { enteredSwapsEvent(); dispatch(setSwapsFromToken(swapsEthToken)); if (usingHardwareWallet) { @@ -152,7 +154,7 @@ const EthOverview = ({ className }) => { {contents} diff --git a/ui/app/components/ui/button/button.component.js b/ui/app/components/ui/button/button.component.js index a1af4da43..4313a301a 100644 --- a/ui/app/components/ui/button/button.component.js +++ b/ui/app/components/ui/button/button.component.js @@ -45,6 +45,15 @@ const Button = ({ } else if (submit) { buttonProps.type = 'submit'; } + if (typeof buttonProps.onClick === 'function') { + buttonProps.onKeyUp ??= (event) => { + if (event.key === 'Enter') { + buttonProps.onClick(); + } + }; + buttonProps.role ??= 'button'; + buttonProps.tabIndex ??= 0; + } return ( {leftIcon &&
{leftIcon}
} {children ?? ( diff --git a/ui/app/components/ui/color-indicator/color-indicator.js b/ui/app/components/ui/color-indicator/color-indicator.js index f34eef3d9..71e15706f 100644 --- a/ui/app/components/ui/color-indicator/color-indicator.js +++ b/ui/app/components/ui/color-indicator/color-indicator.js @@ -4,7 +4,7 @@ import PropTypes from 'prop-types'; import { COLORS, SIZES } from '../../../helpers/constants/design-system'; export default function ColorIndicator({ - size = 'small', + size = SIZES.SM, type = 'outlined', color = COLORS.UI4, borderColor, diff --git a/ui/app/components/ui/confusable/confusable.component.js b/ui/app/components/ui/confusable/confusable.component.js new file mode 100644 index 000000000..6e1ac6b40 --- /dev/null +++ b/ui/app/components/ui/confusable/confusable.component.js @@ -0,0 +1,39 @@ +import React, { useMemo } from 'react'; +import PropTypes from 'prop-types'; +import { confusables } from 'unicode-confusables'; +import Tooltip from '../tooltip'; +import { useI18nContext } from '../../../hooks/useI18nContext'; + +const Confusable = ({ input }) => { + const t = useI18nContext(); + const confusableData = useMemo(() => { + return confusables(input); + }, [input]); + + return confusableData.map(({ point, similarTo }, index) => { + const zeroWidth = similarTo === ''; + if (similarTo === undefined) { + return point; + } + return ( + + {zeroWidth ? '?' : point} + + ); + }); +}; + +Confusable.propTypes = { + input: PropTypes.string.isRequired, +}; + +export default Confusable; diff --git a/ui/app/components/ui/confusable/index.js b/ui/app/components/ui/confusable/index.js new file mode 100644 index 000000000..e117d0df6 --- /dev/null +++ b/ui/app/components/ui/confusable/index.js @@ -0,0 +1 @@ +export { default } from './confusable.component'; diff --git a/ui/app/components/ui/confusable/index.scss b/ui/app/components/ui/confusable/index.scss new file mode 100644 index 000000000..1178eb55d --- /dev/null +++ b/ui/app/components/ui/confusable/index.scss @@ -0,0 +1,5 @@ +.confusable { + &__point { + color: $Red-500; + } +} diff --git a/ui/app/components/ui/confusable/test/confusable.component.test.js b/ui/app/components/ui/confusable/test/confusable.component.test.js new file mode 100644 index 000000000..d3166ccd7 --- /dev/null +++ b/ui/app/components/ui/confusable/test/confusable.component.test.js @@ -0,0 +1,26 @@ +import assert from 'assert'; +import React from 'react'; +import { shallow } from 'enzyme'; +import Confusable from '../confusable.component'; + +describe('Confusable component', function () { + it('should detect zero-width unicode', function () { + const wrapper = shallow(); + assert.ok(wrapper.find('.confusable__point').length === 1); + }); + + it('should detect homoglyphic unicode points', function () { + const wrapper = shallow(); + assert.ok(wrapper.find('.confusable__point').length === 1); + }); + + it('should detect multiple homoglyphic unicode points', function () { + const wrapper = shallow(); + assert.ok(wrapper.find('.confusable__point').length === 5); + }); + + it('should not detect emoji', function () { + const wrapper = shallow(); + assert.ok(wrapper.find('.confusable__point').length === 0); + }); +}); diff --git a/ui/app/components/ui/currency-input/tests/currency-input.container.test.js b/ui/app/components/ui/currency-input/tests/currency-input.container.test.js index ccb5bb6d0..a0858288a 100644 --- a/ui/app/components/ui/currency-input/tests/currency-input.container.test.js +++ b/ui/app/components/ui/currency-input/tests/currency-input.container.test.js @@ -29,6 +29,7 @@ describe('CurrencyInput container', function () { }, provider: { type: 'mainnet', + chainId: '0x1', }, }, }, diff --git a/ui/app/components/ui/dropdown/dropdown.scss b/ui/app/components/ui/dropdown/dropdown.scss index e5d555ef9..ffcf9c99a 100644 --- a/ui/app/components/ui/dropdown/dropdown.scss +++ b/ui/app/components/ui/dropdown/dropdown.scss @@ -6,7 +6,7 @@ // TODO: remove these after getting autoprefixer working in Storybook -moz-appearance: none; -webkit-appearance: none; - border: 1px solid $Grey-500; + border: 1px solid #d2d8dd; border-radius: 6px; background-image: url('/images/icons/caret-down.svg'); background-repeat: no-repeat, repeat; diff --git a/ui/app/components/ui/tooltip/tooltip.js b/ui/app/components/ui/tooltip/tooltip.js index 4c01eaade..19d244737 100644 --- a/ui/app/components/ui/tooltip/tooltip.js +++ b/ui/app/components/ui/tooltip/tooltip.js @@ -14,9 +14,10 @@ export default class Tooltip extends PureComponent { offset: 0, size: 'small', title: null, - trigger: 'mouseenter', + trigger: 'mouseenter focus', wrapperClassName: undefined, theme: '', + tag: 'div', }; static propTypes = { @@ -35,6 +36,8 @@ export default class Tooltip extends PureComponent { wrapperClassName: PropTypes.string, style: PropTypes.object, theme: PropTypes.string, + tabIndex: PropTypes.number, + tag: PropTypes.string, }; render() { @@ -54,33 +57,37 @@ export default class Tooltip extends PureComponent { wrapperClassName, style, theme, + tabIndex, + tag, } = this.props; if (!title && !html) { return
{children}
; } - return ( -
- - {children} - -
+ return React.createElement( + tag, + { className: wrapperClassName }, + + {children} + , ); } } diff --git a/ui/app/components/ui/ui-components.scss b/ui/app/components/ui/ui-components.scss index cc8effe24..96d0c684a 100644 --- a/ui/app/components/ui/ui-components.scss +++ b/ui/app/components/ui/ui-components.scss @@ -12,6 +12,7 @@ @import 'chip/chip'; @import 'circle-icon/index'; @import 'color-indicator/color-indicator'; +@import 'confusable/index'; @import 'currency-display/index'; @import 'currency-input/index'; @import 'definition-list/definition-list'; diff --git a/ui/app/css/index.scss b/ui/app/css/index.scss index 50978fbcb..aa2604242 100644 --- a/ui/app/css/index.scss +++ b/ui/app/css/index.scss @@ -28,4 +28,3 @@ Third Party Library Styles */ @import '../../../node_modules/react-tippy/dist/tippy'; -@import '../../../node_modules/react-select/dist/react-select'; diff --git a/ui/app/css/itcss/components/index.scss b/ui/app/css/itcss/components/index.scss index c0bba546a..7887e1585 100644 --- a/ui/app/css/itcss/components/index.scss +++ b/ui/app/css/itcss/components/index.scss @@ -2,5 +2,3 @@ @import './newui-sections'; @import './send'; -// Tx List and Sections -@import './simple-dropdown'; diff --git a/ui/app/css/itcss/components/send.scss b/ui/app/css/itcss/components/send.scss index 49fcb3955..555692d81 100644 --- a/ui/app/css/itcss/components/send.scss +++ b/ui/app/css/itcss/components/send.scss @@ -641,6 +641,7 @@ &__asset-dropdown { height: 54px; border: none; + position: relative; &__single-asset { display: flex; @@ -653,6 +654,11 @@ } } + &__caret { + color: $silver; + padding: 0 10px; + } + &__asset { display: flex; flex-flow: row nowrap; diff --git a/ui/app/css/itcss/components/simple-dropdown.scss b/ui/app/css/itcss/components/simple-dropdown.scss deleted file mode 100644 index d29aaa55c..000000000 --- a/ui/app/css/itcss/components/simple-dropdown.scss +++ /dev/null @@ -1,66 +0,0 @@ -.simple-dropdown { - @include Paragraph; - - height: 56px; - display: flex; - justify-content: flex-start; - align-items: center; - border: 1px solid $alto; - border-radius: 4px; - background-color: $white; - color: #4d4d4d; - cursor: pointer; - position: relative; -} - -.simple-dropdown__caret { - color: $silver; - padding: 0 10px; -} - -.simple-dropdown__selected { - flex-grow: 1; - padding: 0 15px; -} - -.simple-dropdown__options { - z-index: 1050; - position: absolute; - height: 220px; - width: 100%; - border: 1px solid #d2d8dd; - border-radius: 4px; - background-color: #fff; - -webkit-box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.11); - box-shadow: 0 3px 6px 0 rgba(0, 0, 0, 0.11); - margin-top: 10px; - overflow-y: scroll; - left: 0; - top: 100%; -} - -.simple-dropdown__option { - padding: 10px; - - &:hover { - background-color: $gallery; - } -} - -.simple-dropdown__option--selected { - background-color: $alto; - - &:hover { - background-color: $alto; - cursor: default; - } -} - -.simple-dropdown__close-area { - position: fixed; - top: 0; - left: 0; - z-index: 1000; - width: 100%; - height: 100%; -} diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js index a89eeae36..a59785c7a 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.js @@ -1,4 +1,3 @@ -import { addHexPrefix } from '../../../../app/scripts/lib/util'; import { conversionRateSelector, currentCurrencySelector, @@ -24,32 +23,19 @@ import { conversionUtil } from '../../helpers/utils/conversion-util'; const createActionType = (action) => `metamask/confirm-transaction/${action}`; const UPDATE_TX_DATA = createActionType('UPDATE_TX_DATA'); -const CLEAR_TX_DATA = createActionType('CLEAR_TX_DATA'); const UPDATE_TOKEN_DATA = createActionType('UPDATE_TOKEN_DATA'); -const CLEAR_TOKEN_DATA = createActionType('CLEAR_TOKEN_DATA'); -const UPDATE_METHOD_DATA = createActionType('UPDATE_METHOD_DATA'); -const CLEAR_METHOD_DATA = createActionType('CLEAR_METHOD_DATA'); const CLEAR_CONFIRM_TRANSACTION = createActionType('CLEAR_CONFIRM_TRANSACTION'); const UPDATE_TRANSACTION_AMOUNTS = createActionType( 'UPDATE_TRANSACTION_AMOUNTS', ); const UPDATE_TRANSACTION_FEES = createActionType('UPDATE_TRANSACTION_FEES'); const UPDATE_TRANSACTION_TOTALS = createActionType('UPDATE_TRANSACTION_TOTALS'); -const UPDATE_TOKEN_PROPS = createActionType('UPDATE_TOKEN_PROPS'); const UPDATE_NONCE = createActionType('UPDATE_NONCE'); -const UPDATE_TO_SMART_CONTRACT = createActionType('UPDATE_TO_SMART_CONTRACT'); -const FETCH_DATA_START = createActionType('FETCH_DATA_START'); -const FETCH_DATA_END = createActionType('FETCH_DATA_END'); // Initial state const initState = { txData: {}, tokenData: {}, - methodData: {}, - tokenProps: { - tokenDecimals: '', - tokenSymbol: '', - }, fiatTransactionAmount: '', fiatTransactionFee: '', fiatTransactionTotal: '', @@ -60,8 +46,6 @@ const initState = { hexTransactionFee: '', hexTransactionTotal: '', nonce: '', - toSmartContract: false, - fetchingData: false, }; // Reducer @@ -74,11 +58,6 @@ export default function reducer(state = initState, action = {}) { ...action.payload, }, }; - case CLEAR_TX_DATA: - return { - ...state, - txData: {}, - }; case UPDATE_TOKEN_DATA: return { ...state, @@ -86,23 +65,6 @@ export default function reducer(state = initState, action = {}) { ...action.payload, }, }; - case CLEAR_TOKEN_DATA: - return { - ...state, - tokenData: {}, - }; - case UPDATE_METHOD_DATA: - return { - ...state, - methodData: { - ...action.payload, - }, - }; - case CLEAR_METHOD_DATA: - return { - ...state, - methodData: {}, - }; case UPDATE_TRANSACTION_AMOUNTS: { const { fiatTransactionAmount, @@ -146,37 +108,11 @@ export default function reducer(state = initState, action = {}) { hexTransactionTotal: hexTransactionTotal || state.hexTransactionTotal, }; } - case UPDATE_TOKEN_PROPS: { - const { tokenSymbol = '', tokenDecimals = '' } = action.payload; - return { - ...state, - tokenProps: { - ...state.tokenProps, - tokenSymbol, - tokenDecimals, - }, - }; - } case UPDATE_NONCE: return { ...state, nonce: action.payload, }; - case UPDATE_TO_SMART_CONTRACT: - return { - ...state, - toSmartContract: action.payload, - }; - case FETCH_DATA_START: - return { - ...state, - fetchingData: true, - }; - case FETCH_DATA_END: - return { - ...state, - fetchingData: false, - }; case CLEAR_CONFIRM_TRANSACTION: return initState; default: @@ -192,12 +128,6 @@ export function updateTxData(txData) { }; } -export function clearTxData() { - return { - type: CLEAR_TX_DATA, - }; -} - export function updateTokenData(tokenData) { return { type: UPDATE_TOKEN_DATA, @@ -205,25 +135,6 @@ export function updateTokenData(tokenData) { }; } -export function clearTokenData() { - return { - type: CLEAR_TOKEN_DATA, - }; -} - -export function updateMethodData(methodData) { - return { - type: UPDATE_METHOD_DATA, - payload: methodData, - }; -} - -export function clearMethodData() { - return { - type: CLEAR_METHOD_DATA, - }; -} - export function updateTransactionAmounts(amounts) { return { type: UPDATE_TRANSACTION_AMOUNTS, @@ -245,13 +156,6 @@ export function updateTransactionTotals(totals) { }; } -export function updateTokenProps(tokenProps) { - return { - type: UPDATE_TOKEN_PROPS, - payload: tokenProps, - }; -} - export function updateNonce(nonce) { return { type: UPDATE_NONCE, @@ -259,37 +163,6 @@ export function updateNonce(nonce) { }; } -export function updateToSmartContract(toSmartContract) { - return { - type: UPDATE_TO_SMART_CONTRACT, - payload: toSmartContract, - }; -} - -export function setFetchingData(isFetching) { - return { - type: isFetching ? FETCH_DATA_START : FETCH_DATA_END, - }; -} - -export function updateGasAndCalculate({ gasLimit, gasPrice }) { - return (dispatch, getState) => { - const { - confirmTransaction: { txData }, - } = getState(); - const newTxData = { - ...txData, - txParams: { - ...txData.txParams, - gas: addHexPrefix(gasLimit), - gasPrice: addHexPrefix(gasPrice), - }, - }; - - dispatch(updateTxDataAndCalculate(newTxData)); - }; -} - function increaseFromLastGasPrice(txData) { const { lastGasPrice, diff --git a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js index 6f512a703..1457d766f 100644 --- a/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js +++ b/ui/app/ducks/confirm-transaction/confirm-transaction.duck.test.js @@ -3,20 +3,16 @@ import configureMockStore from 'redux-mock-store'; import thunk from 'redux-thunk'; import sinon from 'sinon'; import { - TRANSACTION_CATEGORIES, - TRANSACTION_STATUSES, -} from '../../../../shared/constants/transaction'; + ROPSTEN_CHAIN_ID, + ROPSTEN_NETWORK_ID, +} from '../../../../shared/constants/network'; +import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; import ConfirmTransactionReducer, * as actions from './confirm-transaction.duck'; const initialState = { txData: {}, tokenData: {}, - methodData: {}, - tokenProps: { - tokenDecimals: '', - tokenSymbol: '', - }, fiatTransactionAmount: '', fiatTransactionFee: '', fiatTransactionTotal: '', @@ -27,28 +23,17 @@ const initialState = { hexTransactionFee: '', hexTransactionTotal: '', nonce: '', - toSmartContract: false, - fetchingData: false, }; const UPDATE_TX_DATA = 'metamask/confirm-transaction/UPDATE_TX_DATA'; -const CLEAR_TX_DATA = 'metamask/confirm-transaction/CLEAR_TX_DATA'; const UPDATE_TOKEN_DATA = 'metamask/confirm-transaction/UPDATE_TOKEN_DATA'; -const CLEAR_TOKEN_DATA = 'metamask/confirm-transaction/CLEAR_TOKEN_DATA'; -const UPDATE_METHOD_DATA = 'metamask/confirm-transaction/UPDATE_METHOD_DATA'; -const CLEAR_METHOD_DATA = 'metamask/confirm-transaction/CLEAR_METHOD_DATA'; const UPDATE_TRANSACTION_AMOUNTS = 'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS'; const UPDATE_TRANSACTION_FEES = 'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES'; const UPDATE_TRANSACTION_TOTALS = 'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS'; -const UPDATE_TOKEN_PROPS = 'metamask/confirm-transaction/UPDATE_TOKEN_PROPS'; const UPDATE_NONCE = 'metamask/confirm-transaction/UPDATE_NONCE'; -const UPDATE_TO_SMART_CONTRACT = - 'metamask/confirm-transaction/UPDATE_TO_SMART_CONTRACT'; -const FETCH_DATA_START = 'metamask/confirm-transaction/FETCH_DATA_START'; -const FETCH_DATA_END = 'metamask/confirm-transaction/FETCH_DATA_END'; const CLEAR_CONFIRM_TRANSACTION = 'metamask/confirm-transaction/CLEAR_CONFIRM_TRANSACTION'; @@ -61,13 +46,6 @@ describe('Confirm Transaction Duck', function () { tokenData: { name: 'abcToken', }, - methodData: { - name: TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE, - }, - tokenProps: { - tokenDecimals: '3', - tokenSymbol: 'ABC', - }, fiatTransactionAmount: '469.26', fiatTransactionFee: '0.01', fiatTransactionTotal: '1.000021', @@ -78,8 +56,6 @@ describe('Confirm Transaction Duck', function () { hexTransactionFee: '0x1319718a5000', hexTransactionTotal: '', nonce: '0x0', - toSmartContract: false, - fetchingData: false, }; it('should initialize state', function () { @@ -117,18 +93,6 @@ describe('Confirm Transaction Duck', function () { ); }); - it('should clear txData when receiving a CLEAR_TX_DATA action', function () { - assert.deepStrictEqual( - ConfirmTransactionReducer(mockState, { - type: CLEAR_TX_DATA, - }), - { - ...mockState, - txData: {}, - }, - ); - }); - it('should set tokenData when receiving a UPDATE_TOKEN_DATA action', function () { assert.deepStrictEqual( ConfirmTransactionReducer(mockState, { @@ -147,48 +111,6 @@ describe('Confirm Transaction Duck', function () { ); }); - it('should clear tokenData when receiving a CLEAR_TOKEN_DATA action', function () { - assert.deepStrictEqual( - ConfirmTransactionReducer(mockState, { - type: CLEAR_TOKEN_DATA, - }), - { - ...mockState, - tokenData: {}, - }, - ); - }); - - it('should set methodData when receiving a UPDATE_METHOD_DATA action', function () { - assert.deepStrictEqual( - ConfirmTransactionReducer(mockState, { - type: UPDATE_METHOD_DATA, - payload: { - name: 'transferFrom', - }, - }), - { - ...mockState, - methodData: { - ...mockState.methodData, - name: 'transferFrom', - }, - }, - ); - }); - - it('should clear methodData when receiving a CLEAR_METHOD_DATA action', function () { - assert.deepStrictEqual( - ConfirmTransactionReducer(mockState, { - type: CLEAR_METHOD_DATA, - }), - { - ...mockState, - methodData: {}, - }, - ); - }); - it('should update transaction amounts when receiving an UPDATE_TRANSACTION_AMOUNTS action', function () { assert.deepStrictEqual( ConfirmTransactionReducer(mockState, { @@ -246,25 +168,6 @@ describe('Confirm Transaction Duck', function () { ); }); - it('should update tokenProps when receiving an UPDATE_TOKEN_PROPS action', function () { - assert.deepStrictEqual( - ConfirmTransactionReducer(mockState, { - type: UPDATE_TOKEN_PROPS, - payload: { - tokenSymbol: 'DEF', - tokenDecimals: '1', - }, - }), - { - ...mockState, - tokenProps: { - tokenSymbol: 'DEF', - tokenDecimals: '1', - }, - }, - ); - }); - it('should update nonce when receiving an UPDATE_NONCE action', function () { assert.deepStrictEqual( ConfirmTransactionReducer(mockState, { @@ -278,41 +181,6 @@ describe('Confirm Transaction Duck', function () { ); }); - it('should update nonce when receiving an UPDATE_TO_SMART_CONTRACT action', function () { - assert.deepStrictEqual( - ConfirmTransactionReducer(mockState, { - type: UPDATE_TO_SMART_CONTRACT, - payload: true, - }), - { - ...mockState, - toSmartContract: true, - }, - ); - }); - - it('should set fetchingData to true when receiving a FETCH_DATA_START action', function () { - assert.deepStrictEqual( - ConfirmTransactionReducer(mockState, { - type: FETCH_DATA_START, - }), - { - ...mockState, - fetchingData: true, - }, - ); - }); - - it('should set fetchingData to false when receiving a FETCH_DATA_END action', function () { - assert.deepStrictEqual( - ConfirmTransactionReducer( - { fetchingData: true }, - { type: FETCH_DATA_END }, - ), - { fetchingData: false }, - ); - }); - it('should clear confirmTransaction when receiving a FETCH_DATA_END action', function () { assert.deepStrictEqual( ConfirmTransactionReducer(mockState, { @@ -334,14 +202,6 @@ describe('Confirm Transaction Duck', function () { assert.deepStrictEqual(actions.updateTxData(txData), expectedAction); }); - it('should create an action to clear txData', function () { - const expectedAction = { - type: CLEAR_TX_DATA, - }; - - assert.deepStrictEqual(actions.clearTxData(), expectedAction); - }); - it('should create an action to update tokenData', function () { const tokenData = { test: 123 }; const expectedAction = { @@ -355,35 +215,6 @@ describe('Confirm Transaction Duck', function () { ); }); - it('should create an action to clear tokenData', function () { - const expectedAction = { - type: CLEAR_TOKEN_DATA, - }; - - assert.deepStrictEqual(actions.clearTokenData(), expectedAction); - }); - - it('should create an action to update methodData', function () { - const methodData = { test: 123 }; - const expectedAction = { - type: UPDATE_METHOD_DATA, - payload: methodData, - }; - - assert.deepStrictEqual( - actions.updateMethodData(methodData), - expectedAction, - ); - }); - - it('should create an action to clear methodData', function () { - const expectedAction = { - type: CLEAR_METHOD_DATA, - }; - - assert.deepStrictEqual(actions.clearMethodData(), expectedAction); - }); - it('should create an action to update transaction amounts', function () { const transactionAmounts = { test: 123 }; const expectedAction = { @@ -423,22 +254,6 @@ describe('Confirm Transaction Duck', function () { ); }); - it('should create an action to update tokenProps', function () { - const tokenProps = { - tokenDecimals: '1', - tokenSymbol: 'abc', - }; - const expectedAction = { - type: UPDATE_TOKEN_PROPS, - payload: tokenProps, - }; - - assert.deepStrictEqual( - actions.updateTokenProps(tokenProps), - expectedAction, - ); - }); - it('should create an action to update nonce', function () { const nonce = '0x1'; const expectedAction = { @@ -449,22 +264,6 @@ describe('Confirm Transaction Duck', function () { assert.deepStrictEqual(actions.updateNonce(nonce), expectedAction); }); - it('should create an action to set fetchingData to true', function () { - const expectedAction = { - type: FETCH_DATA_START, - }; - - assert.deepStrictEqual(actions.setFetchingData(true), expectedAction); - }); - - it('should create an action to set fetchingData to false', function () { - const expectedAction = { - type: FETCH_DATA_END, - }; - - assert.deepStrictEqual(actions.setFetchingData(false), expectedAction); - }); - it('should create an action to clear confirmTransaction', function () { const expectedAction = { type: CLEAR_CONFIRM_TRANSACTION, @@ -489,67 +288,12 @@ describe('Confirm Transaction Duck', function () { global.eth.getCode.resetHistory(); }); - it('updates txData and gas on an existing transaction in confirmTransaction', function () { - const mockState = { - metamask: { - conversionRate: 468.58, - currentCurrency: 'usd', - }, - confirmTransaction: { - ethTransactionAmount: '1', - ethTransactionFee: '0.000021', - ethTransactionTotal: '1.000021', - fetchingData: false, - fiatTransactionAmount: '469.26', - fiatTransactionFee: '0.01', - fiatTransactionTotal: '469.27', - hexGasTotal: '0x1319718a5000', - methodData: {}, - nonce: '', - tokenData: {}, - tokenProps: { - tokenDecimals: '', - tokenSymbol: '', - }, - txData: { - history: [], - id: 2603411941761054, - loadingDefaults: false, - metamaskNetworkId: '3', - origin: 'faucet.metamask.io', - status: TRANSACTION_STATUSES.UNAPPROVED, - time: 1530838113716, - }, - }, - }; - - const middlewares = [thunk]; - const mockStore = configureMockStore(middlewares); - const store = mockStore(mockState); - const expectedActions = [ - 'metamask/confirm-transaction/UPDATE_TX_DATA', - 'metamask/confirm-transaction/UPDATE_TRANSACTION_AMOUNTS', - 'metamask/confirm-transaction/UPDATE_TRANSACTION_FEES', - 'metamask/confirm-transaction/UPDATE_TRANSACTION_TOTALS', - ]; - - store.dispatch( - actions.updateGasAndCalculate({ gasLimit: '0x2', gasPrice: '0x25' }), - ); - - const storeActions = store.getActions(); - assert.strictEqual(storeActions.length, expectedActions.length); - storeActions.forEach((action, index) => - assert.strictEqual(action.type, expectedActions[index]), - ); - }); - it('updates txData and updates gas values in confirmTransaction', function () { const txData = { history: [], id: 2603411941761054, loadingDefaults: false, - metamaskNetworkId: '3', + metamaskNetworkId: ROPSTEN_NETWORK_ID, origin: 'faucet.metamask.io', status: TRANSACTION_STATUSES.UNAPPROVED, time: 1530838113716, @@ -615,13 +359,16 @@ describe('Confirm Transaction Duck', function () { metamask: { conversionRate: 468.58, currentCurrency: 'usd', - network: '3', + network: ROPSTEN_NETWORK_ID, + provider: { + chainId: ROPSTEN_CHAIN_ID, + }, unapprovedTxs: { 2603411941761054: { history: [], id: 2603411941761054, loadingDefaults: false, - metamaskNetworkId: '3', + metamaskNetworkId: ROPSTEN_NETWORK_ID, origin: 'faucet.metamask.io', status: TRANSACTION_STATUSES.UNAPPROVED, time: 1530838113716, diff --git a/ui/app/ducks/gas/gas-duck.test.js b/ui/app/ducks/gas/gas-duck.test.js index 4e7be7956..b1c8447d9 100644 --- a/ui/app/ducks/gas/gas-duck.test.js +++ b/ui/app/ducks/gas/gas-duck.test.js @@ -2,6 +2,7 @@ import assert from 'assert'; import nock from 'nock'; import sinon from 'sinon'; import proxyquire from 'proxyquire'; +import BN from 'bn.js'; const fakeStorage = {}; @@ -58,6 +59,16 @@ describe('Gas Duck', function () { basicEstimateIsLoading: true, basicPriceEstimatesLastRetrieved: 0, }; + + const providerState = { + chainId: '0x1', + nickname: '', + rpcPrefs: {}, + rpcUrl: '', + ticker: 'ETH', + type: 'mainnet', + }; + const BASIC_GAS_ESTIMATE_LOADING_FINISHED = 'metamask/gas/BASIC_GAS_ESTIMATE_LOADING_FINISHED'; const BASIC_GAS_ESTIMATE_LOADING_STARTED = @@ -165,6 +176,7 @@ describe('Gas Duck', function () { await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: { ...initState, basicPriceAEstimatesLastRetrieved: 1000000 }, + metamask: { provider: { ...providerState } }, })); assert.deepStrictEqual(mockDistpatch.getCall(0).args, [ { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }, @@ -193,6 +205,39 @@ describe('Gas Duck', function () { ]); }); + it('should call fetch with the expected params for test network', async function () { + global.eth = { gasPrice: sinon.fake.returns(new BN(48199313, 10)) }; + + const mockDistpatch = sinon.spy(); + const providerStateForTestNetwrok = { + chainId: '0x5', + nickname: '', + rpcPrefs: {}, + rpcUrl: '', + ticker: 'ETH', + type: 'goerli', + }; + + await fetchBasicGasEstimates()(mockDistpatch, () => ({ + gas: { ...initState, basicPriceAEstimatesLastRetrieved: 1000000 }, + metamask: { provider: { ...providerStateForTestNetwrok } }, + })); + assert.deepStrictEqual(mockDistpatch.getCall(0).args, [ + { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }, + ]); + assert.deepStrictEqual(mockDistpatch.getCall(1).args, [ + { + type: SET_BASIC_GAS_ESTIMATE_DATA, + value: { + average: 0.0482, + }, + }, + ]); + assert.deepStrictEqual(mockDistpatch.getCall(2).args, [ + { type: BASIC_GAS_ESTIMATE_LOADING_FINISHED }, + ]); + }); + it('should fetch recently retrieved estimates from storage', async function () { const mockDistpatch = sinon.spy(); @@ -209,6 +254,7 @@ describe('Gas Duck', function () { await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: { ...initState }, + metamask: { provider: { ...providerState } }, })); assert.deepStrictEqual(mockDistpatch.getCall(0).args, [ { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }, @@ -244,6 +290,7 @@ describe('Gas Duck', function () { await fetchBasicGasEstimates()(mockDistpatch, () => ({ gas: { ...initState }, + metamask: { provider: { ...providerState } }, })); assert.deepStrictEqual(mockDistpatch.getCall(0).args, [ { type: BASIC_GAS_ESTIMATE_LOADING_STARTED }, diff --git a/ui/app/ducks/gas/gas.duck.js b/ui/app/ducks/gas/gas.duck.js index 73a621f8f..d97dd70c4 100644 --- a/ui/app/ducks/gas/gas.duck.js +++ b/ui/app/ducks/gas/gas.duck.js @@ -1,8 +1,12 @@ import { cloneDeep } from 'lodash'; import BigNumber from 'bignumber.js'; import { getStorageItem, setStorageItem } from '../../../lib/storage-helpers'; -import { decGWEIToHexWEI } from '../../helpers/utils/conversions.util'; +import { + decGWEIToHexWEI, + getValueFromWeiHex, +} from '../../helpers/utils/conversions.util'; import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'; +import { getIsMainnet, getCurrentChainId } from '../../selectors'; const fetchWithTimeout = getFetchWithTimeout(30000); @@ -111,7 +115,9 @@ async function basicGasPriceQuery() { export function fetchBasicGasEstimates() { return async (dispatch, getState) => { + const isMainnet = getIsMainnet(getState()); const { basicPriceEstimatesLastRetrieved } = getState().gas; + const timeLastRetrieved = basicPriceEstimatesLastRetrieved || (await getStorageItem('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED')) || @@ -120,15 +126,19 @@ export function fetchBasicGasEstimates() { dispatch(basicGasEstimatesLoadingStarted()); let basicEstimates; - if (Date.now() - timeLastRetrieved > 75000) { - basicEstimates = await fetchExternalBasicGasEstimates(dispatch); + if (isMainnet || process.env.IN_TEST) { + if (Date.now() - timeLastRetrieved > 75000) { + basicEstimates = await fetchExternalBasicGasEstimates(dispatch); + } else { + const cachedBasicEstimates = await getStorageItem( + 'BASIC_PRICE_ESTIMATES', + ); + basicEstimates = + cachedBasicEstimates || + (await fetchExternalBasicGasEstimates(dispatch)); + } } else { - const cachedBasicEstimates = await getStorageItem( - 'BASIC_PRICE_ESTIMATES', - ); - basicEstimates = - cachedBasicEstimates || - (await fetchExternalBasicGasEstimates(dispatch)); + basicEstimates = await fetchEthGasPriceEstimates(getState()); } dispatch(setBasicGasEstimateData(basicEstimates)); @@ -161,6 +171,37 @@ async function fetchExternalBasicGasEstimates(dispatch) { setStorageItem('BASIC_PRICE_ESTIMATES_LAST_RETRIEVED', timeRetrieved), ]); dispatch(setBasicPriceEstimatesLastRetrieved(timeRetrieved)); + return basicEstimates; +} + +async function fetchEthGasPriceEstimates(state) { + const chainId = getCurrentChainId(state); + const [cachedTimeLastRetrieved, cachedBasicEstimates] = await Promise.all([ + getStorageItem(`${chainId}_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED`), + getStorageItem(`${chainId}_BASIC_PRICE_ESTIMATES`), + ]); + const timeLastRetrieved = cachedTimeLastRetrieved || 0; + if (cachedBasicEstimates && Date.now() - timeLastRetrieved < 75000) { + return cachedBasicEstimates; + } + const gasPrice = await global.eth.gasPrice(); + const averageGasPriceInDecGWEI = getValueFromWeiHex({ + value: gasPrice.toString(16), + numberOfDecimals: 4, + toDenomination: 'GWEI', + }); + const basicEstimates = { + average: Number(averageGasPriceInDecGWEI), + }; + const timeRetrieved = Date.now(); + + await Promise.all([ + setStorageItem(`${chainId}_BASIC_PRICE_ESTIMATES`, basicEstimates), + setStorageItem( + `${chainId}_BASIC_PRICE_ESTIMATES_LAST_RETRIEVED`, + timeRetrieved, + ), + ]); return basicEstimates; } diff --git a/ui/app/ducks/swaps/swaps.js b/ui/app/ducks/swaps/swaps.js index f59f20639..1354596e2 100644 --- a/ui/app/ducks/swaps/swaps.js +++ b/ui/app/ducks/swaps/swaps.js @@ -288,7 +288,7 @@ export const getApproveTxParams = (state) => { } const data = getSwapsState(state)?.customApproveTxData || approvalNeeded.data; - const gasPrice = getCustomSwapsGasPrice(state) || approvalNeeded.gasPrice; + const gasPrice = getUsedSwapsGasPrice(state); return { ...approvalNeeded, gasPrice, data }; }; diff --git a/ui/app/helpers/constants/common.js b/ui/app/helpers/constants/common.js index c2e8f9bb5..0231bf85b 100644 --- a/ui/app/helpers/constants/common.js +++ b/ui/app/helpers/constants/common.js @@ -5,6 +5,8 @@ export const WEI = 'WEI'; export const PRIMARY = 'PRIMARY'; export const SECONDARY = 'SECONDARY'; +export const ERC20 = 'ERC20'; + export const GAS_ESTIMATE_TYPES = { SLOW: 'SLOW', AVERAGE: 'AVERAGE', diff --git a/ui/app/helpers/constants/routes.js b/ui/app/helpers/constants/routes.js index 5b92c3fd5..2079dcf40 100644 --- a/ui/app/helpers/constants/routes.js +++ b/ui/app/helpers/constants/routes.js @@ -64,6 +64,7 @@ const CONFIRM_TOKEN_METHOD_PATH = '/token-method'; const SIGNATURE_REQUEST_PATH = '/signature-request'; const DECRYPT_MESSAGE_REQUEST_PATH = '/decrypt-message-request'; const ENCRYPTION_PUBLIC_KEY_REQUEST_PATH = '/encryption-public-key-request'; +const CONFIRMATION_V_NEXT_ROUTE = '/confirmation'; // Used to pull a convenient name for analytics tracking events. The key must // be react-router ready path, and can include params such as :id for popup windows @@ -170,6 +171,7 @@ export { SIGNATURE_REQUEST_PATH, DECRYPT_MESSAGE_REQUEST_PATH, ENCRYPTION_PUBLIC_KEY_REQUEST_PATH, + CONFIRMATION_V_NEXT_ROUTE, INITIALIZE_METAMETRICS_OPT_IN_ROUTE, ADVANCED_ROUTE, SECURITY_ROUTE, diff --git a/ui/app/helpers/utils/transactions.util.js b/ui/app/helpers/utils/transactions.util.js index 61f2e1f8c..463ddab5e 100644 --- a/ui/app/helpers/utils/transactions.util.js +++ b/ui/app/helpers/utils/transactions.util.js @@ -205,3 +205,45 @@ export function getBlockExplorerUrlForTx(networkId, hash, rpcPrefs = {}) { const prefix = getEtherscanNetworkPrefix(networkId); return `https://${prefix}etherscan.io/tx/${hash}`; } + +/** + * Returns a title for the given transaction category. + * + * This will throw an error if the transaction category is unrecognized and no default is provided. + * @param {function} t - The translation function + * @param {TRANSACTION_CATEGORIES[keyof TRANSACTION_CATEGORIES]} transactionCategory - The transaction category constant + * @returns {string} The transaction category title + */ +export function getTransactionCategoryTitle(t, transactionCategory) { + switch (transactionCategory) { + case TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER: { + return t('transfer'); + } + case TRANSACTION_CATEGORIES.TOKEN_METHOD_TRANSFER_FROM: { + return t('transferFrom'); + } + case TRANSACTION_CATEGORIES.TOKEN_METHOD_APPROVE: { + return t('approve'); + } + case TRANSACTION_CATEGORIES.SENT_ETHER: { + return t('sentEther'); + } + case TRANSACTION_CATEGORIES.CONTRACT_INTERACTION: { + return t('contractInteraction'); + } + case TRANSACTION_CATEGORIES.DEPLOY_CONTRACT: { + return t('contractDeployment'); + } + case TRANSACTION_CATEGORIES.SWAP: { + return t('swap'); + } + case TRANSACTION_CATEGORIES.SWAP_APPROVAL: { + return t('swapApproval'); + } + default: { + throw new Error( + `Unrecognized transaction category: ${transactionCategory}`, + ); + } + } +} diff --git a/ui/app/helpers/utils/util.js b/ui/app/helpers/utils/util.js index bc22d05c1..a7c06c052 100644 --- a/ui/app/helpers/utils/util.js +++ b/ui/app/helpers/utils/util.js @@ -4,9 +4,6 @@ import BigNumber from 'bignumber.js'; import ethUtil from 'ethereumjs-util'; import { DateTime } from 'luxon'; import { addHexPrefix } from '../../../../app/scripts/lib/util'; -import getFetchWithTimeout from '../../../../shared/modules/fetch-with-timeout'; - -const fetchWithTimeout = getFetchWithTimeout(30000); // formatData :: ( date: ) -> String export function formatDate(date, format = "M/d/y 'at' T") { @@ -353,6 +350,17 @@ export function stripHttpSchemes(urlString) { return urlString.replace(/^https?:\/\//u, ''); } +/** + * Strips the following schemes from URL strings: + * - https + * + * @param {string} urlString - The URL string to strip the scheme from. + * @returns {string} The URL string, without the scheme, if it was stripped. + */ +export function stripHttpsScheme(urlString) { + return urlString.replace(/^https:\/\//u, ''); +} + /** * Checks whether a URL-like value (object or string) is an extension URL. * @@ -456,54 +464,3 @@ export function constructTxParams({ } return addHexPrefixToObjectValues(txParams); } - -/** - * Makes a JSON RPC request to the given URL, with the given RPC method and params. - * - * @param {string} rpcUrl - The RPC endpoint URL to target. - * @param {string} rpcMethod - The RPC method to request. - * @param {Array} [rpcParams] - The RPC method params. - * @returns {Promise} Returns the result of the RPC method call, - * or throws an error in case of failure. - */ -export async function jsonRpcRequest(rpcUrl, rpcMethod, rpcParams = []) { - let fetchUrl = rpcUrl; - const headers = { - 'Content-Type': 'application/json', - }; - // Convert basic auth URL component to Authorization header - const { origin, pathname, username, password, search } = new URL(rpcUrl); - // URLs containing username and password needs special processing - if (username && password) { - const encodedAuth = Buffer.from(`${username}:${password}`).toString( - 'base64', - ); - headers.Authorization = `Basic ${encodedAuth}`; - fetchUrl = `${origin}${pathname}${search}`; - } - const jsonRpcResponse = await fetchWithTimeout(fetchUrl, { - method: 'POST', - body: JSON.stringify({ - id: Date.now().toString(), - jsonrpc: '2.0', - method: rpcMethod, - params: rpcParams, - }), - headers, - cache: 'default', - }).then((httpResponse) => httpResponse.json()); - - if ( - !jsonRpcResponse || - Array.isArray(jsonRpcResponse) || - typeof jsonRpcResponse !== 'object' - ) { - throw new Error(`RPC endpoint ${rpcUrl} returned non-object response.`); - } - const { error, result } = jsonRpcResponse; - - if (error) { - throw new Error(error?.message || error); - } - return result; -} diff --git a/ui/app/hooks/useOriginMetadata.js b/ui/app/hooks/useOriginMetadata.js new file mode 100644 index 000000000..31fb405d7 --- /dev/null +++ b/ui/app/hooks/useOriginMetadata.js @@ -0,0 +1,42 @@ +import { useSelector } from 'react-redux'; +import { getDomainMetadata } from '../selectors'; + +/** + * @typedef {Object} OriginMetadata + * @property {string} host - The host of the origin + * @property {string} hostname - The hostname of the origin (host + port) + * @property {string} origin - The original origin string itself + * @property {string} [icon] - The origin's site icon if available + * @property {number} [lastUpdated] - Timestamp of the last update to the + * origin's metadata + * @property {string} [name] - The registered name of the origin if available + */ + +/** + * Gets origin metadata from redux and formats it appropriately. + * @param {string} origin - The fully formed url of the site interacting with + * MetaMask + * @returns {OriginMetadata | null} - The origin metadata available for the + * current origin + */ +export function useOriginMetadata(origin) { + const domainMetaData = useSelector(getDomainMetadata); + if (!origin) { + return null; + } + const url = new URL(origin); + + const minimumOriginMetadata = { + host: url.host, + hostname: url.hostname, + origin, + }; + + if (domainMetaData?.[origin]) { + return { + ...minimumOriginMetadata, + ...domainMetaData[origin], + }; + } + return minimumOriginMetadata; +} diff --git a/ui/app/hooks/useTransactionDisplayData.js b/ui/app/hooks/useTransactionDisplayData.js index ff0b7b6c9..18b0e7c39 100644 --- a/ui/app/hooks/useTransactionDisplayData.js +++ b/ui/app/hooks/useTransactionDisplayData.js @@ -1,6 +1,9 @@ import { useSelector } from 'react-redux'; import { getKnownMethodData } from '../selectors/selectors'; -import { getStatusKey } from '../helpers/utils/transactions.util'; +import { + getStatusKey, + getTransactionCategoryTitle, +} from '../helpers/utils/transactions.util'; import { camelCaseToCapitalize } from '../helpers/utils/common.util'; import { PRIMARY, SECONDARY } from '../helpers/constants/common'; import { getTokenAddressParam } from '../helpers/utils/token-util'; @@ -186,9 +189,13 @@ export function useTransactionDisplayData(transactionGroup) { transactionCategory === TRANSACTION_CATEGORIES.CONTRACT_INTERACTION ) { category = TRANSACTION_GROUP_CATEGORIES.INTERACTION; + const transactionCategoryTitle = getTransactionCategoryTitle( + t, + transactionCategory, + ); title = (methodData?.name && camelCaseToCapitalize(methodData.name)) || - t(transactionCategory); + transactionCategoryTitle; subtitle = origin; subtitleContainsOrigin = true; } else if (transactionCategory === TRANSACTION_CATEGORIES.INCOMING) { diff --git a/ui/app/pages/asset/asset.scss b/ui/app/pages/asset/asset.scss index f80cd66a4..b9844e8e2 100644 --- a/ui/app/pages/asset/asset.scss +++ b/ui/app/pages/asset/asset.scss @@ -13,7 +13,7 @@ justify-content: space-between; align-items: center; padding: 16px; - height: 54px; + height: 64px; } .asset-breadcrumb { @@ -41,8 +41,6 @@ } &__icon { - @include Paragraph; - font-weight: 900; } } diff --git a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js index bae3e22eb..3ed8f67c2 100644 --- a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js +++ b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.component.js @@ -179,7 +179,7 @@ export default class ConfirmDecryptMessage extends Component { const { t } = this.context; const originMetadata = domainMetadata[txData.msgParams.origin]; - const name = originMetadata?.name || txData.msgParams.origin; + const name = originMetadata?.hostname || txData.msgParams.origin; const notice = t('decryptMessageNotice', [txData.msgParams.origin]); const { diff --git a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js index 800ec7abc..f1cc41f7b 100644 --- a/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js +++ b/ui/app/pages/confirm-decrypt-message/confirm-decrypt-message.container.js @@ -10,6 +10,7 @@ import { } from '../../store/actions'; import { getTargetAccountWithSendEtherInfo, + unconfirmedTransactionsListSelector, conversionRateSelector, } from '../../selectors'; import { clearConfirmTransaction } from '../../ducks/confirm-transaction/confirm-transaction.duck'; @@ -18,11 +19,12 @@ import ConfirmDecryptMessage from './confirm-decrypt-message.component'; function mapStateToProps(state) { const { - confirmTransaction, metamask: { domainMetadata = {} }, } = state; - const { txData = {} } = confirmTransaction; + const unconfirmedTransactions = unconfirmedTransactionsListSelector(state); + + const txData = unconfirmedTransactions[0]; const { msgParams: { from }, diff --git a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js index 45e192da6..fb4100832 100644 --- a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js +++ b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.component.js @@ -160,7 +160,7 @@ export default class ConfirmEncryptionPublicKey extends Component { const originMetadata = domainMetadata[txData.origin]; const notice = t('encryptionPublicKeyNotice', [txData.origin]); - const name = originMetadata?.name || txData.origin; + const name = originMetadata?.hostname || txData.origin; return (
diff --git a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js index ee8061dcf..3439589b6 100644 --- a/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js +++ b/ui/app/pages/confirm-encryption-public-key/confirm-encryption-public-key.container.js @@ -10,6 +10,7 @@ import { import { conversionRateSelector, + unconfirmedTransactionsListSelector, getTargetAccountWithSendEtherInfo, } from '../../selectors'; @@ -19,11 +20,12 @@ import ConfirmEncryptionPublicKey from './confirm-encryption-public-key.componen function mapStateToProps(state) { const { - confirmTransaction, metamask: { domainMetadata = {} }, } = state; - const { txData = {} } = confirmTransaction; + const unconfirmedTransactions = unconfirmedTransactionsListSelector(state); + + const txData = unconfirmedTransactions[0]; const { msgParams: from } = txData; diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js index 5d09b3198..d1b702df9 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.component.js @@ -22,6 +22,7 @@ import { TRANSACTION_CATEGORIES, TRANSACTION_STATUSES, } from '../../../../shared/constants/transaction'; +import { getTransactionCategoryTitle } from '../../helpers/utils/transactions.util'; export default class ConfirmTransactionBase extends Component { static contextTypes = { @@ -690,7 +691,7 @@ export default class ConfirmTransactionBase extends Component { let functionType = getMethodName(name); if (!functionType) { if (transactionCategory) { - functionType = t(transactionCategory) || transactionCategory; + functionType = getTransactionCategoryTitle(t, transactionCategory); } else { functionType = t('contractInteraction'); } diff --git a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js index 0875f8892..69c8fa0d9 100644 --- a/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js +++ b/ui/app/pages/confirm-transaction-base/confirm-transaction-base.container.js @@ -39,6 +39,7 @@ import { transactionFeeSelector, } from '../../selectors'; import { getMostRecentOverviewPage } from '../../ducks/history/history'; +import { transactionMatchesNetwork } from '../../../../shared/modules/transaction.utils'; import ConfirmTransactionBase from './confirm-transaction-base.component'; const casedContractMap = Object.keys(contractMap).reduce((acc, base) => { @@ -77,6 +78,7 @@ const mapStateToProps = (state, ownProps) => { unapprovedTxs, metaMetricsSendCount, nextNonce, + provider: { chainId }, } = metamask; const { tokenData, txData, tokenProps, nonce } = confirmTransaction; const { @@ -127,7 +129,9 @@ const mapStateToProps = (state, ownProps) => { } const currentNetworkUnapprovedTxs = Object.keys(unapprovedTxs) - .filter((key) => unapprovedTxs[key].metamaskNetworkId === network) + .filter((key) => + transactionMatchesNetwork(unapprovedTxs[key], chainId, network), + ) .reduce((acc, key) => ({ ...acc, [key]: unapprovedTxs[key] }), {}); const unapprovedTxCount = valuesFor(currentNetworkUnapprovedTxs).length; diff --git a/ui/app/pages/confirm-transaction/conf-tx.js b/ui/app/pages/confirm-transaction/conf-tx.js index 5acc1c435..ef8657424 100644 --- a/ui/app/pages/confirm-transaction/conf-tx.js +++ b/ui/app/pages/confirm-transaction/conf-tx.js @@ -32,6 +32,7 @@ function mapStateToProps(state) { index: txId, warning: state.appState.warning, network: state.metamask.network, + chainId: state.metamask.provider.chainId, currentCurrency: state.metamask.currentCurrency, blockGasLimit: state.metamask.currentBlockGasLimit, unapprovedMsgCount, @@ -49,6 +50,7 @@ class ConfirmTxScreen extends Component { unapprovedPersonalMsgCount: PropTypes.number, unapprovedTypedMessagesCount: PropTypes.number, network: PropTypes.string, + chainId: PropTypes.string, index: PropTypes.number, unapprovedTxs: PropTypes.object, unapprovedMsgs: PropTypes.object, @@ -94,6 +96,7 @@ class ConfirmTxScreen extends Component { unapprovedPersonalMsgs, unapprovedTypedMessages, match: { params: { id: transactionId } = {} }, + chainId, } = this.props; const unconfTxList = txHelper( @@ -102,6 +105,7 @@ class ConfirmTxScreen extends Component { unapprovedPersonalMsgs, unapprovedTypedMessages, network, + chainId, ); log.info(`rendering a combined ${unconfTxList.length} unconf msgs & txs`); @@ -177,9 +181,10 @@ class ConfirmTxScreen extends Component { history, mostRecentOverviewPage, network, + chainId, send, } = this.props; - const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network); + const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network, chainId); if ( unconfTxList.length === 0 && @@ -194,6 +199,7 @@ class ConfirmTxScreen extends Component { const { unapprovedTxs = {}, network, + chainId, currentNetworkTxList, send, history, @@ -207,13 +213,20 @@ class ConfirmTxScreen extends Component { prevTx = currentNetworkTxList.find(({ id }) => `${id}` === transactionId); } else { const { index: prevIndex, unapprovedTxs: prevUnapprovedTxs } = prevProps; - const prevUnconfTxList = txHelper(prevUnapprovedTxs, {}, {}, {}, network); + const prevUnconfTxList = txHelper( + prevUnapprovedTxs, + {}, + {}, + {}, + network, + chainId, + ); const prevTxData = prevUnconfTxList[prevIndex] || {}; prevTx = currentNetworkTxList.find(({ id }) => id === prevTxData.id) || {}; } - const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network); + const unconfTxList = txHelper(unapprovedTxs, {}, {}, {}, network, chainId); if (prevTx && prevTx.status === TRANSACTION_STATUSES.DROPPED) { this.props.dispatch( diff --git a/ui/app/pages/confirmation/components/confirmation-footer/confirmation-footer.js b/ui/app/pages/confirmation/components/confirmation-footer/confirmation-footer.js new file mode 100644 index 000000000..9574a13a4 --- /dev/null +++ b/ui/app/pages/confirmation/components/confirmation-footer/confirmation-footer.js @@ -0,0 +1,33 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import Button from '../../../../components/ui/button'; + +export default function ConfirmationFooter({ + onApprove, + onCancel, + approveText, + cancelText, + alerts, +}) { + return ( +
+ {alerts} +
+ + +
+
+ ); +} + +ConfirmationFooter.propTypes = { + alerts: PropTypes.node, + onApprove: PropTypes.func.isRequired, + onCancel: PropTypes.func.isRequired, + approveText: PropTypes.string.isRequired, + cancelText: PropTypes.string.isRequired, +}; diff --git a/ui/app/pages/confirmation/components/confirmation-footer/confirmation-footer.scss b/ui/app/pages/confirmation/components/confirmation-footer/confirmation-footer.scss new file mode 100644 index 000000000..9bad79296 --- /dev/null +++ b/ui/app/pages/confirmation/components/confirmation-footer/confirmation-footer.scss @@ -0,0 +1,14 @@ +.confirmation-footer { + grid-area: footer; + + &__actions { + display: flex; + border-top: 1px solid $ui-2; + background-color: white; + padding: 16px; + + & .button:first-child { + margin-right: 16px; + } + } +} diff --git a/ui/app/pages/confirmation/components/confirmation-footer/index.js b/ui/app/pages/confirmation/components/confirmation-footer/index.js new file mode 100644 index 000000000..e2f17c87a --- /dev/null +++ b/ui/app/pages/confirmation/components/confirmation-footer/index.js @@ -0,0 +1 @@ +export { default } from './confirmation-footer'; diff --git a/ui/app/pages/confirmation/confirmation.js b/ui/app/pages/confirmation/confirmation.js new file mode 100644 index 000000000..47ce4f191 --- /dev/null +++ b/ui/app/pages/confirmation/confirmation.js @@ -0,0 +1,230 @@ +import React, { + useCallback, + useEffect, + useMemo, + useReducer, + useState, +} from 'react'; +import { useDispatch, useSelector } from 'react-redux'; +import { useHistory } from 'react-router-dom'; +import { isEqual } from 'lodash'; +import { produce } from 'immer'; +import Box from '../../components/ui/box'; +import Chip from '../../components/ui/chip'; +import MetaMaskTemplateRenderer from '../../components/app/metamask-template-renderer'; +import SiteIcon from '../../components/ui/site-icon'; +import { DEFAULT_ROUTE } from '../../helpers/constants/routes'; +import { stripHttpsScheme } from '../../helpers/utils/util'; +import { useI18nContext } from '../../hooks/useI18nContext'; +import { useOriginMetadata } from '../../hooks/useOriginMetadata'; +import { getUnapprovedConfirmations } from '../../selectors'; +import NetworkDisplay from '../../components/app/network-display/network-display'; +import { COLORS, SIZES } from '../../helpers/constants/design-system'; +import Callout from '../../components/ui/callout'; +import ConfirmationFooter from './components/confirmation-footer'; +import { getTemplateValues, getTemplateAlerts } from './templates'; + +/** + * a very simple reducer using produce from Immer to keep state manipulation + * immutable and painless. This state is not stored in redux state because it + * should persist only for the lifespan of the current session, and will only + * be used on this page. Dismissing alerts for confirmations should persist + * while the user pages back and forth between confirmations. However, if the + * user closes the confirmation window and later reopens the extension they + * should be displayed the alerts again. + */ +const alertStateReducer = produce((state, action) => { + switch (action.type) { + case 'dismiss': + if (state?.[action.confirmationId]?.[action.alertId]) { + state[action.confirmationId][action.alertId].dismissed = true; + } + break; + case 'set': + if (!state[action.confirmationId]) { + state[action.confirmationId] = {}; + } + action.alerts.forEach((alert) => { + state[action.confirmationId][alert.id] = { + ...alert, + dismissed: false, + }; + }); + break; + default: + throw new Error( + 'You must provide a type when dispatching an action for alertState', + ); + } +}); + +/** + * Encapsulates the state and effects needed to manage alert state for the + * confirmation page in a custom hook. This hook is not likely to be used + * outside of this file, but it helps to reduce complexity of the primary + * component. + * @param {Object} pendingConfirmation - a pending confirmation waiting for + * user approval + * @returns {[alertState: Object, dismissAlert: Function]} - tuple with + * the current alert state and function to dismiss an alert by id + */ +function useAlertState(pendingConfirmation) { + const [alertState, dispatch] = useReducer(alertStateReducer, {}); + + /** + * Computation of the current alert state happens every time the current + * pendingConfirmation changes. The async function getTemplateAlerts is + * responsible for returning alert state. Setting state on unmounted + * components is an anti-pattern, so we use a isMounted variable to keep + * track of the current state of the component. Returning a function that + * sets isMounted to false when the component is unmounted. + */ + useEffect(() => { + let isMounted = true; + if (pendingConfirmation) { + getTemplateAlerts(pendingConfirmation).then((alerts) => { + if (isMounted && alerts) { + dispatch({ + type: 'set', + confirmationId: pendingConfirmation.id, + alerts, + }); + } + }); + } + return () => { + isMounted = false; + }; + }, [pendingConfirmation]); + + const dismissAlert = useCallback( + (alertId) => { + dispatch({ + type: 'dismiss', + confirmationId: pendingConfirmation.id, + alertId, + }); + }, + [pendingConfirmation], + ); + + return [alertState, dismissAlert]; +} + +export default function ConfirmationPage() { + const t = useI18nContext(); + const dispatch = useDispatch(); + const history = useHistory(); + const pendingConfirmations = useSelector(getUnapprovedConfirmations, isEqual); + const [currentPendingConfirmation, setCurrentPendingConfirmation] = useState( + 0, + ); + const pendingConfirmation = pendingConfirmations[currentPendingConfirmation]; + const originMetadata = useOriginMetadata(pendingConfirmation?.origin); + const [alertState, dismissAlert] = useAlertState(pendingConfirmation); + + // Generating templatedValues is potentially expensive, and if done on every render + // will result in a new object. Avoiding calling this generation unnecessarily will + // improve performance and prevent unnecessary draws. + const templatedValues = useMemo(() => { + return pendingConfirmation + ? getTemplateValues(pendingConfirmation, t, dispatch) + : {}; + }, [pendingConfirmation, t, dispatch]); + + useEffect(() => { + // If the number of pending confirmations reduces to zero when the user + // return them to the default route. Otherwise, if the number of pending + // confirmations reduces to a number that is less than the currently + // viewed index, reset the index. + if (pendingConfirmations.length === 0) { + history.push(DEFAULT_ROUTE); + } else if (pendingConfirmations.length <= currentPendingConfirmation) { + setCurrentPendingConfirmation(pendingConfirmations.length - 1); + } + }, [pendingConfirmations, history, currentPendingConfirmation]); + if (!pendingConfirmation) { + return null; + } + + return ( +
+ {pendingConfirmations.length > 1 && ( +
+

+ {t('xOfYPending', [ + currentPendingConfirmation + 1, + pendingConfirmations.length, + ])} +

+ {currentPendingConfirmation > 0 && ( + + )} + +
+ )} +
+ + + + + + } + /> + + +
+ alert.dismissed === false) + .map((alert, idx, filtered) => ( + dismissAlert(alert.id)} + isFirst={idx === 0} + isLast={idx === filtered.length - 1} + isMultiple={filtered.length > 1} + > + + + )) + } + onApprove={templatedValues.onApprove} + onCancel={templatedValues.onCancel} + approveText={templatedValues.approvalText} + cancelText={templatedValues.cancelText} + /> +
+ ); +} diff --git a/ui/app/pages/confirmation/confirmation.scss b/ui/app/pages/confirmation/confirmation.scss new file mode 100644 index 000000000..dea6190ee --- /dev/null +++ b/ui/app/pages/confirmation/confirmation.scss @@ -0,0 +1,62 @@ +@import 'components/confirmation-footer/confirmation-footer'; + +.confirmation-page { + width: 100%; + height: 100%; + position: relative; + background: white; + display: grid; + flex-direction: column; + grid-template-columns: 1fr; + grid-template-rows: auto 1fr auto; + grid-template-areas: + 'navigation' + 'content' + 'footer'; + + a { + color: $primary-1; + } + + &__content { + grid-area: content; + padding: 16px 16px 0; + + & > :last-child { + margin-bottom: 16px; + } + } + + &__navigation { + @include H7; + + grid-area: navigation; + background-color: $Grey-000; + border-bottom: 1px solid $geyser; + padding: 6px 16px 5px 16px; + color: $Grey-500; + display: grid; + grid-template-columns: 1fr minmax(0, auto) minmax(0, auto); + align-items: center; + } + + &__navigation-button { + background-color: white; + border-radius: 100px; + color: $Grey-500; + font-size: $font-size-h6; + height: 20px; + width: 20px; + padding: 0; + + &:disabled { + cursor: not-allowed; + background-color: $Grey-100; + color: $Grey-300; + } + } + + &__navigation &__navigation-button:last-child { + margin-left: 8px; + } +} diff --git a/ui/app/pages/confirmation/index.js b/ui/app/pages/confirmation/index.js new file mode 100644 index 000000000..2bb2f9499 --- /dev/null +++ b/ui/app/pages/confirmation/index.js @@ -0,0 +1 @@ +export { default } from './confirmation'; diff --git a/ui/app/pages/confirmation/templates/add-ethereum-chain.js b/ui/app/pages/confirmation/templates/add-ethereum-chain.js new file mode 100644 index 000000000..a9c85c53d --- /dev/null +++ b/ui/app/pages/confirmation/templates/add-ethereum-chain.js @@ -0,0 +1,217 @@ +import { ethErrors } from 'eth-rpc-errors'; +import { + SEVERITIES, + TYPOGRAPHY, +} from '../../../helpers/constants/design-system'; +import fetchWithCache from '../../../helpers/utils/fetch-with-cache'; + +const UNRECOGNIZED_CHAIN = { + id: 'UNRECOGNIZED_CHAIN', + severity: SEVERITIES.WARNING, + content: { + element: 'span', + children: { + element: 'MetaMaskTranslation', + props: { + translationKey: 'unrecognizedChain', + variables: [ + { + element: 'a', + key: 'unrecognizedChainLink', + props: { + href: + 'https://metamask.zendesk.com/hc/en-us/articles/360057142392', + target: '__blank', + tabIndex: 0, + }, + children: { + element: 'MetaMaskTranslation', + props: { + translationKey: 'unrecognizedChainLinkText', + }, + }, + }, + ], + }, + }, + }, +}; + +const INVALID_CHAIN = { + id: 'INVALID_CHAIN', + severity: SEVERITIES.DANGER, + content: { + element: 'span', + children: { + element: 'MetaMaskTranslation', + props: { + translationKey: 'mismatchedChain', + variables: [ + { + element: 'a', + key: 'mismatchedChainLink', + props: { + href: + 'https://metamask.zendesk.com/hc/en-us/articles/360057142392', + target: '__blank', + tabIndex: 0, + }, + children: { + element: 'MetaMaskTranslation', + props: { + translationKey: 'mismatchedChainLinkText', + }, + }, + }, + ], + }, + }, + }, +}; + +async function getAlerts(pendingApproval) { + const alerts = []; + const safeChainsList = await fetchWithCache( + 'https://chainid.network/chains.json', + ); + const matchedChain = safeChainsList.find( + (chain) => + chain.chainId === parseInt(pendingApproval.requestData.chainId, 16), + ); + let validated = Boolean(matchedChain); + + if (matchedChain) { + if ( + matchedChain.nativeCurrency?.decimals !== 18 || + matchedChain.name.toLowerCase() !== + pendingApproval.requestData.chainName.toLowerCase() || + matchedChain.nativeCurrency?.symbol !== pendingApproval.requestData.ticker + ) { + validated = false; + } + + const { origin } = new URL(pendingApproval.requestData.rpcUrl); + if (!matchedChain.rpc.map((rpc) => new URL(rpc).origin).includes(origin)) { + validated = false; + } + } + + if (!matchedChain) { + alerts.push(UNRECOGNIZED_CHAIN); + } else if (!validated) { + alerts.push(INVALID_CHAIN); + } + return alerts; +} + +function getValues(pendingApproval, t, actions) { + return { + content: [ + { + element: 'Typography', + key: 'title', + children: t('addEthereumChainConfirmationTitle'), + props: { + variant: TYPOGRAPHY.H3, + align: 'center', + fontWeight: 'bold', + boxProps: { + margin: [0, 0, 4], + }, + }, + }, + { + element: 'Typography', + key: 'description', + children: t('addEthereumChainConfirmationDescription'), + props: { + variant: TYPOGRAPHY.H7, + align: 'center', + boxProps: { + margin: [0, 0, 4], + }, + }, + }, + { + element: 'Typography', + key: 'only-add-networks-you-trust', + children: [ + { + element: 'b', + key: 'bolded-text', + children: `${t('addEthereumChainConfirmationRisks')} `, + }, + { + element: 'MetaMaskTranslation', + key: 'learn-about-risks', + props: { + translationKey: 'addEthereumChainConfirmationRisksLearnMore', + variables: [ + { + element: 'a', + children: t('addEthereumChainConfirmationRisksLearnMoreLink'), + key: 'addEthereumChainConfirmationRisksLearnMoreLink', + props: { + href: + 'https://metamask.zendesk.com/hc/en-us/articles/360056196151', + target: '__blank', + }, + }, + ], + }, + }, + ], + props: { + variant: TYPOGRAPHY.H7, + align: 'center', + boxProps: { + margin: 0, + }, + }, + }, + { + element: 'TruncatedDefinitionList', + key: 'network-details', + props: { + title: t('networkDetails'), + tooltips: { + [t('networkName')]: t('networkNameDefinition'), + [t('networkURL')]: t('networkURLDefinition'), + [t('chainId')]: t('chainIdDefinition'), + [t('currencySymbol')]: t('currencySymbolDefinition'), + [t('blockExplorerUrl')]: t('blockExplorerUrlDefinition'), + }, + dictionary: { + [t('networkName')]: pendingApproval.requestData.chainName, + [t('networkURL')]: pendingApproval.requestData.rpcUrl, + [t('chainId')]: parseInt(pendingApproval.requestData.chainId, 16), + [t('currencySymbol')]: pendingApproval.requestData.ticker, + [t('blockExplorerUrl')]: pendingApproval.requestData + .blockExplorerUrl, + }, + prefaceKeys: [t('networkName'), t('networkURL'), t('chainId')], + }, + }, + ], + approvalText: t('approveButtonText'), + cancelText: t('cancel'), + onApprove: () => + actions.resolvePendingApproval( + pendingApproval.id, + pendingApproval.requestData, + ), + + onCancel: () => + actions.rejectPendingApproval( + pendingApproval.id, + ethErrors.provider.userRejectedRequest(), + ), + }; +} + +const addEthereumChain = { + getAlerts, + getValues, +}; + +export default addEthereumChain; diff --git a/ui/app/pages/confirmation/templates/index.js b/ui/app/pages/confirmation/templates/index.js new file mode 100644 index 000000000..b00c1552b --- /dev/null +++ b/ui/app/pages/confirmation/templates/index.js @@ -0,0 +1,127 @@ +import { omit, pick } from 'lodash'; +import { MESSAGE_TYPE } from '../../../../../shared/constants/app'; +import { + rejectPendingApproval, + resolvePendingApproval, +} from '../../../store/actions'; +import addEthereumChain from './add-ethereum-chain'; +import switchEthereumChain from './switch-ethereum-chain'; + +const APPROVAL_TEMPLATES = { + [MESSAGE_TYPE.ADD_ETHEREUM_CHAIN]: addEthereumChain, + [MESSAGE_TYPE.SWITCH_ETHEREUM_CHAIN]: switchEthereumChain, +}; + +const ALLOWED_TEMPLATE_KEYS = [ + 'content', + 'approvalText', + 'cancelText', + 'onApprove', + 'onCancel', +]; + +/** + * @typedef {Object} PendingApproval + * @property {string} id - The randomly generated id of the approval + * @property {string} origin - The origin of the site requesting this approval + * @property {number} time - The time the approval was requested + * @property {string} type - The type of approval being requested + * @property {Object} requestData - The data submitted with the request + */ + +/** + * getTemplateAlerts calls the getAlerts function exported by the template if + * it exists, and then returns the result of that function. In the confirmation + * page the alerts returned from the getAlerts method will be set into the + * alertState state object. + * + * @param {Object} pendingApproval - the object representing the confirmation + */ +export async function getTemplateAlerts(pendingApproval) { + const fn = APPROVAL_TEMPLATES[pendingApproval.type]?.getAlerts; + const results = fn ? await fn(pendingApproval) : undefined; + if (!Array.isArray(results)) { + throw new Error(`Template alerts must be an array, received: ${results}`); + } + if (results.some((result) => result?.id === undefined)) { + throw new Error( + `Template alert entries must be objects with an id key. Received: ${results}`, + ); + } + return results; +} + +/** + * The function call to return state must be a promise returning function + * this "NOOP" is here to conform to the requirements for templates without + * state. + */ +async function emptyState() { + return {}; +} + +/** + * getTemplateState calls the getState function exported by the template if + * it exists, and then returns the result of that function. In the confirmation + * page the object returned from the getState method will be set into the + * confirmationState state object. Note, this state is not consumed by the page + * itself. + * @param {Object} pendingApproval - the object representing the confirmation + */ +export async function getTemplateState(pendingApproval) { + const fn = APPROVAL_TEMPLATES[pendingApproval.type]?.getState ?? emptyState; + const result = await fn(pendingApproval); + if (typeof result !== 'object' || Array.isArray(result)) { + throw new Error(`Template state must be an object, received: ${result}`); + } else if (result === null || result === undefined) { + return {}; + } + return result; +} + +/** + * We do not want to pass the entire dispatch function to the template. + * This function should return an object of actions that we generally consider + * to be safe for templates to invoke. In the future we could put these behind + * permission sets so that snaps that wish to manipulate state must ask for + * explicit permission to do so. + * @param {Function} dispatch - Redux dispatch function + */ +function getAttenuatedDispatch(dispatch) { + return { + rejectPendingApproval: (...args) => + dispatch(rejectPendingApproval(...args)), + resolvePendingApproval: (...args) => + dispatch(resolvePendingApproval(...args)), + }; +} + +/** + * Returns the templated values to be consumed in the confirmation page + * @param {Object} pendingApproval - The pending confirmation object + * @param {Function} t - Translation function + * @param {Function} dispatch - Redux dispatch function + */ +export function getTemplateValues(pendingApproval, t, dispatch) { + const fn = APPROVAL_TEMPLATES[pendingApproval.type]?.getValues; + if (!fn) { + throw new Error( + `MESSAGE_TYPE: '${pendingApproval.type}' is not specified in approval templates`, + ); + } + + const safeActions = getAttenuatedDispatch(dispatch); + const values = fn(pendingApproval, t, safeActions); + const extraneousKeys = omit(values, ALLOWED_TEMPLATE_KEYS); + const safeValues = pick(values, ALLOWED_TEMPLATE_KEYS); + if (extraneousKeys.length > 0) { + throw new Error( + `Received extraneous keys from ${ + pendingApproval.type + }.getValues. These keys are not passed to the confirmation page: ${Object.keys( + extraneousKeys, + )}`, + ); + } + return safeValues; +} diff --git a/ui/app/pages/confirmation/templates/switch-ethereum-chain.js b/ui/app/pages/confirmation/templates/switch-ethereum-chain.js new file mode 100644 index 000000000..4dc351027 --- /dev/null +++ b/ui/app/pages/confirmation/templates/switch-ethereum-chain.js @@ -0,0 +1,96 @@ +import { ethErrors } from 'eth-rpc-errors'; +import { NETWORK_TYPE_RPC } from '../../../../../shared/constants/network'; +import { + JUSTIFY_CONTENT, + SEVERITIES, + TYPOGRAPHY, +} from '../../../helpers/constants/design-system'; + +const PENDING_TX_DROP_NOTICE = { + id: 'PENDING_TX_DROP_NOTICE', + severity: SEVERITIES.WARNING, + content: { + element: 'span', + children: { + element: 'MetaMaskTranslation', + props: { + translationKey: 'switchingNetworksCancelsPendingConfirmations', + }, + }, + }, +}; + +async function getAlerts() { + return [PENDING_TX_DROP_NOTICE]; +} + +function getValues(pendingApproval, t, actions) { + return { + content: [ + { + element: 'Typography', + key: 'title', + children: t('switchEthereumChainConfirmationTitle'), + props: { + variant: TYPOGRAPHY.H3, + align: 'center', + fontWeight: 'bold', + boxProps: { + margin: [0, 0, 4], + }, + }, + }, + { + element: 'Typography', + key: 'description', + children: t('switchEthereumChainConfirmationDescription'), + props: { + variant: TYPOGRAPHY.H7, + align: 'center', + boxProps: { + margin: [0, 0, 4], + }, + }, + }, + { + element: 'Box', + key: 'status-box', + props: { + justifyContent: JUSTIFY_CONTENT.CENTER, + }, + children: { + element: 'NetworkDisplay', + key: 'network-being-switched', + props: { + colored: false, + outline: true, + targetNetwork: { + type: NETWORK_TYPE_RPC, + nickname: pendingApproval.requestData.nickname, + }, + }, + }, + }, + ], + approvalText: t('switchNetwork'), + cancelText: t('cancel'), + onApprove: () => + actions.resolvePendingApproval( + pendingApproval.id, + pendingApproval.requestData, + ), + + onCancel: () => + actions.rejectPendingApproval( + pendingApproval.id, + ethErrors.provider.userRejectedRequest(), + ), + }; +} + +const switchEthereumChain = { + getAlerts, + getValues, +}; + +export default switchEthereumChain; diff --git a/ui/app/pages/create-account/connect-hardware/account-list.js b/ui/app/pages/create-account/connect-hardware/account-list.js index df1ec8cdd..53b9d8f7b 100644 --- a/ui/app/pages/create-account/connect-hardware/account-list.js +++ b/ui/app/pages/create-account/connect-hardware/account-list.js @@ -1,19 +1,22 @@ import PropTypes from 'prop-types'; import React, { Component } from 'react'; -import Select from 'react-select'; import getAccountLink from '../../../../lib/account-link'; import Button from '../../../components/ui/button'; +import Dropdown from '../../../components/ui/dropdown'; class AccountList extends Component { getHdPaths() { + const ledgerLiveKey = `m/44'/60'/0'/0/0`; + const mewKey = `m/44'/60'/0'`; + return [ { - label: `Ledger Live`, - value: `m/44'/60'/0'/0/0`, + name: `Ledger Live`, + value: ledgerLiveKey, }, { - label: `Legacy (MEW / MyCrypto)`, - value: `m/44'/60'/0'`, + name: `Legacy (MEW / MyCrypto)`, + value: mewKey, }, ]; } @@ -33,8 +36,8 @@ class AccountList extends Component { renderHdPathSelector() { const { onPathChange, selectedPath } = this.props; - const options = this.getHdPaths(); + return (

@@ -42,14 +45,12 @@ class AccountList extends Component {

{this.context.t('selectPathHelp')}

- { - return { - value: text, - label: text, - }; - })} - onChange={(opt) => { - this.setState({ type: opt.value }); + options={menuItems.map((text) => ({ value: text }))} + selectedOption={type || menuItems[0]} + onChange={(value) => { + this.setState({ type: value }); }} />
diff --git a/ui/app/pages/create-account/import-account/index.scss b/ui/app/pages/create-account/import-account/index.scss index 6749e0e76..11056d25d 100644 --- a/ui/app/pages/create-account/import-account/index.scss +++ b/ui/app/pages/create-account/import-account/index.scss @@ -29,25 +29,9 @@ } &__select { - height: 54px; width: 210px; - border: 1px solid #d2d8dd; - border-radius: 4px; - background-color: #fff; display: flex; align-items: center; - - .Select-control, - .Select-control:hover { - height: 100%; - border: none; - box-shadow: none; - - .Select-value { - display: flex; - align-items: center; - } - } } &__private-key-password-container { diff --git a/ui/app/pages/home/home.component.js b/ui/app/pages/home/home.component.js index d5b5f75d7..3f9c14caa 100644 --- a/ui/app/pages/home/home.component.js +++ b/ui/app/pages/home/home.component.js @@ -27,6 +27,7 @@ import { AWAITING_SWAP_ROUTE, BUILD_QUOTE_ROUTE, VIEW_QUOTE_ROUTE, + CONFIRMATION_V_NEXT_ROUTE, } from '../../helpers/constants/routes'; const LEARN_MORE_URL = @@ -72,6 +73,7 @@ export default class Home extends PureComponent { setWeb3ShimUsageAlertDismissed: PropTypes.func.isRequired, originOfCurrentTab: PropTypes.string, disableWeb3ShimUsageAlert: PropTypes.func.isRequired, + pendingApprovals: PropTypes.arrayOf(PropTypes.object).isRequired, }; state = { @@ -89,6 +91,7 @@ export default class Home extends PureComponent { haveSwapsQuotes, showAwaitingSwapScreen, swapsFetchParams, + pendingApprovals, } = this.props; this.setState({ mounted: true }); @@ -106,6 +109,8 @@ export default class Home extends PureComponent { history.push(CONFIRM_TRANSACTION_ROUTE); } else if (Object.keys(suggestedTokens).length > 0) { history.push(CONFIRM_ADD_SUGGESTED_TOKEN_ROUTE); + } else if (pendingApprovals.length > 0) { + history.push(CONFIRMATION_V_NEXT_ROUTE); } } diff --git a/ui/app/pages/home/home.container.js b/ui/app/pages/home/home.container.js index b53a5a96d..3a9422486 100644 --- a/ui/app/pages/home/home.container.js +++ b/ui/app/pages/home/home.container.js @@ -52,6 +52,7 @@ const mapStateToProps = (state) => { connectedStatusPopoverHasBeenShown, defaultHomeActiveTabName, swapsState, + pendingApprovals = {}, } = metamask; const accountBalance = getCurrentEthBalance(state); const { forgottenPassword, threeBoxLastUpdated } = appState; @@ -101,6 +102,7 @@ const mapStateToProps = (state) => { isMainnet: getIsMainnet(state), originOfCurrentTab, shouldShowWeb3ShimUsageNotification, + pendingApprovals: Object.values(pendingApprovals), }; }; diff --git a/ui/app/pages/pages.scss b/ui/app/pages/pages.scss index adb813e7f..09c1c58bc 100644 --- a/ui/app/pages/pages.scss +++ b/ui/app/pages/pages.scss @@ -5,6 +5,7 @@ @import 'confirm-approve/index'; @import 'confirm-decrypt-message/confirm-decrypt-message'; @import 'confirm-encryption-public-key/confirm-encryption-public-key'; +@import 'confirmation/confirmation'; @import 'connected-sites/index'; @import 'connected-accounts/index'; @import 'connected-sites/index'; diff --git a/ui/app/pages/routes/routes.component.js b/ui/app/pages/routes/routes.component.js index c563d2b03..1f5e0eef3 100644 --- a/ui/app/pages/routes/routes.component.js +++ b/ui/app/pages/routes/routes.component.js @@ -53,6 +53,7 @@ import { SETTINGS_ROUTE, UNLOCK_ROUTE, BUILD_QUOTE_ROUTE, + CONFIRMATION_V_NEXT_ROUTE, } from '../../helpers/constants/routes'; import { @@ -61,6 +62,7 @@ import { } from '../../../../shared/constants/app'; import { getEnvironmentType } from '../../../../app/scripts/lib/util'; import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; +import ConfirmationPage from '../confirmation'; export default class Routes extends Component { static propTypes = { @@ -158,6 +160,10 @@ export default class Routes extends Component { component={ConfirmAddSuggestedTokenPage} exact /> +
- {name || ellipsify(address)} + {name ? : ellipsify(address)}
{name && (
@@ -211,14 +213,13 @@ export default class AddRecipient extends Component { } renderDialogs() { - const { toError, ensResolutionError, ensResolution } = this.props; + const { + toError, + toWarning, + ensResolutionError, + ensResolution, + } = this.props; const { t } = this.context; - const contacts = this.searchForContacts(); - const recents = this.searchForRecents(); - - if (contacts.length || recents.length) { - return null; - } if (ensResolutionError) { return ( @@ -226,14 +227,18 @@ export default class AddRecipient extends Component { {ensResolutionError} ); - } - - if (toError && toError !== 'required' && !ensResolution) { + } else if (toError && toError !== 'required' && !ensResolution) { return ( {t(toError)} ); + } else if (toWarning) { + return ( + + {t(toWarning)} + + ); } return null; diff --git a/ui/app/pages/send/send-content/add-recipient/add-recipient.js b/ui/app/pages/send/send-content/add-recipient/add-recipient.js index 9a423e974..195da89cb 100644 --- a/ui/app/pages/send/send-content/add-recipient/add-recipient.js +++ b/ui/app/pages/send/send-content/add-recipient/add-recipient.js @@ -1,16 +1,19 @@ import ethUtil from 'ethereumjs-util'; import contractMap from '@metamask/contract-metadata'; +import { isConfusing } from 'unicode-confusables'; import { REQUIRED_ERROR, INVALID_RECIPIENT_ADDRESS_ERROR, KNOWN_RECIPIENT_ADDRESS_ERROR, INVALID_RECIPIENT_ADDRESS_NOT_ETH_NETWORK_ERROR, + CONFUSING_ENS_ERROR, } from '../../send.constants'; import { isValidAddress, isEthNetwork, checkExistingAddresses, + isValidDomainName, } from '../../../../helpers/utils/util'; export function getToErrorObject(to, hasHexData = false, network) { @@ -36,6 +39,9 @@ export function getToWarningObject(to, tokens = [], sendToken = null) { checkExistingAddresses(to, tokens)) ) { toWarning = KNOWN_RECIPIENT_ADDRESS_ERROR; + } else if (isValidDomainName(to) && isConfusing(to)) { + toWarning = CONFUSING_ENS_ERROR; } + return { to: toWarning }; } diff --git a/ui/app/pages/send/send-content/add-recipient/ens-input.container.js b/ui/app/pages/send/send-content/add-recipient/ens-input.container.js index f8ad890bc..42e75e501 100644 --- a/ui/app/pages/send/send-content/add-recipient/ens-input.container.js +++ b/ui/app/pages/send/send-content/add-recipient/ens-input.container.js @@ -1,16 +1,18 @@ import { connect } from 'react-redux'; +import { CHAIN_ID_TO_NETWORK_ID_MAP } from '../../../../../../shared/constants/network'; import { - getCurrentNetwork, getSendTo, getSendToNickname, getAddressBookEntry, + getCurrentChainId, } from '../../../../selectors'; import EnsInput from './ens-input.component'; export default connect((state) => { const selectedAddress = getSendTo(state); + const chainId = getCurrentChainId(state); return { - network: getCurrentNetwork(state), + network: CHAIN_ID_TO_NETWORK_ID_MAP[chainId], selectedAddress, selectedName: getSendToNickname(state), contact: getAddressBookEntry(state, selectedAddress), diff --git a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js index 7736969e9..55f193590 100644 --- a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js +++ b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-component.test.js @@ -210,20 +210,5 @@ describe('AddRecipient Component', function () { assert.strictEqual(dialog.length, 0); }); - - it('should not render error when query has results', function () { - wrapper.setProps({ - addressBook: [ - { address: '0x125', name: 'alice' }, - { address: '0x126', name: 'alex' }, - { address: '0x127', name: 'catherine' }, - ], - toError: 'bad', - }); - - const dialog = wrapper.find(Dialog); - - assert.strictEqual(dialog.length, 0); - }); }); }); diff --git a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js index 9d4947107..cdf1a0c36 100644 --- a/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js +++ b/ui/app/pages/send/send-content/add-recipient/tests/add-recipient-utils.test.js @@ -6,6 +6,7 @@ import { REQUIRED_ERROR, INVALID_RECIPIENT_ADDRESS_ERROR, KNOWN_RECIPIENT_ADDRESS_ERROR, + CONFUSING_ENS_ERROR, } from '../../../send.constants'; const stubs = { @@ -93,5 +94,17 @@ describe('add-recipient utils', function () { }, ); }); + + it('should warn if name is a valid domain and confusable', function () { + assert.deepEqual(getToWarningObject('vita‍lik.eth'), { + to: CONFUSING_ENS_ERROR, + }); + }); + + it('should not warn if name is a valid domain and not confusable', function () { + assert.deepEqual(getToWarningObject('vitalik.eth'), { + to: null, + }); + }); }); }); diff --git a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js index 870ff79e8..589eb048e 100644 --- a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js +++ b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.component.js @@ -4,7 +4,7 @@ import SendRowWrapper from '../send-row-wrapper'; import Identicon from '../../../../components/ui/identicon/identicon.component'; import TokenBalance from '../../../../components/ui/token-balance'; import UserPreferencedCurrencyDisplay from '../../../../components/app/user-preferenced-currency-display'; -import { PRIMARY } from '../../../../helpers/constants/common'; +import { ERC20, ETH, PRIMARY } from '../../../../helpers/constants/common'; export default class SendAssetRow extends Component { static propTypes = { @@ -19,6 +19,7 @@ export default class SendAssetRow extends Component { selectedAddress: PropTypes.string.isRequired, sendTokenAddress: PropTypes.string, setSendToken: PropTypes.func.isRequired, + nativeCurrency: PropTypes.string, }; static contextTypes = { @@ -47,7 +48,7 @@ export default class SendAssetRow extends Component { name: 'User clicks "Assets" dropdown', }, customVariables: { - assetSelected: token ? 'ERC20' : 'ETH', + assetSelected: token ? ERC20 : this.props.nativeCurrency, }, }); this.props.setSendToken(token); @@ -78,7 +79,7 @@ export default class SendAssetRow extends Component { className="send-v2__asset-dropdown__input-wrapper" onClick={this.openDropdown} > - {token ? this.renderAsset(token) : this.renderEth()} + {token ? this.renderAsset(token) : this.renderNativeCurrency()}
); } @@ -92,7 +93,7 @@ export default class SendAssetRow extends Component { onClick={this.closeDropdown} />
- {this.renderEth(true)} + {this.renderNativeCurrency(true)} {this.props.tokens.map((token) => this.renderAsset(token, true))}
@@ -100,9 +101,9 @@ export default class SendAssetRow extends Component { ); } - renderEth(insideDropdown = false) { + renderNativeCurrency(insideDropdown = false) { const { t } = this.context; - const { accounts, selectedAddress } = this.props; + const { accounts, selectedAddress, nativeCurrency } = this.props; const balanceValue = accounts[selectedAddress] ? accounts[selectedAddress].balance @@ -118,10 +119,15 @@ export default class SendAssetRow extends Component { onClick={() => this.selectToken()} >
- +
-
ETH
+
+ {nativeCurrency} +
{`${t('balance')}:`} @@ -133,7 +139,7 @@ export default class SendAssetRow extends Component {
{!insideDropdown && this.props.tokens.length > 0 && ( - + )}
); @@ -162,7 +168,7 @@ export default class SendAssetRow extends Component {
{!insideDropdown && ( - + )} ); diff --git a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js index 05a2d4a23..5eee73797 100644 --- a/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js +++ b/ui/app/pages/send/send-content/send-asset-row/send-asset-row.container.js @@ -1,6 +1,7 @@ import { connect } from 'react-redux'; import { getMetaMaskAccounts, + getNativeCurrency, getSendTokenAddress, } from '../../../../selectors'; import { updateSendToken } from '../../../../store/actions'; @@ -12,6 +13,7 @@ function mapStateToProps(state) { selectedAddress: state.metamask.selectedAddress, sendTokenAddress: getSendTokenAddress(state), accounts: getMetaMaskAccounts(state), + nativeCurrency: getNativeCurrency(state), }; } diff --git a/ui/app/pages/send/send.component.js b/ui/app/pages/send/send.component.js index 74d4f86f4..98c3b6600 100644 --- a/ui/app/pages/send/send.component.js +++ b/ui/app/pages/send/send.component.js @@ -147,6 +147,7 @@ export default class SendTransactionScreen extends Component { address, }); updateToNicknameIfNecessary(to, toNickname, addressBook); + this.props.fetchBasicGasEstimates(); updateGas = true; } } @@ -340,7 +341,7 @@ export default class SendTransactionScreen extends Component { } renderAddRecipient() { - const { toError } = this.state; + const { toError, toWarning } = this.state; return ( @@ -348,6 +349,7 @@ export default class SendTransactionScreen extends Component { } query={this.state.query} toError={toError} + toWarning={toWarning} setInternalSearch={(internalSearch) => this.setInternalSearch(internalSearch) } diff --git a/ui/app/pages/send/send.constants.js b/ui/app/pages/send/send.constants.js index 7b1a1f1a3..5584a6c99 100644 --- a/ui/app/pages/send/send.constants.js +++ b/ui/app/pages/send/send.constants.js @@ -35,6 +35,7 @@ const INVALID_RECIPIENT_ADDRESS_NOT_ETH_NETWORK_ERROR = 'invalidAddressRecipientNotEthNetwork'; const REQUIRED_ERROR = 'required'; const KNOWN_RECIPIENT_ADDRESS_ERROR = 'knownAddressRecipient'; +const CONFUSING_ENS_ERROR = 'confusingEnsDomain'; const SIMPLE_GAS_COST = '0x5208'; // Hex for 21000, cost of a simple send. const BASE_TOKEN_GAS_COST = '0x186a0'; // Hex for 100000, a base estimate for token transfers. @@ -53,6 +54,7 @@ export { MIN_GAS_TOTAL, NEGATIVE_ETH_ERROR, REQUIRED_ERROR, + CONFUSING_ENS_ERROR, SIMPLE_GAS_COST, TOKEN_TRANSFER_FUNCTION_SIGNATURE, BASE_TOKEN_GAS_COST, diff --git a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js index 4d9e10a6e..da665045a 100644 --- a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js +++ b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js @@ -8,8 +8,8 @@ import Tooltip from '../../../../components/ui/tooltip'; import { isPrefixedFormattedHexString, isSafeChainId, -} from '../../../../../../shared/modules/utils'; -import { jsonRpcRequest } from '../../../../helpers/utils/util'; +} from '../../../../../../shared/modules/network.utils'; +import { jsonRpcRequest } from '../../../../../../shared/modules/rpc.utils'; const FORM_STATE_KEYS = [ 'rpcUrl', @@ -250,14 +250,15 @@ export default class NetworkForm extends PureComponent { ); } - renderFormTextField( + renderFormTextField({ fieldKey, textFieldId, onChange, value, optionalTextFieldKey, tooltipText, - ) { + autoFocus = false, + }) { const { errors } = this.state; const { viewOnly } = this.props; @@ -286,6 +287,7 @@ export default class NetworkForm extends PureComponent { value={value} disabled={viewOnly} error={errors[fieldKey]} + autoFocus={autoFocus} /> ); @@ -456,43 +458,46 @@ export default class NetworkForm extends PureComponent { return (
{viewOnly ? null : this.renderWarning()} - {this.renderFormTextField( - 'networkName', - 'network-name', - this.setStateWithValue('networkName'), - networkName, - )} - {this.renderFormTextField( - 'rpcUrl', - 'rpc-url', - this.setStateWithValue('rpcUrl', this.validateUrlRpcUrl), - rpcUrl, - )} - {this.renderFormTextField( - 'chainId', - 'chainId', - this.setStateWithValue('chainId', this.validateChainIdOnChange), - chainId, - null, - viewOnly ? null : t('networkSettingsChainIdDescription'), - )} - {this.renderFormTextField( - 'symbol', - 'network-ticker', - this.setStateWithValue('ticker'), - ticker, - 'optionalCurrencySymbol', - )} - {this.renderFormTextField( - 'blockExplorerUrl', - 'block-explorer-url', - this.setStateWithValue( + {this.renderFormTextField({ + fieldKey: 'networkName', + textFieldId: 'network-name', + onChange: this.setStateWithValue('networkName'), + value: networkName, + autoFocus: networksTabIsInAddMode, + })} + {this.renderFormTextField({ + fieldKey: 'rpcUrl', + textFieldId: 'rpc-url', + onChange: this.setStateWithValue('rpcUrl', this.validateUrlRpcUrl), + value: rpcUrl, + })} + {this.renderFormTextField({ + fieldKey: 'chainId', + textFieldId: 'chainId', + onChange: this.setStateWithValue( + 'chainId', + this.validateChainIdOnChange, + ), + value: chainId, + tooltipText: viewOnly ? null : t('networkSettingsChainIdDescription'), + })} + {this.renderFormTextField({ + fieldKey: 'symbol', + textFieldId: 'network-ticker', + onChange: this.setStateWithValue('ticker'), + value: ticker, + optionalTextFieldKey: 'optionalCurrencySymbol', + })} + {this.renderFormTextField({ + fieldKey: 'blockExplorerUrl', + textFieldId: 'block-explorer-url', + onChange: this.setStateWithValue( 'blockExplorerUrl', this.validateBlockExplorerURL, ), - blockExplorerUrl, - 'optionalBlockExplorerUrl', - )} + value: blockExplorerUrl, + optionalTextFieldKey: 'optionalBlockExplorerUrl', + })}
{!viewOnly && ( <> diff --git a/ui/app/pages/settings/settings-tab/settings-tab.component.js b/ui/app/pages/settings/settings-tab/settings-tab.component.js index 6c1452c02..74e9c8563 100644 --- a/ui/app/pages/settings/settings-tab/settings-tab.component.js +++ b/ui/app/pages/settings/settings-tab/settings-tab.component.js @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import PropTypes from 'prop-types'; import availableCurrencies from '../../../helpers/constants/available-conversions.json'; -import SimpleDropdown from '../../../components/app/dropdowns/simple-dropdown'; +import Dropdown from '../../../components/ui/dropdown'; import ToggleButton from '../../../components/ui/toggle-button'; import locales from '../../../../../app/_locales/index.json'; @@ -11,16 +11,14 @@ const sortedCurrencies = availableCurrencies.sort((a, b) => { const currencyOptions = sortedCurrencies.map(({ code, name }) => { return { - displayValue: `${code.toUpperCase()} - ${name}`, - key: code, + name: `${code.toUpperCase()} - ${name}`, value: code, }; }); const localeOptions = locales.map((locale) => { return { - displayValue: `${locale.name}`, - key: locale.code, + name: `${locale.name}`, value: locale.code, }; }); @@ -59,11 +57,11 @@ export default class SettingsTab extends PureComponent {
- setCurrentCurrency(newCurrency)} + onChange={(newCurrency) => setCurrentCurrency(newCurrency)} />
@@ -91,11 +89,11 @@ export default class SettingsTab extends PureComponent {
- updateCurrentLocale(newLocale)} + onChange={async (newLocale) => updateCurrentLocale(newLocale)} />
diff --git a/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js b/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js index 1d1a0b42c..da3630a24 100644 --- a/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js +++ b/ui/app/pages/settings/settings-tab/tests/settings-tab.test.js @@ -30,16 +30,16 @@ describe('Settings Tab', function () { }); it('selects currency', async function () { - const selectCurrency = wrapper.find({ placeholder: 'selectCurrency' }); + const selectCurrency = wrapper.find('#select-currency'); - selectCurrency.props().onSelect('eur'); + selectCurrency.props().onChange('eur'); assert(props.setCurrentCurrency.calledOnce); }); it('selects locale', async function () { - const selectLocale = wrapper.find({ placeholder: 'selectLocale' }); + const selectLocale = wrapper.find('#select-locale'); - await selectLocale.props().onSelect('ja'); + await selectLocale.props().onChange('ja'); assert(props.updateCurrentLocale.calledOnce); }); diff --git a/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js b/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js index b5908d0ee..3828dab6f 100644 --- a/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js +++ b/ui/app/pages/swaps/awaiting-swap/awaiting-swap.js @@ -111,7 +111,17 @@ export default function AwaitingSwap({ statusImage = ; } else if (errorKey === SWAP_FAILED_ERROR) { headerText = t('swapFailedErrorTitle'); - descriptionText = t('swapFailedErrorDescription'); + descriptionText = t('swapFailedErrorDescriptionWithSupportLink', [ + + support.metamask.io + , + ]); submitText = t('tryAgain'); statusImage = ; content = blockExplorerUrl && ( diff --git a/ui/app/pages/swaps/awaiting-swap/index.scss b/ui/app/pages/swaps/awaiting-swap/index.scss index 9a0eddd93..0ad246934 100644 --- a/ui/app/pages/swaps/awaiting-swap/index.scss +++ b/ui/app/pages/swaps/awaiting-swap/index.scss @@ -60,12 +60,20 @@ font-weight: bold; } - &__view-on-etherscan { - @include H7; - + &__view-on-etherscan, + &__support-link { color: $Blue-500; margin-top: 24px; cursor: pointer; + } + + &__support-link { + @include H6; + } + + &__view-on-etherscan { + @include H7; + transition: opacity 1s ease-in-out; } diff --git a/ui/app/pages/swaps/build-quote/build-quote.js b/ui/app/pages/swaps/build-quote/build-quote.js index c1a063681..d71f78ad7 100644 --- a/ui/app/pages/swaps/build-quote/build-quote.js +++ b/ui/app/pages/swaps/build-quote/build-quote.js @@ -113,7 +113,7 @@ export default function BuildQuote({ const toTokenIsNotEth = selectedToToken?.address && selectedToToken?.address !== ETH_SWAPS_TOKEN_OBJECT.address; - + const occurances = Number(selectedToToken?.occurances || 0); const { address: fromTokenAddress, symbol: fromTokenSymbol, @@ -376,12 +376,14 @@ export default function BuildQuote({ /> {toTokenIsNotEth && - (selectedToToken.occurances === 1 ? ( + (occurances < 2 ? (
- {t('swapTokenVerificationOnlyOneSource')} + {occurances === 1 + ? t('swapTokenVerificationOnlyOneSource') + : t('swapTokenVerificationNoSource')}
{t('verifyThisTokenOn', [ @@ -416,9 +418,7 @@ export default function BuildQuote({ className="build-quote__bold" key="token-verification-bold-text" > - {t('swapTokenVerificationSources', [ - selectedToToken.occurances, - ])} + {t('swapTokenVerificationSources', [occurances])} {t('swapTokenVerificationMessage', [ MAX_ALLOWED_SLIPPAGE || - (toTokenIsNotEth && - selectedToToken.occurances === 1 && - !verificationClicked) + (toTokenIsNotEth && occurances < 2 && !verificationClicked) } hideCancel showTermsOfService diff --git a/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.js b/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.js index 5577d3517..005294a34 100644 --- a/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.js +++ b/ui/app/pages/swaps/dropdown-search-list/dropdown-search-list.js @@ -161,7 +161,7 @@ export default function DropdownSearchList({ listContainerClassName={listContainerClassName} />
{ event.stopPropagation(); setIsOpen(false); diff --git a/ui/app/pages/swaps/dropdown-search-list/index.scss b/ui/app/pages/swaps/dropdown-search-list/index.scss index fe5bd26da..c75c22bbb 100644 --- a/ui/app/pages/swaps/dropdown-search-list/index.scss +++ b/ui/app/pages/swaps/dropdown-search-list/index.scss @@ -22,6 +22,15 @@ border: 1px solid $Grey-100; } + &__close-area { + position: fixed; + top: 0; + left: 0; + z-index: 1000; + width: 100%; + height: 100%; + } + &__selector-closed-container { display: flex; width: 100%; diff --git a/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js b/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js index 0a2359bae..8835c372e 100644 --- a/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js +++ b/ui/app/pages/swaps/loading-swaps-quotes/loading-swaps-quotes.js @@ -112,13 +112,9 @@ export default function LoadingSwapsQuotes({ // This is to give the user a sense of progress. The callback passed to `setTimeout` updates the quoteCount and therefore causes // a new logo to be shown, the fox to look at that logo, the logo bar and aggregator name to update. - // If loading is complete and all logos + aggregator names have been shown, give the user 1.2 seconds to read the - // "Finalizing message" and prepare for the screen change - if (quoteCount === numberOfQuotes && loadingComplete) { - timeoutLength = 1200; - } else if (loadingComplete) { - // If loading is complete, but the quoteCount is not, we quickly display the remaining logos/names/fox looks. 0.5s each - timeoutLength = 500; + if (loadingComplete) { + // If loading is complete, but the quoteCount is not, we quickly display the remaining logos/names/fox looks. 0.2s each + timeoutLength = 200; } else { // If loading is not complete, we display remaining logos/names/fox looks at random intervals between 0.5s and 2s, to simulate the // sort of loading a user would experience in most async scenarios diff --git a/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js b/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js index ae41cd794..437c67eea 100644 --- a/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js +++ b/ui/app/pages/swaps/view-quote/tests/view-quote-price-difference.test.js @@ -51,7 +51,7 @@ describe('View Price Quote Difference', function () { calculationError: '', bucket: 'low', sourceAmountInETH: 1, - destinationAmountInEth: 0.9921849150875727, + destinationAmountInETH: 0.9921849150875727, }, slippage: 2, sourceTokenInfo: { diff --git a/ui/app/pages/swaps/view-quote/view-quote.js b/ui/app/pages/swaps/view-quote/view-quote.js index f3fd90e58..c553be9d9 100644 --- a/ui/app/pages/swaps/view-quote/view-quote.js +++ b/ui/app/pages/swaps/view-quote/view-quote.js @@ -148,7 +148,7 @@ export default function ViewQuote() { const gasTotalInWeiHex = calcGasTotal(maxGasLimit, gasPrice); - const { tokensWithBalances } = useTokenTracker(swapsTokens); + const { tokensWithBalances } = useTokenTracker(swapsTokens, true); const swapsEthToken = useSwapsEthToken(); const balanceToken = fetchParamsSourceToken === swapsEthToken.address @@ -164,6 +164,8 @@ export default function ViewQuote() { selectedFromToken.balance || '0x0', selectedFromToken.decimals, ).toFixed(9); + const tokenBalanceUnavailable = + tokensWithBalances && balanceToken === undefined; const approveData = getTokenData(approveTxParams?.data); const approveValue = approveData && getTokenValueParam(approveData); @@ -473,14 +475,16 @@ export default function ViewQuote() { ); - const actionableInsufficientMessage = t('swapApproveNeedMoreTokens', [ - - {tokenBalanceNeeded || ethBalanceNeeded} - , - tokenBalanceNeeded && !(sourceTokenSymbol === 'ETH') - ? sourceTokenSymbol - : 'ETH', - ]); + const actionableBalanceErrorMessage = tokenBalanceUnavailable + ? t('swapTokenBalanceUnavailable', [sourceTokenSymbol]) + : t('swapApproveNeedMoreTokens', [ + + {tokenBalanceNeeded || ethBalanceNeeded} + , + tokenBalanceNeeded && !(sourceTokenSymbol === 'ETH') + ? sourceTokenSymbol + : 'ETH', + ]); // Price difference warning const priceSlippageBucket = usedQuote?.priceSlippage?.bucket; @@ -506,7 +510,7 @@ export default function ViewQuote() { usedQuote?.priceSlippage?.sourceAmountInETH || 0, ); const priceSlippageFromDestination = useEthFiatAmount( - usedQuote?.priceSlippage?.destinationAmountInEth || 0, + usedQuote?.priceSlippage?.destinationAmountInETH || 0, ); // We cannot present fiat value if there is a calculation error or no slippage @@ -528,6 +532,7 @@ export default function ViewQuote() { } const shouldShowPriceDifferenceWarning = + !tokenBalanceUnavailable && !showInsufficientWarning && usedQuote && (priceDifferenceRiskyBuckets.includes(priceSlippageBucket) || @@ -580,9 +585,9 @@ export default function ViewQuote() { })} > {viewQuotePriceDifferenceComponent} - {showInsufficientWarning && ( + {(showInsufficientWarning || tokenBalanceUnavailable) && ( setWarningHidden(true)} /> )} @@ -661,6 +666,7 @@ export default function ViewQuote() { disabled={ submitClicked || balanceError || + tokenBalanceUnavailable || disableSubmissionDueToPriceWarning || gasPrice === null || gasPrice === undefined diff --git a/ui/app/selectors/confirm-transaction.js b/ui/app/selectors/confirm-transaction.js index 030da5f8e..a6f9f1d94 100644 --- a/ui/app/selectors/confirm-transaction.js +++ b/ui/app/selectors/confirm-transaction.js @@ -10,6 +10,8 @@ import { addEth, } from '../helpers/utils/confirm-tx.util'; import { sumHexes } from '../helpers/utils/transactions.util'; +import { transactionMatchesNetwork } from '../../../shared/modules/transaction.utils'; +import { getCurrentChainId, getCurrentNetworkId } from './selectors'; import { getNativeCurrency } from '.'; const unapprovedTxsSelector = (state) => state.metamask.unapprovedTxs; @@ -22,7 +24,6 @@ const unapprovedEncryptionPublicKeyMsgsSelector = (state) => state.metamask.unapprovedEncryptionPublicKeyMsgs; const unapprovedTypedMessagesSelector = (state) => state.metamask.unapprovedTypedMessages; -const networkSelector = (state) => state.metamask.network; export const unconfirmedTransactionsListSelector = createSelector( unapprovedTxsSelector, @@ -31,7 +32,8 @@ export const unconfirmedTransactionsListSelector = createSelector( unapprovedDecryptMsgsSelector, unapprovedEncryptionPublicKeyMsgsSelector, unapprovedTypedMessagesSelector, - networkSelector, + getCurrentNetworkId, + getCurrentChainId, ( unapprovedTxs = {}, unapprovedMsgs = {}, @@ -40,6 +42,7 @@ export const unconfirmedTransactionsListSelector = createSelector( unapprovedEncryptionPublicKeyMsgs = {}, unapprovedTypedMessages = {}, network, + chainId, ) => txHelper( unapprovedTxs, @@ -49,6 +52,7 @@ export const unconfirmedTransactionsListSelector = createSelector( unapprovedEncryptionPublicKeyMsgs, unapprovedTypedMessages, network, + chainId, ) || [], ); @@ -59,7 +63,8 @@ export const unconfirmedTransactionsHashSelector = createSelector( unapprovedDecryptMsgsSelector, unapprovedEncryptionPublicKeyMsgsSelector, unapprovedTypedMessagesSelector, - networkSelector, + getCurrentNetworkId, + getCurrentChainId, ( unapprovedTxs = {}, unapprovedMsgs = {}, @@ -68,13 +73,15 @@ export const unconfirmedTransactionsHashSelector = createSelector( unapprovedEncryptionPublicKeyMsgs = {}, unapprovedTypedMessages = {}, network, + chainId, ) => { const filteredUnapprovedTxs = Object.keys(unapprovedTxs).reduce( (acc, address) => { - const { metamaskNetworkId } = unapprovedTxs[address]; const transactions = { ...acc }; - if (metamaskNetworkId === network) { + if ( + transactionMatchesNetwork(unapprovedTxs[address], chainId, network) + ) { transactions[address] = unapprovedTxs[address]; } @@ -111,7 +118,8 @@ export const unconfirmedTransactionsCountSelector = createSelector( unapprovedDecryptMsgCountSelector, unapprovedEncryptionPublicKeyMsgCountSelector, unapprovedTypedMessagesCountSelector, - networkSelector, + getCurrentNetworkId, + getCurrentChainId, ( unapprovedTxs = {}, unapprovedMsgCount = 0, @@ -120,12 +128,10 @@ export const unconfirmedTransactionsCountSelector = createSelector( unapprovedEncryptionPublicKeyMsgCount = 0, unapprovedTypedMessagesCount = 0, network, + chainId, ) => { - const filteredUnapprovedTxIds = Object.keys(unapprovedTxs).filter( - (txId) => { - const { metamaskNetworkId } = unapprovedTxs[txId]; - return metamaskNetworkId === network; - }, + const filteredUnapprovedTxIds = Object.keys(unapprovedTxs).filter((txId) => + transactionMatchesNetwork(unapprovedTxs[txId], chainId, network), ); return ( diff --git a/ui/app/selectors/permissions.js b/ui/app/selectors/permissions.js index 6b104f2e1..8ac46cc96 100644 --- a/ui/app/selectors/permissions.js +++ b/ui/app/selectors/permissions.js @@ -282,11 +282,6 @@ export function getPermissionsRequests(state) { return state.metamask.permissionsRequests || []; } -export function getPermissionsRequestCount(state) { - const permissionsRequests = getPermissionsRequests(state); - return permissionsRequests.length; -} - export function getFirstPermissionRequest(state) { const requests = getPermissionsRequests(state); return requests && requests[0] ? requests[0] : null; diff --git a/ui/app/selectors/selectors.js b/ui/app/selectors/selectors.js index 9e8711e2f..46ac30393 100644 --- a/ui/app/selectors/selectors.js +++ b/ui/app/selectors/selectors.js @@ -1,13 +1,16 @@ import { stripHexPrefix } from 'ethereumjs-util'; import { createSelector } from 'reselect'; import { addHexPrefix } from '../../../app/scripts/lib/util'; -import { MAINNET, NETWORK_TYPE_RPC } from '../../../shared/constants/network'; +import { + MAINNET_CHAIN_ID, + TEST_CHAINS, + NETWORK_TYPE_RPC, +} from '../../../shared/constants/network'; import { shortenAddress, checksumAddress, getAccountByAddress, } from '../helpers/utils/util'; -import { getPermissionsRequestCount } from './permissions'; export function getNetworkIdentifier(state) { const { @@ -255,6 +258,7 @@ export function getTotalUnapprovedCount(state) { unapprovedDecryptMsgCount = 0, unapprovedEncryptionPublicKeyMsgCount = 0, unapprovedTypedMessagesCount = 0, + pendingApprovalCount = 0, } = state.metamask; return ( @@ -264,7 +268,7 @@ export function getTotalUnapprovedCount(state) { unapprovedEncryptionPublicKeyMsgCount + unapprovedTypedMessagesCount + getUnapprovedTxCount(state) + - getPermissionsRequestCount(state) + + pendingApprovalCount + getSuggestedTokenCount(state) ); } @@ -274,14 +278,24 @@ function getUnapprovedTxCount(state) { return Object.keys(unapprovedTxs).length; } +export function getUnapprovedConfirmations(state) { + const { pendingApprovals } = state.metamask; + return Object.values(pendingApprovals); +} + function getSuggestedTokenCount(state) { const { suggestedTokens = {} } = state.metamask; return Object.keys(suggestedTokens).length; } export function getIsMainnet(state) { - const networkType = getNetworkIdentifier(state); - return networkType === MAINNET; + const chainId = getCurrentChainId(state); + return chainId === MAINNET_CHAIN_ID; +} + +export function getIsTestnet(state) { + const chainId = getCurrentChainId(state); + return TEST_CHAINS.includes(chainId); } export function getPreferences({ metamask }) { diff --git a/ui/app/selectors/tests/confirm-transaction.test.js b/ui/app/selectors/tests/confirm-transaction.test.js index 738000037..8f36689cb 100644 --- a/ui/app/selectors/tests/confirm-transaction.test.js +++ b/ui/app/selectors/tests/confirm-transaction.test.js @@ -1,4 +1,9 @@ import assert from 'assert'; +import { + KOVAN_CHAIN_ID, + KOVAN_NETWORK_ID, + MAINNET_CHAIN_ID, +} from '../../../../shared/constants/network'; import { TRANSACTION_CATEGORIES } from '../../../../shared/constants/transaction'; import { unconfirmedTransactionsCountSelector, @@ -22,16 +27,19 @@ describe('Confirm Transaction Selector', function () { metamask: { unapprovedTxs: { 1: { - metamaskNetworkId: 'test', + metamaskNetworkId: KOVAN_NETWORK_ID, }, 2: { - metmaskNetworkId: 'other network', + chainId: MAINNET_CHAIN_ID, }, }, unapprovedMsgCount: 1, unapprovedPersonalMsgCount: 1, unapprovedTypedMessagesCount: 1, - network: 'test', + network: KOVAN_NETWORK_ID, + provider: { + chainId: KOVAN_CHAIN_ID, + }, }, }; diff --git a/ui/app/selectors/tests/custom-gas.test.js b/ui/app/selectors/tests/custom-gas.test.js index e0a94eaf5..020648fbd 100644 --- a/ui/app/selectors/tests/custom-gas.test.js +++ b/ui/app/selectors/tests/custom-gas.test.js @@ -55,6 +55,7 @@ describe('custom-gas selectors', function () { }, provider: { type: 'mainnet', + chainId: '0x1', }, }, gas: { @@ -105,6 +106,7 @@ describe('custom-gas selectors', function () { }, provider: { type: 'mainnet', + chainId: '0x1', }, }, gas: { @@ -155,6 +157,7 @@ describe('custom-gas selectors', function () { }, provider: { type: 'rinkeby', + chainId: '0x4', }, }, gas: { @@ -205,6 +208,7 @@ describe('custom-gas selectors', function () { }, provider: { type: 'rinkeby', + chainId: '0x4', }, }, gas: { @@ -249,6 +253,7 @@ describe('custom-gas selectors', function () { }, provider: { type: 'mainnet', + chainId: '0x1', }, }, gas: { @@ -310,6 +315,7 @@ describe('custom-gas selectors', function () { }, provider: { type: 'mainnet', + chainId: '0x1', }, }, gas: { @@ -354,6 +360,7 @@ describe('custom-gas selectors', function () { }, provider: { type: 'mainnet', + chainId: '0x1', }, }, gas: { @@ -404,6 +411,7 @@ describe('custom-gas selectors', function () { }, provider: { type: 'rinkeby', + chainId: '0x4', }, }, gas: { @@ -454,6 +462,7 @@ describe('custom-gas selectors', function () { }, provider: { type: 'rinkeby', + chainId: '0x4', }, }, gas: { @@ -498,6 +507,7 @@ describe('custom-gas selectors', function () { }, provider: { type: 'mainnet', + chainId: '0x1', }, }, gas: { diff --git a/ui/app/selectors/tests/transactions.test.js b/ui/app/selectors/tests/transactions.test.js index c38dd4d30..6d2d59015 100644 --- a/ui/app/selectors/tests/transactions.test.js +++ b/ui/app/selectors/tests/transactions.test.js @@ -1,4 +1,8 @@ import { strict as assert } from 'assert'; +import { + KOVAN_CHAIN_ID, + MAINNET_CHAIN_ID, +} from '../../../../shared/constants/network'; import { TRANSACTION_STATUSES } from '../../../../shared/constants/transaction'; import { unapprovedMessagesSelector, @@ -29,6 +33,9 @@ describe('Transaction Selectors', function () { unapprovedMsgs: { 1: msg, }, + provider: { + chainId: KOVAN_CHAIN_ID, + }, }, }; @@ -56,6 +63,9 @@ describe('Transaction Selectors', function () { unapprovedPersonalMsgs: { 1: msg, }, + provider: { + chainId: KOVAN_CHAIN_ID, + }, }, }; @@ -84,6 +94,9 @@ describe('Transaction Selectors', function () { unapprovedTypedMessages: { 1: msg, }, + provider: { + chainId: KOVAN_CHAIN_ID, + }, }, }; @@ -100,6 +113,7 @@ describe('Transaction Selectors', function () { metamask: { provider: { nickname: 'mainnet', + chainId: MAINNET_CHAIN_ID, }, featureFlags: { showIncomingTransactions: false, @@ -163,6 +177,7 @@ describe('Transaction Selectors', function () { metamask: { provider: { nickname: 'mainnet', + chainId: MAINNET_CHAIN_ID, }, selectedAddress: '0xAddress', featureFlags: { @@ -247,6 +262,7 @@ describe('Transaction Selectors', function () { metamask: { provider: { nickname: 'mainnet', + chainId: MAINNET_CHAIN_ID, }, selectedAddress: '0xAddress', featureFlags: { diff --git a/ui/app/selectors/transactions.js b/ui/app/selectors/transactions.js index f9a8539d6..3fdcbfe41 100644 --- a/ui/app/selectors/transactions.js +++ b/ui/app/selectors/transactions.js @@ -10,6 +10,8 @@ import { TRANSACTION_STATUSES, TRANSACTION_TYPES, } from '../../../shared/constants/transaction'; +import { transactionMatchesNetwork } from '../../../shared/modules/transaction.utils'; +import { getCurrentChainId, getCurrentNetworkId } from './selectors'; import { getSelectedAddress } from '.'; export const incomingTxListSelector = (state) => { @@ -18,11 +20,15 @@ export const incomingTxListSelector = (state) => { return []; } - const { network } = state.metamask; + const { + network, + provider: { chainId }, + } = state.metamask; const selectedAddress = getSelectedAddress(state); return Object.values(state.metamask.incomingTransactions).filter( - ({ metamaskNetworkId, txParams }) => - txParams.to === selectedAddress && metamaskNetworkId === network, + (tx) => + tx.txParams.to === selectedAddress && + transactionMatchesNetwork(tx, chainId, network), ); }; export const unapprovedMsgsSelector = (state) => state.metamask.unapprovedMsgs; @@ -36,7 +42,6 @@ export const unapprovedEncryptionPublicKeyMsgsSelector = (state) => state.metamask.unapprovedEncryptionPublicKeyMsgs; export const unapprovedTypedMessagesSelector = (state) => state.metamask.unapprovedTypedMessages; -export const networkSelector = (state) => state.metamask.network; export const selectedAddressTxListSelector = createSelector( getSelectedAddress, @@ -54,7 +59,8 @@ export const unapprovedMessagesSelector = createSelector( unapprovedDecryptMsgsSelector, unapprovedEncryptionPublicKeyMsgsSelector, unapprovedTypedMessagesSelector, - networkSelector, + getCurrentNetworkId, + getCurrentChainId, ( unapprovedMsgs = {}, unapprovedPersonalMsgs = {}, @@ -62,6 +68,7 @@ export const unapprovedMessagesSelector = createSelector( unapprovedEncryptionPublicKeyMsgs = {}, unapprovedTypedMessages = {}, network, + chainId, ) => txHelper( {}, @@ -71,6 +78,7 @@ export const unapprovedMessagesSelector = createSelector( unapprovedEncryptionPublicKeyMsgs, unapprovedTypedMessages, network, + chainId, ) || [], ); diff --git a/ui/app/store/actionConstants.js b/ui/app/store/actionConstants.js index 5cdaf608c..2fe280251 100644 --- a/ui/app/store/actionConstants.js +++ b/ui/app/store/actionConstants.js @@ -2,8 +2,6 @@ export const GO_HOME = 'GO_HOME'; // modal state export const MODAL_OPEN = 'UI_MODAL_OPEN'; export const MODAL_CLOSE = 'UI_MODAL_CLOSE'; -// notification state -export const CLOSE_NOTIFICATION_WINDOW = 'CLOSE_NOTIFICATION_WINDOW'; // sidebar state export const SIDEBAR_OPEN = 'UI_SIDEBAR_OPEN'; export const SIDEBAR_CLOSE = 'UI_SIDEBAR_CLOSE'; diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index e8187d723..d0dae9c76 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -930,6 +930,7 @@ export function completedTx(id) { unapprovedPersonalMsgs, unapprovedTypedMessages, network, + provider: { chainId }, } = state.metamask; const unconfirmedActions = txHelper( unapprovedTxs, @@ -937,6 +938,7 @@ export function completedTx(id) { unapprovedPersonalMsgs, unapprovedTypedMessages, network, + chainId, ); const otherUnconfirmedActions = unconfirmedActions.filter( (tx) => tx.id !== id, @@ -1772,24 +1774,16 @@ export function hideModal(payload) { } export function closeCurrentNotificationWindow() { - return (dispatch, getState) => { + return (_, getState) => { if ( getEnvironmentType() === ENVIRONMENT_TYPE_NOTIFICATION && !hasUnconfirmedTransactions(getState()) ) { global.platform.closeCurrentWindow(); - - dispatch(closeNotificationWindow()); } }; } -export function closeNotificationWindow() { - return { - type: actionConstants.CLOSE_NOTIFICATION_WINDOW, - }; -} - export function showSidebar({ transitionName, type, props }) { return { type: actionConstants.SIDEBAR_OPEN, @@ -2463,6 +2457,44 @@ export function clearPermissions() { }; } +// Pending Approvals + +/** + * Resolves a pending approval and closes the current notification window if no + * further approvals are pending after the background state updates. + * @param {string} id - The pending approval id + * @param {any} [value] - The value required to confirm a pending approval + */ +export function resolvePendingApproval(id, value) { + return async (dispatch) => { + await promisifiedBackground.resolvePendingApproval(id, value); + // Before closing the current window, check if any additional confirmations + // are added as a result of this confirmation being accepted + const { pendingApprovals } = await forceUpdateMetamaskState(dispatch); + if (Object.values(pendingApprovals).length === 0) { + dispatch(closeCurrentNotificationWindow()); + } + }; +} + +/** + * Rejects a pending approval and closes the current notification window if no + * further approvals are pending after the background state updates. + * @param {string} id - The pending approval id + * @param {Error} [error] - The error to throw when rejecting the approval + */ +export function rejectPendingApproval(id, error) { + return async (dispatch) => { + await promisifiedBackground.rejectPendingApproval(id, error); + // Before closing the current window, check if any additional confirmations + // are added as a result of this confirmation being rejected + const { pendingApprovals } = await forceUpdateMetamaskState(dispatch); + if (Object.values(pendingApprovals).length === 0) { + dispatch(closeCurrentNotificationWindow()); + } + }; +} + export function setFirstTimeFlowType(type) { return (dispatch) => { log.debug(`background.setFirstTimeFlowType`); diff --git a/ui/index.js b/ui/index.js index b21c62959..3ccc25b6c 100644 --- a/ui/index.js +++ b/ui/index.js @@ -117,6 +117,7 @@ async function startApp(metamaskState, backgroundConnection, opts) { metamaskState.unapprovedEncryptionPublicKeyMsgs, metamaskState.unapprovedTypedMessages, metamaskState.network, + metamaskState.provider.chainId, ); const numberOfUnapprovedTx = unapprovedTxsAll.length; if (numberOfUnapprovedTx > 0) { diff --git a/ui/lib/tx-helper.js b/ui/lib/tx-helper.js index 698f0157a..7585b33fe 100644 --- a/ui/lib/tx-helper.js +++ b/ui/lib/tx-helper.js @@ -1,4 +1,5 @@ import log from 'loglevel'; +import { transactionMatchesNetwork } from '../../shared/modules/transaction.utils'; import { valuesFor } from '../app/helpers/utils/util'; export default function txHelper( @@ -9,6 +10,7 @@ export default function txHelper( encryptionPublicKeyMsgs, typedMessages, network, + chainId, ) { log.debug('tx-helper called with params:'); log.debug({ @@ -19,11 +21,12 @@ export default function txHelper( encryptionPublicKeyMsgs, typedMessages, network, + chainId, }); const txValues = network - ? valuesFor(unapprovedTxs).filter( - (txMeta) => txMeta.metamaskNetworkId === network, + ? valuesFor(unapprovedTxs).filter((txMeta) => + transactionMatchesNetwork(txMeta, chainId, network), ) : valuesFor(unapprovedTxs); log.debug(`tx helper found ${txValues.length} unapproved txs`); diff --git a/yarn.lock b/yarn.lock index efcfa3599..1f7a9175e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -347,11 +347,16 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.12.7", "@babel/parser@^7.7.5": +"@babel/parser@^7.10.1", "@babel/parser@^7.12.7": version "7.12.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.7.tgz#fee7b39fe809d0e73e5b25eecaf5780ef3d73056" integrity sha512-oWR02Ubp4xTLCAqPRiNIuMVgNO5Aif/xpXtabhzW2HWUD47XJsAB4Zd/Rg30+XeQA3juXigV7hlquOTmwqLiwg== +"@babel/parser@^7.7.5": + version "7.12.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.12.3.tgz#a305415ebe7a6c7023b40b5122a0662d928334cd" + integrity sha512-kFsOS0IbsuhO5ojF8Hc8z/8vEIOkylVBrjiZUbLTE3XFe0Qi+uu6HjzQixkFaqr0ZPAMZcBVxEwmsnsLPZ2Xsw== + "@babel/plugin-proposal-async-generator-functions@^7.12.1": version "7.12.1" resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.12.1.tgz#dc6c1170e27d8aca99ff65f4925bd06b1c90550e" @@ -1074,6 +1079,21 @@ "@babel/parser" "^7.12.7" "@babel/types" "^7.12.7" +"@babel/traverse@^7.10.1": + version "7.12.8" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.8.tgz#c1c2983bf9ba0f4f0eaa11dff7e77fa63307b2a4" + integrity sha512-EIRQXPTwFEGRZyu6gXbjfpNORN1oZvwuzJbxcXjAgWV0iqXYDszN1Hx3FVm6YgZfu1ZQbCVAk3l+nIw95Xll9Q== + dependencies: + "@babel/code-frame" "^7.10.4" + "@babel/generator" "^7.12.5" + "@babel/helper-function-name" "^7.10.4" + "@babel/helper-split-export-declaration" "^7.11.0" + "@babel/parser" "^7.12.7" + "@babel/types" "^7.12.7" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.19" + "@babel/traverse@^7.10.4", "@babel/traverse@^7.12.1", "@babel/traverse@^7.12.5", "@babel/traverse@^7.12.9", "@babel/traverse@^7.7.4": version "7.12.9" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.12.9.tgz#fad26c972eabbc11350e0b695978de6cc8e8596f" @@ -2032,15 +2052,15 @@ react-is "^16.8.0" "@metamask/contract-metadata@^1.19.0": - version "1.21.0" - resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.21.0.tgz#487f05111d0f58a01355a2d5e47d8db1fc3f38ea" - integrity sha512-+uF5evAguHmEZwheHQQ/Elrt23oEIjtdryyzsWhjVMdoyAoQovHH9yRaj7dMglYCOJAPNbFQc7+9qXEPKiTJEA== - -"@metamask/contract-metadata@^1.22.0": version "1.22.0" resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.22.0.tgz#55cc84756c703c433176b484b1d34f0e03d16d1e" integrity sha512-t4ijbU+4OH9UAlrPkfLPFo6KmkRTRZJHB+Vly4ajF8oZMnota5YjVVl/SmltsoRC9xvJtRn9DUVf3YMHMIdofw== +"@metamask/contract-metadata@^1.22.0": + version "1.23.0" + resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.23.0.tgz#c70be7f3eaeeb791651ce793b7cdc230e9780b18" + integrity sha512-oTUqL9dtXtbng60DZMRsBmZ5HiOUUfEsZjuswOJ0yHO24YsW0ktCcgCJVYPv1HcOsF0SVrRtG4rtrvOl4nY+HA== + "@metamask/controllers@^5.0.0", "@metamask/controllers@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-5.1.0.tgz#02c1957295bcb6db1655a716d165665d170e7f34" @@ -2098,10 +2118,10 @@ human-standard-token-abi "^1.0.2" safe-event-emitter "^1.0.1" -"@metamask/etherscan-link@^1.4.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@metamask/etherscan-link/-/etherscan-link-1.4.0.tgz#4631e9beec17de26b35b3ccd643ede2bae8ed811" - integrity sha512-4Bi72Y8/FQZbfTARyv+oWKGuECzdQ37cQKt88Eu5JPDrHAcRDZt4Bt7bWC9phUBrphAr1qbCKh9S90X9hW0pZg== +"@metamask/etherscan-link@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@metamask/etherscan-link/-/etherscan-link-1.4.1.tgz#44377c5c9be2c02ef26aff5da74bd839e50c09f9" + integrity sha512-hs8Qi62+6BZN9J7dknnoJR4DStEP6PzWEwRt+ScEVM4CuBVo08mqY0HXRny52A6FjBQrSnBgA5gvMbBOMqDavg== "@metamask/forwarder@^1.1.0": version "1.1.0" @@ -2243,7 +2263,7 @@ schema-utils "^2.6.5" source-map "^0.7.3" -"@popperjs/core@^2.4.0", "@popperjs/core@^2.4.4", "@popperjs/core@^2.5.4": +"@popperjs/core@^2.4.0", "@popperjs/core@^2.5.4": version "2.5.4" resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.5.4.tgz#de25b5da9f727985a3757fd59b5d028aba75841a" integrity sha512-ZpKr+WTb8zsajqgDkvCEWgp6d5eJT6Q63Ng2neTbzBO76Lbe91vX/iVIW9dikq+Fs3yEo+ls4cxeXABD2LtcbQ== @@ -2406,17 +2426,17 @@ resolved "https://registry.yarnpkg.com/@stablelib/utf8/-/utf8-0.10.1.tgz#eecf54884da7b2bee235e3c70efb8cd5c07ba5bd" integrity sha512-+uM1YZ4MhBC82vt99prF7DXNGqhYmJ9cQ3p5qNowMNkkzn9OWEkqBvguBW3ChAt7JvqZ3SD5HJOfc6YgnfMTHw== -"@storybook/addon-actions@^6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-6.1.9.tgz#b6d185b8e4e73691acc428b59e4d331195d64a40" - integrity sha512-vYqwuaBHrjRbbuyf4WBc5uDhrSejVEEiCabuu4g00R3dN7P5Ne/tbSw9EkYbbrRKxlEhdkk83DU1/J/+mCY5jw== - dependencies: - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/client-api" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/core-events" "6.1.9" - "@storybook/theming" "6.1.9" +"@storybook/addon-actions@^6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-6.1.17.tgz#9d32336284738cefa69b99acafa4b132d5533600" + integrity sha512-4hyAvmjnI4C1ZQ7/t21jKKXE0jO1zAk310BkYin0NJf77Qi0tUE1DNOwirJY/xzRih36wWi1V79c/ZOJNsLv9Q== + dependencies: + "@storybook/addons" "6.1.17" + "@storybook/api" "6.1.17" + "@storybook/client-api" "6.1.17" + "@storybook/components" "6.1.17" + "@storybook/core-events" "6.1.17" + "@storybook/theming" "6.1.17" core-js "^3.0.1" fast-deep-equal "^3.1.1" global "^4.3.2" @@ -2429,17 +2449,17 @@ util-deprecate "^1.0.2" uuid "^8.0.0" -"@storybook/addon-backgrounds@^6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-6.1.9.tgz#4e9647001b2f396f56428218480f541e3a8a0e60" - integrity sha512-0/nnbnWZqo4NjyHFxcCHkcU+t8uUdk///9jSXRs4swmOLIFRaftEc/ZJ2rScu1Sc7y0CQdbk1Jjyx5/2cHBQtw== - dependencies: - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/core-events" "6.1.9" - "@storybook/theming" "6.1.9" +"@storybook/addon-backgrounds@^6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/addon-backgrounds/-/addon-backgrounds-6.1.17.tgz#df4eeec1df72d5f835e82bee433493110463f896" + integrity sha512-1a8Vu50eQWdwMek9w2QOehhu10aZYzyR404qwGvPCRGt5uMMsKxoKvv1M6/ETW7d2G4Srl/Ka+k4x6ykoHIepA== + dependencies: + "@storybook/addons" "6.1.17" + "@storybook/api" "6.1.17" + "@storybook/client-logger" "6.1.17" + "@storybook/components" "6.1.17" + "@storybook/core-events" "6.1.17" + "@storybook/theming" "6.1.17" core-js "^3.0.1" global "^4.3.2" memoizerific "^1.11.3" @@ -2447,18 +2467,18 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/addon-knobs@^6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-6.1.9.tgz#49773931770effc208db094c61eeecbceaf5836b" - integrity sha512-aUKD9FaQGl/WOkGT6utElspYZJ7cBtUARe41JN59qOao7RNviabipQUASrjORcYUUU55sfKsLPEqQaEKB3x2bw== - dependencies: - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/channels" "6.1.9" - "@storybook/client-api" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/core-events" "6.1.9" - "@storybook/theming" "6.1.9" +"@storybook/addon-knobs@^6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-6.1.17.tgz#c7cdd5be813c2b80ce7f464eabf8ceb06486e82d" + integrity sha512-WUkoGtHhXIurXFQybsMXZaphAtCNclZjZHvji8O5eg+ahx7pIM/Wldh3uJwOdOkW5LHxT76hLxPvuXvOEysnbw== + dependencies: + "@storybook/addons" "6.1.17" + "@storybook/api" "6.1.17" + "@storybook/channels" "6.1.17" + "@storybook/client-api" "6.1.17" + "@storybook/components" "6.1.17" + "@storybook/core-events" "6.1.17" + "@storybook/theming" "6.1.17" copy-to-clipboard "^3.0.8" core-js "^3.0.1" escape-html "^1.0.3" @@ -2498,21 +2518,6 @@ global "^4.3.2" regenerator-runtime "^0.13.7" -"@storybook/addons@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-6.1.9.tgz#78f3cb27b7d934f091f311f89b6ca312d34f12b8" - integrity sha512-NRxdlGLmmSoVwlirVRgKC8xmW9cFkG+Sp5GEd4XkJDaaIg2vKR3RuFU9GuvIOVMxOhhERqhQ07bnDaAMKbFzGw== - dependencies: - "@storybook/api" "6.1.9" - "@storybook/channels" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/core-events" "6.1.9" - "@storybook/router" "6.1.9" - "@storybook/theming" "6.1.9" - core-js "^3.0.1" - global "^4.3.2" - regenerator-runtime "^0.13.7" - "@storybook/api@6.1.17": version "6.1.17" resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.1.17.tgz#50393ce9b718063b67680212df895eceacc0c11d" @@ -2538,31 +2543,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/api@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/api/-/api-6.1.9.tgz#3f9bf00b2b18fa02965079fe775bd713677b30a3" - integrity sha512-S9SXlSiMeI450NIbOnx3UU9TZNyVD7jcBCjfNzhj0PqzRX/IG5Usj+R88Jm6MSIDjtsVjrWRCou+PrCh2xMnlQ== - dependencies: - "@reach/router" "^1.3.3" - "@storybook/channels" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/core-events" "6.1.9" - "@storybook/csf" "0.0.1" - "@storybook/router" "6.1.9" - "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.1.9" - "@types/reach__router" "^1.3.5" - core-js "^3.0.1" - fast-deep-equal "^3.1.1" - global "^4.3.2" - lodash "^4.17.15" - memoizerific "^1.11.3" - regenerator-runtime "^0.13.7" - store2 "^2.7.1" - telejson "^5.0.2" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/channel-postmessage@6.1.17": version "6.1.17" resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.1.17.tgz#309ce67c94637ec13319d4ce360a8f3742ddbaf4" @@ -2576,19 +2556,6 @@ qs "^6.6.0" telejson "^5.0.2" -"@storybook/channel-postmessage@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-6.1.9.tgz#5d73c67ba94bcf68b14138bba6c5bb0850c72c5e" - integrity sha512-tX7pD9Xrf1WsatpJqtJ6o8MlgxG7jH+oFhNPkGvUbWiolVDQmuDndwM8Hh1kUnOWlyE1AN5hlM7av8MY+9D3NA== - dependencies: - "@storybook/channels" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/core-events" "6.1.9" - core-js "^3.0.1" - global "^4.3.2" - qs "^6.6.0" - telejson "^5.0.2" - "@storybook/channels@6.1.17": version "6.1.17" resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.1.17.tgz#2cc89a6b9727d19c24b15fa3cb15569b469db864" @@ -2598,15 +2565,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/channels@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-6.1.9.tgz#94f07ff3615b11c07d1902be6b6cd298c0eea55c" - integrity sha512-aV+KsZPuoTtFKSMUkSCyVlVmtVHkSH35dSbyMazjlUD9cOLwkXB1s+LZL/GxxSR6a6uR75V0QWxItfNxaJETMQ== - dependencies: - core-js "^3.0.1" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/client-api@6.1.17": version "6.1.17" resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.1.17.tgz#3ced22f08a47af70ccf8929111bc44b79e9e8ec0" @@ -2631,30 +2589,6 @@ ts-dedent "^2.0.0" util-deprecate "^1.0.2" -"@storybook/client-api@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-6.1.9.tgz#d4a8d38bc657f26e4837831b961e085da1954d51" - integrity sha512-b2DFaGAS5G2ly3UJY5NJNXh/LxgLgSJLbqPL4t48MFW5XjH+rmEWXE9P+ujCaPclH1/y7mZRMprDj3ycDbRo3Q== - dependencies: - "@storybook/addons" "6.1.9" - "@storybook/channel-postmessage" "6.1.9" - "@storybook/channels" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/core-events" "6.1.9" - "@storybook/csf" "0.0.1" - "@types/qs" "^6.9.0" - "@types/webpack-env" "^1.15.3" - core-js "^3.0.1" - global "^4.3.2" - lodash "^4.17.15" - memoizerific "^1.11.3" - qs "^6.6.0" - regenerator-runtime "^0.13.7" - stable "^0.1.8" - store2 "^2.7.1" - ts-dedent "^2.0.0" - util-deprecate "^1.0.2" - "@storybook/client-logger@6.1.17": version "6.1.17" resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.1.17.tgz#0d89aaf824457f19bf9aa585bbcada57595e7d01" @@ -2663,14 +2597,6 @@ core-js "^3.0.1" global "^4.3.2" -"@storybook/client-logger@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-6.1.9.tgz#1d61a64000d4691780d75e19b78fd44adfdb5d9c" - integrity sha512-i7Q2ky9+Jwv+wmnlOGxmDOEdmaTIB69OQnnZNWGKufOwoIMjn6QO0VifARyA9W++nNSijjJ5th84tLJALaoCTA== - dependencies: - core-js "^3.0.1" - global "^4.3.2" - "@storybook/components@6.1.17": version "6.1.17" resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.1.17.tgz#f92d36e370ec6039d8c7cee9ef13dda866eed3da" @@ -2697,32 +2623,6 @@ react-textarea-autosize "^8.1.1" ts-dedent "^2.0.0" -"@storybook/components@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-6.1.9.tgz#f25d18f3a410cc7e9549ddb3c971c40d9108d4d8" - integrity sha512-cYYm3fHo9MW0bbl47lu1ncwulV7V9VEF8FC96uvys07oaCTFWKzQ0z/FD0nCqeK6eEz1+SEqnGwLFmOtqlRXDQ== - dependencies: - "@popperjs/core" "^2.4.4" - "@storybook/client-logger" "6.1.9" - "@storybook/csf" "0.0.1" - "@storybook/theming" "6.1.9" - "@types/overlayscrollbars" "^1.9.0" - "@types/react-color" "^3.0.1" - "@types/react-syntax-highlighter" "11.0.4" - core-js "^3.0.1" - fast-deep-equal "^3.1.1" - global "^4.3.2" - lodash "^4.17.15" - markdown-to-jsx "^6.11.4" - memoizerific "^1.11.3" - overlayscrollbars "^1.10.2" - polished "^3.4.4" - react-color "^2.17.0" - react-popper-tooltip "^3.1.0" - react-syntax-highlighter "^13.5.0" - react-textarea-autosize "^8.1.1" - ts-dedent "^2.0.0" - "@storybook/core-events@6.1.17": version "6.1.17" resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.1.17.tgz#697ed916fcb2a411bc9f8bdbfacd0eb9d394eb58" @@ -2730,17 +2630,10 @@ dependencies: core-js "^3.0.1" -"@storybook/core-events@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-6.1.9.tgz#0a88281837d1aa657a93a9abf7f5aad65b8d68e7" - integrity sha512-oOpqpjCTJCt0U5lnQ16OZU0iKIDh2/MIg4yrnDw+Pt6zGyX3zSvtB+9W8LQFnMwm+cXaNmiizGwt/W+4OiORjQ== - dependencies: - core-js "^3.0.1" - -"@storybook/core@6.1.9", "@storybook/core@^6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.1.9.tgz#e6575e294cb4d2d9b57d5976a145cae8f4a88594" - integrity sha512-guz+R6eDX923Cw7NqgS5PrpTmmjDB+m5X1iF9pwKlpPTfzIiT/wTzJm4PwhFoGONNoXrItObX/6hW6OQbX4aOA== +"@storybook/core@6.1.17", "@storybook/core@^6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-6.1.17.tgz#21c3d2c23fcaac4b930c9413f396d158aaeb7546" + integrity sha512-9x8ezlKlm8SQ+OW3kKwJwuVcaTDCw2OlA9YZEOo1kdRKsiiy5X14VqjJocl/BqnDt2VgzUUchz3m4neHYMAivQ== dependencies: "@babel/core" "^7.12.3" "@babel/plugin-proposal-class-properties" "^7.12.1" @@ -2764,20 +2657,20 @@ "@babel/preset-react" "^7.12.1" "@babel/preset-typescript" "^7.12.1" "@babel/register" "^7.12.1" - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/channel-postmessage" "6.1.9" - "@storybook/channels" "6.1.9" - "@storybook/client-api" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/core-events" "6.1.9" + "@storybook/addons" "6.1.17" + "@storybook/api" "6.1.17" + "@storybook/channel-postmessage" "6.1.17" + "@storybook/channels" "6.1.17" + "@storybook/client-api" "6.1.17" + "@storybook/client-logger" "6.1.17" + "@storybook/components" "6.1.17" + "@storybook/core-events" "6.1.17" "@storybook/csf" "0.0.1" - "@storybook/node-logger" "6.1.9" - "@storybook/router" "6.1.9" + "@storybook/node-logger" "6.1.17" + "@storybook/router" "6.1.17" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.1.9" - "@storybook/ui" "6.1.9" + "@storybook/theming" "6.1.17" + "@storybook/ui" "6.1.17" "@types/glob-base" "^0.3.0" "@types/micromatch" "^4.0.1" "@types/node-fetch" "^2.5.4" @@ -2851,10 +2744,10 @@ dependencies: lodash "^4.17.15" -"@storybook/node-logger@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.1.9.tgz#c63a61f72209d76eeeffe9d151fec043864b9438" - integrity sha512-2gP9BSBXEOGIcUyzRdIkIJi1UEINUAIyuv9bfKODo4GfujRg7DLz/mpi/FdwmulGg/viXWSXa6ccb6ziIgY9RA== +"@storybook/node-logger@6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-6.1.17.tgz#468e65c9f0c103d4b0cd7f5da945af81e9aaa3d4" + integrity sha512-Z0xQ4kzvf7GnwFG9UY1HJO2UR66t8IBnC5GxvWrJ/kwXE+DRF3mm/MT41Zz/d9zAY5Vo4mhE5zRwlYSAtrxQIQ== dependencies: "@types/npmlog" "^4.1.2" chalk "^4.0.0" @@ -2862,17 +2755,17 @@ npmlog "^4.1.2" pretty-hrtime "^1.0.3" -"@storybook/react@^6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/react/-/react-6.1.9.tgz#063427015b3d0ce582b1b6b7826d40d963d265ce" - integrity sha512-HJWHQE+eCC7sz1vqvgmBMn2sA1uc0ByEj+NeSgyi45jBFI+Ke4a8hxx6k5XA7k9gLznqG8TPGg0z6EdQTJTLkQ== +"@storybook/react@^6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-6.1.17.tgz#cb48386d435984d7ca58a24e686a72159367077b" + integrity sha512-gBylKDuwUzWueB6mEhTo72SelWU3vPWHAFsi+NK6zWFIc2a5dJc9QqDfN+2rBhVOdRXqhSHzYwNWurqYpWuqew== dependencies: "@babel/preset-flow" "^7.12.1" "@babel/preset-react" "^7.12.1" "@pmmmwh/react-refresh-webpack-plugin" "^0.4.2" - "@storybook/addons" "6.1.9" - "@storybook/core" "6.1.9" - "@storybook/node-logger" "6.1.9" + "@storybook/addons" "6.1.17" + "@storybook/core" "6.1.17" + "@storybook/node-logger" "6.1.17" "@storybook/semver" "^7.3.2" "@types/webpack-env" "^1.15.3" babel-plugin-add-react-displayname "^0.0.5" @@ -2901,18 +2794,6 @@ memoizerific "^1.11.3" qs "^6.6.0" -"@storybook/router@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-6.1.9.tgz#c0b24dc3ab53d58541b81c7abea2f11d7fbbebf6" - integrity sha512-kIlmSFBnqI198oMCncFZR7MxoV5/kP6KS0paFcyu1XE1zO2ovV6eQZ8pPpOjSsD/ISu4Y44uE+ZDNsEehjj6GQ== - dependencies: - "@reach/router" "^1.3.3" - "@types/reach__router" "^1.3.5" - core-js "^3.0.1" - global "^4.3.2" - memoizerific "^1.11.3" - qs "^6.6.0" - "@storybook/semver@^7.3.2": version "7.3.2" resolved "https://registry.yarnpkg.com/@storybook/semver/-/semver-7.3.2.tgz#f3b9c44a1c9a0b933c04e66d0048fcf2fa10dac0" @@ -2921,10 +2802,10 @@ core-js "^3.6.5" find-up "^4.1.0" -"@storybook/storybook-deployer@^2.8.6": - version "2.8.6" - resolved "https://registry.yarnpkg.com/@storybook/storybook-deployer/-/storybook-deployer-2.8.6.tgz#00c2e84f27dfaa88cb0785361453f23b1ebb4ea3" - integrity sha512-Bpe7ZtsR5NUuohK3VsQa+nxEHtVxMZZo3DRlRUZW5IZOmzmvSID3i+jkizloG9xO7sw5zUvlD31YMHm7OtdrMA== +"@storybook/storybook-deployer@^2.8.7": + version "2.8.7" + resolved "https://registry.yarnpkg.com/@storybook/storybook-deployer/-/storybook-deployer-2.8.7.tgz#c1eed33d03bd9267f884c60eea8e03dc3261ec11" + integrity sha512-O0hKHV6hg93fPMvKGC5M/sd7KTL473+SzMKm+WZNVEyLEfXXcVU+Ts9/VL1IhmC1P2A8Bg9oBnkcPqAqjAN46w== dependencies: git-url-parse "^11.1.2" glob "^7.1.3" @@ -2950,39 +2831,21 @@ resolve-from "^5.0.0" ts-dedent "^2.0.0" -"@storybook/theming@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-6.1.9.tgz#8c584aa623f3d6e33b1e3b3de2ec1f41bdc5d9ab" - integrity sha512-orzMQkyEhAQEi0E9iwmUkzh5yPHoYGBz17t2aydDeT6oGKii6if8Mq2oPVycfVKZ84QO7GFAS9q1nVCRcuD8oA== - dependencies: - "@emotion/core" "^10.1.1" - "@emotion/is-prop-valid" "^0.8.6" - "@emotion/styled" "^10.0.23" - "@storybook/client-logger" "6.1.9" - core-js "^3.0.1" - deep-object-diff "^1.1.0" - emotion-theming "^10.0.19" - global "^4.3.2" - memoizerific "^1.11.3" - polished "^3.4.4" - resolve-from "^5.0.0" - ts-dedent "^2.0.0" - -"@storybook/ui@6.1.9": - version "6.1.9" - resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.1.9.tgz#1ed3168d9fe5827285c13d8507dd1fd872830542" - integrity sha512-4MK5iTf7kI5DYVeWRiD6lkXdd0S6eiQJu9lvWqMOQJLOH5Bq77g0Ejo+38RTEQpV6we7hCPWWnRXQBjmJ2+19w== +"@storybook/ui@6.1.17": + version "6.1.17" + resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-6.1.17.tgz#c29e7a03c645dd94793a3cbd587fcb6e0ba0f22e" + integrity sha512-D4Vri1MmqfmNq+g1hSRqZyld5zX2VLUexQHGSPmNj+FhlOzkeNA5RcoMBWMvIUSUENiBx3a5gmr/6cbXo7ljdQ== dependencies: "@emotion/core" "^10.1.1" - "@storybook/addons" "6.1.9" - "@storybook/api" "6.1.9" - "@storybook/channels" "6.1.9" - "@storybook/client-logger" "6.1.9" - "@storybook/components" "6.1.9" - "@storybook/core-events" "6.1.9" - "@storybook/router" "6.1.9" + "@storybook/addons" "6.1.17" + "@storybook/api" "6.1.17" + "@storybook/channels" "6.1.17" + "@storybook/client-logger" "6.1.17" + "@storybook/components" "6.1.17" + "@storybook/core-events" "6.1.17" + "@storybook/router" "6.1.17" "@storybook/semver" "^7.3.2" - "@storybook/theming" "6.1.9" + "@storybook/theming" "6.1.17" "@types/markdown-to-jsx" "^6.11.0" copy-to-clipboard "^3.0.8" core-js "^3.0.1" @@ -3145,11 +3008,6 @@ dependencies: "@types/unist" "*" -"@types/history@*": - version "4.7.3" - resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.3.tgz#856c99cdc1551d22c22b18b5402719affec9839a" - integrity sha512-cS5owqtwzLN5kY+l+KgKdRJ/Cee8tlmQoGQuIE9tWnSmS3JMKzmxo2HIAk2wODMifGwO20d62xZQLYz+RLfXmw== - "@types/html-minifier-terser@^5.0.0": version "5.1.1" resolved "https://registry.yarnpkg.com/@types/html-minifier-terser/-/html-minifier-terser-5.1.1.tgz#3c9ee980f1a10d6021ae6632ca3e79ca2ec4fb50" @@ -3195,12 +3053,7 @@ resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha1-7ihweulOEdK4J7y+UnC86n8+ce4= -"@types/lodash@^4.14.107": - version "4.14.124" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.124.tgz#16fb067a8fc4be42f044c505d8b5316c6f54de93" - integrity sha512-6bKEUVbHJ8z34jisA7lseJZD2g31SIvee3cGX2KEZCS4XXWNbjPZpmO1/2rGNR9BhGtaYr6iYXPl1EzRrDAFTA== - -"@types/lodash@^4.14.136": +"@types/lodash@^4.14.107", "@types/lodash@^4.14.136": version "4.14.168" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.168.tgz#fe24632e79b7ade3f132891afff86caa5e5ce008" integrity sha512-oVfRvqHV/V6D1yifJbVRU3TMp8OT6o6BG+U9MkwuJ3U8/CsDHvalRpsxBqivn71ztOFZBTfJMvETbqHiaNSj7Q== @@ -3294,24 +3147,11 @@ resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw== -"@types/q@^1.5.1": - version "1.5.2" - resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" - integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== - "@types/qs@^6.9.0": version "6.9.5" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b" integrity sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ== -"@types/reach__router@^1.3.5": - version "1.3.6" - resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.3.6.tgz#413417ce74caab331c70ce6a03a4c825188e4709" - integrity sha512-RHYataCUPQnt+GHoASyRLq6wmZ0n8jWlBW8Lxcwd30NN6vQfbmTeoSDfkgxO0S1lEzArp8OFDsq5KIs7FygjtA== - dependencies: - "@types/history" "*" - "@types/react" "*" - "@types/reach__router@^1.3.7": version "1.3.7" resolved "https://registry.yarnpkg.com/@types/reach__router/-/reach__router-1.3.7.tgz#de8ab374259ae7f7499fc1373b9697a5f3cd6428" @@ -3785,7 +3625,7 @@ acorn@^6.0.1, acorn@^6.0.2, acorn@^6.0.7, acorn@^6.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" integrity sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ== -acorn@^7.0.0, acorn@^7.1.1, acorn@^7.4.0: +acorn@^7.0.0, acorn@^7.4.0: version "7.4.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== @@ -3982,7 +3822,7 @@ ajv@^4.7.0: co "^4.6.0" json-stable-stringify "^1.0.1" -ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.5.5, ajv@^6.9.1: +ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4, ajv@^6.12.5, ajv@^6.9.1: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== @@ -4256,18 +4096,6 @@ aproba@^1.0.3, aproba@^1.1.1: resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== -arch@^2.1.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/arch/-/arch-2.1.1.tgz#8f5c2731aa35a30929221bb0640eed65175ec84e" - integrity sha512-BLM56aPo9vLLFVa8+/+pJLnrZ7QGGTVHWsCwieAWT9o9K8UeGaQbzZbGoabWLOo2ksBCztoXdqBZBplqLDDCSg== - -archive-type@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/archive-type/-/archive-type-4.0.0.tgz#f92e72233056dfc6969472749c267bdb046b1d70" - integrity sha1-+S5yIzBW38aWlHJ0nCZ72wRrHXA= - dependencies: - file-type "^4.2.0" - archy@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" @@ -4455,11 +4283,6 @@ array-uniq@^1.0.1: resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= -array-uniq@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-2.1.0.tgz#46603d5e28e79bfd02b046fcc1d77c6820bd8e98" - integrity sha512-bdHxtev7FN6+MXI1YFW0Q8mQ8dTJc2S8AMfju+ZR77pbg2yAdVyDlwkaUI7Har0LyOMRFPHrJ9lYdyjZZswdlQ== - array-unique@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" @@ -4688,55 +4511,6 @@ async-settle@^1.0.0: dependencies: async-done "^1.2.2" -async.queue@^0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.queue/-/async.queue-0.5.2.tgz#8d5d90812e1481066bc0904e8cc1712b17c3bd7c" - integrity sha1-jV2QgS4UgQZrwJBOjMFxKxfDvXw= - dependencies: - async.util.queue "0.5.2" - -async.util.arrayeach@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.arrayeach/-/async.util.arrayeach-0.5.2.tgz#58c4e98028d55d69bfb05aeb3af44e0a555a829c" - integrity sha1-WMTpgCjVXWm/sFrrOvROClVagpw= - -async.util.isarray@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.isarray/-/async.util.isarray-0.5.2.tgz#e62dac8f2636f65875dcf7521c2d24d0dfb2bbdf" - integrity sha1-5i2sjyY29lh13PdSHC0k0N+yu98= - -async.util.map@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.map/-/async.util.map-0.5.2.tgz#e588ef86e0b3ab5f027d97af4d6835d055ca69d6" - integrity sha1-5YjvhuCzq18CfZevTWg10FXKadY= - -async.util.noop@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.noop/-/async.util.noop-0.5.2.tgz#bdd62b97cb0aa3f60b586ad148468698975e58b9" - integrity sha1-vdYrl8sKo/YLWGrRSEaGmJdeWLk= - -async.util.onlyonce@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.onlyonce/-/async.util.onlyonce-0.5.2.tgz#b8e6fc004adc923164d79e32f2813ee465c24ff2" - integrity sha1-uOb8AErckjFk154y8oE+5GXCT/I= - -async.util.queue@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.queue/-/async.util.queue-0.5.2.tgz#57f65abe1a3cdf273d31abd28ab95425f8222ee5" - integrity sha1-V/Zavho83yc9MavSirlUJfgiLuU= - dependencies: - async.util.arrayeach "0.5.2" - async.util.isarray "0.5.2" - async.util.map "0.5.2" - async.util.noop "0.5.2" - async.util.onlyonce "0.5.2" - async.util.setimmediate "0.5.2" - -async.util.setimmediate@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/async.util.setimmediate/-/async.util.setimmediate-0.5.2.tgz#2812ebabf2a58027758d4bc7793d1ccfaf10255f" - integrity sha1-KBLrq/KlgCd1jUvHeT0cz68QJV8= - async@0.9.x: version "0.9.2" resolved "https://registry.yarnpkg.com/async/-/async-0.9.2.tgz#aea74d5e61c1f899613bf64bda66d4c78f2fd17d" @@ -5673,14 +5447,14 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= -base-x@3.0.4, base-x@^3.0.2: +base-x@3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.4.tgz#94c1788736da065edb1d68808869e357c977fa77" integrity sha512-UYOadoSIkEI/VrRGSG6qp93rp2WdokiAiNYDfGW5qURAY8GiAQkvMbwNNSDYiVJopqv4gCna7xqf4rrNGp+5AA== dependencies: safe-buffer "^5.0.1" -base-x@3.0.8: +base-x@3.0.8, base-x@^3.0.2: version "3.0.8" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.8.tgz#1e1106c2537f0162e8b52474a557ebb09000018d" integrity sha512-Rl/1AWP4J/zRrk54hhlxH4drNxPJXYUaKffODVI53/dAsV4t9fBxyxYKAVPU1XBHxYwOWP9h9H0hM2MVw4YfJA== @@ -5812,12 +5586,7 @@ bignumber.js@^8.0.1, bignumber.js@^8.0.2, bignumber.js@^8.1.1: resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-8.1.1.tgz#4b072ae5aea9c20f6730e4e5d529df1271c4d885" integrity sha512-QD46ppGintwPGuL1KqmwhR0O+N2cZUg8JG/VzwI2e28sM9TqHjQB10lI4QAaMHVbLzwVLLAwEglpKPViWX+5NQ== -bignumber.js@^9.0.0: - version "9.0.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.0.tgz#805880f84a329b5eac6e7cb6f8274b6d82bdf075" - integrity sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A== - -bignumber.js@^9.0.1: +bignumber.js@^9.0.0, bignumber.js@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.0.1.tgz#8d7ba124c882bfd8e43260c67475518d0689e4e5" integrity sha512-IdZR9mh6ahOBv/hYGiXyVuyCetmGJhtYkqLBpTStdhEGjegpPlUawydyaF3pbIOFynJTpllEs+NP+CS9jKFLjA== @@ -5826,54 +5595,6 @@ bignumber.js@^9.0.1: version "2.0.7" resolved "git+https://github.com/frozeman/bignumber.js-nolookahead.git#57692b3ecfc98bbdd6b3a516cb2353652ea49934" -bin-build@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/bin-build/-/bin-build-3.0.0.tgz#c5780a25a8a9f966d8244217e6c1f5082a143861" - integrity sha512-jcUOof71/TNAI2uM5uoUaDq2ePcVBQ3R/qhxAz1rX7UfvduAL/RXD3jXzvn8cVcDJdGVkiR1shal3OH0ImpuhA== - dependencies: - decompress "^4.0.0" - download "^6.2.2" - execa "^0.7.0" - p-map-series "^1.0.0" - tempfile "^2.0.0" - -bin-check@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bin-check/-/bin-check-4.1.0.tgz#fc495970bdc88bb1d5a35fc17e65c4a149fc4a49" - integrity sha512-b6weQyEUKsDGFlACWSIOfveEnImkJyK/FGW6FAG42loyoquvjdtOIqO6yBFzHyqyVVhNgNkQxxx09SFLK28YnA== - dependencies: - execa "^0.7.0" - executable "^4.1.0" - -bin-version-check@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/bin-version-check/-/bin-version-check-4.0.0.tgz#7d819c62496991f80d893e6e02a3032361608f71" - integrity sha512-sR631OrhC+1f8Cvs8WyVWOA33Y8tgwjETNPyyD/myRBXLkfS/vl74FmH/lFcRl9KY3zwGh7jFhvyk9vV3/3ilQ== - dependencies: - bin-version "^3.0.0" - semver "^5.6.0" - semver-truncate "^1.1.2" - -bin-version@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bin-version/-/bin-version-3.1.0.tgz#5b09eb280752b1bd28f0c9db3f96f2f43b6c0839" - integrity sha512-Mkfm4iE1VFt4xd4vH+gx+0/71esbfus2LsnCGe8Pi4mndSPyT+NGES/Eg99jx8/lUGWfu3z2yuB/bt5UB+iVbQ== - dependencies: - execa "^1.0.0" - find-versions "^3.0.0" - -bin-wrapper@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bin-wrapper/-/bin-wrapper-4.1.0.tgz#99348f2cf85031e3ef7efce7e5300aeaae960605" - integrity sha512-hfRmo7hWIXPkbpi0ZltboCMVrU+0ClXR/JgbCKKjlDjQf6igXa7OwdqNcFWQZPZTgiY7ZpzE3+LjjkLiTN2T7Q== - dependencies: - bin-check "^4.1.0" - bin-version-check "^4.0.0" - download "^7.1.0" - import-lazy "^3.1.0" - os-filter-obj "^2.0.0" - pify "^4.0.1" - binary-extensions@^1.0.0: version "1.11.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" @@ -5894,11 +5615,6 @@ binaryen@77.0.0-nightly.20190407: resolved "https://registry.yarnpkg.com/binaryen/-/binaryen-77.0.0-nightly.20190407.tgz#fbe4f8ba0d6bd0809a84eb519d2d5b5ddff3a7d1" integrity sha512-1mxYNvQ0xywMe582K7V6Vo2zzhZZxMTeGHH8aE/+/AND8f64D8Q1GThVY3RVRwGY/4p+p95ccw9Xbw2ovFXRIg== -binaryextensions@2: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.2.0.tgz#e7c6ba82d4f5f5758c26078fe8eea28881233311" - integrity sha512-bHhs98rj/7i/RZpCSJ3uk55pLXOItjIrh2sRQZSM6OoktScX+LxJzvlU+FELp9j3TdcddTmmYArLSGptCTwjuw== - bindings@^1.2.1, bindings@^1.3.0, bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" @@ -6039,12 +5755,12 @@ bn.js@^1.0.0: resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-1.3.0.tgz#0db4cbf96f8f23b742f5bcb9d1aa7a9994a05e83" integrity sha1-DbTL+W+PI7dC9by50ap6mZSgXoM= -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.1, bn.js@^4.11.6, bn.js@^4.11.7, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.4.0, bn.js@^4.8.0: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.0, bn.js@^4.11.1, bn.js@^4.11.6, bn.js@^4.11.7, bn.js@^4.11.8, bn.js@^4.11.9, bn.js@^4.4.0, bn.js@^4.8.0: version "4.11.9" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.9.tgz#26d556829458f9d1e81fc48952493d0ba3507828" integrity sha512-E6QoYqCKZfgatHTdHzs1RRKP7ip4vvm+EyRUeE2RF0NblwVvb0p6jSVeNTOFxPn26QXN2o6SMfNxKp6kU8zQaw== -bn.js@^5.1.1: +bn.js@^5.1.1, bn.js@^5.1.2: version "5.1.3" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-5.1.3.tgz#beca005408f642ebebea80b042b4d18d2ac0ee6b" integrity sha512-GkTiFpjFtUzU9CbMeJ5iazkCzGL3jrhzerzZIuqLABjbwRaFt33I9tUdSNryIptM+RxDet6OKm2WnLXzW51KsQ== @@ -6075,7 +5791,7 @@ body@^5.1.0: raw-body "~1.1.0" safe-json-parse "~1.0.1" -boolbase@^1.0.0, boolbase@~1.0.0: +boolbase@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= @@ -6261,14 +5977,6 @@ browserify-cipher@^1.0.0: browserify-des "^1.0.0" evp_bytestokey "^1.0.0" -browserify-derequire@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/browserify-derequire/-/browserify-derequire-1.0.1.tgz#6c7cdb228ccf21226e9a1d203a16be9da5afd253" - integrity sha512-UYKzp7fjiwq2+zj4IgS9lLUhNIdO3I4k+xEAAs5a6i3aQC3E+3gMYq9bDfyckojxNKCPnWxFWjJS4gGcxTXhUw== - dependencies: - derequire "2.0.6" - through2 "3.0.1" - browserify-des@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.0.tgz#daa277717470922ed2fe18594118a175439721dd" @@ -6433,19 +6141,6 @@ btoa@^1.2.1: resolved "https://registry.yarnpkg.com/btoa/-/btoa-1.2.1.tgz#01a9909f8b2c93f6bf680ba26131eb30f7fa3d73" integrity sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g== -buffer-alloc-unsafe@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" - integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== - -buffer-alloc@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" - integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== - dependencies: - buffer-alloc-unsafe "^1.1.0" - buffer-fill "^1.0.0" - buffer-compare@=1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-compare/-/buffer-compare-1.0.0.tgz#acaa7a966e98eee9fae14b31c39a5f158fb3c4a2" @@ -6471,11 +6166,6 @@ buffer-equal@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-1.0.0.tgz#59616b498304d556abd466966b22eeda3eca5fbe" integrity sha1-WWFrSYME1Var1GaWayLu2j7KX74= -buffer-fill@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" - integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= - buffer-from@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-0.1.2.tgz#15f4b9bcef012044df31142c14333caf6e0260d0" @@ -6518,6 +6208,13 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= +buffer-xor@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-2.0.2.tgz#34f7c64f04c777a1f8aac5e661273bb9dd320289" + integrity sha512-eHslX0bin3GB+Lx2p7lEYRShRewuNZL3fUl4qlVJGGiwoPGftmt8JQgk2Y9Ji5/01TnVDo33E5b5O3vUB1HdqQ== + dependencies: + safe-buffer "^5.1.1" + buffer@^4.3.0: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" @@ -6670,19 +6367,6 @@ cache-content-type@^1.0.0: mime-types "^2.1.18" ylru "^1.2.0" -cacheable-request@^2.1.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-2.1.4.tgz#0d808801b6342ad33c91df9d0b44dc09b91e5c3d" - integrity sha1-DYCIAbY0KtM8kd+dC0TcCbkeXD0= - dependencies: - clone-response "1.0.2" - get-stream "3.0.0" - http-cache-semantics "3.8.1" - keyv "3.0.0" - lowercase-keys "1.0.0" - normalize-url "2.0.1" - responselike "1.0.2" - cacheable-request@^6.0.0: version "6.1.0" resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912" @@ -6828,16 +6512,6 @@ cashaddrjs@^0.3.12, cashaddrjs@^0.3.3: dependencies: big-integer "1.6.36" -caw@^2.0.0, caw@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/caw/-/caw-2.0.1.tgz#6c3ca071fc194720883c2dc5da9b074bfc7e9e95" - integrity sha512-Cg8/ZSBEa8ZVY9HspcGUYaK63d/bN7rqS3CYCzEGUxuYv6UlmcjzDUz2fCFFHyTvUW5Pk0I+3hkA3iXlIj6guA== - dependencies: - get-proxy "^2.0.0" - isurl "^1.0.0-alpha5" - tunnel-agent "^0.6.0" - url-to-options "^1.0.1" - cbor-sync@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/cbor-sync/-/cbor-sync-1.0.4.tgz#5a11a1ab75c2a14d1af1b237fd84aa8c1593662f" @@ -6867,18 +6541,6 @@ chai-checkmark@^1.0.1: deep-eql "^0.1.3" type-detect "^1.0.0" -chai@^4.1.0: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c" - integrity sha1-D2RYS6ZC8PKs4oBiefTwbKI61zw= - dependencies: - assertion-error "^1.0.1" - check-error "^1.0.1" - deep-eql "^3.0.0" - get-func-name "^2.0.0" - pathval "^1.0.0" - type-detect "^4.0.0" - chain-function@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/chain-function/-/chain-function-1.0.1.tgz#c63045e5b4b663fb86f1c6e186adaf1de402a1cc" @@ -6973,11 +6635,6 @@ charenc@0.0.2: resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= -check-error@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= - checkpoint-store@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" @@ -7012,7 +6669,7 @@ chokidar@3.3.0: optionalDependencies: fsevents "~2.1.1" -"chokidar@>=2.0.0 <4.0.0": +"chokidar@>=2.0.0 <4.0.0", chokidar@^3.3.0, chokidar@^3.4.1: version "3.5.1" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== @@ -7046,21 +6703,6 @@ chokidar@^2.0.0, chokidar@^2.1.1, chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" -chokidar@^3.3.0, chokidar@^3.4.1: - version "3.4.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" - integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== - dependencies: - anymatch "~3.1.1" - braces "~3.0.2" - glob-parent "~5.1.0" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.5.0" - optionalDependencies: - fsevents "~2.1.2" - chownr@^1.1.1: version "1.1.3" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.3.tgz#42d837d5239688d55f303003a508230fa6727142" @@ -7158,7 +6800,7 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" -classnames@^2.2.4, classnames@^2.2.5, classnames@^2.2.6: +classnames@^2.2.5, classnames@^2.2.6: version "2.2.6" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== @@ -7271,6 +6913,17 @@ clone-buffer@^1.0.0: resolved "https://registry.yarnpkg.com/clone-buffer/-/clone-buffer-1.0.0.tgz#e3e25b207ac4e701af721e2cb5a16792cac3dc58" integrity sha1-4+JbIHrE5wGvch4staFnksrD3Fg= +clone-deep@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-0.2.4.tgz#4e73dd09e9fb971cc38670c5dced9c1896481cc6" + integrity sha1-TnPdCen7lxzDhnDF3O2cGJZIHMY= + dependencies: + for-own "^0.1.3" + is-plain-object "^2.0.1" + kind-of "^3.0.2" + lazy-cache "^1.0.3" + shallow-clone "^0.1.2" + clone-deep@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713" @@ -7288,7 +6941,7 @@ clone-regexp@^2.1.0: dependencies: is-regexp "^2.0.0" -clone-response@1.0.2, clone-response@^1.0.2: +clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws= @@ -7310,7 +6963,7 @@ clone@2.1.1: resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.1.tgz#d217d1e961118e3ac9a4b8bba3285553bf647cdb" integrity sha1-0hfR6WERjjrJpLi7oyhVU79kfNs= -clone@2.1.2, clone@^2.0.0, clone@^2.1.1, clone@^2.1.2: +clone@2.1.2, clone@^2.0.0, clone@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= @@ -7339,15 +6992,6 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ= -coa@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" - integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== - dependencies: - "@types/q" "^1.5.1" - chalk "^2.4.1" - q "^1.1.2" - code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" @@ -7493,13 +7137,6 @@ commander@^5.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae" integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg== -commander@~2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - integrity sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ= - dependencies: - graceful-readlink ">= 1.0.0" - common-tags@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" @@ -7515,12 +7152,12 @@ component-bind@1.0.0: resolved "https://registry.yarnpkg.com/component-bind/-/component-bind-1.0.0.tgz#00c608ab7dcd93897c0009651b1d3a8e1e73bbd1" integrity sha1-AMYIq33Nk4l8AAllGx06jh5zu9E= -component-emitter@1.2.1, component-emitter@^1.2.0, component-emitter@^1.2.1: +component-emitter@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.2.1.tgz#137918d6d78283f7df7a6b7c5a63e140e69425e6" integrity sha1-E3kY1teCg/ffemt8WmPhQOaUJeY= -component-emitter@~1.3.0: +component-emitter@^1.2.0, component-emitter@^1.2.1, component-emitter@~1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== @@ -7552,7 +7189,7 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= -concat-stream@^1.4.6, concat-stream@^1.5.0, concat-stream@^1.5.1, concat-stream@^1.5.2, concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@^1.6.2, concat-stream@~1.6.0: +concat-stream@^1.5.0, concat-stream@^1.5.1, concat-stream@^1.5.2, concat-stream@^1.6.0, concat-stream@^1.6.1, concat-stream@^1.6.2, concat-stream@~1.6.0: version "1.6.2" resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== @@ -7628,11 +7265,6 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= -console-stream@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/console-stream/-/console-stream-0.1.1.tgz#a095fe07b20465955f2fafd28b5d72bccd949d44" - integrity sha1-oJX+B7IEZZVfL6/Si11yvM2UnUQ= - constants-browserify@^1.0.0, constants-browserify@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" @@ -7648,7 +7280,7 @@ content-disposition@0.5.2: resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" integrity sha1-DPaLud318r55YcOoUXjLhdunjLQ= -content-disposition@0.5.3, content-disposition@^0.5.2, content-disposition@~0.5.2: +content-disposition@0.5.3, content-disposition@~0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== @@ -7791,12 +7423,7 @@ core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.3: resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== -core-js@^3.0.1, core-js@^3.0.4: - version "3.6.5" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a" - integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA== - -core-js@^3.6.5: +core-js@^3.0.1, core-js@^3.0.4, core-js@^3.6.5: version "3.8.3" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.8.3.tgz#c21906e1f14f3689f93abcc6e26883550dd92dd0" integrity sha512-KPYXeVZYemC2TkNEkX/01I+7yd+nX3KddKwZ1Ww7SKWdI2wQprSgLmrTddT8nw92AjEklTsPBoSdQBhbI1bQ6Q== @@ -8048,11 +7675,6 @@ css-loader@^3.5.3: schema-utils "^2.7.0" semver "^6.3.0" -css-select-base-adapter@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" - integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== - css-select@^1.1.0, css-select@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" @@ -8063,32 +7685,6 @@ css-select@^1.1.0, css-select@~1.2.0: domutils "1.5.1" nth-check "~1.0.1" -css-select@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.0.2.tgz#ab4386cec9e1f668855564b17c3733b43b2a5ede" - integrity sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ== - dependencies: - boolbase "^1.0.0" - css-what "^2.1.2" - domutils "^1.7.0" - nth-check "^1.0.2" - -css-tree@1.0.0-alpha.29: - version "1.0.0-alpha.29" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.29.tgz#3fa9d4ef3142cbd1c301e7664c1f352bd82f5a39" - integrity sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg== - dependencies: - mdn-data "~1.1.0" - source-map "^0.5.3" - -css-tree@1.0.0-alpha.33: - version "1.0.0-alpha.33" - resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.33.tgz#970e20e5a91f7a378ddd0fc58d0b6c8d4f3be93e" - integrity sha512-SPt57bh5nQnpsTBsx/IXbO14sRc9xXu5MtMAVuo0BaQQmyf0NupNPPSoMaqiAF5tDFafYsTkfeH4Q/HCKXkg4w== - dependencies: - mdn-data "2.0.4" - source-map "^0.5.3" - css-vendor@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/css-vendor/-/css-vendor-2.0.8.tgz#e47f91d3bd3117d49180a3c935e62e3d9f7f449d" @@ -8097,7 +7693,7 @@ css-vendor@^2.0.8: "@babel/runtime" "^7.8.3" is-in-browser "^1.0.2" -css-what@2.1, css-what@^2.1.2: +css-what@2.1: version "2.1.3" resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== @@ -8117,13 +7713,6 @@ cssesc@^3.0.0: resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== -csso@^3.5.1: - version "3.5.1" - resolved "https://registry.yarnpkg.com/csso/-/csso-3.5.1.tgz#7b9eb8be61628973c1b261e169d2f024008e758b" - integrity sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg== - dependencies: - css-tree "1.0.0-alpha.29" - cssom@0.3.x, "cssom@>= 0.3.2 < 0.4.0": version "0.3.2" resolved "https://registry.yarnpkg.com/cssom/-/cssom-0.3.2.tgz#b8036170c79f07a90ff2f16e22284027a243848b" @@ -8308,12 +7897,12 @@ debug@3.2.6, debug@3.X, debug@^3.0.0, debug@^3.1.0, debug@^3.2.6: dependencies: ms "^2.1.1" -debug@4, debug@^4.0.1, debug@~4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== +debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== dependencies: - ms "^2.1.1" + ms "2.1.2" debug@4.1.0: version "4.1.0" @@ -8322,12 +7911,12 @@ debug@4.1.0: dependencies: ms "^2.1.1" -debug@^4.1.0, debug@^4.1.1: - version "4.3.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" - integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== +debug@~4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== dependencies: - ms "2.1.2" + ms "^2.1.1" debuglog@^1.0.1: version "1.0.1" @@ -8364,59 +7953,6 @@ decompress-response@^3.2.0, decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" -decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - integrity sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ== - dependencies: - file-type "^5.2.0" - is-stream "^1.1.0" - tar-stream "^1.5.2" - -decompress-tarbz2@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - integrity sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A== - dependencies: - decompress-tar "^4.1.0" - file-type "^6.1.0" - is-stream "^1.1.0" - seek-bzip "^1.0.5" - unbzip2-stream "^1.0.9" - -decompress-targz@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" - integrity sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w== - dependencies: - decompress-tar "^4.1.1" - file-type "^5.2.0" - is-stream "^1.1.0" - -decompress-unzip@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - integrity sha1-3qrM39FK6vhVePczroIQ+bSEj2k= - dependencies: - file-type "^3.8.0" - get-stream "^2.2.0" - pify "^2.3.0" - yauzl "^2.4.2" - -decompress@^4.0.0, decompress@^4.2.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.1.tgz#007f55cc6a62c055afa37c07eb6a4ee1b773f118" - integrity sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ== - dependencies: - decompress-tar "^4.0.0" - decompress-tarbz2 "^4.0.0" - decompress-targz "^4.0.0" - decompress-unzip "^4.0.1" - graceful-fs "^4.1.10" - make-dir "^1.0.0" - pify "^2.3.0" - strip-dirs "^2.0.0" - dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" @@ -8429,13 +7965,6 @@ deep-eql@^0.1.3: dependencies: type-detect "0.1.1" -deep-eql@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" - integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== - dependencies: - type-detect "^4.0.0" - deep-equal@^1.0.0, deep-equal@^1.0.1, deep-equal@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" @@ -8648,15 +8177,6 @@ deprecated-decorator@^0.1.6: resolved "https://registry.yarnpkg.com/deprecated-decorator/-/deprecated-decorator-0.1.6.tgz#00966317b7a12fe92f3cc831f7583af329b86c37" integrity sha1-AJZjF7ehL+kvPMgx91g68ym4bDc= -deps-dump@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/deps-dump/-/deps-dump-1.1.0.tgz#13bcb20462b9e267adf4126e5b45d325f2408dd7" - integrity sha512-ZTUZxdYSMuZdQGhQFc2rTlpVGBBREH5XAGFpxtdgHCvNEw4KPr9nJu816HWdBMoBjS9m84/zytwys9i6uK41JQ== - dependencies: - clone "^2.1.2" - json-stable-stringify "^1.0.1" - through2 "^3.0.1" - deps-sort@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/deps-sort/-/deps-sort-2.0.0.tgz#091724902e84658260eb910748cccd1af6e21fb5" @@ -8667,17 +8187,6 @@ deps-sort@^2.0.0: subarg "^1.0.0" through2 "^2.0.0" -derequire@2.0.6, derequire@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/derequire/-/derequire-2.1.1.tgz#342527ff5a460d4dd6745085e4091a4697a6803c" - integrity sha512-5hGVgKAEGhSGZM02abtkwDzqEOXun1dP9Ocw0yh7Pz7j70k4SNk7WURm93YyHbs2PcieRyX8m4ta1glGakw84Q== - dependencies: - acorn "^7.1.1" - concat-stream "^1.4.6" - escope "^3.6.0" - through2 "^2.0.0" - yargs "^15.3.1" - des.js@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.0.tgz#c074d2e2aa6a8a9a07dbd61f9a15c2cd83ec8ecc" @@ -9010,7 +8519,7 @@ domutils@1.5.1: dom-serializer "0" domelementtype "1" -domutils@^1.5.1, domutils@^1.7.0: +domutils@^1.5.1: version "1.7.0" resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== @@ -9062,41 +8571,6 @@ dotenv@^8.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== -download@^6.2.2: - version "6.2.5" - resolved "https://registry.yarnpkg.com/download/-/download-6.2.5.tgz#acd6a542e4cd0bb42ca70cfc98c9e43b07039714" - integrity sha512-DpO9K1sXAST8Cpzb7kmEhogJxymyVUd5qz/vCOSyvwtp2Klj2XcDt5YUuasgxka44SxF0q5RriKIwJmQHG2AuA== - dependencies: - caw "^2.0.0" - content-disposition "^0.5.2" - decompress "^4.0.0" - ext-name "^5.0.0" - file-type "5.2.0" - filenamify "^2.0.0" - get-stream "^3.0.0" - got "^7.0.0" - make-dir "^1.0.0" - p-event "^1.0.0" - pify "^3.0.0" - -download@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/download/-/download-7.1.0.tgz#9059aa9d70b503ee76a132897be6dec8e5587233" - integrity sha512-xqnBTVd/E+GxJVrX5/eUJiLYjCGPwMpdL+jGhGU57BvtcA7wwhtHVbXBeUk51kOpW3S7Jn3BQbN9Q1R1Km2qDQ== - dependencies: - archive-type "^4.0.0" - caw "^2.0.1" - content-disposition "^0.5.2" - decompress "^4.2.0" - ext-name "^5.0.0" - file-type "^8.1.0" - filenamify "^2.0.0" - get-stream "^3.0.0" - got "^8.3.1" - make-dir "^1.2.0" - p-event "^2.1.0" - pify "^3.0.0" - downshift@^6.0.6: version "6.0.6" resolved "https://registry.yarnpkg.com/downshift/-/downshift-6.0.6.tgz#82aee8e2e260d7ad99df8a0969bd002dd523abe8" @@ -9174,11 +8648,6 @@ ecurve@^1.0.0, ecurve@^1.0.3: bigi "^1.1.0" safe-buffer "^5.0.1" -editions@^1.3.3: - version "1.3.4" - resolved "https://registry.yarnpkg.com/editions/-/editions-1.3.4.tgz#3662cb592347c3168eb8e498a0ff73271d67f50b" - integrity sha512-gzao+mxnYDzIysXKMQi/+M1mjy/rjestjg6OPoYTtI+3Izp23oiGZitsl9lPDPiTGXbcSIk1iJWhliSaglxnUg== - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -9566,12 +9035,7 @@ es6-map@^0.1.3, es6-map@^0.1.5: es6-symbol "~3.1.1" event-emitter "~0.3.5" -es6-promise@^4.0.3: - version "4.2.4" - resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.4.tgz#dc4221c2b16518760bd8c39a52d8f356fc00ed29" - integrity sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ== - -es6-promise@^4.2.8: +es6-promise@^4.0.3, es6-promise@^4.2.8: version "4.2.8" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== @@ -9632,7 +9096,7 @@ escape-html@^1.0.3, escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.3, escape-string-regexp@^1.0.5: +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= @@ -10238,14 +9702,7 @@ eth-rpc-errors@^3.0.0: dependencies: fast-safe-stringify "^2.0.6" -eth-rpc-errors@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-4.0.1.tgz#bb95cc6de85b59dcbd5453b661a9e99545eff550" - integrity sha512-BCx0QBS6eVM+KWleeChtYOUIKBbnUvM9amzMlenvJfMK4KA7gBA1zRpQsLf8e98VziuHcnqdCIX7YVw3DbbKkw== - dependencies: - fast-safe-stringify "^2.0.6" - -eth-rpc-errors@^4.0.2: +eth-rpc-errors@^4.0.0, eth-rpc-errors@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/eth-rpc-errors/-/eth-rpc-errors-4.0.2.tgz#11bc164e25237a679061ac05b7da7537b673d3b7" integrity sha512-n+Re6Gu8XGyfFy1it0AwbD1x0MUzspQs0D5UiPs1fFPCr6WAwZM+vbIhXheBFrpgosqN9bs5PqlB4Q61U/QytQ== @@ -10261,27 +9718,23 @@ eth-sig-util@^1.4.0, eth-sig-util@^1.4.2: ethereumjs-util "^5.1.1" eth-sig-util@^2.0.0, eth-sig-util@^2.4.4, eth-sig-util@^2.5.0: - version "2.5.3" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.5.3.tgz#6938308b38226e0b3085435474900b03036abcbe" - integrity sha512-KpXbCKmmBUNUTGh9MRKmNkIPietfhzBqqYqysDavLseIiMUGl95k6UcPEkALAZlj41e9E6yioYXc1PC333RKqw== + version "2.5.4" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.5.4.tgz#577b01fe491b6bf59b0464be09633e20c1677bc5" + integrity sha512-aCMBwp8q/4wrW4QLsF/HYBOSA7TpLKmkVwP3pYQNkEEseW2Rr8Z5Uxc9/h6HX+OG3tuHo+2bINVSihIeBfym6A== dependencies: - buffer "^5.2.1" - elliptic "^6.4.0" - ethereumjs-abi "0.6.5" + ethereumjs-abi "0.6.8" ethereumjs-util "^5.1.1" - tweetnacl "^1.0.0" + tweetnacl "^1.0.3" tweetnacl-util "^0.15.0" eth-sig-util@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.0.tgz#75133b3d7c20a5731af0690c385e184ab942b97e" - integrity sha512-4eFkMOhpGbTxBQ3AMzVf0haUX2uTur7DpWiHzWyTURa28BVJJtOkcb9Ok5TV0YvEPG61DODPW7ZUATbJTslioQ== + version "3.0.1" + resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-3.0.1.tgz#8753297c83a3f58346bd13547b59c4b2cd110c96" + integrity sha512-0Us50HiGGvZgjtWTyAI/+qTzYPMLy5Q451D0Xy68bxq1QMWdoOddDwGvsqcFT27uohKgalM9z/yxplyt+mY2iQ== dependencies: - buffer "^5.2.1" - elliptic "^6.4.0" - ethereumjs-abi "0.6.5" + ethereumjs-abi "^0.6.8" ethereumjs-util "^5.1.1" - tweetnacl "^1.0.0" + tweetnacl "^1.0.3" tweetnacl-util "^0.15.0" eth-simple-keyring@^3.5.0: @@ -10324,13 +9777,13 @@ eth-tx-summary@^3.1.2: through2 "^2.0.3" ethashjs@~0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.7.tgz#30bfe4196726690a0c59d3b8272e70d4d0c34bae" - integrity sha1-ML/kGWcmaQoMWdO4Jy5w1NDDS64= + version "0.0.8" + resolved "https://registry.yarnpkg.com/ethashjs/-/ethashjs-0.0.8.tgz#227442f1bdee409a548fb04136e24c874f3aa6f9" + integrity sha512-/MSbf/r2/Ld8o0l15AymjOTlPqpN8Cr4ByUEA9GtR4x0yAh3TdtDzEg29zMjXCNPI7u6E5fOQdj/Cf9Tc7oVNw== dependencies: - async "^1.4.2" - buffer-xor "^1.0.3" - ethereumjs-util "^4.0.1" + async "^2.1.2" + buffer-xor "^2.0.1" + ethereumjs-util "^7.0.2" miller-rabin "^4.0.0" ethereum-bloom-filters@^1.0.6: @@ -10376,15 +9829,7 @@ ethereum-ens-network-map@^1.0.0, ethereum-ens-network-map@^1.0.2: resolved "https://registry.yarnpkg.com/ethereum-ens-network-map/-/ethereum-ens-network-map-1.0.2.tgz#4e27bad18dae7bd95d84edbcac2c9e739fc959b9" integrity sha512-5qwJ5n3YhjSpE6O/WEBXCAb2nagUgyagJ6C0lGUBWC4LjKp/rRzD+pwtDJ6KCiITFEAoX4eIrWOjRy0Sylq5Hg== -ethereumjs-abi@0.6.5: - version "0.6.5" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" - integrity sha1-WmN+8Wq0NHP6cqKa2QhxQFs/UkE= - dependencies: - bn.js "^4.10.0" - ethereumjs-util "^4.3.0" - -ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.4, ethereumjs-abi@^0.6.5: +ethereumjs-abi@0.6.8, ethereumjs-abi@^0.6.4, ethereumjs-abi@^0.6.5, ethereumjs-abi@^0.6.8: version "0.6.8" resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.8.tgz#71bc152db099f70e62f108b7cdfca1b362c6fcae" integrity sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA== @@ -10505,17 +9950,6 @@ ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumj ethjs-util "0.1.6" rlp "^2.2.3" -ethereumjs-util@^4.0.1, ethereumjs-util@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" - integrity sha1-PpQosxfuvaPXJg2FT93alUsfG8Y= - dependencies: - bn.js "^4.8.0" - create-hash "^1.1.2" - keccakjs "^0.2.0" - rlp "^2.0.0" - secp256k1 "^3.0.1" - ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" @@ -10529,6 +9963,18 @@ ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereum safe-buffer "^5.1.1" secp256k1 "^3.0.1" +ethereumjs-util@^7.0.2: + version "7.0.8" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.8.tgz#5258762b7b17e3d828e41834948363ff0a703ffd" + integrity sha512-JJt7tDpCAmDPw/sGoFYeq0guOVqT3pTE9xlEbBmc/nlCij3JRCoS2c96SQ6kXVHOT3xWUNLDm5QCJLQaUnVAtQ== + dependencies: + "@types/bn.js" "^4.11.3" + bn.js "^5.1.2" + create-hash "^1.1.2" + ethereum-cryptography "^0.1.3" + ethjs-util "0.1.6" + rlp "^2.2.4" + ethereumjs-util@~6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.1.0.tgz#e9c51e5549e8ebd757a339cc00f5380507e799c8" @@ -10898,12 +10344,7 @@ events@^2.0.0: resolved "https://registry.yarnpkg.com/events/-/events-2.1.0.tgz#2a9a1e18e6106e0e812aa9ebd4a819b3c29c0ba5" integrity sha512-3Zmiobend8P9DjmKAty0Era4jV8oJ0yGYe2nJJAxgymF9+N8F2m0hhZiMoWtcfepExzNKZumFU3ksdQbInGWCg== -events@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" - integrity sha512-Dc381HFWJzEOhQ+d8pkNon++bk9h6cdAoAj4iE6Q4y6xgTzySWXlKn05/TVNpjnfRqi/X0EpJEJohPjNI3zpVA== - -events@^3.2.0: +events@^3.0.0, events@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/events/-/events-3.2.0.tgz#93b87c18f8efcd4202a461aec4dfc0556b639379" integrity sha512-/46HWwbfCX2xTawVfkKLGxMifJYQBWMwY1mjywRtb4c9x8l5NP3KoJtnIOiL1hfdRkIuYhETxQlo62IF8tcnlg== @@ -10916,17 +10357,6 @@ evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: md5.js "^1.3.4" safe-buffer "^5.1.1" -exec-buffer@^3.0.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/exec-buffer/-/exec-buffer-3.2.0.tgz#b1686dbd904c7cf982e652c1f5a79b1e5573082b" - integrity sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA== - dependencies: - execa "^0.7.0" - p-finally "^1.0.0" - pify "^3.0.0" - rimraf "^2.5.4" - tempfile "^2.0.0" - execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" @@ -10960,13 +10390,6 @@ execall@^2.0.0: dependencies: clone-regexp "^2.1.0" -executable@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c" - integrity sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg== - dependencies: - pify "^2.2.0" - exit-hook@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8" @@ -11052,21 +10475,6 @@ express@^4.13.3, express@^4.14.0, express@^4.17.0: utils-merge "1.0.1" vary "~1.1.2" -ext-list@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/ext-list/-/ext-list-2.2.2.tgz#0b98e64ed82f5acf0f2931babf69212ef52ddd37" - integrity sha512-u+SQgsubraE6zItfVA0tBuCBhfU9ogSRnsvygI7wht9TS510oLkBRXBsqopeUG/GBOIQyKZO9wjTqIu/sf5zFA== - dependencies: - mime-db "^1.28.0" - -ext-name@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/ext-name/-/ext-name-5.0.0.tgz#70781981d183ee15d13993c8822045c506c8f0a6" - integrity sha512-yblEwXAbGv1VQDmow7s38W77hzAgJAO50ztBLMcUyUBfxv1HC+LGwtiEN+Co6LtlqT/5uwVOxsD4TNIilWhwdQ== - dependencies: - ext-list "^2.0.0" - sort-keys-length "^1.0.0" - extend-shallow@^1.1.2: version "1.1.4" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-1.1.4.tgz#19d6bf94dfc09d76ba711f39b872d21ff4dd9071" @@ -11221,7 +10629,7 @@ fast-glob@^2.0.2, fast-glob@^2.2.6: merge2 "^1.2.3" micromatch "^3.1.10" -fast-glob@^3.0.3, fast-glob@^3.1.1, fast-glob@^3.2.2, fast-glob@^3.2.4: +fast-glob@^3.1.1, fast-glob@^3.2.2, fast-glob@^3.2.4: version "3.2.4" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== @@ -11354,14 +10762,6 @@ file-entry-cache@^5.0.1: dependencies: flat-cache "^2.0.1" -file-loader@^1.1.11: - version "1.1.11" - resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-1.1.11.tgz#6fe886449b0f2a936e43cabaac0cdbfb369506f8" - integrity sha512-TGR4HU7HUsGg6GCOPJnFk06RhWgEWFLAGWiT6rcD+GRC2keU3s9RGJ+b3Z6/U73jwwNb2gKLJ7YCrp+jvU4ALg== - dependencies: - loader-utils "^1.0.2" - schema-utils "^0.4.5" - file-loader@^6.0.0: version "6.2.0" resolved "https://registry.yarnpkg.com/file-loader/-/file-loader-6.2.0.tgz#baef7cf8e1840df325e4390b4484879480eebe4d" @@ -11379,42 +10779,12 @@ file-system-cache@^1.0.5: fs-extra "^0.30.0" ramda "^0.21.0" -file-type@5.2.0, file-type@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - integrity sha1-LdvqfHP/42No365J3DOMBYwritY= - -file-type@^10.4.0: - version "10.11.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-10.11.0.tgz#2961d09e4675b9fb9a3ee6b69e9cd23f43fd1890" - integrity sha512-uzk64HRpUZyTGZtVuvrjP0FYxzQrBf4rojot6J65YMEbwBLB0CWm0CLojVpwpmFmxcE/lkvYICgfcGozbBq6rw== - file-type@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-11.1.0.tgz#93780f3fed98b599755d846b99a1617a2ad063b8" integrity sha512-rM0UO7Qm9K7TWTtA6AShI/t7H5BPjDeGVDaNyg9BjHAj3PysKy7+8C8D137R88jnR3rFJZQB/tFgydl5sN5m7g== -file-type@^12.0.0: - version "12.3.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-12.3.0.tgz#74d755e5dc9c5cbc7ee6f182529b453906ac88c2" - integrity sha512-4E4Esq9KLwjYCY32E7qSmd0h7LefcniZHX+XcdJ4Wfx1uGJX7QCigiqw/U0yT7WOslm28yhxl87DJ0wHYv0RAA== - -file-type@^3.8.0: - version "3.9.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek= - -file-type@^4.2.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-4.4.0.tgz#1b600e5fca1fbdc6e80c0a70c71c8dba5f7906c5" - integrity sha1-G2AOX8ofvcboDApwxxyNul95BsU= - -file-type@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" - integrity sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg== - -file-type@^8.0.0, file-type@^8.1.0: +file-type@^8.0.0: version "8.1.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-8.1.0.tgz#244f3b7ef641bbe0cca196c7276e4b332399f68c" integrity sha512-qyQ0pzAy78gVoJsmYeNgl8uH8yKhr1lVhW7JbzJmnlRi0I4R2eEDEJZVKG8agpDnLpacwNbDhLNG/LMdxHD2YQ== @@ -11441,15 +10811,6 @@ filename-reserved-regex@^2.0.0: resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz#abf73dfab735d045440abfea2d91f389ebbfa229" integrity sha1-q/c9+rc10EVECr/qLZHzieu/oik= -filenamify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-2.1.0.tgz#88faf495fb1b47abfd612300002a16228c677ee9" - integrity sha512-ICw7NTT6RsDp2rnYKVd8Fu4cr6ITzGy3+u4vUujPkabyaz+03F24NWEX7fs5fp+kBonlaqPH8fAO2NM+SXt/JA== - dependencies: - filename-reserved-regex "^2.0.0" - strip-outer "^1.0.0" - trim-repeated "^1.0.0" - filenamify@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-4.2.0.tgz#c99716d676869585b3b5d328b3f06590d032e89f" @@ -11571,14 +10932,6 @@ find-up@^2.0.0, find-up@^2.1.0: dependencies: locate-path "^2.0.0" -find-versions@^3.0.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/find-versions/-/find-versions-3.1.0.tgz#10161f29cf3eb4350dec10a29bdde75bff0df32d" - integrity sha512-NCTfNiVzeE/xL+roNDffGuRbrWI6atI18lTJ22vKp7rs2OhYzMK3W1dIdO2TUndH/QMcacM4d1uWwgcZcHK69Q== - dependencies: - array-uniq "^2.1.0" - semver-regex "^2.0.0" - find-yarn-workspace-root@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/find-yarn-workspace-root/-/find-yarn-workspace-root-1.2.1.tgz#40eb8e6e7c2502ddfaa2577c176f221422f860db" @@ -11726,7 +11079,7 @@ for-in@^1.0.1, for-in@^1.0.2: resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= -for-own@^0.1.4: +for-own@^0.1.3, for-own@^0.1.4: version "0.1.5" resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" integrity sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4= @@ -11825,7 +11178,7 @@ fresh@0.5.2, fresh@~0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= -from2@^2.1.0, from2@^2.1.1: +from2@^2.1.0: version "2.3.0" resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= @@ -11955,7 +11308,7 @@ fsevents@^1.2.7: nan "^2.12.1" node-pre-gyp "^0.12.0" -fsevents@~2.1.1, fsevents@~2.1.2: +fsevents@~2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== @@ -12165,21 +11518,11 @@ get-folder-size@^2.0.0: gar "^1.0.4" tiny-each-async "2.0.3" -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= - get-iterator@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/get-iterator/-/get-iterator-1.0.2.tgz#cd747c02b4c084461fac14f48f6b45a80ed25c82" integrity sha512-v+dm9bNVfOYsY1OrhaCrmyOcYoSeVvbt+hHZ0Au+T+p1y+0Uyj9aMaGIeUTT6xdpRbWzDeYKvfOslPhggQMcsg== -get-own-enumerable-property-symbols@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz#5c4ad87f2834c4b9b4e84549dc1e0650fb38c24b" - integrity sha512-TtY/sbOemiMKPRUDDanGCSgBYe7Mf0vbRsWnBZ+9yghpZ1MvcpSpuZFjHdEeY/LZjZy0vdLjS77L6HosisFiug== - get-params@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/get-params/-/get-params-0.1.2.tgz#bae0dfaba588a0c60d7834c0d8dc2ff60eeef2fe" @@ -12190,13 +11533,6 @@ get-port@^5.1.0: resolved "https://registry.yarnpkg.com/get-port/-/get-port-5.1.0.tgz#a8f6510d0000f07d5c65653a4b0ae648fe832683" integrity sha512-bjioH1E9bTQUvgaB6VycVy1QVbTZI41yTnF9qkZz6ixgy/uhCH6D63bKeZ6Code/07JYA61MeI94jSdHss8PNA== -get-proxy@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/get-proxy/-/get-proxy-2.1.0.tgz#349f2b4d91d44c4d4d4e9cba2ad90143fac5ef93" - integrity sha512-zmZIaQTWnNQb4R4fJUEp/FC51eZsc6EkErspy3xtIYStaq8EB/hDIWipxsal+E8rz0qD7f2sL/NA9Xee4RInJw== - dependencies: - npm-conf "^1.1.0" - get-stdin@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe" @@ -12207,19 +11543,11 @@ get-stdin@^8.0.0: resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-8.0.0.tgz#cbad6a73feb75f6eeb22ba9e01f89aa28aa97a53" integrity sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg== -get-stream@3.0.0, get-stream@^3.0.0: +get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= -get-stream@^2.2.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" - integrity sha1-Xzj5PzRgCWZu4BUKBUFn+Rvdld4= - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - get-stream@^4.0.0, get-stream@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -12270,16 +11598,6 @@ gettext-parser@1.1.0: dependencies: encoding "^0.1.11" -gifsicle@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/gifsicle/-/gifsicle-4.0.1.tgz#30e1e61e3ee4884ef702641b2e98a15c2127b2e2" - integrity sha512-A/kiCLfDdV+ERV/UB+2O41mifd+RxH8jlRG8DMxZO84Bma/Fw0htqZ+hY2iaalLRNyUu7tYZQslqUBJxBggxbg== - dependencies: - bin-build "^3.0.0" - bin-wrapper "^4.0.0" - execa "^1.0.0" - logalot "^2.0.0" - git-up@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/git-up/-/git-up-4.0.1.tgz#cb2ef086653640e721d2042fe3104857d89007c0" @@ -12541,20 +11859,6 @@ globby@8.0.2: pify "^3.0.0" slash "^1.0.0" -globby@^10.0.0: - version "10.0.1" - resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" - integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== - dependencies: - "@types/glob" "^7.1.1" - array-union "^2.1.0" - dir-glob "^3.0.1" - fast-glob "^3.0.3" - glob "^7.1.3" - ignore "^5.1.1" - merge2 "^1.2.3" - slash "^3.0.0" - globby@^11.0.1: version "11.0.1" resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" @@ -12695,7 +11999,7 @@ got@^6.7.1: unzip-response "^2.0.1" url-parse-lax "^1.0.0" -got@^7.0.0, got@^7.1.0: +got@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" integrity sha512-Y5WMo7xKKq1muPsxD+KmrR8DH5auG7fBdDVueZwETwV6VytKyU9OX/ddpq2/1hp1vIPvVb4T81dKQz3BivkNLw== @@ -12715,44 +12019,11 @@ got@^7.0.0, got@^7.1.0: url-parse-lax "^1.0.0" url-to-options "^1.0.1" -got@^8.3.1: - version "8.3.2" - resolved "https://registry.yarnpkg.com/got/-/got-8.3.2.tgz#1d23f64390e97f776cac52e5b936e5f514d2e937" - integrity sha512-qjUJ5U/hawxosMryILofZCkm3C84PLJS/0grRIpjAwu+Lkxxj5cxeCU25BG0/3mDSpXKTyZr8oh8wIgLaH0QCw== - dependencies: - "@sindresorhus/is" "^0.7.0" - cacheable-request "^2.1.1" - decompress-response "^3.3.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - into-stream "^3.1.0" - is-retry-allowed "^1.1.0" - isurl "^1.0.0-alpha5" - lowercase-keys "^1.0.0" - mimic-response "^1.0.0" - p-cancelable "^0.4.0" - p-timeout "^2.0.1" - pify "^3.0.0" - safe-buffer "^5.1.1" - timed-out "^4.0.1" - url-parse-lax "^3.0.0" - url-to-options "^1.0.1" - -graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.9: - version "4.2.3" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" - integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== - -graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.3: +graceful-fs@4.X, graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.3: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw== -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - integrity sha1-TK+tdrxi8C+gObL5Tpo906ORpyU= - graphql-extensions@^0.0.x, graphql-extensions@~0.0.9: version "0.0.10" resolved "https://registry.yarnpkg.com/graphql-extensions/-/graphql-extensions-0.0.10.tgz#34bdb2546d43f6a5bc89ab23c295ec0466c6843d" @@ -12815,16 +12086,6 @@ gulp-autoprefixer@^5.0.0: through2 "^2.0.0" vinyl-sourcemaps-apply "^0.2.0" -gulp-babel@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/gulp-babel/-/gulp-babel-8.0.0.tgz#e0da96f4f2ec4a88dd3a3030f476e38ab2126d87" - integrity sha512-oomaIqDXxFkg7lbpBou/gnUkX51/Y/M2ZfSjL2hdqXTAlSWZcgZtd2o0cOH0r/eE8LWD0+Q/PsLsr2DKOoqToQ== - dependencies: - plugin-error "^1.0.1" - replace-ext "^1.0.0" - through2 "^2.0.0" - vinyl-sourcemaps-apply "^0.2.0" - gulp-cli@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/gulp-cli/-/gulp-cli-2.3.0.tgz#ec0d380e29e52aa45e47977f0d32e18fd161122f" @@ -12849,36 +12110,6 @@ gulp-cli@^2.2.0: v8flags "^3.2.0" yargs "^7.1.0" -gulp-debug@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/gulp-debug/-/gulp-debug-3.2.0.tgz#45aba4439fa79fe0788f6a411ee0778f4492dfa5" - integrity sha512-2LZzP+ydczqz1rhqq/NYxvVvYTmOa0IgBl2B1sQTdkQgku9ayOUM/KHuGPjF4QA5aO1VcG+Sskw7iCcRUqHKkA== - dependencies: - chalk "^2.3.0" - fancy-log "^1.3.2" - plur "^2.0.0" - stringify-object "^3.0.0" - through2 "^2.0.0" - tildify "^1.1.2" - -gulp-imagemin@^6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/gulp-imagemin/-/gulp-imagemin-6.1.0.tgz#d1f1cb17b930da6424c1994388bada2355bc4295" - integrity sha512-0TPkak5BsiRfw+kfcKwIcODbOHHcTyvBM9arlRSwXdUVzrGAcq/7urZoOQD5n4uWvKhjg+l9/yn1GDZsDuWUow== - dependencies: - chalk "^2.4.1" - fancy-log "^1.3.2" - imagemin "^7.0.0" - plugin-error "^1.0.1" - plur "^3.0.1" - pretty-bytes "^5.3.0" - through2-concurrent "^2.0.0" - optionalDependencies: - imagemin-gifsicle "^6.0.1" - imagemin-jpegtran "^6.0.0" - imagemin-optipng "^7.0.0" - imagemin-svgo "^7.0.0" - gulp-livereload@4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/gulp-livereload/-/gulp-livereload-4.0.0.tgz#be4a6b01731a93f76f4fb29c9e62e323affe7d03" @@ -12892,27 +12123,11 @@ gulp-livereload@4.0.0: tiny-lr "^1.1.1" vinyl "^2.2.0" -gulp-multi-process@^1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/gulp-multi-process/-/gulp-multi-process-1.3.1.tgz#e12aa818e4c234357ad99d5caff8df8a18f46e9e" - integrity sha512-okxYy3mxUkekM0RNjkBg8OPuzpnD2yXMAdnGOaQPSJ2wzBdE9R9pkTV+tzPZ65ORK7b57YUc6s+gROA4+EIOLg== - dependencies: - async.queue "^0.5.2" - gulp-rename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/gulp-rename/-/gulp-rename-2.0.0.tgz#9bbc3962b0c0f52fc67cd5eaff6c223ec5b9cf6c" integrity sha512-97Vba4KBzbYmR5VBs9mWmK+HwIf5mj+/zioxfZhOKeXtx5ZjBk57KFlePf5nxq9QsTtFl0ejnHE3zTC9MHXqyQ== -gulp-replace@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/gulp-replace/-/gulp-replace-1.0.0.tgz#b32bd61654d97b8d78430a67b3e8ce067b7c9143" - integrity sha512-lgdmrFSI1SdhNMXZQbrC75MOl1UjYWlOWNbNRnz+F/KHmgxt3l6XstBoAYIdadwETFyG/6i+vWUSCawdC3pqOw== - dependencies: - istextorbinary "2.2.1" - readable-stream "^2.0.1" - replacestream "^4.0.0" - gulp-rtlcss@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/gulp-rtlcss/-/gulp-rtlcss-1.4.0.tgz#a1e4caef39182af03778cb9c18add9d3ee5e1c97" @@ -13053,14 +12268,6 @@ har-schema@^2.0.0: resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= -har-validator@~5.1.0: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== - dependencies: - ajv "^6.5.5" - har-schema "^2.0.0" - har-validator@~5.1.3: version "5.1.5" resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" @@ -13336,11 +12543,6 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.5.0.tgz#6d60e34b3abbc8313062c3b798ef8d901a07af3c" integrity sha512-pNgbURSuab90KbTqvRPsseaTxOJCZBD0a7t+haSN33piP9cCM4l0CqdzAif2hUqm716UovKB2ROmiabGAKVXyg== -html-comment-regex@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" - integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== - html-element-map@^1.0.0: version "1.2.0" resolved "https://registry.yarnpkg.com/html-element-map/-/html-element-map-1.2.0.tgz#dfbb09efe882806af63d990cf6db37993f099f22" @@ -13398,7 +12600,7 @@ html-webpack-plugin@^4.2.1: tapable "^1.1.3" util.promisify "1.0.0" -htmlescape@^1.1.0: +htmlescape@^1.1.0, htmlescape@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/htmlescape/-/htmlescape-1.1.1.tgz#3a03edc2214bca3b66424a3e7959349509cb0351" integrity sha1-OgPtwiFLyjtmQko+eVk0lQnLA1E= @@ -13423,11 +12625,6 @@ http-assert@^1.3.0: deep-equal "~1.0.1" http-errors "~1.7.2" -http-cache-semantics@3.8.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-3.8.1.tgz#39b0e16add9b605bf0a9ef3d9daaf4843b4cacd2" - integrity sha512-5ai2iksyV8ZXmnZhHH4rWPoxxistEexSi5936zIQ1bnNTW5VnA85B6P/VpXiRM017IgRvb2kKo1a//y+0wSp3w== - http-cache-semantics@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390" @@ -13630,53 +12827,6 @@ ignore@^5.1.1, ignore@^5.1.4, ignore@^5.1.8: resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== -imagemin-gifsicle@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/imagemin-gifsicle/-/imagemin-gifsicle-6.0.1.tgz#6abad4e95566d52e5a104aba1c24b4f3b48581b3" - integrity sha512-kuu47c6iKDQ6R9J10xCwL0lgs0+sMz3LRHqRcJ2CRBWdcNmo3T5hUaM8hSZfksptZXJLGKk8heSAvwtSdB1Fng== - dependencies: - exec-buffer "^3.0.0" - gifsicle "^4.0.0" - is-gif "^3.0.0" - -imagemin-jpegtran@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/imagemin-jpegtran/-/imagemin-jpegtran-6.0.0.tgz#c8d3bcfb6ec9c561c20a987142854be70d90b04f" - integrity sha512-Ih+NgThzqYfEWv9t58EItncaaXIHR0u9RuhKa8CtVBlMBvY0dCIxgQJQCfwImA4AV1PMfmUKlkyIHJjb7V4z1g== - dependencies: - exec-buffer "^3.0.0" - is-jpg "^2.0.0" - jpegtran-bin "^4.0.0" - -imagemin-optipng@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/imagemin-optipng/-/imagemin-optipng-7.0.0.tgz#7680359bcf254bb85bbe87e727d1bdfc03491b1d" - integrity sha512-N40bmLgiyv5H8xFp/RYmWKdg6Z19MGqzcNW+IWXG7VPrLV75NbcOn8y6A7eZcSHOCNW+DqBx+b95yw+Tf6Sl/g== - dependencies: - exec-buffer "^3.0.0" - is-png "^2.0.0" - optipng-bin "^6.0.0" - -imagemin-svgo@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/imagemin-svgo/-/imagemin-svgo-7.0.0.tgz#a22d0a5917a0d0f37e436932c30f5e000fa91b1c" - integrity sha512-+iGJFaPIMx8TjFW6zN+EkOhlqcemdL7F3N3Y0wODvV2kCUBuUtZK7DRZc1+Zfu4U2W/lTMUyx2G8YMOrZntIWg== - dependencies: - is-svg "^3.0.0" - svgo "^1.0.5" - -imagemin@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/imagemin/-/imagemin-7.0.0.tgz#48651ab86c1975157306e3a18f8994814db085ff" - integrity sha512-TXvCSSIYl4KQUASur9S0+E4olVECzvxvZABU9rNqsza7vzIrUQMRTjyczGf8OmtcgvZ9jOYyinXW3epOpd/04A== - dependencies: - file-type "^12.0.0" - globby "^10.0.0" - junk "^3.1.0" - make-dir "^3.0.0" - p-pipe "^3.0.0" - replace-ext "^1.0.0" - immediate@^3.2.3, immediate@~3.2.3: version "3.2.3" resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" @@ -13692,7 +12842,7 @@ immer@1.10.0: resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg== -immer@^8.0.0: +immer@^8.0.0, immer@^8.0.1: version "8.0.1" resolved "https://registry.yarnpkg.com/immer/-/immer-8.0.1.tgz#9c73db683e2b3975c424fb0572af5889877ae656" integrity sha512-aqXhGP7//Gui2+UrEtvxZxSquQVXTpZ7KDxfCcKAF3Vysvw0CViVaW9RZ1j1xlIYqaaaipBoqdqeibkc18PNvA== @@ -13724,11 +12874,6 @@ import-lazy@^2.1.0: resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= -import-lazy@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-3.1.0.tgz#891279202c8a2280fdbd6674dbd8da1a1dfc67cc" - integrity sha512-8/gvXvX2JMn0F+CDlSC4l6kOmVaLOO3XLkksI7CI3Ud95KDYJuYur2b9P/PUt/i/pDAMd/DulQsNbbbmRRsDIQ== - import-lazy@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" @@ -13794,16 +12939,11 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ini@^1.3.4: +ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.8" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -ini@^1.3.5, ini@~1.3.0: - version "1.3.7" - resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.7.tgz#a09363e1911972ea16d7a8851005d84cf09a9a84" - integrity sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ== - inline-source-map@~0.6.0: version "0.6.2" resolved "https://registry.yarnpkg.com/inline-source-map/-/inline-source-map-0.6.2.tgz#f9393471c18a79d1724f863fa38b586370ade2a5" @@ -13941,14 +13081,6 @@ interpret@^2.0.0: resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.0.0.tgz#b783ffac0b8371503e9ab39561df223286aa5433" integrity sha512-e0/LknJ8wpMMhTiWcjivB+ESwIuvHnBSlBbmP/pSb8CQJldoj1p2qv7xGZ/+BtbTziYRFSz8OsvdbiX45LtYQA== -into-stream@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-3.1.0.tgz#96fb0a936c12babd6ff1752a17d05616abd094c6" - integrity sha1-lvsKk2wSur1v8XUqF9BWFqvQlMY= - dependencies: - from2 "^2.1.1" - p-is-promise "^1.1.0" - invariant@2.2.4, invariant@^2.0.0, invariant@^2.1.0, invariant@^2.2.2, invariant@^2.2.3, invariant@^2.2.4: version "2.2.4" resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" @@ -14527,16 +13659,6 @@ ipns@~0.5.2: protons "^1.0.1" timestamp-nano "^1.0.0" -irregular-plurals@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-1.4.0.tgz#2ca9b033651111855412f16be5d77c62a458a766" - integrity sha1-LKmwM2UREYVUEvFr5dd8YqRYp2Y= - -irregular-plurals@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/irregular-plurals/-/irregular-plurals-2.0.0.tgz#39d40f05b00f656d0b7fa471230dd3b714af2872" - integrity sha512-Y75zBYLkh0lJ9qxeHlMjQ7bSbyiSqNW/UOPWDmzC7cXskL1hekSITh1Oc6JV0XCWWZ9DE8VYSB71xocLk3gmGw== - is-absolute@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-absolute/-/is-absolute-1.0.0.tgz#395e1ae84b11f26ad1795e73c17378e48a301576" @@ -14606,7 +13728,7 @@ is-boolean-object@^1.0.0: resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.0.0.tgz#98f8b28030684219a95f375cfbd88ce3405dff93" integrity sha1-mPiygDBoQhmpXzdc+9iM40Bd/5M= -is-buffer@^1.1.0, is-buffer@^1.1.5, is-buffer@~1.1.6: +is-buffer@^1.0.2, is-buffer@^1.1.0, is-buffer@^1.1.5, is-buffer@~1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -14647,6 +13769,13 @@ is-core-module@^2.0.0: dependencies: has "^1.0.3" +is-core-module@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.1.0.tgz#a4cc031d9b1aca63eecbd18a650e13cb4eeab946" + integrity sha512-YcV7BgVMRFRua2FqQzKtTDMz8iCuLEyGKjr70q8Zm1yy2qKcurbFEd79PAdHV77oL3NrAaOVQIbMmiHQCHB7ZA== + dependencies: + has "^1.0.3" + is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" @@ -14785,13 +13914,6 @@ is-generator-function@^1.0.7: resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522" integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw== -is-gif@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-gif/-/is-gif-3.0.0.tgz#c4be60b26a301d695bb833b20d9b5d66c6cf83b1" - integrity sha512-IqJ/jlbw5WJSNfwQ/lHEDXF8rxhRgF6ythk2oiEvhpG29F704eX9NO6TvPfMiq9DrbwgcEDnETYNcZDPewQoVw== - dependencies: - file-type "^10.4.0" - is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" @@ -14865,11 +13987,6 @@ is-ipfs@~0.6.1: multibase "~0.6.0" multihashes "~0.4.13" -is-jpg@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-jpg/-/is-jpg-2.0.0.tgz#2e1997fa6e9166eaac0242daae443403e4ef1d97" - integrity sha1-LhmX+m6RZuqsAkLarkQ0A+TvHZc= - is-mergeable-object@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/is-mergeable-object/-/is-mergeable-object-1.1.1.tgz#faaa3ed1cfce87d6f7d2f5885e92cc30af3e2ebf" @@ -14891,11 +14008,6 @@ is-my-json-valid@^2.10.0: jsonpointer "^4.0.0" xtend "^4.0.0" -is-natural-number@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - integrity sha1-q5124dtM7VHjXeDHLr7PCfc0zeg= - is-negated-glob@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" @@ -14945,11 +14057,6 @@ is-number@^7.0.0: resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-obj@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" - integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= - is-obj@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" @@ -15022,11 +14129,6 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-png@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-png/-/is-png-2.0.0.tgz#ee8cbc9e9b050425cedeeb4a6fb74a649b0a4a8d" - integrity sha512-4KPGizaVGj2LK7xwJIz8o5B2ubu1D/vcQsgOGFEDlpcvgZHto4gBnyd0ig7Ws+67ixmwKoNmu0hYnpo6AaKb5g== - is-posix-bracket@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" @@ -15069,11 +14171,6 @@ is-regex@^1.0.4, is-regex@^1.1.1: dependencies: has-symbols "^1.0.1" -is-regexp@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" - integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= - is-regexp@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-2.1.0.tgz#cd734a56864e23b956bf4e7c66c396a4c0b22c2d" @@ -15128,13 +14225,6 @@ is-subset@^0.1.1: resolved "https://registry.yarnpkg.com/is-subset/-/is-subset-0.1.1.tgz#8a59117d932de1de00f245fcdd39ce43f1e939a6" integrity sha1-ilkRfZMt4d4A8kX83TnOQ/HpOaY= -is-svg@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" - integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== - dependencies: - html-comment-regex "^1.1.0" - is-symbol@^1.0.2, is-symbol@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" @@ -15350,17 +14440,8 @@ istanbul-reports@^3.0.0: resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.0.0.tgz#d4d16d035db99581b6194e119bbf36c963c5eb70" integrity sha512-2osTcC8zcOSUkImzN2EWQta3Vdi4WjjKw99P2yWx5mLnigAM0Rd5uYFn1cf2i/Ois45GkNjaoTqc5CxgMSX80A== dependencies: - html-escaper "^2.0.0" - istanbul-lib-report "^3.0.0" - -istextorbinary@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/istextorbinary/-/istextorbinary-2.2.1.tgz#a5231a08ef6dd22b268d0895084cf8d58b5bec53" - integrity sha512-TS+hoFl8Z5FAFMK38nhBkdLt44CclNRgDHWeMgsV8ko3nDlr/9UI2Sf839sW7enijf8oKsZYXRvM8g0it9Zmcw== - dependencies: - binaryextensions "2" - editions "^1.3.3" - textextensions "2" + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" isurl@^1.0.0-alpha5: version "1.0.0" @@ -15414,15 +14495,6 @@ join-component@^1.1.0: resolved "https://registry.yarnpkg.com/join-component/-/join-component-1.1.0.tgz#b8417b750661a392bee2c2537c68b2a9d4977cd5" integrity sha1-uEF7dQZho5K+4sJTfGiyqdSXfNU= -jpegtran-bin@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jpegtran-bin/-/jpegtran-bin-4.0.0.tgz#d00aed809fba7aa6f30817e59eee4ddf198f8f10" - integrity sha512-2cRl1ism+wJUoYAYFt6O/rLBfpXNWG2dUWbgcEkTt5WGMnqI46eEro8T4C5zGROxKRqyKpCBSdHPvt5UYCtxaQ== - dependencies: - bin-build "^3.0.0" - bin-wrapper "^4.0.0" - logalot "^2.0.0" - js-base64@^2.1.8: version "2.4.3" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.4.3.tgz#2e545ec2b0f2957f41356510205214e98fad6582" @@ -15923,7 +14995,7 @@ keccak@^1.0.2: nan "^2.2.1" safe-buffer "^5.1.0" -keccakjs@^0.2.0, keccakjs@^0.2.1: +keccakjs@^0.2.1: version "0.2.3" resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.3.tgz#5e4e969ce39689a3861f445d7752ee3477f9fe72" integrity sha512-BjLkNDcfaZ6l8HBG9tH0tpmDv3sS2mA7FNQxFHpCdzP3Gb2MVruXBSuoM66SnVxKJpAr5dKGdkHD+bDokt8fTg== @@ -15943,13 +15015,6 @@ keypair@^1.0.1: resolved "https://registry.yarnpkg.com/keypair/-/keypair-1.0.1.tgz#7603719270afb6564ed38a22087a06fc9aa4ea1b" integrity sha1-dgNxknCvtlZO04oiCHoG/Jqk6hs= -keyv@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" - integrity sha512-eguHnq22OE3uVoSYG0LVWNP+4ppamWr9+zWBe1bsNcovIMy6huUJFPgy4mGwCd/rnl3vOLGW1MTlu4c57CT1xA== - dependencies: - json-buffer "3.0.0" - keyv@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9" @@ -15962,6 +15027,13 @@ kind-of@^1.1.0: resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-1.1.0.tgz#140a3d2d41a36d2efcfa9377b62c24f8495a5c44" integrity sha1-FAo9LUGjbS78+pN3tiwk+ElaXEQ= +kind-of@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-2.0.1.tgz#018ec7a4ce7e3a86cb9141be519d24c8faa981b5" + integrity sha1-AY7HpM5+OobLkUG+UZ0kyPqpgbU= + dependencies: + is-buffer "^1.0.2" + kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" @@ -16121,6 +15193,63 @@ latest-version@^5.0.0: dependencies: package-json "^6.3.0" +lavamoat-core@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/lavamoat-core/-/lavamoat-core-9.0.1.tgz#a34a822b4bfabea38f73b7f9bc1a19f86baa9b1f" + integrity sha512-FqqasOjl3V6CX/ETniw59r20ukcydOtFhQxtwl6TIEuSc5CJJgY5y9Fi3adk5BTxml3JUMsR3dtygFOV3NuBBw== + dependencies: + fromentries "^1.2.0" + json-stable-stringify "^1.0.1" + lavamoat-tofu "^5.1.1" + merge-deep "^3.0.2" + resolve "^1.15.1" + +lavamoat-tofu@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lavamoat-tofu/-/lavamoat-tofu-5.1.1.tgz#67d3c5775b587dd439c426f1cd86650b10443760" + integrity sha512-LIZTifbbTATA5UClVGI7YGMTOjUXjrVCBOz0DaeUicldLonLlwG81/53/vTIfPM1xV/KA85MIzGPHz4pDdiVkA== + dependencies: + "@babel/parser" "^7.10.1" + "@babel/traverse" "^7.10.1" + +lavamoat-viz@^6.0.4: + version "6.0.4" + resolved "https://registry.yarnpkg.com/lavamoat-viz/-/lavamoat-viz-6.0.4.tgz#00b132cef06c24a6836044842548438e0c144059" + integrity sha512-LqSNLLTtodZUCxFihGCFrVVEBBICEs79hu2fSJGZFxe8I+R6FNcKmBMVAwpAuPj9dpKJmvckTi2sP8osZX8KCw== + dependencies: + lavamoat-core "^9.0.1" + ncp "^2.0.0" + open "^7.0.3" + pify "^4.0.1" + serve-handler "^6.1.3" + yargs "^16.0.0" + +lavamoat@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/lavamoat/-/lavamoat-5.1.4.tgz#211ea0bb2dfaf624f2f5d85a90d6c93b9c1da599" + integrity sha512-NaD8Jyt4OVO2euP8XVnlJuDsAO1Tfdt5Mg4wNwms+E8fe/a6mvH6kQncr1O/X42ky9u29+m2NinFMCQKmd8fQw== + dependencies: + "@babel/code-frame" "^7.10.4" + bindings "^1.5.0" + htmlescape "^1.1.1" + json-stable-stringify "^1.0.1" + lavamoat-core "^9.0.1" + lavamoat-tofu "^5.1.1" + node-gyp-build "^4.2.3" + object.fromentries "^2.0.2" + resolve "^1.17.0" + yargs "^16.0.0" + +lazy-cache@^0.2.3: + version "0.2.7" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-0.2.7.tgz#7feddf2dcb6edb77d11ef1d117ab5ffdf0ab1b65" + integrity sha1-f+3fLctu23fRHvHRF6tf/fCrG2U= + +lazy-cache@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-1.0.4.tgz#a1d78fc3a50474cb80845d3b3b6e1da49a446e8e" + integrity sha1-odePw6UEdMuAhF07O24dpJpEbo4= + lazy-universal-dotenv@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/lazy-universal-dotenv/-/lazy-universal-dotenv-3.0.1.tgz#a6c8938414bca426ab8c9463940da451a911db38" @@ -17133,14 +16262,6 @@ log-symbols@^4.0.0: dependencies: chalk "^4.0.0" -logalot@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/logalot/-/logalot-2.1.0.tgz#5f8e8c90d304edf12530951a5554abb8c5e3f552" - integrity sha1-X46MkNME7fElMJUaVVSruMXj9VI= - dependencies: - figures "^1.3.5" - squeak "^1.0.0" - loglevel@^1.4.1, loglevel@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.0.tgz#ae0caa561111498c5ba13723d6fb631d24003934" @@ -17174,11 +16295,6 @@ longest-streak@^2.0.1: resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.3.tgz#3de7a3f47ee18e9074ded8575b5c091f5d0a4105" integrity sha512-9lz5IVdpwsKLMzQi0MQ+oD9EA0mIGcWYP7jXMTZVXP8D42PwuAk+M/HBFYQoxt1G5OR8m7aSIgb1UymfWGBWEw== -longest@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097" - integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc= - looper@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/looper/-/looper-2.0.0.tgz#66cd0c774af3d4fedac53794f742db56da8f09ec" @@ -17216,11 +16332,6 @@ lower-case@^2.0.1: dependencies: tslib "^1.10.0" -lowercase-keys@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.0.tgz#4e3366b39e7f5457e35f1324bdf6f88d0bfc7306" - integrity sha1-TjNms55/VFfjXxMkvfb4jQv8cwY= - lowercase-keys@^1.0.0, lowercase-keys@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" @@ -17239,16 +16350,6 @@ lowlight@^1.14.0: fault "^1.0.0" highlight.js "~10.4.0" -lpad-align@^1.0.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/lpad-align/-/lpad-align-1.1.2.tgz#21f600ac1c3095c3c6e497ee67271ee08481fe9e" - integrity sha1-IfYArBwwlcPG5JfuZyce4ISB/p4= - dependencies: - get-stdin "^4.0.1" - indent-string "^2.1.0" - longest "^1.0.0" - meow "^3.3.0" - lru-cache@4.1.x, lru-cache@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.1.tgz#622e32e82488b49279114a4f9ecf45e7cd6bba55" @@ -17321,7 +16422,7 @@ magic-string@0.25.1: dependencies: sourcemap-codec "^1.4.1" -make-dir@^1.0.0, make-dir@^1.2.0: +make-dir@^1.0.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== @@ -17473,16 +16574,6 @@ mdn-browser-compat-data@0.0.94: dependencies: extend "3.0.2" -mdn-data@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" - integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== - -mdn-data@~1.1.0: - version "1.1.4" - resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-1.1.4.tgz#50b5d4ffc4575276573c4eedb8780812a8419f01" - integrity sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA== - media-typer@0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" @@ -17572,7 +16663,7 @@ memory-fs@^0.5.0: errno "^0.1.3" readable-stream "^2.0.1" -meow@^3.3.0, meow@^3.7.0: +meow@^3.7.0: version "3.7.0" resolved "https://registry.yarnpkg.com/meow/-/meow-3.7.0.tgz#72cb668b425228290abbfa856892587308a801fb" integrity sha1-cstmi0JSKCkKu/qFaJJYcwioAfs= @@ -17607,6 +16698,15 @@ meow@^7.0.1: type-fest "^0.13.1" yargs-parser "^18.1.3" +merge-deep@^3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/merge-deep/-/merge-deep-3.0.3.tgz#1a2b2ae926da8b2ae93a0ac15d90cd1922766003" + integrity sha512-qtmzAS6t6grwEkNrunqTBdn0qKwFgNWvlxUbAV8es9M7Ot1EbyApytCnvE0jALPa46ZpKDUo527kKiaWplmlFA== + dependencies: + arr-union "^3.1.0" + clone-deep "^0.2.4" + kind-of "^3.0.2" + merge-descriptors@1.0.1, merge-descriptors@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" @@ -17737,12 +16837,7 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -mime-db@1.44.0, mime-db@1.x.x, mime-db@^1.28.0: - version "1.44.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" - integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== - -mime-db@1.45.0: +mime-db@1.45.0, mime-db@1.x.x: version "1.45.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.45.0.tgz#cceeda21ccd7c3a745eba2decd55d4b73e7879ea" integrity sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w== @@ -17759,14 +16854,7 @@ mime-types@2.1.18: dependencies: mime-db "~1.33.0" -mime-types@^2.1.12, mime-types@^2.1.16, mime-types@^2.1.18, mime-types@^2.1.21, mime-types@^2.1.27, mime-types@~2.1.19: - version "2.1.27" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" - integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== - dependencies: - mime-db "1.44.0" - -mime-types@~2.1.24: +mime-types@^2.1.12, mime-types@^2.1.16, mime-types@^2.1.18, mime-types@^2.1.21, mime-types@^2.1.27, mime-types@~2.1.19, mime-types@~2.1.24: version "2.1.28" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.28.tgz#1160c4757eab2c5363888e005273ecf79d2a0ecd" integrity sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ== @@ -18076,12 +17164,12 @@ ms@2.1.1: resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== -ms@2.1.2, ms@^2.0.0: +ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.1.1: +ms@^2.0.0, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -18341,6 +17429,11 @@ ncom@^1.0.2: dependencies: sc-formatter "~3.0.1" +ncp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ncp/-/ncp-2.0.0.tgz#195a21d6c46e361d2fb1281ba38b91e9df7bdbb3" + integrity sha1-GVoh1sRuNh0vsSgbo4uR6d9727M= + "ndjson@github:hugomrdias/ndjson#feat/readable-stream3": version "1.5.0" resolved "https://codeload.github.com/hugomrdias/ndjson/tar.gz/4db16da6b42e5b39bf300c3a7cde62abb3fa3a11" @@ -18375,12 +17468,7 @@ negotiator@0.6.2: resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -neo-async@^2.5.0, neo-async@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" - integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== - -neo-async@^2.6.2: +neo-async@^2.5.0, neo-async@^2.6.1, neo-async@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== @@ -18483,7 +17571,7 @@ node-forge@^0.10.0, node-forge@^0.7.1, node-forge@^0.7.5, node-forge@~0.7.6: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.10.0.tgz#32dea2afb3e9926f02ee5ce8794902691a676bf3" integrity sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA== -node-gyp-build@^4.2.0: +node-gyp-build@^4.2.0, node-gyp-build@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.3.tgz#ce6277f853835f718829efb47db20f3e4d9c4739" integrity sha512-MN6ZpzmfNCRM+3t57PTJHgHyw/h4OWnZ6mR8P5j/uZtqQr46RRuDE/P+g3n0YR/AiYXeWixZZzaip77gdICfRg== @@ -18746,15 +17834,6 @@ normalize-selector@^0.2.0: resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= -normalize-url@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" - integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw== - dependencies: - prepend-http "^2.0.0" - query-string "^5.0.1" - sort-keys "^2.0.0" - normalize-url@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" @@ -18777,7 +17856,7 @@ npm-bundled@^1.0.1: resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.6.tgz#e7ba9aadcef962bb61248f91721cd932b3fe6bdd" integrity sha512-8/JCaftHwbd//k6y2rEWp6k1wxVfpFzB6t1p825+cUb7Ym2XQfhwIC5KwhrvzZRJu+LtDE585zVaS32+CGtf0g== -npm-conf@^1.1.0, npm-conf@^1.1.3: +npm-conf@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/npm-conf/-/npm-conf-1.1.3.tgz#256cc47bd0e218c259c4e9550bf413bc2192aff9" integrity sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw== @@ -18820,7 +17899,7 @@ npm-run-path@^2.0.0: gauge "~2.7.3" set-blocking "~2.0.0" -nth-check@^1.0.2, nth-check@~1.0.1: +nth-check@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== @@ -19176,15 +18255,6 @@ options@>=0.0.5: resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f" integrity sha1-7CLTEoBrtT5zF3Pnza788cZDEo8= -optipng-bin@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/optipng-bin/-/optipng-bin-6.0.0.tgz#376120fa79d5e71eee2f524176efdd3a5eabd316" - integrity sha512-95bB4y8IaTsa/8x6QH4bLUuyvyOoGBCLDA7wOgDL8UFqJpSUh1Hob8JRJhit+wC1ZLN3tQ7mFt7KuBj0x8F2Wg== - dependencies: - bin-build "^3.0.0" - bin-wrapper "^4.0.0" - logalot "^2.0.0" - optjs@latest: version "3.2.2" resolved "https://registry.yarnpkg.com/optjs/-/optjs-3.2.2.tgz#69a6ce89c442a44403141ad2f9b370bd5bb6f4ee" @@ -19339,13 +18409,6 @@ os-browserify@^0.3.0, os-browserify@~0.3.0: resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= -os-filter-obj@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/os-filter-obj/-/os-filter-obj-2.0.0.tgz#1c0b62d5f3a2442749a2d139e6dddee6e81d8d16" - integrity sha512-uksVLsqG3pVdzzPvmAHpBK0wKxYItuzZr7SziusRPoz67tGV8rL1szZ6IdeUrbqLjGDwApBtN29eEE3IqGHOjg== - dependencies: - arch "^2.1.0" - os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" @@ -19413,11 +18476,6 @@ p-cancelable@^0.3.0: resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.3.0.tgz#b9e123800bcebb7ac13a479be195b507b98d30fa" integrity sha512-RVbZPLso8+jFeq1MfNvgXtCRED2raz/dKpacfTNxsx6pLEpEomM7gah6VeHSYV3+vo0OAi4MkArtQcWWXuQoyw== -p-cancelable@^0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-0.4.1.tgz#35f363d67d52081c8d9585e37bcceb7e0bbcb2a0" - integrity sha512-HNa1A8LvB1kie7cERyy21VNeHb2CWJJYqyyC2o3klWFfMGlFmWv2Z7sFgZH8ZiaYL95ydToKTFVXgMV/Os0bBQ== - p-cancelable@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc" @@ -19440,20 +18498,6 @@ p-each-series@^2.1.0: resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48" integrity sha512-ZuRs1miPT4HrjFa+9fRfOFXxGJfORgelKV9f9nNOWw2gl6gVsRaVDOQP0+MI0G0wGKns1Yacsu0GjOFbTK0JFQ== -p-event@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-event/-/p-event-1.3.0.tgz#8e6b4f4f65c72bc5b6fe28b75eda874f96a4a085" - integrity sha1-jmtPT2XHK8W2/ii3XtqHT5akoIU= - dependencies: - p-timeout "^1.1.1" - -p-event@^2.1.0: - version "2.3.1" - resolved "https://registry.yarnpkg.com/p-event/-/p-event-2.3.1.tgz#596279ef169ab2c3e0cae88c1cfbb08079993ef6" - integrity sha512-NQCqOFhbpVTMX4qMe8PF8lbGtzZ+LCiN7pcNrb/413Na7+TRoe1xkKUzuWa/YEJdGQ0FvKtj35EEbDoVPO2kbA== - dependencies: - p-timeout "^2.0.1" - p-event@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/p-event/-/p-event-4.2.0.tgz#af4b049c8acd91ae81083ebd1e6f5cae2044c1b5" @@ -19478,11 +18522,6 @@ p-forever@^1.0.1: resolved "https://registry.yarnpkg.com/p-forever/-/p-forever-1.0.1.tgz#d8da0e9f88b3929e51596c2f8aa50cf2f1ad06ab" integrity sha512-9IVAxJdPk88BFMvPjzE+WTZLmAt/FBa47mYY49E2elBki4yJJmQ57XHu3o3Dm1GMde+Xf2d+PzElJIogAPwkug== -p-is-promise@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-1.1.0.tgz#9c9456989e9f6588017b0434d56097675c3da05e" - integrity sha1-nJRWmJ6fZYgBewQ01WCXZ1w9oF4= - p-is-promise@^2.0.0, p-is-promise@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" @@ -19566,11 +18605,6 @@ p-map@~1.1.1: resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.1.1.tgz#05f5e4ae97a068371bc2a5cc86bfbdbc19c4ae7a" integrity sha1-BfXkrpegaDcbwqXMhr+9vBnErno= -p-pipe@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/p-pipe/-/p-pipe-3.0.0.tgz#ab1fb87c0b8dd79b3bb03a8a23680fc9d054e132" - integrity sha512-gwwdRFmaxsT3IU+Tl3vYKVRdjfhg8Bbdjw7B+E0y6F7Yz6l+eaQLn0BRmGMXIhcPDONPtOkMoNwx1etZh4zPJA== - p-queue@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-queue/-/p-queue-5.0.0.tgz#80f1741d5e78a6fa72fce889406481baa5617a3c" @@ -19598,13 +18632,6 @@ p-timeout@^1.1.1: dependencies: p-finally "^1.0.0" -p-timeout@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-2.0.1.tgz#d8dd1979595d2dc0139e1fe46b8b646cb3cdf038" - integrity sha512-88em58dDVB/KzPEx1X0N3LwFfYZPyDc4B6eF38M1rk9VTZMbxXXgjugz8mmwpS9Ox4BDZ+t6t3QP5+/gazweIA== - dependencies: - p-finally "^1.0.0" - p-timeout@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-3.2.0.tgz#c7e17abc971d2a7962ef83626b35d635acf23dfe" @@ -19873,7 +18900,7 @@ pascalcase@^0.1.1: resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= -patch-package@6.2.2: +patch-package@6.2.2, patch-package@^6.2.2: version "6.2.2" resolved "https://registry.yarnpkg.com/patch-package/-/patch-package-6.2.2.tgz#71d170d650c65c26556f0d0fbbb48d92b6cc5f39" integrity sha512-YqScVYkVcClUY0v8fF0kWOjDYopzIM8e3bj/RU1DPeEF14+dCGm6UeOYm4jvCyxqIEQ5/eJzmbWfDWnUleFNMg== @@ -20005,11 +19032,6 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== -pathval@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - integrity sha1-uULm1L3mUwBe9rcTYd74cn0GReA= - pause-stream@0.0.11: version "0.0.11" resolved "https://registry.yarnpkg.com/pause-stream/-/pause-stream-0.0.11.tgz#fe5a34b0cbce12b5aa6a2b403ee2e73b602f1445" @@ -20126,7 +19148,7 @@ picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== -pify@^2.0.0, pify@^2.2.0, pify@^2.3.0: +pify@^2.0.0, pify@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= @@ -20246,20 +19268,6 @@ plugin-error@^0.1.2: arr-union "^2.0.1" extend-shallow "^1.1.2" -plur@^2.0.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/plur/-/plur-2.1.2.tgz#7482452c1a0f508e3e344eaec312c91c29dc655a" - integrity sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo= - dependencies: - irregular-plurals "^1.0.0" - -plur@^3.0.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/plur/-/plur-3.1.1.tgz#60267967866a8d811504fe58f2faaba237546a5b" - integrity sha512-t1Ax8KUvV3FFII8ltczPn2tJdjqbd1sIzu6t4JL7nQ3EyeL/lTrj5PWKb06ic5/6XYDr65rQ4uzQEGN70/6X5w== - dependencies: - irregular-plurals "^2.0.0" - pluralize@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/pluralize/-/pluralize-1.2.1.tgz#d1a21483fd22bb41e58a12fa3421823140897c45" @@ -20575,11 +19583,6 @@ prettier@^2.1.1: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.1.tgz#d9485dd5e499daa6cb547023b87a6cf51bee37d6" integrity sha512-9bY+5ZWCfqj3ghYBLxApy2zf6m+NJo5GzmLTpr9FsApsfjriNnS2dahWReHMi7qNPhhHl9SYHJs2cHZLgexNIw== -pretty-bytes@^5.3.0: - version "5.3.0" - resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" - integrity sha512-hjGrh+P926p4R4WbaB6OckyRtO0F0/lQBiT+0gnxjV+5kjPBrfVBFCsCLbMqVQeydvIoouYTCmmEURiH3R1Bdg== - pretty-error@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" @@ -20857,11 +19860,6 @@ pseudomap@^1.0.1, pseudomap@^1.0.2: resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= -psl@^1.1.24: - version "1.4.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.4.0.tgz#5dd26156cdb69fa1fdb8ab1991667d3f80ced7c2" - integrity sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw== - psl@^1.1.28: version "1.8.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" @@ -21133,7 +20131,7 @@ punycode@2.1.0: resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" integrity sha1-X4Y+3Im5bbCQdLrXlHvwkFbKTn0= -punycode@^1.2.4, punycode@^1.3.2, punycode@^1.4.1: +punycode@^1.2.4, punycode@^1.3.2: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= @@ -21150,11 +20148,6 @@ pushdata-bitcoin@^1.0.1: dependencies: bitcoin-ops "^1.3.0" -q@^1.1.2: - version "1.5.1" - resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" - integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= - qrcode-generator@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/qrcode-generator/-/qrcode-generator-1.4.1.tgz#bfb6760e05d12c39df8acd60a0d459bdb2fa0756" @@ -21374,24 +20367,24 @@ react-dev-utils@^10.0.0: strip-ansi "6.0.0" text-table "0.2.0" -react-devtools-core@4.8.2: - version "4.8.2" - resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.8.2.tgz#4465f2e8de7795564aa20f28b2f3a9737586db23" - integrity sha512-3Lv3nI8FPAwKqUco35oOlgf+4j8mgYNnIcDv2QTfxEqg2G69q17ZJ8ScU9aBnymS28YC1OW+kTxLmdIQeTN8yg== +react-devtools-core@4.10.1: + version "4.10.1" + resolved "https://registry.yarnpkg.com/react-devtools-core/-/react-devtools-core-4.10.1.tgz#6d57db291aeac9cc45ef9fb4636dd2ab97490daf" + integrity sha512-sXbBjGAWcf9HAblTP/zMtFhGHqxAfIR+GPxONZsSGN9FHnF4635dx1s2LdQWG9rJ+Ehr3nWg+BUAB6P78my5PA== dependencies: shell-quote "^1.6.1" ws "^7" -react-devtools@^4.8.0: - version "4.8.2" - resolved "https://registry.yarnpkg.com/react-devtools/-/react-devtools-4.8.2.tgz#24c2e1d4975ac087665ab48c925cd418a97797c2" - integrity sha512-NGANnExgSsd34IGJlKURCBtDG6Avi2LeWcqfLQ7/oG7khCT6Wm390ZM+GBnI1gGnZD7y/h7oWXd5B/Dp2s5s6Q== +react-devtools@^4.10.1: + version "4.10.1" + resolved "https://registry.yarnpkg.com/react-devtools/-/react-devtools-4.10.1.tgz#579c14fe0b181e222e262a75fc55c2e2e17abc7a" + integrity sha512-gGOu0tcpCdm2+LZNrFgyimImtkYDoi6z5aKMRxxfuRM0VrJpmZakxAwaLs0BMRA9+UUF22Emzku366+m5eBtIQ== dependencies: cross-spawn "^5.0.1" electron "^9.1.0" ip "^1.1.4" minimist "^1.2.3" - react-devtools-core "4.8.2" + react-devtools-core "4.10.1" update-notifier "^2.1.0" react-dnd-html5-backend@^7.4.4: @@ -21510,7 +20503,7 @@ react-idle-timer@^4.2.5: resolved "https://registry.yarnpkg.com/react-idle-timer/-/react-idle-timer-4.2.5.tgz#eb7d6e1b318f7755b5e0ee810254a8e95a2271b7" integrity sha512-8B/OwjG8E/DTx1fHYKTpZ4cnCbL9+LOc5I9t8SYe8tbEkP14KChiYg0xPIuyRpO33wUZHcgmQl93CVePaDhmRA== -react-input-autosize@^2.1.0, react-input-autosize@^2.2.2: +react-input-autosize@^2.2.2: version "2.2.2" resolved "https://registry.yarnpkg.com/react-input-autosize/-/react-input-autosize-2.2.2.tgz#fcaa7020568ec206bc04be36f4eb68e647c4d8c2" integrity sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw== @@ -21553,7 +20546,7 @@ react-motion@^0.5.2: prop-types "^15.5.8" raf "^3.1.0" -react-popper-tooltip@^3.1.0, react-popper-tooltip@^3.1.1: +react-popper-tooltip@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-3.1.1.tgz#329569eb7b287008f04fcbddb6370452ad3f9eac" integrity sha512-EnERAnnKRptQBJyaee5GJScWNUKQPDD2ywvzZyUjst/wj5U64C8/CnSYLNEmP2hG0IJ3ZhtDxE8oDN+KOyavXQ== @@ -21615,15 +20608,6 @@ react-router@5.1.2: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react-select@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/react-select/-/react-select-1.1.0.tgz#626a2de839fdea2ade74dd1b143a9bde34be6c82" - integrity sha512-c4CdxweEHN9ra85HGWjSjIMBlJ5c0fsIXOymLFZS5UbZEQCiJGHnZTVLTt6/wDh8RKQnxl85gHUwzhG5XZLcyw== - dependencies: - classnames "^2.2.4" - prop-types "^15.5.8" - react-input-autosize "^2.1.0" - react-select@^3.0.8: version "3.0.8" resolved "https://registry.yarnpkg.com/react-select/-/react-select-3.0.8.tgz#06ff764e29db843bcec439ef13e196865242e0c1" @@ -21666,7 +20650,7 @@ react-syntax-highlighter@^13.5.0: prismjs "^1.21.0" refractor "^3.1.0" -react-test-renderer@^16.0.0-0, react-test-renderer@^16.12.0: +react-test-renderer@^16.0.0-0: version "16.12.0" resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-16.12.0.tgz#11417ffda579306d4e841a794d32140f3da1b43f" integrity sha512-Vj/teSqt2oayaWxkbhQ6gKis+t5JrknXfPVo+aIJ8QwYAqMPH77uptOdrlphyxl8eQI/rtkOYg86i/UWkpFu0w== @@ -21858,10 +20842,10 @@ read-pkg@^5.2.0: parse-json "^5.0.0" type-fest "^0.6.0" -"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.6, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.5, readable-stream@~2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== +"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.5, readable-stream@^2.0.6, readable-stream@^2.1.4, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.2.8, readable-stream@^2.2.9, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6, readable-stream@~2.3.3, readable-stream@~2.3.5, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== dependencies: core-util-is "~1.0.0" inherits "~2.0.3" @@ -21890,19 +20874,6 @@ readable-stream@1.1.x, readable-stream@^1.0.33: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.2.2: - version "2.3.7" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" - integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - readable-stream@~1.0.15: version "1.0.34" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" @@ -22072,7 +21043,7 @@ regenerator-runtime@^0.12.0: resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de" integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg== -regenerator-runtime@^0.13.3, regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: +regenerator-runtime@^0.13.4, regenerator-runtime@^0.13.7: version "0.13.7" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz#cac2dacc8a1ea675feaabaeb8ae833898ae46f55" integrity sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew== @@ -22398,15 +21369,6 @@ replace-homedir@^1.0.0: is-absolute "^1.0.0" remove-trailing-separator "^1.1.0" -replacestream@^4.0.0: - version "4.0.3" - resolved "https://registry.yarnpkg.com/replacestream/-/replacestream-4.0.3.tgz#3ee5798092be364b1cdb1484308492cb3dff2f36" - integrity sha512-AC0FiLS352pBBiZhd4VXB1Ab/lh0lEgpP+GGvZqbQh8a5cmXVoTe5EX/YeTFArnp4SRGTHh1qCHu9lGs1qG8sA== - dependencies: - escape-string-regexp "^1.0.3" - object-assign "^4.0.1" - readable-stream "^2.0.2" - request-promise-core@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" @@ -22423,33 +21385,7 @@ request-promise-native@^1.0.3: stealthy-require "^1.1.0" tough-cookie ">=2.3.3" -request@^2.79.0, request@^2.83.0, request@^2.85.0, request@^2.87.0, request@^2.88.0, request@~2.88.0: - version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.0" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.4.3" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -request@^2.88.2: +request@^2.79.0, request@^2.83.0, request@^2.85.0, request@^2.87.0, request@^2.88.0, request@^2.88.2, request@~2.88.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -22587,6 +21523,14 @@ resolve@^1.1.4, resolve@^1.1.5, resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, is-core-module "^2.0.0" path-parse "^1.0.6" +resolve@^1.15.1: + version "1.19.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c" + integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg== + dependencies: + is-core-module "^2.1.0" + path-parse "^1.0.6" + resolve@~1.11.1: version "1.11.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e" @@ -22594,7 +21538,7 @@ resolve@~1.11.1: dependencies: path-parse "^1.0.6" -responselike@1.0.2, responselike@^1.0.2: +responselike@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7" integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec= @@ -22752,10 +21696,10 @@ ripple-lib@1.8.2: ripple-lib-transactionparser "0.8.2" ws "^7.2.0" -rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3: - version "2.2.4" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.4.tgz#d6b0e1659e9285fc509a5d169a9bd06f704951c1" - integrity sha512-fdq2yYCWpAQBhwkZv+Z8o/Z4sPmYm1CUq6P7n6lVTOdb949CnqA0sndXal5C1NleSVSZm6q5F3iEbauyVln/iw== +rlp@^2.0.0, rlp@^2.2.1, rlp@^2.2.2, rlp@^2.2.3, rlp@^2.2.4: + version "2.2.6" + resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.6.tgz#c80ba6266ac7a483ef1e69e8e2f056656de2fb2c" + integrity sha512-HAfAmL6SDYNWPUOJNrM500x4Thn4PZsEy5pijPh40U9WfNk0z15hUYzO9xVIMAdIHdFtD8CBDHd75Td1g36Mjg== dependencies: bn.js "^4.11.1" @@ -22955,7 +21899,7 @@ sass@^1.32.4: dependencies: chokidar ">=2.0.0 <4.0.0" -sax@^1.2.1, sax@^1.2.4, sax@~1.2.4: +sax@^1.2.1, sax@^1.2.4: version "1.2.4" resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== @@ -23111,21 +22055,7 @@ scss-tokenizer@^0.2.3: js-base64 "^2.1.8" source-map "^0.4.2" -secp256k1@^3.0.1, secp256k1@^3.6.1, secp256k1@^3.6.2: - version "3.7.1" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.7.1.tgz#12e473e0e9a7c2f2d4d4818e722ad0e14cc1e2f1" - integrity sha512-1cf8sbnRreXrQFdH6qsg2H71Xw91fCCS9Yp021GnUNJzWJS/py96fS4lHbnTnouLp08Xj6jBoBB6V78Tdbdu5g== - dependencies: - bindings "^1.5.0" - bip66 "^1.1.5" - bn.js "^4.11.8" - create-hash "^1.2.0" - drbg.js "^1.0.1" - elliptic "^6.4.1" - nan "^2.14.0" - safe-buffer "^5.1.2" - -secp256k1@^3.5.2: +secp256k1@^3.0.1, secp256k1@^3.5.2, secp256k1@^3.6.1, secp256k1@^3.6.2: version "3.8.0" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.8.0.tgz#28f59f4b01dbee9575f56a47034b7d2e3b3b352d" integrity sha512-k5ke5avRZbtl9Tqx/SA7CbY3NF6Ro+Sj9cZxezFzuBlLDmyqPiL8hJJ+EmzD8Ig4LUDByHJ3/iPOVoRixs/hmw== @@ -23153,13 +22083,6 @@ seedrandom@3.0.1: resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.1.tgz#eb3dde015bcf55df05a233514e5df44ef9dce083" integrity sha512-1/02Y/rUeU1CJBAGLebiC5Lbo5FnB22gQbIFFYTLkwvp1xdABZJH1sn4ZT1MzXmPpzv+Rf/Lu2NcsLJiK4rcDg== -seek-bzip@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - integrity sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w= - dependencies: - commander "~2.8.1" - select@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" @@ -23198,18 +22121,6 @@ semver-greatest-satisfied-range@^1.1.0: dependencies: sver-compat "^1.5.0" -semver-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-2.0.0.tgz#a93c2c5844539a770233379107b38c7b4ac9d338" - integrity sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw== - -semver-truncate@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/semver-truncate/-/semver-truncate-1.1.2.tgz#57f41de69707a62709a7e0104ba2117109ea47e8" - integrity sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g= - dependencies: - semver "^5.3.0" - "semver@2 || 3 || 4 || 5", semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" @@ -23225,12 +22136,7 @@ semver@7.0.0: resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== -semver@^7.2.1: - version "7.3.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" - integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== - -semver@^7.3.2, semver@^7.3.4: +semver@^7.2.1, semver@^7.3.2, semver@^7.3.4: version "7.3.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97" integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw== @@ -23305,6 +22211,20 @@ serve-handler@^6.1.2: path-to-regexp "2.2.1" range-parser "1.2.0" +serve-handler@^6.1.3: + version "6.1.3" + resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8" + integrity sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w== + dependencies: + bytes "3.0.0" + content-disposition "0.5.2" + fast-url-parser "1.1.3" + mime-types "2.1.18" + minimatch "3.0.4" + path-is-inside "1.0.2" + path-to-regexp "2.2.1" + range-parser "1.2.0" + serve-static@1.14.1: version "1.14.1" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" @@ -23385,6 +22305,16 @@ sha3@^1.2.2: dependencies: nan "2.13.2" +shallow-clone@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-0.1.2.tgz#5909e874ba77106d73ac414cfec1ffca87d97060" + integrity sha1-WQnodLp3EG1zrEFM/sH/yofZcGA= + dependencies: + is-extendable "^0.1.1" + kind-of "^2.0.1" + lazy-cache "^0.2.3" + mixin-object "^2.0.1" + shallow-clone@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-1.0.0.tgz#4480cd06e882ef68b2ad88a3ea54832e2c48b571" @@ -23737,20 +22667,6 @@ sonic-boom@^0.7.5: dependencies: flatstr "^1.0.12" -sort-keys-length@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sort-keys-length/-/sort-keys-length-1.0.1.tgz#9cb6f4f4e9e48155a6aa0671edd336ff1479a188" - integrity sha1-nLb09OnkgVWmqgZx7dM2/xR5oYg= - dependencies: - sort-keys "^1.0.0" - -sort-keys@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" - integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= - dependencies: - is-plain-obj "^1.0.0" - sort-keys@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" @@ -23852,7 +22768,7 @@ source-map@^0.4.2: dependencies: amdefine ">=0.0.4" -source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3: +source-map@^0.5.0, source-map@^0.5.1, source-map@^0.5.6, source-map@^0.5.7, source-map@~0.5.3: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= @@ -23956,15 +22872,6 @@ sqlite3@^4.0.4: node-pre-gyp "^0.11.0" request "^2.87.0" -squeak@^1.0.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/squeak/-/squeak-1.3.0.tgz#33045037b64388b567674b84322a6521073916c3" - integrity sha1-MwRQN7ZDiLVnZ0uEMiplIQc5FsM= - dependencies: - chalk "^1.0.0" - console-stream "^0.1.1" - lpad-align "^1.0.1" - sshpk@^1.7.0: version "1.16.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" @@ -24317,15 +23224,6 @@ stringify-entities@^3.0.0: is-decimal "^1.0.2" is-hexadecimal "^1.0.0" -stringify-object@^3.0.0: - version "3.2.2" - resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.2.2.tgz#9853052e5a88fb605a44cd27445aa257ad7ffbcd" - integrity sha512-O696NF21oLiDy8PhpWu8AEqoZHw++QW6mUv0UvKZe8gWSdSvMXkiLufK7OmnP27Dro4GU5kb9U7JIO0mBuCRQg== - dependencies: - get-own-enumerable-property-symbols "^2.0.1" - is-obj "^1.0.1" - is-regexp "^1.0.0" - strip-ansi@6.0.0, strip-ansi@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" @@ -24404,13 +23302,6 @@ strip-bom@^4.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== -strip-dirs@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - integrity sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g== - dependencies: - is-natural-number "^4.0.1" - strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -24447,7 +23338,7 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strip-outer@^1.0.0, strip-outer@^1.0.1: +strip-outer@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631" integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg== @@ -24633,25 +23524,6 @@ svg-tags@^1.0.0: resolved "https://registry.yarnpkg.com/svg-tags/-/svg-tags-1.0.0.tgz#58f71cee3bd519b59d4b2a843b6c7de64ac04764" integrity sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= -svgo@^1.0.5: - version "1.3.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.0.tgz#bae51ba95ded9a33a36b7c46ce9c359ae9154313" - integrity sha512-MLfUA6O+qauLDbym+mMZgtXCGRfIxyQoeH6IKVcFslyODEe/ElJNwr0FohQ3xG4C6HK6bk3KYPPXwHVJk3V5NQ== - dependencies: - chalk "^2.4.1" - coa "^2.0.2" - css-select "^2.0.0" - css-select-base-adapter "^0.1.1" - css-tree "1.0.0-alpha.33" - csso "^3.5.1" - js-yaml "^3.13.1" - mkdirp "~0.5.1" - object.values "^1.1.0" - sax "~1.2.4" - stable "^0.1.8" - unquote "~1.1.1" - util.promisify "~1.0.0" - swappable-obj-proxy@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/swappable-obj-proxy/-/swappable-obj-proxy-1.1.0.tgz#fe23c60a0df22499e85d94b71297d9c39ff05fa4" @@ -24744,19 +23616,6 @@ tape@^4.6.3, tape@^4.8.0: string.prototype.trim "~1.1.2" through "~2.3.8" -tar-stream@^1.5.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== - dependencies: - bl "^1.0.0" - buffer-alloc "^1.2.0" - end-of-stream "^1.0.0" - fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.1" - xtend "^4.0.0" - tar-stream@^2.0.0, tar-stream@^2.0.1: version "2.1.0" resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.1.0.tgz#d1aaa3661f05b38b5acc9b7020efdca5179a2cc3" @@ -24836,11 +23695,6 @@ telejson@^5.0.2: lodash "^4.17.20" memoizerific "^1.11.3" -temp-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" - integrity sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0= - temp@^0.9.1, temp@~0.9.0: version "0.9.1" resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.1.tgz#2d666114fafa26966cd4065996d7ceedd4dd4697" @@ -24848,14 +23702,6 @@ temp@^0.9.1, temp@~0.9.0: dependencies: rimraf "~2.6.2" -tempfile@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/tempfile/-/tempfile-2.0.0.tgz#6b0446856a9b1114d1856ffcbe509cccb0977265" - integrity sha1-awRGhWqbERTRhW/8vlCczLCXcmU= - dependencies: - temp-dir "^1.0.0" - uuid "^3.0.1" - term-size@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" @@ -24931,23 +23777,11 @@ textarea-caret@^3.0.1: resolved "https://registry.yarnpkg.com/textarea-caret/-/textarea-caret-3.0.2.tgz#f360c48699aa1abf718680a43a31a850665c2caf" integrity sha1-82DEhpmqGr9xhoCkOjGoUGZcLK8= -textextensions@2: - version "2.6.0" - resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.6.0.tgz#d7e4ab13fe54e32e08873be40d51b74229b00fc4" - integrity sha512-49WtAWS+tcsy93dRt6P0P3AMD2m5PvXRhuEA0kaXos5ZLlujtYmpmFsB+QvWUSxE1ZsstmYXfQ7L40+EcQgpAQ== - throttle-debounce@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-2.1.0.tgz#257e648f0a56bd9e54fe0f132c4ab8611df4e1d5" integrity sha512-AOvyNahXQuU7NN+VVvOOX+uW6FPaWdAOdRP5HfwYxAfCzXTFKRMoIMk+n+po318+ktcChx+F1Dd91G3YHeMKyg== -through2-concurrent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/through2-concurrent/-/through2-concurrent-2.0.0.tgz#c9dd2c146504ec9962dbc86a5168b63d662669fa" - integrity sha512-R5/jLkfMvdmDD+seLwN7vB+mhbqzWop5fAjx5IX8/yQq7VhBhzDmhXgaHAOnhnWkCpRMM7gToYHycB0CS/pd+A== - dependencies: - through2 "^2.0.0" - through2-filter@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/through2-filter/-/through2-filter-2.0.0.tgz#60bc55a0dacb76085db1f9dae99ab43f83d622ec" @@ -24964,14 +23798,14 @@ through2@2.X, through2@^2.0.0, through2@^2.0.1, through2@^2.0.3, through2@^2.0.5 readable-stream "~2.3.6" xtend "~4.0.1" -through2@3.0.1, through2@^3.0.0, through2@^3.0.1: +through2@^3.0.0, through2@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.1.tgz#39276e713c3302edf9e388dd9c812dd3b825bd5a" integrity sha512-M96dvTalPT3YbYLaKaCuwu+j06D/8Jfib0o/PxbVt6Amhv3dUAtW6rTV1jPgJSBG83I/e04Y6xkVdVhSRhi0ww== dependencies: readable-stream "2 || 3" -through@2, "through@>=2.2.7 <3", through@^2.3.6, through@^2.3.8, through@~2.3, through@~2.3.1, through@~2.3.4, through@~2.3.8: +through@2, "through@>=2.2.7 <3", through@^2.3.6, through@~2.3, through@~2.3.1, through@~2.3.4, through@~2.3.8: version "2.3.8" resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= @@ -24986,7 +23820,7 @@ thunky@^1.0.2: resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.0.3.tgz#f5df732453407b09191dae73e2a8cc73f381a826" integrity sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow== -tildify@1.2.0, tildify@^1.1.2: +tildify@1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/tildify/-/tildify-1.2.0.tgz#dcec03f55dca9b7aa3e5b04f21817eb56e63588a" integrity sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo= @@ -25141,11 +23975,6 @@ to-arraybuffer@^1.0.0: resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= -to-buffer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== - to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -25215,15 +24044,7 @@ tosource@1.0.0: resolved "https://registry.yarnpkg.com/tosource/-/tosource-1.0.0.tgz#42d88dd116618bcf00d6106dd5446f3427902ff1" integrity sha1-QtiN0RZhi88A1hBt1URvNCeQL/E= -tough-cookie@>=2.3.3, tough-cookie@^2.3.3, tough-cookie@~2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ== - dependencies: - psl "^1.1.24" - punycode "^1.4.1" - -tough-cookie@~2.5.0: +tough-cookie@>=2.3.3, tough-cookie@^2.3.3, tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== @@ -25426,7 +24247,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= -tweetnacl@^1.0.0, tweetnacl@^1.0.1: +tweetnacl@^1.0.0, tweetnacl@^1.0.1, tweetnacl@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== @@ -25450,7 +24271,7 @@ type-detect@0.1.1: resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822" integrity sha1-C6XsKohWQORw6k6FBZcZANrFiCI= -type-detect@4.0.8, type-detect@^4.0.0, type-detect@^4.0.8: +type-detect@4.0.8, type-detect@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== @@ -25547,14 +24368,6 @@ umd@^3.0.0: resolved "https://registry.yarnpkg.com/umd/-/umd-3.0.3.tgz#aa9fe653c42b9097678489c01000acb69f0b26cf" integrity sha512-4IcGSufhFshvLNcMCV80UnQVlZ5pMOC8mvNPForqwA4+lzYQuetTESLDQkeLmihq8bRcnpbQa48Wb8Lh16/xow== -unbzip2-stream@^1.0.9: - version "1.3.3" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.3.tgz#d156d205e670d8d8c393e1c02ebd506422873f6a" - integrity sha512-fUlAF7U9Ah1Q6EieQ4x4zLNejrRvDWUYmxXUpN3uziFYCHapjWFaCAnreY9bGgxzaMCFAPPpYNng57CypwJVhg== - dependencies: - buffer "^5.2.1" - through "^2.3.8" - unc-path-regex@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/unc-path-regex/-/unc-path-regex-0.1.2.tgz#e73dd3d7b0d7c5ed86fbac6b0ae7d8c6a69d50fa" @@ -25623,6 +24436,11 @@ unicode-canonical-property-names-ecmascript@^1.0.4: resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== +unicode-confusables@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/unicode-confusables/-/unicode-confusables-0.1.1.tgz#17f14e8dc53ff81c12e92fd86e836ebdf14ea0c2" + integrity sha512-XTPBWmT88BDpXz9NycWk4KxDn+/AJmJYYaYBwuIH9119sopwk2E9GxU9azc+JNbhEsfiPul78DGocEihCp6MFQ== + unicode-match-property-ecmascript@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" @@ -25770,7 +24588,7 @@ unpipe@1.0.0, unpipe@~1.0.0: resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= -unquote@^1.1.0, unquote@~1.1.1: +unquote@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= @@ -25981,7 +24799,7 @@ util.promisify@1.0.0: define-properties "^1.1.2" object.getownpropertydescriptors "^2.0.3" -util.promisify@^1.0.0, util.promisify@~1.0.0: +util.promisify@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== @@ -26743,12 +25561,7 @@ whatwg-fetch@2.0.4: resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" integrity sha512-dcQ1GWpOD/eEQ97k66aiEVpNnapVj90/+R+SXTPYGHpYBBypfKJEQjLrvMZ7YXbKm21gXd4NcuxUTjiv1YtLng== -whatwg-fetch@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.4.1.tgz#e5f871572d6879663fa5674c8f833f15a8425ab3" - integrity sha512-sofZVzE1wKwO+EYPbWfiwzaKovWiZXf4coEzjGP9b2GBVgQRLQUZ2QcuPpQExGDAW5GItpEm6Tl4OU5mywnAoQ== - -whatwg-fetch@^3.5.0: +whatwg-fetch@^3.4.1, whatwg-fetch@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.5.0.tgz#605a2cd0a7146e5db141e29d1c62ab84c0c4c868" integrity sha512-jXkLtsR42xhXg7akoDKvKWE40eJeI+2KZqcp2h3NsOrRnDvtWX36KcKl30dy+hxECivdk2BVUHVNrPtoMBUx6A== @@ -26939,7 +25752,7 @@ ws@7.1.0: dependencies: async-limiter "^1.0.0" -ws@7.2.3, ws@^7: +ws@7.2.3: version "7.2.3" resolved "https://registry.yarnpkg.com/ws/-/ws-7.2.3.tgz#a5411e1fb04d5ed0efee76d26d5c46d830c39b46" integrity sha512-HTDl9G9hbkNDk98naoR/cHDws7+EyYMOdL1BmjsZXRUjf7d+MficC4B7HLUPlSiho0vg+CWKrGIt/VJBd1xunQ== @@ -26968,7 +25781,7 @@ ws@^5.1.1: dependencies: async-limiter "~1.0.0" -ws@^7.2.0, ws@^7.4.0, ws@~7.4.2: +ws@^7, ws@^7.2.0, ws@^7.4.0, ws@~7.4.2: version "7.4.2" resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.2.tgz#782100048e54eb36fe9843363ab1c68672b261dd" integrity sha512-T4tewALS3+qsrpGI/8dqNMLIVdq/g/85U98HPMa6F0m6xTbvhXU6RCQLqPH3+SlomNV/LdY6RXEbBpMH6EOJnA== @@ -27214,7 +26027,7 @@ yargs@^15.0.0, yargs@^15.0.2, yargs@^15.3.1: y18n "^4.0.0" yargs-parser "^18.1.2" -yargs@^16.2.0: +yargs@^16.0.0, yargs@^16.2.0: version "16.2.0" resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== @@ -27254,7 +26067,7 @@ yarn-logical-tree@^1.0.2: npm-logical-tree "^1.2.1" semver "^5.5.0" -yauzl@2.10.0, yauzl@^2.10.0, yauzl@^2.4.2: +yauzl@2.10.0, yauzl@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" integrity sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=