@lifi/widget 3.23.3 → 3.24.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 (156) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/LICENSE +165 -0
  3. package/README.md +14 -14
  4. package/dist/esm/components/AppContainer.js +22 -8
  5. package/dist/esm/components/AppContainer.js.map +1 -1
  6. package/dist/esm/components/Avatar/Avatar.d.ts +6 -1
  7. package/dist/esm/components/Avatar/Avatar.js +4 -4
  8. package/dist/esm/components/Avatar/Avatar.js.map +1 -1
  9. package/dist/esm/components/Avatar/Avatar.style.d.ts +13 -4
  10. package/dist/esm/components/Avatar/Avatar.style.js +20 -10
  11. package/dist/esm/components/Avatar/Avatar.style.js.map +1 -1
  12. package/dist/esm/components/Avatar/SmallAvatar.d.ts +8 -2
  13. package/dist/esm/components/Avatar/SmallAvatar.js +7 -5
  14. package/dist/esm/components/Avatar/SmallAvatar.js.map +1 -1
  15. package/dist/esm/components/Avatar/TokenAvatar.d.ts +6 -0
  16. package/dist/esm/components/Avatar/TokenAvatar.js +7 -7
  17. package/dist/esm/components/Avatar/TokenAvatar.js.map +1 -1
  18. package/dist/esm/components/Avatar/utils.d.ts +1 -8
  19. package/dist/esm/components/Avatar/utils.js +5 -8
  20. package/dist/esm/components/Avatar/utils.js.map +1 -1
  21. package/dist/esm/components/BaseTransactionButton/BaseTransactionButton.js +6 -1
  22. package/dist/esm/components/BaseTransactionButton/BaseTransactionButton.js.map +1 -1
  23. package/dist/esm/components/Header/Header.style.d.ts +4 -1
  24. package/dist/esm/components/Header/Header.style.js +8 -5
  25. package/dist/esm/components/Header/Header.style.js.map +1 -1
  26. package/dist/esm/components/RouteCard/RouteCardEssentials.js +2 -8
  27. package/dist/esm/components/RouteCard/RouteCardEssentials.js.map +1 -1
  28. package/dist/esm/components/Routes/RoutesExpanded.js.map +1 -1
  29. package/dist/esm/components/SelectTokenButton/SelectTokenButton.style.js +2 -2
  30. package/dist/esm/components/SendToWallet/SendToWalletButton.js +2 -1
  31. package/dist/esm/components/SendToWallet/SendToWalletButton.js.map +1 -1
  32. package/dist/esm/components/Step/CircularProgress.style.js +22 -17
  33. package/dist/esm/components/Step/CircularProgress.style.js.map +1 -1
  34. package/dist/esm/components/StepActions/StepActions.style.d.ts +4 -1
  35. package/dist/esm/components/TokenList/TokenDetailsSheet.d.ts +6 -0
  36. package/dist/esm/components/TokenList/TokenDetailsSheet.js +24 -0
  37. package/dist/esm/components/TokenList/TokenDetailsSheet.js.map +1 -0
  38. package/dist/esm/components/TokenList/TokenDetailsSheetContent.d.ts +8 -0
  39. package/dist/esm/components/TokenList/TokenDetailsSheetContent.js +67 -0
  40. package/dist/esm/components/TokenList/TokenDetailsSheetContent.js.map +1 -0
  41. package/dist/esm/components/TokenList/TokenDetailsSheetContent.style.d.ts +5 -0
  42. package/dist/esm/components/TokenList/TokenDetailsSheetContent.style.js +28 -0
  43. package/dist/esm/components/TokenList/TokenDetailsSheetContent.style.js.map +1 -0
  44. package/dist/esm/components/TokenList/TokenList.js +2 -2
  45. package/dist/esm/components/TokenList/TokenList.js.map +1 -1
  46. package/dist/esm/components/TokenList/TokenListItem.js +29 -11
  47. package/dist/esm/components/TokenList/TokenListItem.js.map +1 -1
  48. package/dist/esm/components/TokenList/VirtualizedTokenList.js +45 -40
  49. package/dist/esm/components/TokenList/VirtualizedTokenList.js.map +1 -1
  50. package/dist/esm/components/TokenList/types.d.ts +7 -0
  51. package/dist/esm/config/version.d.ts +1 -1
  52. package/dist/esm/config/version.js +1 -1
  53. package/dist/esm/hooks/useTokenBalances.d.ts +2 -1
  54. package/dist/esm/hooks/useTokenBalances.js +2 -2
  55. package/dist/esm/hooks/useTokenBalances.js.map +1 -1
  56. package/dist/esm/hooks/useTokenSearch.d.ts +2 -1
  57. package/dist/esm/hooks/useTokenSearch.js +7 -2
  58. package/dist/esm/hooks/useTokenSearch.js.map +1 -1
  59. package/dist/esm/hooks/useTokens.d.ts +2 -1
  60. package/dist/esm/hooks/useTokens.js +6 -13
  61. package/dist/esm/hooks/useTokens.js.map +1 -1
  62. package/dist/esm/i18n/bn.json +5 -0
  63. package/dist/esm/i18n/de.json +5 -0
  64. package/dist/esm/i18n/en.json +4 -0
  65. package/dist/esm/i18n/es.json +5 -0
  66. package/dist/esm/i18n/fr.json +5 -0
  67. package/dist/esm/i18n/hi.json +5 -0
  68. package/dist/esm/i18n/id.json +5 -0
  69. package/dist/esm/i18n/it.json +5 -0
  70. package/dist/esm/i18n/ja.json +5 -0
  71. package/dist/esm/i18n/ko.json +5 -0
  72. package/dist/esm/i18n/pt.json +5 -0
  73. package/dist/esm/i18n/th.json +5 -0
  74. package/dist/esm/i18n/tr.json +5 -0
  75. package/dist/esm/i18n/uk.json +5 -0
  76. package/dist/esm/i18n/vi.json +5 -0
  77. package/dist/esm/i18n/zh.json +5 -0
  78. package/dist/esm/icons/lifi.d.ts +1 -1
  79. package/dist/esm/icons/lifi.js +1 -1
  80. package/dist/esm/icons/lifi.js.map +1 -1
  81. package/dist/esm/index.d.ts +1 -0
  82. package/dist/esm/index.js +1 -0
  83. package/dist/esm/index.js.map +1 -1
  84. package/dist/esm/pages/ActiveTransactionsPage/ActiveTransactionsPage.js +1 -1
  85. package/dist/esm/pages/ActiveTransactionsPage/ActiveTransactionsPage.js.map +1 -1
  86. package/dist/esm/pages/RoutesPage/RoutesPage.js +1 -1
  87. package/dist/esm/pages/RoutesPage/RoutesPage.js.map +1 -1
  88. package/dist/esm/pages/SelectChainPage/SelectChainPage.js +1 -1
  89. package/dist/esm/pages/SelectChainPage/SelectChainPage.js.map +1 -1
  90. package/dist/esm/pages/SelectEnabledToolsPage.js +1 -1
  91. package/dist/esm/pages/SelectEnabledToolsPage.js.map +1 -1
  92. package/dist/esm/pages/TransactionHistoryPage/TransactionHistoryPage.js +1 -1
  93. package/dist/esm/pages/TransactionHistoryPage/TransactionHistoryPage.js.map +1 -1
  94. package/dist/esm/pages/TransactionPage/StatusBottomSheet.style.js +18 -7
  95. package/dist/esm/pages/TransactionPage/StatusBottomSheet.style.js.map +1 -1
  96. package/dist/esm/types/widget.d.ts +2 -0
  97. package/dist/esm/utils/format.d.ts +1 -0
  98. package/dist/esm/utils/format.js +16 -0
  99. package/dist/esm/utils/format.js.map +1 -1
  100. package/dist/esm/utils/item.d.ts +7 -2
  101. package/dist/esm/utils/item.js +10 -3
  102. package/dist/esm/utils/item.js.map +1 -1
  103. package/package.json +18 -18
  104. package/package.json.tmp +18 -18
  105. package/src/components/AppContainer.tsx +26 -8
  106. package/src/components/Avatar/Avatar.style.tsx +23 -11
  107. package/src/components/Avatar/Avatar.tsx +11 -6
  108. package/src/components/Avatar/SmallAvatar.tsx +13 -5
  109. package/src/components/Avatar/TokenAvatar.tsx +38 -8
  110. package/src/components/Avatar/utils.ts +5 -10
  111. package/src/components/BaseTransactionButton/BaseTransactionButton.tsx +5 -1
  112. package/src/components/Header/Header.style.ts +11 -6
  113. package/src/components/RouteCard/RouteCardEssentials.tsx +2 -9
  114. package/src/components/Routes/RoutesExpanded.tsx +7 -2
  115. package/src/components/SelectTokenButton/SelectTokenButton.style.tsx +2 -2
  116. package/src/components/SendToWallet/SendToWalletButton.tsx +3 -2
  117. package/src/components/Step/CircularProgress.style.tsx +25 -17
  118. package/src/components/TokenList/TokenDetailsSheet.tsx +48 -0
  119. package/src/components/TokenList/TokenDetailsSheetContent.style.tsx +34 -0
  120. package/src/components/TokenList/TokenDetailsSheetContent.tsx +200 -0
  121. package/src/components/TokenList/TokenList.tsx +7 -2
  122. package/src/components/TokenList/TokenListItem.tsx +117 -50
  123. package/src/components/TokenList/VirtualizedTokenList.tsx +95 -74
  124. package/src/components/TokenList/types.ts +8 -0
  125. package/src/config/version.ts +1 -1
  126. package/src/hooks/useTokenBalances.ts +9 -3
  127. package/src/hooks/useTokenSearch.ts +11 -2
  128. package/src/hooks/useTokens.ts +10 -21
  129. package/src/i18n/bn.json +5 -0
  130. package/src/i18n/de.json +5 -0
  131. package/src/i18n/en.json +4 -0
  132. package/src/i18n/es.json +5 -0
  133. package/src/i18n/fr.json +5 -0
  134. package/src/i18n/hi.json +5 -0
  135. package/src/i18n/id.json +5 -0
  136. package/src/i18n/it.json +5 -0
  137. package/src/i18n/ja.json +5 -0
  138. package/src/i18n/ko.json +5 -0
  139. package/src/i18n/pt.json +5 -0
  140. package/src/i18n/th.json +5 -0
  141. package/src/i18n/tr.json +5 -0
  142. package/src/i18n/uk.json +5 -0
  143. package/src/i18n/vi.json +5 -0
  144. package/src/i18n/zh.json +5 -0
  145. package/src/icons/lifi.ts +1 -1
  146. package/src/index.ts +1 -0
  147. package/src/pages/ActiveTransactionsPage/ActiveTransactionsPage.tsx +1 -0
  148. package/src/pages/RoutesPage/RoutesPage.tsx +1 -1
  149. package/src/pages/SelectChainPage/SelectChainPage.tsx +1 -1
  150. package/src/pages/SelectEnabledToolsPage.tsx +1 -1
  151. package/src/pages/TransactionHistoryPage/TransactionHistoryPage.tsx +1 -0
  152. package/src/pages/TransactionPage/StatusBottomSheet.style.tsx +19 -11
  153. package/src/types/widget.ts +2 -0
  154. package/src/utils/format.ts +19 -0
  155. package/src/utils/item.ts +29 -4
  156. package/LICENSE.md +0 -201
@@ -3,15 +3,21 @@ import { useAccount } from '@lifi/wallet-management'
3
3
  import { useQuery } from '@tanstack/react-query'
4
4
  import { formatUnits } from 'viem'
5
5
  import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
6
+ import type { FormType } from '../stores/form/types.js'
6
7
  import type { TokenAmount } from '../types/token.js'
7
8
  import { getQueryKey } from '../utils/queries.js'
8
9
  import { useTokens } from './useTokens.js'
9
10
 
10
11
  const defaultRefetchInterval = 32_000
11
12
 
12
- export const useTokenBalances = (selectedChainId?: number) => {
13
- const { tokens, featuredTokens, popularTokens, chain, isLoading } =
14
- useTokens(selectedChainId)
13
+ export const useTokenBalances = (
14
+ selectedChainId?: number,
15
+ formType?: FormType
16
+ ) => {
17
+ const { tokens, featuredTokens, popularTokens, chain, isLoading } = useTokens(
18
+ selectedChainId,
19
+ formType
20
+ )
15
21
  const { account } = useAccount({ chainType: chain?.chainType })
16
22
  const { keyPrefix } = useWidgetConfig()
17
23
 
@@ -1,16 +1,20 @@
1
1
  import { type ChainId, type TokensResponse, getToken } from '@lifi/sdk'
2
2
  import { useQuery, useQueryClient } from '@tanstack/react-query'
3
3
  import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
4
+ import type { FormType } from '../stores/form/types.js'
4
5
  import type { TokenAmount } from '../types/token.js'
6
+ import { isTokenAllowed } from '../utils/item.js'
5
7
  import { getQueryKey } from '../utils/queries.js'
6
8
 
7
9
  export const useTokenSearch = (
8
10
  chainId?: number,
9
11
  tokenQuery?: string,
10
- enabled?: boolean
12
+ enabled?: boolean,
13
+ formType?: FormType
11
14
  ) => {
12
15
  const queryClient = useQueryClient()
13
- const { keyPrefix } = useWidgetConfig()
16
+ const { tokens: configTokens, keyPrefix } = useWidgetConfig()
17
+
14
18
  const { data, isLoading } = useQuery({
15
19
  queryKey: [getQueryKey('token-search', keyPrefix), chainId, tokenQuery],
16
20
  queryFn: async ({ queryKey: [, chainId, tokenQuery], signal }) => {
@@ -19,6 +23,11 @@ export const useTokenSearch = (
19
23
  })
20
24
 
21
25
  if (token) {
26
+ // Return undefined if the token is denied
27
+ if (!isTokenAllowed(token, configTokens, formType)) {
28
+ return undefined
29
+ }
30
+
22
31
  queryClient.setQueriesData<TokensResponse>(
23
32
  { queryKey: [getQueryKey('tokens', keyPrefix)] },
24
33
  (data) => {
@@ -2,11 +2,13 @@ import { ChainType, getTokens } from '@lifi/sdk'
2
2
  import { useQuery } from '@tanstack/react-query'
3
3
  import { useMemo } from 'react'
4
4
  import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
5
+ import type { FormType } from '../stores/form/types.js'
5
6
  import type { TokenAmount } from '../types/token.js'
7
+ import { isTokenAllowed } from '../utils/item.js'
6
8
  import { getQueryKey } from '../utils/queries.js'
7
9
  import { useChains } from './useChains.js'
8
10
 
9
- export const useTokens = (selectedChainId?: number) => {
11
+ export const useTokens = (selectedChainId?: number, formType?: FormType) => {
10
12
  const { tokens: configTokens, keyPrefix } = useWidgetConfig()
11
13
  const { data, isLoading } = useQuery({
12
14
  queryKey: [getQueryKey('tokens', keyPrefix)],
@@ -45,27 +47,13 @@ export const useTokens = (selectedChainId?: number) => {
45
47
  filteredTokens = [...includedTokens, ...filteredTokens]
46
48
  }
47
49
 
48
- if (configTokens?.allow?.length || configTokens?.deny?.length) {
49
- const allowedTokensSet = new Set(
50
- configTokens?.allow
51
- ?.filter((token) => token.chainId === selectedChainId)
52
- .map((token) => token.address)
53
- )
54
-
55
- const deniedTokenAddressesSet = new Set(
56
- configTokens?.deny
57
- ?.filter((token) => token.chainId === selectedChainId)
58
- .map((token) => token.address)
59
- )
50
+ // Get the appropriate allow/deny lists based on formType
51
+ filteredTokens = filteredTokens.filter(
52
+ (token) =>
53
+ token.chainId === selectedChainId &&
54
+ isTokenAllowed(token, configTokens, formType)
55
+ )
60
56
 
61
- if (allowedTokensSet.size || deniedTokenAddressesSet.size) {
62
- filteredTokens = filteredTokens.filter(
63
- (token) =>
64
- (!allowedTokensSet.size || allowedTokensSet.has(token.address)) &&
65
- !deniedTokenAddressesSet.has(token.address)
66
- )
67
- }
68
- }
69
57
  const filteredTokensMap = new Map(
70
58
  filteredTokens.map((token) => [token.address, token])
71
59
  )
@@ -118,6 +106,7 @@ export const useTokens = (selectedChainId?: number) => {
118
106
  getChainById,
119
107
  isSupportedChainsLoading,
120
108
  selectedChainId,
109
+ formType,
121
110
  ])
122
111
 
123
112
  return {
package/src/i18n/bn.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "আপনার {{chainName}} গ্যাস কম। চালিয়ে যাওয়ার মাধ্যমে, আপনি সোওয়াপ সম্পূর্ণ করার জন্য পর্যাপ্ত গ্যাস পাবেন।",
90
91
  "emptyActiveTransactions": "",
91
92
  "emptyBridgesList": "",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "",
341
342
  "noConnectedWallets": "",
342
343
  "noRecentWallets": ""
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/i18n/de.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "Sie haben nicht genug Gas auf {{chainName}}. Wenn Sie fortfahren, erhalten Sie zusätzlich genug Gas um den Swap abzuschließen.",
90
91
  "emptyActiveTransactions": "Laufende Swaps werden hier angezeigt. Sobald Sie fertig sind, finden Sie sie in der Transaktionshistorie.",
91
92
  "emptyBridgesList": "",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "",
341
342
  "noConnectedWallets": "",
342
343
  "noRecentWallets": ""
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/i18n/en.json CHANGED
@@ -341,5 +341,9 @@
341
341
  "noBookmarkedWallets": "No bookmarked wallets",
342
342
  "noConnectedWallets": "No connected wallets",
343
343
  "noRecentWallets": "No recent wallets"
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "Current price",
347
+ "contractAddress": "Contract address"
344
348
  }
345
349
  }
package/src/i18n/es.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "Tienes poco gas en {{chainName}}. Al continuar, obtendrás suficiente gas para completar la transacción.",
90
91
  "emptyActiveTransactions": "Las transacciones en progreso aparecerán aquí. Una vez completadas, encuéntralas en el historial de transacciones.",
91
92
  "emptyBridgesList": "No pudimos encontrar ningún puente que coincida con tu búsqueda",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "No hay billeteras preferidas",
341
342
  "noConnectedWallets": "No hay billeteras conectadas",
342
343
  "noRecentWallets": "No hay billeteras recientes"
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/i18n/fr.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "Vous avez peu de gaz sur {{chainName}}. En continuant, vous aurez assez de gaz pour compléter l'échange.",
90
91
  "emptyActiveTransactions": "Les transactions en cours apparaîtront ici. Une fois terminées, retrouvez-les dans l'historique des transactions.",
91
92
  "emptyBridgesList": "",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "Aucun portefeuille favori",
341
342
  "noConnectedWallets": "Aucun portefeuille connecté",
342
343
  "noRecentWallets": "Aucun portefeuille récent"
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/i18n/hi.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "",
90
91
  "emptyActiveTransactions": "",
91
92
  "emptyBridgesList": "",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "",
341
342
  "noConnectedWallets": "",
342
343
  "noRecentWallets": ""
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/i18n/id.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "Gas anda hampir habis {{chainName}}. Dengan melanjutkan, anda akan mendapatkan cukup gas untuk menyelesaikan penukaran.",
90
91
  "emptyActiveTransactions": "Transaksi yang sedang berlangsung akan muncul di sini. Setelah selesai, temukan di riwayat transaksi.",
91
92
  "emptyBridgesList": "Kami tidak dapat menemukan bridge yang sesuai dengan pencarian Anda",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "Tidak ada dompet yang ditandai",
341
342
  "noConnectedWallets": "Tida ada dompet yang di hubungkan",
342
343
  "noRecentWallets": "Tidak ada dompet terakhir yang digunakan"
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/i18n/it.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "Livello basso di gas su {{chainName}}. Continuando avrai abbastanza gas per completare lo scambio.",
90
91
  "emptyActiveTransactions": "Le transazioni in corso appariranno qui. Una volta completate, potrai trovarle nella cronologia delle transazioni.",
91
92
  "emptyBridgesList": "",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "",
341
342
  "noConnectedWallets": "",
342
343
  "noRecentWallets": ""
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/i18n/ja.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "{{chainName}} のガスが不足していますが、続行することでトランザクションを完了するのに十分なガスが補填されます。",
90
91
  "emptyActiveTransactions": "進行中のトランザクションがここに表示されます。完了すると、トランザクション履歴に表示されます。",
91
92
  "emptyBridgesList": "",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "ブックマークされたウォレットはありません",
341
342
  "noConnectedWallets": "接続中のウォレットはありません",
342
343
  "noRecentWallets": "最近使ったウォレットはありません"
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/i18n/ko.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "현재 {{chainName}} 가스가 부족합니다. 이 기능을 통하여 스왑을 완료할 가스를 보충할 수 있습니다.",
90
91
  "emptyActiveTransactions": "진행 중인 스왑이 여기에 나타납니다. 완료 후에는 스왑 기록을 참조하십시오",
91
92
  "emptyBridgesList": "",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "",
341
342
  "noConnectedWallets": "",
342
343
  "noRecentWallets": ""
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/i18n/pt.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "Sua conta inteligente pode não ter o mesmo endereço em outras cadeias. Por favor, verifique novamente antes de prosseguir.",
89
90
  "autoRefuel": "Você está com pouco gás na rede {{chainName}}. Ao continuar, você obterá gás suficiente para completar a conversão.",
90
91
  "emptyActiveTransactions": "As transações em andamento aparecerão aqui. Uma vez concluídas, encontre-as no histórico de transações.",
91
92
  "emptyBridgesList": "Não conseguimos encontrar nenhuma ponte que corresponda à sua pesquisa",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "Sem carteiras favoritas",
341
342
  "noConnectedWallets": "Sem carteiras conectadas",
342
343
  "noRecentWallets": "Sem carteiras recentes"
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "Preço atual",
347
+ "contractAddress": "Endereço do Contrato"
343
348
  }
344
349
  }
package/src/i18n/th.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "คุณใช้แก็ส {{chainName}} เหลือน้อย เมื่อดำเนินการต่อ คุณจะได้รับแก็สเพียงพอสำหรับการแลกเปลี่ยนให้เสร็จสมบูรณ์",
90
91
  "emptyActiveTransactions": "การแลกเปลี่ยนที่กำลังดำเนินการจะปรากฏที่นี่. เมื่อเสร็จสิ้น, จะพบประวัติการแลกเปลี่ยน.",
91
92
  "emptyBridgesList": "",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "ไม่มีกระเป๋าเงินที่ bookmark ไว้",
341
342
  "noConnectedWallets": "ไม่มีกระเป๋าเงินที่เชื่อมต่อไว้",
342
343
  "noRecentWallets": "ไม่พบกระเป๋าเงินล่าสุด"
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/i18n/tr.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "{{chainName}} ağında gaz yetersiz. Devam ederek, işlem için gereken miktarda gaz alacaksınız.",
90
91
  "emptyActiveTransactions": "Devam eden işlemler burada görünecek. Tamamlandığında, işlem geçmişinden bulabilirsiniz.",
91
92
  "emptyBridgesList": "Aradığın köprüyü bulamadık",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "Kayıtlı cüzdan bulunamadı",
341
342
  "noConnectedWallets": "Bağlı cüzdan bulunamadı",
342
343
  "noRecentWallets": "Son kullanılan cüzdan bulunamadı"
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/i18n/uk.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "У вас замало {{chainName}} газу. Продовжуючи, ви отримаєте достатньо газу, щоб завершити обмін.",
90
91
  "emptyActiveTransactions": "Тут показуються незавершені транзакції. Після завершення ви можете знайти їх в історії транзакцій.",
91
92
  "emptyBridgesList": "Ми не змогли знайти жодного моста, що відповідає вашому запиту",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "Немає гаманців в закладках",
341
342
  "noConnectedWallets": "Немає підключених гаманців",
342
343
  "noRecentWallets": "Немає недавніх гаманців"
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/i18n/vi.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "Gas trên {{chainName}} chain của bạn đang thấp. Để tiếp tục, bạn nên có thêm gas để hoàn thành việc swap.",
90
91
  "emptyActiveTransactions": "Các lệnh swap đang xử lý sẽ được hiện ở đây. Khi nào lệnh hoàn tất, bạn có thể kiểm tra lại tại mục lịch sử swap.",
91
92
  "emptyBridgesList": "",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "Không có ví được đánh dấu",
341
342
  "noConnectedWallets": "Không có ví được kết nối",
342
343
  "noRecentWallets": "Không có ví gần đây"
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/i18n/zh.json CHANGED
@@ -86,6 +86,7 @@
86
86
  },
87
87
  "info": {
88
88
  "message": {
89
+ "accountDeployedMessage": "",
89
90
  "autoRefuel": "您在 {{chainName}} 链上的燃气费很低。如果启用该选项,您将获得足够的燃气费完成此次兑换。",
90
91
  "emptyActiveTransactions": "正在进行的兑换将在这里显示。一旦完成,你可在兑换记录中找到它们。",
91
92
  "emptyBridgesList": "我们找不到任何匹配的桥",
@@ -340,5 +341,9 @@
340
341
  "noBookmarkedWallets": "没有收藏的钱包",
341
342
  "noConnectedWallets": "没有已连接的钱包",
342
343
  "noRecentWallets": "没有最近使用的钱包"
344
+ },
345
+ "tokenMetric": {
346
+ "currentPrice": "",
347
+ "contractAddress": ""
343
348
  }
344
349
  }
package/src/icons/lifi.ts CHANGED
@@ -1,2 +1,2 @@
1
1
  export const LiFiToolLogo =
2
- "data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' fill='none'%3e %3ccircle cx='16' cy='16' r='16' fill='%23F5B5FF'/%3e %3cpath fill='black' d='m15.503 19.203-5.334 1.235a.468.468 0 0 0-.34.439v3.672c0 .308.243.503.55.438l7.443-1.722c.308-.065.437-.357.308-.634l-1.346-2.778c-.21-.439 0-.894.47-.991l4.864-1.17c.34-.081.632-.439.632-.796V13.5c0-.309-.243-.52-.551-.439l-7.02 1.674c-.438.097-.633.52-.438.926l1.232 2.551c.211.439 0 .877-.47.991'/%3e %3cpath fill='black' d='m11.985 10.023 1.394 2.86c.179.374 0 .764-.405.845l-2.578.601c-.324.081-.584.406-.584.731v3.07c0 .52.422.846.925.732l2.4-.552c.323-.065.583-.406.583-.732l.016-3.151c0-.44.357-.878.778-.975l7.863-1.885a.468.468 0 0 0 .34-.439V7.456c0-.309-.242-.52-.55-.439L12.293 9.39c-.308.065-.438.357-.308.633'/%3e %3c/svg%3e"
2
+ "data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' width='32' height='32' fill='none' viewBox='0 0 32 32'%3e %3cpath fill='%23f5b5ff' d='M0 0h32v32H0z'/%3e %3cpath fill='black' d='m16 6 4.116 4.116a1.25 1.25 0 0 1 0 1.768l-2.45 2.45-1.667-1.667A4.714 4.714 0 0 1 16 6'/%3e %3cpath fill='black' fill-rule='evenodd' d='m16 26-6.667-6.667a4.714 4.714 0 0 1 0-6.666l5.783 5.783a1.25 1.25 0 0 0 1.767 0l5.783-5.783a4.714 4.714 0 0 1 0 6.666z' clip-rule='evenodd'/%3e %3c/svg%3e"
package/src/index.ts CHANGED
@@ -25,6 +25,7 @@ export * from './types/events.js'
25
25
  export type { TokenAmount } from './types/token.js'
26
26
  export * from './types/widget.js'
27
27
  export { getPriceImpact } from './utils/getPriceImpact.js'
28
+ export * from './utils/format.js'
28
29
  export { percentFormatter } from './utils/percentFormatter.js'
29
30
  export { compactNumberFormatter } from './utils/compactNumberFormatter.js'
30
31
  export { currencyExtendedFormatter } from './utils/currencyExtendedFormatter.js'
@@ -61,6 +61,7 @@ export const ActiveTransactionsPage = () => {
61
61
  return (
62
62
  <PageContainer disableGutters>
63
63
  <List
64
+ className="long-list"
64
65
  sx={{
65
66
  paddingTop: 0,
66
67
  paddingLeft: 1.5,
@@ -69,7 +69,7 @@ export const RoutesPage: React.FC<BoxProps> = () => {
69
69
  const allowInteraction = account.isConnected && !toAddressUnsatisfied
70
70
 
71
71
  return (
72
- <Stack direction="column" spacing={2} flex={1}>
72
+ <Stack className="long-list" direction="column" spacing={2} flex={1}>
73
73
  {routeNotFound ? (
74
74
  <RouteNotFoundCard />
75
75
  ) : isLoading && !routes?.length ? (
@@ -72,7 +72,7 @@ export const SelectChainPage: React.FC<SelectChainPageProps> = ({
72
72
  placeholder={t('main.searchChains')}
73
73
  />
74
74
  {filteredChains.length ? (
75
- <SearchList>
75
+ <SearchList className="long-list">
76
76
  {filteredChains.map((chain) => (
77
77
  <ListItemButton key={chain.id} onClick={() => handleClick(chain)}>
78
78
  <ListItemAvatar>
@@ -146,7 +146,7 @@ export const SelectEnabledToolsPage: React.FC<{
146
146
  placeholder={t(`main.search${type}`)}
147
147
  />
148
148
  {filteredTools.length ? (
149
- <SearchList>
149
+ <SearchList className="long-list">
150
150
  {filteredTools.map((tool) => (
151
151
  <SettingsListItemButton
152
152
  key={tool.name}
@@ -63,6 +63,7 @@ export const TransactionHistoryPage: React.FC = () => {
63
63
  </List>
64
64
  ) : (
65
65
  <List
66
+ className="long-list"
66
67
  style={{
67
68
  height: getTotalSize(),
68
69
  position: 'relative',
@@ -10,13 +10,15 @@ const getStatusColor = (status: StatusColor, theme: Theme) => {
10
10
  return {
11
11
  color: theme.vars.palette.success.mainChannel,
12
12
  alpha: 0.12,
13
- darken: 0,
13
+ lightDarken: 0,
14
+ darkDarken: 0,
14
15
  }
15
16
  case RouteExecutionStatus.Failed:
16
17
  return {
17
18
  color: theme.vars.palette.error.mainChannel,
18
19
  alpha: 0.12,
19
- darken: 0,
20
+ lightDarken: 0,
21
+ darkDarken: 0,
20
22
  }
21
23
  case RouteExecutionStatus.Done | RouteExecutionStatus.Partial:
22
24
  case RouteExecutionStatus.Done | RouteExecutionStatus.Refunded:
@@ -24,13 +26,15 @@ const getStatusColor = (status: StatusColor, theme: Theme) => {
24
26
  return {
25
27
  color: theme.vars.palette.warning.mainChannel,
26
28
  alpha: 0.48,
27
- darken: theme.palette.mode === 'light' ? 0.32 : 0,
29
+ lightDarken: 0.32,
30
+ darkDarken: 0,
28
31
  }
29
32
  default:
30
33
  return {
31
34
  color: theme.vars.palette.primary.mainChannel,
32
35
  alpha: 0.12,
33
- darken: 0,
36
+ lightDarken: 0,
37
+ darkDarken: 0,
34
38
  }
35
39
  }
36
40
  }
@@ -44,13 +48,10 @@ export const CenterContainer = styled(Box)(() => ({
44
48
  export const IconCircle = styled(Box, {
45
49
  shouldForwardProp: (prop) => prop !== 'status',
46
50
  })<{ status: StatusColor }>(({ theme, status }) => {
47
- const {
48
- color,
49
- alpha: alphaValue,
50
- darken: darkenValue,
51
- } = getStatusColor(status, theme)
51
+ const statusConfig = getStatusColor(status, theme)
52
+
52
53
  return {
53
- backgroundColor: `rgba(${color} / ${alphaValue})`,
54
+ backgroundColor: `rgba(${statusConfig.color} / ${statusConfig.alpha})`,
54
55
  borderRadius: '50%',
55
56
  width: 72,
56
57
  height: 72,
@@ -58,9 +59,16 @@ export const IconCircle = styled(Box, {
58
59
  position: 'relative',
59
60
  placeItems: 'center',
60
61
  '& > svg': {
61
- color: `color-mix(in srgb, rgb(${color}) ${(1 - darkenValue) * 100}%, black)`,
62
+ color: `color-mix(in srgb, rgb(${statusConfig.color}) ${(1 - statusConfig.lightDarken) * 100}%, black)`,
62
63
  width: 36,
63
64
  height: 36,
64
65
  },
66
+ ...theme.applyStyles('dark', {
67
+ '& > svg': {
68
+ color: `color-mix(in srgb, rgb(${statusConfig.color}) ${(1 - statusConfig.darkDarken) * 100}%, black)`,
69
+ width: 36,
70
+ height: 36,
71
+ },
72
+ }),
65
73
  }
66
74
  })
@@ -218,6 +218,8 @@ export type WidgetTokens = {
218
218
  featured?: StaticToken[]
219
219
  include?: Token[]
220
220
  popular?: StaticToken[]
221
+ from?: AllowDeny<BaseToken>
222
+ to?: AllowDeny<BaseToken>
221
223
  } & AllowDeny<BaseToken>
222
224
 
223
225
  export type WidgetLanguages = {
@@ -95,3 +95,22 @@ export function formatTokenPrice(
95
95
  }
96
96
  return Number.parseFloat(formattedAmount) * Number.parseFloat(price)
97
97
  }
98
+
99
+ const units = [
100
+ ['day', 86400],
101
+ ['hour', 3600],
102
+ ['minute', 60],
103
+ ['second', 1],
104
+ ] as const
105
+
106
+ export function formatDuration(seconds: number, locale: string): string {
107
+ const match = units.find(([, v]) => seconds >= v)
108
+ const amount = match ? Math.floor(seconds / match[1]) : 0
109
+ const unit = match?.[0] ?? 'second'
110
+
111
+ return amount.toLocaleString(locale, {
112
+ style: 'unit',
113
+ unit,
114
+ unitDisplay: 'narrow',
115
+ })
116
+ }
package/src/utils/item.ts CHANGED
@@ -1,8 +1,33 @@
1
- import type { AllowDeny } from '../types/widget.js'
1
+ import type { BaseToken } from '@lifi/sdk'
2
+ import type { FormType } from '../stores/form/types.js'
3
+ import type { AllowDeny, WidgetTokens } from '../types/widget.js'
2
4
 
3
- export const isItemAllowed = <T>(itemId: T, items?: AllowDeny<T>) => {
5
+ type IncludesFn<T> = (list: T[], item: T) => boolean
6
+
7
+ export const isItemAllowed = <T>(
8
+ item: T,
9
+ items?: AllowDeny<T>,
10
+ includes: IncludesFn<T> = (list, val) => list.includes(val)
11
+ ): boolean => {
4
12
  if (items?.allow?.length) {
5
- return items.allow.includes(itemId)
13
+ return includes(items.allow, item)
6
14
  }
7
- return !items?.deny?.includes(itemId)
15
+
16
+ return !includes(items?.deny ?? [], item)
17
+ }
18
+
19
+ const tokenIncludes = (list: BaseToken[], item: BaseToken) =>
20
+ list.some((t) => t.address === item.address && t.chainId === item.chainId)
21
+
22
+ export const isTokenAllowed = (
23
+ token: BaseToken,
24
+ configTokens: WidgetTokens | undefined,
25
+ formType: FormType | undefined
26
+ ) => {
27
+ return (
28
+ isItemAllowed(token, configTokens, tokenIncludes) &&
29
+ (formType
30
+ ? isItemAllowed(token, configTokens?.[formType], tokenIncludes)
31
+ : true)
32
+ )
8
33
  }