Skip to content

Commit c5cad3f

Browse files
committed
Merge branch 'main' of https://github.com/MetaMask/metamask-mobile into fix/tab-individual-height
2 parents d35661f + 179605b commit c5cad3f

File tree

103 files changed

+2937
-971
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

103 files changed

+2937
-971
lines changed

app/components/UI/CustomNetworkSelector/CustomNetworkSelector.styles.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ const createStyles = () =>
55
// custom network styles
66
container: {
77
flex: 1,
8+
paddingVertical: 12,
89
},
910
scrollContentContainer: {
1011
paddingBottom: 100,

app/components/UI/Predict/components/PredictPosition/PredictPosition.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { useStyles } from '../../../../../component-library/hooks';
88
import { PredictPosition as PredictPositionType } from '../../types';
99
import { formatPercentage, formatPrice } from '../../utils/format';
1010
import styleSheet from './PredictPosition.styles';
11-
import { getPredictPositionSelector } from '../../../../../../e2e/selectors/Predict/Predict.selectors';
11+
import { PredictPositionSelectorsIDs } from '../../../../../../e2e/selectors/Predict/Predict.selectors';
1212

1313
interface PredictPositionProps {
1414
position: PredictPositionType;
@@ -32,7 +32,7 @@ const PredictPosition: React.FC<PredictPositionProps> = ({
3232

3333
return (
3434
<TouchableOpacity
35-
testID={getPredictPositionSelector.currentPositionCard}
35+
testID={PredictPositionSelectorsIDs.CURRENT_POSITION_CARD}
3636
style={styles.positionContainer}
3737
onPress={() => onPress?.(position)}
3838
>

app/components/UI/Predict/components/PredictPositionResolved/PredictPositionResolved.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { useStyles } from '../../../../../component-library/hooks';
1010
import { PredictPosition as PredictPositionType } from '../../types';
1111
import { formatPrice } from '../../utils/format';
1212
import styleSheet from './PredictPositionResolved.styles';
13-
import { getPredictPositionSelector } from '../../../../../../e2e/selectors/Predict/Predict.selectors';
13+
import { PredictPositionSelectorsIDs } from '../../../../../../e2e/selectors/Predict/Predict.selectors';
1414

1515
dayjs.extend(relativeTime);
1616

@@ -46,7 +46,7 @@ const PredictPositionResolved: React.FC<PredictPositionResolvedProps> = ({
4646

4747
return (
4848
<TouchableOpacity
49-
testID={getPredictPositionSelector.resolvedPositionCard(position.id)}
49+
testID={PredictPositionSelectorsIDs.RESOLVED_POSITION_CARD}
5050
style={styles.positionContainer}
5151
onPress={() => onPress?.(position)}
5252
>

app/components/UI/Rewards/components/Tabs/OverviewTab/ActiveBoosts.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,11 @@ const BoostCard: React.FC<BoostCardProps> = ({
113113
if (boost.endDate) {
114114
return (
115115
<Box twClassName="flex-row items-center gap-2">
116-
<Icon name={IconName.Clock} size={IconSize.Sm} />
116+
<Icon
117+
name={IconName.Clock}
118+
size={IconSize.Sm}
119+
twClassName="text-white"
120+
/>
117121
<Text variant={TextVariant.BodySm} twClassName="text-white">
118122
{timeRemaining}
119123
</Text>
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
import type { Asset } from '@metamask/assets-controllers';
2+
import { CHAIN_IDS } from '@metamask/transaction-controller';
3+
import type { CaipChainId, Hex } from '@metamask/utils';
4+
import {
5+
compareFiatBalanceWithPriority,
6+
sortAssetsWithPriority,
7+
} from './sortAssetsWithPriority';
8+
9+
function createMockAsset({
10+
name,
11+
fiatBalance,
12+
isNative = true,
13+
chainId = CHAIN_IDS.MAINNET,
14+
}: {
15+
name: string;
16+
fiatBalance?: number;
17+
isNative?: boolean;
18+
chainId?: Hex | CaipChainId;
19+
}): Asset {
20+
return {
21+
name,
22+
fiat: fiatBalance === undefined ? undefined : { balance: fiatBalance },
23+
isNative,
24+
chainId,
25+
} as unknown as Asset;
26+
}
27+
28+
describe('sortAssetsWithPriority', () => {
29+
function extractAssetNames(assets: Asset[]): string[] {
30+
return assets.map((asset) => asset.name);
31+
}
32+
33+
it('sorts by name when key is "name"', () => {
34+
const assets = [
35+
createMockAsset({ name: 'Asset B', fiatBalance: 400 }),
36+
createMockAsset({ name: 'Asset A', fiatBalance: 600 }),
37+
createMockAsset({ name: 'Asset Z', fiatBalance: 500 }),
38+
];
39+
40+
const sortedAssets = sortAssetsWithPriority(assets, {
41+
key: 'name',
42+
order: 'asc',
43+
sortCallback: 'alphaNumeric',
44+
});
45+
46+
expect(extractAssetNames(sortedAssets)).toStrictEqual([
47+
'Asset A',
48+
'Asset B',
49+
'Asset Z',
50+
]);
51+
});
52+
53+
it('sorts by fiat balance when key is "tokenFiatAmount"', () => {
54+
const assets = [
55+
createMockAsset({ name: 'Asset B', fiatBalance: 400 }),
56+
createMockAsset({ name: 'Asset A', fiatBalance: 600 }),
57+
createMockAsset({ name: 'Asset Z', fiatBalance: 500 }),
58+
];
59+
60+
const sortedAssets = sortAssetsWithPriority(assets, {
61+
key: 'tokenFiatAmount',
62+
order: 'dsc',
63+
sortCallback: 'stringNumeric',
64+
});
65+
66+
expect(extractAssetNames(sortedAssets)).toStrictEqual([
67+
'Asset A',
68+
'Asset Z',
69+
'Asset B',
70+
]);
71+
});
72+
});
73+
74+
describe('compareFiatBalanceWithPriority', () => {
75+
describe('fiat balance comparison', () => {
76+
it('compares second value above first if the second asset has a fiat balance and the first asset does not', () => {
77+
const assetA = createMockAsset({
78+
name: 'Asset A',
79+
fiatBalance: undefined,
80+
});
81+
const assetB = createMockAsset({ name: 'Asset B', fiatBalance: 400 });
82+
83+
const result = compareFiatBalanceWithPriority(assetA, assetB);
84+
85+
expect(result).toBeGreaterThan(0);
86+
});
87+
88+
it('compares second value above the first value if both assets have fiat balances and the second value is greater', () => {
89+
const assetA = createMockAsset({ name: 'Asset A', fiatBalance: 300 });
90+
const assetB = createMockAsset({ name: 'Asset B', fiatBalance: 400 });
91+
92+
const result = compareFiatBalanceWithPriority(assetA, assetB);
93+
94+
expect(result).toBeGreaterThan(0);
95+
});
96+
});
97+
98+
describe('non-native asset comparison', () => {
99+
it('returns -1 if the first asset is native and the second asset is not', () => {
100+
const assetA = createMockAsset({ name: 'Asset A', isNative: true });
101+
const assetB = createMockAsset({ name: 'Asset B', isNative: false });
102+
103+
const result = compareFiatBalanceWithPriority(assetA, assetB);
104+
105+
expect(result).toBeLessThan(0);
106+
});
107+
108+
it('returns 1 if the second asset is native and the first asset is not', () => {
109+
const assetA = createMockAsset({ name: 'Asset A', isNative: false });
110+
const assetB = createMockAsset({ name: 'Asset B', isNative: true });
111+
112+
const result = compareFiatBalanceWithPriority(assetA, assetB);
113+
114+
expect(result).toBeGreaterThan(0);
115+
});
116+
117+
it('compares name values if neither asset is native', () => {
118+
const assetA = createMockAsset({ name: 'Asset A', isNative: false });
119+
const assetB = createMockAsset({ name: 'Asset B', isNative: false });
120+
121+
const result = compareFiatBalanceWithPriority(assetA, assetB);
122+
123+
expect(result).toBeLessThan(0);
124+
});
125+
});
126+
127+
describe('native asset comparison', () => {
128+
it('compares name values if neither asset is in the defaultNativeAssetOrder', () => {
129+
const assetA = createMockAsset({
130+
name: 'Asset A',
131+
chainId: '0xeeeeeeeeeeeee1',
132+
});
133+
const assetB = createMockAsset({
134+
name: 'Asset B',
135+
chainId: '0xeeeeeeeeeeeee2',
136+
});
137+
138+
const result = compareFiatBalanceWithPriority(assetA, assetB);
139+
140+
expect(result).toBeLessThan(0);
141+
});
142+
143+
it('compares second value above first if the second asset is in the defaultNativeAssetOrder and the first asset is not', () => {
144+
const assetA = createMockAsset({
145+
name: 'Asset A',
146+
chainId: '0xeeeeeeeeeeeee1',
147+
});
148+
const assetB = createMockAsset({
149+
name: 'Asset B',
150+
chainId: CHAIN_IDS.BASE,
151+
});
152+
153+
const result = compareFiatBalanceWithPriority(assetA, assetB);
154+
155+
expect(result).toBeGreaterThan(0);
156+
});
157+
158+
it('compares second value above first if both assets are in the defaultNativeAssetOrder and the second value has higher priority', () => {
159+
const assetA = createMockAsset({
160+
name: 'Asset A',
161+
chainId: CHAIN_IDS.ARBITRUM,
162+
});
163+
const assetB = createMockAsset({
164+
name: 'Asset B',
165+
chainId: CHAIN_IDS.LINEA_MAINNET,
166+
});
167+
168+
const result = compareFiatBalanceWithPriority(assetA, assetB);
169+
170+
expect(result).toBeGreaterThan(0);
171+
});
172+
173+
it('compares second value above first if both assets are in the defaultNativeAssetOrder and the second value has higher priority (both values have balances of zero)', () => {
174+
const assetA = createMockAsset({
175+
name: 'Asset A',
176+
chainId: CHAIN_IDS.ARBITRUM,
177+
fiatBalance: 0,
178+
});
179+
const assetB = createMockAsset({
180+
name: 'Asset B',
181+
chainId: CHAIN_IDS.LINEA_MAINNET,
182+
fiatBalance: 0,
183+
});
184+
185+
const result = compareFiatBalanceWithPriority(assetA, assetB);
186+
187+
expect(result).toBeGreaterThan(0);
188+
});
189+
});
190+
});
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import type { Asset } from '@metamask/assets-controllers';
2+
import { CHAIN_IDS } from '@metamask/transaction-controller';
3+
import type { CaipChainId, Hex } from '@metamask/utils';
4+
import { BtcScope, SolScope, TrxScope } from '@metamask/keyring-api';
5+
import { sortAssets, type SortCriteria } from './sortAssets';
6+
7+
// These are the only two options for sorting assets
8+
// {"key": "name", "order": "asc", "sortCallback": "alphaNumeric"}
9+
// {"key": "tokenFiatAmount", "order": "dsc", "sortCallback": "stringNumeric"}
10+
export function sortAssetsWithPriority(
11+
array: Asset[],
12+
criteria: SortCriteria,
13+
): Asset[] {
14+
if (criteria.key === 'name') {
15+
return sortAssets(array, {
16+
key: 'name',
17+
order: 'asc',
18+
sortCallback: 'alphaNumeric',
19+
});
20+
}
21+
22+
return [...array].sort(compareFiatBalanceWithPriority);
23+
}
24+
25+
// Higher priority assets are last in the array to facilitate sorting
26+
const defaultNativeAssetOrder: (Hex | CaipChainId)[] = [
27+
CHAIN_IDS.POLYGON,
28+
CHAIN_IDS.OPTIMISM,
29+
CHAIN_IDS.BSC,
30+
CHAIN_IDS.ARBITRUM,
31+
CHAIN_IDS.BASE,
32+
TrxScope.Mainnet,
33+
BtcScope.Mainnet,
34+
SolScope.Mainnet,
35+
CHAIN_IDS.LINEA_MAINNET,
36+
CHAIN_IDS.MAINNET,
37+
];
38+
39+
/**
40+
* Compares assets by fiat balance with priority sorting.
41+
*
42+
* @param a - The first asset to compare.
43+
* @param b - The second asset to compare.
44+
* @returns A negative number if the first asset should appear before the second, a positive number if the first asset should appear after the second, or 0 if they are equal.
45+
*/
46+
export function compareFiatBalanceWithPriority(a: Asset, b: Asset) {
47+
// If one of the fiat balances is greater than the other, return the comparison
48+
const fiatBalanceComparison = (b.fiat?.balance ?? 0) - (a.fiat?.balance ?? 0);
49+
50+
// Only return comparison if it is not zero
51+
if (fiatBalanceComparison) {
52+
return fiatBalanceComparison;
53+
}
54+
55+
// With equal fiat balances
56+
// Always return native assets before token assets
57+
// Apply the priority defined in defaultNativeAssetOrder if both are native assets
58+
// If both assets are tokens or none is in the defaultNativeAssetOrder, compare by name
59+
if (a.isNative && !b.isNative) {
60+
return -1;
61+
}
62+
63+
if (b.isNative && !a.isNative) {
64+
return 1;
65+
}
66+
67+
if (!a.isNative && !b.isNative) {
68+
return a.name.localeCompare(b.name);
69+
}
70+
71+
const nativeAssetOrderA = defaultNativeAssetOrder.indexOf(a.chainId);
72+
const nativeAssetOrderB = defaultNativeAssetOrder.indexOf(b.chainId);
73+
74+
const nativeAssetOrderComparison = nativeAssetOrderB - nativeAssetOrderA;
75+
76+
if (nativeAssetOrderComparison) {
77+
return nativeAssetOrderComparison;
78+
}
79+
80+
// If neither asset is in the defaultNativeAssetOrder, compare by name
81+
return a.name.localeCompare(b.name);
82+
}

app/components/UI/Transactions/TransactionsFooter.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ const TransactionsFooter = ({
9393
return null;
9494
}
9595

96-
if (isMainnetByChainId(chainId) || providerType !== RPC) {
96+
if (isMainnetByChainId(chainId) || (providerType && providerType !== RPC)) {
9797
return strings('transactions.view_full_history_on_etherscan');
9898
}
9999

app/components/Views/Login/index.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,11 @@ const Login: React.FC<LoginProps> = ({ saveOnboardingEvent }) => {
364364
};
365365

366366
const handleUseOtherMethod = () => {
367+
if (isComingFromOauthOnboarding) {
368+
track(MetaMetricsEvents.USE_DIFFERENT_LOGIN_METHOD_CLICKED, {
369+
account_type: 'social',
370+
});
371+
}
367372
navigation.goBack();
368373
OAuthService.resetOauthState();
369374
};

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,7 @@ exports[`AdvancedSettings should render correctly 1`] = `
781781
}
782782
}
783783
>
784-
Select this to show fiat conversion on test networks
784+
Select this to show fiat conversion on test networks.
785785
</Text>
786786
</View>
787787
<View

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ exports[`ExperimentalSettings should render correctly 1`] = `
3939
}
4040
}
4141
>
42-
View the list of active WalletConnect sessions
42+
View the list of active WalletConnect sessions.
4343
</Text>
4444
<TouchableOpacity
4545
accessibilityRole="button"

0 commit comments

Comments
 (0)