diff --git a/package.json b/package.json index 5d81e09ba..c2c90c493 100644 --- a/package.json +++ b/package.json @@ -13,8 +13,8 @@ }, "devDependencies": { "@testing-library/jest-dom": "^5.16.3", - "@testing-library/react": "^12.1.4", - "@testing-library/user-event": "^14.0.0", + "@testing-library/react": "^13.0.0", + "@testing-library/user-event": "^14.0.4", "@types/big.js": "^6.1.3", "@types/node": "^17.0.23", "@types/react": "^17.0.43", diff --git a/packages/widget-embedded/package.json b/packages/widget-embedded/package.json index cca31b920..4339bab80 100644 --- a/packages/widget-embedded/package.json +++ b/packages/widget-embedded/package.json @@ -31,7 +31,7 @@ ] }, "devDependencies": { - "@testing-library/user-event": "^14.0.0", + "@testing-library/user-event": "^14.0.4", "@types/react": "^17.0.43", "@typescript-eslint/eslint-plugin": "^5.17.0", "@typescript-eslint/parser": "^5.17.0", diff --git a/packages/widget-embedded/src/index.tsx b/packages/widget-embedded/src/index.tsx index 945064660..b0654f6dd 100644 --- a/packages/widget-embedded/src/index.tsx +++ b/packages/widget-embedded/src/index.tsx @@ -12,7 +12,7 @@ const root = createRoot(rootElement); const config: WidgetConfig = { enabledChains: process.env.LIFI_ENABLED_CHAINS_JSON!, - fromChain: 'pol', + fromChain: 'eth', // toChain: 'okt', useInternalWalletManagement: true, }; diff --git a/packages/widget/package.json b/packages/widget/package.json index f54be6a3b..5d73a5b19 100644 --- a/packages/widget/package.json +++ b/packages/widget/package.json @@ -31,7 +31,7 @@ "react-i18next": "^11.16.2", "react-query": "^3.34.19", "react-resize-detector": "^7.0.0", - "react-router-dom": "^6.2.2", + "react-router-dom": "^6.3.0", "react-virtual": "^2.10.4" }, "eslintConfig": { diff --git a/packages/widget/src/components/SwapButton.tsx b/packages/widget/src/components/SwapButton.tsx index d90207d8c..a4dc7dea1 100644 --- a/packages/widget/src/components/SwapButton.tsx +++ b/packages/widget/src/components/SwapButton.tsx @@ -5,6 +5,7 @@ import { useWatch } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; import { ChainId, getChainById } from '..'; +import { useHasSufficientBalance } from '../hooks/useHasSufficientBalance'; import { useSwapRoutes } from '../hooks/useSwapRoutes'; import { SwapFormKeyHelper } from '../providers/SwapFormProvider'; import { useWalletInterface } from '../services/walletInterface'; @@ -23,6 +24,11 @@ export const SwapButton: React.FC<{ const navigate = useNavigate(); const { t } = useTranslation(); const { routes: swapRoutes } = useSwapRoutes(); + const { + hasGasBalanceOnStartChain, + hasGasOnCrossChain, + hasSufficientBalance, + } = useHasSufficientBalance(swapRoutes?.[0]); const { account, switchChain } = useWalletInterface(); const [chainId] = useWatch({ name: [SwapFormKeyHelper.getChainKey('from')], diff --git a/packages/widget/src/components/SwapInputAdornment/SwapInputAdornment.tsx b/packages/widget/src/components/SwapInputAdornment/SwapInputAdornment.tsx index 1a5c1463d..f452fb4d9 100644 --- a/packages/widget/src/components/SwapInputAdornment/SwapInputAdornment.tsx +++ b/packages/widget/src/components/SwapInputAdornment/SwapInputAdornment.tsx @@ -38,7 +38,6 @@ export const SwapInputAdornment: React.FC = ({ const handleMax = () => { setValue(SwapFormKeyHelper.getAmountKey(formType), amount); }; - console.log(tokenWithBalance); return ( diff --git a/packages/widget/src/components/SwapRoute/SwapRoute.tsx b/packages/widget/src/components/SwapRoute/SwapRoute.tsx index 1451e121b..e4bef5335 100644 --- a/packages/widget/src/components/SwapRoute/SwapRoute.tsx +++ b/packages/widget/src/components/SwapRoute/SwapRoute.tsx @@ -16,7 +16,7 @@ const parsedStepTypes: { export const SwapRoute: React.FC = () => { const { t } = useTranslation(); const { routes, isFetching, isFetched } = useSwapRoutes(); - console.log(routes); + const renderRoutesLoading = () => { return ( { + const [fromChainId, toChainId] = useWatch({ + name: [ + SwapFormKeyHelper.getChainKey('from'), + SwapFormKeyHelper.getChainKey('to'), + ], + }); + const lastStep = route?.steps.at(-1); + const { tokensWithBalance: fromChainTokenBalances } = useTokens(fromChainId); + const { tokensWithBalance: toChainTokenBalances } = useTokens( + lastStep?.action.fromChainId ?? toChainId, + ); + + const hasGasBalanceOnStartChain = useMemo(() => { + const token = route?.steps[0].estimate.gasCosts?.[0].token; + if (!token) { + return true; + } + const balance = Big( + fromChainTokenBalances?.[route.fromChainId].find( + (t) => t.address === token.address, + )?.amount ?? 0, + ); + const requiredAmount = route.steps + .filter((step) => step.action.fromChainId === route.fromChainId) + .map((step) => step.estimate.gasCosts?.[0].amount) + .map((amount) => Big(amount || 0)) + .reduce((a, b) => a.plus(b), Big(0)) + .div(10 ** token.decimals); + return balance.gt(0) && balance.gte(requiredAmount); + }, [fromChainTokenBalances, route]); + + const hasGasOnCrossChain = useMemo(() => { + const token = lastStep?.estimate.gasCosts?.[0].token; + if (!token || !isSwapStep(lastStep)) { + return true; + } + const balance = Big( + toChainTokenBalances?.[lastStep.action.fromChainId].find( + (t) => t.address === token.address, + )?.amount ?? 0, + ); + const gasEstimate = lastStep.estimate.gasCosts?.[0].amount; + const requiredAmount = Big(gasEstimate || 0).div( + 10 ** (lastStep.estimate.gasCosts?.[0].token.decimals ?? 0), + ); + return balance.gt(0) && balance.gte(requiredAmount); + }, [lastStep, toChainTokenBalances]); + + const hasSufficientBalance = useMemo(() => { + if (!route) { + return true; + } + + const balance = Big( + fromChainTokenBalances?.[route.fromChainId].find( + (t) => t.address === route.fromToken.address, + )?.amount ?? 0, + ); + + return Big(route.fromAmount) + .div(10 ** (route.fromToken.decimals ?? 0)) + .lte(balance); + }, [fromChainTokenBalances, route]); + + return { + hasGasBalanceOnStartChain, + hasGasOnCrossChain, + hasSufficientBalance, + }; +}; diff --git a/packages/widget/src/hooks/useSwapRoutes.ts b/packages/widget/src/hooks/useSwapRoutes.ts index 984ef533d..b1dda299e 100644 --- a/packages/widget/src/hooks/useSwapRoutes.ts +++ b/packages/widget/src/hooks/useSwapRoutes.ts @@ -6,7 +6,6 @@ import { SwapFormKey, SwapFormKeyHelper } from '../providers/SwapFormProvider'; import { useWalletInterface } from '../services/walletInterface'; import { formatTokenAmount } from '../utils/format'; import { useDebouncedWatch } from './useDebouncedWatch'; -// import { usePriorityAccount } from './connectorHooks'; import { useToken } from './useToken'; export const useSwapRoutes = () => { diff --git a/packages/widget/src/hooks/useTokenBalance.ts b/packages/widget/src/hooks/useTokenBalance.ts index e36c4494b..fd4b196df 100644 --- a/packages/widget/src/hooks/useTokenBalance.ts +++ b/packages/widget/src/hooks/useTokenBalance.ts @@ -8,8 +8,8 @@ export const useTokenBalance = (chainId: number, tokenAddress: string) => { const { token } = useToken(chainId, tokenAddress); const { data: tokenWithBalance, isLoading } = useQuery( - ['token', token?.symbol, account.address], - async ({ queryKey: [_, tokenSymbol, address] }) => { + ['token', tokenAddress, account.address], + async ({ queryKey: [_, __, address] }) => { if (!address || !token) { return null; } diff --git a/yarn.lock b/yarn.lock index 9910ebe03..850ebbd33 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3077,7 +3077,7 @@ "@svgr/plugin-jsx" "^6.2.1" "@svgr/plugin-svgo" "^6.2.0" -"@testing-library/dom@^8.0.0": +"@testing-library/dom@^8.5.0": version "8.12.0" resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.12.0.tgz#fef5e545533fb084175dda6509ee71d7d2f72e23" integrity sha512-rBrJk5WjI02X1edtiUcZhgyhgBhiut96r5Jp8J5qktKdcvLcZpKDW8i2hkGMMItxrghjXuQ5AM6aE0imnFawaw== @@ -3106,19 +3106,19 @@ lodash "^4.17.15" redent "^3.0.0" -"@testing-library/react@^12.1.4": - version "12.1.4" - resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-12.1.4.tgz#09674b117e550af713db3f4ec4c0942aa8bbf2c0" - integrity sha512-jiPKOm7vyUw311Hn/HlNQ9P8/lHNtArAx0PisXyFixDDvfl8DbD6EUdbshK5eqauvBSvzZd19itqQ9j3nferJA== +"@testing-library/react@^13.0.0": + version "13.0.0" + resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-13.0.0.tgz#8cdaf4667c6c2b082eb0513731551e9db784e8bc" + integrity sha512-p0lYA1M7uoEmk2LnCbZLGmHJHyH59sAaZVXChTXlyhV/PRW9LoIh4mdf7tiXsO8BoNG+vN8UnFJff1hbZeXv+w== dependencies: "@babel/runtime" "^7.12.5" - "@testing-library/dom" "^8.0.0" + "@testing-library/dom" "^8.5.0" "@types/react-dom" "*" -"@testing-library/user-event@^14.0.0": - version "14.0.0" - resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.0.0.tgz#3906aa6f0e56fd012d73559f5f05c02e63ba18dd" - integrity sha512-hZhjNrle/DMi1ziHwHy8LS0fYJtf+cID7fuG5+4h+Bk83xQaRDQT/DlqfL4hJYw3mxW6KTIxoODrhGnhqJebdQ== +"@testing-library/user-event@^14.0.4": + version "14.0.4" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-14.0.4.tgz#5b430a9c27f25078bff4471661b755115d0db9d4" + integrity sha512-VBZe5lcUsmrQyOwIFvqOxLBoaTw1/Qy4Ek+VgmFYs719bs2SxUp42vbsb7ATlQDkHdj4OIQlucfpwxe5WoG1jA== "@tootallnate/once@1": version "1.1.2" @@ -10963,18 +10963,18 @@ react-resize-detector@^7.0.0: "@types/resize-observer-browser" "^0.1.6" lodash "^4.17.21" -react-router-dom@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.2.2.tgz#f1a2c88365593c76b9612ae80154a13fcb72e442" - integrity sha512-AtYEsAST7bDD4dLSQHDnk/qxWLJdad5t1HFa1qJyUrCeGgEuCSw0VB/27ARbF9Fi/W5598ujvJOm3ujUCVzuYQ== +react-router-dom@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.3.0.tgz#a0216da813454e521905b5fa55e0e5176123f43d" + integrity sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw== dependencies: history "^5.2.0" - react-router "6.2.2" + react-router "6.3.0" -react-router@6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.2.2.tgz#495e683a0c04461eeb3d705fe445d6cf42f0c249" - integrity sha512-/MbxyLzd7Q7amp4gDOGaYvXwhEojkJD5BtExkuKmj39VEE0m3l/zipf6h2WIB2jyAO0lI6NGETh4RDcktRm4AQ== +react-router@6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.3.0.tgz#3970cc64b4cb4eae0c1ea5203a80334fdd175557" + integrity sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ== dependencies: history "^5.2.0"