Skip to content

Commit 6b34488

Browse files
sethkfmanGustavo AntunesCal-Lrickycodesandrepimenta
authored
[HOTFIX] 4.0.1 - RC2 (#3658)
* Fix gte error (#3654) * Fix gte error * Fix * Add hextoBN * Cherry pick gte fix * Update build numbers * Update build number to 812 * [Hotfix] /4.0.1 NFT improvement (#3657) * created new shared collectibel detection info modal added to NFT wallet view * added nft info modal to import nft view * hooked up settings to engine state * added boolean for dismiss state * added action and reducer for nft dismiss state * added snap to toggles * updated nft modal styles * added comments to props * added user profile property methods * bumped version for test release analytics * yarn lint fix * updated state fetch * Switch from `develop` to `main` (#3508) * point build badges to main * point video_source_uri to main * point architecture.svg to main * point translation subtitle uris to main * [FIX] Update warning image (#3649) * Revert - use empty string quotes for anon id (#3144) (#3561) * fix: Dismiss keyboard correctly (#3644) * [FIX] Update warning image (#3649) * Revert - use empty string quotes for anon id (#3144) (#3561) * PR feedback * PR feedback * Refactor RPC Methods logic (Fix network change) (#3341) * Refactor RPC Methods * Migrate to typescript * Improve selectedAddress code * Implement Swappable proxy for provider * Fix url on rpc methods * Fix app version code * Temporarily fix Typescript issues on RPCMethodMiddleware * Remove Beta Co-authored-by: Cal Leung <[email protected]> * chore: Add `ts` and `tsx` extension to linting scripts (#3479) * Bump version name * merge issue resolution * update unit testing * added logic to display only on mainnet * added migration to make detection false * PR feedback * test case update * Revert "Refactor RPC Methods logic (Fix network change) (#3341)" This reverts commit 375f742. * revert fix for Alert * readme revert * SRP video link revert * revert SRP video subtitle links * fix for modal display in token view and animate security settings navigation * fix onboarding flow + request payments * remove contract logo filter in collectibleContractsSelector Co-authored-by: ricky <[email protected]> Co-authored-by: Gustavo Antunes <[email protected]> Co-authored-by: Andre Pimenta <[email protected]> Co-authored-by: Cal Leung <[email protected]> Co-authored-by: Pedro Pablo Aste Kompen <[email protected]> Co-authored-by: github-actions <[email protected]> Co-authored-by: Curtis <[email protected]> * version bump and migration patch (#3660) * Fix/advisory simple get (#3662) * version bump and migration patch * simple get resolver update for security advisory Co-authored-by: Gustavo Antunes <[email protected]> Co-authored-by: Cal Leung <[email protected]> Co-authored-by: ricky <[email protected]> Co-authored-by: Andre Pimenta <[email protected]> Co-authored-by: Pedro Pablo Aste Kompen <[email protected]> Co-authored-by: github-actions <[email protected]> Co-authored-by: Curtis <[email protected]>
1 parent 8f0c8da commit 6b34488

File tree

28 files changed

+312
-34
lines changed

28 files changed

+312
-34
lines changed

android/app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ android {
160160
applicationId "io.metamask"
161161
minSdkVersion rootProject.ext.minSdkVersion
162162
targetSdkVersion rootProject.ext.targetSdkVersion
163-
versionCode 810
164-
versionName "4.0.0"
163+
versionCode 814
164+
versionName "4.0.1"
165165
multiDexEnabled true
166166
testBuildType System.getProperty('testBuildType', 'debug')
167167
missingDimensionStrategy "minReactNative", "minReactNative46"

android/app/src/main/java/io/metamask/nativeModules/RCTAnalytics.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ public void peopleIdentify() {
7676
this.mixpanel.getPeople().identify(distinctId);
7777
}
7878

79+
@ReactMethod
80+
public void setUserProfileProperty(String propertyName, String propertyValue) {
81+
String distinctId = this.mixpanel.getDistinctId();
82+
this.mixpanel.getPeople().identify(distinctId);
83+
this.mixpanel.getPeople().set(propertyName, propertyValue);
84+
}
85+
7986
@ReactMethod
8087
public void optIn(boolean val) {
8188
if(val){

app/actions/user/index.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ export function setGasEducationCarouselSeen() {
6565
};
6666
}
6767

68+
export function setNftDetectionDismissed() {
69+
return {
70+
type: 'SET_NFT_DETECTION_DISMISSED',
71+
};
72+
}
73+
6874
export function logIn() {
6975
return {
7076
type: 'LOGIN',

app/components/Base/Alert.tsx

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
ViewProps,
1010
TextStyle,
1111
} from 'react-native';
12+
import IonicIcon from 'react-native-vector-icons/Ionicons';
1213
import { colors } from '../../styles/common';
1314
import CustomText from './Text';
1415
// TODO: Convert into typescript and correctly type optionals
@@ -27,6 +28,7 @@ interface Props {
2728
small?: boolean;
2829
renderIcon?: () => ReactNode;
2930
onPress?: () => void;
31+
onDismiss?: () => void;
3032
children?: ReactNode;
3133
}
3234

@@ -53,6 +55,9 @@ const styles = StyleSheet.create({
5355
backgroundColor: colors.red000,
5456
borderColor: colors.red,
5557
},
58+
closeIcon: {
59+
color: colors.black,
60+
},
5661
baseTextStyle: { fontSize: 14, flex: 1, lineHeight: 17 },
5762
textInfo: { color: colors.blue },
5863
textWarning: { color: colors.black },
@@ -78,7 +83,7 @@ const getAlertStyles: (alertType: AlertType) => [StyleProp<ViewStyle>, StyleProp
7883
}
7984
};
8085

81-
const Alert = ({ type = AlertType.Info, small, renderIcon, style, onPress, children, ...props }: Props) => {
86+
const Alert = ({ type = AlertType.Info, small, renderIcon, style, onPress, onDismiss, children, ...props }: Props) => {
8287
const Wrapper: React.ComponentClass<TouchableOpacityProps | ViewProps> = onPress ? TouchableOpacity : View;
8388

8489
const [wrapperStyle, textStyle] = getAlertStyles(type);
@@ -93,6 +98,13 @@ const Alert = ({ type = AlertType.Info, small, renderIcon, style, onPress, child
9398
{children}
9499
</Text>
95100
)}
101+
{onDismiss && (
102+
<View style={styles.iconWrapper}>
103+
<TouchableOpacity onPress={onDismiss} hitSlop={{ top: 20, left: 20, right: 20, bottom: 20 }}>
104+
<IonicIcon name="ios-close" style={styles.closeIcon} size={30} />
105+
</TouchableOpacity>
106+
</View>
107+
)}
96108
</Wrapper>
97109
);
98110
};

app/components/UI/CollectibleContracts/__snapshots__/index.test.tsx.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@ exports[`CollectibleContracts should render correctly 1`] = `
2626
]
2727
}
2828
favoriteCollectibles={Array []}
29+
nftDetectionDismissed={true}
2930
removeFavoriteCollectible={[Function]}
3031
selectedAddress="0x1"
32+
setNftDetectionDismissed={[Function]}
3133
/>
3234
`;

app/components/UI/CollectibleContracts/index.js

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,13 @@ import {
1414
favoritesCollectiblesSelector,
1515
} from '../../../reducers/collectibles';
1616
import { removeFavoriteCollectible } from '../../../actions/collectibles';
17+
import { setNftDetectionDismissed } from '../../../actions/user';
1718
import Text from '../../Base/Text';
1819
import AppConstants from '../../../core/AppConstants';
1920
import { toLowerCaseEquals } from '../../../util/general';
2021
import { compareTokenIds } from '../../../util/tokens';
22+
import CollectibleDetectionModal from '../CollectibleDetectionModal';
23+
import { isMainNet } from '../../../util/networks';
2124

2225
const styles = StyleSheet.create({
2326
wrapper: {
@@ -29,7 +32,7 @@ const styles = StyleSheet.create({
2932
emptyView: {
3033
justifyContent: 'center',
3134
alignItems: 'center',
32-
marginTop: 40,
35+
marginTop: 10,
3336
},
3437
add: {
3538
flexDirection: 'row',
@@ -56,6 +59,7 @@ const styles = StyleSheet.create({
5659
emptyImageContainer: {
5760
width: 76,
5861
height: 76,
62+
marginTop: 30,
5963
marginBottom: 12,
6064
},
6165
emptyTitleText: {
@@ -81,6 +85,9 @@ const CollectibleContracts = ({
8185
collectibles,
8286
favoriteCollectibles,
8387
removeFavoriteCollectible,
88+
useCollectibleDetection,
89+
setNftDetectionDismissed,
90+
nftDetectionDismissed,
8491
}) => {
8592
const onItemPress = useCallback(
8693
(collectible, contractName) => {
@@ -189,6 +196,10 @@ const CollectibleContracts = ({
189196
const goToLearnMore = () =>
190197
navigation.navigate('Webview', { screen: 'SimpleWebview', params: { url: AppConstants.URLS.NFT } });
191198

199+
const dismissNftInfo = async () => {
200+
setNftDetectionDismissed(true);
201+
};
202+
192203
const renderEmpty = () => (
193204
<View style={styles.emptyView}>
194205
<View style={styles.emptyContainer}>
@@ -209,6 +220,11 @@ const CollectibleContracts = ({
209220

210221
return (
211222
<View style={styles.wrapper} testID={'collectible-contracts'}>
223+
{isMainNet(chainId) && !nftDetectionDismissed && !useCollectibleDetection && (
224+
<View style={styles.emptyView}>
225+
<CollectibleDetectionModal onDismiss={dismissNftInfo} navigation={navigation} />
226+
</View>
227+
)}
212228
{collectibleContracts.length > 0 ? renderList() : renderEmpty()}
213229
{renderFooter()}
214230
</View>
@@ -245,11 +261,25 @@ CollectibleContracts.propTypes = {
245261
* Dispatch remove collectible from favorites action
246262
*/
247263
removeFavoriteCollectible: PropTypes.func,
264+
/**
265+
* Boolean to show if NFT detection is enabled
266+
*/
267+
useCollectibleDetection: PropTypes.bool,
268+
/**
269+
* Setter for NFT detection state
270+
*/
271+
setNftDetectionDismissed: PropTypes.func,
272+
/**
273+
* State to manage display of modal
274+
*/
275+
nftDetectionDismissed: PropTypes.bool,
248276
};
249277

250278
const mapStateToProps = (state) => ({
251279
chainId: state.engine.backgroundState.NetworkController.provider.chainId,
252280
selectedAddress: state.engine.backgroundState.PreferencesController.selectedAddress,
281+
useCollectibleDetection: state.engine.backgroundState.PreferencesController.useCollectibleDetection,
282+
nftDetectionDismissed: state.user.nftDetectionDismissed,
253283
collectibleContracts: collectibleContractsSelector(state),
254284
collectibles: collectiblesSelector(state),
255285
favoriteCollectibles: favoritesCollectiblesSelector(state),
@@ -258,6 +288,7 @@ const mapStateToProps = (state) => ({
258288
const mapDispatchToProps = (dispatch) => ({
259289
removeFavoriteCollectible: (selectedAddress, chainId, collectible) =>
260290
dispatch(removeFavoriteCollectible(selectedAddress, chainId, collectible)),
291+
setNftDetectionDismissed: () => dispatch(setNftDetectionDismissed()),
261292
});
262293

263294
export default connect(mapStateToProps, mapDispatchToProps)(CollectibleContracts);

app/components/UI/CollectibleContracts/index.test.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ const initialState = {
4949
},
5050
},
5151
},
52+
user: {
53+
nftDetectionDismissed: true,
54+
},
5255
};
5356
const store = mockStore(initialState);
5457

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import React from 'react';
2+
import { StyleSheet, View } from 'react-native';
3+
import Alert, { AlertType } from '../../Base/Alert';
4+
import Text from '../../Base/Text';
5+
import { strings } from '../../../../locales/i18n';
6+
7+
const styles = StyleSheet.create({
8+
alertBar: {
9+
width: '95%',
10+
marginBottom: 15,
11+
},
12+
});
13+
14+
interface Props {
15+
/**
16+
* Function for dismissing of modal
17+
*/
18+
onDismiss: () => void;
19+
/**
20+
* Navigation object needed to link to settings
21+
*/
22+
navigation: any;
23+
}
24+
25+
const CollectibleDetectionModal = ({ onDismiss, navigation }: Props) => {
26+
const goToSecuritySettings = () => {
27+
navigation.navigate('SettingsView', {
28+
screen: 'SecuritySettings',
29+
params: {
30+
scrollToBottom: true,
31+
},
32+
});
33+
};
34+
35+
return (
36+
<View style={styles.alertBar}>
37+
<Alert small onDismiss={onDismiss} type={AlertType.Info}>
38+
<Text infoModal bold small>
39+
{strings('wallet.nfts_autodetection_title')}
40+
</Text>
41+
{'\n'}
42+
<Text infoModal small>
43+
{strings('wallet.nfts_autodetection_desc')}
44+
</Text>
45+
{'\n'}
46+
<Text infoModal link bold small onPress={goToSecuritySettings}>
47+
{strings('wallet.nfts_autodetection_cta')}
48+
</Text>
49+
</Alert>
50+
</View>
51+
);
52+
};
53+
54+
export default CollectibleDetectionModal;

app/components/Views/AddAsset/__snapshots__/index.test.tsx.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,6 @@ exports[`AddAsset should render correctly 1`] = `
1111
},
1212
}
1313
}
14+
useCollectibleDetection={true}
1415
/>
1516
`;

app/components/Views/AddAsset/index.js

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React, { PureComponent } from 'react';
2-
import { SafeAreaView, StyleSheet } from 'react-native';
2+
import { SafeAreaView, View, StyleSheet } from 'react-native';
33
import { colors, fontStyles } from '../../../styles/common';
44
import { connect } from 'react-redux';
55
import DefaultTabBar from 'react-native-scrollable-tab-view/DefaultTabBar';
@@ -11,12 +11,18 @@ import { strings } from '../../../../locales/i18n';
1111
import AddCustomCollectible from '../../UI/AddCustomCollectible';
1212
import { getNetworkNavbarOptions } from '../../UI/Navbar';
1313
import { NetworksChainId } from '@metamask/controllers';
14+
import CollectibleDetectionModal from '../../UI/CollectibleDetectionModal';
15+
import { isMainNet } from '../../../util/networks';
1416

1517
const styles = StyleSheet.create({
1618
wrapper: {
1719
flex: 1,
1820
backgroundColor: colors.white,
1921
},
22+
infoWrapper: {
23+
alignItems: 'center',
24+
marginTop: 10,
25+
},
2026
tabUnderlineStyle: {
2127
height: 2,
2228
backgroundColor: colors.blue,
@@ -46,6 +52,7 @@ class AddAsset extends PureComponent {
4652
address: '',
4753
symbol: '',
4854
decimals: '',
55+
dismissNftInfo: false,
4956
};
5057

5158
static propTypes = {
@@ -61,6 +68,10 @@ class AddAsset extends PureComponent {
6168
* Object that represents the current route info like params passed to it
6269
*/
6370
route: PropTypes.object,
71+
/**
72+
* Boolean to show if NFT detection is enabled
73+
*/
74+
useCollectibleDetection: PropTypes.bool,
6475
};
6576

6677
renderTabBar() {
@@ -76,15 +87,28 @@ class AddAsset extends PureComponent {
7687
);
7788
}
7889

90+
dismissNftInfo = async () => {
91+
this.setState({ dismissNftInfo: true });
92+
};
93+
7994
render = () => {
8095
const {
8196
route: {
8297
params: { assetType, collectibleContract },
8398
},
8499
navigation,
100+
chainId,
101+
useCollectibleDetection,
85102
} = this.props;
103+
const { dismissNftInfo } = this.state;
104+
86105
return (
87106
<SafeAreaView style={styles.wrapper} testID={`add-${assetType}-screen`}>
107+
{isMainNet(chainId) && assetType !== 'token' && !dismissNftInfo && !useCollectibleDetection && (
108+
<View style={styles.infoWrapper}>
109+
<CollectibleDetectionModal onDismiss={this.dismissNftInfo} navigation={navigation} />
110+
</View>
111+
)}
88112
{assetType === 'token' ? (
89113
<ScrollableTabView renderTabBar={this.renderTabBar}>
90114
{NetworksChainId.mainnet === this.props.chainId && (
@@ -114,6 +138,7 @@ class AddAsset extends PureComponent {
114138

115139
const mapStateToProps = (state) => ({
116140
chainId: state.engine.backgroundState.NetworkController.provider.chainId,
141+
useCollectibleDetection: state.engine.backgroundState.PreferencesController.useCollectibleDetection,
117142
});
118143

119144
export default connect(mapStateToProps)(AddAsset);

app/components/Views/AddAsset/index.test.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@ const initialState = {
1313
chainId: '1',
1414
},
1515
},
16+
PreferencesController: {
17+
useCollectibleDetection: true,
18+
},
1619
},
1720
},
1821
};

app/components/Views/SendFlow/Confirm/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ class Confirm extends PureComponent {
783783
}
784784
} else {
785785
const [, , amount] = decodeTransferData('transfer', transaction.data);
786-
weiBalance = contractBalances[selectedAsset.address];
786+
weiBalance = hexToBN(contractBalances[selectedAsset.address]);
787787
weiInput = hexToBN(amount);
788788
error =
789789
weiBalance && weiBalance.gte(weiInput)

app/components/Views/Settings/SecuritySettings/__snapshots__/index.test.tsx.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,6 @@ exports[`SecuritySettings should render correctly 1`] = `
3232
setLockTime={[Function]}
3333
setPrivacyMode={[Function]}
3434
setThirdPartyApiMode={[Function]}
35+
type="mainnet"
3536
/>
3637
`;

0 commit comments

Comments
 (0)