diff --git a/packages/widget-playground/src/config.ts b/packages/widget-playground/src/config.ts
index 5b8b47bea..105b6d2ac 100644
--- a/packages/widget-playground/src/config.ts
+++ b/packages/widget-playground/src/config.ts
@@ -30,6 +30,7 @@ export const widgetBaseConfig: WidgetConfig = {
buildSwapUrl: true,
// disabledUI: ['toAddress', 'fromAmount', 'toToken', 'fromToken'],
// requiredUI: ['toAddress'],
+ // slippage: 0.003,
sdkConfig: {
// apiUrl: 'https://staging.li.quest/v1/',
defaultRouteOptions: {
diff --git a/packages/widget/src/AppRoutes.tsx b/packages/widget/src/AppRoutes.tsx
index 77179bce0..91ab6a80d 100644
--- a/packages/widget/src/AppRoutes.tsx
+++ b/packages/widget/src/AppRoutes.tsx
@@ -3,6 +3,7 @@ import { NotFound } from './components/NotFound';
import { ActiveSwapsPage } from './pages/ActiveSwapsPage';
import { MainPage } from './pages/MainPage';
import { SelectChainPage } from './pages/SelectChainPage';
+import { SelectEnabledToolsPage } from './pages/SelectEnabledToolsPage';
import { SelectTokenPage } from './pages/SelectTokenPage';
import { SelectWalletPage } from './pages/SelectWalletPage';
import { SettingsPage } from './pages/SettingsPage';
@@ -22,6 +23,14 @@ export const AppRoutes = () => {
path: navigationRoutes.settings,
element: ,
},
+ {
+ path: `${navigationRoutes.settings}/${navigationRoutes.bridges}`,
+ element: ,
+ },
+ {
+ path: `${navigationRoutes.settings}/${navigationRoutes.exchanges}`,
+ element: ,
+ },
{
path: navigationRoutes.fromToken,
element: ,
diff --git a/packages/widget/src/components/Header/NavigationHeader.tsx b/packages/widget/src/components/Header/NavigationHeader.tsx
index fc418617c..fbb558043 100644
--- a/packages/widget/src/components/Header/NavigationHeader.tsx
+++ b/packages/widget/src/components/Header/NavigationHeader.tsx
@@ -36,6 +36,10 @@ export const NavigationHeader: React.FC = () => {
return t(`header.selectWallet`);
case navigationRoutes.settings:
return t(`header.settings`);
+ case navigationRoutes.bridges:
+ return t(`settings.enabledBridges`);
+ case navigationRoutes.exchanges:
+ return t(`settings.enabledExchanges`);
case navigationRoutes.swapHistory:
return t(`header.swapHistory`);
case navigationRoutes.fromToken:
diff --git a/packages/widget/src/components/ListItemButton.tsx b/packages/widget/src/components/ListItemButton.tsx
new file mode 100644
index 000000000..0f99027a0
--- /dev/null
+++ b/packages/widget/src/components/ListItemButton.tsx
@@ -0,0 +1,12 @@
+import { ListItemButton as MuiListItemButton } from '@mui/material';
+import { styled } from '@mui/material/styles';
+import { getContrastAlphaColor } from '../utils';
+
+export const ListItemButton = styled(MuiListItemButton)(({ theme }) => ({
+ borderRadius: theme.shape.borderRadius,
+ paddingLeft: theme.spacing(1.5),
+ height: 56,
+ '&:hover': {
+ backgroundColor: getContrastAlphaColor(theme, '4%'),
+ },
+}));
diff --git a/packages/widget/src/components/ListItemText.tsx b/packages/widget/src/components/ListItemText.tsx
new file mode 100644
index 000000000..61025f615
--- /dev/null
+++ b/packages/widget/src/components/ListItemText.tsx
@@ -0,0 +1,9 @@
+import { ListItemText as MuiListItemText } from '@mui/material';
+import { listItemTextClasses } from '@mui/material/ListItemText';
+import { styled } from '@mui/material/styles';
+
+export const ListItemText = styled(MuiListItemText)(({ theme }) => ({
+ [`.${listItemTextClasses.primary}`]: {
+ fontWeight: 400,
+ },
+}));
diff --git a/packages/widget/src/components/Select.tsx b/packages/widget/src/components/Select.tsx
index 7f0572928..2736b103b 100644
--- a/packages/widget/src/components/Select.tsx
+++ b/packages/widget/src/components/Select.tsx
@@ -19,6 +19,7 @@ export const Select = styled(MuiSelect, {
},
[`.${selectClasses.icon}`]: {
right: 10,
+ color: theme.palette.text.primary,
},
[`.${listItemIconClasses.root}`]: {
minWidth: 38,
diff --git a/packages/widget/src/components/TokenList/TokenList.style.tsx b/packages/widget/src/components/TokenList/TokenList.style.tsx
index ed3948d6a..14f151021 100644
--- a/packages/widget/src/components/TokenList/TokenList.style.tsx
+++ b/packages/widget/src/components/TokenList/TokenList.style.tsx
@@ -1,21 +1,14 @@
-import {
- ListItem as MuiListItem,
- ListItemButton as MuiListItemButton,
-} from '@mui/material';
+import { ListItem as MuiListItem } from '@mui/material';
import { listItemSecondaryActionClasses } from '@mui/material/ListItemSecondaryAction';
import { listItemTextClasses } from '@mui/material/ListItemText';
import { styled } from '@mui/material/styles';
-import { getContrastAlphaColor } from '../../utils';
+import { ListItemButton as ListItemButtonBase } from '../ListItemButton';
-export const ListItemButton = styled(MuiListItemButton)(({ theme }) => ({
- borderRadius: theme.shape.borderRadius,
+export const ListItemButton = styled(ListItemButtonBase)(({ theme }) => ({
paddingLeft: theme.spacing(1.5),
paddingRight: theme.spacing(1.5),
height: 64,
width: '100%',
- '&:hover': {
- backgroundColor: getContrastAlphaColor(theme, '4%'),
- },
}));
export const ListItem = styled(MuiListItem)(({ theme }) => ({
diff --git a/packages/widget/src/config/env.ts b/packages/widget/src/config/env.ts
index 6df81354d..42e289fdd 100644
--- a/packages/widget/src/config/env.ts
+++ b/packages/widget/src/config/env.ts
@@ -1,3 +1,3 @@
export const env = {
- LIFI_API_URL: 'https://li.quest/v1/', // 'https://developkub.li.finance/v1/',
+ LIFI_API_URL: 'https://li.quest/v1/', // 'https://develop.li.quest/v1/',
};
diff --git a/packages/widget/src/hooks/useTools.ts b/packages/widget/src/hooks/useTools.ts
index 426c96245..8c064d42f 100644
--- a/packages/widget/src/hooks/useTools.ts
+++ b/packages/widget/src/hooks/useTools.ts
@@ -1,53 +1,42 @@
/* eslint-disable no-underscore-dangle */
-import type { Bridge, Exchange } from '@lifi/sdk';
+import type { ToolsResponse } from '@lifi/sdk';
import { useQuery } from '@tanstack/react-query';
-import { useMemo } from 'react';
import { isItemAllowed, useLiFi, useWidgetConfig } from '../providers';
import { useSettingsStoreContext } from '../stores';
-interface WidgetBridge extends Omit {
- key: string;
-}
-
-type FormattedTool = Record>;
-
export const useTools = () => {
const lifi = useLiFi();
const { bridges, exchanges } = useWidgetConfig();
const settingsStoreContext = useSettingsStoreContext();
- const { data } = useQuery(['tools'], () => lifi.getTools(), {
- onSuccess(data) {
- const { initializeTools } = settingsStoreContext.getState();
- initializeTools(
- 'Bridges',
- data.bridges
- .filter((bridge) => isItemAllowed(bridge.key, bridges))
- .map((bridge) => bridge.key),
- );
- initializeTools(
- 'Exchanges',
- data.exchanges
- .filter((exchange) => isItemAllowed(exchange.key, exchanges))
- .map((exchange) => exchange.key),
- );
+ const { data } = useQuery(
+ ['tools'],
+ async (): Promise => {
+ const tools = await lifi.getTools();
+ return {
+ bridges: tools.bridges.filter((bridge) =>
+ isItemAllowed(bridge.key, bridges),
+ ),
+ exchanges: tools.exchanges.filter((exchange) =>
+ isItemAllowed(exchange.key, exchanges),
+ ),
+ };
+ },
+ {
+ onSuccess(data) {
+ const { initializeTools } = settingsStoreContext.getState();
+ initializeTools(
+ 'Bridges',
+ data.bridges.map((bridge) => bridge.key),
+ );
+ initializeTools(
+ 'Exchanges',
+ data.exchanges.map((exchange) => exchange.key),
+ );
+ },
+ refetchInterval: 180000,
+ staleTime: 180000,
},
- refetchInterval: 180000,
- staleTime: 180000,
- });
-
- const formattedTools = useMemo(
- () => ({
- bridges: data?.bridges.reduce((bridges, bridge) => {
- bridges[bridge.key] = bridge;
- return bridges;
- }, {} as FormattedTool),
- exchanges: data?.exchanges.reduce((exchanges, exchange) => {
- exchanges[exchange.key] = exchange;
- return exchanges;
- }, {} as FormattedTool),
- }),
- [data?.bridges, data?.exchanges],
);
- return { tools: data, formattedTools };
+ return { tools: data };
};
diff --git a/packages/widget/src/i18n/en.json b/packages/widget/src/i18n/en.json
index 421d98bf5..c3fd3ea38 100644
--- a/packages/widget/src/i18n/en.json
+++ b/packages/widget/src/i18n/en.json
@@ -6,7 +6,6 @@
"contactSupport": "Contact support",
"continue": "Continue",
"copyAddress": "Copy address",
- "viewOnExplorer": "View on explorer",
"dark": "Dark",
"delete": "Delete",
"disconnect": "Disconnect",
@@ -19,6 +18,8 @@
"ok": "Ok",
"okay": "Okay",
"removeSwap": "Remove swap",
+ "reset": "Reset",
+ "resetSettings": "Reset settings",
"restartSwap": "Restart swap",
"reviewGasSwap": "Review gas swap",
"reviewSwap": "Review swap",
@@ -27,7 +28,8 @@
"startGasSwap": "Start gas swap",
"startSwap": "Start swap",
"swap": "Swap",
- "tryAgain": "Try again"
+ "tryAgain": "Try again",
+ "viewOnExplorer": "View on explorer"
},
"format": {
"currency": "{{value, currency(currency: USD)}}",
@@ -201,7 +203,8 @@
"highValueLoss": "The value of the received tokens is significantly lower than the swapped tokens and transaction cost.",
"insufficientFunds": "You don't have enough funds to execute the swap.",
"insufficientGas": "You need to add at least:",
- "rateChanged": "The exchange rate has changed. By continuing the swap, you'll accept the new rate."
+ "rateChanged": "The exchange rate has changed. By continuing the swap, you'll accept the new rate.",
+ "resetSettings": "This will reset your route priority, slippage, gas price, enabled bridges and exchanges."
},
"title": {
"deleteActiveSwaps": "Delete all active swaps?",
@@ -209,7 +212,8 @@
"deleteSwapHistory": "Delete swap history?",
"highValueLoss": "High value loss",
"insufficientGas": "Insufficient gas",
- "rateChanged": "Rate changed"
+ "rateChanged": "Rate changed",
+ "resetSettings": "Reset settings?"
}
}
},
diff --git a/packages/widget/src/pages/SelectChainPage/SelectChainPage.style.tsx b/packages/widget/src/pages/SelectChainPage/SelectChainPage.style.tsx
deleted file mode 100644
index 5b5fb66e6..000000000
--- a/packages/widget/src/pages/SelectChainPage/SelectChainPage.style.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import {
- ListItemButton as MuiListItemButton,
- ListItemText as MuiListItemText,
-} from '@mui/material';
-import { listItemTextClasses } from '@mui/material/ListItemText';
-import { styled } from '@mui/material/styles';
-import { getContrastAlphaColor } from '../../utils';
-
-export const ListItemButton = styled(MuiListItemButton)(({ theme }) => ({
- borderRadius: theme.shape.borderRadius,
- paddingLeft: theme.spacing(1.5),
- height: 56,
- '&:hover': {
- backgroundColor: getContrastAlphaColor(theme, '4%'),
- },
-}));
-
-export const ListItemText = styled(MuiListItemText)(({ theme }) => ({
- [`.${listItemTextClasses.primary}`]: {
- fontWeight: 400,
- },
-}));
diff --git a/packages/widget/src/pages/SelectChainPage/SelectChainPage.tsx b/packages/widget/src/pages/SelectChainPage/SelectChainPage.tsx
index b733a9f28..3e831f5e9 100644
--- a/packages/widget/src/pages/SelectChainPage/SelectChainPage.tsx
+++ b/packages/widget/src/pages/SelectChainPage/SelectChainPage.tsx
@@ -1,9 +1,10 @@
import type { ExtendedChain } from '@lifi/sdk';
import { Avatar, Container, List, ListItemAvatar } from '@mui/material';
import { useChainSelect } from '../../components/ChainSelect';
+import { ListItemButton } from '../../components/ListItemButton';
+import { ListItemText } from '../../components/ListItemText';
import { useTokenSelect } from '../../components/TokenList';
import { useNavigateBack } from '../../hooks';
-import { ListItemButton, ListItemText } from './SelectChainPage.style';
import type { SelectChainPageProps } from './types';
export const SelectChainPage: React.FC = ({
diff --git a/packages/widget/src/pages/SelectEnabledToolsPage/SelectEnabledToolsPage.style.tsx b/packages/widget/src/pages/SelectEnabledToolsPage/SelectEnabledToolsPage.style.tsx
new file mode 100644
index 000000000..b928bb82c
--- /dev/null
+++ b/packages/widget/src/pages/SelectEnabledToolsPage/SelectEnabledToolsPage.style.tsx
@@ -0,0 +1,6 @@
+import { styled } from '@mui/material/styles';
+import { ListItemButton as ListItemButtonBase } from '../../components/ListItemButton';
+
+export const ListItemButton = styled(ListItemButtonBase)(({ theme }) => ({
+ paddingRight: theme.spacing(1),
+}));
diff --git a/packages/widget/src/pages/SelectEnabledToolsPage/SelectEnabledToolsPage.tsx b/packages/widget/src/pages/SelectEnabledToolsPage/SelectEnabledToolsPage.tsx
new file mode 100644
index 000000000..b45e31c46
--- /dev/null
+++ b/packages/widget/src/pages/SelectEnabledToolsPage/SelectEnabledToolsPage.tsx
@@ -0,0 +1,105 @@
+import {
+ CheckBox,
+ CheckBoxOutlineBlankOutlined,
+ CheckBoxOutlined,
+ IndeterminateCheckBoxOutlined,
+} from '@mui/icons-material';
+import {
+ Avatar,
+ Container,
+ IconButton,
+ List,
+ ListItemAvatar,
+} from '@mui/material';
+import { useHeaderActionStore } from '../../components/Header';
+
+import { useEffect } from 'react';
+import { shallow } from 'zustand/shallow';
+import { ListItemText } from '../../components/ListItemText';
+import { useTools } from '../../hooks';
+import { useSettingsStore } from '../../stores';
+import { ListItemButton } from './SelectEnabledToolsPage.style';
+
+export const SelectEnabledToolsPage: React.FC<{
+ type: 'Bridges' | 'Exchanges';
+}> = ({ type }) => {
+ const typeKey = type.toLowerCase() as 'bridges' | 'exchanges';
+ const { tools } = useTools();
+ const [enabledTools, setTools] = useSettingsStore(
+ (state) => [state[`enabled${type}`], state.setTools],
+ shallow,
+ );
+
+ const handleClick = (key: string) => {
+ if (!tools) {
+ return;
+ }
+ const toolKeys = tools[typeKey].map((tool) => tool.key);
+ if (enabledTools?.includes(key)) {
+ setTools(
+ type,
+ enabledTools.filter((toolKey) => toolKey !== key),
+ toolKeys,
+ );
+ } else {
+ setTools(type, [...enabledTools, key], toolKeys);
+ }
+ };
+
+ useEffect(() => {
+ const allToolsSelected = tools?.[typeKey].length === enabledTools.length;
+ const toggleCheckboxes = () => {
+ if (!tools) {
+ return;
+ }
+ const toolKeys = tools[typeKey].map((tool) => tool.key);
+ if (allToolsSelected) {
+ setTools(type, [], toolKeys);
+ } else {
+ setTools(type, toolKeys, toolKeys);
+ }
+ };
+ return useHeaderActionStore.getState().setAction(
+
+ {allToolsSelected ? (
+
+ ) : enabledTools.length ? (
+
+ ) : (
+
+ )}
+ ,
+ );
+ }, [enabledTools.length, setTools, tools, type, typeKey]);
+
+ return (
+
+
+ {tools?.[typeKey].map((tool) => (
+ handleClick(tool.key)}
+ disableRipple
+ >
+
+
+ {tool.name[0]}
+
+
+
+ {enabledTools?.includes(tool.key) ? (
+
+ ) : (
+
+ )}
+
+ ))}
+
+
+ );
+};
diff --git a/packages/widget/src/pages/SelectEnabledToolsPage/index.ts b/packages/widget/src/pages/SelectEnabledToolsPage/index.ts
new file mode 100644
index 000000000..20bfe8d1b
--- /dev/null
+++ b/packages/widget/src/pages/SelectEnabledToolsPage/index.ts
@@ -0,0 +1 @@
+export * from './SelectEnabledToolsPage';
diff --git a/packages/widget/src/pages/SelectNativeTokenPage/SelectNativeTokenPage.style.tsx b/packages/widget/src/pages/SelectNativeTokenPage/SelectNativeTokenPage.style.tsx
deleted file mode 100644
index 5b5fb66e6..000000000
--- a/packages/widget/src/pages/SelectNativeTokenPage/SelectNativeTokenPage.style.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import {
- ListItemButton as MuiListItemButton,
- ListItemText as MuiListItemText,
-} from '@mui/material';
-import { listItemTextClasses } from '@mui/material/ListItemText';
-import { styled } from '@mui/material/styles';
-import { getContrastAlphaColor } from '../../utils';
-
-export const ListItemButton = styled(MuiListItemButton)(({ theme }) => ({
- borderRadius: theme.shape.borderRadius,
- paddingLeft: theme.spacing(1.5),
- height: 56,
- '&:hover': {
- backgroundColor: getContrastAlphaColor(theme, '4%'),
- },
-}));
-
-export const ListItemText = styled(MuiListItemText)(({ theme }) => ({
- [`.${listItemTextClasses.primary}`]: {
- fontWeight: 400,
- },
-}));
diff --git a/packages/widget/src/pages/SelectNativeTokenPage/SelectNativeTokenPage.tsx b/packages/widget/src/pages/SelectNativeTokenPage/SelectNativeTokenPage.tsx
index 30bd6d9fb..23eed0eaa 100644
--- a/packages/widget/src/pages/SelectNativeTokenPage/SelectNativeTokenPage.tsx
+++ b/packages/widget/src/pages/SelectNativeTokenPage/SelectNativeTokenPage.tsx
@@ -1,10 +1,11 @@
import { Container, List, ListItemAvatar } from '@mui/material';
import { useTranslation } from 'react-i18next';
+import { ListItemButton } from '../../components/ListItemButton';
+import { ListItemText } from '../../components/ListItemText';
import { TokenAvatar } from '../../components/TokenAvatar';
import { useTokenSelect } from '../../components/TokenList';
import { useChains, useNavigateBack } from '../../hooks';
import type { SwapFormTypeProps } from '../../providers';
-import { ListItemButton, ListItemText } from './SelectNativeTokenPage.style';
export const SelectNativeTokenPage: React.FC = ({
formType,
diff --git a/packages/widget/src/pages/SelectWalletPage/SelectWalletPage.style.tsx b/packages/widget/src/pages/SelectWalletPage/SelectWalletPage.style.tsx
deleted file mode 100644
index 5b5fb66e6..000000000
--- a/packages/widget/src/pages/SelectWalletPage/SelectWalletPage.style.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-import {
- ListItemButton as MuiListItemButton,
- ListItemText as MuiListItemText,
-} from '@mui/material';
-import { listItemTextClasses } from '@mui/material/ListItemText';
-import { styled } from '@mui/material/styles';
-import { getContrastAlphaColor } from '../../utils';
-
-export const ListItemButton = styled(MuiListItemButton)(({ theme }) => ({
- borderRadius: theme.shape.borderRadius,
- paddingLeft: theme.spacing(1.5),
- height: 56,
- '&:hover': {
- backgroundColor: getContrastAlphaColor(theme, '4%'),
- },
-}));
-
-export const ListItemText = styled(MuiListItemText)(({ theme }) => ({
- [`.${listItemTextClasses.primary}`]: {
- fontWeight: 400,
- },
-}));
diff --git a/packages/widget/src/pages/SelectWalletPage/SelectWalletPage.tsx b/packages/widget/src/pages/SelectWalletPage/SelectWalletPage.tsx
index abd751261..f034753e0 100644
--- a/packages/widget/src/pages/SelectWalletPage/SelectWalletPage.tsx
+++ b/packages/widget/src/pages/SelectWalletPage/SelectWalletPage.tsx
@@ -13,9 +13,10 @@ import {
import { useCallback, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Dialog } from '../../components/Dialog';
+import { ListItemButton } from '../../components/ListItemButton';
+import { ListItemText } from '../../components/ListItemText';
import { useNavigateBack } from '../../hooks';
import { useWallet } from '../../providers';
-import { ListItemButton, ListItemText } from './SelectWalletPage.style';
export const SelectWalletPage = () => {
const { t } = useTranslation();
diff --git a/packages/widget/src/pages/SettingsPage/AdvancedPreferences.tsx b/packages/widget/src/pages/SettingsPage/AdvancedPreferences.tsx
deleted file mode 100644
index f54b32e8d..000000000
--- a/packages/widget/src/pages/SettingsPage/AdvancedPreferences.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-import { Box, Typography } from '@mui/material';
-import type { ChangeEvent } from 'react';
-import { useTranslation } from 'react-i18next';
-import { Switch } from '../../components/Switch';
-import { useSettings, useSettingsStore } from '../../stores';
-import { EnabledBridgesSelect } from './EnabledBridgesSelect';
-import { EnabledExchangesSelect } from './EnabledExchangesSelect';
-
-export const AdvancedPreferences = () => {
- const { t } = useTranslation();
- const setValue = useSettingsStore((state) => state.setValue);
- const { advancedPreferences } = useSettings(['advancedPreferences']);
-
- const handleAdvancedPreferences = (
- _: ChangeEvent,
- checked: boolean,
- ) => {
- setValue('advancedPreferences', checked);
- };
-
- return (
-
-
-
-
- {t(`settings.advancedPreferences`)}
-
-
-
-
- {advancedPreferences && (
-
-
-
-
-
-
- )}
-
- );
-};
diff --git a/packages/widget/src/pages/SettingsPage/EnabledBridgesSelect.tsx b/packages/widget/src/pages/SettingsPage/EnabledBridgesSelect.tsx
deleted file mode 100644
index e8f362eea..000000000
--- a/packages/widget/src/pages/SettingsPage/EnabledBridgesSelect.tsx
+++ /dev/null
@@ -1,70 +0,0 @@
-import { KeyboardArrowDown as KeyboardArrowDownIcon } from '@mui/icons-material';
-import {
- Box,
- Checkbox,
- Chip,
- FormControl,
- MenuItem,
- Skeleton,
-} from '@mui/material';
-import { useTranslation } from 'react-i18next';
-import { shallow } from 'zustand/shallow';
-import { Card, CardTitle } from '../../components/Card';
-import { Select } from '../../components/Select';
-import { useTools } from '../../hooks';
-import { useSettingsStore } from '../../stores';
-
-export const EnabledBridgesSelect: React.FC = () => {
- const { t } = useTranslation();
- const { tools, formattedTools } = useTools();
- const [enabledBridges, setTools] = useSettingsStore(
- (state) => [state.enabledBridges, state.setTools],
- shallow,
- );
-
- return tools?.bridges.length ? (
-
- {t(`settings.enabledBridges`)}
-
-
-
-
- ) : (
-
- );
-};
diff --git a/packages/widget/src/pages/SettingsPage/EnabledExchangesSelect.tsx b/packages/widget/src/pages/SettingsPage/EnabledExchangesSelect.tsx
deleted file mode 100644
index cfaf7860a..000000000
--- a/packages/widget/src/pages/SettingsPage/EnabledExchangesSelect.tsx
+++ /dev/null
@@ -1,74 +0,0 @@
-import { KeyboardArrowDown as KeyboardArrowDownIcon } from '@mui/icons-material';
-import {
- Box,
- Checkbox,
- Chip,
- FormControl,
- MenuItem,
- Skeleton,
-} from '@mui/material';
-import { useTranslation } from 'react-i18next';
-import { shallow } from 'zustand/shallow';
-import { Card, CardTitle } from '../../components/Card';
-import { Select } from '../../components/Select';
-import { useTools } from '../../hooks';
-import { useSettingsStore } from '../../stores';
-
-export const EnabledExchangesSelect: React.FC = () => {
- const { t } = useTranslation();
- const { tools, formattedTools } = useTools();
- const [enabledExchanges, setTools] = useSettingsStore(
- (state) => [state.enabledExchanges, state.setTools],
- shallow,
- );
-
- return tools?.exchanges.length ? (
-
- {t(`settings.enabledExchanges`)}
-
-
-
-
- ) : (
-
- );
-};
diff --git a/packages/widget/src/pages/SettingsPage/EnabledToolsButton.style.tsx b/packages/widget/src/pages/SettingsPage/EnabledToolsButton.style.tsx
new file mode 100644
index 000000000..6d3f21fcc
--- /dev/null
+++ b/packages/widget/src/pages/SettingsPage/EnabledToolsButton.style.tsx
@@ -0,0 +1,16 @@
+import { ListItemText as MuiListItemText } from '@mui/material';
+import { listItemTextClasses } from '@mui/material/ListItemText';
+import { styled } from '@mui/material/styles';
+import { ListItemButton as ListItemButtonBase } from '../../components/ListItemButton';
+
+export const ListItemButton = styled(ListItemButtonBase)(({ theme }) => ({
+ height: 48,
+ paddingRight: theme.spacing(0.5),
+}));
+
+export const ListItemText = styled(MuiListItemText)({
+ [`.${listItemTextClasses.primary}`]: {
+ fontWeight: 400,
+ fontSize: '1rem',
+ },
+});
diff --git a/packages/widget/src/pages/SettingsPage/EnabledToolsButton.tsx b/packages/widget/src/pages/SettingsPage/EnabledToolsButton.tsx
new file mode 100644
index 000000000..df10c7785
--- /dev/null
+++ b/packages/widget/src/pages/SettingsPage/EnabledToolsButton.tsx
@@ -0,0 +1,33 @@
+import { ChevronRight as ChevronRightIcon } from '@mui/icons-material';
+import { Box } from '@mui/material';
+import { useTranslation } from 'react-i18next';
+import { useNavigate } from 'react-router-dom';
+import { shallow } from 'zustand/shallow';
+import { useSettingsStore } from '../../stores';
+import { navigationRoutes } from '../../utils';
+import { ListItemButton, ListItemText } from './EnabledToolsButton.style';
+
+export const EnabledToolsButton: React.FC<{
+ type: 'Bridges' | 'Exchanges';
+}> = ({ type }) => {
+ const { t } = useTranslation();
+ const navigate = useNavigate();
+ const [enabledTools, tools] = useSettingsStore((state) => {
+ const enabledTools = Object.values(state[`_enabled${type}`] ?? {});
+ return [enabledTools.filter((tool) => tool).length, enabledTools.length];
+ }, shallow);
+
+ const handleClick = () => {
+ navigate(navigationRoutes[type.toLowerCase() as 'bridges' | 'exchanges']);
+ };
+
+ return (
+
+
+
+
+
+
+
+ );
+};
diff --git a/packages/widget/src/pages/SettingsPage/ResetSettingsButton.tsx b/packages/widget/src/pages/SettingsPage/ResetSettingsButton.tsx
new file mode 100644
index 000000000..138141555
--- /dev/null
+++ b/packages/widget/src/pages/SettingsPage/ResetSettingsButton.tsx
@@ -0,0 +1,56 @@
+import {
+ Box,
+ Button,
+ DialogActions,
+ DialogContent,
+ DialogContentText,
+ DialogTitle,
+} from '@mui/material';
+import { useCallback, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { Dialog } from '../../components/Dialog';
+import { useTools } from '../../hooks';
+import { useSettingsStore } from '../../stores';
+
+export const ResetSettingsButton: React.FC = () => {
+ const { t } = useTranslation();
+ const { tools } = useTools();
+ const resetSettings = useSettingsStore((state) => state.reset);
+ const [open, setOpen] = useState(false);
+
+ const toggleDialog = useCallback(() => {
+ setOpen((open) => !open);
+ }, []);
+
+ const handleReset = () => {
+ if (tools) {
+ resetSettings(
+ tools.bridges.map((tool) => tool.key),
+ tools.exchanges.map((tool) => tool.key),
+ );
+ }
+ toggleDialog();
+ };
+
+ return (
+
+
+
+
+ );
+};
diff --git a/packages/widget/src/pages/SettingsPage/SettingsPage.tsx b/packages/widget/src/pages/SettingsPage/SettingsPage.tsx
index 5e06aec65..7df36d1b5 100644
--- a/packages/widget/src/pages/SettingsPage/SettingsPage.tsx
+++ b/packages/widget/src/pages/SettingsPage/SettingsPage.tsx
@@ -1,8 +1,9 @@
import { Box, Container } from '@mui/material';
-import { AdvancedPreferences } from './AdvancedPreferences';
import { ColorSchemeButtonGroup } from './ColorSchemeButtonGroup';
+import { EnabledToolsButton } from './EnabledToolsButton';
import { GasPriceSelect } from './GasPriceSelect';
import { LanguageSelect } from './LanguageSelect';
+import { ResetSettingsButton } from './ResetSettingsButton';
import { RoutePrioritySelect } from './RoutePrioritySelect';
import { ShowDestinationWallet } from './ShowDestinationWallet';
import { SlippageInput } from './SlippageInput';
@@ -22,7 +23,11 @@ export const SettingsPage = () => {
-
+
+
+
+
+
);
};
diff --git a/packages/widget/src/pages/SettingsPage/ShowDestinationWallet.tsx b/packages/widget/src/pages/SettingsPage/ShowDestinationWallet.tsx
index d5be13898..5dc87a6dc 100644
--- a/packages/widget/src/pages/SettingsPage/ShowDestinationWallet.tsx
+++ b/packages/widget/src/pages/SettingsPage/ShowDestinationWallet.tsx
@@ -29,7 +29,7 @@ export const ShowDestinationWallet = () => {
};
return (
-
+
create(
persist(
- (set) => ({
+ (set, get) => ({
...defaultSettings,
setValue: (key, value) =>
set(() => ({
@@ -40,14 +41,14 @@ export const createSettingsStore = ({ namePrefix }: PersistStoreProps) =>
}
return updatedState;
}),
- initializeTools: (toolType, tools) => {
+ initializeTools: (toolType, tools, reset) => {
if (!tools.length) {
return;
}
set((state) => {
const updatedState = { ...state };
- if (updatedState[`_enabled${toolType}`]) {
- // Add a new tools
+ if (updatedState[`_enabled${toolType}`] && !reset) {
+ // Add new tools
const enabledTools = tools
.filter(
(tool) =>
@@ -86,11 +87,22 @@ export const createSettingsStore = ({ namePrefix }: PersistStoreProps) =>
setTools: (toolType, tools, availableTools) =>
set(() => ({
[`enabled${toolType}`]: tools,
- [`_enabled${toolType}`]: availableTools.reduce((values, tool) => {
- values[tool.key] = tools.includes(tool.key);
- return values;
- }, {} as Record),
+ [`_enabled${toolType}`]: availableTools.reduce(
+ (values, toolKey) => {
+ values[toolKey] = tools.includes(toolKey);
+ return values;
+ },
+ {} as Record,
+ ),
})),
+ reset: (bridges, exchanges) => {
+ set(() => ({
+ ...defaultSettings,
+ ...defaultConfigurableSettings,
+ }));
+ get().initializeTools('Bridges', bridges, true);
+ get().initializeTools('Exchanges', exchanges, true);
+ },
}),
{
name: `${namePrefix || 'li.fi'}-widget-settings`,
diff --git a/packages/widget/src/stores/settings/types.ts b/packages/widget/src/stores/settings/types.ts
index 9c39cb162..b7e123c4a 100644
--- a/packages/widget/src/stores/settings/types.ts
+++ b/packages/widget/src/stores/settings/types.ts
@@ -1,4 +1,4 @@
-import type { Bridge, Exchange, Order } from '@lifi/sdk';
+import type { Order } from '@lifi/sdk';
import type { Appearance } from '../../types';
export type ValueSetter = (
@@ -14,28 +14,32 @@ export type SettingsToolType = 'Bridges' | 'Exchanges';
export const SettingsToolTypes: SettingsToolType[] = ['Bridges', 'Exchanges'];
export interface SettingsProps {
- advancedPreferences: boolean;
appearance: Appearance;
gasPrice?: string;
language?: string;
routePriority?: Order;
showDestinationWallet: boolean;
slippage?: string;
- enabledBridges?: string[];
+ enabledBridges: string[];
_enabledBridges?: Record;
- enabledExchanges?: string[];
+ enabledExchanges: string[];
_enabledExchanges?: Record;
}
export interface SettingsState extends SettingsProps {
setValue: ValueSetter;
setValues: ValuesSetter;
- initializeTools(toolType: SettingsToolType, tools: string[]): void;
+ initializeTools(
+ toolType: SettingsToolType,
+ tools: string[],
+ reset?: boolean,
+ ): void;
setTools(
toolType: SettingsToolType,
tools: string[],
- availableTools: (Pick | Pick)[],
+ availableTools: string[],
): void;
+ reset(bridges: string[], exchanges: string[]): void;
}
export interface SendToWalletState {
diff --git a/packages/widget/src/utils/navigationRoutes.ts b/packages/widget/src/utils/navigationRoutes.ts
index 5e5750561..aeecedbec 100644
--- a/packages/widget/src/utils/navigationRoutes.ts
+++ b/packages/widget/src/utils/navigationRoutes.ts
@@ -1,6 +1,8 @@
export const navigationRoutes = {
home: '/',
activeSwaps: 'active-swaps',
+ bridges: 'bridges',
+ exchanges: 'exchanges',
fromChain: 'from-chain',
fromToken: 'from-token',
selectWallet: 'wallet',
@@ -18,6 +20,8 @@ export const navigationRoutesValues = Object.values(navigationRoutes);
export const stickyHeaderRoutes = [
navigationRoutes.activeSwaps,
+ navigationRoutes.bridges,
+ navigationRoutes.exchanges,
navigationRoutes.fromChain,
navigationRoutes.home,
navigationRoutes.selectWallet,
@@ -32,6 +36,8 @@ export const stickyHeaderRoutes = [
export const backButtonRoutes = [
navigationRoutes.activeSwaps,
+ navigationRoutes.bridges,
+ navigationRoutes.exchanges,
navigationRoutes.fromChain,
navigationRoutes.fromToken,
navigationRoutes.selectWallet,