diff --git a/.circleci/config.yml b/.circleci/config.yml
index 52702030dfb..ed48900b8e1 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -20,7 +20,7 @@ jobs:
prep-deps:
<<: *defaults
docker:
- - image: circleci/node:10
+ - image: circleci/node:14
steps:
- checkout
- run:
@@ -33,7 +33,7 @@ jobs:
prep-node-deps:
<<: *defaults
docker:
- - image: circleci/node:10
+ - image: circleci/node:14
steps:
- checkout
- restore_cache: *restore-node-cache
@@ -49,7 +49,7 @@ jobs:
lint:
<<: *defaults
docker:
- - image: circleci/node:10
+ - image: circleci/node:14
steps:
- checkout
- attach_workspace:
@@ -60,7 +60,7 @@ jobs:
<<: *defaults
parallelism: 3
docker:
- - image: circleci/node:10
+ - image: circleci/node:14
steps:
- checkout
- attach_workspace:
@@ -74,7 +74,7 @@ jobs:
test-deps:
<<: *defaults
docker:
- - image: circleci/node:10
+ - image: circleci/node:14
steps:
- checkout
- attach_workspace:
@@ -106,7 +106,7 @@ jobs:
upload-coverage:
<<: *defaults
docker:
- - image: circleci/node:10
+ - image: circleci/node:14
steps:
- checkout
- attach_workspace:
@@ -117,7 +117,7 @@ jobs:
all-tests-pass:
<<: *defaults
docker:
- - image: circleci/node:10
+ - image: circleci/node:14
steps:
- run:
name: All Tests Passed
@@ -189,6 +189,9 @@ jobs:
- store_artifacts:
path: sourcemaps/ios
destination: sourcemaps-ios
+ - store_artifacts:
+ path: ios/output/gym
+ destination: output
workflows:
full_test:
jobs:
diff --git a/.eslintrc.js b/.eslintrc.js
index bcf2b8df859..2b876e8b391 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -1,3 +1,4 @@
+// eslint-disable-next-line import/no-commonjs
module.exports = {
root: true,
parser: 'babel-eslint',
diff --git a/.nvmrc b/.nvmrc
index e338b86593f..958b5a36e1f 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-v10
+v14
diff --git a/CHANGELOG.md b/CHANGELOG.md
index fb592ef25a1..a5e846579f0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,49 @@
# Changelog
+## v.2.3.0 - May 5 2021
+- [#2674](https://github.com/MetaMask/metamask-mobile/pull/2674): Fix deploy contract and create token testnets
+- [#2669](https://github.com/MetaMask/metamask-mobile/pull/2669): Key off accounts
+- [#2670](https://github.com/MetaMask/metamask-mobile/pull/2670): Bump hosted-git-info from 2.8.8 to 2.8.9
+- [#2667](https://github.com/MetaMask/metamask-mobile/pull/2667): added export of iOS artifacts
+- [#2664](https://github.com/MetaMask/metamask-mobile/pull/2664): updated version code and change logs
+- [#2663](https://github.com/MetaMask/metamask-mobile/pull/2663): Load video over the network
+- [#2656](https://github.com/MetaMask/metamask-mobile/pull/2656): Fix Balance undefined for deeplink payment requests
+- [#2657](https://github.com/MetaMask/metamask-mobile/pull/2657): Fix missing seed phrase updates
+- [#2645](https://github.com/MetaMask/metamask-mobile/pull/2645): Safe navbar for iphone 12
+- [#2643](https://github.com/MetaMask/metamask-mobile/pull/2643): Fix undefined is not an object identities[selectedAddress].importTime
+- [#2639](https://github.com/MetaMask/metamask-mobile/pull/2639): Exclude native asset from hiding when balance is zero
+- [#2631](https://github.com/MetaMask/metamask-mobile/pull/2631): updated change log
+- [#2633](https://github.com/MetaMask/metamask-mobile/pull/2633): Address yarn audit
+- [#2625](https://github.com/MetaMask/metamask-mobile/pull/2625): Fix isZero is undefined
+- [#2444](https://github.com/MetaMask/metamask-mobile/pull/2444): Implement 'hide zero balance token' setting for token balances on home screen
+- [#2621](https://github.com/MetaMask/metamask-mobile/pull/2621): RC v2.3.0
+- [#2605](https://github.com/MetaMask/metamask-mobile/pull/2605): Feature/update seed phrase wording
+- [#2564](https://github.com/MetaMask/metamask-mobile/pull/2564): Improve rpc errors logging and removing user rejected errors
+- [#2556](https://github.com/MetaMask/metamask-mobile/pull/2556): Fix/respect custom spend limit on dapp approve modal
+- [#2614](https://github.com/MetaMask/metamask-mobile/pull/2614): updated lock files
+- [#2586](https://github.com/MetaMask/metamask-mobile/pull/2586): Upgrade swaps-controller v4
+- [#2613](https://github.com/MetaMask/metamask-mobile/pull/2613): remove typo
+- [#2603](https://github.com/MetaMask/metamask-mobile/pull/2603): Bugfix/android anr
+- [#2565](https://github.com/MetaMask/metamask-mobile/pull/2565): This will fix sentry errors with no title by using the extra info as a title
+- [#2552](https://github.com/MetaMask/metamask-mobile/pull/2552): Upgrade wallet connect
+- [#2607](https://github.com/MetaMask/metamask-mobile/pull/2607): Detox/Fix failing tests
+- [#2604](https://github.com/MetaMask/metamask-mobile/pull/2604): Don't hide url modal on emulator
+- [#2529](https://github.com/MetaMask/metamask-mobile/pull/2529): Move some errors to analytics instead of sentry
+- [#2446](https://github.com/MetaMask/metamask-mobile/pull/2446): Add New Zealand Dollar to currency options
+- [#2464](https://github.com/MetaMask/metamask-mobile/pull/2464): Feature/confusables
+- [#2610](https://github.com/MetaMask/metamask-mobile/pull/2610): fix typeface on login text field
+- [#2416](https://github.com/MetaMask/metamask-mobile/pull/2416): Replace controller context
+- [#2590](https://github.com/MetaMask/metamask-mobile/pull/2590): Fix adding custom token in custom network
+- [#2470](https://github.com/MetaMask/metamask-mobile/pull/2470): only add custom tokens if not in mainnet
+- [#2524](https://github.com/MetaMask/metamask-mobile/pull/2524): Address yarn lints
+- [#2588](https://github.com/MetaMask/metamask-mobile/pull/2588): Upgrade .nvmrc to node v14
+- [#2514](https://github.com/MetaMask/metamask-mobile/pull/2514): Swaps: Add cache thresholds configuration
+- [#2468](https://github.com/MetaMask/metamask-mobile/pull/2468): Swaps: BSC Support
+- [#2539](https://github.com/MetaMask/metamask-mobile/pull/2539): Use node 14
+- [#2568](https://github.com/MetaMask/metamask-mobile/pull/2568): resolve isENS without case sensitivity (#2545)
+- [#2566](https://github.com/MetaMask/metamask-mobile/pull/2566): Revert "resolve isENS without case sensitivity (#2545)"
+- [#2545](https://github.com/MetaMask/metamask-mobile/pull/2545): resolve isENS without case sensitivity
+
## v2.2.0 - Apr 21 2021
- [#2547](https://github.com/MetaMask/metamask-mobile/pull/2547): Include decimalsToShow in balanceToFiatNumber
- [#2554](https://github.com/MetaMask/metamask-mobile/pull/2554): Bug fix/sync import time
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 87caea76f7b..838e4c4277b 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -166,8 +166,8 @@ android {
applicationId "io.metamask"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 54
- versionName "2.2.0"
+ versionCode 715
+ versionName "2.3.0"
multiDexEnabled true
testBuildType System.getProperty('testBuildType', 'debug')
missingDimensionStrategy "minReactNative", "minReactNative46"
diff --git a/app/__mocks__/react-native-device-info.js b/app/__mocks__/react-native-device-info.js
new file mode 100644
index 00000000000..5d6f3a8f2e9
--- /dev/null
+++ b/app/__mocks__/react-native-device-info.js
@@ -0,0 +1,4 @@
+export const getModel = () => Promise.resolve('iPhone 12');
+export const getApplicationName = () => Promise.resolve('applicationName');
+export const getVersion = () => Promise.resolve('version');
+export const getBuildNumber = () => Promise.resolve('500');
diff --git a/app/__mocks__/rn-fetch-blob.js b/app/__mocks__/rn-fetch-blob.js
index 2e08193f590..efdd761092c 100644
--- a/app/__mocks__/rn-fetch-blob.js
+++ b/app/__mocks__/rn-fetch-blob.js
@@ -9,6 +9,7 @@ export default {
config: noop,
session: noop,
fs: {
+ writeFile: () => Promise.resolve(),
exists: () => Promise.resolve(),
dirs: {
CacheDir: noop,
diff --git a/app/actions/settings/index.js b/app/actions/settings/index.js
index 8bec8eda1f1..eca421a12c9 100644
--- a/app/actions/settings/index.js
+++ b/app/actions/settings/index.js
@@ -19,6 +19,13 @@ export function setShowCustomNonce(showCustomNonce) {
};
}
+export function setHideZeroBalanceTokens(hideZeroBalanceTokens) {
+ return {
+ type: 'SET_HIDE_ZERO_BALANCE_TOKENS',
+ hideZeroBalanceTokens
+ };
+}
+
export function setLockTime(lockTime) {
return {
type: 'SET_LOCK_TIME',
diff --git a/app/components/Base/Text.js b/app/components/Base/Text.js
index 906ba541319..1478cb60198 100644
--- a/app/components/Base/Text.js
+++ b/app/components/Base/Text.js
@@ -16,10 +16,13 @@ const style = StyleSheet.create({
right: {
textAlign: 'right'
},
- bold: fontStyles.bold,
+ red: {
+ color: colors.red
+ },
black: {
color: colors.black
},
+ bold: fontStyles.bold,
blue: {
color: colors.blue
},
@@ -66,6 +69,7 @@ const Text = ({
green,
black,
blue,
+ red,
primary,
small,
upper,
@@ -87,6 +91,8 @@ const Text = ({
green && style.green,
black && style.black,
blue && style.blue,
+ red && style.red,
+ black && style.black,
primary && style.primary,
disclaimer && [style.small, style.disclaimer],
small && style.small,
@@ -110,6 +116,7 @@ Text.defaultProps = {
green: false,
black: false,
blue: false,
+ red: false,
primary: false,
disclaimer: false,
modal: false,
@@ -150,6 +157,10 @@ Text.propTypes = {
* Makes text blue
*/
blue: PropTypes.bool,
+ /**
+ * Makes text red
+ */
+ red: PropTypes.bool,
/**
* Makes text fontPrimary color
*/
diff --git a/app/components/Nav/App/index.js b/app/components/Nav/App/index.js
index 12309f49053..bfecc8ddaf9 100644
--- a/app/components/Nav/App/index.js
+++ b/app/components/Nav/App/index.js
@@ -28,6 +28,7 @@ import Engine from '../../../core/Engine';
import Logger from '../../../util/Logger';
import Branch from 'react-native-branch';
import AppConstants from '../../../core/AppConstants';
+import { trackErrorAsAnalytics } from '../../../util/analyticsV2';
/**
* Stack navigator responsible for the onboarding process
@@ -186,7 +187,11 @@ class App extends PureComponent {
handleDeeplinks = async ({ error, params, uri }) => {
if (error) {
- Logger.error(error, 'Deeplink: Error from Branch');
+ if (error === 'Trouble reaching the Branch servers, please try again shortly.') {
+ trackErrorAsAnalytics('Branch: Trouble reaching servers', error);
+ } else {
+ Logger.error(error, 'Deeplink: Error from Branch');
+ }
}
const deeplink = params['+non_branch_link'] || uri || null;
try {
diff --git a/app/components/Nav/Main/index.js b/app/components/Nav/Main/index.js
index 096f0f05d88..219c9c299d0 100644
--- a/app/components/Nav/Main/index.js
+++ b/app/components/Nav/Main/index.js
@@ -38,7 +38,6 @@ import {
decodeApproveData
} from '../../../util/transactions';
import { BN } from 'ethereumjs-util';
-import { safeToChecksumAddress } from '../../../util/address';
import Logger from '../../../util/Logger';
import contractMap from '@metamask/contract-metadata';
import MessageSign from '../../UI/MessageSign';
@@ -58,7 +57,8 @@ import AccountApproval from '../../UI/AccountApproval';
import ProtectYourWalletModal from '../../UI/ProtectYourWalletModal';
import MainNavigator from './MainNavigator';
import SkipAccountSecurityModal from '../../UI/SkipAccountSecurityModal';
-import { swapsUtils, util } from '@estebanmino/controllers';
+import { swapsUtils } from '@metamask/swaps-controller';
+import { util } from '@metamask/controllers';
import SwapsLiveness from '../../UI/Swaps/SwapsLiveness';
import Analytics from '../../../core/Analytics';
import { ANALYTICS_EVENT_OPTS } from '../../../util/analytics';
@@ -67,7 +67,8 @@ import { setInfuraAvailabilityBlocked, setInfuraAvailabilityNotBlocked } from '.
const styles = StyleSheet.create({
flex: {
- flex: 1
+ flex: 1,
+ marginTop: Device.isIphone12() ? 20 : 0
},
loader: {
backgroundColor: colors.white,
@@ -238,12 +239,12 @@ const Main = props => {
.div(gasEstimate)
.times(100)
.toFixed(2)}%`;
- const quoteVsExecutionRatio = `${util
+ const quoteVsExecutionRatio = `${swapsUtils
.calcTokenAmount(tokensReceived || '0x0', swapTransaction.destinationTokenDecimals)
.div(swapTransaction.destinationAmount)
.times(100)
.toFixed(2)}%`;
- const tokenToAmountReceived = util.calcTokenAmount(
+ const tokenToAmountReceived = swapsUtils.calcTokenAmount(
tokensReceived,
swapTransaction.destinationToken.decimals
);
@@ -310,16 +311,18 @@ const Main = props => {
async transactionMeta => {
if (transactionMeta.origin === TransactionTypes.MMM) return;
- const to = safeToChecksumAddress(transactionMeta.transaction.to);
+ const to = transactionMeta.transaction.to?.toLowerCase();
const { data } = transactionMeta.transaction;
// if approval data includes metaswap contract
// if destination address is metaswap contract
if (
- to === safeToChecksumAddress(swapsUtils.SWAPS_CONTRACT_ADDRESS) ||
- (data &&
- data.substr(0, 10) === APPROVE_FUNCTION_SIGNATURE &&
- decodeApproveData(data).spenderAddress === swapsUtils.SWAPS_CONTRACT_ADDRESS)
+ to &&
+ (to === swapsUtils.getSwapsContractAddress(props.chainId) ||
+ (data &&
+ data.substr(0, 10) === APPROVE_FUNCTION_SIGNATURE &&
+ decodeApproveData(data).spenderAddress?.toLowerCase() ===
+ swapsUtils.getSwapsContractAddress(props.chainId)))
) {
if (transactionMeta.origin === process.env.MM_FOX_CODE) {
autoSign(transactionMeta);
@@ -388,6 +391,7 @@ const Main = props => {
},
[
props.tokens,
+ props.chainId,
setEtherTransaction,
setTransactionObject,
toggleApproveModal,
@@ -568,6 +572,14 @@ const Main = props => {
}
});
+ // unapprovedTransaction effect
+ useEffect(() => {
+ Engine.context.TransactionController.hub.on('unapprovedTransaction', onUnapprovedTransaction);
+ return () => {
+ Engine.context.TransactionController.hub.removeListener('unapprovedTransaction', onUnapprovedTransaction);
+ };
+ }, [onUnapprovedTransaction]);
+
useEffect(() => {
initializeWalletConnect();
AppState.addEventListener('change', handleAppStateChange);
@@ -596,8 +608,6 @@ const Main = props => {
}
});
- Engine.context.TransactionController.hub.on('unapprovedTransaction', onUnapprovedTransaction);
-
Engine.context.MessageManager.hub.on('unapprovedMessage', messageParams =>
onUnapprovedMessage(messageParams, 'eth')
);
@@ -628,7 +638,6 @@ const Main = props => {
lockManager.current.stopListening();
Engine.context.PersonalMessageManager.hub.removeAllListeners();
Engine.context.TypedMessageManager.hub.removeAllListeners();
- Engine.context.TransactionController.hub.removeListener('unapprovedTransaction', onUnapprovedTransaction);
WalletConnect.hub.removeAllListeners();
removeConnectionStatusListener.current && removeConnectionStatusListener.current();
};
@@ -737,6 +746,10 @@ Main.propTypes = {
* Selected address
*/
selectedAddress: PropTypes.string,
+ /**
+ * Chain id
+ */
+ chainId: PropTypes.string,
/**
* Network provider type
*/
@@ -755,6 +768,7 @@ const mapStateToProps = state => ({
lockTime: state.settings.lockTime,
thirdPartyApiMode: state.privacy.thirdPartyApiMode,
selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress,
+ chainId: state.engine.backgroundState.NetworkController.provider.chainId,
tokens: state.engine.backgroundState.AssetsController.tokens,
isPaymentRequest: state.transaction.paymentRequest,
dappTransactionModalVisible: state.modals.dappTransactionModalVisible,
diff --git a/app/components/UI/AccountOverview/index.js b/app/components/UI/AccountOverview/index.js
index 9b11b04316f..101bafc2f3e 100644
--- a/app/components/UI/AccountOverview/index.js
+++ b/app/components/UI/AccountOverview/index.js
@@ -2,7 +2,7 @@ import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import { ScrollView, TextInput, StyleSheet, Text, View, TouchableOpacity, InteractionManager } from 'react-native';
import Clipboard from '@react-native-community/clipboard';
-import { swapsUtils } from '@estebanmino/controllers';
+import { swapsUtils } from '@metamask/swaps-controller';
import { connect } from 'react-redux';
import Engine from '../../../core/Engine';
import Analytics from '../../../core/Analytics';
@@ -21,6 +21,7 @@ import { renderFiat } from '../../../util/number';
import { renderAccountName } from '../../../util/address';
import { isMainNet } from '../../../util/networks';
import { getEther } from '../../../util/transactions';
+import { isSwapsAllowed } from '../Swaps/utils';
import Identicon from '../Identicon';
import AssetActionButton from '../AssetActionButton';
@@ -257,7 +258,7 @@ class AccountOverview extends PureComponent {
goToSwaps = () =>
this.props.navigation.navigate('Swaps', {
- sourceToken: swapsUtils.ETH_SWAPS_TOKEN_ADDRESS
+ sourceToken: swapsUtils.NATIVE_SWAPS_TOKEN_ADDRESS
});
render() {
@@ -325,13 +326,14 @@ class AccountOverview extends PureComponent {
: { borderColor: colors.white }
]}
numberOfLines={1}
+ testID={'edit-account-label'}
>
{name}
)}
- {fiatBalance}
+ {isMainNet(chainId) && {fiatBalance}}
@@ -358,7 +360,7 @@ class AccountOverview extends PureComponent {
{AppConstants.SWAPS.ACTIVE && (
diff --git a/app/components/UI/AddCustomNetwork/__snapshots__/index.test.js.snap b/app/components/UI/AddCustomNetwork/__snapshots__/index.test.js.snap
index 19c45c50f29..7d82f7e0e3d 100644
--- a/app/components/UI/AddCustomNetwork/__snapshots__/index.test.js.snap
+++ b/app/components/UI/AddCustomNetwork/__snapshots__/index.test.js.snap
@@ -26,6 +26,7 @@ exports[`AddCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -55,6 +56,7 @@ exports[`AddCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -83,6 +85,7 @@ exports[`AddCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -109,6 +112,7 @@ exports[`AddCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -132,6 +136,7 @@ exports[`AddCustomNetwork should render correctly 1`] = `
noMargin={true}
onPress={[Function]}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -174,6 +179,7 @@ exports[`AddCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={true}
+ red={false}
reset={false}
right={false}
small={true}
@@ -199,6 +205,7 @@ exports[`AddCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={true}
+ red={false}
reset={false}
right={true}
small={false}
@@ -232,6 +239,7 @@ exports[`AddCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={true}
+ red={false}
reset={false}
right={false}
small={true}
@@ -257,6 +265,7 @@ exports[`AddCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={true}
+ red={false}
reset={false}
right={true}
small={false}
@@ -289,6 +298,7 @@ exports[`AddCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={true}
+ red={false}
reset={false}
right={false}
small={true}
@@ -314,6 +324,7 @@ exports[`AddCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={true}
+ red={false}
reset={false}
right={true}
small={false}
@@ -350,6 +361,7 @@ exports[`AddCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
diff --git a/app/components/UI/AddCustomToken/index.js b/app/components/UI/AddCustomToken/index.js
index 1e6a08cd346..d1e01408d02 100644
--- a/app/components/UI/AddCustomToken/index.js
+++ b/app/components/UI/AddCustomToken/index.js
@@ -125,7 +125,9 @@ export default class AddCustomToken extends PureComponent {
let validated = true;
const address = this.state.address;
const isValidTokenAddress = isValidAddress(address);
- const toSmartContract = isValidTokenAddress && (await isSmartContractAddress(address));
+ const { NetworkController } = Engine.context;
+ const { chainId } = NetworkController?.state?.provider || {};
+ const toSmartContract = isValidTokenAddress && (await isSmartContractAddress(address, chainId));
if (address.length === 0) {
this.setState({ warningAddress: strings('token.address_cant_be_empty') });
validated = false;
diff --git a/app/components/UI/ApproveTransactionReview/EditPermission/index.js b/app/components/UI/ApproveTransactionReview/EditPermission/index.js
index 992eb40781b..f460bdbedcc 100644
--- a/app/components/UI/ApproveTransactionReview/EditPermission/index.js
+++ b/app/components/UI/ApproveTransactionReview/EditPermission/index.js
@@ -1,4 +1,4 @@
-import React, { useCallback, useMemo, useState, useEffect } from 'react';
+import React, { useCallback, useMemo, useState } from 'react';
import PropTypes from 'prop-types';
import { View, StyleSheet, TouchableOpacity, TextInput } from 'react-native';
import { colors, fontStyles } from '../../../../styles/common';
@@ -9,6 +9,8 @@ import ConnectHeader from '../../ConnectHeader';
import Device from '../../../../util/Device';
import ErrorMessage from '../../../Views/SendFlow/ErrorMessage';
+export const MINIMUM_VALUE = '1';
+
const styles = StyleSheet.create({
wrapper: {
paddingHorizontal: 24,
@@ -106,15 +108,14 @@ function EditPermission({
onPressSpendLimitCustomSelected,
toggleEditPermission
}) {
- const [approvalSet, setApprovalSet] = useState(false);
+ const [initialState] = useState({ spendLimitUnlimitedSelected, spendLimitCustomValue });
const displayErrorMessage = useMemo(
- () => !spendLimitUnlimitedSelected && minimumSpendLimit > spendLimitCustomValue,
+ () => !spendLimitUnlimitedSelected && Number(minimumSpendLimit) > spendLimitCustomValue,
[spendLimitUnlimitedSelected, spendLimitCustomValue, minimumSpendLimit]
);
const onSetApprovalAmount = useCallback(() => {
- setApprovalSet(true);
if (!spendLimitUnlimitedSelected && !spendLimitCustomValue) {
onPressSpendLimitUnlimitedSelected();
} else {
@@ -122,17 +123,26 @@ function EditPermission({
}
}, [spendLimitUnlimitedSelected, spendLimitCustomValue, onPressSpendLimitUnlimitedSelected, setApprovalAmount]);
- useEffect(
- () =>
- function cleanup() {
- if (!spendLimitUnlimitedSelected && !approvalSet) onPressSpendLimitUnlimitedSelected();
- },
- [spendLimitUnlimitedSelected, approvalSet, onPressSpendLimitUnlimitedSelected]
- );
+ const onBackPress = useCallback(() => {
+ const { spendLimitUnlimitedSelected, spendLimitCustomValue } = initialState;
+ if (spendLimitUnlimitedSelected) {
+ onPressSpendLimitUnlimitedSelected();
+ } else {
+ onPressSpendLimitCustomSelected();
+ }
+ onSpendLimitCustomValueChange(spendLimitCustomValue);
+ toggleEditPermission();
+ }, [
+ initialState,
+ onPressSpendLimitCustomSelected,
+ onPressSpendLimitUnlimitedSelected,
+ onSpendLimitCustomValueChange,
+ toggleEditPermission
+ ]);
return (
-
+
{strings('spend_limit_edition.spend_limit')}
@@ -225,7 +235,7 @@ function EditPermission({
);
}
EditPermission.defaultProps = {
- minimumSpendLimit: '1'
+ minimumSpendLimit: MINIMUM_VALUE
};
EditPermission.propTypes = {
diff --git a/app/components/UI/ApproveTransactionReview/index.js b/app/components/UI/ApproveTransactionReview/index.js
index 35873b19479..3131af86ef2 100644
--- a/app/components/UI/ApproveTransactionReview/index.js
+++ b/app/components/UI/ApproveTransactionReview/index.js
@@ -38,7 +38,8 @@ import { withNavigation } from 'react-navigation';
import { getNetworkName, isMainNet } from '../../../util/networks';
import scaling from '../../../util/scaling';
import { capitalize } from '../../../util/general';
-import EditPermission from './EditPermission';
+import EditPermission, { MINIMUM_VALUE } from './EditPermission';
+import Logger from '../../../util/Logger';
const { hexToBN } = util;
const styles = StyleSheet.create({
@@ -369,7 +370,6 @@ class ApproveTransactionReview extends PureComponent {
toggleEditPermission = () => {
const { editPermissionVisible } = this.state;
- this.onPressSpendLimitUnlimitedSelected();
!editPermissionVisible && this.trackApproveEvent(ANALYTICS_EVENT_OPTS.DAPP_APPROVE_SCREEN_EDIT_PERMISSION);
this.setState({ editPermissionVisible: !editPermissionVisible });
};
@@ -419,16 +419,22 @@ class ApproveTransactionReview extends PureComponent {
spendLimitCustomValue,
transaction
} = this.state;
- const uint = toTokenMinimalUnit(
- spendLimitUnlimitedSelected ? originalApproveAmount : spendLimitCustomValue,
- token.decimals
- ).toString();
- const approvalData = generateApproveData({
- spender: spenderAddress,
- value: Number(uint).toString(16)
- });
- const newApprovalTransaction = { ...transaction, data: approvalData };
- setTransactionObject(newApprovalTransaction);
+
+ try {
+ const uint = toTokenMinimalUnit(
+ spendLimitUnlimitedSelected ? originalApproveAmount : spendLimitCustomValue,
+ token.decimals
+ ).toString(10);
+
+ const approvalData = generateApproveData({
+ spender: spenderAddress,
+ value: Number(uint).toString(16)
+ });
+ const newApprovalTransaction = { ...transaction, data: approvalData };
+ setTransactionObject(newApprovalTransaction);
+ } catch (err) {
+ Logger.log('Failed to setTransactionObject', err);
+ }
this.toggleEditPermission();
AnalyticsV2.trackEvent(AnalyticsV2.ANALYTICS_EVENTS.APPROVAL_PERMISSION_UPDATED, this.getAnalyticsParams());
};
@@ -442,12 +448,14 @@ class ApproveTransactionReview extends PureComponent {
originalApproveAmount
} = this.state;
+ const _spendLimitCustomValue = spendLimitCustomValue ?? MINIMUM_VALUE;
+
return (
{
+ const { host, tokenSymbol, totalGas, totalGasFiat, ticker, spenderAddress } = this.state;
+
+ const {
+ primaryCurrency,
+ currentCurrency,
+ gasError,
+ activeTabUrl,
+ transaction: { origin },
+ network,
+ over,
+ warningGasPriceHigh
+ } = this.props;
+ const is_main_net = isMainNet(network);
+ const isFiat = primaryCurrency.toLowerCase() === 'fiat';
+ const currencySymbol = currencySymbols[currentCurrency];
+ const totalGasFiatRounded = Math.round(totalGasFiat * 100) / 100;
+ const originIsDeeplink = origin === ORIGIN_DEEPLINK || origin === ORIGIN_QR_CODE;
+ const errorPress = is_main_net ? this.buyEth : this.gotoFaucet;
+ const networkName = capitalize(getNetworkName(network));
+ const errorLinkText = is_main_net
+ ? strings('transaction.buy_more_eth')
+ : strings('transaction.get_ether', { networkName });
+
+ return (
+ <>
+
+
+
+ {strings(
+ `spend_limit_edition.${originIsDeeplink ? 'allow_to_address_access' : 'allow_to_access'}`,
+ { tokenSymbol }
+ )}
+
+
+ {`${strings(
+ `spend_limit_edition.${originIsDeeplink ? 'you_trust_this_address' : 'you_trust_this_site'}`
+ )}`}
+
+
+
+
+
+
+ {strings('spend_limit_edition.edit_permission')}
+
+
+
+
+
+
+
+
+ {strings('transaction.transaction_fee')}
+
+
+ {isFiat && currencySymbol}
+ {isFiat ? totalGasFiatRounded : totalGas} {!isFiat && ticker}
+
+
+
+
+
+
+ {gasError && (
+
+
+ {gasError}
+ {/* only show buy more on mainnet */}
+ {over && is_main_net && (
+
+ {errorLinkText}
+
+ )}
+
+
+ )}
+ {!!warningGasPriceHigh && (
+
+ {warningGasPriceHigh}
+
+ )}
+ {!gasError && (
+
+
+
+ {strings('spend_limit_edition.view_details')}
+
+
+
+ )}
+
+
+
+
+
+
+ >
+ );
+ };
+
renderTransactionReview = () => {
const {
host,
@@ -465,8 +589,11 @@ class ApproveTransactionReview extends PureComponent {
viewData,
tokenSymbol,
originalApproveAmount,
+ spendLimitUnlimitedSelected,
+ spendLimitCustomValue,
transaction: { to, data }
} = this.state;
+ const allowance = (!spendLimitUnlimitedSelected && spendLimitCustomValue) || originalApproveAmount;
return (
{
- const {
- host,
- tokenSymbol,
- viewDetails,
- totalGas,
- totalGasFiat,
- editPermissionVisible,
- ticker,
- spenderAddress
- } = this.state;
-
- const {
- primaryCurrency,
- currentCurrency,
- gasError,
- activeTabUrl,
- transaction: { origin },
- network,
- over,
- warningGasPriceHigh
- } = this.props;
- const is_main_net = isMainNet(network);
- const isFiat = primaryCurrency.toLowerCase() === 'fiat';
- const currencySymbol = currencySymbols[currentCurrency];
- const totalGasFiatRounded = Math.round(totalGasFiat * 100) / 100;
- const originIsDeeplink = origin === ORIGIN_DEEPLINK || origin === ORIGIN_QR_CODE;
- const errorPress = is_main_net ? this.buyEth : this.gotoFaucet;
- const networkName = capitalize(getNetworkName(network));
- const errorLinkText = is_main_net
- ? strings('transaction.buy_more_eth')
- : strings('transaction.get_ether', { networkName });
+ const { viewDetails, editPermissionVisible } = this.state;
return (
- {viewDetails ? (
- this.renderTransactionReview()
- ) : editPermissionVisible ? (
- this.renderEditPermission()
- ) : (
- <>
-
-
-
- {strings(
- `spend_limit_edition.${
- originIsDeeplink ? 'allow_to_address_access' : 'allow_to_access'
- }`,
- { tokenSymbol }
- )}
-
-
- {`${strings(
- `spend_limit_edition.${
- originIsDeeplink ? 'you_trust_this_address' : 'you_trust_this_site'
- }`
- )}`}
-
-
-
-
-
-
- {strings('spend_limit_edition.edit_permission')}
-
-
-
-
-
-
-
-
- {strings('transaction.transaction_fee')}
-
-
- {isFiat && currencySymbol}
- {isFiat ? totalGasFiatRounded : totalGas}{' '}
- {!isFiat && ticker}
-
-
-
-
-
-
- {gasError && (
-
-
- {gasError}
- {/* only show buy more on mainnet */}
- {over && is_main_net && (
-
- {errorLinkText}
-
- )}
-
-
- )}
- {!!warningGasPriceHigh && (
-
- {warningGasPriceHigh}
-
- )}
- {!gasError && (
-
-
-
- {strings('spend_limit_edition.view_details')}
-
-
-
- )}
-
-
-
-
-
-
- >
- )}
+ {viewDetails
+ ? this.renderTransactionReview()
+ : editPermissionVisible
+ ? this.renderEditPermission()
+ : this.renderDetails()}
);
};
diff --git a/app/components/UI/AssetActionButton/__snapshots__/index.test.js.snap b/app/components/UI/AssetActionButton/__snapshots__/index.test.js.snap
index 7e4369c5da1..08125e83109 100644
--- a/app/components/UI/AssetActionButton/__snapshots__/index.test.js.snap
+++ b/app/components/UI/AssetActionButton/__snapshots__/index.test.js.snap
@@ -40,6 +40,7 @@ exports[`AssetActionButtons should render correctly 1`] = `
modal={false}
numberOfLines={1}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -97,6 +98,7 @@ exports[`AssetActionButtons should render type add correctly 1`] = `
modal={false}
numberOfLines={1}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -154,6 +156,7 @@ exports[`AssetActionButtons should render type information correctly 1`] = `
modal={false}
numberOfLines={1}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -211,6 +214,7 @@ exports[`AssetActionButtons should render type receive correctly 1`] = `
modal={false}
numberOfLines={1}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -268,6 +272,7 @@ exports[`AssetActionButtons should render type send correctly 1`] = `
modal={false}
numberOfLines={1}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -325,6 +330,7 @@ exports[`AssetActionButtons should render type swap correctly 1`] = `
modal={false}
numberOfLines={1}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
diff --git a/app/components/UI/AssetOverview/index.js b/app/components/UI/AssetOverview/index.js
index 87fd44b11df..b4b56e83529 100644
--- a/app/components/UI/AssetOverview/index.js
+++ b/app/components/UI/AssetOverview/index.js
@@ -1,7 +1,7 @@
import React, { PureComponent } from 'react';
import { InteractionManager, StyleSheet, Text, View, TouchableOpacity } from 'react-native';
import PropTypes from 'prop-types';
-import { swapsUtils } from '@estebanmino/controllers';
+import { swapsUtils } from '@metamask/swaps-controller';
import AssetIcon from '../AssetIcon';
import Identicon from '../Identicon';
import AssetActionButton from '../AssetActionButton';
@@ -12,9 +12,10 @@ import { toggleReceiveModal } from '../../../actions/modals';
import { connect } from 'react-redux';
import { renderFromTokenMinimalUnit, balanceToFiat, renderFromWei, weiToFiat, hexToBN } from '../../../util/number';
import { safeToChecksumAddress } from '../../../util/address';
+import { isMainNet } from '../../../util/networks';
import { getEther } from '../../../util/transactions';
import { newAssetTransaction } from '../../../actions/transaction';
-import { isMainNet } from '../../../util/networks';
+import { isSwapsAllowed } from '../Swaps/utils';
import { swapsLivenessSelector, swapsTokensObjectSelector } from '../../../reducers/swaps';
import Engine from '../../../core/Engine';
import Logger from '../../../util/Logger';
@@ -178,7 +179,7 @@ class AssetOverview extends PureComponent {
goToSwaps = () => {
this.props.navigation.navigate('Swaps', {
- sourceToken: this.props.asset.isETH ? swapsUtils.ETH_SWAPS_TOKEN_ADDRESS : this.props.asset.address
+ sourceToken: this.props.asset.isETH ? swapsUtils.NATIVE_SWAPS_TOKEN_ADDRESS : this.props.asset.address
});
};
@@ -208,7 +209,7 @@ class AssetOverview extends PureComponent {
try {
await SwapsController.fetchTokenWithCache();
} catch (error) {
- Logger.error(error, 'Swaps: error while fetching tokens with catche in AssetOverview');
+ Logger.error(error, 'Swaps: error while fetching tokens with cache in AssetOverview');
}
};
@@ -249,12 +250,16 @@ class AssetOverview extends PureComponent {
let balance, balanceFiat;
if (isETH) {
balance = renderFromWei(accounts[selectedAddress] && accounts[selectedAddress].balance);
- balanceFiat = weiToFiat(hexToBN(accounts[selectedAddress].balance), conversionRate, currentCurrency);
+ balanceFiat = isMainNet(chainId)
+ ? weiToFiat(hexToBN(accounts[selectedAddress].balance), conversionRate, currentCurrency)
+ : null;
} else {
const exchangeRate = itemAddress in tokenExchangeRates ? tokenExchangeRates[itemAddress] : undefined;
balance =
itemAddress in tokenBalances ? renderFromTokenMinimalUnit(tokenBalances[itemAddress], decimals) : 0;
- balanceFiat = balanceToFiat(balance, conversionRate, exchangeRate, currentCurrency);
+ balanceFiat = isMainNet(chainId)
+ ? balanceToFiat(balance, conversionRate, exchangeRate, currentCurrency)
+ : null;
}
// choose balances depending on 'primaryCurrency'
if (primaryCurrency === 'ETH') {
@@ -275,7 +280,7 @@ class AssetOverview extends PureComponent {
{mainBalance}
- {secondaryBalance}
+ {secondaryBalance && {secondaryBalance}}
>
)}
@@ -303,7 +308,7 @@ class AssetOverview extends PureComponent {
{AppConstants.SWAPS.ACTIVE && (
diff --git a/app/components/UI/ComponentErrorBoundary/index.js b/app/components/UI/ComponentErrorBoundary/index.js
index a18a1b2da03..7193cb7346a 100644
--- a/app/components/UI/ComponentErrorBoundary/index.js
+++ b/app/components/UI/ComponentErrorBoundary/index.js
@@ -1,6 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import Logger from '../../../util/Logger';
+import { trackErrorAsAnalytics } from '../../../util/analyticsV2';
class ComponentErrorBoundary extends React.Component {
state = { error: null };
@@ -17,7 +18,11 @@ class ComponentErrorBoundary extends React.Component {
/**
* Function to be called when there is an error
*/
- onError: PropTypes.func
+ onError: PropTypes.func,
+ /**
+ * Will not track as an error, but still log to analytics
+ */
+ dontTrackAsError: PropTypes.bool
};
static getDerivedStateFromError(error) {
@@ -28,6 +33,11 @@ class ComponentErrorBoundary extends React.Component {
// eslint-disable-next-line no-unused-expressions
this.props.onError?.();
+ const { componentLabel, dontTrackAsError } = this.props;
+
+ if (dontTrackAsError) {
+ return trackErrorAsAnalytics(`Component Error Boundary: ${componentLabel}`, error?.message);
+ }
Logger.error(error, { View: this.props.componentLabel, ...errorInfo });
}
diff --git a/app/components/UI/CustomGas/index.js b/app/components/UI/CustomGas/index.js
index 3103e63b99c..be6d5ab7a29 100644
--- a/app/components/UI/CustomGas/index.js
+++ b/app/components/UI/CustomGas/index.js
@@ -252,6 +252,10 @@ class CustomGas extends PureComponent {
* Object BN containing gas price
*/
gasPrice: PropTypes.object,
+ /**
+ * Object BN containing mininum gas price
+ */
+ minimumGasPrice: PropTypes.object,
/**
* Callback to modify parent state
*/
@@ -488,6 +492,11 @@ class CustomGas extends PureComponent {
const warningSufficientFunds = this.hasSufficientFunds(customGasLimitBN, gasPriceBNWei);
let warningGasPrice;
let warningGasPriceHigh = '';
+ if (this.onlyAdvanced() && this.props.minimumGasPrice) {
+ if (parseInt(gasPrice) < parseInt(fromWei(this.props.minimumGasPrice, 'gwei'))) {
+ warningGasPrice = strings('transaction.low_gas_price');
+ }
+ }
if (this.props.basicGasEstimates) {
if (parseInt(gasPrice) < parseInt(this.props.basicGasEstimates.safeLowGwei))
warningGasPrice = strings('transaction.low_gas_price');
diff --git a/app/components/UI/CustomNonceModal/__snapshots__/index.test.js.snap b/app/components/UI/CustomNonceModal/__snapshots__/index.test.js.snap
index 5177dd71ee4..79962ceefa0 100644
--- a/app/components/UI/CustomNonceModal/__snapshots__/index.test.js.snap
+++ b/app/components/UI/CustomNonceModal/__snapshots__/index.test.js.snap
@@ -88,6 +88,7 @@ exports[`CustomNonceModal should render correctly 1`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -150,6 +151,7 @@ exports[`CustomNonceModal should render correctly 1`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -176,6 +178,7 @@ exports[`CustomNonceModal should render correctly 1`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -280,6 +283,7 @@ exports[`CustomNonceModal should render correctly 1`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -309,6 +313,7 @@ exports[`CustomNonceModal should render correctly 1`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -336,6 +341,7 @@ exports[`CustomNonceModal should render correctly 1`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
diff --git a/app/components/UI/DrawerView/index.js b/app/components/UI/DrawerView/index.js
index 4590ab75626..5f348aab50f 100644
--- a/app/components/UI/DrawerView/index.js
+++ b/app/components/UI/DrawerView/index.js
@@ -8,7 +8,7 @@ import Icon from 'react-native-vector-icons/FontAwesome';
import FeatherIcon from 'react-native-vector-icons/Feather';
import MaterialIcon from 'react-native-vector-icons/MaterialCommunityIcons';
import { colors, fontStyles } from '../../../styles/common';
-import { hasBlockExplorer, findBlockExplorerForRpc, getBlockExplorerName } from '../../../util/networks';
+import { hasBlockExplorer, findBlockExplorerForRpc, getBlockExplorerName, isMainNet } from '../../../util/networks';
import Identicon from '../Identicon';
import StyledButton from '../StyledButton';
import AccountList from '../AccountList';
@@ -338,6 +338,10 @@ class DrawerView extends PureComponent {
* Wizard onboarding state
*/
wizard: PropTypes.object,
+ /**
+ * Chain Id
+ */
+ chainId: PropTypes.string,
/**
* Current provider ticker
*/
@@ -830,6 +834,7 @@ class DrawerView extends PureComponent {
selectedAddress,
keyrings,
currentCurrency,
+ chainId,
ticker,
seedphraseBackedUp
} = this.props;
@@ -876,7 +881,7 @@ class DrawerView extends PureComponent {
- {fiatBalanceStr}
+ {isMainNet(chainId) && {fiatBalanceStr}}
({
receiveModalVisible: state.modals.receiveModalVisible,
passwordSet: state.user.passwordSet,
wizard: state.wizard,
+ chainId: state.engine.backgroundState.NetworkController.provider.chainId,
ticker: state.engine.backgroundState.NetworkController.provider.ticker,
tokens: state.engine.backgroundState.AssetsController.tokens,
tokenBalances: state.engine.backgroundState.TokenBalancesController.contractBalances,
diff --git a/app/components/UI/HintModal/__snapshots__/index.test.js.snap b/app/components/UI/HintModal/__snapshots__/index.test.js.snap
index 48abffbe4e1..72fc7341aea 100644
--- a/app/components/UI/HintModal/__snapshots__/index.test.js.snap
+++ b/app/components/UI/HintModal/__snapshots__/index.test.js.snap
@@ -83,7 +83,7 @@ exports[`HintModal should render correctly 1`] = `
}
}
>
- Do not use this to write your seed phrase.
+ Do not use this to write your Secret Recovery phrase.
+
{backButtonText}
) : (
-
+
)
diff --git a/app/components/UI/NetworkList/__snapshots__/index.test.js.snap b/app/components/UI/NetworkList/__snapshots__/index.test.js.snap
index f9a971fd11f..e93a2b0ff95 100644
--- a/app/components/UI/NetworkList/__snapshots__/index.test.js.snap
+++ b/app/components/UI/NetworkList/__snapshots__/index.test.js.snap
@@ -42,6 +42,7 @@ exports[`NetworkList should render correctly 1`] = `
"flex": 1,
}
}
+ testID="other-networks-scroll"
>
-
+
{this.renderMainnet()}
diff --git a/app/components/UI/Notification/TransactionNotification/index.js b/app/components/UI/Notification/TransactionNotification/index.js
index 0cff2f48f06..043e60f817f 100644
--- a/app/components/UI/Notification/TransactionNotification/index.js
+++ b/app/components/UI/Notification/TransactionNotification/index.js
@@ -94,7 +94,6 @@ function TransactionNotification(props) {
accounts,
currentNotification,
isInBrowserView,
- navigation,
notificationAnimated,
onClose,
transactions,
@@ -179,6 +178,7 @@ function TransactionNotification(props) {
const {
selectedAddress,
ticker,
+ chainId,
conversionRate,
currentCurrency,
exchangeRate,
@@ -194,6 +194,7 @@ function TransactionNotification(props) {
tx,
selectedAddress,
ticker,
+ chainId,
conversionRate,
currentCurrency,
exchangeRate,
@@ -252,7 +253,6 @@ function TransactionNotification(props) {
({
selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress,
transactions: state.engine.backgroundState.TransactionController.transactions,
ticker: state.engine.backgroundState.NetworkController.provider.ticker,
+ chainId: state.engine.backgroundState.NetworkController.provider.chainId,
tokens: state.engine.backgroundState.AssetsController.tokens.reduce((tokens, token) => {
tokens[token.address] = token;
return tokens;
diff --git a/app/components/UI/ReceiveRequest/__snapshots__/index.test.js.snap b/app/components/UI/ReceiveRequest/__snapshots__/index.test.js.snap
index 71e670559c0..84e57f358d0 100644
--- a/app/components/UI/ReceiveRequest/__snapshots__/index.test.js.snap
+++ b/app/components/UI/ReceiveRequest/__snapshots__/index.test.js.snap
@@ -28,6 +28,7 @@ exports[`ReceiveRequest should render correctly 1`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -70,6 +71,7 @@ exports[`ReceiveRequest should render correctly 1`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -104,6 +106,7 @@ exports[`ReceiveRequest should render correctly 1`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -126,6 +129,7 @@ exports[`ReceiveRequest should render correctly 1`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={true}
diff --git a/app/components/UI/SeedPhraseVideo/index.js b/app/components/UI/SeedPhraseVideo/index.js
new file mode 100644
index 00000000000..526c35be22e
--- /dev/null
+++ b/app/components/UI/SeedPhraseVideo/index.js
@@ -0,0 +1,122 @@
+import React, { useState } from 'react';
+import PropTypes from 'prop-types';
+import { StyleSheet, View, Image, TouchableOpacity } from 'react-native';
+import VideoPlayer from 'react-native-video-controls';
+import { colors, fontStyles } from '../../../styles/common';
+import Logger from '../../../util/Logger';
+import scaling from '../../../util/scaling';
+import Svg, { Circle, Path } from 'react-native-svg';
+import Text from '../../Base/Text';
+import { strings } from '../../../../locales/i18n';
+
+const styles = StyleSheet.create({
+ videoContainer: {
+ justifyContent: 'center',
+ alignItems: 'center',
+ position: 'relative',
+ borderRadius: 8,
+ overflow: 'hidden',
+ width: '100%',
+ height: 180
+ },
+ image: {
+ zIndex: 0,
+ width: scaling.scale(138),
+ height: scaling.scale(162)
+ },
+ cover: {
+ justifyContent: 'center',
+ alignItems: 'center',
+ zIndex: 1,
+ position: 'absolute',
+ left: 0,
+ top: 0,
+ backgroundColor: colors.grey,
+ opacity: 0.2,
+ width: '100%',
+ height: '100%'
+ },
+ errorWrapper: {
+ justifyContent: 'center',
+ alignItems: 'center'
+ },
+ errorText: {
+ ...fontStyles.normal,
+ color: colors.red
+ }
+});
+
+const FAILED_TO_LOAD_MSG = strings('app_settings.video_failed');
+
+// eslint-disable-next-line import/no-commonjs
+const explain_backup_seedphrase = require('../../../images/explain-backup-seedphrase.png');
+
+const video_source_uri =
+ 'https://github.com/MetaMask/metamask-mobile/blob/develop/app/videos/recovery-phrase.mp4?raw=true';
+
+const SeedPhraseVideo = ({ style }) => {
+ const [isPlaying, setPlaying] = useState(false);
+ const [isError, setError] = useState(false);
+
+ const onError = e => {
+ Logger.error(e, FAILED_TO_LOAD_MSG);
+ setError(true);
+ setPlaying(false);
+ };
+ const onPlay = () => {
+ Logger.log('User clicked play');
+ setPlaying(true);
+ };
+
+ return (
+
+ {!isPlaying ? (
+ <>
+ {isError ? (
+
+ {FAILED_TO_LOAD_MSG}
+
+ ) : (
+ <>
+
+ {isError ? <>> : <>>}
+
+
+
+ >
+ )}
+ >
+ ) : (
+
+ )}
+
+ );
+};
+
+SeedPhraseVideo.propTypes = {
+ style: PropTypes.object
+};
+
+export default SeedPhraseVideo;
diff --git a/app/components/UI/SeedphraseModal/__snapshots__/index.test.js.snap b/app/components/UI/SeedphraseModal/__snapshots__/index.test.js.snap
index 42a61c7aa8e..35cba44fe08 100644
--- a/app/components/UI/SeedphraseModal/__snapshots__/index.test.js.snap
+++ b/app/components/UI/SeedphraseModal/__snapshots__/index.test.js.snap
@@ -57,7 +57,7 @@ exports[`SeedphraseModal should render correctly 1`] = `
}
}
>
- What is a ‘Seed phrase’
+ What is a ‘Secret recovery phrase’
- A seed phrase is a set of twelve words that contains all the information about your wallet, including your funds. It’s like a secret code used to access your entire wallet.
+ A Secret Recovery phrase is a set of twelve words that contains all the information about your wallet, including your funds. It’s like a secret code used to access your entire wallet.
- You must keep your seed phrase secret and safe. If someone gets your seed phrase, they’ll gain control over your accounts.
+ You must keep your Secret Recovery phrase secret and safe. If someone gets your Secret Recovery phrase, they’ll gain control over your accounts.
diff --git a/app/components/UI/SkipAccountSecurityModal/__snapshots__/index.test.js.snap b/app/components/UI/SkipAccountSecurityModal/__snapshots__/index.test.js.snap
index c6f209c10d7..a5ee0e1963e 100644
--- a/app/components/UI/SkipAccountSecurityModal/__snapshots__/index.test.js.snap
+++ b/app/components/UI/SkipAccountSecurityModal/__snapshots__/index.test.js.snap
@@ -130,7 +130,7 @@ exports[`HintModal should render correctly 1`] = `
}
testID="skip-backup-text"
>
- I understand that if I lose my seed phrase I will not be able to access my wallet.
+ I understand that if I lose my Secret Recovery phrase I will not be able to access my wallet.
diff --git a/app/components/UI/Swaps/QuotesView.js b/app/components/UI/Swaps/QuotesView.js
index e50bc23b3c7..c9c438cd366 100644
--- a/app/components/UI/Swaps/QuotesView.js
+++ b/app/components/UI/Swaps/QuotesView.js
@@ -7,8 +7,8 @@ import MaterialCommunityIcons from 'react-native-vector-icons/MaterialCommunityI
import FAIcon from 'react-native-vector-icons/FontAwesome';
import BigNumber from 'bignumber.js';
import { NavigationContext } from 'react-navigation';
-import { swapsUtils, util } from '@estebanmino/controllers';
-import { WalletDevice } from '@metamask/controllers/';
+import { swapsUtils } from '@metamask/swaps-controller';
+import { WalletDevice, util } from '@metamask/controllers/';
import {
BNToHex,
@@ -20,8 +20,9 @@ import {
toWei,
weiToFiat
} from '../../../util/number';
+import { isMainNet } from '../../../util/networks';
import { safeToChecksumAddress } from '../../../util/address';
-import { getErrorMessage, getFetchParams, getQuotesNavigationsParams, isSwapsETH } from './utils';
+import { getErrorMessage, getFetchParams, getQuotesNavigationsParams, isSwapsNativeAsset } from './utils';
import { colors } from '../../../styles/common';
import { strings } from '../../../../locales/i18n';
@@ -49,8 +50,8 @@ import InfoModal from './components/InfoModal';
import useModalHandler from '../../Base/hooks/useModalHandler';
import useBalance from './utils/useBalance';
import useGasPrice from './utils/useGasPrice';
-import { decodeApproveData } from '../../../util/transactions';
-import Logger from '../../../util/Logger';
+import { trackErrorAsAnalytics } from '../../../util/analyticsV2';
+import { decodeApproveData, getTicker } from '../../../util/transactions';
const POLLING_INTERVAL = AppConstants.SWAPS.POLLING_INTERVAL;
const EDIT_MODE_GAS = 'EDIT_MODE_GAS';
@@ -198,6 +199,9 @@ const styles = StyleSheet.create({
termsButton: {
marginTop: 10,
marginBottom: 6
+ },
+ text: {
+ lineHeight: 20
}
});
@@ -209,7 +213,7 @@ async function resetAndStartPolling({ slippage, sourceToken, destinationToken, s
const contractExchangeRates = TokenRatesController.state.contractExchangeRates;
// ff the token is not in the wallet, we'll add it
if (
- destinationToken.address !== swapsUtils.ETH_SWAPS_TOKEN_ADDRESS &&
+ !isSwapsNativeAsset(destinationToken) &&
!contractExchangeRates[safeToChecksumAddress(destinationToken.address)]
) {
const { address, symbol, decimals } = destinationToken;
@@ -253,6 +257,8 @@ function SwapsQuotesView({
selectedAddress,
currentCurrency,
conversionRate,
+ chainId,
+ ticker,
isInPolling,
quotesLastFetched,
pollingCyclesLeft,
@@ -280,7 +286,7 @@ function SwapsQuotesView({
const hasConversionRate =
Boolean(destinationToken) &&
- (isSwapsETH(destinationToken) ||
+ (isSwapsNativeAsset(destinationToken) ||
Boolean(
Engine.context.TokenRatesController.state.contractExchangeRates?.[
safeToChecksumAddress(destinationToken.address)
@@ -373,7 +379,7 @@ function SwapsQuotesView({
const hasEnoughTokenBalance = tokenBalanceBN.gte(sourceBN);
const missingTokenBalance = hasEnoughTokenBalance ? null : sourceBN.minus(tokenBalanceBN);
- const ethAmountBN = sourceToken.address === swapsUtils.ETH_SWAPS_TOKEN_ADDRESS ? sourceBN : new BigNumber(0);
+ const ethAmountBN = isSwapsNativeAsset(sourceToken) ? sourceBN : new BigNumber(0);
const ethBalanceBN = new BigNumber(accounts[selectedAddress].balance);
const gasBN = toWei(selectedQuoteValue?.maxEthFee || '0');
const hasEnoughEthBalance = ethBalanceBN.gte(ethAmountBN.plus(gasBN));
@@ -681,7 +687,7 @@ function SwapsQuotesView({
speed_set: details.mode === 'advanced' ? undefined : details.mode,
gas_mode: details.mode === 'advanced' ? 'Advanced' : 'Basic',
gas_fees: weiToFiat(
- toWei(util.calcTokenAmount(newGasLimit.times(newGasPrice), 18)),
+ toWei(swapsUtils.calcTokenAmount(newGasLimit.times(newGasPrice), 18)),
conversionRate,
currentCurrency
)
@@ -772,7 +778,6 @@ function SwapsQuotesView({
slippage,
custom_slippage: slippage !== AppConstants.SWAPS.DEFAULT_SLIPPAGE
};
- Logger.error(error?.description, `Swaps: ${error?.key}`);
if (error?.key === swapsUtils.SwapsError.QUOTES_EXPIRED_ERROR) {
InteractionManager.runAfterInteractions(() => {
const parameters = {
@@ -788,6 +793,8 @@ function SwapsQuotesView({
Analytics.trackEventWithParameters(ANALYTICS_EVENT_OPTS.NO_QUOTES_AVAILABLE, {});
Analytics.trackEventWithParameters(ANALYTICS_EVENT_OPTS.NO_QUOTES_AVAILABLE, parameters, true);
});
+ } else {
+ trackErrorAsAnalytics(`Swaps: ${error?.key}`, error?.description);
}
},
[sourceToken, sourceAmount, destinationToken, hasEnoughTokenBalance, slippage]
@@ -1022,22 +1029,23 @@ function SwapsQuotesView({
{`${strings('swaps.you_need')} `}
- {!hasEnoughTokenBalance && sourceToken.address !== swapsUtils.ETH_SWAPS_TOKEN_ADDRESS
+ {!hasEnoughTokenBalance && !isSwapsNativeAsset(sourceToken)
? `${renderFromTokenMinimalUnit(missingTokenBalance, sourceToken.decimals)} ${
sourceToken.symbol
// eslint-disable-next-line no-mixed-spaces-and-tabs
} `
- : `${renderFromWei(missingEthBalance)} ETH `}
+ : `${renderFromWei(missingEthBalance)} ${getTicker(ticker)} `}
{!hasEnoughTokenBalance
? `${strings('swaps.more_to_complete')} `
: `${strings('swaps.more_gas_to_complete')} `}
- {(sourceToken.address === swapsUtils.ETH_SWAPS_TOKEN_ADDRESS ||
- (hasEnoughTokenBalance && !hasEnoughEthBalance)) && (
-
- {strings('swaps.buy_more_eth')}
-
- )}
+ {isMainNet(chainId) &&
+ (isSwapsNativeAsset(sourceToken) ||
+ (hasEnoughTokenBalance && !hasEnoughEthBalance)) && (
+
+ {strings('swaps.buy_more_eth')}
+
+ )}
)}
@@ -1209,7 +1217,7 @@ function SwapsQuotesView({
- {renderFromWei(toWei(selectedQuoteValue?.ethFee))} ETH
+ {renderFromWei(toWei(selectedQuoteValue?.ethFee))} {getTicker(ticker)}
{` ${weiToFiat(
@@ -1233,7 +1241,10 @@ function SwapsQuotesView({
- {renderFromWei(toWei(selectedQuoteValue?.maxEthFee || '0x0'))} ETH
+
+ {renderFromWei(toWei(selectedQuoteValue?.maxEthFee || '0x0'))}{' '}
+ {getTicker(ticker)}
+
{` ${weiToFiat(
toWei(selectedQuoteValue?.maxEthFee),
@@ -1296,20 +1307,20 @@ function SwapsQuotesView({
isVisible={isUpdateModalVisible}
toggleModal={toggleUpdateModal}
title={strings('swaps.quotes_update_often')}
- body={{strings('swaps.quotes_update_often_text')}}
+ body={{strings('swaps.quotes_update_often_text')}}
/>
{strings('swaps.price_difference_body')}}
+ body={{strings('swaps.price_difference_body')}}
/>
+
{strings('swaps.fee_text.get_the')} {strings('swaps.fee_text.best_price')}{' '}
{strings('swaps.fee_text.from_the')} {strings('swaps.fee_text.top_liquidity')}{' '}
{strings('swaps.fee_text.fee_is_applied', {
@@ -1326,6 +1337,7 @@ function SwapsQuotesView({
destinationToken={destinationToken}
selectedQuote={selectedQuoteId}
showOverallValue={hasConversionRate}
+ ticker={getTicker(ticker)}
/>
);
@@ -1374,6 +1387,14 @@ SwapsQuotesView.propTypes = {
* A string that represents the selected address
*/
selectedAddress: PropTypes.string,
+ /**
+ * Chain Id
+ */
+ chainId: PropTypes.string,
+ /**
+ * Native asset ticker
+ */
+ ticker: PropTypes.string,
isInPolling: PropTypes.bool,
quotesLastFetched: PropTypes.number,
topAggId: PropTypes.string,
@@ -1392,6 +1413,8 @@ SwapsQuotesView.propTypes = {
const mapStateToProps = state => ({
accounts: state.engine.backgroundState.AccountTrackerController.accounts,
+ chainId: state.engine.backgroundState.NetworkController.provider.chainId,
+ ticker: state.engine.backgroundState.NetworkController.provider.ticker,
selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress,
balances: state.engine.backgroundState.TokenBalancesController.contractBalances,
conversionRate: state.engine.backgroundState.CurrencyRateController.conversionRate,
diff --git a/app/components/UI/Swaps/SwapsLiveness.js b/app/components/UI/Swaps/SwapsLiveness.js
index 27ba0a6fb07..16d3324a1d8 100644
--- a/app/components/UI/Swaps/SwapsLiveness.js
+++ b/app/components/UI/Swaps/SwapsLiveness.js
@@ -1,4 +1,4 @@
-import { swapsUtils } from '@estebanmino/controllers';
+import { swapsUtils } from '@metamask/swaps-controller';
import { useCallback, useEffect, useState } from 'react';
import { AppState } from 'react-native';
import { connect } from 'react-redux';
@@ -10,18 +10,18 @@ import useInterval from '../../hooks/useInterval';
const SWAPS_ACTIVE = AppConstants.SWAPS.ACTIVE;
const POLLING_FREQUENCY = AppConstants.SWAPS.LIVENESS_POLLING_FREQUENCY;
-function SwapLiveness({ isLive, setLiveness }) {
+function SwapLiveness({ isLive, chainId, setLiveness }) {
const [hasMountChecked, setHasMountChecked] = useState(false);
const checkLiveness = useCallback(async () => {
try {
- const { mobile_active: liveness } = await swapsUtils.fetchSwapsFeatureLiveness();
- setLiveness(liveness);
+ const { mobile_active: liveness } = await swapsUtils.fetchSwapsFeatureLiveness(chainId);
+ setLiveness(liveness, chainId);
} catch (error) {
Logger.error(error, 'Swaps: error while fetching swaps liveness');
- setLiveness(false);
+ setLiveness(false, chainId);
}
- }, [setLiveness]);
+ }, [setLiveness, chainId]);
// Check on mount
useEffect(() => {
@@ -62,11 +62,12 @@ function SwapLiveness({ isLive, setLiveness }) {
}
const mapStateToProps = state => ({
- isLive: swapsLivenessSelector(state)
+ isLive: swapsLivenessSelector(state),
+ chainId: state.engine.backgroundState.NetworkController.provider.chainId
});
const mapDispatchToProps = dispatch => ({
- setLiveness: liveness => dispatch(setSwapsLiveness(liveness))
+ setLiveness: (liveness, chainId) => dispatch(setSwapsLiveness(liveness, chainId))
});
export default connect(
diff --git a/app/components/UI/Swaps/components/QuotesModal.js b/app/components/UI/Swaps/components/QuotesModal.js
index 9078cd8ca13..514245d3497 100644
--- a/app/components/UI/Swaps/components/QuotesModal.js
+++ b/app/components/UI/Swaps/components/QuotesModal.js
@@ -137,7 +137,8 @@ function QuotesModal({
conversionRate,
currentCurrency,
quoteValues,
- showOverallValue
+ showOverallValue,
+ ticker
}) {
const bestOverallValue = quoteValues[quotes[0].aggregator].overallValueOfQuote;
const [displayDetails, setDisplayDetails] = useState(false);
@@ -290,7 +291,7 @@ function QuotesModal({
{renderFromWei(toWei(selectedDetailsQuoteValues.ethFee))}{' '}
- ETH
+ {ticker}
{' '}
(~
@@ -466,6 +467,10 @@ QuotesModal.propTypes = {
* Currency code of the currently-active currency
*/
currentCurrency: PropTypes.string,
+ /**
+ * Native asset ticker
+ */
+ ticker: PropTypes.string,
quoteValues: PropTypes.object,
showOverallValue: PropTypes.bool
};
diff --git a/app/components/UI/Swaps/components/TokenIcon.js b/app/components/UI/Swaps/components/TokenIcon.js
index d0ef90f26b9..b857ef30c93 100644
--- a/app/components/UI/Swaps/components/TokenIcon.js
+++ b/app/components/UI/Swaps/components/TokenIcon.js
@@ -6,8 +6,10 @@ import RemoteImage from '../../../Base/RemoteImage';
import Text from '../../../Base/Text';
import { colors } from '../../../../styles/common';
-// eslint-disable-next-line import/no-commonjs
+/* eslint-disable import/no-commonjs */
const ethLogo = require('../../../../images/eth-logo.png');
+const bnbLogo = require('../../../../images/bnb-logo.png');
+/* eslint-enable import/no-commonjs */
const REGULAR_SIZE = 24;
const REGULAR_RADIUS = 12;
@@ -79,11 +81,11 @@ EmptyIcon.propTypes = {
};
function TokenIcon({ symbol, icon, medium, big, biggest, style }) {
- if (symbol === 'ETH') {
+ if (symbol === 'ETH' || symbol === 'BNB') {
return (
({
diff --git a/app/components/UI/Swaps/components/__snapshots__/TokenIcon.test.js.snap b/app/components/UI/Swaps/components/__snapshots__/TokenIcon.test.js.snap
index db85e8e40db..2e5a01e3d1d 100644
--- a/app/components/UI/Swaps/components/__snapshots__/TokenIcon.test.js.snap
+++ b/app/components/UI/Swaps/components/__snapshots__/TokenIcon.test.js.snap
@@ -38,6 +38,7 @@ exports[`TokenIcon component should Render correctly 3`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -134,6 +135,7 @@ exports[`TokenIcon component should Render correctly 7`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
diff --git a/app/components/UI/Swaps/components/__snapshots__/TokenSelectButton.test.js.snap b/app/components/UI/Swaps/components/__snapshots__/TokenSelectButton.test.js.snap
index 60cadcd3f84..a609ae4002a 100644
--- a/app/components/UI/Swaps/components/__snapshots__/TokenSelectButton.test.js.snap
+++ b/app/components/UI/Swaps/components/__snapshots__/TokenSelectButton.test.js.snap
@@ -34,6 +34,7 @@ exports[`TokenSelectButton component should Render correctly 1`] = `
link={false}
modal={false}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -96,6 +97,7 @@ exports[`TokenSelectButton component should Render correctly 2`] = `
link={false}
modal={false}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -158,6 +160,7 @@ exports[`TokenSelectButton component should Render correctly 3`] = `
link={false}
modal={false}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -221,6 +224,7 @@ exports[`TokenSelectButton component should Render correctly 4`] = `
link={false}
modal={false}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -286,6 +290,7 @@ exports[`TokenSelectButton component should Render correctly 5`] = `
link={false}
modal={false}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
diff --git a/app/components/UI/Swaps/index.js b/app/components/UI/Swaps/index.js
index f244c074dce..ab6b62f733a 100644
--- a/app/components/UI/Swaps/index.js
+++ b/app/components/UI/Swaps/index.js
@@ -15,7 +15,7 @@ import {
weiToFiat
} from '../../../util/number';
import { safeToChecksumAddress } from '../../../util/address';
-import { swapsUtils } from '@estebanmino/controllers';
+import { swapsUtils } from '@metamask/swaps-controller';
import { ANALYTICS_EVENT_OPTS } from '../../../util/analytics';
import {
@@ -30,10 +30,9 @@ import Device from '../../../util/Device';
import Engine from '../../../core/Engine';
import AppConstants from '../../../core/AppConstants';
-import { getEtherscanAddressUrl } from '../../../util/etherscan';
import { strings } from '../../../../locales/i18n';
import { colors } from '../../../styles/common';
-import { setQuotesNavigationsParams, isSwapsETH } from './utils';
+import { setQuotesNavigationsParams, isSwapsNativeAsset } from './utils';
import { getSwapsAmountNavbar } from '../Navbar';
import Onboarding from './components/Onboarding';
@@ -47,6 +46,7 @@ import TokenSelectButton from './components/TokenSelectButton';
import TokenSelectModal from './components/TokenSelectModal';
import SlippageModal from './components/SlippageModal';
import useBalance from './utils/useBalance';
+import useBlockExplorer from './utils/useBlockExplorer';
import InfoModal from './components/InfoModal';
const styles = StyleSheet.create({
@@ -130,7 +130,7 @@ const styles = StyleSheet.create({
}
});
-const SWAPS_ETH_ADDRESS = swapsUtils.ETH_SWAPS_TOKEN_ADDRESS;
+const SWAPS_NATIVE_ADDRESS = swapsUtils.NATIVE_SWAPS_TOKEN_ADDRESS;
const TOKEN_MINIMUM_SOURCES = 1;
const MAX_TOP_ASSETS = 20;
@@ -138,6 +138,9 @@ function SwapsAmountView({
swapsTokens,
accounts,
selectedAddress,
+ chainId,
+ provider,
+ frequentRpcList,
balances,
tokensWithBalance,
tokensTopAssets,
@@ -149,7 +152,8 @@ function SwapsAmountView({
setLiveness
}) {
const navigation = useContext(NavigationContext);
- const initialSource = navigation.getParam('sourceToken', SWAPS_ETH_ADDRESS);
+ const explorer = useBlockExplorer(provider, frequentRpcList);
+ const initialSource = navigation.getParam('sourceToken', SWAPS_NATIVE_ADDRESS);
const [amount, setAmount] = useState('0');
const [slippage, setSlippage] = useState(AppConstants.SWAPS.DEFAULT_SLIPPAGE);
const [isInitialLoadingTokens, setInitialLoadingTokens] = useState(false);
@@ -179,13 +183,13 @@ function SwapsAmountView({
useEffect(() => {
(async () => {
try {
- const { mobile_active: liveness } = await swapsUtils.fetchSwapsFeatureLiveness();
- setLiveness(liveness);
+ const { mobile_active: liveness } = await swapsUtils.fetchSwapsFeatureLiveness(chainId);
+ setLiveness(liveness, chainId);
if (liveness) {
// Triggered when a user enters the MetaMask Swap feature
InteractionManager.runAfterInteractions(() => {
const parameters = {
- source: initialSource === SWAPS_ETH_ADDRESS ? 'MainView' : 'TokenView',
+ source: initialSource === SWAPS_NATIVE_ADDRESS ? 'MainView' : 'TokenView',
activeCurrency: swapsTokens?.find(
token => token.address?.toLowerCase() === initialSource.toLowerCase()
)?.symbol
@@ -198,12 +202,12 @@ function SwapsAmountView({
}
} catch (error) {
Logger.error(error, 'Swaps: error while fetching swaps liveness');
- setLiveness(false);
+ setLiveness(false, chainId);
navigation.pop();
}
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [initialSource, navigation, setLiveness]);
+ }, [initialSource, chainId, navigation, setLiveness]);
const keypadViewRef = useRef(null);
@@ -251,11 +255,13 @@ function SwapsAmountView({
}, [destinationToken]);
const isTokenInBalances =
- sourceToken && !isSwapsETH(sourceToken) ? safeToChecksumAddress(sourceToken.address) in balances : false;
+ sourceToken && !isSwapsNativeAsset(sourceToken)
+ ? safeToChecksumAddress(sourceToken.address) in balances
+ : false;
useEffect(() => {
(async () => {
- if (sourceToken && !isSwapsETH(sourceToken) && !isTokenInBalances) {
+ if (sourceToken && !isSwapsNativeAsset(sourceToken) && !isTokenInBalances) {
setContractBalance(null);
setContractBalanceAsUnits(numberToBN(0));
const { AssetsContractController } = Engine.context;
@@ -285,9 +291,9 @@ function SwapsAmountView({
const controllerBalance = useBalance(accounts, balances, selectedAddress, sourceToken);
const controllerBalanceAsUnits = useBalance(accounts, balances, selectedAddress, sourceToken, { asUnits: true });
- const balance = isSwapsETH(sourceToken) || isTokenInBalances ? controllerBalance : contractBalance;
+ const balance = isSwapsNativeAsset(sourceToken) || isTokenInBalances ? controllerBalance : contractBalance;
const balanceAsUnits =
- isSwapsETH(sourceToken) || isTokenInBalances ? controllerBalanceAsUnits : contractBalanceAsUnits;
+ isSwapsNativeAsset(sourceToken) || isTokenInBalances ? controllerBalanceAsUnits : contractBalanceAsUnits;
const hasBalance = useMemo(() => {
if (!balanceAsUnits || !sourceToken) {
return false;
@@ -308,7 +314,7 @@ function SwapsAmountView({
return undefined;
}
let balanceFiat;
- if (isSwapsETH(sourceToken)) {
+ if (isSwapsNativeAsset(sourceToken)) {
balanceFiat = weiToFiat(toTokenMinimalUnit(amount, sourceToken?.decimals), conversionRate, currentCurrency);
} else {
const sourceAddress = safeToChecksumAddress(sourceToken.address);
@@ -319,7 +325,7 @@ function SwapsAmountView({
}, [amount, conversionRate, currentCurrency, hasInvalidDecimals, sourceToken, tokenExchangeRates]);
const destinationTokenHasEnoughOcurrances = useMemo(() => {
- if (!destinationToken || isSwapsETH(destinationToken)) {
+ if (!destinationToken || isSwapsNativeAsset(destinationToken)) {
return true;
}
return destinationToken?.occurances > TOKEN_MINIMUM_SOURCES;
@@ -330,7 +336,7 @@ function SwapsAmountView({
if (hasInvalidDecimals) {
return;
}
- if (!isSwapsETH(sourceToken) && !isTokenInBalances && !balanceAsUnits?.isZero()) {
+ if (!isSwapsNativeAsset(sourceToken) && !isTokenInBalances && !balanceAsUnits?.isZero()) {
const { AssetsController } = Engine.context;
const { address, symbol, decimals } = sourceToken;
await AssetsController.addToken(address, symbol, decimals);
@@ -404,10 +410,10 @@ function SwapsAmountView({
}
hideTokenVerificationModal();
navigation.navigate('Webview', {
- url: getEtherscanAddressUrl('mainnet', destinationToken.address),
+ url: explorer.token(destinationToken.address),
title: strings('swaps.verify')
});
- }, [destinationToken, hideTokenVerificationModal, navigation]);
+ }, [explorer, destinationToken, hideTokenVerificationModal, navigation]);
const handleAmountPress = useCallback(() => keypadViewRef?.current?.shake?.(), []);
@@ -481,7 +487,7 @@ function SwapsAmountView({
strings('swaps.available_to_swap', {
asset: `${balance} ${sourceToken.symbol}`
})}
- {!isSwapsETH(sourceToken) && hasBalance && (
+ {!isSwapsNativeAsset(sourceToken) && hasBalance && (
{' '}
{strings('swaps.use_max')}
@@ -519,23 +525,33 @@ function SwapsAmountView({
dismiss={toggleDestinationModal}
title={strings('swaps.convert_to')}
tokens={swapsTokens}
- initialTokens={[swapsUtils.ETH_SWAPS_TOKEN_OBJECT, ...tokensTopAssets.slice(0, MAX_TOP_ASSETS)]}
+ initialTokens={[
+ swapsUtils.getNativeSwapsToken(chainId),
+ ...tokensTopAssets.slice(0, MAX_TOP_ASSETS)
+ ]}
onItemPress={handleDestinationTokenPress}
excludeAddresses={[sourceToken?.address]}
/>
- {Boolean(destinationToken) && !isSwapsETH(destinationToken) ? (
+ {Boolean(destinationToken) && !isSwapsNativeAsset(destinationToken) ? (
destinationTokenHasEnoughOcurrances ? (
-
+
{strings('swaps.verified_on_sources', { sources: destinationToken.occurances })}
{` ${strings('swaps.verify_on')} `}
-
- Etherscan
-
+ {explorer.isValid ? (
+
+ {explorer.name}
+
+ ) : (
+ strings('swaps.a_block_explorer')
+ )}
.
@@ -548,7 +564,7 @@ function SwapsAmountView({
onInfoPress={toggleTokenVerificationModal}
>
{textStyle => (
-
+
{strings('swaps.only_verified_on', {
symbol: destinationToken.symbol,
@@ -557,9 +573,13 @@ function SwapsAmountView({
{`${strings('swaps.verify_address_on')} `}
-
- Etherscan
-
+ {explorer.isValid ? (
+
+ {explorer.name}
+
+ ) : (
+ strings('swaps.a_block_explorer')
+ )}
.
@@ -617,9 +637,13 @@ function SwapsAmountView({
{strings('swaps.token_multiple')}
{` ${strings('swaps.token_check')} `}
-
- Etherscan
-
+ {explorer.isValid ? (
+
+ {explorer.name}
+
+ ) : (
+ strings('swaps.a_block_explorer')
+ )}
{` ${strings('swaps.token_to_verify')}`}
}
@@ -672,6 +696,18 @@ SwapsAmountView.propTypes = {
* Function to set hasOnboarded
*/
setHasOnboarded: PropTypes.func,
+ /**
+ * Current Network provider
+ */
+ provider: PropTypes.object,
+ /**
+ * Chain Id
+ */
+ chainId: PropTypes.string,
+ /**
+ * Frequent RPC list from PreferencesController
+ */
+ frequentRpcList: PropTypes.array,
/**
* Function to set liveness
*/
@@ -686,6 +722,9 @@ const mapStateToProps = state => ({
conversionRate: state.engine.backgroundState.CurrencyRateController.conversionRate,
tokenExchangeRates: state.engine.backgroundState.TokenRatesController.contractExchangeRates,
currentCurrency: state.engine.backgroundState.CurrencyRateController.currentCurrency,
+ provider: state.engine.backgroundState.NetworkController.provider,
+ frequentRpcList: state.engine.backgroundState.PreferencesController.frequentRpcList,
+ chainId: state.engine.backgroundState.NetworkController.provider.chainId,
tokensWithBalance: swapsTokensWithBalanceSelector(state),
tokensTopAssets: swapsTopAssetsSelector(state),
userHasOnboarded: swapsHasOnboardedSelector(state)
@@ -693,7 +732,7 @@ const mapStateToProps = state => ({
const mapDispatchToProps = dispatch => ({
setHasOnboarded: hasOnboarded => dispatch(setSwapsHasOnboarded(hasOnboarded)),
- setLiveness: liveness => dispatch(setSwapsLiveness(liveness))
+ setLiveness: (liveness, chainId) => dispatch(setSwapsLiveness(liveness, chainId))
});
export default connect(
diff --git a/app/components/UI/Swaps/utils/index.js b/app/components/UI/Swaps/utils/index.js
index 31bf2a6f10c..46baab4f9fe 100644
--- a/app/components/UI/Swaps/utils/index.js
+++ b/app/components/UI/Swaps/utils/index.js
@@ -1,10 +1,25 @@
import { useMemo } from 'react';
import BigNumber from 'bignumber.js';
-import { swapsUtils } from '@estebanmino/controllers';
+import { swapsUtils } from '@metamask/swaps-controller';
import { strings } from '../../../../../locales/i18n';
+import AppConstants from '../../../../core/AppConstants';
-export function isSwapsETH(token) {
- return Boolean(token) && token?.address === swapsUtils.ETH_SWAPS_TOKEN_ADDRESS;
+const { ETH_CHAIN_ID, BSC_CHAIN_ID, SWAPS_TESTNET_CHAIN_ID } = swapsUtils;
+
+const allowedChainIds = [ETH_CHAIN_ID, BSC_CHAIN_ID];
+
+export function isSwapsAllowed(chainId) {
+ if (!AppConstants.SWAPS.ACTIVE) {
+ return false;
+ }
+ if (!AppConstants.SWAPS.ONLY_MAINNET) {
+ allowedChainIds.push(SWAPS_TESTNET_CHAIN_ID);
+ }
+ return allowedChainIds.includes(chainId);
+}
+
+export function isSwapsNativeAsset(token) {
+ return Boolean(token) && token?.address === swapsUtils.NATIVE_SWAPS_TOKEN_ADDRESS;
}
/**
diff --git a/app/components/UI/Swaps/utils/useBalance.js b/app/components/UI/Swaps/utils/useBalance.js
index 4d4e09bfee1..d006be26a8f 100644
--- a/app/components/UI/Swaps/utils/useBalance.js
+++ b/app/components/UI/Swaps/utils/useBalance.js
@@ -1,6 +1,6 @@
-import { swapsUtils } from '@estebanmino/controllers';
import { useMemo } from 'react';
import numberToBN from 'number-to-bn';
+import { isSwapsNativeAsset } from '.';
import { renderFromTokenMinimalUnit, renderFromWei } from '../../../../util/number';
import { safeToChecksumAddress } from '../../../../util/address';
@@ -9,7 +9,7 @@ function useBalance(accounts, balances, selectedAddress, sourceToken, { asUnits
if (!sourceToken) {
return null;
}
- if (sourceToken.address === swapsUtils.ETH_SWAPS_TOKEN_ADDRESS) {
+ if (isSwapsNativeAsset(sourceToken)) {
if (asUnits) {
// Controller stores balances in hex for ETH
return numberToBN((accounts[selectedAddress] && accounts[selectedAddress].balance) || 0);
diff --git a/app/components/UI/Swaps/utils/useBlockExplorer.js b/app/components/UI/Swaps/utils/useBlockExplorer.js
new file mode 100644
index 00000000000..193c7fb1a8b
--- /dev/null
+++ b/app/components/UI/Swaps/utils/useBlockExplorer.js
@@ -0,0 +1,76 @@
+import { useCallback, useEffect, useState } from 'react';
+import etherscanLink from '@metamask/etherscan-link';
+import { RPC } from '../../../../constants/network';
+import { findBlockExplorerForRpc, getBlockExplorerName } from '../../../../util/networks';
+import { strings } from '../../../../../locales/i18n';
+
+function useBlockExplorer(provider, frequentRpcList) {
+ const [explorer, setExplorer] = useState({ name: '', value: null, isValid: false, isRPC: false });
+
+ useEffect(() => {
+ if (provider.type === RPC) {
+ try {
+ const blockExplorer = findBlockExplorerForRpc(provider.rpcTarget, frequentRpcList);
+ if (!blockExplorer) {
+ throw new Error('No block explorer url');
+ }
+ const url = new URL(blockExplorer);
+ if (!['http:', 'https:'].includes(url.protocol)) {
+ throw new Error('Block explorer URL is not a valid http(s) protocol');
+ }
+
+ const name = getBlockExplorerName(blockExplorer) || strings('swaps.block_explorer');
+ setExplorer({ name, value: blockExplorer, isValid: true, isRPC: true });
+ } catch {
+ setExplorer({ name: '', value: null, isValid: false, isRPC: false });
+ }
+ } else {
+ setExplorer({ name: 'Etherscan', value: provider.chainId, isValid: true, isRPC: false });
+ }
+ }, [frequentRpcList, provider]);
+
+ const tx = useCallback(
+ hash => {
+ if (!explorer.isValid) {
+ return '';
+ }
+
+ const create = explorer.isRPC ? etherscanLink.createCustomExplorerLink : etherscanLink.createExplorerLink;
+ return create(hash, explorer.value);
+ },
+ [explorer]
+ );
+ const account = useCallback(
+ address => {
+ if (!explorer.isValid) {
+ return '';
+ }
+
+ const create = explorer.isRPC ? etherscanLink.createCustomAccountLink : etherscanLink.createAccountLink;
+ return create(address, explorer.value);
+ },
+ [explorer]
+ );
+ const token = useCallback(
+ address => {
+ if (!explorer.isValid) {
+ return '';
+ }
+
+ const create = explorer.isRPC
+ ? etherscanLink.createCustomTokenTrackerLink
+ : etherscanLink.createTokenTrackerLink;
+ return create(address, explorer.value);
+ },
+ [explorer]
+ );
+
+ return {
+ ...explorer,
+ tx,
+ account,
+ token
+ };
+}
+
+export default useBlockExplorer;
diff --git a/app/components/UI/SwitchCustomNetwork/__snapshots__/index.test.js.snap b/app/components/UI/SwitchCustomNetwork/__snapshots__/index.test.js.snap
index cab6e467afd..b1c7d1a29d4 100644
--- a/app/components/UI/SwitchCustomNetwork/__snapshots__/index.test.js.snap
+++ b/app/components/UI/SwitchCustomNetwork/__snapshots__/index.test.js.snap
@@ -24,6 +24,7 @@ exports[`SwitchCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -53,6 +54,7 @@ exports[`SwitchCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -79,6 +81,7 @@ exports[`SwitchCustomNetwork should render correctly 1`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -97,6 +100,7 @@ exports[`SwitchCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -117,6 +121,7 @@ exports[`SwitchCustomNetwork should render correctly 1`] = `
modal={false}
noMargin={true}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
diff --git a/app/components/UI/Tokens/__snapshots__/index.test.js.snap b/app/components/UI/Tokens/__snapshots__/index.test.js.snap
index b2c6ecffe93..08ad2070218 100644
--- a/app/components/UI/Tokens/__snapshots__/index.test.js.snap
+++ b/app/components/UI/Tokens/__snapshots__/index.test.js.snap
@@ -1,5 +1,219 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
+exports[`Tokens should hide zero balance tokens when setting is on 1`] = `
+
+
+
+
+
+
+ 0 ETH
+
+
+
+
+
+
+
+ < 0.00001 BAT
+
+
+
+
+
+ Buy ETH
+
+
+
+
+
+
+ ADD TOKENS
+
+
+
+
+
+
+`;
+
exports[`Tokens should render correctly 1`] = `
`;
+
+exports[`Tokens should show all balance tokens when hideZeroBalanceTokens setting is off 1`] = `
+
+
+
+
+
+
+ 0 ETH
+
+
+
+
+
+
+
+ < 0.00001 BAT
+
+
+
+
+
+
+
+ 0 LINK
+
+
+
+
+
+ Buy ETH
+
+
+
+
+
+
+ ADD TOKENS
+
+
+
+
+
+
+`;
diff --git a/app/components/UI/Tokens/index.js b/app/components/UI/Tokens/index.js
index cd1f46b10d5..7903889d0e5 100644
--- a/app/components/UI/Tokens/index.js
+++ b/app/components/UI/Tokens/index.js
@@ -17,6 +17,7 @@ import { ANALYTICS_EVENT_OPTS } from '../../../util/analytics';
import StyledButton from '../StyledButton';
import { allowedToBuy } from '../FiatOrders';
import NetworkMainAssetLogo from '../NetworkMainAssetLogo';
+import { isMainNet } from '../../../util/networks';
const styles = StyleSheet.create({
wrapper: {
@@ -135,7 +136,11 @@ class Tokens extends PureComponent {
/**
* Chain id
*/
- chainId: PropTypes.string
+ chainId: PropTypes.string,
+ /**
+ * A bool that represents if the user wants to hide zero balance token
+ */
+ hideZeroBalanceTokens: PropTypes.bool
};
actionSheet = null;
@@ -162,14 +167,23 @@ class Tokens extends PureComponent {
);
renderItem = asset => {
- const { conversionRate, currentCurrency, tokenBalances, tokenExchangeRates, primaryCurrency } = this.props;
+ const {
+ chainId,
+ conversionRate,
+ currentCurrency,
+ tokenBalances,
+ tokenExchangeRates,
+ primaryCurrency
+ } = this.props;
const itemAddress = safeToChecksumAddress(asset.address);
const logo = asset.logo || ((contractMap[itemAddress] && contractMap[itemAddress].logo) || undefined);
const exchangeRate = itemAddress in tokenExchangeRates ? tokenExchangeRates[itemAddress] : undefined;
const balance =
asset.balance ||
(itemAddress in tokenBalances ? renderFromTokenMinimalUnit(tokenBalances[itemAddress], asset.decimals) : 0);
- const balanceFiat = asset.balanceFiat || balanceToFiat(balance, conversionRate, exchangeRate, currentCurrency);
+ const balanceFiat = isMainNet(chainId)
+ ? asset.balanceFiat || balanceToFiat(balance, conversionRate, exchangeRate, currentCurrency)
+ : null;
const balanceValue = `${balance} ${asset.symbol}`;
// render balances according to primary currency
@@ -232,7 +246,7 @@ class Tokens extends PureComponent {
const hasTokensBalance =
hasTokens &&
tokens.some(
- token => !token.isETH && tokenBalances[token.address] && !tokenBalances[token.address].isZero()
+ token => !token.isETH && tokenBalances[token.address] && !tokenBalances[token.address]?.isZero?.()
);
return (
@@ -248,11 +262,18 @@ class Tokens extends PureComponent {
}
renderList() {
- const { tokens } = this.props;
+ const { tokens, hideZeroBalanceTokens, tokenBalances } = this.props;
+ const tokensToDisplay = hideZeroBalanceTokens
+ ? tokens.filter(token => {
+ const { address, isETH } = token;
+ return (tokenBalances[address] && !tokenBalances[address]?.isZero?.()) || isETH;
+ // eslint-disable-next-line no-mixed-spaces-and-tabs
+ })
+ : tokens;
return (
- {tokens.map(item => this.renderItem(item))}
+ {tokensToDisplay.map(item => this.renderItem(item))}
{this.renderBuyEth()}
{this.renderFooter()}
@@ -307,7 +328,8 @@ const mapStateToProps = state => ({
conversionRate: state.engine.backgroundState.CurrencyRateController.conversionRate,
primaryCurrency: state.settings.primaryCurrency,
tokenBalances: state.engine.backgroundState.TokenBalancesController.contractBalances,
- tokenExchangeRates: state.engine.backgroundState.TokenRatesController.contractExchangeRates
+ tokenExchangeRates: state.engine.backgroundState.TokenRatesController.contractExchangeRates,
+ hideZeroBalanceTokens: state.settings.hideZeroBalanceTokens
});
export default connect(mapStateToProps)(Tokens);
diff --git a/app/components/UI/Tokens/index.test.js b/app/components/UI/Tokens/index.test.js
index 6865c592143..9ede7381491 100644
--- a/app/components/UI/Tokens/index.test.js
+++ b/app/components/UI/Tokens/index.test.js
@@ -2,6 +2,7 @@ import React from 'react';
import { shallow } from 'enzyme';
import Tokens from './';
import configureMockStore from 'redux-mock-store';
+import { BN } from 'ethereumjs-util';
const mockStore = configureMockStore();
@@ -38,4 +39,88 @@ describe('Tokens', () => {
});
expect(wrapper.dive()).toMatchSnapshot();
});
+
+ it('should hide zero balance tokens when setting is on', () => {
+ const initialState = {
+ engine: {
+ backgroundState: {
+ AssetsController: {
+ tokens: [
+ { symbol: 'ETH', address: '0x0', decimals: 18, isETH: true },
+ { symbol: 'BAT', address: '0x01', decimals: 18 },
+ { symbol: 'LINK', address: '0x02', decimals: 18 }
+ ]
+ },
+ TokenRatesController: {
+ contractExchangeRates: {}
+ },
+ CurrencyRateController: {
+ currentCurrency: 'USD',
+ conversionRate: 1
+ },
+ TokenBalancesController: {
+ contractBalances: {
+ '0x01': new BN(2),
+ '0x02': new BN(0)
+ }
+ },
+ NetworkController: {
+ provider: { chainId: '1' }
+ }
+ }
+ },
+ settings: {
+ primaryCurrency: 'usd',
+ hideZeroBalanceTokens: true
+ }
+ };
+
+ const wrapper = shallow(, {
+ context: { store: mockStore(initialState) }
+ });
+ // ETH and BAT should display
+ expect(wrapper.dive()).toMatchSnapshot();
+ });
+
+ it('should show all balance tokens when hideZeroBalanceTokens setting is off', () => {
+ const initialState = {
+ engine: {
+ backgroundState: {
+ AssetsController: {
+ tokens: [
+ { symbol: 'ETH', address: '0x0', decimals: 18, isETH: true },
+ { symbol: 'BAT', address: '0x01', decimals: 18 },
+ { symbol: 'LINK', address: '0x02', decimals: 18 }
+ ]
+ },
+ TokenRatesController: {
+ contractExchangeRates: {}
+ },
+ CurrencyRateController: {
+ currentCurrency: 'USD',
+ conversionRate: 1
+ },
+ TokenBalancesController: {
+ contractBalances: {
+ '0x01': new BN(2),
+ '0x02': new BN(0)
+ }
+ },
+ NetworkController: {
+ provider: { chainId: '1' }
+ }
+ }
+ },
+ settings: {
+ primaryCurrency: 'usd',
+ hideZeroBalanceTokens: false
+ }
+ };
+
+ const wrapper = shallow(, {
+ context: { store: mockStore(initialState) }
+ });
+ // All three should display
+ expect(wrapper.dive()).toMatchSnapshot();
+ });
});
diff --git a/app/components/UI/TransactionElement/TransactionDetails/__snapshots__/index.test.js.snap b/app/components/UI/TransactionElement/TransactionDetails/__snapshots__/index.test.js.snap
index 554bf0e3fc0..fae6798ed89 100644
--- a/app/components/UI/TransactionElement/TransactionDetails/__snapshots__/index.test.js.snap
+++ b/app/components/UI/TransactionElement/TransactionDetails/__snapshots__/index.test.js.snap
@@ -1,122 +1,37 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`TransactionDetails should render correctly 1`] = `
-
-
-
-
- Status
-
-
-
-
-
- Date
-
-
- [missing "en.date.months.NaN" translation] NaN at NaN:NaNam
-
-
-
-
-
-
- From
-
-
-
-
-
-
-
- To
-
-
-
-
-
-
-
-
-
-
+ }
+ transactionDetails={
+ Object {
+ "renderFrom": "0x0",
+ "renderGas": "21000",
+ "renderGasPrice": "2",
+ "renderTo": "0x1",
+ "renderTotalValue": "2 TKN / 0.001 ETH",
+ "renderTotalValueFiat": "",
+ "renderValue": "2 TKN",
+ "transactionHash": "0x2",
+ }
+ }
+ transactionObject={
+ Object {
+ "networkID": "1",
+ "status": "confirmed",
+ "transaction": Object {
+ "nonce": "",
+ },
+ }
+ }
+/>
`;
diff --git a/app/components/UI/TransactionElement/TransactionDetails/index.js b/app/components/UI/TransactionElement/TransactionDetails/index.js
index 647bb168250..4a704a823b7 100644
--- a/app/components/UI/TransactionElement/TransactionDetails/index.js
+++ b/app/components/UI/TransactionElement/TransactionDetails/index.js
@@ -3,7 +3,12 @@ import PropTypes from 'prop-types';
import { TouchableOpacity, StyleSheet, View } from 'react-native';
import { colors, fontStyles } from '../../../../styles/common';
import { strings } from '../../../../../locales/i18n';
-import { getNetworkTypeById, findBlockExplorerForRpc, getBlockExplorerName } from '../../../../util/networks';
+import {
+ getNetworkTypeById,
+ findBlockExplorerForRpc,
+ getBlockExplorerName,
+ isMainNet
+} from '../../../../util/networks';
import { getEtherscanTransactionUrl, getEtherscanBaseUrl } from '../../../../util/etherscan';
import Logger from '../../../../util/Logger';
import { connect } from 'react-redux';
@@ -16,6 +21,7 @@ import StatusText from '../../../Base/StatusText';
import Text from '../../../Base/Text';
import DetailsModal from '../../../Base/DetailsModal';
import { RPC } from '../../../../constants/network';
+import { withNavigation } from 'react-navigation';
const styles = StyleSheet.create({
viewOnEtherscan: {
@@ -61,6 +67,10 @@ class TransactionDetails extends PureComponent {
/* navigation object required to push new views
*/
navigation: PropTypes.object,
+ /**
+ * Chain Id
+ */
+ chainId: PropTypes.string,
/**
* Object representing the selected the selected network
*/
@@ -166,6 +176,7 @@ class TransactionDetails extends PureComponent {
render = () => {
const {
+ chainId,
transactionDetails,
transactionObject,
transactionObject: {
@@ -223,7 +234,9 @@ class TransactionDetails extends PureComponent {
amount={transactionDetails.summaryAmount}
fee={transactionDetails.summaryFee}
totalAmount={transactionDetails.summaryTotalAmount}
- secondaryTotalAmount={transactionDetails.summarySecondaryTotalAmount}
+ secondaryTotalAmount={
+ isMainNet(chainId) ? transactionDetails.summarySecondaryTotalAmount : undefined
+ }
gasEstimationReady
transactionType={transactionDetails.transactionType}
/>
@@ -247,6 +260,7 @@ class TransactionDetails extends PureComponent {
const mapStateToProps = state => ({
network: state.engine.backgroundState.NetworkController,
+ chainId: state.engine.backgroundState.NetworkController.provider.chainId,
frequentRpcList: state.engine.backgroundState.PreferencesController.frequentRpcList
});
-export default connect(mapStateToProps)(TransactionDetails);
+export default connect(mapStateToProps)(withNavigation(TransactionDetails));
diff --git a/app/components/UI/TransactionElement/TransactionDetails/index.test.js b/app/components/UI/TransactionElement/TransactionDetails/index.test.js
index b644919a622..a198e801c93 100644
--- a/app/components/UI/TransactionElement/TransactionDetails/index.test.js
+++ b/app/components/UI/TransactionElement/TransactionDetails/index.test.js
@@ -52,6 +52,6 @@ describe('TransactionDetails', () => {
context: { store: mockStore(initialState) }
}
);
- expect(wrapper.dive()).toMatchSnapshot();
+ expect(wrapper).toMatchSnapshot();
});
});
diff --git a/app/components/UI/TransactionElement/index.js b/app/components/UI/TransactionElement/index.js
index c08e11a7506..c8bee8401a4 100644
--- a/app/components/UI/TransactionElement/index.js
+++ b/app/components/UI/TransactionElement/index.js
@@ -15,6 +15,7 @@ import { TRANSACTION_TYPES } from '../../../util/transactions';
import ListItem from '../../Base/ListItem';
import StatusText from '../../Base/StatusText';
import DetailsModal from '../../Base/DetailsModal';
+import { isMainNet } from '../../../util/networks';
import { WalletDevice } from '@metamask/controllers/';
const styles = StyleSheet.create({
@@ -81,10 +82,6 @@ const transactionIconReceivedFailed = require('../../../images/transaction-icons
class TransactionElement extends PureComponent {
static propTypes = {
assetSymbol: PropTypes.string,
- /**
- /* navigation object required to push new views
- */
- navigation: PropTypes.object,
/**
* Asset object (in this case ERC721 token)
*/
@@ -114,7 +111,11 @@ class TransactionElement extends PureComponent {
*/
onCancelAction: PropTypes.func,
swapsTransactions: PropTypes.object,
- swapsTokens: PropTypes.arrayOf(PropTypes.object)
+ swapsTokens: PropTypes.arrayOf(PropTypes.object),
+ /**
+ * Chain Id
+ */
+ chainId: PropTypes.string
};
state = {
@@ -173,7 +174,7 @@ class TransactionElement extends PureComponent {
'transactions.from_device_label'
// eslint-disable-next-line no-mixed-spaces-and-tabs
)}`
- : `${toDateFormat(tx.time)}
+ : `${toDateFormat(tx.time)}
`
}`;
};
@@ -184,7 +185,8 @@ class TransactionElement extends PureComponent {
*/
renderImportTime = () => {
const { tx, identities, selectedAddress } = this.props;
- if (tx.insertImportTime && identities[selectedAddress].importTime) {
+ const accountImportTime = identities[selectedAddress]?.importTime;
+ if (tx.insertImportTime && accountImportTime) {
return (
<>
@@ -192,7 +194,7 @@ class TransactionElement extends PureComponent {
{`${strings('transactions.import_wallet_row')} `}
- {toDateFormat(identities[selectedAddress].importTime)}
+ {toDateFormat(accountImportTime)}
>
);
@@ -233,12 +235,13 @@ class TransactionElement extends PureComponent {
renderTxElement = transactionElement => {
const {
identities,
+ chainId,
selectedAddress,
tx: { time, status }
} = this.props;
const { value, fiatValue = false, actionKey } = transactionElement;
const renderTxActions = status === 'submitted' || status === 'approved';
- const accountImportTime = identities[selectedAddress].importTime;
+ const accountImportTime = identities[selectedAddress]?.importTime;
return (
<>
{accountImportTime > time && this.renderImportTime()}
@@ -253,7 +256,7 @@ class TransactionElement extends PureComponent {
{Boolean(value) && (
{value}
- {fiatValue}
+ {isMainNet(chainId) && {fiatValue}}
)}
@@ -341,7 +344,6 @@ class TransactionElement extends PureComponent {
@@ -371,11 +373,12 @@ class TransactionElement extends PureComponent {
}
const mapStateToProps = state => ({
+ ticker: state.engine.backgroundState.NetworkController.provider.ticker,
+ chainId: state.engine.backgroundState.NetworkController.provider.chainId,
identities: state.engine.backgroundState.PreferencesController.identities,
primaryCurrency: state.settings.primaryCurrency,
selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress,
swapsTransactions: state.engine.backgroundState.TransactionController.swapsTransactions || {},
- swapsTokens: state.engine.backgroundState.SwapsController.tokens,
- ticker: state.engine.backgroundState.NetworkController.provider.ticker
+ swapsTokens: state.engine.backgroundState.SwapsController.tokens
});
export default connect(mapStateToProps)(TransactionElement);
diff --git a/app/components/UI/TransactionElement/utils.js b/app/components/UI/TransactionElement/utils.js
index 88a08654d9f..8c7753326cc 100644
--- a/app/components/UI/TransactionElement/utils.js
+++ b/app/components/UI/TransactionElement/utils.js
@@ -23,9 +23,10 @@ import {
} from '../../../util/transactions';
import contractMap from '@metamask/contract-metadata';
import { toChecksumAddress } from 'ethereumjs-util';
-import { swapsUtils } from '@estebanmino/controllers';
+import { swapsUtils } from '@metamask/swaps-controller';
+import { isSwapsNativeAsset } from '../Swaps/utils';
-const { ETH_SWAPS_TOKEN_ADDRESS, SWAPS_CONTRACT_ADDRESS } = swapsUtils;
+const { getSwapsContractAddress } = swapsUtils;
function calculateTotalGas(gas, gasPrice) {
const gasBN = hexToBN(gas);
@@ -604,16 +605,14 @@ function decodeSwapsTx(args) {
);
}
- const sourceExchangeRate =
- sourceToken.address === ETH_SWAPS_TOKEN_ADDRESS
- ? 1
- : contractExchangeRates[safeToChecksumAddress(sourceToken.address)];
+ const sourceExchangeRate = isSwapsNativeAsset(sourceToken)
+ ? 1
+ : contractExchangeRates[safeToChecksumAddress(sourceToken.address)];
const renderSourceTokenFiatNumber = balanceToFiatNumber(decimalSourceAmount, conversionRate, sourceExchangeRate);
- const destinationExchangeRate =
- destinationToken.address === ETH_SWAPS_TOKEN_ADDRESS
- ? 1
- : contractExchangeRates[safeToChecksumAddress(destinationToken.address)];
+ const destinationExchangeRate = isSwapsNativeAsset(destinationToken)
+ ? 1
+ : contractExchangeRates[safeToChecksumAddress(destinationToken.address)];
const renderDestinationTokenFiatNumber = balanceToFiatNumber(
decimalDestinationAmount,
conversionRate,
@@ -682,13 +681,13 @@ function decodeSwapsTx(args) {
* currentCurrency, exchangeRate, contractExchangeRates, collectibleContracts, tokens
*/
export default async function decodeTransaction(args) {
- const { tx, selectedAddress, ticker, swapsTransactions = {} } = args;
+ const { tx, selectedAddress, ticker, chainId, swapsTransactions = {} } = args;
const { isTransfer } = tx || {};
- const actionKey = await getActionKey(tx, selectedAddress, ticker);
+ const actionKey = await getActionKey(tx, selectedAddress, ticker, chainId);
let transactionElement, transactionDetails;
- if (tx.transaction.to === SWAPS_CONTRACT_ADDRESS || swapsTransactions[tx.id]) {
+ if (tx.transaction.to?.toLowerCase() === getSwapsContractAddress(chainId) || swapsTransactions[tx.id]) {
const [transactionElement, transactionDetails] = decodeSwapsTx({ ...args, actionKey });
if (transactionElement && transactionDetails) return [transactionElement, transactionDetails];
}
diff --git a/app/components/UI/TransactionReview/TransactionReviewFeeCard/__snapshots__/index.test.js.snap b/app/components/UI/TransactionReview/TransactionReviewFeeCard/__snapshots__/index.test.js.snap
index c4aede01781..e0a24358079 100644
--- a/app/components/UI/TransactionReview/TransactionReviewFeeCard/__snapshots__/index.test.js.snap
+++ b/app/components/UI/TransactionReview/TransactionReviewFeeCard/__snapshots__/index.test.js.snap
@@ -20,6 +20,7 @@ exports[`TransactionReviewFeeCard should render correctly 1`] = `
link={false}
modal={false}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -39,6 +40,7 @@ exports[`TransactionReviewFeeCard should render correctly 1`] = `
link={false}
modal={false}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -59,6 +61,7 @@ exports[`TransactionReviewFeeCard should render correctly 1`] = `
link={false}
modal={false}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
@@ -81,6 +84,7 @@ exports[`TransactionReviewFeeCard should render correctly 1`] = `
link={true}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={false}
@@ -121,6 +125,7 @@ exports[`TransactionReviewFeeCard should render correctly 1`] = `
link={false}
modal={false}
primary={true}
+ red={false}
reset={false}
right={false}
small={false}
diff --git a/app/components/UI/TransactionReview/index.js b/app/components/UI/TransactionReview/index.js
index c6d6461ef81..e8c7520ee74 100644
--- a/app/components/UI/TransactionReview/index.js
+++ b/app/components/UI/TransactionReview/index.js
@@ -124,6 +124,10 @@ class TransactionReview extends PureComponent {
* Current provider ticker
*/
ticker: PropTypes.string,
+ /**
+ * Chain id
+ */
+ chainId: PropTypes.string,
/**
* ETH or fiat, depending on user setting
*/
@@ -174,14 +178,15 @@ class TransactionReview extends PureComponent {
validate,
transaction,
transaction: { data, to },
- tokens
+ tokens,
+ chainId
} = this.props;
let { showHexData } = this.props;
let assetAmount, conversionRate, fiatValue;
showHexData = showHexData || data;
const approveTransaction = data && data.substr(0, 10) === APPROVE_FUNCTION_SIGNATURE;
const error = validate && (await validate());
- const actionKey = await getTransactionReviewActionKey(transaction);
+ const actionKey = await getTransactionReviewActionKey(transaction, chainId);
if (approveTransaction) {
let contract = contractMap[safeToChecksumAddress(to)];
if (!contract) {
@@ -358,6 +363,7 @@ const mapStateToProps = state => ({
contractExchangeRates: state.engine.backgroundState.TokenRatesController.contractExchangeRates,
conversionRate: state.engine.backgroundState.CurrencyRateController.conversionRate,
ticker: state.engine.backgroundState.NetworkController.provider.ticker,
+ chainId: state.engine.backgroundState.NetworkController.provider.chainId,
showHexData: state.settings.showHexData,
transaction: getNormalizedTxState(state),
browser: state.browser,
diff --git a/app/components/Views/AccountBackupStep1/__snapshots__/index.test.js.snap b/app/components/Views/AccountBackupStep1/__snapshots__/index.test.js.snap
index 0f5b8221dc3..244e8059602 100644
--- a/app/components/Views/AccountBackupStep1/__snapshots__/index.test.js.snap
+++ b/app/components/Views/AccountBackupStep1/__snapshots__/index.test.js.snap
@@ -40,7 +40,7 @@ exports[`AccountBackupStep1 should render correctly 1`] = `
Array [
"Create password",
"Secure wallet",
- "Confirm seed phrase",
+ "Confirm Secret Recovery phrase",
]
}
/>
@@ -68,21 +68,7 @@ exports[`AccountBackupStep1 should render correctly 1`] = `
>
Secure your wallet
-
+
- seed phrase
+ Secret Recovery phrase
in a place you trust.
diff --git a/app/components/Views/AccountBackupStep1/index.js b/app/components/Views/AccountBackupStep1/index.js
index a163643acd8..da71f756c23 100644
--- a/app/components/Views/AccountBackupStep1/index.js
+++ b/app/components/Views/AccountBackupStep1/index.js
@@ -1,5 +1,5 @@
import React, { useState, useEffect } from 'react';
-import { ScrollView, TouchableOpacity, Text, View, SafeAreaView, StyleSheet, Image, BackHandler } from 'react-native';
+import { ScrollView, TouchableOpacity, Text, View, SafeAreaView, StyleSheet, BackHandler } from 'react-native';
import PropTypes from 'prop-types';
import AsyncStorage from '@react-native-community/async-storage';
import { colors, fontStyles } from '../../../styles/common';
@@ -15,8 +15,7 @@ import Engine from '../../../core/Engine';
import { ONBOARDING_WIZARD, METRICS_OPT_IN } from '../../../constants/storage';
import { CHOOSE_PASSWORD_STEPS } from '../../../constants/onboarding';
import SkipAccountSecurityModal from '../../UI/SkipAccountSecurityModal';
-
-const explain_backup_seedphrase = require('../../../images/explain-backup-seedphrase.png'); // eslint-disable-line
+import SeedPhraseVideo from '../../UI/SeedPhraseVideo';
const styles = StyleSheet.create({
mainWrapper: {
@@ -96,10 +95,6 @@ const styles = StyleSheet.create({
},
ctaContainer: {
marginBottom: 30
- },
- image: {
- width: scaling.scale(138),
- height: scaling.scale(162)
}
});
@@ -186,12 +181,7 @@ const AccountBackupStep1 = props => {
{strings('account_backup_step_1.title')}
-
+
{strings('account_backup_step_1.info_text_1_1')}{' '}
diff --git a/app/components/Views/AccountBackupStep1B/__snapshots__/index.test.js.snap b/app/components/Views/AccountBackupStep1B/__snapshots__/index.test.js.snap
index 236bb92852d..462498c3646 100644
--- a/app/components/Views/AccountBackupStep1B/__snapshots__/index.test.js.snap
+++ b/app/components/Views/AccountBackupStep1B/__snapshots__/index.test.js.snap
@@ -40,7 +40,7 @@ exports[`AccountBackupStep1B should render correctly 1`] = `
Array [
"Create password",
"Secure wallet",
- "Confirm seed phrase",
+ "Confirm Secret Recovery phrase",
]
}
/>
@@ -107,7 +107,7 @@ exports[`AccountBackupStep1B should render correctly 1`] = `
}
}
>
- seed phrase.
+ Secret Recovery phrase.
@@ -189,7 +189,7 @@ exports[`AccountBackupStep1B should render correctly 1`] = `
}
}
>
- Write down your seed phrase on a piece of paper and store in a safe place.
+ Write down your Secret Recovery phrase on a piece of paper and store in a safe place.
- Don’t risk losing your funds. Protect your wallet by saving your seed phrase in a place you trust.
+ Don’t risk losing your funds. Protect your wallet by saving your Secret Recovery phrase in a place you trust.
getNetworkNavbarOptions('add_asset.title', true, navigation);
state = {
@@ -45,7 +47,11 @@ export default class AddAsset extends PureComponent {
/**
/* navigation object required to push new views
*/
- navigation: PropTypes.object
+ navigation: PropTypes.object,
+ /**
+ * Chain id
+ */
+ chainId: PropTypes.string
};
renderTabBar() {
@@ -74,11 +80,13 @@ export default class AddAsset extends PureComponent {
{assetType === 'token' ? (
-
+ {NetworksChainId.mainnet === this.props.chainId && (
+
+ )}
({
+ chainId: state.engine.backgroundState.NetworkController.provider.chainId
+});
+
+export default connect(mapStateToProps)(AddAsset);
diff --git a/app/components/Views/AddAsset/index.test.js b/app/components/Views/AddAsset/index.test.js
index 310a5389180..a3e33019bdd 100644
--- a/app/components/Views/AddAsset/index.test.js
+++ b/app/components/Views/AddAsset/index.test.js
@@ -1,10 +1,27 @@
import React from 'react';
+import configureMockStore from 'redux-mock-store';
import { shallow } from 'enzyme';
import AddAsset from './';
+const mockStore = configureMockStore();
+
describe('AddAsset', () => {
it('should render correctly', () => {
- const wrapper = shallow();
- expect(wrapper).toMatchSnapshot();
+ const initialState = {
+ engine: {
+ backgroundState: {
+ NetworkController: {
+ provider: {
+ chainId: '1'
+ }
+ }
+ }
+ }
+ };
+
+ const wrapper = shallow(, {
+ context: { store: mockStore(initialState) }
+ });
+ expect(wrapper.dive()).toMatchSnapshot();
});
});
diff --git a/app/components/Views/Asset/index.js b/app/components/Views/Asset/index.js
index f88c527139c..7fed702bfcf 100644
--- a/app/components/Views/Asset/index.js
+++ b/app/components/Views/Asset/index.js
@@ -2,13 +2,14 @@ import React, { PureComponent } from 'react';
import { ActivityIndicator, InteractionManager, View, StyleSheet } from 'react-native';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
+import { swapsUtils } from '@metamask/swaps-controller/';
+
import { colors } from '../../../styles/common';
import AssetOverview from '../../UI/AssetOverview';
import Transactions from '../../UI/Transactions';
import { getNetworkNavbarOptions } from '../../UI/Navbar';
import Engine from '../../../core/Engine';
import { safeToChecksumAddress } from '../../../util/address';
-import { SWAPS_CONTRACT_ADDRESS } from '@estebanmino/controllers/dist/swaps/SwapsUtil';
import { addAccountTimeFlagFilter } from '../../../util/transactions';
const styles = StyleSheet.create({
@@ -168,7 +169,8 @@ class Asset extends PureComponent {
if (isTransfer) return this.navAddress === transferInformation.contractAddress.toLowerCase();
if (
swapsTransactions[tx.id] &&
- (to?.toLowerCase() === SWAPS_CONTRACT_ADDRESS || to?.toLowerCase() === this.navAddress)
+ (to?.toLowerCase() === swapsUtils.getSwapsContractAddress(chainId) ||
+ to?.toLowerCase() === this.navAddress)
) {
const { destinationToken, sourceToken } = swapsTransactions[tx.id];
return destinationToken.address === this.navAddress || sourceToken.address === this.navAddress;
diff --git a/app/components/Views/BrowserTab/__snapshots__/index.test.js.snap b/app/components/Views/BrowserTab/__snapshots__/index.test.js.snap
index 20e5dcf04a1..be35fc8eb2d 100644
--- a/app/components/Views/BrowserTab/__snapshots__/index.test.js.snap
+++ b/app/components/Views/BrowserTab/__snapshots__/index.test.js.snap
@@ -181,7 +181,7 @@ exports[`Browser should render correctly 1`] = `
"marginTop": 7,
}
}
- testID="cancel-url-button"
+ testID="ios-cancel-url-button"
>
{
ensIgnoreList.push(hostname);
return { url: fullUrl, reload: true };
}
- Logger.error(err, 'Failed to resolve ENS name');
- Alert.alert(strings('browser.error'), strings('browser.failed_to_resolve_ens_name'));
+ if (err?.message?.startsWith('EnsIpfsResolver - no known ens-ipfs registry for chainId')) {
+ trackErrorAsAnalytics('Browser: Failed to resolve ENS name for chainId', err?.message);
+ } else {
+ Logger.error(err, 'Failed to resolve ENS name');
+ }
+
+ Alert.alert(strings('browser.failed_to_resolve_ens_name'), err.message);
goBack();
}
},
@@ -988,7 +994,7 @@ export const BrowserTab = props => {
* Handle keyboard hide
*/
const keyboardDidHide = useCallback(() => {
- if (!isTabActive()) return false;
+ if (!isTabActive() || isEmulatorSync()) return false;
if (!fromHomepage.current) {
if (showUrlModal) {
hideUrlModal();
@@ -1413,12 +1419,17 @@ export const BrowserTab = props => {
onPress={() => (!autocompleteValue ? setShowUrlModal(false) : setAutocompleteValue(''))}
style={styles.iconCloseButton}
>
-
+
) : (
{strings('browser.cancel')}
diff --git a/app/components/Views/ChoosePassword/__snapshots__/index.test.js.snap b/app/components/Views/ChoosePassword/__snapshots__/index.test.js.snap
index 9e928630fda..1e5887b6990 100644
--- a/app/components/Views/ChoosePassword/__snapshots__/index.test.js.snap
+++ b/app/components/Views/ChoosePassword/__snapshots__/index.test.js.snap
@@ -24,7 +24,7 @@ exports[`ChoosePassword should render correctly 1`] = `
Array [
"Create password",
"Secure wallet",
- "Confirm seed phrase",
+ "Confirm Secret Recovery phrase",
]
}
/>
diff --git a/app/components/Views/ChoosePassword/index.js b/app/components/Views/ChoosePassword/index.js
index 5601e44c747..731396c1a28 100644
--- a/app/components/Views/ChoosePassword/index.js
+++ b/app/components/Views/ChoosePassword/index.js
@@ -418,7 +418,7 @@ class ChoosePassword extends PureComponent {
if (hdKeyring.accounts.includes(selectedAddress)) {
PreferencesController.setSelectedAddress(selectedAddress);
} else {
- PreferencesController.setSelectedAddress(hdKeyring[0]);
+ PreferencesController.setSelectedAddress(hdKeyring.accounts[0]);
}
};
diff --git a/app/components/Views/Entry/index.js b/app/components/Views/Entry/index.js
index e458b8f5827..a5c03710ad4 100644
--- a/app/components/Views/Entry/index.js
+++ b/app/components/Views/Entry/index.js
@@ -76,7 +76,7 @@ const Entry = props => {
const animation = useRef(null);
const animationName = useRef(null);
- const opacity = new Animated.Value(1);
+ const opacity = useRef(new Animated.Value(1)).current;
const onAnimationFinished = useCallback(() => {
Animated.timing(opacity, {
diff --git a/app/components/Views/ImportFromSeed/__snapshots__/index.test.js.snap b/app/components/Views/ImportFromSeed/__snapshots__/index.test.js.snap
index 25e9974b730..d2e80f81121 100644
--- a/app/components/Views/ImportFromSeed/__snapshots__/index.test.js.snap
+++ b/app/components/Views/ImportFromSeed/__snapshots__/index.test.js.snap
@@ -75,7 +75,7 @@ exports[`ImportFromSeed should render correctly 1`] = `
}
}
>
- Seed phrase
+ Secret recovery phrase
- Imported accounts are viewable in your wallet but are not recoverable with your MetaMask seed phrase.
+ Imported accounts are viewable in your wallet but are not recoverable with your MetaMask Secret Recovery phrase.
String(text).toLowerCase() === 'delete';
const deviceHeight = Device.getDeviceHeight();
@@ -182,13 +183,11 @@ const styles = StyleSheet.create({
}
});
-/* TODO: we should have translation strings for these */
-const PASSCODE_NOT_SET_ERROR = 'Error: Passcode not set.';
-const WRONG_PASSWORD_ERROR = 'Error: Decrypt failed';
-const WRONG_PASSWORD_ERROR_ANDROID = 'Error: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT';
-const VAULT_ERROR = 'Error: Cannot unlock without a previous vault.';
-const CLEAN_VAULT_ERROR =
- 'MetaMask encountered an error due to reaching a storage limit. The local data has been corrupted. Please reinstall MetaMask and restore with your seed phrase.';
+const PASSCODE_NOT_SET_ERROR = strings('login.passcode_not_set_error');
+const WRONG_PASSWORD_ERROR = strings('login.wrong_password_error');
+const WRONG_PASSWORD_ERROR_ANDROID = strings('login.wrong_password_error_android');
+const VAULT_ERROR = strings('login.vault_error');
+const CLEAN_VAULT_ERROR = strings('login.clean_vault_error');
/**
* View where returning users can authenticate
@@ -319,6 +318,10 @@ class Login extends PureComponent {
error.toLowerCase() === WRONG_PASSWORD_ERROR_ANDROID.toLowerCase()
) {
this.setState({ loading: false, error: strings('login.invalid_password') });
+
+ trackErrorAsAnalytics('Login: Invalid Password', error);
+
+ return;
} else if (error === PASSCODE_NOT_SET_ERROR) {
Alert.alert(
'Security Alert',
@@ -520,6 +523,7 @@ class Login extends PureComponent {
{strings('login.password')}
@@ -61,7 +61,7 @@ exports[`ManualBackupStep1 should render correctly 1`] = `
}
}
>
- Write down your seed phrase
+ Write down your Secret Recovery phrase
- This is your seed phrase. Write it down on a paper and keep it in a safe place. You'll be asked to re-enter this phrase (in order) on the next step.
+ This is your Secret Recovery phrase. Write it down on a paper and keep it in a safe place. You'll be asked to re-enter this phrase (in order) on the next step.
- Tap to reveal your seed phrase
+ Tap to reveal your Secret Recovery phrase
- Confirm seed phrase
+ Confirm Secret Recovery phrase
{
+ if (confusableCollection.length) {
+ const texts = toAddressName.split('').map((char, index) => {
+ // if text has a confusable highlight it red
+ if (confusableCollection.includes(char)) {
+ // if the confusable is zero width, replace it with `?`
+ const replacement = hasZeroWidthPoints(char) ? '?' : char;
+ return (
+
+ {replacement}
+
+ );
+ }
+ return (
+
+ {char}
+
+ );
+ });
+ return (
+
+ {texts}
+
+ );
+ }
+ return (
+
+ {toAddressName}
+
+ );
+};
+
+AddressName.propTypes = {
+ toAddressName: PropTypes.string,
+ confusableCollection: PropTypes.array
+};
+
export const AddressTo = props => {
const {
addressToReady,
@@ -132,7 +179,9 @@ export const AddressTo = props => {
onInputFocus,
onSubmit,
onInputBlur,
- inputWidth
+ inputWidth,
+ confusableCollection,
+ displayExclamation
} = props;
return (
@@ -173,12 +222,18 @@ export const AddressTo = props => {
+ {displayExclamation && (
+
+
+
+ )}
{toAddressName && (
-
- {toAddressName}
-
+
)}
{
diff --git a/app/components/Views/SendFlow/Amount/index.js b/app/components/Views/SendFlow/Amount/index.js
index f2f3e27e5db..6f64eb6bf7d 100644
--- a/app/components/Views/SendFlow/Amount/index.js
+++ b/app/components/Views/SendFlow/Amount/index.js
@@ -52,6 +52,7 @@ import Analytics from '../../../../core/Analytics';
import { ANALYTICS_EVENT_OPTS } from '../../../../util/analytics';
import dismissKeyboard from 'react-native/Libraries/Utilities/dismissKeyboard';
import NetworkMainAssetLogo from '../../../UI/NetworkMainAssetLogo';
+import { isMainNet } from '../../../../util/networks';
const { hexToBN, BNToHex } = util;
@@ -330,6 +331,10 @@ class Amount extends PureComponent {
* An array that represents the user tokens
*/
tokens: PropTypes.array,
+ /**
+ * Chain Id
+ */
+ chainId: PropTypes.string,
/**
* Current provider ticker
*/
@@ -664,7 +669,7 @@ class Amount extends PureComponent {
};
onInputChange = (inputValue, selectedAsset, useMax) => {
- const { contractExchangeRates, conversionRate, currentCurrency, ticker } = this.props;
+ const { contractExchangeRates, conversionRate, currentCurrency, chainId, ticker } = this.props;
const { internalPrimaryCurrencyIsCrypto } = this.state;
let inputValueConversion, renderableInputValueConversion, hasExchangeRate, comma;
// Remove spaces from input
@@ -678,7 +683,7 @@ class Amount extends PureComponent {
const processedInputValue = isDecimal(inputValue) ? handleWeiNumber(inputValue) : '0';
selectedAsset = selectedAsset || this.props.selectedAsset;
if (selectedAsset.isETH) {
- hasExchangeRate = !!conversionRate;
+ hasExchangeRate = isMainNet(chainId) ? !!conversionRate : false;
if (internalPrimaryCurrencyIsCrypto) {
inputValueConversion = `${weiToFiatNumber(toWei(processedInputValue), conversionRate)}`;
renderableInputValueConversion = `${weiToFiat(
@@ -692,7 +697,7 @@ class Amount extends PureComponent {
}
} else {
const exchangeRate = contractExchangeRates[selectedAsset.address];
- hasExchangeRate = !!exchangeRate;
+ hasExchangeRate = isMainNet(chainId) ? !!exchangeRate : false;
// If !hasExchangeRate we have to handle crypto amount
if (internalPrimaryCurrencyIsCrypto || !hasExchangeRate) {
inputValueConversion = `${balanceToFiatNumber(processedInputValue, conversionRate, exchangeRate)}`;
@@ -766,6 +771,7 @@ class Amount extends PureComponent {
renderToken = (token, index) => {
const {
accounts,
+ chainId,
selectedAddress,
conversionRate,
currentCurrency,
@@ -776,11 +782,15 @@ class Amount extends PureComponent {
const { address, decimals, symbol } = token;
if (token.isETH) {
balance = renderFromWei(accounts[selectedAddress].balance);
- balanceFiat = weiToFiat(hexToBN(accounts[selectedAddress].balance), conversionRate, currentCurrency);
+ balanceFiat = isMainNet(chainId)
+ ? weiToFiat(hexToBN(accounts[selectedAddress].balance), conversionRate, currentCurrency)
+ : null;
} else {
balance = renderFromTokenMinimalUnit(contractBalances[address], decimals);
const exchangeRate = contractExchangeRates[address];
- balanceFiat = balanceToFiat(balance, conversionRate, exchangeRate, currentCurrency);
+ balanceFiat = isMainNet(chainId)
+ ? balanceToFiat(balance, conversionRate, exchangeRate, currentCurrency)
+ : null;
}
return (
({
providerType: state.engine.backgroundState.NetworkController.provider.type,
primaryCurrency: state.settings.primaryCurrency,
selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress,
+ chainId: state.engine.backgroundState.NetworkController.provider.chainId,
ticker: state.engine.backgroundState.NetworkController.provider.ticker,
tokens: state.engine.backgroundState.AssetsController.tokens,
transactionState: ownProps.transaction || state.transaction,
diff --git a/app/components/Views/SendFlow/Confirm/__snapshots__/index.test.js.snap b/app/components/Views/SendFlow/Confirm/__snapshots__/index.test.js.snap
index c91387b3fb9..9ef917d8156 100644
--- a/app/components/Views/SendFlow/Confirm/__snapshots__/index.test.js.snap
+++ b/app/components/Views/SendFlow/Confirm/__snapshots__/index.test.js.snap
@@ -24,11 +24,40 @@ exports[`Confirm should render correctly 1`] = `
fromAccountAddress="0x1"
onPressIcon={null}
/>
-
+
+
+ We have detected a confusable character in the ENS name. Check the ENS name to avoid a potential scam.
+
+ }
+ isVisible={false}
+ title="Check the recipient address"
+ toggleModal={[Function]}
+ />
-
balance
*/
@@ -262,6 +272,10 @@ class Confirm extends PureComponent {
* Set transaction object to be sent
*/
prepareTransaction: PropTypes.func,
+ /**
+ * Chain Id
+ */
+ chainId: PropTypes.string,
/**
* Network id
*/
@@ -309,6 +323,7 @@ class Confirm extends PureComponent {
};
state = {
+ confusableCollection: [],
gasSpeedSelected: 'average',
gasEstimationReady: false,
customGas: undefined,
@@ -327,6 +342,7 @@ class Confirm extends PureComponent {
transactionTotalAmountFiat: undefined,
errorMessage: undefined,
fromAccountModalVisible: false,
+ warningModalVisible: false,
mode: REVIEW,
over: false
};
@@ -364,6 +380,18 @@ class Confirm extends PureComponent {
}
};
+ handleConfusables = () => {
+ const { identities = undefined, transactionState } = this.props;
+ const { transactionToName = undefined } = transactionState;
+ const accountNames = (identities && Object.keys(identities).map(hash => identities[hash].name)) || [];
+ const isOwnAccount = accountNames.includes(transactionToName);
+ if (transactionToName && !isOwnAccount) {
+ this.setState({ confusableCollection: collectConfusables(transactionToName) });
+ }
+ };
+
+ toggleWarningModal = () => this.setState(state => ({ warningModalVisible: !state.warningModalVisible }));
+
componentDidMount = async () => {
// For analytics
AnalyticsV2.trackEvent(AnalyticsV2.ANALYTICS_EVENTS.SEND_TRANSACTION_STARTED, this.getAnalyticsParams());
@@ -372,6 +400,7 @@ class Confirm extends PureComponent {
await this.handleFetchBasicEstimates();
showCustomNonce && (await this.setNetworkNonce());
navigation.setParams({ providerType });
+ this.handleConfusables();
this.parseTransactionData();
this.prepareTransaction();
};
@@ -907,7 +936,7 @@ class Confirm extends PureComponent {
render = () => {
const { transactionToName, selectedAsset, paymentRequest } = this.props.transactionState;
- const { showHexData, showCustomNonce, primaryCurrency, network } = this.props;
+ const { addressBook, showHexData, showCustomNonce, primaryCurrency, network, chainId } = this.props;
const { nonce } = this.props.transaction;
const {
gasEstimationReady,
@@ -924,10 +953,36 @@ class Confirm extends PureComponent {
errorMessage,
transactionConfirmed,
warningGasPriceHigh,
+ confusableCollection,
mode,
- over
+ over,
+ warningModalVisible
} = this.state;
+ const checksummedAddress = transactionTo && toChecksumAddress(transactionTo);
+ const existingContact = checksummedAddress && addressBook[network] && addressBook[network][checksummedAddress];
+ const displayExclamation = !existingContact && !!confusableCollection.length;
+
+ const AdressToComponent = () => (
+
+ );
+
+ const AdressToComponentWrap = () =>
+ !existingContact && confusableCollection.length ? (
+
+
+
+ ) : (
+
+ );
+
const is_main_net = isMainNet(network);
const errorPress = is_main_net ? this.buyEth : this.gotoFaucet;
const networkName = capitalize(getNetworkName(network));
@@ -943,14 +998,16 @@ class Confirm extends PureComponent {
fromAccountName={fromAccountName}
fromAccountBalance={fromAccountBalance}
/>
-
+
+ {strings('transaction.confusable_msg')}}
+ />
+
{!selectedAsset.tokenId ? (
@@ -958,7 +1015,7 @@ class Confirm extends PureComponent {
{transactionValue}
- {transactionValueFiat}
+ {isMainNet(chainId) && {transactionValueFiat}}
) : (
@@ -979,7 +1036,7 @@ class Confirm extends PureComponent {
}
fiat={transactionValueFiat}
totalValue={transactionTotalAmount}
transactionValue={transactionValue}
@@ -1042,6 +1099,7 @@ class Confirm extends PureComponent {
const mapStateToProps = state => ({
accounts: state.engine.backgroundState.AccountTrackerController.accounts,
+ addressBook: state.engine.backgroundState.AddressBookController?.addressBook,
contractBalances: state.engine.backgroundState.TokenBalancesController.contractBalances,
contractExchangeRates: state.engine.backgroundState.TokenRatesController.contractExchangeRates,
currentCurrency: state.engine.backgroundState.CurrencyRateController.currentCurrency,
@@ -1051,6 +1109,7 @@ const mapStateToProps = state => ({
providerType: state.engine.backgroundState.NetworkController.provider.type,
showHexData: state.settings.showHexData,
showCustomNonce: state.settings.showCustomNonce,
+ chainId: state.engine.backgroundState.NetworkController.provider.chainId,
ticker: state.engine.backgroundState.NetworkController.provider.ticker,
keyrings: state.engine.backgroundState.KeyringController.keyrings,
transaction: getNormalizedTxState(state),
diff --git a/app/components/Views/SendFlow/ErrorMessage/__snapshots__/index.test.js.snap b/app/components/Views/SendFlow/ErrorMessage/__snapshots__/index.test.js.snap
index 57413a9c970..621c6cfde6f 100644
--- a/app/components/Views/SendFlow/ErrorMessage/__snapshots__/index.test.js.snap
+++ b/app/components/Views/SendFlow/ErrorMessage/__snapshots__/index.test.js.snap
@@ -32,6 +32,7 @@ exports[`ErrorMessage should render correctly 1`] = `
link={false}
modal={false}
primary={false}
+ red={false}
reset={false}
right={false}
small={true}
diff --git a/app/components/Views/SendFlow/SendTo/__snapshots__/index.test.js.snap b/app/components/Views/SendFlow/SendTo/__snapshots__/index.test.js.snap
index d6855203729..c9965feb7e4 100644
--- a/app/components/Views/SendFlow/SendTo/__snapshots__/index.test.js.snap
+++ b/app/components/Views/SendFlow/SendTo/__snapshots__/index.test.js.snap
@@ -27,6 +27,7 @@ exports[`SendTo should render correctly 1`] = `
/>
Add to address book
Enter an alias
diff --git a/app/components/Views/SendFlow/SendTo/index.js b/app/components/Views/SendFlow/SendTo/index.js
index 54a4e6adda7..bd0f0b7bd42 100644
--- a/app/components/Views/SendFlow/SendTo/index.js
+++ b/app/components/Views/SendFlow/SendTo/index.js
@@ -7,7 +7,6 @@ import {
StyleSheet,
View,
TouchableOpacity,
- Text,
TextInput,
SafeAreaView,
InteractionManager,
@@ -34,6 +33,9 @@ import Analytics from '../../../../core/Analytics';
import { ANALYTICS_EVENT_OPTS } from '../../../../util/analytics';
import { allowedToBuy } from '../../../UI/FiatOrders';
import NetworkList from '../../../../util/networks';
+import Text from '../../../Base/Text';
+import Icon from 'react-native-vector-icons/FontAwesome';
+import { collectConfusables, hasZeroWidthPoints } from '../../../../util/validators';
const { hexToBN } = util;
const styles = StyleSheet.create({
@@ -125,12 +127,41 @@ const styles = StyleSheet.create({
marginBottom: 32
},
buyEth: {
- ...fontStyles.bold,
color: colors.black,
textDecorationLine: 'underline'
},
- bold: {
- ...fontStyles.bold
+ confusabeError: {
+ display: 'flex',
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ margin: 16,
+ padding: 16,
+ borderWidth: 1,
+ borderColor: colors.red,
+ backgroundColor: colors.red000,
+ borderRadius: 8
+ },
+ confusabeWarning: {
+ borderColor: colors.yellow,
+ backgroundColor: colors.yellow100
+ },
+ confusableTitle: {
+ marginTop: -3,
+ color: colors.red,
+ ...fontStyles.bold,
+ fontSize: 14
+ },
+ confusableMsg: {
+ color: colors.red,
+ fontSize: 12,
+ lineHeight: 16,
+ paddingRight: 10
+ },
+ black: {
+ color: colors.black
+ },
+ warningIcon: {
+ marginRight: 8
}
});
@@ -210,6 +241,7 @@ class SendFlow extends PureComponent {
toEnsName: undefined,
addToAddressToAddressBook: false,
alias: undefined,
+ confusableCollection: [],
inputWidth: { width: '99%' }
};
@@ -274,7 +306,7 @@ class SendFlow extends PureComponent {
const { AssetsContractController } = Engine.context;
const { addressBook, network, identities, providerType } = this.props;
const networkAddressBook = addressBook[network] || {};
- let addressError, toAddressName, toEnsName, errorContinue, isOnlyWarning;
+ let addressError, toAddressName, toEnsName, errorContinue, isOnlyWarning, confusableCollection;
let [addToAddressToAddressBook, toSelectedAddressReady] = [false, false];
if (isValidAddress(toSelectedAddress)) {
const checksummedToSelectedAddress = toChecksumAddress(toSelectedAddress);
@@ -304,7 +336,7 @@ class SendFlow extends PureComponent {
addressError = (
{strings('transaction.tokenContractAddressWarning_1')}
- {strings('transaction.tokenContractAddressWarning_2')}
+ {strings('transaction.tokenContractAddressWarning_2')}
{strings('transaction.tokenContractAddressWarning_3')}
);
@@ -329,6 +361,7 @@ class SendFlow extends PureComponent {
*/
} else if (isENS(toSelectedAddress)) {
toEnsName = toSelectedAddress;
+ confusableCollection = collectConfusables(toEnsName);
const resolvedAddress = await doENSLookup(toSelectedAddress, network);
if (resolvedAddress) {
const checksummedResolvedAddress = toChecksumAddress(resolvedAddress);
@@ -352,7 +385,8 @@ class SendFlow extends PureComponent {
toSelectedAddressName: toAddressName,
toEnsName,
errorContinue,
- isOnlyWarning
+ isOnlyWarning,
+ confusableCollection
});
};
@@ -510,7 +544,7 @@ class SendFlow extends PureComponent {
return (
<>
{'\n'}
-
+
{strings('fiat_on_ramp.buy_eth')}
>
@@ -519,6 +553,7 @@ class SendFlow extends PureComponent {
render = () => {
const { ticker } = this.props;
+ const { addressBook, network } = this.props;
const {
fromSelectedAddress,
fromAccountName,
@@ -532,8 +567,16 @@ class SendFlow extends PureComponent {
toInputHighlighted,
inputWidth,
errorContinue,
- isOnlyWarning
+ isOnlyWarning,
+ confusableCollection
} = this.state;
+
+ const checksummedAddress = toSelectedAddress && toChecksumAddress(toSelectedAddress);
+ const existingContact = checksummedAddress && addressBook[network] && addressBook[network][checksummedAddress];
+ const displayConfusableWarning = !existingContact && confusableCollection && !!confusableCollection.length;
+ const displayAsWarning =
+ confusableCollection && confusableCollection.length && !confusableCollection.some(hasZeroWidthPoints);
+
return (
@@ -556,6 +599,7 @@ class SendFlow extends PureComponent {
onInputBlur={this.onToInputFocus}
onSubmit={this.onTransactionDirectionSet}
inputWidth={inputWidth}
+ confusableCollection={(!existingContact && confusableCollection) || []}
/>
@@ -578,6 +622,25 @@ class SendFlow extends PureComponent {
/>
)}
+ {displayConfusableWarning && (
+
+
+
+
+
+
+ {strings('transaction.confusable_title')}
+
+
+ {strings('transaction.confusable_msg')}
+
+
+
+ )}
{addToAddressToAddressBook && (
+
+
+ Hide Tokens Without Balance
+
+
+ Prevents tokens with no balance from displaying in your token listing.
+
+
+
+
+
@@ -174,6 +191,10 @@ class Settings extends PureComponent {
this.props.setPrimaryCurrency(primaryCurrency);
};
+ toggleHideZeroBalanceTokens = toggleHideZeroBalanceTokens => {
+ this.props.setHideZeroBalanceTokens(toggleHideZeroBalanceTokens);
+ };
+
componentDidMount = () => {
const languages = getLanguages();
this.setState({ languages });
@@ -189,7 +210,14 @@ class Settings extends PureComponent {
};
render() {
- const { currentCurrency, primaryCurrency, useBlockieIcon, setUseBlockieIcon, selectedAddress } = this.props;
+ const {
+ currentCurrency,
+ primaryCurrency,
+ useBlockieIcon,
+ setUseBlockieIcon,
+ selectedAddress,
+ hideZeroBalanceTokens
+ } = this.props;
return (
@@ -249,6 +277,18 @@ class Settings extends PureComponent {
)}
+
+ {strings('app_settings.hide_zero_balance_tokens_title')}
+ {strings('app_settings.hide_zero_balance_tokens_desc')}
+
+
+
+
{strings('app_settings.accounts_identicon_title')}
{strings('app_settings.accounts_identicon_desc')}
@@ -282,13 +322,15 @@ const mapStateToProps = state => ({
searchEngine: state.settings.searchEngine,
primaryCurrency: state.settings.primaryCurrency,
useBlockieIcon: state.settings.useBlockieIcon,
- selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress
+ selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress,
+ hideZeroBalanceTokens: state.settings.hideZeroBalanceTokens
});
const mapDispatchToProps = dispatch => ({
setSearchEngine: searchEngine => dispatch(setSearchEngine(searchEngine)),
setPrimaryCurrency: primaryCurrency => dispatch(setPrimaryCurrency(primaryCurrency)),
- setUseBlockieIcon: useBlockieIcon => dispatch(setUseBlockieIcon(useBlockieIcon))
+ setUseBlockieIcon: useBlockieIcon => dispatch(setUseBlockieIcon(useBlockieIcon)),
+ setHideZeroBalanceTokens: hideZeroBalanceTokens => dispatch(setHideZeroBalanceTokens(hideZeroBalanceTokens))
});
export default connect(
diff --git a/app/components/Views/Settings/NetworksSettings/__snapshots__/index.test.js.snap b/app/components/Views/Settings/NetworksSettings/__snapshots__/index.test.js.snap
index 7272f90e459..c377e72f308 100644
--- a/app/components/Views/Settings/NetworksSettings/__snapshots__/index.test.js.snap
+++ b/app/components/Views/Settings/NetworksSettings/__snapshots__/index.test.js.snap
@@ -268,7 +268,9 @@ exports[`NetworksSettings should render correctly 1`] = `
-
+
0) {
return (
-
+
{strings('app_settings.network_rpc_networks')}
{this.renderRpcNetworks()}
diff --git a/app/components/Views/Settings/SecuritySettings/__snapshots__/index.test.js.snap b/app/components/Views/Settings/SecuritySettings/__snapshots__/index.test.js.snap
index 7f7062dde0d..701c965d354 100644
--- a/app/components/Views/Settings/SecuritySettings/__snapshots__/index.test.js.snap
+++ b/app/components/Views/Settings/SecuritySettings/__snapshots__/index.test.js.snap
@@ -63,6 +63,13 @@ exports[`SecuritySettings should render correctly 1`] = `
Protect your wallet
+
- Protect your wallet by saving your seed phrase in various places like on a piece of paper, password manager and/or the cloud.
+ Protect your wallet by saving your Secret Recovery phrase in various places like on a piece of paper, password manager and/or the cloud.
- Important! Seed phrase not backed up
+ Important! Secret recovery phrase not backed up
- Choose a strong password to unlock MetaMask app on your device. If you lose this password, you will need your seedphrase to re-import your wallet.
+ Choose a strong password to unlock MetaMask app on your device. If you lose this password, you will need your Secret recovery phrase to re-import your wallet.
{strings('app_settings.protect_title')}
+
{strings('app_settings.protect_desc')}
{
- const { TransactionController } = this.datamodel.context;
- try {
- const hash = await (await TransactionController.addTransaction(
- payload.params[0],
- payload.origin,
- WalletDevice.MM_MOBILE
- )).result;
- end(undefined, hash);
- } catch (error) {
- end(error);
- }
- }
- },
- getAccounts: (end, payload) => {
- const { approvedHosts, privacyMode } = store.getState();
- const isEnabled = !privacyMode || approvedHosts[payload.hostname];
- const { KeyringController } = this.datamodel.context;
- const isUnlocked = KeyringController.isUnlocked();
- const selectedAddress = this.datamodel.context.PreferencesController.state
- .selectedAddress;
- end(null, isUnlocked && isEnabled && selectedAddress ? [selectedAddress] : []);
+ const preferencesController = new PreferencesController(
+ {},
+ {
+ ipfsGateway: AppConstants.IPFS_DEFAULT_GATEWAY_URL
+ }
+ );
+ const networkController = new NetworkController({
+ infuraProjectId: process.env.MM_INFURA_PROJECT_ID || NON_EMPTY,
+ providerConfig: {
+ static: {
+ eth_sendTransaction: async (payload, next, end) => {
+ const { TransactionController } = this.context;
+ try {
+ const hash = await (await TransactionController.addTransaction(
+ payload.params[0],
+ payload.origin,
+ WalletDevice.MM_MOBILE
+ )).result;
+ end(undefined, hash);
+ } catch (error) {
+ end(error);
}
}
- }),
- new PhishingController(),
- new PreferencesController(
- {},
- {
- ipfsGateway: AppConstants.IPFS_DEFAULT_GATEWAY_URL
- }
+ },
+ getAccounts: (end, payload) => {
+ const { approvedHosts, privacyMode } = store.getState();
+ const isEnabled = !privacyMode || approvedHosts[payload.hostname];
+ const { KeyringController } = this.context;
+ const isUnlocked = KeyringController.isUnlocked();
+ const selectedAddress = this.context.PreferencesController.state.selectedAddress;
+ end(null, isUnlocked && isEnabled && selectedAddress ? [selectedAddress] : []);
+ }
+ }
+ });
+ const assetsContractController = new AssetsContractController();
+ const assetsController = new AssetsController({
+ onPreferencesStateChange: listener => preferencesController.subscribe(listener),
+ onNetworkStateChange: listener => networkController.subscribe(listener),
+ getAssetName: assetsContractController.getAssetName.bind(assetsContractController),
+ getAssetSymbol: assetsContractController.getAssetSymbol.bind(assetsContractController),
+ getCollectibleTokenURI: assetsContractController.getCollectibleTokenURI.bind(assetsContractController)
+ });
+ const currencyRateController = new CurrencyRateController({
+ nativeCurrency,
+ currentCurrency
+ });
+
+ const controllers = [
+ new KeyringController(
+ {
+ removeIdentity: preferencesController.removeIdentity.bind(preferencesController),
+ syncIdentities: preferencesController.syncIdentities.bind(preferencesController),
+ updateIdentities: preferencesController.updateIdentities.bind(preferencesController),
+ setSelectedAddress: preferencesController.setSelectedAddress.bind(preferencesController)
+ },
+ { encryptor },
+ initialState.KeyringController
+ ),
+ new AccountTrackerController({
+ onPreferencesStateChange: listener => preferencesController.subscribe(listener),
+ getIdentities: () => preferencesController.state.identities
+ }),
+ new AddressBookController(),
+ assetsContractController,
+ assetsController,
+ new AssetsDetectionController({
+ onAssetsStateChange: listener => assetsController.subscribe(listener),
+ onPreferencesStateChange: listener => preferencesController.subscribe(listener),
+ onNetworkStateChange: listener => networkController.subscribe(listener),
+ getOpenSeaApiKey: () => assetsController.openSeaApiKey,
+ getBalancesInSingleCall: assetsContractController.getBalancesInSingleCall.bind(
+ assetsContractController
),
- new TokenBalancesController({ interval: 10000 }),
- new TokenRatesController(),
- new TransactionController(),
- new TypedMessageManager(),
- new SwapsController({ clientId: AppConstants.SWAPS.CLIENT_ID })
- ],
- initialState
- );
+ addTokens: assetsController.addTokens.bind(assetsController),
+ addCollectible: assetsController.addCollectible.bind(assetsController),
+ removeCollectible: assetsController.removeCollectible.bind(assetsController),
+ getAssetsState: () => assetsController.state
+ }),
+ currencyRateController,
+ new PersonalMessageManager(),
+ new MessageManager(),
+ networkController,
+ new PhishingController(),
+ preferencesController,
+ new TokenBalancesController(
+ {
+ onAssetsStateChange: listener => assetsController.subscribe(listener),
+ getSelectedAddress: () => preferencesController.state.selectedAddress,
+ getBalanceOf: assetsContractController.getBalanceOf.bind(assetsContractController)
+ },
+ { interval: 10000 }
+ ),
+ new TokenRatesController({
+ onAssetsStateChange: listener => assetsController.subscribe(listener),
+ onCurrencyRateStateChange: listener => currencyRateController.subscribe(listener)
+ }),
+ new TransactionController({
+ getNetworkState: () => networkController.state,
+ onNetworkStateChange: listener => networkController.subscribe(listener),
+ getProvider: () => networkController.provider
+ }),
+ new TypedMessageManager(),
+ new SwapsController({
+ clientId: AppConstants.SWAPS.CLIENT_ID,
+ fetchAggregatorMetadataThreshold: AppConstants.SWAPS.CACHE_AGGREGATOR_METADATA_THRESHOLD,
+ fetchTokensThreshold: AppConstants.SWAPS.CACHE_TOKENS_THRESHOLD,
+ fetchTopAssetsThreshold: AppConstants.SWAPS.CACHE_TOP_ASSETS_THRESHOLD
+ })
+ ];
+
+ // set initial state
+ // TODO: Pass initial state into each controller constructor instead
+ // This is being set post-construction for now to ensure it's functionally equivalent with
+ // how the `ComponsedController` used to set initial state.
+ for (const controller of controllers) {
+ if (initialState[controller.name]) {
+ controller.update(initialState[controller.name]);
+ }
+ }
+
+ this.datamodel = new ComposableController(controllers, initialState);
+ this.context = controllers.reduce((context, controller) => {
+ context[controller.name] = controller;
+ return context;
+ }, {});
const {
AssetsController: assets,
KeyringController: keyring,
NetworkController: network,
TransactionController: transaction
- } = this.datamodel.context;
+ } = this.context;
assets.setApiKey(process.env.MM_OPENSEA_KEY);
network.refreshNetwork();
@@ -154,16 +221,18 @@ class Engine {
AccountTrackerController,
AssetsContractController,
AssetsDetectionController,
- NetworkController: { provider },
+ NetworkController: { provider, state: NetworkControllerState },
TransactionController,
SwapsController
- } = this.datamodel.context;
+ } = this.context;
provider.sendAsync = provider.sendAsync.bind(provider);
AccountTrackerController.configure({ provider });
AssetsContractController.configure({ provider });
+
SwapsController.configure({
provider,
+ chainId: NetworkControllerState?.provider?.chainId,
pollCountLimit: AppConstants.SWAPS.POLL_COUNT_LIMIT,
quotePollingInterval: AppConstants.SWAPS.POLLING_INTERVAL
});
@@ -174,7 +243,7 @@ class Engine {
}
refreshTransactionHistory = async forceCheck => {
- const { TransactionController, PreferencesController, NetworkController } = this.datamodel.context;
+ const { TransactionController, PreferencesController, NetworkController } = this.context;
const { selectedAddress } = PreferencesController.state;
const { type: networkType } = NetworkController.state.provider;
const { networkId } = Networks[networkType];
@@ -235,7 +304,7 @@ class Engine {
AssetsController,
TokenBalancesController,
TokenRatesController
- } = this.datamodel.context;
+ } = this.context;
const { selectedAddress } = PreferencesController.state;
const { conversionRate, currentCurrency } = CurrencyRateController.state;
const { accounts } = AccountTrackerController.state;
@@ -301,12 +370,7 @@ class Engine {
// Whenever we are gonna start a new wallet
// either imported or created, we need to
// get rid of the old data from state
- const {
- TransactionController,
- AssetsController,
- TokenBalancesController,
- TokenRatesController
- } = this.datamodel.context;
+ const { TransactionController, AssetsController, TokenBalancesController, TokenRatesController } = this.context;
//Clear assets info
AssetsController.update({
@@ -339,7 +403,7 @@ class Engine {
NetworkController,
TransactionController,
AssetsController
- } = this.datamodel.context;
+ } = this.context;
// Select same network ?
await NetworkController.setProviderType(network.provider.type);
@@ -427,7 +491,7 @@ let instance;
export default {
get context() {
- return instance && instance.datamodel && instance.datamodel.context;
+ return instance && instance.context;
},
get state() {
const {
diff --git a/app/core/Engine.test.js b/app/core/Engine.test.js
index 8265d38a60f..a400440d10a 100644
--- a/app/core/Engine.test.js
+++ b/app/core/Engine.test.js
@@ -2,19 +2,19 @@ import Engine from './Engine';
describe('Engine', () => {
it('should expose an API', () => {
const engine = Engine.init({});
- expect(engine.datamodel.context).toHaveProperty('AccountTrackerController');
- expect(engine.datamodel.context).toHaveProperty('AddressBookController');
- expect(engine.datamodel.context).toHaveProperty('AssetsContractController');
- expect(engine.datamodel.context).toHaveProperty('AssetsController');
- expect(engine.datamodel.context).toHaveProperty('AssetsDetectionController');
- expect(engine.datamodel.context).toHaveProperty('CurrencyRateController');
- expect(engine.datamodel.context).toHaveProperty('KeyringController');
- expect(engine.datamodel.context).toHaveProperty('NetworkController');
- expect(engine.datamodel.context).toHaveProperty('PersonalMessageManager');
- expect(engine.datamodel.context).toHaveProperty('PhishingController');
- expect(engine.datamodel.context).toHaveProperty('PreferencesController');
- expect(engine.datamodel.context).toHaveProperty('TokenBalancesController');
- expect(engine.datamodel.context).toHaveProperty('TokenRatesController');
- expect(engine.datamodel.context).toHaveProperty('TypedMessageManager');
+ expect(engine.context).toHaveProperty('AccountTrackerController');
+ expect(engine.context).toHaveProperty('AddressBookController');
+ expect(engine.context).toHaveProperty('AssetsContractController');
+ expect(engine.context).toHaveProperty('AssetsController');
+ expect(engine.context).toHaveProperty('AssetsDetectionController');
+ expect(engine.context).toHaveProperty('CurrencyRateController');
+ expect(engine.context).toHaveProperty('KeyringController');
+ expect(engine.context).toHaveProperty('NetworkController');
+ expect(engine.context).toHaveProperty('PersonalMessageManager');
+ expect(engine.context).toHaveProperty('PhishingController');
+ expect(engine.context).toHaveProperty('PreferencesController');
+ expect(engine.context).toHaveProperty('TokenBalancesController');
+ expect(engine.context).toHaveProperty('TokenRatesController');
+ expect(engine.context).toHaveProperty('TypedMessageManager');
});
});
diff --git a/app/core/Vault.js b/app/core/Vault.js
index 6c3ef8684d1..b001330f5ae 100644
--- a/app/core/Vault.js
+++ b/app/core/Vault.js
@@ -76,6 +76,6 @@ export const recreateVaultWithSamePassword = async (password = '', selectedAddre
if (hdKeyring.accounts.includes(selectedAddress)) {
PreferencesController.setSelectedAddress(selectedAddress);
} else {
- PreferencesController.setSelectedAddress(hdKeyring[0]);
+ PreferencesController.setSelectedAddress(hdKeyring.accounts[0]);
}
};
diff --git a/app/images/bnb-logo.png b/app/images/bnb-logo.png
new file mode 100644
index 00000000000..3712a470d2f
Binary files /dev/null and b/app/images/bnb-logo.png differ
diff --git a/app/reducers/settings/index.js b/app/reducers/settings/index.js
index f269bea8a51..12e43aba595 100644
--- a/app/reducers/settings/index.js
+++ b/app/reducers/settings/index.js
@@ -5,7 +5,8 @@ const initialState = {
searchEngine: AppConstants.DEFAULT_SEARCH_ENGINE,
primaryCurrency: 'ETH',
lockTime: -1, // Disabled by default
- useBlockieIcon: true
+ useBlockieIcon: true,
+ hideZeroBalanceTokens: false
};
const settingsReducer = (state = initialState, action) => {
@@ -35,6 +36,11 @@ const settingsReducer = (state = initialState, action) => {
...state,
showCustomNonce: action.showCustomNonce
};
+ case 'SET_HIDE_ZERO_BALANCE_TOKENS':
+ return {
+ ...state,
+ hideZeroBalanceTokens: action.hideZeroBalanceTokens
+ };
case 'SET_USE_BLOCKIE_ICON':
return {
...state,
diff --git a/app/reducers/swaps/index.js b/app/reducers/swaps/index.js
index 48569c4e948..5c3bbd139f7 100644
--- a/app/reducers/swaps/index.js
+++ b/app/reducers/swaps/index.js
@@ -6,7 +6,7 @@ export const SWAPS_SET_HAS_ONBOARDED = 'SWAPS_SET_HAS_ONBOARDED';
const MAX_TOKENS_WITH_BALANCE = 5;
// * Action Creator
-export const setSwapsLiveness = live => ({ type: SWAPS_SET_LIVENESS, payload: live });
+export const setSwapsLiveness = (live, chainId) => ({ type: SWAPS_SET_LIVENESS, payload: { live, chainId } });
export const setSwapsHasOnboarded = hasOnboarded => ({ type: SWAPS_SET_HAS_ONBOARDED, payload: hasOnboarded });
// * Selectors
@@ -15,7 +15,10 @@ export const setSwapsHasOnboarded = hasOnboarded => ({ type: SWAPS_SET_HAS_ONBOA
* Returns the swaps liveness state
*/
-export const swapsLivenessSelector = state => state.swaps.isLive;
+export const swapsLivenessSelector = state => {
+ const chainId = state.engine.backgroundState.NetworkController.provider.chainId;
+ return state.swaps[chainId]?.isLive || false;
+};
/**
* Returns the swaps onboarded state
@@ -106,16 +109,25 @@ export const swapsTopAssetsSelector = createSelector(
// * Reducer
export const initialState = {
- isLive: true,
- hasOnboarded: false
+ isLive: true, // TODO: should we remove it?
+ hasOnboarded: false,
+
+ '1': {
+ isLive: true
+ }
};
function swapsReducer(state = initialState, action) {
switch (action.type) {
case SWAPS_SET_LIVENESS: {
+ const { live, chainId } = action.payload;
+ const data = state[chainId];
return {
...state,
- isLive: Boolean(action.payload)
+ [chainId]: {
+ ...data,
+ isLive: live
+ }
};
}
case SWAPS_SET_HAS_ONBOARDED: {
diff --git a/app/reducers/swaps/swaps.test.js b/app/reducers/swaps/swaps.test.js
index 8ad95806c35..94812cdeae6 100644
--- a/app/reducers/swaps/swaps.test.js
+++ b/app/reducers/swaps/swaps.test.js
@@ -10,10 +10,10 @@ describe('swaps reducer', () => {
it('should set liveness', () => {
const initalState = reducer(undefined, emptyAction);
- const notLiveState = reducer(initalState, { type: SWAPS_SET_LIVENESS, payload: false });
- expect(notLiveState.isLive).toBe(false);
- const liveState = reducer(initalState, { type: SWAPS_SET_LIVENESS, payload: true });
- expect(liveState.isLive).toBe(true);
+ const notLiveState = reducer(initalState, { type: SWAPS_SET_LIVENESS, payload: { live: false, chainId: 1 } });
+ expect(notLiveState['1'].isLive).toBe(false);
+ const liveState = reducer(initalState, { type: SWAPS_SET_LIVENESS, payload: { live: true, chainId: 1 } });
+ expect(liveState['1'].isLive).toBe(true);
});
it('should set has onboarded', () => {
diff --git a/app/util/Device.js b/app/util/Device.js
index e172643eee2..7fc173d2373 100644
--- a/app/util/Device.js
+++ b/app/util/Device.js
@@ -1,6 +1,7 @@
'use strict';
import { Dimensions, Platform } from 'react-native';
+import { getModel } from 'react-native-device-info';
export default class Device {
static getDeviceWidth() {
@@ -80,4 +81,10 @@ export default class Device {
static isMediumDevice() {
return this.getDeviceHeight() < 736;
}
+
+ static isIphone12() {
+ const model = getModel();
+ const models = ['iPhone 12', 'iPhone 12 Pro', 'iPhone 12 Pro Max'];
+ return models.includes(model);
+ }
}
diff --git a/app/util/Logger.js b/app/util/Logger.js
index 12262b83046..68da02eeca3 100644
--- a/app/util/Logger.js
+++ b/app/util/Logger.js
@@ -43,8 +43,27 @@ export default class Logger {
if (__DEV__) {
console.warn(DEBUG, error); // eslint-disable-line no-console
} else if (metricsOptIn === AGREED) {
- let exception = error.error || error.message || error.originalError || error;
- if (!(error instanceof Error)) {
+ let exception = error;
+
+ if (!error) {
+ if (!extra) return console.warn('No error nor extra info provided');
+
+ const typeExtra = typeof extra;
+ switch (typeExtra) {
+ case 'string':
+ exception = new Error(extra);
+ break;
+ case 'object':
+ if (extra.message) {
+ exception = new Error(extra.message);
+ } else {
+ exception = new Error(JSON.stringify(extra));
+ }
+ break;
+ default:
+ exception = new Error('error to capture is not an error instance');
+ }
+ } else if (!(error instanceof Error)) {
const type = typeof error;
switch (type) {
case 'string':
diff --git a/app/util/address.js b/app/util/address.js
index 842a597adbd..d7ae893516c 100644
--- a/app/util/address.js
+++ b/app/util/address.js
@@ -2,6 +2,9 @@ import { toChecksumAddress } from 'ethereumjs-util';
import Engine from '../core/Engine';
import AppConstants from '../core/AppConstants';
import { strings } from '../../locales/i18n';
+import { tlc } from '../util/general';
+
+const { supportedTLDs } = AppConstants;
/**
* Returns full checksummed address
@@ -67,11 +70,11 @@ export async function importAccountFromPrivateKey(private_key) {
* @returns {boolean} - Returns a boolean indicating if it is valid
*/
export function isENS(name) {
- const rec = name && name.split('.');
- if (!rec || rec.length === 1 || !AppConstants.supportedTLDs.includes(rec[rec.length - 1])) {
- return false;
- }
- return true;
+ const OFFSET = 1;
+ const index = name && name.lastIndexOf('.');
+ const tld = index && index >= OFFSET && tlc(name.substr(index + OFFSET, name.length - OFFSET));
+ if (index && tld && supportedTLDs.includes(tld)) return true;
+ return false;
}
/**
diff --git a/app/util/address.test.js b/app/util/address.test.js
new file mode 100644
index 00000000000..3ef53dd3455
--- /dev/null
+++ b/app/util/address.test.js
@@ -0,0 +1,19 @@
+import { isENS } from './address';
+
+describe('isENS', () => {
+ it('should return false by default', () => {
+ expect(isENS()).toBe(false);
+ });
+ it('should return false for normal domain', () => {
+ expect(isENS('ricky.codes')).toBe(false);
+ });
+ it('should return true for ens', () => {
+ expect(isENS('rickycodes.eth')).toBe(true);
+ });
+ it('should return true for eth ens', () => {
+ expect(isENS('ricky.eth.eth')).toBe(true);
+ });
+ it('should return true for metamask ens', () => {
+ expect(isENS('ricky.metamask.eth')).toBe(true);
+ });
+});
diff --git a/app/util/analyticsV2.js b/app/util/analyticsV2.js
index c1083b179fe..3bcffe71f46 100644
--- a/app/util/analyticsV2.js
+++ b/app/util/analyticsV2.js
@@ -88,7 +88,30 @@ export const trackEventV2 = (eventName, params) => {
});
};
+/**
+ * This functions logs errors to analytics instead of sentry.
+ * The objective is to log errors (that are not errors from our side) like “Invalid Password”.
+ * An error like this generally means a user inserted the wrong password, so logging to sentry doesn't make sense.
+ * But we still want to log this to analytics so that we are aware of a rapid increase which may mean it's an error from our side, for example, an error with the encryption library.
+ * @param {String} type
+ * @param {String} errorMessage
+ * @param {String} otherInfo
+ */
+export const trackErrorAsAnalytics = (type, errorMessage, otherInfo) => {
+ try {
+ Analytics.trackEventWithParameters(generateOpt('Error occurred'), {
+ error: true,
+ type,
+ errorMessage,
+ otherInfo
+ });
+ } catch (error) {
+ Logger.error(error, 'Error logging analytics - trackErrorAsAnalytics');
+ }
+};
+
export default {
ANALYTICS_EVENTS: ANALYTICS_EVENTS_V2,
- trackEvent: trackEventV2
+ trackEvent: trackEventV2,
+ trackErrorAsAnalytics
};
diff --git a/app/util/infura-conversion.json b/app/util/infura-conversion.json
index 28eb58d2055..67020bab413 100644
--- a/app/util/infura-conversion.json
+++ b/app/util/infura-conversion.json
@@ -28,6 +28,13 @@
"name": "Indonesian Rupiah"
}
},
+ {
+ "symbol": "ethnzd",
+ "quote": {
+ "code": "nzd",
+ "name": "New Zealand Dollar"
+ }
+ },
{
"symbol": "ethphp",
"quote": {
diff --git a/app/util/middlewares.js b/app/util/middlewares.js
index bc47af3df66..7e43dfd3b15 100644
--- a/app/util/middlewares.js
+++ b/app/util/middlewares.js
@@ -1,6 +1,19 @@
import Logger from './Logger';
+import { trackErrorAsAnalytics } from './analyticsV2';
-const REJECTED_TRANSACTION_ERROR = 'User rejected the transaction';
+/**
+ * List of rpc errors caused by the user rejecting a certain action.
+ * Errors that include these phrases should not be logged to Sentry.
+ * Examples of these errors include:
+ * - User rejected the transaction
+ * - User cancelled the transaction
+ * - User rejected the request.
+ * - MetaMask Message Signature: User denied message signature.
+ * - MetaMask Personal Message Signature: User denied message signature.
+ */
+const USER_REJECTED_ERRORS = ['user rejected', 'user denied', 'user cancelled'];
+
+const USER_REJECTED_ERROR_CODE = 4001;
/**
* Returns a middleware that appends the DApp origin to request
@@ -21,6 +34,29 @@ export function createOriginMiddleware(opts) {
};
}
+/**
+ * Checks if the error code or message contains a user rejected error
+ * @param {String} errorMessage
+ * @returns {boolean}
+ */
+function containsUserRejectedError(errorMessage, errorCode) {
+ try {
+ if (!errorMessage || !(typeof errorMessage === 'string')) return false;
+
+ const userRejectedErrorMessage = USER_REJECTED_ERRORS.some(userRejectedError =>
+ errorMessage.toLowerCase().includes(userRejectedError.toLowerCase())
+ );
+
+ if (userRejectedErrorMessage) return true;
+
+ if (errorCode === USER_REJECTED_ERROR_CODE) return true;
+
+ return false;
+ } catch (e) {
+ return false;
+ }
+}
+
/**
* Returns a middleware that logs RPC activity
* @param {{ origin: string }} opts - The middleware options
@@ -31,8 +67,40 @@ export function createLoggerMiddleware(opts) {
next((/** @type {Function} */ cb) => {
if (res.error) {
const { error, ...resWithoutError } = res;
- if (error && error.message !== REJECTED_TRANSACTION_ERROR) {
- Logger.error(error, { message: 'Error in RPC response', res: resWithoutError });
+ if (error) {
+ if (containsUserRejectedError(error.message, error.code)) {
+ trackErrorAsAnalytics(`Error in RPC response: User rejected`, error.message);
+ } else {
+ /**
+ * Example of a rpc error:
+ * { "code":-32603,
+ * "message":"Internal JSON-RPC error.",
+ * "data":{"code":-32000,"message":"gas required exceeds allowance (59956966) or always failing transaction"}
+ * }
+ * This will make the error log to sentry with the title "gas required exceeds allowance (59956966) or always failing transaction"
+ * making it easier to differentiate each error.
+ */
+ let errorToLog = error;
+ const errorParams = {
+ message: 'Error in RPC response',
+ orginalError: error,
+ res: resWithoutError
+ };
+
+ if (error.message) {
+ errorToLog = new Error(error.message);
+ }
+
+ if (error.data) {
+ errorParams.data = error.data;
+
+ if (error.data.message) {
+ errorToLog = new Error(error.data.message);
+ }
+ }
+
+ Logger.error(errorToLog, errorParams);
+ }
}
}
if (req.isMetamaskInternal) {
diff --git a/app/util/testSetup.js b/app/util/testSetup.js
index f49f82f2be4..7794d231a18 100644
--- a/app/util/testSetup.js
+++ b/app/util/testSetup.js
@@ -86,7 +86,6 @@ jest.mock('react-native-keychain', () => ({ getSupportedBiometryType: () => Prom
jest.mock('react-native-share', () => 'RNShare');
jest.mock('react-native-branch', () => ({ subscribe: () => 'RNBranch' }));
jest.mock('react-native-sensors', () => 'RNSensors');
-jest.mock('react-native-device-info', () => 'DeviceInfo');
jest.mock('react-native-search-api', () => 'SearchApi');
jest.mock('react-native-reanimated', () => require('react-native-reanimated/mock'));
jest.mock('react-native-background-timer', () => 'RNBackgroundTimer');
diff --git a/app/util/transactions.js b/app/util/transactions.js
index 8058191ef0f..42d5aa9815d 100644
--- a/app/util/transactions.js
+++ b/app/util/transactions.js
@@ -5,9 +5,10 @@ import { strings } from '../../locales/i18n';
import contractMap from '@metamask/contract-metadata';
import { safeToChecksumAddress } from './address';
import { util } from '@metamask/controllers';
-import { swapsUtils } from '@estebanmino/controllers';
+import { swapsUtils } from '@metamask/swaps-controller';
import { hexToBN } from './number';
import AppConstants from '../core/AppConstants';
+import { isMainnetByChainId } from './networks';
const { SAI_ADDRESS } = AppConstants;
export const TOKEN_METHOD_TRANSFER = 'transfer';
@@ -41,7 +42,7 @@ export const TRANSACTION_TYPES = {
APPROVE: 'transaction_approve'
};
-const { SWAPS_CONTRACT_ADDRESS } = swapsUtils;
+const { getSwapsContractAddress } = swapsUtils;
/**
* Utility class with the single responsibility
* of caching CollectibleAddresses
@@ -210,13 +211,14 @@ export async function getMethodData(data) {
* Returns wether the given address is a contract
*
* @param {string} address - Ethereum address
+ * @param {string} chainId - Current chainId
* @returns {boolean} - Whether the given address is a contract
*/
-export async function isSmartContractAddress(address) {
+export async function isSmartContractAddress(address, chainId) {
if (!address) return false;
address = toChecksumAddress(address);
// If in contract map we don't need to cache it
- if (contractMap[address]) {
+ if (isMainnetByChainId(chainId) && contractMap[address]) {
return Promise.resolve(true);
}
const { TransactionController } = Engine.context;
@@ -250,12 +252,13 @@ export async function isCollectibleAddress(address, tokenId) {
* Returns corresponding transaction action key
*
* @param {object} transaction - Transaction object
+ * @param {string} chainId - Current chainId
* @returns {string} - Corresponding transaction action key
*/
-export async function getTransactionActionKey(transaction) {
+export async function getTransactionActionKey(transaction, chainId) {
const { transaction: { data, to } = {} } = transaction;
if (!to) return CONTRACT_METHOD_DEPLOY;
- if (to === SWAPS_CONTRACT_ADDRESS) return SWAPS_TRANSACTION_ACTION_KEY;
+ if (to === getSwapsContractAddress(chainId)) return SWAPS_TRANSACTION_ACTION_KEY;
let ret;
// if data in transaction try to get method data
if (data && data !== '0x') {
@@ -282,7 +285,7 @@ export async function getTransactionActionKey(transaction) {
* @param {string} selectedAddress - Current account public address
* @returns {string} - Transaction type message
*/
-export async function getActionKey(tx, selectedAddress, ticker) {
+export async function getActionKey(tx, selectedAddress, ticker, chainId) {
if (tx && tx.isTransfer) {
const selfSent = safeToChecksumAddress(tx.transaction.from) === selectedAddress;
const translationKey = selfSent ? 'transactions.self_sent_unit' : 'transactions.received_unit';
@@ -290,7 +293,7 @@ export async function getActionKey(tx, selectedAddress, ticker) {
if (tx.transferInformation.contractAddress === SAI_ADDRESS.toLowerCase()) tx.transferInformation.symbol = 'SAI';
return strings(translationKey, { unit: tx.transferInformation.symbol });
}
- const actionKey = await getTransactionActionKey(tx);
+ const actionKey = await getTransactionActionKey(tx, chainId);
if (actionKey === SEND_ETHER_ACTION_KEY) {
const incoming = safeToChecksumAddress(tx.transaction.to) === selectedAddress;
const selfSent = incoming && safeToChecksumAddress(tx.transaction.from) === selectedAddress;
@@ -319,10 +322,11 @@ export async function getActionKey(tx, selectedAddress, ticker) {
* Returns corresponding transaction function type
*
* @param {object} tx - Transaction object
+ * @param {string} chainId - Current chainId
* @returns {string} - Transaction function type
*/
-export async function getTransactionReviewActionKey(transaction) {
- const actionKey = await getTransactionActionKey({ transaction });
+export async function getTransactionReviewActionKey(transaction, chainId) {
+ const actionKey = await getTransactionActionKey({ transaction }, chainId);
const transactionReviewActionKey = reviewActionKeys[actionKey];
if (transactionReviewActionKey) {
return transactionReviewActionKey;
diff --git a/app/util/validators.js b/app/util/validators.js
index 25195c8e272..1eb1f24207e 100644
--- a/app/util/validators.js
+++ b/app/util/validators.js
@@ -1,4 +1,5 @@
import { ethers } from 'ethers';
+import { confusables } from 'unicode-confusables';
export const failedSeedPhraseRequirements = seed => {
const wordCount = seed.split(/\s/u).length;
@@ -13,3 +14,23 @@ export const parseSeedPhrase = seedPhrase =>
?.join(' ') || '';
export const { isValidMnemonic } = ethers.utils;
+
+export const collectConfusables = ensName => {
+ const key = 'similarTo';
+ const collection = confusables(ensName).reduce(
+ (total, current) => (key in current ? [...total, current.point] : total),
+ []
+ );
+ return collection;
+};
+
+const zeroWidthPoints = new Set([
+ '\u200b', // zero width space
+ '\u200c', // zero width non-joiner
+ '\u200d', // zero width joiner
+ '\ufeff', // zero width no-break space
+ '\u2028', // line separator
+ '\u2029' // paragraph separator,
+]);
+
+export const hasZeroWidthPoints = char => zeroWidthPoints.has(char);
diff --git a/app/util/validators.test.js b/app/util/validators.test.js
index a9f8b7c90e6..0f676b55953 100644
--- a/app/util/validators.test.js
+++ b/app/util/validators.test.js
@@ -1,4 +1,4 @@
-import { failedSeedPhraseRequirements, parseSeedPhrase } from './validators';
+import { failedSeedPhraseRequirements, parseSeedPhrase, hasZeroWidthPoints, collectConfusables } from './validators';
const VALID_24 =
'verb middle giant soon wage common wide tool gentle garlic issue nut retreat until album recall expire bronze bundle live accident expect dry cook';
@@ -37,3 +37,23 @@ describe('parseSeedPhrase', () => {
expect(parseSeedPhrase(` ${String(VALID_12).toUpperCase()}`)).toEqual(VALID_12);
});
});
+
+describe('hasZeroWidthPoints', () => {
+ it('should detect zero-width unicode', () => {
+ expect('vitalik.eth'.split('').some(hasZeroWidthPoints)).toEqual(true);
+ });
+ it('should not detect zero-width unicode', () => {
+ expect('vitalik.eth'.split('').some(hasZeroWidthPoints)).toEqual(false);
+ });
+});
+
+describe('collectConfusables', () => {
+ it('should detect homoglyphic unicode points', () => {
+ expect(collectConfusables('vitalik.eth')).toHaveLength(1);
+ expect(collectConfusables('faceboоk.eth')).toHaveLength(1);
+ });
+
+ it('should detect multiple homoglyphic unicode points', () => {
+ expect(collectConfusables('ѕсоре.eth')).toHaveLength(5);
+ });
+});
diff --git a/app/videos/recovery-phrase.mp4 b/app/videos/recovery-phrase.mp4
new file mode 100644
index 00000000000..442ebdae82c
Binary files /dev/null and b/app/videos/recovery-phrase.mp4 differ
diff --git a/e2e/add-custom-rpc.spec.js b/e2e/add-custom-rpc.spec.js
index 60efc364d04..d40b4db819a 100644
--- a/e2e/add-custom-rpc.spec.js
+++ b/e2e/add-custom-rpc.spec.js
@@ -129,30 +129,21 @@ describe('Custom RPC Tests', () => {
await TestHelpers.tap('open-networks-button');
// Check that networks list is visible
await TestHelpers.checkIfVisible('networks-list');
- // Swipe down on networks list
- await TestHelpers.swipe('networks-list', 'up');
// Check that our network is added
await TestHelpers.checkIfElementHasString('other-network-name', 'xDai');
-
- // iOS change networks tests
- if (device.getPlatform() === 'ios') {
- // Change to Rinkeby Network
- await TestHelpers.tapByText(RINKEBY);
- // Check that we are on correct network
- await TestHelpers.checkIfElementHasString('network-name', RINKEBY);
- // Tap to prompt network list
- await TestHelpers.tap('open-networks-button');
- // Check that networks list is visible
- await TestHelpers.checkIfVisible('networks-list');
- // Swipe down on networks list
- await TestHelpers.swipe('networks-list', 'up');
- // Change to back to xDai Network
- await TestHelpers.tapByText('xDai');
- } else {
- // Close list
- await TestHelpers.tapByText('Close');
- }
-
+ // Change to Rinkeby Network
+ await TestHelpers.tapByText(RINKEBY);
+ // Check that we are on correct network
+ await TestHelpers.checkIfElementHasString('network-name', RINKEBY);
+ // Tap to prompt network list
+ await TestHelpers.tap('open-networks-button');
+ // Check that networks list is visible
+ await TestHelpers.checkIfVisible('networks-list');
+ // Swipe up on networks list
+ await TestHelpers.swipe('other-networks-scroll', 'up', 'fast');
+ await TestHelpers.delay(1000);
+ // Change to back to xDai Network
+ await TestHelpers.tapByText('xDai');
// Check that we are on the wallet screen
await TestHelpers.checkIfVisible('wallet-screen');
// Check that we are on correct network
@@ -171,22 +162,21 @@ describe('Custom RPC Tests', () => {
// Check that we are on the networks screen
await TestHelpers.checkIfVisible('networks-screen');
// Tap on xDai to remove network
- await element(by.text('xDai')).longPress();
- // Tap remove
+ await TestHelpers.tapAndLongPressAtIndex('rpc-networks', 0);
+ //Remove xDAI and verify removed on wallet view
+ //Tap remove
await TestHelpers.tapByText('Remove');
-
// Go back to wallet screen
if (device.getPlatform() === 'ios') {
// Tap on back arrow
- await TestHelpers.tapAtPoint('networks-screen', { x: 25, y: -22 });
+ await TestHelpers.tap('nav-ios-back');
// Tap close
await TestHelpers.tapByText('Close');
} else {
// Go Back for android
- await device.pressBack();
- await device.pressBack();
+ await TestHelpers.tap('nav-android-back');
+ await TestHelpers.tap('nav-android-back');
}
-
// Check that we are on the wallet screen
await TestHelpers.checkIfExists('wallet-screen');
// Check that we are on Mainnet
diff --git a/e2e/addressbook-tests.spec.js b/e2e/addressbook-tests.spec.js
index 3fb208c3acc..0f0af8384dc 100644
--- a/e2e/addressbook-tests.spec.js
+++ b/e2e/addressbook-tests.spec.js
@@ -2,6 +2,7 @@
import TestHelpers from './helpers';
const INVALID_ADDRESS = '0xB8B4EE5B1b693971eB60bDa15211570df2dB221L';
+const TETHER_ADDRESS = '0xdac17f958d2ee523a2206206994597c13d831ec7';
const MYTH_ADDRESS = '0x1FDb169Ef12954F20A15852980e1F0C122BfC1D6';
const MEMO = 'Test adding ENS';
const PASSWORD = '12345678';
@@ -84,12 +85,12 @@ describe('Addressbook Tests', () => {
it('should go to send view', async () => {
// Check that we are on the wallet screen
await TestHelpers.checkIfVisible('wallet-screen');
- // Tap on ETH asset
- await TestHelpers.waitAndTap('eth-logo');
- // Check that we are on the token overview screen
- await TestHelpers.checkIfVisible('token-asset-overview');
+ // Open Drawer
+ await TestHelpers.tap('hamburger-menu-button-wallet');
+ // Check that the drawer is visbile
+ await TestHelpers.checkIfVisible('drawer-screen');
// Tap on Send button
- await TestHelpers.tapByText('SEND');
+ await TestHelpers.tap('drawer-send-button');
// Check that we are on the send screen
await TestHelpers.checkIfVisible('send-screen');
// Make sure view with my accounts visible
@@ -97,15 +98,26 @@ describe('Addressbook Tests', () => {
});
it('should input a valid address to send to', async () => {
- // Input incorrect address
+ // Input incorrect address Currently commented out until https://github.com/MetaMask/metamask-mobile/issues/2533 is fixed
+ // if (device.getPlatform() === 'android') {
+ // await TestHelpers.replaceTextInField('txn-to-address-input', INVALID_ADDRESS);
+ // await element(by.id('txn-to-address-input')).tapReturnKey();
+ // } else {
+ // await TestHelpers.typeTextAndHideKeyboard('txn-to-address-input', INVALID_ADDRESS);
+ // }
+ // // Check that the error is displayed
+ // await TestHelpers.checkIfVisible('address-error');
+ //Input token address to test for error
if (device.getPlatform() === 'android') {
- await TestHelpers.replaceTextInField('txn-to-address-input', INVALID_ADDRESS);
- await element(by.id('txn-to-address-input')).tapReturnKey();
+ await TestHelpers.replaceTextInField('txn-to-address-input', TETHER_ADDRESS);
} else {
- await TestHelpers.typeTextAndHideKeyboard('txn-to-address-input', INVALID_ADDRESS);
+ await TestHelpers.typeTextAndHideKeyboard('txn-to-address-input', TETHER_ADDRESS);
}
// Check that the error is displayed
await TestHelpers.checkIfVisible('address-error');
+ // Tap x to remove address
+ await TestHelpers.tap('clear-address-button');
+ await TestHelpers.delay(1000);
// Input valid myth address
if (device.getPlatform() === 'android') {
await TestHelpers.replaceTextInField('txn-to-address-input', MYTH_ADDRESS);
@@ -142,8 +154,6 @@ describe('Addressbook Tests', () => {
it('should go to settings then select contacts', async () => {
// Tap on cancel button
await TestHelpers.tap('send-cancel-button');
- // Tap on back button to proceed to wallet view
- await TestHelpers.tap('asset-back-button');
// Check that we are on the wallet screen
await TestHelpers.checkIfVisible('wallet-screen');
// Open Drawer
@@ -186,11 +196,10 @@ describe('Addressbook Tests', () => {
await TestHelpers.replaceTextInField('contact-memo-input', MEMO);
// Tap add contact button
if (device.getPlatform() === 'android') {
- await TestHelpers.tapByText('Add contact');
- await TestHelpers.delay(1000);
- await TestHelpers.tapByText('Add contact');
- } else {
await TestHelpers.tap('contact-add-contact-button');
+ await TestHelpers.delay(700);
+ await TestHelpers.tap('contact-add-contact-button');
+ } else {
await TestHelpers.tap('contact-add-contact-button');
}
// Check that we are on the contacts screen
@@ -208,6 +217,9 @@ describe('Addressbook Tests', () => {
await TestHelpers.replaceTextInField('contact-name-input', 'Moon');
// Tap on Edit contact button
await TestHelpers.tapByText('Edit contact');
+ if (device.getPlatform() === 'ios') {
+ await TestHelpers.tapByText('Edit contact');
+ }
// Check that we are on the contacts screen
await TestHelpers.checkIfVisible('contacts-screen');
// Check that Ibrahim address is saved in the address book
@@ -223,8 +235,11 @@ describe('Addressbook Tests', () => {
await TestHelpers.tapByText('Edit');
// Tap on Delete
await TestHelpers.tapByText('Delete');
- // Tap on Delete
- await TestHelpers.tapByText('Delete');
+ if (device.getPlatform() === 'ios') {
+ await TestHelpers.tapByText('Delete', 1);
+ } else {
+ await TestHelpers.tapByText('Delete');
+ }
// Ensure Moon is not visible
await TestHelpers.checkIfElementWithTextIsNotVisible('Moon');
});
@@ -234,7 +249,7 @@ describe('Addressbook Tests', () => {
await TestHelpers.tap('title-back-arrow-button');
// tap to get out of settings view
if (device.getPlatform() === 'android') {
- await device.pressBack();
+ await TestHelpers.tap('nav-android-back');
} else {
await TestHelpers.tapByText('Close');
}
diff --git a/e2e/browser-tests.spec.js b/e2e/browser-tests.spec.js
index 2f85fecd908..642e14790e7 100644
--- a/e2e/browser-tests.spec.js
+++ b/e2e/browser-tests.spec.js
@@ -3,7 +3,7 @@ import TestHelpers from './helpers';
const ENS_Example = 'https://brunobarbieri.eth';
const ENS_TLD = 'https://inbox.mailchain.xyz';
-const UNISWAP = 'https://uniswap.eth';
+const UNISWAP = 'https://uniswap.exchange';
const PASSWORD = '12345678';
describe('Browser Tests', () => {
@@ -95,42 +95,46 @@ describe('Browser Tests', () => {
});
it('should go to first explore tab and navigate back to homepage', async () => {
- // Tap on first category
- if (device.getPlatform() === 'android') {
+ // This can only be done on Android since we removed option for iOS due to Appstore
+ if (!device.getPlatform() === 'android') {
+ // Tap on first category
await TestHelpers.tapAtPoint('browser-screen', { x: 100, y: 425 });
- } else {
- await TestHelpers.tapAtPoint('browser-screen', { x: 100, y: 450 });
+ // Tap on first option
+ await TestHelpers.tapAtPoint('browser-screen', { x: 80, y: 100 });
+ // Tap back button
+ await TestHelpers.waitAndTap('go-back-button');
+ // Tap back button
+ await TestHelpers.waitAndTap('go-back-button');
+ // Wait for page to load
+ await TestHelpers.delay(1000);
+ // Check that we are on the browser screen
+ await TestHelpers.checkIfVisible('browser-screen');
}
- // Tap on first option
- await TestHelpers.tapAtPoint('browser-screen', { x: 80, y: 100 });
- // Tap back button
- await TestHelpers.waitAndTap('go-back-button');
- // Tap back button
- await TestHelpers.waitAndTap('go-back-button');
- // Wait for page to load
- await TestHelpers.delay(1000);
- // Check that we are on the browser screen
- await TestHelpers.checkIfVisible('browser-screen');
});
it('should go to uniswap', async () => {
// Tap on home on bottom navbar
- await TestHelpers.tap('home-button');
+ // await TestHelpers.tap('home-button');
// Wait for page to load
- await TestHelpers.delay(1000);
+ await TestHelpers.delay(3000);
// Tap on search in bottom navbar
await TestHelpers.tap('search-button');
// Navigate to URL
if (device.getPlatform() === 'ios') {
+ await TestHelpers.clearField('url-input');
await TestHelpers.typeTextAndHideKeyboard('url-input', UNISWAP);
+ await TestHelpers.delay(2000);
} else {
+ await TestHelpers.tap('android-cancel-url-button');
await TestHelpers.replaceTextInField('url-input', UNISWAP);
await element(by.id('url-input')).tapReturnKey();
}
// Wait for page to load
await TestHelpers.delay(5000);
- // Check that the dapp title is correct
- await TestHelpers.checkIfElementWithTextIsVisible('uniswap.eth', 0);
+ if (device.getPlatform() === 'android') {
+ // Check that the dapp title is correct
+ await TestHelpers.checkIfElementWithTextIsVisible('app.uniswap.org', 0);
+ }
// Tap on CANCEL button
await TestHelpers.tap('connect-cancel-button');
@@ -139,7 +143,11 @@ describe('Browser Tests', () => {
// Wait for page to load
await TestHelpers.delay(3000);
await TestHelpers.tap('connect-cancel-button');
-
+ // Android has weird behavior where the URL modal stays open, so this closes it
+ // Close URL modal
+ if (device.getPlatform() === 'android') {
+ await device.pressBack();
+ }
// Check that we are still on the browser screen
await TestHelpers.checkIfVisible('browser-screen');
});
@@ -166,7 +174,10 @@ describe('Browser Tests', () => {
await TestHelpers.checkIfVisible('browser-screen');
// Tap on Favorites tab
if (device.getPlatform() === 'ios') {
- await TestHelpers.tapAtPoint('browser-screen', { x: 274, y: 227 });
+ // Tap on options
+ await TestHelpers.waitAndTap('options-button');
+ // Open new tab
+ await TestHelpers.tapByText('New tab');
await TestHelpers.tapAtPoint('browser-screen', { x: 174, y: 281 });
await TestHelpers.delay(1500);
} else {
@@ -220,7 +231,7 @@ describe('Browser Tests', () => {
await TestHelpers.checkIfVisible('browser-screen');
// Tap on empowr from search results
if (device.getPlatform() === 'ios') {
- await TestHelpers.tapAtPoint('browser-screen', { x: 20, y: 245 });
+ await TestHelpers.tapAtPoint('browser-screen', { x: 60, y: 270 });
} else {
await TestHelpers.tapAtPoint('browser-screen', { x: 56, y: 284 });
await TestHelpers.delay(700);
diff --git a/e2e/helpers.js b/e2e/helpers.js
index 309f9ebba6a..f0818ea95ee 100644
--- a/e2e/helpers.js
+++ b/e2e/helpers.js
@@ -52,7 +52,13 @@ export default class TestHelpers {
static async tapAndLongPress(elementId) {
await TestHelpers.tap(elementId);
- return element(by.id(elementId)).longPress();
+ return element(by.id(elementId)).longPress(2000);
+ }
+
+ static async tapAndLongPressAtIndex(elementId, index) {
+ return element(by.id(elementId, index))
+ .atIndex(index || 0)
+ .longPress(2000);
}
static async replaceTextInField(elementId, text) {
@@ -71,8 +77,8 @@ export default class TestHelpers {
.tap();
}
- static async swipe(elementId, direction) {
- await element(by.id(elementId)).swipe(direction);
+ static async swipe(elementId, direction, speed, percentage) {
+ await element(by.id(elementId)).swipe(direction, speed, percentage);
}
static async scrollTo(scrollviewId, edge) {
diff --git a/e2e/onboarding-wizard-opt-out.spec.js b/e2e/onboarding-wizard-opt-out.spec.js
index 9246407301f..a282eccc314 100644
--- a/e2e/onboarding-wizard-opt-out.spec.js
+++ b/e2e/onboarding-wizard-opt-out.spec.js
@@ -84,28 +84,11 @@ describe('Onboarding wizard opt-out', () => {
// Scroll to the bottom
if (device.getPlatform() === 'android') {
- await TestHelpers.swipe('change-password-section', 'up');
- TestHelpers.delay(1500);
- await TestHelpers.swipe('change-password-section', 'up');
- TestHelpers.delay(1500);
- await TestHelpers.swipe('auto-lock-section', 'up');
- TestHelpers.delay(1500);
- await TestHelpers.swipe('clear-privacy-section', 'up');
- TestHelpers.delay(1500);
- await TestHelpers.swipe('clear-cookies-section', 'up');
- TestHelpers.delay(1500);
- await TestHelpers.swipe('privacy-mode-section', 'up');
- TestHelpers.delay(1500);
- await TestHelpers.swipe('privacy-mode-section', 'up');
- TestHelpers.delay(1500);
- await TestHelpers.swipe('privacy-mode-section', 'up');
- TestHelpers.delay(1500);
- await TestHelpers.swipe('metametrics-section', 'up');
- TestHelpers.delay(1500);
+ await TestHelpers.swipe('security-settings-scrollview', 'up', 'fast');
+ await TestHelpers.delay(1000);
} else {
- await TestHelpers.swipe('auto-lock-section', 'up');
+ await TestHelpers.swipe('auto-lock-section', 'up', 'fast');
}
-
// Toggle Metametrics on
await TestHelpers.tap('metametrics-switch');
TestHelpers.delay(1000);
@@ -133,43 +116,40 @@ describe('Onboarding wizard opt-out', () => {
await TestHelpers.checkIfNotVisible('onboarding-wizard-step1-view');
});
- // commenting this out as tapping on this take a tour prompt currently doesn't work
- // once fixed I can add it back in
-
- // it('should take tour and skip tutorial', async () => {
- // // Open Drawer
- // await TestHelpers.tap('hamburger-menu-button-wallet');
- // // Check that the drawer is visbile
- // await TestHelpers.checkIfVisible('drawer-screen');
- // // Tap on Browser
- // await TestHelpers.tapByText('Browser');
- // // Wait for page to load
- // await TestHelpers.delay(1000);
- // // Check that we are on the browser screen
- // await TestHelpers.checkIfVisible('browser-screen');
- // // Scroll on browser to show tutorial box and tap to skip
- // if (device.getPlatform() === 'ios') {
- // await TestHelpers.swipe('browser-screen', 'up');
- // } else {
- // await TestHelpers.checkIfExists('browser-webview');
- // await TestHelpers.swipe('browser-webview', 'up');
- // await TestHelpers.delay(1000);
- // }
- // // Tap on the Take a tour box
- // if (device.getPlatform() === 'ios') {
- // await TestHelpers.tapAtPoint('browser-screen', { x: 215, y: 555 });
- // } else {
- // await TestHelpers.tapAtPoint('browser-screen', { x: 175, y: 480 });
- // }
- // // Check that we are on the wallet screen
- // await TestHelpers.checkIfNotVisible('browser-screen');
- // // Check that the onboarding wizard is present
- // await TestHelpers.checkIfVisible('onboarding-wizard-step1-view');
- // // Check that Take the tour CTA is visible and tap it
- // await TestHelpers.waitAndTap('onboarding-wizard-next-button');
- // // Tap on Skip Tutorial
- // await TestHelpers.tapByText('Skip Tutorial');
- // // Check that the wizard is not visible anymore
- // await TestHelpers.checkIfNotVisible('onboarding-wizard-step1-view');
- // });
+ it('should take tour and skip tutorial', async () => {
+ // Open Drawer
+ await TestHelpers.tap('hamburger-menu-button-wallet');
+ // Check that the drawer is visbile
+ await TestHelpers.checkIfVisible('drawer-screen');
+ // Tap on Browser
+ await TestHelpers.tapByText('Browser');
+ // Wait for page to load
+ await TestHelpers.delay(1000);
+ // Check that we are on the browser screen
+ await TestHelpers.checkIfVisible('browser-screen');
+ // Scroll on browser to show tutorial box and tap to skip
+ if (device.getPlatform() === 'ios') {
+ await TestHelpers.swipe('browser-screen', 'up');
+ } else {
+ await TestHelpers.checkIfExists('browser-webview');
+ await TestHelpers.swipe('browser-webview', 'up');
+ await TestHelpers.delay(1000);
+ }
+ // Tap on the Take a tour box
+ if (device.getPlatform() === 'ios') {
+ await TestHelpers.tapAtPoint('browser-screen', { x: 215, y: 555 });
+ } else {
+ await TestHelpers.tapAtPoint('browser-screen', { x: 175, y: 480 });
+ }
+ // Check that we are on the wallet screen
+ await TestHelpers.checkIfNotVisible('browser-screen');
+ // Check that the onboarding wizard is present
+ await TestHelpers.checkIfVisible('onboarding-wizard-step1-view');
+ // Check that Take the tour CTA is visible and tap it
+ await TestHelpers.waitAndTap('onboarding-wizard-next-button');
+ // Tap on Skip Tutorial
+ await TestHelpers.tapByText('Skip Tutorial');
+ // Check that the wizard is not visible anymore
+ await TestHelpers.checkIfNotVisible('onboarding-wizard-step1-view');
+ });
});
diff --git a/e2e/request-token-flow.spec.js b/e2e/request-token-flow.spec.js
index 65bc6835692..3c4583dc3c8 100644
--- a/e2e/request-token-flow.spec.js
+++ b/e2e/request-token-flow.spec.js
@@ -90,7 +90,7 @@ describe('Request Token Flow', () => {
await TestHelpers.checkIfVisible('receive-request-screen');
});
- it('should request ETH', async () => {
+ it('should request DAI', async () => {
// Tap on request payment button
await TestHelpers.tap('request-payment-button');
// Tap on ETH
@@ -110,9 +110,13 @@ describe('Request Token Flow', () => {
await TestHelpers.typeTextAndHideKeyboard('request-search-asset-input', 'DAI');
} else {
await TestHelpers.replaceTextInField('request-search-asset-input', 'DAI');
+ await TestHelpers.delay(1000);
}
// Select DAI from search results
await TestHelpers.tapByText('DAI', 1);
+ if (device.getPlatform() === 'ios') {
+ await TestHelpers.tapByText('DAI', 1);
+ }
// Request 5.50 DAI
await TestHelpers.typeTextAndHideKeyboard('request-amount-input', 5.5);
// Make sure we're on the right screen
diff --git a/e2e/start-exploring.spec.js b/e2e/start-exploring.spec.js
index 28dbf2d7b18..f940774bfc2 100644
--- a/e2e/start-exploring.spec.js
+++ b/e2e/start-exploring.spec.js
@@ -94,15 +94,13 @@ describe('Start Exploring', () => {
// Ensure step 3 is shown correctly
await TestHelpers.checkIfVisible('step3-title');
// Focus into account 1 name
- await TestHelpers.tapAndLongPress('account-label');
- // Clear text
- await TestHelpers.clearField('account-label-text-input');
- // Change account name
if (device.getPlatform() === 'android') {
+ await TestHelpers.tapAndLongPress('edit-account-label');
+ // Clear text
+ await TestHelpers.clearField('account-label-text-input');
+ // Change account name
await TestHelpers.replaceTextInField('account-label-text-input', ACCOUNT);
await element(by.id('account-label-text-input')).tapReturnKey();
- } else {
- await TestHelpers.typeTextAndHideKeyboard('account-label-text-input', ACCOUNT);
}
// Check that Got it! CTA is visible and tap it
if (!device.getPlatform() === 'android') {
@@ -133,6 +131,14 @@ describe('Start Exploring', () => {
await TestHelpers.tapByText('Back');
// Ensure step 5 is shown correctly
await TestHelpers.checkIfVisible('step5-title');
+ // Tap on Back
+ await TestHelpers.tapByText('Back');
+ // Ensure step 4 is shown correctly
+ await TestHelpers.checkIfVisible('step4-title');
+ // Check that Got it! CTA is visible and tap it
+ await TestHelpers.tapByText('Got it!');
+ // Ensure step 5 is shown correctly
+ await TestHelpers.checkIfVisible('step5-title');
// Check that Got it! CTA is visible and tap it
await TestHelpers.tapByText('Got it!');
// Ensure step 6 is shown correctly
diff --git a/e2e/wallet-tests.spec.js b/e2e/wallet-tests.spec.js
index f7b3070484d..a582db45ffc 100644
--- a/e2e/wallet-tests.spec.js
+++ b/e2e/wallet-tests.spec.js
@@ -5,9 +5,10 @@ const CORRECT_SEED_WORDS = 'fold media south add since false relax immense pause
const CORRECT_PASSWORD = `12345678`;
const TEST_PUBLIC_ADDRESS = '0xd3B9Cbea7856AECf4A6F7c3F4E8791F79cBeeD62';
const RINKEBY = 'Rinkeby Test Network';
+const ETHEREUM = 'Ethereum Main Network';
const COLLECTIBLE_CONTRACT_ADDRESS = '0x16baf0de678e52367adc69fd067e5edd1d33e3bf';
const COLLECTIBLE_IDENTIFIER = '404';
-const TOKEN_ADDRESS = '0x12525e53a7fB9e072e60062D087b19a05442BD8f';
+const TOKEN_ADDRESS = '0x107c4504cd79c5d2696ea0030a8dd4e92601b82e';
const TEST_PRIVATE_KEY = 'cbfd798afcfd1fd8ecc48cbecb6dc7e876543395640b758a90e11d986e758ad1';
const VALID_ADDRESS = '0xebe6CcB6B55e1d094d9c58980Bc10Fed69932cAb';
@@ -68,7 +69,9 @@ describe('Wallet Tests', () => {
// Tap on Create New Account
await TestHelpers.waitAndTap('create-account-button');
// Check if account was added
- await TestHelpers.checkIfElementWithTextIsVisible('Account 2');
+ if (device.getPlatform() === 'android') {
+ await TestHelpers.checkIfElementWithTextIsVisible('Account 2');
+ }
});
it('should be able to import account', async () => {
@@ -178,15 +181,8 @@ describe('Wallet Tests', () => {
await TestHelpers.tapByText('ADD');
// Check that identifier warning appears
await TestHelpers.checkIfVisible('collectible-identifier-warning');
-
// Go Back one view
- if (device.getPlatform() === 'android') {
- await device.pressBack();
- await TestHelpers.delay(1000);
- } else {
- await TestHelpers.tapAtPoint('add-custom-token-screen', { x: 25, y: -22 });
- }
-
+ await TestHelpers.tap('asset-back-button');
// Tap on the add collectibles button
await TestHelpers.waitAndTap('add-collectible-button');
// Check that we are on the add collectible asset screen
@@ -213,12 +209,7 @@ describe('Wallet Tests', () => {
// Check that the asset is correct
await TestHelpers.checkIfElementHasString('collectible-name', '1 CryptoKitties');
// Tap on back arrow
- if (device.getPlatform() === 'android') {
- await device.pressBack();
- await TestHelpers.delay(1000);
- } else {
- await TestHelpers.tapAtPoint('collectible-overview-screen', { x: 25, y: -22 });
- }
+ await TestHelpers.tap('asset-back-button');
});
it('should add a token', async () => {
@@ -226,6 +217,14 @@ describe('Wallet Tests', () => {
await TestHelpers.checkIfVisible('wallet-screen');
// Tap on TOKENS tab
await TestHelpers.tapByText('TOKENS');
+ // Switch to mainnet
+ await TestHelpers.waitAndTap('open-networks-button');
+ // Check that the Networks modal pops up
+ await TestHelpers.checkIfVisible('networks-list');
+ // Tap on Eth Mainnet
+ await TestHelpers.tapByText(ETHEREUM);
+ // Check that we are on Eth Mainnet
+ await TestHelpers.checkIfElementWithTextIsVisible(ETHEREUM);
// Tap on Add Tokens
await TestHelpers.tap('add-token-button');
// Search for SAI
@@ -233,12 +232,8 @@ describe('Wallet Tests', () => {
// Wait for results to load
await TestHelpers.delay(2000);
// Select SAI
- if (device.getPlatform() === 'android') {
- await TestHelpers.tapItemAtIndex('searched-token-result');
- await TestHelpers.delay(500);
- } else {
- await TestHelpers.tapAtPoint('search-token-screen', { x: 115, y: 160 });
- }
+ await TestHelpers.tapItemAtIndex('searched-token-result');
+ await TestHelpers.delay(500);
// Tap on Add Token button
await TestHelpers.tapByText('ADD TOKEN');
// Check that we are on the wallet screen
@@ -272,11 +267,11 @@ describe('Wallet Tests', () => {
await TestHelpers.delay(700);
// Check that token decimals warning is displayed
await TestHelpers.checkIfVisible('token-decimals-warning');
- // Tap on cancel button
+ // Go back
if (device.getPlatform() === 'android') {
await device.pressBack();
} else {
- await TestHelpers.tapByText('CANCEL');
+ await TestHelpers.tap('asset-back-button');
}
// Tap on Add Tokens
await TestHelpers.tap('add-token-button');
@@ -303,18 +298,29 @@ describe('Wallet Tests', () => {
// Check that we are on the wallet screen
await TestHelpers.checkIfVisible('wallet-screen');
// Check that TENX is added to wallet
- await TestHelpers.checkIfElementWithTextIsVisible('0 TENX');
+ await TestHelpers.checkIfElementWithTextIsVisible('0 BLT');
+ });
+
+ it('should switch back to Rinkeby network', async () => {
+ // Tap on Ethereum Main Network to prompt modal
+ await TestHelpers.waitAndTap('open-networks-button');
+ // Check that the Networks modal pops up
+ await TestHelpers.checkIfVisible('networks-list');
+ // Tap on Rinkeby Test Nework
+ await TestHelpers.tapByText(RINKEBY);
+ // Check that we are on Rinkeby network
+ await TestHelpers.checkIfElementWithTextIsVisible(RINKEBY);
});
it('should input a valid address', async () => {
// Check that we are on the wallet screen
await TestHelpers.checkIfVisible('wallet-screen');
- // Tap on ETH asset
- await TestHelpers.waitAndTap('eth-logo');
- // Check that we are on the token overview screen
- await TestHelpers.checkIfVisible('token-asset-overview');
+ // Open Drawer
+ await TestHelpers.tap('hamburger-menu-button-wallet');
+ // Check that the drawer is visbile
+ await TestHelpers.checkIfVisible('drawer-screen');
// Tap on Send button
- await TestHelpers.tapByText('SEND');
+ await TestHelpers.tap('drawer-send-button');
// Check that we are on the send screen
await TestHelpers.checkIfVisible('send-screen');
// Input test address
@@ -327,11 +333,7 @@ describe('Wallet Tests', () => {
it('should input and validate amount', async () => {
// Input amount
- if (device.getPlatform() === 'android') {
- await TestHelpers.replaceTextInField('txn-amount-input', '5');
- } else {
- await TestHelpers.typeTextAndHideKeyboard('txn-amount-input', '5');
- }
+ await TestHelpers.replaceTextInField('txn-amount-input', '5');
// Tap Next CTA
await TestHelpers.tap('txn-amount-next-button');
// Check that the insufficient funds warning pops up
@@ -349,7 +351,7 @@ describe('Wallet Tests', () => {
await TestHelpers.checkIfHasText('confirm-txn-amount', '0.00004 ETH');
// Tap on the Send CTA
await TestHelpers.tap('txn-confirm-send-button');
- // Check that we are on the token overview screen
- await TestHelpers.checkIfVisible('token-asset-overview');
+ // Check that we are on the wallet screen
+ await TestHelpers.checkIfVisible('wallet-screen');
});
});
diff --git a/index.js b/index.js
index e33a253cd25..45e25584a01 100644
--- a/index.js
+++ b/index.js
@@ -1,6 +1,7 @@
import './shim.js';
import 'react-native-gesture-handler';
+import 'react-native-url-polyfill/auto';
import crypto from 'crypto'; // eslint-disable-line import/no-nodejs-modules, no-unused-vars
require('react-native-browser-polyfill'); // eslint-disable-line import/no-commonjs
@@ -15,9 +16,10 @@ import { name } from './app.json';
// List of warnings that we're ignoring
LogBox.ignoreLogs([
'{}',
- // Uncomment the below line to run browser-tests.spec.js in debug mode
+ // Uncomment the below lines (21 and 22) to run browser-tests.spec.js in debug mode
// in e2e tests until issue https://github.com/MetaMask/metamask-mobile/issues/1395 is resolved
//"Error in RPC response",
+ // 'User rejected account access',
"Can't perform a React state update",
'Error evaluating injectedJavaScript',
'createErrorFromErrorData',
diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj
index 6e7beb4b1f4..76f02eaeba9 100644
--- a/ios/MetaMask.xcodeproj/project.pbxproj
+++ b/ios/MetaMask.xcodeproj/project.pbxproj
@@ -28,6 +28,7 @@
2370F9A340CF4ADFBCFB0543 /* EuclidCircularB-RegularItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 58572D81B5D54ED79A16A16D /* EuclidCircularB-RegularItalic.otf */; };
298242C958524BB38FB44CAE /* Roboto-BoldItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = C9FD3FB1258A41A5A0546C83 /* Roboto-BoldItalic.ttf */; };
2A27FC9EEF1F4FD18E658544 /* config.json in Resources */ = {isa = PBXBuildFile; fileRef = EF1C01B7F08047F9B8ADCFBA /* config.json */; };
+ 2C2671FF7C9738D73A97E1E3 /* libPods-MetaMask.a in Frameworks */ = {isa = PBXBuildFile; fileRef = AECD4D0D95B36200E86EEAAE /* libPods-MetaMask.a */; };
2CDF19FE9DEE4BF8B07154B1 /* EuclidCircularB-LightItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = F79EAC4A7BF74E458277AFA4 /* EuclidCircularB-LightItalic.otf */; };
2DB27BE39B164356A98A0FB1 /* Roboto-Italic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 5D7956F8525C4A45A2A555C3 /* Roboto-Italic.ttf */; };
34CEE49BC79D411687B42FA9 /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 459C4774EB724F2D8E12F088 /* Roboto-Regular.ttf */; };
@@ -43,7 +44,6 @@
813214A2220E40C7BBB5ED9E /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = A783D1CD7D27456796FE2E1B /* Roboto-Bold.ttf */; };
887E75FB64A54509A08D6C50 /* Roboto-LightItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = E020F42F788744B3BCE17F05 /* Roboto-LightItalic.ttf */; };
8DEB44A7E7EF48E1B3298910 /* EuclidCircularB-Medium.otf in Resources */ = {isa = PBXBuildFile; fileRef = CE0434C5FB7C4C6F9FEBDCE2 /* EuclidCircularB-Medium.otf */; };
- 8F24036CB356C6465E07CB50 /* libPods-MetaMask.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 789B8FA040E544968673792F /* libPods-MetaMask.a */; };
BF39E5BAE0F34F9091FF6AC0 /* EuclidCircularB-Semibold.otf in Resources */ = {isa = PBXBuildFile; fileRef = A8DE9C5BC0714D648276E123 /* EuclidCircularB-Semibold.otf */; };
CD13D926E1E84D9ABFE672C0 /* Roboto-BlackItalic.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 3E2492C67CF345CABD7B8601 /* Roboto-BlackItalic.ttf */; };
D171C39A8BD44DBEB6B68480 /* EuclidCircularB-MediumItalic.otf in Resources */ = {isa = PBXBuildFile; fileRef = 42CBA652072F4BE2A8B815C1 /* EuclidCircularB-MediumItalic.otf */; };
@@ -189,9 +189,9 @@
178440FE3F1C4F4180D14622 /* libTcpSockets.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libTcpSockets.a; sourceTree = ""; };
1C516951C09F43CB97129B66 /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; sourceTree = ""; };
1F06D56A2D2F41FB9345D16F /* Lottie.framework */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = wrapper.framework; name = Lottie.framework; path = System/Library/Frameworks/Lottie.framework; sourceTree = SDKROOT; };
+ 1F907A61887952BF381AC8E3 /* Pods-MetaMask.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MetaMask.debug.xcconfig"; path = "Target Support Files/Pods-MetaMask/Pods-MetaMask.debug.xcconfig"; sourceTree = ""; };
278065D027394AD9B2906E38 /* libBVLinearGradient.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libBVLinearGradient.a; sourceTree = ""; };
2D16E6891FA4F8E400B85C8A /* libReact.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; path = libReact.a; sourceTree = BUILT_PRODUCTS_DIR; };
- 327DD2DF6994E9948B4D7E0F /* Pods-MetaMask.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MetaMask.release.xcconfig"; path = "Target Support Files/Pods-MetaMask/Pods-MetaMask.release.xcconfig"; sourceTree = ""; };
3E2492C67CF345CABD7B8601 /* Roboto-BlackItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-BlackItalic.ttf"; path = "../app/fonts/Roboto-BlackItalic.ttf"; sourceTree = ""; };
42C239E9FAA64BD9A34B8D8A /* MaterialCommunityIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = MaterialCommunityIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/MaterialCommunityIcons.ttf"; sourceTree = ""; };
42C6DDE3B80F47AFA9C9D4F5 /* Foundation.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Foundation.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Foundation.ttf"; sourceTree = ""; };
@@ -202,6 +202,7 @@
4A2D27104599412CA00C35EF /* Ionicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Ionicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Ionicons.ttf"; sourceTree = ""; };
57C103F40F394637B5A886FC /* FontAwesome5_Brands.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Brands.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Brands.ttf"; sourceTree = ""; };
58572D81B5D54ED79A16A16D /* EuclidCircularB-RegularItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "EuclidCircularB-RegularItalic.otf"; path = "../app/fonts/EuclidCircularB-RegularItalic.otf"; sourceTree = ""; };
+ 589C418BA726A01F27EA894F /* Pods-MetaMask.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MetaMask.release.xcconfig"; path = "Target Support Files/Pods-MetaMask/Pods-MetaMask.release.xcconfig"; sourceTree = ""; };
5D7956F8525C4A45A2A555C3 /* Roboto-Italic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Italic.ttf"; path = "../app/fonts/Roboto-Italic.ttf"; sourceTree = ""; };
5E32A09A7BDC431FA403BA73 /* FontAwesome.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome.ttf"; sourceTree = ""; };
650F2B9724DC5FEB00C3B9C4 /* RCTAesForked.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = RCTAesForked.xcodeproj; path = "../node_modules/react-native-aes-crypto-forked/ios/RCTAesForked.xcodeproj"; sourceTree = ""; };
@@ -209,7 +210,6 @@
654378AF243E2ADC00571B9C /* File.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = File.swift; sourceTree = ""; };
67FBD519E04742E0AF191782 /* EuclidCircularB-Bold.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "EuclidCircularB-Bold.otf"; path = "../app/fonts/EuclidCircularB-Bold.otf"; sourceTree = ""; };
684F2C84313849199863B5FE /* Roboto-Black.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Black.ttf"; path = "../app/fonts/Roboto-Black.ttf"; sourceTree = ""; };
- 789B8FA040E544968673792F /* libPods-MetaMask.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MetaMask.a"; sourceTree = BUILT_PRODUCTS_DIR; };
7FF1597C0ACA4902B86140B2 /* Zocial.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Zocial.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Zocial.ttf"; sourceTree = ""; };
8E369AC13A2049B6B21E5120 /* libRCTSearchApi.a */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = archive.ar; path = libRCTSearchApi.a; sourceTree = ""; };
9499B01ECAC44DA29AC44E80 /* EuclidCircularB-SemiboldItalic.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "EuclidCircularB-SemiboldItalic.otf"; path = "../app/fonts/EuclidCircularB-SemiboldItalic.otf"; sourceTree = ""; };
@@ -219,9 +219,9 @@
A98029A3662F4C1391489A6B /* EuclidCircularB-Light.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "EuclidCircularB-Light.otf"; path = "../app/fonts/EuclidCircularB-Light.otf"; sourceTree = ""; };
A98DB430A7DA47EFB97EDF8B /* FontAwesome5_Solid.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = FontAwesome5_Solid.ttf; path = "../node_modules/react-native-vector-icons/Fonts/FontAwesome5_Solid.ttf"; sourceTree = ""; };
AA9EDF17249955C7005D89EE /* MetaMaskDebug.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = MetaMaskDebug.entitlements; path = MetaMask/MetaMaskDebug.entitlements; sourceTree = ""; };
+ AECD4D0D95B36200E86EEAAE /* libPods-MetaMask.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-MetaMask.a"; sourceTree = BUILT_PRODUCTS_DIR; };
BB8BA2D3C0354D6090B56A8A /* Roboto-Light.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Light.ttf"; path = "../app/fonts/Roboto-Light.ttf"; sourceTree = ""; };
BF485CDA047B4D52852B87F5 /* EvilIcons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = EvilIcons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/EvilIcons.ttf"; sourceTree = ""; };
- BF8DE2E5A176599FCD8A7CFD /* Pods-MetaMask.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MetaMask.debug.xcconfig"; path = "Target Support Files/Pods-MetaMask/Pods-MetaMask.debug.xcconfig"; sourceTree = ""; };
C752564A28B44392AEE16BD5 /* Roboto-Medium.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-Medium.ttf"; path = "../app/fonts/Roboto-Medium.ttf"; sourceTree = ""; };
C9FD3FB1258A41A5A0546C83 /* Roboto-BoldItalic.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "Roboto-BoldItalic.ttf"; path = "../app/fonts/Roboto-BoldItalic.ttf"; sourceTree = ""; };
CE0434C5FB7C4C6F9FEBDCE2 /* EuclidCircularB-Medium.otf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = "EuclidCircularB-Medium.otf"; path = "../app/fonts/EuclidCircularB-Medium.otf"; sourceTree = ""; };
@@ -250,7 +250,7 @@
15ACC9FC22655C3A0063978B /* Lottie.framework in Frameworks */,
15F7795E22A1B7B500B1DF8C /* Mixpanel.framework in Frameworks */,
153F84CA2319B8FD00C19B63 /* Branch.framework in Frameworks */,
- 8F24036CB356C6465E07CB50 /* libPods-MetaMask.a in Frameworks */,
+ 2C2671FF7C9738D73A97E1E3 /* libPods-MetaMask.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -358,7 +358,7 @@
children = (
153C1A742217BCDC0088EFE0 /* JavaScriptCore.framework */,
2D16E6891FA4F8E400B85C8A /* libReact.a */,
- 789B8FA040E544968673792F /* libPods-MetaMask.a */,
+ AECD4D0D95B36200E86EEAAE /* libPods-MetaMask.a */,
);
name = Frameworks;
sourceTree = "";
@@ -460,8 +460,8 @@
AA342D524556DBBE26F5997C /* Pods */ = {
isa = PBXGroup;
children = (
- BF8DE2E5A176599FCD8A7CFD /* Pods-MetaMask.debug.xcconfig */,
- 327DD2DF6994E9948B4D7E0F /* Pods-MetaMask.release.xcconfig */,
+ 1F907A61887952BF381AC8E3 /* Pods-MetaMask.debug.xcconfig */,
+ 589C418BA726A01F27EA894F /* Pods-MetaMask.release.xcconfig */,
);
path = Pods;
sourceTree = "";
@@ -473,7 +473,7 @@
isa = PBXNativeTarget;
buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "MetaMask" */;
buildPhases = (
- 72868E350C2B4E37DD67D4DA /* [CP] Check Pods Manifest.lock */,
+ AB8811CF1B31FCE5CC98A7C6 /* [CP] Check Pods Manifest.lock */,
65E00B0A247EA25400E5AC88 /* Start Packager */,
15FDD86321B76696006B7C35 /* Override xcconfig files */,
13B07F871A680F5B00A75B9A /* Sources */,
@@ -481,7 +481,7 @@
13B07F8E1A680F5B00A75B9A /* Resources */,
00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */,
15ACCA0022655C3A0063978B /* Embed Frameworks */,
- 84D295E70E7158158F0F4201 /* [CP] Copy Pods Resources */,
+ B6E9B4C4CCD9D5D5F8286546 /* [CP] Copy Pods Resources */,
);
buildRules = (
);
@@ -722,7 +722,7 @@
shellScript = "export RCT_METRO_PORT=\"${RCT_METRO_PORT:=8081}\"\necho \"export RCT_METRO_PORT=${RCT_METRO_PORT}\" > \"${SRCROOT}/../node_modules/react-native/scripts/.packager.env\"\nif [ -z \"${RCT_NO_LAUNCH_PACKAGER+xxx}\" ] ; then\n if nc -w 5 -z localhost ${RCT_METRO_PORT} ; then\n if ! curl -s \"http://localhost:${RCT_METRO_PORT}/status\" | grep -q \"packager-status:running\" ; then\n echo \"Port ${RCT_METRO_PORT} already in use, packager is either not running or not running correctly\"\n exit 2\n fi\n else\n open \"$SRCROOT/../node_modules/react-native/scripts/launchPackager.command\" || echo \"Can't start packager automatically\"\n fi\nfi\n";
showEnvVarsInLog = 0;
};
- 72868E350C2B4E37DD67D4DA /* [CP] Check Pods Manifest.lock */ = {
+ AB8811CF1B31FCE5CC98A7C6 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -744,7 +744,7 @@
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
- 84D295E70E7158158F0F4201 /* [CP] Copy Pods Resources */ = {
+ B6E9B4C4CCD9D5D5F8286546 /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
@@ -841,7 +841,7 @@
/* Begin XCBuildConfiguration section */
13B07F941A680F5B00A75B9A /* Debug */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = BF8DE2E5A176599FCD8A7CFD /* Pods-MetaMask.debug.xcconfig */;
+ baseConfigurationReference = 1F907A61887952BF381AC8E3 /* Pods-MetaMask.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_OPTIMIZATION = time;
@@ -849,7 +849,7 @@
CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 613;
+ CURRENT_PROJECT_VERSION = 715;
DEAD_CODE_STRIPPING = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 48XVW22RCG;
@@ -882,7 +882,7 @@
"\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 2.2.0;
+ MARKETING_VERSION = 2.3.0;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"$(inherited)",
@@ -905,7 +905,7 @@
};
13B07F951A680F5B00A75B9A /* Release */ = {
isa = XCBuildConfiguration;
- baseConfigurationReference = 327DD2DF6994E9948B4D7E0F /* Pods-MetaMask.release.xcconfig */;
+ baseConfigurationReference = 589C418BA726A01F27EA894F /* Pods-MetaMask.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_OPTIMIZATION = time;
@@ -913,7 +913,7 @@
CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 613;
+ CURRENT_PROJECT_VERSION = 715;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 48XVW22RCG;
FRAMEWORK_SEARCH_PATHS = (
@@ -945,7 +945,7 @@
"\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 2.2.0;
+ MARKETING_VERSION = 2.3.0;
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = (
"$(inherited)",
diff --git a/ios/Podfile.lock b/ios/Podfile.lock
index 5b829048f67..582b362a534 100644
--- a/ios/Podfile.lock
+++ b/ios/Podfile.lock
@@ -271,14 +271,19 @@ PODS:
- React
- react-native-cookies (4.0.1):
- React
- - react-native-netinfo (4.1.5):
- - React
+ - react-native-netinfo (6.0.0):
+ - React-Core
- react-native-randombytes (3.5.3):
- React
- react-native-safe-area-context (3.1.9):
- React-Core
- react-native-splash-screen (3.2.0):
- React
+ - react-native-video (5.1.1):
+ - React-Core
+ - react-native-video/Video (= 5.1.1)
+ - react-native-video/Video (5.1.1):
+ - React-Core
- react-native-view-shot (3.1.2):
- React
- react-native-viewpager (3.3.0):
@@ -363,8 +368,8 @@ PODS:
- React
- RNCMaskedView (0.1.10):
- React
- - RNDeviceInfo (3.1.4):
- - React
+ - RNDeviceInfo (8.1.3):
+ - React-Core
- RNFS (2.16.6):
- React
- RNGestureHandler (1.9.0):
@@ -381,18 +386,18 @@ PODS:
- React-Core
- RNSensors (5.3.0):
- React
- - RNSentry (1.3.3):
- - React
- - Sentry (~> 4.4.0)
- - RNShare (3.3.2):
- - React
+ - RNSentry (2.4.2):
+ - React-Core
+ - Sentry (= 6.1.4)
+ - RNShare (5.2.2):
+ - React-Core
- RNSVG (12.1.0):
- React
- RNVectorIcons (6.4.2):
- React
- - Sentry (4.4.3):
- - Sentry/Core (= 4.4.3)
- - Sentry/Core (4.4.3)
+ - Sentry (6.1.4):
+ - Sentry/Core (= 6.1.4)
+ - Sentry/Core (6.1.4)
- TcpSockets (4.0.0):
- CocoaAsyncSocket
- React
@@ -449,6 +454,7 @@ DEPENDENCIES:
- react-native-randombytes (from `../node_modules/react-native-randombytes`)
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
- react-native-splash-screen (from `../node_modules/react-native-splash-screen`)
+ - react-native-video (from `../node_modules/react-native-video`)
- react-native-view-shot (from `../node_modules/react-native-view-shot`)
- "react-native-viewpager (from `../node_modules/@react-native-community/viewpager`)"
- react-native-webview (from `../node_modules/react-native-webview`)
@@ -558,6 +564,8 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native-safe-area-context"
react-native-splash-screen:
:path: "../node_modules/react-native-splash-screen"
+ react-native-video:
+ :path: "../node_modules/react-native-video"
react-native-view-shot:
:path: "../node_modules/react-native-view-shot"
react-native-viewpager:
@@ -666,10 +674,11 @@ SPEC CHECKSUMS:
react-native-branch: f630e0e399c64230463246469ca0817e4f821b78
react-native-camera: 8016138a8348b889e22c95b23f668a234f124335
react-native-cookies: ff2e6865dff2e5feeca8f1ed082ae7898e4fa912
- react-native-netinfo: 0e563248a4b9a99c33ec29bd03c2d50767db22a6
+ react-native-netinfo: e849fc21ca2f4128a5726c801a82fc6f4a6db50d
react-native-randombytes: 3638d24759d67c68f6ccba60c52a7a8a8faa6a23
react-native-safe-area-context: b6e0e284002381d2ff29fa4fff42b4d8282e3c94
react-native-splash-screen: 200d11d188e2e78cea3ad319964f6142b6384865
+ react-native-video: 0bb76b6d6b77da3009611586c7dbf817b947f30e
react-native-view-shot: 4475fde003fe8a210053d1f98fb9e06c1d834e1c
react-native-viewpager: a7b438ca32c57b2614ece2a123e7fe116f743131
react-native-webview: dfd7202ff115c44d3ea401c2f36122fb3ac79f07
@@ -690,7 +699,7 @@ SPEC CHECKSUMS:
RNCCheckbox: 357578d3b42652c78ee9a1bb9bcfc3195af6e161
RNCClipboard: 8148e21ac347c51fd6cd4b683389094c216bb543
RNCMaskedView: 5a8ec07677aa885546a0d98da336457e2bea557f
- RNDeviceInfo: 88099e84466f053bae3f34c307b506738b2b6946
+ RNDeviceInfo: 8d3a29207835f972bce883723882980143270d55
RNFS: 2bd9eb49dc82fa9676382f0585b992c424cd59df
RNGestureHandler: 9b7e605a741412e20e13c512738a31bd1611759b
RNI18n: e2f7e76389fcc6e84f2c8733ea89b92502351fd8
@@ -699,11 +708,11 @@ SPEC CHECKSUMS:
RNReanimated: e03f7425cb7a38dcf1b644d680d1bfc91c3337ad
RNScreens: 45c457af3d2ee9e08fc01e70da87e653d46b1198
RNSensors: c363d486c879e181905dea84a2535e49af1c2d25
- RNSentry: 86baf0c87120cd5eb491d073989f8cbc1a2174c6
- RNShare: bd6518701db274b8ba282b33620885f2225a5bcf
+ RNSentry: e86fb2e2fec0365644f4b582938bf66be515acce
+ RNShare: 5cfe16bfd42cd2c4869a7692462181ac8cc15a6d
RNSVG: ce9d996113475209013317e48b05c21ee988d42e
RNVectorIcons: 6607bd3a30291d0edb56f9bbe7ae411ee2b928b0
- Sentry: 14bdd673870e8cf64932b149fad5bbbf39a9b390
+ Sentry: 9d055e2de30a77685e86b219acf02e59b82091fc
TcpSockets: a8eb6b5867fe643e6cfed5db2e4de62f4d1e8fd0
Yoga: 4bd86afe9883422a7c4028c00e34790f560923d6
YogaKit: f782866e155069a2cca2517aafea43200b01fd5a
diff --git a/locales/languages/en.json b/locales/languages/en.json
index 45bb14c9d99..44f6add00ba 100644
--- a/locales/languages/en.json
+++ b/locales/languages/en.json
@@ -43,7 +43,7 @@
"warning_text_1": "Your current wallet and accounts will be",
"warning_text_2": "removed",
"warning_text_3": "if you proceed.",
- "warning_text_4": "You can ONLY recover them with your wallet’s seed phrase. MetaMask cannot help you recover it.",
+ "warning_text_4": "You can ONLY recover them with your wallet’s Secret Recovery phrase. MetaMask cannot help you recover it.",
"warning_proceed": "Remove wallet & proceed",
"warning_cancel": "Cancel",
"step1": "Wallet setup",
@@ -123,7 +123,7 @@
"sync_help_step_four": "4. Scan the QR Code to start syncing",
"sync_from_browser_extension_button": "Sync with MetaMask extension",
"or": "OR",
- "import_from_seed_button": "Import using seed phrase"
+ "import_from_seed_button": "Import using Secret Recovery phrase"
},
"login": {
"title": "Welcome Back!",
@@ -142,7 +142,12 @@
"you_can_only": "You can ONLY recover this wallet with your ",
"recovery_phrase": "Recovery Phrase ",
"metamask_does_not": "MetaMask does not have your recovery phrase.",
- "i_understand": "I understand, continue"
+ "i_understand": "I understand, continue",
+ "passcode_not_set_error": "Error: Passcode not set.",
+ "wrong_password_error": "Error: Decrypt failed",
+ "wrong_password_error_android": "Error: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT",
+ "vault_error": "Error: Cannot unlock without a previous vault.",
+ "clean_vault_error": "MetaMask encountered an error due to reaching a storage limit. The local data has been corrupted. Please reinstall MetaMask and restore with your Secret Recovery phrase."
},
"enter_password": {
"title": "Enter your password",
@@ -157,7 +162,7 @@
"password": "New Password",
"confirm_password": "Confirm password",
"create_button": "Create password",
- "import_with_seed_phrase": "Import with seed phrase",
+ "import_with_seed_phrase": "Import with Secret Recovery phrase",
"password_length_error": "The password needs to be at least 8 characters long",
"password_dont_match": "Passwords don't match",
"password_strength": "Password strength:",
@@ -166,7 +171,7 @@
"strength_strong": "Strong",
"show": "Show",
"hide": "Hide",
- "seed_phrase": "Seed phrase",
+ "seed_phrase": "Secret recovery phrase",
"must_be_at_least": "Must be at least {{number}} characters",
"remember_me": "Remember me",
"security_alert_title": "Security Alert",
@@ -174,7 +179,7 @@
"i_understand": "I understand that MetaMask cannot recover this password for me.",
"learn_more": "Learn more.",
"secure": "Secure wallet",
- "confirm": "Confirm seed phrase"
+ "confirm": "Confirm Secret Recovery phrase"
},
"reset_password": {
"title": "Change password",
@@ -182,7 +187,7 @@
"password": "New Password",
"confirm_password": "Confirm password",
"reset_button": "Reset password",
- "import_with_seed_phrase": "Import with seed phrase",
+ "import_with_seed_phrase": "Import with Secret Recovery phrase",
"password_length_error": "The password needs to be at least 8 characters long",
"password_dont_match": "Passwords don't match",
"password_strength": "Password strength:",
@@ -191,7 +196,7 @@
"strength_strong": "Strong",
"show": "Show",
"hide": "Hide",
- "seed_phrase": "Seed phrase",
+ "seed_phrase": "Secret recovery phrase",
"must_be_at_least": "Must be at least {{number}} characters",
"remember_me": "Remember me",
"security_alert_title": "Security Alert",
@@ -199,24 +204,24 @@
"i_understand": "I understand that MetaMask cannot recover this password for me.",
"learn_more": "Learn more.",
"secure": "Secure wallet",
- "confirm": "Confirm seed phrase",
+ "confirm": "Confirm Secret Recovery phrase",
"password_updated": "Password updated",
"successfully_changed": "Your password has been successfully changed"
},
"import_from_seed": {
"title": "Import from seed",
- "seed_phrase_placeholder": "Enter your seed phrase here",
+ "seed_phrase_placeholder": "Enter your Secret Recovery phrase here",
"new_password": "New Password",
"confirm_password": "Confirm password",
"import_button": "IMPORT",
"cancel_button": "Cancel",
"password_length_error": "The password needs to be at least 8 characters long",
"password_dont_match": "Passwords don't match",
- "seed_phrase_requirements": "Seed phrases contain 12, 15, 18, 21, or 24 words",
- "invalid_seed_phrase": "Invalid seed phrase",
+ "seed_phrase_requirements": "Secret recovery phrases contain 12, 15, 18, 21, or 24 words",
+ "invalid_seed_phrase": "Invalid Secret Recovery phrase",
"error": "Error",
"invalid_qr_code_title": "Invalid QR Code",
- "invalid_qr_code_message": "This QR code doesn't represent a valid seed phrase"
+ "invalid_qr_code_message": "This QR code doesn't represent a valid Secret Recovery phrase"
},
"bottom_tab_bar": {
"dapps": "ÐApps",
@@ -289,7 +294,7 @@
"private_key_detected": "Private key detected",
"do_you_want_to_import_this_account": "Do you want to import this account?",
"error": "Error",
- "logout_to_import_seed": "You need to log out first in order to import a seed phrase.",
+ "logout_to_import_seed": "You need to log out first in order to import a Secret Recovery phrase.",
"ready_to_explore": "Ready to start exploring blockchain applications?",
"unable_to_load": "Unable to load balance"
},
@@ -420,9 +425,10 @@
"clear": "CLEAR",
"protect_cta": "Protect",
"protect_title": "Protect your wallet",
- "protect_desc": "Protect your wallet by saving your seed phrase in various places like on a piece of paper, password manager and/or the cloud.",
- "seedphrase_not_backed_up": "Important! Seed phrase not backed up",
- "seedphrase_backed_up": "Seed phrase backed up",
+ "video_failed": "Video Failed to Load.",
+ "protect_desc": "Protect your wallet by saving your Secret Recovery phrase in various places like on a piece of paper, password manager and/or the cloud.",
+ "seedphrase_not_backed_up": "Important! Secret recovery phrase not backed up",
+ "seedphrase_backed_up": "Secret recovery phrase backed up",
"back_up_now": "Back up now",
"back_up_again": "Back up again",
"view_hint": "View hint",
@@ -444,7 +450,7 @@
"contacts_desc": "Add, edit, remove, and manage your accounts",
"security_title": "Security & Privacy",
"back": "Back",
- "security_desc": "Privacy settings, MetaMetrics, private key and wallet seed phrase",
+ "security_desc": "Privacy settings, MetaMetrics, private key and wallet Secret Recovery phrase",
"networks_title": "Networks",
"networks_desc": "Add and edit custom RPC networks",
"network_name_label": "Network Name",
@@ -503,7 +509,9 @@
"invalid_hex_number_leading_zeros": "Invalid hexadecimal number. Remove any leading zeros.",
"invalid_number": "Invalid number. Enter a decimal or '0x'-prefixed hexadecimal number.",
"invalid_number_leading_zeros": "Invalid number. Remove any leading zeros.",
- "invalid_number_range": "Invalid number. Enter a number between 1 and %{maxSafeChainId}"
+ "invalid_number_range": "Invalid number. Enter a number between 1 and %{maxSafeChainId}",
+ "hide_zero_balance_tokens_title": "Hide Tokens Without Balance",
+ "hide_zero_balance_tokens_desc": "Prevents tokens with no balance from displaying in your token listing."
},
"app_information": {
"title": "Information",
@@ -516,22 +524,22 @@
"contact_us": "Contact Us"
},
"reveal_credential": {
- "seed_phrase_title": "Reveal seed phrase",
+ "seed_phrase_title": "Reveal Secret Recovery phrase",
"private_key_title": "Show private key",
"show_private_key": "Show private key",
"private_key_title_for_account": "Show private key for \"{{accountName}}\"",
"cancel": "Cancel",
"confirm": "Next",
- "seed_phrase_explanation": "If you ever change browsers or move computers, you will need this seed phrase to access your accounts. Save them somewhere safe and secret.",
+ "seed_phrase_explanation": "If you ever change browsers or move computers, you will need this Secret Recovery phrase to access your accounts. Save them somewhere safe and secret.",
"private_key_explanation": "Save it somewhere safe and secret.",
"private_key_warning": "This is the private key for the current selected account: {{accountName}}. Never disclose this key. Anyone with your private key can fully control your account, including transferring away any of your funds.",
"seed_phrase_warning_explanation": "DO NOT share this phrase with anyone! These words can be used to steal all your accounts.",
"private_key_warning_explanation": "Never disclose this key. Anyone with your private key can fully control your account, including transferring away any of your funds.",
- "seed_phrase": "Your seed phrase",
+ "seed_phrase": "Your Secret Recovery phrase",
"private_key": "Your private key",
"copy_to_clipboard": "Copy to clipboard",
"enter_password": "Enter password to continue",
- "seed_phrase_copied": "Seed phrase copied to clipboard",
+ "seed_phrase_copied": "Secret recovery phrase copied to clipboard",
"private_key_copied": "Private key copied to clipboard",
"warning_incorrect_password": "Incorrect password",
"unknown_error": "Couldn't unlock your account. Please try again.",
@@ -541,7 +549,7 @@
},
"password_reset": {
"password_title": "Password",
- "password_desc": "Choose a strong password to unlock MetaMask app on your device. If you lose this password, you will need your seedphrase to re-import your wallet.",
+ "password_desc": "Choose a strong password to unlock MetaMask app on your device. If you lose this password, you will need your Secret recovery phrase to re-import your wallet.",
"password_learn_more": "Learn more.",
"change_password": "Change password"
},
@@ -670,7 +678,9 @@
"tokenContractAddressWarning_2": "token contract address",
"tokenContractAddressWarning_3": ". If you send tokens to this address, you will lose them.",
"smartContractAddressWarning": "This address is a smart contract address. Please make sure you understand what this address is for, otherwise you risk losing your funds.",
- "continueError": "I understand the risks, continue"
+ "continueError": "I understand the risks, continue",
+ "confusable_title": "Check the recipient address",
+ "confusable_msg": "We have detected a confusable character in the ENS name. Check the ENS name to avoid a potential scam."
},
"custom_gas": {
"total": "Total",
@@ -875,13 +885,13 @@
"outdated_qr_code": "Expired QR Code",
"outdated_qr_code_desc": "This seems to be an expired QR code! Please try scanning a new one",
"something_wrong": "Ooops! Something went wrong...",
- "something_wrong_desc": "We are having issues while trying to sync your wallet. Please try again later or import your wallet using your seed phrase",
+ "something_wrong_desc": "We are having issues while trying to sync your wallet. Please try again later or import your wallet using your Secret Recovery phrase",
"allow_biometrics_title": "Do you want to enable {{biometrics}}?",
"allow_biometrics_desc": "You can use {{biometrics}} to authenticate on MetaMask"
},
"sync_with_extension_success": {
"title": "Wallet imported",
- "sync_complete_1": "Just remember, MetaMask cannot recover your seed phrase should you lose it. You can find the seed phrase in",
+ "sync_complete_1": "Just remember, MetaMask cannot recover your Secret Recovery phrase should you lose it. You can find the Secret Recovery phrase in",
"sync_complete_2": "Settings > Security & Privacy",
"button_continue": "Done",
"password_tip": "The password to unlock your mobile wallet is the same one you set for the extension.",
@@ -965,7 +975,7 @@
},
"import_private_key": {
"title": "Import Account",
- "description_one": "Imported accounts are viewable in your wallet but are not recoverable with your MetaMask seed phrase.",
+ "description_one": "Imported accounts are viewable in your wallet but are not recoverable with your MetaMask Secret Recovery phrase.",
"learn_more_here": "Learn more about imported accounts here.",
"subtitle": "Paste your private key string",
"cta_text": "IMPORT",
@@ -991,7 +1001,7 @@
"step_1": "Step 1:",
"step_1_description": "Create password",
"step_2": "Step 2:",
- "step_2_description": "Save wallet seed phrase",
+ "step_2_description": "Save wallet Secret Recovery phrase",
"info_text_1": "Take a few moments to finish setting up your MetaMask wallet.",
"info_text_2": "This will ensure only you can access your funds and will let you recover your wallet if you lose your device",
"cta_text": "Create Password",
@@ -1002,7 +1012,7 @@
"remind_me_later_subtext": "(Not recommended)",
"title": "Secure your wallet",
"info_text_1_1": "Don’t risk losing your funds. Protect your wallet by saving your",
- "info_text_1_2": "seed phrase",
+ "info_text_1_2": "Secret Recovery phrase",
"info_text_1_3": "in a place you trust.",
"info_text_1_4": "It’s the only way to recover your wallet if you get locked out of the app or get a new device.",
"cta_text": "Start",
@@ -1010,21 +1020,21 @@
"skip_button_cancel": "Secure now",
"skip_button_confirm": "Skip",
"skip_title": "Skip account security?",
- "skip_check": "I understand that if I lose my seed phrase I will not be able to access my wallet.",
- "what_is_seedphrase_title": "What is a ‘Seed phrase’",
- "what_is_seedphrase_text_1": "A seed phrase is a set of twelve words that contains all the information about your wallet, including your funds. It’s like a secret code used to access your entire wallet.",
- "what_is_seedphrase_text_2": "You must keep your seed phrase secret and safe. If someone gets your seed phrase, they’ll gain control over your accounts.",
+ "skip_check": "I understand that if I lose my Secret Recovery phrase I will not be able to access my wallet.",
+ "what_is_seedphrase_title": "What is a ‘Secret recovery phrase’",
+ "what_is_seedphrase_text_1": "A Secret Recovery phrase is a set of twelve words that contains all the information about your wallet, including your funds. It’s like a secret code used to access your entire wallet.",
+ "what_is_seedphrase_text_2": "You must keep your Secret Recovery phrase secret and safe. If someone gets your Secret Recovery phrase, they’ll gain control over your accounts.",
"what_is_seedphrase_text_3": "Save it in a place where only you can access it. If you lose it, not even MetaMask can help you recover it."
},
"account_backup_step_1B": {
"title": "Secure your wallet",
"subtitle_1": "Secure your wallet's",
- "subtitle_2": "seed phrase.",
+ "subtitle_2": "Secret Recovery phrase.",
"cta_text": "Start",
"learn_more": "Learn More",
"why_important": "Why is it important?",
"manual_title": "Manual",
- "manual_subtitle": "Write down your seed phrase on a piece of paper and store in a safe place.",
+ "manual_subtitle": "Write down your Secret Recovery phrase on a piece of paper and store in a safe place.",
"manual_security": "Security level: Very strong",
"risks_title": "Risks are:",
"risks_1": "You lose it",
@@ -1036,16 +1046,16 @@
"tips_2": "Store in a safe",
"tips_3": "Store in multiple secret places",
"why_secure_title": "Protect your wallet",
- "why_secure_1": "Don’t risk losing your funds. Protect your wallet by saving your seed phrase in a place you trust.",
+ "why_secure_1": "Don’t risk losing your funds. Protect your wallet by saving your Secret Recovery phrase in a place you trust.",
"why_secure_2": " It’s the only way to recover your wallet if you get locked out of the app or get a new device."
},
"account_backup_step_2": {
"cancel_backup_title": "Cancel Backup",
- "cancel_backup_message": "We highly recommend you save your seed phrase in order to restore your wallet.",
+ "cancel_backup_message": "We highly recommend you save your Secret Recovery phrase in order to restore your wallet.",
"cancel_backup_ok": "Yes, I'll take the risk",
- "cancel_backup_no": "No, back up Seed Phrase",
+ "cancel_backup_no": "No, back up Secret Recovery Phrase",
"title": "Grab a pen and paper",
- "info": "Next step is to write your seed phrase down.",
+ "info": "Next step is to write your Secret Recovery phrase down.",
"info_2_1": "You will be asked to ",
"info_2_2": "re-enter",
"info_2_3": " it for confirmation",
@@ -1053,20 +1063,20 @@
},
"account_backup_step_3": {
"cancel_backup_title": "Cancel Backup",
- "cancel_backup_message": "We highly recommend you save your seed phrase in order to restore your wallet.",
+ "cancel_backup_message": "We highly recommend you save your Secret Recovery phrase in order to restore your wallet.",
"cancel_backup_ok": "Yes, I'll take the risk",
- "cancel_backup_no": "No, back up Seed Phrase",
+ "cancel_backup_no": "No, back up Secret Recovery Phrase",
"title": "Is anyone watching?",
- "info_text": "Make sure no other human or robot is watching your screen. If your seed phrase is copied, it can be used on other devices to steal your funds",
+ "info_text": "Make sure no other human or robot is watching your screen. If your Secret Recovery phrase is copied, it can be used on other devices to steal your funds",
"cta_text": "NO ONE'S WATCHING ME"
},
"account_backup_step_4": {
"cancel_backup_title": "Cancel Backup",
- "cancel_backup_message": "We highly recommend you save your seed phrase in order to restore your wallet.",
+ "cancel_backup_message": "We highly recommend you save your Secret Recovery phrase in order to restore your wallet.",
"cancel_backup_ok": "Yes, I'll take the risk",
- "cancel_backup_no": "No, back up Seed Phrase",
+ "cancel_backup_no": "No, back up Secret Recovery Phrase",
"back": "Back",
- "title": "Your seed phrase",
+ "title": "Your Secret Recovery phrase",
"info_text_1": "Carefully write down these words on paper. Their order matters.",
"info_text_2": "You'll be asked to re-enter it on the next screen",
"cta_text": "I'VE COPIED THE PHRASE",
@@ -1078,37 +1088,37 @@
"error_title": "Oops!",
"error_message": "The order of the words is incorrect. Please make sure you wrote it down correctly and go to the previous screen if it is necessary",
"back": "Back",
- "title": "Confirm seed phrase",
+ "title": "Confirm Secret Recovery phrase",
"info_text": "Insert each word in the order it was presented to you on the previous screen.",
"cta_text": "CONFIRM PHRASE",
- "modal_title": "Seed phrase confirmed!",
+ "modal_title": "Secret recovery phrase confirmed!",
"modal_text": "This was to ensure you follow this security measure",
"modal_button": "NEXT"
},
"account_backup_step_6": {
"title": "Security Tips",
- "info_text": "MetaMask cannot recover your seed phrase if you lose it",
- "tip_1": "Keep multiple backups of your seed phrase",
+ "info_text": "MetaMask cannot recover your Secret Recovery phrase if you lose it",
+ "tip_1": "Keep multiple backups of your Secret Recovery phrase",
"tip_2": "Store the phrase in a trusted password manager and paper backups in a safe place",
"tip_3": "Never share this phrase with anyone",
- "disclaimer": "* You can find your seedphrase if you go to ",
+ "disclaimer": "* You can find your Secret recovery phrase if you go to ",
"disclaimer_bold": "Settings > Security & Privacy",
"cta_text": "GOT IT!",
"modal_title": "Congratulations!",
"modal_text": "You are all backed up and ready to go!",
"modal_button": "DONE",
- "copy_seed_phrase": "COPY SEED PHRASE TO CLIPBOARD"
+ "copy_seed_phrase": "COPY SECRET RECOVERY PHRASE TO CLIPBOARD"
},
"manual_backup": {
"progressOne": "Create Password",
"progressTwo": "Secure wallet",
- "progressThree": "Confirm seed phrase"
+ "progressThree": "Confirm Secret Recovery phrase"
},
"manual_backup_step_1": {
- "action": "Write down your seed phrase",
- "info": "This is your seed phrase. Write it down on a paper and keep it in a safe place. You'll be asked to re-enter this phrase (in order) on the next step.",
+ "action": "Write down your Secret Recovery phrase",
+ "info": "This is your Secret Recovery phrase. Write it down on a paper and keep it in a safe place. You'll be asked to re-enter this phrase (in order) on the next step.",
"continue": "Continue",
- "reveal": "Tap to reveal your seed phrase",
+ "reveal": "Tap to reveal your Secret Recovery phrase",
"watching": "Make sure no one is watching your screen.",
"view": "View",
"confirm_password": "Confirm your password",
@@ -1116,21 +1126,21 @@
"confirm": "CONFIRM"
},
"manual_backup_step_2": {
- "action": "Confirm seed phrase",
+ "action": "Confirm Secret Recovery phrase",
"info": "Select each word in the order it was presented to you.",
"complete": "Complete Backup",
"success": "Success"
},
"manual_backup_step_3": {
"congratulations": "Congratulations",
- "success": "You’ve successfully protected your wallet. Remember to keep your seed phrase safe, it's your responsibility!",
+ "success": "You’ve successfully protected your wallet. Remember to keep your Secret Recovery phrase safe, it's your responsibility!",
"hint": "Leave yourself a hint?",
- "recover": "MetaMask cannot recover your wallet should you lose it. You can find your seedphrase in Settings > Security & Privacy.",
+ "recover": "MetaMask cannot recover your wallet should you lose it. You can find your Secret recovery phrase in Settings > Security & Privacy.",
"learn": "Learn more",
"done": "Done",
"recovery_hint": "Recovery hint",
"leave_hint": "Leave yourself a hint. Write the location / where you saved it to remind yourself how you can access it. This information does not leave your device.",
- "no_seedphrase": "Do not use this to write your seed phrase.",
+ "no_seedphrase": "Do not use this to write your Secret Recovery phrase.",
"example": "e.g. Mom's house",
"save": "Save",
"cancel": "Cancel"
@@ -1186,8 +1196,8 @@
},
"protect_your_wallet_modal": {
"title": "Protect your wallet",
- "body_for_password": "Protect your wallet by setting a password and saving your seed phrase (required).",
- "body_for_seedphrase": "Now that value was added to your wallet, protect your wallet by setting a password and saving your seed phrase (required).",
+ "body_for_password": "Protect your wallet by setting a password and saving your Secret Recovery phrase (required).",
+ "body_for_seedphrase": "Now that value was added to your wallet, protect your wallet by setting a password and saving your Secret Recovery phrase (required).",
"button": "Protect wallet"
},
"payment_request": {
@@ -1369,6 +1379,8 @@
"verify_on": "Always verify the token address on",
"verify_address_on": "Verify token address on",
"only_verified_on": "{{symbol}} is only verified on {{occurances}} source.",
+ "block_explorer": "block explorer",
+ "a_block_explorer": "a block explorer",
"token_verification": "Token verification",
"token_multiple": "Multiple tokens can use the same name and symbol.",
"token_check": "Check",
@@ -1482,7 +1494,7 @@
"title": "Protect your wallet",
"top_button": "Protect wallet",
"bottom_button": "Remind me later",
- "text": "Don’t risk losing your funds. Protect your wallet by saving your seed phrase in a place you trust.",
+ "text": "Don’t risk losing your funds. Protect your wallet by saving your Secret Recovery phrase in a place you trust.",
"text_bold": "It’s the only way to recover your wallet if you get locked out of the app or get a new device.",
"action": "Learn more"
},
@@ -1502,15 +1514,15 @@
"submit_ticket_6": "here.",
"submit_ticket_7": "Please include the error message and the screenshot.",
"save_seedphrase_1": "If this error persists,",
- "save_seedphrase_2": "save your seed phrase",
- "save_seedphrase_3": "& re-install the app. Note: you can NOT restore your wallet without your seed phrase.",
+ "save_seedphrase_2": "save your Secret Recovery phrase",
+ "save_seedphrase_3": "& re-install the app. Note: you can NOT restore your wallet without your Secret Recovery phrase.",
"copied_clipboard": "Copied to clipboard",
"ok": "OK"
},
"whats_new": {
"title": "See what's new",
"feature_security_settings_title": "Improved security settings",
- "feature_security_settings_text": "You can now change your MetaMask app password & review how to backup your wallet seed phrase from Settings > Security & Privacy.",
+ "feature_security_settings_text": "You can now change your MetaMask app password & review how to backup your wallet Secret Recovery phrase from Settings > Security & Privacy.",
"feature_security_settings_button": "View in Settings"
},
"invalid_network": {
diff --git a/package.json b/package.json
index 61a48e635d0..c6d68c79465 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "metamask",
- "version": "2.2.0",
+ "version": "2.3.0",
"private": true,
"scripts": {
"watch": "./scripts/build.sh watcher watch",
@@ -65,6 +65,8 @@
]
},
"resolutions": {
+ "**/lodash": "^4.17.21",
+ "**/ua-parser-js": "^0.7.24",
"**/elliptic": "^6.5.4",
"**/y18n": "^3.2.2",
"pubnub/**/netmask": "^2.0.1",
@@ -73,10 +75,11 @@
"react-native-level-fs/**/semver": "^4.3.2"
},
"dependencies": {
- "@estebanmino/controllers": "^3.3.17",
"@exodus/react-native-payments": "https://github.com/wachunei/react-native-payments.git#package-json-hack",
"@metamask/contract-metadata": "^1.23.0",
- "@metamask/controllers": "^7.0.0",
+ "@metamask/controllers": "^8.0.0",
+ "@metamask/etherscan-link": "^2.0.0",
+ "@metamask/swaps-controller": "^4.0.0",
"@react-native-community/async-storage": "1.12.1",
"@react-native-community/blur": "^3.6.0",
"@react-native-community/checkbox": "^0.4.2",
@@ -86,11 +89,11 @@
"@react-native-community/netinfo": "6.0.0",
"@react-native-community/viewpager": "^3.3.0",
"@rnhooks/keyboard": "^0.0.3",
- "@sentry/integrations": "5.13.0",
- "@sentry/react-native": "1.3.3",
+ "@sentry/integrations": "6.3.1",
+ "@sentry/react-native": "2.4.2",
"@tradle/react-native-http": "2.0.1",
- "@walletconnect/client": "1.3.4",
- "@walletconnect/utils": "1.3.4",
+ "@walletconnect/client": "^1.4.1",
+ "@walletconnect/utils": "^1.4.1",
"asyncstorage-down": "4.2.0",
"axios": "^0.21.1",
"babel-plugin-transform-inline-environment-variables": "0.4.3",
@@ -147,7 +150,7 @@
"react-native-confetti": "^0.1.0",
"react-native-confetti-cannon": "^1.5.0",
"react-native-crypto": "2.1.2",
- "react-native-device-info": "3.1.4",
+ "react-native-device-info": "^8.1.3",
"react-native-elevated-view": "0.0.6",
"react-native-emoji": "1.3.1",
"react-native-fade-in-image": "1.4.1",
@@ -178,8 +181,11 @@
"react-native-svg": "12.1.0",
"react-native-swipe-gestures": "1.0.3",
"react-native-tcp": "aprock/react-native-tcp#11/head",
+ "react-native-url-polyfill": "^1.3.0",
"react-native-v8": "^0.62.2-patch.1",
"react-native-vector-icons": "6.4.2",
+ "react-native-video": "^5.1.1",
+ "react-native-video-controls": "^2.7.1",
"react-native-view-shot": "^3.1.2",
"react-native-webview": "^11.0.2",
"react-navigation": "^4.4.3",
@@ -196,8 +202,9 @@
"rn-fetch-blob": "^0.12.0",
"stream-browserify": "1.0.0",
"through2": "3.0.1",
+ "unicode-confusables": "^0.1.1",
"url": "0.11.0",
- "url-parse": "1.4.4",
+ "url-parse": "1.5.0",
"valid-url": "1.0.9",
"vm-browserify": "1.1.2",
"web3-provider-engine": "^16.0.1",
@@ -213,11 +220,11 @@
"babel-eslint": "10.1.0",
"babel-jest": "^26.6.3",
"concat-cli": "4.0.0",
- "detox": "17.3.1",
+ "detox": "17.14.9",
"enzyme": "3.9.0",
"enzyme-adapter-react-16": "1.10.0",
"enzyme-to-json": "3.3.5",
- "eslint": "^6.5.1",
+ "eslint": "^7.14.0",
"eslint-config-react-native": "4.0.0",
"eslint-plugin-import": "2.18.2",
"eslint-plugin-prettier": "^3.3.1",
@@ -332,7 +339,7 @@
"fs": "react-native-level-fs"
},
"engines": {
- "node": "^10.17.0",
+ "node": "^14.0.0",
"yarn": "^1.22.0"
},
"rnpm": {
diff --git a/patches/unicode-confusables+0.1.1.patch b/patches/unicode-confusables+0.1.1.patch
new file mode 100644
index 00000000000..9b90e6b4c18
--- /dev/null
+++ b/patches/unicode-confusables+0.1.1.patch
@@ -0,0 +1,15 @@
+diff --git a/node_modules/unicode-confusables/data/confusables.json b/node_modules/unicode-confusables/data/confusables.json
+index 855e49c..b0b8a0b 100644
+--- a/node_modules/unicode-confusables/data/confusables.json
++++ b/node_modules/unicode-confusables/data/confusables.json
+@@ -157,8 +157,8 @@
+ "໊": "๊",
+ "໋": "๋",
+ "꙯": "⃩",
+- "
": " ",
+- "
": " ",
++ "\u2028": " ",
++ "\u2029": " ",
+ " ": " ",
+ " ": " ",
+ " ": " ",
diff --git a/yarn.lock b/yarn.lock
index 4ff283b7705..e42458fa18a 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2,7 +2,7 @@
# yarn lockfile v1
-"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.1", "@babel/code-frame@^7.10.4":
+"@babel/code-frame@7.12.11", "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.1", "@babel/code-frame@^7.10.4":
version "7.12.11"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f"
integrity sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==
@@ -871,34 +871,20 @@
dependencies:
"@types/hammerjs" "^2.0.36"
-"@estebanmino/controllers@^3.3.17":
- version "3.3.17"
- resolved "https://registry.yarnpkg.com/@estebanmino/controllers/-/controllers-3.3.17.tgz#22f06daf2b5a004bcf40a12f905699263276159f"
- integrity sha512-tmONppQxqLOW7uZSSk9gUAiNokU1tW2LezPggjZjzOp9CTBIc3cgr28o07hss7DF4+8IX6XOEtAjfeVgUUCQ2Q==
+"@eslint/eslintrc@^0.4.0":
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.4.0.tgz#99cc0a0584d72f1df38b900fb062ba995f395547"
+ integrity sha512-2ZPCc+uNbjV5ERJr+aKSPRwZgKd2z11x0EgLvb1PURmUrn9QNRXFqje0Ldq454PfAVyaJYyrDvvIKSFP4NnBog==
dependencies:
- "@metamask/contract-metadata" "^1.22.0"
- abort-controller "^3.0.0"
- async-mutex "^0.3.1"
- bignumber.js "^9.0.1"
- eth-ens-namehash "^2.0.8"
- eth-json-rpc-infura "^5.1.0"
- eth-keyring-controller "^6.1.0"
- eth-method-registry "1.1.0"
- eth-phishing-detect "^1.1.13"
- eth-query "^2.1.2"
- eth-rpc-errors "^4.0.0"
- eth-sig-util "^3.0.0"
- ethereumjs-util "^6.1.0"
- ethereumjs-wallet "^1.0.1"
- human-standard-collectible-abi "^1.0.2"
- human-standard-token-abi "^2.0.0"
- isomorphic-fetch "^3.0.0"
- jsonschema "^1.2.4"
- nanoid "^3.1.12"
- single-call-balance-checker-abi "^1.0.0"
- uuid "^8.3.2"
- web3 "^0.20.7"
- web3-provider-engine "^16.0.1"
+ ajv "^6.12.4"
+ debug "^4.1.1"
+ espree "^7.3.0"
+ globals "^12.1.0"
+ ignore "^4.0.6"
+ import-fresh "^3.2.1"
+ js-yaml "^3.13.1"
+ minimatch "^3.0.4"
+ strip-json-comments "^3.1.1"
"@ethersproject/abi@^5.0.5":
version "5.0.5"
@@ -1534,36 +1520,36 @@
"@types/yargs" "^15.0.0"
chalk "^4.0.0"
-"@json-rpc-tools/types@^1.5.7":
- version "1.5.7"
- resolved "https://registry.yarnpkg.com/@json-rpc-tools/types/-/types-1.5.7.tgz#6bfce4db9bfe5a40123866c520351c454f8da195"
- integrity sha512-IlcqmYjrwAQ3sexea/0CB0JVFRrjblpk7SzlbiqHCNtYczgWIT8wrezpfFVC6S1XfIvKm9fIhqg2zU4FUsfh6w==
+"@json-rpc-tools/types@^1.6.1":
+ version "1.7.1"
+ resolved "https://registry.yarnpkg.com/@json-rpc-tools/types/-/types-1.7.1.tgz#e341947679c57192b13e7d2e4ec49009b1c448c2"
+ integrity sha512-SNhhx84LQwc9/QnOpdVd8LvXqurB0WcfIEe6961Qx+9ixeK1+U3Dt4tZTPkVohyKwBZ6YyRsqQl9ZYsy2SjdxQ==
dependencies:
- keyvaluestorage "^0.6.0"
+ keyvaluestorage-interface "^1.0.0"
-"@json-rpc-tools/utils@1.5.7":
- version "1.5.7"
- resolved "https://registry.yarnpkg.com/@json-rpc-tools/utils/-/utils-1.5.7.tgz#932fa5b7885919e746caff0d32a61b613c631fd6"
- integrity sha512-AE7p5p15Lgu/L6onIaQfvIEUHD3U95hmOBNp3rdIe/lTjZIZrwm+CUiA/UAa+4QqwlG74Ri4fKbm+uriW5HaZA==
+"@json-rpc-tools/utils@1.6.1":
+ version "1.6.1"
+ resolved "https://registry.yarnpkg.com/@json-rpc-tools/utils/-/utils-1.6.1.tgz#26e37d0fc4522721158d0f6057e136daa8813263"
+ integrity sha512-cNwP4QapAls+xATU8zLLqPYa9qCbgwEyWEK7vE1oH91b3LfbUYwHtiWZ1+rv0X/mh/9cWNTo2Oi2Sah/QX0WwA==
dependencies:
- "@json-rpc-tools/types" "^1.5.7"
-
-"@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==
+ "@json-rpc-tools/types" "^1.6.1"
"@metamask/contract-metadata@^1.23.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@^7.0.0":
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-7.0.0.tgz#8daecd284faa897ca1f112a3f6f28d6936dac674"
- integrity sha512-vb2/wgGfJFMUa4Ej67FMkV94s0vp765t2vwOt8EOxhWfmEP2v9myc2B95L5jJJZZgvCk2ojaV11CrFF4ookLng==
+"@metamask/contract-metadata@^1.24.0":
+ version "1.25.0"
+ resolved "https://registry.yarnpkg.com/@metamask/contract-metadata/-/contract-metadata-1.25.0.tgz#442ace91fb40165310764b68d8096d0017bb0492"
+ integrity sha512-yhmYB9CQPv0dckNcPoWDcgtrdUp0OgK0uvkRE5QIBv4b3qENI1/03BztvK2ijbTuMlORUpjPq7/1MQDUPoRPVw==
+
+"@metamask/controllers@^8.0.0":
+ version "8.0.0"
+ resolved "https://registry.yarnpkg.com/@metamask/controllers/-/controllers-8.0.0.tgz#42ac5aaef67a03d3fe599a67a36597e01902ca8d"
+ integrity sha512-TrteMifsCxV1g3WHcSD1X98fF4hKep3sXZNGfrvkPqa8mrF03hJke21WBSTRtvJ3vkNLRWgi+5I6lVXFTzbYuQ==
dependencies:
- "@metamask/contract-metadata" "^1.23.0"
+ "@metamask/contract-metadata" "^1.24.0"
"@types/uuid" "^8.3.0"
async-mutex "^0.2.6"
babel-runtime "^6.26.0"
@@ -1590,6 +1576,11 @@
web3 "^0.20.7"
web3-provider-engine "^16.0.1"
+"@metamask/etherscan-link@^2.0.0":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@metamask/etherscan-link/-/etherscan-link-2.0.0.tgz#89035736515a39532ba1142d87b9a8c2b4f920f1"
+ integrity sha512-/YS32hS2UTTxs0KyUmAgaDj1w4dzAvOrT+p4TJtpICeH3E/k51r2FO0Or7WJJI/mpzTqNKgcH5yyS2oCtupGiA==
+
"@metamask/mobile-provider@^2.0.1":
version "2.0.1"
resolved "https://registry.yarnpkg.com/@metamask/mobile-provider/-/mobile-provider-2.0.1.tgz#892f883deafe49200a3ae57d85237016ded63c12"
@@ -1600,6 +1591,20 @@
resolved "https://registry.yarnpkg.com/@metamask/safe-event-emitter/-/safe-event-emitter-2.0.0.tgz#af577b477c683fad17c619a78208cede06f9605c"
integrity sha512-/kSXhY692qiV1MXu6EeOZvg5nECLclxNXcKCxJ3cXQgYuRymRHpdx/t7JXfsK+JLjwA1e1c1/SBrlQYpusC29Q==
+"@metamask/swaps-controller@^4.0.0":
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/@metamask/swaps-controller/-/swaps-controller-4.0.0.tgz#60c1c1b8fd7ed90bb86a7402dccfee69322d29a6"
+ integrity sha512-D5D4Ld6rJRkJurAVUkWNTuijrQR4IqXaXh5mJAJn2IDgncXWK8XvIuIpFz/z6dURuoj/JIbfqMB2jX4GsWrBMA==
+ dependencies:
+ "@metamask/controllers" "^8.0.0"
+ abort-controller "^3.0.0"
+ async-mutex "^0.3.1"
+ bignumber.js "^9.0.1"
+ eth-query "^2.1.2"
+ ethereumjs-util "^7.0.10"
+ human-standard-token-abi "^2.0.0"
+ web3 "^0.20.7"
+
"@pedrouid/iso-crypto@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@pedrouid/iso-crypto/-/iso-crypto-1.0.0.tgz#cf06b40ef3da3d7ca7363bd7a521ed59fa2fd13d"
@@ -1828,14 +1833,14 @@
resolved "https://registry.yarnpkg.com/@rnhooks/keyboard/-/keyboard-0.0.3.tgz#e17a62a9f1e4f25efdf0afa4359b82e3dbea6523"
integrity sha512-tBaDWQkcLgeEQCol/6NkB8JyRkvS7L3//mkkOSNOoeLc74Fttz8kiLUsSj9cBwSyFCrWP2K04Tn8zNgWfdFQYg==
-"@sentry/browser@^5.12.1":
- version "5.19.1"
- resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.19.1.tgz#b22f36fc71f36719ad352a54e6b31722622128c0"
- integrity sha512-Aon5Nc2n8sIXKg6Xbr4RM3/Xs7vFpXksL56z3yIuGrmpCM8ToQ25/tQv8h+anYi72x5bn1npzaXB/NwU1Qwfhg==
+"@sentry/browser@6.2.1":
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.2.1.tgz#f9f277e6f8cad0c7efd1a01726095d63a47a1c16"
+ integrity sha512-OAikFZ9EimD3noxMp8tA6Cf6qJcQ2U8k5QSgTPwdx+09nZOGJzbRFteK7WWmrS93ZJdzN61lpSQbg5v+bmmfbQ==
dependencies:
- "@sentry/core" "5.19.1"
- "@sentry/types" "5.19.1"
- "@sentry/utils" "5.19.1"
+ "@sentry/core" "6.2.1"
+ "@sentry/types" "6.2.1"
+ "@sentry/utils" "6.2.1"
tslib "^1.9.3"
"@sentry/cli@^1.52.4":
@@ -1849,95 +1854,123 @@
progress "^2.0.3"
proxy-from-env "^1.1.0"
-"@sentry/core@5.19.1", "@sentry/core@^5.12.0":
- version "5.19.1"
- resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.19.1.tgz#f5ff7feb1118035f75f1d0bc2a76e2b040d2aa8e"
- integrity sha512-BGGxjeT95Og/hloBhQXAVcndVXPmIU6drtF3oKRT12cBpiG965xEDEUwiJVvyb5MAvojdVEZBK2LURUFY/d7Zw==
+"@sentry/core@6.2.1":
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/@sentry/core/-/core-6.2.1.tgz#8b177e9bf591e2e7ddcb04f0b1403de3f5aa8755"
+ integrity sha512-jPqQEtafxxDtLONhCbTHh/Uq8mZRhsfbwJTSVYfPVEe/ELfFZLQK7tP6rOh7zEWKbTkE0mE6XcaoH3ZRAhgrqg==
dependencies:
- "@sentry/hub" "5.19.1"
- "@sentry/minimal" "5.19.1"
- "@sentry/types" "5.19.1"
- "@sentry/utils" "5.19.1"
+ "@sentry/hub" "6.2.1"
+ "@sentry/minimal" "6.2.1"
+ "@sentry/types" "6.2.1"
+ "@sentry/utils" "6.2.1"
tslib "^1.9.3"
-"@sentry/hub@5.19.1":
- version "5.19.1"
- resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.19.1.tgz#f3bc8500680974ce43c1eedcd8e90696cc18b306"
- integrity sha512-XjfbNGWVeDsP38alm5Cm08YPIw5Hu6HbPkw7a3y1piViTrg4HdtsE+ZJqq0YcURo2RTpg6Ks6coCS/zJxIPygQ==
+"@sentry/hub@6.2.1":
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-6.2.1.tgz#35bc6bf841a93f4354b3a17592c938b3dba20b73"
+ integrity sha512-pG7wCQeRpzeP6t0bT4T0X029R19dbDS3/qswF8BL6bg0AI3afjfjBAZm/fqn1Uwe/uBoMHVVdbxgJDZeQ5d4rQ==
dependencies:
- "@sentry/types" "5.19.1"
- "@sentry/utils" "5.19.1"
+ "@sentry/types" "6.2.1"
+ "@sentry/utils" "6.2.1"
tslib "^1.9.3"
-"@sentry/integrations@5.13.0":
- version "5.13.0"
- resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-5.13.0.tgz#358e3225ff302353ea38214daa4a5eed1eb5d4aa"
- integrity sha512-xfi3LyspqFxb2xaSKu5MMrA4kuN8waagbOjInAut48jrdqATLioMjCcUruU/aHILAUCCznPW9zsR42J1OmVoMw==
+"@sentry/integrations@6.2.1":
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-6.2.1.tgz#caa9b49de29523698668d45827633be86b2268ff"
+ integrity sha512-UBvuil/b9M5HGH6aBDzTiIVRsmpC/wqwDKy28IO05XLdalmKgJ9C1EQhoyN6xw+1lINpXXFtfq4NhfgZgWbc7Q==
dependencies:
- "@sentry/types" "5.12.4"
- "@sentry/utils" "5.13.0"
+ "@sentry/types" "6.2.1"
+ "@sentry/utils" "6.2.1"
+ localforage "^1.8.1"
tslib "^1.9.3"
-"@sentry/integrations@^5.12.0":
- version "5.19.1"
- resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-5.19.1.tgz#9c6680eceff95b9fb66ad18c2cf9fa2e9f0181b5"
- integrity sha512-JMiYtHh6m50eMC8BHkcZZjl6/Nx2JVivhkLx6EGsbgNTpGlsODhrRt+kgRKFhPWhEjKlcjx+l6tmq90NbfLusg==
+"@sentry/integrations@6.3.1":
+ version "6.3.1"
+ resolved "https://registry.yarnpkg.com/@sentry/integrations/-/integrations-6.3.1.tgz#8bd4c05a83c5fe8ece6cb59a6e31e1e632a14af8"
+ integrity sha512-fB0+CmU2L2VJ8WyI33t060lxpBNAoh092jzMGEnnfPKTVMxnscjFrISzrWXQZs/OoR6q8Yo/+pZAT5gWA0dDOQ==
dependencies:
- "@sentry/types" "5.19.1"
- "@sentry/utils" "5.19.1"
+ "@sentry/types" "6.3.1"
+ "@sentry/utils" "6.3.1"
+ localforage "^1.8.1"
tslib "^1.9.3"
-"@sentry/minimal@5.19.1":
- version "5.19.1"
- resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.19.1.tgz#04043d93a7dc90cbed1a31d80f6bf59688ea3100"
- integrity sha512-pgNfsaCroEsC8gv+NqmPTIkj4wyK6ZgYLV12IT4k2oJLkGyg45TSAKabyB7oEP5jsj8sRzm8tDomu8M4HpaCHg==
+"@sentry/minimal@6.2.1":
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-6.2.1.tgz#8f01480e1b56bc7dd54adf925e5317f233e19384"
+ integrity sha512-wuSXB4Ayxv9rBEQ4pm7fnG4UU2ZPtPnnChoEfd4/mw1UthXSvmPFEn6O4pdo2G8fTkl8eqm6wT/Q7uIXMEmw+A==
dependencies:
- "@sentry/hub" "5.19.1"
- "@sentry/types" "5.19.1"
+ "@sentry/hub" "6.2.1"
+ "@sentry/types" "6.2.1"
tslib "^1.9.3"
-"@sentry/react-native@1.3.3":
- version "1.3.3"
- resolved "https://registry.yarnpkg.com/@sentry/react-native/-/react-native-1.3.3.tgz#a2acb53171c743d89e92eb578dde9af9e6a91422"
- integrity sha512-OGeq1igrYTtgPYnOZEEWFRPyDESiGCkvyShL6YJ7U7kaDq5Fw3hgOHJovo/QhsQC7qVaYjgaMPX3Ht08xbh4IQ==
- dependencies:
- "@sentry/browser" "^5.12.1"
- "@sentry/core" "^5.12.0"
- "@sentry/integrations" "^5.12.0"
- "@sentry/types" "^5.12.0"
- "@sentry/utils" "^5.12.0"
- "@sentry/wizard" "^1.1.1"
-
-"@sentry/types@5.12.4":
- version "5.12.4"
- resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.12.4.tgz#6e52639bc3b4e136e9a0da5385890f8f78bb7697"
- integrity sha512-JoN3YIp7Z+uxUZArj2B6NcEoXFQDhd0kqO0QpfiHZyg4Dhx2/E2aHuVx0H6Fndk+60iEZSECaCBXe2MOPo4fqA==
-
-"@sentry/types@5.19.1", "@sentry/types@^5.12.0":
- version "5.19.1"
- resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.19.1.tgz#8762f668d3fc2416fbde31d15d13009544caeb54"
- integrity sha512-M5MhTLnjqYFwxMwcFPBpBgYQqI9hCvtVuj/A+NvcBHpe7VWOXdn/Sys+zD6C76DWGFYQdw3OWCsZimP24dL8mA==
-
-"@sentry/utils@5.13.0":
- version "5.13.0"
- resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.13.0.tgz#6463e53b6178dbbd3b90e671517cbca82744b055"
- integrity sha512-BcmNQN+IfFbVWGnEwXHku69zqJc97sjBRYVxpStKMaO/4aLVIQcOJCMWxVJtVoSVAHQaigBZmFutWH7EJMRJxg==
- dependencies:
- "@sentry/types" "5.12.4"
+"@sentry/react-native@2.4.2":
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/@sentry/react-native/-/react-native-2.4.2.tgz#82095e33a2dcd7720c2f71f35f02329ab7351547"
+ integrity sha512-+GAH2cdbZBz+EJOpBGAvVRl2jExLYrZ/gfmHnew3NYGlE/77GX1KQGJ+sKLA6xnPtXjcC7tJ13uvbQD6cltZnQ==
+ dependencies:
+ "@sentry/browser" "6.2.1"
+ "@sentry/core" "6.2.1"
+ "@sentry/hub" "6.2.1"
+ "@sentry/integrations" "6.2.1"
+ "@sentry/react" "6.2.1"
+ "@sentry/tracing" "6.2.1"
+ "@sentry/types" "6.2.1"
+ "@sentry/utils" "6.2.1"
+ "@sentry/wizard" "^1.2.2"
+
+"@sentry/react@6.2.1":
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/@sentry/react/-/react-6.2.1.tgz#26587f3f47e9699003b04ac558d8aa8a2b7416d7"
+ integrity sha512-emJnYVASM2hej2f8eSjqiDRMljwLsDJDSwa6kVc5HUOs9gnVrE4MR+vSywraACf5tKZbH1YI+NUXCmR++fIB0g==
+ dependencies:
+ "@sentry/browser" "6.2.1"
+ "@sentry/minimal" "6.2.1"
+ "@sentry/types" "6.2.1"
+ "@sentry/utils" "6.2.1"
+ hoist-non-react-statics "^3.3.2"
tslib "^1.9.3"
-"@sentry/utils@5.19.1", "@sentry/utils@^5.12.0":
- version "5.19.1"
- resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.19.1.tgz#e1134db40e4bb9732251e515721cec7ee94d4d9c"
- integrity sha512-neUiNBnZSHjWTZWy2QV02EHTx1C2L3DBPzRXlh0ca5xrI7LMBLmhkHlhebn1E5ky3PW1teqZTgmh0jZoL99TEA==
+"@sentry/tracing@6.2.1":
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-6.2.1.tgz#61c18c43c5390c348b35dafe73947ab379252d8f"
+ integrity sha512-bvStY1SnL08wkSeVK3j9K5rivQQJdKFCPR2VYRFOCaUoleZ6ChPUnBvxQ/E2LXc0hk/y/wo1q4r5B0dfCCY+bQ==
dependencies:
- "@sentry/types" "5.19.1"
+ "@sentry/hub" "6.2.1"
+ "@sentry/minimal" "6.2.1"
+ "@sentry/types" "6.2.1"
+ "@sentry/utils" "6.2.1"
tslib "^1.9.3"
-"@sentry/wizard@^1.1.1":
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/@sentry/wizard/-/wizard-1.1.4.tgz#df51af4271d11f729b938dde4864514b69e4aac9"
- integrity sha512-xVpL0lnQK2bbEwUKKjs3dKhy27va8HW75Q8r1vaR63iBCpB5LpP4Q4NN5G/VEWdYnH8rcazsOA207716E1cm4g==
+"@sentry/types@6.2.1":
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.2.1.tgz#28c946230b2023f72307b65606d32052ad9e5353"
+ integrity sha512-h0OV1QT+fv5ojfK5/+iEXClu33HirmvbjcQC2jf05IHj9yXIOWy6EB10S8nBjuLiiFqQiAQYj3FN9Ip4eN8NJA==
+
+"@sentry/types@6.3.1":
+ version "6.3.1"
+ resolved "https://registry.yarnpkg.com/@sentry/types/-/types-6.3.1.tgz#af3b54728b29f633f38fbe51b8c10e3834fbc158"
+ integrity sha512-BEBn8JX1yaooCAuonbaMci9z0RjwwMbQ3Eny/eyDdd+rjXprZCZaStZnCvSThbNBqAJ8YaUqY2YBMnEwJxarAw==
+
+"@sentry/utils@6.2.1":
+ version "6.2.1"
+ resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.2.1.tgz#bfcb12c20d44bf2aeb0073b1264703c11c179ebd"
+ integrity sha512-6kQgM/yBPdXu+3qbJnI6HBcWztN9QfiMkH++ZiKk4ERhg9d2LYWlze478uTU5Fyo/JQYcp+McpjtjpR9QIrr0g==
+ dependencies:
+ "@sentry/types" "6.2.1"
+ tslib "^1.9.3"
+
+"@sentry/utils@6.3.1":
+ version "6.3.1"
+ resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-6.3.1.tgz#6d8e691139b5b49d8c655ad1dcaf2cb3ff0d0b03"
+ integrity sha512-cdtl/QWC9FtinAuW3w8QfvSfh/Q9ui5vwvjzVHiS1ga/U38edi2XX+cttY39ZYwz0SQG99cE10GOIhd1p7/mAA==
+ dependencies:
+ "@sentry/types" "6.3.1"
+ tslib "^1.9.3"
+
+"@sentry/wizard@^1.2.2":
+ version "1.2.6"
+ resolved "https://registry.yarnpkg.com/@sentry/wizard/-/wizard-1.2.6.tgz#bb4e176e79dcab26c2ca18ddfbd0cc4a97645327"
+ integrity sha512-2flmpdOGfKXutHbiTRYWE4j5rUyTZGVHacai2A+z5giDN4WMSr1sqy04weyZzxF/fqMN6KMkDE5wtmK+btnEfw==
dependencies:
"@sentry/cli" "^1.52.4"
chalk "^2.4.1"
@@ -2005,6 +2038,13 @@
dependencies:
"@types/node" "*"
+"@types/bn.js@^5.1.0":
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.1.0.tgz#32c5d271503a12653c62cf4d2b45e6eab8cebc68"
+ integrity sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==
+ dependencies:
+ "@types/node" "*"
+
"@types/color-name@^1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0"
@@ -2165,62 +2205,71 @@
semver "^7.3.2"
tsutils "^3.17.1"
-"@walletconnect/client@1.3.4":
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/@walletconnect/client/-/client-1.3.4.tgz#6468f562a5df59dd33498da2649508e6b8261e63"
- integrity sha512-CRV4npHVNb7D1BVRRCiVQ3YBGNp7lEq8Ikkrgg1eWDAXCUNTtzAhmGo6uCzxjh6cpvfiHQNjZbShrqP+d286QQ==
+"@walletconnect/browser-utils@^1.4.1":
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/browser-utils/-/browser-utils-1.4.1.tgz#a8d5a038d28c19b739eb0ff4194ced140c922d36"
+ integrity sha512-ONrkPSI/27o1Wj8kUwE0uUZFk0GDCDQBJy614GsrhcwuQwJEW/B+nXPQ+Ca/4WvQySM5hWVHp1gO1kozSUkh3A==
dependencies:
- "@walletconnect/core" "^1.3.4"
- "@walletconnect/iso-crypto" "^1.3.4"
- "@walletconnect/types" "^1.3.4"
- "@walletconnect/utils" "^1.3.4"
+ "@walletconnect/types" "^1.4.1"
+ detect-browser "5.2.0"
+ safe-json-utils "1.0.0"
+ window-getters "1.0.0"
+ window-metadata "1.0.0"
-"@walletconnect/core@^1.3.4":
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-1.3.4.tgz#2059404ea778f582904bd71ab5ecf5a5bf6266b2"
- integrity sha512-CwAiQYT7oo3MwrYIOoLSce8iaZT5mNwVavc4s3S2TvkxoVc+ORywaXvUDavgFfWqW0P4gg4tO+e8QPD2Mxfm1w==
+"@walletconnect/client@^1.4.1":
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/client/-/client-1.4.1.tgz#c9c50df5afde23a35e23d96fe6d207c102e53850"
+ integrity sha512-JRW+9+j9LwszY76/WcIumEiLmhX7eidorH9SFFmI2pFfbrhB6KLe87FaA106kxwZUyWKOLZ6jVV4d1urYSdEwA==
dependencies:
- "@walletconnect/socket-transport" "^1.3.4"
- "@walletconnect/types" "^1.3.4"
- "@walletconnect/utils" "^1.3.4"
+ "@walletconnect/core" "^1.4.1"
+ "@walletconnect/iso-crypto" "^1.4.1"
+ "@walletconnect/types" "^1.4.1"
+ "@walletconnect/utils" "^1.4.1"
-"@walletconnect/iso-crypto@^1.3.4":
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/@walletconnect/iso-crypto/-/iso-crypto-1.3.4.tgz#3fb64d19509da8e3ef4b0ad0c2aaf4285c240968"
- integrity sha512-LHH3x+ISyIzF+5RYmQxd9FesNSCfQvRlCmEFjBp0NjlqRr0q1hRD4kj71+B7B0W+5a9zwS5FkkKJ2gaxxNntdg==
+"@walletconnect/core@^1.4.1":
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-1.4.1.tgz#68310ee7c9737a7a0a7f1308abbfc1c31212b9a6"
+ integrity sha512-NzWvhk4akI2uhORUxMDMS/8yAdfp+nzvb5QdTE0eTD0WOrK16qAfYLSU/IjFc2J2lqhuPVxfO2XV7QoxgCXfwA==
+ dependencies:
+ "@walletconnect/socket-transport" "^1.4.1"
+ "@walletconnect/types" "^1.4.1"
+ "@walletconnect/utils" "^1.4.1"
+
+"@walletconnect/iso-crypto@^1.4.1":
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/iso-crypto/-/iso-crypto-1.4.1.tgz#0d9793c679d6c5443c49cce83f5d8dd476a65df2"
+ integrity sha512-rzfqM/DFhzNxBriMCU4DOarPkH+Brgll+2a2YeO6zHgMlwZtBKi5mMgzBwbDC3XygOvKbcRTB9G9hr8uYn+i5g==
dependencies:
"@pedrouid/iso-crypto" "^1.0.0"
- "@walletconnect/types" "^1.3.4"
- "@walletconnect/utils" "^1.3.4"
+ "@walletconnect/types" "^1.4.1"
+ "@walletconnect/utils" "^1.4.1"
-"@walletconnect/socket-transport@^1.3.4":
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/@walletconnect/socket-transport/-/socket-transport-1.3.4.tgz#ef4ab90664562009f0e54d6e0c8cf417f4337810"
- integrity sha512-zjh3gQ0B6i5QyKSsQFAXDvF+Wttl/OVf2BiHKcHi9XSH+lFKJJeXDACmEja3ujRMEBw4U6nr/iH2X2kHeHkP+w==
+"@walletconnect/socket-transport@^1.4.1":
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/socket-transport/-/socket-transport-1.4.1.tgz#d9b7ebb9a2843cc44cf96c880c62be78d4a1625f"
+ integrity sha512-/5Mhu4bu3tS52LqTlmmjx5x/N89XqbuT0YMobvQ+k/m+VqSeBDntqIjwBt7XiFlCbrUTq3/yTajavGFxWFB6pA==
dependencies:
- "@walletconnect/types" "^1.3.4"
+ "@walletconnect/types" "^1.4.1"
+ "@walletconnect/utils" "^1.4.1"
ws "7.3.0"
-"@walletconnect/types@^1.3.4":
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-1.3.4.tgz#e44d4817bb2299ff8c2731cbad2f023ea506d912"
- integrity sha512-XK9cogoYdMkk8UcJIBi23iMazYdFLll0MeR10sjVY2rc1twqQ/8oiJHw8u8o1m5Qdw3Zxm30UrgBebPvcv9m5g==
+"@walletconnect/types@^1.4.1":
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-1.4.1.tgz#48297238b86f846b8c694504ca45f0059a2cca88"
+ integrity sha512-lzS9NbXjVb5N+W/UnCZAflxjLtYepUi4ev1IeFozSvr/cWxAhEe/sjixe7WEIpYklW27kfBhKccMH/KjUoRC7w==
-"@walletconnect/utils@1.3.4", "@walletconnect/utils@^1.3.4":
- version "1.3.4"
- resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-1.3.4.tgz#2ee9625cc4c30dc6e4aacd27bea962ab8d2e6587"
- integrity sha512-AI/U5tvG7UfyLwTpo5hGL5ZFV31ypk/cG2MUOGoUYKfjKhyQcxX+wc6kXv2S+nBdS5aFgCS1aT9qHcbAIfOFHw==
+"@walletconnect/utils@^1.4.1":
+ version "1.4.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-1.4.1.tgz#86108470c211a02609274a6c7bbd516c5182a22e"
+ integrity sha512-JrVjcXmWVcU02fmVNZFBpJ48f84qyar24CF7szGv+k9ZxvU9J7XkM+Fic4790Dt3DaWhOzS9/eBUa+BEZcBbNw==
dependencies:
- "@json-rpc-tools/utils" "1.5.7"
- "@walletconnect/types" "^1.3.4"
+ "@json-rpc-tools/utils" "1.6.1"
+ "@walletconnect/browser-utils" "^1.4.1"
+ "@walletconnect/types" "^1.4.1"
bn.js "4.11.8"
- detect-browser "5.1.0"
enc-utils "3.0.0"
js-sha3 "0.8.0"
query-string "6.13.5"
- safe-json-utils "1.0.0"
- window-getters "1.0.0"
- window-metadata "1.0.0"
"@yarnpkg/lockfile@^1.0.0", "@yarnpkg/lockfile@^1.1.0":
version "1.1.0"
@@ -2298,7 +2347,7 @@ acorn-jsx@^5.0.0:
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.2.0.tgz#4c66069173d6fdd68ed85239fc256226182b2ebe"
integrity sha512-HiUX/+K2YpkpJ+SzBffkM/AQ2YE03S0U1kjTLVpoJdhZMOWy8qvXVN9JdLqv2QsaQ6MPYQIuNmwD8zOiYUofLQ==
-acorn-jsx@^5.2.0:
+acorn-jsx@^5.3.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b"
integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==
@@ -2318,7 +2367,7 @@ acorn@^7.1.0:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.2.0.tgz#17ea7e40d7c8640ff54a694c889c26f31704effe"
integrity sha512-apwXVmYVpQ34m/i71vrApRrRKCWQnZZF1+npOD0WV5xZFfwWOmKGQ2RWlfdy9vWITsenisM8M0Qeq8agcFHNiQ==
-acorn@^7.1.1:
+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==
@@ -2395,6 +2444,26 @@ ajv@^6.10.0, ajv@^6.10.2, ajv@^6.5.5, ajv@^6.9.1:
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
+ajv@^6.12.4:
+ version "6.12.6"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
+ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ fast-json-stable-stringify "^2.0.0"
+ json-schema-traverse "^0.4.1"
+ uri-js "^4.2.2"
+
+ajv@^8.0.1:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.1.0.tgz#45d5d3d36c7cdd808930cc3e603cf6200dbeb736"
+ integrity sha512-B/Sk2Ix7A36fs/ZkuGLIR86EdjbgR6fsAcbx9lOP/QBSXujDNbVmIS/U4Itz5k8fPFDeVZl/zQ/gJW4Jrq6XjQ==
+ dependencies:
+ fast-deep-equal "^3.1.1"
+ json-schema-traverse "^1.0.0"
+ require-from-string "^2.0.2"
+ uri-js "^4.2.2"
+
anser@^1.4.9:
version "1.4.9"
resolved "https://registry.yarnpkg.com/anser/-/anser-1.4.9.tgz#1f85423a5dcf8da4631a341665ff675b96845760"
@@ -2515,19 +2584,6 @@ anymatch@^3.0.3:
normalize-path "^3.0.0"
picomatch "^2.0.4"
-aproba@^1.0.3:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
- integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
-
-are-we-there-yet@~1.1.2:
- version "1.1.5"
- resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
- integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==
- dependencies:
- delegates "^1.0.0"
- readable-stream "^2.0.6"
-
argparse@^1.0.7:
version "1.0.10"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911"
@@ -3021,15 +3077,6 @@ bech32@1.1.4:
resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9"
integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==
-better-sqlite3@^7.1.2:
- version "7.1.2"
- resolved "https://registry.yarnpkg.com/better-sqlite3/-/better-sqlite3-7.1.2.tgz#95565757a834093f1ecae0d4457f60820ed5dd2a"
- integrity sha512-8FWYnJ6Bx94MBX03J5Ka7sTRlvXXMEm4FW2Op7nM8ErQZeyALYLmSlbMBnfr4cMpS0tj0aYZv0a+26G2YJuIjg==
- dependencies:
- bindings "^1.5.0"
- prebuild-install "^5.3.3"
- tar "^6.0.5"
-
big-integer@^1.6.44:
version "1.6.48"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.48.tgz#8fd88bd1632cba4a1c8c3e3d7159f08bb95b4b9e"
@@ -3087,15 +3134,6 @@ bl@^1.2.3, bl@~0.8.1:
readable-stream "^2.3.5"
safe-buffer "^5.1.1"
-bl@^4.0.3:
- version "4.0.3"
- resolved "https://registry.yarnpkg.com/bl/-/bl-4.0.3.tgz#12d6287adc29080e22a705e5764b2a9522cdc489"
- integrity sha512-fs4G6/Hu4/EE+F75J8DuN/0IpQqNjAdC7aEQv7Qt8MHGUH7Ckv2MwTEEeN9QehD0pfIDkMI1bkHYkKy7xHyKIg==
- dependencies:
- buffer "^5.5.0"
- inherits "^2.0.4"
- readable-stream "^3.4.0"
-
blakejs@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/blakejs/-/blakejs-1.1.0.tgz#69df92ef953aa88ca51a32df6ab1c54a155fc7a5"
@@ -3440,6 +3478,11 @@ camelcase@^5.0.0, camelcase@^5.3.1:
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
+camelcase@^6.0.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809"
+ integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==
+
capture-exit@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4"
@@ -3531,16 +3574,6 @@ child-process-promise@^2.2.0:
node-version "^1.0.0"
promise-polyfill "^6.0.1"
-chownr@^1.1.1:
- version "1.1.4"
- resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
- integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
-
-chownr@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
- integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
-
ci-info@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
@@ -3617,11 +3650,6 @@ cli-width@^2.0.0:
resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.1.tgz#b0433d0b4e9c847ef18868a4ef16fd5fc8271c48"
integrity sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==
-cli-width@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6"
- integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==
-
cliui@^3.0.3:
version "3.2.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d"
@@ -3658,6 +3686,15 @@ cliui@^6.0.0:
strip-ansi "^6.0.0"
wrap-ansi "^6.2.0"
+cliui@^7.0.2:
+ version "7.0.4"
+ resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f"
+ integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==
+ dependencies:
+ string-width "^4.2.0"
+ strip-ansi "^6.0.0"
+ wrap-ansi "^7.0.0"
+
clone@^1.0.2:
version "1.0.4"
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
@@ -3866,11 +3903,6 @@ connect@^3.6.5:
parseurl "~1.3.3"
utils-merge "1.0.1"
-console-control-strings@^1.0.0, console-control-strings@~1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
- integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
-
contains-path@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a"
@@ -4026,7 +4058,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5:
shebang-command "^1.2.0"
which "^1.2.9"
-cross-spawn@^7.0.0:
+cross-spawn@^7.0.0, cross-spawn@^7.0.2:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@@ -4164,18 +4196,16 @@ decamelize@^1.1.1, decamelize@^1.2.0:
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=
+decamelize@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837"
+ integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==
+
decode-uri-component@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
-decompress-response@^4.2.0:
- version "4.2.1"
- resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986"
- integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==
- dependencies:
- mimic-response "^2.0.0"
-
dedent@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.6.0.tgz#0e6da8f0ce52838ef5cec5c8f9396b0c1b64a3cb"
@@ -4230,7 +4260,7 @@ deep-extend@^0.6.0:
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==
-deep-is@~0.1.3:
+deep-is@^0.1.3, deep-is@~0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34"
integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=
@@ -4309,11 +4339,6 @@ delayed-stream@~1.0.0:
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
-delegates@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
- integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
-
denodeify@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/denodeify/-/denodeify-1.2.1.tgz#3a36287f5034e699e7577901052c2e6c94251631"
@@ -4337,25 +4362,20 @@ destroy@~1.0.4:
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
-detect-browser@5.1.0:
- version "5.1.0"
- resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.1.0.tgz#0c51c66b747ad8f98a6832bf3026a5a23a7850ff"
- integrity sha512-WKa9p+/MNwmTiS+V2AS6eGxic+807qvnV3hC+4z2GTY+F42h1n8AynVTMMc4EJBC32qMs6yjOTpeDEQQt/AVqQ==
-
-detect-libc@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
- integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
+detect-browser@5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.2.0.tgz#c9cd5afa96a6a19fda0bbe9e9be48a6b6e1e9c97"
+ integrity sha512-tr7XntDAu50BVENgQfajMLzacmSe34D+qZc4zjnniz0ZVuw/TZcLcyxHQjYpJTM36sGEkZZlYLnIM1hH7alTMA==
detect-newline@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
-detox@17.3.1:
- version "17.3.1"
- resolved "https://registry.yarnpkg.com/detox/-/detox-17.3.1.tgz#508a1358c3c0c56670d520b2ab7480dddbfc486f"
- integrity sha512-UFhHxsjfaOdO0tf6tIMXYCEIClfhgHHfjU/XZmrLavL2GKSfS3udGu+EcQ/Iqt57C1GYCHfnxMi2pgghjASmRQ==
+detox@17.14.9:
+ version "17.14.9"
+ resolved "https://registry.yarnpkg.com/detox/-/detox-17.14.9.tgz#e269de0937e615eac92ac283b2303751bcf2c072"
+ integrity sha512-WLpl7BJ2xecZJ02hFFWgzo61RnlO/LlsH/U8GWztoXsT0z0t9iKsBci8AhSSErQfH0IHnNtDcZknIxt0gzNhoQ==
dependencies:
bunyan "^1.8.12"
bunyan-debug-stream "^1.1.0"
@@ -4369,16 +4389,17 @@ detox@17.3.1:
lodash "^4.17.5"
minimist "^1.2.0"
proper-lockfile "^3.0.2"
+ resolve-from "^5.0.0"
sanitize-filename "^1.6.1"
- shell-utils "^1.0.9"
+ shell-quote "^1.7.2"
signal-exit "^3.0.3"
tail "^2.0.0"
telnet-client "1.2.8"
tempfile "^2.0.0"
which "^1.3.1"
ws "^3.3.1"
- yargs "^13.0.0"
- yargs-parser "^13.0.0"
+ yargs "^16.0.3"
+ yargs-unparser "^2.0.0"
diff-sequences@^25.2.6:
version "25.2.6"
@@ -4547,6 +4568,11 @@ elliptic@6.5.3, elliptic@^6.0.0, elliptic@^6.4.0, elliptic@^6.5.2, elliptic@^6.5
minimalistic-assert "^1.0.1"
minimalistic-crypto-utils "^1.0.1"
+eme-encryption-scheme-polyfill@^2.0.1:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/eme-encryption-scheme-polyfill/-/eme-encryption-scheme-polyfill-2.0.3.tgz#2ca6e06480e06cceb5e50efd27943ac46c959878"
+ integrity sha512-44CNFMsqzHdKHrzWxlS7xZ8KUHn5XutBqpmCuWzNIynmAyFInHrrD3ozv/RvK9ZhgV6QY6Easx8EWAmxteNodg==
+
emoji-regex@^7.0.1:
version "7.0.3"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
@@ -4577,14 +4603,14 @@ encoding@^0.1.11:
dependencies:
iconv-lite "~0.4.13"
-end-of-stream@^1.1.0, end-of-stream@^1.4.0, end-of-stream@^1.4.1:
+end-of-stream@^1.1.0, end-of-stream@^1.4.0:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
dependencies:
once "^1.4.0"
-enquirer@^2.3.6:
+enquirer@^2.3.5, enquirer@^2.3.6:
version "2.3.6"
resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==
@@ -4749,6 +4775,11 @@ es6-promisify@^5.0.0:
dependencies:
es6-promise "^4.0.3"
+escalade@^3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
+ integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
+
escape-html@~1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
@@ -4990,14 +5021,22 @@ eslint-scope@^5.0.0:
esrecurse "^4.1.0"
estraverse "^4.1.1"
-eslint-utils@^1.3.1, eslint-utils@^1.4.3:
+eslint-scope@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c"
+ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==
+ dependencies:
+ esrecurse "^4.3.0"
+ estraverse "^4.1.1"
+
+eslint-utils@^1.3.1:
version "1.4.3"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.4.3.tgz#74fec7c54d0776b6f67e0251040b5806564e981f"
integrity sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==
dependencies:
eslint-visitor-keys "^1.1.0"
-eslint-utils@^2.0.0:
+eslint-utils@^2.0.0, eslint-utils@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27"
integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==
@@ -5009,6 +5048,16 @@ eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0:
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.1.0.tgz#e2a82cea84ff246ad6fb57f9bde5b46621459ec2"
integrity sha512-8y9YjtM1JBJU/A9Kc+SbaOV4y29sSWckBwMHa+FGtVj5gN/sbnKDf6xJUl+8g7FAij9LVaP8C24DUiH/f/2Z9A==
+eslint-visitor-keys@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e"
+ integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==
+
+eslint-visitor-keys@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8"
+ integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ==
+
eslint@^5.6.0:
version "5.16.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea"
@@ -5051,46 +5100,46 @@ eslint@^5.6.0:
table "^5.2.3"
text-table "^0.2.0"
-eslint@^6.5.1:
- version "6.8.0"
- resolved "https://registry.yarnpkg.com/eslint/-/eslint-6.8.0.tgz#62262d6729739f9275723824302fb227c8c93ffb"
- integrity sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==
+eslint@^7.14.0:
+ version "7.24.0"
+ resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.24.0.tgz#2e44fa62d93892bfdb100521f17345ba54b8513a"
+ integrity sha512-k9gaHeHiFmGCDQ2rEfvULlSLruz6tgfA8DEn+rY9/oYPFFTlz55mM/Q/Rij1b2Y42jwZiK3lXvNTw6w6TXzcKQ==
dependencies:
- "@babel/code-frame" "^7.0.0"
+ "@babel/code-frame" "7.12.11"
+ "@eslint/eslintrc" "^0.4.0"
ajv "^6.10.0"
- chalk "^2.1.0"
- cross-spawn "^6.0.5"
+ chalk "^4.0.0"
+ cross-spawn "^7.0.2"
debug "^4.0.1"
doctrine "^3.0.0"
- eslint-scope "^5.0.0"
- eslint-utils "^1.4.3"
- eslint-visitor-keys "^1.1.0"
- espree "^6.1.2"
- esquery "^1.0.1"
+ enquirer "^2.3.5"
+ eslint-scope "^5.1.1"
+ eslint-utils "^2.1.0"
+ eslint-visitor-keys "^2.0.0"
+ espree "^7.3.1"
+ esquery "^1.4.0"
esutils "^2.0.2"
- file-entry-cache "^5.0.1"
+ file-entry-cache "^6.0.1"
functional-red-black-tree "^1.0.1"
glob-parent "^5.0.0"
- globals "^12.1.0"
+ globals "^13.6.0"
ignore "^4.0.6"
import-fresh "^3.0.0"
imurmurhash "^0.1.4"
- inquirer "^7.0.0"
is-glob "^4.0.0"
js-yaml "^3.13.1"
json-stable-stringify-without-jsonify "^1.0.1"
- levn "^0.3.0"
- lodash "^4.17.14"
+ levn "^0.4.1"
+ lodash "^4.17.21"
minimatch "^3.0.4"
- mkdirp "^0.5.1"
natural-compare "^1.4.0"
- optionator "^0.8.3"
+ optionator "^0.9.1"
progress "^2.0.0"
- regexpp "^2.0.1"
- semver "^6.1.2"
- strip-ansi "^5.2.0"
- strip-json-comments "^3.0.1"
- table "^5.2.3"
+ regexpp "^3.1.0"
+ semver "^7.2.1"
+ strip-ansi "^6.0.0"
+ strip-json-comments "^3.1.0"
+ table "^6.0.4"
text-table "^0.2.0"
v8-compile-cache "^2.0.3"
@@ -5103,14 +5152,14 @@ espree@^5.0.1:
acorn-jsx "^5.0.0"
eslint-visitor-keys "^1.0.0"
-espree@^6.1.2:
- version "6.2.1"
- resolved "https://registry.yarnpkg.com/espree/-/espree-6.2.1.tgz#77fc72e1fd744a2052c20f38a5b575832e82734a"
- integrity sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==
+espree@^7.3.0, espree@^7.3.1:
+ version "7.3.1"
+ resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.1.tgz#f2df330b752c6f55019f8bd89b7660039c1bbbb6"
+ integrity sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==
dependencies:
- acorn "^7.1.1"
- acorn-jsx "^5.2.0"
- eslint-visitor-keys "^1.1.0"
+ acorn "^7.4.0"
+ acorn-jsx "^5.3.1"
+ eslint-visitor-keys "^1.3.0"
esprima@3.x.x:
version "3.1.3"
@@ -5129,6 +5178,13 @@ esquery@^1.0.1:
dependencies:
estraverse "^5.1.0"
+esquery@^1.4.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5"
+ integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==
+ dependencies:
+ estraverse "^5.1.0"
+
esrecurse@^4.1.0:
version "4.2.1"
resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf"
@@ -5136,6 +5192,13 @@ esrecurse@^4.1.0:
dependencies:
estraverse "^4.1.0"
+esrecurse@^4.3.0:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921"
+ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==
+ dependencies:
+ estraverse "^5.2.0"
+
estraverse@^4.1.0, estraverse@^4.1.1, estraverse@^4.2.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d"
@@ -5146,6 +5209,11 @@ estraverse@^5.1.0:
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.1.0.tgz#374309d39fd935ae500e7b92e8a6b4c720e59642"
integrity sha512-FyohXK+R0vE+y1nHLoBM7ZTyqRpqAlhdZHCWIWEviFLiGB8b04H6bQs8G+XTthacvT8VuwvteiP7RJSxMs8UEw==
+estraverse@^5.2.0:
+ version "5.2.0"
+ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880"
+ integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==
+
esutils@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
@@ -5542,6 +5610,18 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0:
rlp "^2.2.3"
secp256k1 "^3.0.1"
+ethereumjs-util@^7.0.10:
+ version "7.0.10"
+ resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz#5fb7b69fa1fda0acc59634cf39d6b0291180fc1f"
+ integrity sha512-c/xThw6A+EAnej5Xk5kOzFzyoSnw0WX0tSlZ6pAsfGVvQj3TItaDg9b1+Fz1RJXA+y2YksKwQnuzgt1eY6LKzw==
+ dependencies:
+ "@types/bn.js" "^5.1.0"
+ bn.js "^5.1.2"
+ create-hash "^1.1.2"
+ ethereum-cryptography "^0.1.3"
+ ethjs-util "0.1.6"
+ rlp "^2.2.4"
+
ethereumjs-util@^7.0.2:
version "7.0.8"
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.0.8.tgz#5258762b7b17e3d828e41834948363ff0a703ffd"
@@ -5932,11 +6012,6 @@ expand-brackets@^2.1.4:
snapdragon "^0.8.1"
to-regex "^3.0.1"
-expand-template@^2.0.3:
- version "2.0.3"
- resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
- integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
-
expect@^25.5.0:
version "25.5.0"
resolved "https://registry.yarnpkg.com/expect/-/expect-25.5.0.tgz#f07f848712a2813bb59167da3fb828ca21f58bba"
@@ -6147,7 +6222,7 @@ figures@^2.0.0:
dependencies:
escape-string-regexp "^1.0.5"
-figures@^3.0.0, figures@^3.2.0:
+figures@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==
@@ -6161,6 +6236,13 @@ file-entry-cache@^5.0.1:
dependencies:
flat-cache "^2.0.1"
+file-entry-cache@^6.0.1:
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027"
+ integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==
+ dependencies:
+ flat-cache "^3.0.4"
+
file-uri-to-path@1, file-uri-to-path@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
@@ -6249,11 +6331,29 @@ flat-cache@^2.0.1:
rimraf "2.6.3"
write "1.0.3"
+flat-cache@^3.0.4:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
+ integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==
+ dependencies:
+ flatted "^3.1.0"
+ rimraf "^3.0.2"
+
+flat@^5.0.2:
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241"
+ integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==
+
flatted@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138"
integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==
+flatted@^3.1.0:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.1.1.tgz#c4b489e80096d9df1dfc97c79871aea7c617c469"
+ integrity sha512-zAoAQiudy+r5SvnSw3KJy5os/oRJYHzrzja/tBDqrZtNhUw8bt6y8OBzMWcjWr+8liV8Eb6yOhw8WZ7VFZ5ZzA==
+
follow-redirects@^1.10.0:
version "1.13.1"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.1.tgz#5f69b813376cee4fd0474a3aba835df04ab763b7"
@@ -6309,11 +6409,6 @@ fresh@0.5.2:
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
-fs-constants@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
- integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
-
fs-extra@^0.22.1:
version "0.22.1"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.22.1.tgz#5fd6f8049dc976ca19eb2355d658173cabcce056"
@@ -6359,13 +6454,6 @@ fs-extra@^8.1.0:
jsonfile "^4.0.0"
universalify "^0.1.0"
-fs-minipass@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
- integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
- dependencies:
- minipass "^3.0.0"
-
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
@@ -6433,20 +6521,6 @@ fwd-stream@^1.0.4:
dependencies:
readable-stream "~1.0.26-4"
-gauge@~2.7.3:
- version "2.7.4"
- resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
- integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=
- dependencies:
- aproba "^1.0.3"
- console-control-strings "^1.0.0"
- has-unicode "^2.0.0"
- object-assign "^4.1.0"
- signal-exit "^3.0.0"
- string-width "^1.0.1"
- strip-ansi "^3.0.1"
- wide-align "^1.1.0"
-
gensync@^1.0.0-beta.1:
version "1.0.0-beta.1"
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269"
@@ -6457,7 +6531,7 @@ get-caller-file@^1.0.1:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a"
integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==
-get-caller-file@^2.0.1:
+get-caller-file@^2.0.1, get-caller-file@^2.0.5:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
@@ -6522,11 +6596,6 @@ getpass@^0.1.1:
dependencies:
assert-plus "^1.0.0"
-github-from-package@0.0.0:
- version "0.0.0"
- resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
- integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=
-
glob-parent@^5.0.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
@@ -6589,6 +6658,13 @@ globals@^12.1.0:
dependencies:
type-fest "^0.8.1"
+globals@^13.6.0:
+ version "13.8.0"
+ resolved "https://registry.yarnpkg.com/globals/-/globals-13.8.0.tgz#3e20f504810ce87a8d72e55aecf8435b50f4c1b3"
+ integrity sha512-rHtdA6+PDBIjeEvA91rpqzEvk/k3/i7EeNQiryiWuJH0Hw9cpyJMAt2jtbAwUaRdhD+573X4vWw6IcjKPasi9Q==
+ dependencies:
+ type-fest "^0.20.2"
+
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4:
version "4.2.4"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
@@ -6639,11 +6715,6 @@ has-symbols@^1.0.0, has-symbols@^1.0.1:
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8"
integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==
-has-unicode@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
- integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
-
has-value@^0.3.1:
version "0.3.1"
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
@@ -6750,9 +6821,9 @@ hoist-non-react-statics@^3.1.0, hoist-non-react-statics@^3.3.0, hoist-non-react-
react-is "^16.7.0"
hosted-git-info@^2.1.4:
- version "2.8.8"
- resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
- integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
+ version "2.8.9"
+ resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
+ integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
html-element-map@^1.0.0:
version "1.2.0"
@@ -6928,6 +6999,11 @@ immediate@^3.2.3:
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c"
integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw=
+immediate@~3.0.5:
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
+ integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
+
immer@^8.0.1:
version "8.0.1"
resolved "https://registry.yarnpkg.com/immer/-/immer-8.0.1.tgz#9c73db683e2b3975c424fb0572af5889877ae656"
@@ -7003,7 +7079,7 @@ 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.0:
+ini@^1.3.4:
version "1.3.8"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
@@ -7047,25 +7123,6 @@ inquirer@^6.2.0, inquirer@^6.2.2:
strip-ansi "^5.1.0"
through "^2.3.6"
-inquirer@^7.0.0:
- version "7.3.3"
- resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-7.3.3.tgz#04d176b2af04afc157a83fd7c100e98ee0aad003"
- integrity sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==
- dependencies:
- ansi-escapes "^4.2.1"
- chalk "^4.1.0"
- cli-cursor "^3.1.0"
- cli-width "^3.0.0"
- external-editor "^3.0.3"
- figures "^3.0.0"
- lodash "^4.17.19"
- mute-stream "0.0.8"
- run-async "^2.4.0"
- rxjs "^6.6.0"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
- through "^2.3.6"
-
internal-slot@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.2.tgz#9c2e9fb3cd8e5e4256c6f45fe310067fcfa378a3"
@@ -7308,6 +7365,11 @@ is-object@~0.1.2:
resolved "https://registry.yarnpkg.com/is-object/-/is-object-0.1.2.tgz#00efbc08816c33cfc4ac8251d132e10dc65098d7"
integrity sha1-AO+8CIFsM8/ErIJR0TLhDcZQmNc=
+is-plain-obj@^2.1.0:
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287"
+ integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==
+
is-plain-object@^2.0.3, is-plain-object@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
@@ -8146,6 +8208,11 @@ json-schema-traverse@^0.4.1:
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
+json-schema-traverse@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
+ integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+
json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
@@ -8253,14 +8320,15 @@ keccakjs@^0.2.0:
browserify-sha3 "^0.0.4"
sha3 "^1.2.2"
-keyvaluestorage@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/keyvaluestorage/-/keyvaluestorage-0.6.0.tgz#8ec60592741fca865ff6ff797c0d696c7315f8f5"
- integrity sha512-27+JPFNTkGPTgckVEk7PAXVlFcODbyXVZQjR1Q7RBWC8rDXjBbBbP3HC9itpmHY9naxf8w7hanM3hUecQmAsQA==
- dependencies:
- better-sqlite3 "^7.1.2"
- localStorage "^1.0.4"
- safe-json-utils "^1.1.1"
+keymirror@^0.1.1:
+ version "0.1.1"
+ resolved "https://registry.yarnpkg.com/keymirror/-/keymirror-0.1.1.tgz#918889ea13f8d0a42e7c557250eee713adc95c35"
+ integrity sha1-kYiJ6hP40KQufFVyUO7nE63JXDU=
+
+keyvaluestorage-interface@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz#13ebdf71f5284ad54be94bd1ad9ed79adad515ff"
+ integrity sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==
kind-of@^1.1.0:
version "1.1.0"
@@ -8460,6 +8528,21 @@ levn@^0.3.0, levn@~0.3.0:
prelude-ls "~1.1.2"
type-check "~0.3.2"
+levn@^0.4.1:
+ version "0.4.1"
+ resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade"
+ integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==
+ dependencies:
+ prelude-ls "^1.2.1"
+ type-check "~0.4.0"
+
+lie@3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"
+ integrity sha1-mkNrLMd0bKWd56QfpGmz77dr2H4=
+ dependencies:
+ immediate "~3.0.5"
+
lil-uuid@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/lil-uuid/-/lil-uuid-0.1.1.tgz#f9edcf23f00e42bf43f0f843d98d8b53f3341f16"
@@ -8516,10 +8599,12 @@ load-json-file@^2.0.0:
pify "^2.0.0"
strip-bom "^3.0.0"
-localStorage@^1.0.4:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/localStorage/-/localStorage-1.0.4.tgz#57dfa28084385f81431accb8ae24b196398223f7"
- integrity sha512-r35zrihcDiX+dqWlJSeIwS9nrF95OQTgqMFm3FB2D/+XgdmZtcutZOb7t0xXkhOEM8a9kpuu7cc28g1g36I5DQ==
+localforage@^1.8.1:
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/localforage/-/localforage-1.9.0.tgz#f3e4d32a8300b362b4634cc4e066d9d00d2f09d1"
+ integrity sha512-rR1oyNrKulpe+VM9cYmcFn6tsHuokyVHFaCM3+osEmxaHTbEk8oQu6eGDfS6DQLWi/N67XRmB8ECG37OES368g==
+ dependencies:
+ lie "3.1.1"
locate-path@^2.0.0:
version "2.0.0"
@@ -8544,11 +8629,21 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
+lodash.clonedeep@^4.5.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
+ integrity sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=
+
lodash.escape@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/lodash.escape/-/lodash.escape-4.0.1.tgz#c9044690c21e04294beaa517712fded1fa88de98"
integrity sha1-yQRGkMIeBClL6qUXcS/e0fqI3pg=
+lodash.flatten@^4.4.0:
+ version "4.4.0"
+ resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
+ integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
+
lodash.flattendeep@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2"
@@ -8579,15 +8674,15 @@ lodash.toarray@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE=
-lodash@4.x.x, lodash@^4.0.0, lodash@^4.15.0, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0:
- version "4.17.19"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
- integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
+lodash.truncate@^4.4.2:
+ version "4.4.2"
+ resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193"
+ integrity sha1-WjUNoLERO4N+z//VgSy+WNbq4ZM=
-lodash@^4.17.19:
- version "4.17.20"
- resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52"
- integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==
+lodash@^4.0.0, lodash@^4.15.0, lodash@^4.16.4, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.3.0:
+ version "4.17.21"
+ resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
+ integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
log-symbols@^2.2.0:
version "2.2.0"
@@ -9312,11 +9407,6 @@ mimic-fn@^2.0.0, mimic-fn@^2.1.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
-mimic-response@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43"
- integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==
-
min-document@^2.19.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
@@ -9341,26 +9431,11 @@ minimalistic-crypto-utils@^1.0.1:
dependencies:
brace-expansion "^1.1.7"
-minimist@^1.1.1, minimist@^1.1.2, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5:
+minimist@^1.1.1, minimist@^1.1.2, minimist@^1.2.0, minimist@^1.2.5:
version "1.2.5"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
-minipass@^3.0.0:
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd"
- integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==
- dependencies:
- yallist "^4.0.0"
-
-minizlib@^2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
- integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
- dependencies:
- minipass "^3.0.0"
- yallist "^4.0.0"
-
mixin-deep@^1.2.0:
version "1.3.2"
resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566"
@@ -9369,11 +9444,6 @@ mixin-deep@^1.2.0:
for-in "^1.0.2"
is-extendable "^1.0.1"
-mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
- version "0.5.3"
- resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
- integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
-
mkdirp@0.x.x, mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.1:
version "0.5.5"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def"
@@ -9381,11 +9451,6 @@ mkdirp@0.x.x, mkdirp@^0.5.1, mkdirp@^0.5.5, mkdirp@~0.5.1:
dependencies:
minimist "^1.2.5"
-mkdirp@^1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
- integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
-
moment@^2.10.6:
version "2.26.0"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.26.0.tgz#5e1f82c6bafca6e83e808b30c8705eed0dcbd39a"
@@ -9464,7 +9529,7 @@ mute-stream@0.0.7:
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab"
integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=
-mute-stream@0.0.8, mute-stream@~0.0.4:
+mute-stream@~0.0.4:
version "0.0.8"
resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"
integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==
@@ -9510,11 +9575,6 @@ nanomatch@^1.2.9:
snapdragon "^0.8.1"
to-regex "^3.0.1"
-napi-build-utils@^1.0.1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806"
- integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==
-
natural-compare@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
@@ -9561,13 +9621,6 @@ nocache@^2.1.0:
resolved "https://registry.yarnpkg.com/nocache/-/nocache-2.1.0.tgz#120c9ffec43b5729b1d5de88cd71aa75a0ba491f"
integrity sha512-0L9FvHG3nfnnmaEQPjT9xhfN4ISk0A8/2j4M37Np4mcDesJjHgEUfgPhdCyZuFI954tjokaIj/A3NdpFNdEh4Q==
-node-abi@^2.7.0:
- version "2.19.3"
- resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.19.3.tgz#252f5dcab12dad1b5503b2d27eddd4733930282d"
- integrity sha512-9xZrlyfvKhWme2EXFKQhZRp1yNWT/uI1luYPr3sFl+H4keYY4xR+1jO7mvTTijIsHf1M+QDe9uWuKeEpLInIlg==
- dependencies:
- semver "^5.4.1"
-
node-addon-api@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32"
@@ -9639,11 +9692,6 @@ node-version@^1.0.0:
resolved "https://registry.yarnpkg.com/node-version/-/node-version-1.2.0.tgz#34fde3ffa8e1149bd323983479dda620e1b5060d"
integrity sha512-ma6oU4Sk0qOoKEAymVoTvk8EdXEobdS7m/mAGhDJ8Rouugho48crHBORAmy5BoOcv8wraPM6xumapQp5hl4iIQ==
-noop-logger@^0.1.1:
- version "0.1.1"
- resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
- integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=
-
normalize-package-data@^2.3.2, normalize-package-data@^2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.5.0.tgz#e66db1838b200c1dfc233225d12cb36520e234a8"
@@ -9680,16 +9728,6 @@ npm-run-path@^4.0.0:
dependencies:
path-key "^3.0.0"
-npmlog@^4.0.1:
- version "4.1.2"
- resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
- integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
- dependencies:
- are-we-there-yet "~1.1.2"
- console-control-strings "~1.1.0"
- gauge "~2.7.3"
- set-blocking "~2.0.0"
-
nth-check@^1.0.2, nth-check@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c"
@@ -9915,7 +9953,7 @@ opn@^5.4.0:
dependencies:
is-wsl "^1.1.0"
-optionator@^0.8.1, optionator@^0.8.2, optionator@^0.8.3:
+optionator@^0.8.1, optionator@^0.8.2:
version "0.8.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==
@@ -9927,6 +9965,18 @@ optionator@^0.8.1, optionator@^0.8.2, optionator@^0.8.3:
type-check "~0.3.2"
word-wrap "~1.2.3"
+optionator@^0.9.1:
+ version "0.9.1"
+ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
+ integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==
+ dependencies:
+ deep-is "^0.1.3"
+ fast-levenshtein "^2.0.6"
+ levn "^0.4.1"
+ prelude-ls "^1.2.1"
+ type-check "^0.4.0"
+ word-wrap "^1.2.3"
+
options@>=0.0.5:
version "0.0.6"
resolved "https://registry.yarnpkg.com/options/-/options-0.0.6.tgz#ec22d312806bb53e731773e7cdaefcf1c643128f"
@@ -10374,32 +10424,16 @@ posix-character-classes@^0.1.0:
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
-prebuild-install@^5.3.3:
- version "5.3.6"
- resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-5.3.6.tgz#7c225568d864c71d89d07f8796042733a3f54291"
- integrity sha512-s8Aai8++QQGi4sSbs/M1Qku62PFK49Jm1CbgXklGz4nmHveDq0wzJkg7Na5QbnO1uNH8K7iqx2EQ/mV0MZEmOg==
- dependencies:
- detect-libc "^1.0.3"
- expand-template "^2.0.3"
- github-from-package "0.0.0"
- minimist "^1.2.3"
- mkdirp-classic "^0.5.3"
- napi-build-utils "^1.0.1"
- node-abi "^2.7.0"
- noop-logger "^0.1.1"
- npmlog "^4.0.1"
- pump "^3.0.0"
- rc "^1.2.7"
- simple-get "^3.0.3"
- tar-fs "^2.0.0"
- tunnel-agent "^0.6.0"
- which-pm-runs "^1.0.0"
-
precond@0.2:
version "0.2.3"
resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac"
integrity sha1-qpWRvKokkj8eD0hJ0kD0fvwQdaw=
+prelude-ls@^1.2.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
+ integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==
+
prelude-ls@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
@@ -10685,10 +10719,10 @@ querystring@0.2.0:
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=
-querystringify@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e"
- integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA==
+querystringify@^2.1.1:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
+ integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
r2@^2.0.1:
version "2.0.1"
@@ -10748,16 +10782,6 @@ raw-body@^2.2.0:
iconv-lite "0.4.24"
unpipe "1.0.0"
-rc@^1.2.7:
- version "1.2.8"
- resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
- integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
- dependencies:
- deep-extend "^0.6.0"
- ini "~1.3.0"
- minimist "^1.2.0"
- strip-json-comments "~2.0.1"
-
react-clone-referenced-element@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/react-clone-referenced-element/-/react-clone-referenced-element-1.1.0.tgz#9cdda7f2aeb54fea791f3ab8c6ab96c7a77d0158"
@@ -10888,10 +10912,10 @@ react-native-crypto@2.1.2:
pbkdf2 "3.0.8"
public-encrypt "^4.0.0"
-react-native-device-info@3.1.4:
- version "3.1.4"
- resolved "https://registry.yarnpkg.com/react-native-device-info/-/react-native-device-info-3.1.4.tgz#58a1d465ce9e2c28809132b1c68dd7ec7ce5f00f"
- integrity sha512-r+7APHkPO9EA/9w3e9K7yrFigaU+0/g8i3psrNUwCGFxoDewkCHOPj/1YZnAPUwPxgyG3svjZXeCtymI3xcSlA==
+react-native-device-info@^8.1.3:
+ version "8.1.3"
+ resolved "https://registry.yarnpkg.com/react-native-device-info/-/react-native-device-info-8.1.3.tgz#022fc01372632bf80c0a6d201aab53344efc715f"
+ integrity sha512-73e3wiGFL8DvIXEd8x4Aq+mO8mZvHARwfYorIEu+X0trLHY92bP5Ict8DJHDjCQ0+HtAvpA4Wda2VoUVN1zh6Q==
react-native-elevated-view@0.0.6:
version "0.0.6"
@@ -11131,6 +11155,13 @@ react-native-tcp@aprock/react-native-tcp#11/head:
process "^0.11.9"
util "^0.12.1"
+react-native-url-polyfill@^1.3.0:
+ version "1.3.0"
+ resolved "https://registry.yarnpkg.com/react-native-url-polyfill/-/react-native-url-polyfill-1.3.0.tgz#c1763de0f2a8c22cc3e959b654c8790622b6ef6a"
+ integrity sha512-w9JfSkvpqqlix9UjDvJjm1EjSt652zVQ6iwCIj1cVVkwXf4jQhQgTNXY6EVTwuAmUjg6BC6k9RHCBynoLFo3IQ==
+ dependencies:
+ whatwg-url-without-unicode "8.0.0-3"
+
react-native-v8@^0.62.2-patch.1:
version "0.62.2-patch.1"
resolved "https://registry.yarnpkg.com/react-native-v8/-/react-native-v8-0.62.2-patch.1.tgz#016a932ed5e60f6bca6803fbdf6c746fe1b55bf5"
@@ -11147,6 +11178,22 @@ react-native-vector-icons@6.4.2:
prop-types "^15.6.2"
yargs "^13.2.2"
+react-native-video-controls@^2.7.1:
+ version "2.7.1"
+ resolved "https://registry.yarnpkg.com/react-native-video-controls/-/react-native-video-controls-2.7.1.tgz#52bd22ea83a964c9bf1e741e7ed6380ad0e28f1e"
+ integrity sha512-yoquLUx2x7EJOnDNGw0H4bb0gO4Io+ziFSDoDGGJqaT15IaXIiD+GCvCDbW9gLcUxsyLDwCr65sx8Yt2ZMvbCg==
+ dependencies:
+ lodash "^4.16.4"
+
+react-native-video@^5.1.1:
+ version "5.1.1"
+ resolved "https://registry.yarnpkg.com/react-native-video/-/react-native-video-5.1.1.tgz#89a7989efeb8d404611c06154d1da227a745d7d8"
+ integrity sha512-zee8gRUrjPWRoZSEBiMebClqu1iAuCQNLjzqpmXFrRWEoJj7azM3BPqLQWJgsnfLiYUYGySeApC/G60THM5+tw==
+ dependencies:
+ keymirror "^0.1.1"
+ prop-types "^15.7.2"
+ shaka-player "^2.5.9"
+
react-native-view-shot@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/react-native-view-shot/-/react-native-view-shot-3.1.2.tgz#8c8e84c67a4bc8b603e697dbbd59dbc9b4f84825"
@@ -11346,7 +11393,7 @@ readable-stream@1.1.x, readable-stream@^1.0.26-4, readable-stream@^1.0.27-1, rea
isarray "0.0.1"
string_decoder "~0.10.x"
-readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@~2.3.6:
+readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.2.2, readable-stream@^2.2.9, 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==
@@ -11359,7 +11406,7 @@ readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stre
string_decoder "~1.1.1"
util-deprecate "~1.0.1"
-"readable-stream@2 || 3", readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
+"readable-stream@2 || 3", readable-stream@^3.1.1, readable-stream@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
@@ -11471,7 +11518,7 @@ regexpp@^2.0.1:
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f"
integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==
-regexpp@^3.0.0:
+regexpp@^3.0.0, regexpp@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2"
integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q==
@@ -11579,6 +11626,11 @@ require-directory@^2.1.1:
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I=
+require-from-string@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
+ integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+
require-main-filename@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1"
@@ -11683,7 +11735,7 @@ rimraf@2.x.x, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.3:
dependencies:
glob "^7.1.3"
-rimraf@^3.0.0:
+rimraf@^3.0.0, rimraf@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==
@@ -11760,7 +11812,7 @@ rsvp@^4.8.4:
resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734"
integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA==
-run-async@^2.2.0, run-async@^2.4.0:
+run-async@^2.2.0:
version "2.4.1"
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
@@ -11806,13 +11858,6 @@ rxjs@^5.4.3:
dependencies:
symbol-observable "1.0.1"
-rxjs@^6.6.0:
- version "6.6.3"
- resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.3.tgz#8ca84635c4daa900c0d3967a6ee7ac60271ee552"
- integrity sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==
- dependencies:
- tslib "^1.9.0"
-
rxjs@^6.6.6:
version "6.6.6"
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.6.tgz#14d8417aa5a07c5e633995b525e1e3c0dec03b70"
@@ -11847,11 +11892,6 @@ safe-json-utils@1.0.0:
resolved "https://registry.yarnpkg.com/safe-json-utils/-/safe-json-utils-1.0.0.tgz#8b1d68b13cff2ac6a5b68e6c9651cf7f8bb56d9b"
integrity sha512-n0hJm6BgX8wk3G+AS8MOQnfcA8dfE6ZMUfwkHUNx69YxPlU3HDaZTHXWto35Z+C4mOjK1odlT95WutkGC+0Idw==
-safe-json-utils@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/safe-json-utils/-/safe-json-utils-1.1.1.tgz#0e883874467d95ab914c3f511096b89bfb3e63b1"
- integrity sha512-SAJWGKDs50tAbiDXLf89PDwt9XYkWyANFWVzn4dTXl5QyI8t2o/bW5/OJl3lvc2WVU4MEpTo9Yz5NVFNsp+OJQ==
-
safe-regex@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e"
@@ -11985,11 +12025,18 @@ semver@^4.3.2, semver@~2.3.1:
resolved "https://registry.yarnpkg.com/semver/-/semver-4.3.6.tgz#300bc6e0e86374f7ba61068b5b1ecd57fc6532da"
integrity sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=
-semver@^6.0.0, semver@^6.1.2, semver@^6.3.0:
+semver@^6.0.0, semver@^6.3.0:
version "6.3.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
+semver@^7.2.1:
+ version "7.3.5"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.5.tgz#0b621c879348d8998e4b0e4be94b3f12e6018ef7"
+ integrity sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==
+ dependencies:
+ lru-cache "^6.0.0"
+
semver@^7.3.2:
version "7.3.4"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97"
@@ -12036,7 +12083,7 @@ serve-static@^1.13.1:
parseurl "~1.3.3"
send "0.17.1"
-set-blocking@^2.0.0, set-blocking@~2.0.0:
+set-blocking@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
@@ -12081,6 +12128,13 @@ sha3@^1.2.2:
dependencies:
nan "2.13.2"
+shaka-player@^2.5.9:
+ version "2.5.22"
+ resolved "https://registry.yarnpkg.com/shaka-player/-/shaka-player-2.5.22.tgz#64b4547b742b2a3a022be9fbe0686d944f9d0300"
+ integrity sha512-PAoeNLUQ/hT/9dY7QvNFgIiDtXSqbYVFuXXtLHh7ytVVqTvI/p4HLwfYShiR+sE/sbsDOr9D5l9D/ztLPhxgtw==
+ dependencies:
+ eme-encryption-scheme-polyfill "^2.0.1"
+
shebang-command@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
@@ -12115,18 +12169,11 @@ shell-quote@1.6.1:
array-reduce "~0.0.0"
jsonify "~0.0.0"
-shell-quote@^1.6.1:
+shell-quote@^1.6.1, shell-quote@^1.7.2:
version "1.7.2"
resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2"
integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg==
-shell-utils@^1.0.9:
- version "1.0.10"
- resolved "https://registry.yarnpkg.com/shell-utils/-/shell-utils-1.0.10.tgz#7fe7b8084f5d6d21323d941267013bc38aed063e"
- integrity sha512-p1xuqhj3jgcXiV8wGoF1eL/NOvapN9tyGDoObqKwvZTUZn7fIzK75swLTEHfGa7sObeN9vxFplHw/zgYUYRTsg==
- dependencies:
- lodash "4.x.x"
-
shellwords@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
@@ -12145,20 +12192,6 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
-simple-concat@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f"
- integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==
-
-simple-get@^3.0.3:
- version "3.1.0"
- resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3"
- integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==
- dependencies:
- decompress-response "^4.2.0"
- once "^1.3.1"
- simple-concat "^1.0.0"
-
simple-plist@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/simple-plist/-/simple-plist-1.1.0.tgz#8354ab63eb3922a054c78ce96c209c532e907a23"
@@ -12483,7 +12516,7 @@ string-width@^1.0.1:
is-fullwidth-code-point "^1.0.0"
strip-ansi "^3.0.0"
-"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
+string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
@@ -12647,12 +12680,12 @@ strip-hex-prefix@1.0.0:
dependencies:
is-hex-prefixed "1.0.0"
-strip-json-comments@^2.0.1, strip-json-comments@~2.0.1:
+strip-json-comments@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
-strip-json-comments@^3.0.1:
+strip-json-comments@^3.1.0, strip-json-comments@^3.1.1:
version "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==
@@ -12745,44 +12778,23 @@ table@^5.2.3:
slice-ansi "^2.1.0"
string-width "^3.0.0"
+table@^6.0.4:
+ version "6.4.0"
+ resolved "https://registry.yarnpkg.com/table/-/table-6.4.0.tgz#9501324358c313162cf52b2843a8b221e75fbefc"
+ integrity sha512-/Vfr23BDjJT2kfsCmYtnJqEPdD/8Dh/MDIQxfcbe+09lZUel6gluquwdMTrLERBw623Nv34DLGZ11krWn5AAqw==
+ dependencies:
+ ajv "^8.0.1"
+ lodash.clonedeep "^4.5.0"
+ lodash.flatten "^4.4.0"
+ lodash.truncate "^4.4.2"
+ slice-ansi "^4.0.0"
+ string-width "^4.2.0"
+
tail@^2.0.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/tail/-/tail-2.0.3.tgz#37567adc4624a70b35f1d146c3376fa3d6ef7c04"
integrity sha512-s9NOGkLqqiDEtBttQZI7acLS8ycYK5sTlDwNjGnpXG9c8AWj0cfAtwEIzo/hVRMMiC5EYz+bXaJWC1u1u0GPpQ==
-tar-fs@^2.0.0:
- version "2.1.1"
- resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784"
- integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==
- dependencies:
- chownr "^1.1.1"
- mkdirp-classic "^0.5.2"
- pump "^3.0.0"
- tar-stream "^2.1.4"
-
-tar-stream@^2.1.4:
- version "2.2.0"
- resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
- integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
- dependencies:
- bl "^4.0.3"
- end-of-stream "^1.4.1"
- fs-constants "^1.0.0"
- inherits "^2.0.3"
- readable-stream "^3.1.1"
-
-tar@^6.0.5:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.0.tgz#d1724e9bcc04b977b18d5c573b333a2207229a83"
- integrity sha512-DUCttfhsnLCjwoDoFcI+B2iJgYa93vBnDUATYEeRx6sntCTdN01VnqsIuTlALXla/LWooNg0yEGeB+Y8WdFxGA==
- dependencies:
- chownr "^2.0.0"
- fs-minipass "^2.0.0"
- minipass "^3.0.0"
- minizlib "^2.1.1"
- mkdirp "^1.0.3"
- yallist "^4.0.0"
-
telnet-client@1.2.8:
version "1.2.8"
resolved "https://registry.yarnpkg.com/telnet-client/-/telnet-client-1.2.8.tgz#946c0dadc8daa3f19bb40a3e898cb870403a4ca4"
@@ -12973,11 +12985,16 @@ tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
-tslib@^2.0.0, tslib@^2.1.0:
+tslib@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"
integrity sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==
+tslib@^2.1.0:
+ version "2.2.0"
+ resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.2.0.tgz#fb2c475977e35e241311ede2693cee1ec6698f5c"
+ integrity sha512-gS9GVHRU+RGn5KQM2rllAlR3dU6m7AcpJKdtH8gFvQiC4Otgk98XnmMU+nZenHt/+VhnBPWwgrJsyrdcw6i23w==
+
tsutils@^3.17.1:
version "3.17.1"
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
@@ -13007,6 +13024,13 @@ tweetnacl@^1.0.0:
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596"
integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==
+type-check@^0.4.0, type-check@~0.4.0:
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1"
+ integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==
+ dependencies:
+ prelude-ls "^1.2.1"
+
type-check@~0.3.2:
version "0.3.2"
resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72"
@@ -13024,6 +13048,11 @@ type-fest@^0.11.0:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1"
integrity sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==
+type-fest@^0.20.2:
+ version "0.20.2"
+ resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
+ integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==
+
type-fest@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.6.0.tgz#8d2a2370d3df886eb5c90ada1c5bf6188acf838b"
@@ -13051,10 +13080,10 @@ typedarray@^0.0.6:
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=
-ua-parser-js@^0.7.18:
- version "0.7.21"
- resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.21.tgz#853cf9ce93f642f67174273cc34565ae6f308777"
- integrity sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ==
+ua-parser-js@^0.7.18, ua-parser-js@^0.7.24:
+ version "0.7.28"
+ resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.28.tgz#8ba04e653f35ce210239c64661685bf9121dec31"
+ integrity sha512-6Gurc1n//gjp9eQNXjD9O3M/sMwVtN5S8Lv9bvOYBfKfDNiIIhqiyi01vMBO45u4zkDE420w/e0se7Vs+sIg+g==
uglify-es@^3.1.9:
version "3.3.9"
@@ -13079,6 +13108,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"
@@ -13142,12 +13176,12 @@ urix@^0.1.0:
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=
-url-parse@1.4.4:
- version "1.4.4"
- resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.4.tgz#cac1556e95faa0303691fec5cf9d5a1bc34648f8"
- integrity sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg==
+url-parse@1.5.0:
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.0.tgz#90aba6c902aeb2d80eac17b91131c27665d5d828"
+ integrity sha512-9iT6N4s93SMfzunOyDPe4vo4nLcSu1yq0IQK1gURmjm8tQNlM6loiuCRrKG1hHGXfB2EWd6H4cGi7tGdaygMFw==
dependencies:
- querystringify "^2.0.0"
+ querystringify "^2.1.1"
requires-port "^1.0.0"
url@0.11.0:
@@ -13396,6 +13430,11 @@ webidl-conversions@^4.0.2:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad"
integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==
+webidl-conversions@^5.0.0:
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
+ integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==
+
whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
@@ -13423,6 +13462,15 @@ whatwg-mimetype@^2.2.0, whatwg-mimetype@^2.3.0:
resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf"
integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==
+whatwg-url-without-unicode@8.0.0-3:
+ version "8.0.0-3"
+ resolved "https://registry.yarnpkg.com/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz#ab6df4bf6caaa6c85a59f6e82c026151d4bb376b"
+ integrity sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==
+ dependencies:
+ buffer "^5.4.3"
+ punycode "^2.1.1"
+ webidl-conversions "^5.0.0"
+
whatwg-url@^7.0.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06"
@@ -13458,11 +13506,6 @@ which-module@^2.0.0:
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
-which-pm-runs@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb"
- integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=
-
which-typed-array@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.2.tgz#e5f98e56bda93e3dac196b01d47c1156679c00b2"
@@ -13489,13 +13532,6 @@ which@^2.0.1, which@^2.0.2:
dependencies:
isexe "^2.0.0"
-wide-align@^1.1.0:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
- integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==
- dependencies:
- string-width "^1.0.2 || 2"
-
window-getters@1.0.0, window-getters@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/window-getters/-/window-getters-1.0.0.tgz#b5b264538c4c79cead027f9997850222bf6d0852"
@@ -13526,7 +13562,7 @@ winston@0.8.x:
pkginfo "0.3.x"
stack-trace "0.0.x"
-word-wrap@~1.2.3:
+word-wrap@^1.2.3, word-wrap@~1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c"
integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
@@ -13753,7 +13789,7 @@ xtend@~3.0.0:
resolved "https://registry.yarnpkg.com/xtend/-/xtend-3.0.0.tgz#5cce7407baf642cba7becda568111c493f59665a"
integrity sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=
-y18n@^3.2.0, "y18n@^3.2.1 || ^4.0.0", y18n@^3.2.2, y18n@^4.0.0:
+y18n@^3.2.0, "y18n@^3.2.1 || ^4.0.0", y18n@^3.2.2, y18n@^4.0.0, y18n@^5.0.5:
version "3.2.2"
resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696"
integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==
@@ -13786,7 +13822,7 @@ yargs-parser@^11.1.1:
camelcase "^5.0.0"
decamelize "^1.2.0"
-yargs-parser@^13.0.0, yargs-parser@^13.1.2:
+yargs-parser@^13.1.2:
version "13.1.2"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38"
integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==
@@ -13810,6 +13846,21 @@ yargs-parser@^18.1.1, yargs-parser@^18.1.2:
camelcase "^5.0.0"
decamelize "^1.2.0"
+yargs-parser@^20.2.2:
+ version "20.2.7"
+ resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.7.tgz#61df85c113edfb5a7a4e36eb8aa60ef423cbc90a"
+ integrity sha512-FiNkvbeHzB/syOjIUxFDCnhSfzAL8R5vs40MgLFBorXACCOAEaWu0gRZl14vG8MR9AOJIZbmkjhusqBYZ3HTHw==
+
+yargs-unparser@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb"
+ integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==
+ dependencies:
+ camelcase "^6.0.0"
+ decamelize "^4.0.0"
+ flat "^5.0.2"
+ is-plain-obj "^2.1.0"
+
yargs@^12.0.2:
version "12.0.5"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13"
@@ -13828,7 +13879,7 @@ yargs@^12.0.2:
y18n "^3.2.1 || ^4.0.0"
yargs-parser "^11.1.1"
-yargs@^13.0.0, yargs@^13.2.2, yargs@^13.2.4:
+yargs@^13.2.2, yargs@^13.2.4:
version "13.3.2"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd"
integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==
@@ -13895,6 +13946,19 @@ yargs@^15.3.1:
y18n "^4.0.0"
yargs-parser "^18.1.1"
+yargs@^16.0.3:
+ version "16.2.0"
+ resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"
+ integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==
+ dependencies:
+ cliui "^7.0.2"
+ escalade "^3.1.1"
+ get-caller-file "^2.0.5"
+ require-directory "^2.1.1"
+ string-width "^4.2.0"
+ y18n "^5.0.5"
+ yargs-parser "^20.2.2"
+
yargs@^3.30.0:
version "3.32.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-3.32.0.tgz#03088e9ebf9e756b69751611d2a5ef591482c995"
@@ -13911,4 +13975,4 @@ yargs@^3.30.0:
zxcvbn@4.4.2:
version "4.4.2"
resolved "https://registry.yarnpkg.com/zxcvbn/-/zxcvbn-4.4.2.tgz#28ec17cf09743edcab056ddd8b1b06262cc73c30"
- integrity sha1-KOwXzwl0PtyrBW3dixsGJizHPDA=
\ No newline at end of file
+ integrity sha1-KOwXzwl0PtyrBW3dixsGJizHPDA=