diff --git a/packages/web/components/swap-tool/index.tsx b/packages/web/components/swap-tool/index.tsx index 3f8a149be0..378148b098 100644 --- a/packages/web/components/swap-tool/index.tsx +++ b/packages/web/components/swap-tool/index.tsx @@ -11,6 +11,7 @@ import { ReactNode, useCallback, useEffect, + useMemo, useRef, useState, } from "react"; @@ -143,11 +144,15 @@ export const SwapTool: FunctionComponent = observer( } } - const outputDifference = new RatePretty( - swapState.inAmountInput?.fiatValue - ?.toDec() - .sub(swapState.tokenOutFiatValue?.toDec()) - .quo(swapState.inAmountInput?.fiatValue?.toDec()) ?? new Dec(0) + const outputDifference = useMemo( + () => + new RatePretty( + swapState.inAmountInput?.fiatValue + ?.toDec() + .sub(swapState.tokenOutFiatValue?.toDec()) + .quo(swapState.inAmountInput?.fiatValue?.toDec()) ?? new Dec(0) + ), + [swapState.inAmountInput?.fiatValue, swapState.tokenOutFiatValue] ); const showOutputDifferenceWarning = outputDifference diff --git a/packages/web/hooks/use-deep-memo.ts b/packages/web/hooks/use-deep-memo.ts new file mode 100644 index 0000000000..f3eb3146e4 --- /dev/null +++ b/packages/web/hooks/use-deep-memo.ts @@ -0,0 +1,27 @@ +import equal from "fast-deep-equal"; +import { DependencyList, useRef } from "react"; + +/** + * A custom hook for `useMemo` that uses deep comparison on the dependencies. + * + * @param factory - A function that produces the memoized value. + * @param dependencies - The dependency array to be deeply compared. + * @returns The memoized value. + */ +export function useDeepMemo( + factory: () => T, + dependencies: DependencyList +): T { + if (!Array.isArray(dependencies)) { + throw new Error("useDeepMemo expects a dependency array"); + } + const dependenciesRef = useRef(); + const memoizedValueRef = useRef(); + + if (!equal(dependenciesRef.current, dependencies)) { + dependenciesRef.current = dependencies; + memoizedValueRef.current = factory(); + } + + return memoizedValueRef.current!; +} diff --git a/packages/web/hooks/use-swap.tsx b/packages/web/hooks/use-swap.tsx index f4aa4a236b..489c9caeef 100644 --- a/packages/web/hooks/use-swap.tsx +++ b/packages/web/hooks/use-swap.tsx @@ -46,6 +46,7 @@ import { import { useTranslation } from "~/hooks/language"; import { useOneClickTradingSession } from "~/hooks/one-click-trading"; import { mulPrice } from "~/hooks/queries/assets/use-coin-fiat-value"; +import { useDeepMemo } from "~/hooks/use-deep-memo"; import { useEstimateTxFees } from "~/hooks/use-estimate-tx-fees"; import { useShowPreviewAssets } from "~/hooks/use-show-preview-assets"; import { AppRouter } from "~/server/api/root-router"; @@ -703,6 +704,14 @@ export function useSwap( quoteType, outAmountInput.fiatValue, ]); + const totalFee = useDeepMemo( + () => + sum([ + tokenInFeeAmountFiatValue, + networkFee?.gasUsdValueToPay?.toDec() ?? new Dec(0), + ]), + [tokenInFeeAmountFiatValue, networkFee?.gasUsdValueToPay] + ); return { ...swapAssets, @@ -717,10 +726,7 @@ export function useSwap( ? quote : undefined, inBaseOutQuoteSpotPrice, - totalFee: sum([ - tokenInFeeAmountFiatValue, - networkFee?.gasUsdValueToPay?.toDec() ?? new Dec(0), - ]), + totalFee, networkFee, isLoadingNetworkFee: inAmountInput.isLoadingCurrentBalanceNetworkFee || isLoadingNetworkFee, @@ -1087,12 +1093,21 @@ function useSwapAmountInput({ ); }, [currentBalanceNetworkFee?.gasAmount]); - return { - ...inAmountInput, + const returnValue = useDeepMemo(() => { + return { + ...inAmountInput, + isLoadingCurrentBalanceNetworkFee, + hasErrorWithCurrentBalanceQuote, + notEnoughBalanceForMax, + }; + }, [ + inAmountInput, isLoadingCurrentBalanceNetworkFee, hasErrorWithCurrentBalanceQuote, notEnoughBalanceForMax, - }; + ]); + + return returnValue; } /** @@ -1142,7 +1157,7 @@ function useToFromDenoms({ // if using query params perform one push instead of two as the router // doesn't handle two immediate pushes well within `useQueryParamState` hooks - const switchAssets = () => { + const switchAssets = useCallback(() => { if (useQueryParams) { const temp = fromDenomQueryParam; setFromDenomQueryParam(toAssetQueryParam); @@ -1153,7 +1168,17 @@ function useToFromDenoms({ const temp = fromAssetState; setFromAssetState(toAssetState); setToAssetState(temp); - }; + }, [ + useQueryParams, + fromDenomQueryParam, + toAssetQueryParam, + setFromDenomQueryParam, + setToAssetQueryParam, + fromAssetState, + toAssetState, + setFromAssetState, + setToAssetState, + ]); const fromAssetDenom = useQueryParams ? fromDenomQueryParamStr @@ -1296,18 +1321,16 @@ function useQueryRouterBestQuote( } ); - const quoteResult = - quoteType === "out-given-in" ? outGivenInQuote : inGivenOutQuote; const { data: quote, isSuccess, isError, error, - } = useMemo(() => { - return quoteResult; - }, [quoteResult]); + } = useDeepMemo(() => { + return quoteType === "out-given-in" ? outGivenInQuote : inGivenOutQuote; + }, [quoteType, outGivenInQuote, inGivenOutQuote]); - const acceptedQuote = useMemo(() => { + const acceptedQuote = useDeepMemo(() => { if ( !quote || !input.tokenIn || @@ -1368,8 +1391,13 @@ function useQueryRouterBestQuote( quoteType, ]); + const quoteData = useDeepMemo( + () => (acceptedQuote ? { ...acceptedQuote, messages } : undefined), + [acceptedQuote, messages] + ); + return { - data: acceptedQuote ? { ...acceptedQuote, messages } : undefined, + data: quoteData, isLoading: !isSuccess, errorMsg: error?.message, numSucceeded: isSuccess ? 1 : 0, diff --git a/packages/web/package.json b/packages/web/package.json index d03f5f91fa..eaf7aea808 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -98,6 +98,7 @@ "decompress": "^4.2.1", "eventemitter3": "^4.0.7", "fancy-canvas": "^2.1.0", + "fast-deep-equal": "^3.1.3", "focus-trap-react": "^10.0.2", "fuse.js": "^6.5.3", "highcharts": "^9.1.0", diff --git a/yarn.lock b/yarn.lock index 4311d5ac66..c6f2313b3d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4409,7 +4409,29 @@ buffer "^6.0.3" delay "^4.4.0" -"@keplr-wallet/cosmos@0.10.24-ibc.go.v7.hot.fix", "@keplr-wallet/cosmos@0.12.12", "@keplr-wallet/cosmos@0.12.28": +"@keplr-wallet/common@0.12.12": + version "0.12.12" + resolved "https://registry.yarnpkg.com/@keplr-wallet/common/-/common-0.12.12.tgz#55030d985b729eac582c0d7203190e25ea2cb3ec" + integrity sha512-AxpwmXdqs083lMvA8j0/V30oTGyobsefNaCou+lP4rCyDdYuXSEux+x2+1AGL9xB3yZfN+4jvEEKJdMwHYEHcQ== + dependencies: + "@keplr-wallet/crypto" "0.12.12" + "@keplr-wallet/types" "0.12.12" + buffer "^6.0.3" + delay "^4.4.0" + mobx "^6.1.7" + +"@keplr-wallet/common@0.12.28": + version "0.12.28" + resolved "https://registry.yarnpkg.com/@keplr-wallet/common/-/common-0.12.28.tgz#1d5d985070aced31a34a6426c9ac4b775081acca" + integrity sha512-ESQorPZw8PRiUXhsrxED+E1FEWkAdc6Kwi3Az7ce204gMBQDI2j0XJtTd4uCUp+C24Em9fk0samdHzdoB4caIg== + dependencies: + "@keplr-wallet/crypto" "0.12.28" + "@keplr-wallet/types" "0.12.28" + buffer "^6.0.3" + delay "^4.4.0" + mobx "^6.1.7" + +"@keplr-wallet/cosmos@0.10.24-ibc.go.v7.hot.fix": version "0.10.24-ibc.go.v7.hot.fix" resolved "https://registry.npmjs.org/@keplr-wallet/cosmos/-/cosmos-0.10.24-ibc.go.v7.hot.fix.tgz" integrity sha512-/A/wHyYo5gQIW5YkAQYZadEv/12EcAuDclO0KboIb9ti4XFJW6S4VY8LnA16R7DZyBx1cnQknyDm101fUrJfJQ== @@ -4426,6 +4448,40 @@ long "^4.0.0" protobufjs "^6.11.2" +"@keplr-wallet/cosmos@0.12.12": + version "0.12.12" + resolved "https://registry.yarnpkg.com/@keplr-wallet/cosmos/-/cosmos-0.12.12.tgz#72c0505d2327bbf2f5cb51502acaf399b88b4ae3" + integrity sha512-9TLsefUIAuDqqf1WHBt9Bk29rPlkezmLM8P1eEsXGUaHBfuqUrO+RwL3eLA3HGcgNvdy9s8e0p/4CMInH/LLLQ== + dependencies: + "@ethersproject/address" "^5.6.0" + "@keplr-wallet/common" "0.12.12" + "@keplr-wallet/crypto" "0.12.12" + "@keplr-wallet/proto-types" "0.12.12" + "@keplr-wallet/simple-fetch" "0.12.12" + "@keplr-wallet/types" "0.12.12" + "@keplr-wallet/unit" "0.12.12" + bech32 "^1.1.4" + buffer "^6.0.3" + long "^4.0.0" + protobufjs "^6.11.2" + +"@keplr-wallet/cosmos@0.12.28": + version "0.12.28" + resolved "https://registry.yarnpkg.com/@keplr-wallet/cosmos/-/cosmos-0.12.28.tgz#d56e73468256e7276a66bb41f145449dbf11efa1" + integrity sha512-IuqmSBgKgIeWBA0XGQKKs28IXFeFMCrfadCbtiZccNc7qnNr5Y/Cyyk01BPC8Dd1ZyEyAByoICgrxvtGN0GGvA== + dependencies: + "@ethersproject/address" "^5.6.0" + "@keplr-wallet/common" "0.12.28" + "@keplr-wallet/crypto" "0.12.28" + "@keplr-wallet/proto-types" "0.12.28" + "@keplr-wallet/simple-fetch" "0.12.28" + "@keplr-wallet/types" "0.12.28" + "@keplr-wallet/unit" "0.12.28" + bech32 "^1.1.4" + buffer "^6.0.3" + long "^4.0.0" + protobufjs "^6.11.2" + "@keplr-wallet/crypto@0.10.24-ibc.go.v7.hot.fix": version "0.10.24-ibc.go.v7.hot.fix" resolved "https://registry.npmjs.org/@keplr-wallet/crypto/-/crypto-0.10.24-ibc.go.v7.hot.fix.tgz" @@ -4498,7 +4554,7 @@ resolved "https://registry.npmjs.org/@keplr-wallet/popup/-/popup-0.10.24-ibc.go.v7.hot.fix.tgz" integrity sha512-Q/teyV6vdmpH3SySGd1xrNc/mVGK/tCP5vFEG2I3Y4FDCSV1yD7vcVgUy+tN19Z8EM3goR57V2QlarSOidtdjQ== -"@keplr-wallet/proto-types@0.10.24-ibc.go.v7.hot.fix", "@keplr-wallet/proto-types@0.12.12": +"@keplr-wallet/proto-types@0.10.24-ibc.go.v7.hot.fix": version "0.10.24-ibc.go.v7.hot.fix" resolved "https://registry.npmjs.org/@keplr-wallet/proto-types/-/proto-types-0.10.24-ibc.go.v7.hot.fix.tgz" integrity sha512-fLUJEtDadYJIMBzhMSZpEDTvXqk8wW68TwnUCRAcAooEQEtXPwY5gfo3hcekQEiCYtIu8XqzJ9fg01rp2Z4d3w== @@ -4506,6 +4562,22 @@ long "^4.0.0" protobufjs "^6.11.2" +"@keplr-wallet/proto-types@0.12.12": + version "0.12.12" + resolved "https://registry.yarnpkg.com/@keplr-wallet/proto-types/-/proto-types-0.12.12.tgz#24e0530af7604a90f33a397a82fe500865c76154" + integrity sha512-iAqqNlJpxu/8j+SwOXEH2ymM4W0anfxn+eNeWuqz2c/0JxGTWeLURioxQmCtewtllfHdDHHcoQ7/S+NmXiaEgQ== + dependencies: + long "^4.0.0" + protobufjs "^6.11.2" + +"@keplr-wallet/proto-types@0.12.28": + version "0.12.28" + resolved "https://registry.yarnpkg.com/@keplr-wallet/proto-types/-/proto-types-0.12.28.tgz#2fb2c37749ce7db974f01d07387e966c9b99027d" + integrity sha512-ukti/eCTltPUP64jxtk5TjtwJogyfKPqlBIT3KGUCGzBLIPeYMsffL5w5aoHsMjINzOITjYqzXyEF8LTIK/fmw== + dependencies: + long "^4.0.0" + protobufjs "^6.11.2" + "@keplr-wallet/provider-extension@^0.12.95": version "0.12.107" resolved "https://registry.yarnpkg.com/@keplr-wallet/provider-extension/-/provider-extension-0.12.107.tgz#98a0fb42cb0c54d4e681e60e6b1145429a6e3e23" @@ -4581,12 +4653,32 @@ deepmerge "^4.2.2" long "^4.0.0" -"@keplr-wallet/router@0.10.24-ibc.go.v7.hot.fix", "@keplr-wallet/router@0.12.12", "@keplr-wallet/router@0.12.96": +"@keplr-wallet/router@0.10.24-ibc.go.v7.hot.fix": version "0.10.24-ibc.go.v7.hot.fix" resolved "https://registry.npmjs.org/@keplr-wallet/router/-/router-0.10.24-ibc.go.v7.hot.fix.tgz" integrity sha512-bt9weexlbhlh8KsOvbDrvHJ8jtUXrXgB2LX+hEAwjclHQt7PMUhx9a5z0Obd19/ive5G/1M7/ccdPIWxRBpKQw== -"@keplr-wallet/types@0.10.24-ibc.go.v7.hot.fix", "@keplr-wallet/types@0.12.107", "@keplr-wallet/types@0.12.12", "@keplr-wallet/types@0.12.96", "@keplr-wallet/types@^0.12.95": +"@keplr-wallet/router@0.12.12": + version "0.12.12" + resolved "https://registry.yarnpkg.com/@keplr-wallet/router/-/router-0.12.12.tgz#92a2c006aec6945ed313575af6b0801f8e84e315" + integrity sha512-Aa1TiVRIEPaqs1t27nCNs5Kz6Ty4CLarVdfqcRWlFQL6zFq33GT46s6K9U4Lz2swVCwdmerSXaq308K/GJHTlw== + +"@keplr-wallet/router@0.12.96": + version "0.12.96" + resolved "https://registry.yarnpkg.com/@keplr-wallet/router/-/router-0.12.96.tgz#6a20ed2c90ba3ed4f3fc43ed7513f72d7055482d" + integrity sha512-O8izj032ZKQIoTus96BFqem+w6NpYHU3j6NEnSaQBh6Zncj9fgjoOVs0CKK+jsuLYUsOHx2t86BxMSKESsR0Ug== + +"@keplr-wallet/simple-fetch@0.12.12": + version "0.12.12" + resolved "https://registry.yarnpkg.com/@keplr-wallet/simple-fetch/-/simple-fetch-0.12.12.tgz#aacc5c3f22b7ab2804b39e864725294a32f858fd" + integrity sha512-lCOsaI8upMpbusfwJqEK8VIEX77+QE8+8MJVRqoCYwjOTqKGdUH7D1ieZWh+pzvzOnVgedM3lxqdmCvdgU91qw== + +"@keplr-wallet/simple-fetch@0.12.28": + version "0.12.28" + resolved "https://registry.yarnpkg.com/@keplr-wallet/simple-fetch/-/simple-fetch-0.12.28.tgz#44225df5b329c823076280df1ec9930a21b1373e" + integrity sha512-T2CiKS2B5n0ZA7CWw0CA6qIAH0XYI1siE50MP+i+V0ZniCGBeL+BMcDw64vFJUcEH+1L5X4sDAzV37fQxGwllA== + +"@keplr-wallet/types@0.10.24-ibc.go.v7.hot.fix": version "0.10.24-ibc.go.v7.hot.fix" resolved "https://registry.npmjs.org/@keplr-wallet/types/-/types-0.10.24-ibc.go.v7.hot.fix.tgz" integrity sha512-3KUjDMUCscYkvKnC+JsJh9+X0NHlsvBgAghP/uy2p5OGtiULqPBAjWiO+hnBbhis3ZEkzGcCROnnBOoccKd3CQ== @@ -4597,6 +4689,41 @@ long "^4.0.0" secretjs "^0.17.0" +"@keplr-wallet/types@0.12.107": + version "0.12.107" + resolved "https://registry.yarnpkg.com/@keplr-wallet/types/-/types-0.12.107.tgz#8d6726d86e17a79131b4b6f4f114052d6384aa58" + integrity sha512-jBpjJO+nNL8cgsJLjZYoq84n+7nXHDdztTgRMVnnomFb+Vy0FVIEI8VUl89ImmHDUImDd0562ywsvA496/0yCA== + dependencies: + long "^4.0.0" + +"@keplr-wallet/types@0.12.12": + version "0.12.12" + resolved "https://registry.yarnpkg.com/@keplr-wallet/types/-/types-0.12.12.tgz#f4bd9e710d5e53504f6b53330abb45bedd9c20ae" + integrity sha512-fo6b8j9EXnJukGvZorifJWEm1BPIrvaTLuu5PqaU5k1ANDasm/FL1NaUuaTBVvhRjINtvVXqYpW/rVUinA9MBA== + dependencies: + long "^4.0.0" + +"@keplr-wallet/types@0.12.28": + version "0.12.28" + resolved "https://registry.yarnpkg.com/@keplr-wallet/types/-/types-0.12.28.tgz#eac3c2c9d4560856c5c403a87e67925992a04fbf" + integrity sha512-EcM9d46hYDm3AO4lf4GUbTSLRySONtTmhKb7p88q56OQOgJN3MMjRacEo2p9jX9gpPe7gRIjMUalhAfUiFpZoQ== + dependencies: + long "^4.0.0" + +"@keplr-wallet/types@0.12.96": + version "0.12.96" + resolved "https://registry.yarnpkg.com/@keplr-wallet/types/-/types-0.12.96.tgz#a7735051b1f7cbcdf9b8c29010b1c3c45d195c19" + integrity sha512-tr4tPjMrJCsfRXXhhmqnpb9DqH9auJp3uuj8SvDB3pQTTaYJNxkdonLv1tYmXZZ6J9oWtk9WVEDTVgBQN/wisw== + dependencies: + long "^4.0.0" + +"@keplr-wallet/types@^0.12.95": + version "0.12.156" + resolved "https://registry.yarnpkg.com/@keplr-wallet/types/-/types-0.12.156.tgz#5e9346c12065a21394fa45112ad1b7a072e0f3f3" + integrity sha512-Z/Lf6VEsl/Am3birKE8ZEVZj/x5YGSoTdFMDtq/EfcB+hcJ/ogoiZTVEBweAig/2zcu7MsZvFTVMEXu5+y3e4A== + dependencies: + long "^4.0.0" + "@keplr-wallet/unit@0.10.24-ibc.go.v7.hot.fix": version "0.10.24-ibc.go.v7.hot.fix" resolved "https://registry.npmjs.org/@keplr-wallet/unit/-/unit-0.10.24-ibc.go.v7.hot.fix.tgz" @@ -4606,6 +4733,24 @@ big-integer "^1.6.48" utility-types "^3.10.0" +"@keplr-wallet/unit@0.12.12": + version "0.12.12" + resolved "https://registry.yarnpkg.com/@keplr-wallet/unit/-/unit-0.12.12.tgz#2d7f2e38df4e09c8123dcc0784ffc4b5f4166217" + integrity sha512-fayJcfXWKUnbDZiRJHyuA9GMVS9DymjRlCzlpAJ0+xV0c4Kun/f+9FajL9OQAdPPhnJ7A3KevMI4VHZsd9Yw+A== + dependencies: + "@keplr-wallet/types" "0.12.12" + big-integer "^1.6.48" + utility-types "^3.10.0" + +"@keplr-wallet/unit@0.12.28": + version "0.12.28" + resolved "https://registry.yarnpkg.com/@keplr-wallet/unit/-/unit-0.12.28.tgz#907c7fa0b49a729cda207fca14fc0a38871cc6c4" + integrity sha512-kpXigHDBJGOmhtPkv9hqsQid9zkFo7OQPeKgO2n8GUlOINIXW6kWG5LXYTi/Yg9Uiw1CQF69gFMuZCJ8IzVHlA== + dependencies: + "@keplr-wallet/types" "0.12.28" + big-integer "^1.6.48" + utility-types "^3.10.0" + "@keplr-wallet/wc-client@^0.12.95": version "0.12.96" resolved "https://registry.yarnpkg.com/@keplr-wallet/wc-client/-/wc-client-0.12.96.tgz#a56995172dcdc73d32b24d5a704a954062befc2a"