Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add funds routes view #2216

Draft
wants to merge 28 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
ad7780a
Remove Swap from options drawer
mimi-imtbl Sep 19, 2024
e4ed511
Fix card options captions
mimi-imtbl Sep 19, 2024
832efde
Fetch routes
mimi-imtbl Sep 19, 2024
2864e11
Clean up useSquid
mimi-imtbl Sep 23, 2024
8ffff8d
Set isCheckNetworkEnabled for add funds widget
mimi-imtbl Sep 23, 2024
e73fa61
Add FiatOptionType
mimi-imtbl Sep 23, 2024
7fa9056
Add FiatOption
mimi-imtbl Sep 23, 2024
f258866
Fetch routes
mimi-imtbl Sep 24, 2024
8e82a7d
Render routes
mimi-imtbl Sep 24, 2024
8240fb3
Clean up
mimi-imtbl Sep 24, 2024
9cc8e73
Merge branch 'main' into add-funds-routes-view
mimi-imtbl Sep 24, 2024
f52a054
Fix handle route fn
mimi-imtbl Sep 24, 2024
58a39fe
Merge branch 'main' into add-funds-routes-view
mimi-imtbl Sep 25, 2024
eb06576
Initialise balances to null
mimi-imtbl Sep 25, 2024
93b0650
Initialise routes to undefined
mimi-imtbl Sep 25, 2024
3cd2f14
Open drawer while fetching routes
mimi-imtbl Sep 25, 2024
ad69ad3
Clean up Options
mimi-imtbl Sep 25, 2024
9c8ee65
Remove check for squid before drawer
mimi-imtbl Sep 25, 2024
738d464
Initialise chains to null
mimi-imtbl Sep 26, 2024
410b58c
Add function to convert balance to usd
mimi-imtbl Sep 26, 2024
53dbe72
Add logic to format balances
mimi-imtbl Sep 26, 2024
47f2237
Clean up
mimi-imtbl Sep 26, 2024
e3d1a82
Use convert function
mimi-imtbl Sep 26, 2024
b33c81a
Add function to sort routes by the fastest estimated time
mimi-imtbl Sep 26, 2024
129de41
Display fastest route
mimi-imtbl Sep 26, 2024
0f71316
Add placeholder loading overlay
mimi-imtbl Sep 26, 2024
31c1ae1
Merge
mimi-imtbl Sep 26, 2024
e2de560
Merge branch 'main' into add-funds-routes-view
mimi-imtbl Sep 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions packages/checkout/widgets-lib/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -643,19 +643,14 @@
"ADD_FUNDS": {
"drawer": {
"options": {
"swap": {
"heading": "Swap",
"caption": "Swap tokens on this network.",
"disabledCaption": "Currently not available."
},
"debit": {
"heading": "Debit Card",
"caption": "The recommended way to pay with card.",
"caption": "The recommended way to add funds with card",
"disabledCaption": "Unavailable for your selection. We recommend adding tokens."
},
"credit": {
"heading": "Credit Card",
"caption": "Not recommended since transactions may be blocked by your bank.",
"caption": "Not recommended due to failure rates & charges",
"disabledCaption": "Unavailable for your selection. We recommend adding tokens."
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ export class AddFunds extends Base<WidgetType.ADD_FUNDS> {
getL1ChainId(this.checkout.config),
getL2ChainId(this.checkout.config),
],
isCheckNetworkEnabled: false,
};

this.reactRoot.render(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,43 +1,103 @@
import { Box, MenuItemSize } from '@biom3/react';

import {
Box, LoadingOverlay, MenuItemSize,
} from '@biom3/react';
import { motion } from 'framer-motion';
import { useMemo } from 'react';
import { TokenBalance } from '@0xsquid/sdk/dist/types';
import {
listItemVariants,
listVariants,
} from '../../../lib/animation/listAnimation';
import { Option, OptionTypes } from './Option';
import { FiatOption } from './FiatOption';
import { Chain, FiatOptionType, RouteData } from '../types';
import { RouteOption } from './RouteOption';
import { convertTokenBalanceToUsd } from '../functions/convertTokenBalanceToUsd';
import { sortRoutesByFastestTime } from '../functions/sortRoutesByFastestTime';

const defaultOptions: OptionTypes[] = [
OptionTypes.SWAP,
OptionTypes.DEBIT,
OptionTypes.CREDIT,
const defaultFiatOptions: FiatOptionType[] = [
FiatOptionType.DEBIT,
FiatOptionType.CREDIT,
];

export interface OptionsProps {
onClick: (type: OptionTypes) => void;
disabledOptions?: OptionTypes[];
options?: OptionTypes[];
captions?: Partial<Record<OptionTypes, string>>;
chains: Chain[] | null;
balances: TokenBalance[] | null;
onCardClick?: (type: FiatOptionType) => void;
onRouteClick?: (route: RouteData) => void;
routes?: RouteData[];
size?: MenuItemSize;
hideDisabledOptions?: boolean;
showOnrampOption?: boolean;
}

export function Options(props: OptionsProps) {
const {
disabledOptions = [],
options,
onClick,
captions,
size,
hideDisabledOptions,
} = props;
const filteredOptions = useMemo(
() => (options || defaultOptions).filter(
(option) => !hideDisabledOptions || !disabledOptions.includes(option),
),
[options, disabledOptions, hideDisabledOptions],
);
export function Options({
routes,
chains,
balances,
onCardClick,
onRouteClick,
size,
showOnrampOption,
}: OptionsProps) {
const getUsdBalance = (balance: TokenBalance | undefined, route: RouteData) => {
if (!balance) return undefined;

try {
return convertTokenBalanceToUsd(balance, route.route)?.toString();
} catch (error) {
// eslint-disable-next-line no-console
console.error('Error calculating USD balance:', error);
return undefined;
}
};

const sortedRoutes = sortRoutesByFastestTime(routes);

if (!sortedRoutes) {
return (
<LoadingOverlay visible>
<LoadingOverlay.Content>
<LoadingOverlay.Content.LoopingText
text={['Fetching balances', 'Fetching routes']}
textDuration={5000}
/>
</LoadingOverlay.Content>
</LoadingOverlay>
);
}

const routeOptions = sortedRoutes.map((route: RouteData) => {
const { fromToken } = route.amountData;

const chain = chains?.find((c) => c.id === fromToken.chainId);
const balance = balances?.find(
(bal) => bal.address === fromToken.address && bal.chainId === fromToken.chainId,
);

const usdBalance = getUsdBalance(balance, route);

return (
<RouteOption
key={`route-option-${fromToken.chainId}-${fromToken.address}`}
chain={chain}
route={route}
usdBalance={usdBalance}
onClick={onRouteClick}
size={size}
rc={<motion.div variants={listItemVariants} />}
/>
);
});

const fiatOptions = showOnrampOption
? defaultFiatOptions.map((type, idx) => (
<FiatOption
key={`fiat-option-${type}`}
type={type}
size={size}
onClick={onCardClick}
rc={<motion.div custom={idx} variants={listItemVariants} />}
/>
))
: null;

return (
<Box
Expand All @@ -49,21 +109,10 @@ export function Options(props: OptionsProps) {
justifyContent: 'center',
alignItems: 'flex-start',
}}
rc={
<motion.div variants={listVariants} initial="hidden" animate="show" />
}
rc={<motion.div variants={listVariants} initial="hidden" animate="show" />}
>
{filteredOptions.map((type, idx: number) => (
<Option
key={`option-type-${type}`}
type={type}
size={size}
onClick={onClick}
disabled={disabledOptions.includes(type)}
caption={captions?.[type]}
rc={<motion.div custom={idx} variants={listItemVariants} />}
/>
))}
{routeOptions}
{fiatOptions}
</Box>
);
}
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
import { Box, Drawer } from '@biom3/react';
import { motion } from 'framer-motion';
import { useContext } from 'react';
import { listVariants } from '../../../lib/animation/listAnimation';
import { Options } from './Options';
import { OptionTypes } from './Option';
import { FiatOptionType, RouteData } from '../types';
import { AddFundsContext } from '../context/AddFundsContext';

type OptionsDrawerProps = {
routes: RouteData[] | undefined;
visible: boolean;
onClose: () => void;
onRouteClick: (route: RouteData | undefined) => void;
onCardClick: (type: FiatOptionType) => void;
showOnrampOption?: boolean;
showSwapOption?: boolean;
showBridgeOption?: boolean;
visible: boolean;
onClose: () => void;
onPayWithCard?: (paymentType: OptionTypes) => void;
};

export function OptionsDrawer({
routes,
visible,
onClose,
onRouteClick,
onCardClick,
showOnrampOption,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
showSwapOption,
// eslint-disable-next-line @typescript-eslint/no-unused-vars
showBridgeOption,
visible,
onClose,
onPayWithCard,
}: OptionsDrawerProps) {
const disabledOptions: OptionTypes[] = [];
if (!showOnrampOption) {
disabledOptions.push(OptionTypes.CREDIT);
disabledOptions.push(OptionTypes.DEBIT);
}
if (!showSwapOption) {
disabledOptions.push(OptionTypes.SWAP);
}
const {
addFundsState: { chains, balances },
} = useContext(AddFundsContext);

return (
<Drawer
Expand All @@ -42,7 +44,7 @@ export function OptionsDrawer({
<Drawer.Content
rc={
<motion.div variants={listVariants} initial="hidden" animate="show" />
}
}
>
<Box
sx={{
Expand All @@ -54,21 +56,13 @@ export function OptionsDrawer({
}}
>
<Options
onClick={onPayWithCard ?? (() => {
})}
size="medium"
hideDisabledOptions
options={[
OptionTypes.SWAP,
OptionTypes.DEBIT,
OptionTypes.CREDIT,
]}
disabledOptions={disabledOptions}
captions={{
[OptionTypes.SWAP]: 'Swap',
[OptionTypes.DEBIT]: 'Debit',
[OptionTypes.CREDIT]: 'Credit',
}}
routes={routes}
chains={chains}
balances={balances}
onCardClick={onCardClick}
onRouteClick={onRouteClick}
showOnrampOption={showOnrampOption}
/>
</Box>
</Drawer.Content>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { delay } from '../functions/delay';
import { AmountData, RouteData } from '../types';

export const useRoutes = () => {
const [routes, setRoutes] = useState<RouteData[]>([]);
const [routes, setRoutes] = useState<RouteData[] | undefined>(undefined);

const getFromAmount = async (
squid: Squid,
Expand Down
Loading