Skip to content

Commit d51b4cd

Browse files
authored
chore(runway): cherry-pick fix: cp-7.47.0 fix display contract address on non evm chains (#15845)
- fix: cp-7.47.0 fix display contract address on non evm chains (#15803) ## **Description** PR to fix display of contract address on non EVM chains in token details page If the user clicks on native asset, we should not display address; else we should display correct address ## **Related issues** Fixes: #15764 ## **Manual testing steps** 1. Click on non evm account with assets 2. Click on native asset 3. You should not see contract address 4. Click on SPL token 5. You should see contract address 6. Copy it and go to solscan https://solscan.io/ 7. You should be able to see the address ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- [screenshots/recordings] --> ### **After** <!-- [screenshots/recordings] --> https://github.com/user-attachments/assets/7f676a43-b560-4935-973a-a58c3ec52e37 <img width="1792" alt="Screenshot 2025-05-28 at 16 14 00" src="https://github.com/user-attachments/assets/ad05e699-f5e2-481d-96b2-5eaec3f46c88" /> ## **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. [eb6957d](eb6957d)
2 parents 9443b5a + bddbd41 commit d51b4cd

3 files changed

Lines changed: 67 additions & 75 deletions

File tree

app/components/UI/AssetOverview/__snapshots__/AssetOverview.test.tsx.snap

Lines changed: 0 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -3438,79 +3438,6 @@ exports[`AssetOverview should render native balances when non evm network is sel
34383438
}
34393439
}
34403440
>
3441-
<View
3442-
style={
3443-
[
3444-
{
3445-
"flexDirection": "row",
3446-
"justifyContent": "space-between",
3447-
"paddingVertical": 4,
3448-
},
3449-
{
3450-
"paddingTop": 0,
3451-
},
3452-
]
3453-
}
3454-
>
3455-
<Text
3456-
accessibilityRole="text"
3457-
style={
3458-
{
3459-
"color": "#686e7d",
3460-
"fontFamily": "CentraNo1-Medium",
3461-
"fontSize": 16,
3462-
"fontWeight": "500",
3463-
"letterSpacing": 0,
3464-
"lineHeight": 24,
3465-
}
3466-
}
3467-
>
3468-
Contract address
3469-
</Text>
3470-
<TouchableOpacity
3471-
onPress={[Function]}
3472-
style={
3473-
{
3474-
"alignItems": "center",
3475-
"backgroundColor": "#4459ff1a",
3476-
"borderRadius": 20,
3477-
"flexDirection": "row",
3478-
"marginLeft": 8,
3479-
"paddingHorizontal": 8,
3480-
}
3481-
}
3482-
>
3483-
<Text
3484-
accessibilityRole="text"
3485-
style={
3486-
{
3487-
"color": "#4459ff",
3488-
"fontFamily": "CentraNo1-Book",
3489-
"fontSize": 14,
3490-
"fontWeight": "400",
3491-
"letterSpacing": 0,
3492-
"lineHeight": 22,
3493-
}
3494-
}
3495-
>
3496-
solana:...4:501
3497-
</Text>
3498-
<SvgMock
3499-
color="#4459ff"
3500-
fill="currentColor"
3501-
height={16}
3502-
name="Copy"
3503-
style={
3504-
{
3505-
"height": 16,
3506-
"marginLeft": 4,
3507-
"width": 16,
3508-
}
3509-
}
3510-
width={16}
3511-
/>
3512-
</TouchableOpacity>
3513-
</View>
35143441
<View
35153442
style={
35163443
{

app/components/UI/AssetOverview/utils/getTokenDetails.test.ts

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ import { zeroAddress } from 'ethereumjs-util';
22
import { getTokenDetails } from './getTokenDetails';
33
import { TokenI } from '../../Tokens/types';
44

5+
// In test file
6+
jest.mock('@metamask/utils', () => ({
7+
...jest.requireActual('@metamask/utils'),
8+
parseCaipAssetType: jest.fn(),
9+
}));
10+
11+
import { parseCaipAssetType } from '@metamask/utils';
12+
513
describe('getTokenDetails', () => {
614
// Base test data
715
const mockAsset: TokenI = {
@@ -23,7 +31,17 @@ describe('getTokenDetails', () => {
2331
};
2432

2533
describe('Network-specific behavior', () => {
26-
it('should format token details for non-EVM networks', () => {
34+
it('should format token details for non-EVM networks for spl token', () => {
35+
(parseCaipAssetType as jest.Mock).mockReturnValue({
36+
assetNamespace: 'token',
37+
assetReference: '0x123',
38+
chainId: 'test:test',
39+
chain: {
40+
namespace: 'slip44',
41+
reference: '0x123',
42+
},
43+
});
44+
2745
const result = getTokenDetails(
2846
mockAsset,
2947
true, // isNonEvmAsset
@@ -37,6 +55,30 @@ describe('getTokenDetails', () => {
3755
tokenList: 'uniswap, 1inch',
3856
});
3957
});
58+
it('should format token details for non-EVM networks for native token', () => {
59+
(parseCaipAssetType as jest.Mock).mockReturnValue({
60+
assetNamespace: 'slip44',
61+
assetReference: '0x123',
62+
chainId: 'test:test',
63+
chain: {
64+
namespace: 'slip44',
65+
reference: '0x123',
66+
},
67+
});
68+
69+
const result = getTokenDetails(
70+
mockAsset,
71+
true, // isNonEvmAsset
72+
undefined,
73+
mockEvmMetadata,
74+
);
75+
76+
expect(result).toEqual({
77+
contractAddress: null,
78+
tokenDecimal: 18,
79+
tokenList: 'uniswap, 1inch',
80+
});
81+
});
4082

4183
it('should format ETH token details for EVM networks', () => {
4284
const ethAsset: TokenI = {
@@ -156,6 +198,15 @@ describe('getTokenDetails', () => {
156198
});
157199

158200
it('should handle zero decimals in asset', () => {
201+
(parseCaipAssetType as jest.Mock).mockReturnValue({
202+
assetNamespace: 'token',
203+
assetReference: '0x123',
204+
chainId: 'test:test',
205+
chain: {
206+
namespace: 'slip44',
207+
reference: '0x123',
208+
},
209+
});
159210
const assetWithoutDecimals: TokenI = {
160211
...mockAsset,
161212
decimals: 0,
@@ -176,6 +227,15 @@ describe('getTokenDetails', () => {
176227
});
177228

178229
it('should handle empty aggregators array in asset', () => {
230+
(parseCaipAssetType as jest.Mock).mockReturnValue({
231+
assetNamespace: 'token',
232+
assetReference: '0x123',
233+
chainId: 'test:test',
234+
chain: {
235+
namespace: 'slip44',
236+
reference: '0x123',
237+
},
238+
});
179239
const assetWithoutAggregators: TokenI = {
180240
...mockAsset,
181241
aggregators: [],

app/components/UI/AssetOverview/utils/getTokenDetails.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { zeroAddress } from 'ethereumjs-util';
22
import { TokenI } from '../../Tokens/types';
33
import { TokenDetails } from '../TokenDetails/TokenDetails';
4+
import { parseCaipAssetType } from '@metamask/utils';
45

56
export const getTokenDetails = (
67
asset: TokenI,
@@ -9,8 +10,12 @@ export const getTokenDetails = (
910
tokenMetadata: Record<string, string | number | string[]>,
1011
): TokenDetails => {
1112
if (isNonEvmAsset) {
13+
const { assetNamespace, assetReference } = parseCaipAssetType(
14+
asset.address as `${string}:${string}/${string}:${string}`,
15+
);
16+
const isNative = assetNamespace === 'slip44';
1217
return {
13-
contractAddress: asset.address || null,
18+
contractAddress: isNative ? null : assetReference || null,
1419
tokenDecimal: asset.decimals || null,
1520
tokenList: asset?.aggregators?.join(', ') || null,
1621
};

0 commit comments

Comments
 (0)