diff --git a/packages/checkout/widgets-lib/src/widgets/add-funds/AddFundsWidget.tsx b/packages/checkout/widgets-lib/src/widgets/add-funds/AddFundsWidget.tsx index 770accaf9a..6d1c226a42 100644 --- a/packages/checkout/widgets-lib/src/widgets/add-funds/AddFundsWidget.tsx +++ b/packages/checkout/widgets-lib/src/widgets/add-funds/AddFundsWidget.tsx @@ -90,10 +90,14 @@ export default function AddFundsWidget({ chainIds, evmAddress: fromAddress, }); + const filteredBalances = balances?.evmBalances?.filter( + (balance) => balance.balance !== '0', + ); + addFundsDispatch({ payload: { type: AddFundsActions.SET_BALANCES, - balances: balances?.evmBalances ?? [], + balances: filteredBalances ?? [], }, }); })(); @@ -140,7 +144,6 @@ export default function AddFundsWidget({ {viewState.view.type === AddFundsWidgetViews.ADD_FUNDS && ( new Promise((resolve) => { + setTimeout(resolve, ms); +}); diff --git a/packages/checkout/widgets-lib/src/widgets/add-funds/hooks/useRoutes.ts b/packages/checkout/widgets-lib/src/widgets/add-funds/hooks/useRoutes.ts index a896337ec9..d6a46116de 100644 --- a/packages/checkout/widgets-lib/src/widgets/add-funds/hooks/useRoutes.ts +++ b/packages/checkout/widgets-lib/src/widgets/add-funds/hooks/useRoutes.ts @@ -1,73 +1,98 @@ -/* eslint-disable no-console */ import { TokenBalance } from '@0xsquid/sdk/dist/types'; import { RouteResponse, Token } from '@0xsquid/squid-types'; import { Squid } from '@0xsquid/sdk'; import { utils } from 'ethers'; import { useState } from 'react'; - -const delay = (ms: number) => new Promise((resolve) => { - setTimeout(resolve, ms); -}); - -export type AmountData = { - fromAmount: string; - fromToken: Token; - toToken: Token; - toAmount: string; - balance: TokenBalance; -}; - -export type RouteData = { - amountData: AmountData; - route: RouteResponse; -}; +import { delay } from '../functions/delay'; +import { AmountData, RouteData } from '../types'; export const useRoutes = () => { const [routes, setRoutes] = useState([]); - const getFromAmounts = ( + const getFromAmount = async ( + squid: Squid, + balance: TokenBalance, + toAmount: string, + toChainId: string, + toTokenAddress: string, + ): Promise => { + const fromTokenData = squid?.getTokenData( + balance.address, + balance.chainId.toString(), + ); + const toTokenData = squid?.getTokenData(toTokenAddress, toChainId); + + if (!fromTokenData || !toTokenData) { + return undefined; + } + + try { + const fromAmount = await squid.getFromAmount({ + fromToken: fromTokenData, + toToken: toTokenData, + toAmount, + }); + + return { + fromAmount, + fromToken: fromTokenData, + toToken: toTokenData, + toAmount, + balance, + }; + } catch (error) { + return undefined; + } + }; + + const getSufficientFromAmounts = async ( squid: Squid, balances: TokenBalance[], - toChanId: string, + toChainId: string, toTokenAddress: string, toAmount: string, - ): Promise[] => { + bulkNumber: number, + delayMs: number, + ): Promise => { const filteredBalances = balances.filter( - (balance) => balance.address !== toTokenAddress, + (balance) => !(balance.address === toTokenAddress && balance.chainId === toChainId), ); - return filteredBalances.map( - (balance: TokenBalance): Promise => { - const fromTokenData = squid?.getTokenData( - balance.address, - balance.chainId.toString(), - ); - const toTokenData = squid?.getTokenData(toTokenAddress, toChanId); - - if (!fromTokenData || !toTokenData) { - console.log('tokenData not found', fromTokenData, toTokenData); - return Promise.resolve(undefined); - } - - return squid - .getFromAmount({ - fromToken: fromTokenData, - toToken: toTokenData, - toAmount, - }) - .then((fromAmount: string) => ({ - fromAmount, - fromToken: fromTokenData, - toToken: toTokenData, - toAmount, - balance, - })) - .catch((error) => { - console.log('error', error); - return Promise.resolve(undefined); - }); + const result :AmountData[] = []; + + for (let i = 0; i < filteredBalances.length; i += bulkNumber) { + const promises = filteredBalances.slice(i, i + bulkNumber).map( + (balance) => getFromAmount( + squid, + balance, + toAmount, + toChainId, + toTokenAddress, + ), + ); + + // eslint-disable-next-line no-await-in-loop + const amountsData = await Promise.all(promises); + + const filteredAmountsData = amountsData.filter( + (amountData): amountData is AmountData => amountData !== undefined, + ); + + if (filteredAmountsData.length > 0) { + result.push(...filteredAmountsData); + } + + // eslint-disable-next-line no-await-in-loop + await delay(delayMs); + } + + const filteredAmountData = result.filter( + (data: AmountData) => { + const formattedBalance = utils.formatUnits(data.balance.balance, data.balance.decimals); + return parseFloat(formattedBalance.toString()) > parseFloat(data.fromAmount); }, ); + return filteredAmountData; }; const getRoute = async ( @@ -77,66 +102,93 @@ export const useRoutes = () => { toAmount: string, toAddress: string, quoteOnly = true, - ): Promise => { - const fromAmount = await squid.getFromAmount({ - fromToken, - toToken, - toAmount, - }); + ): Promise => { + try { + const fromAmount = await squid.getFromAmount({ + fromToken, + toToken, + toAmount, + }); + + const parsedFromAmount = parseFloat(fromAmount).toFixed(fromToken.decimals); + const formattedFromAmount = utils.parseUnits( + parsedFromAmount, + fromToken.decimals, + ); + + const route = await squid.getRoute({ + fromChain: fromToken.chainId, + fromToken: fromToken.address, + fromAmount: formattedFromAmount.toString(), + toChain: toToken.chainId, + toToken: toToken.address, + toAddress, + quoteOnly, + enableBoost: true, + }); + + return route; + } catch (error) { + return undefined; + } + }; - const parsedFromAmount = parseFloat(fromAmount).toFixed(fromToken.decimals); - const formattedFromAmount = utils.parseUnits( - parsedFromAmount, - fromToken.decimals, + const getRoutes = async ( + squid: Squid, + amountDataArray: AmountData[], + toTokenAddress: string, + ): Promise => { + const routePromises = amountDataArray.map( + (data) => getRoute( + squid, + data.fromToken, + data.toToken, + data.toAmount, + toTokenAddress, + ).then((route) => ({ + amountData: data, + route, + })), ); - return squid.getRoute({ - fromChain: fromToken.chainId, - fromToken: fromToken.address, - fromAmount: formattedFromAmount.toString(), - toChain: toToken.chainId, - toToken: toToken.address, - toAddress, - quoteOnly, - enableBoost: true, - }); + const routesData = await Promise.all(routePromises); + return routesData.filter((route): route is RouteData => route !== undefined); }; - const getRoutes = async ( + const fetchRoutesWithRateLimit = async ( squid: Squid, balances: TokenBalance[], toChanId: string, toTokenAddress: string, toAmount: string, - ) => { - const getAmountData = await Promise.all( - getFromAmounts(squid, balances, toChanId, toTokenAddress, toAmount), + bulkNumber = 5, + delayMs = 1000, + ):Promise => { + const amountDataArray = await getSufficientFromAmounts( + squid, + balances, + toChanId, + toTokenAddress, + toAmount, + 10, + 1000, ); - const filteredAmountData = getAmountData.filter( - (amountData) => amountData !== undefined, - ) as AmountData[]; - delay(2000); + const allRoutes: RouteData[] = []; - const getRoutePromises = filteredAmountData.map((data: AmountData): Promise => getRoute( - squid, - data.fromToken, - data.toToken, - data.toAmount, - toTokenAddress, - ).then((route) => ({ - amountData: data, - route, - })).catch((error) => { - console.log('error', error); - return Promise.resolve(undefined); - })); - - const getRouteData = await Promise.all(getRoutePromises); - const routesData = getRouteData.filter((routeData) => routeData !== undefined) as RouteData[]; - setRoutes(routesData); - return routesData; + for (let i = 0; i < amountDataArray.length; i += bulkNumber) { + const slicedAmountDataArray = amountDataArray.slice(i, i + bulkNumber); + + // eslint-disable-next-line no-await-in-loop + allRoutes.push(...await getRoutes(squid, slicedAmountDataArray, toTokenAddress)); + + // eslint-disable-next-line no-await-in-loop + await delay(delayMs); + } + + setRoutes(allRoutes); + return allRoutes; }; - return { routes, getRoutes, getRoute }; + return { routes, fetchRoutesWithRateLimit }; }; diff --git a/packages/checkout/widgets-lib/src/widgets/add-funds/types.ts b/packages/checkout/widgets-lib/src/widgets/add-funds/types.ts index 895810afe3..ce5c8bad7b 100644 --- a/packages/checkout/widgets-lib/src/widgets/add-funds/types.ts +++ b/packages/checkout/widgets-lib/src/widgets/add-funds/types.ts @@ -1,6 +1,22 @@ +import { TokenBalance } from '@0xsquid/sdk/dist/types'; +import { RouteResponse, Token } from '@0xsquid/squid-types'; + export type Chain = { id: string; type: string; name: string; iconUrl: string; }; + +export type AmountData = { + fromToken: Token; + fromAmount: string; + toToken: Token; + toAmount: string; + balance: TokenBalance; +}; + +export type RouteData = { + amountData: AmountData; + route: RouteResponse; +}; diff --git a/packages/checkout/widgets-lib/src/widgets/add-funds/views/AddFunds.tsx b/packages/checkout/widgets-lib/src/widgets/add-funds/views/AddFunds.tsx index 34f0f27322..6d0c1e7f93 100644 --- a/packages/checkout/widgets-lib/src/widgets/add-funds/views/AddFunds.tsx +++ b/packages/checkout/widgets-lib/src/widgets/add-funds/views/AddFunds.tsx @@ -1,5 +1,3 @@ -/* eslint-disable no-console */ -import { Web3Provider } from '@ethersproject/providers'; import { Checkout, IMTBLWidgetEvents, @@ -30,7 +28,6 @@ import { interface AddFundsProps { checkout?: Checkout; - provider?: Web3Provider; showBackButton?: boolean; showOnrampOption?: boolean; showSwapOption?: boolean; @@ -43,7 +40,6 @@ interface AddFundsProps { export function AddFunds({ checkout, - provider, toAmount, toTokenAddress, showBackButton = false, @@ -53,11 +49,6 @@ export function AddFunds({ onBackButtonClick, onCloseButtonClick, }: AddFundsProps) { - console.log('provider', provider); - console.log('showOnrampOption', showOnrampOption); - console.log('showSwapOption', showSwapOption); - console.log('showBridgeOption', showBridgeOption); - const showBack = showBackButton || !!onBackButtonClick; const { addFundsDispatch } = useContext(AddFundsContext); @@ -174,10 +165,6 @@ export function AddFunds({ // }; const onPayWithCard = (paymentType: OptionTypes) => { - console.log('paymentType', paymentType); - console.log('=== toTokenAddress', currentToTokenAddress); - console.log('=== toAmount', toAmount); - if (paymentType === OptionTypes.SWAP) { orchestrationEvents.sendRequestSwapEvent( eventTarget,