Skip to content

Commit

Permalink
feat: add details to route cards
Browse files Browse the repository at this point in the history
  • Loading branch information
chybisov committed May 18, 2022
1 parent a637ca0 commit bbd5926
Show file tree
Hide file tree
Showing 13 changed files with 268 additions and 134 deletions.
6 changes: 4 additions & 2 deletions packages/widget-embedded/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ const root = createRoot(rootElement);

const config: WidgetConfig = {
enabledChains: JSON.parse(process.env.LIFI_ENABLED_CHAINS_JSON!),
fromChain: 'eth',
// toChain: 'okt',
fromChain: 'pol',
toChain: 'bsc',
fromToken: '0x0000000000000000000000000000000000000000',
toToken: '0xcc42724c6683b7e57334c4e856f4c9965ed682bd',
useInternalWalletManagement: true,
containerStyle: {
width: 480,
Expand Down
43 changes: 43 additions & 0 deletions packages/widget/src/components/StepActions/StepActions.style.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import {
StepConnector as MuiStepConnector,
StepContent as MuiStepContent,
StepLabel as MuiStepLabel,
} from '@mui/material';
import { stepConnectorClasses } from '@mui/material/StepConnector';
import { stepContentClasses } from '@mui/material/StepContent';
import { stepLabelClasses } from '@mui/material/StepLabel';
import { styled } from '@mui/material/styles';

export const StepIcon = styled('span')(({ theme }) => ({
width: 12,
height: 12,
borderRadius: '50%',
border: `2px solid ${theme.palette.grey[300]}`,
}));

export const StepConnector = styled(MuiStepConnector)(({ theme }) => ({
marginLeft: theme.spacing(1.875),
[`.${stepConnectorClasses.line}`]: {
minHeight: 8,
borderLeftWidth: 2,
borderColor: theme.palette.grey[300],
},
}));

export const StepLabel = styled(MuiStepLabel)(({ theme }) => ({
padding: 0,
[`.${stepLabelClasses.iconContainer}`]: {
paddingLeft: theme.spacing(1),
paddingRight: theme.spacing(3),
},
}));

export const StepContent = styled(MuiStepContent)(({ theme }) => ({
borderLeft: `2px solid ${theme.palette.grey[300]}`,
marginLeft: theme.spacing(1.875),
paddingLeft: theme.spacing(3.9375),
[`&.${stepContentClasses.last}`]: {
borderLeft: 'none',
paddingLeft: theme.spacing(4.1875),
},
}));
150 changes: 150 additions & 0 deletions packages/widget/src/components/StepActions/StepActions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { LifiStep, Step } from '@lifinance/sdk';
import { ArrowForward as ArrowForwardIcon } from '@mui/icons-material';
import {
Avatar,
Box,
Step as MuiStep,
Stepper,
Typography,
TypographyProps,
} from '@mui/material';
import { useTranslation } from 'react-i18next';
import { useChains } from '../../hooks';
import LiFiLogo from '../../icons/LiFiLogo.svg';
import { formatTokenAmount } from '../../utils/format';
import {
StepConnector,
StepContent,
StepIcon,
StepLabel,
} from './StepActions.style';
import { StepActionsProps } from './types';

export const StepActions: React.FC<StepActionsProps> = ({
step,
dense,
...other
}) => {
const StepDetailsLabel =
step.type === 'cross' || step.type === 'lifi'
? CrossStepDetailsLabel
: SwapStepDetailsLabel;
const isFullView = !dense && (step as LifiStep).includedSteps?.length;
return (
<Box {...other}>
<Box
sx={{ display: 'flex', alignItems: 'center' }}
mb={isFullView ? 1 : 0}
>
<Avatar
variant={step.type === 'lifi' ? 'square' : 'circular'}
src={step.type === 'lifi' ? LiFiLogo : step.toolDetails.logoURI}
alt={step.toolDetails.name}
>
{step.toolDetails.name[0]}
</Avatar>
<Typography
ml={2}
fontSize={18}
fontWeight="500"
textTransform="capitalize"
>
{step.type === 'lifi'
? 'LI.FI Smart Contract'
: step.toolDetails.name}
</Typography>
</Box>
{isFullView ? (
<Stepper
orientation="vertical"
connector={<StepConnector />}
activeStep={-1}
>
{(step as LifiStep).includedSteps.map((step) => (
<MuiStep key={step.id} expanded>
<StepLabel StepIconComponent={StepIcon}>
<StepDetailsLabel step={step} />
</StepLabel>
<StepContent>
<StepDetailsContent step={step} />
</StepContent>
</MuiStep>
))}
</Stepper>
) : (
<>
<StepDetailsLabel ml={6} step={step} />
<StepDetailsContent ml={6} step={step} />
</>
)}
</Box>
);
};

export const StepDetailsContent: React.FC<{ step: Step } & TypographyProps> = ({
step,
...other
}) => {
return (
<Typography
fontSize={12}
fontWeight="500"
color="text.secondary"
alignItems="center"
display="flex"
{...other}
>
{formatTokenAmount(
step.estimate.fromAmount,
step.action.fromToken.decimals,
)}{' '}
{step.action.fromToken.symbol}
<ArrowForwardIcon sx={{ fontSize: '.75rem', paddingX: 0.5 }} />
{formatTokenAmount(
step.estimate.toAmount,
step.action.toToken.decimals,
)}{' '}
{step.action.toToken.symbol}
</Typography>
);
};

export const CrossStepDetailsLabel: React.FC<
{ step: Step } & TypographyProps
> = ({ step, ...other }) => {
const { t } = useTranslation();
const { getChainById } = useChains();

return (
<Typography
fontSize={12}
fontWeight="500"
color="text.secondary"
{...other}
>
{t('swapping.crossStepDetails', {
from: getChainById(step.action.fromChainId)?.name,
to: getChainById(step.action.toChainId)?.name,
tool: step.toolDetails.name,
})}
</Typography>
);
};

export const SwapStepDetailsLabel: React.FC<
{ step: Step } & TypographyProps
> = ({ step, ...other }) => {
const { t } = useTranslation();
return (
<Typography
fontSize={12}
fontWeight="500"
color="text.secondary"
{...other}
>
{t('swapping.swapStepDetails', {
value: step.toolDetails.name,
})}
</Typography>
);
};
1 change: 1 addition & 0 deletions packages/widget/src/components/StepActions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { StepActions } from './StepActions';
7 changes: 7 additions & 0 deletions packages/widget/src/components/StepActions/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Step } from '@lifinance/sdk';
import { BoxProps } from '@mui/material';

export interface StepActionsProps extends BoxProps {
step: Step;
dense?: boolean;
}
54 changes: 39 additions & 15 deletions packages/widget/src/components/SwapRouteCard/SwapRouteCard.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,49 @@
import { Box, BoxProps, Typography } from '@mui/material';
import { Avatar, Box, BoxProps, Typography } from '@mui/material';
import { useTranslation } from 'react-i18next';
import { formatTokenAmount } from '../../utils/format';
import { StepActions } from '../StepActions';
import { Card, Label } from './SwapRouteCard.style';
import { SwapRouteCardProps } from './types';

export const SwapRouteCard: React.FC<SwapRouteCardProps & BoxProps> = ({
amount,
token,
time,
gas,
route,
index,
active,
type,
dense,
...other
}) => {
const { t } = useTranslation();
return (
<Card active={active} {...other}>
<Box>
<Label active={active} mb={2}>
{type}
ROUTE {index + 1}
</Label>
<Typography fontSize={32} fontWeight="bold" lineHeight="normal">
{amount}
</Typography>
<Typography fontSize={14} mb={2} color="text.secondary">
{token}
</Typography>
<Box
sx={{
display: 'flex',
}}
mb={2}
>
<Avatar
src={route.toToken.logoURI}
alt={route.toToken.symbol}
sx={{ marginRight: 2, paddingY: 0.375 }}
>
{route.toToken.symbol[0]}
</Avatar>
<Box>
<Typography fontSize={32} fontWeight="bold" lineHeight="normal">
{formatTokenAmount(route.toAmount, route.toToken.decimals)}
</Typography>
<Typography fontSize={14} color="text.secondary">
{route.toToken.symbol}
</Typography>
</Box>
</Box>
{!dense
? route.steps.map((step) => <StepActions step={step} mb={2} />)
: null}
<Box
sx={{
display: 'flex',
Expand All @@ -33,15 +52,20 @@ export const SwapRouteCard: React.FC<SwapRouteCardProps & BoxProps> = ({
>
<Box>
<Typography fontSize={18} fontWeight="500">
{gas}
{t(`swap.currency`, { value: route.gasCostUSD })}
</Typography>
<Typography fontSize={12} color="text.secondary">
{t(`swap.gas`)}
</Typography>
</Box>
<Box>
<Typography fontSize={18} fontWeight="500">
~{time}
~
{(
route.steps
.map((step) => step.estimate.executionDuration)
.reduce((cumulated, x) => cumulated + x) / 60
).toFixed(0)}
</Typography>
<Typography fontSize={12} color="text.secondary" textAlign="end">
{t(`swap.minutes`)}
Expand Down
10 changes: 5 additions & 5 deletions packages/widget/src/components/SwapRouteCard/types.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Route } from '@lifinance/sdk';

export interface SwapRouteCardProps {
amount: string | number;
token: string;
time: string;
gas: string;
type: 'recommended' | 'fastest' | 'cheapest';
route: Route;
index: number;
dense?: boolean;
active?: boolean;
blur?: boolean;
}
30 changes: 10 additions & 20 deletions packages/widget/src/components/SwapRoutes/SwapRoutes.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
/* eslint-disable react/no-array-index-key */
import { KeyboardArrowRight as KeyboardArrowRightIcon } from '@mui/icons-material';
import { Box, BoxProps, IconButton, Skeleton } from '@mui/material';
import { Box, BoxProps, Skeleton } from '@mui/material';
import { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { useSwapRoutes } from '../../hooks';
import { formatTokenAmount } from '../../utils/format';
import { routes } from '../../utils/routes';
import { CardContainer, CardTitle } from '../Card';
import { SwapRouteCard } from '../SwapRouteCard';
Expand All @@ -15,9 +14,9 @@ export const SwapRoutes: React.FC<BoxProps> = ({ mb }) => {
const navigate = useNavigate();
const { routes: swapRoutes, isLoading } = useSwapRoutes();

const handleCardClick = () => {
const handleCardClick = useCallback(() => {
navigate(routes.swapRoutes);
};
}, [navigate]);

if (!swapRoutes?.length && !isLoading) {
return null;
Expand All @@ -44,25 +43,16 @@ export const SwapRoutes: React.FC<BoxProps> = ({ mb }) => {
<SwapRouteCard
key={route.id}
onClick={index !== 0 ? handleCardClick : undefined}
minWidth="75%"
amount={formatTokenAmount(
route.toAmount,
route.toToken.decimals,
)}
token={route.toToken.name}
gas={t(`swap.currency`, { value: route.gasCostUSD })}
time={(
route.steps
.map((step) => step.estimate.executionDuration)
.reduce((cumulated, x) => cumulated + x) / 60
).toFixed(0)}
type={index === 0 ? 'recommended' : 'fastest'}
minWidth="80%"
route={route}
index={index}
active={index === 0}
blur={index !== 0}
dense
/>
))}
</Stack>
<Box p={1}>
{/* <Box p={1}>
<IconButton
onClick={handleCardClick}
size="medium"
Expand All @@ -71,7 +61,7 @@ export const SwapRoutes: React.FC<BoxProps> = ({ mb }) => {
>
<KeyboardArrowRightIcon />
</IconButton>
</Box>
</Box> */}
</Box>
</CardContainer>
);
Expand Down
6 changes: 3 additions & 3 deletions packages/widget/src/hooks/useSwapRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,10 @@ export const useSwapRoutes = () => {
{
enabled: isEnabled,
refetchIntervalInBackground: true,
refetchInterval: 30_000,
staleTime: 30_000,
refetchInterval: 30000000,
staleTime: 30000000,
// TODO: probably should be removed
cacheTime: 30_000,
cacheTime: 30000000,
},
);

Expand Down
Loading

0 comments on commit bbd5926

Please sign in to comment.