@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.
- package/CHANGELOG.md +19 -0
- package/dist/esm/components/AmountInput/AmountInputEndAdornment.d.ts +1 -1
- package/dist/esm/components/AmountInput/AmountInputEndAdornment.js +3 -2
- package/dist/esm/components/AmountInput/AmountInputEndAdornment.js.map +1 -1
- package/dist/esm/components/AmountInput/PriceFormHelperText.d.ts +1 -1
- package/dist/esm/components/AmountInput/PriceFormHelperText.js +3 -2
- package/dist/esm/components/AmountInput/PriceFormHelperText.js.map +1 -1
- package/dist/esm/components/BottomSheet/BottomSheet.js +2 -2
- package/dist/esm/components/BottomSheet/BottomSheet.js.map +1 -1
- package/dist/esm/components/BottomSheet/types.d.ts +1 -0
- package/dist/esm/components/ChainSelect/ChainSelect.js +35 -18
- package/dist/esm/components/ChainSelect/ChainSelect.js.map +1 -1
- package/dist/esm/components/ChainSelect/useChainSelect.d.ts +1 -1
- package/dist/esm/components/ChainSelect/useChainSelect.js +3 -3
- package/dist/esm/components/ChainSelect/useChainSelect.js.map +1 -1
- package/dist/esm/components/Chains/AllChainsAvatar.d.ts +7 -0
- package/dist/esm/components/Chains/AllChainsAvatar.js +77 -0
- package/dist/esm/components/Chains/AllChainsAvatar.js.map +1 -0
- package/dist/esm/components/Chains/ChainList.d.ts +2 -1
- package/dist/esm/components/Chains/ChainList.js +2 -2
- package/dist/esm/components/Chains/ChainList.js.map +1 -1
- package/dist/esm/components/Chains/ChainSearchInput.js +2 -2
- package/dist/esm/components/Chains/ChainSearchInput.js.map +1 -1
- package/dist/esm/components/Chains/SelectChainContent.js +1 -1
- package/dist/esm/components/Chains/SelectChainContent.js.map +1 -1
- package/dist/esm/components/Chains/VirtualizedChainList.d.ts +2 -1
- package/dist/esm/components/Chains/VirtualizedChainList.js +42 -10
- package/dist/esm/components/Chains/VirtualizedChainList.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteCardEssentials.js +1 -1
- package/dist/esm/components/RouteCard/RouteCardEssentials.js.map +1 -1
- package/dist/esm/components/TokenList/TokenDetailsSheet.d.ts +1 -5
- package/dist/esm/components/TokenList/TokenDetailsSheet.js +5 -3
- package/dist/esm/components/TokenList/TokenDetailsSheet.js.map +1 -1
- package/dist/esm/components/TokenList/TokenDetailsSheetContent.js +2 -2
- package/dist/esm/components/TokenList/TokenDetailsSheetContent.js.map +1 -1
- package/dist/esm/components/TokenList/TokenList.js +11 -53
- package/dist/esm/components/TokenList/TokenList.js.map +1 -1
- package/dist/esm/components/TokenList/TokenListItem.d.ts +1 -1
- package/dist/esm/components/TokenList/TokenListItem.js +29 -25
- package/dist/esm/components/TokenList/TokenListItem.js.map +1 -1
- package/dist/esm/components/TokenList/VirtualizedTokenList.js +56 -37
- package/dist/esm/components/TokenList/VirtualizedTokenList.js.map +1 -1
- package/dist/esm/components/TokenList/types.d.ts +6 -10
- package/dist/esm/components/TokenList/useTokenSelect.js +3 -4
- package/dist/esm/components/TokenList/useTokenSelect.js.map +1 -1
- package/dist/esm/components/TransactionDetails.js +2 -2
- package/dist/esm/components/TransactionDetails.js.map +1 -1
- package/dist/esm/config/version.d.ts +1 -1
- package/dist/esm/config/version.js +1 -1
- package/dist/esm/hooks/useAccountsBalancesData.d.ts +6 -0
- package/dist/esm/hooks/useAccountsBalancesData.js +64 -0
- package/dist/esm/hooks/useAccountsBalancesData.js.map +1 -0
- package/dist/esm/hooks/useFilteredByTokenBalances.d.ts +8 -0
- package/dist/esm/hooks/useFilteredByTokenBalances.js +69 -0
- package/dist/esm/hooks/useFilteredByTokenBalances.js.map +1 -0
- package/dist/esm/hooks/useListHeight.d.ts +0 -1
- package/dist/esm/hooks/useListHeight.js +0 -1
- package/dist/esm/hooks/useListHeight.js.map +1 -1
- package/dist/esm/hooks/useToken.d.ts +2 -2
- package/dist/esm/hooks/useToken.js +13 -11
- package/dist/esm/hooks/useToken.js.map +1 -1
- package/dist/esm/hooks/useTokenAddressBalance.d.ts +2 -3
- package/dist/esm/hooks/useTokenAddressBalance.js +10 -14
- package/dist/esm/hooks/useTokenAddressBalance.js.map +1 -1
- package/dist/esm/hooks/useTokenBalances.d.ts +6 -9
- package/dist/esm/hooks/useTokenBalances.js +57 -72
- package/dist/esm/hooks/useTokenBalances.js.map +1 -1
- package/dist/esm/hooks/useTokenBalancesQueries.d.ts +11 -0
- package/dist/esm/hooks/useTokenBalancesQueries.js +74 -0
- package/dist/esm/hooks/useTokenBalancesQueries.js.map +1 -0
- package/dist/esm/hooks/useTokens.d.ts +6 -6
- package/dist/esm/hooks/useTokens.js +78 -70
- package/dist/esm/hooks/useTokens.js.map +1 -1
- package/dist/esm/i18n/bn.json +3 -3
- package/dist/esm/i18n/de.json +3 -3
- package/dist/esm/i18n/en.json +3 -3
- package/dist/esm/i18n/es.json +3 -3
- package/dist/esm/i18n/fr.json +3 -3
- package/dist/esm/i18n/hi.json +3 -3
- package/dist/esm/i18n/id.json +3 -3
- package/dist/esm/i18n/it.json +3 -3
- package/dist/esm/i18n/ja.json +3 -3
- package/dist/esm/i18n/ko.json +3 -3
- package/dist/esm/i18n/pl.json +3 -3
- package/dist/esm/i18n/pt.json +3 -3
- package/dist/esm/i18n/th.json +3 -3
- package/dist/esm/i18n/tr.json +3 -3
- package/dist/esm/i18n/uk.json +3 -3
- package/dist/esm/i18n/vi.json +3 -3
- package/dist/esm/i18n/zh.json +3 -3
- package/dist/esm/pages/SelectTokenPage/SearchTokenInput.js +6 -1
- package/dist/esm/pages/SelectTokenPage/SearchTokenInput.js.map +1 -1
- package/dist/esm/pages/SelectTokenPage/SelectTokenPage.js +2 -4
- package/dist/esm/pages/SelectTokenPage/SelectTokenPage.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js +1 -1
- package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js.map +1 -1
- package/dist/esm/stores/chains/createChainOrderStore.d.ts +3 -2
- package/dist/esm/stores/chains/createChainOrderStore.js +13 -8
- package/dist/esm/stores/chains/createChainOrderStore.js.map +1 -1
- package/dist/esm/stores/chains/types.d.ts +2 -0
- package/dist/esm/stores/chains/useChainOrder.js +5 -1
- package/dist/esm/stores/chains/useChainOrder.js.map +1 -1
- package/dist/esm/types/token.d.ts +7 -2
- package/dist/esm/utils/chainType.d.ts +1 -0
- package/dist/esm/utils/chainType.js +2 -0
- package/dist/esm/utils/chainType.js.map +1 -1
- package/dist/esm/utils/token.d.ts +8 -0
- package/dist/esm/utils/token.js +29 -0
- package/dist/esm/utils/token.js.map +1 -0
- package/dist/esm/utils/tokenList.d.ts +13 -0
- package/dist/esm/utils/tokenList.js +106 -0
- package/dist/esm/utils/tokenList.js.map +1 -0
- package/package.json +8 -8
- package/package.json.tmp +7 -7
- package/src/components/AmountInput/AmountInputEndAdornment.tsx +3 -2
- package/src/components/AmountInput/PriceFormHelperText.tsx +3 -2
- package/src/components/BottomSheet/BottomSheet.tsx +2 -2
- package/src/components/BottomSheet/types.ts +1 -0
- package/src/components/ChainSelect/ChainSelect.tsx +112 -40
- package/src/components/ChainSelect/useChainSelect.ts +3 -3
- package/src/components/Chains/AllChainsAvatar.tsx +113 -0
- package/src/components/Chains/ChainList.tsx +3 -0
- package/src/components/Chains/ChainSearchInput.tsx +2 -2
- package/src/components/Chains/SelectChainContent.tsx +1 -0
- package/src/components/Chains/VirtualizedChainList.tsx +80 -12
- package/src/components/RouteCard/RouteCardEssentials.tsx +1 -1
- package/src/components/TokenList/TokenDetailsSheet.tsx +5 -10
- package/src/components/TokenList/TokenDetailsSheetContent.tsx +2 -6
- package/src/components/TokenList/TokenList.tsx +57 -129
- package/src/components/TokenList/TokenListItem.tsx +191 -166
- package/src/components/TokenList/VirtualizedTokenList.tsx +88 -48
- package/src/components/TokenList/types.ts +14 -10
- package/src/components/TokenList/useTokenSelect.ts +3 -4
- package/src/components/TransactionDetails.tsx +2 -2
- package/src/config/version.ts +1 -1
- package/src/hooks/useAccountsBalancesData.ts +101 -0
- package/src/hooks/useFilteredByTokenBalances.ts +101 -0
- package/src/hooks/useListHeight.ts +0 -1
- package/src/hooks/useToken.ts +26 -14
- package/src/hooks/useTokenAddressBalance.ts +14 -20
- package/src/hooks/useTokenBalances.ts +81 -80
- package/src/hooks/useTokenBalancesQueries.ts +94 -0
- package/src/hooks/useTokens.ts +118 -90
- package/src/i18n/bn.json +3 -3
- package/src/i18n/de.json +3 -3
- package/src/i18n/en.json +3 -3
- package/src/i18n/es.json +3 -3
- package/src/i18n/fr.json +3 -3
- package/src/i18n/hi.json +3 -3
- package/src/i18n/id.json +3 -3
- package/src/i18n/it.json +3 -3
- package/src/i18n/ja.json +3 -3
- package/src/i18n/ko.json +3 -3
- package/src/i18n/pl.json +3 -3
- package/src/i18n/pt.json +3 -3
- package/src/i18n/th.json +3 -3
- package/src/i18n/tr.json +3 -3
- package/src/i18n/uk.json +3 -3
- package/src/i18n/vi.json +3 -3
- package/src/i18n/zh.json +3 -3
- package/src/pages/SelectTokenPage/SearchTokenInput.tsx +5 -0
- package/src/pages/SelectTokenPage/SelectTokenPage.tsx +7 -13
- package/src/pages/TransactionPage/TokenValueBottomSheet.tsx +1 -1
- package/src/stores/chains/createChainOrderStore.ts +17 -8
- package/src/stores/chains/types.ts +2 -0
- package/src/stores/chains/useChainOrder.ts +5 -1
- package/src/types/token.ts +11 -2
- package/src/utils/chainType.ts +2 -0
- package/src/utils/token.ts +65 -0
- package/src/utils/tokenList.ts +172 -0
- package/dist/esm/components/TokenList/utils.d.ts +0 -2
- package/dist/esm/components/TokenList/utils.js +0 -35
- package/dist/esm/components/TokenList/utils.js.map +0 -1
- package/src/components/TokenList/utils.ts +0 -42
package/src/i18n/ja.json
CHANGED
|
@@ -212,6 +212,7 @@
|
|
|
212
212
|
"slippage": ""
|
|
213
213
|
},
|
|
214
214
|
"main": {
|
|
215
|
+
"allNetworks": "",
|
|
215
216
|
"allTokens": "すべてのトークン",
|
|
216
217
|
"bridgeStepDetails": "{{from}} から {{to}} を {{tool}} でブリッジ",
|
|
217
218
|
"checkoutStepDetails": "{{tool}} 経由で購入",
|
|
@@ -310,10 +311,9 @@
|
|
|
310
311
|
"tokenOnChainAmount": "",
|
|
311
312
|
"tokenSearch": "",
|
|
312
313
|
"valueLoss": "損失額",
|
|
313
|
-
"searchChain": "",
|
|
314
|
-
"searchChains": "",
|
|
315
314
|
"searchBridges": "",
|
|
316
|
-
"searchExchanges": ""
|
|
315
|
+
"searchExchanges": "",
|
|
316
|
+
"searchNetwork": ""
|
|
317
317
|
},
|
|
318
318
|
"settings": {
|
|
319
319
|
"appearance": "",
|
package/src/i18n/ko.json
CHANGED
|
@@ -212,6 +212,7 @@
|
|
|
212
212
|
"slippage": ""
|
|
213
213
|
},
|
|
214
214
|
"main": {
|
|
215
|
+
"allNetworks": "",
|
|
215
216
|
"allTokens": "",
|
|
216
217
|
"bridgeStepDetails": "",
|
|
217
218
|
"checkoutStepDetails": "",
|
|
@@ -310,10 +311,9 @@
|
|
|
310
311
|
"tokenOnChainAmount": "",
|
|
311
312
|
"tokenSearch": "",
|
|
312
313
|
"valueLoss": "가치 손실",
|
|
313
|
-
"searchChain": "",
|
|
314
|
-
"searchChains": "",
|
|
315
314
|
"searchBridges": "",
|
|
316
|
-
"searchExchanges": ""
|
|
315
|
+
"searchExchanges": "",
|
|
316
|
+
"searchNetwork": ""
|
|
317
317
|
},
|
|
318
318
|
"settings": {
|
|
319
319
|
"appearance": "",
|
package/src/i18n/pl.json
CHANGED
|
@@ -212,6 +212,7 @@
|
|
|
212
212
|
"slippage": ""
|
|
213
213
|
},
|
|
214
214
|
"main": {
|
|
215
|
+
"allNetworks": "",
|
|
215
216
|
"allTokens": "",
|
|
216
217
|
"bridgeStepDetails": "",
|
|
217
218
|
"checkoutStepDetails": "",
|
|
@@ -310,10 +311,9 @@
|
|
|
310
311
|
"tokenOnChainAmount": "",
|
|
311
312
|
"tokenSearch": "",
|
|
312
313
|
"valueLoss": "",
|
|
313
|
-
"searchChain": "",
|
|
314
|
-
"searchChains": "",
|
|
315
314
|
"searchBridges": "",
|
|
316
|
-
"searchExchanges": ""
|
|
315
|
+
"searchExchanges": "",
|
|
316
|
+
"searchNetwork": ""
|
|
317
317
|
},
|
|
318
318
|
"settings": {
|
|
319
319
|
"appearance": "",
|
package/src/i18n/pt.json
CHANGED
|
@@ -212,6 +212,7 @@
|
|
|
212
212
|
"slippage": "A diferença percentual máxima entre o preço esperado, e o preço atual pelo qual a transferência é executada. Esse valor pode ser alterado nas configurações."
|
|
213
213
|
},
|
|
214
214
|
"main": {
|
|
215
|
+
"allNetworks": "",
|
|
215
216
|
"allTokens": "Todos os tokens",
|
|
216
217
|
"bridgeStepDetails": "Ponte de {{from}} para {{to}} via {{tool}}",
|
|
217
218
|
"checkoutStepDetails": "Comprar via {{tool}}",
|
|
@@ -310,10 +311,9 @@
|
|
|
310
311
|
"tokenOnChainAmount": "{{amount, numberExt}} {{tokenSymbol}} na {{chainName}}",
|
|
311
312
|
"tokenSearch": "Pesquisar por token ou endereço",
|
|
312
313
|
"valueLoss": "Perda de Valor",
|
|
313
|
-
"searchChain": "Pesquisar cadeia",
|
|
314
|
-
"searchChains": "Pesquisar pelo nome da rede",
|
|
315
314
|
"searchBridges": "Pesquisar pelo nome da ponte",
|
|
316
|
-
"searchExchanges": "Pesquisar pelo nome da corretora"
|
|
315
|
+
"searchExchanges": "Pesquisar pelo nome da corretora",
|
|
316
|
+
"searchNetwork": ""
|
|
317
317
|
},
|
|
318
318
|
"settings": {
|
|
319
319
|
"appearance": "Aparência",
|
package/src/i18n/th.json
CHANGED
|
@@ -212,6 +212,7 @@
|
|
|
212
212
|
"slippage": ""
|
|
213
213
|
},
|
|
214
214
|
"main": {
|
|
215
|
+
"allNetworks": "",
|
|
215
216
|
"allTokens": "โทเคนทั้งหมด",
|
|
216
217
|
"bridgeStepDetails": "บริดจ์จาก{{from}} ไปยัง {{to}} โดย {{tool}}",
|
|
217
218
|
"checkoutStepDetails": "ซื้อผ่าน {{tool}}",
|
|
@@ -310,10 +311,9 @@
|
|
|
310
311
|
"tokenOnChainAmount": "",
|
|
311
312
|
"tokenSearch": "",
|
|
312
313
|
"valueLoss": "มูลค่าที่สูญเสีย",
|
|
313
|
-
"searchChain": "",
|
|
314
|
-
"searchChains": "",
|
|
315
314
|
"searchBridges": "",
|
|
316
|
-
"searchExchanges": ""
|
|
315
|
+
"searchExchanges": "",
|
|
316
|
+
"searchNetwork": ""
|
|
317
317
|
},
|
|
318
318
|
"settings": {
|
|
319
319
|
"appearance": "",
|
package/src/i18n/tr.json
CHANGED
|
@@ -212,6 +212,7 @@
|
|
|
212
212
|
"slippage": "Beklenen fiyat ile transferin gerçekleştirildiği gerçek fiyat arasındaki maksimum yüzde fark. Bu değer ayarlardan değiştirilebilir."
|
|
213
213
|
},
|
|
214
214
|
"main": {
|
|
215
|
+
"allNetworks": "",
|
|
215
216
|
"allTokens": "Tüm varlıklar",
|
|
216
217
|
"bridgeStepDetails": "{{tool}} aracılığıyla {{from}} ağından {{to}} ağına köprüle",
|
|
217
218
|
"checkoutStepDetails": "{{tool}} aracılığıyla alım yap",
|
|
@@ -310,10 +311,9 @@
|
|
|
310
311
|
"tokenOnChainAmount": "",
|
|
311
312
|
"tokenSearch": "",
|
|
312
313
|
"valueLoss": "Değer kaybı",
|
|
313
|
-
"searchChain": "",
|
|
314
|
-
"searchChains": "Zincir adına göre ara",
|
|
315
314
|
"searchBridges": "Köprü adına göre ara",
|
|
316
|
-
"searchExchanges": "Borsa adına göre ara"
|
|
315
|
+
"searchExchanges": "Borsa adına göre ara",
|
|
316
|
+
"searchNetwork": ""
|
|
317
317
|
},
|
|
318
318
|
"settings": {
|
|
319
319
|
"appearance": "",
|
package/src/i18n/uk.json
CHANGED
|
@@ -212,6 +212,7 @@
|
|
|
212
212
|
"slippage": "Максимальна процентна різниця між очікуваною ціною і фактичною ціною з якою виконується трансфер. Ця величина може бути змінена в налаштуваннях."
|
|
213
213
|
},
|
|
214
214
|
"main": {
|
|
215
|
+
"allNetworks": "",
|
|
215
216
|
"allTokens": "Всі токени",
|
|
216
217
|
"bridgeStepDetails": "Бридж з {{from}} до {{to}} через {{tool}}",
|
|
217
218
|
"checkoutStepDetails": "Купівля через {{tool}}",
|
|
@@ -310,10 +311,9 @@
|
|
|
310
311
|
"tokenOnChainAmount": "{{amount, numberExt}} {{tokenSymbol}} на {{chainName}}",
|
|
311
312
|
"tokenSearch": "Шукати за ім'ям або адресою",
|
|
312
313
|
"valueLoss": "Втрата вартості",
|
|
313
|
-
"searchChain": "Шукати чейн",
|
|
314
|
-
"searchChains": "Пошук за назвою чейна",
|
|
315
314
|
"searchBridges": "Пошук за назвою моста",
|
|
316
|
-
"searchExchanges": "Пошук за назвою обмінника"
|
|
315
|
+
"searchExchanges": "Пошук за назвою обмінника",
|
|
316
|
+
"searchNetwork": ""
|
|
317
317
|
},
|
|
318
318
|
"settings": {
|
|
319
319
|
"appearance": "Вигляд",
|
package/src/i18n/vi.json
CHANGED
|
@@ -212,6 +212,7 @@
|
|
|
212
212
|
"slippage": ""
|
|
213
213
|
},
|
|
214
214
|
"main": {
|
|
215
|
+
"allNetworks": "",
|
|
215
216
|
"allTokens": "Tất cả mã thông báo",
|
|
216
217
|
"bridgeStepDetails": "Chuyển từ {{from}} đến {{to}} thông qua {{tool}}",
|
|
217
218
|
"checkoutStepDetails": "Thanh toán thông qua {{tool}}",
|
|
@@ -310,10 +311,9 @@
|
|
|
310
311
|
"tokenOnChainAmount": "",
|
|
311
312
|
"tokenSearch": "",
|
|
312
313
|
"valueLoss": "Bạn sẽ mất",
|
|
313
|
-
"searchChain": "",
|
|
314
|
-
"searchChains": "",
|
|
315
314
|
"searchBridges": "",
|
|
316
|
-
"searchExchanges": ""
|
|
315
|
+
"searchExchanges": "",
|
|
316
|
+
"searchNetwork": ""
|
|
317
317
|
},
|
|
318
318
|
"settings": {
|
|
319
319
|
"appearance": "",
|
package/src/i18n/zh.json
CHANGED
|
@@ -212,6 +212,7 @@
|
|
|
212
212
|
"slippage": "真实的成交价位与预设的成交价位间相差的最大百分比。该值可以在设置中更改。"
|
|
213
213
|
},
|
|
214
214
|
"main": {
|
|
215
|
+
"allNetworks": "",
|
|
215
216
|
"allTokens": "所有代币",
|
|
216
217
|
"bridgeStepDetails": "通过 {{tool}} 把资产从 {{from}} 链跨到 {{to}} 链上",
|
|
217
218
|
"checkoutStepDetails": "通过 {{tool}} 购买",
|
|
@@ -310,10 +311,9 @@
|
|
|
310
311
|
"tokenOnChainAmount": "",
|
|
311
312
|
"tokenSearch": "",
|
|
312
313
|
"valueLoss": "资金损失",
|
|
313
|
-
"searchChain": "",
|
|
314
|
-
"searchChains": "搜索链",
|
|
315
314
|
"searchBridges": "搜索跨链桥",
|
|
316
|
-
"searchExchanges": "搜索交易所"
|
|
315
|
+
"searchExchanges": "搜索交易所",
|
|
316
|
+
"searchNetwork": ""
|
|
317
317
|
},
|
|
318
318
|
"settings": {
|
|
319
319
|
"appearance": "",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { useCallback, useEffect } from 'react'
|
|
2
2
|
import { useTranslation } from 'react-i18next'
|
|
3
3
|
import { SearchInput } from '../../components/Search/SearchInput.js'
|
|
4
|
+
import { useChainOrderStore } from '../../stores/chains/ChainOrderStore.js'
|
|
4
5
|
import { useFieldActions } from '../../stores/form/useFieldActions.js'
|
|
5
6
|
import { useFieldValues } from '../../stores/form/useFieldValues.js'
|
|
6
7
|
|
|
@@ -8,6 +9,8 @@ export const SearchTokenInput = () => {
|
|
|
8
9
|
const { t } = useTranslation()
|
|
9
10
|
const [value] = useFieldValues('tokenSearchFilter')
|
|
10
11
|
const { setFieldValue, setAsTouched } = useFieldActions()
|
|
12
|
+
const [fromChain, toChain] = useFieldValues('fromChain', 'toChain')
|
|
13
|
+
const isAllNetworks = useChainOrderStore((state) => state.isAllNetworks)
|
|
11
14
|
|
|
12
15
|
const onChange = useCallback(
|
|
13
16
|
(newValue: string | number | undefined) => {
|
|
@@ -32,6 +35,8 @@ export const SearchTokenInput = () => {
|
|
|
32
35
|
|
|
33
36
|
return (
|
|
34
37
|
<SearchInput
|
|
38
|
+
// Reset the search input when a chain or the "All Networks" is changed
|
|
39
|
+
key={`${fromChain}-${toChain}-${isAllNetworks}`}
|
|
35
40
|
name="tokenSearchFilter"
|
|
36
41
|
placeholder={t('main.tokenSearch')}
|
|
37
42
|
onChange={(e) => onChange((e.target as HTMLInputElement).value)}
|
|
@@ -92,22 +92,16 @@ type WrappedTokenListProps = {
|
|
|
92
92
|
const WrappedTokenList = ({ headerRef, formType }: WrappedTokenListProps) => {
|
|
93
93
|
const { navigateBack } = useNavigateBack()
|
|
94
94
|
const listParentRef = useRef<HTMLUListElement | null>(null)
|
|
95
|
-
const { listHeight
|
|
95
|
+
const { listHeight } = useListHeight({
|
|
96
96
|
listParentRef,
|
|
97
97
|
headerRef,
|
|
98
98
|
})
|
|
99
99
|
return (
|
|
100
|
-
<
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
parentRef={listParentRef}
|
|
107
|
-
height={listHeight}
|
|
108
|
-
onClick={navigateBack}
|
|
109
|
-
formType={formType}
|
|
110
|
-
/>
|
|
111
|
-
</Box>
|
|
100
|
+
<TokenList
|
|
101
|
+
parentRef={listParentRef}
|
|
102
|
+
height={listHeight}
|
|
103
|
+
onClick={navigateBack}
|
|
104
|
+
formType={formType}
|
|
105
|
+
/>
|
|
112
106
|
)
|
|
113
107
|
}
|
|
@@ -113,7 +113,7 @@ const TokenValueBottomSheetContent: React.FC<TokenValueBottomSheetProps> = ({
|
|
|
113
113
|
fontWeight: 600,
|
|
114
114
|
}}
|
|
115
115
|
>
|
|
116
|
-
{hasRelayerSupport
|
|
116
|
+
{hasRelayerSupport || !gasCostUSD
|
|
117
117
|
? t('main.fees.free')
|
|
118
118
|
: t('format.currency', { value: gasCostUSD })}
|
|
119
119
|
</Typography>
|
|
@@ -4,8 +4,13 @@ import { createWithEqualityFn } from 'zustand/traditional'
|
|
|
4
4
|
import type { PersistStoreProps } from '../types.js'
|
|
5
5
|
import type { ChainOrderState } from './types.js'
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
export const
|
|
7
|
+
// (10 tiles: 9 + 1 for "All chains")
|
|
8
|
+
export const maxGridItemsToShow = 10
|
|
9
|
+
export const maxChainsToShow = maxGridItemsToShow - 1
|
|
10
|
+
// If there are more than maxChainsToShow chains to show,
|
|
11
|
+
// -1 tile to show a button "+ N" more chains
|
|
12
|
+
export const maxChainsToOrder = maxChainsToShow - 1
|
|
13
|
+
|
|
9
14
|
const defaultChainState = {
|
|
10
15
|
from: [],
|
|
11
16
|
to: [],
|
|
@@ -16,6 +21,7 @@ export const createChainOrderStore = ({ namePrefix }: PersistStoreProps) =>
|
|
|
16
21
|
persist(
|
|
17
22
|
(set, get) => ({
|
|
18
23
|
chainOrder: defaultChainState,
|
|
24
|
+
isAllNetworks: true,
|
|
19
25
|
availableChains: defaultChainState,
|
|
20
26
|
pinnedChains: [],
|
|
21
27
|
initializeChains: (chainIds, type) => {
|
|
@@ -53,7 +59,7 @@ export const createChainOrderStore = ({ namePrefix }: PersistStoreProps) =>
|
|
|
53
59
|
},
|
|
54
60
|
}
|
|
55
61
|
})
|
|
56
|
-
return get().chainOrder[type]
|
|
62
|
+
return get().chainOrder[type].slice(0, maxChainsToOrder)
|
|
57
63
|
},
|
|
58
64
|
setChain: (chainId, type) => {
|
|
59
65
|
const state = get()
|
|
@@ -64,11 +70,10 @@ export const createChainOrderStore = ({ namePrefix }: PersistStoreProps) =>
|
|
|
64
70
|
return
|
|
65
71
|
}
|
|
66
72
|
set((state: ChainOrderState) => {
|
|
67
|
-
const chainOrder = state.chainOrder[type].slice(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
}
|
|
73
|
+
const chainOrder = [chainId, ...state.chainOrder[type]].slice(
|
|
74
|
+
0,
|
|
75
|
+
maxChainsToOrder
|
|
76
|
+
)
|
|
72
77
|
return {
|
|
73
78
|
chainOrder: {
|
|
74
79
|
...state.chainOrder,
|
|
@@ -77,6 +82,9 @@ export const createChainOrderStore = ({ namePrefix }: PersistStoreProps) =>
|
|
|
77
82
|
}
|
|
78
83
|
})
|
|
79
84
|
},
|
|
85
|
+
setIsAllNetworks: (isAllNetworks) => {
|
|
86
|
+
set({ isAllNetworks })
|
|
87
|
+
},
|
|
80
88
|
setPinnedChain: (chainId) => {
|
|
81
89
|
set((state: ChainOrderState) => {
|
|
82
90
|
const pinnedChains = [...state.pinnedChains]
|
|
@@ -97,6 +105,7 @@ export const createChainOrderStore = ({ namePrefix }: PersistStoreProps) =>
|
|
|
97
105
|
version: 2,
|
|
98
106
|
partialize: (state) => ({
|
|
99
107
|
chainOrder: state.chainOrder,
|
|
108
|
+
isAllNetworks: state.isAllNetworks,
|
|
100
109
|
pinnedChains: state.pinnedChains,
|
|
101
110
|
}),
|
|
102
111
|
}
|
|
@@ -9,11 +9,13 @@ export interface ChainOrderProps {
|
|
|
9
9
|
from: number[]
|
|
10
10
|
to: number[]
|
|
11
11
|
}
|
|
12
|
+
isAllNetworks: boolean
|
|
12
13
|
pinnedChains: number[]
|
|
13
14
|
}
|
|
14
15
|
|
|
15
16
|
export interface ChainOrderState extends ChainOrderProps {
|
|
16
17
|
initializeChains(chainIds: number[], type: FormType): number[]
|
|
17
18
|
setChain(chainId: number, type: FormType): void
|
|
19
|
+
setIsAllNetworks(isAllNetworks: boolean): void
|
|
18
20
|
setPinnedChain(chainId: number): void
|
|
19
21
|
}
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import type { FormType } from '../form/types.js'
|
|
2
2
|
import { useChainOrderStore } from './ChainOrderStore.js'
|
|
3
|
+
import { maxChainsToOrder } from './createChainOrderStore.js'
|
|
3
4
|
|
|
4
5
|
export const useChainOrder = (
|
|
5
6
|
type: FormType
|
|
6
7
|
): [number[], (chainId: number, type: FormType) => void] => {
|
|
7
|
-
return useChainOrderStore((state) => [
|
|
8
|
+
return useChainOrderStore((state) => [
|
|
9
|
+
state.chainOrder[type].slice(0, maxChainsToOrder),
|
|
10
|
+
state.setChain,
|
|
11
|
+
])
|
|
8
12
|
}
|
package/src/types/token.ts
CHANGED
|
@@ -1,6 +1,15 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
TokenAmount as SDKTokenAmount,
|
|
3
|
+
TokenAmountExtended as SDKTokenAmountExtended,
|
|
4
|
+
} from '@lifi/sdk'
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
interface TokenFlags {
|
|
4
7
|
featured?: boolean
|
|
5
8
|
popular?: boolean
|
|
6
9
|
}
|
|
10
|
+
|
|
11
|
+
export interface TokenAmount extends SDKTokenAmount, TokenFlags {}
|
|
12
|
+
|
|
13
|
+
export interface TokenAmountExtended
|
|
14
|
+
extends SDKTokenAmountExtended,
|
|
15
|
+
TokenFlags {}
|
package/src/utils/chainType.ts
CHANGED
|
@@ -8,6 +8,7 @@ const chainTypeAddressValidation = {
|
|
|
8
8
|
[ChainType.SVM]: isSVMAddress,
|
|
9
9
|
[ChainType.MVM]: isValidSuiAddress,
|
|
10
10
|
[ChainType.UTXO]: isUTXOAddress,
|
|
11
|
+
[ChainType.TVM]: () => false,
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export const getChainTypeFromAddress = (
|
|
@@ -27,4 +28,5 @@ export const defaultChainIdsByType = {
|
|
|
27
28
|
[ChainType.SVM]: ChainId.SOL,
|
|
28
29
|
[ChainType.UTXO]: ChainId.BTC,
|
|
29
30
|
[ChainType.MVM]: ChainId.SUI,
|
|
31
|
+
[ChainType.TVM]: ChainId.TRN,
|
|
30
32
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { BaseToken, TokenExtended } from '@lifi/sdk'
|
|
2
|
+
import type { FormType } from '../stores/form/types.js'
|
|
3
|
+
import type { WidgetChains, WidgetTokens } from '../types/widget.js'
|
|
4
|
+
import {
|
|
5
|
+
getConfigItemSets,
|
|
6
|
+
isFormItemAllowed,
|
|
7
|
+
isItemAllowedForSets,
|
|
8
|
+
} from './item.js'
|
|
9
|
+
|
|
10
|
+
export const filterAllowedTokens = (
|
|
11
|
+
dataTokens: { [chainId: number]: TokenExtended[] } | undefined,
|
|
12
|
+
configTokens?: WidgetTokens,
|
|
13
|
+
chainsConfig?: WidgetChains,
|
|
14
|
+
formType?: FormType
|
|
15
|
+
): { [chainId: number]: TokenExtended[] } | undefined => {
|
|
16
|
+
if (!dataTokens) {
|
|
17
|
+
return
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const includedTokens = configTokens?.include || []
|
|
21
|
+
const allChainIds = Array.from(
|
|
22
|
+
new Set([
|
|
23
|
+
...includedTokens.map((t) => t.chainId),
|
|
24
|
+
...Object.keys(dataTokens),
|
|
25
|
+
])
|
|
26
|
+
).map((chainId) => Number(chainId))
|
|
27
|
+
|
|
28
|
+
const configChainIdsSet = getConfigItemSets(
|
|
29
|
+
chainsConfig,
|
|
30
|
+
(chainIds: number[]) => new Set(chainIds),
|
|
31
|
+
formType
|
|
32
|
+
)
|
|
33
|
+
const allowedChainIds = configChainIdsSet
|
|
34
|
+
? allChainIds.filter((chainId) =>
|
|
35
|
+
isItemAllowedForSets(chainId, configChainIdsSet)
|
|
36
|
+
)
|
|
37
|
+
: allChainIds
|
|
38
|
+
|
|
39
|
+
const allowedTokensByChain: { [chainId: number]: TokenExtended[] } = {}
|
|
40
|
+
for (const chainId of allowedChainIds) {
|
|
41
|
+
const chainTokens = [
|
|
42
|
+
...dataTokens[chainId],
|
|
43
|
+
...includedTokens.filter((t) => Number(t.chainId) === chainId),
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
const allowedAddresses = getConfigItemSets(
|
|
47
|
+
configTokens,
|
|
48
|
+
(tokens: BaseToken[]) =>
|
|
49
|
+
new Set(
|
|
50
|
+
tokens
|
|
51
|
+
.filter((t) => Number(t.chainId) === chainId)
|
|
52
|
+
.map((t) => t.address)
|
|
53
|
+
),
|
|
54
|
+
formType
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
const filtered = chainTokens.filter((token) =>
|
|
58
|
+
isFormItemAllowed(token, allowedAddresses, formType, (t) => t.address)
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
allowedTokensByChain[chainId] = filtered
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return allowedTokensByChain
|
|
65
|
+
}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import type { TokenExtended, WalletTokenExtended } from '@lifi/sdk'
|
|
2
|
+
import { formatUnits } from 'viem'
|
|
3
|
+
import type { TokenAmount, TokenAmountExtended } from '../types/token.js'
|
|
4
|
+
import type { WidgetTokens } from '../types/widget.js'
|
|
5
|
+
|
|
6
|
+
const sortByBalances = (a: TokenAmount, b: TokenAmount) =>
|
|
7
|
+
Number.parseFloat(formatUnits(b.amount ?? 0n, b.decimals)) *
|
|
8
|
+
Number.parseFloat(b.priceUSD ?? '0') -
|
|
9
|
+
Number.parseFloat(formatUnits(a.amount ?? 0n, a.decimals)) *
|
|
10
|
+
Number.parseFloat(a.priceUSD ?? '0')
|
|
11
|
+
|
|
12
|
+
const sortByVolume = (a: TokenExtended, b: TokenExtended) =>
|
|
13
|
+
(b.volumeUSD24H ?? 0) - (a.volumeUSD24H ?? 0)
|
|
14
|
+
|
|
15
|
+
export const processTokenBalances = (
|
|
16
|
+
isBalanceLoading: boolean,
|
|
17
|
+
isAllNetworks: boolean,
|
|
18
|
+
configTokens?: WidgetTokens,
|
|
19
|
+
selectedChainId?: number,
|
|
20
|
+
tokens?: TokenExtended[],
|
|
21
|
+
tokensWithBalances?: TokenAmount[]
|
|
22
|
+
) => {
|
|
23
|
+
if (isBalanceLoading) {
|
|
24
|
+
if (isAllNetworks) {
|
|
25
|
+
const sortedTokens = [...(tokens ?? [])].sort(sortByVolume)
|
|
26
|
+
return {
|
|
27
|
+
processedTokens: sortedTokens,
|
|
28
|
+
withCategories: false,
|
|
29
|
+
}
|
|
30
|
+
} else {
|
|
31
|
+
return processedTypedTokens(
|
|
32
|
+
tokens ?? [],
|
|
33
|
+
[],
|
|
34
|
+
selectedChainId,
|
|
35
|
+
configTokens
|
|
36
|
+
)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const sortedTokensWithBalances = [...(tokensWithBalances ?? [])].sort(
|
|
41
|
+
sortByBalances
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
const tokensWithBalancesSet = new Set(
|
|
45
|
+
sortedTokensWithBalances.map(
|
|
46
|
+
(token) => `${token.chainId}-${token.address.toLowerCase()}`
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
const tokensWithoutBalances =
|
|
50
|
+
tokens
|
|
51
|
+
?.filter((token) => {
|
|
52
|
+
const tokenKey = `${token.chainId}-${token.address.toLowerCase()}`
|
|
53
|
+
return !tokensWithBalancesSet.has(tokenKey)
|
|
54
|
+
})
|
|
55
|
+
.sort(sortByVolume) ?? []
|
|
56
|
+
|
|
57
|
+
if (isAllNetworks) {
|
|
58
|
+
return {
|
|
59
|
+
processedTokens: [...sortedTokensWithBalances, ...tokensWithoutBalances],
|
|
60
|
+
withCategories: false,
|
|
61
|
+
}
|
|
62
|
+
} else {
|
|
63
|
+
return processedTypedTokens(
|
|
64
|
+
tokensWithoutBalances,
|
|
65
|
+
sortedTokensWithBalances,
|
|
66
|
+
selectedChainId,
|
|
67
|
+
configTokens
|
|
68
|
+
)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// NB: only for non-all-networks
|
|
73
|
+
export const processedTypedTokens = (
|
|
74
|
+
tokens: TokenAmount[],
|
|
75
|
+
tokensWithBalances: TokenAmount[],
|
|
76
|
+
selectedChainId?: number,
|
|
77
|
+
configTokens?: WidgetTokens
|
|
78
|
+
) => {
|
|
79
|
+
const filteredTokensMap = new Map(
|
|
80
|
+
tokens.map((token) => [token.address, token])
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
const featuredTokensFromConfig: TokenAmount[] = []
|
|
84
|
+
const popularTokensFromConfig: TokenAmount[] = []
|
|
85
|
+
|
|
86
|
+
;(['popular', 'featured'] as const).forEach((tokenType) => {
|
|
87
|
+
const typedTokens = configTokens?.[tokenType]?.filter(
|
|
88
|
+
(token) => token.chainId === selectedChainId
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
typedTokens?.forEach((token) => {
|
|
92
|
+
const tokenAmount = { ...token } as TokenAmount
|
|
93
|
+
tokenAmount[tokenType] = true
|
|
94
|
+
|
|
95
|
+
const match = filteredTokensMap.get(token.address)
|
|
96
|
+
if (match?.priceUSD) {
|
|
97
|
+
tokenAmount.priceUSD = match.priceUSD
|
|
98
|
+
}
|
|
99
|
+
if (!token.logoURI && match?.logoURI) {
|
|
100
|
+
tokenAmount.logoURI = match.logoURI
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (tokenType === 'popular') {
|
|
104
|
+
popularTokensFromConfig.push(tokenAmount)
|
|
105
|
+
} else {
|
|
106
|
+
featuredTokensFromConfig.push(tokenAmount)
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
// Filter out config-added tokens from main list
|
|
112
|
+
const configTokenAddresses = new Set(
|
|
113
|
+
[...popularTokensFromConfig, ...featuredTokensFromConfig].map(
|
|
114
|
+
(t) => t.address
|
|
115
|
+
)
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
const remainingTokens = tokens.filter(
|
|
119
|
+
(token) => !configTokenAddresses.has(token.address)
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
const otherTokens: TokenAmount[] = []
|
|
123
|
+
|
|
124
|
+
for (const token of remainingTokens) {
|
|
125
|
+
if (token.featured) {
|
|
126
|
+
featuredTokensFromConfig.push(token)
|
|
127
|
+
} else if (token.popular) {
|
|
128
|
+
popularTokensFromConfig.push(token)
|
|
129
|
+
} else {
|
|
130
|
+
otherTokens.push(token)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const sortedFeaturedTokens = [...featuredTokensFromConfig].sort(sortByVolume)
|
|
135
|
+
const sortedPopularTokens = [...popularTokensFromConfig].sort(sortByVolume)
|
|
136
|
+
const sortedOtherTokens = [...otherTokens].sort(sortByVolume)
|
|
137
|
+
|
|
138
|
+
return {
|
|
139
|
+
processedTokens: [
|
|
140
|
+
...sortedFeaturedTokens,
|
|
141
|
+
...tokensWithBalances,
|
|
142
|
+
...sortedPopularTokens,
|
|
143
|
+
...sortedOtherTokens,
|
|
144
|
+
],
|
|
145
|
+
withCategories: Boolean(
|
|
146
|
+
featuredTokensFromConfig?.length || popularTokensFromConfig?.length
|
|
147
|
+
),
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export const isSearchMatch = (
|
|
152
|
+
token: TokenExtended | TokenAmountExtended,
|
|
153
|
+
search?: string
|
|
154
|
+
) => {
|
|
155
|
+
if (!search) {
|
|
156
|
+
return true
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const searchLowerCase = search.toLowerCase()
|
|
160
|
+
return (
|
|
161
|
+
token.name?.toLowerCase().includes(searchLowerCase) ||
|
|
162
|
+
token.symbol
|
|
163
|
+
?.replaceAll('₮', 'T')
|
|
164
|
+
.toLowerCase()
|
|
165
|
+
.includes(searchLowerCase) ||
|
|
166
|
+
token.address?.toLowerCase().includes(searchLowerCase)
|
|
167
|
+
)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export const isSupportedToken = (token: WalletTokenExtended) => {
|
|
171
|
+
return token.name && token.symbol && token.priceUSD && token.chainId
|
|
172
|
+
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
export const filteredTokensComparator = (searchFilter) => {
|
|
2
|
-
const isExactMatch = (token) => {
|
|
3
|
-
return (token.name?.toUpperCase() === searchFilter ||
|
|
4
|
-
token.symbol.toUpperCase() === searchFilter ||
|
|
5
|
-
token.address.toUpperCase() === searchFilter);
|
|
6
|
-
};
|
|
7
|
-
return (tokenA, tokenB) => {
|
|
8
|
-
const isExactMatchA = isExactMatch(tokenA);
|
|
9
|
-
const isExactMatchB = isExactMatch(tokenB);
|
|
10
|
-
// Exact match with logo
|
|
11
|
-
if (isExactMatchB && tokenB.logoURI) {
|
|
12
|
-
return 1;
|
|
13
|
-
}
|
|
14
|
-
if (isExactMatchA && tokenA.logoURI) {
|
|
15
|
-
return -1;
|
|
16
|
-
}
|
|
17
|
-
// Any token with a logo (exact match or not)
|
|
18
|
-
if (tokenB.logoURI && !tokenA.logoURI) {
|
|
19
|
-
return 1;
|
|
20
|
-
}
|
|
21
|
-
if (tokenA.logoURI && !tokenB.logoURI) {
|
|
22
|
-
return -1;
|
|
23
|
-
}
|
|
24
|
-
// Exact match without logo
|
|
25
|
-
if (isExactMatchB && !tokenB.logoURI) {
|
|
26
|
-
return 1;
|
|
27
|
-
}
|
|
28
|
-
if (isExactMatchA && !tokenA.logoURI) {
|
|
29
|
-
return -1;
|
|
30
|
-
}
|
|
31
|
-
// All other tokens are considered equal in sorting priority
|
|
32
|
-
return 0;
|
|
33
|
-
};
|
|
34
|
-
};
|
|
35
|
-
//# sourceMappingURL=utils.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/components/TokenList/utils.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,YAAoB,EAAE,EAAE;IAC/D,MAAM,YAAY,GAAG,CAAC,KAAkB,EAAE,EAAE;QAC1C,OAAO,CACL,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,YAAY;YAC1C,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,YAAY;YAC3C,KAAK,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,YAAY,CAC7C,CAAA;IACH,CAAC,CAAA;IACD,OAAO,CAAC,MAAmB,EAAE,MAAmB,EAAE,EAAE;QAClD,MAAM,aAAa,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;QAC1C,MAAM,aAAa,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;QAE1C,wBAAwB;QACxB,IAAI,aAAa,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,OAAO,CAAC,CAAA;QACV,CAAC;QACD,IAAI,aAAa,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACpC,OAAO,CAAC,CAAC,CAAA;QACX,CAAC;QAED,6CAA6C;QAC7C,IAAI,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACtC,OAAO,CAAC,CAAA;QACV,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACtC,OAAO,CAAC,CAAC,CAAA;QACX,CAAC;QAED,2BAA2B;QAC3B,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACrC,OAAO,CAAC,CAAA;QACV,CAAC;QACD,IAAI,aAAa,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACrC,OAAO,CAAC,CAAC,CAAA;QACX,CAAC;QAED,4DAA4D;QAC5D,OAAO,CAAC,CAAA;IACV,CAAC,CAAA;AACH,CAAC,CAAA"}
|