From cb3644073723509c77ef8a28b983cd2f3e828ded Mon Sep 17 00:00:00 2001 From: Pivi Lartisant Date: Thu, 20 Jun 2024 10:51:58 +0200 Subject: [PATCH] Usd value v2 (#747) * style input * revamp fetch usdc price * fix dusa price estimate * fmt * remove unecessary warns * use params in custom hook again + return undefined * improve-styling * update imports * remove try catch --------- Co-authored-by: Pierre Seznec --- src/components/inputAmount/InputAmount.tsx | 73 +++++++++---------- src/custom/usdPrice/useFetchPrice.ts | 55 ++++++++++---- .../BoxLayoutComponents/TokenBalance.tsx | 2 +- src/store/helpers/index.ts | 2 + src/store/index.ts | 8 ++ 5 files changed, 87 insertions(+), 53 deletions(-) create mode 100644 src/store/helpers/index.ts create mode 100644 src/store/index.ts diff --git a/src/components/inputAmount/InputAmount.tsx b/src/components/inputAmount/InputAmount.tsx index cc2f62c5..09031547 100644 --- a/src/components/inputAmount/InputAmount.tsx +++ b/src/components/inputAmount/InputAmount.tsx @@ -1,15 +1,17 @@ -import { Money, formatAmount } from '@massalabs/react-ui-kit'; +import { FetchingLine, Money, formatAmount } from '@massalabs/react-ui-kit'; import Big from 'big.js'; import { parseUnits } from 'viem'; import useEvmToken from '../../custom/bridge/useEvmToken'; -import { useMassaNetworkValidation } from '../../custom/bridge/useNetworkValidation'; import { useServiceFee } from '../../custom/bridge/useServiceFee'; import { useUsdValue } from '../../custom/usdPrice/useFetchPrice'; import { TokenBalance, TokenOptions } from '../../pages'; -import { useGlobalStatusesStore } from '../../store/globalStatusesStore'; -import { useOperationStore } from '../../store/operationStore'; -import { useTokenStore } from '../../store/tokenStore'; + import Intl from '@/i18n/i18n'; +import { + useGlobalStatusesStore, + useOperationStore, + useTokenStore, +} from '@/store'; import { getAmountToReceive } from '@/utils/utils'; export interface InputAmountProps { @@ -20,7 +22,7 @@ export interface InputAmountProps { export const InputAmount = (props: InputAmountProps) => { const { isInput, massaTokens } = props; const { inputAmount, outputAmount, setAmounts, isMassaToEvm } = - useOperationStore.getState(); + useOperationStore(); const { serviceFee } = useServiceFee(); const { selectedToken } = useTokenStore(); @@ -28,12 +30,11 @@ export const InputAmount = (props: InputAmountProps) => { useEvmToken(); const { setAmountError, amountError } = useGlobalStatusesStore(); // Price are fetched onchain from Dusa. If massa network is not valid, we don't show the price - const isValidMassaNetwork = useMassaNetworkValidation(); const massaToEvm = isMassaToEvm(); const decimals = selectedToken?.decimals; - const { usdValue } = useUsdValue( + const { usdValue, isFetching: isFetchingUsdAmount } = useUsdValue( isInput ? inputAmount : outputAmount, selectedToken, ); @@ -86,37 +87,35 @@ export const InputAmount = (props: InputAmountProps) => { return (
-
-
-
- changeAmount(o.value)} - placeholder={Intl.t( - isInput - ? 'index.input.placeholder.amount' - : 'index.input.placeholder.receive', - )} - suffix="" - decimalScale={decimals} - error={isInput ? amountError : ''} - /> -
- {isValidMassaNetwork && !!inputAmount && !!usdValue && ( -
USD {usdValue}
+
+
+ changeAmount(o.value)} + placeholder={Intl.t( + isInput + ? 'index.input.placeholder.amount' + : 'index.input.placeholder.receive', + )} + suffix="" + decimalScale={decimals} + error={isInput ? amountError : ''} + /> + + {isFetchingUsdAmount ? ( + + ) : ( + !!usdValue && ( +
{`$ ${usdValue}`}
+ ) )}
-
-
- -
- {isInput && ( -
- -
- )} +
+ + {isInput && }
diff --git a/src/custom/usdPrice/useFetchPrice.ts b/src/custom/usdPrice/useFetchPrice.ts index f4326e41..e7f869c8 100644 --- a/src/custom/usdPrice/useFetchPrice.ts +++ b/src/custom/usdPrice/useFetchPrice.ts @@ -15,23 +15,42 @@ import { formatAmount } from '@massalabs/react-ui-kit'; import { useDebounceValue } from 'usehooks-ts'; import { useBridgeModeStore } from '../../store/modeStore'; import { useAccountStore } from '../../store/store'; -import { IToken } from '../../store/tokenStore'; +import { useMassaNetworkValidation } from '../bridge/useNetworkValidation'; +import { IToken } from '@/store/tokenStore'; -export const useUsdValue = (amount?: bigint, token?: IToken) => { - const { isMainnet } = useBridgeModeStore(); - const [usdValue, setUsdValue] = useState(); - const [debouncedAmount] = useDebounceValue(amount, 300); +export function useUsdValue( + inputAmount: bigint | undefined, + selectedToken: IToken | undefined, +) { + const { isMainnet, currentMode } = useBridgeModeStore(); + + const [debouncedAmount] = useDebounceValue(inputAmount, 300); const { massaClient } = useAccountStore(); + const isValidMassaNetwork = useMassaNetworkValidation(); + const [usdValue, setUsdValue] = useState(); + const [isFetching, setIsFetching] = useState(false); + const getUsdValue = useCallback(async () => { - if (!token || !debouncedAmount || !massaClient) { + if ( + !selectedToken || + !debouncedAmount || + !massaClient || + !inputAmount || + !isValidMassaNetwork + ) { + setIsFetching(false); + setUsdValue(undefined); return; } - - const symbol = token.symbolEVM.toUpperCase(); + setIsFetching(true); + const symbol = selectedToken.symbolEVM.toUpperCase(); let outputAmount: string; if (symbol.includes('USD') || symbol.includes('DAI')) { - outputAmount = formatAmount(debouncedAmount, token.decimals).preview; + outputAmount = formatAmount( + debouncedAmount, + selectedToken.decimals, + ).preview; } else { const chainId = isMainnet() ? ChainId.MAINNET : ChainId.BUILDNET; const USDC = _USDC[chainId]; @@ -70,7 +89,9 @@ export const useUsdValue = (amount?: bigint, token?: IToken) => { ); // chooses the best trade - const bestTrade = TradeV2.chooseBestTrade(trades, true); + let bestTrade; + + bestTrade = TradeV2.chooseBestTrade(trades, true); const quoter = new IQuoter(LB_QUOTER_ADDRESS[chainId], massaClient); @@ -78,19 +99,23 @@ export const useUsdValue = (amount?: bigint, token?: IToken) => { bestTrade.route.pathToStrArr(), debouncedAmount.toString(), ); + // get the output amount without slippage outputAmount = formatAmount( - prices.virtualAmountsWithoutSlippage[2], + prices.virtualAmountsWithoutSlippage[ + prices.virtualAmountsWithoutSlippage.length - 1 + ], outputToken.decimals, ).preview; } setUsdValue(outputAmount); - }, [debouncedAmount, token, massaClient, isMainnet]); + setIsFetching(false); + }, [debouncedAmount, massaClient, isMainnet, inputAmount]); useEffect(() => { getUsdValue(); - }, [getUsdValue]); + }, [getUsdValue, currentMode, selectedToken]); - return { usdValue }; -}; + return { usdValue, isFetching }; +} diff --git a/src/pages/IndexPage/Layouts/BridgeRedeemLayout/BoxLayoutComponents/TokenBalance.tsx b/src/pages/IndexPage/Layouts/BridgeRedeemLayout/BoxLayoutComponents/TokenBalance.tsx index fb53f8a4..9a423b27 100644 --- a/src/pages/IndexPage/Layouts/BridgeRedeemLayout/BoxLayoutComponents/TokenBalance.tsx +++ b/src/pages/IndexPage/Layouts/BridgeRedeemLayout/BoxLayoutComponents/TokenBalance.tsx @@ -35,7 +35,7 @@ export function TokenBalance() { {!isFetched || !selectedToken || amount === undefined ? ( ) : ( -
+
{preview}
diff --git a/src/store/helpers/index.ts b/src/store/helpers/index.ts new file mode 100644 index 00000000..3aa238d0 --- /dev/null +++ b/src/store/helpers/index.ts @@ -0,0 +1,2 @@ +export * from './massaProviders'; +export * from './tokenSymbol'; diff --git a/src/store/index.ts b/src/store/index.ts new file mode 100644 index 00000000..f263c963 --- /dev/null +++ b/src/store/index.ts @@ -0,0 +1,8 @@ +export * from './accountStore'; +export * from './configStore'; +export * from './globalStatusesStore'; +export * from './modeStore'; +export * from './operationStore'; +export * from './store'; +export * from './tokenStore'; +export * from './helpers/index';