@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
@@ -0,0 +1,106 @@
1
+ import { formatUnits } from 'viem';
2
+ const sortByBalances = (a, b) => Number.parseFloat(formatUnits(b.amount ?? 0n, b.decimals)) *
3
+ Number.parseFloat(b.priceUSD ?? '0') -
4
+ Number.parseFloat(formatUnits(a.amount ?? 0n, a.decimals)) *
5
+ Number.parseFloat(a.priceUSD ?? '0');
6
+ const sortByVolume = (a, b) => (b.volumeUSD24H ?? 0) - (a.volumeUSD24H ?? 0);
7
+ export const processTokenBalances = (isBalanceLoading, isAllNetworks, configTokens, selectedChainId, tokens, tokensWithBalances) => {
8
+ if (isBalanceLoading) {
9
+ if (isAllNetworks) {
10
+ const sortedTokens = [...(tokens ?? [])].sort(sortByVolume);
11
+ return {
12
+ processedTokens: sortedTokens,
13
+ withCategories: false,
14
+ };
15
+ }
16
+ else {
17
+ return processedTypedTokens(tokens ?? [], [], selectedChainId, configTokens);
18
+ }
19
+ }
20
+ const sortedTokensWithBalances = [...(tokensWithBalances ?? [])].sort(sortByBalances);
21
+ const tokensWithBalancesSet = new Set(sortedTokensWithBalances.map((token) => `${token.chainId}-${token.address.toLowerCase()}`));
22
+ const tokensWithoutBalances = tokens
23
+ ?.filter((token) => {
24
+ const tokenKey = `${token.chainId}-${token.address.toLowerCase()}`;
25
+ return !tokensWithBalancesSet.has(tokenKey);
26
+ })
27
+ .sort(sortByVolume) ?? [];
28
+ if (isAllNetworks) {
29
+ return {
30
+ processedTokens: [...sortedTokensWithBalances, ...tokensWithoutBalances],
31
+ withCategories: false,
32
+ };
33
+ }
34
+ else {
35
+ return processedTypedTokens(tokensWithoutBalances, sortedTokensWithBalances, selectedChainId, configTokens);
36
+ }
37
+ };
38
+ // NB: only for non-all-networks
39
+ export const processedTypedTokens = (tokens, tokensWithBalances, selectedChainId, configTokens) => {
40
+ const filteredTokensMap = new Map(tokens.map((token) => [token.address, token]));
41
+ const featuredTokensFromConfig = [];
42
+ const popularTokensFromConfig = [];
43
+ ['popular', 'featured'].forEach((tokenType) => {
44
+ const typedTokens = configTokens?.[tokenType]?.filter((token) => token.chainId === selectedChainId);
45
+ typedTokens?.forEach((token) => {
46
+ const tokenAmount = { ...token };
47
+ tokenAmount[tokenType] = true;
48
+ const match = filteredTokensMap.get(token.address);
49
+ if (match?.priceUSD) {
50
+ tokenAmount.priceUSD = match.priceUSD;
51
+ }
52
+ if (!token.logoURI && match?.logoURI) {
53
+ tokenAmount.logoURI = match.logoURI;
54
+ }
55
+ if (tokenType === 'popular') {
56
+ popularTokensFromConfig.push(tokenAmount);
57
+ }
58
+ else {
59
+ featuredTokensFromConfig.push(tokenAmount);
60
+ }
61
+ });
62
+ });
63
+ // Filter out config-added tokens from main list
64
+ const configTokenAddresses = new Set([...popularTokensFromConfig, ...featuredTokensFromConfig].map((t) => t.address));
65
+ const remainingTokens = tokens.filter((token) => !configTokenAddresses.has(token.address));
66
+ const otherTokens = [];
67
+ for (const token of remainingTokens) {
68
+ if (token.featured) {
69
+ featuredTokensFromConfig.push(token);
70
+ }
71
+ else if (token.popular) {
72
+ popularTokensFromConfig.push(token);
73
+ }
74
+ else {
75
+ otherTokens.push(token);
76
+ }
77
+ }
78
+ const sortedFeaturedTokens = [...featuredTokensFromConfig].sort(sortByVolume);
79
+ const sortedPopularTokens = [...popularTokensFromConfig].sort(sortByVolume);
80
+ const sortedOtherTokens = [...otherTokens].sort(sortByVolume);
81
+ return {
82
+ processedTokens: [
83
+ ...sortedFeaturedTokens,
84
+ ...tokensWithBalances,
85
+ ...sortedPopularTokens,
86
+ ...sortedOtherTokens,
87
+ ],
88
+ withCategories: Boolean(featuredTokensFromConfig?.length || popularTokensFromConfig?.length),
89
+ };
90
+ };
91
+ export const isSearchMatch = (token, search) => {
92
+ if (!search) {
93
+ return true;
94
+ }
95
+ const searchLowerCase = search.toLowerCase();
96
+ return (token.name?.toLowerCase().includes(searchLowerCase) ||
97
+ token.symbol
98
+ ?.replaceAll('₮', 'T')
99
+ .toLowerCase()
100
+ .includes(searchLowerCase) ||
101
+ token.address?.toLowerCase().includes(searchLowerCase));
102
+ };
103
+ export const isSupportedToken = (token) => {
104
+ return token.name && token.symbol && token.priceUSD && token.chainId;
105
+ };
106
+ //# sourceMappingURL=tokenList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokenList.js","sourceRoot":"","sources":["../../../src/utils/tokenList.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifi/widget",
3
- "version": "3.29.0",
3
+ "version": "3.30.0",
4
4
  "description": "LI.FI Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.",
5
5
  "type": "module",
6
6
  "main": "./dist/esm/index.js",
@@ -34,10 +34,10 @@
34
34
  "@bigmi/core": "^0.5.2",
35
35
  "@emotion/react": "^11.14.0",
36
36
  "@emotion/styled": "^11.14.1",
37
- "@lifi/sdk": "^3.11.3",
38
- "@mui/icons-material": "^7.3.1",
39
- "@mui/material": "^7.3.1",
40
- "@mui/system": "^7.3.1",
37
+ "@lifi/sdk": "^3.12.0",
38
+ "@mui/icons-material": "^7.3.2",
39
+ "@mui/material": "^7.3.2",
40
+ "@mui/system": "^7.3.2",
41
41
  "@mysten/sui": "^1.37.4",
42
42
  "@solana/wallet-adapter-base": "^0.9.27",
43
43
  "@solana/wallet-adapter-coinbase": "^0.1.23",
@@ -46,13 +46,13 @@
46
46
  "i18next": "^25.4.2",
47
47
  "microdiff": "^1.5.0",
48
48
  "mitt": "^3.0.1",
49
- "react-i18next": "^15.7.2",
49
+ "react-i18next": "^15.7.3",
50
50
  "react-intersection-observer": "^9.16.0",
51
51
  "react-router-dom": "^6.30.0",
52
52
  "react-transition-group": "^4.4.5",
53
- "viem": "^2.36.0",
53
+ "viem": "^2.37.1",
54
54
  "zustand": "^5.0.8",
55
- "@lifi/wallet-management": "^3.15.0"
55
+ "@lifi/wallet-management": "^3.16.0"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "@bigmi/react": ">=0.5.0",
package/package.json.tmp CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lifi/widget",
3
- "version": "3.29.0",
3
+ "version": "3.30.0",
4
4
  "description": "LI.FI Widget for cross-chain bridging and swapping. It will drive your multi-chain strategy and attract new users from everywhere.",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -53,11 +53,11 @@
53
53
  "@bigmi/core": "^0.5.2",
54
54
  "@emotion/react": "^11.14.0",
55
55
  "@emotion/styled": "^11.14.1",
56
- "@lifi/sdk": "^3.11.3",
56
+ "@lifi/sdk": "^3.12.0",
57
57
  "@lifi/wallet-management": "workspace:^",
58
- "@mui/icons-material": "^7.3.1",
59
- "@mui/material": "^7.3.1",
60
- "@mui/system": "^7.3.1",
58
+ "@mui/icons-material": "^7.3.2",
59
+ "@mui/material": "^7.3.2",
60
+ "@mui/system": "^7.3.2",
61
61
  "@mysten/sui": "^1.37.4",
62
62
  "@solana/wallet-adapter-base": "^0.9.27",
63
63
  "@solana/wallet-adapter-coinbase": "^0.1.23",
@@ -66,11 +66,11 @@
66
66
  "i18next": "^25.4.2",
67
67
  "microdiff": "^1.5.0",
68
68
  "mitt": "^3.0.1",
69
- "react-i18next": "^15.7.2",
69
+ "react-i18next": "^15.7.3",
70
70
  "react-intersection-observer": "^9.16.0",
71
71
  "react-router-dom": "^6.30.0",
72
72
  "react-transition-group": "^4.4.5",
73
- "viem": "^2.36.0",
73
+ "viem": "^2.37.1",
74
74
  "zustand": "^5.0.8"
75
75
  },
76
76
  "devDependencies": {
@@ -1,4 +1,5 @@
1
1
  import { InputAdornment } from '@mui/material'
2
+ import { memo } from 'react'
2
3
  import { useTranslation } from 'react-i18next'
3
4
  import { formatUnits } from 'viem'
4
5
  import { useAvailableChains } from '../../hooks/useAvailableChains.js'
@@ -10,7 +11,7 @@ import { useFieldActions } from '../../stores/form/useFieldActions.js'
10
11
  import { useFieldValues } from '../../stores/form/useFieldValues.js'
11
12
  import { ButtonContainer, MaxButton } from './AmountInputAdornment.style.js'
12
13
 
13
- export const AmountInputEndAdornment = ({ formType }: FormTypeProps) => {
14
+ export const AmountInputEndAdornment = memo(({ formType }: FormTypeProps) => {
14
15
  const { t } = useTranslation()
15
16
  const { getChainById } = useAvailableChains()
16
17
  const { setFieldValue } = useFieldActions()
@@ -88,4 +89,4 @@ export const AmountInputEndAdornment = ({ formType }: FormTypeProps) => {
88
89
  ) : null}
89
90
  </InputAdornment>
90
91
  )
91
- }
92
+ })
@@ -1,6 +1,7 @@
1
1
  import type { TokenAmount } from '@lifi/sdk'
2
2
  import SwapVertIcon from '@mui/icons-material/SwapVert'
3
3
  import { FormHelperText, Skeleton, Typography } from '@mui/material'
4
+ import { memo } from 'react'
4
5
  import { useTranslation } from 'react-i18next'
5
6
  import { useTokenAddressBalance } from '../../hooks/useTokenAddressBalance.js'
6
7
  import type { FormTypeProps } from '../../stores/form/types.js'
@@ -10,7 +11,7 @@ import { useInputModeStore } from '../../stores/inputMode/useInputModeStore.js'
10
11
  import { formatTokenAmount, formatTokenPrice } from '../../utils/format.js'
11
12
  import { InputPriceButton } from './PriceFormHelperText.style.js'
12
13
 
13
- export const PriceFormHelperText: React.FC<FormTypeProps> = ({ formType }) => {
14
+ export const PriceFormHelperText = memo<FormTypeProps>(({ formType }) => {
14
15
  const [chainId, tokenAddress] = useFieldValues(
15
16
  FormKeyHelper.getChainKey(formType),
16
17
  FormKeyHelper.getTokenKey(formType)
@@ -25,7 +26,7 @@ export const PriceFormHelperText: React.FC<FormTypeProps> = ({ formType }) => {
25
26
  token={token}
26
27
  />
27
28
  )
28
- }
29
+ })
29
30
 
30
31
  export const PriceFormHelperTextBase: React.FC<
31
32
  FormTypeProps & {
@@ -12,7 +12,7 @@ import { modalProps, slotProps } from '../Dialog.js'
12
12
  import type { BottomSheetBase, BottomSheetProps } from './types.js'
13
13
 
14
14
  export const BottomSheet = forwardRef<BottomSheetBase, BottomSheetProps>(
15
- ({ elementRef, children, open, onClose }, ref) => {
15
+ ({ elementRef, children, open, onClose, keepMounted = false }, ref) => {
16
16
  const getContainer = useGetScrollableContainer()
17
17
  const openRef = useRef(open)
18
18
  const [drawerOpen, setDrawerOpen] = useState(open)
@@ -54,7 +54,7 @@ export const BottomSheet = forwardRef<BottomSheetBase, BottomSheetProps>(
54
54
  ModalProps={modalProps}
55
55
  slotProps={slotProps}
56
56
  disableAutoFocus
57
- keepMounted={true}
57
+ keepMounted={keepMounted}
58
58
  inert={isInert}
59
59
  >
60
60
  {children}
@@ -4,6 +4,7 @@ import type { RefObject } from 'react'
4
4
  export type BottomSheetProps = Omit<DrawerProps, 'onClose'> & {
5
5
  elementRef?: RefObject<HTMLDivElement>
6
6
  onClose?(): void
7
+ keepMounted?: boolean
7
8
  }
8
9
 
9
10
  export interface BottomSheetBase {
@@ -1,15 +1,20 @@
1
1
  import type { EVMChain } from '@lifi/sdk'
2
- import { Skeleton, Tooltip } from '@mui/material'
2
+ import { Skeleton, type Theme, Tooltip, useMediaQuery } from '@mui/material'
3
3
  import { memo, useCallback, useEffect, useMemo } from 'react'
4
+ import { useTranslation } from 'react-i18next'
4
5
  import { useNavigate } from 'react-router-dom'
6
+ import { useChainOrderStore } from '../../stores/chains/ChainOrderStore.js'
5
7
  import {
6
8
  maxChainsToOrder,
7
9
  maxChainsToShow,
10
+ maxGridItemsToShow,
8
11
  } from '../../stores/chains/createChainOrderStore.js'
9
12
  import type { FormTypeProps } from '../../stores/form/types.js'
10
13
  import { FormKeyHelper } from '../../stores/form/types.js'
14
+ import { useFieldActions } from '../../stores/form/useFieldActions.js'
11
15
  import { useFieldValues } from '../../stores/form/useFieldValues.js'
12
16
  import { navigationRoutes } from '../../utils/navigationRoutes.js'
17
+ import { AllChainsAvatar } from '../Chains/AllChainsAvatar.js'
13
18
  import {
14
19
  ChainAvatar,
15
20
  ChainCard,
@@ -20,16 +25,27 @@ import {
20
25
  import { useChainSelect } from './useChainSelect.js'
21
26
 
22
27
  export const ChainSelect = memo(({ formType }: FormTypeProps) => {
28
+ const { t } = useTranslation()
23
29
  const navigate = useNavigate()
30
+ const { setFieldValue } = useFieldActions()
31
+ const isMobile = useMediaQuery((theme: Theme) =>
32
+ theme.breakpoints.down(theme.breakpoints.values.xs)
33
+ )
34
+
24
35
  const {
25
36
  chainOrder,
26
37
  chains,
27
- getChains,
28
38
  isLoading,
39
+ getSelectedChains,
29
40
  setChainOrder,
30
41
  setCurrentChain,
31
42
  } = useChainSelect(formType)
32
43
 
44
+ const { isAllNetworks, setIsAllNetworks } = useChainOrderStore((state) => ({
45
+ isAllNetworks: state.isAllNetworks,
46
+ setIsAllNetworks: state.setIsAllNetworks,
47
+ }))
48
+
33
49
  const [chainId] = useFieldValues(FormKeyHelper.getChainKey(formType))
34
50
 
35
51
  useEffect(() => {
@@ -42,60 +58,116 @@ export const ChainSelect = memo(({ formType }: FormTypeProps) => {
42
58
  }
43
59
  }, [chainId, chainOrder, formType, setChainOrder])
44
60
 
61
+ const onChainSelect = useCallback(
62
+ (selectedChainId: number) => {
63
+ setIsAllNetworks(false)
64
+ setCurrentChain(selectedChainId)
65
+ },
66
+ [setIsAllNetworks, setCurrentChain]
67
+ )
68
+
45
69
  const showAllChains = useCallback(() => {
46
70
  navigate(navigationRoutes[`${formType}Chain`])
47
71
  }, [navigate, formType])
48
72
 
49
- const { chainsToHide, chainsToShow, tilesCount } = useMemo(() => {
50
- // We check if we can accommodate all the chains on the grid
51
- // If there are more than 10 chains we show the number of hidden chains as the last one tile
52
- const chainsToHide =
53
- chains?.length === maxChainsToShow
54
- ? 0
55
- : (chains?.length ?? 0) - maxChainsToOrder
73
+ const selectAllNetworks = useCallback(() => {
74
+ setIsAllNetworks(true)
75
+ setFieldValue('tokenSearchFilter', '')
76
+ }, [setIsAllNetworks, setFieldValue])
56
77
 
57
- // When there is less than 10 chains we don't care about the order
58
- const chainsToShow = chainsToHide > 0 ? getChains() : chains
78
+ const chainsToHide =
79
+ chains?.length === maxChainsToShow
80
+ ? 0
81
+ : (chains?.length ?? 0) - maxChainsToOrder
59
82
 
60
- // Number of tiles to show in the grid
61
- const tilesCount = (chainsToShow?.length ?? 0) + (chainsToHide > 0 ? 1 : 0)
83
+ const chainsToShow = useMemo(
84
+ () => (chainsToHide > 0 ? getSelectedChains() : chains) ?? [],
85
+ [chainsToHide, getSelectedChains, chains]
86
+ )
87
+
88
+ const showAllNetworks = chainsToShow.length > 1
89
+
90
+ const tilesCount =
91
+ chainsToShow.length + (showAllNetworks ? 1 : 0) + (chainsToHide > 0 ? 1 : 0)
62
92
 
63
- return { chainsToHide, chainsToShow, tilesCount }
64
- }, [chains, getChains])
93
+ if (isLoading) {
94
+ return (
95
+ <ChainContainer itemCount={tilesCount}>
96
+ {Array.from({ length: maxGridItemsToShow }).map((_, index) => (
97
+ <Skeleton
98
+ key={index}
99
+ variant="rectangular"
100
+ width={56}
101
+ height={isMobile ? 36 : 56}
102
+ sx={{ borderRadius: 1 }}
103
+ />
104
+ ))}
105
+ </ChainContainer>
106
+ )
107
+ }
65
108
 
66
109
  return (
67
110
  <ChainContainer itemCount={tilesCount}>
68
- {isLoading
69
- ? Array.from({ length: maxChainsToOrder }).map((_, index) => (
70
- <Skeleton
71
- key={index}
72
- variant="rectangular"
73
- width={56}
74
- height={56}
75
- sx={{ borderRadius: 1 }}
111
+ {showAllNetworks && (
112
+ <Tooltip title={t('main.allNetworks')} enterNextDelay={100}>
113
+ <ChainCard
114
+ component="button"
115
+ onClick={selectAllNetworks}
116
+ type={isAllNetworks ? 'selected' : 'default'}
117
+ selectionColor="secondary"
118
+ >
119
+ <AllChainsAvatar
120
+ chains={chains ?? []}
121
+ size={isMobile ? 'small' : 'medium'}
76
122
  />
77
- ))
78
- : chainsToShow?.map((chain: EVMChain) => (
79
- <Tooltip key={chain.id} title={chain.name} enterNextDelay={100}>
80
- <ChainCard
81
- component="button"
82
- onClick={() => setCurrentChain(chain.id)}
83
- type={chainId === chain.id ? 'selected' : 'default'}
84
- selectionColor="secondary"
85
- >
86
- <ChainAvatar src={chain.logoURI} alt={chain.key}>
87
- {chain.name[0]}
88
- </ChainAvatar>
89
- </ChainCard>
90
- </Tooltip>
91
- ))}
92
- {chainsToHide > 0 ? (
123
+ </ChainCard>
124
+ </Tooltip>
125
+ )}
126
+ {chainsToShow.map((chain: EVMChain) => (
127
+ <ChainItem
128
+ key={chain.id}
129
+ chain={chain}
130
+ isSelected={chainId === chain.id}
131
+ isAllNetworks={isAllNetworks}
132
+ onSelect={onChainSelect}
133
+ />
134
+ ))}
135
+ {chainsToHide > 0 && (
93
136
  <ChainCard component="button" onClick={showAllChains}>
94
137
  <MoreChainsBox>
95
138
  <MoreChainsText>+{chainsToHide}</MoreChainsText>
96
139
  </MoreChainsBox>
97
140
  </ChainCard>
98
- ) : null}
141
+ )}
99
142
  </ChainContainer>
100
143
  )
101
144
  })
145
+
146
+ const ChainItem = memo(
147
+ ({
148
+ chain,
149
+ isSelected,
150
+ isAllNetworks,
151
+ onSelect,
152
+ }: {
153
+ chain: EVMChain
154
+ isSelected: boolean
155
+ isAllNetworks: boolean
156
+ onSelect: (id: number) => void
157
+ }) => {
158
+ return (
159
+ <Tooltip title={chain.name} enterNextDelay={100}>
160
+ <ChainCard
161
+ component="button"
162
+ onClick={() => onSelect(chain.id)}
163
+ type={!isAllNetworks && isSelected ? 'selected' : 'default'}
164
+ selectionColor="secondary"
165
+ >
166
+ <ChainAvatar src={chain.logoURI} alt={chain.key}>
167
+ {chain.name[0]}
168
+ </ChainAvatar>
169
+ </ChainCard>
170
+ </Tooltip>
171
+ )
172
+ }
173
+ )
@@ -31,7 +31,7 @@ export const useChainSelect = (formType: FormType) => {
31
31
  const swapOnly = useSwapOnly()
32
32
  const { tryResetToAddress } = useToAddressReset()
33
33
 
34
- const getChains = () => {
34
+ const getSelectedChains = useCallback(() => {
35
35
  if (!chains) {
36
36
  return []
37
37
  }
@@ -39,7 +39,7 @@ export const useChainSelect = (formType: FormType) => {
39
39
  .map((chainId) => chains.find((chain) => chain.id === chainId))
40
40
  .filter(Boolean) as EVMChain[]
41
41
  return selectedChains
42
- }
42
+ }, [chains, chainOrder])
43
43
 
44
44
  const setCurrentChain = useCallback(
45
45
  (chainId: number) => {
@@ -82,7 +82,7 @@ export const useChainSelect = (formType: FormType) => {
82
82
  return {
83
83
  chainOrder,
84
84
  chains,
85
- getChains,
85
+ getSelectedChains,
86
86
  isLoading,
87
87
  setChainOrder,
88
88
  setCurrentChain,
@@ -0,0 +1,113 @@
1
+ import { ChainType, type EVMChain, type ExtendedChain } from '@lifi/sdk'
2
+ import { Avatar, Box } from '@mui/material'
3
+ import { memo, useMemo } from 'react'
4
+
5
+ interface AllChainsAvatarProps {
6
+ chains: ExtendedChain[] | EVMChain[]
7
+ size: 'small' | 'medium'
8
+ }
9
+
10
+ const chainTypeIcons = [
11
+ {
12
+ name: 'Ethereum',
13
+ chainType: ChainType.EVM,
14
+ icon: 'https://lifinance.github.io/types/src/assets/icons/chains/ethereum.svg',
15
+ },
16
+ {
17
+ name: 'Solana',
18
+ chainType: ChainType.SVM,
19
+ icon: 'https://lifinance.github.io/types/src/assets/icons/chains/solana.svg',
20
+ },
21
+ {
22
+ name: 'Bitcoin',
23
+ chainType: ChainType.UTXO,
24
+ icon: 'https://lifinance.github.io/types/src/assets/icons/chains/bitcoin.svg',
25
+ },
26
+ {
27
+ name: 'Sui',
28
+ chainType: ChainType.MVM,
29
+ icon: 'https://lifinance.github.io/types/src/assets/icons/chains/sui.svg',
30
+ },
31
+ ]
32
+
33
+ const maxChainAvatarsCount = chainTypeIcons.length
34
+
35
+ export const AllChainsAvatar = memo(
36
+ ({ chains, size }: AllChainsAvatarProps) => {
37
+ const icons = useMemo(() => {
38
+ // Get existing ecosystem icons
39
+ const existingChainTypeIcons = chainTypeIcons.filter((predefinedChain) =>
40
+ chains.some((chain) => chain.chainType === predefinedChain.chainType)
41
+ )
42
+ if (existingChainTypeIcons.length === maxChainAvatarsCount) {
43
+ return existingChainTypeIcons
44
+ }
45
+
46
+ const remainingSlots =
47
+ maxChainAvatarsCount - existingChainTypeIcons.length
48
+
49
+ const chainsWithLogos = chains.filter((chain) => {
50
+ // Filter out chain icons matching ecosystem icons
51
+ const hasPredefinedIcon = existingChainTypeIcons.some(
52
+ (icon) => icon.name === chain.name
53
+ )
54
+ const hasLogoURI = Boolean(chain.logoURI)
55
+ return !hasPredefinedIcon && hasLogoURI
56
+ })
57
+
58
+ const additionalIcons = chainsWithLogos
59
+ .slice(0, remainingSlots)
60
+ .map((chain) => ({
61
+ name: chain.name,
62
+ chainType: chain.chainType,
63
+ icon: chain.logoURI!,
64
+ }))
65
+
66
+ return [...existingChainTypeIcons, ...additionalIcons]
67
+ }, [chains])
68
+
69
+ const wrapperSize = size === 'small' ? '32px' : '40px'
70
+ const avatarSize = size === 'small' ? '12px' : '16px'
71
+ const avatarsCount = Math.min(icons.length, maxChainAvatarsCount)
72
+ const gridRows = avatarsCount > 2 ? 2 : 1
73
+ const gridColumns = avatarsCount > 1 ? 2 : 1
74
+
75
+ return (
76
+ <Box
77
+ sx={{
78
+ width: wrapperSize,
79
+ height: wrapperSize,
80
+ display: 'grid',
81
+ gridTemplateRows: `repeat(${gridRows}, 1fr)`,
82
+ gridTemplateColumns: `repeat(${gridColumns}, 1fr)`,
83
+ placeItems: 'center',
84
+ }}
85
+ >
86
+ {icons.slice(0, avatarsCount).map((chain, idx) => {
87
+ const isThirdAvatarInThreeAvatarLayout =
88
+ avatarsCount === 3 && idx === 2
89
+
90
+ return (
91
+ <Avatar
92
+ key={`${chain.chainType}-${idx}`}
93
+ src={chain.icon}
94
+ alt={chain.name}
95
+ sx={{
96
+ width: avatarSize,
97
+ height: avatarSize,
98
+ margin: 'auto',
99
+ ...(isThirdAvatarInThreeAvatarLayout && {
100
+ gridColumn: '1 / span 2',
101
+ gridRow: '2',
102
+ justifySelf: 'center',
103
+ }),
104
+ }}
105
+ >
106
+ {chain.chainType[0]}
107
+ </Avatar>
108
+ )
109
+ })}
110
+ </Box>
111
+ )
112
+ }
113
+ )
@@ -17,12 +17,14 @@ interface ChainListProps {
17
17
  onSelect: (chain: ExtendedChain) => void
18
18
  selectedChainId?: number
19
19
  isLoading: boolean
20
+ hasSearchQuery: boolean
20
21
  inExpansion: boolean
21
22
  }
22
23
 
23
24
  export const ChainList = ({
24
25
  parentRef,
25
26
  chains,
27
+ hasSearchQuery,
26
28
  onSelect,
27
29
  selectedChainId,
28
30
  isLoading,
@@ -78,6 +80,7 @@ export const ChainList = ({
78
80
  <VirtualizedChainList
79
81
  scrollElementRef={parentRef}
80
82
  chains={chains}
83
+ hasSearchQuery={hasSearchQuery}
81
84
  onSelect={onSelect}
82
85
  selectedChainId={selectedChainId}
83
86
  itemsSize={itemsSize}
@@ -33,7 +33,7 @@ export const ChainSearchInput = ({
33
33
  <SearchInput
34
34
  inputRef={inputRef}
35
35
  onChange={onChange}
36
- placeholder={t('main.searchChain')}
36
+ placeholder={t('main.searchNetwork')}
37
37
  size="small"
38
38
  onClear={handleClear}
39
39
  />
@@ -45,7 +45,7 @@ export const ChainSearchInput = ({
45
45
  <StickySearchInput
46
46
  inputRef={inputRef}
47
47
  onChange={onChange}
48
- placeholder={t('main.searchChain')}
48
+ placeholder={t('main.searchNetwork')}
49
49
  onClear={handleClear}
50
50
  />
51
51
  )
@@ -104,6 +104,7 @@ export const SelectChainContent = memo(function SelectChainContent({
104
104
  isLoading={isLoading}
105
105
  onSelect={onSelect ?? onSelectChainFallback}
106
106
  selectedChainId={selectedChainId}
107
+ hasSearchQuery={!!inputRef.current?.value}
107
108
  inExpansion={inExpansion}
108
109
  />
109
110
  </Box>