Skip to content

Commit d42d736

Browse files
fix: cp-7.59.0 fix crash when hiding token on token details in android (#22327)
## **Description** PR to fix undefined error when trying to hide a token from Asset details page. ## **Changelog** CHANGELOG entry: Fixed a bug that was causing app crash when trying to hide a token from asset details page. ## **Related issues** Fixes: #22325 ## **Manual testing steps** ```gherkin Feature: my feature name Scenario: user [verb for user action] Given [describe expected initial app state] When user [verb for user action] Then [describe expected outcome] ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> https://github.com/user-attachments/assets/c2eafdbd-2399-4294-b37b-7f04e8e5e00c ### **After** <!-- [screenshots/recordings] --> https://github.com/user-attachments/assets/a6c9e115-9399-47ab-ae2b-3511db97cbff ## **Pre-merge author checklist** - [ ] I’ve followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [ ] I've completed the PR template to the best of my ability - [ ] I’ve included tests if applicable - [ ] I’ve documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [ ] I’ve applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Refactors AssetDetails to a container/presentational pattern that resolves the token via normalized address matching and passes it in, returning null if missing. > > - **Asset Details refactor**: > - Introduce `AssetDetailsContainer` that: > - Selects tokens by `chainId`/account, finds the token using `areAddressesEqual(address)`. > - Returns `null` if the token is not found. > - Passes the resolved `token` to `AssetDetails`. > - Update `AssetDetails` to accept a `token` prop and remove internal token selection logic. > - **Address handling**: Use `areAddressesEqual` for robust token address comparison. > - **Export**: Default export switched to `AssetDetailsContainer`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 4af9f02. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: sahar-fehri <sahar.fehri@consensys.net>
1 parent 1c5f2ec commit d42d736

File tree

1 file changed

+37
-16
lines changed

1 file changed

+37
-16
lines changed

app/components/Views/AssetDetails/index.tsx

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ import { Colors } from '../../../util/theme/models';
5050
import { Hex } from '@metamask/utils';
5151
import { selectLastSelectedEvmAccount } from '../../../selectors/accountsController';
5252
import { TokenI } from '../../UI/Tokens/types';
53+
import { areAddressesEqual } from '../../../util/address';
5354

5455
const createStyles = (colors: Colors) =>
5556
StyleSheet.create({
@@ -110,15 +111,17 @@ interface Props {
110111
};
111112
}
112113

113-
const AssetDetails = (props: Props) => {
114+
type InnerProps = Props & { token: TokenType };
115+
116+
const AssetDetails = (props: InnerProps) => {
114117
const { address, chainId: networkId, asset } = props.route.params;
118+
const { token } = props;
115119
const { colors } = useTheme();
116120
const { trackEvent, createEventBuilder } = useMetrics();
117121
const styles = createStyles(colors);
118122
const navigation = useNavigation();
119123
const dispatch = useDispatch();
120124
const providerConfig = useSelector(selectProviderConfig);
121-
const allTokens = useSelector(selectAllTokens);
122125
const selectedAccountAddressEvm = useSelector(selectLastSelectedEvmAccount);
123126

124127
const selectedAccountAddress = selectedAccountAddressEvm?.address;
@@ -131,11 +134,6 @@ const AssetDetails = (props: Props) => {
131134

132135
const tokenNetworkConfig = networkConfigurations[networkId]?.name;
133136

134-
const tokensByChain = useMemo(
135-
() => allTokens?.[networkId as Hex]?.[selectedAccountAddress as Hex] ?? [],
136-
[allTokens, networkId, selectedAccountAddress],
137-
);
138-
139137
const networkConfigurationByChainId = useSelector((state: RootState) =>
140138
selectNetworkConfigurationByChainId(state, chainId),
141139
);
@@ -155,14 +153,7 @@ const AssetDetails = (props: Props) => {
155153
);
156154
const allTokenBalances = useSelector(selectTokensBalances);
157155

158-
const portfolioToken = useMemo(
159-
() => tokensByChain.find((rawToken) => rawToken.address === address),
160-
[tokensByChain, address],
161-
);
162-
163-
const token: TokenType | undefined = portfolioToken;
164-
165-
const { symbol, decimals, aggregators = [] } = token as TokenType;
156+
const { symbol, decimals, aggregators = [] } = token;
166157

167158
const getNetworkName = useCallback(() => {
168159
let name = '';
@@ -398,4 +389,34 @@ const AssetDetails = (props: Props) => {
398389
);
399390
};
400391

401-
export default AssetDetails;
392+
const AssetDetailsContainer = (props: Props) => {
393+
const { address, chainId: networkId } = props.route.params;
394+
395+
const allTokens = useSelector(selectAllTokens);
396+
const selectedAccountAddressEvm = useSelector(selectLastSelectedEvmAccount);
397+
398+
const selectedAccountAddress = selectedAccountAddressEvm?.address;
399+
400+
const tokensByChain = useMemo(
401+
() => allTokens?.[networkId as Hex]?.[selectedAccountAddress as Hex] ?? [],
402+
[allTokens, networkId, selectedAccountAddress],
403+
);
404+
405+
const portfolioToken = useMemo(
406+
() =>
407+
tokensByChain.find((rawToken) =>
408+
areAddressesEqual(rawToken.address, address),
409+
),
410+
[tokensByChain, address],
411+
);
412+
413+
const token: TokenType | undefined = portfolioToken;
414+
415+
if (!token) {
416+
return null;
417+
}
418+
419+
return <AssetDetails {...props} token={token} />;
420+
};
421+
422+
export default AssetDetailsContainer;

0 commit comments

Comments
 (0)