@lifi/widget 4.4.0 → 4.6.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/dist/esm/App.js.map +1 -1
- package/dist/esm/AppDrawer.js +2 -1
- package/dist/esm/AppDrawer.js.map +1 -1
- package/dist/esm/AppLayout.js.map +1 -1
- package/dist/esm/AppProvider.js.map +1 -1
- package/dist/esm/components/ActionRow/ActionRow.js.map +1 -1
- package/dist/esm/components/AmountInput/AmountInput.js +13 -7
- package/dist/esm/components/AmountInput/AmountInput.js.map +1 -1
- package/dist/esm/components/AmountInput/AmountInputEndAdornment.js +2 -13
- package/dist/esm/components/AmountInput/AmountInputEndAdornment.js.map +1 -1
- package/dist/esm/components/AmountInput/PriceFormHelperText.js.map +1 -1
- package/dist/esm/components/AmountInputCard/AmountInputCardPair.js.map +1 -1
- package/dist/esm/components/AmountInputCard/BalanceDisplay.js.map +1 -1
- package/dist/esm/components/AmountInputCard/FiatValueToggle.js.map +1 -1
- package/dist/esm/components/AmountInputCard/PercentageChips.js +2 -13
- package/dist/esm/components/AmountInputCard/PercentageChips.js.map +1 -1
- package/dist/esm/components/AmountInputCard/PercentageChips.style.js +1 -1
- package/dist/esm/components/AmountInputCard/PercentageChips.style.js.map +1 -1
- package/dist/esm/components/AmountInputCard/ReceiveAmountCard.js.map +1 -1
- package/dist/esm/components/AmountInputCard/SendAmountCard.js +13 -6
- package/dist/esm/components/AmountInputCard/SendAmountCard.js.map +1 -1
- package/dist/esm/components/AppContainer.js.map +1 -1
- package/dist/esm/components/Avatar/AccountAvatar.js.map +1 -1
- package/dist/esm/components/Avatar/Avatar.js.map +1 -1
- package/dist/esm/components/Avatar/ChainBadgeContent.js.map +1 -1
- package/dist/esm/components/Avatar/TokenAvatar.js.map +1 -1
- package/dist/esm/components/BaseTransactionButton/BaseTransactionButton.js.map +1 -1
- package/dist/esm/components/Card/CardButton.js.map +1 -1
- package/dist/esm/components/ChainSelect/ChainSelect.js.map +1 -1
- package/dist/esm/components/Chains/AllChainsAvatar.js +7 -1
- package/dist/esm/components/Chains/AllChainsAvatar.js.map +1 -1
- package/dist/esm/components/Chains/ChainList.js.map +1 -1
- package/dist/esm/components/Chains/ChainListItem.js.map +1 -1
- package/dist/esm/components/Chains/ChainsExpanded.js.map +1 -1
- package/dist/esm/components/Chains/PinChainButton.js.map +1 -1
- package/dist/esm/components/Chains/SelectChainExpansionContent.js.map +1 -1
- package/dist/esm/components/Chains/SelectChainPageContent.js.map +1 -1
- package/dist/esm/components/Chains/VirtualizedChainList.js.map +1 -1
- package/dist/esm/components/ContextMenu.js.map +1 -1
- package/dist/esm/components/ContractComponent/NFT/NFTBase.js.map +1 -1
- package/dist/esm/components/Dialog/Dialog.js +2 -1
- package/dist/esm/components/Dialog/Dialog.js.map +1 -1
- package/dist/esm/components/ExecutionStatusCard/ExecutionChecklist.js.map +1 -1
- package/dist/esm/components/ExecutionStatusCard/ExecutionStatusCard.js.map +1 -1
- package/dist/esm/components/ExecutionStatusCard/StaggeredRevealTypography.js.map +1 -1
- package/dist/esm/components/ExecutionStatusCard/StatusIcon.js.map +1 -1
- package/dist/esm/components/Expansion/Expansion.js +4 -3
- package/dist/esm/components/Expansion/Expansion.js.map +1 -1
- package/dist/esm/components/Expansion/ExpansionTransition.js.map +1 -1
- package/dist/esm/components/FeeBreakdownTooltip.js.map +1 -1
- package/dist/esm/components/Header/ActivitiesButton.js.map +1 -1
- package/dist/esm/components/Header/BackButton.js.map +1 -1
- package/dist/esm/components/Header/CloseDrawerButton.js.map +1 -1
- package/dist/esm/components/Header/DisconnectIconButton.js.map +1 -1
- package/dist/esm/components/Header/HeaderTabs.js.map +1 -1
- package/dist/esm/components/Header/NavigationHeader.js.map +1 -1
- package/dist/esm/components/Header/SettingsButton.js +2 -1
- package/dist/esm/components/Header/SettingsButton.js.map +1 -1
- package/dist/esm/components/Header/WalletHeader.js.map +1 -1
- package/dist/esm/components/Header/WalletMenu.js.map +1 -1
- package/dist/esm/components/IconCircle/IconCircle.js +2 -1
- package/dist/esm/components/IconCircle/IconCircle.js.map +1 -1
- package/dist/esm/components/LimitOrderSettings/LimitOrderSettings.js.map +1 -1
- package/dist/esm/components/LimitPriceCard/LimitPriceCard.js.map +1 -1
- package/dist/esm/components/LimitPriceCard/LimitPricePresets.js.map +1 -1
- package/dist/esm/components/Messages/AccountDeployedMessage.js.map +1 -1
- package/dist/esm/components/Messages/AccountNotDeployedMessage.js.map +1 -1
- package/dist/esm/components/Messages/AlertMessage.js.map +1 -1
- package/dist/esm/components/Messages/FundsSufficiencyMessage.js.map +1 -1
- package/dist/esm/components/Messages/GasRefuelMessage.js.map +1 -1
- package/dist/esm/components/Messages/GasSufficiencyMessage.js.map +1 -1
- package/dist/esm/components/Messages/MinFromAmountUSDMessage.js.map +1 -1
- package/dist/esm/components/Messages/MissingRouteRequiredAccountMessage.js.map +1 -1
- package/dist/esm/components/Messages/UnsupportedToAddressMessage.js +27 -0
- package/dist/esm/components/Messages/UnsupportedToAddressMessage.js.map +1 -0
- package/dist/esm/components/Messages/WarningMessages.d.ts.map +1 -1
- package/dist/esm/components/Messages/WarningMessages.js +2 -0
- package/dist/esm/components/Messages/WarningMessages.js.map +1 -1
- package/dist/esm/components/Messages/useMessageQueue.js +6 -1
- package/dist/esm/components/Messages/useMessageQueue.js.map +1 -1
- package/dist/esm/components/NotFound.js.map +1 -1
- package/dist/esm/components/PoweredBy/PoweredBy.js.map +1 -1
- package/dist/esm/components/ProgressToNextUpdate.js.map +1 -1
- package/dist/esm/components/ReverseTokensButton/ReverseTokensButton.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteCard.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteCardEssentials.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteCardSkeleton.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteDetails.js +2 -1
- package/dist/esm/components/RouteCard/RouteDetails.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteNotFoundCard.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteProviderCard.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteToken.js.map +1 -1
- package/dist/esm/components/RouteCard/RouteTokens.js.map +1 -1
- package/dist/esm/components/Routes/LimitOrderRoutes.js +2 -2
- package/dist/esm/components/Routes/LimitOrderRoutes.js.map +1 -1
- package/dist/esm/components/Routes/Routes.js.map +1 -1
- package/dist/esm/components/Routes/RoutesContent.js +2 -2
- package/dist/esm/components/Routes/RoutesContent.js.map +1 -1
- package/dist/esm/components/Routes/RoutesExpanded.js.map +1 -1
- package/dist/esm/components/Search/SearchInput.js.map +1 -1
- package/dist/esm/components/SelectChainAndToken.js.map +1 -1
- package/dist/esm/components/SelectTokenButton/SelectTokenButton.js.map +1 -1
- package/dist/esm/components/SendToWallet/SendToWalletButton.js.map +1 -1
- package/dist/esm/components/SendToWallet/SendToWalletExpandButton.js +2 -2
- package/dist/esm/components/SendToWallet/SendToWalletExpandButton.js.map +1 -1
- package/dist/esm/components/SettingsPanel/SettingsPanel.js.map +1 -1
- package/dist/esm/components/Skeleton/WidgetSkeleton.js +2 -1
- package/dist/esm/components/Skeleton/WidgetSkeleton.js.map +1 -1
- package/dist/esm/components/Step/StepActions.js +18 -16
- package/dist/esm/components/Step/StepActions.js.map +1 -1
- package/dist/esm/components/StepActions/SentToWalletRow.js.map +1 -1
- package/dist/esm/components/StepActions/StepActionRow.js +2 -1
- package/dist/esm/components/StepActions/StepActionRow.js.map +1 -1
- package/dist/esm/components/StepActions/StepActionsList.js.map +1 -1
- package/dist/esm/components/SwapButton/SwapButton.js.map +1 -1
- package/dist/esm/components/Switch.js +1 -1
- package/dist/esm/components/Switch.js.map +1 -1
- package/dist/esm/components/Tabs/Tabs.style.js +4 -2
- package/dist/esm/components/Tabs/Tabs.style.js.map +1 -1
- package/dist/esm/components/TextFitter/TextFitter.js.map +1 -1
- package/dist/esm/components/Timer/StepStatusTimer.js.map +1 -1
- package/dist/esm/components/Token/Token.js.map +1 -1
- package/dist/esm/components/TokenList/PinTokenButton.js.map +1 -1
- package/dist/esm/components/TokenList/TokenDetailsSheet.js.map +1 -1
- package/dist/esm/components/TokenList/TokenDetailsSheetContent.js.map +1 -1
- package/dist/esm/components/TokenList/TokenList.js.map +1 -1
- package/dist/esm/components/TokenList/TokenListItem.js +46 -8
- package/dist/esm/components/TokenList/TokenListItem.js.map +1 -1
- package/dist/esm/components/TokenList/VirtualizedTokenList.js +22 -9
- package/dist/esm/components/TokenList/VirtualizedTokenList.js.map +1 -1
- package/dist/esm/components/TokenPillButton/TokenPillButton.js.map +1 -1
- package/dist/esm/components/TokenRate/TokenRate.js +2 -1
- package/dist/esm/components/TokenRate/TokenRate.js.map +1 -1
- package/dist/esm/components/Tools/ToolItem.js.map +1 -1
- package/dist/esm/components/Tools/Tools.js.map +1 -1
- package/dist/esm/components/TransactionCard/ActiveTransactionCard.js +22 -21
- package/dist/esm/components/TransactionCard/ActiveTransactionCard.js.map +1 -1
- package/dist/esm/components/TransactionCard/TransactionCard.js.map +1 -1
- package/dist/esm/components/TransactionCard/TransactionCardSkeleton.js.map +1 -1
- package/dist/esm/config/version.d.ts +1 -1
- package/dist/esm/config/version.js +1 -1
- package/dist/esm/config/version.js.map +1 -1
- package/dist/esm/hooks/timer/time.js +2 -2
- package/dist/esm/hooks/timer/time.js.map +1 -1
- package/dist/esm/hooks/useAccountsBalancesData.js +1 -14
- package/dist/esm/hooks/useAccountsBalancesData.js.map +1 -1
- package/dist/esm/hooks/useAvailableChains.d.ts.map +1 -1
- package/dist/esm/hooks/useAvailableChains.js +2 -1
- package/dist/esm/hooks/useAvailableChains.js.map +1 -1
- package/dist/esm/hooks/useExplorer.d.ts.map +1 -1
- package/dist/esm/hooks/useExplorer.js +4 -0
- package/dist/esm/hooks/useExplorer.js.map +1 -1
- package/dist/esm/hooks/useFlaggedTokenGuard.js +28 -0
- package/dist/esm/hooks/useFlaggedTokenGuard.js.map +1 -0
- package/dist/esm/hooks/useGasSufficiency.js +3 -1
- package/dist/esm/hooks/useGasSufficiency.js.map +1 -1
- package/dist/esm/hooks/useMaxSendAmount.js +15 -0
- package/dist/esm/hooks/useMaxSendAmount.js.map +1 -0
- package/dist/esm/hooks/usePacedRouteExecution.js +3 -2
- package/dist/esm/hooks/usePacedRouteExecution.js.map +1 -1
- package/dist/esm/hooks/useRouteExecutionMessage.js +3 -2
- package/dist/esm/hooks/useRouteExecutionMessage.js.map +1 -1
- package/dist/esm/hooks/useRoutes.d.ts.map +1 -1
- package/dist/esm/hooks/useRoutes.js +3 -1
- package/dist/esm/hooks/useRoutes.js.map +1 -1
- package/dist/esm/hooks/useToAddressAutoPopulate.js.map +1 -1
- package/dist/esm/hooks/useToAddressRequirements.d.ts +2 -0
- package/dist/esm/hooks/useToAddressRequirements.d.ts.map +1 -1
- package/dist/esm/hooks/useToAddressRequirements.js +7 -1
- package/dist/esm/hooks/useToAddressRequirements.js.map +1 -1
- package/dist/esm/hooks/useTokenBalances.d.ts.map +1 -1
- package/dist/esm/hooks/useTokenBalances.js +7 -2
- package/dist/esm/hooks/useTokenBalances.js.map +1 -1
- package/dist/esm/hooks/useTokenBalancesQueries.js +32 -29
- package/dist/esm/hooks/useTokenBalancesQueries.js.map +1 -1
- package/dist/esm/hooks/useTokenSearch.js +3 -5
- package/dist/esm/hooks/useTokenSearch.js.map +1 -1
- package/dist/esm/hooks/useTokens.js +14 -10
- package/dist/esm/hooks/useTokens.js.map +1 -1
- package/dist/esm/hooks/useWideVariant.js +2 -1
- package/dist/esm/hooks/useWideVariant.js.map +1 -1
- package/dist/esm/i18n/bn.json +3 -1
- package/dist/esm/i18n/de.json +3 -1
- package/dist/esm/i18n/en.json +12 -3
- package/dist/esm/i18n/es.json +3 -1
- package/dist/esm/i18n/fr.json +3 -1
- package/dist/esm/i18n/hi.json +3 -1
- package/dist/esm/i18n/id.json +3 -1
- package/dist/esm/i18n/it.json +3 -1
- package/dist/esm/i18n/ja.json +3 -1
- package/dist/esm/i18n/ko.json +3 -1
- package/dist/esm/i18n/pl.json +3 -1
- package/dist/esm/i18n/pt.json +3 -1
- package/dist/esm/i18n/th.json +3 -1
- package/dist/esm/i18n/tr.json +3 -1
- package/dist/esm/i18n/uk.json +3 -1
- package/dist/esm/i18n/vi.json +3 -1
- package/dist/esm/i18n/zh.json +3 -1
- package/dist/esm/pages/ActivitiesPage/ActivitiesPage.js.map +1 -1
- package/dist/esm/pages/ActivitiesPage/ActivitiesPageMenuButton.js.map +1 -1
- package/dist/esm/pages/LanguagesPage.js.map +1 -1
- package/dist/esm/pages/MainPage/LimitPageContent.js.map +1 -1
- package/dist/esm/pages/MainPage/MainPage.js +2 -1
- package/dist/esm/pages/MainPage/MainPage.js.map +1 -1
- package/dist/esm/pages/MainPage/MainPageActions.js.map +1 -1
- package/dist/esm/pages/MainPage/ReviewButton.js +2 -2
- package/dist/esm/pages/MainPage/ReviewButton.js.map +1 -1
- package/dist/esm/pages/RoutePriorityPage.js.map +1 -1
- package/dist/esm/pages/RoutesPage/RoutesPage.js +2 -2
- package/dist/esm/pages/RoutesPage/RoutesPage.js.map +1 -1
- package/dist/esm/pages/SelectChainPage/SelectChainPage.js +13 -12
- package/dist/esm/pages/SelectChainPage/SelectChainPage.js.map +1 -1
- package/dist/esm/pages/SelectEnabledToolsPage.js +8 -5
- package/dist/esm/pages/SelectEnabledToolsPage.js.map +1 -1
- package/dist/esm/pages/SelectTokenPage/SelectTokenPage.js +2 -1
- package/dist/esm/pages/SelectTokenPage/SelectTokenPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/BookmarkAddressSheet.js.map +1 -1
- package/dist/esm/pages/SendToWallet/BookmarksPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/ConfirmAddressSheet.js.map +1 -1
- package/dist/esm/pages/SendToWallet/ConnectedWalletsPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/RecentWalletsPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/SendToConfiguredWalletPage.js.map +1 -1
- package/dist/esm/pages/SendToWallet/SendToWalletPage.js.map +1 -1
- package/dist/esm/pages/SettingsPage/BridgeAndExchangeSettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/GasPriceSettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/LanguageSetting.js.map +1 -1
- package/dist/esm/pages/SettingsPage/ResetSettingsButton.js.map +1 -1
- package/dist/esm/pages/SettingsPage/RoutePrioritySettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SettingsCard/BadgedValue.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SettingsCard/SettingCardExpandable.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SettingsPage.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SlippageSettings/SlippagePage.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SlippageSettings/SlippageSettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SmallBalanceFilterSettings.js +2 -1
- package/dist/esm/pages/SettingsPage/SmallBalanceFilterSettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/ThemeSettings.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/ContactSupportButton.js +2 -1
- package/dist/esm/pages/TransactionDetailsPage/ContactSupportButton.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/ReceiptsCard.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsPage.js +2 -1
- package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsPage.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/TransactionDetailsSkeleton.js.map +1 -1
- package/dist/esm/pages/TransactionDetailsPage/TransferIdCard.js.map +1 -1
- package/dist/esm/pages/TransactionPage/ConfirmToAddressSheet.js.map +1 -1
- package/dist/esm/pages/TransactionPage/ExchangeRateBottomSheet.js.map +1 -1
- package/dist/esm/pages/TransactionPage/ExecutionDoneCard.js.map +1 -1
- package/dist/esm/pages/TransactionPage/StartTransactionButton.js +4 -3
- package/dist/esm/pages/TransactionPage/StartTransactionButton.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TokenValueBottomSheet.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TokenVerificationBottomSheet.js +64 -0
- package/dist/esm/pages/TransactionPage/TokenVerificationBottomSheet.js.map +1 -0
- package/dist/esm/pages/TransactionPage/TransactionDoneButtons.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TransactionExecutionContent.js +19 -16
- package/dist/esm/pages/TransactionPage/TransactionExecutionContent.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TransactionFailedButtons.js +3 -1
- package/dist/esm/pages/TransactionPage/TransactionFailedButtons.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TransactionPage.js.map +1 -1
- package/dist/esm/pages/TransactionPage/TransactionReview.js +24 -2
- package/dist/esm/pages/TransactionPage/TransactionReview.js.map +1 -1
- package/dist/esm/providers/I18nProvider/I18nProvider.js +37 -36
- package/dist/esm/providers/I18nProvider/I18nProvider.js.map +1 -1
- package/dist/esm/providers/I18nProvider/types.d.ts.map +1 -1
- package/dist/esm/providers/ThemeProvider/ThemeProvider.js +2 -1
- package/dist/esm/providers/ThemeProvider/ThemeProvider.js.map +1 -1
- package/dist/esm/providers/WalletProvider/WalletProvider.js +10 -9
- package/dist/esm/providers/WalletProvider/WalletProvider.js.map +1 -1
- package/dist/esm/providers/WalletProvider/useExternalWalletProvider.js +7 -3
- package/dist/esm/providers/WalletProvider/useExternalWalletProvider.js.map +1 -1
- package/dist/esm/stores/StoreProvider.js.map +1 -1
- package/dist/esm/stores/form/FormStore.js.map +1 -1
- package/dist/esm/stores/form/FormUpdater.js.map +1 -1
- package/dist/esm/stores/navigationTabs/useNavigationTabsStore.js.map +1 -1
- package/dist/esm/stores/routes/useRouteExecutionIndicator.js +4 -3
- package/dist/esm/stores/routes/useRouteExecutionIndicator.js.map +1 -1
- package/dist/esm/types/token.d.ts +4 -1
- package/dist/esm/types/token.d.ts.map +1 -1
- package/dist/esm/utils/compactNumberFormatter.js +1 -3
- package/dist/esm/utils/compactNumberFormatter.js.map +1 -1
- package/dist/esm/utils/customReceiver.js +7 -0
- package/dist/esm/utils/customReceiver.js.map +1 -0
- package/dist/esm/utils/gas.js +24 -0
- package/dist/esm/utils/gas.js.map +1 -0
- package/dist/esm/utils/getErrorMessage.js +0 -1
- package/dist/esm/utils/getErrorMessage.js.map +1 -1
- package/dist/esm/utils/limitOrder.js +1 -1
- package/dist/esm/utils/limitOrder.js.map +1 -1
- package/dist/esm/utils/token.js +21 -4
- package/dist/esm/utils/token.js.map +1 -1
- package/dist/esm/utils/tokenList.js +37 -23
- package/dist/esm/utils/tokenList.js.map +1 -1
- package/package.json +15 -15
- package/src/components/AmountInput/AmountInputEndAdornment.tsx +2 -21
- package/src/components/AmountInputCard/PercentageChips.tsx +2 -18
- package/src/components/Chains/AllChainsAvatar.tsx +7 -1
- package/src/components/Messages/UnsupportedToAddressMessage.tsx +24 -0
- package/src/components/Messages/WarningMessages.tsx +3 -0
- package/src/components/Messages/useMessageQueue.ts +9 -0
- package/src/components/Routes/LimitOrderRoutes.tsx +5 -2
- package/src/components/Routes/RoutesContent.tsx +5 -2
- package/src/components/SendToWallet/SendToWalletExpandButton.tsx +2 -1
- package/src/components/TokenList/TokenListItem.tsx +68 -9
- package/src/components/TokenList/VirtualizedTokenList.tsx +33 -9
- package/src/components/TokenList/types.ts +4 -0
- package/src/config/version.ts +1 -1
- package/src/hooks/useAccountsBalancesData.ts +4 -31
- package/src/hooks/useAvailableChains.ts +1 -0
- package/src/hooks/useExplorer.ts +2 -0
- package/src/hooks/useFlaggedTokenGuard.ts +33 -0
- package/src/hooks/useGasSufficiency.ts +9 -1
- package/src/hooks/useMaxSendAmount.ts +21 -0
- package/src/hooks/useRoutes.ts +7 -0
- package/src/hooks/useToAddressRequirements.ts +17 -1
- package/src/hooks/useTokenBalances.ts +18 -2
- package/src/hooks/useTokenBalancesQueries.ts +12 -4
- package/src/hooks/useTokenSearch.ts +1 -5
- package/src/hooks/useTokens.ts +28 -13
- package/src/pages/MainPage/ReviewButton.tsx +6 -2
- package/src/pages/RoutesPage/RoutesPage.tsx +5 -2
- package/src/pages/TransactionPage/TokenVerificationBottomSheet.tsx +93 -0
- package/src/pages/TransactionPage/TransactionReview.tsx +28 -1
- package/src/providers/WalletProvider/useExternalWalletProvider.ts +9 -1
- package/src/types/token.ts +6 -3
- package/src/utils/customReceiver.ts +7 -0
- package/src/utils/gas.ts +41 -0
- package/src/utils/token.ts +53 -9
- package/src/utils/tokenList.ts +27 -7
- package/dist/esm/hooks/useFilteredByTokenBalances.js +0 -74
- package/dist/esm/hooks/useFilteredByTokenBalances.js.map +0 -1
- package/src/hooks/useFilteredByTokenBalances.ts +0 -145
|
@@ -5,6 +5,7 @@ import { useQuery } from '@tanstack/react-query'
|
|
|
5
5
|
import { useMemo } from 'react'
|
|
6
6
|
import { useSDKClient } from '../providers/SDKClientProvider.js'
|
|
7
7
|
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
|
|
8
|
+
import { getSelfFundedGasAmount } from '../utils/gas.js'
|
|
8
9
|
import { getQueryKey } from '../utils/queries.js'
|
|
9
10
|
import { useAvailableChains } from './useAvailableChains.js'
|
|
10
11
|
import { useIsContractAddress } from './useIsContractAddress.js'
|
|
@@ -108,7 +109,14 @@ export const useGasSufficiency = (
|
|
|
108
109
|
amount + BigInt(Number(gasCost.amount).toFixed(0)),
|
|
109
110
|
0n
|
|
110
111
|
)
|
|
111
|
-
|
|
112
|
+
// A previous step can deliver this step's gas token (XLM bridged to
|
|
113
|
+
// Stellar), so the user does not have to hold it up front
|
|
114
|
+
const selfFundedGasAmount = getSelfFundedGasAmount(
|
|
115
|
+
route,
|
|
116
|
+
step,
|
|
117
|
+
getChainById(token.chainId)?.chainType
|
|
118
|
+
)
|
|
119
|
+
if (gasCostAmount > 0n && gasCostAmount > selfFundedGasAmount) {
|
|
112
120
|
groupedGasCosts[token.chainId] = {
|
|
113
121
|
gasAmount: groupedGasCosts[token.chainId]
|
|
114
122
|
? groupedGasCosts[token.chainId].gasAmount + gasCostAmount
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useGasRecommendation } from './useGasRecommendation.js'
|
|
2
|
+
import { useTokenAddressBalance } from './useTokenAddressBalance.js'
|
|
3
|
+
|
|
4
|
+
// Largest amount of the token the wallet can send: for the native token that is
|
|
5
|
+
// the balance less the gas the chain recommends keeping back.
|
|
6
|
+
export const useMaxSendAmount = (
|
|
7
|
+
chainId?: number,
|
|
8
|
+
tokenAddress?: string
|
|
9
|
+
): bigint => {
|
|
10
|
+
const { token, chain } = useTokenAddressBalance(chainId, tokenAddress)
|
|
11
|
+
const { data } = useGasRecommendation(chainId)
|
|
12
|
+
|
|
13
|
+
if (!token?.amount) {
|
|
14
|
+
return 0n
|
|
15
|
+
}
|
|
16
|
+
if (chain?.nativeToken.address !== tokenAddress) {
|
|
17
|
+
return token.amount
|
|
18
|
+
}
|
|
19
|
+
const reserved = BigInt(data?.recommended?.amount ?? 0)
|
|
20
|
+
return token.amount > reserved ? token.amount - reserved : token.amount
|
|
21
|
+
}
|
package/src/hooks/useRoutes.ts
CHANGED
|
@@ -29,6 +29,7 @@ import { defaultSlippage } from '../stores/settings/createSettingsStore.js'
|
|
|
29
29
|
import { useSettings } from '../stores/settings/useSettings.js'
|
|
30
30
|
import { WidgetEvent } from '../types/events.js'
|
|
31
31
|
import type { TokensByChain } from '../types/token.js'
|
|
32
|
+
import { isCustomReceiverUnsupported } from '../utils/customReceiver.js'
|
|
32
33
|
import { getQueryKey } from '../utils/queries.js'
|
|
33
34
|
import { updateTokenInCache } from '../utils/token.js'
|
|
34
35
|
import { useChain } from './useChain.js'
|
|
@@ -177,6 +178,11 @@ export const useRoutes = ({
|
|
|
177
178
|
? hasToAddressAndChainTypeSatisfied
|
|
178
179
|
: true
|
|
179
180
|
|
|
181
|
+
// Stellar settles to the signer, so a set receiver makes the route unfulfillable.
|
|
182
|
+
const customReceiverBlocked =
|
|
183
|
+
isCustomReceiverUnsupported(fromChain?.chainType, toChain?.chainType) &&
|
|
184
|
+
Boolean(toAddress)
|
|
185
|
+
|
|
180
186
|
// toAddress might be an empty string, but we need to pass undefined if there is no value
|
|
181
187
|
const toWalletAddress = toAddress || undefined
|
|
182
188
|
|
|
@@ -197,6 +203,7 @@ export const useRoutes = ({
|
|
|
197
203
|
!Number.isNaN(slippage) &&
|
|
198
204
|
hasAmount &&
|
|
199
205
|
isToAddressSatisfied &&
|
|
206
|
+
!customReceiverBlocked &&
|
|
200
207
|
contractCallQuoteEnabled &&
|
|
201
208
|
!isBatchingSupportedLoading
|
|
202
209
|
|
|
@@ -4,12 +4,15 @@ import { useEthereumContext } from '@lifi/widget-provider'
|
|
|
4
4
|
import { useChain } from '../hooks/useChain.js'
|
|
5
5
|
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
|
|
6
6
|
import { useFieldValues } from '../stores/form/useFieldValues.js'
|
|
7
|
+
import { isCustomReceiverUnsupported } from '../utils/customReceiver.js'
|
|
7
8
|
import { useIsContractAddress } from './useIsContractAddress.js'
|
|
8
9
|
|
|
9
10
|
export const useToAddressRequirements = (
|
|
10
11
|
route?: RouteExtended
|
|
11
12
|
): {
|
|
12
13
|
requiredToAddress: boolean
|
|
14
|
+
unsupportedToAddress: boolean
|
|
15
|
+
unsupportedReceiverBlocking: boolean
|
|
13
16
|
requiredToChainType: ChainType | undefined
|
|
14
17
|
accountNotDeployedAtDestination: boolean
|
|
15
18
|
accountDeployedAtDestination: boolean
|
|
@@ -68,11 +71,22 @@ export const useToAddressRequirements = (
|
|
|
68
71
|
fromChainId !== toChainId &&
|
|
69
72
|
!fromContractCodeHasDelegationIndicator
|
|
70
73
|
|
|
74
|
+
const unsupportedToAddress = isCustomReceiverUnsupported(
|
|
75
|
+
fromChain?.chainType,
|
|
76
|
+
toChain?.chainType
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
// Stellar routes settle to the signer, so a required receiver is never honoured.
|
|
80
|
+
const unsupportedReceiverBlocking = Boolean(
|
|
81
|
+
unsupportedToAddress && (toAddress || requiredUI?.toAddress)
|
|
82
|
+
)
|
|
83
|
+
|
|
71
84
|
const requiredToAddress = Boolean(
|
|
72
85
|
(isDifferentChainType ||
|
|
73
86
|
isCrossChainContractAddress ||
|
|
74
87
|
requiredUI?.toAddress) &&
|
|
75
|
-
!hiddenUI?.toAddress
|
|
88
|
+
!hiddenUI?.toAddress &&
|
|
89
|
+
!unsupportedToAddress
|
|
76
90
|
)
|
|
77
91
|
|
|
78
92
|
const accountNotDeployedAtDestination = Boolean(
|
|
@@ -91,6 +105,8 @@ export const useToAddressRequirements = (
|
|
|
91
105
|
|
|
92
106
|
return {
|
|
93
107
|
requiredToAddress,
|
|
108
|
+
unsupportedToAddress,
|
|
109
|
+
unsupportedReceiverBlocking,
|
|
94
110
|
requiredToChainType: toChain?.chainType,
|
|
95
111
|
accountNotDeployedAtDestination,
|
|
96
112
|
accountDeployedAtDestination,
|
|
@@ -4,7 +4,11 @@ import type { FormType } from '../stores/form/types.js'
|
|
|
4
4
|
import { useSettings } from '../stores/settings/useSettings.js'
|
|
5
5
|
import type { TokenAmount } from '../types/token.js'
|
|
6
6
|
import { formatTokenPrice } from '../utils/format.js'
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
hoistNativeToken,
|
|
9
|
+
isSearchMatch,
|
|
10
|
+
processTokenList,
|
|
11
|
+
} from '../utils/tokenList.js'
|
|
8
12
|
import { useAccountsBalancesData } from './useAccountsBalancesData.js'
|
|
9
13
|
import { useDisplayedTokens } from './useDisplayedTokens.js'
|
|
10
14
|
import { useTokenBalancesQueries } from './useTokenBalancesQueries.js'
|
|
@@ -115,7 +119,7 @@ export const useTokenBalances = (
|
|
|
115
119
|
])
|
|
116
120
|
|
|
117
121
|
const { processedTokens, withCategories, withPinnedTokens } = useMemo(() => {
|
|
118
|
-
|
|
122
|
+
const result = processTokenList(
|
|
119
123
|
isBalanceLoading,
|
|
120
124
|
isAllNetworks || !!search,
|
|
121
125
|
configTokens,
|
|
@@ -124,6 +128,18 @@ export const useTokenBalances = (
|
|
|
124
128
|
displayedTokensWithBalances,
|
|
125
129
|
isPinnedToken
|
|
126
130
|
)
|
|
131
|
+
// A search keeps its results ranked by match, and "All networks" has no
|
|
132
|
+
// single native token to lead with.
|
|
133
|
+
if (isAllNetworks || search) {
|
|
134
|
+
return result
|
|
135
|
+
}
|
|
136
|
+
return {
|
|
137
|
+
...result,
|
|
138
|
+
processedTokens: hoistNativeToken(
|
|
139
|
+
result.processedTokens,
|
|
140
|
+
selectedChainId
|
|
141
|
+
),
|
|
142
|
+
}
|
|
127
143
|
}, [
|
|
128
144
|
isBalanceLoading,
|
|
129
145
|
isAllNetworks,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getTokenBalances, type TokenExtended } from '@lifi/sdk'
|
|
2
|
-
import { useQueries } from '@tanstack/react-query'
|
|
2
|
+
import { keepPreviousData, useQueries } from '@tanstack/react-query'
|
|
3
3
|
import { useMemo, useRef } from 'react'
|
|
4
4
|
import { useSDKClient } from '../providers/SDKClientProvider.js'
|
|
5
5
|
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
|
|
@@ -7,6 +7,10 @@ import type { TokenAmount, TokenAmountExtended } from '../types/token.js'
|
|
|
7
7
|
import { getQueryKey } from '../utils/queries.js'
|
|
8
8
|
|
|
9
9
|
const defaultRefetchInterval = 32_000
|
|
10
|
+
// Max time to hold the skeleton before revealing balances in the multi-chain view.
|
|
11
|
+
// Sits just below the typical full-settle time so the list reveals once, sorted,
|
|
12
|
+
// instead of reordering as each chain streams in.
|
|
13
|
+
const balanceRevealTimeout = 2_000
|
|
10
14
|
|
|
11
15
|
export const useTokenBalancesQueries = (
|
|
12
16
|
accountsWithTokens?: Record<string, Record<number, TokenExtended[]>>,
|
|
@@ -44,7 +48,10 @@ export const useTokenBalancesQueries = (
|
|
|
44
48
|
enabled: isBalanceLoadingEnabled,
|
|
45
49
|
refetchInterval: defaultRefetchInterval,
|
|
46
50
|
staleTime: defaultRefetchInterval,
|
|
47
|
-
|
|
51
|
+
placeholderData: keepPreviousData,
|
|
52
|
+
// Resolve a failed chain immediately instead of retrying past the reveal
|
|
53
|
+
// window (retries would pop the chain in late and re-sort the list).
|
|
54
|
+
retry: false,
|
|
48
55
|
}
|
|
49
56
|
})
|
|
50
57
|
)
|
|
@@ -74,8 +81,9 @@ export const useTokenBalancesQueries = (
|
|
|
74
81
|
? now - firstLoadStartRef.current
|
|
75
82
|
: 0
|
|
76
83
|
|
|
77
|
-
// Return results
|
|
78
|
-
const shouldReturnResults =
|
|
84
|
+
// Return results once all queries complete, or once the reveal timeout elapses
|
|
85
|
+
const shouldReturnResults =
|
|
86
|
+
allComplete || timeSinceStart >= balanceRevealTimeout
|
|
79
87
|
|
|
80
88
|
if (shouldReturnResults) {
|
|
81
89
|
const data: TokenAmount[] = results
|
|
@@ -74,13 +74,9 @@ export const useTokenSearch = (
|
|
|
74
74
|
) {
|
|
75
75
|
return data
|
|
76
76
|
}
|
|
77
|
-
// Mark token from search as unverified
|
|
78
77
|
return {
|
|
79
78
|
...data,
|
|
80
|
-
[chainId as number]: [
|
|
81
|
-
...(chainTokens ?? []),
|
|
82
|
-
{ ...token, verified: false },
|
|
83
|
-
],
|
|
79
|
+
[chainId as number]: [...(chainTokens ?? []), token],
|
|
84
80
|
}
|
|
85
81
|
}
|
|
86
82
|
)
|
package/src/hooks/useTokens.ts
CHANGED
|
@@ -17,8 +17,10 @@ import { isItemAllowed } from '../utils/item.js'
|
|
|
17
17
|
import { getQueryKey } from '../utils/queries.js'
|
|
18
18
|
import {
|
|
19
19
|
filterAllowedTokens,
|
|
20
|
+
getNativeTokenAddresses,
|
|
20
21
|
mergeVerifiedWithSearchTokens,
|
|
21
22
|
} from '../utils/token.js'
|
|
23
|
+
import { useAvailableChains } from './useAvailableChains.js'
|
|
22
24
|
|
|
23
25
|
const refetchInterval = 300_000
|
|
24
26
|
|
|
@@ -49,6 +51,7 @@ export const useTokens = (
|
|
|
49
51
|
ChainType.UTXO,
|
|
50
52
|
ChainType.MVM,
|
|
51
53
|
ChainType.TVM,
|
|
54
|
+
ChainType.STL,
|
|
52
55
|
].filter((chainType) => isItemAllowed(chainType, chainsConfig?.types))
|
|
53
56
|
|
|
54
57
|
const tokensResponse: TokensExtendedResponse = await getTokens(
|
|
@@ -63,11 +66,11 @@ export const useTokens = (
|
|
|
63
66
|
{ signal }
|
|
64
67
|
)
|
|
65
68
|
|
|
66
|
-
//
|
|
69
|
+
// `listed` tells a main-list token from a searched one
|
|
67
70
|
const tokens: TokensByChain = Object.fromEntries(
|
|
68
71
|
Object.entries(tokensResponse.tokens).map(([chainId, tokens]) => [
|
|
69
72
|
chainId,
|
|
70
|
-
tokens.map((token) => ({ ...token,
|
|
73
|
+
tokens.map((token) => ({ ...token, listed: true })),
|
|
71
74
|
])
|
|
72
75
|
)
|
|
73
76
|
|
|
@@ -92,6 +95,7 @@ export const useTokens = (
|
|
|
92
95
|
ChainType.UTXO,
|
|
93
96
|
ChainType.MVM,
|
|
94
97
|
ChainType.TVM,
|
|
98
|
+
ChainType.STL,
|
|
95
99
|
].filter((chainType) => isItemAllowed(chainType, chainsConfig?.types))
|
|
96
100
|
|
|
97
101
|
const tokensResponse: TokensExtendedResponse = await getTokens(
|
|
@@ -130,26 +134,37 @@ export const useTokens = (
|
|
|
130
134
|
}
|
|
131
135
|
}
|
|
132
136
|
|
|
133
|
-
|
|
134
|
-
const tokens: TokensByChain = Object.fromEntries(
|
|
135
|
-
Object.entries(tokensResponse.tokens).map(([chainId, tokens]) => [
|
|
136
|
-
chainId,
|
|
137
|
-
tokens.map((token) => ({ ...token, verified: false })),
|
|
138
|
-
])
|
|
139
|
-
)
|
|
140
|
-
|
|
141
|
-
return tokens
|
|
137
|
+
return tokensResponse.tokens as TokensByChain
|
|
142
138
|
},
|
|
143
139
|
enabled: !!search,
|
|
144
140
|
refetchInterval,
|
|
145
141
|
staleTime: refetchInterval,
|
|
146
142
|
})
|
|
147
143
|
|
|
144
|
+
const { chains } = useAvailableChains()
|
|
145
|
+
const nativeTokenAddresses = useMemo(
|
|
146
|
+
() => getNativeTokenAddresses(chains),
|
|
147
|
+
[chains]
|
|
148
|
+
)
|
|
149
|
+
|
|
148
150
|
// Merge tokens at read time - single place where caches are combined
|
|
149
151
|
const allTokens = useMemo(() => {
|
|
150
152
|
const merged = mergeVerifiedWithSearchTokens(verifiedTokens, searchTokens)
|
|
151
|
-
return filterAllowedTokens(
|
|
152
|
-
|
|
153
|
+
return filterAllowedTokens(
|
|
154
|
+
merged,
|
|
155
|
+
configTokens,
|
|
156
|
+
chainsConfig,
|
|
157
|
+
formType,
|
|
158
|
+
nativeTokenAddresses
|
|
159
|
+
)
|
|
160
|
+
}, [
|
|
161
|
+
verifiedTokens,
|
|
162
|
+
searchTokens,
|
|
163
|
+
configTokens,
|
|
164
|
+
chainsConfig,
|
|
165
|
+
formType,
|
|
166
|
+
nativeTokenAddresses,
|
|
167
|
+
])
|
|
153
168
|
|
|
154
169
|
return {
|
|
155
170
|
allTokens,
|
|
@@ -16,7 +16,8 @@ export const ReviewButton: React.FC = () => {
|
|
|
16
16
|
const emitter = useWidgetEvents()
|
|
17
17
|
const { mode, modeOptions } = useWidgetConfig()
|
|
18
18
|
const splitState = useSplitMode()
|
|
19
|
-
const { toAddress, requiredToAddress } =
|
|
19
|
+
const { toAddress, requiredToAddress, unsupportedReceiverBlocking } =
|
|
20
|
+
useToAddressRequirements()
|
|
20
21
|
const { routes, setReviewableRoute } = useRoutes()
|
|
21
22
|
const [selectedRouteId] = useFieldValues('selectedRouteId')
|
|
22
23
|
|
|
@@ -85,7 +86,10 @@ export const ReviewButton: React.FC = () => {
|
|
|
85
86
|
<BaseTransactionButton
|
|
86
87
|
text={getButtonText()}
|
|
87
88
|
onClick={handleClick}
|
|
88
|
-
disabled={
|
|
89
|
+
disabled={
|
|
90
|
+
currentRoute &&
|
|
91
|
+
(unsupportedReceiverBlocking || (requiredToAddress && !toAddress))
|
|
92
|
+
}
|
|
89
93
|
route={currentRoute}
|
|
90
94
|
sx={{ flex: 1 }}
|
|
91
95
|
/>
|
|
@@ -36,7 +36,8 @@ export const RoutesPage = (): JSX.Element => {
|
|
|
36
36
|
} = useRoutes()
|
|
37
37
|
const { account } = useAccount({ chainType: fromChain?.chainType })
|
|
38
38
|
const [toAddress] = useFieldValues('toAddress')
|
|
39
|
-
const { requiredToAddress } =
|
|
39
|
+
const { requiredToAddress, unsupportedReceiverBlocking } =
|
|
40
|
+
useToAddressRequirements()
|
|
40
41
|
|
|
41
42
|
const headerAction = useMemo(
|
|
42
43
|
() => (
|
|
@@ -72,7 +73,9 @@ export const RoutesPage = (): JSX.Element => {
|
|
|
72
73
|
|
|
73
74
|
const routeNotFound = !routes?.length && !isLoading && !isFetching
|
|
74
75
|
|
|
75
|
-
const toAddressUnsatisfied =
|
|
76
|
+
const toAddressUnsatisfied =
|
|
77
|
+
routes?.[0] &&
|
|
78
|
+
(unsupportedReceiverBlocking || (requiredToAddress && !toAddress))
|
|
76
79
|
|
|
77
80
|
const allowInteraction = account.isConnected && !toAddressUnsatisfied
|
|
78
81
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import type { Token } from '@lifi/sdk'
|
|
2
|
+
import { Button, Checkbox, FormControlLabel } from '@mui/material'
|
|
3
|
+
import type { JSX, Ref, RefObject } from 'react'
|
|
4
|
+
import { useRef, useState } from 'react'
|
|
5
|
+
import { useTranslation } from 'react-i18next'
|
|
6
|
+
import { BottomSheet } from '../../components/BottomSheet/BottomSheet.js'
|
|
7
|
+
import type { BottomSheetBase } from '../../components/BottomSheet/types.js'
|
|
8
|
+
import { IconCircle } from '../../components/IconCircle/IconCircle.js'
|
|
9
|
+
import { useSetContentHeight } from '../../hooks/useSetContentHeight.js'
|
|
10
|
+
import {
|
|
11
|
+
ButtonRow,
|
|
12
|
+
CenterContainer,
|
|
13
|
+
ContentContainer,
|
|
14
|
+
WarningMessage,
|
|
15
|
+
WarningTitle,
|
|
16
|
+
} from './TokenValueBottomSheet.style.js'
|
|
17
|
+
|
|
18
|
+
interface TokenVerificationBottomSheetProps {
|
|
19
|
+
/** Source and/or destination tokens the screening provider flagged. */
|
|
20
|
+
tokens: Token[]
|
|
21
|
+
onContinue(): void
|
|
22
|
+
onCancel?(): void
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const TokenVerificationBottomSheet = ({
|
|
26
|
+
tokens,
|
|
27
|
+
onContinue,
|
|
28
|
+
onCancel,
|
|
29
|
+
ref,
|
|
30
|
+
}: TokenVerificationBottomSheetProps & {
|
|
31
|
+
ref?: Ref<BottomSheetBase>
|
|
32
|
+
}): JSX.Element => {
|
|
33
|
+
const handleCancel = () => {
|
|
34
|
+
;(ref as RefObject<BottomSheetBase>).current?.close()
|
|
35
|
+
onCancel?.()
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<BottomSheet ref={ref} onClose={onCancel}>
|
|
40
|
+
<TokenVerificationBottomSheetContent
|
|
41
|
+
tokens={tokens}
|
|
42
|
+
onContinue={onContinue}
|
|
43
|
+
onCancel={handleCancel}
|
|
44
|
+
/>
|
|
45
|
+
</BottomSheet>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const TokenVerificationBottomSheetContent: React.FC<
|
|
50
|
+
TokenVerificationBottomSheetProps
|
|
51
|
+
> = ({ tokens, onCancel, onContinue }) => {
|
|
52
|
+
const [accepted, setAccepted] = useState(false)
|
|
53
|
+
const { t } = useTranslation()
|
|
54
|
+
const ref = useRef<HTMLElement>(null)
|
|
55
|
+
useSetContentHeight(ref)
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<ContentContainer ref={ref}>
|
|
59
|
+
<CenterContainer>
|
|
60
|
+
<IconCircle status="error" sx={{ mb: 2.5 }} />
|
|
61
|
+
<WarningTitle>{t('warning.title.tokenFlagged')}</WarningTitle>
|
|
62
|
+
</CenterContainer>
|
|
63
|
+
{tokens.map((token) => (
|
|
64
|
+
<WarningMessage key={`${token.chainId}-${token.address}`}>
|
|
65
|
+
{t('warning.message.tokenFlagged', { tokenSymbol: token.symbol })}
|
|
66
|
+
</WarningMessage>
|
|
67
|
+
))}
|
|
68
|
+
<FormControlLabel
|
|
69
|
+
control={
|
|
70
|
+
<Checkbox
|
|
71
|
+
checked={accepted}
|
|
72
|
+
onChange={(_, checked) => setAccepted(checked)}
|
|
73
|
+
/>
|
|
74
|
+
}
|
|
75
|
+
label={t('warning.checkbox.tokenFlagged')}
|
|
76
|
+
sx={{ mt: 1 }}
|
|
77
|
+
/>
|
|
78
|
+
<ButtonRow>
|
|
79
|
+
<Button variant="text" onClick={onCancel} fullWidth>
|
|
80
|
+
{t('button.cancel')}
|
|
81
|
+
</Button>
|
|
82
|
+
<Button
|
|
83
|
+
variant="contained"
|
|
84
|
+
onClick={onContinue}
|
|
85
|
+
disabled={!accepted}
|
|
86
|
+
fullWidth
|
|
87
|
+
>
|
|
88
|
+
{t('button.continue')}
|
|
89
|
+
</Button>
|
|
90
|
+
</ButtonRow>
|
|
91
|
+
</ContentContainer>
|
|
92
|
+
)
|
|
93
|
+
}
|
|
@@ -8,6 +8,7 @@ import { Card } from '../../components/Card/Card.js'
|
|
|
8
8
|
import { WarningMessages } from '../../components/Messages/WarningMessages.js'
|
|
9
9
|
import { RouteTokens } from '../../components/RouteCard/RouteTokens.js'
|
|
10
10
|
import { useAddressActivity } from '../../hooks/useAddressActivity.js'
|
|
11
|
+
import { useFlaggedTokenGuard } from '../../hooks/useFlaggedTokenGuard.js'
|
|
11
12
|
import { useWidgetEvents } from '../../hooks/useWidgetEvents.js'
|
|
12
13
|
import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js'
|
|
13
14
|
import { useFieldActions } from '../../stores/form/useFieldActions.js'
|
|
@@ -18,6 +19,7 @@ import { navigationRoutes } from '../../utils/navigationRoutes.js'
|
|
|
18
19
|
import { ConfirmToAddressSheet } from './ConfirmToAddressSheet.js'
|
|
19
20
|
import { StartTransactionButton } from './StartTransactionButton.js'
|
|
20
21
|
import { TokenValueBottomSheet } from './TokenValueBottomSheet.js'
|
|
22
|
+
import { TokenVerificationBottomSheet } from './TokenVerificationBottomSheet.js'
|
|
21
23
|
import {
|
|
22
24
|
calculateValueLossPercentage,
|
|
23
25
|
getTokenValueLossThreshold,
|
|
@@ -44,6 +46,8 @@ export const TransactionReview: React.FC<TransactionReviewProps> = ({
|
|
|
44
46
|
const tokenValueBottomSheetRef = useRef<BottomSheetBase>(null)
|
|
45
47
|
const confirmToAddressSheetRef = useRef<BottomSheetBase>(null)
|
|
46
48
|
|
|
49
|
+
const { flaggedTokens, flaggedTokenSheetRef } = useFlaggedTokenGuard(route)
|
|
50
|
+
|
|
47
51
|
const {
|
|
48
52
|
toAddress,
|
|
49
53
|
hasActivity,
|
|
@@ -70,6 +74,7 @@ export const TransactionReview: React.FC<TransactionReviewProps> = ({
|
|
|
70
74
|
})
|
|
71
75
|
}
|
|
72
76
|
tokenValueBottomSheetRef.current?.close()
|
|
77
|
+
flaggedTokenSheetRef.current?.close()
|
|
73
78
|
executeRoute()
|
|
74
79
|
setFieldValue('fromAmount', '')
|
|
75
80
|
if (mode === 'custom') {
|
|
@@ -81,7 +86,9 @@ export const TransactionReview: React.FC<TransactionReviewProps> = ({
|
|
|
81
86
|
})
|
|
82
87
|
}
|
|
83
88
|
|
|
84
|
-
|
|
89
|
+
// Runs the remaining gates. The flagged-token sheet continues into this
|
|
90
|
+
// rather than executing, so accepting it does not skip the others.
|
|
91
|
+
const handleStartAfterTokenCheck = () => {
|
|
85
92
|
if (
|
|
86
93
|
toAddress &&
|
|
87
94
|
!hasActivity &&
|
|
@@ -109,6 +116,19 @@ export const TransactionReview: React.FC<TransactionReviewProps> = ({
|
|
|
109
116
|
}
|
|
110
117
|
}
|
|
111
118
|
|
|
119
|
+
const handleStartClick = () => {
|
|
120
|
+
if (flaggedTokens.length) {
|
|
121
|
+
flaggedTokenSheetRef.current?.open()
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
handleStartAfterTokenCheck()
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const handleFlaggedTokensContinue = () => {
|
|
128
|
+
flaggedTokenSheetRef.current?.close()
|
|
129
|
+
handleStartAfterTokenCheck()
|
|
130
|
+
}
|
|
131
|
+
|
|
112
132
|
const getButtonText = (): string => {
|
|
113
133
|
switch (mode) {
|
|
114
134
|
case 'custom':
|
|
@@ -150,6 +170,13 @@ export const TransactionReview: React.FC<TransactionReviewProps> = ({
|
|
|
150
170
|
onContinue={handleExecuteRoute}
|
|
151
171
|
/>
|
|
152
172
|
) : null}
|
|
173
|
+
{flaggedTokens.length ? (
|
|
174
|
+
<TokenVerificationBottomSheet
|
|
175
|
+
ref={flaggedTokenSheetRef}
|
|
176
|
+
tokens={flaggedTokens}
|
|
177
|
+
onContinue={handleFlaggedTokensContinue}
|
|
178
|
+
/>
|
|
179
|
+
) : null}
|
|
153
180
|
{!hiddenUI?.lowAddressActivityConfirmation ? (
|
|
154
181
|
<ConfirmToAddressSheet
|
|
155
182
|
ref={confirmToAddressSheetRef}
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
useBitcoinContext,
|
|
4
4
|
useEthereumContext,
|
|
5
5
|
useSolanaContext,
|
|
6
|
+
useStellarContext,
|
|
6
7
|
useSuiContext,
|
|
7
8
|
useTronContext,
|
|
8
9
|
} from '@lifi/widget-provider'
|
|
@@ -21,6 +22,7 @@ const internalChainTypes = [
|
|
|
21
22
|
ChainType.UTXO,
|
|
22
23
|
ChainType.MVM,
|
|
23
24
|
ChainType.TVM,
|
|
25
|
+
ChainType.STL,
|
|
24
26
|
]
|
|
25
27
|
|
|
26
28
|
export function useExternalWalletProvider(): ExternalWalletProvider {
|
|
@@ -30,6 +32,7 @@ export function useExternalWalletProvider(): ExternalWalletProvider {
|
|
|
30
32
|
const { isExternalContext: hasExternalBitcoinContext } = useBitcoinContext()
|
|
31
33
|
const { isExternalContext: hasExternalSuiContext } = useSuiContext()
|
|
32
34
|
const { isExternalContext: hasExternalTronContext } = useTronContext()
|
|
35
|
+
const { isExternalContext: hasExternalStellarContext } = useStellarContext()
|
|
33
36
|
const data = useMemo(() => {
|
|
34
37
|
const providers: ChainType[] = []
|
|
35
38
|
if (hasExternalEthereumContext) {
|
|
@@ -47,12 +50,16 @@ export function useExternalWalletProvider(): ExternalWalletProvider {
|
|
|
47
50
|
if (hasExternalTronContext) {
|
|
48
51
|
providers.push(ChainType.TVM)
|
|
49
52
|
}
|
|
53
|
+
if (hasExternalStellarContext) {
|
|
54
|
+
providers.push(ChainType.STL)
|
|
55
|
+
}
|
|
50
56
|
const hasExternalProvider =
|
|
51
57
|
hasExternalEthereumContext ||
|
|
52
58
|
hasExternalSolanaContext ||
|
|
53
59
|
hasExternalBitcoinContext ||
|
|
54
60
|
hasExternalSuiContext ||
|
|
55
|
-
hasExternalTronContext
|
|
61
|
+
hasExternalTronContext ||
|
|
62
|
+
hasExternalStellarContext
|
|
56
63
|
|
|
57
64
|
const useExternalWalletProvidersOnly =
|
|
58
65
|
hasExternalProvider &&
|
|
@@ -71,6 +78,7 @@ export function useExternalWalletProvider(): ExternalWalletProvider {
|
|
|
71
78
|
hasExternalBitcoinContext,
|
|
72
79
|
hasExternalSuiContext,
|
|
73
80
|
hasExternalTronContext,
|
|
81
|
+
hasExternalStellarContext,
|
|
74
82
|
walletConfig?.usePartialWalletManagement,
|
|
75
83
|
walletConfig?.forceInternalWalletManagement,
|
|
76
84
|
])
|
package/src/types/token.ts
CHANGED
|
@@ -4,11 +4,14 @@ import type {
|
|
|
4
4
|
TokenExtended,
|
|
5
5
|
} from '@lifi/sdk'
|
|
6
6
|
|
|
7
|
-
interface TokenFlags {
|
|
7
|
+
export interface TokenFlags {
|
|
8
8
|
featured?: boolean
|
|
9
9
|
popular?: boolean
|
|
10
10
|
pinned?: boolean
|
|
11
11
|
verified?: boolean
|
|
12
|
+
native?: boolean
|
|
13
|
+
/** Came from the main token list rather than from a search. */
|
|
14
|
+
listed?: boolean
|
|
12
15
|
}
|
|
13
16
|
|
|
14
17
|
export interface TokenAmount extends SDKTokenAmount, TokenFlags {}
|
|
@@ -17,5 +20,5 @@ export interface TokenAmountExtended
|
|
|
17
20
|
extends SDKTokenAmountExtended,
|
|
18
21
|
TokenFlags {}
|
|
19
22
|
|
|
20
|
-
export type
|
|
21
|
-
export type TokensByChain = Record<number,
|
|
23
|
+
export type TokenWithFlags = TokenExtended & TokenFlags
|
|
24
|
+
export type TokensByChain = Record<number, TokenWithFlags[]>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ChainType } from '@lifi/sdk'
|
|
2
|
+
|
|
3
|
+
// Stellar routes always settle to the account that signs them.
|
|
4
|
+
export const isCustomReceiverUnsupported = (
|
|
5
|
+
fromChainType?: ChainType,
|
|
6
|
+
toChainType?: ChainType
|
|
7
|
+
): boolean => fromChainType === ChainType.STL && toChainType === ChainType.STL
|
package/src/utils/gas.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { LiFiStepExtended, RouteExtended } from '@lifi/sdk'
|
|
2
|
+
import { ChainType } from '@lifi/sdk'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Returns how much of a step's gas token the route itself delivers before that
|
|
6
|
+
* step runs. The previous step must output the gas token on the same chain, and
|
|
7
|
+
* whatever this step consumes as input is not available for gas.
|
|
8
|
+
* Stellar routes only — they bridge XLM to the receiver and hold back a buffer
|
|
9
|
+
* for the account reserve and the destination step fees.
|
|
10
|
+
*/
|
|
11
|
+
export const getSelfFundedGasAmount = (
|
|
12
|
+
route: RouteExtended,
|
|
13
|
+
step: LiFiStepExtended,
|
|
14
|
+
gasChainType?: ChainType
|
|
15
|
+
): bigint => {
|
|
16
|
+
// TODO: remove the chain gate when the backend reserves gas on every chain
|
|
17
|
+
if (gasChainType !== ChainType.STL) {
|
|
18
|
+
return 0n
|
|
19
|
+
}
|
|
20
|
+
const gasToken = step.estimate.gasCosts?.[0]?.token
|
|
21
|
+
const previousStep = route.steps[route.steps.indexOf(step) - 1]
|
|
22
|
+
if (!gasToken || !previousStep) {
|
|
23
|
+
return 0n
|
|
24
|
+
}
|
|
25
|
+
const { toToken } = previousStep.action
|
|
26
|
+
if (
|
|
27
|
+
toToken.chainId !== gasToken.chainId ||
|
|
28
|
+
toToken.address.toLowerCase() !== gasToken.address.toLowerCase()
|
|
29
|
+
) {
|
|
30
|
+
return 0n
|
|
31
|
+
}
|
|
32
|
+
const deliveredAmount = BigInt(previousStep.estimate.toAmountMin)
|
|
33
|
+
const consumedAmount =
|
|
34
|
+
step.action.fromToken.address.toLowerCase() ===
|
|
35
|
+
gasToken.address.toLowerCase()
|
|
36
|
+
? BigInt(step.action.fromAmount)
|
|
37
|
+
: 0n
|
|
38
|
+
return deliveredAmount > consumedAmount
|
|
39
|
+
? deliveredAmount - consumedAmount
|
|
40
|
+
: 0n
|
|
41
|
+
}
|