= T extends (...args: infer P) => any
? NullifyOrPartial
: never;
@@ -83,7 +85,9 @@ export default function useSDKMethod(
},
(
...customParams: PartialParameters | []
- ) => Promise | ReturnType,
+ ) => // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ Promise | ReturnType,
] {
const method = typeof config === 'string' ? config : config.method;
const onMount = typeof config === 'string' ? true : config.onMount ?? true;
diff --git a/app/components/UI/Ramp/index.tsx b/app/components/UI/Ramp/index.tsx
index d3ee337d6b7..91a26fec925 100644
--- a/app/components/UI/Ramp/index.tsx
+++ b/app/components/UI/Ramp/index.tsx
@@ -220,8 +220,14 @@ function FiatOrders() {
const dispatch = useDispatch();
const dispatchThunk = useThunkDispatch();
const navigation = useNavigation();
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const pendingOrders = useSelector(getPendingOrders);
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const customOrderIds = useSelector(getCustomOrderIds);
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const authenticationUrls = useSelector(getAuthenticationUrls);
const dispatchAddFiatOrder = useCallback(
diff --git a/app/components/UI/Ramp/orderProcessor/customOrderId.test.ts b/app/components/UI/Ramp/orderProcessor/customOrderId.test.ts
index 71600ff6970..f7eef66a56b 100644
--- a/app/components/UI/Ramp/orderProcessor/customOrderId.test.ts
+++ b/app/components/UI/Ramp/orderProcessor/customOrderId.test.ts
@@ -85,6 +85,8 @@ describe('CustomOrderId processor', () => {
status: OrderStatusEnum.Precreated,
lastTimeFetched: 1000 + 1,
}),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
@@ -121,6 +123,8 @@ describe('CustomOrderId processor', () => {
getOrder: jest.fn().mockResolvedValue({
status: OrderStatusEnum.Precreated,
}),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
@@ -137,6 +141,8 @@ describe('CustomOrderId processor', () => {
getOrder: jest
.fn()
.mockResolvedValue({ status: OrderStatusEnum.Pending }),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
@@ -165,6 +171,8 @@ describe('CustomOrderId processor', () => {
getOrder: jest
.fn()
.mockResolvedValue({ status: OrderStatusEnum.Precreated }),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
@@ -193,6 +201,8 @@ describe('CustomOrderId processor', () => {
getOrder: jest.fn().mockImplementation(() => {
throw new Error('Request error');
}),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
@@ -221,6 +231,8 @@ describe('CustomOrderId processor', () => {
getOrder: jest.fn().mockResolvedValue({
status: OrderStatusEnum.Precreated,
}),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
@@ -254,6 +266,8 @@ describe('CustomOrderId processor', () => {
getSellOrder: jest.fn().mockResolvedValue({
status: OrderStatusEnum.Precreated,
}),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
@@ -287,6 +301,8 @@ describe('CustomOrderId processor', () => {
getOrder: jest.fn().mockResolvedValue({
status: OrderStatusEnum.Unknown,
}),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
@@ -322,6 +338,8 @@ describe('CustomOrderId processor', () => {
getSellOrder: jest.fn().mockResolvedValue({
status: OrderStatusEnum.Unknown,
}),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
@@ -357,6 +375,8 @@ describe('CustomOrderId processor', () => {
getOrder: jest.fn().mockResolvedValue({
status: OrderStatusEnum.IdExpired,
}),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
@@ -390,6 +410,8 @@ describe('CustomOrderId processor', () => {
getSellOrder: jest.fn().mockResolvedValue({
status: OrderStatusEnum.IdExpired,
}),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
@@ -423,6 +445,8 @@ describe('CustomOrderId processor', () => {
getOrder: jest.fn().mockResolvedValue({
status: OrderStatusEnum.Unknown,
}),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
@@ -457,6 +481,8 @@ describe('CustomOrderId processor', () => {
getSellOrder: jest.fn().mockResolvedValue({
status: OrderStatusEnum.Unknown,
}),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
diff --git a/app/components/UI/Ramp/orderProcessor/customOrderId.ts b/app/components/UI/Ramp/orderProcessor/customOrderId.ts
index f0a45540841..4eefba8be28 100644
--- a/app/components/UI/Ramp/orderProcessor/customOrderId.ts
+++ b/app/components/UI/Ramp/orderProcessor/customOrderId.ts
@@ -84,6 +84,8 @@ export default async function processCustomOrderIdData(
{ ...customOrderIdData, lastTimeFetched: Date.now(), errorCount: 0 },
null,
];
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
return [customOrderIdData, null];
}
diff --git a/app/components/UI/Ramp/sdk/index.tsx b/app/components/UI/Ramp/sdk/index.tsx
index 3317d6c5cc0..7de245ee06a 100644
--- a/app/components/UI/Ramp/sdk/index.tsx
+++ b/app/components/UI/Ramp/sdk/index.tsx
@@ -300,6 +300,8 @@ export const useRampSDK = () => {
return contextValue as RampSDK;
};
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const withRampSDK = (Component: React.FC) => (props: any) =>
(
diff --git a/app/components/UI/Ramp/utils/index.test.ts b/app/components/UI/Ramp/utils/index.test.ts
index 976035a4e68..7eeafdedb63 100644
--- a/app/components/UI/Ramp/utils/index.test.ts
+++ b/app/components/UI/Ramp/utils/index.test.ts
@@ -61,6 +61,8 @@ describe('formatAmount', () => {
() =>
({
format: jest.fn().mockImplementation(() => '123,123'),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
expect(formatAmount(123123)).toBe('123,123');
@@ -74,6 +76,8 @@ describe('formatAmount', () => {
format: jest.fn().mockImplementation(() => {
throw Error();
}),
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any),
);
expect(formatAmount(123123)).toBe('123123');
@@ -520,6 +524,8 @@ describe('getOrderAmount', () => {
cryptoAmount: 0.012361263,
data: {
...mockOrder.data,
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
cryptoCurrency: undefined as any,
},
}),
diff --git a/app/components/UI/ReceiveRequest/index.js b/app/components/UI/ReceiveRequest/index.js
index 94c0c01d916..c3494a32349 100644
--- a/app/components/UI/ReceiveRequest/index.js
+++ b/app/components/UI/ReceiveRequest/index.js
@@ -40,7 +40,7 @@ import {
selectTicker,
} from '../../../selectors/networkController';
import { isNetworkRampSupported } from '../Ramp/utils';
-import { selectSelectedAddress } from '../../../selectors/preferencesController';
+import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController';
import { getRampNetworks } from '../../../reducers/fiatOrders';
import { RequestPaymentModalSelectorsIDs } from '../../../../e2e/selectors/Modals/RequestPaymentModal.selectors';
import { getDecimalChainId } from '../../../util/networks';
@@ -60,7 +60,7 @@ const createStyles = (theme) =>
qrWrapper: {
margin: 8,
padding: 8,
- backgroundColor: theme.brandColors.white000,
+ backgroundColor: theme.brandColors.white,
},
addressWrapper: {
flexDirection: 'row',
@@ -364,7 +364,7 @@ ReceiveRequest.contextType = ThemeContext;
const mapStateToProps = (state) => ({
chainId: selectChainId(state),
ticker: selectTicker(state),
- selectedAddress: selectSelectedAddress(state),
+ selectedAddress: selectSelectedInternalAccountChecksummedAddress(state),
receiveAsset: state.modals.receiveAsset,
seedphraseBackedUp: state.user.seedphraseBackedUp,
isNetworkBuySupported: isNetworkRampSupported(
diff --git a/app/components/UI/ReceiveRequest/index.test.tsx b/app/components/UI/ReceiveRequest/index.test.tsx
index 70c3c8872c3..1b95e369856 100644
--- a/app/components/UI/ReceiveRequest/index.test.tsx
+++ b/app/components/UI/ReceiveRequest/index.test.tsx
@@ -4,11 +4,15 @@ import ReceiveRequest from './';
import configureMockStore from 'redux-mock-store';
import { Provider } from 'react-redux';
import initialBackgroundState from '../../../util/test/initial-background-state.json';
+import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../util/test/accountsControllerTestUtils';
const mockStore = configureMockStore();
const initialState = {
engine: {
- backgroundState: initialBackgroundState,
+ backgroundState: {
+ ...initialBackgroundState,
+ AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE,
+ },
},
modals: {
receiveAsset: {},
diff --git a/app/components/UI/ReviewModal/styles.ts b/app/components/UI/ReviewModal/styles.ts
index 23e74fdfae0..77bca68ad7b 100644
--- a/app/components/UI/ReviewModal/styles.ts
+++ b/app/components/UI/ReviewModal/styles.ts
@@ -1,6 +1,8 @@
/* eslint-disable import/prefer-default-export */
import { StyleSheet } from 'react-native';
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const createStyles = (colors: any) =>
StyleSheet.create({
screen: { justifyContent: 'center', paddingHorizontal: 24 },
diff --git a/app/components/UI/SearchTokenAutocomplete/__snapshots__/index.test.tsx.snap b/app/components/UI/SearchTokenAutocomplete/__snapshots__/index.test.tsx.snap
index 75ac831f1c2..652b09a00df 100644
--- a/app/components/UI/SearchTokenAutocomplete/__snapshots__/index.test.tsx.snap
+++ b/app/components/UI/SearchTokenAutocomplete/__snapshots__/index.test.tsx.snap
@@ -329,10 +329,10 @@ exports[`SearchTokenAutocomplete should render correctly 1`] = `
[
{
"alignItems": "center",
- "borderColor": "#BBC0C5",
+ "borderColor": "#bbc0c5",
"borderRadius": 8,
"borderWidth": 1,
- "color": "#24272A",
+ "color": "#141618",
"flex": 1,
"flexDirection": "row",
"justifyContent": "center",
@@ -346,13 +346,13 @@ exports[`SearchTokenAutocomplete should render correctly 1`] = `
StyleSheet.create({
wrapper: {
@@ -66,6 +68,8 @@ interface Props {
/**
/* navigation object required to push new views
*/
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
navigation: any;
}
@@ -76,6 +80,8 @@ const SearchTokenAutocomplete = ({ navigation }: Props) => {
const { trackEvent } = useMetrics();
const [searchResults, setSearchResults] = useState([]);
const [searchQuery, setSearchQuery] = useState('');
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const [selectedAsset, setSelectedAsset] = useState([]);
const [isSearchFocused, setIsSearchFocused] = useState(false);
@@ -108,6 +114,8 @@ const SearchTokenAutocomplete = ({ navigation }: Props) => {
}, [selectedAsset, chainId]);
const handleSearch = useCallback(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(opts: any) => {
setSearchResults(opts.results);
setSearchQuery(opts.searchQuery);
@@ -142,6 +150,8 @@ const SearchTokenAutocomplete = ({ navigation }: Props) => {
const addToken = useCallback(
async ({ address, symbol, decimals, iconUrl, name }) => {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const { TokensController } = Engine.context as any;
await TokensController.addToken({
address,
diff --git a/app/components/UI/SecurityOptionToggle/SecurityOptionToggle.tsx b/app/components/UI/SecurityOptionToggle/SecurityOptionToggle.tsx
index b86ecb8b581..245a8b98d5d 100644
--- a/app/components/UI/SecurityOptionToggle/SecurityOptionToggle.tsx
+++ b/app/components/UI/SecurityOptionToggle/SecurityOptionToggle.tsx
@@ -53,7 +53,7 @@ const SecurityOptionToggle = ({
true: colors.primary.default,
false: colors.border.muted,
}}
- thumbColor={theme.brandColors.white000}
+ thumbColor={theme.brandColors.white}
style={styles.switch}
ios_backgroundColor={colors.border.muted}
disabled={disabled}
diff --git a/app/components/UI/SeedphraseModal/__snapshots__/index.test.tsx.snap b/app/components/UI/SeedphraseModal/__snapshots__/index.test.tsx.snap
index dc31304315d..f8054f51968 100644
--- a/app/components/UI/SeedphraseModal/__snapshots__/index.test.tsx.snap
+++ b/app/components/UI/SeedphraseModal/__snapshots__/index.test.tsx.snap
@@ -169,7 +169,7 @@ exports[`SeedphraseModal should render correctly 1`] = `
style={
[
{
- "backgroundColor": "#FFFFFF",
+ "backgroundColor": "#ffffff",
"borderRadius": 10,
"width": "100%",
},
@@ -217,7 +217,7 @@ exports[`SeedphraseModal should render correctly 1`] = `
{
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const network: any = Object.values(NetworkList).find(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(nw: any) => nw.chainId === chainId,
);
return network?.imageSource || null;
diff --git a/app/components/UI/SimulationDetails/FiatDisplay/FiatDisplay.test.tsx b/app/components/UI/SimulationDetails/FiatDisplay/FiatDisplay.test.tsx
index b4981211377..c5c3a1f4a78 100644
--- a/app/components/UI/SimulationDetails/FiatDisplay/FiatDisplay.test.tsx
+++ b/app/components/UI/SimulationDetails/FiatDisplay/FiatDisplay.test.tsx
@@ -1,14 +1,13 @@
import React from 'react';
-import useFiatFormatter from './useFiatFormatter';
-
+import { merge } from 'lodash';
import renderWithProvider from '../../../../util/test/renderWithProvider';
import initialBackgroundState from '../../../../util/test/initial-background-state.json';
-
-import { IndividualFiatDisplay, TotalFiatDisplay } from './FiatDisplay';
import { FIAT_UNAVAILABLE } from '../types';
+import { IndividualFiatDisplay, TotalFiatDisplay } from './FiatDisplay';
+import useFiatFormatter from './useFiatFormatter';
+import { NETWORKS_CHAIN_ID } from '../../../../constants/network';
jest.mock('./useFiatFormatter');
-(useFiatFormatter as jest.Mock).mockReturnValue((value: number) => `$${value}`);
const mockInitialState = {
engine: {
@@ -16,31 +15,88 @@ const mockInitialState = {
},
};
-describe('IndividualFiatDisplay', () => {
- it.each([
- [FIAT_UNAVAILABLE, 'Not Available'],
- [100, '$100'],
- [-100, '$100'],
- ])('when fiatAmount is %s it renders %s', (fiatAmount, expected) => {
- const { getByText } = renderWithProvider(
- ,
- { state: mockInitialState },
- );
- expect(getByText(expected)).toBeDefined();
- });
+const mockStateWithTestnet = merge({}, mockInitialState, {
+ engine: {
+ backgroundState: {
+ NetworkController: {
+ providerConfig: {
+ chainId: NETWORKS_CHAIN_ID.SEPOLIA,
+ },
+ },
+ },
+ },
+});
+
+const mockStateWithShowingFiatOnTestnets = merge({}, mockStateWithTestnet, {
+ engine: {
+ backgroundState: {
+ PreferencesController: {
+ showFiatInTestnets: true,
+ },
+ },
+ },
+});
+
+const mockStateWithHidingFiatOnTestnets = merge({}, mockStateWithTestnet, {
+ engine: {
+ backgroundState: {
+ PreferencesController: {
+ showFiatInTestnets: false,
+ },
+ },
+ },
});
-describe('TotalFiatDisplay', () => {
- it.each([
- [[FIAT_UNAVAILABLE, FIAT_UNAVAILABLE], 'Not Available'],
- [[], 'Not Available'],
- [[100, 200, FIAT_UNAVAILABLE, 300], 'Total = $600'],
- [[-100, -200, FIAT_UNAVAILABLE, -300], 'Total = $600'],
- ])('when fiatAmounts is %s it renders %s', (fiatAmounts, expected) => {
- const { getByText } = renderWithProvider(
- ,
- { state: mockInitialState },
- );
- expect(getByText(expected)).toBeDefined();
+describe('FiatDisplay', () => {
+ const mockUseFiatFormatter = jest.mocked(useFiatFormatter);
+
+ beforeEach(() => {
+ jest.resetAllMocks();
+ mockUseFiatFormatter.mockReturnValue((value: number) => `$${value}`);
+ });
+
+ describe('IndividualFiatDisplay', () => {
+ it.each([
+ [FIAT_UNAVAILABLE, 'Not Available'],
+ [100, '$100'],
+ [-100, '$100'],
+ ])('when fiatAmount is %s it renders %s', (fiatAmount, expected) => {
+ const { queryByText } = renderWithProvider(
+ ,
+ { state: mockStateWithShowingFiatOnTestnets },
+ );
+ expect(queryByText(expected)).toBeDefined();
+ });
+
+ it('does not render anything if hideFiatForTestnet is true', () => {
+ const { queryByText } = renderWithProvider(
+ ,
+ { state: mockStateWithHidingFiatOnTestnets },
+ );
+ expect(queryByText('100')).toBe(null);
+ });
+ });
+
+ describe('TotalFiatDisplay', () => {
+ it.each([
+ [[FIAT_UNAVAILABLE, FIAT_UNAVAILABLE], 'Not Available'],
+ [[], 'Not Available'],
+ [[100, 200, FIAT_UNAVAILABLE, 300], 'Total = $600'],
+ [[-100, -200, FIAT_UNAVAILABLE, -300], 'Total = $600'],
+ ])('when fiatAmounts is %s it renders %s', (fiatAmounts, expected) => {
+ const { queryByText } = renderWithProvider(
+ ,
+ { state: mockStateWithShowingFiatOnTestnets },
+ );
+ expect(queryByText(expected)).toBeDefined();
+ });
+
+ it('does not render anything if hideFiatForTestnet is true', () => {
+ const { queryByText } = renderWithProvider(
+ ,
+ { state: mockStateWithHidingFiatOnTestnets },
+ );
+ expect(queryByText('600')).toBe(null);
+ });
});
});
diff --git a/app/components/UI/SimulationDetails/FiatDisplay/FiatDisplay.tsx b/app/components/UI/SimulationDetails/FiatDisplay/FiatDisplay.tsx
index b7619a1d1e3..58d65d86171 100644
--- a/app/components/UI/SimulationDetails/FiatDisplay/FiatDisplay.tsx
+++ b/app/components/UI/SimulationDetails/FiatDisplay/FiatDisplay.tsx
@@ -9,6 +9,7 @@ import Text, {
import { strings } from '../../../../../locales/i18n';
import useFiatFormatter from './useFiatFormatter';
import { FIAT_UNAVAILABLE, FiatAmount } from '../types';
+import useHideFiatForTestnet from '../../../hooks/useHideFiatForTestnet';
const styleSheet = () =>
StyleSheet.create({
@@ -48,9 +49,14 @@ export function calculateTotalFiat(fiatAmounts: FiatAmount[]): number {
export const IndividualFiatDisplay: React.FC<{ fiatAmount: FiatAmount }> = ({
fiatAmount,
}) => {
+ const hideFiatForTestnet = useHideFiatForTestnet();
const { styles } = useStyles(styleSheet, {});
const fiatFormatter = useFiatFormatter();
+ if (hideFiatForTestnet) {
+ return null;
+ }
+
if (fiatAmount === FIAT_UNAVAILABLE) {
return ;
}
@@ -72,10 +78,15 @@ export const IndividualFiatDisplay: React.FC<{ fiatAmount: FiatAmount }> = ({
export const TotalFiatDisplay: React.FC<{
fiatAmounts: FiatAmount[];
}> = ({ fiatAmounts }) => {
+ const hideFiatForTestnet = useHideFiatForTestnet();
const { styles } = useStyles(styleSheet, {});
const fiatFormatter = useFiatFormatter();
const totalFiat = calculateTotalFiat(fiatAmounts);
+ if (hideFiatForTestnet) {
+ return null;
+ }
+
return totalFiat === 0 ? (
) : (
diff --git a/app/components/UI/SimulationDetails/SimulationDetails.stories.tsx b/app/components/UI/SimulationDetails/SimulationDetails.stories.tsx
index e2f031a1674..ba4c600fc44 100644
--- a/app/components/UI/SimulationDetails/SimulationDetails.stories.tsx
+++ b/app/components/UI/SimulationDetails/SimulationDetails.stories.tsx
@@ -27,11 +27,12 @@ const DUMMY_BALANCE_CHANGE = {
const CHAIN_ID_MOCK = '0x1';
const ERC20_TOKEN_1_MOCK = '0x2260fac5e5542a773aa44fbcfedf7c193bc2c599'; // WBTC
const ERC20_TOKEN_2_MOCK = '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'; // USDC
+const ERC20_TOKEN_3_MOCK = '0xabcd6991c6218b36c1d19d4a2e9eb0ce36056789'; // UNKOWN
const ERC721_TOKEN_MOCK = '0x06012c8cf97bead5deae237070f9587f8e7a266d'; // CryptoKitties
const ERC1155_TOKEN_MOCK = '0x60e4d786628fea6478f785a6d7e704777c86a7c6'; // MAYC
const preloadedEngineState = {
- settings: { useBlockieIcon: false },
+ settings: { useBlockieIcon: false, showFiatInTestnets: true },
engine: {
backgroundState: {
PreferencesController: {
@@ -156,7 +157,7 @@ export const MultipleTokens: Story = {
{
...DUMMY_BALANCE_CHANGE,
address: ERC20_TOKEN_1_MOCK,
- difference: '0x123456',
+ difference: '0x1323232333232320',
isDecrease: false,
standard: SimulationTokenStandard.erc20,
},
@@ -183,6 +184,13 @@ export const MultipleTokens: Story = {
id: '0x1155',
standard: SimulationTokenStandard.erc1155,
},
+ {
+ ...DUMMY_BALANCE_CHANGE,
+ address: ERC20_TOKEN_3_MOCK,
+ difference: '0x123456901',
+ isDecrease: false,
+ standard: SimulationTokenStandard.erc20,
+ },
],
},
},
diff --git a/app/components/UI/SimulationDetails/useBalanceChanges.test.ts b/app/components/UI/SimulationDetails/useBalanceChanges.test.ts
index 9bd1109cef9..720c09c5397 100644
--- a/app/components/UI/SimulationDetails/useBalanceChanges.test.ts
+++ b/app/components/UI/SimulationDetails/useBalanceChanges.test.ts
@@ -35,6 +35,8 @@ jest.mock('@metamask/assets-controllers', () => ({
fetchTokenContractExchangeRates: jest.fn(),
}));
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const mockSelectConversionRate = selectConversionRate as any;
const mockGetTokenDetails = getTokenDetails as jest.Mock;
const mockFetchTokenContractExchangeRates =
diff --git a/app/components/UI/SimulationDetails/useBalanceChanges.ts b/app/components/UI/SimulationDetails/useBalanceChanges.ts
index 0052773bb6b..9dfbbb91943 100644
--- a/app/components/UI/SimulationDetails/useBalanceChanges.ts
+++ b/app/components/UI/SimulationDetails/useBalanceChanges.ts
@@ -184,7 +184,11 @@ export default function useBalanceChanges(
simulationData ?? {};
const erc20TokenAddresses = tokenBalanceChanges
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
.filter((tbc: any) => tbc.standard === SimulationTokenStandard.erc20)
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
.map((tbc: any) => tbc.address);
const erc20Decimals = useAsyncResultOrThrow(
diff --git a/app/components/UI/SkipAccountSecurityModal/__snapshots__/index.test.tsx.snap b/app/components/UI/SkipAccountSecurityModal/__snapshots__/index.test.tsx.snap
index fbce16f317e..72963d409d4 100644
--- a/app/components/UI/SkipAccountSecurityModal/__snapshots__/index.test.tsx.snap
+++ b/app/components/UI/SkipAccountSecurityModal/__snapshots__/index.test.tsx.snap
@@ -52,7 +52,7 @@ exports[`HintModal should render correctly 1`] = `
size={12}
style={
{
- "color": "#24272A",
+ "color": "#141618",
"fontSize": 16,
}
}
@@ -65,7 +65,7 @@ exports[`HintModal should render correctly 1`] = `
style={
{
"alignSelf": "center",
- "color": "#D73847",
+ "color": "#d73847",
}
}
testID="skip-backup-warning"
@@ -73,7 +73,7 @@ exports[`HintModal should render correctly 1`] = `
StyleSheet.create({
@@ -85,8 +79,8 @@ const SkipAccountSecurityModal = ({
return (
{strings('account_backup_step_1.skip_check')}
diff --git a/app/components/UI/SliderButton/__snapshots__/index.test.tsx.snap b/app/components/UI/SliderButton/__snapshots__/index.test.tsx.snap
index 7db97506d5b..113c8979836 100644
--- a/app/components/UI/SliderButton/__snapshots__/index.test.tsx.snap
+++ b/app/components/UI/SliderButton/__snapshots__/index.test.tsx.snap
@@ -7,7 +7,7 @@ exports[`SliderButton should render correctly 1`] = `
[
{
"elevation": 0,
- "shadowColor": "#0376C933",
+ "shadowColor": "#0376c933",
"shadowOffset": {
"height": 2,
"width": 0,
@@ -24,7 +24,7 @@ exports[`SliderButton should render correctly 1`] = `
style={
{
"alignItems": "center",
- "backgroundColor": "#0260A4",
+ "backgroundColor": "#0260a4",
"borderRadius": 60,
"height": 60,
"justifyContent": "center",
@@ -91,7 +91,7 @@ exports[`SliderButton should render correctly 1`] = `
StyleSheet.create({
container: {
...shadows.size.sm,
- shadowColor: colors.primary.shadow,
+ shadowColor: colors.shadow.primary,
elevation: 0, // shadow colors not supported on Android. nothing > gray shadow
},
disabledContainer: {
diff --git a/app/components/UI/SlippageSlider/__snapshots__/index.test.tsx.snap b/app/components/UI/SlippageSlider/__snapshots__/index.test.tsx.snap
index 2ee43a72c02..60d33af2f76 100644
--- a/app/components/UI/SlippageSlider/__snapshots__/index.test.tsx.snap
+++ b/app/components/UI/SlippageSlider/__snapshots__/index.test.tsx.snap
@@ -33,8 +33,8 @@ exports[`SlippageSlider should render correctly 1`] = `
style={
{
"alignItems": "center",
- "backgroundColor": "#0376C919",
- "borderColor": "#0376C919",
+ "backgroundColor": "#0376c91a",
+ "borderColor": "#0376c91a",
"borderRadius": 9,
"borderWidth": 2,
"flexDirection": "row",
@@ -47,7 +47,7 @@ exports[`SlippageSlider should render correctly 1`] = `
key="0"
style={
{
- "backgroundColor": "#0376C9",
+ "backgroundColor": "#0376c9",
"borderRadius": 5,
"height": 5,
"opacity": 0.5,
@@ -59,7 +59,7 @@ exports[`SlippageSlider should render correctly 1`] = `
key="1"
style={
{
- "backgroundColor": "#0376C9",
+ "backgroundColor": "#0376c9",
"borderRadius": 5,
"height": 5,
"opacity": 0.5,
@@ -71,7 +71,7 @@ exports[`SlippageSlider should render correctly 1`] = `
key="2"
style={
{
- "backgroundColor": "#0376C9",
+ "backgroundColor": "#0376c9",
"borderRadius": 5,
"height": 5,
"opacity": 0.5,
@@ -83,7 +83,7 @@ exports[`SlippageSlider should render correctly 1`] = `
key="3"
style={
{
- "backgroundColor": "#0376C9",
+ "backgroundColor": "#0376c9",
"borderRadius": 5,
"height": 5,
"opacity": 0.5,
@@ -95,7 +95,7 @@ exports[`SlippageSlider should render correctly 1`] = `
key="4"
style={
{
- "backgroundColor": "#0376C9",
+ "backgroundColor": "#0376c9",
"borderRadius": 5,
"height": 5,
"opacity": 0.5,
@@ -163,14 +163,14 @@ exports[`SlippageSlider should render correctly 1`] = `
>
({
chainId: selectChainId(state),
ticker: selectTicker(state),
balances: selectContractBalances(state),
- selectedAddress: selectSelectedAddress(state),
+ selectedAddress: selectSelectedInternalAccountChecksummedAddress(state),
conversionRate: selectConversionRate(state),
currentCurrency: selectCurrentCurrency(state),
isInPolling: state.engine.backgroundState.SwapsController.isInPolling,
diff --git a/app/components/UI/Swaps/SwapsLiveness.ts b/app/components/UI/Swaps/SwapsLiveness.ts
index c95922d1f94..60aa6c6211c 100644
--- a/app/components/UI/Swaps/SwapsLiveness.ts
+++ b/app/components/UI/Swaps/SwapsLiveness.ts
@@ -34,6 +34,8 @@ function SwapLiveness() {
setLiveness(chainId, featureFlags);
} catch (error) {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
Logger.error(error as any, 'Swaps: error while fetching swaps liveness');
setLiveness(chainId, null);
}
diff --git a/app/components/UI/Swaps/components/TokenIcon.js b/app/components/UI/Swaps/components/TokenIcon.js
index da256dde30c..2e201eaa107 100644
--- a/app/components/UI/Swaps/components/TokenIcon.js
+++ b/app/components/UI/Swaps/components/TokenIcon.js
@@ -87,9 +87,10 @@ EmptyIcon.propTypes = {
big: PropTypes.bool,
biggest: PropTypes.bool,
style: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
+ testID: PropTypes.string,
};
-function TokenIcon({ symbol, icon, medium, big, biggest, style }) {
+function TokenIcon({ symbol, icon, medium, big, biggest, style, testID }) {
const [showFallback, setShowFallback] = useState(false);
const { colors } = useTheme();
const styles = createStyles(colors);
@@ -114,6 +115,7 @@ function TokenIcon({ symbol, icon, medium, big, biggest, style }) {
if (source && !showFallback) {
return (
setShowFallback(true)}
@@ -130,7 +132,13 @@ function TokenIcon({ symbol, icon, medium, big, biggest, style }) {
if (symbol) {
return (
-
+
({
accounts: selectAccounts(state),
conversionRate: selectConversionRate(state),
currentCurrency: selectCurrentCurrency(state),
- selectedAddress: selectSelectedAddress(state),
+ selectedAddress: selectSelectedInternalAccountChecksummedAddress(state),
tokenExchangeRates: selectContractExchangeRates(state),
balances: selectContractBalances(state),
chainId: selectChainId(state),
diff --git a/app/components/UI/Swaps/components/__snapshots__/TokenIcon.test.js.snap b/app/components/UI/Swaps/components/__snapshots__/TokenIcon.test.js.snap
index ce5826565a6..7d76d1bfc00 100644
--- a/app/components/UI/Swaps/components/__snapshots__/TokenIcon.test.js.snap
+++ b/app/components/UI/Swaps/components/__snapshots__/TokenIcon.test.js.snap
@@ -35,7 +35,7 @@ exports[`TokenIcon component should Render correctly 3`] = `
style={
[
{
- "color": "#24272A",
+ "color": "#141618",
"fontSize": 16,
"textAlign": "center",
"textAlignVertical": "center",
@@ -121,13 +121,13 @@ exports[`TokenIcon component should Render correctly 7`] = `
style={
[
{
- "color": "#24272A",
+ "color": "#141618",
"fontSize": 16,
"textAlign": "center",
"textAlignVertical": "center",
},
{
- "color": "#24272A",
+ "color": "#141618",
"fontSize": 22,
},
undefined,
diff --git a/app/components/UI/Swaps/index.js b/app/components/UI/Swaps/index.js
index 665bfdcfe09..e7a2ef448fa 100644
--- a/app/components/UI/Swaps/index.js
+++ b/app/components/UI/Swaps/index.js
@@ -80,7 +80,7 @@ import {
import { selectContractExchangeRates } from '../../../selectors/tokenRatesController';
import { selectAccounts } from '../../../selectors/accountTrackerController';
import { selectContractBalances } from '../../../selectors/tokenBalancesController';
-import { selectSelectedAddress } from '../../../selectors/preferencesController';
+import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController';
import AccountSelector from '../Ramp/components/AccountSelector';
import {
SWAP_SOURCE_TOKEN,
@@ -1009,7 +1009,7 @@ const mapStateToProps = (state) => ({
swapsControllerTokens: swapsControllerTokens(state),
accounts: selectAccounts(state),
balances: selectContractBalances(state),
- selectedAddress: selectSelectedAddress(state),
+ selectedAddress: selectSelectedInternalAccountChecksummedAddress(state),
conversionRate: selectConversionRate(state),
currentCurrency: selectCurrentCurrency(state),
tokenExchangeRates: selectContractExchangeRates(state),
diff --git a/app/components/UI/SwitchCustomNetwork/__snapshots__/index.test.tsx.snap b/app/components/UI/SwitchCustomNetwork/__snapshots__/index.test.tsx.snap
index 013d39ed8c6..35bd474aa89 100644
--- a/app/components/UI/SwitchCustomNetwork/__snapshots__/index.test.tsx.snap
+++ b/app/components/UI/SwitchCustomNetwork/__snapshots__/index.test.tsx.snap
@@ -4,7 +4,7 @@ exports[`SwitchCustomNetwork should render correctly 1`] = `
{
const component = section?.element;
if (!component && !isValidElementName(component)) {
diff --git a/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap b/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap
index d68d832dd85..4aaccc2fc58 100644
--- a/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap
+++ b/app/components/UI/Tokens/__snapshots__/index.test.tsx.snap
@@ -307,7 +307,7 @@ exports[`Tokens should hide zero balance tokens when setting is on 1`] = `
}
removeClippedSubviews={false}
@@ -425,7 +425,7 @@ exports[`Tokens should hide zero balance tokens when setting is on 1`] = `
accessibilityRole="text"
style={
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 32,
"fontWeight": "500",
@@ -449,7 +449,7 @@ exports[`Tokens should hide zero balance tokens when setting is on 1`] = `
"alignItems": "center",
"alignSelf": "stretch",
"backgroundColor": "transparent",
- "borderColor": "#0376C9",
+ "borderColor": "#0376c9",
"borderRadius": 20,
"borderWidth": 1,
"flexDirection": "row",
@@ -466,7 +466,7 @@ exports[`Tokens should hide zero balance tokens when setting is on 1`] = `
accessibilityRole="text"
style={
{
- "color": "#0376C9",
+ "color": "#0376c9",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
@@ -478,7 +478,7 @@ exports[`Tokens should hide zero balance tokens when setting is on 1`] = `
Portfolio
}
removeClippedSubviews={false}
@@ -1599,7 +1599,7 @@ exports[`Tokens should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 32,
"fontWeight": "500",
@@ -1623,7 +1623,7 @@ exports[`Tokens should render correctly 1`] = `
"alignItems": "center",
"alignSelf": "stretch",
"backgroundColor": "transparent",
- "borderColor": "#0376C9",
+ "borderColor": "#0376c9",
"borderRadius": 20,
"borderWidth": 1,
"flexDirection": "row",
@@ -1640,7 +1640,7 @@ exports[`Tokens should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#0376C9",
+ "color": "#0376c9",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
@@ -1652,7 +1652,7 @@ exports[`Tokens should render correctly 1`] = `
Portfolio
}
removeClippedSubviews={false}
@@ -2781,7 +2781,7 @@ exports[`Tokens should show all balance tokens when hideZeroBalanceTokens settin
accessibilityRole="text"
style={
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 32,
"fontWeight": "500",
@@ -2805,7 +2805,7 @@ exports[`Tokens should show all balance tokens when hideZeroBalanceTokens settin
"alignItems": "center",
"alignSelf": "stretch",
"backgroundColor": "transparent",
- "borderColor": "#0376C9",
+ "borderColor": "#0376c9",
"borderRadius": 20,
"borderWidth": 1,
"flexDirection": "row",
@@ -2822,7 +2822,7 @@ exports[`Tokens should show all balance tokens when hideZeroBalanceTokens settin
accessibilityRole="text"
style={
{
- "color": "#0376C9",
+ "color": "#0376c9",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
@@ -2834,7 +2834,7 @@ exports[`Tokens should show all balance tokens when hideZeroBalanceTokens settin
Portfolio
{
});
const Stack = createStackNavigator();
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const renderComponent = (state: any = {}) =>
renderWithProvider(
diff --git a/app/components/UI/Tokens/index.tsx b/app/components/UI/Tokens/index.tsx
index 69b830cfc35..ecdcf614ee3 100644
--- a/app/components/UI/Tokens/index.tsx
+++ b/app/components/UI/Tokens/index.tsx
@@ -109,6 +109,8 @@ const Tokens: React.FC = ({ tokens }) => {
const { colors } = useTheme();
const { trackEvent } = useMetrics();
const styles = createStyles(colors);
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const navigation = useNavigation>();
const [tokenToRemove, setTokenToRemove] = useState();
const [isAddTokenEnabled, setIsAddTokenEnabled] = useState(true);
@@ -127,15 +129,21 @@ const Tokens: React.FC = ({ tokens }) => {
const currentCurrency = useSelector(selectCurrentCurrency);
const conversionRate = useSelector(selectConversionRate);
const primaryCurrency = useSelector(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(state: any) => state.settings.primaryCurrency,
);
const { data: tokenBalances } = useTokenBalancesController();
const tokenExchangeRates = useSelector(selectContractExchangeRates);
const hideZeroBalanceTokens = useSelector(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(state: any) => state.settings.hideZeroBalanceTokens,
);
const detectedTokens = useSelector(selectDetectedTokens);
const isTokenDetectionEnabled = useSelector(selectUseTokenDetection);
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const browserTabs = useSelector((state: any) => state.browser.tabs);
const isOriginalNativeTokenSymbol = useIsOriginalNativeTokenSymbol(
@@ -667,6 +675,8 @@ const Tokens: React.FC = ({ tokens }) => {
};
const removeToken = async () => {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const { TokensController }: any = Engine.context;
const tokenAddress = tokenToRemove?.address;
const symbol = tokenToRemove?.symbol;
diff --git a/app/components/UI/TransactionElement/TransactionDetails/index.js b/app/components/UI/TransactionElement/TransactionDetails/index.js
index ded80f167bd..5a5eca528d1 100644
--- a/app/components/UI/TransactionElement/TransactionDetails/index.js
+++ b/app/components/UI/TransactionElement/TransactionDetails/index.js
@@ -38,7 +38,7 @@ import {
} from '../../../../selectors/currencyRateController';
import { selectTokensByAddress } from '../../../../selectors/tokensController';
import { selectContractExchangeRates } from '../../../../selectors/tokenRatesController';
-import { selectSelectedAddress } from '../../../../selectors/preferencesController';
+import { selectSelectedInternalAccountChecksummedAddress } from '../../../../selectors/accountsController';
import { regex } from '../../../../../app/util/regex';
import { selectShouldUseSmartTransaction } from '../../../../selectors/smartTransactionsController';
@@ -423,7 +423,7 @@ const mapStateToProps = (state) => ({
providerConfig: selectProviderConfig(state),
chainId: selectChainId(state),
networkConfigurations: selectNetworkConfigurations(state),
- selectedAddress: selectSelectedAddress(state),
+ selectedAddress: selectSelectedInternalAccountChecksummedAddress(state),
transactions: state.engine.backgroundState.TransactionController.transactions,
ticker: selectTicker(state),
tokens: selectTokensByAddress(state),
diff --git a/app/components/UI/TransactionElement/TransactionDetails/index.test.tsx b/app/components/UI/TransactionElement/TransactionDetails/index.test.tsx
index c7e8ff3d639..0d5ea358db1 100644
--- a/app/components/UI/TransactionElement/TransactionDetails/index.test.tsx
+++ b/app/components/UI/TransactionElement/TransactionDetails/index.test.tsx
@@ -4,11 +4,15 @@ import configureMockStore from 'redux-mock-store';
import { shallow } from 'enzyme';
import { Provider } from 'react-redux';
import initialBackgroundState from '../../../../util/test/initial-background-state.json';
+import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../../util/test/accountsControllerTestUtils';
const mockStore = configureMockStore();
const initialState = {
engine: {
- backgroundState: initialBackgroundState,
+ backgroundState: {
+ ...initialBackgroundState,
+ AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE,
+ },
},
};
const store = mockStore(initialState);
diff --git a/app/components/UI/TransactionElement/index.js b/app/components/UI/TransactionElement/index.js
index a916b87399e..2801450fe07 100644
--- a/app/components/UI/TransactionElement/index.js
+++ b/app/components/UI/TransactionElement/index.js
@@ -33,10 +33,8 @@ import {
selectChainId,
selectTicker,
} from '../../../selectors/networkController';
-import {
- selectIdentities,
- selectSelectedAddress,
-} from '../../../selectors/preferencesController';
+import { selectIdentities } from '../../../selectors/preferencesController';
+import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController';
const createStyles = (colors, typography) =>
StyleSheet.create({
@@ -297,6 +295,8 @@ class TransactionElement extends PureComponent {
: transactionIconSwap;
break;
case TRANSACTION_TYPES.APPROVE:
+ case TRANSACTION_TYPES.INCREASE_ALLOWANCE:
+ case TRANSACTION_TYPES.SET_APPROVAL_FOR_ALL:
icon = isFailedTransaction
? transactionIconApproveFailed
: transactionIconApprove;
@@ -607,7 +607,7 @@ const mapStateToProps = (state) => ({
chainId: selectChainId(state),
identities: selectIdentities(state),
primaryCurrency: state.settings.primaryCurrency,
- selectedAddress: selectSelectedAddress(state),
+ selectedAddress: selectSelectedInternalAccountChecksummedAddress(state),
swapsTransactions:
state.engine.backgroundState.TransactionController.swapsTransactions || {},
swapsTokens: state.engine.backgroundState.SwapsController.tokens,
diff --git a/app/components/UI/TransactionElement/index.test.tsx b/app/components/UI/TransactionElement/index.test.tsx
index aaddb7bab75..c14056f2f03 100644
--- a/app/components/UI/TransactionElement/index.test.tsx
+++ b/app/components/UI/TransactionElement/index.test.tsx
@@ -4,11 +4,15 @@ import configureMockStore from 'redux-mock-store';
import { shallow } from 'enzyme';
import { Provider } from 'react-redux';
import initialBackgroundState from '../../../util/test/initial-background-state.json';
+import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../util/test/accountsControllerTestUtils';
const mockStore = configureMockStore();
const initialState = {
engine: {
- backgroundState: initialBackgroundState,
+ backgroundState: {
+ ...initialBackgroundState,
+ AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE,
+ },
},
settings: {
primaryCurrency: 'ETH',
diff --git a/app/components/UI/TransactionElement/utils.js b/app/components/UI/TransactionElement/utils.js
index bc391969aa1..1f6f7ef9a45 100644
--- a/app/components/UI/TransactionElement/utils.js
+++ b/app/components/UI/TransactionElement/utils.js
@@ -605,6 +605,10 @@ function decodeConfirmTx(args) {
let transactionType;
if (actionKey === strings('transactions.approve'))
transactionType = TRANSACTION_TYPES.APPROVE;
+ else if (actionKey === strings('transactions.increase_allowance'))
+ transactionType = TRANSACTION_TYPES.INCREASE_ALLOWANCE;
+ else if (actionKey === strings('transactions.set_approval_for_all'))
+ transactionType = TRANSACTION_TYPES.SET_APPROVAL_FOR_ALL;
else if (actionKey === strings('transactions.swaps_transaction'))
transactionType = TRANSACTION_TYPES.SWAPS_TRANSACTION;
else if (
diff --git a/app/components/UI/TransactionElement/utils.test.js b/app/components/UI/TransactionElement/utils.test.js
index d4a251629d3..5e85a9abdbb 100644
--- a/app/components/UI/TransactionElement/utils.test.js
+++ b/app/components/UI/TransactionElement/utils.test.js
@@ -1,108 +1,290 @@
-import { decodeIncomingTransfer } from './utils';
-describe('decodeIncomingTransfer', () => {
- it('should decode an incoming transfer', () => {
- // Arrange
- const args = {
- tx: {
- txParams: {
- to: '0x77648f1407986479fb1fa5cc3597084b5dbdb057',
- from: '0x1440ec793ae50fa046b95bfeca5af475b6003f9e',
- value: '52daf0',
- },
- transferInformation: {
- symbol: 'USDT',
- decimals: 6,
- contractAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',
+import {
+ CONTRACT_CREATION_SIGNATURE,
+ TRANSACTION_TYPES,
+} from '../../../util/transactions';
+import decodeTransaction, { decodeIncomingTransfer } from './utils';
+
+jest.mock('../../../core/Engine', () => ({
+ context: {
+ KeyringController: {
+ getQRKeyringState: async () => ({ subscribe: () => ({}) }),
+ },
+ TokenListController: {
+ state: {
+ tokenList: {
+ '0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f': {
+ address: '0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f',
+ symbol: 'SNX',
+ decimals: 18,
+ name: 'Synthetix Network Token',
+ iconUrl:
+ 'https://static.cx.metamask.io/api/v1/tokenIcons/1/0xc011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f.png',
+ type: 'erc20',
+ aggregators: [
+ 'Aave',
+ 'Bancor',
+ 'CMC',
+ 'Crypto.com',
+ 'CoinGecko',
+ '1inch',
+ 'PMM',
+ 'Synthetix',
+ 'Zerion',
+ 'Lifi',
+ ],
+ occurrences: 10,
+ fees: {
+ '0x5fd79d46eba7f351fe49bff9e87cdea6c821ef9f': 0,
+ '0xda4ef8520b1a57d7d63f1e249606d1a459698876': 0,
+ },
+ },
},
- hash: '0x942d7843454266b81bf631022aa5f3f944691731b62d67c4e80c4bb5740058bb',
},
- currentCurrency: 'usd',
- contractExchangeRates: {},
- totalGas: '0x64',
- actionKey: 'key',
- primaryCurrency: 'ETH',
- selectedAddress: '0x77648f1407986479fb1fa5cc3597084b5dbdb057',
- ticker: 'ETH',
- };
+ tokensChainsCache: {},
+ preventPollingOnNetworkRestart: false,
+ },
+ },
+}));
+
+describe('Utils', () => {
+ describe('decodeIncomingTransfer', () => {
+ it('should decode an incoming transfer', () => {
+ // Arrange
+ const args = {
+ tx: {
+ txParams: {
+ to: '0x77648f1407986479fb1fa5cc3597084b5dbdb057',
+ from: '0x1440ec793ae50fa046b95bfeca5af475b6003f9e',
+ value: '52daf0',
+ },
+ transferInformation: {
+ symbol: 'USDT',
+ decimals: 6,
+ contractAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',
+ },
+ hash: '0x942d7843454266b81bf631022aa5f3f944691731b62d67c4e80c4bb5740058bb',
+ },
+ currentCurrency: 'usd',
+ contractExchangeRates: {},
+ totalGas: '0x64',
+ actionKey: 'key',
+ primaryCurrency: 'ETH',
+ selectedAddress: '0x77648f1407986479fb1fa5cc3597084b5dbdb057',
+ ticker: 'ETH',
+ };
+
+ // Act
+ const [transactionElement, transactionDetails] =
+ decodeIncomingTransfer(args);
- // Act
- const [transactionElement, transactionDetails] =
- decodeIncomingTransfer(args);
-
- // Assert
- expect(transactionElement).toEqual({
- actionKey: 'key',
- renderFrom: '0x1440ec793aE50fA046B95bFeCa5aF475b6003f9e',
- renderTo: '0x77648F1407986479fb1fA5Cc3597084B5dbDB057',
- value: '5.43 USDT',
- fiatValue: undefined,
- isIncomingTransfer: true,
- transactionType: 'transaction_received_token',
+ // Assert
+ expect(transactionElement).toEqual({
+ actionKey: 'key',
+ renderFrom: '0x1440ec793aE50fA046B95bFeCa5aF475b6003f9e',
+ renderTo: '0x77648F1407986479fb1fA5Cc3597084B5dbDB057',
+ value: '5.43 USDT',
+ fiatValue: undefined,
+ isIncomingTransfer: true,
+ transactionType: 'transaction_received_token',
+ });
+ expect(transactionDetails).toEqual({
+ renderTotalGas: '< 0.00001 ETH',
+ renderValue: '5.43 USDT',
+ renderFrom: '0x1440ec793aE50fA046B95bFeCa5aF475b6003f9e',
+ renderTo: '0x77648F1407986479fb1fA5Cc3597084B5dbDB057',
+ hash: '0x942d7843454266b81bf631022aa5f3f944691731b62d67c4e80c4bb5740058bb',
+ transactionType: 'transaction_received_token',
+ summaryAmount: '5.43 USDT',
+ summaryFee: '< 0.00001 ETH',
+ summaryTotalAmount: '5.43 USDT / < 0.00001 ETH',
+ summarySecondaryTotalAmount: undefined,
+ });
});
- expect(transactionDetails).toEqual({
- renderTotalGas: '< 0.00001 ETH',
- renderValue: '5.43 USDT',
- renderFrom: '0x1440ec793aE50fA046B95bFeCa5aF475b6003f9e',
- renderTo: '0x77648F1407986479fb1fA5Cc3597084B5dbDB057',
- hash: '0x942d7843454266b81bf631022aa5f3f944691731b62d67c4e80c4bb5740058bb',
- transactionType: 'transaction_received_token',
- summaryAmount: '5.43 USDT',
- summaryFee: '< 0.00001 ETH',
- summaryTotalAmount: '5.43 USDT / < 0.00001 ETH',
- summarySecondaryTotalAmount: undefined,
+
+ it('should decode an incoming transfer with big number with 10 digits', () => {
+ // Arrange
+ const args = {
+ tx: {
+ txParams: {
+ to: '0x77648f1407986479fb1fa5cc3597084b5dbdb057',
+ from: '0x1440ec793ae50fa046b95bfeca5af475b6003f9e',
+ value: '3B9ACA00', // 1000000000 in decimal
+ },
+ transferInformation: {
+ symbol: 'USDT',
+ decimals: 6,
+ contractAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',
+ },
+ hash: '0x942d7843454266b81bf631022aa5f3f944691731b62d67c4e80c4bb5740058bb',
+ },
+ currentCurrency: 'usd',
+ contractExchangeRates: {},
+ totalGas: '0x64',
+ actionKey: 'key',
+ primaryCurrency: 'ETH',
+ selectedAddress: '0x77648f1407986479fb1fa5cc3597084b5dbdb057',
+ ticker: 'ETH',
+ };
+
+ // Act
+ const [transactionElement, transactionDetails] =
+ decodeIncomingTransfer(args);
+
+ // Assert
+ expect(transactionElement).toEqual({
+ actionKey: 'key',
+ renderFrom: '0x1440ec793aE50fA046B95bFeCa5aF475b6003f9e',
+ renderTo: '0x77648F1407986479fb1fA5Cc3597084B5dbDB057',
+ value: '1000 USDT',
+ fiatValue: undefined,
+ isIncomingTransfer: true,
+ transactionType: 'transaction_received_token',
+ });
+ expect(transactionDetails).toEqual({
+ renderTotalGas: '< 0.00001 ETH',
+ renderValue: '1000 USDT',
+ renderFrom: '0x1440ec793aE50fA046B95bFeCa5aF475b6003f9e',
+ renderTo: '0x77648F1407986479fb1fA5Cc3597084B5dbDB057',
+ hash: '0x942d7843454266b81bf631022aa5f3f944691731b62d67c4e80c4bb5740058bb',
+ transactionType: 'transaction_received_token',
+ summaryAmount: '1000 USDT',
+ summaryFee: '< 0.00001 ETH',
+ summaryTotalAmount: '1000 USDT / < 0.00001 ETH',
+ summarySecondaryTotalAmount: undefined,
+ });
});
});
- it('should decode an incoming transfer with big number with 10 digits', () => {
- // Arrange
- const args = {
- tx: {
- txParams: {
- to: '0x77648f1407986479fb1fa5cc3597084b5dbdb057',
- from: '0x1440ec793ae50fa046b95bfeca5af475b6003f9e',
- value: '3B9ACA00', // 1000000000 in decimal
+ describe('decodeTransaction', () => {
+ const expectedTransactionDetails = {
+ hash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
+ renderFrom: '0xABcdEFABcdEFabcdEfAbCdefabcdeFABcDEFabCD',
+ renderGas: '21000',
+ renderGasPrice: 1,
+ renderTo: '0x1234567890AbcdEF1234567890aBcdef12345678',
+ renderTotalGas: '0.00002 ETH',
+ renderValue: '0 ETH',
+ summaryAmount: '0 ETH',
+ summaryFee: '0.00002 ETH',
+ summarySecondaryTotalAmount: undefined,
+ summaryTotalAmount: '0.00002 ETH',
+ };
+
+ const txParamsMock = {
+ to: '0x1234567890abcdef1234567890abcdef12345678',
+ from: '0xabcdefabcdefabcdefabcdefabcdefabcdefabcd',
+ value: '0',
+ data: '0xa22cb4650000000000000000000000000000000000000000000000000000000000000001',
+ gas: '0x5208',
+ gasPrice: '0x3b9aca00',
+ };
+
+ it('decodes a transaction with type set approval for all', async () => {
+ const args = {
+ tx: {
+ txParams: txParamsMock,
+ transactionType: TRANSACTION_TYPES.SET_APPROVAL_FOR_ALL,
+ hash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
},
- transferInformation: {
- symbol: 'USDT',
- decimals: 6,
- contractAddress: '0xdac17f958d2ee523a2206206994597c13d831ec7',
+ currentCurrency: 'usd',
+ contractExchangeRates: {},
+ totalGas: '0x5208',
+ actionKey: 'transactions.set_approval_for_all',
+ primaryCurrency: 'ETH',
+ selectedAddress: '0x1234567890abcdef1234567890abcdef12345678',
+ ticker: 'ETH',
+ };
+
+ const result = await decodeTransaction(args);
+
+ expect(result).toEqual([
+ {
+ actionKey: 'Set Approval For All',
+ fiatValue: undefined,
+ renderFrom: '0xABcdEFABcdEFabcdEfAbCdefabcdeFABcDEFabCD',
+ renderTo: '0x1234567890AbcdEF1234567890aBcdef12345678',
+ transactionType: 'transaction_set_approval_for_all',
+ value: '0 ETH',
},
- hash: '0x942d7843454266b81bf631022aa5f3f944691731b62d67c4e80c4bb5740058bb',
- },
- currentCurrency: 'usd',
- contractExchangeRates: {},
- totalGas: '0x64',
- actionKey: 'key',
- primaryCurrency: 'ETH',
- selectedAddress: '0x77648f1407986479fb1fa5cc3597084b5dbdb057',
- ticker: 'ETH',
- };
+ {
+ ...expectedTransactionDetails,
+ transactionType: 'transaction_set_approval_for_all',
+ },
+ ]);
+ });
+
+ it('decodes a transaction with type increase allowance', async () => {
+ const args = {
+ tx: {
+ txParams: {
+ ...txParamsMock,
+ data: '0x39509351',
+ },
+ transactionType: TRANSACTION_TYPES.INCREASE_ALLOWANCE,
+ hash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
+ },
+ currentCurrency: 'usd',
+ contractExchangeRates: {},
+ totalGas: '0x5208',
+ actionKey: 'transactions.increase_allowance',
+ primaryCurrency: 'ETH',
+ selectedAddress: '0x1234567890abcdef1234567890abcdef12345678',
+ ticker: 'ETH',
+ };
+
+ const result = await decodeTransaction(args);
- // Act
- const [transactionElement, transactionDetails] =
- decodeIncomingTransfer(args);
-
- // Assert
- expect(transactionElement).toEqual({
- actionKey: 'key',
- renderFrom: '0x1440ec793aE50fA046B95bFeCa5aF475b6003f9e',
- renderTo: '0x77648F1407986479fb1fA5Cc3597084B5dbDB057',
- value: '1000 USDT',
- fiatValue: undefined,
- isIncomingTransfer: true,
- transactionType: 'transaction_received_token',
+ expect(result).toEqual([
+ {
+ actionKey: 'Increase Allowance',
+ fiatValue: undefined,
+ renderFrom: '0xABcdEFABcdEFabcdEfAbCdefabcdeFABcDEFabCD',
+ renderTo: '0x1234567890AbcdEF1234567890aBcdef12345678',
+ transactionType: 'transaction_increase_allowance',
+ value: '0 ETH',
+ },
+ {
+ ...expectedTransactionDetails,
+ transactionType: 'transaction_increase_allowance',
+ },
+ ]);
});
- expect(transactionDetails).toEqual({
- renderTotalGas: '< 0.00001 ETH',
- renderValue: '1000 USDT',
- renderFrom: '0x1440ec793aE50fA046B95bFeCa5aF475b6003f9e',
- renderTo: '0x77648F1407986479fb1fA5Cc3597084B5dbDB057',
- hash: '0x942d7843454266b81bf631022aa5f3f944691731b62d67c4e80c4bb5740058bb',
- transactionType: 'transaction_received_token',
- summaryAmount: '1000 USDT',
- summaryFee: '< 0.00001 ETH',
- summaryTotalAmount: '1000 USDT / < 0.00001 ETH',
- summarySecondaryTotalAmount: undefined,
+
+ it('decodes a transaction with type contract interactions', async () => {
+ const args = {
+ tx: {
+ txParams: {
+ ...txParamsMock,
+ data: CONTRACT_CREATION_SIGNATURE,
+ },
+ hash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
+ },
+ currentCurrency: 'usd',
+ contractExchangeRates: {},
+ totalGas: '0x5208',
+ actionKey: 'transactions.swaps_transaction',
+ primaryCurrency: 'ETH',
+ selectedAddress: '0x1234567890abcdef1234567890abcdef12345678',
+ ticker: 'ETH',
+ };
+
+ const result = await decodeTransaction(args);
+
+ expect(result).toEqual([
+ {
+ actionKey: 'Contract Deployment',
+ fiatValue: undefined,
+ contractDeployment: true,
+ renderFrom: '0xABcdEFABcdEFabcdEfAbCdefabcdeFABcDEFabCD',
+ renderTo: 'New Contract',
+ transactionType: 'transaction_site_interaction',
+ value: '0.00002 ETH',
+ },
+ {
+ ...expectedTransactionDetails,
+ renderTo: 'New Contract',
+ },
+ ]);
});
});
});
diff --git a/app/components/UI/Transactions/RetryModal/index.tsx b/app/components/UI/Transactions/RetryModal/index.tsx
index ef1224c5dd9..e91598a90ea 100644
--- a/app/components/UI/Transactions/RetryModal/index.tsx
+++ b/app/components/UI/Transactions/RetryModal/index.tsx
@@ -7,6 +7,8 @@ import { strings } from '../../../../../locales/i18n';
import { useTheme } from '../../../../util/theme';
import ActionModal from '../../ActionModal';
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const createStyles = (colors: any) =>
StyleSheet.create({
modal: {
diff --git a/app/components/UI/Transactions/index.js b/app/components/UI/Transactions/index.js
index 23da44f1a27..312bd96b798 100644
--- a/app/components/UI/Transactions/index.js
+++ b/app/components/UI/Transactions/index.js
@@ -59,7 +59,7 @@ import {
} from '../../../selectors/currencyRateController';
import { selectContractExchangeRates } from '../../../selectors/tokenRatesController';
import { selectAccounts } from '../../../selectors/accountTrackerController';
-import { selectSelectedAddress } from '../../../selectors/preferencesController';
+import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController';
import {
TransactionError,
CancelTransactionError,
@@ -866,7 +866,7 @@ const mapStateToProps = (state) => ({
contractExchangeRates: selectContractExchangeRates(state),
conversionRate: selectConversionRate(state),
currentCurrency: selectCurrentCurrency(state),
- selectedAddress: selectSelectedAddress(state),
+ selectedAddress: selectSelectedInternalAccountChecksummedAddress(state),
networkConfigurations: selectNetworkConfigurations(state),
providerConfig: selectProviderConfig(state),
gasFeeEstimates: selectGasFeeEstimates(state),
diff --git a/app/components/UI/Transactions/index.test.tsx b/app/components/UI/Transactions/index.test.tsx
index b0fb62bb481..4cd3c5a9985 100644
--- a/app/components/UI/Transactions/index.test.tsx
+++ b/app/components/UI/Transactions/index.test.tsx
@@ -4,11 +4,15 @@ import configureMockStore from 'redux-mock-store';
import { shallow } from 'enzyme';
import { Provider } from 'react-redux';
import initialBackgroundState from '../../../util/test/initial-background-state.json';
+import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../util/test/accountsControllerTestUtils';
const mockStore = configureMockStore();
const initialState = {
engine: {
- backgroundState: initialBackgroundState,
+ backgroundState: {
+ ...initialBackgroundState,
+ AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE,
+ },
},
settings: {
primaryCurrency: 'USD',
diff --git a/app/components/UI/TurnOffRememberMeModal/styles.ts b/app/components/UI/TurnOffRememberMeModal/styles.ts
index ba461bc1a53..1204096c616 100644
--- a/app/components/UI/TurnOffRememberMeModal/styles.ts
+++ b/app/components/UI/TurnOffRememberMeModal/styles.ts
@@ -2,6 +2,8 @@
import { fontStyles } from '../../../styles/common';
import { StyleSheet } from 'react-native';
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const createStyles = (colors: any) =>
StyleSheet.create({
container: {
diff --git a/app/components/UI/UpdateNeeded/__snapshots__/UpdateNeeded.test.tsx.snap b/app/components/UI/UpdateNeeded/__snapshots__/UpdateNeeded.test.tsx.snap
index 0a0340ba3fa..b83aa3f5690 100644
--- a/app/components/UI/UpdateNeeded/__snapshots__/UpdateNeeded.test.tsx.snap
+++ b/app/components/UI/UpdateNeeded/__snapshots__/UpdateNeeded.test.tsx.snap
@@ -356,7 +356,7 @@ exports[`UpdateNeeded should render correctly 1`] = `
],
{
"alignItems": "center",
- "backgroundColor": "#FFFFFF",
+ "backgroundColor": "#ffffff",
"flex": 1,
"justifyContent": "space-between",
"paddingHorizontal": 24,
@@ -412,7 +412,7 @@ exports[`UpdateNeeded should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "Euclid Circular B",
"fontSize": 32,
"fontWeight": "700",
@@ -429,7 +429,7 @@ exports[`UpdateNeeded should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
@@ -462,7 +462,7 @@ exports[`UpdateNeeded should render correctly 1`] = `
{
"alignItems": "center",
"alignSelf": "stretch",
- "backgroundColor": "#0376C9",
+ "backgroundColor": "#0376c9",
"borderRadius": 20,
"flexDirection": "row",
"height": undefined,
@@ -478,7 +478,7 @@ exports[`UpdateNeeded should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#FFFFFF",
+ "color": "#ffffff",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
@@ -515,7 +515,7 @@ exports[`UpdateNeeded should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#0376C9",
+ "color": "#0376c9",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
diff --git a/app/components/UI/UpdateNeeded/styles.ts b/app/components/UI/UpdateNeeded/styles.ts
index 5a1485f4f54..9a901dac982 100644
--- a/app/components/UI/UpdateNeeded/styles.ts
+++ b/app/components/UI/UpdateNeeded/styles.ts
@@ -1,6 +1,8 @@
/* eslint-disable import/prefer-default-export */
import { StyleSheet } from 'react-native';
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const createStyles = (colors: any) =>
StyleSheet.create({
screen: {
diff --git a/app/components/UI/UrlAutocomplete/__snapshots__/index.test.js.snap b/app/components/UI/UrlAutocomplete/__snapshots__/index.test.js.snap
index 0409eb9b901..3bc95571b8a 100644
--- a/app/components/UI/UrlAutocomplete/__snapshots__/index.test.js.snap
+++ b/app/components/UI/UrlAutocomplete/__snapshots__/index.test.js.snap
@@ -4,7 +4,7 @@ exports[`UrlAutocomplete should render correctly 1`] = `
) => {
const { styles } = useStyles(styleSheet, { style });
@@ -50,6 +52,8 @@ const WalletAccount = ({ style }: WalletAccountProps, ref: React.Ref) => {
accountActionsRef,
}));
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const accountAvatarType = useSelector((state: any) =>
state.settings.useBlockieIcon
? AvatarAccountType.Blockies
diff --git a/app/components/UI/WalletAccount/__snapshots__/WalletAccount.test.tsx.snap b/app/components/UI/WalletAccount/__snapshots__/WalletAccount.test.tsx.snap
index 68d82fb5a86..510d1b649a1 100644
--- a/app/components/UI/WalletAccount/__snapshots__/WalletAccount.test.tsx.snap
+++ b/app/components/UI/WalletAccount/__snapshots__/WalletAccount.test.tsx.snap
@@ -4,7 +4,7 @@ exports[`WalletAccount renders correctly 1`] = `
+ >
+ 0xC496...a756
+
{
const { colors } = useTheme();
@@ -30,6 +31,7 @@ const WalletAction = ({
void;
containerStyle?: ViewStyle;
iconStyle?: ImageStyle;
+ actionID?: string;
}
diff --git a/app/components/UI/WarningAlert/__snapshots__/WarningAlert.test.tsx.snap b/app/components/UI/WarningAlert/__snapshots__/WarningAlert.test.tsx.snap
index c3f5871cdae..b32e14968a8 100644
--- a/app/components/UI/WarningAlert/__snapshots__/WarningAlert.test.tsx.snap
+++ b/app/components/UI/WarningAlert/__snapshots__/WarningAlert.test.tsx.snap
@@ -5,8 +5,8 @@ exports[`ButtonBase should render correctly 1`] = `
style={
[
{
- "backgroundColor": "#FFFFFF",
- "borderColor": "#BF5208",
+ "backgroundColor": "#ffffff",
+ "borderColor": "#bf5208",
"borderRadius": 8,
"bottom": 20,
"left": 16,
@@ -35,7 +35,7 @@ exports[`ButtonBase should render correctly 1`] = `
primary={true}
style={
{
- "color": "#24272A",
+ "color": "#141618",
"lineHeight": 18,
"paddingLeft": 4,
}
diff --git a/app/components/UI/WebsiteIcon/__snapshots__/index.test.tsx.snap b/app/components/UI/WebsiteIcon/__snapshots__/index.test.tsx.snap
index 83f810a3c3f..bdfc9824112 100644
--- a/app/components/UI/WebsiteIcon/__snapshots__/index.test.tsx.snap
+++ b/app/components/UI/WebsiteIcon/__snapshots__/index.test.tsx.snap
@@ -5,7 +5,7 @@ exports[`WebsiteIcon should render correctly 1`] = `
{
const navigation = useNavigation();
const callButton = useCallback(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(onPress: any) => {
dismissModal(() => onPress({ navigation }));
},
[navigation],
);
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const renderSlideElement = (elementInfo: any) => {
switch (elementInfo.type) {
case 'title':
@@ -185,16 +189,24 @@ const WhatsNewModal = () => {
return null;
};
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const renderSlide = (slideInfo: any, index: number) => {
const key = `slide-info-${index}`;
return (
- {slideInfo.map((elementInfo: any, elIndex: number) => {
- const elKey = `${key}-${elIndex}`;
- return {renderSlideElement(elementInfo)};
- })}
+ {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ slideInfo.map((elementInfo: any, elIndex: number) => {
+ const elKey = `${key}-${elIndex}`;
+ return (
+ {renderSlideElement(elementInfo)}
+ );
+ })
+ }
diff --git a/app/components/UI/WhatsNewModal/types.ts b/app/components/UI/WhatsNewModal/types.ts
index c10a16ac2e6..400cda01593 100644
--- a/app/components/UI/WhatsNewModal/types.ts
+++ b/app/components/UI/WhatsNewModal/types.ts
@@ -29,6 +29,8 @@ interface SlideButton {
type: 'button';
buttonType: SlideButtonType;
buttonText: string;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
onPress: (props: { navigation: any }) => void;
}
diff --git a/app/components/UI/WhatsNewModal/whatsNewList.ts b/app/components/UI/WhatsNewModal/whatsNewList.ts
index d7fc56a2c5a..c546a30fdae 100644
--- a/app/components/UI/WhatsNewModal/whatsNewList.ts
+++ b/app/components/UI/WhatsNewModal/whatsNewList.ts
@@ -52,5 +52,23 @@ export const whatsNew: WhatsNew = {
],
] as WhatsNew['slides'])
: []),
+ [
+ {
+ type: 'image',
+ image: require('../../../images/whats_new_transaction_simulation.png'),
+ },
+ {
+ type: 'title',
+ title: strings('whats_new.transaction_simulation.title'),
+ },
+ {
+ type: 'description',
+ description: strings('whats_new.transaction_simulation.description_1'),
+ },
+ {
+ type: 'description',
+ description: strings('whats_new.transaction_simulation.description_2'),
+ },
+ ],
],
};
diff --git a/app/components/Views/AccountActions/AccountActions.test.tsx b/app/components/Views/AccountActions/AccountActions.test.tsx
index a25e5ccd3ec..07f6e5f04ef 100644
--- a/app/components/Views/AccountActions/AccountActions.test.tsx
+++ b/app/components/Views/AccountActions/AccountActions.test.tsx
@@ -15,6 +15,11 @@ import {
VIEW_ETHERSCAN,
} from './AccountActions.constants';
import initialBackgroundState from '../../../util/test/initial-background-state.json';
+import {
+ MOCK_ACCOUNTS_CONTROLLER_STATE,
+ MOCK_ADDRESS_2,
+} from '../../../util/test/accountsControllerTestUtils';
+import { toChecksumHexAddress } from '@metamask/controller-utils';
const mockEngine = Engine;
@@ -23,12 +28,7 @@ const initialState = {
engine: {
backgroundState: {
...initialBackgroundState,
- PreferencesController: {
- selectedAddress: '0xe7E125654064EEa56229f273dA586F10DF96B0a1',
- identities: {
- '0xe7E125654064EEa56229f273dA586F10DF96B0a1': { name: 'Account 1' },
- },
- },
+ AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE,
},
},
};
@@ -93,7 +93,7 @@ describe('AccountActions', () => {
expect(mockNavigate).toHaveBeenCalledWith('Webview', {
screen: 'SimpleWebview',
params: {
- url: 'https://etherscan.io/address/0xe7E125654064EEa56229f273dA586F10DF96B0a1',
+ url: 'https://etherscan.io/address/0xC4966c0D659D99699BFD7EB54D8fafEE40e4a756',
title: 'etherscan.io',
},
});
@@ -107,7 +107,7 @@ describe('AccountActions', () => {
fireEvent.press(getByTestId(SHARE_ADDRESS));
expect(Share.open).toHaveBeenCalledWith({
- message: '0xe7E125654064EEa56229f273dA586F10DF96B0a1',
+ message: toChecksumHexAddress(MOCK_ADDRESS_2),
});
});
diff --git a/app/components/Views/AccountActions/AccountActions.tsx b/app/components/Views/AccountActions/AccountActions.tsx
index 6a083f36cac..a0d387b1fcc 100644
--- a/app/components/Views/AccountActions/AccountActions.tsx
+++ b/app/components/Views/AccountActions/AccountActions.tsx
@@ -26,7 +26,7 @@ import {
selectNetworkConfigurations,
selectProviderConfig,
} from '../../../selectors/networkController';
-import { selectSelectedAddress } from '../../../selectors/preferencesController';
+import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController';
import { strings } from '../../../../locales/i18n';
// Internal dependencies
@@ -52,7 +52,9 @@ const AccountActions = () => {
const providerConfig = useSelector(selectProviderConfig);
- const selectedAddress = useSelector(selectSelectedAddress);
+ const selectedAddress = useSelector(
+ selectSelectedInternalAccountChecksummedAddress,
+ );
const networkConfigurations = useSelector(selectNetworkConfigurations);
const blockExplorer = useMemo(() => {
diff --git a/app/components/Views/AccountBackupStep1/__snapshots__/index.test.tsx.snap b/app/components/Views/AccountBackupStep1/__snapshots__/index.test.tsx.snap
index 3dfa9e4cebf..1f92981eb93 100644
--- a/app/components/Views/AccountBackupStep1/__snapshots__/index.test.tsx.snap
+++ b/app/components/Views/AccountBackupStep1/__snapshots__/index.test.tsx.snap
@@ -54,7 +54,7 @@ exports[`AccountBackupStep1 should render correctly 1`] = `
collapsable={false}
style={
{
- "backgroundColor": "#FFFFFF",
+ "backgroundColor": "#ffffff",
"borderBottomColor": "rgb(216, 216, 216)",
"elevation": 0,
"flex": 1,
@@ -149,7 +149,7 @@ exports[`AccountBackupStep1 should render correctly 1`] = `
style={
{
"height": 15,
- "tintColor": "#24272A",
+ "tintColor": "#141618",
"width": 122,
}
}
@@ -353,7 +353,7 @@ exports[`AccountBackupStep1 should render correctly 1`] = `
@@ -879,7 +879,7 @@ exports[`AccountBackupStep1 should render correctly 1`] = `
@@ -829,7 +829,7 @@ exports[`AccountBackupStep1B should render correctly 1`] = `
style={
[
{
- "color": "#0376C9",
+ "color": "#0376c9",
"fontSize": 12,
},
{
@@ -850,7 +850,7 @@ exports[`AccountBackupStep1B should render correctly 1`] = `
{
props.navigation.navigate('Webview', {
screen: 'SimpleWebview',
params: {
- url: 'https://metamask.zendesk.com/hc/en-us/articles/360015489591-Basic-Safety-Tips',
+ url: 'https://support.metamask.io/privacy-and-security/basic-safety-and-security-tips-for-metamask/',
title: strings('drawer.metamask_support'),
},
});
diff --git a/app/components/Views/AccountConnect/AccountConnect.tsx b/app/components/Views/AccountConnect/AccountConnect.tsx
index 7889c88029f..774e6b12fa2 100644
--- a/app/components/Views/AccountConnect/AccountConnect.tsx
+++ b/app/components/Views/AccountConnect/AccountConnect.tsx
@@ -27,10 +27,8 @@ import { USER_INTENT } from '../../../constants/permissions';
import { MetaMetricsEvents } from '../../../core/Analytics';
import UntypedEngine from '../../../core/Engine';
import { selectAccountsLength } from '../../../selectors/accountTrackerController';
-import {
- selectIdentities,
- selectSelectedAddress,
-} from '../../../selectors/preferencesController';
+import { selectIdentities } from '../../../selectors/preferencesController';
+import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController';
import { isDefaultAccountName } from '../../../util/ENSUtils';
import Logger from '../../../util/Logger';
import getAccountNameWithENS from '../../../util/accounts';
@@ -75,6 +73,8 @@ const createStyles = () =>
});
const AccountConnect = (props: AccountConnectProps) => {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const Engine = UntypedEngine as any;
const { colors } = useTheme();
@@ -86,7 +86,9 @@ const AccountConnect = (props: AccountConnectProps) => {
const [blockedUrl, setBlockedUrl] = useState('');
- const selectedWalletAddress = useSelector(selectSelectedAddress);
+ const selectedWalletAddress = useSelector(
+ selectSelectedInternalAccountChecksummedAddress,
+ );
const [selectedAddresses, setSelectedAddresses] = useState([
selectedWalletAddress,
]);
@@ -103,6 +105,8 @@ const AccountConnect = (props: AccountConnectProps) => {
const [userIntent, setUserIntent] = useState(USER_INTENT.None);
const { toastRef } = useContext(ToastContext);
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const accountAvatarType = useSelector((state: any) =>
state.settings.useBlockieIcon
? AvatarAccountType.Blockies
@@ -336,6 +340,8 @@ const AccountConnect = (props: AccountConnectProps) => {
accountAddress: activeAddress,
accountAvatarType,
});
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (e: any) {
Logger.error(e, 'Error while trying to connect to a dApp.');
} finally {
@@ -367,6 +373,8 @@ const AccountConnect = (props: AccountConnectProps) => {
) as string;
!isMultiSelect && setSelectedAddresses([checksummedAddress]);
trackEvent(MetaMetricsEvents.ACCOUNTS_ADDED_NEW_ACCOUNT);
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (e: any) {
Logger.error(e, 'error while trying to add a new account');
} finally {
diff --git a/app/components/Views/AccountConnect/AccountConnectSingle/AccountConnectSingle.tsx b/app/components/Views/AccountConnect/AccountConnectSingle/AccountConnectSingle.tsx
index 3fab788978e..64574d6fcac 100644
--- a/app/components/Views/AccountConnect/AccountConnectSingle/AccountConnectSingle.tsx
+++ b/app/components/Views/AccountConnect/AccountConnectSingle/AccountConnectSingle.tsx
@@ -50,6 +50,8 @@ const AccountConnectSingle = ({
connection,
}: AccountConnectSingleProps) => {
const { styles } = useStyles(styleSheet, {});
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const accountAvatarType = useSelector((state: any) =>
state.settings.useBlockieIcon
? AvatarAccountType.Blockies
diff --git a/app/components/Views/AccountPermissions/AccountPermissions.tsx b/app/components/Views/AccountPermissions/AccountPermissions.tsx
index e770d42a6af..c6a51d2a392 100755
--- a/app/components/Views/AccountPermissions/AccountPermissions.tsx
+++ b/app/components/Views/AccountPermissions/AccountPermissions.tsx
@@ -54,12 +54,16 @@ import { useMetrics } from '../../../components/hooks/useMetrics';
const AccountPermissions = (props: AccountPermissionsProps) => {
const navigation = useNavigation();
const { trackEvent } = useMetrics();
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const Engine = UntypedEngine as any;
const {
hostInfo: {
metadata: { origin: hostname },
},
} = props.route.params;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const accountAvatarType = useSelector((state: any) =>
state.settings.useBlockieIcon
? AvatarAccountType.Blockies
@@ -69,6 +73,8 @@ const AccountPermissions = (props: AccountPermissionsProps) => {
const accountsLength = useSelector(selectAccountsLength);
const nonTestnetNetworks = useSelector(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(state: any) => Object.keys(selectNetworkConfigurations(state)).length + 1,
);
@@ -89,6 +95,8 @@ const AccountPermissions = (props: AccountPermissionsProps) => {
const { toastRef } = useContext(ToastContext);
const [isLoading, setIsLoading] = useState(false);
const permittedAccountsList = useSelector(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(state: any) => state.engine.backgroundState.PermissionController,
);
const permittedAccountsByHostname = getPermittedAccountsByHostname(
@@ -177,6 +185,8 @@ const AccountPermissions = (props: AccountPermissionsProps) => {
source: metricsSource,
number_of_accounts: accounts?.length,
});
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (e: any) {
Logger.error(e, 'Error while trying to add a new account.');
} finally {
@@ -230,6 +240,8 @@ const AccountPermissions = (props: AccountPermissionsProps) => {
number_of_accounts_connected: connectedAccounts,
number_of_networks: nonTestnetNetworks,
});
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (e: any) {
Logger.error(e, 'Error while trying to connect to a dApp.');
} finally {
diff --git a/app/components/Views/AccountPermissions/AccountPermissionsRevoke/AccountPermissionsRevoke.tsx b/app/components/Views/AccountPermissions/AccountPermissionsRevoke/AccountPermissionsRevoke.tsx
index b6deec5c041..10ff892a81a 100644
--- a/app/components/Views/AccountPermissions/AccountPermissionsRevoke/AccountPermissionsRevoke.tsx
+++ b/app/components/Views/AccountPermissions/AccountPermissionsRevoke/AccountPermissionsRevoke.tsx
@@ -50,6 +50,8 @@ const AccountPermissionsRevoke = ({
secureIcon,
accountAvatarType,
}: AccountPermissionsRevokeProps) => {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const Engine = UntypedEngine as any;
const { styles } = useStyles(styleSheet, {});
const { trackEvent } = useMetrics();
@@ -59,6 +61,8 @@ const AccountPermissionsRevoke = ({
const accountsLength = useSelector(selectAccountsLength);
const nonTestnetNetworks = useSelector(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(state: any) => Object.keys(selectNetworkConfigurations(state)).length + 1,
);
diff --git a/app/components/Views/AccountSelector/AccountSelector.tsx b/app/components/Views/AccountSelector/AccountSelector.tsx
index 9bab9847ee6..3054bf4cbcc 100644
--- a/app/components/Views/AccountSelector/AccountSelector.tsx
+++ b/app/components/Views/AccountSelector/AccountSelector.tsx
@@ -47,6 +47,8 @@ const AccountSelector = ({ route }: AccountSelectorProps) => {
const { onSelectAccount, checkBalanceError } = route.params || {};
const { reloadAccounts } = useSelector((state: RootState) => state.accounts);
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const Engine = UntypedEngine as any;
const sheetRef = useRef(null);
const { accounts, ensByAccountAddress } = useAccounts({
diff --git a/app/components/Views/ActivityView/index.js b/app/components/Views/ActivityView/index.js
index 777a69d6abe..9594308f3d1 100644
--- a/app/components/Views/ActivityView/index.js
+++ b/app/components/Views/ActivityView/index.js
@@ -14,7 +14,7 @@ import { useTheme } from '../../../util/theme';
import Routes from '../../../constants/navigation/Routes';
import { MetaMetricsEvents } from '../../../core/Analytics';
import { selectAccountsByChainId } from '../../../selectors/accountTrackerController';
-import { selectSelectedAddress } from '../../../selectors/preferencesController';
+import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController';
import { useMetrics } from '../../../components/hooks/useMetrics';
const styles = StyleSheet.create({
@@ -27,7 +27,9 @@ const ActivityView = () => {
const { colors } = useTheme();
const { trackEvent } = useMetrics();
const navigation = useNavigation();
- const selectedAddress = useSelector(selectSelectedAddress);
+ const selectedAddress = useSelector(
+ selectSelectedInternalAccountChecksummedAddress,
+ );
const hasOrders = useSelector((state) => getHasOrders(state) || false);
const accountsByChainId = useSelector(selectAccountsByChainId);
diff --git a/app/components/Views/AddAccountActions/AddAccountActions.tsx b/app/components/Views/AddAccountActions/AddAccountActions.tsx
index 51dfea1b41e..bc94ae631c9 100644
--- a/app/components/Views/AddAccountActions/AddAccountActions.tsx
+++ b/app/components/Views/AddAccountActions/AddAccountActions.tsx
@@ -43,6 +43,8 @@ const AddAccountActions = ({ onBack }: AddAccountActionsProps) => {
const addedAccountAddress = await KeyringController.addNewAccount();
Engine.setSelectedAddress(addedAccountAddress);
trackEvent(MetaMetricsEvents.ACCOUNTS_ADDED_NEW_ACCOUNT, {});
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (e: any) {
Logger.error(e, 'error while trying to add a new account');
} finally {
diff --git a/app/components/Views/AddAsset/AddAsset.test.tsx b/app/components/Views/AddAsset/AddAsset.test.tsx
index a81b1568ece..3a2241e15fe 100644
--- a/app/components/Views/AddAsset/AddAsset.test.tsx
+++ b/app/components/Views/AddAsset/AddAsset.test.tsx
@@ -3,6 +3,7 @@ import renderWithProvider from '../../../util/test/renderWithProvider';
import initialBackgroundState from '../../../util/test/initial-background-state.json';
import AddAsset from './AddAsset';
import { AddAssetViewSelectorsIDs } from '../../../../e2e/selectors/AddAssetView.selectors';
+import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../util/test/accountsControllerTestUtils';
const mockNavigate = jest.fn();
const mockSetOptions = jest.fn();
@@ -42,7 +43,10 @@ jest.mock('react-native-scrollable-tab-view', () => {
const initialState = {
engine: {
- backgroundState: initialBackgroundState,
+ backgroundState: {
+ ...initialBackgroundState,
+ AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE,
+ },
},
};
diff --git a/app/components/Views/AddAsset/__snapshots__/AddAsset.test.tsx.snap b/app/components/Views/AddAsset/__snapshots__/AddAsset.test.tsx.snap
index 847be6ab267..36f43f06e59 100644
--- a/app/components/Views/AddAsset/__snapshots__/AddAsset.test.tsx.snap
+++ b/app/components/Views/AddAsset/__snapshots__/AddAsset.test.tsx.snap
@@ -4,7 +4,7 @@ exports[`AddAsset component renders correctly 1`] = `
},
qrCode: {
padding: 8,
- backgroundColor: theme.brandColors.white000,
+ backgroundColor: theme.brandColors.white,
},
addressWrapper: {
alignItems: 'center',
@@ -175,7 +175,7 @@ class AddressQRCode extends PureComponent {
}
const mapStateToProps = (state) => ({
- selectedAddress: selectSelectedAddress(state),
+ selectedAddress: selectSelectedInternalAccountChecksummedAddress(state),
seedphraseBackedUp: state.user.seedphraseBackedUp,
});
diff --git a/app/components/Views/AesCryptoTestForm/AesCryptoTestForm.test.tsx b/app/components/Views/AesCryptoTestForm/AesCryptoTestForm.test.tsx
new file mode 100644
index 00000000000..162bb706cea
--- /dev/null
+++ b/app/components/Views/AesCryptoTestForm/AesCryptoTestForm.test.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+import { render } from '@testing-library/react-native';
+
+import AesCryptoTestForm from './AesCryptoTestForm';
+
+jest.mock('@react-navigation/native', () => {
+ const actualReactNavigation = jest.requireActual('@react-navigation/native');
+ return {
+ ...actualReactNavigation,
+ useNavigation: () => ({
+ navigate: jest.fn(),
+ setOptions: jest.fn(),
+ goBack: jest.fn(),
+ }),
+ };
+});
+
+describe('AesCryptoTestForm', () => {
+ it('renders correctly', () => {
+ const wrapper = render();
+
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/app/components/Views/AesCryptoTestForm/AesCryptoTestForm.tsx b/app/components/Views/AesCryptoTestForm/AesCryptoTestForm.tsx
new file mode 100644
index 00000000000..c2217f4e5a3
--- /dev/null
+++ b/app/components/Views/AesCryptoTestForm/AesCryptoTestForm.tsx
@@ -0,0 +1,242 @@
+import React, { useState, useEffect, useCallback } from 'react';
+import { SafeAreaView, ScrollView } from 'react-native';
+import { useNavigation } from '@react-navigation/native';
+
+import {
+ Encryptor,
+ ENCRYPTION_LIBRARY,
+ DERIVATION_OPTIONS_DEFAULT_OWASP2023,
+} from '../../../core/Encryptor';
+import { useTheme } from '../../../util/theme';
+
+import { getNavigationOptionsTitle } from '../../UI/Navbar';
+import { strings } from '../../../../locales/i18n';
+
+import TestForm from './Form';
+import createStyles from './styles';
+import {
+ aesCryptoFormInputs,
+ aesCryptoFormResponses,
+ aesCryptoFormButtons,
+ aesCryptoFormScrollIdentifier,
+} from '../../../../e2e/selectors/AesCrypto.selectors';
+
+const AesCryptoTestForm = () => {
+ const navigation = useNavigation();
+ const theme = useTheme();
+ const { colors } = theme;
+ const styles = createStyles(colors);
+
+ const [encryptor, setEncryptor] = useState();
+
+ const [passwordEncryptedData, setPasswordEncryptedData] =
+ useState('');
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const [keyEncryptedData, setKeyEncryptedData] = useState();
+
+ useEffect(() => {
+ const encryptorInstance = new Encryptor({
+ keyDerivationOptions: DERIVATION_OPTIONS_DEFAULT_OWASP2023,
+ });
+ setEncryptor(encryptorInstance);
+ }, []);
+
+ useEffect(() => {
+ navigation.setOptions(
+ getNavigationOptionsTitle(
+ strings('app_settings.aes_crypto_test_form_title'),
+ navigation,
+ false,
+ colors,
+ null,
+ ),
+ );
+ }, [colors, navigation]);
+
+ const generateSalt = useCallback(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ async (args: any[]) => await encryptor?.generateSalt(args[0]),
+ [encryptor],
+ );
+
+ const generateEncryptionKey = useCallback(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ async (args: any[]) => {
+ const response = await encryptor?.keyFromPassword(args[0], args[1]);
+ return response?.key;
+ },
+ [encryptor],
+ );
+
+ const encrypt = useCallback(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ async (args: any[]) => {
+ const response = await encryptor?.encrypt(args[1], args[0]);
+ if (!response) {
+ throw new Error('Encryption failed');
+ }
+
+ setPasswordEncryptedData(response);
+ return JSON.parse(response).cipher;
+ },
+ [encryptor],
+ );
+
+ const decrypt = useCallback(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ async (args: any[]) => {
+ const response = await encryptor?.decrypt(args[0], passwordEncryptedData);
+ return response;
+ },
+ [encryptor, passwordEncryptedData],
+ );
+
+ const encryptWithKey = useCallback(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ async (args: any[]) => {
+ const response = await encryptor?.encryptWithKey(
+ {
+ key: args[0],
+ lib: ENCRYPTION_LIBRARY.original,
+ exportable: false,
+ keyMetadata: DERIVATION_OPTIONS_DEFAULT_OWASP2023,
+ },
+ args[1],
+ );
+ setKeyEncryptedData(response);
+ return response?.cipher;
+ },
+ [encryptor],
+ );
+
+ const decryptWithKey = useCallback(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ async (args: any[]) => {
+ const response = await encryptor?.decryptWithKey(
+ {
+ key: args[0],
+ lib: ENCRYPTION_LIBRARY.original,
+ exportable: false,
+ keyMetadata: DERIVATION_OPTIONS_DEFAULT_OWASP2023,
+ },
+ keyEncryptedData,
+ );
+ return response;
+ },
+ [encryptor, keyEncryptedData],
+ );
+
+ return (
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default AesCryptoTestForm;
diff --git a/app/components/Views/AesCryptoTestForm/Clipboard.test.tsx b/app/components/Views/AesCryptoTestForm/Clipboard.test.tsx
new file mode 100644
index 00000000000..19695b71a97
--- /dev/null
+++ b/app/components/Views/AesCryptoTestForm/Clipboard.test.tsx
@@ -0,0 +1,18 @@
+import React from 'react';
+import { render } from '@testing-library/react-native';
+
+import ClipboardText from './Clipboard';
+
+describe('ClipboardText', () => {
+ it('renders correctly', () => {
+ const wrapper = render(
+ ,
+ );
+
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/app/components/Views/AesCryptoTestForm/Clipboard.tsx b/app/components/Views/AesCryptoTestForm/Clipboard.tsx
new file mode 100644
index 00000000000..09afd78ddd6
--- /dev/null
+++ b/app/components/Views/AesCryptoTestForm/Clipboard.tsx
@@ -0,0 +1,35 @@
+import React, { useCallback } from 'react';
+import { TouchableOpacity } from 'react-native';
+
+import ClipboardManager from '../../../core/ClipboardManager';
+import Text, {
+ TextVariant,
+} from '../../../component-library/components/Texts/Text';
+
+const ClipboardText = ({
+ text,
+ testID,
+ styles,
+}: {
+ text: string;
+ testID: string;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ styles: any;
+}) => {
+ const copy = useCallback(async () => {
+ await ClipboardManager.setString(text);
+ }, [text]);
+
+ return (
+
+ {text}
+
+ );
+};
+
+export default ClipboardText;
diff --git a/app/components/Views/AesCryptoTestForm/Form.test.tsx b/app/components/Views/AesCryptoTestForm/Form.test.tsx
new file mode 100644
index 00000000000..210a6b6a3b5
--- /dev/null
+++ b/app/components/Views/AesCryptoTestForm/Form.test.tsx
@@ -0,0 +1,31 @@
+import React from 'react';
+import { render } from '@testing-library/react-native';
+
+import TestForm from './Form';
+
+describe('TestForm', () => {
+ it('renders correctly', () => {
+ const wrapper = render(
+ jest.fn()}
+ callbackTestId={'random-callback-test-id'}
+ responseTestId={'random-response-test-id'}
+ styles={{
+ container: {},
+ title: {},
+ textFieldsContainer: {},
+ textField: {},
+ button: {},
+ response: {},
+ }}
+ />,
+ );
+
+ expect(wrapper).toMatchSnapshot();
+ });
+});
diff --git a/app/components/Views/AesCryptoTestForm/Form.tsx b/app/components/Views/AesCryptoTestForm/Form.tsx
new file mode 100644
index 00000000000..0e77e597a36
--- /dev/null
+++ b/app/components/Views/AesCryptoTestForm/Form.tsx
@@ -0,0 +1,102 @@
+import React, { useState, useEffect, useCallback } from 'react';
+import { View, SafeAreaView, Keyboard, TextInput } from 'react-native';
+
+import Text, {
+ TextVariant,
+} from '../../../component-library/components/Texts/Text';
+import Button, {
+ ButtonSize,
+ ButtonVariants,
+} from '../../../component-library/components/Buttons/Button';
+import ClipboardText from './Clipboard';
+
+const TestForm = ({
+ title,
+ textFields,
+ buttonLabel,
+ callback,
+ callbackTestId,
+ responseTestId,
+ styles,
+}: {
+ title: string;
+ textFields: {
+ placeholder: string;
+ testId: string;
+ }[];
+ buttonLabel: string;
+ callback: // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ | ((...args: any[]) => Promise)
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ | ((...args: any[]) => unknown);
+ callbackTestId: string;
+ responseTestId: string;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ styles: any;
+}) => {
+ const [result, setResult] = useState('');
+ const [args, setArgs] = useState([]);
+
+ useEffect(() => {
+ setArgs(new Array(textFields.length).fill(''));
+ }, [textFields]);
+
+ const handleInputChange = useCallback(
+ (index: number, value: string) => {
+ const newArgs = [...args];
+ newArgs[index] = value;
+ setArgs(newArgs);
+ },
+ [args],
+ );
+
+ const executeTest = useCallback(async () => {
+ const response = (await callback(args)) as string;
+ setResult(response);
+ Keyboard.dismiss();
+ }, [callback, args]);
+
+ return (
+
+
+ {title}
+
+ {textFields.map((textField, index) => (
+
+ handleInputChange(index, value)}
+ testID={textField.testId}
+ autoFocus={false}
+ style={styles.textInput}
+ />
+
+ ))}
+ {result && (
+ <>
+ Response
+
+ >
+ )}
+
+
+ );
+};
+
+export default TestForm;
diff --git a/app/components/Views/AesCryptoTestForm/__snapshots__/AesCryptoTestForm.test.tsx.snap b/app/components/Views/AesCryptoTestForm/__snapshots__/AesCryptoTestForm.test.tsx.snap
new file mode 100644
index 00000000000..ea1e5052403
--- /dev/null
+++ b/app/components/Views/AesCryptoTestForm/__snapshots__/AesCryptoTestForm.test.tsx.snap
@@ -0,0 +1,621 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AesCryptoTestForm renders correctly 1`] = `
+
+
+
+
+
+ Generate Random Salt
+
+
+
+
+
+
+ Generate
+
+
+
+
+
+ Generate encryption key from password
+
+
+
+
+
+
+
+
+
+ Generate
+
+
+
+
+
+ Encrypt with key
+
+
+
+
+
+
+
+
+
+ Encrypt
+
+
+
+
+
+ Decrypt with key
+
+
+
+
+
+
+ Decrypt
+
+
+
+
+
+ Encrypt
+
+
+
+
+
+
+
+
+
+ Encrypt
+
+
+
+
+
+ Decrypt
+
+
+
+
+
+
+ Decrypt
+
+
+
+
+
+
+`;
diff --git a/app/components/Views/AesCryptoTestForm/__snapshots__/Clipboard.test.tsx.snap b/app/components/Views/AesCryptoTestForm/__snapshots__/Clipboard.test.tsx.snap
new file mode 100644
index 00000000000..de6369879dd
--- /dev/null
+++ b/app/components/Views/AesCryptoTestForm/__snapshots__/Clipboard.test.tsx.snap
@@ -0,0 +1,25 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`ClipboardText renders correctly 1`] = `
+
+
+ random text
+
+
+`;
diff --git a/app/components/Views/AesCryptoTestForm/__snapshots__/Form.test.tsx.snap b/app/components/Views/AesCryptoTestForm/__snapshots__/Form.test.tsx.snap
new file mode 100644
index 00000000000..235f7ddfac2
--- /dev/null
+++ b/app/components/Views/AesCryptoTestForm/__snapshots__/Form.test.tsx.snap
@@ -0,0 +1,69 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`TestForm renders correctly 1`] = `
+
+
+ random title
+
+
+
+
+
+
+ random button label
+
+
+
+`;
diff --git a/app/components/Views/AesCryptoTestForm/index.ts b/app/components/Views/AesCryptoTestForm/index.ts
new file mode 100644
index 00000000000..b13b9a644fa
--- /dev/null
+++ b/app/components/Views/AesCryptoTestForm/index.ts
@@ -0,0 +1,4 @@
+import AesCryptoTestForm from './AesCryptoTestForm';
+
+// eslint-disable-next-line import/prefer-default-export
+export { AesCryptoTestForm };
diff --git a/app/components/Views/AesCryptoTestForm/styles.ts b/app/components/Views/AesCryptoTestForm/styles.ts
new file mode 100644
index 00000000000..976b12e40c7
--- /dev/null
+++ b/app/components/Views/AesCryptoTestForm/styles.ts
@@ -0,0 +1,40 @@
+import { StyleSheet } from 'react-native';
+
+import Device from '../../../util/device';
+
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const createStyles = (colors: any) =>
+ StyleSheet.create({
+ container: {
+ paddingHorizontal: 15,
+ },
+ formTitle: {
+ paddingVertical: 5,
+ },
+ form: {
+ paddingVertical: 10,
+ },
+ input: {
+ paddingVertical: 5,
+ },
+ button: {
+ width: '100%',
+ },
+ clipboardText: {
+ marginVertical: 5,
+ paddingVertical: 5,
+ paddingHorizontal: 10,
+ backgroundColor: colors.background.alternative,
+ borderRadius: 15,
+ },
+ textInput: {
+ borderColor: colors.background.alternative,
+ borderWidth: 2,
+ borderRadius: 50,
+ paddingHorizontal: Device.isAndroid() ? 20 : 10,
+ paddingVertical: Device.isAndroid() ? 0 : 10,
+ },
+ });
+
+export default createStyles;
diff --git a/app/components/Views/Asset/__snapshots__/index.test.js.snap b/app/components/Views/Asset/__snapshots__/index.test.js.snap
index 77960e91f13..95ba680a0da 100644
--- a/app/components/Views/Asset/__snapshots__/index.test.js.snap
+++ b/app/components/Views/Asset/__snapshots__/index.test.js.snap
@@ -4,7 +4,7 @@ exports[`Asset should render correctly 1`] = `
({
state.engine.backgroundState.TransactionController.swapsTransactions || {},
conversionRate: selectConversionRate(state),
currentCurrency: selectCurrentCurrency(state),
- selectedAddress: selectSelectedAddress(state),
+ selectedAddress: selectSelectedInternalAccountChecksummedAddress(state),
identities: selectIdentities(state),
chainId: selectChainId(state),
tokens: selectTokens(state),
diff --git a/app/components/Views/Asset/index.test.js b/app/components/Views/Asset/index.test.js
index f73d6be58fc..556bebca2fe 100644
--- a/app/components/Views/Asset/index.test.js
+++ b/app/components/Views/Asset/index.test.js
@@ -3,6 +3,7 @@ import renderWithProvider from '../../../util/test/renderWithProvider';
import initialBackgroundState from '../../../util/test/initial-background-state.json';
import Asset from './';
import Engine from '../../../core/Engine';
+import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../util/test/accountsControllerTestUtils';
const mockedEngine = Engine;
@@ -10,21 +11,35 @@ const mockInitialState = {
engine: {
backgroundState: {
...initialBackgroundState,
+ AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE,
},
},
};
-jest.mock('../../../core/Engine.ts', () => ({
- init: () => mockedEngine.init({}),
- context: {
- KeyringController: {
- getOrAddQRKeyring: async () => ({ subscribe: () => ({}) }),
+jest.mock('../../../core/Engine.ts', () => {
+ const {
+ MOCK_ADDRESS_1,
+ } = require('../../../util/test/accountsControllerTestUtils');
+
+ return {
+ init: () => mockedEngine.init({}),
+ context: {
+ KeyringController: {
+ getOrAddQRKeyring: async () => ({ subscribe: () => ({}) }),
+ state: {
+ keyrings: [
+ {
+ accounts: [MOCK_ADDRESS_1],
+ },
+ ],
+ },
+ },
},
- },
- controllerMessenger: {
- subscribe: jest.fn(),
- },
-}));
+ controllerMessenger: {
+ subscribe: jest.fn(),
+ },
+ };
+});
describe('Asset', () => {
it('should render correctly', () => {
diff --git a/app/components/Views/AssetDetails/index.tsx b/app/components/Views/AssetDetails/index.tsx
index 5af5ba85310..6b0e411298a 100644
--- a/app/components/Views/AssetDetails/index.tsx
+++ b/app/components/Views/AssetDetails/index.tsx
@@ -44,6 +44,8 @@ import { selectContractExchangeRates } from '../../../selectors/tokenRatesContro
import { selectContractBalances } from '../../../selectors/tokenBalancesController';
import { useMetrics } from '../../../components/hooks/useMetrics';
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const createStyles = (colors: any) =>
StyleSheet.create({
container: {
@@ -58,6 +60,8 @@ const createStyles = (colors: any) =>
},
tokenImage: { height: 36, width: 36, marginRight: 8 },
sectionTitleLabel: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.bold as any),
fontSize: 16,
color: colors.text.default,
@@ -67,6 +71,8 @@ const createStyles = (colors: any) =>
marginTop: 8,
},
descriptionLabel: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.normal as any),
fontSize: 16,
color: colors.text.default,
@@ -75,11 +81,15 @@ const createStyles = (colors: any) =>
marginTop: 48,
},
hideButtonLabel: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.normal as any),
fontSize: 16,
color: colors.error.default,
},
addressLinkLabel: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.normal as any),
fontSize: 16,
color: colors.primary.default,
@@ -114,6 +124,8 @@ const AssetDetails = (props: Props) => {
const currentCurrency = useSelector(selectCurrentCurrency);
const chainId = useSelector(selectChainId);
const primaryCurrency = useSelector(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(state: any) => state.settings.primaryCurrency,
);
const tokenExchangeRates = useSelector(selectContractExchangeRates);
@@ -130,6 +142,8 @@ const AssetDetails = (props: Props) => {
name = providerConfig.nickname;
} else {
name =
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(Networks as any)[providerConfig.type]?.name ||
{ ...Networks.rpc, color: null }.name;
}
@@ -162,6 +176,8 @@ const AssetDetails = (props: Props) => {
};
const triggerHideToken = () => {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const { TokensController } = Engine.context as any;
navigation.navigate(Routes.MODAL.ROOT_MODAL_FLOW, {
screen: 'AssetHideConfirmation',
diff --git a/app/components/Views/AssetHideConfirmation/index.tsx b/app/components/Views/AssetHideConfirmation/index.tsx
index 1c8f2201622..bc388cb6c85 100644
--- a/app/components/Views/AssetHideConfirmation/index.tsx
+++ b/app/components/Views/AssetHideConfirmation/index.tsx
@@ -6,6 +6,8 @@ import StyledButton from '../../UI/StyledButton';
import { strings } from '../../../../locales/i18n';
import { useTheme } from '../../../util/theme';
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const createStyles = (colors: any) =>
StyleSheet.create({
fill: {
@@ -23,6 +25,8 @@ const createStyles = (colors: any) =>
},
headerLabel: {
textAlign: 'center',
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.bold as any),
fontSize: 24,
marginBottom: 16,
@@ -31,6 +35,8 @@ const createStyles = (colors: any) =>
description: {
textAlign: 'center',
fontSize: 16,
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.normal as any),
color: colors.text.default,
},
diff --git a/app/components/Views/BrowserTab/index.js b/app/components/Views/BrowserTab/index.js
index 7ab4da831d4..b7c87e1615a 100644
--- a/app/components/Views/BrowserTab/index.js
+++ b/app/components/Views/BrowserTab/index.js
@@ -83,8 +83,8 @@ import {
import {
selectIpfsGateway,
selectIsIpfsGatewayEnabled,
- selectSelectedAddress,
} from '../../../selectors/preferencesController';
+import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController';
import useFavicon from '../../hooks/useFavicon/useFavicon';
import { IPFS_GATEWAY_DISABLED_ERROR } from './constants';
import Banner from '../../../component-library/components/Banners/Banner/Banner';
@@ -1655,7 +1655,8 @@ BrowserTab.defaultProps = {
const mapStateToProps = (state) => ({
bookmarks: state.bookmarks,
ipfsGateway: selectIpfsGateway(state),
- selectedAddress: selectSelectedAddress(state)?.toLowerCase(),
+ selectedAddress:
+ selectSelectedInternalAccountChecksummedAddress(state)?.toLowerCase(),
isIpfsGatewayEnabled: selectIsIpfsGatewayEnabled(state),
searchEngine: state.settings.searchEngine,
whitelist: state.browser.whitelist,
diff --git a/app/components/Views/BrowserTab/index.test.tsx b/app/components/Views/BrowserTab/index.test.tsx
index ec044573aa8..75cd8d59f8f 100644
--- a/app/components/Views/BrowserTab/index.test.tsx
+++ b/app/components/Views/BrowserTab/index.test.tsx
@@ -4,11 +4,15 @@ import { BrowserTab } from './';
import { Provider } from 'react-redux';
import configureMockStore from 'redux-mock-store';
import initialBackgroundState from '../../../util/test/initial-background-state.json';
+import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../util/test/accountsControllerTestUtils';
const mockInitialState = {
browser: { activeTab: '' },
engine: {
- backgroundState: initialBackgroundState,
+ backgroundState: {
+ ...initialBackgroundState,
+ AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE,
+ },
},
transaction: {
selectedAsset: '',
diff --git a/app/components/Views/BrowserUrlModal/BrowserUrlModal.test.tsx b/app/components/Views/BrowserUrlModal/BrowserUrlModal.test.tsx
index 71cf1b67f0b..945d3fe9aa1 100644
--- a/app/components/Views/BrowserUrlModal/BrowserUrlModal.test.tsx
+++ b/app/components/Views/BrowserUrlModal/BrowserUrlModal.test.tsx
@@ -20,6 +20,8 @@ jest.mock('@react-navigation/native', () => {
params: {},
};
return {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...jest.requireActual('@react-navigation/native'),
useRoute: jest.fn(() => ({ params: navigation.params })),
useNavigation: jest.fn(() => mockNavigation),
diff --git a/app/components/Views/BrowserUrlModal/__snapshots__/BrowserUrlModal.test.tsx.snap b/app/components/Views/BrowserUrlModal/__snapshots__/BrowserUrlModal.test.tsx.snap
index 52f1a0e6725..887b92dc729 100644
--- a/app/components/Views/BrowserUrlModal/__snapshots__/BrowserUrlModal.test.tsx.snap
+++ b/app/components/Views/BrowserUrlModal/__snapshots__/BrowserUrlModal.test.tsx.snap
@@ -4,7 +4,7 @@ exports[`BrowserUrlModal should render correctly 1`] = `
StyleSheet.create({
screen: {
@@ -27,6 +29,8 @@ export const createStyles = (colors: any) =>
paddingLeft: 15,
flex: 1,
color: colors.text.default,
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any,
cancelButton: {
marginTop: -6,
@@ -37,6 +41,8 @@ export const createStyles = (colors: any) =>
fontSize: 14,
color: colors.primary.default,
...fontStyles.normal,
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any,
searchWrapper: {
flexDirection: 'row',
diff --git a/app/components/Views/ChoosePassword/index.js b/app/components/Views/ChoosePassword/index.js
index 2c43cb981b9..4057e52d9aa 100644
--- a/app/components/Views/ChoosePassword/index.js
+++ b/app/components/Views/ChoosePassword/index.js
@@ -540,8 +540,8 @@ class ChoosePassword extends PureComponent {
this.props.navigation.push('Webview', {
screen: 'SimpleWebview',
params: {
- url: 'https://metamask.zendesk.com/hc/en-us/articles/360039616872-How-can-I-reset-my-password-',
- title: 'metamask.zendesk.com',
+ url: 'https://support.metamask.io/managing-my-wallet/resetting-deleting-and-restoring/how-can-i-reset-my-password/',
+ title: 'support.metamask.io',
},
});
};
diff --git a/app/components/Views/ChoosePassword/index.test.tsx b/app/components/Views/ChoosePassword/index.test.tsx
index 233fcf24644..e82e36a1f56 100644
--- a/app/components/Views/ChoosePassword/index.test.tsx
+++ b/app/components/Views/ChoosePassword/index.test.tsx
@@ -5,6 +5,7 @@ import configureMockStore from 'redux-mock-store';
import { ONBOARDING, PROTECT } from '../../../constants/navigation';
import { Provider } from 'react-redux';
import initialBackgroundState from '../../../util/test/initial-background-state.json';
+import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../util/test/accountsControllerTestUtils';
const mockStore = configureMockStore();
const initialState = {
@@ -13,7 +14,10 @@ const initialState = {
seedphraseBackedUp: false,
},
engine: {
- backgroundState: initialBackgroundState,
+ backgroundState: {
+ ...initialBackgroundState,
+ AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE,
+ },
},
};
const store = mockStore(initialState);
diff --git a/app/components/Views/ConnectHardware/SelectHardware/index.tsx b/app/components/Views/ConnectHardware/SelectHardware/index.tsx
index af34227fad0..54769552fab 100644
--- a/app/components/Views/ConnectHardware/SelectHardware/index.tsx
+++ b/app/components/Views/ConnectHardware/SelectHardware/index.tsx
@@ -27,6 +27,8 @@ import { getNavigationOptionsTitle } from '../../../UI/Navbar';
import { useMetrics } from '../../../../components/hooks/useMetrics';
import type LedgerKeyring from '@consensys/ledgerhq-metamask-keyring';
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const createStyle = (colors: any) =>
StyleSheet.create({
screen: { justifyContent: 'center' },
@@ -126,6 +128,8 @@ const SelectHardwareWallet = () => {
}
};
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const renderHardwareButton = (image: any, onPress: any) => (
diff --git a/app/components/Views/ConnectQRHardware/Instruction/index.tsx b/app/components/Views/ConnectQRHardware/Instruction/index.tsx
index 53699ef0f9d..ea931184878 100644
--- a/app/components/Views/ConnectQRHardware/Instruction/index.tsx
+++ b/app/components/Views/ConnectQRHardware/Instruction/index.tsx
@@ -14,6 +14,8 @@ import { createStyles } from './styles';
import StyledButton from '../../../UI/StyledButton';
interface IConnectQRInstructionProps {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
navigation: any;
onConnect: () => void;
renderAlert: () => Element;
diff --git a/app/components/Views/ConnectQRHardware/Instruction/styles.ts b/app/components/Views/ConnectQRHardware/Instruction/styles.ts
index 62d63282c5e..28edca88f3c 100644
--- a/app/components/Views/ConnectQRHardware/Instruction/styles.ts
+++ b/app/components/Views/ConnectQRHardware/Instruction/styles.ts
@@ -50,7 +50,7 @@ export const createStyles = (theme: Theme) =>
paddingHorizontal: '30%',
},
buttonText: {
- color: theme.brandColors.white000,
+ color: theme.brandColors.white,
...fontStyles.normal,
},
image: {
diff --git a/app/components/Views/ConnectQRHardware/index.tsx b/app/components/Views/ConnectQRHardware/index.tsx
index ecb34b81152..19f8a1711fc 100644
--- a/app/components/Views/ConnectQRHardware/index.tsx
+++ b/app/components/Views/ConnectQRHardware/index.tsx
@@ -31,8 +31,12 @@ import type { MetaMaskKeyring as QRKeyring } from '@keystonehq/metamask-airgappe
import { KeyringTypes } from '@metamask/keyring-controller';
interface IConnectQRHardwareProps {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
navigation: any;
}
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const createStyles = (colors: any) =>
StyleSheet.create({
container: {
@@ -131,6 +135,8 @@ const ConnectQRHardware = ({ navigation }: IConnectQRHardwareProps) => {
const styles = createStyles(colors);
const KeyringController = useMemo(() => {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const { KeyringController: keyring } = Engine.context as any;
return keyring;
}, []);
@@ -166,6 +172,8 @@ const ConnectQRHardware = ({ navigation }: IConnectQRHardwareProps) => {
});
}, [KeyringController]);
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const subscribeKeyringState = useCallback((storeValue: any) => {
setQRState(storeValue);
}, []);
diff --git a/app/components/Views/DataCollectionModal/__snapshots__/index.test.tsx.snap b/app/components/Views/DataCollectionModal/__snapshots__/index.test.tsx.snap
index d7d6eea8295..444fca23ca1 100644
--- a/app/components/Views/DataCollectionModal/__snapshots__/index.test.tsx.snap
+++ b/app/components/Views/DataCollectionModal/__snapshots__/index.test.tsx.snap
@@ -69,15 +69,15 @@ exports[`DataCollectionModal should render expected snapshot 1`] = `
style={
[
{
- "backgroundColor": "#FFFFFF",
- "borderColor": "#D6D9DC",
+ "backgroundColor": "#ffffff",
+ "borderColor": "#bbc0c566",
"borderTopLeftRadius": 8,
"borderTopRightRadius": 8,
"borderWidth": 1,
"maxHeight": 1333,
"overflow": "hidden",
"paddingBottom": 3,
- "shadowColor": "#0000001A",
+ "shadowColor": "#0000001a",
"shadowOffset": {
"height": 2,
"width": 0,
@@ -107,7 +107,7 @@ exports[`DataCollectionModal should render expected snapshot 1`] = `
StyleSheet.create({
logo: {
@@ -31,12 +33,16 @@ const createStyles = (colors: any) =>
tokenContainer: { flexDirection: 'row', paddingVertical: 16 },
tokenInfoContainer: { flex: 1, marginLeft: 8, marginRight: 16 },
tokenUnitLabel: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.normal as any),
fontSize: 18,
color: colors.text.default,
marginBottom: 4,
},
tokenDollarLabel: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.normal as any),
fontSize: 14,
color: colors.text.alternative,
@@ -47,6 +53,8 @@ const createStyles = (colors: any) =>
marginBottom: 4,
},
tokenAddressLabel: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.normal as any),
fontSize: 14,
color: colors.text.alternative,
@@ -56,6 +64,8 @@ const createStyles = (colors: any) =>
alignItems: 'center',
},
addressLinkLabel: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.normal as any),
fontSize: 14,
color: colors.primary.default,
@@ -70,11 +80,15 @@ const createStyles = (colors: any) =>
flexWrap: 'wrap',
},
tokenAggregatorLabel: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.normal as any),
fontSize: 14,
color: colors.text.default,
},
aggregatorLinkLabel: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.normal as any),
fontSize: 14,
color: colors.primary.default,
diff --git a/app/components/Views/DetectedTokens/index.tsx b/app/components/Views/DetectedTokens/index.tsx
index 7e9650b6169..72692507ddc 100644
--- a/app/components/Views/DetectedTokens/index.tsx
+++ b/app/components/Views/DetectedTokens/index.tsx
@@ -27,6 +27,8 @@ import BottomSheet, {
import { useMetrics } from '../../../components/hooks/useMetrics';
import { DetectedTokensSelectorIDs } from '../../../../e2e/selectors/wallet/DetectedTokensView.selectors';
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const createStyles = (colors: any) =>
StyleSheet.create({
fill: {
@@ -48,6 +50,8 @@ const createStyles = (colors: any) =>
},
headerLabel: {
textAlign: 'center',
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.normal as any),
fontSize: 18,
paddingVertical: 16,
@@ -86,6 +90,8 @@ const DetectedTokens = () => {
const dismissModalAndTriggerAction = useCallback(
(ignoreAllTokens?: boolean) => {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const { TokensController } = Engine.context as any;
let title = '';
let description = '';
diff --git a/app/components/Views/DetectedTokensConfirmation/index.tsx b/app/components/Views/DetectedTokensConfirmation/index.tsx
index e94f14a9b3d..97ab215c948 100644
--- a/app/components/Views/DetectedTokensConfirmation/index.tsx
+++ b/app/components/Views/DetectedTokensConfirmation/index.tsx
@@ -6,6 +6,8 @@ import StyledButton from '../../UI/StyledButton';
import { strings } from '../../../../locales/i18n';
import { useTheme } from '../../../util/theme';
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const createStyles = (colors: any) =>
StyleSheet.create({
fill: {
@@ -23,6 +25,8 @@ const createStyles = (colors: any) =>
},
headerLabel: {
textAlign: 'center',
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.bold as any),
fontSize: 24,
marginBottom: 16,
@@ -31,6 +35,8 @@ const createStyles = (colors: any) =>
description: {
textAlign: 'center',
fontSize: 16,
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
...(fontStyles.normal as any),
color: colors.text.default,
},
diff --git a/app/components/Views/EditAccountName/EditAccountName.test.tsx b/app/components/Views/EditAccountName/EditAccountName.test.tsx
index 4c3f8edf6e7..6601bb15bfc 100644
--- a/app/components/Views/EditAccountName/EditAccountName.test.tsx
+++ b/app/components/Views/EditAccountName/EditAccountName.test.tsx
@@ -6,11 +6,17 @@ import { fireEvent } from '@testing-library/react-native';
import EditAccountName from './EditAccountName';
import renderWithProvider from '../../../util/test/renderWithProvider';
import initialBackgroundState from '../../../util/test/initial-background-state.json';
+import { createMockAccountsControllerState } from '../../../util/test/accountsControllerTestUtils';
const mockPreferencesSetAccountLabel = jest.fn();
const mockEngineSetAccountLabel = jest.fn();
const mockAccountsControllerSetAccountName = jest.fn();
+const MOCK_ADDRESS = '0x0';
+const MOCK_ACCOUNTS_CONTROLLER_STATE = createMockAccountsControllerState([
+ MOCK_ADDRESS,
+]);
+
jest.mock('../../../core/Engine', () => ({
setAccountLabel: () => mockEngineSetAccountLabel,
context: {
@@ -19,6 +25,7 @@ jest.mock('../../../core/Engine', () => ({
},
AccountsController: {
setAccountName: () => mockAccountsControllerSetAccountName,
+ ...MOCK_ACCOUNTS_CONTROLLER_STATE,
},
},
}));
@@ -35,37 +42,7 @@ const mockInitialState = {
backgroundState: {
...initialBackgroundState,
AccountsController: {
- internalAccounts: {
- accounts: {
- '30313233-3435-4637-b839-383736353430': {
- address: '0x0',
- id: '30313233-3435-4637-b839-383736353430',
- options: {},
- metadata: {
- name: 'Account 1',
- keyring: {
- type: 'HD Key Tree',
- },
- },
- methods: [
- 'personal_sign',
- 'eth_sign',
- 'eth_signTransaction',
- 'eth_signTypedData_v1',
- 'eth_signTypedData_v3',
- 'eth_signTypedData_v4',
- ],
- type: 'eip155:eoa',
- },
- },
- },
- selectedAccount: '30313233-3435-4637-b839-383736353430',
- },
- PreferencesController: {
- selectedAddress: '0x0',
- identities: {
- '0x0': { name: 'Account 1', address: '0x0' },
- },
+ ...MOCK_ACCOUNTS_CONTROLLER_STATE,
},
},
},
@@ -94,6 +71,8 @@ jest.mock('@react-navigation/native', () => {
};
});
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const renderComponent = (state: any) =>
renderWithProvider(, { state });
diff --git a/app/components/Views/EditAccountName/EditAccountName.tsx b/app/components/Views/EditAccountName/EditAccountName.tsx
index fe6e9e8910a..95e95af1139 100644
--- a/app/components/Views/EditAccountName/EditAccountName.tsx
+++ b/app/components/Views/EditAccountName/EditAccountName.tsx
@@ -24,15 +24,13 @@ import Engine from '../../../core/Engine';
import generateTestId from '../../../../wdio/utils/generateTestId';
import { MetaMetricsEvents } from '../../../core/Analytics';
import { selectChainId } from '../../../selectors/networkController';
-import {
- selectIdentities,
- selectSelectedAddress,
-} from '../../../selectors/preferencesController';
+import { selectSelectedInternalAccount } from '../../../selectors/accountsController';
import {
doENSReverseLookup,
isDefaultAccountName,
} from '../../../util/ENSUtils';
import { useTheme } from '../../../util/theme';
+import { toChecksumHexAddress } from '@metamask/controller-utils';
// Internal dependencies
import styleSheet from './EditAccountName.styles';
@@ -47,19 +45,27 @@ const EditAccountName = () => {
const [accountName, setAccountName] = useState();
const [ens, setEns] = useState();
- const selectedAddress = useSelector(selectSelectedAddress);
- const identities = useSelector(selectIdentities);
+ const selectedInternalAccount = useSelector(selectSelectedInternalAccount);
+
+ const selectedChecksummedAddress = selectedInternalAccount?.address
+ ? toChecksumHexAddress(selectedInternalAccount.address)
+ : undefined;
const chainId = useSelector(selectChainId);
const lookupEns = useCallback(async () => {
- try {
- const accountEns = await doENSReverseLookup(selectedAddress, chainId);
-
- setEns(accountEns);
- // eslint-disable-next-line no-empty
- } catch {}
- }, [selectedAddress, chainId]);
+ if (selectedChecksummedAddress) {
+ try {
+ const accountEns = await doENSReverseLookup(
+ selectedChecksummedAddress,
+ chainId,
+ );
+
+ setEns(accountEns);
+ // eslint-disable-next-line no-empty
+ } catch {}
+ }
+ }, [selectedChecksummedAddress, chainId]);
useEffect(() => {
lookupEns();
@@ -74,22 +80,28 @@ const EditAccountName = () => {
}, [updateNavBar]);
useEffect(() => {
- const name = identities[selectedAddress].name;
+ const name = selectedInternalAccount?.metadata.name;
setAccountName(isDefaultAccountName(name) && ens ? ens : name);
- }, [selectedAddress, identities, ens]);
+ }, [ens, selectedInternalAccount?.metadata.name]);
const onChangeName = (name: string) => {
setAccountName(name);
};
const saveAccountName = async () => {
- if (accountName && accountName.length > 0) {
- Engine.setAccountLabel(selectedAddress, accountName);
+ if (
+ accountName &&
+ accountName.length > 0 &&
+ selectedInternalAccount?.address
+ ) {
+ Engine.setAccountLabel(selectedInternalAccount?.address, accountName);
navigate('WalletView');
try {
const analyticsProperties = async () => {
- const accountType = getAddressAccountType(selectedAddress);
+ const accountType = getAddressAccountType(
+ selectedInternalAccount?.address,
+ );
const account_type = accountType === 'QR' ? 'hardware' : accountType;
return { account_type, chain_id: getDecimalChainId(chainId) };
};
@@ -118,10 +130,15 @@ const EditAccountName = () => {
{strings('address_book.address')}
-
+ {selectedInternalAccount?.address ? (
+
+ ) : null}
diff --git a/app/components/Views/EditAccountName/__snapshots__/EditAccountName.test.tsx.snap b/app/components/Views/EditAccountName/__snapshots__/EditAccountName.test.tsx.snap
index 1204d81f15d..c0d580907db 100644
--- a/app/components/Views/EditAccountName/__snapshots__/EditAccountName.test.tsx.snap
+++ b/app/components/Views/EditAccountName/__snapshots__/EditAccountName.test.tsx.snap
@@ -4,7 +4,7 @@ exports[`EditAccountName should render correctly 1`] = `
},
});
+const UserFeedbackSection = ({ styles, sentryId }) => {
+ /**
+ * Prompt bug report form
+ */
+ const promptBugReport = useCallback(() => {
+ Alert.prompt(
+ strings('error_screen.bug_report_prompt_title'),
+ strings('error_screen.bug_report_prompt_description'),
+ [
+ { text: strings('error_screen.cancel'), style: 'cancel' },
+ {
+ text: strings('error_screen.send'),
+ onPress: (comments = '') => {
+ // Send Sentry feedback
+ captureSentryFeedback({ sentryId, comments });
+ Alert.alert(strings('error_screen.bug_report_thanks'));
+ },
+ },
+ ],
+ );
+ }, [sentryId]);
+
+ return (
+
+
+ {' '}
+ {strings('error_screen.submit_ticket_8')}{' '}
+
+ {strings('error_screen.submit_ticket_6')}
+ {' '}
+ {strings('error_screen.submit_ticket_9')}
+
+ );
+};
+
+UserFeedbackSection.propTypes = {
+ styles: PropTypes.object,
+ sentryId: PropTypes.string,
+};
+
const Fallback = (props) => {
const { colors } = useTheme();
const styles = createStyles(colors);
@@ -157,6 +199,7 @@ const Fallback = (props) => {
{' '}
{strings('error_screen.submit_ticket_7')}
+
{strings('error_screen.save_seedphrase_1')}{' '}
@@ -176,6 +219,7 @@ Fallback.propTypes = {
showExportSeedphrase: PropTypes.func,
copyErrorToClipboard: PropTypes.func,
openTicket: PropTypes.func,
+ sentryId: PropTypes.string,
};
class ErrorBoundary extends Component {
@@ -212,6 +256,10 @@ class ErrorBoundary extends Component {
};
componentDidCatch(error, errorInfo) {
+ // Note: Sentry briefly removed this in the next version but eventually added it back in later versions.
+ // Read more here - https://github.com/getsentry/sentry-javascript/issues/11951
+ const sentryId = getLatestSentryId();
+ this.setState({ sentryId });
this.generateErrorReport(error, errorInfo?.componentStack);
Logger.error(error, { View: this.props.view, ...errorInfo });
}
@@ -244,7 +292,7 @@ class ErrorBoundary extends Component {
};
openTicket = () => {
- const url = 'https://metamask.zendesk.com/hc/en-us';
+ const url = 'https://support.metamask.io';
Linking.openURL(url);
};
@@ -272,6 +320,7 @@ class ErrorBoundary extends Component {
showExportSeedphrase={this.showExportSeedphrase}
copyErrorToClipboard={this.copyErrorToClipboard}
openTicket={this.openTicket}
+ sentryId={this.state.sentryId}
/>,
)
: this.props.children;
diff --git a/app/components/Views/ErrorBoundary/index.test.tsx b/app/components/Views/ErrorBoundary/index.test.tsx
index 87c43dc5a2d..1c6f6547f4c 100644
--- a/app/components/Views/ErrorBoundary/index.test.tsx
+++ b/app/components/Views/ErrorBoundary/index.test.tsx
@@ -9,6 +9,8 @@ jest.mock('../../../components/hooks/useMetrics', () => ({
...jest.requireActual('../../../components/hooks/useMetrics'),
withMetricsAwareness: jest
.fn()
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
.mockImplementation((Children) => (props: any) => (
)),
diff --git a/app/components/Views/ExperienceEnhancerModal/index.test.tsx b/app/components/Views/ExperienceEnhancerModal/index.test.tsx
index b7817724a95..d33f6e7698a 100644
--- a/app/components/Views/ExperienceEnhancerModal/index.test.tsx
+++ b/app/components/Views/ExperienceEnhancerModal/index.test.tsx
@@ -12,6 +12,8 @@ import { ExperienceEnhancerModalSelectorsIDs } from '../../../../e2e/selectors/M
jest.mock(
'../../../component-library/components/BottomSheets/BottomSheet',
() => {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const mockBottomSheet = ({ children }: any) => <>{children}>;
return mockBottomSheet;
},
diff --git a/app/components/Views/GasEducationCarousel/__snapshots__/index.test.tsx.snap b/app/components/Views/GasEducationCarousel/__snapshots__/index.test.tsx.snap
index 23e97d68171..40334a08359 100644
--- a/app/components/Views/GasEducationCarousel/__snapshots__/index.test.tsx.snap
+++ b/app/components/Views/GasEducationCarousel/__snapshots__/index.test.tsx.snap
@@ -11,7 +11,7 @@ exports[`GasEducationCarousel should render correctly 1`] = `
StyleSheet.create({
mainWrapper: {
diff --git a/app/components/Views/ImportPrivateKey/__snapshots__/index.test.tsx.snap b/app/components/Views/ImportPrivateKey/__snapshots__/index.test.tsx.snap
index ce7d4eaa15a..d2fba73cb74 100644
--- a/app/components/Views/ImportPrivateKey/__snapshots__/index.test.tsx.snap
+++ b/app/components/Views/ImportPrivateKey/__snapshots__/index.test.tsx.snap
@@ -307,7 +307,7 @@ exports[`ImportPrivateKey should render correctly 1`] = `
{
navigation.navigate('Webview', {
screen: 'SimpleWebview',
params: {
- url: 'https://metamask.zendesk.com/hc/en-us/articles/360015289932-What-are-imported-accounts-',
+ url: 'https://support.metamask.io/managing-my-wallet/accounts-and-addresses/what-are-imported-accounts-/',
title: strings('drawer.metamask_support'),
},
});
diff --git a/app/components/Views/ImportPrivateKey/styles.ts b/app/components/Views/ImportPrivateKey/styles.ts
index 119dc01d676..561832eb625 100644
--- a/app/components/Views/ImportPrivateKey/styles.ts
+++ b/app/components/Views/ImportPrivateKey/styles.ts
@@ -3,6 +3,8 @@ import { StyleSheet } from 'react-native';
import { fontStyles } from '../../../styles/common';
import Device from '../../../util/device';
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const createStyles = (colors: any) =>
StyleSheet.create({
mainWrapper: {
diff --git a/app/components/Views/ImportPrivateKeySuccess/__snapshots__/index.test.tsx.snap b/app/components/Views/ImportPrivateKeySuccess/__snapshots__/index.test.tsx.snap
index 3ae7ab072e2..8d35af69734 100644
--- a/app/components/Views/ImportPrivateKeySuccess/__snapshots__/index.test.tsx.snap
+++ b/app/components/Views/ImportPrivateKeySuccess/__snapshots__/index.test.tsx.snap
@@ -307,7 +307,7 @@ exports[`ImportPrivateKeySuccess should render correctly 1`] = `
StyleSheet.create({
container: {
@@ -89,12 +91,18 @@ const LedgerAccountInfo = () => {
ledgerDeviceLightImage,
ledgerDeviceDarkImage,
);
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const { AccountTrackerController } = Engine.context as any;
const provider = useSelector(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(state: any) =>
state.engine.backgroundState.NetworkController.providerConfig,
);
const frequentRpcList = useSelector(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(state: any) =>
state.engine.backgroundState.PreferencesController.frequentRpcList,
);
diff --git a/app/components/Views/LedgerConnect/__snapshots__/index.test.tsx.snap b/app/components/Views/LedgerConnect/__snapshots__/index.test.tsx.snap
index e929bf736f3..d9227ecbdec 100644
--- a/app/components/Views/LedgerConnect/__snapshots__/index.test.tsx.snap
+++ b/app/components/Views/LedgerConnect/__snapshots__/index.test.tsx.snap
@@ -5,7 +5,7 @@ exports[`LedgerConnect render matches latest snapshot 1`] = `
style={
{
"alignItems": "center",
- "backgroundColor": "#FFFFFF",
+ "backgroundColor": "#ffffff",
"flex": 1,
"position": "relative",
}
@@ -37,7 +37,7 @@ exports[`LedgerConnect render matches latest snapshot 1`] = `
style={
[
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 30,
"fontWeight": "400",
@@ -121,7 +121,7 @@ exports[`LedgerConnect render matches latest snapshot 1`] = `
style={
[
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 30,
"fontWeight": "400",
@@ -166,7 +166,7 @@ exports[`LedgerConnect render matches latest snapshot 1`] = `
style={
[
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 30,
"fontWeight": "400",
@@ -207,7 +207,7 @@ exports[`LedgerConnect render matches latest snapshot 1`] = `
style={
[
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 30,
"fontWeight": "400",
@@ -248,7 +248,7 @@ exports[`LedgerConnect render matches latest snapshot 1`] = `
style={
[
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 30,
"fontWeight": "400",
@@ -289,7 +289,7 @@ exports[`LedgerConnect render matches latest snapshot 1`] = `
style={
[
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 30,
"fontWeight": "400",
@@ -330,7 +330,7 @@ exports[`LedgerConnect render matches latest snapshot 1`] = `
style={
[
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 30,
"fontWeight": "400",
@@ -371,7 +371,7 @@ exports[`LedgerConnect render matches latest snapshot 1`] = `
style={
[
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 30,
"fontWeight": "400",
@@ -413,7 +413,7 @@ exports[`LedgerConnect render matches latest snapshot 1`] = `
style={
[
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "EuclidCircularB-Regular",
"fontSize": 30,
"fontWeight": "400",
@@ -444,7 +444,7 @@ exports[`LedgerConnect render matches latest snapshot 1`] = `
undefined,
undefined,
{
- "color": "#0376C9",
+ "color": "#0376c9",
},
undefined,
undefined,
@@ -477,7 +477,7 @@ exports[`LedgerConnect render matches latest snapshot 1`] = `
StyleSheet.create({
container: {
@@ -107,11 +109,13 @@ const createStyles = (theme: any) =>
marginTop: Device.getDeviceHeight() * 0.025,
},
loader: {
- color: theme.brandColors.white000,
+ color: theme.brandColors.white,
},
});
const LedgerConnect = () => {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const { AccountTrackerController } = Engine.context as any;
const theme = useAppThemeFromContext() ?? mockTheme;
const { trackEvent } = useMetrics();
diff --git a/app/components/Views/LockScreen/__snapshots__/index.test.tsx.snap b/app/components/Views/LockScreen/__snapshots__/index.test.tsx.snap
index f1d7821d162..e122e592a19 100644
--- a/app/components/Views/LockScreen/__snapshots__/index.test.tsx.snap
+++ b/app/components/Views/LockScreen/__snapshots__/index.test.tsx.snap
@@ -311,7 +311,7 @@ exports[`LockScreen should render correctly 1`] = `
"flex": 1,
},
{
- "backgroundColor": "#FFFFFF",
+ "backgroundColor": "#ffffff",
"flex": 1,
},
]
@@ -365,7 +365,7 @@ exports[`LockScreen should render correctly 1`] = `
onAnimationFinish={[Function]}
progress={0}
resizeMode="contain"
- sourceJson="{\"v\":\"5.5.1\",\"fr\":30,\"ip\":0,\"op\":16,\"w\":1120,\"h\":930,\"nm\":\"Bounce\",\"ddd\":0,\"assets\":[{\"id\":\"comp_0\",\"layers\":[{\"ddd\":0,\"ind\":1,\"ty\":4,\"nm\":\"Romb_shadow\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":1,\"k\":[{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":0,\"s\":[562.688,850.992,0],\"e\":[562.688,626.992,0],\"to\":[0,-37.333,0],\"ti\":[0,0,0]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":12,\"s\":[562.688,626.992,0],\"e\":[562.688,850.992,0],\"to\":[0,0,0],\"ti\":[0,-37.333,0]},{\"t\":22}],\"ix\":2},\"a\":{\"a\":0,\"k\":[0.188,-367.008,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":1,\"k\":[{\"i\":{\"x\":0.667,\"y\":1},\"o\":{\"x\":0.333,\"y\":0},\"t\":0,\"s\":[{\"i\":[[0,0],[0,0],[0,0],[0,0]],\"o\":[[0,0],[0,0],[0,0],[0,0]],\"v\":[[-52.392,-367.008],[0.188,-271.228],[-52.232,-367.008],[0.188,-462.788]],\"c\":true}],\"e\":[{\"i\":[[0,0],[0,0],[0,0],[0,0]],\"o\":[[0,0],[0,0],[0,0],[0,0]],\"v\":[[52.608,-367.008],[0.188,-271.228],[-52.232,-367.008],[0.188,-462.788]],\"c\":true}]},{\"i\":{\"x\":0.833,\"y\":1},\"o\":{\"x\":0.167,\"y\":0},\"t\":7,\"s\":[{\"i\":[[0,0],[0,0],[0,0],[0,0]],\"o\":[[0,0],[0,0],[0,0],[0,0]],\"v\":[[52.608,-367.008],[0.188,-271.228],[-52.232,-367.008],[0.188,-462.788]],\"c\":true}],\"e\":[{\"i\":[[0,0],[0,0],[0,0],[0,0]],\"o\":[[0,0],[0,0],[0,0],[0,0]],\"v\":[[52.608,-367.008],[0.188,-271.228],[51.768,-367.008],[0.188,-462.788]],\"c\":true}]},{\"t\":12}],\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.745802696078,0.358373754165,0.146384325214,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Group 1\",\"np\":2,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":23,\"st\":0,\"bm\":0},{\"ddd\":0,\"ind\":2,\"ty\":4,\"nm\":\"Romb\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":1,\"k\":[{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":0,\"s\":[562.688,850.992,0],\"e\":[562.688,626.992,0],\"to\":[0,-37.333,0],\"ti\":[0,0,0]},{\"i\":{\"x\":0.833,\"y\":0.833},\"o\":{\"x\":0.167,\"y\":0.167},\"t\":12,\"s\":[562.688,626.992,0],\"e\":[562.688,850.992,0],\"to\":[0,0,0],\"ti\":[0,-37.333,0]},{\"t\":22}],\"ix\":2},\"a\":{\"a\":0,\"k\":[0.188,-367.008,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"shapes\":[{\"ty\":\"gr\",\"it\":[{\"ind\":0,\"ty\":\"sh\",\"ix\":1,\"ks\":{\"a\":0,\"k\":{\"i\":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],\"o\":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],\"v\":[[52.608,-367.018],[52.608,-367.008],[52.598,-366.998],[0.188,-271.228],[-52.232,-367.008],[0.188,-462.788]],\"c\":true},\"ix\":2},\"nm\":\"Path 1\",\"mn\":\"ADBE Vector Shape - Group\",\"hd\":false},{\"ty\":\"st\",\"c\":{\"a\":0,\"k\":[0.960784375668,0.517647087574,0.121568635106,1],\"ix\":3},\"o\":{\"a\":0,\"k\":100,\"ix\":4},\"w\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.167],\"y\":[0.167]},\"t\":27,\"s\":[0],\"e\":[2]},{\"t\":30}],\"ix\":5},\"lc\":1,\"lj\":1,\"ml\":4,\"bm\":0,\"nm\":\"Stroke 1\",\"mn\":\"ADBE Vector Graphic - Stroke\",\"hd\":false},{\"ty\":\"fl\",\"c\":{\"a\":0,\"k\":[0.960784316063,0.517647087574,0.121568627656,1],\"ix\":4},\"o\":{\"a\":0,\"k\":100,\"ix\":5},\"r\":1,\"bm\":0,\"nm\":\"Fill 1\",\"mn\":\"ADBE Vector Graphic - Fill\",\"hd\":false},{\"ty\":\"tr\",\"p\":{\"a\":0,\"k\":[0,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[0,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100],\"ix\":3},\"r\":{\"a\":0,\"k\":0,\"ix\":6},\"o\":{\"a\":0,\"k\":100,\"ix\":7},\"sk\":{\"a\":0,\"k\":0,\"ix\":4},\"sa\":{\"a\":0,\"k\":0,\"ix\":5},\"nm\":\"Transform\"}],\"nm\":\"Group 1\",\"np\":3,\"cix\":2,\"bm\":0,\"ix\":1,\"mn\":\"ADBE Vector Group\",\"hd\":false}],\"ip\":0,\"op\":23,\"st\":0,\"bm\":0}]}],\"layers\":[{\"ddd\":0,\"ind\":1,\"ty\":0,\"nm\":\"Bounce_no_easing\",\"refId\":\"comp_0\",\"sr\":1,\"ks\":{\"o\":{\"a\":0,\"k\":100,\"ix\":11},\"r\":{\"a\":0,\"k\":0,\"ix\":10},\"p\":{\"a\":0,\"k\":[560,733,0],\"ix\":2},\"a\":{\"a\":0,\"k\":[562.5,1218,0],\"ix\":1},\"s\":{\"a\":0,\"k\":[100,100,100],\"ix\":6}},\"ao\":0,\"tm\":{\"a\":1,\"k\":[{\"i\":{\"x\":[0],\"y\":[1]},\"o\":{\"x\":[0.135],\"y\":[0]},\"t\":0,\"s\":[0],\"e\":[0.4]},{\"i\":{\"x\":[0.928],\"y\":[1]},\"o\":{\"x\":[1],\"y\":[0]},\"t\":8,\"s\":[0.4],\"e\":[0.733]},{\"i\":{\"x\":[0.858],\"y\":[1]},\"o\":{\"x\":[0.158],\"y\":[0]},\"t\":16,\"s\":[0.733],\"e\":[0.733]},{\"i\":{\"x\":[0.833],\"y\":[0.833]},\"o\":{\"x\":[0.037],\"y\":[0]},\"t\":102,\"s\":[0.733],\"e\":[10]},{\"t\":300}],\"ix\":2},\"w\":1125,\"h\":2436,\"ip\":0,\"op\":21,\"st\":0,\"bm\":0}],\"markers\":[{\"tm\":95,\"cm\":\"1\",\"dr\":0}]}"
+ sourceJson="{"v":"5.5.1","fr":30,"ip":0,"op":16,"w":1120,"h":930,"nm":"Bounce","ddd":0,"assets":[{"id":"comp_0","layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Romb_shadow","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[562.688,850.992,0],"e":[562.688,626.992,0],"to":[0,-37.333,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":12,"s":[562.688,626.992,0],"e":[562.688,850.992,0],"to":[0,0,0],"ti":[0,-37.333,0]},{"t":22}],"ix":2},"a":{"a":0,"k":[0.188,-367.008,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":1,"k":[{"i":{"x":0.667,"y":1},"o":{"x":0.333,"y":0},"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-52.392,-367.008],[0.188,-271.228],[-52.232,-367.008],[0.188,-462.788]],"c":true}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[52.608,-367.008],[0.188,-271.228],[-52.232,-367.008],[0.188,-462.788]],"c":true}]},{"i":{"x":0.833,"y":1},"o":{"x":0.167,"y":0},"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[52.608,-367.008],[0.188,-271.228],[-52.232,-367.008],[0.188,-462.788]],"c":true}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[52.608,-367.008],[0.188,-271.228],[51.768,-367.008],[0.188,-462.788]],"c":true}]},{"t":12}],"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"fl","c":{"a":0,"k":[0.745802696078,0.358373754165,0.146384325214,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":23,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Romb","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":1,"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":0,"s":[562.688,850.992,0],"e":[562.688,626.992,0],"to":[0,-37.333,0],"ti":[0,0,0]},{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"t":12,"s":[562.688,626.992,0],"e":[562.688,850.992,0],"to":[0,0,0],"ti":[0,-37.333,0]},{"t":22}],"ix":2},"a":{"a":0,"k":[0.188,-367.008,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0],[0,0],[0,0]],"v":[[52.608,-367.018],[52.608,-367.008],[52.598,-366.998],[0.188,-271.228],[-52.232,-367.008],[0.188,-462.788]],"c":true},"ix":2},"nm":"Path 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.960784375668,0.517647087574,0.121568635106,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":27,"s":[0],"e":[2]},{"t":30}],"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"fl","c":{"a":0,"k":[0.960784316063,0.517647087574,0.121568627656,1],"ix":4},"o":{"a":0,"k":100,"ix":5},"r":1,"bm":0,"nm":"Fill 1","mn":"ADBE Vector Graphic - Fill","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Group 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":23,"st":0,"bm":0}]}],"layers":[{"ddd":0,"ind":1,"ty":0,"nm":"Bounce_no_easing","refId":"comp_0","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[560,733,0],"ix":2},"a":{"a":0,"k":[562.5,1218,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"tm":{"a":1,"k":[{"i":{"x":[0],"y":[1]},"o":{"x":[0.135],"y":[0]},"t":0,"s":[0],"e":[0.4]},{"i":{"x":[0.928],"y":[1]},"o":{"x":[1],"y":[0]},"t":8,"s":[0.4],"e":[0.733]},{"i":{"x":[0.858],"y":[1]},"o":{"x":[0.158],"y":[0]},"t":16,"s":[0.733],"e":[0.733]},{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.037],"y":[0]},"t":102,"s":[0.733],"e":[10]},{"t":300}],"ix":2},"w":1125,"h":2436,"ip":0,"op":21,"st":0,"bm":0}],"markers":[{"tm":95,"cm":"1","dr":0}]}"
speed={1}
style={
{
diff --git a/app/components/Views/LockScreen/index.test.tsx b/app/components/Views/LockScreen/index.test.tsx
index 2fb8d2873e7..05afe792def 100644
--- a/app/components/Views/LockScreen/index.test.tsx
+++ b/app/components/Views/LockScreen/index.test.tsx
@@ -2,6 +2,7 @@ import { renderScreen } from '../../../util/test/renderWithProvider';
import initialBackgroundState from '../../../util/test/initial-background-state.json';
import LockScreen from './';
import Routes from '../../../constants/navigation/Routes';
+import { MOCK_ACCOUNTS_CONTROLLER_STATE } from '../../../util/test/accountsControllerTestUtils';
const mockInitialState = {
settings: {},
@@ -13,6 +14,7 @@ const mockInitialState = {
securityAlertsEnabled: true,
},
},
+ AccountsController: MOCK_ACCOUNTS_CONTROLLER_STATE,
},
},
};
diff --git a/app/components/Views/ManualBackupStep1/styles.ts b/app/components/Views/ManualBackupStep1/styles.ts
index 36f706c2a93..9a05b1d095a 100644
--- a/app/components/Views/ManualBackupStep1/styles.ts
+++ b/app/components/Views/ManualBackupStep1/styles.ts
@@ -3,6 +3,8 @@ import { StyleSheet } from 'react-native';
import { fontStyles } from '../../../styles/common';
import Device from '../../../util/device';
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const createStyles = (colors: any) =>
StyleSheet.create({
mainWrapper: {
diff --git a/app/components/Views/ManualBackupStep2/styles.ts b/app/components/Views/ManualBackupStep2/styles.ts
index 96b3256c289..15272e13d4e 100644
--- a/app/components/Views/ManualBackupStep2/styles.ts
+++ b/app/components/Views/ManualBackupStep2/styles.ts
@@ -2,6 +2,8 @@ import { StyleSheet } from 'react-native';
import { fontStyles } from '../../../styles/common';
import Device from '../../../util/device';
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const createStyles = (colors: any) =>
StyleSheet.create({
mainWrapper: {
diff --git a/app/components/Views/MediaPlayer/AndroidMediaPlayer.js b/app/components/Views/MediaPlayer/AndroidMediaPlayer.js
index de7f1e9896a..3103e323ad1 100644
--- a/app/components/Views/MediaPlayer/AndroidMediaPlayer.js
+++ b/app/components/Views/MediaPlayer/AndroidMediaPlayer.js
@@ -121,7 +121,7 @@ const createStyles = (theme) =>
height: 4,
width: '100%',
borderRadius: 2,
- backgroundColor: theme.brandColors.white000,
+ backgroundColor: theme.brandColors.white,
},
seekbarPermanentFill: {
width: '100%',
@@ -137,7 +137,7 @@ const createStyles = (theme) =>
top: 14,
height: 14,
width: 14,
- backgroundColor: theme.brandColors.white000,
+ backgroundColor: theme.brandColors.white,
},
actionButton: {
width: 44,
@@ -150,7 +150,7 @@ const createStyles = (theme) =>
marginHorizontal: 8,
},
actionButtons: {
- color: theme.brandColors.white000,
+ color: theme.brandColors.white,
},
});
diff --git a/app/components/Views/NetworkSelector/NetworkSelector.styles.ts b/app/components/Views/NetworkSelector/NetworkSelector.styles.ts
index b96cd5cad8d..481940e3763 100644
--- a/app/components/Views/NetworkSelector/NetworkSelector.styles.ts
+++ b/app/components/Views/NetworkSelector/NetworkSelector.styles.ts
@@ -1,26 +1,44 @@
// Third party dependencies.
import Device from '../../../util/device';
import { StyleSheet } from 'react-native';
-
+import { fontStyles } from '../../../styles/common';
/**
* Style sheet function for NetworkSelector screen.
* @returns StyleSheet object.
*/
-const styleSheet = StyleSheet.create({
- addNetworkButton: {
- marginHorizontal: 16,
- marginBottom: Device.isAndroid() ? 16 : 0,
- },
- switchContainer: {
- flexDirection: 'row',
- justifyContent: 'space-between',
- alignItems: 'center',
- marginVertical: 16,
- marginHorizontal: 16,
- },
- networkCell: {
- alignItems: 'center',
- },
-});
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const createStyles = (colors: any) =>
+ StyleSheet.create({
+ addNetworkButton: {
+ marginHorizontal: 16,
+ marginBottom: Device.isAndroid() ? 16 : 0,
+ },
+ switchContainer: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ marginVertical: 16,
+ marginHorizontal: 16,
+ },
+ addtionalNetworksContainer: {
+ marginHorizontal: 16,
+ },
+ networkCell: {
+ alignItems: 'center',
+ },
+ titleContainer: {
+ margin: 16,
+ },
+ desc: {
+ fontSize: 14,
+ color: colors.text.default,
+ ...fontStyles.normal,
+ },
+ blueText: {
+ color: colors.primary.default,
+ marginTop: 1,
+ },
+ });
-export default styleSheet;
+export default createStyles;
diff --git a/app/components/Views/NetworkSelector/NetworkSelector.test.tsx b/app/components/Views/NetworkSelector/NetworkSelector.test.tsx
index 3354b6c5347..36feaf8de3a 100644
--- a/app/components/Views/NetworkSelector/NetworkSelector.test.tsx
+++ b/app/components/Views/NetworkSelector/NetworkSelector.test.tsx
@@ -120,6 +120,8 @@ const initialState = {
const Stack = createStackNavigator();
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const renderComponent = (state: any = {}) =>
renderWithProvider(
diff --git a/app/components/Views/NetworkSelector/NetworkSelector.tsx b/app/components/Views/NetworkSelector/NetworkSelector.tsx
index d512169712d..24ff171bf65 100644
--- a/app/components/Views/NetworkSelector/NetworkSelector.tsx
+++ b/app/components/Views/NetworkSelector/NetworkSelector.tsx
@@ -1,6 +1,6 @@
// Third party dependencies.
-import React, { useRef } from 'react';
-import { Switch, View } from 'react-native';
+import React, { useRef, useState } from 'react';
+import { Linking, Switch, View } from 'react-native';
import { ScrollView } from 'react-native-gesture-handler';
import images from 'images/image-icons';
import { useNavigation } from '@react-navigation/native';
@@ -11,7 +11,10 @@ import SheetHeader from '../../../component-library/components/Sheet/SheetHeader
import Cell, {
CellVariant,
} from '../../../component-library/components/Cells/Cell';
-import { AvatarVariant } from '../../../component-library/components/Avatars/Avatar';
+import {
+ AvatarSize,
+ AvatarVariant,
+} from '../../../component-library/components/Avatars/Avatar';
import { strings } from '../../../../locales/i18n';
import BottomSheet, {
BottomSheetRef,
@@ -28,6 +31,7 @@ import Networks, {
getDecimalChainId,
isTestNet,
getNetworkImageSource,
+ isNetworkUiRedesignEnabled,
} from '../../../util/networks';
import {
LINEA_MAINNET,
@@ -55,20 +59,29 @@ import { updateIncomingTransactions } from '../../../util/transaction-controller
import { useMetrics } from '../../../components/hooks/useMetrics';
// Internal dependencies
-import styles from './NetworkSelector.styles';
+import createStyles from './NetworkSelector.styles';
import { TESTNET_TICKER_SYMBOLS } from '@metamask/controller-utils';
+import InfoModal from '../../../../app/components/UI/Swaps/components/InfoModal';
+import hideKeyFromUrl from '../../../util/hideKeyFromUrl';
+import CustomNetwork from '../Settings/NetworksSettings/NetworkSettings/CustomNetworkView/CustomNetwork';
const NetworkSelector = () => {
+ const [showPopularNetworkModal, setShowPopularNetworkModal] = useState(false);
+ const [popularNetwork, setPopularNetwork] = useState(undefined);
+ const [showWarningModal, setShowWarningModal] = useState(false);
const { navigate } = useNavigation();
const theme = useTheme();
const { trackEvent } = useMetrics();
const { colors } = theme;
+ const styles = createStyles(colors);
const sheetRef = useRef(null);
const showTestNetworks = useSelector(selectShowTestNetworks);
const providerConfig: ProviderConfig = useSelector(selectProviderConfig);
const networkConfigurations = useSelector(selectNetworkConfigurations);
+ const avatarSize = isNetworkUiRedesignEnabled ? AvatarSize.Sm : undefined;
+
// The only possible value types are mainnet, linea-mainnet, sepolia and linea-sepolia
const onNetworkChange = (type: string) => {
const {
@@ -129,6 +142,31 @@ const NetworkSelector = () => {
}
};
+ // TODO: type the any below to import { Network } from './CustomNetwork.types';
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const showNetworkModal = (networkConfiguration: any) => {
+ setShowPopularNetworkModal(true);
+ setPopularNetwork({
+ ...networkConfiguration,
+ formattedRpcUrl: networkConfiguration.warning
+ ? null
+ : hideKeyFromUrl(networkConfiguration.rpcUrl),
+ });
+ };
+
+ const onCancel = () => {
+ setShowPopularNetworkModal(false);
+ setPopularNetwork(undefined);
+ };
+
+ const toggleWarningModal = () => {
+ setShowWarningModal(!showWarningModal);
+ };
+ const goToLearnMore = () => {
+ Linking.openURL(strings('networks.learn_more_url'));
+ };
+
const renderMainnet = () => {
const { name: mainnetName, chainId } = Networks.mainnet;
return (
@@ -139,6 +177,7 @@ const NetworkSelector = () => {
variant: AvatarVariant.Network,
name: mainnetName,
imageSource: images.ETHEREUM,
+ size: avatarSize,
}}
isSelected={
chainId === providerConfig.chainId && !providerConfig.rpcUrl
@@ -159,6 +198,7 @@ const NetworkSelector = () => {
variant: AvatarVariant.Network,
name: lineaMainnetName,
imageSource: images['LINEA-MAINNET'],
+ size: avatarSize,
}}
isSelected={chainId === providerConfig.chainId}
onPress={() => onNetworkChange(LINEA_MAINNET)}
@@ -183,6 +223,7 @@ const NetworkSelector = () => {
variant: AvatarVariant.Network,
name,
imageSource: image,
+ size: avatarSize,
}}
isSelected={Boolean(
chainId === providerConfig.chainId && providerConfig.rpcUrl,
@@ -198,6 +239,8 @@ const NetworkSelector = () => {
const getOtherNetworks = () => getAllNetworks().slice(2);
return getOtherNetworks().map((networkType) => {
// TODO: Provide correct types for network.
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const { name, imageSource, chainId } = (Networks as any)[networkType];
return (
@@ -209,6 +252,7 @@ const NetworkSelector = () => {
variant: AvatarVariant.Network,
name,
imageSource,
+ size: avatarSize,
}}
isSelected={chainId === providerConfig.chainId}
onPress={() => onNetworkChange(networkType)}
@@ -241,7 +285,7 @@ const NetworkSelector = () => {
true: colors.primary.default,
false: colors.border.muted,
}}
- thumbColor={theme.brandColors.white000}
+ thumbColor={theme.brandColors.white}
ios_backgroundColor={colors.border.muted}
testID={NetworkListModalSelectorsIDs.TEST_NET_TOGGLE}
disabled={isTestNet(providerConfig.chainId)}
@@ -249,13 +293,38 @@ const NetworkSelector = () => {
);
+ const renderAdditonalNetworks = () => (
+
+
+
+ );
+
+ const renderTitle = (title: string) => (
+
+
+ {strings(title)}
+
+
+ );
+
return (
+ {isNetworkUiRedesignEnabled && renderTitle('networks.enabled_networks')}
{renderMainnet()}
{renderLineaMainnet()}
{renderRpcNetworks()}
+ {isNetworkUiRedesignEnabled &&
+ renderTitle('networks.additional_networks')}
+ {isNetworkUiRedesignEnabled && renderAdditonalNetworks()}
{renderTestNetworksSwitch()}
{showTestNetworks && renderOtherNetworks()}
@@ -269,6 +338,23 @@ const NetworkSelector = () => {
style={styles.addNetworkButton}
testID={NetworkListModalSelectorsIDs.ADD_BUTTON}
/>
+ {showWarningModal ? (
+
+
+ {strings('networks.network_warning_desc')}
+ {' '}
+
+ {strings('networks.learn_more')}
+
+
+ }
+ toggleModal={toggleWarningModal}
+ />
+ ) : null}
);
};
diff --git a/app/components/Views/NetworkSelector/__snapshots__/NetworkSelector.test.tsx.snap b/app/components/Views/NetworkSelector/__snapshots__/NetworkSelector.test.tsx.snap
index 6b232fa0ad1..f0f74c96292 100644
--- a/app/components/Views/NetworkSelector/__snapshots__/NetworkSelector.test.tsx.snap
+++ b/app/components/Views/NetworkSelector/__snapshots__/NetworkSelector.test.tsx.snap
@@ -372,15 +372,15 @@ exports[`Network Selector renders correctly 1`] = `
style={
[
{
- "backgroundColor": "#FFFFFF",
- "borderColor": "#D6D9DC",
+ "backgroundColor": "#ffffff",
+ "borderColor": "#bbc0c566",
"borderTopLeftRadius": 8,
"borderTopRightRadius": 8,
"borderWidth": 1,
"maxHeight": 1314,
"overflow": "hidden",
"paddingBottom": 0,
- "shadowColor": "#0000001A",
+ "shadowColor": "#0000001a",
"shadowOffset": {
"height": 2,
"width": 0,
@@ -410,7 +410,7 @@ exports[`Network Selector renders correctly 1`] = `
@@ -1134,7 +1134,7 @@ exports[`Network Selector renders correctly 1`] = `
"alignItems": "center",
"alignSelf": "stretch",
"backgroundColor": "transparent",
- "borderColor": "#0376C9",
+ "borderColor": "#0376c9",
"borderRadius": 24,
"borderWidth": 1,
"flexDirection": "row",
@@ -1152,7 +1152,7 @@ exports[`Network Selector renders correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#0376C9",
+ "color": "#0376c9",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
diff --git a/app/components/Views/Notifications/Details/Announcements/__snapshots__/index.test.tsx.snap b/app/components/Views/Notifications/Details/Announcements/__snapshots__/index.test.tsx.snap
new file mode 100644
index 00000000000..ad6748cb0a0
--- /dev/null
+++ b/app/components/Views/Notifications/Details/Announcements/__snapshots__/index.test.tsx.snap
@@ -0,0 +1,126 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`AnnouncementsDetails should renders correctly 1`] = `
+
+
+
+
+
+ Welcome to the new MyMetaverse!
+
+
+ We are excited to announce the launch of our brand new website and app!
+
+
+
+ Learn more
+
+
+
+
+`;
diff --git a/app/components/Views/Notifications/Details/Announcements/index.test.tsx b/app/components/Views/Notifications/Details/Announcements/index.test.tsx
new file mode 100644
index 00000000000..7a2fe0e4f50
--- /dev/null
+++ b/app/components/Views/Notifications/Details/Announcements/index.test.tsx
@@ -0,0 +1,59 @@
+import React from 'react';
+import { NavigationProp, ParamListBase } from '@react-navigation/native';
+import { Provider } from 'react-redux';
+import configureMockStore from 'redux-mock-store';
+import { render } from '@testing-library/react-native';
+
+import AnnouncementsDetails from '.';
+import { createStyles } from '../styles';
+import MOCK_NOTIFICATIONS from '../../../../../components/UI/Notification/__mocks__/mock_notifications';
+import initialBackgroundState from '../../../../../util/test/initial-background-state.json';
+import { mockTheme } from '../../../../../util/theme';
+import { FeatureAnnouncementRawNotification } from '../../../../../util/notifications/types';
+
+const mockInitialState = {
+ settings: {
+ useBlockieIcon: false,
+ },
+ notificationsSettings: {
+ isEnabled: true,
+ },
+ engine: {
+ backgroundState: {
+ ...initialBackgroundState,
+ },
+ },
+};
+
+jest.mock('@react-navigation/native');
+
+describe('AnnouncementsDetails', () => {
+ const mockStore = configureMockStore();
+ const store = mockStore(mockInitialState);
+
+ let navigation: NavigationProp;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ let styles: Record;
+ beforeEach(() => {
+ navigation = {
+ navigate: jest.fn(),
+ } as unknown as NavigationProp;
+ styles = createStyles(mockTheme);
+ });
+
+ it('should renders correctly', () => {
+ const { toJSON } = render(
+
+
+ ,
+ );
+ expect(toJSON()).toMatchSnapshot();
+ });
+});
diff --git a/app/components/Views/Notifications/Details/Announcements/index.tsx b/app/components/Views/Notifications/Details/Announcements/index.tsx
new file mode 100644
index 00000000000..922b56fd7da
--- /dev/null
+++ b/app/components/Views/Notifications/Details/Announcements/index.tsx
@@ -0,0 +1,84 @@
+import React from 'react';
+import { Image, View } from 'react-native';
+import { NavigationProp, ParamListBase } from '@react-navigation/native';
+import Button, {
+ ButtonVariants,
+} from '../../../../../component-library/components/Buttons/Button';
+
+import Text, {
+ TextColor,
+ TextVariant,
+} from '../../../../../component-library/components/Texts/Text';
+
+import { FeatureAnnouncementRawNotification } from '../../../../../util/notifications';
+import { IconName } from '../../../../../component-library/components/Icons/Icon';
+import { TypeLinkFields } from '../../../../../util/notifications/types/featureAnnouncement/TypeLink';
+
+// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires, import/no-commonjs
+const PLACEHOLDER_IMG_URI = require('../../../../../images/no-image-placeholder.jpeg');
+
+interface Props {
+ notification: FeatureAnnouncementRawNotification;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ styles: Record;
+ navigation: NavigationProp;
+}
+
+const AnnouncementsDetails: React.FC = ({
+ notification,
+ styles,
+ navigation,
+}: Props) => {
+ const handleCTAPress = () => {
+ // TODO: Currently handling CTAs with external links only. For now, we aren't handling deeplinks.
+ const { link } = notification.data as unknown as {
+ link: TypeLinkFields['fields'];
+ };
+ if (!link) return;
+ navigation.navigate('Webview', {
+ screen: 'SimpleWebview',
+ params: {
+ url: link.linkUrl,
+ },
+ });
+ };
+
+ const IMAGE_URI = notification.data.image?.file?.url || PLACEHOLDER_IMG_URI;
+ return (
+
+
+
+
+ {notification.data.title && (
+
+ {notification.data.title}
+
+ )}
+
+
+ {notification.data.longDescription}
+
+
+ {(notification.data.link || notification.data.action) && (
+
+ )}
+
+ );
+};
+
+export default AnnouncementsDetails;
diff --git a/app/components/Views/Notifications/Details/Badge/__snapshots__/index.test.tsx.snap b/app/components/Views/Notifications/Details/Badge/__snapshots__/index.test.tsx.snap
new file mode 100644
index 00000000000..b7901ab01b1
--- /dev/null
+++ b/app/components/Views/Notifications/Details/Badge/__snapshots__/index.test.tsx.snap
@@ -0,0 +1,162 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`NotificationBadge should renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+`;
diff --git a/app/components/Views/Notifications/Details/Badge/index.test.tsx b/app/components/Views/Notifications/Details/Badge/index.test.tsx
new file mode 100644
index 00000000000..e1fa5ada0ef
--- /dev/null
+++ b/app/components/Views/Notifications/Details/Badge/index.test.tsx
@@ -0,0 +1,84 @@
+import React from 'react';
+import { Provider } from 'react-redux';
+import configureMockStore from 'redux-mock-store';
+import { render } from '@testing-library/react-native';
+
+import NotificationBadge from '.';
+import { createStyles } from '../styles';
+import { mockTheme } from '../../../../../util/theme';
+import { TRIGGER_TYPES } from '../../../../../util/notifications';
+import initialBackgroundState from '../../../../../util/test/initial-background-state.json';
+
+jest.mock('@react-navigation/native');
+
+const mockedTheme = createStyles(mockTheme);
+const mockStyles = {
+ ...mockedTheme,
+};
+
+const mockInitialState = {
+ engine: {
+ backgroundState: {
+ ...initialBackgroundState,
+ },
+ },
+};
+
+describe('NotificationBadge', () => {
+ const mockStore = configureMockStore();
+ const store = mockStore(mockInitialState);
+ const commonProps = {
+ styles: mockStyles,
+ badgeImageSource: { uri: 'badgeImage' },
+ imageUrl:
+ 'https://token.api.cx.metamask.io/assets/nativeCurrencyLogos/ethereum.svg',
+ };
+
+ it('should renders correctly', () => {
+ const { toJSON } = render(
+
+
+ ,
+ );
+ expect(toJSON()).toMatchSnapshot();
+ });
+
+ it('should renders NetworkMainAssetLogo for ETH notification types', () => {
+ const { getByTestId } = render(
+
+
+ ,
+ );
+ expect(getByTestId('network-main-asset-badge')).toBeTruthy();
+ });
+
+ it('should renders AvatarToken for NFT notification types', () => {
+ const { getByTestId } = render(
+
+
+ ,
+ );
+ expect(getByTestId('avatar-asset-badge')).toBeTruthy();
+ });
+
+ it('should renders AvatarToken for non-ETH and non-NFT notification types', () => {
+ const { getByTestId } = render(
+
+
+ ,
+ );
+ expect(getByTestId('avatar-asset-badge')).toBeTruthy();
+ });
+});
diff --git a/app/components/Views/Notifications/Details/Badge/index.tsx b/app/components/Views/Notifications/Details/Badge/index.tsx
new file mode 100644
index 00000000000..f74ce3d4996
--- /dev/null
+++ b/app/components/Views/Notifications/Details/Badge/index.tsx
@@ -0,0 +1,83 @@
+import React from 'react';
+import { ImageSourcePropType } from 'react-native';
+import BadgeWrapper from '../../../../../component-library/components/Badges/BadgeWrapper';
+import Badge, {
+ BadgeVariant,
+} from '../../../../../component-library/components/Badges/Badge';
+import { BOTTOM_BADGEWRAPPER_BADGEPOSITION } from '../../../../../component-library/components/Badges/BadgeWrapper/BadgeWrapper.constants';
+import { TRIGGER_TYPES } from '../../../../../util/notifications';
+import NetworkMainAssetLogo from '../../../../UI/NetworkMainAssetLogo';
+
+import {
+ AvatarSize,
+ AvatarVariant,
+} from '../../../../../component-library/components/Avatars/Avatar';
+import AvatarToken from '../../../../../component-library/components/Avatars/Avatar/variants/AvatarToken';
+
+interface NotificationBadgeProps {
+ notificationType: TRIGGER_TYPES;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ styles: Record;
+ badgeImageSource?: ImageSourcePropType;
+ imageUrl?: string;
+}
+function NotificationBadge({
+ notificationType,
+ styles,
+ badgeImageSource,
+ imageUrl,
+}: NotificationBadgeProps) {
+ const customStyles = () => {
+ if (
+ [
+ TRIGGER_TYPES.ERC1155_RECEIVED,
+ TRIGGER_TYPES.ERC1155_SENT,
+ TRIGGER_TYPES.ERC721_RECEIVED,
+ TRIGGER_TYPES.ERC721_SENT,
+ ].includes(notificationType)
+ ) {
+ return {
+ style: styles.nftLogo,
+ placeholderStyle: styles.nftPlaceholder,
+ };
+ }
+ return {
+ style: styles.assetLogo,
+ placeholderStyle: styles.assetPlaceholder,
+ };
+ };
+
+ return (
+
+ }
+ style={styles.badgeWrapper}
+ >
+ {notificationType.toLowerCase().includes('eth') ? (
+
+ ) : (
+
+ )}
+
+ );
+}
+
+export default NotificationBadge;
diff --git a/app/components/Views/Notifications/Details/Header/__snapshots__/index.test.tsx.snap b/app/components/Views/Notifications/Details/Header/__snapshots__/index.test.tsx.snap
new file mode 100644
index 00000000000..548edbda275
--- /dev/null
+++ b/app/components/Views/Notifications/Details/Header/__snapshots__/index.test.tsx.snap
@@ -0,0 +1,16 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`Header should render correctly 1`] = `
+
+ Notification Announcement
+ This is a mock of description
+
+`;
diff --git a/app/components/Views/Notifications/Details/Header/index.test.tsx b/app/components/Views/Notifications/Details/Header/index.test.tsx
new file mode 100644
index 00000000000..4d24b187055
--- /dev/null
+++ b/app/components/Views/Notifications/Details/Header/index.test.tsx
@@ -0,0 +1,27 @@
+import React from 'react';
+import Header from '.';
+import { render } from '@testing-library/react-native';
+
+jest.mock('../../../../../util/theme');
+jest.mock('@react-navigation/native');
+
+jest.mock('../../../../../component-library/components/Texts/Text', () => {
+ const originalModule = jest.requireActual(
+ '../../../../../component-library/components/Texts/Text',
+ );
+ return {
+ ...originalModule,
+ __esModule: true,
+ default: jest.fn(({ children }) => children),
+ };
+});
+
+describe('Header', () => {
+ const TITLE = 'Notification Announcement';
+ const DESCRIPTION = 'This is a mock of description';
+
+ it('should render correctly', () => {
+ const { toJSON } = render();
+ expect(toJSON()).toMatchSnapshot();
+ });
+});
diff --git a/app/components/Views/Notifications/Details/Header/index.tsx b/app/components/Views/Notifications/Details/Header/index.tsx
new file mode 100644
index 00000000000..c3d7d092ecb
--- /dev/null
+++ b/app/components/Views/Notifications/Details/Header/index.tsx
@@ -0,0 +1,45 @@
+import React from 'react';
+import { View } from 'react-native';
+
+import Text, {
+ TextColor,
+ TextVariant,
+} from '../../../../../component-library/components/Texts/Text';
+import { useTheme } from '../../../../../util/theme';
+import { createStyles } from '../styles';
+import NotificationsDetailViewSelectorsIDs from '../../constants';
+
+const Header = ({ title, subtitle }: { title: string; subtitle: string }) => {
+ const theme = useTheme();
+ const styles = createStyles(theme);
+
+ return (
+
+
+ {title}
+
+
+ {subtitle}
+
+
+ );
+};
+
+export default Header;
diff --git a/app/components/Views/Notifications/Details/NetworkFee/index.tsx b/app/components/Views/Notifications/Details/NetworkFee/index.tsx
new file mode 100644
index 00000000000..e1d962fa7e1
--- /dev/null
+++ b/app/components/Views/Notifications/Details/NetworkFee/index.tsx
@@ -0,0 +1,101 @@
+import React, { useCallback, useEffect, useState } from 'react';
+import { View } from 'react-native';
+
+import { strings } from '../../../../../../locales/i18n';
+
+import BottomSheet, {
+ BottomSheetRef,
+} from '../../../../../component-library/components/BottomSheets/BottomSheet';
+import Text, {
+ TextColor,
+ TextVariant,
+} from '../../../../../component-library/components/Texts/Text';
+
+import type { HalRawNotificationsWithNetworkFields } from '../../../../../util/notifications/types/halNotification';
+import {
+ getNetworkFees,
+ networkFeeDetails,
+} from '../../../../../util/notifications';
+
+type NetworkFees = {
+ transactionFee: {
+ transactionFeeInEther: string;
+ transactionFeeInUsd: string;
+ };
+ gasLimitUnits: number;
+ gasUsedUnits: number;
+ baseFee: string | null;
+ priorityFee: string | null;
+ maxFeePerGas: string | null;
+} | null;
+
+interface NotificationModalNetworkFeeProps {
+ notification: HalRawNotificationsWithNetworkFields;
+ sheetRef: React.RefObject;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ styles: Record;
+ onClosed: () => void;
+}
+
+const NetworkFee = ({
+ notification,
+ sheetRef,
+ styles,
+ onClosed,
+}: NotificationModalNetworkFeeProps) => {
+ const [networkFees, setNetworkFees] = useState(null);
+ const [networkFeesError, setNetworkFeesError] = useState(false);
+
+ const fetchNetworkFees = useCallback(async () => {
+ try {
+ const fees = await getNetworkFees(notification);
+ if (fees) {
+ setNetworkFees({
+ transactionFee: {
+ transactionFeeInEther: fees.transactionFeeInEth,
+ transactionFeeInUsd: fees.transactionFeeInUsd,
+ },
+ gasLimitUnits: fees.gasLimit,
+ gasUsedUnits: fees.gasUsed,
+ baseFee: fees.baseFee,
+ priorityFee: fees.priorityFee,
+ maxFeePerGas: fees.maxFeePerGas,
+ });
+ }
+ } catch (err) {
+ setNetworkFeesError(true);
+ }
+ }, [notification]);
+
+ useEffect(() => {
+ fetchNetworkFees();
+ }, [fetchNetworkFees]);
+
+ // TODO: Present an error screen when there is an error fetching the network fees
+ return (
+
+ {!networkFeesError && (
+
+ {Object.keys(networkFeeDetails).map((key, value) => (
+
+
+ {strings(key)}
+
+
+ {networkFees?.[networkFeeDetails[value] as keyof NetworkFees] ||
+ 'N/A'}
+
+
+ ))}
+
+ )}
+
+ );
+};
+
+export default NetworkFee;
diff --git a/app/components/Views/Notifications/Details/OnChain/__snapshots__/index.test.tsx.snap b/app/components/Views/Notifications/Details/OnChain/__snapshots__/index.test.tsx.snap
new file mode 100644
index 00000000000..45c67e1e9dd
--- /dev/null
+++ b/app/components/Views/Notifications/Details/OnChain/__snapshots__/index.test.tsx.snap
@@ -0,0 +1,1073 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`OnChainDetails should renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Staked
+
+
+ Ethereum
+
+
+
+
+ 330303634023928032
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Received
+
+
+ Liquid staked Ether 2.0
+
+
+
+
+ 330303634023928032
+
+
+
+
+
+
+
+
+
+
+ Status
+
+
+ Confirmed
+
+
+
+
+ Transaction ID
+
+
+
+
+
+
+
+
+ Staking Provider
+
+
+ Lido-staked ETH
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Gas Limit (Units)
+
+
+ N/A
+
+
+
+
+ Gas Used (Units)
+
+
+ N/A
+
+
+
+
+ Base Fee (GWEI)
+
+
+ N/A
+
+
+
+
+ Priority Fee (GWEI)
+
+
+ N/A
+
+
+
+
+ Max Fee Per Gas
+
+
+ N/A
+
+
+
+
+
+
+
+
+ View on Etherscan
+
+
+
+
+`;
diff --git a/app/components/Views/Notifications/Details/OnChain/index.test.tsx b/app/components/Views/Notifications/Details/OnChain/index.test.tsx
new file mode 100644
index 00000000000..5cd06b06189
--- /dev/null
+++ b/app/components/Views/Notifications/Details/OnChain/index.test.tsx
@@ -0,0 +1,92 @@
+import React from 'react';
+import { NavigationProp, ParamListBase } from '@react-navigation/native';
+import { Provider } from 'react-redux';
+import configureMockStore from 'redux-mock-store';
+import { render } from '@testing-library/react-native';
+
+import OnChainDetails from '.';
+import { createStyles } from '../styles';
+import MOCK_NOTIFICATIONS from '../../../../../components/UI/Notification/__mocks__/mock_notifications';
+import initialBackgroundState from '../../../../../util/test/initial-background-state.json';
+import { mockTheme } from '../../../../../util/theme';
+import { HalRawNotification } from '../../../../../util/notifications/types';
+import { AvatarAccountType } from '../../../../../component-library/components/Avatars/Avatar';
+
+const mockInitialState = {
+ settings: {
+ useBlockieIcon: false,
+ },
+ notificationsSettings: {
+ isEnabled: true,
+ },
+ engine: {
+ backgroundState: {
+ ...initialBackgroundState,
+ },
+ },
+};
+const accountAvatarType = AvatarAccountType.Blockies;
+const copyToClipboard = jest.fn();
+
+jest.mock('@react-navigation/native');
+jest.mock('react-native-safe-area-context', () => {
+ const inset = { top: 0, right: 0, bottom: 0, left: 0 };
+ const frame = { width: 0, height: 0, x: 0, y: 0 };
+ return {
+ SafeAreaProvider: jest.fn().mockImplementation(({ children }) => children),
+ SafeAreaConsumer: jest
+ .fn()
+ .mockImplementation(({ children }) => children(inset)),
+ useSafeAreaInsets: jest.fn().mockImplementation(() => inset),
+ useSafeAreaFrame: jest.fn().mockImplementation(() => frame),
+ };
+});
+
+describe('OnChainDetails', () => {
+ const mockStore = configureMockStore();
+ const store = mockStore(mockInitialState);
+
+ let navigation: NavigationProp;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ let styles: Record;
+
+ beforeEach(() => {
+ navigation = {
+ navigate: jest.fn(),
+ } as unknown as NavigationProp;
+ styles = createStyles(mockTheme);
+ });
+
+ it('should renders correctly', () => {
+ const { toJSON } = render(
+
+
+ ,
+ );
+ expect(toJSON()).toMatchSnapshot();
+ });
+
+ it('renders the notification details correctly', () => {
+ const { getByText } = render(
+
+
+ ,
+ );
+ expect(getByText('Liquid staked Ether 2.0')).toBeTruthy();
+ });
+});
diff --git a/app/components/Views/Notifications/Details/OnChain/index.tsx b/app/components/Views/Notifications/Details/OnChain/index.tsx
new file mode 100644
index 00000000000..c96d5a58fcf
--- /dev/null
+++ b/app/components/Views/Notifications/Details/OnChain/index.tsx
@@ -0,0 +1,137 @@
+/* eslint-disable react/prop-types */
+import React, { useCallback, useRef, useState } from 'react';
+import { Linking, View } from 'react-native';
+import { useSelector } from 'react-redux';
+import { NavigationProp, ParamListBase } from '@react-navigation/native';
+import { strings } from '../../../../../../locales/i18n';
+
+import {
+ getRowDetails,
+ HalRawNotification,
+ HalRawNotificationsWithNetworkFields,
+ Notification,
+ TRIGGER_TYPES,
+} from '../../../../../util/notifications';
+
+import { AvatarAccountType } from '../../../../../component-library/components/Avatars/Avatar';
+import { BottomSheetRef } from '../../../../../component-library/components/BottomSheets/BottomSheet';
+import Button, {
+ ButtonVariants,
+} from '../../../../../component-library/components/Buttons/Button';
+import { IconName } from '../../../../../component-library/components/Icons/Icon';
+
+import { Theme } from '../../../../../util/theme/models';
+import useDetails from '../hooks/useDetails';
+import NetworkFee from '../NetworkFee';
+import {
+ selectNetworkConfigurations,
+ selectProviderConfig,
+} from '../../../../../selectors/networkController';
+
+import useBlockExplorer from '../../../../../components/UI/Swaps/utils/useBlockExplorer.js';
+
+interface OnChainDetailsProps {
+ notification: HalRawNotification;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ styles: Record;
+ theme: Theme;
+ accountAvatarType?: AvatarAccountType;
+ navigation: NavigationProp;
+ copyToClipboard: (type: string, selectedString?: string) => Promise;
+}
+
+const OnChainDetails = ({
+ notification,
+ styles,
+ theme,
+ accountAvatarType,
+ navigation,
+ copyToClipboard,
+}: OnChainDetailsProps) => {
+ const [isCollapsed, setIsCollapsed] = useState(false);
+ const providerConfig = useSelector(selectProviderConfig);
+ const networkConfigurations = useSelector(selectNetworkConfigurations);
+ const explorer = useBlockExplorer(providerConfig, networkConfigurations);
+
+ const handleExplorerLinkPress = useCallback((url: string) => {
+ Linking.openURL(url);
+ }, []);
+
+ const sheetRef = useRef(null);
+
+ const notificationDetails = getRowDetails(
+ notification as Notification,
+ )?.details;
+
+ const {
+ renderNFT,
+ renderTransfer,
+ renderStake,
+ renderStakeReadyToBeWithdrawn,
+ renderSwap,
+ } = useDetails({
+ theme,
+ accountAvatarType,
+ navigation,
+ copyToClipboard,
+ });
+
+ const renderNotificationDetails = useCallback(() => {
+ switch (notification.type) {
+ case TRIGGER_TYPES.ERC721_SENT:
+ case TRIGGER_TYPES.ERC721_RECEIVED:
+ case TRIGGER_TYPES.ERC1155_SENT:
+ case TRIGGER_TYPES.ERC1155_RECEIVED:
+ return renderNFT(notificationDetails);
+ case TRIGGER_TYPES.LIDO_STAKE_COMPLETED:
+ case TRIGGER_TYPES.LIDO_WITHDRAWAL_COMPLETED:
+ case TRIGGER_TYPES.LIDO_WITHDRAWAL_REQUESTED:
+ case TRIGGER_TYPES.ROCKETPOOL_STAKE_COMPLETED:
+ case TRIGGER_TYPES.ROCKETPOOL_UNSTAKE_COMPLETED:
+ return renderStake(notificationDetails);
+ case TRIGGER_TYPES.ERC20_RECEIVED:
+ return renderTransfer(notificationDetails);
+ case TRIGGER_TYPES.LIDO_STAKE_READY_TO_BE_WITHDRAWN:
+ return renderStakeReadyToBeWithdrawn(notificationDetails);
+ case TRIGGER_TYPES.METAMASK_SWAP_COMPLETED:
+ return renderSwap(notificationDetails);
+ case TRIGGER_TYPES.ERC20_SENT:
+ default:
+ return renderTransfer(notificationDetails);
+ }
+ }, [
+ notification.type,
+ notificationDetails,
+ renderNFT,
+ renderStake,
+ renderStakeReadyToBeWithdrawn,
+ renderSwap,
+ renderTransfer,
+ ]);
+
+ return (
+
+ {renderNotificationDetails()}
+ {!isCollapsed && (
+ setIsCollapsed(true)}
+ />
+ )}
+
+ );
+};
+
+export default OnChainDetails;
diff --git a/app/components/Views/Notifications/Details/__snapshots__/index.test.tsx.snap b/app/components/Views/Notifications/Details/__snapshots__/index.test.tsx.snap
new file mode 100644
index 00000000000..1a11adc1d25
--- /dev/null
+++ b/app/components/Views/Notifications/Details/__snapshots__/index.test.tsx.snap
@@ -0,0 +1,1089 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`NotificationsDetails should renders correctly 1`] = `
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Staked
+
+
+ Ethereum
+
+
+
+
+ 330303634023928032
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Received
+
+
+ Liquid staked Ether 2.0
+
+
+
+
+ 330303634023928032
+
+
+
+
+
+
+
+
+
+
+ Status
+
+
+ Confirmed
+
+
+
+
+ Transaction ID
+
+
+
+
+
+
+
+
+ Staking Provider
+
+
+ Lido-staked ETH
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Gas Limit (Units)
+
+
+ N/A
+
+
+
+
+ Gas Used (Units)
+
+
+ N/A
+
+
+
+
+ Base Fee (GWEI)
+
+
+ N/A
+
+
+
+
+ Priority Fee (GWEI)
+
+
+ N/A
+
+
+
+
+ Max Fee Per Gas
+
+
+ N/A
+
+
+
+
+
+
+
+
+ View on Etherscan
+
+
+
+
+
+
+`;
diff --git a/app/components/Views/Notifications/Details/hooks/useDetails.test.tsx b/app/components/Views/Notifications/Details/hooks/useDetails.test.tsx
new file mode 100644
index 00000000000..64d3608cddf
--- /dev/null
+++ b/app/components/Views/Notifications/Details/hooks/useDetails.test.tsx
@@ -0,0 +1,45 @@
+import { useSelector, useDispatch } from 'react-redux';
+import useDetails from './useDetails';
+import { AvatarAccountType } from '../../../../../component-library/components/Avatars/Avatar';
+import { mockTheme } from '../../../../../util/theme';
+import { renderHookWithProvider } from '../../../../../util/test/renderWithProvider';
+
+jest.mock('react-redux', () => ({
+ ...jest.requireActual('react-redux'),
+ useSelector: jest.fn(),
+ useDispatch: jest.fn(),
+}));
+
+describe('useDetails', () => {
+ const mockUseSelector = useSelector as jest.Mock;
+ const mockUseDispatch = useDispatch as jest.Mock;
+
+ beforeEach(() => {
+ mockUseSelector.mockReset();
+ mockUseDispatch.mockReset();
+ });
+
+ it('should return renderNFT, renderTransfer, renderStake, renderStakeReadyToBeWithdrawn and renderSwap functions', () => {
+ const { result } = renderHookWithProvider(() =>
+ useDetails({
+ theme: mockTheme,
+ accountAvatarType: AvatarAccountType.JazzIcon,
+ navigation: {},
+ copyToClipboard: () => Promise.resolve(),
+ }),
+ );
+
+ const {
+ renderNFT,
+ renderTransfer,
+ renderStake,
+ renderStakeReadyToBeWithdrawn,
+ renderSwap,
+ } = result.current;
+ expect(renderNFT).toBeDefined();
+ expect(renderTransfer).toBeDefined();
+ expect(renderStake).toBeDefined();
+ expect(renderStakeReadyToBeWithdrawn).toBeDefined();
+ expect(renderSwap).toBeDefined();
+ });
+});
diff --git a/app/components/Views/Notifications/Details/hooks/useDetails.tsx b/app/components/Views/Notifications/Details/hooks/useDetails.tsx
new file mode 100644
index 00000000000..8b3d6ae926a
--- /dev/null
+++ b/app/components/Views/Notifications/Details/hooks/useDetails.tsx
@@ -0,0 +1,512 @@
+import React, { useCallback } from 'react';
+import { Pressable, View } from 'react-native';
+import { useSelector } from 'react-redux';
+
+import Badge, {
+ BadgeVariant,
+} from '../../../../../component-library/components/Badges/Badge';
+import RemoteImage from '../../../../Base/RemoteImage';
+import NftFallbackImage from '../../../../../../docs/assets/nft-fallback.png';
+import Avatar, {
+ AvatarAccountType,
+ AvatarSize,
+ AvatarVariant,
+} from '../../../../../component-library/components/Avatars/Avatar';
+import EthereumAddress from '../../../../UI/EthereumAddress';
+
+import { strings } from '../../../../../../locales/i18n';
+import Text, {
+ TextColor,
+ TextVariant,
+} from '../../../../../component-library/components/Texts/Text';
+import {
+ selectConversionRate,
+ selectCurrentCurrency,
+} from '../../../../../selectors/currencyRateController';
+import { selectContractExchangeRates } from '../../../../../selectors/tokenRatesController';
+
+import { balanceToFiat } from '../../../../../util/number';
+
+import {
+ TRIGGER_TYPES,
+ TxStatus,
+ returnAvatarProps,
+ STAKING_PROVIDER_MAP,
+} from '../../../../../util/notifications';
+
+import Icon, {
+ IconColor,
+ IconName,
+ IconSize,
+} from '../../../../../component-library/components/Icons/Icon';
+import { createStyles } from '../styles';
+import { Theme } from '../../../../../util/theme/models';
+import NotificationBadge from '../Badge';
+import BadgeWrapper from '../../../../../component-library/components/Badges/BadgeWrapper';
+import { DEFAULT_BADGEWRAPPER_BADGEPOSITION } from '../../../../../component-library/components/Badges/BadgeWrapper/BadgeWrapper.constants';
+
+interface UseDetailsProps {
+ theme: Theme;
+ accountAvatarType?: AvatarAccountType;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ navigation: any;
+ copyToClipboard: (type: string, selectedString?: string) => Promise;
+}
+
+const useDetails = ({
+ theme,
+ accountAvatarType,
+ navigation,
+ copyToClipboard,
+}: UseDetailsProps) => {
+ const ADD = 'add';
+ const conversionRate = useSelector(selectConversionRate);
+ const currentCurrency = useSelector(selectCurrentCurrency);
+ const contractExchangeRates = useSelector(selectContractExchangeRates);
+ const styles = createStyles(theme);
+
+ const renderAddress = useCallback(
+ ({
+ key,
+ address,
+ actionType,
+ }: {
+ key: string;
+ address: string;
+ actionType: TRIGGER_TYPES;
+ }) => {
+ const showsAddContact =
+ (actionType?.includes('received') && key === 'from') ||
+ (actionType?.includes('sent') && key === 'to');
+ return (
+
+
+
+
+ {strings(
+ key === 'from' ? 'transactions.from' : 'transactions.to',
+ )}
+
+ copyToClipboard('address', address)}
+ hitSlop={{ top: 24, bottom: 24, left: 24, right: 24 }}
+ >
+
+
+
+
+ {showsAddContact && (
+ navigation.navigate('ContactForm', { mode: ADD })}
+ >
+
+ {strings('address_book.add_contact')}
+
+
+ )}
+
+ );
+ },
+ [accountAvatarType, copyToClipboard, navigation, styles],
+ );
+
+ const renderStatus = useCallback(
+ (status: TxStatus, tx_hash: string) => (
+
+
+
+
+ {strings('transactions.status')}
+
+
+
+ {strings(`transaction.${status}`)}
+
+
+ copyToClipboard('transaction', tx_hash)}
+ hitSlop={{ top: 24, bottom: 24, left: 24, right: 24 }}
+ >
+
+ {strings('transaction.transaction_id')}
+
+
+
+
+ ),
+ [
+ copyToClipboard,
+ styles.badgeWrapper,
+ styles.boxLeft,
+ styles.copyIconRight,
+ styles.copyTextBtn,
+ styles.rightSection,
+ styles.row,
+ theme,
+ ],
+ );
+
+ const renderNetwork = useCallback(
+ (network) => (
+
+
+
+
+
+ {strings('asset_details.network')}
+
+
+
+ {network.name}
+
+
+
+ ),
+ [styles.badgeWrapper, styles.boxLeft, styles.row],
+ );
+
+ const renderCollection = useCallback(
+ (collection, network) => (
+
+
+ }
+ style={styles.badgeWrapper}
+ >
+
+
+
+
+ {strings('collectible.collection')}
+
+
+ {collection.name}
+
+
+
+ ),
+ [styles],
+ );
+
+ const renderAsset = useCallback(
+ (type, title, token, network) => {
+ const exchangeRate =
+ token.address && contractExchangeRates[token.address];
+ const balanceFiat = token
+ ? balanceToFiat(
+ token.amount || '0',
+ conversionRate,
+ exchangeRate || 0,
+ currentCurrency,
+ )
+ : undefined;
+ return (
+
+
+
+ {title}
+
+ {token.name}
+
+
+
+
+ {token.amount || 0 + ' ' + token?.symbol}
+
+
+ {balanceFiat}
+
+
+
+ );
+ },
+ [contractExchangeRates, conversionRate, currentCurrency, styles],
+ );
+
+ const renderNFT = useCallback(
+ (notificationDetails) => {
+ const { type, nft, from, to, status, tx_hash, collection, network } =
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ notificationDetails as Record;
+ return (
+ <>
+
+
+ {renderAddress({
+ key: 'from',
+ address: from,
+ actionType: type,
+ })}
+ {renderAddress({
+ key: 'to',
+ address: to,
+ actionType: type,
+ })}
+ {renderStatus(status, tx_hash)}
+ {renderCollection(collection, network)}
+ {renderNetwork(network)}
+ >
+ );
+ },
+ [
+ renderAddress,
+ renderCollection,
+ renderNetwork,
+ renderStatus,
+ styles.nftBadgeWrapper,
+ styles.nftPlaceholder,
+ styles.renderTxNFT,
+ ],
+ );
+
+ const renderTransfer = useCallback(
+ (notificationDetails) => {
+ const { type, from, to, status, tx_hash, token, network } =
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ notificationDetails as Record;
+ return (
+ <>
+ {renderAddress({
+ key: 'from',
+ address: from,
+ actionType: type,
+ })}
+ {renderAddress({
+ key: 'to',
+ address: to,
+ actionType: type,
+ })}
+ {renderAsset(type, strings('transaction.asset'), token, network)}
+ {renderStatus(status, tx_hash)}
+ {renderNetwork(network)}
+ >
+ );
+ },
+ [renderAddress, renderAsset, renderNetwork, renderStatus],
+ );
+
+ const renderStakeProvider = useCallback(
+ (type, stake_in) => {
+ //@ts-expect-error most of this types will be refactored to be using sharedlibrary ones.
+ const stakingProvider = STAKING_PROVIDER_MAP[type];
+ return (
+
+
+
+
+ {strings('notifications.staking_provider')}
+
+
+ {stakingProvider}
+
+
+
+ );
+ },
+ [styles.assetLogo, styles.assetPlaceholder, styles.boxLeft, styles.row],
+ );
+
+ const renderStake = useCallback(
+ (notificationDetails) => {
+ const { type, status, tx_hash, stake_in, stake_out, network } =
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ notificationDetails as Record;
+ const unstakingInProgress =
+ type?.indexOf(TRIGGER_TYPES.LIDO_WITHDRAWAL_REQUESTED) > -1;
+
+ if (unstakingInProgress) {
+ return;
+ }
+
+ return (
+ <>
+ {/*
+ // TODO: At the moment, we don’t show this data in the UI.
+ The backend team is working to include this information in the notifications API
+ {renderAddress({
+ key: 'from',
+ address: from,
+ actionType: type,
+ })} */}
+ {renderAsset(
+ type,
+ strings('notifications.staked'),
+ stake_in,
+ network,
+ )}
+ {renderAsset(
+ type,
+ strings('notifications.received'),
+ stake_out,
+ network,
+ )}
+ {renderStatus(status, tx_hash)}
+ {renderStakeProvider(type, stake_in)}
+ >
+ );
+ },
+ [renderAsset, renderStakeProvider, renderStatus],
+ );
+
+ const renderStakeReadyToBeWithdrawn = useCallback(
+ (notificationDetails) => {
+ const { type, staked_eth, tx_hash, status, network } =
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ notificationDetails as Record;
+
+ return (
+ <>
+ {/*
+ // TODO: At the moment, we don’t show this data in the UI.
+ The backend team is working to include this information in the notifications API
+ {renderAddress({
+ key: 'from',
+ address: from, // TODO: how to get from in a stake?
+ actionType: type,
+ })} */}
+ {renderStatus(status, tx_hash)}
+ {renderAsset(
+ type,
+ strings('notifications.unstaking_requested'),
+ staked_eth,
+ network,
+ )}
+ {renderStakeProvider(type, staked_eth)}
+ >
+ );
+ },
+ [renderAsset, renderStakeProvider, renderStatus],
+ );
+
+ const renderRate = useCallback(
+ (rate) => (
+
+
+
+
+ {strings('notifications.rate')}
+
+
+ {rate}
+
+
+
+ ),
+ [
+ styles.badgeWrapper,
+ styles.boxLeft,
+ styles.row,
+ theme.colors.success.muted,
+ ],
+ );
+
+ const renderSwap = useCallback(
+ (notificationDetails) => {
+ const { type, status, tx_hash, token_in, token_out, rate, network } =
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ notificationDetails as Record;
+ // TODO: on next change from API we need to use render the account involved on the swap.
+ return (
+ <>
+ {renderAsset(type, strings('notifications.swap'), token_in, network)}
+ {renderAsset(type, strings('notifications.to'), token_out, network)}
+ {renderStatus(status, tx_hash)}
+ {renderRate(rate)}
+ {renderNetwork(network)}
+ >
+ );
+ },
+ [renderAsset, renderNetwork, renderRate, renderStatus],
+ );
+
+ return {
+ renderNFT,
+ renderTransfer,
+ renderStake,
+ renderStakeReadyToBeWithdrawn,
+ renderSwap,
+ };
+};
+
+export default useDetails;
diff --git a/app/components/Views/Notifications/Details/index.test.tsx b/app/components/Views/Notifications/Details/index.test.tsx
new file mode 100644
index 00000000000..0a48526c3fc
--- /dev/null
+++ b/app/components/Views/Notifications/Details/index.test.tsx
@@ -0,0 +1,68 @@
+import React from 'react';
+import { NavigationProp, ParamListBase } from '@react-navigation/native';
+import { render } from '@testing-library/react-native';
+import { Provider } from 'react-redux';
+import configureMockStore from 'redux-mock-store';
+
+import NotificationsDetails from './index';
+import initialBackgroundState from '../../../../util/test/initial-background-state.json';
+import MOCK_NOTIFICATIONS from '../../../../components/UI/Notification/__mocks__/mock_notifications';
+
+const mockInitialState = {
+ settings: {
+ useBlockieIcon: false,
+ },
+ engine: {
+ backgroundState: {
+ ...initialBackgroundState,
+ },
+ },
+};
+
+jest.mock('../../../../actions/alert', () => ({
+ showAlert: jest.fn(),
+}));
+
+jest.mock('@react-navigation/native');
+jest.mock('react-native-safe-area-context', () => {
+ const inset = { top: 0, right: 0, bottom: 0, left: 0 };
+ const frame = { width: 0, height: 0, x: 0, y: 0 };
+ return {
+ SafeAreaProvider: jest.fn().mockImplementation(({ children }) => children),
+ SafeAreaConsumer: jest
+ .fn()
+ .mockImplementation(({ children }) => children(inset)),
+ useSafeAreaInsets: jest.fn().mockImplementation(() => inset),
+ useSafeAreaFrame: jest.fn().mockImplementation(() => frame),
+ };
+});
+
+describe('NotificationsDetails', () => {
+ const mockStore = configureMockStore();
+ const store = mockStore(mockInitialState);
+
+ let navigation: NavigationProp;
+
+ beforeEach(() => {
+ navigation = {
+ navigate: jest.fn(),
+ } as unknown as NavigationProp;
+ });
+
+ it('should renders correctly', () => {
+ const { toJSON } = render(
+
+
+ ,
+ );
+
+ expect(toJSON()).toMatchSnapshot();
+ });
+});
diff --git a/app/components/Views/Notifications/Details/index.tsx b/app/components/Views/Notifications/Details/index.tsx
new file mode 100644
index 00000000000..0198a5f801c
--- /dev/null
+++ b/app/components/Views/Notifications/Details/index.tsx
@@ -0,0 +1,140 @@
+/* eslint-disable react/display-name */
+import React from 'react';
+import { TouchableOpacity } from 'react-native';
+import { capitalize } from 'lodash';
+import { ScrollView } from 'react-native-gesture-handler';
+import { useDispatch, useSelector } from 'react-redux';
+
+import {
+ Notification,
+ TRIGGER_TYPES,
+ formatDate,
+ formatNotificationTitle,
+} from '../../../../util/notifications';
+
+import { useTheme } from '../../../../util/theme';
+
+import ClipboardManager from '../../../../core/ClipboardManager';
+import { strings } from '../../../../../locales/i18n';
+
+import Icon, {
+ IconName,
+ IconSize,
+} from '../../../../component-library/components/Icons/Icon';
+import { AvatarAccountType } from '../../../../component-library/components/Avatars/Avatar';
+
+import { showAlert } from '../../../../actions/alert';
+import { protectWalletModalVisible } from '../../../../actions/user';
+
+import { createStyles } from './styles';
+
+import renderAnnouncementsDetails from './Announcements';
+import renderOnChainDetails from './OnChain';
+import Header from './Header';
+
+interface Props {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ navigation: any;
+ route: {
+ params: {
+ notification: Notification;
+ };
+ };
+}
+
+const NotificationsDetails = ({ navigation, route }: Props) => {
+ const { notification } = route.params;
+
+ const dispatch = useDispatch();
+ const theme = useTheme();
+ const styles = createStyles(theme);
+
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const accountAvatarType = useSelector((state: any) =>
+ state.settings.useBlockieIcon
+ ? AvatarAccountType.Blockies
+ : AvatarAccountType.JazzIcon,
+ );
+
+ const handleShowAlert = (config: {
+ isVisible: boolean;
+ autodismiss: number;
+ content: string;
+ data: { msg: string };
+ }) => dispatch(showAlert(config));
+
+ const handleProtectWalletModalVisible = () =>
+ dispatch(protectWalletModalVisible());
+
+ const copyToClipboard = async (type: string, selectedString?: string) => {
+ if (!selectedString) return;
+ await ClipboardManager.setString(selectedString);
+ handleShowAlert({
+ isVisible: true,
+ autodismiss: 1500,
+ content: 'clipboard-alert',
+ data: {
+ msg:
+ type === 'address'
+ ? strings('notifications.address_copied_to_clipboard')
+ : strings('notifications.transaction_id_copied_to_clipboard'),
+ },
+ });
+ setTimeout(() => handleProtectWalletModalVisible(), 2000);
+ };
+
+ return (
+
+ {notification.type === TRIGGER_TYPES.FEATURES_ANNOUNCEMENT
+ ? renderAnnouncementsDetails({ notification, styles, navigation })
+ : renderOnChainDetails({
+ notification,
+ styles,
+ theme,
+ accountAvatarType,
+ navigation,
+ copyToClipboard,
+ })}
+
+ );
+};
+
+export default NotificationsDetails;
+
+NotificationsDetails.navigationOptions = ({
+ route,
+ theme,
+ navigation,
+}: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ route: any;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ theme: any;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ navigation: any;
+}) => ({
+ headerLeft: () => (
+ navigation.goBack()}>
+
+
+ ),
+ headerTitle: () => (
+
+ ),
+});
diff --git a/app/components/Views/Notifications/Details/styles.ts b/app/components/Views/Notifications/Details/styles.ts
new file mode 100644
index 00000000000..3393c2c7bc2
--- /dev/null
+++ b/app/components/Views/Notifications/Details/styles.ts
@@ -0,0 +1,178 @@
+/* eslint-disable import/prefer-default-export */
+import { StyleSheet } from 'react-native';
+import type { Theme } from '@metamask/design-tokens';
+import Device from '../../../../util/device';
+import { fontStyles } from '../../../../styles/common';
+import scaling from '../../../../util/scaling';
+
+const HEIGHT = scaling.scale(240);
+const DEVICE_WIDTH = Device.getDeviceWidth();
+const COLLECTIBLE_WIDTH = (DEVICE_WIDTH - 30 - 16) / 3;
+
+export const createStyles = ({ colors }: Theme) =>
+ StyleSheet.create({
+ contentContainerWrapper: {
+ flex: 1,
+ alignItems: 'flex-start',
+ backgroundColor: colors.background.default,
+ paddingTop: 16,
+ },
+ headerTitle: { alignItems: 'center', top: 4 },
+ row: {
+ flexDirection: 'row',
+ justifyContent: 'flex-start',
+ minWidth: '100%',
+ paddingVertical: 8,
+ paddingHorizontal: 16,
+ },
+ badgeWrapper: {
+ alignItems: 'center',
+ justifyContent: 'center',
+ alignSelf: 'flex-start',
+ position: 'absolute',
+ },
+ nftBadgeWrapper: {
+ position: 'absolute',
+ top: 0,
+ right: 0,
+ width: 12,
+ height: 12,
+ borderRadius: 6,
+ alignSelf: 'center',
+ },
+ copyIconDefault: {
+ color: colors.text.alternative,
+ marginHorizontal: 8,
+ },
+ boxLeft: { alignSelf: 'flex-start' },
+ boxRight: { marginLeft: 'auto' },
+ text: {
+ marginBottom: 8,
+ paddingHorizontal: 32,
+ textAlign: 'center',
+ },
+ descriptionContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ addressLinkLabel: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ ...(fontStyles.normal as any),
+ color: colors.text.alternative,
+ },
+ icon: { marginHorizontal: 20 },
+ touchableViewOnEtherscan: {
+ marginBottom: 24,
+ marginTop: 12,
+ },
+ viewOnEtherscan: {
+ fontSize: 16,
+ color: colors.primary.default,
+ ...fontStyles.normal,
+ textAlign: 'center',
+ },
+ renderContainer: {
+ alignItems: 'flex-start',
+ flex: 1,
+ },
+ renderFCMText: {
+ textAlign: 'left',
+ },
+ renderFCMCard: {
+ height: HEIGHT,
+ width: Device.getDeviceWidth() - 32,
+ alignContent: 'center',
+ borderRadius: 12,
+ overflow: 'hidden',
+ marginBottom: 16,
+ },
+ FCMImage: {
+ resizeMode: 'cover',
+ height: HEIGHT,
+ width: Device.getDeviceWidth() - 32,
+ },
+ renderTxContainer: {
+ alignSelf: 'center',
+ },
+ renderTxNFT: {
+ height: COLLECTIBLE_WIDTH,
+ width: COLLECTIBLE_WIDTH,
+ alignContent: 'center',
+ borderRadius: 4,
+ overflow: 'hidden',
+ alignSelf: 'center',
+ },
+ ctaBtn: {
+ bottom: 0,
+ position: 'absolute',
+ width: '90%',
+ alignSelf: 'center',
+ margin: 16,
+ backgroundColor: colors.background.default,
+ },
+ rightSection: {
+ alignSelf: 'flex-start',
+ flexDirection: 'row',
+ marginLeft: 'auto',
+ },
+ copyTextBtn: {
+ color: colors.primary.default,
+ alignSelf: 'flex-start',
+ },
+ copyIconRight: {
+ marginLeft: 8,
+ },
+ ethLogo: {
+ width: 32,
+ height: 32,
+ borderRadius: 16,
+ },
+ gasDetails: {
+ marginBottom: 80,
+ },
+ nftLogo: {
+ width: 32,
+ height: 32,
+ borderRadius: 8,
+ overflow: 'hidden',
+ borderWidth: 0.5,
+ borderColor: colors.background.alternative,
+ },
+ nftPlaceholder: {
+ backgroundColor: colors.background.alternative,
+ width: 32,
+ height: 32,
+ borderRadius: 8,
+ borderWidth: 0.5,
+ borderColor: colors.background.alternative,
+ },
+ assetLogo: {
+ width: 32,
+ height: 32,
+ borderRadius: 16,
+ overflow: 'hidden',
+ borderWidth: 0.5,
+ borderColor: colors.background.alternative,
+ },
+ assetPlaceholder: {
+ backgroundColor: colors.background.alternative,
+ width: 32,
+ height: 32,
+ borderRadius: 16,
+ borderWidth: 0.5,
+ borderColor: colors.background.alternative,
+ },
+ foxWrapper: {
+ width: 32,
+ height: 32,
+ borderRadius: 16,
+ backgroundColor: colors.background.alternative,
+ alignItems: 'center',
+ justifyContent: 'center',
+ alignSelf: 'flex-start',
+ position: 'absolute',
+ top: '25%',
+ },
+ header: { alignItems: 'center', marginTop: 4 },
+ });
diff --git a/app/components/Views/Notifications/OptIn/index.tsx b/app/components/Views/Notifications/OptIn/index.tsx
index 10ab6714303..0a09a46ac2c 100644
--- a/app/components/Views/Notifications/OptIn/index.tsx
+++ b/app/components/Views/Notifications/OptIn/index.tsx
@@ -24,6 +24,8 @@ const OptIn = () => {
const styles = createStyles(theme);
const navigation = useNavigation();
const isNotificationEnabled = useSelector(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(state: any) => state.notification?.notificationsSettings?.isEnabled,
);
const [promptCount, setPromptCount] = useState(0);
diff --git a/app/components/Views/Notifications/constants.ts b/app/components/Views/Notifications/constants.ts
new file mode 100644
index 00000000000..b31a488f1bb
--- /dev/null
+++ b/app/components/Views/Notifications/constants.ts
@@ -0,0 +1,7 @@
+const NotificationsDetailViewSelectorsIDs = {
+ NOTIFICATIONS_HEADER_CONTAINER_ID: 'notification-details-header',
+ NOTIFICATIONS_HEADER_TITLE_ID: 'notification-details-header-title',
+ NOTIFICATIONS_HEADER_SUBTITLE_ID: 'notification-details-header-subtitle',
+};
+
+export default NotificationsDetailViewSelectorsIDs;
diff --git a/app/components/Views/Notifications/index.tsx b/app/components/Views/Notifications/index.tsx
index 65dffa8c14c..eab7b912476 100644
--- a/app/components/Views/Notifications/index.tsx
+++ b/app/components/Views/Notifications/index.tsx
@@ -30,6 +30,8 @@ const NotificationsView = ({
selectedAddress,
notifications,
}: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
navigation: any;
selectedAddress: string;
notifications: Notification[];
@@ -44,6 +46,8 @@ const NotificationsView = ({
FeatureAnnouncementRawNotification[]
>([]);
const isNotificationEnabled = useSelector(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(state: any) => state.notification.notificationsSettings?.isEnabled,
);
const [loading, setLoading] = useState(false);
@@ -126,6 +130,8 @@ export default NotificationsView;
NotificationsView.navigationOptions = ({
navigation,
}: {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
navigation: any;
}) => ({
headerRight: () => (
diff --git a/app/components/Views/OfflineMode/__snapshots__/index.test.tsx.snap b/app/components/Views/OfflineMode/__snapshots__/index.test.tsx.snap
index 8b9693806ac..8205ae100be 100644
--- a/app/components/Views/OfflineMode/__snapshots__/index.test.tsx.snap
+++ b/app/components/Views/OfflineMode/__snapshots__/index.test.tsx.snap
@@ -4,7 +4,7 @@ exports[`OfflineMode should render correctly 1`] = `
@@ -102,7 +102,7 @@ exports[`DefaultSettings should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#535A61",
+ "color": "#6a737d",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
@@ -117,7 +117,7 @@ exports[`DefaultSettings should render correctly 1`] = `
onPress={[Function]}
style={
{
- "color": "#0376C9",
+ "color": "#0376c9",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
@@ -151,7 +151,7 @@ exports[`DefaultSettings should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "Euclid Circular B",
"fontSize": 16,
"fontWeight": "700",
@@ -167,7 +167,7 @@ exports[`DefaultSettings should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#535A61",
+ "color": "#6a737d",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
@@ -184,7 +184,7 @@ exports[`DefaultSettings should render correctly 1`] = `
onPress={[Function]}
style={
{
- "color": "#0376C9",
+ "color": "#0376c9",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
@@ -203,7 +203,7 @@ exports[`DefaultSettings should render correctly 1`] = `
{
"alignItems": "center",
"alignSelf": "flex-start",
- "backgroundColor": "#F2F4F6",
+ "backgroundColor": "#f2f4f6",
"borderRadius": 16,
"flexDirection": "row",
"height": 32,
@@ -217,7 +217,7 @@ exports[`DefaultSettings should render correctly 1`] = `
style={
{
"alignItems": "center",
- "backgroundColor": "#F2F4F6",
+ "backgroundColor": "#f2f4f6",
"borderRadius": 8,
"borderWidth": 1,
"height": 16,
@@ -231,7 +231,7 @@ exports[`DefaultSettings should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "Euclid Circular B",
"fontSize": 10,
"fontWeight": "400",
@@ -248,7 +248,7 @@ exports[`DefaultSettings should render correctly 1`] = `
numberOfLines={1}
style={
{
- "color": "#24272A",
+ "color": "#141618",
"flexShrink": 1,
"fontFamily": "Euclid Circular B",
"fontSize": 14,
@@ -263,7 +263,7 @@ exports[`DefaultSettings should render correctly 1`] = `
Ethereum Main Network
void;
onScanError?: (error: string) => void;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
onStartScan?: (data: any) => Promise;
origin?: string;
}
@@ -70,6 +74,8 @@ const QRScanner = () => {
navigation.goBack();
try {
onScanError?.('USER_CANCELLED');
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
console.warn(`Error setting onScanError: ${error.message}`);
}
@@ -181,6 +187,8 @@ const QRScanner = () => {
onScanSuccess(data, content);
return;
}
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const { KeyringController } = Engine.context as any;
const isUnlocked = KeyringController.isUnlocked();
@@ -215,6 +223,8 @@ const QRScanner = () => {
const handledByDeeplink = SharedDeeplinkManager.parse(content, {
origin: AppConstants.DEEPLINKS.ORIGIN_QR_CODE,
// TODO: Check is pop is still valid.
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
onHandled: () => (navigation as any).pop(2),
});
diff --git a/app/components/Views/QRScanner/styles.ts b/app/components/Views/QRScanner/styles.ts
index 1e5986e4ff7..756516f0c42 100644
--- a/app/components/Views/QRScanner/styles.ts
+++ b/app/components/Views/QRScanner/styles.ts
@@ -5,7 +5,7 @@ const createStyles = (theme: Theme) =>
StyleSheet.create({
container: {
flex: 1,
- backgroundColor: theme.brandColors.black000,
+ backgroundColor: theme.brandColors.black,
},
preview: {
flex: 1,
@@ -18,7 +18,7 @@ const createStyles = (theme: Theme) =>
marginRight: 20,
width: 40,
alignSelf: 'flex-end',
- color: theme.brandColors.white000,
+ color: theme.brandColors.white,
},
frame: {
width: 250,
@@ -31,7 +31,7 @@ const createStyles = (theme: Theme) =>
text: {
flex: 1,
fontSize: 17,
- color: theme.brandColors.white000,
+ color: theme.brandColors.white,
textAlign: 'center',
justifyContent: 'center',
marginTop: 100,
diff --git a/app/components/Views/Quiz/types.ts b/app/components/Views/Quiz/types.ts
index 07af3ee82e1..e14e9caca6c 100644
--- a/app/components/Views/Quiz/types.ts
+++ b/app/components/Views/Quiz/types.ts
@@ -14,6 +14,8 @@ export enum QuizStage {
export interface IQuizInformationProps {
title: {
content: string;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
style?: any;
};
buttons: {
@@ -25,5 +27,7 @@ export interface IQuizInformationProps {
header?: string;
image?: ImageSourcePropType;
content?: string;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
icon?: any;
}
diff --git a/app/components/Views/ResetPassword/index.js b/app/components/Views/ResetPassword/index.js
index c0546a6230c..d917a16806a 100644
--- a/app/components/Views/ResetPassword/index.js
+++ b/app/components/Views/ResetPassword/index.js
@@ -53,7 +53,7 @@ import AnimatedFox from '@metamask/react-native-animated-fox';
import { LoginOptionsSwitch } from '../../UI/LoginOptionsSwitch';
import { recreateVaultWithNewPassword } from '../../../core/Vault';
import Logger from '../../../util/Logger';
-import { selectSelectedAddress } from '../../../selectors/preferencesController';
+import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController';
import { ChoosePasswordSelectorsIDs } from '../../../../e2e/selectors/Onboarding/ChoosePassword.selectors';
const createStyles = (colors) =>
@@ -504,8 +504,8 @@ class ResetPassword extends PureComponent {
this.props.navigation.push('Webview', {
screen: 'SimpleWebview',
params: {
- url: 'https://metamask.zendesk.com/hc/en-us/articles/360039616872-How-can-I-reset-my-password-',
- title: 'metamask.zendesk.com',
+ url: 'https://support.metamask.io/managing-my-wallet/resetting-deleting-and-restoring/how-can-i-reset-my-password/',
+ title: 'support.metamask.io',
},
});
};
@@ -809,7 +809,7 @@ class ResetPassword extends PureComponent {
ResetPassword.contextType = ThemeContext;
const mapStateToProps = (state) => ({
- selectedAddress: selectSelectedAddress(state),
+ selectedAddress: selectSelectedInternalAccountChecksummedAddress(state),
});
const mapDispatchToProps = (dispatch) => ({
diff --git a/app/components/Views/RestoreWallet/RestoreWallet.tsx b/app/components/Views/RestoreWallet/RestoreWallet.tsx
index 2333630949a..256c2d99b76 100644
--- a/app/components/Views/RestoreWallet/RestoreWallet.tsx
+++ b/app/components/Views/RestoreWallet/RestoreWallet.tsx
@@ -50,6 +50,8 @@ const RestoreWallet = () => {
const [loading, setLoading] = useState(false);
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const { replace } = useNavigation>();
const deviceMetaData = useMemo(() => generateDeviceAnalyticsMetaData(), []);
diff --git a/app/components/Views/RestoreWallet/WalletResetNeeded.tsx b/app/components/Views/RestoreWallet/WalletResetNeeded.tsx
index 8fb3ecfbeeb..2d8c0875397 100644
--- a/app/components/Views/RestoreWallet/WalletResetNeeded.tsx
+++ b/app/components/Views/RestoreWallet/WalletResetNeeded.tsx
@@ -30,6 +30,8 @@ const WalletResetNeeded = () => {
const { trackEvent } = useMetrics();
const styles = createStyles(colors);
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const navigation = useNavigation>();
const deviceMetaData = useMemo(() => generateDeviceAnalyticsMetaData(), []);
diff --git a/app/components/Views/RestoreWallet/WalletRestored.tsx b/app/components/Views/RestoreWallet/WalletRestored.tsx
index dbf8ccf9d1e..d2836c0531b 100644
--- a/app/components/Views/RestoreWallet/WalletRestored.tsx
+++ b/app/components/Views/RestoreWallet/WalletRestored.tsx
@@ -34,6 +34,8 @@ const WalletRestored = () => {
const { colors } = useAppThemeFromContext();
const { trackEvent } = useMetrics();
const styles = createStyles(colors);
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const navigation = useNavigation>();
const deviceMetaData = useMemo(() => generateDeviceAnalyticsMetaData(), []);
diff --git a/app/components/Views/RevealPrivateCredential/RevealPrivateCredential.tsx b/app/components/Views/RevealPrivateCredential/RevealPrivateCredential.tsx
index a9dbab7fe4a..5e896bd75b8 100644
--- a/app/components/Views/RevealPrivateCredential/RevealPrivateCredential.tsx
+++ b/app/components/Views/RevealPrivateCredential/RevealPrivateCredential.tsx
@@ -15,6 +15,8 @@ import QRCode from 'react-native-qrcode-svg';
import ScrollableTabView, {
DefaultTabBar,
} from 'react-native-scrollable-tab-view';
+// TODO: Replace "any" with type
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
const CustomTabView = View as any;
import Icon from 'react-native-vector-icons/FontAwesome5';
import AsyncStorage from '../../../store/async-storage-wrapper';
@@ -52,15 +54,19 @@ import { getNavigationOptionsTitle } from '../../../components/UI/Navbar';
import generateTestId from '../../../../wdio/utils/generateTestId';
import { RevealSeedViewSelectorsIDs } from '../../../../e2e/selectors/Settings/SecurityAndPrivacy/RevealSeedView.selectors';
-import { selectSelectedAddress } from '../../../selectors/preferencesController';
+import { selectSelectedInternalAccountChecksummedAddress } from '../../../selectors/accountsController';
import { useMetrics } from '../../../components/hooks/useMetrics';
const PRIVATE_KEY = 'private_key';
interface IRevealPrivateCredentialProps {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
navigation: any;
credentialName: string;
cancel: () => void;
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
route: any;
}
@@ -83,7 +89,11 @@ const RevealPrivateCredential = ({
const [clipboardEnabled, setClipboardEnabled] = useState(false);
const [isModalVisible, setIsModalVisible] = useState(false);
- const selectedAddress = useSelector(selectSelectedAddress);
+ const selectedAddress = useSelector(
+ selectSelectedInternalAccountChecksummedAddress,
+ );
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const passwordSet = useSelector((state: any) => state.user.passwordSet);
const dispatch = useDispatch();
@@ -115,6 +125,8 @@ const RevealPrivateCredential = ({
pswd: string,
privCredentialName?: string,
) => {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const { KeyringController } = Engine.context as any;
const isPrivateKeyReveal = privCredentialName === PRIVATE_KEY;
@@ -134,6 +146,8 @@ const RevealPrivateCredential = ({
setClipboardPrivateCredential(privateCredential);
setUnlocked(true);
}
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (e: any) {
let msg = strings('reveal_credential.warning_incorrect_password');
if (isHardwareAccount(selectedAddress)) {
@@ -200,6 +214,8 @@ const RevealPrivateCredential = ({
};
const tryUnlock = async () => {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
const { KeyringController } = Engine.context as any;
try {
await KeyringController.verifyPassword(password);
@@ -317,6 +333,8 @@ const RevealPrivateCredential = ({
const renderTabView = (privCredentialName: string) => (
renderTabBar()}
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
onChangeTab={(event: any) => onTabBarChange(event)}
>
alignSelf: 'center',
justifyContent: 'center',
padding: 8,
- backgroundColor: theme.brandColors.white000,
+ backgroundColor: theme.brandColors.white,
},
tabUnderlineStyle: {
height: 2,
diff --git a/app/components/Views/Root/index.test.tsx b/app/components/Views/Root/index.test.tsx
index b3543d0e2ec..258bad53dfb 100644
--- a/app/components/Views/Root/index.test.tsx
+++ b/app/components/Views/Root/index.test.tsx
@@ -8,6 +8,8 @@ jest.mock('redux-persist', () => {
.mockImplementation((_, reducers) => reducers);
const mockCombineReducers = jest
.fn()
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
.mockReturnValue((reducers: any) => reducers);
return {
diff --git a/app/components/Views/SDK/SDKSessionModal/SDKSessionModal.tsx b/app/components/Views/SDK/SDKSessionModal/SDKSessionModal.tsx
index c3340971d68..6c563ce131b 100644
--- a/app/components/Views/SDK/SDKSessionModal/SDKSessionModal.tsx
+++ b/app/components/Views/SDK/SDKSessionModal/SDKSessionModal.tsx
@@ -92,6 +92,8 @@ const SDKSessionModal = ({ route }: SDKSEssionMoodalProps) => {
const styles = createStyles(colors, typography, safeAreaInsets);
const { navigate } = useNavigation();
const permittedAccountsList = useSelector(
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
(state: any) => state.engine.backgroundState.PermissionController,
);
diff --git a/app/components/Views/SDK/SDKSessionsManager/SDKSessionsManager.tsx b/app/components/Views/SDK/SDKSessionsManager/SDKSessionsManager.tsx
index defaa11edb8..43d5abc3d43 100644
--- a/app/components/Views/SDK/SDKSessionsManager/SDKSessionsManager.tsx
+++ b/app/components/Views/SDK/SDKSessionsManager/SDKSessionsManager.tsx
@@ -26,6 +26,8 @@ import { getNavigationOptionsTitle } from '../../../UI/Navbar';
import SDKSessionItem from './SDKSessionItem';
interface SDKSessionsManagerProps {
+ // TODO: Replace "any" with type
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
navigation: StackNavigationProp;
}
diff --git a/app/components/Views/Settings/AdvancedSettings/EthSignFriction/EthSignFriction.tsx b/app/components/Views/Settings/AdvancedSettings/EthSignFriction/EthSignFriction.tsx
index 46f1b830662..3289e72abf7 100644
--- a/app/components/Views/Settings/AdvancedSettings/EthSignFriction/EthSignFriction.tsx
+++ b/app/components/Views/Settings/AdvancedSettings/EthSignFriction/EthSignFriction.tsx
@@ -1,6 +1,6 @@
// Third party dependencies.
import React, { useEffect, useMemo, useRef, useState } from 'react';
-import { Platform, View } from 'react-native';
+import { View } from 'react-native';
import { useNavigation } from '@react-navigation/native';
// External dependencies.
@@ -26,13 +26,7 @@ import Button, {
} from '../../../../../component-library/components/Buttons/Button';
import AppConstants from '../../../../../core/AppConstants';
import { MetaMetricsEvents, useMetrics } from '../../../../hooks/useMetrics';
-import generateTestId from '../../../../../../wdio/utils/generateTestId';
-import {
- TOGGLE_ETH_SIGN_CONTINUE_BUTTON,
- TOGGLE_ETH_SIGN_MODAL,
- TOGGLE_ETH_SIGN_UNDERSTAND_CHECKBOX,
- TOGGLE_ETH_SIGN_UNDERSTAND_INPUT,
-} from '../../../../../../wdio/screen-objects/testIDs/Components/ToggleEthSignModal.testIds';
+import { ToggleEthSignModalSelectorsIDs } from '../../../../../../e2e/selectors/Modals/ToggleEthSignModal.selectors';
// Internal dependencies
import createStyles from './EthSignFriction.styles';
@@ -124,7 +118,7 @@ const EthSignFriction = () => {
{/*Common explanation content for both steps*/}
{
// First step checkbox content
{
)}
onEndEditing={(e) => setApproveText(e.nativeEvent.text)}
onFocus={() => setApproveText('')}
- {...generateTestId(Platform, TOGGLE_ETH_SIGN_UNDERSTAND_INPUT)}
+ testID={ToggleEthSignModalSelectorsIDs.UNDERSTAND_INPUT}
/>
{approveText.length > 0 && isPrimaryButtonDisabled && (
@@ -239,7 +233,7 @@ const EthSignFriction = () => {
: 'app_settings.toggleEthSignContinueButton',
)}
onPress={onPrimaryPress}
- {...generateTestId(Platform, TOGGLE_ETH_SIGN_CONTINUE_BUTTON)}
+ testID={ToggleEthSignModalSelectorsIDs.CONTINUE_BUTTON}
/>
diff --git a/app/components/Views/Settings/AdvancedSettings/EthSignFriction/__snapshots__/EthSignFriction.test.tsx.snap b/app/components/Views/Settings/AdvancedSettings/EthSignFriction/__snapshots__/EthSignFriction.test.tsx.snap
index e27493f3630..cbc3668dd90 100644
--- a/app/components/Views/Settings/AdvancedSettings/EthSignFriction/__snapshots__/EthSignFriction.test.tsx.snap
+++ b/app/components/Views/Settings/AdvancedSettings/EthSignFriction/__snapshots__/EthSignFriction.test.tsx.snap
@@ -21,7 +21,7 @@ exports[`Eth_sign friction bottom sheet should render initial friction step corr
{
diff --git a/app/components/Views/Settings/AdvancedSettings/FiatOnTestnetsFriction/__snapshots__/FiatOnTestnetsFriction.test.tsx.snap b/app/components/Views/Settings/AdvancedSettings/FiatOnTestnetsFriction/__snapshots__/FiatOnTestnetsFriction.test.tsx.snap
index 71494688799..58f9654aabc 100644
--- a/app/components/Views/Settings/AdvancedSettings/FiatOnTestnetsFriction/__snapshots__/FiatOnTestnetsFriction.test.tsx.snap
+++ b/app/components/Views/Settings/AdvancedSettings/FiatOnTestnetsFriction/__snapshots__/FiatOnTestnetsFriction.test.tsx.snap
@@ -69,15 +69,15 @@ exports[`Show fiat on testnets friction bottom sheet should render 1`] = `
style={
[
{
- "backgroundColor": "#FFFFFF",
- "borderColor": "#D6D9DC",
+ "backgroundColor": "#ffffff",
+ "borderColor": "#bbc0c566",
"borderTopLeftRadius": 8,
"borderTopRightRadius": 8,
"borderWidth": 1,
"maxHeight": NaN,
"overflow": "hidden",
"paddingBottom": undefined,
- "shadowColor": "#0000001A",
+ "shadowColor": "#0000001a",
"shadowOffset": {
"height": 2,
"width": 0,
@@ -107,7 +107,7 @@ exports[`Show fiat on testnets friction bottom sheet should render 1`] = `
@@ -248,7 +248,7 @@ exports[`AdvancedSettings should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#535A61",
+ "color": "#6a737d",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
@@ -266,7 +266,7 @@ exports[`AdvancedSettings should render correctly 1`] = `
onPress={[Function]}
style={
{
- "color": "#0376C9",
+ "color": "#0376c9",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
@@ -298,7 +298,7 @@ exports[`AdvancedSettings should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#24272A",
+ "color": "#141618",
"flex": 1,
"fontFamily": "Euclid Circular B",
"fontSize": 16,
@@ -324,7 +324,7 @@ exports[`AdvancedSettings should render correctly 1`] = `
onChange={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
- onTintColor="#0376C9"
+ onTintColor="#0376c9"
style={
[
{
@@ -336,14 +336,14 @@ exports[`AdvancedSettings should render correctly 1`] = `
"alignSelf": "flex-start",
},
{
- "backgroundColor": "#D6D9DC",
+ "backgroundColor": "#bbc0c566",
"borderRadius": 16,
},
],
]
}
thumbTintColor="#ffffff"
- tintColor="#D6D9DC"
+ tintColor="#bbc0c566"
value={true}
/>
@@ -352,7 +352,7 @@ exports[`AdvancedSettings should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#535A61",
+ "color": "#6a737d",
"fontFamily": "Euclid Circular B",
"fontSize": 14,
"fontWeight": "400",
@@ -384,7 +384,7 @@ exports[`AdvancedSettings should render correctly 1`] = `
accessibilityRole="text"
style={
{
- "color": "#24272A",
+ "color": "#141618",
"flex": 1,
"fontFamily": "Euclid Circular B",
"fontSize": 16,
@@ -410,7 +410,7 @@ exports[`AdvancedSettings should render correctly 1`] = `
onPress={[Function]}
style={
{
- "color": "#24272A",
+ "color": "#141618",
"fontFamily": "Euclid Circular B",
"fontSize": 12,
"fontWeight": "400",
@@ -428,7 +428,7 @@ exports[`AdvancedSettings should render correctly 1`] = `
onChange={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
- onTintColor="#0376C9"
+ onTintColor="#0376c9"
style={
[
{
@@ -440,7 +440,7 @@ exports[`AdvancedSettings should render correctly 1`] = `
"alignSelf": "flex-start",
},
{
- "backgroundColor": "#D6D9DC",
+ "backgroundColor": "#bbc0c566",
"borderRadius": 16,
},
],
@@ -448,7 +448,7 @@ exports[`AdvancedSettings should render correctly 1`] = `
}
testID="eth-sign-switch"
thumbTintColor="#ffffff"
- tintColor="#D6D9DC"
+ tintColor="#bbc0c566"
value={false}
/>