diff --git a/.gitmodules b/.gitmodules
index 5a0e571b021..a136390f3db 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,4 +4,4 @@
[submodule "ios/mixpanel-iphone"]
path = ios/mixpanel-iphone
- url = https://github.com/mixpanel/mixpanel-iphone
\ No newline at end of file
+ url = https://github.com/mixpanel/mixpanel-iphone
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d5bede07261..51ce8b266e3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,14 @@
## Current Main Branch
-## 6.0.1 - Feb 27, 2023
+## 6.1.2 - Mar 03, 2023
+- [#5925](https://github.com/MetaMask/metamask-mobile/pull/5925): [FIX] handle all ios biometric errors and create wallet
+- [#5906](https://github.com/MetaMask/metamask-mobile/pull/5906): [FIX] Add try-catch to recreateVault
+
+## 6.1.1 - Mar 01, 2023
+- [#5848](https://github.com/MetaMask/metamask-mobile/pull/5848): [FIX] Remove default eth sign
+
+## 6.1.0 - Feb 27, 2023
- [#5851](https://github.com/MetaMask/metamask-mobile/pull/5851): [FIX] Fix search network crasher
- [#5809](https://github.com/MetaMask/metamask-mobile/pull/5809): [FIX] Resolve tab bar merge conflicts
- [#5461](https://github.com/MetaMask/metamask-mobile/pull/5461): [IMPROVEMENT] On-ramp: Refactor Payment Methods view to componentization
diff --git a/android/app/build.gradle b/android/app/build.gradle
index b040dbbeaf4..f50f8ed0c12 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -159,8 +159,8 @@ android {
applicationId "io.metamask"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
- versionCode 1078
- versionName "6.1.0"
+ versionCode 1082
+ versionName "6.1.2"
multiDexEnabled true
testBuildType System.getProperty('testBuildType', 'debug')
missingDimensionStrategy "minReactNative", "minReactNative46"
diff --git a/app/component-library/components-temp/Contracts/ContractBox/ContractBox.constants.ts b/app/component-library/components-temp/Contracts/ContractBox/ContractBox.constants.ts
index ca6692fe3bc..2aadf982816 100644
--- a/app/component-library/components-temp/Contracts/ContractBox/ContractBox.constants.ts
+++ b/app/component-library/components-temp/Contracts/ContractBox/ContractBox.constants.ts
@@ -4,7 +4,6 @@ import { ImageSourcePropType } from 'react-native';
const imageSource =
'https://assets.coingecko.com/coins/images/279/small/ethereum.png?1595348880';
-export const CONTRACT_ADDRESS = '0x2990079bcdEe240329a520d2444386FC119da21a';
export const CONTRACT_PET_NAME = 'DAI';
export const CONTRACT_BOX_TEST_ID = 'contract-box';
export const CONTRACT_LOCAL_IMAGE: ImageSourcePropType = {
@@ -22,3 +21,6 @@ export const CONTRACT_EXPORT_ADDRESS = () => {
export const CONTRACT_ON_PRESS = () => {
console.log('contract pressed');
};
+
+export const HAS_BLOCK_EXPLORER = true;
+export const TOKEN_SYMBOL = 'D';
diff --git a/app/component-library/components-temp/Contracts/ContractBox/ContractBox.stories.tsx b/app/component-library/components-temp/Contracts/ContractBox/ContractBox.stories.tsx
index 9a4ab1ae7e6..922b9ba7d07 100644
--- a/app/component-library/components-temp/Contracts/ContractBox/ContractBox.stories.tsx
+++ b/app/component-library/components-temp/Contracts/ContractBox/ContractBox.stories.tsx
@@ -2,34 +2,41 @@
import React from 'react';
import { storiesOf } from '@storybook/react-native';
+// External depencies
+import TEST_ADDRESS from '../../../../constants/address';
+
// Internal dependencies.
import ContractBox from './ContractBox';
import {
- CONTRACT_ADDRESS,
CONTRACT_PET_NAME,
CONTRACT_LOCAL_IMAGE,
CONTRACT_COPY_ADDRESS,
CONTRACT_EXPORT_ADDRESS,
CONTRACT_ON_PRESS,
+ HAS_BLOCK_EXPLORER,
+ TOKEN_SYMBOL,
} from './ContractBox.constants';
storiesOf('Component Library / Contract Box', module)
.add('Address Not Saved', () => (
))
.add('Saved Address', () => (
));
diff --git a/app/component-library/components-temp/Contracts/ContractBox/ContractBox.styles.ts b/app/component-library/components-temp/Contracts/ContractBox/ContractBox.styles.ts
index 49fa2cb8f58..46ff512773f 100644
--- a/app/component-library/components-temp/Contracts/ContractBox/ContractBox.styles.ts
+++ b/app/component-library/components-temp/Contracts/ContractBox/ContractBox.styles.ts
@@ -10,7 +10,6 @@ const styleSheet = StyleSheet.create({
container: {
flexDirection: 'row',
justifyContent: 'space-between',
- marginHorizontal: 10,
},
});
diff --git a/app/component-library/components-temp/Contracts/ContractBox/ContractBox.test.tsx b/app/component-library/components-temp/Contracts/ContractBox/ContractBox.test.tsx
index fc40d805ab1..d56e7750bed 100644
--- a/app/component-library/components-temp/Contracts/ContractBox/ContractBox.test.tsx
+++ b/app/component-library/components-temp/Contracts/ContractBox/ContractBox.test.tsx
@@ -1,10 +1,10 @@
import React from 'react';
import { shallow } from 'enzyme';
+import TEST_ADDRESS from '../../../../constants/address';
import { ContractBoxProps } from './ContractBox.types';
import ContractBox from './ContractBox';
import {
CONTRACT_BOX_TEST_ID,
- CONTRACT_ADDRESS,
CONTRACT_PET_NAME,
CONTRACT_LOCAL_IMAGE,
CONTRACT_COPY_ADDRESS,
@@ -16,7 +16,7 @@ describe('ContractBox', () => {
it('should render ContractBox', () => {
const wrapper = shallow(
(
@@ -23,6 +25,8 @@ const ContractBox = ({
onExportAddress={onExportAddress}
onCopyAddress={onCopyAddress}
onContractPress={onContractPress}
+ hasBlockExplorer={hasBlockExplorer}
+ tokenSymbol={tokenSymbol}
/>
diff --git a/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.styles.ts b/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.styles.ts
index 770c46727d8..8d164eb6a7a 100644
--- a/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.styles.ts
+++ b/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.styles.ts
@@ -18,9 +18,14 @@ const styleSheet = (params: { theme: Theme }) => {
flexDirection: 'row',
alignItems: 'center',
},
+ imageContainer: {
+ marginRight: 16,
+ },
+ icon: {
+ paddingHorizontal: 6,
+ },
iconContainer: {
flexDirection: 'row',
- width: 60,
alignItems: 'center',
justifyContent: 'space-between',
},
diff --git a/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.test.tsx b/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.test.tsx
index b38b5c5413b..c7fb7934b7f 100644
--- a/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.test.tsx
+++ b/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.test.tsx
@@ -1,8 +1,8 @@
import React from 'react';
import { shallow } from 'enzyme';
import ContractBoxBase from './ContractBoxBase';
+import TEST_ADDRESS from '../../../../constants/address';
import {
- CONTRACT_ADDRESS,
CONTRACT_PET_NAME,
CONTRACT_LOCAL_IMAGE,
} from '../ContractBox/ContractBox.constants';
@@ -14,7 +14,7 @@ describe('Component ContractBoxBase', () => {
beforeEach(() => {
props = {
- contractAddress: CONTRACT_ADDRESS,
+ contractAddress: TEST_ADDRESS,
contractPetName: CONTRACT_PET_NAME,
contractLocalImage: CONTRACT_LOCAL_IMAGE,
};
diff --git a/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.tsx b/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.tsx
index eb65133600b..d8de8944d70 100644
--- a/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.tsx
+++ b/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.tsx
@@ -12,6 +12,7 @@ import { formatAddress } from '../../../../util/address';
import Icon, { IconName, IconSize } from '../../../components/Icons/Icon';
import { useStyles } from '../../../hooks';
import Button, { ButtonVariants } from '../../../components/Buttons/Button';
+import Identicon from '../../../../components/UI/Identicon';
// Internal dependencies.
import { ContractBoxBaseProps, IconViewProps } from './ContractBoxBase.types';
@@ -30,24 +31,37 @@ const ContractBoxBase = ({
onCopyAddress,
onExportAddress,
onContractPress,
+ hasBlockExplorer,
+ tokenSymbol,
}: ContractBoxBaseProps) => {
const formattedAddress = formatAddress(contractAddress, 'short');
- const { styles } = useStyles(styleSheet, {});
+ const {
+ styles,
+ theme: { colors },
+ } = useStyles(styleSheet, {});
const IconView = ({ onPress, name, size, testID }: IconViewProps) => (
-
-
+
+
);
return (
-
+
+ {contractLocalImage ? (
+
+ ) : tokenSymbol ? (
+ {tokenSymbol}
+ ) : (
+
+ )}
+
{contractPetName ? (
@@ -60,11 +74,10 @@ const ContractBoxBase = ({
+ />
)}
@@ -75,12 +88,14 @@ const ContractBoxBase = ({
size={IconSize.Lg}
testID={COPY_ICON_TEST_ID}
/>
-
+ {hasBlockExplorer && (
+
+ )}
);
diff --git a/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.types.ts b/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.types.ts
index bc9214e05e0..9242659f155 100644
--- a/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.types.ts
+++ b/app/component-library/components-temp/Contracts/ContractBoxBase/ContractBoxBase.types.ts
@@ -4,7 +4,7 @@ import { IconName, IconSize } from '../../../components/Icons/Icon';
export interface ContractBoxBaseProps {
contractAddress: string;
contractPetName?: string;
- contractLocalImage: ImageSourcePropType;
+ contractLocalImage?: ImageSourcePropType;
/**
* function that copies the contract address to the clipboard
*/
@@ -17,6 +17,11 @@ export interface ContractBoxBaseProps {
* functions that called when the user clicks on the contract name
*/
onContractPress: () => void;
+ /**
+ * Boolean that determines if the contract has a block explorer
+ */
+ hasBlockExplorer?: boolean;
+ tokenSymbol?: string;
}
export interface IconViewProps {
diff --git a/app/component-library/components-temp/Contracts/ContractBoxBase/__snapshots__/ContractBoxBase.test.tsx.snap b/app/component-library/components-temp/Contracts/ContractBoxBase/__snapshots__/ContractBoxBase.test.tsx.snap
index 129be0be37e..54c91704a9f 100644
--- a/app/component-library/components-temp/Contracts/ContractBoxBase/__snapshots__/ContractBoxBase.test.tsx.snap
+++ b/app/component-library/components-temp/Contracts/ContractBoxBase/__snapshots__/ContractBoxBase.test.tsx.snap
@@ -19,15 +19,23 @@ exports[`Component ContractBoxBase should render correctly 1`] = `
}
}
>
-
+ >
+
+
@@ -61,11 +68,6 @@ exports[`Component ContractBoxBase should render correctly 1`] = `
size="24"
testID="copy-icon"
/>
-
`;
diff --git a/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx b/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx
index fd06f94ec97..e2412868b0c 100644
--- a/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx
+++ b/app/component-library/components-temp/CustomSpendCap/CustomSpendCap.tsx
@@ -151,7 +151,9 @@ const CustomSpendCap = ({
)
: strings(
'contract_allowance.custom_spend_cap.no_value_selected',
- { domain },
+ {
+ domain,
+ },
)}
}
diff --git a/app/components/UI/ApproveTransactionHeader/ApproveTransactionHeader.test.tsx b/app/components/UI/ApproveTransactionHeader/ApproveTransactionHeader.test.tsx
index 811b2ef9568..3df0c0afd10 100644
--- a/app/components/UI/ApproveTransactionHeader/ApproveTransactionHeader.test.tsx
+++ b/app/components/UI/ApproveTransactionHeader/ApproveTransactionHeader.test.tsx
@@ -43,7 +43,7 @@ describe('ApproveTransactionHeader', () => {
it('should render correctly', () => {
const wrapper = shallow(
-
+
,
);
expect(wrapper).toMatchSnapshot();
diff --git a/app/components/UI/ApproveTransactionHeader/ApproveTransactionHeader.tsx b/app/components/UI/ApproveTransactionHeader/ApproveTransactionHeader.tsx
index 027a6ddc6eb..2a5e70c4f9a 100644
--- a/app/components/UI/ApproveTransactionHeader/ApproveTransactionHeader.tsx
+++ b/app/components/UI/ApproveTransactionHeader/ApproveTransactionHeader.tsx
@@ -3,16 +3,19 @@ import { View } from 'react-native';
import { getHost } from '../../../util/browser';
import { useSelector } from 'react-redux';
-import networkList, { isMainnetByChainId } from '../../../util/networks';
+import {
+ getNetworkNameFromProvider,
+ getNetworkImageSource,
+} from '../../../util/networks';
import { renderShortAddress, renderAccountName } from '../../../util/address';
import { WALLET_CONNECT_ORIGIN } from '../../../util/walletconnect';
import { MM_SDK_REMOTE_ORIGIN } from '../../../core/SDKConnect';
import { renderFromWei, hexToBN } from '../../../util/number';
+import { toChecksumAddress } from 'ethereumjs-util';
import { getTicker } from '../../../util/transactions';
-import getImage from '../../../util/getImage';
-import { TEST_REMOTE_IMAGE_SOURCE } from '../../../component-library/components-temp/Accounts/AccountBalance/AccountBalance.constants';
import AccountBalance from '../../../component-library/components-temp/Accounts/AccountBalance';
+import TagUrl from '../../../component-library/components/Tags/TagUrl';
import { BadgeVariants } from '../../../component-library/components/Badges/Badge/Badge.types';
import { strings } from '../../../../locales/i18n';
@@ -23,17 +26,15 @@ import {
ORIGIN_DEEPLINK,
ORIGIN_QR_CODE,
} from './ApproveTransactionHeader.constants';
-import { getPermittedAccountsByHostname } from '../../../core/Permissions';
import {
AccountInfoI,
ApproveTransactionHeaderI,
OriginsI,
} from './ApproveTransactionHeader.types';
-import images from 'images/image-icons';
-import TagUrl from '../../../component-library/components/Tags/TagUrl';
+import { selectProviderConfig } from '../../../selectors/networkController';
const ApproveTransactionHeader = ({
- spenderAddress,
+ from,
origin,
url,
currentEnsName,
@@ -42,7 +43,6 @@ const ApproveTransactionHeader = ({
balance: 0,
currency: '',
accountName: '',
- networkName: '',
});
const [origins, setOrigins] = useState({
isOriginDeepLink: false,
@@ -62,24 +62,18 @@ const ApproveTransactionHeader = ({
state.engine.backgroundState.PreferencesController.identities,
);
- const permittedAccountsList = useSelector(
- (state: any) => state.engine.backgroundState.PermissionController,
- );
-
- const permittedAccountsByHostname = getPermittedAccountsByHostname(
- permittedAccountsList,
- origin,
- );
-
- const activeAddress: string = permittedAccountsByHostname[0];
-
const network = useSelector(
(state: any) =>
state.engine.backgroundState.NetworkController.providerConfig,
);
+ const activeAddress = toChecksumAddress(from);
+
+ const networkProvider = useSelector(selectProviderConfig);
+ const networkName = getNetworkNameFromProvider(networkProvider);
+
useEffect(() => {
- const { ticker, type } = network;
+ const { ticker } = network;
const weiBalance = activeAddress
? hexToBN(accounts[activeAddress].balance)
: 0;
@@ -96,13 +90,10 @@ const ApproveTransactionHeader = ({
const isOriginMMSDKRemoteConn = origin?.startsWith(MM_SDK_REMOTE_ORIGIN);
- const networkName = networkList[type as keyof typeof networkList].name;
-
setAccountInfo({
balance,
currency,
accountName,
- networkName,
});
setOrigins({
isOriginDeepLink,
@@ -111,21 +102,16 @@ const ApproveTransactionHeader = ({
});
}, [accounts, identities, origin, activeAddress, network]);
- const networkImage = useMemo(() => {
- const { chainId } = network;
- if (isMainnetByChainId(chainId)) return TEST_REMOTE_IMAGE_SOURCE;
- const networkImageName = getImage(chainId);
- if (networkImageName)
- return images[networkImageName as keyof typeof images];
-
- return null;
- }, [network]);
+ const networkImage = getNetworkImageSource({
+ networkType: networkProvider.type,
+ chainId: networkProvider.chainId,
+ });
const domainTitle = useMemo(() => {
const { isOriginDeepLink, isOriginWalletConnect, isOriginMMSDKRemoteConn } =
origins;
let title = '';
- if (isOriginDeepLink) title = renderShortAddress(spenderAddress);
+ if (isOriginDeepLink) title = renderShortAddress(from);
else if (isOriginWalletConnect)
title = getHost(origin.split(WALLET_CONNECT_ORIGIN)[1]);
else if (isOriginMMSDKRemoteConn) {
@@ -133,7 +119,7 @@ const ApproveTransactionHeader = ({
} else title = getHost(currentEnsName || url || origin);
return title;
- }, [currentEnsName, origin, origins, spenderAddress, url]);
+ }, [currentEnsName, origin, origins, from, url]);
const favIconUrl = useMemo(() => {
const { isOriginWalletConnect, isOriginMMSDKRemoteConn } = origins;
@@ -159,10 +145,10 @@ const ApproveTransactionHeader = ({
accountBalance={accountInfo.balance}
accountName={accountInfo.accountName}
accountBalanceLabel={strings('transaction.balance')}
- accountNetwork={network.nickname || accountInfo.networkName}
+ accountNetwork={networkName}
badgeProps={{
variant: BadgeVariants.Network,
- name: accountInfo.networkName,
+ name: networkName,
imageSource: networkImage,
}}
/>
diff --git a/app/components/UI/ApproveTransactionHeader/ApproveTransactionHeader.types.ts b/app/components/UI/ApproveTransactionHeader/ApproveTransactionHeader.types.ts
index 5f08534f4fb..0316759093d 100644
--- a/app/components/UI/ApproveTransactionHeader/ApproveTransactionHeader.types.ts
+++ b/app/components/UI/ApproveTransactionHeader/ApproveTransactionHeader.types.ts
@@ -1,15 +1,14 @@
export interface ApproveTransactionHeaderI {
- spenderAddress: string;
origin: string;
url: string;
currentEnsName?: string;
+ from: string;
}
export interface AccountInfoI {
balance: number;
currency: string;
accountName: string;
- networkName: string;
}
export interface OriginsI {
diff --git a/app/components/UI/ApproveTransactionHeader/__snapshots__/ApproveTransactionHeader.test.tsx.snap b/app/components/UI/ApproveTransactionHeader/__snapshots__/ApproveTransactionHeader.test.tsx.snap
index c95ca43e18b..a2a46b4108b 100644
--- a/app/components/UI/ApproveTransactionHeader/__snapshots__/ApproveTransactionHeader.test.tsx.snap
+++ b/app/components/UI/ApproveTransactionHeader/__snapshots__/ApproveTransactionHeader.test.tsx.snap
@@ -2,8 +2,8 @@
exports[`ApproveTransactionHeader should render correctly 1`] = `
`;
diff --git a/app/components/UI/ApproveTransactionReview/AddNickNameHeader/index.tsx b/app/components/UI/ApproveTransactionReview/AddNickNameHeader/index.tsx
index 33b3b4579cb..5671df5da8a 100644
--- a/app/components/UI/ApproveTransactionReview/AddNickNameHeader/index.tsx
+++ b/app/components/UI/ApproveTransactionReview/AddNickNameHeader/index.tsx
@@ -1,11 +1,11 @@
import React from 'react';
import { View } from 'react-native';
-import Text from '../../../Base/Text';
+import Text from '../../../../component-library/components/Texts/Text';
import { strings } from '../../../../../locales/i18n';
import AntDesignIcon from 'react-native-vector-icons/AntDesign';
interface HeaderProps {
- onUpdateContractNickname: () => void;
+ closeModal: () => void;
nicknameExists: boolean;
headerWrapperStyle?: any;
headerTextStyle?: any;
@@ -14,15 +14,16 @@ interface HeaderProps {
const Header = (props: HeaderProps) => {
const {
- onUpdateContractNickname,
+ closeModal,
nicknameExists,
headerWrapperStyle,
headerTextStyle,
iconStyle,
} = props;
+
return (
-
+
{nicknameExists
? strings('nickname.edit_nickname')
: strings('nickname.add_nickname')}
@@ -31,7 +32,7 @@ const Header = (props: HeaderProps) => {
name={'close'}
size={20}
style={iconStyle}
- onPress={() => onUpdateContractNickname()}
+ onPress={() => closeModal()}
/>
);
diff --git a/app/components/UI/ApproveTransactionReview/AddNickname/index.tsx b/app/components/UI/ApproveTransactionReview/AddNickname/index.tsx
index 123137cb53c..d58a7bf9801 100644
--- a/app/components/UI/ApproveTransactionReview/AddNickname/index.tsx
+++ b/app/components/UI/ApproveTransactionReview/AddNickname/index.tsx
@@ -1,13 +1,6 @@
-import React, { useState } from 'react';
-import {
- SafeAreaView,
- View,
- StyleSheet,
- TextInput,
- TouchableOpacity,
-} from 'react-native';
+import React, { useState, useEffect, useCallback } from 'react';
+import { SafeAreaView, View, TextInput, TouchableOpacity } from 'react-native';
import AntDesignIcon from 'react-native-vector-icons/AntDesign';
-import { fontStyles } from '../../../../styles/common';
import EthereumAddress from '../../EthereumAddress';
import Engine from '../../../../core/Engine';
import { MetaMetricsEvents } from '../../../../core/Analytics';
@@ -15,9 +8,8 @@ import { trackEvent } from '../../../../util/analyticsV2';
import { toChecksumAddress } from 'ethereumjs-util';
import { connect } from 'react-redux';
import StyledButton from '../../StyledButton';
-import Text from '../../../Base/Text';
+import Text from '../../../../component-library/components/Texts/Text';
import InfoModal from '../../Swaps/components/InfoModal';
-import { showSimpleNotification } from '../../../../actions/notification';
import Identicon from '../../../UI/Identicon';
import Feather from 'react-native-vector-icons/Feather';
import { strings } from '../../../../../locales/i18n';
@@ -27,121 +19,83 @@ import ClipboardManager from '../../../../core/ClipboardManager';
import Header from '../AddNickNameHeader';
import ShowBlockExplorer from '../ShowBlockExplorer';
import { useTheme } from '../../../../util/theme';
-
-const createStyles = (colors: any) =>
- StyleSheet.create({
- container: {
- flex: 1,
- backgroundColor: colors.background.default,
- },
- headerWrapper: {
- position: 'relative',
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'center',
- marginHorizontal: 15,
- marginVertical: 5,
- paddingVertical: 10,
- },
- icon: {
- position: 'absolute',
- right: 0,
- padding: 10,
- color: colors.icon.default,
- },
- headerText: {
- color: colors.text.default,
- textAlign: 'center',
- fontSize: 15,
- },
- addressWrapperPrimary: {
- flexDirection: 'row',
- alignItems: 'center',
- justifyContent: 'space-between',
- marginBottom: 10,
- },
- addressWrapper: {
- backgroundColor: colors.primary.muted,
- flexDirection: 'row',
- alignItems: 'center',
- borderRadius: 40,
- paddingVertical: 10,
- paddingHorizontal: 15,
- width: '90%',
- },
- address: {
- fontSize: 12,
- color: colors.text.default,
- letterSpacing: 0.8,
- marginLeft: 10,
- },
- label: {
- fontSize: 14,
- paddingVertical: 12,
- color: colors.text.default,
- },
- input: {
- ...fontStyles.normal,
- fontSize: 12,
- borderColor: colors.border.default,
- borderRadius: 5,
- borderWidth: 2,
- padding: 10,
- flexDirection: 'row',
- alignItems: 'center',
- color: colors.text.default,
- },
- bodyWrapper: {
- marginHorizontal: 20,
- marginBottom: 'auto',
- },
- updateButton: {
- marginHorizontal: 20,
- },
- addressIdenticon: {
- alignItems: 'center',
- marginVertical: 10,
- },
- actionIcon: {
- color: colors.primary.default,
- },
- });
-
-interface AddNicknameProps {
- onUpdateContractNickname: () => void;
- contractAddress: string;
- network: number;
- nicknameExists: boolean;
- nickname: string;
- addressBook: [];
- showModalAlert: (config: any) => void;
- networkState: any;
- type: string;
-}
+import createStyles from './styles';
+import { AddNicknameProps } from './types';
+import { validateAddressOrENS } from '../../../../util/address';
+import ErrorMessage from '../../../Views/SendFlow/ErrorMessage';
+import {
+ CONTACT_ALREADY_SAVED,
+ SYMBOL_ERROR,
+} from '../../../../constants/error';
+import {
+ selectChainId,
+ selectNetwork,
+ selectProviderType,
+ selectRpcTarget,
+} from '../../../../selectors/networkController';
const getAnalyticsParams = () => ({});
const AddNickname = (props: AddNicknameProps) => {
const {
- onUpdateContractNickname,
- contractAddress,
- nicknameExists,
- nickname,
+ closeModal,
+ address,
showModalAlert,
- networkState: {
- network,
- providerConfig: { type },
- },
+ addressNickname,
+ providerType,
+ providerChainId,
+ providerNetwork,
+ providerRpcTarget,
+ addressBook,
+ identities,
} = props;
- const [newNickname, setNewNickname] = useState(nickname);
+ const [newNickname, setNewNickname] = useState(addressNickname);
+ const [addressErr, setAddressErr] = useState(null);
+ const [addressHasError, setAddressHasError] = useState(false);
+ const [errContinue, setErrContinue] = useState(false);
const [isBlockExplorerVisible, setIsBlockExplorerVisible] = useState(false);
const [showFullAddress, setShowFullAddress] = useState(false);
+ const [shouldDisableButton, setShouldDisableButton] = useState(true);
const { colors, themeAppearance } = useTheme();
const styles = createStyles(colors);
- const copyContractAddress = async () => {
- await ClipboardManager.setString(contractAddress);
+ const chooseToContinue = () => {
+ setAddressHasError(true);
+ return setAddressHasError(!addressHasError);
+ };
+
+ const validateAddressOrENSFromInput = useCallback(async () => {
+ const { addressError, errorContinue } = await validateAddressOrENS({
+ toAccount: address,
+ providerNetwork,
+ addressBook,
+ identities,
+ providerChainId,
+ });
+
+ setAddressErr(addressError);
+ setErrContinue(errorContinue);
+ setAddressHasError(addressError);
+ }, [address, providerNetwork, addressBook, identities, providerChainId]);
+
+ useEffect(() => {
+ validateAddressOrENSFromInput();
+ }, [validateAddressOrENSFromInput]);
+
+ const shouldButtonBeDisabled = useCallback(() => {
+ if (!newNickname || addressHasError) {
+ return setShouldDisableButton(true);
+ }
+ return setShouldDisableButton(false);
+ }, [newNickname, addressHasError]);
+
+ useEffect(() => {
+ shouldButtonBeDisabled();
+ }, [shouldButtonBeDisabled]);
+
+ const copyAddress = async () => {
+ await ClipboardManager.setString(address);
showModalAlert({
isVisible: true,
autodismiss: 1500,
@@ -154,13 +108,13 @@ const AddNickname = (props: AddNicknameProps) => {
const saveTokenNickname = () => {
const { AddressBookController } = Engine.context as any;
- if (!newNickname || !contractAddress) return;
+ if (!newNickname || !address) return;
AddressBookController.set(
- toChecksumAddress(contractAddress),
+ toChecksumAddress(address),
newNickname,
- network,
+ providerNetwork,
);
- onUpdateContractNickname();
+ closeModal();
trackEvent(
MetaMetricsEvents.CONTRACT_ADDRESS_NICKNAME,
getAnalyticsParams(),
@@ -173,22 +127,41 @@ const AddNickname = (props: AddNicknameProps) => {
const toggleBlockExplorer = () => setIsBlockExplorerVisible(true);
+ const renderErrorMessage = (addressError: any) => {
+ let errorMessage = addressError;
+
+ if (addressError === CONTACT_ALREADY_SAVED) {
+ errorMessage = strings('address_book.address_already_saved');
+ }
+ if (addressError === SYMBOL_ERROR) {
+ errorMessage = `${
+ strings('transaction.tokenContractAddressWarning_1') +
+ strings('transaction.tokenContractAddressWarning_2') +
+ strings('transaction.tokenContractAddressWarning_3')
+ }`;
+ }
+
+ return errorMessage;
+ };
+
return (
{isBlockExplorerVisible ? (
) : (
<>
{
{showFullAddress && (
)}
-
+
{strings('nickname.address')}
@@ -237,14 +210,24 @@ const AddNickname = (props: AddNicknameProps) => {
numberOfLines={1}
style={styles.input}
value={newNickname}
+ editable={!addressHasError}
testID={'contract-name-input'}
keyboardAppearance={themeAppearance}
/>
+ {addressHasError && (
+
+
+
+ )}
@@ -259,14 +242,21 @@ const AddNickname = (props: AddNicknameProps) => {
};
const mapStateToProps = (state: any) => ({
+ providerType: selectProviderType(state),
+ providerRpcTarget: selectRpcTarget(state),
+ providerChainId: selectChainId(state),
+ providerNetwork: selectNetwork(state),
addressBook: state.engine.backgroundState.AddressBookController.addressBook,
- networkState: state.engine.backgroundState.NetworkController,
+ identities: state.engine.backgroundState.PreferencesController.identities,
});
const mapDispatchToProps = (dispatch: any) => ({
- showModalAlert: (config) => dispatch(showAlert(config)),
- showSimpleNotification: (notification: Notification) =>
- dispatch(showSimpleNotification(notification)),
+ showModalAlert: (config: {
+ isVisible: boolean;
+ autodismiss: number;
+ content: string;
+ data: { msg: string };
+ }) => dispatch(showAlert(config)),
});
export default connect(mapStateToProps, mapDispatchToProps)(AddNickname);
diff --git a/app/components/UI/ApproveTransactionReview/AddNickname/styles.ts b/app/components/UI/ApproveTransactionReview/AddNickname/styles.ts
new file mode 100644
index 00000000000..1db8f03dff3
--- /dev/null
+++ b/app/components/UI/ApproveTransactionReview/AddNickname/styles.ts
@@ -0,0 +1,86 @@
+import { StyleSheet } from 'react-native';
+import { fontStyles } from '../../../../styles/common';
+
+const createStyles = (colors: any) =>
+ StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: colors.background.default,
+ },
+ headerWrapper: {
+ position: 'relative',
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginHorizontal: 15,
+ marginVertical: 5,
+ paddingVertical: 10,
+ },
+ icon: {
+ position: 'absolute',
+ right: 0,
+ padding: 10,
+ color: colors.icon.default,
+ },
+ headerText: {
+ color: colors.text.default,
+ textAlign: 'center',
+ fontSize: 15,
+ },
+ addressWrapperPrimary: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ marginBottom: 10,
+ },
+ addressWrapper: {
+ backgroundColor: colors.primary.muted,
+ flexDirection: 'row',
+ alignItems: 'center',
+ borderRadius: 40,
+ paddingVertical: 10,
+ paddingHorizontal: 15,
+ width: '90%',
+ },
+ address: {
+ fontSize: 12,
+ color: colors.text.default,
+ letterSpacing: 0.8,
+ marginLeft: 10,
+ },
+ label: {
+ fontSize: 14,
+ paddingVertical: 12,
+ color: colors.text.default,
+ },
+ input: {
+ ...fontStyles.normal,
+ fontSize: 12,
+ borderColor: colors.border.default,
+ borderRadius: 5,
+ borderWidth: 2,
+ padding: 10,
+ flexDirection: 'row',
+ alignItems: 'center',
+ color: colors.text.default,
+ },
+ bodyWrapper: {
+ marginHorizontal: 20,
+ marginBottom: 'auto',
+ },
+ updateButton: {
+ marginHorizontal: 20,
+ },
+ addressIdenticon: {
+ alignItems: 'center',
+ marginVertical: 10,
+ },
+ actionIcon: {
+ color: colors.primary.default,
+ },
+ errorContinue: {
+ marginVertical: 16,
+ },
+ });
+
+export default createStyles;
diff --git a/app/components/UI/ApproveTransactionReview/AddNickname/types.ts b/app/components/UI/ApproveTransactionReview/AddNickname/types.ts
new file mode 100644
index 00000000000..3c25650d2ad
--- /dev/null
+++ b/app/components/UI/ApproveTransactionReview/AddNickname/types.ts
@@ -0,0 +1,20 @@
+export interface AddNicknameProps {
+ closeModal: () => void;
+ address: string;
+ addressNickname: string;
+ nicknameExists: boolean;
+ showModalAlert: (config: any) => void;
+ providerType: string;
+ providerChainId: string;
+ providerNetwork: number;
+ providerRpcTarget: string;
+ addressBook: {
+ [key: string]: {
+ address: string;
+ chainId: string;
+ memo: string;
+ name: string;
+ };
+ };
+ identities: any;
+}
diff --git a/app/components/UI/ApproveTransactionReview/ShowBlockExplorer/index.tsx b/app/components/UI/ApproveTransactionReview/ShowBlockExplorer/index.tsx
index 00da7ec2e02..fe653268da8 100644
--- a/app/components/UI/ApproveTransactionReview/ShowBlockExplorer/index.tsx
+++ b/app/components/UI/ApproveTransactionReview/ShowBlockExplorer/index.tsx
@@ -1,13 +1,17 @@
import React, { useState } from 'react';
-import { View, StyleSheet } from 'react-native';
+import { View, StyleSheet, SafeAreaView } from 'react-native';
import WebviewProgressBar from '../../../UI/WebviewProgressBar';
+import Text, {
+ TextVariant,
+} from '../../../../component-library/components/Texts/Text';
import {
getEtherscanAddressUrl,
getEtherscanBaseUrl,
} from '../../../../util/etherscan';
+import { findBlockExplorerForRpc } from '../../../../util/networks';
import { WebView } from 'react-native-webview';
-import Text from '../../../Base/Text';
import AntDesignIcon from 'react-native-vector-icons/AntDesign';
+import { RPC } from '../../../../constants/network';
const styles = StyleSheet.create({
progressBarWrapper: {
@@ -19,29 +23,48 @@ const styles = StyleSheet.create({
position: 'absolute',
zIndex: 999999,
},
+ container: {
+ height: '100%',
+ },
});
interface ShowBlockExplorerProps {
- contractAddress: string;
+ address: string;
type: string;
setIsBlockExplorerVisible: (isBlockExplorerVisible: boolean) => void;
headerWrapperStyle?: any;
headerTextStyle?: any;
iconStyle?: any;
+ providerRpcTarget: string;
+ frequentRpcList: any[];
}
const ShowBlockExplorer = (props: ShowBlockExplorerProps) => {
const {
type,
- contractAddress,
+ address,
setIsBlockExplorerVisible,
headerWrapperStyle,
headerTextStyle,
iconStyle,
+ providerRpcTarget,
+ frequentRpcList,
} = props;
- const [loading, setLoading] = useState(0);
- const url = getEtherscanAddressUrl(type, contractAddress);
- const etherscan_url = getEtherscanBaseUrl(type).replace('https://', '');
+
+ const [loading, setLoading] = useState(0);
+
+ const url =
+ type === RPC
+ ? `${findBlockExplorerForRpc(
+ providerRpcTarget,
+ frequentRpcList,
+ )}/address/${address}`
+ : getEtherscanAddressUrl(type, address);
+ const title =
+ type === RPC
+ ? new URL(findBlockExplorerForRpc(providerRpcTarget, frequentRpcList))
+ .hostname
+ : getEtherscanBaseUrl(type).replace('https://', '');
const onLoadProgress = ({
nativeEvent: { progress },
@@ -58,10 +81,10 @@ const ShowBlockExplorer = (props: ShowBlockExplorerProps) => {
);
return (
- <>
+
-
- {etherscan_url}
+
+ {title}
{
{renderProgressBar()}
- >
+
);
};
diff --git a/app/components/UI/ApproveTransactionReview/VerifyContractDetails/VerifyContractDetails.styles.ts b/app/components/UI/ApproveTransactionReview/VerifyContractDetails/VerifyContractDetails.styles.ts
new file mode 100644
index 00000000000..5dc77eb5a01
--- /dev/null
+++ b/app/components/UI/ApproveTransactionReview/VerifyContractDetails/VerifyContractDetails.styles.ts
@@ -0,0 +1,26 @@
+import { StyleSheet } from 'react-native';
+
+const createStyles = (colors: any) =>
+ StyleSheet.create({
+ container: {
+ paddingHorizontal: 16,
+ backgroundColor: colors.background,
+ },
+ description: {
+ marginVertical: 8,
+ },
+ text: {
+ color: colors.text.alternative,
+ },
+ contractSection: {
+ marginBottom: 8,
+ },
+ sectionContainer: {
+ marginVertical: 8,
+ },
+ title: {
+ marginVertical: 8,
+ },
+ });
+
+export default createStyles;
diff --git a/app/components/UI/ApproveTransactionReview/VerifyContractDetails/VerifyContractDetails.tsx b/app/components/UI/ApproveTransactionReview/VerifyContractDetails/VerifyContractDetails.tsx
new file mode 100644
index 00000000000..49dfbafa27c
--- /dev/null
+++ b/app/components/UI/ApproveTransactionReview/VerifyContractDetails/VerifyContractDetails.tsx
@@ -0,0 +1,139 @@
+import React, { useEffect, useMemo, useCallback } from 'react';
+import { View } from 'react-native';
+import Text, {
+ TextVariant,
+} from '../../../../component-library/components/Texts/Text';
+import { useSelector } from 'react-redux';
+import { strings } from '../../../../../locales/i18n';
+import { useAppThemeFromContext, mockTheme } from '../../../../util/theme';
+import ConnectHeader from '../../ConnectHeader';
+import ContractBox from '../../../../component-library/components-temp/Contracts/ContractBox';
+import createStyles from './VerifyContractDetails.styles';
+import { VerifyContractDetailsProps } from './VerifyContractDetails.types';
+import { findBlockExplorerForRpc } from '../../../../util/networks';
+import { RPC } from '../../../../constants/network';
+import TransactionTypes from '../../../../core/TransactionTypes';
+import { safeToChecksumAddress } from '../../../../util/address';
+import { Token as TokenType } from '@metamask/assets-controllers';
+
+const {
+ ASSET: { ERC20, ERC1155, ERC721 },
+} = TransactionTypes;
+
+const VerifyContractDetails = ({
+ contractAddress,
+ closeVerifyContractView,
+ copyAddress,
+ toggleBlockExplorer,
+ showNickname,
+ tokenAddress,
+ savedContactListToArray,
+ tokenSymbol,
+ providerType,
+ providerRpcTarget,
+ frequentRpcList,
+ tokenStandard,
+}: VerifyContractDetailsProps) => {
+ const [contractNickname, setContractNickname] = React.useState('');
+ const [tokenNickname, setTokenNickname] = React.useState('');
+ const { colors } = useAppThemeFromContext() || mockTheme;
+ const styles = createStyles(colors);
+
+ const tokens = useSelector(
+ (state: any) =>
+ state.engine.backgroundState.TokensController.tokens as TokenType[],
+ );
+
+ const tokenData = useMemo(
+ () =>
+ tokens.filter(
+ (token: any) => token.address === safeToChecksumAddress(tokenAddress),
+ ),
+ [tokens, tokenAddress],
+ );
+
+ const tokenSymbolFirstLetter = tokenSymbol?.charAt(0);
+
+ useEffect(() => {
+ savedContactListToArray.forEach((contact: any) => {
+ if (contact.address === safeToChecksumAddress(contractAddress)) {
+ setContractNickname(contact.name);
+ }
+ if (contact.address === safeToChecksumAddress(tokenAddress)) {
+ setTokenNickname(contact.name);
+ }
+ });
+ }, [contractAddress, tokenAddress, savedContactListToArray]);
+
+ const showBlockExplorerIcon = useCallback(() => {
+ if (providerType === RPC) {
+ return findBlockExplorerForRpc(providerRpcTarget, frequentRpcList);
+ }
+ return true;
+ }, [providerType, providerRpcTarget, frequentRpcList]);
+
+ const hasBlockExplorer = showBlockExplorerIcon();
+
+ return (
+
+
+
+
+ {strings('contract_allowance.token_allowance.protect_from_scams')}
+
+
+
+
+ {tokenStandard === ERC20
+ ? strings('contract_allowance.token_allowance.token_contract')
+ : tokenStandard === ERC721 || tokenStandard === ERC1155
+ ? strings('contract_allowance.token_allowance.nft_contract')
+ : strings('contract_allowance.token_allowance.address')}
+
+
+ copyAddress(tokenAddress)}
+ onExportAddress={() => toggleBlockExplorer(tokenAddress)}
+ contractLocalImage={
+ tokenData.length ? { uri: tokenData[0]?.image } : undefined
+ }
+ tokenSymbol={tokenSymbolFirstLetter && tokenSymbolFirstLetter}
+ hasBlockExplorer={Boolean(hasBlockExplorer)}
+ onContractPress={() => showNickname(tokenAddress)}
+ />
+
+
+ {strings(
+ 'contract_allowance.token_allowance.third_party_requesting_text',
+ {
+ action:
+ tokenStandard === ERC20
+ ? strings('contract_allowance.token_allowance.spending_cap')
+ : tokenStandard === ERC721 || tokenStandard === ERC1155
+ ? strings('contract_allowance.token_allowance.access')
+ : '',
+ },
+ )}
+
+
+ copyAddress(contractAddress)}
+ onExportAddress={() => toggleBlockExplorer(contractAddress)}
+ onContractPress={() => showNickname(contractAddress)}
+ hasBlockExplorer={Boolean(hasBlockExplorer)}
+ />
+
+
+
+ );
+};
+export default VerifyContractDetails;
diff --git a/app/components/UI/ApproveTransactionReview/VerifyContractDetails/VerifyContractDetails.types.ts b/app/components/UI/ApproveTransactionReview/VerifyContractDetails/VerifyContractDetails.types.ts
new file mode 100644
index 00000000000..470d5fd89bc
--- /dev/null
+++ b/app/components/UI/ApproveTransactionReview/VerifyContractDetails/VerifyContractDetails.types.ts
@@ -0,0 +1,26 @@
+export interface VerifyContractDetailsProps {
+ /**
+ * contract address
+ */
+ contractAddress: string;
+ closeVerifyContractView: () => void;
+ tokenAddress: string;
+ savedContactListToArray: any[];
+ /**
+ * copy contract address
+ */
+ copyAddress: (address: string) => void;
+ /**
+ * toggle block explorer view
+ */
+ toggleBlockExplorer: (address: string) => void;
+ /**
+ * toggle nickname view
+ */
+ showNickname: (address: string) => void;
+ tokenStandard: string;
+ tokenSymbol: string;
+ providerType: string;
+ providerRpcTarget: string;
+ frequentRpcList: any[];
+}
diff --git a/app/components/UI/ApproveTransactionReview/VerifyContractDetails/index.ts b/app/components/UI/ApproveTransactionReview/VerifyContractDetails/index.ts
new file mode 100644
index 00000000000..3f36e5c118e
--- /dev/null
+++ b/app/components/UI/ApproveTransactionReview/VerifyContractDetails/index.ts
@@ -0,0 +1,2 @@
+/* eslint-disable import/prefer-default-export */
+export { default as VerifyContractDetails } from './VerifyContractDetails';
diff --git a/app/components/UI/ApproveTransactionReview/index.js b/app/components/UI/ApproveTransactionReview/index.js
index 1bfe5461e4b..a94d9704282 100644
--- a/app/components/UI/ApproveTransactionReview/index.js
+++ b/app/components/UI/ApproveTransactionReview/index.js
@@ -17,7 +17,6 @@ import { getApproveNavbar } from '../../UI/Navbar';
import { getHost } from '../../../util/browser';
import {
safeToChecksumAddress,
- renderShortAddress,
getAddressAccountType,
getTokenDetails,
} from '../../../util/address';
@@ -25,7 +24,6 @@ import { strings } from '../../../../locales/i18n';
import { setTransactionObject } from '../../../actions/transaction';
import { hexToBN } from '@metamask/controller-utils';
import { fromTokenMinimalUnit } from '../../../util/number';
-import EthereumAddress from '../EthereumAddress';
import {
getTicker,
getNormalizedTxState,
@@ -36,8 +34,6 @@ import {
minimumTokenAllowance,
} from '../../../util/transactions';
import TransactionTypes from '../../../core/TransactionTypes';
-import Feather from 'react-native-vector-icons/Feather';
-import Identicon from '../../UI/Identicon';
import { showAlert } from '../../../actions/alert';
import { trackEvent, trackLegacyEvent } from '../../../util/analyticsV2';
import TransactionHeader from '../../UI/TransactionHeader';
@@ -54,6 +50,7 @@ import {
import EditPermission from './EditPermission';
import Logger from '../../../util/Logger';
import InfoModal from '../Swaps/components/InfoModal';
+import ButtonLink from '../../../component-library/components/Buttons/Button/variants/ButtonLink';
import { getTokenList } from '../../../reducers/tokens';
import TransactionReview from '../../UI/TransactionReview/TransactionReviewEIP1559Update';
import ClipboardManager from '../../../core/ClipboardManager';
@@ -70,12 +67,14 @@ import {
selectNetwork,
selectProviderType,
selectTicker,
+ selectRpcTarget,
} from '../../../selectors/networkController';
-import ButtonLink from '../../../component-library/components/Buttons/Button/variants/ButtonLink';
import Text, {
TextVariant,
} from '../../../component-library/components/Texts/Text';
import ApproveTransactionHeader from '../ApproveTransactionHeader';
+import VerifyContractDetails from './VerifyContractDetails/VerifyContractDetails';
+import ShowBlockExplorer from './ShowBlockExplorer';
const { ORIGIN_DEEPLINK, ORIGIN_QR_CODE } = AppConstants.DEEPLINKS;
const POLLING_INTERVAL_ESTIMATED_L1_FEE = 30000;
@@ -199,9 +198,9 @@ class ApproveTransactionReview extends PureComponent {
*/
setTransactionObject: PropTypes.func,
/**
- * Update contract nickname
+ * toggle nickname modal
*/
- onUpdateContractNickname: PropTypes.func,
+ toggleModal: PropTypes.func,
/**
* The saved nickname of the address
*/
@@ -229,6 +228,15 @@ class ApproveTransactionReview extends PureComponent {
*/
eip1559GasObject: PropTypes.object,
showBlockExplorer: PropTypes.func,
+ /**
+ * function to toggle the verify contract details modal
+ */
+ showVerifyContractDetails: PropTypes.func,
+ savedContactListToArray: PropTypes.array,
+ closeVerifyContractDetails: PropTypes.func,
+ shouldVerifyContractDetails: PropTypes.bool,
+ frequentRpcList: PropTypes.array,
+ providerRpcTarget: PropTypes.string,
};
state = {
@@ -248,6 +256,8 @@ class ApproveTransactionReview extends PureComponent {
gasTransactionObject: {},
multiLayerL1FeeTotal: '0x0',
fetchingUpdateDone: false,
+ showBlockExplorerModal: false,
+ address: '',
};
customSpendLimitInput = React.createRef();
@@ -477,9 +487,8 @@ class ApproveTransactionReview extends PureComponent {
this.setState({ spendLimitCustomValue: value });
};
- copyContractAddress = async () => {
- const { transaction } = this.props;
- await ClipboardManager.setString(transaction.to);
+ copyContractAddress = async (address) => {
+ await ClipboardManager.setString(address);
this.props.showAlert({
isVisible: true,
autodismiss: 1500,
@@ -618,11 +627,8 @@ class ApproveTransactionReview extends PureComponent {
return createStyles(colors);
};
- toggleDisplay = () => this.props.onUpdateContractNickname();
-
renderDetails = () => {
const {
- spenderAddress,
originalApproveAmount,
customSpendAmount,
token: { tokenStandard, tokenSymbol, tokenName, tokenValue },
@@ -633,7 +639,7 @@ class ApproveTransactionReview extends PureComponent {
primaryCurrency,
gasError,
activeTabUrl,
- transaction: { origin },
+ transaction: { origin, from },
network,
over,
gasEstimateType,
@@ -648,6 +654,7 @@ class ApproveTransactionReview extends PureComponent {
eip1559GasObject,
updateTransactionState,
showBlockExplorer,
+ showVerifyContractDetails,
} = this.props;
const styles = this.getStyles();
const isTestNetwork = isTestNet(network);
@@ -679,8 +686,8 @@ class ApproveTransactionReview extends PureComponent {
-
- {strings('nickname.contract')}:
-
-
- {this.props.nicknameExists ? (
-
- {this.props.nickname}
-
- ) : (
-
- )}
-
-
-
-
- {this.props.nicknameExists ? 'Edit' : 'Add'}{' '}
- {strings('nickname.nickname')}
-
+
{
+ const {
+ providerType,
+ providerRpcTarget,
+ savedContactListToArray,
+ toggleModal,
+ closeVerifyContractDetails,
+ frequentRpcList,
+ } = this.props;
+ const {
+ transaction: { to },
+ showBlockExplorerModal,
+ spenderAddress,
+ token: { tokenSymbol },
+ } = this.state;
+
+ const toggleBlockExplorerModal = (address) => {
+ closeVerifyContractDetails();
+ this.setState({
+ showBlockExplorerModal: !showBlockExplorerModal,
+ address,
+ });
+ };
+
+ const showNickname = (address) => {
+ toggleModal(address);
+ };
+
+ return (
+
+ );
+ };
+
+ renderBlockExplorerView = () => {
+ const {
+ providerType,
+ showVerifyContractDetails,
+ frequentRpcList,
+ providerRpcTarget,
+ } = this.props;
+ const { showBlockExplorerModal, address } = this.state;
+
+ const styles = this.getStyles();
+ const closeModal = () => {
+ showVerifyContractDetails();
+ this.setState({
+ showBlockExplorerModal: !showBlockExplorerModal,
+ });
+ };
+
+ return (
+
+ );
+ };
+
buyEth = () => {
const { navigation } = this.props;
/* this is kinda weird, we have to reject the transaction to collapse the modal */
@@ -961,12 +1024,18 @@ class ApproveTransactionReview extends PureComponent {
}
render = () => {
- const { viewDetails, editPermissionVisible } = this.state;
- const { isSigningQRObject } = this.props;
+ const { viewDetails, editPermissionVisible, showBlockExplorerModal } =
+ this.state;
+ const { isSigningQRObject, shouldVerifyContractDetails } = this.props;
+
return (
{viewDetails
? this.renderTransactionReview()
+ : shouldVerifyContractDetails
+ ? this.renderVerifyContractDetails()
+ : showBlockExplorerModal
+ ? this.renderBlockExplorerView()
: editPermissionVisible
? this.renderEditPermission()
: isSigningQRObject
@@ -980,12 +1049,18 @@ class ApproveTransactionReview extends PureComponent {
const mapStateToProps = (state) => ({
accounts: state.engine.backgroundState.AccountTrackerController.accounts,
ticker: selectTicker(state),
+ frequentRpcList:
+ state.engine.backgroundState.PreferencesController.frequentRpcList,
+ selectedAddress:
+ state.engine.backgroundState.PreferencesController.selectedAddress,
+ provider: state.engine.backgroundState.NetworkController.provider,
transaction: getNormalizedTxState(state),
accountsLength: Object.keys(
state.engine.backgroundState.AccountTrackerController.accounts || {},
).length,
tokensLength: state.engine.backgroundState.TokensController.tokens.length,
providerType: selectProviderType(state),
+ providerRpcTarget: selectRpcTarget(state),
primaryCurrency: state.settings.primaryCurrency,
activeTabUrl: getActiveTabUrl(state),
network: selectNetwork(state),
diff --git a/app/components/UI/ApproveTransactionReview/styles.ts b/app/components/UI/ApproveTransactionReview/styles.ts
index 085f17ed534..f500d94b3c4 100644
--- a/app/components/UI/ApproveTransactionReview/styles.ts
+++ b/app/components/UI/ApproveTransactionReview/styles.ts
@@ -115,11 +115,11 @@ const createStyles = (colors: any) =>
justifyContent: 'center',
marginVertical: 15,
},
- nickname: {
- ...fontStyles.normal,
+ verifyContractLink: {
textAlign: 'center',
color: colors.primary.default,
- marginBottom: 10,
+ paddingVertical: 16,
+ lineHeight: 22,
},
actionIcon: {
color: colors.primary.default,
@@ -127,6 +127,26 @@ const createStyles = (colors: any) =>
buttonColor: {
color: colors.primary.default,
},
+ headerWrapper: {
+ position: 'relative',
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ marginHorizontal: 15,
+ marginVertical: 5,
+ paddingVertical: 10,
+ },
+ icon: {
+ position: 'absolute',
+ right: 0,
+ padding: 10,
+ color: colors.icon.default,
+ },
+ headerText: {
+ color: colors.text.default,
+ textAlign: 'center',
+ fontSize: 15,
+ },
});
export default createStyles;
diff --git a/app/components/UI/ConnectHeader/index.js b/app/components/UI/ConnectHeader/index.js
index 1183df5d574..acd3af74261 100644
--- a/app/components/UI/ConnectHeader/index.js
+++ b/app/components/UI/ConnectHeader/index.js
@@ -1,8 +1,10 @@
import React, { Component } from 'react';
-import { View, StyleSheet, Text, TouchableOpacity } from 'react-native';
+import { View, StyleSheet, TouchableOpacity } from 'react-native';
import PropTypes from 'prop-types';
import IonicIcon from 'react-native-vector-icons/Ionicons';
-import { fontStyles } from '../../../styles/common';
+import Text, {
+ TextVariant,
+} from '../../../component-library/components/Texts/Text';
import { ThemeContext, mockTheme } from '../../../util/theme';
const createStyles = (colors) =>
@@ -13,9 +15,8 @@ const createStyles = (colors) =>
paddingBottom: 20,
},
title: {
- ...fontStyles.bold,
color: colors.text.default,
- fontSize: 14,
+ fontSize: 16,
textAlign: 'center',
paddingVertical: 12,
},
@@ -47,7 +48,9 @@ class ConnectHeader extends Component {
color={colors.text.default}
/>
- {title}
+
+ {title}
+
);
}
diff --git a/app/components/UI/FiatOnRampAggregator/Views/Checkout.tsx b/app/components/UI/FiatOnRampAggregator/Views/Checkout.tsx
index 883062dcc29..b442a8ba709 100644
--- a/app/components/UI/FiatOnRampAggregator/Views/Checkout.tsx
+++ b/app/components/UI/FiatOnRampAggregator/Views/Checkout.tsx
@@ -25,10 +25,7 @@ import {
} from '../../../../util/navigation/navUtils';
import { hexToBN } from '../../../../util/number';
import { protectWalletModalVisible } from '../../../../actions/user';
-import {
- processAggregatorOrder,
- aggregatorInitialFiatOrder,
-} from '../orderProcessor/aggregator';
+import { aggregatorOrderToFiatOrder } from '../orderProcessor/aggregator';
import { createCustomOrderIdData } from '../orderProcessor/customOrderId';
import { getNotificationDetails } from '..';
import NotificationManager from '../../../../core/NotificationManager';
@@ -185,12 +182,12 @@ const CheckoutWebView = () => {
const handleNavigationStateChange = async (navState: WebViewNavigation) => {
if (
!isRedirectionHandled &&
- navState?.url.startsWith(callbackBaseUrl) &&
+ navState.url.startsWith(callbackBaseUrl) &&
navState.loading === false
) {
setIsRedirectionHandled(true);
try {
- const parsedUrl = parseUrl(navState?.url);
+ const parsedUrl = parseUrl(navState.url);
if (Object.keys(parsedUrl.query).length === 0) {
// There was no query params in the URL to parse
// Most likely the user clicked the X in Wyre widget
@@ -199,14 +196,15 @@ const CheckoutWebView = () => {
return;
}
const orders = await SDK.orders();
- const orderId = await orders.getOrderIdFromCallback(
+ const order = await orders.getOrderFromCallback(
provider.id,
navState?.url,
+ selectedAddress,
);
- if (!orderId) {
+ if (!order) {
throw new Error(
- `Order ID could not be retrieved. Callback was ${navState?.url}`,
+ `Order could not be retrieved. Callback was ${navState?.url}`,
);
}
@@ -215,14 +213,7 @@ const CheckoutWebView = () => {
}
const transformedOrder = {
- ...(await processAggregatorOrder(
- aggregatorInitialFiatOrder({
- id: orderId,
- account: selectedAddress,
- network: selectedChainId,
- }),
- )),
- id: orderId,
+ ...aggregatorOrderToFiatOrder(order),
account: selectedAddress,
network: selectedChainId,
};
diff --git a/app/components/UI/FiatOnRampAggregator/Views/GetQuotes.tsx b/app/components/UI/FiatOnRampAggregator/Views/GetQuotes.tsx
index 75021257bdb..c976ddb7d4f 100644
--- a/app/components/UI/FiatOnRampAggregator/Views/GetQuotes.tsx
+++ b/app/components/UI/FiatOnRampAggregator/Views/GetQuotes.tsx
@@ -372,8 +372,8 @@ const GetQuotes = () => {
amountOut: acc.amountOut + (curr?.amountOut || 0),
totalFee,
totalGasFee: acc.totalGasFee + (curr?.networkFee || 0),
- totalProccessingFee:
- acc.totalProccessingFee + (curr?.providerFee || 0),
+ totalProcessingFee:
+ acc.totalProcessingFee + (curr?.providerFee || 0),
feeAmountRatio:
acc.feeAmountRatio + totalFee / (curr?.amountOut || 0),
};
@@ -382,7 +382,7 @@ const GetQuotes = () => {
amountOut: 0,
totalFee: 0,
totalGasFee: 0,
- totalProccessingFee: 0,
+ totalProcessingFee: 0,
feeAmountRatio: 0,
},
);
@@ -398,7 +398,7 @@ const GetQuotes = () => {
average_total_fee: totals.totalFee / quotesWithoutError.length,
average_gas_fee: totals.totalGasFee / quotesWithoutError.length,
average_processing_fee:
- totals.totalProccessingFee / quotesWithoutError.length,
+ totals.totalProcessingFee / quotesWithoutError.length,
provider_onramp_list: quotesWithoutError.map(
({ provider }) => provider.name,
),
diff --git a/app/components/UI/FiatOnRampAggregator/hooks/useInAppBrowser.ts b/app/components/UI/FiatOnRampAggregator/hooks/useInAppBrowser.ts
index 36f046195f4..2b0e7b04829 100644
--- a/app/components/UI/FiatOnRampAggregator/hooks/useInAppBrowser.ts
+++ b/app/components/UI/FiatOnRampAggregator/hooks/useInAppBrowser.ts
@@ -39,10 +39,9 @@ export default function useInAppBrowser() {
);
const handleSuccessfulOrder = useCallback(
- (order: Order, orderId: string) => {
+ (order: Order) => {
const transformedOrder: FiatOrder = {
...aggregatorOrderToFiatOrder(order),
- id: orderId,
account: selectedAddress,
network: selectedChainId,
};
@@ -56,7 +55,7 @@ export default function useInAppBrowser() {
// @ts-expect-error navigation prop mismatch
navigation.dangerouslyGetParent()?.pop();
NotificationManager.showSimpleNotification(
- getNotificationDetails(transformedOrder as any),
+ getNotificationDetails(transformedOrder),
);
trackEvent('ONRAMP_PURCHASE_SUBMITTED', {
provider_onramp: ((transformedOrder as FiatOrder)?.data as Order)
@@ -115,16 +114,8 @@ export default function useInAppBrowser() {
try {
dispatch(setLockTime(-1));
const result = await InAppBrowser.openAuth(url, deeplinkRedirectUrl);
- let orderId;
- let orders;
-
- if (result.type === 'success' && result.url) {
- orders = await SDK.orders();
- orderId = await orders.getOrderIdFromCallback(
- provider.id,
- result.url,
- );
- } else {
+
+ if (result.type !== 'success' || !result.url) {
trackEvent('ONRAMP_PURCHASE_CANCELLED', {
amount: amount as number,
chain_id_destination: selectedChainId,
@@ -137,11 +128,12 @@ export default function useInAppBrowser() {
return;
}
- if (!orderId) {
- return;
- }
-
- const order = await orders.getOrder(orderId, selectedAddress);
+ const orders = await SDK.orders();
+ const order = await orders.getOrderFromCallback(
+ provider.id,
+ result.url,
+ selectedAddress,
+ );
if (!order) return;
@@ -162,7 +154,7 @@ export default function useInAppBrowser() {
return;
}
- handleSuccessfulOrder(order, orderId);
+ handleSuccessfulOrder(order);
} catch (error) {
Logger.error(error as Error, {
message:
diff --git a/app/components/UI/FiatOnRampAggregator/orderProcessor/aggregator.test.ts b/app/components/UI/FiatOnRampAggregator/orderProcessor/aggregator.test.ts
index 524cf69e3ce..fcb25c3eff4 100644
--- a/app/components/UI/FiatOnRampAggregator/orderProcessor/aggregator.test.ts
+++ b/app/components/UI/FiatOnRampAggregator/orderProcessor/aggregator.test.ts
@@ -1,36 +1,9 @@
import { Order } from '@consensys/on-ramp-sdk';
import {
- aggregatorInitialFiatOrder,
aggregatorOrderToFiatOrder,
processAggregatorOrder,
} from './aggregator';
-describe('aggregatorInitialFiatOrder', () => {
- it('should return an initial aggregator fiat order', () => {
- jest.spyOn(Date, 'now').mockImplementationOnce(() => 1233123123);
- expect(
- aggregatorInitialFiatOrder({
- id: 'test-id',
- account: '0x1235',
- network: '1',
- }),
- ).toEqual({
- id: 'test-id',
- account: '0x1235',
- network: '1',
- state: 'PENDING',
- provider: 'AGGREGATOR',
- createdAt: 1233123123,
- amount: null,
- fee: null,
- currency: '',
- cryptoAmount: null,
- cryptocurrency: '',
- data: null,
- });
- });
-});
-
describe('aggregatorOrderToFiatOrder', () => {
it('should return a fiat order', () => {
const mockOrder = {
diff --git a/app/components/UI/FiatOnRampAggregator/orderProcessor/aggregator.ts b/app/components/UI/FiatOnRampAggregator/orderProcessor/aggregator.ts
index 693ccbbd09a..324befe2336 100644
--- a/app/components/UI/FiatOnRampAggregator/orderProcessor/aggregator.ts
+++ b/app/components/UI/FiatOnRampAggregator/orderProcessor/aggregator.ts
@@ -38,21 +38,6 @@ interface InitialAggregatorOrder {
network: string;
}
-export const aggregatorInitialFiatOrder = (
- initialOrder: InitialAggregatorOrder,
-) => ({
- ...initialOrder,
- state: FIAT_ORDER_STATES.PENDING,
- provider: FIAT_ORDER_PROVIDERS.AGGREGATOR,
- createdAt: Date.now(),
- amount: null,
- fee: null,
- currency: '',
- cryptoAmount: null,
- cryptocurrency: '',
- data: null,
-});
-
export const aggregatorOrderToFiatOrder = (aggregatorOrder: Order) => ({
id: aggregatorOrder.id,
provider: FIAT_ORDER_PROVIDERS.AGGREGATOR,
diff --git a/app/components/UI/TransactionReview/TransactionReviewDetailsCard/index.js b/app/components/UI/TransactionReview/TransactionReviewDetailsCard/index.js
index a7f67b540ca..015f9451d51 100644
--- a/app/components/UI/TransactionReview/TransactionReviewDetailsCard/index.js
+++ b/app/components/UI/TransactionReview/TransactionReviewDetailsCard/index.js
@@ -10,6 +10,7 @@ import { ThemeContext, mockTheme } from '../../../../util/theme';
import ConnectHeader from '../../ConnectHeader';
import formatNumber from '../../../../util/formatNumber';
import TransactionTypes from '../../../../core/TransactionTypes';
+import { renderShortAddress } from '../../../../util/address';
const {
ASSET: { ERC20 },
@@ -150,14 +151,16 @@ export default class TransactionReviewDetailsCard extends Component {
{nickname}
) : (
- {address}
+
+ {renderShortAddress(address)}
+
)}
copyContractAddress(address)}
/>
diff --git a/app/components/UI/TransactionReview/index.js b/app/components/UI/TransactionReview/index.js
index 5f37f096d1d..177af30bea0 100644
--- a/app/components/UI/TransactionReview/index.js
+++ b/app/components/UI/TransactionReview/index.js
@@ -443,7 +443,7 @@ class TransactionReview extends PureComponent {
dappSuggestedGasWarning,
gasSelected,
chainId,
- transaction: { origin: transactionOrigin },
+ transaction: { origin, from, ensRecipient },
} = this.props;
const {
actionKey,
@@ -454,9 +454,7 @@ class TransactionReview extends PureComponent {
approveTransaction,
multiLayerL1FeeTotal,
} = this.state;
- const currentPageInformation = { url: this.getUrlFromBrowser() };
- const { currentEnsName, spenderAddress, origin, url } =
- currentPageInformation;
+ const url = this.getUrlFromBrowser();
const styles = this.getStyles();
return (
@@ -468,10 +466,10 @@ class TransactionReview extends PureComponent {
])}
>
{
@@ -189,8 +191,16 @@ class Approve extends PureComponent {
}
};
- onUpdateContractNickname = () => {
- this.setState({ addNickname: !this.state.addNickname });
+ showVerifyContractDetails = () =>
+ this.setState({ shouldVerifyContractDetails: true });
+ closeVerifyContractDetails = () =>
+ this.setState({ shouldVerifyContractDetails: false });
+
+ toggleModal = (val) => {
+ this.setState({
+ shouldAddNickname: !this.state.shouldAddNickname,
+ address: val,
+ });
};
startPolling = async () => {
@@ -539,6 +549,8 @@ class Approve extends PureComponent {
eip1559GasTransaction,
legacyGasObject,
gasError,
+ address,
+ shouldAddNickname,
} = this.state;
const {
@@ -569,12 +581,26 @@ class Approve extends PureComponent {
suggestedGasPrice: legacyGasObject?.suggestedGasPrice,
};
- const addressData = checkIfAddressIsSaved(
+ const savedContactList = checkIfAddressIsSaved(
addressBook,
network,
transaction,
);
+ const savedContactListToArray = Object.values(addressBook).flatMap(
+ (value) => Object.values(value),
+ );
+
+ let addressNickname = '';
+
+ const filteredSavedContactList = savedContactListToArray.filter(
+ (contact) => contact.address === safeToChecksumAddress(address),
+ );
+
+ if (filteredSavedContactList.length > 0) {
+ addressNickname = filteredSavedContactList[0].name;
+ }
+
if (!transaction.id) return null;
return (
- {this.state.addNickname ? (
+ {shouldAddNickname ? (
0
- ? addressData[0].nickname
- : ''
- }
+ closeModal={this.toggleModal}
+ address={address}
+ savedContactListToArray={savedContactListToArray}
+ addressNickname={addressNickname}
/>
) : this.state.isBlockExplorerVisible ? (
0
- ? addressData[0].nickname
+ savedContactList && savedContactList.length > 0
+ ? savedContactList[0].nickname
: ''
}
chainId={chainId}
diff --git a/app/components/Views/ChoosePassword/index.js b/app/components/Views/ChoosePassword/index.js
index a3a25d22a85..a364996385c 100644
--- a/app/components/Views/ChoosePassword/index.js
+++ b/app/components/Views/ChoosePassword/index.js
@@ -69,6 +69,7 @@ import {
import { LoginOptionsSwitch } from '../../UI/LoginOptionsSwitch';
import generateTestId from '../../../../wdio/utils/generateTestId';
import { scale } from 'react-native-size-matters';
+import SecureKeychain from '../../../core/SecureKeychain';
const createStyles = (colors) =>
StyleSheet.create({
@@ -233,8 +234,6 @@ const createStyles = (colors) =>
});
const PASSCODE_NOT_SET_ERROR = 'Error: Passcode not set.';
-const IOS_REJECTED_BIOMETRICS_ERROR =
- 'Error: The user name or passphrase you entered is not correct.';
/**
* View where users can set their password for the first time
@@ -381,12 +380,7 @@ class ChoosePassword extends PureComponent {
try {
await Authentication.newWalletAndKeychain(password, authType);
} catch (error) {
- // retry faceID if the user cancels the
- if (
- Device.isIos &&
- error.toString() === IOS_REJECTED_BIOMETRICS_ERROR
- )
- await this.handleRejectedOsBiometricPrompt();
+ if (Device.isIos) await this.handleRejectedOsBiometricPrompt(error);
}
this.keyringControllerPasswordSet = true;
this.props.seedphraseNotBackedUp();
@@ -408,7 +402,11 @@ class ChoosePassword extends PureComponent {
});
});
} catch (error) {
- await this.recreateVault('');
+ try {
+ await this.recreateVault('');
+ } catch (e) {
+ Logger.error(e);
+ }
// Set state in app as it was with no password
await AsyncStorage.setItem(EXISTING_USER, TRUE);
await AsyncStorage.removeItem(SEED_PHRASE_HINTS);
@@ -437,23 +435,9 @@ class ChoosePassword extends PureComponent {
* This function handles the case when the user rejects the OS prompt for allowing use of biometrics.
* If this occurs we will create the wallet automatically with password as the login method
*/
- handleRejectedOsBiometricPrompt = async () => {
- const newAuthData = await Authentication.componentAuthenticationType(
- false,
- false,
- );
- try {
- await Authentication.newWalletAndKeychain(
- this.state.password,
- newAuthData,
- );
- } catch (err) {
- throw Error(strings('choose_password.disable_biometric_error'));
- }
- this.setState({
- biometryType: newAuthData.availableBiometryType,
- biometryChoice: false,
- });
+ handleRejectedOsBiometricPrompt = async (error) => {
+ this.updateBiometryChoice(false);
+ await SecureKeychain.resetGenericPassword();
};
/**
diff --git a/app/components/Views/Settings/AdvancedSettings/__snapshots__/index.test.tsx.snap b/app/components/Views/Settings/AdvancedSettings/__snapshots__/index.test.tsx.snap
index d4d2caf13a2..e15c11b5f4e 100644
--- a/app/components/Views/Settings/AdvancedSettings/__snapshots__/index.test.tsx.snap
+++ b/app/components/Views/Settings/AdvancedSettings/__snapshots__/index.test.tsx.snap
@@ -3,6 +3,7 @@
exports[`AdvancedSettings should render correctly 1`] = `
{
+ const { PreferencesController } = Engine.context;
+ PreferencesController.setDisabledRpcMethodPreference('eth_sign', enabled);
+ };
+
toggleTokenDetection = (detectionStatus) => {
const { PreferencesController } = Engine.context;
PreferencesController.setUseTokenDetection(detectionStatus);
@@ -337,6 +346,7 @@ class AdvancedSettings extends PureComponent {
setShowHexData,
setShowCustomNonce,
ipfsGateway,
+ enableEthSign,
} = this.props;
const { resetModalVisible, onlineIpfsGateways } = this.state;
const { styles, colors } = this.getStyles();
@@ -425,6 +435,27 @@ class AdvancedSettings extends PureComponent {
/>
+
+
+ {strings('app_settings.enable_eth_sign')}
+
+
+ {strings('app_settings.enable_eth_sign_desc')}
+
+
+
+
+
{strings('app_settings.show_custom_nonce')}
@@ -475,6 +506,9 @@ const mapStateToProps = (state) => ({
ipfsGateway: state.engine.backgroundState.PreferencesController.ipfsGateway,
showHexData: state.settings.showHexData,
showCustomNonce: state.settings.showCustomNonce,
+ enableEthSign:
+ state.engine.backgroundState.PreferencesController
+ .disabledRpcMethodPreferences.eth_sign,
fullState: state,
isTokenDetectionEnabled:
state.engine.backgroundState.PreferencesController.useTokenDetection,
diff --git a/app/components/Views/Settings/AdvancedSettings/index.test.tsx b/app/components/Views/Settings/AdvancedSettings/index.test.tsx
index de88182310b..01561ecff13 100644
--- a/app/components/Views/Settings/AdvancedSettings/index.test.tsx
+++ b/app/components/Views/Settings/AdvancedSettings/index.test.tsx
@@ -11,6 +11,9 @@ const initialState = {
backgroundState: {
PreferencesController: {
ipfsGateway: 'https://ipfs.io/ipfs/',
+ disabledRpcMethodPreferences: {
+ eth_sign: false,
+ },
},
NetworkController: {
providerConfig: { chainId: '1' },
diff --git a/app/constants/address.ts b/app/constants/address.ts
new file mode 100644
index 00000000000..40570fb80ae
--- /dev/null
+++ b/app/constants/address.ts
@@ -0,0 +1,3 @@
+const TEST_ADDRESS = '0x2990079bcdEe240329a520d2444386FC119da21a';
+
+export default TEST_ADDRESS;
diff --git a/app/core/RPCMethods/RPCMethodMiddleware.ts b/app/core/RPCMethods/RPCMethodMiddleware.ts
index cfbf6b669b8..7d6999921cb 100644
--- a/app/core/RPCMethods/RPCMethodMiddleware.ts
+++ b/app/core/RPCMethods/RPCMethodMiddleware.ts
@@ -346,7 +346,15 @@ export const getRpcMethodMiddleware = ({
throw ethErrors.rpc.methodNotSupported();
},
eth_sign: async () => {
- const { MessageManager } = Engine.context;
+ const { MessageManager, PreferencesController } = Engine.context;
+ const { disabledRpcMethodPreferences } = PreferencesController.state;
+ const { eth_sign } = disabledRpcMethodPreferences;
+
+ if (!eth_sign) {
+ throw ethErrors.rpc.methodNotFound(
+ 'eth_sign has been disabled. You must enable it in the advanced settings',
+ );
+ }
const pageMeta = {
meta: {
url: url.current,
diff --git a/app/images/static-logos.js b/app/images/static-logos.js
index 06aed57842b..7c7b044a04e 100644
--- a/app/images/static-logos.js
+++ b/app/images/static-logos.js
@@ -2,6 +2,11 @@
/* eslint-disable */
export default {
+ 'OFE.svg': require('metamask/node_modules/@metamask/contract-metadata/images/OFE.svg'),
+ 'MOA.svg': require('metamask/node_modules/@metamask/contract-metadata/images/MOA.svg'),
+ 'PREMA.svg': require('metamask/node_modules/@metamask/contract-metadata/images/PREMA.svg'),
+ 'energi.svg': require('metamask/node_modules/@metamask/contract-metadata/images/energi.svg'),
+ 'aventus.svg': require('metamask/node_modules/@metamask/contract-metadata/images/aventus.svg'),
'STAT.svg': require('metamask/node_modules/@metamask/contract-metadata/images/STAT.svg'),
'GPO.svg': require('metamask/node_modules/@metamask/contract-metadata/images/GPO.svg'),
'NEAR.svg': require('metamask/node_modules/@metamask/contract-metadata/images/NEAR.svg'),
@@ -63,6 +68,8 @@ export default {
'SLP.svg': require('metamask/node_modules/@metamask/contract-metadata/images/SLP.svg'),
'dvision.svg': require('metamask/node_modules/@metamask/contract-metadata/images/dvision.svg'),
'vEth2.svg': require('metamask/node_modules/@metamask/contract-metadata/images/vEth2.svg'),
+ 'ctx.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ctx.svg'),
+ 'tcap.svg': require('metamask/node_modules/@metamask/contract-metadata/images/tcap.svg'),
'halodao-rnbw.svg': require('metamask/node_modules/@metamask/contract-metadata/images/halodao-rnbw.svg'),
'halodao-xrnbw.svg': require('metamask/node_modules/@metamask/contract-metadata/images/halodao-xrnbw.svg'),
'VAB.svg': require('metamask/node_modules/@metamask/contract-metadata/images/VAB.svg'),
@@ -128,6 +135,7 @@ export default {
'dlpducktoken.svg': require('metamask/node_modules/@metamask/contract-metadata/images/dlpducktoken.svg'),
'ddim.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ddim.svg'),
'MAHA.svg': require('metamask/node_modules/@metamask/contract-metadata/images/MAHA.svg'),
+ 'ARTH.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ARTH.svg'),
'EURe.svg': require('metamask/node_modules/@metamask/contract-metadata/images/EURe.svg'),
'GBPe.svg': require('metamask/node_modules/@metamask/contract-metadata/images/GBPe.svg'),
'USDe.svg': require('metamask/node_modules/@metamask/contract-metadata/images/USDe.svg'),
@@ -208,7 +216,7 @@ export default {
'Eristica.svg': require('metamask/node_modules/@metamask/contract-metadata/images/Eristica.svg'),
'usdt.svg': require('metamask/node_modules/@metamask/contract-metadata/images/usdt.svg'),
'CHAI.svg': require('metamask/node_modules/@metamask/contract-metadata/images/CHAI.svg'),
- 'UMA.png': require('metamask/node_modules/@metamask/contract-metadata/images/UMA.png'),
+ 'uma.svg': require('metamask/node_modules/@metamask/contract-metadata/images/uma.svg'),
'UPX.svg': require('metamask/node_modules/@metamask/contract-metadata/images/UPX.svg'),
'ETHBNT.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ETHBNT.svg'),
'enigma.svg': require('metamask/node_modules/@metamask/contract-metadata/images/enigma.svg'),
@@ -241,26 +249,21 @@ export default {
'herc.png': require('metamask/node_modules/@metamask/contract-metadata/images/herc.png'),
'FOAM.svg': require('metamask/node_modules/@metamask/contract-metadata/images/FOAM.svg'),
'Menlo_One.png': require('metamask/node_modules/@metamask/contract-metadata/images/Menlo_One.png'),
- 'spnd.png': require('metamask/node_modules/@metamask/contract-metadata/images/spnd.png'),
- 'AST.png': require('metamask/node_modules/@metamask/contract-metadata/images/AST.png'),
+ 'AirSwapLogo.svg': require('metamask/node_modules/@metamask/contract-metadata/images/AirSwapLogo.svg'),
'Rmesh.png': require('metamask/node_modules/@metamask/contract-metadata/images/Rmesh.png'),
'JOY.png': require('metamask/node_modules/@metamask/contract-metadata/images/JOY.png'),
'J8T.svg': require('metamask/node_modules/@metamask/contract-metadata/images/J8T.svg'),
'quant-network.svg': require('metamask/node_modules/@metamask/contract-metadata/images/quant-network.svg'),
'ink_protocol.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ink_protocol.svg'),
- 'Aion.png': require('metamask/node_modules/@metamask/contract-metadata/images/Aion.png'),
'ely.png': require('metamask/node_modules/@metamask/contract-metadata/images/ely.png'),
'polyswarm_nectar.svg': require('metamask/node_modules/@metamask/contract-metadata/images/polyswarm_nectar.svg'),
'box_token.png': require('metamask/node_modules/@metamask/contract-metadata/images/box_token.png'),
- 'dutyof.care-square.png': require('metamask/node_modules/@metamask/contract-metadata/images/dutyof.care-square.png'),
- 'rchain.png': require('metamask/node_modules/@metamask/contract-metadata/images/rchain.png'),
'DAOstack.png': require('metamask/node_modules/@metamask/contract-metadata/images/DAOstack.png'),
'dragonglass.svg': require('metamask/node_modules/@metamask/contract-metadata/images/dragonglass.svg'),
- 'omg.jpg': require('metamask/node_modules/@metamask/contract-metadata/images/omg.jpg'),
+ 'omg.svg': require('metamask/node_modules/@metamask/contract-metadata/images/omg.svg'),
'qsp.svg': require('metamask/node_modules/@metamask/contract-metadata/images/qsp.svg'),
- 'cln.png': require('metamask/node_modules/@metamask/contract-metadata/images/cln.png'),
- 'storj.jpg': require('metamask/node_modules/@metamask/contract-metadata/images/storj.jpg'),
- 'ZORA.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ZORA.svg'),
+ 'storj.svg': require('metamask/node_modules/@metamask/contract-metadata/images/storj.svg'),
+ 'zora.svg': require('metamask/node_modules/@metamask/contract-metadata/images/zora.svg'),
'VISR.svg': require('metamask/node_modules/@metamask/contract-metadata/images/VISR.svg'),
'mana.svg': require('metamask/node_modules/@metamask/contract-metadata/images/mana.svg'),
'XSC_Logo.svg': require('metamask/node_modules/@metamask/contract-metadata/images/XSC_Logo.svg'),
@@ -268,9 +271,8 @@ export default {
'hydro.svg': require('metamask/node_modules/@metamask/contract-metadata/images/hydro.svg'),
'playkey.svg': require('metamask/node_modules/@metamask/contract-metadata/images/playkey.svg'),
'zrx.svg': require('metamask/node_modules/@metamask/contract-metadata/images/zrx.svg'),
- 'redcab.png': require('metamask/node_modules/@metamask/contract-metadata/images/redcab.png'),
'modum.svg': require('metamask/node_modules/@metamask/contract-metadata/images/modum.svg'),
- 'appcoins.png': require('metamask/node_modules/@metamask/contract-metadata/images/appcoins.png'),
+ 'appc.svg': require('metamask/node_modules/@metamask/contract-metadata/images/appc.svg'),
'stasis-eurs.svg': require('metamask/node_modules/@metamask/contract-metadata/images/stasis-eurs.svg'),
'amlt.png': require('metamask/node_modules/@metamask/contract-metadata/images/amlt.png'),
'synthetix.svg': require('metamask/node_modules/@metamask/contract-metadata/images/synthetix.svg'),
@@ -280,13 +282,12 @@ export default {
'iqeon.svg': require('metamask/node_modules/@metamask/contract-metadata/images/iqeon.svg'),
'c10.svg': require('metamask/node_modules/@metamask/contract-metadata/images/c10.svg'),
//'c20.svg': require('metamask/node_modules/@metamask/contract-metadata/images/c20.svg'),
- 'CryptoKitties-Kitty-13733.svg': require('metamask/node_modules/@metamask/contract-metadata/images/CryptoKitties-Kitty-13733.svg'),
+ 'ck.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ck.svg'),
'herocoin_logo.png': require('metamask/node_modules/@metamask/contract-metadata/images/herocoin_logo.png'),
'gee-icon.svg': require('metamask/node_modules/@metamask/contract-metadata/images/gee-icon.svg'),
- 'mln.jpg': require('metamask/node_modules/@metamask/contract-metadata/images/mln.jpg'),
+ 'mln.svg': require('metamask/node_modules/@metamask/contract-metadata/images/mln.svg'),
'hgt.png': require('metamask/node_modules/@metamask/contract-metadata/images/hgt.png'),
'hub.svg': require('metamask/node_modules/@metamask/contract-metadata/images/hub.svg'),
- 'goldx.png': require('metamask/node_modules/@metamask/contract-metadata/images/goldx.png'),
'JETCOIN28.png': require('metamask/node_modules/@metamask/contract-metadata/images/JETCOIN28.png'),
'indorseLogo.jpg': require('metamask/node_modules/@metamask/contract-metadata/images/indorseLogo.jpg'),
'ndc.png': require('metamask/node_modules/@metamask/contract-metadata/images/ndc.png'),
@@ -296,19 +297,18 @@ export default {
'CELR.svg': require('metamask/node_modules/@metamask/contract-metadata/images/CELR.svg'),
'gladius.svg': require('metamask/node_modules/@metamask/contract-metadata/images/gladius.svg'),
'kyber.svg': require('metamask/node_modules/@metamask/contract-metadata/images/kyber.svg'),
- 'bancor.png': require('metamask/node_modules/@metamask/contract-metadata/images/bancor.png'),
- 'lun.png': require('metamask/node_modules/@metamask/contract-metadata/images/lun.png'),
+ 'bnt.svg': require('metamask/node_modules/@metamask/contract-metadata/images/bnt.svg'),
+ 'lun.svg': require('metamask/node_modules/@metamask/contract-metadata/images/lun.svg'),
'edu.svg': require('metamask/node_modules/@metamask/contract-metadata/images/edu.svg'),
'vslice.png': require('metamask/node_modules/@metamask/contract-metadata/images/vslice.png'),
'bcap.svg': require('metamask/node_modules/@metamask/contract-metadata/images/bcap.svg'),
'chronobank.png': require('metamask/node_modules/@metamask/contract-metadata/images/chronobank.png'),
- 'taas-ico.png': require('metamask/node_modules/@metamask/contract-metadata/images/taas-ico.png'),
'tkn.svg': require('metamask/node_modules/@metamask/contract-metadata/images/tkn.svg'),
- 'edgeless.jpg': require('metamask/node_modules/@metamask/contract-metadata/images/edgeless.jpg'),
+ 'edg.svg': require('metamask/node_modules/@metamask/contract-metadata/images/edg.svg'),
'guppy.png': require('metamask/node_modules/@metamask/contract-metadata/images/guppy.png'),
'xaurum_logo.svg': require('metamask/node_modules/@metamask/contract-metadata/images/xaurum_logo.svg'),
- 'swt.jpg': require('metamask/node_modules/@metamask/contract-metadata/images/swt.jpg'),
- 'trustcoin.jpg': require('metamask/node_modules/@metamask/contract-metadata/images/trustcoin.jpg'),
+ 'swt.svg': require('metamask/node_modules/@metamask/contract-metadata/images/swt.svg'),
+ 'trst.svg': require('metamask/node_modules/@metamask/contract-metadata/images/trst.svg'),
'cig.svg': require('metamask/node_modules/@metamask/contract-metadata/images/cig.svg'),
'antv1.svg': require('metamask/node_modules/@metamask/contract-metadata/images/antv1.svg'),
'wings_logo.svg': require('metamask/node_modules/@metamask/contract-metadata/images/wings_logo.svg'),
@@ -317,13 +317,12 @@ export default {
'rlc.svg': require('metamask/node_modules/@metamask/contract-metadata/images/rlc.svg'),
'singulardtv.svg': require('metamask/node_modules/@metamask/contract-metadata/images/singulardtv.svg'),
'iconomi.png': require('metamask/node_modules/@metamask/contract-metadata/images/iconomi.png'),
- 'DGD.png': require('metamask/node_modules/@metamask/contract-metadata/images/DGD.png'),
'mkr.svg': require('metamask/node_modules/@metamask/contract-metadata/images/mkr.svg'),
'sai.svg': require('metamask/node_modules/@metamask/contract-metadata/images/sai.svg'),
'dai.svg': require('metamask/node_modules/@metamask/contract-metadata/images/dai.svg'),
'boson.svg': require('metamask/node_modules/@metamask/contract-metadata/images/boson.svg'),
'ampl.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ampl.svg'),
- 'Mainframe.png': require('metamask/node_modules/@metamask/contract-metadata/images/Mainframe.png'),
+ 'hifi.svg': require('metamask/node_modules/@metamask/contract-metadata/images/hifi.svg'),
'bat.svg': require('metamask/node_modules/@metamask/contract-metadata/images/bat.svg'),
'bee_token.svg': require('metamask/node_modules/@metamask/contract-metadata/images/bee_token.svg'),
'gnosis.svg': require('metamask/node_modules/@metamask/contract-metadata/images/gnosis.svg'),
@@ -341,7 +340,7 @@ export default {
'renFIL.svg': require('metamask/node_modules/@metamask/contract-metadata/images/renFIL.svg'),
'golem.svg': require('metamask/node_modules/@metamask/contract-metadata/images/golem.svg'),
'spectiv.svg': require('metamask/node_modules/@metamask/contract-metadata/images/spectiv.svg'),
- 'qtum_28.png': require('metamask/node_modules/@metamask/contract-metadata/images/qtum_28.png'),
+ 'qtum.svg': require('metamask/node_modules/@metamask/contract-metadata/images/qtum.svg'),
'bitclave.svg': require('metamask/node_modules/@metamask/contract-metadata/images/bitclave.svg'),
'change.svg': require('metamask/node_modules/@metamask/contract-metadata/images/change.svg'),
'CanYa.svg': require('metamask/node_modules/@metamask/contract-metadata/images/CanYa.svg'),
@@ -351,9 +350,8 @@ export default {
'Maecenas.jpg': require('metamask/node_modules/@metamask/contract-metadata/images/Maecenas.jpg'),
'zilliqa.svg': require('metamask/node_modules/@metamask/contract-metadata/images/zilliqa.svg'),
'bitmart.png': require('metamask/node_modules/@metamask/contract-metadata/images/bitmart.png'),
- 'StandardBounties.png': require('metamask/node_modules/@metamask/contract-metadata/images/StandardBounties.png'),
'viewly.svg': require('metamask/node_modules/@metamask/contract-metadata/images/viewly.svg'),
- 'weth.png': require('metamask/node_modules/@metamask/contract-metadata/images/weth.png'),
+ 'weth.svg': require('metamask/node_modules/@metamask/contract-metadata/images/weth.svg'),
'rare.svg': require('metamask/node_modules/@metamask/contract-metadata/images/rare.svg'),
'ctoken-bat.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ctoken-bat.svg'),
'ctoken-comp.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ctoken-comp.svg'),
@@ -369,7 +367,7 @@ export default {
'nanjcoin.svg': require('metamask/node_modules/@metamask/contract-metadata/images/nanjcoin.svg'),
'0xbitcoin.svg': require('metamask/node_modules/@metamask/contract-metadata/images/0xbitcoin.svg'),
'snt.svg': require('metamask/node_modules/@metamask/contract-metadata/images/snt.svg'),
- 'SPANK.png': require('metamask/node_modules/@metamask/contract-metadata/images/SPANK.png'),
+ 'spank.svg': require('metamask/node_modules/@metamask/contract-metadata/images/spank.svg'),
'booty.png': require('metamask/node_modules/@metamask/contract-metadata/images/booty.png'),
'Brickblock.svg': require('metamask/node_modules/@metamask/contract-metadata/images/Brickblock.svg'),
'lend.svg': require('metamask/node_modules/@metamask/contract-metadata/images/lend.svg'),
@@ -377,14 +375,13 @@ export default {
'like.svg': require('metamask/node_modules/@metamask/contract-metadata/images/like.svg'),
'bnb.png': require('metamask/node_modules/@metamask/contract-metadata/images/bnb.png'),
'ven.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ven.svg'),
- 'icon-icx-logo.png': require('metamask/node_modules/@metamask/contract-metadata/images/icon-icx-logo.png'),
'Aergo.svg': require('metamask/node_modules/@metamask/contract-metadata/images/Aergo.svg'),
'aeternity.svg': require('metamask/node_modules/@metamask/contract-metadata/images/aeternity.svg'),
- 'FEATURED.POP_.png': require('metamask/node_modules/@metamask/contract-metadata/images/FEATURED.POP_.png'),
+ 'ppt.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ppt.svg'),
'iost.png': require('metamask/node_modules/@metamask/contract-metadata/images/iost.png'),
'kucoin.svg': require('metamask/node_modules/@metamask/contract-metadata/images/kucoin.svg'),
- 'mithril-featured.png': require('metamask/node_modules/@metamask/contract-metadata/images/mithril-featured.png'),
- 'waltonchain.png': require('metamask/node_modules/@metamask/contract-metadata/images/waltonchain.png'),
+ 'mith.svg': require('metamask/node_modules/@metamask/contract-metadata/images/mith.svg'),
+ 'wtc.svg': require('metamask/node_modules/@metamask/contract-metadata/images/wtc.svg'),
'nmr.png': require('metamask/node_modules/@metamask/contract-metadata/images/nmr.png'),
'gusd.svg': require('metamask/node_modules/@metamask/contract-metadata/images/gusd.svg'),
'usds.svg': require('metamask/node_modules/@metamask/contract-metadata/images/usds.svg'),
@@ -409,25 +406,26 @@ export default {
'LTO.svg': require('metamask/node_modules/@metamask/contract-metadata/images/LTO.svg'),
'LTO.svg': require('metamask/node_modules/@metamask/contract-metadata/images/LTO.svg'),
'VIDT.svg': require('metamask/node_modules/@metamask/contract-metadata/images/VIDT.svg'),
+ 'VIDT.svg': require('metamask/node_modules/@metamask/contract-metadata/images/VIDT.svg'),
'Cpollo.svg': require('metamask/node_modules/@metamask/contract-metadata/images/Cpollo.svg'),
'neeo.png': require('metamask/node_modules/@metamask/contract-metadata/images/neeo.png'),
'neu.svg': require('metamask/node_modules/@metamask/contract-metadata/images/neu.svg'),
'streamr.svg': require('metamask/node_modules/@metamask/contract-metadata/images/streamr.svg'),
'streamr_old.svg': require('metamask/node_modules/@metamask/contract-metadata/images/streamr_old.svg'),
- 'CRO.png': require('metamask/node_modules/@metamask/contract-metadata/images/CRO.png'),
+ 'cro.svg': require('metamask/node_modules/@metamask/contract-metadata/images/cro.svg'),
'starbase.png': require('metamask/node_modules/@metamask/contract-metadata/images/starbase.png'),
'santiment.svg': require('metamask/node_modules/@metamask/contract-metadata/images/santiment.svg'),
- 'livepeer.png': require('metamask/node_modules/@metamask/contract-metadata/images/livepeer.png'),
+ 'lpt.svg': require('metamask/node_modules/@metamask/contract-metadata/images/lpt.svg'),
'props.png': require('metamask/node_modules/@metamask/contract-metadata/images/props.png'),
- 'holotoken.png': require('metamask/node_modules/@metamask/contract-metadata/images/holotoken.png'),
+ 'hot.svg': require('metamask/node_modules/@metamask/contract-metadata/images/hot.svg'),
'enj.svg': require('metamask/node_modules/@metamask/contract-metadata/images/enj.svg'),
- 'aelf.png': require('metamask/node_modules/@metamask/contract-metadata/images/aelf.png'),
- 'wax.png': require('metamask/node_modules/@metamask/contract-metadata/images/wax.png'),
- 'power.png': require('metamask/node_modules/@metamask/contract-metadata/images/power.png'),
+ 'elf.svg': require('metamask/node_modules/@metamask/contract-metadata/images/elf.svg'),
+ 'wax.svg': require('metamask/node_modules/@metamask/contract-metadata/images/wax.svg'),
+ 'powr.svg': require('metamask/node_modules/@metamask/contract-metadata/images/powr.svg'),
'blitzpredict.svg': require('metamask/node_modules/@metamask/contract-metadata/images/blitzpredict.svg'),
'maple-finance.svg': require('metamask/node_modules/@metamask/contract-metadata/images/maple-finance.svg'),
'knownorigin.svg': require('metamask/node_modules/@metamask/contract-metadata/images/knownorigin.svg'),
- 'originprotocol.png': require('metamask/node_modules/@metamask/contract-metadata/images/originprotocol.png'),
+ 'ogn.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ogn.svg'),
'ousd.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ousd.svg'),
'ogv.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ogv.svg'),
'veogv.svg': require('metamask/node_modules/@metamask/contract-metadata/images/veogv.svg'),
@@ -437,7 +435,6 @@ export default {
'hunt.png': require('metamask/node_modules/@metamask/contract-metadata/images/hunt.png'),
'metamorph.svg': require('metamask/node_modules/@metamask/contract-metadata/images/metamorph.svg'),
'district0x.svg': require('metamask/node_modules/@metamask/contract-metadata/images/district0x.svg'),
- 'neutraldollar.png': require('metamask/node_modules/@metamask/contract-metadata/images/neutraldollar.png'),
'minds.svg': require('metamask/node_modules/@metamask/contract-metadata/images/minds.svg'),
'SOUL.svg': require('metamask/node_modules/@metamask/contract-metadata/images/SOUL.svg'),
'origo.svg': require('metamask/node_modules/@metamask/contract-metadata/images/origo.svg'),
@@ -463,7 +460,7 @@ export default {
'kton.svg': require('metamask/node_modules/@metamask/contract-metadata/images/kton.svg'),
'2key.svg': require('metamask/node_modules/@metamask/contract-metadata/images/2key.svg'),
'fuse.svg': require('metamask/node_modules/@metamask/contract-metadata/images/fuse.svg'),
- 'stake.png': require('metamask/node_modules/@metamask/contract-metadata/images/stake.png'),
+ 'stake.svg': require('metamask/node_modules/@metamask/contract-metadata/images/stake.svg'),
'DKA.svg': require('metamask/node_modules/@metamask/contract-metadata/images/DKA.svg'),
'ring.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ring.svg'),
'ROOBEE.svg': require('metamask/node_modules/@metamask/contract-metadata/images/ROOBEE.svg'),
@@ -521,7 +518,7 @@ export default {
'WKDA.svg': require('metamask/node_modules/@metamask/contract-metadata/images/WKDA.svg'),
'WXRP.svg': require('metamask/node_modules/@metamask/contract-metadata/images/WXRP.svg'),
'INX.svg': require('metamask/node_modules/@metamask/contract-metadata/images/INX.svg'),
- 'Vesper-VSP-Token.svg': require('metamask/node_modules/@metamask/contract-metadata/images/Vesper-VSP-Token.svg'),
+ 'vsp.svg': require('metamask/node_modules/@metamask/contract-metadata/images/vsp.svg'),
'INSUR.svg': require('metamask/node_modules/@metamask/contract-metadata/images/INSUR.svg'),
'chainswap.svg': require('metamask/node_modules/@metamask/contract-metadata/images/chainswap.svg'),
'keyTango.svg': require('metamask/node_modules/@metamask/contract-metadata/images/keyTango.svg'),
@@ -598,4 +595,12 @@ export default {
'BitDAO.svg': require('metamask/node_modules/@metamask/contract-metadata/images/BitDAO.svg'),
'home.svg': require('metamask/node_modules/@metamask/contract-metadata/images/home.svg'),
'bacon.svg': require('metamask/node_modules/@metamask/contract-metadata/images/bacon.svg'),
+ 'VERSE.svg': require('metamask/node_modules/@metamask/contract-metadata/images/VERSE.svg'),
+ 'tidex.svg': require('metamask/node_modules/@metamask/contract-metadata/images/tidex.svg'),
+ 'shib.svg': require('metamask/node_modules/@metamask/contract-metadata/images/shib.svg'),
+ 'chz.svg': require('metamask/node_modules/@metamask/contract-metadata/images/chz.svg'),
+ 'gala.svg': require('metamask/node_modules/@metamask/contract-metadata/images/gala.svg'),
+ 'mask.svg': require('metamask/node_modules/@metamask/contract-metadata/images/mask.svg'),
+ 'crv.svg': require('metamask/node_modules/@metamask/contract-metadata/images/crv.svg'),
+ 'dydx.svg': require('metamask/node_modules/@metamask/contract-metadata/images/dydx.svg'),
};
diff --git a/bitrise.yml b/bitrise.yml
index 6e94fd0689e..1a321a81457 100644
--- a/bitrise.yml
+++ b/bitrise.yml
@@ -28,6 +28,18 @@ workflows:
inputs:
- command: audit:ci
title: Audit Dependencies
+ code_setup_dev:
+ before_run:
+ - setup
+ steps:
+ - script@1:
+ title: Generate `.npmrc` file for preview builds
+ inputs:
+ - content: |
+ #!/bin/bash
+ printf '%s\n\n%s' '@metamask:registry=https://npm.pkg.github.com' "//npm.pkg.github.com/:_authToken=${PACKAGE_READ_TOKEN}" > .npmrc
+ after_run:
+ - code_setup
# Notifications utility workflows
# Provides values for commit or branch message and path depending on commit env setup initialised or not
@@ -141,7 +153,7 @@ workflows:
title: Detox - Install CLI
android_e2e_test:
before_run:
- - code_setup
+ - code_setup_dev
- e2e_setup
after_run:
- _e2e_notify_on_slack
@@ -168,7 +180,7 @@ workflows:
is_always_run: false
ios_e2e_test:
before_run:
- - code_setup
+ - code_setup_dev
- e2e_setup
after_run:
- _e2e_notify_on_slack
@@ -257,7 +269,7 @@ workflows:
is_always_run: false
create_qa_builds:
before_run:
- - code_setup
+ - code_setup_dev
steps:
- build-router-start@0:
inputs:
@@ -331,7 +343,7 @@ workflows:
title: Bitrise Deploy Sourcemaps
build_android_qa:
before_run:
- - code_setup
+ - code_setup_dev
after_run:
- _upload_apk_to_browserstack
- _build_failure_notify_on_slack
@@ -510,7 +522,7 @@ workflows:
title: Deploy Source Map
build_ios_qa:
before_run:
- - code_setup
+ - code_setup_dev
after_run:
- _build_failure_notify_on_slack
steps:
@@ -578,10 +590,10 @@ app:
PROJECT_LOCATION_IOS: ios
- opts:
is_expand: false
- VERSION_NAME: 6.1.0
+ VERSION_NAME: 6.1.2
- opts:
is_expand: false
- VERSION_NUMBER: 1078
+ VERSION_NUMBER: 1082
- opts:
is_expand: false
ANDROID_APK_LINK: ''
diff --git a/ios/MetaMask.xcodeproj/project.pbxproj b/ios/MetaMask.xcodeproj/project.pbxproj
index 5f9c233bbf1..f80830ec18e 100644
--- a/ios/MetaMask.xcodeproj/project.pbxproj
+++ b/ios/MetaMask.xcodeproj/project.pbxproj
@@ -1021,7 +1021,7 @@
CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1078;
+ CURRENT_PROJECT_VERSION = 1082;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 48XVW22RCG;
@@ -1057,7 +1057,7 @@
"\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.1.0;
+ MARKETING_VERSION = 6.1.2;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"$(inherited)",
@@ -1088,7 +1088,7 @@
CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1078;
+ CURRENT_PROJECT_VERSION = 1082;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 48XVW22RCG;
ENABLE_BITCODE = NO;
@@ -1124,7 +1124,7 @@
"\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.1.0;
+ MARKETING_VERSION = 6.1.2;
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = (
"$(inherited)",
@@ -1234,7 +1234,7 @@
CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMaskDebug.entitlements;
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1078;
+ CURRENT_PROJECT_VERSION = 1082;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 48XVW22RCG;
@@ -1270,7 +1270,7 @@
"\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.1.0;
+ MARKETING_VERSION = 6.1.2;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = (
"$(inherited)",
@@ -1301,7 +1301,7 @@
CODE_SIGN_ENTITLEMENTS = MetaMask/MetaMask.entitlements;
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
- CURRENT_PROJECT_VERSION = 1078;
+ CURRENT_PROJECT_VERSION = 1082;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
DEVELOPMENT_TEAM = 48XVW22RCG;
ENABLE_BITCODE = NO;
@@ -1337,7 +1337,7 @@
"\"$(SRCROOT)/MetaMask/System/Library/Frameworks\"",
);
LLVM_LTO = YES;
- MARKETING_VERSION = 6.1.0;
+ MARKETING_VERSION = 6.1.2;
ONLY_ACTIVE_ARCH = NO;
OTHER_CFLAGS = (
"$(inherited)",
diff --git a/locales/languages/en.json b/locales/languages/en.json
index 97e4fa2a663..11a0c0f4652 100644
--- a/locales/languages/en.json
+++ b/locales/languages/en.json
@@ -557,6 +557,8 @@
"nft_autodetect_desc": "Displaying NFT media & data may expose your IP address to centralized servers. Third-party APIs (like OpenSea) are used to detect NFTs in your wallet. This exposes your account address with those services. Leave this disabled if you don't want the app to pull data from those services.",
"show_hex_data": "Show Hex Data",
"show_hex_data_desc": "Select this to show the hex data field on the send screen.",
+ "enable_eth_sign": "Toggle eth_sign requests",
+ "enable_eth_sign_desc": "Turn this on to let dapps request your signature using eth_sign requests. eth_sign is an open-ended signing method that lets you sign an arbitrary hash, making it a dangerous phishing risk. Only sign eth_sign requests if you can read what you are signing and trust the origin of the request.",
"show_custom_nonce": "Customize transaction nonce",
"custom_nonce_desc": "Turn this on to change the nonce (transaction number) on confirmation screens. This is an advanced feature, use cautiously.",
"accounts_identicon_title": "Account Identicon",
@@ -986,7 +988,7 @@
"allow_to_address_access": "Give this address access your",
"token": "token",
"nft": "NFT",
- "you_trust_this_site": "By granting permission, you're allowing the following contract to access your funds.",
+ "you_trust_this_site": "By granting permission, you're allowing the following third party to access your funds.",
"you_trust_this_address": "Do you trust this address? By granting this permission, you're allowing this address to access your funds.",
"edit_permission": "Edit permission",
"edit": "Edit",
@@ -2198,8 +2200,8 @@
"add_nickname": "Add nickname",
"edit_nickname": "Edit nickname",
"save_nickname": "Confirm",
- "address": "Contract Address",
- "name": "Contract Name",
+ "address": "Address",
+ "name": "Nickname",
"name_placeholder": "Add a nickname to this address",
"contract": "Contract",
"nickname": "nickname"
@@ -2278,6 +2280,18 @@
"set_spend_cap": "Set a spending cap",
"be_careful": "Be careful",
"error_enter_number": "Error: Enter only numbers"
+ },
+ "token_allowance": {
+ "verify_third_party_details": "Verify third party details",
+ "protect_from_scams": "To protect yourself against scammers, take a moment to verify third party details.",
+ "learn_to_verify": "Learn how to verify third party details",
+ "spending_cap": "spending cap",
+ "access": "access",
+ "nft_contract": "NFT contract",
+ "token_contract": "Token contract",
+ "third_party_requesting_text": "Third party requesting {{action}}",
+ "third party": "third party",
+ "address": "Address"
}
},
"restore_wallet": {
diff --git a/package.json b/package.json
index 7e173f8bb20..b69f17f1bba 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "metamask",
- "version": "6.1.0",
+ "version": "6.1.1",
"private": true,
"scripts": {
"audit:ci": "./scripts/yarn-audit.sh",
@@ -130,7 +130,7 @@
"oss-attribution-generator/**/debug": "^2.6.9"
},
"dependencies": {
- "@consensys/on-ramp-sdk": "1.8.1",
+ "@consensys/on-ramp-sdk": "1.9.0",
"@eth-optimism/contracts": "0.0.0-2021919175625",
"@ethereumjs/common": "^2.3.1",
"@ethereumjs/tx": "^3.2.1",
@@ -152,8 +152,8 @@
"@metamask/message-manager": "^1.0.1",
"@metamask/network-controller": "^2.0.0",
"@metamask/permission-controller": "^1.0.2",
+ "@metamask/preferences-controller": "^2.1.0",
"@metamask/phishing-controller": "^2.0.0",
- "@metamask/preferences-controller": "^1.0.1",
"@metamask/rpc-methods": "0.24.1",
"@metamask/post-message-stream": "6.0.0",
"@metamask/sdk-communication-layer": "^0.1.0",
diff --git a/wdio/features/AppLaunchTime.feature b/wdio/features/AppLaunchTime.feature
deleted file mode 100644
index a4c54800363..00000000000
--- a/wdio/features/AppLaunchTime.feature
+++ /dev/null
@@ -1,22 +0,0 @@
-@androidApp @ChainScenarios
-Feature: App launch times
- As a user,
- I want to measure the time it takes to launch the app,
- So that I can ensure it is performing well
-
- Scenario: Measure app launch time on fresh install
- Given the app is launched
- When the app displayed the splash animation
- Then the app should launch within x seconds
-
- Scenario: Measure app launch time after importing a wallet
- Given I have imported my wallet
- And I tap No Thanks on the Enable security check screen
- And I tap No thanks on the onboarding welcome tutorial
- And I am on the wallet view
- When I kill the app
- And I relaunch the app
- And the timer starts running
- And I fill my password in the Login screen
- And I log into my wallet
- Then the app should launch within x seconds
diff --git a/wdio/features/Performance/AppLaunchTime.feature b/wdio/features/Performance/AppLaunchTime.feature
new file mode 100644
index 00000000000..9d7b287dba5
--- /dev/null
+++ b/wdio/features/Performance/AppLaunchTime.feature
@@ -0,0 +1,22 @@
+@androidApp @Performance
+Feature: App Cold Start launch times.
+ This feature measures the cold start of the app when:
+ The user installs the app for the very first time
+ The user imports a wallet
+
+ Scenario: Measure cold start launch time on fresh install
+ Given the app is launched
+ When the app displayed the splash animation
+ Then the app should launch within "4" seconds
+
+ Scenario: Measure cold start launch time after importing a wallet
+ Given I have imported my wallet
+ And I tap No Thanks on the Enable security check screen
+ And I tap No thanks on the onboarding welcome tutorial
+ And I am on the wallet view
+ When I kill the app
+ And I relaunch the app
+ And the timer starts running
+ And I fill my password in the Login screen
+ And I log into my wallet
+ Then the app should launch within "14" seconds
diff --git a/wdio/screen-objects/Onboarding/ImportFromSeedScreen.js b/wdio/screen-objects/Onboarding/ImportFromSeedScreen.js
index 525274f2e7d..2cd410bf78c 100644
--- a/wdio/screen-objects/Onboarding/ImportFromSeedScreen.js
+++ b/wdio/screen-objects/Onboarding/ImportFromSeedScreen.js
@@ -74,6 +74,9 @@ class ImportFromSeed {
await Gestures.waitAndTap(this.screenTitle);
await Gestures.waitAndTap(this.importButton);
}
+ async tapImportFromSeedTextToDismissKeyboard() {
+ await Gestures.waitAndTap(this.screenTitle);
+ }
async isPasswordStrengthTextCorrect(text) {
await expect(this.passwordStrengthLabel).toHaveText(text);
diff --git a/wdio/step-definitions/app-launch-times.steps.js b/wdio/step-definitions/app-launch-times.steps.js
index 7ab42cab406..2a480853d5f 100644
--- a/wdio/step-definitions/app-launch-times.steps.js
+++ b/wdio/step-definitions/app-launch-times.steps.js
@@ -4,10 +4,13 @@ import { Given, When, Then } from '@wdio/cucumber-framework';
let startTimer;
let stopTimer;
-Then(/^the app should launch within x seconds$/, async () => {
+Then(/^the app should launch within "([^"]*)?" seconds$/, async (time) => {
stopTimer = new Date().getTime();
- const result = stopTimer - startTimer;
- cucumberJson.attach(`Milliseconds: ${result}`);
+ const launchTime = stopTimer - startTimer;
+ console.log(`The Launch time is: ${launchTime}`);
+
+ await expect(launchTime).toBeLessThan(time * 1000);
+ cucumberJson.attach(`Milliseconds: ${launchTime}`);
});
Given(/^the app is launched$/, async () => {
diff --git a/wdio/step-definitions/common-steps.js b/wdio/step-definitions/common-steps.js
index a2024d02deb..b11d37026ba 100644
--- a/wdio/step-definitions/common-steps.js
+++ b/wdio/step-definitions/common-steps.js
@@ -30,7 +30,9 @@ Given(/^I have imported my wallet$/, async () => {
await ImportFromSeedScreen.isScreenTitleVisible();
await ImportFromSeedScreen.typeSecretRecoveryPhrase(validAccount.seedPhrase);
await ImportFromSeedScreen.typeNewPassword(validAccount.password);
+ await ImportFromSeedScreen.tapImportFromSeedTextToDismissKeyboard();
await ImportFromSeedScreen.typeConfirmPassword(validAccount.password);
+ await ImportFromSeedScreen.tapImportFromSeedTextToDismissKeyboard();
await ImportFromSeedScreen.clickImportButton();
});
diff --git a/yarn.lock b/yarn.lock
index a10363c532a..55418ab5d59 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1649,10 +1649,10 @@
resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9"
integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==
-"@consensys/on-ramp-sdk@1.8.1":
- version "1.8.1"
- resolved "https://registry.yarnpkg.com/@consensys/on-ramp-sdk/-/on-ramp-sdk-1.8.1.tgz#05c2115c16526f4fb5913e7f3b8fad71c38c3b1e"
- integrity sha512-F2POd3UquAByg1cIlAg38XMKP2yjNBxR7UBrfkCA32iNEivFeDu68RMMwYhgnDL4w+eI5U5umw/yumvUZn/b5w==
+"@consensys/on-ramp-sdk@1.9.0":
+ version "1.9.0"
+ resolved "https://registry.yarnpkg.com/@consensys/on-ramp-sdk/-/on-ramp-sdk-1.9.0.tgz#4ab9b8251308769287ebbe3ed8a53a9eb2d4537f"
+ integrity sha512-rFmHxOMsOdP/hHMG2R3FBXUbZggJGrPCbrOAhctdJhmFfHIjkvAF4bKTaj529tAvs+oKnyI0k2i56KtFopZ3vQ==
dependencies:
async "^3.2.3"
axios "^0.21.0"
@@ -4103,6 +4103,14 @@
"@metamask/controller-utils" "^1.0.0"
immer "^9.0.6"
+"@metamask/base-controller@^2.0.0":
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/@metamask/base-controller/-/base-controller-2.0.0.tgz#8f9130df3edaa270ade00378cf57917545d44617"
+ integrity sha512-DppA4/HCabsphVucNRpWA3/mp6m2KhZr/8gidSlpUNLMFqljOKA81GW9nemN3HDqH1RoZdXusI82/4SPEbdbaA==
+ dependencies:
+ "@metamask/controller-utils" "^3.0.0"
+ immer "^9.0.6"
+
"@metamask/bip39@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@metamask/bip39/-/bip39-4.0.0.tgz#1cb867a8454e3d45d065107b4e070d58bdb64aac"
@@ -4154,6 +4162,17 @@
fast-deep-equal "^3.1.3"
isomorphic-fetch "^3.0.0"
+"@metamask/controller-utils@^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@metamask/controller-utils/-/controller-utils-3.0.0.tgz#e0984cdab14280409297671b5858891527c5e4ee"
+ integrity sha512-JjFWBZnnh5DSX2tRsw5xtXxaqVkTzaW7mkSZ+lL3LoCAw47Cf8zGP1kGR6VKxcceKi+MpEFvZr7gf1OFnOoEjw==
+ dependencies:
+ eth-ens-namehash "^2.0.8"
+ eth-rpc-errors "^4.0.0"
+ ethereumjs-util "^7.0.10"
+ ethjs-unit "^0.1.6"
+ fast-deep-equal "^3.1.3"
+
"@metamask/controllers@^26.0.0":
version "26.0.0"
resolved "git+https://github.com/MetaMask/controllers.git#d4e9507d9612f2d36c3f848333b33330a19b811b"
@@ -4445,6 +4464,14 @@
"@metamask/base-controller" "^1.1.1"
"@metamask/controller-utils" "^1.0.0"
+"@metamask/preferences-controller@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/@metamask/preferences-controller/-/preferences-controller-2.1.0.tgz#c3ed464259f3f969ff492167c368752d23db3924"
+ integrity sha512-/GvYSaCCT0DVDZLlt8eiJDcw7WNFeIMpssP0X0+MK+Ye5eGEMp0Wo0n5uoMOKDR+x3HnWo5YuVGHBlSCnusEeg==
+ dependencies:
+ "@metamask/base-controller" "^2.0.0"
+ "@metamask/controller-utils" "^3.0.0"
+
"@metamask/providers@^10.2.0":
version "10.2.1"
resolved "https://registry.yarnpkg.com/@metamask/providers/-/providers-10.2.1.tgz#61304940adeccc7421dcda30ffd1d834273cc77b"