Skip to content

Commit 48d6f35

Browse files
committed
chore: break up token list grouping
1 parent ac25f16 commit 48d6f35

4 files changed

Lines changed: 108 additions & 46 deletions

File tree

src/hooks/useTokenListGrouping.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import { useMemo } from 'react';
2+
import type { Token } from 'config/tokens';
3+
import { amount as sdkAmount } from '@wormhole-foundation/sdk';
4+
import type { Balances } from 'utils/wallet';
5+
6+
export function useTokenListGrouping({
7+
sortedTokens,
8+
opts,
9+
}: {
10+
sortedTokens: Token[];
11+
opts: {
12+
isWalletConnected: boolean;
13+
isGroupingEnabled: boolean;
14+
balances: Balances;
15+
};
16+
}): { listItems: Token[]; ownedCount: number } {
17+
const { isWalletConnected, isGroupingEnabled, balances } = opts;
18+
19+
return useMemo(() => {
20+
if (!isGroupingEnabled) {
21+
return { listItems: sortedTokens, ownedCount: 0 };
22+
}
23+
24+
const getHasPositiveBalance = (t: Token) => {
25+
if (!isWalletConnected) return false;
26+
const bal = balances?.[t.key]?.balance;
27+
return bal != null && sdkAmount.units(bal) > 0n;
28+
};
29+
30+
const native = sortedTokens.find((t) => t.isNativeGasToken);
31+
const nativeKey = native?.key;
32+
33+
const ownedTokens = sortedTokens.filter(getHasPositiveBalance);
34+
const ownedKeys = new Set(ownedTokens.map((t) => t.key));
35+
36+
const listItems = [
37+
// 1) Owned
38+
...ownedTokens,
39+
// 2) Native (only if not owned)
40+
...(native && nativeKey && !ownedKeys.has(nativeKey) ? [native] : []),
41+
// 3) The rest
42+
...sortedTokens.filter(
43+
(t) => !ownedKeys.has(t.key) && t.key !== nativeKey,
44+
),
45+
];
46+
47+
return { listItems, ownedCount: ownedTokens.length };
48+
}, [sortedTokens, isGroupingEnabled, isWalletConnected, balances]);
49+
}

src/utils/index.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,13 @@ export const getUSDFormat = (price: number | undefined): string => {
204204
}
205205

206206
if (price > 0 && price < 0.01) {
207-
return '<$0.01';
207+
// return '<$0.01';
208+
return Intl.NumberFormat('en-EN', {
209+
style: 'currency',
210+
currency: 'USD',
211+
maximumFractionDigits: 2,
212+
minimumFractionDigits: 2,
213+
}).format(price);
208214
}
209215

210216
return Intl.NumberFormat('en-EN', {

src/views/v3/Bridge/AssetPicker/TokenList.tsx

Lines changed: 15 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import config from 'config';
1414
import { useTokens } from 'contexts/TokensContext';
1515
import type { Balances } from 'utils/wallet/types';
1616
import { useTokenListWithSearch } from 'hooks/useTokenListWithSearch';
17-
import { amount as sdkAmount } from '@wormhole-foundation/sdk';
17+
import TokenSectionHeader from './TokenSectionHeader';
18+
import { useTokenListGrouping } from 'hooks/useTokenListGrouping';
1819

1920
type Props = {
2021
tokenList: Array<Token>;
@@ -124,36 +125,14 @@ const TokenList = (props: Props) => {
124125
const isGroupingEnabled = props.isSource && !props.searchQuery;
125126
const isWalletConnected = Boolean(props.wallet?.address);
126127

127-
const { listItems, ownedCount } = useMemo(() => {
128-
if (!isGroupingEnabled) {
129-
return { listItems: sortedTokens, ownedCount: 0 };
130-
}
131-
132-
const hasPositiveBalance = (token: Token) => {
133-
if (!isWalletConnected) {
134-
return false;
135-
}
136-
137-
const bal = props.balances?.[token.key]?.balance;
138-
return Boolean(bal && sdkAmount.units(bal) > 0n);
139-
};
140-
141-
const nativeToken = sortedTokens.find((token) => token.isNativeGasToken);
142-
const ownedTokens = sortedTokens.filter(hasPositiveBalance);
143-
const ownedSet = new Set(ownedTokens.map((t) => t.key));
144-
145-
const nativePart =
146-
nativeToken && !ownedSet.has(nativeToken.key) ? [nativeToken] : [];
147-
148-
const rest = sortedTokens.filter(
149-
(tok) =>
150-
!ownedSet.has(tok.key) && (!nativeToken || tok.key !== nativeToken.key),
151-
);
152-
153-
const listItems = [...ownedTokens, ...nativePart, ...rest];
154-
155-
return { listItems, ownedCount: ownedTokens.length };
156-
}, [isGroupingEnabled, isWalletConnected, props.balances, sortedTokens]);
128+
const { listItems, ownedCount } = useTokenListGrouping({
129+
sortedTokens,
130+
opts: {
131+
isWalletConnected,
132+
isGroupingEnabled,
133+
balances: props.balances,
134+
},
135+
});
157136

158137
const searchList = (
159138
<SearchableList<Token>
@@ -190,20 +169,11 @@ const TokenList = (props: Props) => {
190169

191170
return (
192171
<Fragment key={token.key}>
193-
{isGroupingEnabled && index === 0 && ownedCount > 0 && (
194-
<Box sx={{ padding: '4px 16px' }}>
195-
<Typography fontSize={14} color={theme.palette.text.secondary}>
196-
Your tokens
197-
</Typography>
198-
</Box>
199-
)}
200-
{isGroupingEnabled && index === ownedCount && (
201-
<Box sx={{ padding: '4px 16px' }}>
202-
<Typography fontSize={14} color={theme.palette.text.secondary}>
203-
All tokens
204-
</Typography>
205-
</Box>
206-
)}
172+
<TokenSectionHeader
173+
index={index}
174+
ownedCount={ownedCount}
175+
isGroupingEnabled={isGroupingEnabled}
176+
/>
207177
<TokenItem
208178
key={token.key}
209179
token={token}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { Box, useTheme } from '@mui/material';
2+
3+
import { Typography } from '@mui/material';
4+
import React from 'react';
5+
6+
const TokenSectionHeader = ({
7+
index,
8+
ownedCount,
9+
isGroupingEnabled,
10+
}: {
11+
index: number;
12+
ownedCount: number;
13+
isGroupingEnabled: boolean;
14+
}) => {
15+
const theme = useTheme();
16+
17+
return (
18+
<>
19+
{isGroupingEnabled && index === 0 && ownedCount > 0 && (
20+
<Box sx={{ padding: '4px 16px' }}>
21+
<Typography fontSize={14} color={theme.palette.text.secondary}>
22+
Your tokens
23+
</Typography>
24+
</Box>
25+
)}
26+
{isGroupingEnabled && index === ownedCount && (
27+
<Box sx={{ padding: '4px 16px' }}>
28+
<Typography fontSize={14} color={theme.palette.text.secondary}>
29+
All tokens
30+
</Typography>
31+
</Box>
32+
)}
33+
</>
34+
);
35+
};
36+
37+
export default TokenSectionHeader;

0 commit comments

Comments
 (0)