@lifi/widget 3.29.0 → 3.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/dist/esm/components/AmountInput/AmountInputEndAdornment.d.ts +1 -1
  3. package/dist/esm/components/AmountInput/AmountInputEndAdornment.js +3 -2
  4. package/dist/esm/components/AmountInput/AmountInputEndAdornment.js.map +1 -1
  5. package/dist/esm/components/AmountInput/PriceFormHelperText.d.ts +1 -1
  6. package/dist/esm/components/AmountInput/PriceFormHelperText.js +3 -2
  7. package/dist/esm/components/AmountInput/PriceFormHelperText.js.map +1 -1
  8. package/dist/esm/components/BottomSheet/BottomSheet.js +2 -2
  9. package/dist/esm/components/BottomSheet/BottomSheet.js.map +1 -1
  10. package/dist/esm/components/BottomSheet/types.d.ts +1 -0
  11. package/dist/esm/components/ChainSelect/ChainSelect.js +35 -18
  12. package/dist/esm/components/ChainSelect/ChainSelect.js.map +1 -1
  13. package/dist/esm/components/ChainSelect/useChainSelect.d.ts +1 -1
  14. package/dist/esm/components/ChainSelect/useChainSelect.js +3 -3
  15. package/dist/esm/components/ChainSelect/useChainSelect.js.map +1 -1
  16. package/dist/esm/components/Chains/AllChainsAvatar.d.ts +7 -0
  17. package/dist/esm/components/Chains/AllChainsAvatar.js +77 -0
  18. package/dist/esm/components/Chains/AllChainsAvatar.js.map +1 -0
  19. package/dist/esm/components/Chains/ChainList.d.ts +2 -1
  20. package/dist/esm/components/Chains/ChainList.js +2 -2
  21. package/dist/esm/components/Chains/ChainList.js.map +1 -1
  22. package/dist/esm/components/Chains/ChainSearchInput.js +2 -2
  23. package/dist/esm/components/Chains/ChainSearchInput.js.map +1 -1
  24. package/dist/esm/components/Chains/SelectChainContent.js +1 -1
  25. package/dist/esm/components/Chains/SelectChainContent.js.map +1 -1
  26. package/dist/esm/components/Chains/VirtualizedChainList.d.ts +2 -1
  27. package/dist/esm/components/Chains/VirtualizedChainList.js +42 -10
  28. package/dist/esm/components/Chains/VirtualizedChainList.js.map +1 -1
  29. package/dist/esm/components/RouteCard/RouteCardEssentials.js +1 -1
  30. package/dist/esm/components/RouteCard/RouteCardEssentials.js.map +1 -1
  31. package/dist/esm/components/TokenList/TokenDetailsSheet.d.ts +1 -5
  32. package/dist/esm/components/TokenList/TokenDetailsSheet.js +5 -3
  33. package/dist/esm/components/TokenList/TokenDetailsSheet.js.map +1 -1
  34. package/dist/esm/components/TokenList/TokenDetailsSheetContent.js +2 -2
  35. package/dist/esm/components/TokenList/TokenDetailsSheetContent.js.map +1 -1
  36. package/dist/esm/components/TokenList/TokenList.js +11 -53
  37. package/dist/esm/components/TokenList/TokenList.js.map +1 -1
  38. package/dist/esm/components/TokenList/TokenListItem.d.ts +1 -1
  39. package/dist/esm/components/TokenList/TokenListItem.js +29 -25
  40. package/dist/esm/components/TokenList/TokenListItem.js.map +1 -1
  41. package/dist/esm/components/TokenList/VirtualizedTokenList.js +56 -37
  42. package/dist/esm/components/TokenList/VirtualizedTokenList.js.map +1 -1
  43. package/dist/esm/components/TokenList/types.d.ts +6 -10
  44. package/dist/esm/components/TokenList/useTokenSelect.js +3 -4
  45. package/dist/esm/components/TokenList/useTokenSelect.js.map +1 -1
  46. package/dist/esm/components/TransactionDetails.js +2 -2
  47. package/dist/esm/components/TransactionDetails.js.map +1 -1
  48. package/dist/esm/config/version.d.ts +1 -1
  49. package/dist/esm/config/version.js +1 -1
  50. package/dist/esm/hooks/useAccountsBalancesData.d.ts +6 -0
  51. package/dist/esm/hooks/useAccountsBalancesData.js +64 -0
  52. package/dist/esm/hooks/useAccountsBalancesData.js.map +1 -0
  53. package/dist/esm/hooks/useFilteredByTokenBalances.d.ts +8 -0
  54. package/dist/esm/hooks/useFilteredByTokenBalances.js +69 -0
  55. package/dist/esm/hooks/useFilteredByTokenBalances.js.map +1 -0
  56. package/dist/esm/hooks/useListHeight.d.ts +0 -1
  57. package/dist/esm/hooks/useListHeight.js +0 -1
  58. package/dist/esm/hooks/useListHeight.js.map +1 -1
  59. package/dist/esm/hooks/useToken.d.ts +2 -2
  60. package/dist/esm/hooks/useToken.js +13 -11
  61. package/dist/esm/hooks/useToken.js.map +1 -1
  62. package/dist/esm/hooks/useTokenAddressBalance.d.ts +2 -3
  63. package/dist/esm/hooks/useTokenAddressBalance.js +10 -14
  64. package/dist/esm/hooks/useTokenAddressBalance.js.map +1 -1
  65. package/dist/esm/hooks/useTokenBalances.d.ts +6 -9
  66. package/dist/esm/hooks/useTokenBalances.js +57 -72
  67. package/dist/esm/hooks/useTokenBalances.js.map +1 -1
  68. package/dist/esm/hooks/useTokenBalancesQueries.d.ts +11 -0
  69. package/dist/esm/hooks/useTokenBalancesQueries.js +74 -0
  70. package/dist/esm/hooks/useTokenBalancesQueries.js.map +1 -0
  71. package/dist/esm/hooks/useTokens.d.ts +6 -6
  72. package/dist/esm/hooks/useTokens.js +78 -70
  73. package/dist/esm/hooks/useTokens.js.map +1 -1
  74. package/dist/esm/i18n/bn.json +3 -3
  75. package/dist/esm/i18n/de.json +3 -3
  76. package/dist/esm/i18n/en.json +3 -3
  77. package/dist/esm/i18n/es.json +3 -3
  78. package/dist/esm/i18n/fr.json +3 -3
  79. package/dist/esm/i18n/hi.json +3 -3
  80. package/dist/esm/i18n/id.json +3 -3
  81. package/dist/esm/i18n/it.json +3 -3
  82. package/dist/esm/i18n/ja.json +3 -3
  83. package/dist/esm/i18n/ko.json +3 -3
  84. package/dist/esm/i18n/pl.json +3 -3
  85. package/dist/esm/i18n/pt.json +3 -3
  86. package/dist/esm/i18n/th.json +3 -3
  87. package/dist/esm/i18n/tr.json +3 -3
  88. package/dist/esm/i18n/uk.json +3 -3
  89. package/dist/esm/i18n/vi.json +3 -3
  90. package/dist/esm/i18n/zh.json +3 -3
  91. package/dist/esm/pages/SelectTokenPage/SearchTokenInput.js +6 -1
  92. package/dist/esm/pages/SelectTokenPage/SearchTokenInput.js.map +1 -1
  93. package/dist/esm/pages/SelectTokenPage/SelectTokenPage.js +2 -4
  94. package/dist/esm/pages/SelectTokenPage/SelectTokenPage.js.map +1 -1
  95. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js +1 -1
  96. package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js.map +1 -1
  97. package/dist/esm/stores/chains/createChainOrderStore.d.ts +3 -2
  98. package/dist/esm/stores/chains/createChainOrderStore.js +13 -8
  99. package/dist/esm/stores/chains/createChainOrderStore.js.map +1 -1
  100. package/dist/esm/stores/chains/types.d.ts +2 -0
  101. package/dist/esm/stores/chains/useChainOrder.js +5 -1
  102. package/dist/esm/stores/chains/useChainOrder.js.map +1 -1
  103. package/dist/esm/types/token.d.ts +7 -2
  104. package/dist/esm/utils/chainType.d.ts +1 -0
  105. package/dist/esm/utils/chainType.js +2 -0
  106. package/dist/esm/utils/chainType.js.map +1 -1
  107. package/dist/esm/utils/token.d.ts +8 -0
  108. package/dist/esm/utils/token.js +29 -0
  109. package/dist/esm/utils/token.js.map +1 -0
  110. package/dist/esm/utils/tokenList.d.ts +13 -0
  111. package/dist/esm/utils/tokenList.js +106 -0
  112. package/dist/esm/utils/tokenList.js.map +1 -0
  113. package/package.json +8 -8
  114. package/package.json.tmp +7 -7
  115. package/src/components/AmountInput/AmountInputEndAdornment.tsx +3 -2
  116. package/src/components/AmountInput/PriceFormHelperText.tsx +3 -2
  117. package/src/components/BottomSheet/BottomSheet.tsx +2 -2
  118. package/src/components/BottomSheet/types.ts +1 -0
  119. package/src/components/ChainSelect/ChainSelect.tsx +112 -40
  120. package/src/components/ChainSelect/useChainSelect.ts +3 -3
  121. package/src/components/Chains/AllChainsAvatar.tsx +113 -0
  122. package/src/components/Chains/ChainList.tsx +3 -0
  123. package/src/components/Chains/ChainSearchInput.tsx +2 -2
  124. package/src/components/Chains/SelectChainContent.tsx +1 -0
  125. package/src/components/Chains/VirtualizedChainList.tsx +80 -12
  126. package/src/components/RouteCard/RouteCardEssentials.tsx +1 -1
  127. package/src/components/TokenList/TokenDetailsSheet.tsx +5 -10
  128. package/src/components/TokenList/TokenDetailsSheetContent.tsx +2 -6
  129. package/src/components/TokenList/TokenList.tsx +57 -129
  130. package/src/components/TokenList/TokenListItem.tsx +191 -166
  131. package/src/components/TokenList/VirtualizedTokenList.tsx +88 -48
  132. package/src/components/TokenList/types.ts +14 -10
  133. package/src/components/TokenList/useTokenSelect.ts +3 -4
  134. package/src/components/TransactionDetails.tsx +2 -2
  135. package/src/config/version.ts +1 -1
  136. package/src/hooks/useAccountsBalancesData.ts +101 -0
  137. package/src/hooks/useFilteredByTokenBalances.ts +101 -0
  138. package/src/hooks/useListHeight.ts +0 -1
  139. package/src/hooks/useToken.ts +26 -14
  140. package/src/hooks/useTokenAddressBalance.ts +14 -20
  141. package/src/hooks/useTokenBalances.ts +81 -80
  142. package/src/hooks/useTokenBalancesQueries.ts +94 -0
  143. package/src/hooks/useTokens.ts +118 -90
  144. package/src/i18n/bn.json +3 -3
  145. package/src/i18n/de.json +3 -3
  146. package/src/i18n/en.json +3 -3
  147. package/src/i18n/es.json +3 -3
  148. package/src/i18n/fr.json +3 -3
  149. package/src/i18n/hi.json +3 -3
  150. package/src/i18n/id.json +3 -3
  151. package/src/i18n/it.json +3 -3
  152. package/src/i18n/ja.json +3 -3
  153. package/src/i18n/ko.json +3 -3
  154. package/src/i18n/pl.json +3 -3
  155. package/src/i18n/pt.json +3 -3
  156. package/src/i18n/th.json +3 -3
  157. package/src/i18n/tr.json +3 -3
  158. package/src/i18n/uk.json +3 -3
  159. package/src/i18n/vi.json +3 -3
  160. package/src/i18n/zh.json +3 -3
  161. package/src/pages/SelectTokenPage/SearchTokenInput.tsx +5 -0
  162. package/src/pages/SelectTokenPage/SelectTokenPage.tsx +7 -13
  163. package/src/pages/TransactionPage/TokenValueBottomSheet.tsx +1 -1
  164. package/src/stores/chains/createChainOrderStore.ts +17 -8
  165. package/src/stores/chains/types.ts +2 -0
  166. package/src/stores/chains/useChainOrder.ts +5 -1
  167. package/src/types/token.ts +11 -2
  168. package/src/utils/chainType.ts +2 -0
  169. package/src/utils/token.ts +65 -0
  170. package/src/utils/tokenList.ts +172 -0
  171. package/dist/esm/components/TokenList/utils.d.ts +0 -2
  172. package/dist/esm/components/TokenList/utils.js +0 -35
  173. package/dist/esm/components/TokenList/utils.js.map +0 -1
  174. package/src/components/TokenList/utils.ts +0 -42
@@ -2,8 +2,17 @@ import type { ExtendedChain } from '@lifi/sdk'
2
2
  import { useVirtualizer } from '@tanstack/react-virtual'
3
3
  import type { RefObject } from 'react'
4
4
  import { useCallback, useEffect, useMemo, useRef } from 'react'
5
+ import { useTranslation } from 'react-i18next'
5
6
  import { useChainOrderStore } from '../../stores/chains/ChainOrderStore.js'
6
- import { List } from './ChainList.style.js'
7
+ import { useFieldActions } from '../../stores/form/useFieldActions.js'
8
+ import { AllChainsAvatar } from './AllChainsAvatar.js'
9
+ import {
10
+ List,
11
+ ListItem,
12
+ ListItemAvatar,
13
+ ListItemButton,
14
+ ListItemText,
15
+ } from './ChainList.style.js'
7
16
  import { ChainListItem } from './ChainListItem.js'
8
17
 
9
18
  interface VirtualizedChainListProps {
@@ -12,23 +21,30 @@ interface VirtualizedChainListProps {
12
21
  onSelect: (chain: ExtendedChain) => void
13
22
  selectedChainId?: number
14
23
  itemsSize: 'small' | 'medium'
24
+ hasSearchQuery: boolean
15
25
  withPinnedChains: boolean
16
26
  }
17
27
 
18
28
  export const VirtualizedChainList = ({
19
29
  chains,
30
+ hasSearchQuery,
20
31
  onSelect,
21
32
  selectedChainId,
22
33
  itemsSize,
23
34
  scrollElementRef,
24
35
  withPinnedChains,
25
36
  }: VirtualizedChainListProps) => {
37
+ const { t } = useTranslation()
38
+ const { setFieldValue } = useFieldActions()
26
39
  const selectedChainIdRef = useRef(selectedChainId) // Store the initial selected chain ID to scroll to it once chains are loaded
27
40
  const hasScrolledRef = useRef(false)
28
- const [pinnedChains, setPinnedChain] = useChainOrderStore((state) => [
29
- state.pinnedChains,
30
- state.setPinnedChain,
31
- ])
41
+ const [pinnedChains, setPinnedChain, isAllNetworks, setIsAllNetworks] =
42
+ useChainOrderStore((state) => [
43
+ state.pinnedChains,
44
+ state.setPinnedChain,
45
+ state.isAllNetworks,
46
+ state.setIsAllNetworks,
47
+ ])
32
48
  const onPin = useCallback(
33
49
  (chainId: number) => {
34
50
  setPinnedChain(chainId)
@@ -49,16 +65,30 @@ export const VirtualizedChainList = ({
49
65
  return [...pinned, ...rest]
50
66
  }, [chains, pinnedChains])
51
67
 
68
+ const showAllNetworks = sortedChains.length > 1 && !hasSearchQuery
69
+
52
70
  const getItemKey = useCallback(
53
71
  (index: number) => {
54
- return `${sortedChains[index].id}-${index}`
72
+ if (showAllNetworks && index === 0) {
73
+ return 'all-chains'
74
+ }
75
+ const chainIndex = index - (showAllNetworks ? 1 : 0)
76
+ return `${sortedChains[chainIndex].id}-${index}`
77
+ },
78
+ [sortedChains, showAllNetworks]
79
+ )
80
+
81
+ const onChainSelect = useCallback(
82
+ (chain: ExtendedChain) => {
83
+ setIsAllNetworks(false)
84
+ onSelect(chain)
55
85
  },
56
- [sortedChains]
86
+ [onSelect, setIsAllNetworks]
57
87
  )
58
88
 
59
89
  const { getVirtualItems, getTotalSize, measure, range, getOffsetForIndex } =
60
90
  useVirtualizer({
61
- count: sortedChains.length,
91
+ count: sortedChains.length + (showAllNetworks ? 1 : 0), // +1 for the all networks item
62
92
  overscan: 3,
63
93
  paddingEnd: 0,
64
94
  getScrollElement: () => scrollElementRef.current,
@@ -96,6 +126,12 @@ export const VirtualizedChainList = ({
96
126
  )
97
127
 
98
128
  useEffect(() => {
129
+ // Mark as scrolled if "All Networks" is initially selected
130
+ if (isAllNetworks) {
131
+ hasScrolledRef.current = true
132
+ return
133
+ }
134
+
99
135
  // Only scroll if sortedChains is not empty and we haven't scrolled yet
100
136
  if (!hasScrolledRef.current && sortedChains.length > 0 && range) {
101
137
  const selectedChainIndex = sortedChains.findIndex(
@@ -113,7 +149,12 @@ export const VirtualizedChainList = ({
113
149
  }
114
150
  hasScrolledRef.current = true // Mark as scrolled (when needed)
115
151
  }
116
- }, [sortedChains, scrollToIndex, range])
152
+ }, [sortedChains, scrollToIndex, range, isAllNetworks])
153
+
154
+ const selectAllNetworks = useCallback(() => {
155
+ setIsAllNetworks(true)
156
+ setFieldValue('tokenSearchFilter', '')
157
+ }, [setIsAllNetworks, setFieldValue])
117
158
 
118
159
  return (
119
160
  <List
@@ -122,13 +163,40 @@ export const VirtualizedChainList = ({
122
163
  disablePadding
123
164
  >
124
165
  {getVirtualItems().map((item) => {
125
- const chain = sortedChains[item.index]
166
+ if (showAllNetworks && item.index === 0) {
167
+ return (
168
+ <ListItem
169
+ key={item.key}
170
+ style={{
171
+ height: `${itemsSize}px`,
172
+ transform: `translateY(${item.start}px)`,
173
+ padding: 0,
174
+ }}
175
+ >
176
+ <ListItemButton
177
+ onClick={selectAllNetworks}
178
+ selected={isAllNetworks}
179
+ size={itemsSize}
180
+ >
181
+ <ListItemAvatar size={itemsSize}>
182
+ <AllChainsAvatar chains={chains} size={itemsSize} />
183
+ </ListItemAvatar>
184
+ <ListItemText
185
+ primary={t('main.allNetworks')}
186
+ size={itemsSize}
187
+ />
188
+ </ListItemButton>
189
+ </ListItem>
190
+ )
191
+ }
192
+
193
+ const chain = sortedChains[item.index - (showAllNetworks ? 1 : 0)]
126
194
  return (
127
195
  <ChainListItem
128
196
  key={item.key}
129
197
  chain={chain}
130
- onSelect={onSelect}
131
- selected={chain.id === selectedChainId}
198
+ onSelect={onChainSelect}
199
+ selected={!isAllNetworks && chain.id === selectedChainId}
132
200
  itemsSize={itemsSize}
133
201
  size={item.size}
134
202
  start={item.start}
@@ -64,7 +64,7 @@ export const RouteCardEssentials: React.FC<RouteCardEssentialsProps> = ({
64
64
  lineHeight: 1,
65
65
  }}
66
66
  >
67
- {hasRelayerSupport
67
+ {hasRelayerSupport || !combinedFeesUSD
68
68
  ? t('main.fees.free')
69
69
  : t('format.currency', {
70
70
  value: combinedFeesUSD,
@@ -4,27 +4,22 @@ import type { BottomSheetBase } from '../BottomSheet/types.js'
4
4
  import { TokenDetailsSheetContent } from './TokenDetailsSheetContent.js'
5
5
  import type { TokenDetailsSheetBase } from './types.js'
6
6
 
7
- interface TokenDetailsSheetProps {
8
- chainId: number | undefined
9
- }
10
-
11
- export const TokenDetailsSheet = forwardRef<
12
- TokenDetailsSheetBase,
13
- TokenDetailsSheetProps
14
- >(({ chainId }, ref) => {
7
+ export const TokenDetailsSheet = forwardRef<TokenDetailsSheetBase>((_, ref) => {
15
8
  const bottomSheetRef = useRef<BottomSheetBase>(null)
16
9
  const [tokenAddress, setTokenAddress] = useState<string | undefined>(
17
10
  undefined
18
11
  )
12
+ const [chainId, setChainId] = useState<number | undefined>(undefined)
19
13
  const [withoutContractAddress, setWithoutContractAddress] = useState(false)
20
14
 
21
15
  useImperativeHandle(
22
16
  ref,
23
17
  () => ({
24
18
  isOpen: () => bottomSheetRef.current?.isOpen(),
25
- open: (address: string, noContractAddress: boolean) => {
19
+ open: (address: string, noContractAddress: boolean, chainId: number) => {
26
20
  setTokenAddress(address)
27
21
  setWithoutContractAddress(noContractAddress)
22
+ setChainId(chainId)
28
23
  bottomSheetRef.current?.open()
29
24
  },
30
25
  close: () => {
@@ -35,7 +30,7 @@ export const TokenDetailsSheet = forwardRef<
35
30
  )
36
31
 
37
32
  return (
38
- <BottomSheet ref={bottomSheetRef}>
33
+ <BottomSheet ref={bottomSheetRef} keepMounted>
39
34
  <TokenDetailsSheetContent
40
35
  ref={ref}
41
36
  tokenAddress={tokenAddress}
@@ -6,7 +6,7 @@ import { forwardRef, type PropsWithChildren, useMemo } from 'react'
6
6
  import { useTranslation } from 'react-i18next'
7
7
  import { useAvailableChains } from '../../hooks/useAvailableChains.js'
8
8
  import { useExplorer } from '../../hooks/useExplorer.js'
9
- import { useTokenSearch } from '../../hooks/useTokenSearch.js'
9
+ import { useToken } from '../../hooks/useToken.js'
10
10
  import { shortenAddress } from '../../utils/wallet.js'
11
11
  import { TokenAvatar } from '../Avatar/TokenAvatar.js'
12
12
  import { CardIconButton } from '../Card/CardIconButton.js'
@@ -34,11 +34,7 @@ export const TokenDetailsSheetContent = forwardRef<
34
34
  const { getAddressLink } = useExplorer()
35
35
  const { getChainById } = useAvailableChains()
36
36
 
37
- const { token, isLoading } = useTokenSearch(
38
- chainId,
39
- tokenAddress,
40
- !!tokenAddress
41
- )
37
+ const { token, isLoading } = useToken(chainId, tokenAddress, true)
42
38
  const chain = useMemo(() => getChainById(chainId), [chainId, getChainById])
43
39
 
44
40
  const copyContractAddress = async (e: React.MouseEvent) => {
@@ -1,151 +1,79 @@
1
- import type { BaseToken } from '@lifi/sdk'
2
- import { useAccount } from '@lifi/wallet-management'
3
1
  import { Box } from '@mui/material'
4
- import { type FC, useEffect } from 'react'
5
- import { useChain } from '../../hooks/useChain.js'
2
+ import { type FC, memo, useEffect } from 'react'
6
3
  import { useDebouncedWatch } from '../../hooks/useDebouncedWatch.js'
7
4
  import { useTokenBalances } from '../../hooks/useTokenBalances.js'
8
- import { useTokenSearch } from '../../hooks/useTokenSearch.js'
9
5
  import { useWidgetEvents } from '../../hooks/useWidgetEvents.js'
10
- import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'
6
+ import { useChainOrderStore } from '../../stores/chains/ChainOrderStore.js'
11
7
  import { FormKeyHelper } from '../../stores/form/types.js'
12
8
  import { useFieldValues } from '../../stores/form/useFieldValues.js'
13
9
  import { WidgetEvent } from '../../types/events.js'
14
- import type { TokenAmount } from '../../types/token.js'
15
- import { getConfigItemSets, isFormItemAllowed } from '../../utils/item.js'
16
10
  import { TokenNotFound } from './TokenNotFound.js'
17
11
  import type { TokenListProps } from './types.js'
18
12
  import { useTokenSelect } from './useTokenSelect.js'
19
- import { filteredTokensComparator } from './utils.js'
20
13
  import { VirtualizedTokenList } from './VirtualizedTokenList.js'
21
14
 
22
- export const TokenList: FC<TokenListProps> = ({
23
- formType,
24
- parentRef,
25
- height,
26
- onClick,
27
- }) => {
28
- const emitter = useWidgetEvents()
29
- const [selectedChainId, selectedTokenAddress] = useFieldValues(
30
- FormKeyHelper.getChainKey(formType),
31
- FormKeyHelper.getTokenKey(formType)
32
- )
33
- const [tokenSearchFilter]: string[] = useDebouncedWatch(
34
- 320,
35
- 'tokenSearchFilter'
36
- )
15
+ export const TokenList: FC<TokenListProps> = memo(
16
+ ({ formType, parentRef, height, onClick }) => {
17
+ const emitter = useWidgetEvents()
37
18
 
38
- const { tokens: configTokens } = useWidgetConfig()
39
-
40
- const { chain: selectedChain, isLoading: isSelectedChainLoading } =
41
- useChain(selectedChainId)
42
- const { account } = useAccount({
43
- chainType: selectedChain?.chainType,
44
- })
45
-
46
- const {
47
- tokens: chainTokens,
48
- tokensWithBalance,
49
- isLoading: isTokensLoading,
50
- isBalanceLoading,
51
- featuredTokens,
52
- popularTokens,
53
- } = useTokenBalances(selectedChainId)
54
-
55
- let filteredTokens = (tokensWithBalance ?? chainTokens ?? []) as TokenAmount[]
56
- const normalizedSearchFilter = tokenSearchFilter?.replaceAll('$', '')
57
- const searchFilter = normalizedSearchFilter?.toUpperCase() ?? ''
58
-
59
- const filteredConfigTokens = getConfigItemSets(
60
- configTokens,
61
- (tokens: BaseToken[]) =>
62
- new Set(
63
- tokens
64
- .filter((t) => t.chainId === selectedChainId)
65
- .map((t) => t.address)
66
- ),
67
- formType
68
- )
69
-
70
- // Get the appropriate allow/deny lists based on formType
71
- filteredTokens = filteredTokens.filter(
72
- (token) =>
73
- token.chainId === selectedChainId &&
74
- isFormItemAllowed(token, filteredConfigTokens, formType, (t) => t.address)
75
- )
19
+ const [selectedChainId, selectedTokenAddress] = useFieldValues(
20
+ FormKeyHelper.getChainKey(formType),
21
+ FormKeyHelper.getTokenKey(formType)
22
+ )
76
23
 
77
- filteredTokens = tokenSearchFilter
78
- ? filteredTokens
79
- .filter(
80
- (token) =>
81
- token.name?.toUpperCase().includes(searchFilter) ||
82
- token.symbol
83
- .toUpperCase()
84
- // Replace ₮ with T for USD₮0
85
- .replaceAll('₮', 'T')
86
- .includes(searchFilter) ||
87
- token.address.toUpperCase().includes(searchFilter)
88
- )
89
- .sort(filteredTokensComparator(searchFilter))
90
- : filteredTokens
24
+ const isAllNetworks = useChainOrderStore((state) => state.isAllNetworks)
91
25
 
92
- const tokenSearchEnabled =
93
- !isTokensLoading &&
94
- !filteredTokens.length &&
95
- !!tokenSearchFilter &&
96
- !!selectedChainId
26
+ const [tokenSearchFilter]: string[] = useDebouncedWatch(
27
+ 320,
28
+ 'tokenSearchFilter'
29
+ )
97
30
 
98
- const { token: searchedToken, isLoading: isSearchedTokenLoading } =
99
- useTokenSearch(
31
+ const {
32
+ tokens,
33
+ withCategories,
34
+ isTokensLoading,
35
+ isBalanceLoading,
36
+ isSearchLoading,
37
+ } = useTokenBalances(
100
38
  selectedChainId,
101
- normalizedSearchFilter,
102
- tokenSearchEnabled,
103
- formType
39
+ formType,
40
+ isAllNetworks,
41
+ tokenSearchFilter
104
42
  )
105
43
 
106
- const isLoading =
107
- isTokensLoading ||
108
- isSelectedChainLoading ||
109
- (tokenSearchEnabled && isSearchedTokenLoading)
44
+ const handleTokenClick = useTokenSelect(formType, onClick)
110
45
 
111
- const tokens = filteredTokens.length
112
- ? filteredTokens
113
- : searchedToken
114
- ? [searchedToken]
115
- : filteredTokens
46
+ const showCategories =
47
+ withCategories && !tokenSearchFilter && !isAllNetworks
116
48
 
117
- const handleTokenClick = useTokenSelect(formType, onClick)
118
- const showCategories =
119
- Boolean(featuredTokens?.length || popularTokens?.length) &&
120
- !tokenSearchFilter
49
+ useEffect(() => {
50
+ const normalizedSearchFilter = tokenSearchFilter?.replaceAll('$', '')
51
+ if (normalizedSearchFilter) {
52
+ emitter.emit(WidgetEvent.TokenSearch, {
53
+ value: normalizedSearchFilter,
54
+ tokens,
55
+ })
56
+ }
57
+ // eslint-disable-next-line react-hooks/exhaustive-deps
58
+ }, [tokenSearchFilter, tokens, emitter])
121
59
 
122
- // biome-ignore lint/correctness/useExhaustiveDependencies: Should fire only when search filter changes
123
- useEffect(() => {
124
- if (normalizedSearchFilter) {
125
- emitter.emit(WidgetEvent.TokenSearch, {
126
- value: normalizedSearchFilter,
127
- tokens,
128
- })
129
- }
130
- }, [normalizedSearchFilter, emitter])
131
-
132
- return (
133
- <Box ref={parentRef} style={{ height, overflow: 'auto' }}>
134
- {!tokens.length && !isLoading ? (
135
- <TokenNotFound formType={formType} />
136
- ) : null}
137
- <VirtualizedTokenList
138
- account={account}
139
- tokens={tokens}
140
- scrollElementRef={parentRef}
141
- chainId={selectedChainId}
142
- chain={selectedChain}
143
- isLoading={isLoading}
144
- isBalanceLoading={isBalanceLoading}
145
- showCategories={showCategories}
146
- onClick={handleTokenClick}
147
- selectedTokenAddress={selectedTokenAddress}
148
- />
149
- </Box>
150
- )
151
- }
60
+ return (
61
+ <Box ref={parentRef} style={{ height, overflow: 'auto' }}>
62
+ {!tokens.length && !isTokensLoading && !isSearchLoading ? (
63
+ <TokenNotFound formType={formType} />
64
+ ) : null}
65
+ <VirtualizedTokenList
66
+ tokens={tokens}
67
+ scrollElementRef={parentRef}
68
+ chainId={selectedChainId}
69
+ isLoading={isTokensLoading || isSearchLoading}
70
+ isBalanceLoading={isBalanceLoading}
71
+ showCategories={showCategories}
72
+ onClick={handleTokenClick}
73
+ selectedTokenAddress={selectedTokenAddress}
74
+ isAllNetworks={isAllNetworks}
75
+ />
76
+ </Box>
77
+ )
78
+ }
79
+ )