diff --git a/apps/main/src/lend/components/PageLoanManage/index.tsx b/apps/main/src/lend/components/PageLoanManage/index.tsx index dacd14a3b..6fbdbfb48 100644 --- a/apps/main/src/lend/components/PageLoanManage/index.tsx +++ b/apps/main/src/lend/components/PageLoanManage/index.tsx @@ -5,11 +5,16 @@ import LoanCollateralRemove from '@/lend/components/PageLoanManage/LoanCollatera import LoanRepay from '@/lend/components/PageLoanManage/LoanRepay' import LoanSelfLiquidation from '@/lend/components/PageLoanManage/LoanSelfLiquidation' import type { CollateralFormType, LeverageFormType, LoanFormType } from '@/lend/components/PageLoanManage/types' +import networks from '@/lend/networks' import { type MarketUrlParams, PageContentProps } from '@/lend/types/lend.types' import { getLoanManagePathname } from '@/lend/utils/utilsRouter' +import { AddCollateralForm } from '@/llamalend/features/manage-loan/components/AddCollateralForm' +import { RemoveCollateralForm } from '@/llamalend/features/manage-loan/components/RemoveCollateralForm' +import { RepayForm } from '@/llamalend/features/manage-loan/components/RepayForm' import Stack from '@mui/material/Stack' import { AppFormContentWrapper } from '@ui/AppForm' import { useNavigate } from '@ui-kit/hooks/router' +import { useManageLoanMuiForm } from '@ui-kit/hooks/useFeatureFlags' import { t } from '@ui-kit/lib/i18n' import { type TabOption, TabsSwitcher } from '@ui-kit/shared/ui/TabsSwitcher' import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' @@ -28,8 +33,10 @@ const tabsCollateral: TabOption[] = [ ] const ManageLoan = (pageProps: PageContentProps & { params: MarketUrlParams }) => { - const { rOwmId, rFormType, market, params } = pageProps + const { rChainId, rOwmId, rFormType, market, params, isLoaded } = pageProps const push = useNavigate() + const shouldUseManageLoanMuiForm = useManageLoanMuiForm() + const useMuiForm = shouldUseManageLoanMuiForm && !!market type Tab = 'loan' | 'collateral' | 'leverage' const tabs: TabOption[] = useMemo( @@ -65,26 +72,84 @@ const ManageLoan = (pageProps: PageContentProps & { params: MarketUrlParams }) = onChange={(key) => push(getLoanManagePathname(params, rOwmId, key))} options={tabs} /> - t.design.Layer[1].Fill }}> - + {useMuiForm ? ( + <> + - - {subTab === 'loan-increase' && } - {subTab === 'loan-decrease' && } + {subTab === 'loan-increase' && ( + t.design.Layer[1].Fill }}> + + + + + )} + {subTab === 'loan-decrease' && market && ( + {}} + /> + )} {subTab === 'loan-liquidate' && } - {subTab === 'collateral-increase' && } - {subTab === 'collateral-decrease' && } + {subTab === 'collateral-increase' && market && ( + {}} + /> + )} + {subTab === 'collateral-decrease' && market && ( + {}} + /> + )} {/** Leverage has no subtabs */} - {rFormType === 'leverage' && } - - + {rFormType === 'leverage' && ( + t.design.Layer[1].Fill }}> + + + + + )} + + ) : ( + t.design.Layer[1].Fill }}> + + + + {subTab === 'loan-increase' && } + {subTab === 'loan-decrease' && } + {subTab === 'loan-liquidate' && } + {subTab === 'collateral-increase' && } + {subTab === 'collateral-decrease' && } + {/** Leverage has no subtabs */} + {rFormType === 'leverage' && } + + + )} ) } diff --git a/apps/main/src/llamalend/features/borrow/components/CreateLoanForm.tsx b/apps/main/src/llamalend/features/borrow/components/CreateLoanForm.tsx index 907b79291..7cd13a2bf 100644 --- a/apps/main/src/llamalend/features/borrow/components/CreateLoanForm.tsx +++ b/apps/main/src/llamalend/features/borrow/components/CreateLoanForm.tsx @@ -14,9 +14,9 @@ import Stack from '@mui/material/Stack' import { useBorrowPreset } from '@ui-kit/hooks/useLocalStorage' import { t } from '@ui-kit/lib/i18n' import { InputDivider } from '../../../widgets/InputDivider' +import { useCreateLoanForm } from '../hooks/useCreateLoanForm' import { setValueOptions } from '../react-form.utils' import { type BorrowFormExternalFields, type OnBorrowFormUpdate } from '../types' -import { useBorrowForm } from '../useBorrowForm' import { AdvancedBorrowOptions } from './AdvancedBorrowOptions' import { CreateLoanInfoAccordion } from './CreateLoanInfoAccordion' import { LeverageInput } from './LeverageInput' @@ -70,7 +70,7 @@ export const CreateLoanForm = ({ formErrors, tooMuchDebt, isApproved, - } = useBorrowForm({ market, network, preset, onCreated }) + } = useCreateLoanForm({ market, network, preset, onCreated }) const setRange = useCallback((range: number) => form.setValue('range', range, setValueOptions), [form]) useFormSync(values, onUpdate) @@ -97,12 +97,9 @@ export const CreateLoanForm = ({ blockchainId={network.id} name="userCollateral" form={form} - isLoading={maxTokenValues.isCollateralLoading} - isError={maxTokenValues.isCollateralError} - max={values.maxCollateral} + max={{ ...maxTokenValues.collateral, fieldName: 'maxCollateral' }} testId="borrow-collateral-input" network={network} - maxFieldName="maxCollateral" /> ({ blockchainId={network.id} name="debt" form={form} - isLoading={maxTokenValues.isDebtLoading} - isError={maxTokenValues.isDebtError} - max={values.maxDebt} + max={{ ...maxTokenValues.debt, fieldName: 'maxDebt' }} testId="borrow-debt-input" network={network} - maxFieldName="maxDebt" message={ values.maxDebt && } @@ -124,12 +118,10 @@ export const CreateLoanForm = ({ {market && hasLeverage(market) && ( )} diff --git a/apps/main/src/llamalend/features/borrow/components/LeverageInput.tsx b/apps/main/src/llamalend/features/borrow/components/LeverageInput.tsx index d7740970a..062d32128 100644 --- a/apps/main/src/llamalend/features/borrow/components/LeverageInput.tsx +++ b/apps/main/src/llamalend/features/borrow/components/LeverageInput.tsx @@ -1,5 +1,6 @@ import { type ChangeEvent, useCallback } from 'react' import type { UseFormReturn } from 'react-hook-form' +import type { Query } from '@/llamalend/widgets/manage-loan/loan.types' import Checkbox from '@mui/material/Checkbox' import FormControlLabel from '@mui/material/FormControlLabel' import Stack from '@mui/material/Stack' @@ -17,18 +18,14 @@ const { Spacing } = SizesAndSpaces export const LeverageInput = ({ form, - leverageEnabled, + checked, params, - maxLeverage, - isError, - isLoading, + maxLeverage: { data: maxLeverage, error, isLoading }, }: { - leverageEnabled: boolean + checked: boolean form: UseFormReturn params: BorrowFormQueryParams - maxLeverage: Decimal | undefined - isError: boolean - isLoading: boolean + maxLeverage: Query }) => { const { leverage } = useCreateLoanExpectedCollateral(params).data ?? {} @@ -44,7 +41,7 @@ export const LeverageInput = ({ <> {t`Enable leverage`} - + {t`up to ${formatNumber(maxLeverage, { maximumFractionDigits: 1 })}x 🔥`} @@ -55,7 +52,7 @@ export const LeverageInput = ({ data-testid="leverage-checkbox" size="small" disabled={!maxLeverage} - checked={leverageEnabled} + checked={checked} onChange={onLeverageChanged} sx={{ padding: 0, paddingInlineEnd: Spacing.xs, alignSelf: 'start' }} /> @@ -64,9 +61,9 @@ export const LeverageInput = ({ diff --git a/apps/main/src/llamalend/features/borrow/useBorrowForm.tsx b/apps/main/src/llamalend/features/borrow/hooks/useCreateLoanForm.tsx similarity index 84% rename from apps/main/src/llamalend/features/borrow/useBorrowForm.tsx rename to apps/main/src/llamalend/features/borrow/hooks/useCreateLoanForm.tsx index d60d2db98..bb099b56c 100644 --- a/apps/main/src/llamalend/features/borrow/useBorrowForm.tsx +++ b/apps/main/src/llamalend/features/borrow/hooks/useCreateLoanForm.tsx @@ -10,18 +10,18 @@ import { useDebouncedValue } from '@ui-kit/hooks/useDebounce' import { formDefaultOptions } from '@ui-kit/lib/model' import { Decimal } from '@ui-kit/utils' import { SLIPPAGE_PRESETS } from '@ui-kit/widgets/SlippageSettings/slippage.utils' -import { BORROW_PRESET_RANGES, BorrowPreset } from '../../constants' -import { type CreateLoanOptions, useCreateLoanMutation } from '../../mutations/create-loan.mutation' -import { useBorrowCreateLoanIsApproved } from '../../queries/create-loan/borrow-create-loan-approved.query' -import { borrowFormValidationSuite } from '../../queries/validation/borrow.validation' -import { useMaxTokenValues } from './hooks/useMaxTokenValues' -import { useFormErrors } from './react-form.utils' -import { type BorrowForm } from './types' +import { BORROW_PRESET_RANGES, BorrowPreset } from '../../../constants' +import { type CreateLoanOptions, useCreateLoanMutation } from '../../../mutations/create-loan.mutation' +import { useBorrowCreateLoanIsApproved } from '../../../queries/create-loan/borrow-create-loan-approved.query' +import { borrowFormValidationSuite } from '../../../queries/validation/borrow.validation' +import { useFormErrors } from '../react-form.utils' +import { type BorrowForm } from '../types' +import { useMaxTokenValues } from './useMaxTokenValues' const useCallbackAfterFormUpdate = (form: UseFormReturn, callback: () => void) => useEffect(() => form.subscribe({ formState: { values: true }, callback }), [form, callback]) -export function useBorrowForm({ +export function useCreateLoanForm({ market, network, network: { chainId }, diff --git a/apps/main/src/llamalend/features/borrow/hooks/useMaxTokenValues.tsx b/apps/main/src/llamalend/features/borrow/hooks/useMaxTokenValues.tsx index 38c93ba2d..eda3daceb 100644 --- a/apps/main/src/llamalend/features/borrow/hooks/useMaxTokenValues.tsx +++ b/apps/main/src/llamalend/features/borrow/hooks/useMaxTokenValues.tsx @@ -24,13 +24,13 @@ export function useMaxTokenValues( ) { const { data: userBalance, - isError: isBalanceError, + error: balanceError, isLoading: isBalanceLoading, } = useTokenBalance(params, collateralToken) - const { data: maxBorrow, isError: isErrorMaxBorrow, isLoading: isLoadingMaxBorrow } = useCreateLoanMaxReceive(params) + const { data: maxBorrow, error: maxBorrowError, isLoading: isLoadingMaxBorrow } = useCreateLoanMaxReceive(params) const { data: maxTotalLeverage, - isError: isErrorMaxLeverage, + error: maxLeverageError, isLoading: isLoadingMaxLeverage, } = useMarketMaxLeverage(params) @@ -46,12 +46,20 @@ export function useMaxTokenValues( useEffect(() => form.setValue('maxCollateral', maxCollateral, setValueOptions), [form, maxCollateral]) return { - isCollateralLoading: !collateralToken || isLoadingMaxBorrow || isBalanceLoading, - isDebtLoading: !collateralToken || isLoadingMaxBorrow, - isCollateralError: isErrorMaxBorrow || isBalanceError, - isDebtError: isErrorMaxBorrow, - isLeverageError: isErrorMaxLeverage || isErrorMaxBorrow, - isLeverageLoading: isLoadingMaxLeverage || isLoadingMaxBorrow, - maxLeverage, + collateral: { + data: maxCollateral, + isLoading: !collateralToken || isLoadingMaxBorrow || isBalanceLoading, + error: maxBorrowError || balanceError, + }, + debt: { + data: maxDebt, + isLoading: !collateralToken || isLoadingMaxBorrow, + error: maxBorrowError, + }, + maxLeverage: { + data: maxLeverage, + isLoading: isLoadingMaxLeverage || isLoadingMaxBorrow, + error: maxLeverageError || maxBorrowError, + }, } } diff --git a/apps/main/src/llamalend/features/borrow/types.ts b/apps/main/src/llamalend/features/borrow/types.ts index ab1f2f912..6fe6eb12b 100644 --- a/apps/main/src/llamalend/features/borrow/types.ts +++ b/apps/main/src/llamalend/features/borrow/types.ts @@ -6,7 +6,7 @@ import type { MakeOptional } from '@ui-kit/types/util' import { Decimal } from '@ui-kit/utils' /** Complete borrow creation form with all fields already filled in (after validation) */ -export type CompleteBorrowForm = { +type CompleteBorrowForm = { userCollateral: Decimal userBorrowed: Decimal // currently hidden and always 0 debt: Decimal @@ -33,5 +33,3 @@ export type BorrowFormQueryParams = FieldsOf> /** A simple token representation */ export type Token = { symbol: string; address: Address } - -export type BorrowFormErrors = (readonly [keyof BorrowForm | 'root', string])[] diff --git a/apps/main/src/llamalend/features/manage-loan/components/AddCollateralForm.tsx b/apps/main/src/llamalend/features/manage-loan/components/AddCollateralForm.tsx new file mode 100644 index 000000000..665729397 --- /dev/null +++ b/apps/main/src/llamalend/features/manage-loan/components/AddCollateralForm.tsx @@ -0,0 +1,117 @@ +import { useLoanToValueFromUserState } from '@/llamalend/features/manage-loan/hooks/useLoanToValueFromUserState' +import type { LlamaMarketTemplate, NetworkDict } from '@/llamalend/llamalend.types' +import type { AddCollateralOptions } from '@/llamalend/mutations/add-collateral.mutation' +import { useMarketRates } from '@/llamalend/queries/market-rates' +import { LoanFormAlerts } from '@/llamalend/widgets/manage-loan/LoanFormAlerts' +import { LoanFormTokenInput } from '@/llamalend/widgets/manage-loan/LoanFormTokenInput' +import { LoanFormWrapper } from '@/llamalend/widgets/manage-loan/LoanFormWrapper' +import { LoanInfoAccordion } from '@/llamalend/widgets/manage-loan/LoanInfoAccordion' +import type { IChainId } from '@curvefi/llamalend-api/lib/interfaces' +import Button from '@mui/material/Button' +import Stack from '@mui/material/Stack' +import { useSwitch } from '@ui-kit/hooks/useSwitch' +import { t } from '@ui-kit/lib/i18n' +import { InputDivider } from '../../../widgets/InputDivider' +import { useAddCollateralForm } from '../hooks/useAddCollateralForm' + +export const AddCollateralForm = ({ + market, + networks, + chainId, + enabled, + onAdded, +}: { + market: LlamaMarketTemplate | undefined + networks: NetworkDict + chainId: ChainId + enabled?: boolean + onAdded: NonNullable +}) => { + const network = networks[chainId] + const [isOpen, , , toggle] = useSwitch(false) + + const { + form, + isPending, + onSubmit, + action, + params, + values, + bands, + healthFull, + prices, + gas, + isApproved, + formErrors, + collateralToken, + borrowToken, + txHash, + } = useAddCollateralForm({ + market, + network, + networks, + enabled, + onAdded, + }) + + const marketRates = useMarketRates(params, isOpen) + + return ( + + } + > + }> + + + + + + + + ) +} diff --git a/apps/main/src/llamalend/features/manage-loan/components/RemoveCollateralForm.tsx b/apps/main/src/llamalend/features/manage-loan/components/RemoveCollateralForm.tsx new file mode 100644 index 000000000..24634fef2 --- /dev/null +++ b/apps/main/src/llamalend/features/manage-loan/components/RemoveCollateralForm.tsx @@ -0,0 +1,127 @@ +import { useLoanToValueFromUserState } from '@/llamalend/features/manage-loan/hooks/useLoanToValueFromUserState' +import type { LlamaMarketTemplate, NetworkDict } from '@/llamalend/llamalend.types' +import type { RemoveCollateralOptions } from '@/llamalend/mutations/remove-collateral.mutation' +import { useMarketRates } from '@/llamalend/queries/market-rates' +import { FormMessage } from '@/llamalend/widgets/manage-loan/FormMessage' +import { LoanFormAlerts } from '@/llamalend/widgets/manage-loan/LoanFormAlerts' +import { LoanFormTokenInput } from '@/llamalend/widgets/manage-loan/LoanFormTokenInput' +import { LoanFormWrapper } from '@/llamalend/widgets/manage-loan/LoanFormWrapper' +import { LoanInfoAccordion } from '@/llamalend/widgets/manage-loan/LoanInfoAccordion' +import type { IChainId } from '@curvefi/llamalend-api/lib/interfaces' +import Button from '@mui/material/Button' +import Stack from '@mui/material/Stack' +import { useSwitch } from '@ui-kit/hooks/useSwitch' +import { t } from '@ui-kit/lib/i18n' +import { InputDivider } from '../../../widgets/InputDivider' +import { useRemoveCollateralForm } from '../hooks/useRemoveCollateralForm' + +export const RemoveCollateralForm = ({ + market, + networks, + chainId, + enabled, + onRemoved, +}: { + market: LlamaMarketTemplate | undefined + networks: NetworkDict + chainId: ChainId + enabled?: boolean + onRemoved: NonNullable +}) => { + const network = networks[chainId] + const [isOpen, , , toggle] = useSwitch(false) + + const { + form, + isPending, + onSubmit, + action, + maxRemovable, + params, + values, + bands, + healthFull, + prices, + gas, + formErrors, + collateralToken, + borrowToken, + txHash, + } = useRemoveCollateralForm({ + market, + network, + networks, + enabled, + onRemoved, + }) + + const marketRates = useMarketRates(params, isOpen) + + return ( + + } + > + }> + + ) + } + /> + + + + + + + ) +} diff --git a/apps/main/src/llamalend/features/manage-loan/components/RepayForm.tsx b/apps/main/src/llamalend/features/manage-loan/components/RepayForm.tsx new file mode 100644 index 000000000..6715ab584 --- /dev/null +++ b/apps/main/src/llamalend/features/manage-loan/components/RepayForm.tsx @@ -0,0 +1,134 @@ +import { useLoanToValueFromUserState } from '@/llamalend/features/manage-loan/hooks/useLoanToValueFromUserState' +import type { LlamaMarketTemplate, NetworkDict } from '@/llamalend/llamalend.types' +import type { RepayOptions } from '@/llamalend/mutations/repay.mutation' +import { useMarketRates } from '@/llamalend/queries/market-rates' +import { LoanFormAlerts } from '@/llamalend/widgets/manage-loan/LoanFormAlerts' +import { LoanFormTokenInput } from '@/llamalend/widgets/manage-loan/LoanFormTokenInput' +import { LoanFormWrapper } from '@/llamalend/widgets/manage-loan/LoanFormWrapper' +import { LoanInfoAccordion } from '@/llamalend/widgets/manage-loan/LoanInfoAccordion' +import type { IChainId } from '@curvefi/llamalend-api/lib/interfaces' +import Button from '@mui/material/Button' +import Stack from '@mui/material/Stack' +import { useSwitch } from '@ui-kit/hooks/useSwitch' +import { t } from '@ui-kit/lib/i18n' +import type { Decimal } from '@ui-kit/utils' +import { InputDivider } from '../../../widgets/InputDivider' +import { useRepayForm } from '../hooks/useRepayForm' + +export const RepayForm = ({ + market, + networks, + chainId, + enabled, + onRepaid, +}: { + market: LlamaMarketTemplate | undefined + networks: NetworkDict + chainId: ChainId + enabled?: boolean + onRepaid: NonNullable +}) => { + const network = networks[chainId] + const [isOpen, , , toggle] = useSwitch(false) + + const { + form, + isPending, + onSubmit, + action, + bands, + healthFull, + prices, + gas, + isAvailable, + isFull, + formErrors, + collateralToken, + borrowToken, + params, + values, + txHash, + } = useRepayForm({ + market, + network, + networks, + enabled, + onRepaid, + }) + + const marketRates = useMarketRates(params, isOpen) + + const isDisabled = formErrors.length > 0 || isAvailable.data === false + + return ( + + } + > + }> + + + + + + + + + + ) +} diff --git a/apps/main/src/llamalend/features/manage-loan/hooks/useAddCollateralForm.ts b/apps/main/src/llamalend/features/manage-loan/hooks/useAddCollateralForm.ts index e20f1412b..f49e726d9 100644 --- a/apps/main/src/llamalend/features/manage-loan/hooks/useAddCollateralForm.ts +++ b/apps/main/src/llamalend/features/manage-loan/hooks/useAddCollateralForm.ts @@ -2,7 +2,8 @@ import { useEffect, useMemo } from 'react' import type { UseFormReturn } from 'react-hook-form' import { useForm } from 'react-hook-form' import { useAccount } from 'wagmi' -import type { LlamaMarketTemplate, NetworkDict } from '@/llamalend/llamalend.types' +import { getTokens } from '@/llamalend/llama.utils' +import type { LlamaMarketTemplate, LlamaNetwork, NetworkDict } from '@/llamalend/llamalend.types' import { type AddCollateralOptions, useAddCollateralMutation } from '@/llamalend/mutations/add-collateral.mutation' import { useAddCollateralIsApproved } from '@/llamalend/queries/add-collateral/add-collateral-approved.query' import { useAddCollateralBands } from '@/llamalend/queries/add-collateral/add-collateral-bands.query' @@ -14,9 +15,8 @@ import { collateralFormValidationSuite, type CollateralForm, } from '@/llamalend/queries/validation/manage-loan.validation' -import type { IChainId as LlamaChainId, INetworkName as LlamaNetworkId } from '@curvefi/llamalend-api/lib/interfaces' +import type { IChainId as LlamaChainId } from '@curvefi/llamalend-api/lib/interfaces' import { vestResolver } from '@hookform/resolvers/vest' -import type { BaseConfig } from '@ui/utils' import { useDebouncedValue } from '@ui-kit/hooks/useDebounce' import { formDefaultOptions } from '@ui-kit/lib/model' import { useFormErrors } from '../../borrow/react-form.utils' @@ -24,7 +24,7 @@ import { useFormErrors } from '../../borrow/react-form.utils' const useCallbackAfterFormUpdate = (form: UseFormReturn, callback: () => void) => useEffect(() => form.subscribe({ formState: { values: true }, callback }), [form, callback]) -export const useAddCollateralForm = ({ +export const useAddCollateralForm = ({ market, network, networks, @@ -32,8 +32,8 @@ export const useAddCollateralForm = ({ onAdded, }: { market: LlamaMarketTemplate | undefined - network: BaseConfig - networks: NetworkDict + network: LlamaNetwork + networks: NetworkDict enabled?: boolean onAdded: NonNullable }) => { @@ -41,6 +41,10 @@ export const useAddCollateralForm = ({ const { chainId } = network const marketId = market?.id + const tokens = market && getTokens(market) + const collateralToken = tokens?.collateralToken + const borrowToken = tokens?.borrowToken + const form = useForm({ ...formDefaultOptions, resolver: vestResolver(collateralFormValidationSuite), @@ -59,7 +63,7 @@ export const useAddCollateralForm = ({ marketId, userAddress, userCollateral: values.userCollateral, - }) as CollateralParams, + }) as CollateralParams, [chainId, marketId, userAddress, values.userCollateral], ), ) @@ -98,5 +102,8 @@ export const useAddCollateralForm = ({ gas, isApproved, formErrors, + collateralToken, + borrowToken, + txHash: action.data?.hash, } } diff --git a/apps/main/src/llamalend/features/manage-loan/hooks/useLoanToValueFromUserState.ts b/apps/main/src/llamalend/features/manage-loan/hooks/useLoanToValueFromUserState.ts new file mode 100644 index 000000000..8f85f4c38 --- /dev/null +++ b/apps/main/src/llamalend/features/manage-loan/hooks/useLoanToValueFromUserState.ts @@ -0,0 +1,77 @@ +import BigNumber from 'bignumber.js' +import type { Address } from 'viem' +import { useUserState } from '@/llamalend/queries/user-state.query' +import type { IChainId } from '@curvefi/llamalend-api/lib/interfaces' +import { useTokenUsdRate } from '@ui-kit/lib/model/entities/token-usd-rate' +import type { Decimal } from '@ui-kit/utils' +import type { Token } from '../../borrow/types' + +type Params = { + chainId: ChainId + marketId: string | null | undefined + userAddress: Address | null | undefined + collateralToken: Token | undefined + borrowToken: Token | undefined + enabled: boolean + /** Net change applied to on-chain collateral (positive = adding, negative = removing). */ + collateralDelta?: Decimal | null + /** Net change applied to on-chain debt (positive = increasing, negative = repaying). */ + debtDelta?: Decimal | null +} + +/** + * Computes current Loan-to-Value (LTV) ratio from the user's on-chain state: + * LTV = (debt in USD) / (collateral in USD) * 100 + * + * It uses the generic userState query so it can be reused across + * add-collateral, remove-collateral and repay flows. + */ +export const useLoanToValueFromUserState = ({ + chainId, + marketId, + userAddress, + collateralToken, + borrowToken, + enabled, + collateralDelta, + debtDelta, +}: Params) => { + const { + data: userState, + isLoading: isUserLoading, + error: userError, + } = useUserState({ chainId, marketId, userAddress }, enabled) + + const { + data: collateralUsdRate, + isLoading: isCollateralUsdRateLoading, + error: collateralUsdRateError, + } = useTokenUsdRate({ chainId, tokenAddress: collateralToken?.address }, enabled && !!collateralToken?.address) + + const { + data: borrowUsdRate, + isLoading: isBorrowUsdRateLoading, + error: borrowUsdRateError, + } = useTokenUsdRate({ chainId, tokenAddress: borrowToken?.address }, enabled && !!borrowToken?.address) + + const baseDebt = userState?.debt + const baseCollateral = userState?.collateral + + const debt = baseDebt == null ? null : new BigNumber(baseDebt).plus(debtDelta ?? '0') + + const collateral = baseCollateral == null ? null : new BigNumber(baseCollateral).plus(collateralDelta ?? '0') + + return { + data: + !enabled || + debt == null || + collateral == null || + collateralUsdRate == null || + borrowUsdRate == null || + collateral.isZero() + ? null + : (debt.times(borrowUsdRate).div(collateral).div(collateralUsdRate).times(100).toString() as Decimal), + isLoading: enabled && (isUserLoading || isCollateralUsdRateLoading || isBorrowUsdRateLoading), + error: userError ?? collateralUsdRateError ?? borrowUsdRateError, + } +} diff --git a/apps/main/src/llamalend/features/manage-loan/hooks/useRemoveCollateralForm.ts b/apps/main/src/llamalend/features/manage-loan/hooks/useRemoveCollateralForm.ts index 021fa33db..b4b7c6355 100644 --- a/apps/main/src/llamalend/features/manage-loan/hooks/useRemoveCollateralForm.ts +++ b/apps/main/src/llamalend/features/manage-loan/hooks/useRemoveCollateralForm.ts @@ -2,6 +2,7 @@ import { useEffect, useMemo } from 'react' import type { UseFormReturn } from 'react-hook-form' import { useForm } from 'react-hook-form' import { useAccount } from 'wagmi' +import { getTokens } from '@/llamalend/llama.utils' import type { LlamaMarketTemplate, NetworkDict } from '@/llamalend/llamalend.types' import { type RemoveCollateralOptions, @@ -27,7 +28,10 @@ import { useFormErrors } from '../../borrow/react-form.utils' const useCallbackAfterFormUpdate = (form: UseFormReturn, callback: () => void) => useEffect(() => form.subscribe({ formState: { values: true }, callback }), [form, callback]) -export const useRemoveCollateralForm = ({ +export const useRemoveCollateralForm = < + ChainId extends LlamaChainId, + NetworkName extends LlamaNetworkId = LlamaNetworkId, +>({ market, network, networks, @@ -35,8 +39,8 @@ export const useRemoveCollateralForm = ({ onRemoved, }: { market: LlamaMarketTemplate | undefined - network: BaseConfig - networks: NetworkDict + network: BaseConfig + networks: NetworkDict enabled?: boolean onRemoved: NonNullable }) => { @@ -44,6 +48,10 @@ export const useRemoveCollateralForm = ({ const { chainId } = network const marketId = market?.id + const tokens = market && getTokens(market) + const collateralToken = tokens?.collateralToken + const borrowToken = tokens?.borrowToken + const form = useForm({ ...formDefaultOptions, resolver: vestResolver(collateralFormValidationSuite), @@ -62,7 +70,7 @@ export const useRemoveCollateralForm = ({ marketId, userAddress, userCollateral: values.userCollateral, - }) as CollateralParams, + }) as CollateralParams, [chainId, marketId, userAddress, values.userCollateral], ), ) @@ -99,6 +107,9 @@ export const useRemoveCollateralForm = ({ healthNotFull, prices, gas, + txHash: action.data?.hash, + collateralToken, + borrowToken, formErrors, } } diff --git a/apps/main/src/llamalend/features/manage-loan/hooks/useRepayForm.ts b/apps/main/src/llamalend/features/manage-loan/hooks/useRepayForm.ts index 832cbd73f..c0e9d966d 100644 --- a/apps/main/src/llamalend/features/manage-loan/hooks/useRepayForm.ts +++ b/apps/main/src/llamalend/features/manage-loan/hooks/useRepayForm.ts @@ -2,6 +2,7 @@ import { useEffect, useMemo } from 'react' import type { UseFormReturn } from 'react-hook-form' import { useForm } from 'react-hook-form' import { useAccount } from 'wagmi' +import { getTokens } from '@/llamalend/llama.utils' import type { LlamaMarketTemplate, NetworkDict } from '@/llamalend/llamalend.types' import { type RepayOptions, useRepayMutation } from '@/llamalend/mutations/repay.mutation' import { useRepayBands } from '@/llamalend/queries/repay/repay-bands.query' @@ -24,7 +25,7 @@ import { useFormErrors } from '../../borrow/react-form.utils' const useCallbackAfterFormUpdate = (form: UseFormReturn, callback: () => void) => useEffect(() => form.subscribe({ formState: { values: true }, callback }), [form, callback]) -export const useRepayForm = ({ +export const useRepayForm = ({ market, network, networks, @@ -32,8 +33,8 @@ export const useRepayForm = ({ onRepaid, }: { market: LlamaMarketTemplate | undefined - network: { id: LlamaNetworkId; chainId: LlamaChainId } - networks: NetworkDict + network: { id: LlamaNetworkId; chainId: ChainId } + networks: NetworkDict enabled?: boolean onRepaid: NonNullable }) => { @@ -41,6 +42,10 @@ export const useRepayForm = ({ const { chainId } = network const marketId = market?.id + const tokens = market && getTokens(market) + const collateralToken = tokens?.collateralToken + const borrowToken = tokens?.borrowToken + const form = useForm({ ...formDefaultOptions, resolver: vestResolver(repayFormValidationSuite), @@ -63,7 +68,7 @@ export const useRepayForm = ({ stateCollateral: values.stateCollateral, userCollateral: values.userCollateral, userBorrowed: values.userBorrowed, - }) as RepayFromCollateralParams, + }) as RepayFromCollateralParams, [chainId, marketId, userAddress, values.stateCollateral, values.userCollateral, values.userBorrowed], ), ) @@ -104,6 +109,9 @@ export const useRepayForm = ({ prices, routeImage, gas, + txHash: action.data?.hash, + collateralToken, + borrowToken, formErrors, } } diff --git a/apps/main/src/llamalend/mutations/add-collateral.mutation.ts b/apps/main/src/llamalend/mutations/add-collateral.mutation.ts index 325cf3dd7..64c4ad553 100644 --- a/apps/main/src/llamalend/mutations/add-collateral.mutation.ts +++ b/apps/main/src/llamalend/mutations/add-collateral.mutation.ts @@ -59,5 +59,5 @@ export const useAddCollateralMutation = ({ const onSubmit = useCallback((form: CollateralForm) => mutateAsync(form as AddCollateralMutation), [mutateAsync]) - return { onSubmit, mutateAsync, error, txHash: data, isPending, isSuccess, reset } + return { onSubmit, mutateAsync, error, data, isPending, isSuccess, reset } } diff --git a/apps/main/src/llamalend/mutations/remove-collateral.mutation.ts b/apps/main/src/llamalend/mutations/remove-collateral.mutation.ts index 2d34907b5..3b2f7f940 100644 --- a/apps/main/src/llamalend/mutations/remove-collateral.mutation.ts +++ b/apps/main/src/llamalend/mutations/remove-collateral.mutation.ts @@ -43,5 +43,5 @@ export const useRemoveCollateralMutation = ({ const onSubmit = useCallback((form: CollateralForm) => mutateAsync(form as RemoveCollateralMutation), [mutateAsync]) - return { onSubmit, mutateAsync, error, txHash: data, isPending, isSuccess, reset } + return { onSubmit, mutateAsync, error, data, isPending, isSuccess, reset } } diff --git a/apps/main/src/llamalend/queries/add-collateral/add-collateral-gas-estimate.query.ts b/apps/main/src/llamalend/queries/add-collateral/add-collateral-gas-estimate.query.ts index 1368c3552..c9787f0fd 100644 --- a/apps/main/src/llamalend/queries/add-collateral/add-collateral-gas-estimate.query.ts +++ b/apps/main/src/llamalend/queries/add-collateral/add-collateral-gas-estimate.query.ts @@ -30,7 +30,15 @@ export const useAddCollateralEstimateGas = ( enabled?: boolean, ) => { const { chainId } = query - const { data: estimate, isLoading: estimateLoading } = useAddCollateralGasEstimate(query, enabled) - const { data, isLoading: conversionLoading } = useEstimateGas(networks, chainId, estimate, enabled) - return { data, isLoading: estimateLoading || conversionLoading } + const { + data: estimate, + isLoading: estimateLoading, + error: estimateError, + } = useAddCollateralGasEstimate(query, enabled) + const { + data, + isLoading: conversionLoading, + error: conversionError, + } = useEstimateGas(networks, chainId, estimate, enabled) + return { data, isLoading: estimateLoading || conversionLoading, error: estimateError ?? conversionError } } diff --git a/apps/main/src/llamalend/queries/create-loan/create-loan-health.query.ts b/apps/main/src/llamalend/queries/create-loan/create-loan-health.query.ts index 94ff364d3..24ec01561 100644 --- a/apps/main/src/llamalend/queries/create-loan/create-loan-health.query.ts +++ b/apps/main/src/llamalend/queries/create-loan/create-loan-health.query.ts @@ -1,6 +1,8 @@ import { getLlamaMarket } from '@/llamalend/llama.utils' import { LendMarketTemplate } from '@curvefi/llamalend-api/lib/lendMarkets' import { queryFactory, rootKeys } from '@ui-kit/lib/model' +import type { Decimal } from '@ui-kit/utils' +import { decimal } from '@ui-kit/utils' import type { BorrowFormQuery, BorrowFormQueryParams } from '../../features/borrow/types' import { borrowQueryValidationSuite } from '../validation/borrow.validation' import { createLoanExpectedCollateralQueryKey } from './create-loan-expected-collateral.query' @@ -32,15 +34,17 @@ export const { useQuery: useCreateLoanHealth } = queryFactory({ debt = '0', leverageEnabled, range, - }: BorrowFormQuery): Promise => { + }: BorrowFormQuery): Promise => { const market = getLlamaMarket(marketId) - return leverageEnabled - ? market instanceof LendMarketTemplate - ? +(await market.leverage.createLoanHealth(userCollateral, userBorrowed, debt, range)) - : market.leverageV2.hasLeverage() - ? +(await market.leverageV2.createLoanHealth(userCollateral, userBorrowed, debt, range)) - : +(await market.leverage.createLoanHealth(userCollateral, debt, range)) - : +(await market.createLoanHealth(userCollateral, debt, range)) + return decimal( + leverageEnabled + ? market instanceof LendMarketTemplate + ? await market.leverage.createLoanHealth(userCollateral, userBorrowed, debt, range) + : market.leverageV2.hasLeverage() + ? await market.leverageV2.createLoanHealth(userCollateral, userBorrowed, debt, range) + : await market.leverage.createLoanHealth(userCollateral, debt, range) + : await market.createLoanHealth(userCollateral, debt, range), + )! }, staleTime: '1m', validationSuite: borrowQueryValidationSuite, diff --git a/apps/main/src/llamalend/queries/remove-collateral/remove-collateral-gas-estimate.query.ts b/apps/main/src/llamalend/queries/remove-collateral/remove-collateral-gas-estimate.query.ts index dd5246c30..b7679db0a 100644 --- a/apps/main/src/llamalend/queries/remove-collateral/remove-collateral-gas-estimate.query.ts +++ b/apps/main/src/llamalend/queries/remove-collateral/remove-collateral-gas-estimate.query.ts @@ -32,7 +32,15 @@ export const useRemoveCollateralEstimateGas = ( enabled?: boolean, ) => { const { chainId } = query - const { data: estimate, isLoading: estimateLoading } = useRemoveCollateralGasEstimate(query, enabled) - const { data, isLoading: conversionLoading } = useEstimateGas(networks, chainId, estimate, enabled) - return { data, isLoading: estimateLoading || conversionLoading } + const { + data: estimate, + isLoading: estimateLoading, + error: estimateError, + } = useRemoveCollateralGasEstimate(query, enabled) + const { + data, + isLoading: conversionLoading, + error: conversionError, + } = useEstimateGas(networks, chainId, estimate, enabled) + return { data, isLoading: estimateLoading || conversionLoading, error: estimateError ?? conversionError } } diff --git a/apps/main/src/llamalend/queries/remove-collateral/remove-collateral-prices.query.ts b/apps/main/src/llamalend/queries/remove-collateral/remove-collateral-prices.query.ts index c7324ff5c..65dbb480b 100644 --- a/apps/main/src/llamalend/queries/remove-collateral/remove-collateral-prices.query.ts +++ b/apps/main/src/llamalend/queries/remove-collateral/remove-collateral-prices.query.ts @@ -1,5 +1,6 @@ import { getLlamaMarket } from '@/llamalend/llama.utils' import { queryFactory, rootKeys } from '@ui-kit/lib/model' +import type { Decimal } from '@ui-kit/utils' import { type CollateralParams, type CollateralQuery } from '../validation/manage-loan.types' import { collateralValidationSuite } from '../validation/manage-loan.validation' import { maxRemovableCollateralKey } from './remove-collateral-max-removable.query' @@ -8,7 +9,7 @@ export const { useQuery: useRemoveCollateralPrices } = queryFactory({ queryKey: ({ chainId, marketId, userAddress, userCollateral }: CollateralParams) => [...rootKeys.userMarket({ chainId, marketId, userAddress }), 'removeCollateralPrices', { userCollateral }] as const, queryFn: async ({ marketId, userCollateral }: CollateralQuery) => - await getLlamaMarket(marketId).removeCollateralPrices(userCollateral), + (await getLlamaMarket(marketId).removeCollateralPrices(userCollateral)) as Decimal[], validationSuite: collateralValidationSuite, dependencies: (params) => [maxRemovableCollateralKey(params)], }) diff --git a/apps/main/src/llamalend/queries/repay/repay-gas-estimate.query.ts b/apps/main/src/llamalend/queries/repay/repay-gas-estimate.query.ts index 6d91f2ee6..0a45f8be8 100644 --- a/apps/main/src/llamalend/queries/repay/repay-gas-estimate.query.ts +++ b/apps/main/src/llamalend/queries/repay/repay-gas-estimate.query.ts @@ -44,7 +44,11 @@ export const useRepayEstimateGas = ( enabled?: boolean, ) => { const { chainId } = query - const { data: estimate, isLoading: estimateLoading } = useRepayGasEstimate(query, enabled) - const { data, isLoading: conversionLoading } = useEstimateGas(networks, chainId, estimate, enabled) - return { data, isLoading: estimateLoading || conversionLoading } + const { data: estimate, isLoading: estimateLoading, error: estimateError } = useRepayGasEstimate(query, enabled) + const { + data, + isLoading: conversionLoading, + error: conversionError, + } = useEstimateGas(networks, chainId, estimate, enabled) + return { data, isLoading: estimateLoading || conversionLoading, error: estimateError ?? conversionError } } diff --git a/apps/main/src/llamalend/widgets/manage-loan/LoanFormTokenInput.tsx b/apps/main/src/llamalend/widgets/manage-loan/LoanFormTokenInput.tsx index f87e0216b..8b99e2226 100644 --- a/apps/main/src/llamalend/widgets/manage-loan/LoanFormTokenInput.tsx +++ b/apps/main/src/llamalend/widgets/manage-loan/LoanFormTokenInput.tsx @@ -4,6 +4,7 @@ import type { Address } from 'viem' import { useAccount } from 'wagmi' import { setValueOptions } from '@/llamalend/features/borrow/react-form.utils' import type { LlamaNetwork } from '@/llamalend/llamalend.types' +import type { Query } from '@/llamalend/widgets/manage-loan/loan.types' import type { INetworkName } from '@curvefi/llamalend-api/lib/interfaces' import type { PartialRecord } from '@curvefi/prices-api/objects.util' import { useTokenBalance } from '@ui-kit/hooks/useTokenBalance' @@ -14,44 +15,45 @@ import { Decimal } from '@ui-kit/utils' /** * A large token input field for loan forms, with balance and max handling. */ -export const LoanFormTokenInput = >({ +export const LoanFormTokenInput = < + TFieldValues extends FieldValues, + TFieldName extends FieldPath, + TMaxFieldName extends FieldPath, +>({ label, token, blockchainId, name, max, - isLoading: isMaxLoading, - isError, form, testId, message, network, - maxFieldName, }: { label: string token: { address: Address; symbol?: string } | undefined blockchainId: INetworkName | undefined - isError: boolean - isLoading: boolean - max: Decimal | undefined + /** + * Optional max-value query for this field, including loading and error state. + * When present, it also carries an optional related max-field name whose errors should be reflected here. + */ + max?: Query & { fieldName?: TMaxFieldName } name: TFieldName form: UseFormReturn // the form, used to set the value and get errors testId: string message?: ReactNode network: LlamaNetwork - /** Optional related max-field name whose errors should be reflected here */ - maxFieldName?: FieldPath }) => { const { address: userAddress } = useAccount() const { data: balance, isLoading: isBalanceLoading, - isError: isBalanceError, + error: balanceError, } = useTokenBalance({ chainId: network?.chainId, userAddress }, token) const errors = form.formState.errors as PartialRecord, Error> - const relatedMaxFieldError = maxFieldName && errors[maxFieldName] - + const relatedMaxFieldError = max?.fieldName && errors[max.fieldName] + const error = errors[name] || max?.error || balanceError || relatedMaxFieldError return ( form.setValue(name, v as FieldPathValue, setValueOptions), [form, name], )} - isError={isError || isBalanceError || !!errors[name] || !!relatedMaxFieldError} - message={errors[name]?.message ?? relatedMaxFieldError?.message ?? message} + isError={!!error} + message={error?.message ?? message} walletBalance={useMemo( - // todo: separate isLoading for balance and for maxBalance - () => ({ balance, symbol: token?.symbol, loading: isBalanceLoading || isMaxLoading }), - [balance, isMaxLoading, isBalanceLoading, token?.symbol], + // todo: support separate isLoading for balance and for maxBalance in LargeTokenInput + () => ({ balance, symbol: token?.symbol, loading: isBalanceLoading }), + [balance, isBalanceLoading, token?.symbol], )} - maxBalance={useMemo(() => ({ balance: max, chips: 'max' }), [max])} + maxBalance={useMemo(() => max && { balance: max.data, chips: 'max' }, [max])} /> ) } diff --git a/apps/main/src/llamalend/widgets/manage-loan/LoanInfoAccordion.tsx b/apps/main/src/llamalend/widgets/manage-loan/LoanInfoAccordion.tsx index a6d8b9c04..57590102f 100644 --- a/apps/main/src/llamalend/widgets/manage-loan/LoanInfoAccordion.tsx +++ b/apps/main/src/llamalend/widgets/manage-loan/LoanInfoAccordion.tsx @@ -24,18 +24,21 @@ export type LoanLeverageMaxReceive = { maxLeverage?: Decimal } +// Note: AddCollateral / RemoveCollateral / Repay manage-loan forms +// do not provide range, rates, futureRates or loanToValue, +// so these props are optional for those forms. type LoanInfoAccordionProps = { isOpen: boolean toggle: () => void - range: number - health: Query + range?: number + health: Query bands: Query<[number, number]> prices: Query rates: Query<{ borrowApr?: Decimal } | null> - futureRates: Query<{ borrowApr?: Decimal } | null> loanToValue: Query + futureRates?: Query<{ borrowApr?: Decimal } | null> gas: Query - leverage: LoanLeverageActionInfoProps & { enabled: boolean } + leverage?: LoanLeverageActionInfoProps & { enabled: boolean } } export const LoanInfoAccordion = ({ @@ -50,67 +53,70 @@ export const LoanInfoAccordion = ({ loanToValue, gas, leverage, -}: LoanInfoAccordionProps) => { - const theme = useTheme() - return ( - // error tooltip isn't displayed correctly because accordion takes the mouse focus. Use title for now. - - - } - expanded={isOpen} - toggle={toggle} - > - - {leverage.enabled && } - - formatNumber(p, { abbreviate: false })).join(' - ') ?? '-'} - error={prices.error ?? undefined} - loading={prices.isLoading} - testId="borrow-price-range" - /> +}: LoanInfoAccordionProps) => ( + // error tooltip isn't displayed correctly because accordion takes the mouse focus. Use title for now. + + + } + expanded={isOpen} + toggle={toggle} + > + + {leverage?.enabled && } + + formatNumber(p, { abbreviate: false })).join(' - ') ?? '-'} + error={prices.error} + loading={prices.isLoading} + testId="borrow-price-range" + /> + {range != null && ( + )} + {rates && futureRates && ( + )} + {loanToValue && ( - - - - - ) -} + )} + + + + +) diff --git a/apps/main/src/loan/components/PageLoanManage/index.tsx b/apps/main/src/loan/components/PageLoanManage/index.tsx index e29d4768f..999d555be 100644 --- a/apps/main/src/loan/components/PageLoanManage/index.tsx +++ b/apps/main/src/loan/components/PageLoanManage/index.tsx @@ -1,4 +1,7 @@ import { useEffect, useMemo, useState } from 'react' +import { AddCollateralForm } from '@/llamalend/features/manage-loan/components/AddCollateralForm' +import { RemoveCollateralForm } from '@/llamalend/features/manage-loan/components/RemoveCollateralForm' +import { RepayForm } from '@/llamalend/features/manage-loan/components/RepayForm' import CollateralDecrease from '@/loan/components/PageLoanManage/CollateralDecrease' import CollateralIncrease from '@/loan/components/PageLoanManage/CollateralIncrease' import LoanDecrease from '@/loan/components/PageLoanManage/LoanDecrease' @@ -12,10 +15,12 @@ import type { PageLoanManageProps, } from '@/loan/components/PageLoanManage/types' import { hasDeleverage } from '@/loan/utils/leverage' +import networks from '@/loan/networks' import { getLoanManagePathname } from '@/loan/utils/utilsRouter' import Stack from '@mui/material/Stack' import { AppFormContentWrapper } from '@ui/AppForm' import { useNavigate } from '@ui-kit/hooks/router' +import { useManageLoanMuiForm } from '@ui-kit/hooks/useFeatureFlags' import { t } from '@ui-kit/lib/i18n' import { type TabOption, TabsSwitcher } from '@ui-kit/shared/ui/TabsSwitcher' import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' @@ -37,6 +42,8 @@ const tabsCollateral: TabOption[] = [ const LoanManage = ({ curve, isReady, llamma, llammaId, params, rChainId, rCollateralId, rFormType }: Props) => { const push = useNavigate() + const shouldUseManageLoanMuiForm = useManageLoanMuiForm() + const useMuiForm = shouldUseManageLoanMuiForm && !!llamma type Tab = 'loan' | 'collateral' | 'deleverage' const tabs: TabOption[] = [ @@ -71,26 +78,77 @@ const LoanManage = ({ curve, isReady, llamma, llammaId, params, rChainId, rColla options={tabs} /> - t.design.Layer[1].Fill }}> - + {useMuiForm ? ( + <> + - - {subTab === 'loan-increase' && } - {subTab === 'loan-decrease' && } + {subTab === 'loan-increase' && ( + t.design.Layer[1].Fill }}> + + + + + )} + {subTab === 'loan-decrease' && llamma && ( + {}} + /> + )} {subTab === 'loan-liquidate' && } - {subTab === 'collateral-increase' && } - {subTab === 'collateral-decrease' && } + {subTab === 'collateral-increase' && llamma && ( + {}} + /> + )} + {subTab === 'collateral-decrease' && llamma && ( + {}} + /> + )} {/** Deleverage has no subtabs */} {rFormType === 'deleverage' && } - - + + ) : ( + t.design.Layer[1].Fill }}> + + + + {subTab === 'loan-increase' && } + {subTab === 'loan-decrease' && } + {subTab === 'loan-liquidate' && } + {subTab === 'collateral-increase' && } + {subTab === 'collateral-decrease' && } + {/** Deleverage has no subtabs */} + {rFormType === 'deleverage' && } + + + )} ) } diff --git a/packages/curve-ui-kit/src/hooks/useFeatureFlags.ts b/packages/curve-ui-kit/src/hooks/useFeatureFlags.ts index b5bd43bf6..0fe7645fe 100644 --- a/packages/curve-ui-kit/src/hooks/useFeatureFlags.ts +++ b/packages/curve-ui-kit/src/hooks/useFeatureFlags.ts @@ -3,12 +3,18 @@ * These return booleans indicating whether a new experience is enabled. */ -import { ReleaseChannel } from '@ui-kit/utils' +import { defaultReleaseChannel, ReleaseChannel } from '@ui-kit/utils' import { useReleaseChannel } from './useLocalStorage' const useBetaChannel = () => useReleaseChannel()[0] === ReleaseChannel.Beta const useStableChannel = () => useReleaseChannel()[0] !== ReleaseChannel.Legacy +/** + * Pre-Beta channel works like beta for preview/localhost urls, but completely hidden in production. + * This is used for features actively under development that are known not to be ready. + * */ +const useAlphaChannel = () => useBetaChannel() && defaultReleaseChannel === ReleaseChannel.Beta + /** LargeTokenInput replaces legacy amount inputs */ const useLargeTokenInput = useStableChannel @@ -24,12 +30,11 @@ export const useDexMarketList = useBetaChannel /** New unified create loan form */ export const useCreateLoanMuiForm = useBetaChannel +/** New manage loan forms (add/remove/repay) */ +export const useManageLoanMuiForm = useAlphaChannel + /** New bands chart (BandsChart) */ export const useNewBandsChart = useBetaChannel -/** - * New card for managing soft liquidations - * Temporarily disabled until we have a Tenderly account again so we can test for lend markets, - * but also I want to see the feature implementation to be progressed further along. - */ -export const useManageSoftLiquidation = () => false +/** New card for managing soft liquidations */ +export const useManageSoftLiquidation = useAlphaChannel diff --git a/packages/curve-ui-kit/src/hooks/useTokenBalance.tsx b/packages/curve-ui-kit/src/hooks/useTokenBalance.tsx index 9765d3792..6cc664cd4 100644 --- a/packages/curve-ui-kit/src/hooks/useTokenBalance.tsx +++ b/packages/curve-ui-kit/src/hooks/useTokenBalance.tsx @@ -19,10 +19,10 @@ export function useTokenBalance( { chainId, userAddress }: FieldsOf<{ chainId: number; userAddress: Address }>, token: { address: Address } | undefined, ) { - const { data, isError, isLoading } = useBalance({ + const { data, error, isLoading } = useBalance({ ...(userAddress && { address: userAddress }), ...(chainId && { chainId: chainId }), ...(token && token.address != ethAddress && { token: token.address }), }) - return { ...(data && { data: convertBalance(data) }), isError, isLoading } + return { ...(data && { data: convertBalance(data) }), error, isLoading } }