From 9b423a6689d3322a0ebb3ac5faf618762e6bab2b Mon Sep 17 00:00:00 2001 From: Alunara Date: Tue, 25 Nov 2025 16:02:18 +0100 Subject: [PATCH 01/23] refactor: remove unnecessary advance mode check --- .../components/MarketParameters.tsx | 62 +++++++++---------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx index 2c63762164..011a57107c 100644 --- a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx +++ b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx @@ -8,7 +8,6 @@ import DetailInfo from '@ui/DetailInfo' import Icon from '@ui/Icon' import Chip from '@ui/Typography/Chip' import { FORMAT_OPTIONS, formatNumber, NumberFormatOptions } from '@ui/utils' -import { useUserProfileStore } from '@ui-kit/features/user-profile' import { t } from '@ui-kit/lib/i18n' const MarketParameters = ({ @@ -26,14 +25,12 @@ const MarketParameters = ({ const vaultPricePerShareResp = useStore((state) => state.markets.vaultPricePerShare[rChainId]?.[rOwmId]) const fetchVaultPricePerShare = useStore((state) => state.markets.fetchVaultPricePerShare) - const isAdvancedMode = useUserProfileStore((state) => state.isAdvancedMode) - const { prices, error: pricesError } = loanPricesResp ?? {} const { parameters, error: parametersError } = parametersResp ?? {} const { pricePerShare, error: pricePerShareError } = vaultPricePerShareResp ?? {} // prettier-ignore - const marketDetails: { label: string; value: string | number | undefined; formatOptions?: NumberFormatOptions; title?: string; isError: string; isRow?: boolean, isAdvance?: boolean; tooltip?: string }[][] = type === 'borrow' ? + const marketDetails: { label: string; value: string | number | undefined; formatOptions?: NumberFormatOptions; title?: string; isError: string; isRow?: boolean, tooltip?: string }[][] = type === 'borrow' ? [ [ { label: t`AMM swap fee`, value: parameters?.fee, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, isError: parametersError }, @@ -41,7 +38,7 @@ const MarketParameters = ({ { label: t`Band width factor`, value: parameters?.A, formatOptions: { useGrouping: false }, isError: parametersError }, { label: t`Loan discount`, value: parameters?.loan_discount, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, isError: parametersError }, { label: t`Liquidation discount`, value: parameters?.liquidation_discount, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, isError: parametersError }, - { label: t`Max LTV`, value: _getMaxLTV( parameters?.A, parameters?.loan_discount), formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, isError: parametersError, isAdvance: true, tooltip: t`Max possible loan at N=4` }, + { label: t`Max LTV`, value: _getMaxLTV( parameters?.A, parameters?.loan_discount), formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, isError: parametersError, tooltip: t`Max possible loan at N=4` }, ], [ { label: t`Base price`, value: prices?.basePrice, formatOptions: { decimals: 5 }, title: t`Prices`, isError: pricesError }, @@ -62,35 +59,32 @@ const MarketParameters = ({ {marketDetails.map((details, idx) => (
- {details.map(({ label, value, formatOptions, title, isError, isRow, isAdvance, tooltip }) => { - const show = typeof isAdvance === 'undefined' || (isAdvance && isAdvancedMode) - return ( - - {show ? ( - <> - {title && {title}} - {isRow ? ( - - {label}: - {formatNumber(value, { ...(formatOptions ?? {}), defaultValue: '-' })} - - ) : ( - - {isError ? ( - '?' - ) : ( - - {formatNumber(value, { ...(formatOptions ?? {}), defaultValue: '-' })} - {tooltip && } - - )} - - )} - - ) : null} - - ) - })} + {details.map(({ label, value, formatOptions, title, isError, isRow, tooltip }) => ( + + { + <> + {title && {title}} + {isRow ? ( + + {label}: + {formatNumber(value, { ...(formatOptions ?? {}), defaultValue: '-' })} + + ) : ( + + {isError ? ( + '?' + ) : ( + + {formatNumber(value, { ...(formatOptions ?? {}), defaultValue: '-' })} + {tooltip && } + + )} + + )} + + } + + ))}
))}
From 8c2ef574df1693b7595f45b8c2c4251e9ec43d55 Mon Sep 17 00:00:00 2001 From: Alunara Date: Tue, 25 Nov 2025 16:04:31 +0100 Subject: [PATCH 02/23] refactor: remove unnecessary isRow differentiation --- .../DetailsMarket/components/MarketParameters.tsx | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx index 011a57107c..d57478696c 100644 --- a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx +++ b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx @@ -30,7 +30,7 @@ const MarketParameters = ({ const { pricePerShare, error: pricePerShareError } = vaultPricePerShareResp ?? {} // prettier-ignore - const marketDetails: { label: string; value: string | number | undefined; formatOptions?: NumberFormatOptions; title?: string; isError: string; isRow?: boolean, tooltip?: string }[][] = type === 'borrow' ? + const marketDetails: { label: string; value: string | number | undefined; formatOptions?: NumberFormatOptions; title?: string; isError: string; tooltip?: string }[][] = type === 'borrow' ? [ [ { label: t`AMM swap fee`, value: parameters?.fee, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, isError: parametersError }, @@ -46,7 +46,7 @@ const MarketParameters = ({ ], ] : [ [ - { label: t`Price per share`, value: pricePerShare, formatOptions: { decimals: 5 }, isRow: true, isError: pricePerShareError }, + { label: t`Price per share`, value: pricePerShare, formatOptions: { decimals: 5 }, isError: pricePerShareError }, ] ] @@ -59,17 +59,12 @@ const MarketParameters = ({ {marketDetails.map((details, idx) => (
- {details.map(({ label, value, formatOptions, title, isError, isRow, tooltip }) => ( + {details.map(({ label, value, formatOptions, title, isError, tooltip }) => ( { <> {title && {title}} - {isRow ? ( - - {label}: - {formatNumber(value, { ...(formatOptions ?? {}), defaultValue: '-' })} - - ) : ( + { {isError ? ( '?' @@ -80,7 +75,7 @@ const MarketParameters = ({ )} - )} + } } From 2d5c563bee76920a62d328422944f3251d78ccde Mon Sep 17 00:00:00 2001 From: Alunara Date: Tue, 25 Nov 2025 16:52:52 +0100 Subject: [PATCH 03/23] refactor: replace box and subtitle for mui stack and typography --- .../components/DetailsContracts.tsx | 12 ++++++++---- .../components/MarketParameters.tsx | 13 ++++++++----- .../src/lend/components/DetailsMarket/styles.ts | 5 ----- .../lend/components/MarketInformationComp.tsx | 12 ++++++++---- .../LoanInfoLlamma/LoanInfoParameters.tsx | 12 +++++------- .../loan/components/LoanInfoLlamma/styles.ts | 5 ----- .../loan/components/MarketInformationComp.tsx | 17 +++++++++++------ 7 files changed, 40 insertions(+), 36 deletions(-) diff --git a/apps/main/src/lend/components/DetailsMarket/components/DetailsContracts.tsx b/apps/main/src/lend/components/DetailsMarket/components/DetailsContracts.tsx index 29f29addfc..94214a4c6b 100644 --- a/apps/main/src/lend/components/DetailsMarket/components/DetailsContracts.tsx +++ b/apps/main/src/lend/components/DetailsMarket/components/DetailsContracts.tsx @@ -2,12 +2,16 @@ import { ReactNode } from 'react' import { zeroAddress } from 'viem' import ChipInactive from '@/lend/components/ChipInactive' import DetailInfoAddressLookup from '@/lend/components/DetailsMarket/components/DetailInfoAddressLookup' -import { SubTitle } from '@/lend/components/DetailsMarket/styles' import TokenLabel from '@/lend/components/TokenLabel' import { PageContentProps } from '@/lend/types/lend.types' +import Stack from '@mui/material/Stack' +import Typography from '@mui/material/Typography' import Box from '@ui/Box' import Chip from '@ui/Typography/Chip' import { t } from '@ui-kit/lib/i18n' +import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' + +const { Spacing } = SizesAndSpaces type ContractItems = { label: ReactNode; address: string | undefined; invalidText?: string }[] @@ -31,8 +35,8 @@ const DetailsContracts = ({ rChainId, market }: Pick - {t`Contracts`} + + {t`Contracts`} {contracts.map((contracts, idx) => (
@@ -61,7 +65,7 @@ const DetailsContracts = ({ rChainId, market }: Pick ))} - + ) } diff --git a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx index d57478696c..14b2e9d430 100644 --- a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx +++ b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx @@ -1,14 +1,17 @@ import { Fragment, useEffect } from 'react' -import { SubTitle } from '@/lend/components/DetailsMarket/styles' import { useOneWayMarket } from '@/lend/entities/chain' import useStore from '@/lend/store/useStore' import { ChainId } from '@/lend/types/lend.types' -import Box from '@ui/Box' +import Stack from '@mui/material/Stack' +import Typography from '@mui/material/Typography' import DetailInfo from '@ui/DetailInfo' import Icon from '@ui/Icon' import Chip from '@ui/Typography/Chip' import { FORMAT_OPTIONS, formatNumber, NumberFormatOptions } from '@ui/utils' import { t } from '@ui-kit/lib/i18n' +import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' + +const { Spacing } = SizesAndSpaces const MarketParameters = ({ rChainId, @@ -56,14 +59,14 @@ const MarketParameters = ({ }, [type, owm]) return ( - + {marketDetails.map((details, idx) => (
{details.map(({ label, value, formatOptions, title, isError, tooltip }) => ( { <> - {title && {title}} + {title && {title}} { {isError ? ( @@ -82,7 +85,7 @@ const MarketParameters = ({ ))}
))} -
+ ) } diff --git a/apps/main/src/lend/components/DetailsMarket/styles.ts b/apps/main/src/lend/components/DetailsMarket/styles.ts index 2a7d0c7238..0ab30c53a5 100644 --- a/apps/main/src/lend/components/DetailsMarket/styles.ts +++ b/apps/main/src/lend/components/DetailsMarket/styles.ts @@ -1,11 +1,6 @@ import { styled } from 'styled-components' import Box from '@ui/Box' -export const SubTitle = styled.h3` - font-size: var(--font-size-3); - margin-bottom: var(--spacing-1); -` - export type StatsProps = { isBorderBottom?: boolean isMultiLine?: boolean diff --git a/apps/main/src/lend/components/MarketInformationComp.tsx b/apps/main/src/lend/components/MarketInformationComp.tsx index b7d92ce175..5f1cef19dc 100644 --- a/apps/main/src/lend/components/MarketInformationComp.tsx +++ b/apps/main/src/lend/components/MarketInformationComp.tsx @@ -2,13 +2,14 @@ import { BandsComp } from '@/lend/components/BandsComp' import ChartOhlcWrapper from '@/lend/components/ChartOhlcWrapper' import DetailsContracts from '@/lend/components/DetailsMarket/components/DetailsContracts' import MarketParameters from '@/lend/components/DetailsMarket/components/MarketParameters' -import { SubTitle } from '@/lend/components/DetailsMarket/styles' import networks from '@/lend/networks' import { PageContentProps } from '@/lend/types/lend.types' import { BandsChart } from '@/llamalend/features/bands-chart/BandsChart' import { useBandsData } from '@/llamalend/features/bands-chart/hooks/useBandsData' import { getBandsChartToken } from '@/llamalend/features/bands-chart/utils' -import { Stack, useTheme } from '@mui/material' +import { useTheme } from '@mui/material' +import Stack from '@mui/material/Stack' +import Typography from '@mui/material/Typography' import { getLib } from '@ui-kit/features/connect-wallet' import { useUserProfileStore } from '@ui-kit/features/user-profile' import { useNewBandsChart } from '@ui-kit/hooks/useFeatureFlags' @@ -108,8 +109,11 @@ export const MarketInformationComp = ({ - t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }}> - {t`Parameters`} + t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }} + > + {t`Loan Parameters`} diff --git a/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx b/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx index ec65422860..d2505bb3c0 100644 --- a/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx +++ b/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx @@ -1,12 +1,12 @@ import type { PageLoanManageProps } from '@/loan/components/PageLoanManage/types' import useStore from '@/loan/store/useStore' -import Box from '@ui/Box' +import Stack from '@mui/material/Stack' import DetailInfo from '@ui/DetailInfo' import { Chip } from '@ui/Typography' import { FORMAT_OPTIONS, formatNumber } from '@ui/utils' import { t } from '@ui-kit/lib/i18n' -interface Props extends Pick {} +type Props = Pick const LoanInfoParameters = ({ llamma, llammaId }: Props) => { const loanDetails = useStore((state) => state.loans.detailsMapper[llammaId]) @@ -14,10 +14,8 @@ const LoanInfoParameters = ({ llamma, llammaId }: Props) => { const { parameters, priceInfo } = loanDetails ?? {} return ( - - - {formatNumber(llamma?.A, { useGrouping: false })} - + + {formatNumber(llamma?.A, { useGrouping: false })} {typeof loanDetails?.basePrice !== 'undefined' && ( { )} - + ) } diff --git a/apps/main/src/loan/components/LoanInfoLlamma/styles.ts b/apps/main/src/loan/components/LoanInfoLlamma/styles.ts index b0a6edb6ce..a50cea2cdf 100644 --- a/apps/main/src/loan/components/LoanInfoLlamma/styles.ts +++ b/apps/main/src/loan/components/LoanInfoLlamma/styles.ts @@ -2,11 +2,6 @@ import { styled } from 'styled-components' import Box from '@ui/Box' import { breakpoints } from '@ui/utils' -export const SubTitle = styled.h3` - font-size: var(--font-size-3); - margin-bottom: 0.75rem; // 12px -` - export type StatsProps = { isBorderBottom?: boolean isMultiLine?: boolean diff --git a/apps/main/src/loan/components/MarketInformationComp.tsx b/apps/main/src/loan/components/MarketInformationComp.tsx index 41a2ce8817..e97d84d280 100644 --- a/apps/main/src/loan/components/MarketInformationComp.tsx +++ b/apps/main/src/loan/components/MarketInformationComp.tsx @@ -5,9 +5,10 @@ import { BandsComp } from '@/loan/components/BandsComp' import ChartOhlcWrapper from '@/loan/components/ChartOhlcWrapper' import DetailInfoAddressLookup from '@/loan/components/LoanInfoLlamma/components/DetailInfoAddressLookup' import LoanInfoParameters from '@/loan/components/LoanInfoLlamma/LoanInfoParameters' -import { SubTitle } from '@/loan/components/LoanInfoLlamma/styles' import type { ChainId, Llamma } from '@/loan/types/loan.types' -import { Stack, useTheme } from '@mui/material' +import { useTheme } from '@mui/material' +import Stack from '@mui/material/Stack' +import Typography from '@mui/material/Typography' import { useConnection } from '@ui-kit/features/connect-wallet' import { useUserProfileStore } from '@ui-kit/features/user-profile' import { useNewBandsChart } from '@ui-kit/hooks/useFeatureFlags' @@ -101,8 +102,9 @@ export const MarketInformationComp = ({ }, }} > - - {t`Contracts`} + + {t`Contracts`} + - t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }}> - {t`Loan Parameters`} + t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }} + > + {t`Loan Parameters`} From f21ff13acb0b12313a8aeddbf58ab6a08769c48c Mon Sep 17 00:00:00 2001 From: Alunara Date: Tue, 25 Nov 2025 17:11:32 +0100 Subject: [PATCH 04/23] refactor: convert loan parameters to actioninfos --- .../LoanInfoLlamma/LoanInfoParameters.tsx | 82 +++++++++---------- .../loan/components/MarketInformationComp.tsx | 4 +- .../PageLoanCreate/LoanFormCreate/index.tsx | 4 +- 3 files changed, 41 insertions(+), 49 deletions(-) diff --git a/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx b/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx index d2505bb3c0..f091e74fbe 100644 --- a/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx +++ b/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx @@ -1,56 +1,48 @@ -import type { PageLoanManageProps } from '@/loan/components/PageLoanManage/types' import useStore from '@/loan/store/useStore' +import type { MintMarketTemplate } from '@curvefi/llamalend-api/lib/mintMarkets' import Stack from '@mui/material/Stack' -import DetailInfo from '@ui/DetailInfo' -import { Chip } from '@ui/Typography' -import { FORMAT_OPTIONS, formatNumber } from '@ui/utils' +import { formatNumber } from '@ui/utils' import { t } from '@ui-kit/lib/i18n' +import ActionInfo from '@ui-kit/shared/ui/ActionInfo' -type Props = Pick - -const LoanInfoParameters = ({ llamma, llammaId }: Props) => { - const loanDetails = useStore((state) => state.loans.detailsMapper[llammaId]) - +export const LoanInfoParameters = ({ + market, + marketId: marketId, +}: { + market: MintMarketTemplate | null + marketId: string +}) => { + const loanDetails = useStore((state) => state.loans.detailsMapper[marketId]) const { parameters, priceInfo } = loanDetails ?? {} return ( - {formatNumber(llamma?.A, { useGrouping: false })} - - {typeof loanDetails?.basePrice !== 'undefined' && ( - - {formatNumber(loanDetails.basePrice)} - - )} - - - {typeof priceInfo?.oraclePrice !== 'undefined' && ( - - {formatNumber(priceInfo.oraclePrice)} - - )} - - - {typeof parameters?.rate !== 'undefined' && ( - - {formatNumber(parameters.rate, FORMAT_OPTIONS.PERCENT)} - - )} - + + + + + + + ) } - -export default LoanInfoParameters diff --git a/apps/main/src/loan/components/MarketInformationComp.tsx b/apps/main/src/loan/components/MarketInformationComp.tsx index e97d84d280..8153d0d164 100644 --- a/apps/main/src/loan/components/MarketInformationComp.tsx +++ b/apps/main/src/loan/components/MarketInformationComp.tsx @@ -4,7 +4,6 @@ import { getBandsChartToken } from '@/llamalend/features/bands-chart/utils' import { BandsComp } from '@/loan/components/BandsComp' import ChartOhlcWrapper from '@/loan/components/ChartOhlcWrapper' import DetailInfoAddressLookup from '@/loan/components/LoanInfoLlamma/components/DetailInfoAddressLookup' -import LoanInfoParameters from '@/loan/components/LoanInfoLlamma/LoanInfoParameters' import type { ChainId, Llamma } from '@/loan/types/loan.types' import { useTheme } from '@mui/material' import Stack from '@mui/material/Stack' @@ -14,6 +13,7 @@ import { useUserProfileStore } from '@ui-kit/features/user-profile' import { useNewBandsChart } from '@ui-kit/hooks/useFeatureFlags' import { t } from '@ui-kit/lib/i18n' import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' +import { LoanInfoParameters } from './LoanInfoLlamma/LoanInfoParameters' const { Spacing } = SizesAndSpaces @@ -123,7 +123,7 @@ export const MarketInformationComp = ({ sx={{ backgroundColor: (t) => t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }} > {t`Loan Parameters`} - + )} diff --git a/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx b/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx index 9be9538cfd..4535d0ff62 100644 --- a/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx +++ b/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx @@ -4,7 +4,6 @@ import { DEFAULT_HEALTH_MODE } from '@/llamalend/constants' import AlertFormError from '@/loan/components/AlertFormError' import DialogHealthWarning from '@/loan/components/DialogHealthWarning' import LoanFormConnect from '@/loan/components/LoanFormConnect' -import LoanInfoParameters from '@/loan/components/LoanInfoLlamma/LoanInfoParameters' import DetailInfo from '@/loan/components/PageLoanCreate/LoanFormCreate/components/DetailInfo' import DialogHealthLeverageWarning from '@/loan/components/PageLoanCreate/LoanFormCreate/components/DialogHealthLeverageWarning' import type { FormStatus, FormValues, PageLoanCreateProps, StepKey } from '@/loan/components/PageLoanCreate/types' @@ -37,6 +36,7 @@ import { useTokenUsdRate } from '@ui-kit/lib/model/entities/token-usd-rate' import { LargeTokenInput } from '@ui-kit/shared/ui/LargeTokenInput' import { TokenLabel } from '@ui-kit/shared/ui/TokenLabel' import { decimal, type Decimal } from '@ui-kit/utils' +import { LoanInfoParameters } from '../../LoanInfoLlamma/LoanInfoParameters' const LoanCreate = ({ collateralAlert, @@ -469,7 +469,7 @@ const LoanCreate = ({ {!isAdvancedMode && ( - + )} From fe4c898e2db449cb03b9196125d7dc0f37658032 Mon Sep 17 00:00:00 2001 From: Alunara Date: Tue, 25 Nov 2025 18:01:26 +0100 Subject: [PATCH 05/23] refactor: convert lend parameters to actioninfos --- .../components/MarketParameters.tsx | 120 +++++++++--------- .../lend/components/MarketInformationComp.tsx | 7 +- .../PageLoanCreate/LoanFormCreate/index.tsx | 4 +- 3 files changed, 63 insertions(+), 68 deletions(-) diff --git a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx index 14b2e9d430..d75a8927c3 100644 --- a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx +++ b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx @@ -1,31 +1,51 @@ -import { Fragment, useEffect } from 'react' -import { useOneWayMarket } from '@/lend/entities/chain' +import { useEffect } from 'react' import useStore from '@/lend/store/useStore' import { ChainId } from '@/lend/types/lend.types' +import type { LendMarketTemplate } from '@curvefi/llamalend-api/lib/lendMarkets' import Stack from '@mui/material/Stack' import Typography from '@mui/material/Typography' -import DetailInfo from '@ui/DetailInfo' -import Icon from '@ui/Icon' -import Chip from '@ui/Typography/Chip' import { FORMAT_OPTIONS, formatNumber, NumberFormatOptions } from '@ui/utils' import { t } from '@ui-kit/lib/i18n' +import ActionInfo from '@ui-kit/shared/ui/ActionInfo' import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' const { Spacing } = SizesAndSpaces -const MarketParameters = ({ - rChainId, - rOwmId, +// In [1]: ltv = lambda x: ((x[0] - 1) / x[0])**2 * (1 - x[1]) +// In [2]: ltv((30, 0.11)) +// Out[2]: 0.8316555555555556 +// where x[0] is A, x[1] is loan discount normalised between 0 and 1 (so 11% is 0.11). multiply ltv by 100 to show percentage. +// always show 'max ltv' which is the max possible loan at N=4 (not advisable but hey it exists!). +function getMaxLTV(a: string | undefined, loanDiscount: string | undefined) { + if (typeof a === 'undefined' || typeof loanDiscount === 'undefined') return + return ((+a - 1) / +a) ** 2 * (1 - +loanDiscount / 100) * 100 +} + +type MarketDetails = { + title: string + details: { + label: string + value: string | number | undefined + formatOptions?: NumberFormatOptions + isError: string + tooltip?: string + }[] +} + +export const MarketParameters = ({ + chainId, + market, + marketId, type, }: { - rChainId: ChainId - rOwmId: string + chainId: ChainId + market: LendMarketTemplate | undefined + marketId: string type: 'borrow' | 'supply' }) => { - const owm = useOneWayMarket(rChainId, rOwmId).data - const loanPricesResp = useStore((state) => state.markets.pricesMapper[rChainId]?.[rOwmId]) - const parametersResp = useStore((state) => state.markets.statsParametersMapper[rChainId]?.[rOwmId]) - const vaultPricePerShareResp = useStore((state) => state.markets.vaultPricePerShare[rChainId]?.[rOwmId]) + const loanPricesResp = useStore((state) => state.markets.pricesMapper[chainId]?.[marketId]) + const parametersResp = useStore((state) => state.markets.statsParametersMapper[chainId]?.[marketId]) + const vaultPricePerShareResp = useStore((state) => state.markets.vaultPricePerShare[chainId]?.[marketId]) const fetchVaultPricePerShare = useStore((state) => state.markets.fetchVaultPricePerShare) const { prices, error: pricesError } = loanPricesResp ?? {} @@ -33,70 +53,48 @@ const MarketParameters = ({ const { pricePerShare, error: pricePerShareError } = vaultPricePerShareResp ?? {} // prettier-ignore - const marketDetails: { label: string; value: string | number | undefined; formatOptions?: NumberFormatOptions; title?: string; isError: string; tooltip?: string }[][] = type === 'borrow' ? + const marketDetails: MarketDetails[] = type === 'borrow' ? [ - [ + { title: t`Loan Parameters`, details: [ { label: t`AMM swap fee`, value: parameters?.fee, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, isError: parametersError }, { label: t`Admin fee`, value: parameters?.admin_fee, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, isError: parametersError }, { label: t`Band width factor`, value: parameters?.A, formatOptions: { useGrouping: false }, isError: parametersError }, { label: t`Loan discount`, value: parameters?.loan_discount, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, isError: parametersError }, { label: t`Liquidation discount`, value: parameters?.liquidation_discount, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, isError: parametersError }, - { label: t`Max LTV`, value: _getMaxLTV( parameters?.A, parameters?.loan_discount), formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, isError: parametersError, tooltip: t`Max possible loan at N=4` }, - ], - [ - { label: t`Base price`, value: prices?.basePrice, formatOptions: { decimals: 5 }, title: t`Prices`, isError: pricesError }, + { label: t`Max LTV`, value: getMaxLTV( parameters?.A, parameters?.loan_discount), formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, isError: parametersError, tooltip: t`Max possible loan at N=4` }, + ]}, + { title: t`Prices`, details: [ + { label: t`Base price`, value: prices?.basePrice, formatOptions: { decimals: 5 }, isError: pricesError }, { label: t`Oracle price`, value: prices?.oraclePrice, formatOptions: { decimals: 5 }, isError: pricesError }, - ], + ]}, ] : [ - [ + {title: t`Prices`, details: [ { label: t`Price per share`, value: pricePerShare, formatOptions: { decimals: 5 }, isError: pricePerShareError }, - ] + ]} ] useEffect(() => { - if (type === 'supply' && owm) void fetchVaultPricePerShare(rChainId, owm) - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [type, owm]) + if (type === 'supply' && market) void fetchVaultPricePerShare(chainId, market) + }, [type, market, fetchVaultPricePerShare, chainId]) return ( - {marketDetails.map((details, idx) => ( -
- {details.map(({ label, value, formatOptions, title, isError, tooltip }) => ( - - { - <> - {title && {title}} - { - - {isError ? ( - '?' - ) : ( - - {formatNumber(value, { ...(formatOptions ?? {}), defaultValue: '-' })} - {tooltip && } - - )} - - } - - } - + {marketDetails.map(({ title, details }) => ( + + {title} + + {details.map(({ label, value, formatOptions, isError, tooltip }) => ( + + + ))} -
+
))} ) } - -// In [1]: ltv = lambda x: ((x[0] - 1) / x[0])**2 * (1 - x[1]) -// In [2]: ltv((30, 0.11)) -// Out[2]: 0.8316555555555556 -// where x[0] is A, x[1] is loan discount normalised between 0 and 1 (so 11% is 0.11). multiply ltv by 100 to show percentage. -// always show 'max ltv' which is the max possible loan at N=4 (not advisable but hey it exists!). -function _getMaxLTV(a: string | undefined, loanDiscount: string | undefined) { - if (typeof a === 'undefined' || typeof loanDiscount === 'undefined') return '' - return ((+a - 1) / +a) ** 2 * (1 - +loanDiscount / 100) * 100 -} - -export default MarketParameters diff --git a/apps/main/src/lend/components/MarketInformationComp.tsx b/apps/main/src/lend/components/MarketInformationComp.tsx index 5f1cef19dc..e642f84171 100644 --- a/apps/main/src/lend/components/MarketInformationComp.tsx +++ b/apps/main/src/lend/components/MarketInformationComp.tsx @@ -1,7 +1,6 @@ import { BandsComp } from '@/lend/components/BandsComp' import ChartOhlcWrapper from '@/lend/components/ChartOhlcWrapper' import DetailsContracts from '@/lend/components/DetailsMarket/components/DetailsContracts' -import MarketParameters from '@/lend/components/DetailsMarket/components/MarketParameters' import networks from '@/lend/networks' import { PageContentProps } from '@/lend/types/lend.types' import { BandsChart } from '@/llamalend/features/bands-chart/BandsChart' @@ -9,12 +8,11 @@ import { useBandsData } from '@/llamalend/features/bands-chart/hooks/useBandsDat import { getBandsChartToken } from '@/llamalend/features/bands-chart/utils' import { useTheme } from '@mui/material' import Stack from '@mui/material/Stack' -import Typography from '@mui/material/Typography' import { getLib } from '@ui-kit/features/connect-wallet' import { useUserProfileStore } from '@ui-kit/features/user-profile' import { useNewBandsChart } from '@ui-kit/hooks/useFeatureFlags' -import { t } from '@ui-kit/lib/i18n' import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' +import { MarketParameters } from './DetailsMarket/components/MarketParameters' const { Spacing } = SizesAndSpaces @@ -113,8 +111,7 @@ export const MarketInformationComp = ({ gap={Spacing.xs} sx={{ backgroundColor: (t) => t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }} > - {t`Loan Parameters`} - + )} diff --git a/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx b/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx index cf8cef2e9d..e6a0231aae 100644 --- a/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx +++ b/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx @@ -1,7 +1,6 @@ import { ReactNode, useCallback, useEffect, useRef, useState } from 'react' import AlertFormError from '@/lend/components/AlertFormError' import AlertLoanSummary from '@/lend/components/AlertLoanSummary' -import MarketParameters from '@/lend/components/DetailsMarket/components/MarketParameters' import DialogFormWarning from '@/lend/components/DialogFormWarning' import InpToken from '@/lend/components/InpToken' import InpTokenBorrow from '@/lend/components/InpTokenBorrow' @@ -38,6 +37,7 @@ import { useNavigate } from '@ui-kit/hooks/router' import usePageVisibleInterval from '@ui-kit/hooks/usePageVisibleInterval' import { t } from '@ui-kit/lib/i18n' import { REFRESH_INTERVAL } from '@ui-kit/lib/model' +import { MarketParameters } from '../../DetailsMarket/components/MarketParameters' const LoanCreate = ({ isLeverage = false, @@ -440,7 +440,7 @@ const LoanCreate = ({ {!isAdvancedMode && ( {t`Market details`}}> - + )} From 9bf274e396534401cc556583ceda94404467d1ac Mon Sep 17 00:00:00 2001 From: Alunara Date: Tue, 25 Nov 2025 18:38:00 +0100 Subject: [PATCH 06/23] refactor: add shared marketprices parameters component --- .../components/MarketParameters.tsx | 115 +++++++++++------- .../lend/components/MarketInformationComp.tsx | 6 +- .../market-parameters/MarketPrices.tsx | 40 ++++++ .../LoanInfoLlamma/LoanInfoParameters.tsx | 16 +-- .../loan/components/MarketInformationComp.tsx | 15 ++- 5 files changed, 125 insertions(+), 67 deletions(-) create mode 100644 apps/main/src/llamalend/features/market-parameters/MarketPrices.tsx diff --git a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx index d75a8927c3..6ee102f061 100644 --- a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx +++ b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx @@ -1,6 +1,7 @@ -import { useEffect } from 'react' +import { useMarketPricePerShare } from '@/lend/entities/market-details' import useStore from '@/lend/store/useStore' import { ChainId } from '@/lend/types/lend.types' +import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' import type { LendMarketTemplate } from '@curvefi/llamalend-api/lib/lendMarkets' import Stack from '@mui/material/Stack' import Typography from '@mui/material/Typography' @@ -22,14 +23,11 @@ function getMaxLTV(a: string | undefined, loanDiscount: string | undefined) { } type MarketDetails = { - title: string - details: { - label: string - value: string | number | undefined - formatOptions?: NumberFormatOptions - isError: string - tooltip?: string - }[] + label: string + value: string | number | undefined + formatOptions: NumberFormatOptions + isError: string + tooltip?: string } export const MarketParameters = ({ @@ -43,35 +41,52 @@ export const MarketParameters = ({ marketId: string type: 'borrow' | 'supply' }) => { - const loanPricesResp = useStore((state) => state.markets.pricesMapper[chainId]?.[marketId]) const parametersResp = useStore((state) => state.markets.statsParametersMapper[chainId]?.[marketId]) const vaultPricePerShareResp = useStore((state) => state.markets.vaultPricePerShare[chainId]?.[marketId]) const fetchVaultPricePerShare = useStore((state) => state.markets.fetchVaultPricePerShare) - const { prices, error: pricesError } = loanPricesResp ?? {} const { parameters, error: parametersError } = parametersResp ?? {} const { pricePerShare, error: pricePerShareError } = vaultPricePerShareResp ?? {} - // prettier-ignore - const marketDetails: MarketDetails[] = type === 'borrow' ? - [ - { title: t`Loan Parameters`, details: [ - { label: t`AMM swap fee`, value: parameters?.fee, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, isError: parametersError }, - { label: t`Admin fee`, value: parameters?.admin_fee, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, isError: parametersError }, - { label: t`Band width factor`, value: parameters?.A, formatOptions: { useGrouping: false }, isError: parametersError }, - { label: t`Loan discount`, value: parameters?.loan_discount, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, isError: parametersError }, - { label: t`Liquidation discount`, value: parameters?.liquidation_discount, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, isError: parametersError }, - { label: t`Max LTV`, value: getMaxLTV( parameters?.A, parameters?.loan_discount), formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, isError: parametersError, tooltip: t`Max possible loan at N=4` }, - ]}, - { title: t`Prices`, details: [ - { label: t`Base price`, value: prices?.basePrice, formatOptions: { decimals: 5 }, isError: pricesError }, - { label: t`Oracle price`, value: prices?.oraclePrice, formatOptions: { decimals: 5 }, isError: pricesError }, - ]}, - ] : [ - {title: t`Prices`, details: [ - { label: t`Price per share`, value: pricePerShare, formatOptions: { decimals: 5 }, isError: pricePerShareError }, - ]} - ] + const borrowDetails: MarketDetails[] = [ + { + label: t`AMM swap fee`, + value: parameters?.fee, + formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, + isError: parametersError, + }, + { + label: t`Admin fee`, + value: parameters?.admin_fee, + formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, + isError: parametersError, + }, + { + label: t`Band width factor`, + value: parameters?.A, + formatOptions: { useGrouping: false }, + isError: parametersError, + }, + { + label: t`Loan discount`, + value: parameters?.loan_discount, + formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, + isError: parametersError, + }, + { + label: t`Liquidation discount`, + value: parameters?.liquidation_discount, + formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, + isError: parametersError, + }, + { + label: t`Max LTV`, + value: getMaxLTV(parameters?.A, parameters?.loan_discount), + formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, + isError: parametersError, + tooltip: t`Max possible loan at N=4`, + }, + ] useEffect(() => { if (type === 'supply' && market) void fetchVaultPricePerShare(chainId, market) @@ -79,22 +94,32 @@ export const MarketParameters = ({ return ( - {marketDetails.map(({ title, details }) => ( - - {title} - - {details.map(({ label, value, formatOptions, isError, tooltip }) => ( - - - + {type === 'borrow' && ( + + {t`Loan Parameters`} + {borrowDetails.map(({ label, value, formatOptions, isError, tooltip }) => ( + ))} - ))} + )} + + + {t`Prices`} + + {type === 'supply' && ( + + )} + ) } diff --git a/apps/main/src/lend/components/MarketInformationComp.tsx b/apps/main/src/lend/components/MarketInformationComp.tsx index e642f84171..556abc4562 100644 --- a/apps/main/src/lend/components/MarketInformationComp.tsx +++ b/apps/main/src/lend/components/MarketInformationComp.tsx @@ -107,10 +107,8 @@ export const MarketInformationComp = ({ - t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }} - > + + t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }}> diff --git a/apps/main/src/llamalend/features/market-parameters/MarketPrices.tsx b/apps/main/src/llamalend/features/market-parameters/MarketPrices.tsx new file mode 100644 index 0000000000..336609119b --- /dev/null +++ b/apps/main/src/llamalend/features/market-parameters/MarketPrices.tsx @@ -0,0 +1,40 @@ +import { useMarketBasePrice } from '@/llamalend/queries/market-base-price.query' +import { useMarketOraclePrice } from '@/llamalend/queries/market-oracle-price.query' +import type { IChainId } from '@curvefi/llamalend-api/lib/interfaces' +import { formatNumber } from '@ui/utils' +import { t } from '@ui-kit/lib/i18n' +import ActionInfo from '@ui-kit/shared/ui/ActionInfo' + +export const MarketPrices = ({ chainId, marketId }: { chainId: IChainId; marketId: string }) => { + const { + data: basePrice, + isLoading: isLoadingBasePrice, + error: errorBasePrice, + } = useMarketBasePrice({ chainId, marketId }) + + const { + data: oraclePrice, + isLoading: isLoadingOraclePrice, + error: errorOraclePrice, + } = useMarketOraclePrice({ chainId, marketId }) + + return ( + <> + + + + + ) +} diff --git a/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx b/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx index f091e74fbe..fec412c47a 100644 --- a/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx +++ b/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx @@ -13,7 +13,7 @@ export const LoanInfoParameters = ({ marketId: string }) => { const loanDetails = useStore((state) => state.loans.detailsMapper[marketId]) - const { parameters, priceInfo } = loanDetails ?? {} + const { parameters } = loanDetails ?? {} return ( @@ -23,20 +23,6 @@ export const LoanInfoParameters = ({ loading={market?.A == null} /> - - - - + t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }} > - {t`Loan Parameters`} - + + {t`Loan Parameters`} + + + + + {t`Prices`} + + )} From 185f56fb29ed4b6d4bc7d26f53299a20e24ee12b Mon Sep 17 00:00:00 2001 From: Alunara Date: Tue, 25 Nov 2025 18:46:03 +0100 Subject: [PATCH 07/23] refactor: replace store with zustand for lend price per share --- .../components/MarketParameters.tsx | 19 +++++++------- apps/main/src/lend/hooks/useVaultShares.ts | 21 ++++++--------- .../main/src/lend/store/createMarketsSlice.ts | 26 ------------------- 3 files changed, 17 insertions(+), 49 deletions(-) diff --git a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx index 6ee102f061..db0ceddc49 100644 --- a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx +++ b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx @@ -42,11 +42,13 @@ export const MarketParameters = ({ type: 'borrow' | 'supply' }) => { const parametersResp = useStore((state) => state.markets.statsParametersMapper[chainId]?.[marketId]) - const vaultPricePerShareResp = useStore((state) => state.markets.vaultPricePerShare[chainId]?.[marketId]) - const fetchVaultPricePerShare = useStore((state) => state.markets.fetchVaultPricePerShare) - const { parameters, error: parametersError } = parametersResp ?? {} - const { pricePerShare, error: pricePerShareError } = vaultPricePerShareResp ?? {} + + const { + data: pricePerShare, + isLoading: isLoadingPricePerShare, + error: errorPricePerShare, + } = useMarketPricePerShare({ chainId, marketId }) const borrowDetails: MarketDetails[] = [ { @@ -88,10 +90,6 @@ export const MarketParameters = ({ }, ] - useEffect(() => { - if (type === 'supply' && market) void fetchVaultPricePerShare(chainId, market) - }, [type, market, fetchVaultPricePerShare, chainId]) - return ( {type === 'borrow' && ( @@ -115,8 +113,9 @@ export const MarketParameters = ({ {type === 'supply' && ( )} diff --git a/apps/main/src/lend/hooks/useVaultShares.ts b/apps/main/src/lend/hooks/useVaultShares.ts index 177ae84c46..7f70242d89 100644 --- a/apps/main/src/lend/hooks/useVaultShares.ts +++ b/apps/main/src/lend/hooks/useVaultShares.ts @@ -1,9 +1,9 @@ -import { useEffect, useMemo } from 'react' +import { useMemo } from 'react' import { useOneWayMarket } from '@/lend/entities/chain' -import useStore from '@/lend/store/useStore' import { ChainId } from '@/lend/types/lend.types' import { useTokenUsdRate } from '@ui-kit/lib/model/entities/token-usd-rate' import { formatNumber } from '@ui-kit/utils' +import { useMarketPricePerShare } from '../entities/market-details' function formatNumberWithPrecision(value: number, precisionDigits: number) { const valueDigits = Math.max(0, Math.floor(Math.log10(value))) @@ -13,15 +13,15 @@ function formatNumberWithPrecision(value: number, precisionDigits: number) { function useVaultShares(rChainId: ChainId, rOwmId: string, vaultShares: string | number | undefined = '0') { const market = useOneWayMarket(rChainId, rOwmId).data - const pricePerShareResp = useStore((state) => state.markets.vaultPricePerShare[rChainId]?.[rOwmId]) + const { data: pricePerShare, error: errorPricePerShare } = useMarketPricePerShare({ + chainId: rChainId, + marketId: rOwmId, + }) const { address = '', symbol = '' } = market?.borrowed_token ?? {} const { data: usdRate } = useTokenUsdRate({ chainId: rChainId, tokenAddress: address }) - const fetchVaultPricePerShare = useStore((state) => state.markets.fetchVaultPricePerShare) const { borrowedAmount, borrowedAmountUsd } = useMemo<{ borrowedAmount: string; borrowedAmountUsd: string }>(() => { - const { pricePerShare, error } = pricePerShareResp ?? {} - - if (error || usdRate == null || isNaN(usdRate)) { + if (pricePerShare == null || errorPricePerShare || usdRate == null || isNaN(usdRate)) { return { borrowedAmount: '?', borrowedAmountUsd: '?' } } @@ -36,12 +36,7 @@ function useVaultShares(rChainId: ChainId, rOwmId: string, vaultShares: string | } return { borrowedAmount: '', borrowedAmountUsd: '' } - }, [pricePerShareResp, usdRate, symbol, vaultShares]) - - useEffect(() => { - if (market && +vaultShares > 0) void fetchVaultPricePerShare(rChainId, market) - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [market?.id, vaultShares]) + }, [pricePerShare, errorPricePerShare, usdRate, symbol, vaultShares]) return { isLoading: borrowedAmount === '' && borrowedAmountUsd === '', diff --git a/apps/main/src/lend/store/createMarketsSlice.ts b/apps/main/src/lend/store/createMarketsSlice.ts index 32bfedf357..c1a1fb0200 100644 --- a/apps/main/src/lend/store/createMarketsSlice.ts +++ b/apps/main/src/lend/store/createMarketsSlice.ts @@ -4,7 +4,6 @@ import apiLending from '@/lend/lib/apiLending' import type { State } from '@/lend/store/useStore' import { Api, - ChainId, MarketDetailsView, MarketsMaxLeverageMapper, MarketsPricesMapper, @@ -15,7 +14,6 @@ import { MarketsStatsParametersMapper, OneWayMarketTemplate, } from '@/lend/types/lend.types' -import { getErrorMessage } from '@/lend/utils/helpers' type StateKey = keyof typeof DEFAULT_STATE @@ -28,7 +26,6 @@ type SliceState = { ratesMapper: { [chainId: string]: MarketsRatesMapper } rewardsMapper: { [chainId: string]: MarketsRewardsMapper } marketDetailsView: MarketDetailsView - vaultPricePerShare: { [chainId: string]: { [owmId: string]: { pricePerShare: string; error: string } } } } const sliceKey = 'markets' @@ -41,7 +38,6 @@ export type MarketsSlice = { // individual fetchAll(api: Api, OneWayMarketTemplate: OneWayMarketTemplate, shouldRefetch?: boolean): Promise - fetchVaultPricePerShare(chainId: ChainId, OneWayMarketTemplate: OneWayMarketTemplate, shouldRefetch?: boolean): Promise setStateByActiveKey(key: StateKey, activeKey: string, value: T): void setStateByKey(key: StateKey, value: T): void @@ -59,7 +55,6 @@ const DEFAULT_STATE: SliceState = { ratesMapper: {}, rewardsMapper: {}, marketDetailsView: '', - vaultPricePerShare: {}, } const createMarketsSlice = (set: StoreApi['setState'], get: StoreApi['getState']): MarketsSlice => ({ @@ -113,27 +108,6 @@ const createMarketsSlice = (set: StoreApi['setState'], get: StoreApi sliceState.fetchDatas(key, api, [OneWayMarketTemplate], shouldRefetch))) }, - fetchVaultPricePerShare: async (chainId, owm, shouldRefetch) => { - const sliceState = get()[sliceKey] - const resp = { pricePerShare: '', error: '' } - - const { pricePerShare: foundPricePerShare } = sliceState.vaultPricePerShare[chainId]?.[owm.id] ?? {} - if (foundPricePerShare && +foundPricePerShare > 0 && !shouldRefetch) { - resp.pricePerShare = foundPricePerShare - } else { - try { - resp.pricePerShare = await owm.vault.previewRedeem(1) - } catch (error) { - console.error(error) - resp.error = getErrorMessage(error, 'error-api') - } - - sliceState.setStateByActiveKey('vaultPricePerShare', chainId.toString(), { - ...(get()[sliceKey].vaultPricePerShare[chainId] ?? {}), - [owm.id]: resp, - }) - } - }, // slice helpers setStateByActiveKey: (key: StateKey, activeKey: string, value: T) => { From 40a752b06bfed4f710ff8706cabaf872d7cba728 Mon Sep 17 00:00:00 2001 From: Alunara Date: Tue, 25 Nov 2025 18:54:50 +0100 Subject: [PATCH 08/23] refactor: remove unused market parameter --- .../components/DetailsMarket/components/MarketParameters.tsx | 3 --- apps/main/src/lend/components/MarketInformationComp.tsx | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx index db0ceddc49..a6b7aa769d 100644 --- a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx +++ b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx @@ -2,7 +2,6 @@ import { useMarketPricePerShare } from '@/lend/entities/market-details' import useStore from '@/lend/store/useStore' import { ChainId } from '@/lend/types/lend.types' import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' -import type { LendMarketTemplate } from '@curvefi/llamalend-api/lib/lendMarkets' import Stack from '@mui/material/Stack' import Typography from '@mui/material/Typography' import { FORMAT_OPTIONS, formatNumber, NumberFormatOptions } from '@ui/utils' @@ -32,12 +31,10 @@ type MarketDetails = { export const MarketParameters = ({ chainId, - market, marketId, type, }: { chainId: ChainId - market: LendMarketTemplate | undefined marketId: string type: 'borrow' | 'supply' }) => { diff --git a/apps/main/src/lend/components/MarketInformationComp.tsx b/apps/main/src/lend/components/MarketInformationComp.tsx index 556abc4562..0120b2b707 100644 --- a/apps/main/src/lend/components/MarketInformationComp.tsx +++ b/apps/main/src/lend/components/MarketInformationComp.tsx @@ -109,7 +109,7 @@ export const MarketInformationComp = ({ t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }}> - + )} From 0936f22fc7e3cd41c21f03d49d0f7076965e9c89 Mon Sep 17 00:00:00 2001 From: Alunara Date: Tue, 25 Nov 2025 18:57:23 +0100 Subject: [PATCH 09/23] refactor: inline query functions for readability --- apps/main/src/lend/entities/market-details.ts | 97 ++++++------------- 1 file changed, 30 insertions(+), 67 deletions(-) diff --git a/apps/main/src/lend/entities/market-details.ts b/apps/main/src/lend/entities/market-details.ts index e827ab6156..7baf6e8f52 100644 --- a/apps/main/src/lend/entities/market-details.ts +++ b/apps/main/src/lend/entities/market-details.ts @@ -8,80 +8,44 @@ import type { MarketQuery, MarketParams } from '@ui-kit/lib/model/query/root-key const getLendMarket = (marketId: string) => requireLib('llamaApi').getLendMarket(marketId) -type MarketCapAndAvailable = { - cap: number - available: number -} -type MarketMaxLeverage = { - maxLeverage: string | null -} -type MarketCollateralAmounts = { - collateralAmount: number - borrowedAmount: number -} - -/** - * The purpose of this query is to allow fetching market collateral amounts on chain - * in order to display the most current data when a wallet is connected. - * */ -const _getMarketCapAndAvailable = async ({ marketId }: MarketQuery): Promise => { - const market = getLendMarket(marketId) - const capAndAvailable = await market.stats.capAndAvailable(false, USE_API) - return { - cap: +capAndAvailable.cap, - available: +capAndAvailable.available, - } -} - export const { useQuery: useMarketCapAndAvailable, invalidate: invalidateMarketCapAndAvailable } = queryFactory({ queryKey: (params: MarketParams) => [...rootKeys.market(params), 'marketCapAndAvailable', 'v1'] as const, - queryFn: _getMarketCapAndAvailable, + queryFn: async ({ marketId }: MarketQuery) => { + const market = getLendMarket(marketId) + const capAndAvailable = await market.stats.capAndAvailable(false, USE_API) + return { + cap: +capAndAvailable.cap, + available: +capAndAvailable.available, + } + }, refetchInterval: '1m', validationSuite: marketIdValidationSuite, }) -/** - * The purpose of this query is to allow fetching market max leverage on chain - * in order to display the most current data when a wallet is connected. - * */ -const _getMarketMaxLeverage = async ({ marketId }: MarketQuery): Promise => { - const market = getLendMarket(marketId) - const maxLeverage = market.leverage.hasLeverage() ? await market.leverage.maxLeverage(market?.minBands) : null - return { maxLeverage } -} - export const { useQuery: useMarketMaxLeverage } = queryFactory({ queryKey: (params: MarketParams) => [...rootKeys.market(params), 'marketMaxLeverage', 'v1'] as const, - queryFn: _getMarketMaxLeverage, + queryFn: async ({ marketId }: MarketQuery) => { + const market = getLendMarket(marketId) + const maxLeverage = market.leverage.hasLeverage() ? await market.leverage.maxLeverage(market?.minBands) : null + return { maxLeverage } + }, validationSuite: marketIdValidationSuite, }) -/** - * The purpose of this query is to allow fetching market collateral amounts on chain - * in order to display the most current data when a wallet is connected. - * */ -const _getMarketCollateralAmounts = async ({ marketId }: MarketQuery): Promise => { - const market = getLendMarket(marketId) - const ammBalance = await market.stats.ammBalances(false, USE_API) - return { - collateralAmount: +ammBalance.collateral, - borrowedAmount: +ammBalance.borrowed, - } -} - export const { useQuery: useMarketCollateralAmounts, invalidate: invalidateMarketCollateralAmounts } = queryFactory({ queryKey: (params: MarketParams) => [...rootKeys.market(params), 'marketCollateralAmounts', 'v1'] as const, - queryFn: _getMarketCollateralAmounts, + queryFn: async ({ marketId }: MarketQuery) => { + const market = getLendMarket(marketId) + const ammBalance = await market.stats.ammBalances(false, USE_API) + return { + collateralAmount: +ammBalance.collateral, + borrowedAmount: +ammBalance.borrowed, + } + }, refetchInterval: '1m', validationSuite: marketIdValidationSuite, }) -const _fetchOnChainMarketRate = async ({ marketId }: MarketQuery) => ({ - rates: await getLendMarket(marketId).stats.rates(false, false), - rewardsApr: await getLendMarket(marketId).vault.rewardsApr(false), - crvRates: await getLendMarket(marketId).vault.crvApr(false), -}) - /** * The purpose of this query is to allow fetching market parameters on chain * in order to display the most current data when a wallet is connected. @@ -89,22 +53,21 @@ const _fetchOnChainMarketRate = async ({ marketId }: MarketQuery) => ({ * */ export const { useQuery: useMarketOnChainRates, invalidate: invalidateMarketOnChainRates } = queryFactory({ queryKey: (params: MarketParams) => [...rootKeys.market(params), 'marketOnchainData', 'v1'] as const, - queryFn: _fetchOnChainMarketRate, + queryFn: async ({ marketId }: MarketQuery) => ({ + rates: await getLendMarket(marketId).stats.rates(false, false), + rewardsApr: await getLendMarket(marketId).vault.rewardsApr(false), + crvRates: await getLendMarket(marketId).vault.crvApr(false), + }), refetchInterval: '1m', validationSuite: marketIdValidationSuite, }) -const _fetchMarketPricePerShare = async ({ marketId }: MarketQuery) => { - const market = getLendMarket(marketId) - return await market.vault.previewRedeem(1) -} - -/** - * Fetches the price per share of a market on chain - */ export const { useQuery: useMarketPricePerShare, invalidate: invalidateMarketPricePerShare } = queryFactory({ queryKey: (params: MarketParams) => [...rootKeys.market(params), 'marketPricePerShare', 'v1'] as const, - queryFn: _fetchMarketPricePerShare, + queryFn: async ({ marketId }: MarketQuery) => { + const market = getLendMarket(marketId) + return await market.vault.previewRedeem(1) + }, refetchInterval: '1m', validationSuite: marketIdValidationSuite, }) From 28b96a0526e8d15628e12a5227c1187bec5f0a45 Mon Sep 17 00:00:00 2001 From: Alunara Date: Tue, 25 Nov 2025 19:04:48 +0100 Subject: [PATCH 10/23] refactor: replace store with zustand for lend market parameters --- .../components/MarketParameters.tsx | 25 ++++++++++-------- apps/main/src/lend/lib/apiLending.ts | 17 ------------ .../main/src/lend/store/createMarketsSlice.ts | 5 ---- apps/main/src/lend/types/lend.types.ts | 12 --------- .../llamalend/queries/market-parameters.ts | 26 +++++++++++++++++++ 5 files changed, 40 insertions(+), 45 deletions(-) create mode 100644 apps/main/src/llamalend/queries/market-parameters.ts diff --git a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx index a6b7aa769d..6955df2b27 100644 --- a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx +++ b/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx @@ -1,7 +1,7 @@ import { useMarketPricePerShare } from '@/lend/entities/market-details' -import useStore from '@/lend/store/useStore' import { ChainId } from '@/lend/types/lend.types' import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' +import { useMarketParameters } from '@/llamalend/queries/market-parameters' import Stack from '@mui/material/Stack' import Typography from '@mui/material/Typography' import { FORMAT_OPTIONS, formatNumber, NumberFormatOptions } from '@ui/utils' @@ -25,7 +25,7 @@ type MarketDetails = { label: string value: string | number | undefined formatOptions: NumberFormatOptions - isError: string + isError: boolean tooltip?: string } @@ -38,8 +38,11 @@ export const MarketParameters = ({ marketId: string type: 'borrow' | 'supply' }) => { - const parametersResp = useStore((state) => state.markets.statsParametersMapper[chainId]?.[marketId]) - const { parameters, error: parametersError } = parametersResp ?? {} + const { + data: parameters, + isLoading: isLoadingParameters, + isError: isErrorParameters, + } = useMarketParameters({ chainId, marketId }) const { data: pricePerShare, @@ -52,37 +55,37 @@ export const MarketParameters = ({ label: t`AMM swap fee`, value: parameters?.fee, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, - isError: parametersError, + isError: isErrorParameters, }, { label: t`Admin fee`, value: parameters?.admin_fee, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, - isError: parametersError, + isError: isErrorParameters, }, { label: t`Band width factor`, value: parameters?.A, formatOptions: { useGrouping: false }, - isError: parametersError, + isError: isErrorParameters, }, { label: t`Loan discount`, value: parameters?.loan_discount, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, - isError: parametersError, + isError: isErrorParameters, }, { label: t`Liquidation discount`, value: parameters?.liquidation_discount, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, - isError: parametersError, + isError: isErrorParameters, }, { label: t`Max LTV`, value: getMaxLTV(parameters?.A, parameters?.loan_discount), formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, - isError: parametersError, + isError: isErrorParameters, tooltip: t`Max possible loan at N=4`, }, ] @@ -98,7 +101,7 @@ export const MarketParameters = ({ label={label} value={isError ? '?' : formatNumber(value, formatOptions)} valueTooltip={tooltip} - loading={value == null} + loading={isLoadingParameters} /> ))} diff --git a/apps/main/src/lend/lib/apiLending.ts b/apps/main/src/lend/lib/apiLending.ts index f7136df21a..5054a2d9ee 100644 --- a/apps/main/src/lend/lib/apiLending.ts +++ b/apps/main/src/lend/lib/apiLending.ts @@ -18,7 +18,6 @@ import { MarketRewards, MarketStatBands, MarketStatCapAndAvailable, - MarketStatParameters, MaxRecvLeverageResp, ParsedBandsBalances, Provider, @@ -54,22 +53,6 @@ export const helpers = { } const market = { - fetchStatsParameters: async (markets: OneWayMarketTemplate[]) => { - log('fetchStatsParameters', markets.length) - const results: { [id: string]: MarketStatParameters } = {} - - await PromisePool.for(markets) - .handleError((errorObj, market) => { - const error = getErrorMessage(errorObj, 'error-api') - results[market.id] = { parameters: null, error } - }) - .process(async (market) => { - const parameters = await market.stats.parameters() - results[market.id] = { parameters, error: '' } - }) - - return results - }, fetchStatsBands: async (markets: OneWayMarketTemplate[]) => { log('fetchStatsBands', markets.length) const results: { [id: string]: MarketStatBands } = {} diff --git a/apps/main/src/lend/store/createMarketsSlice.ts b/apps/main/src/lend/store/createMarketsSlice.ts index c1a1fb0200..a2729115ad 100644 --- a/apps/main/src/lend/store/createMarketsSlice.ts +++ b/apps/main/src/lend/store/createMarketsSlice.ts @@ -11,14 +11,12 @@ import { MarketsRewardsMapper, MarketsStatsBandsMapper, MarketsStatsCapAndAvailableMapper, - MarketsStatsParametersMapper, OneWayMarketTemplate, } from '@/lend/types/lend.types' type StateKey = keyof typeof DEFAULT_STATE type SliceState = { - statsParametersMapper: { [chainId: string]: MarketsStatsParametersMapper } statsBandsMapper: { [chainId: string]: MarketsStatsBandsMapper } statsCapAndAvailableMapper: { [chainId: string]: MarketsStatsCapAndAvailableMapper } maxLeverageMapper: { [chainId: string]: MarketsMaxLeverageMapper } @@ -47,7 +45,6 @@ export type MarketsSlice = { } const DEFAULT_STATE: SliceState = { - statsParametersMapper: {}, statsBandsMapper: {}, statsCapAndAvailableMapper: {}, maxLeverageMapper: {}, @@ -66,7 +63,6 @@ const createMarketsSlice = (set: StoreApi['setState'], get: StoreApi['setState'], get: StoreApi [...rootKeys.market(params), 'market-parameters'] as const, + queryFn: async ({ marketId }: MarketQuery) => { + const market = getLlamaMarket(marketId) + + if (market instanceof MintMarketTemplate) { + // Mint markets don't have their A value in the parameters + // object, but we want it regardless for type similarity + // with lend markets. + const parameters = await market.stats.parameters() + return { ...parameters, A: market.A.toString() } + } else { + const parameters = await market.stats.parameters() + return parameters + } + }, + refetchInterval: '1m', + validationSuite: marketIdValidationSuite, +}) From 79e7cb9cb3f13513020ed36504f4e522204cf5d9 Mon Sep 17 00:00:00 2001 From: Alunara Date: Wed, 26 Nov 2025 17:43:50 +0100 Subject: [PATCH 11/23] refactor: make MarketParameters more generic and move to llamalend --- .../lend/components/MarketInformationComp.tsx | 23 ++++-- .../PageLoanCreate/LoanFormCreate/index.tsx | 4 +- .../market-parameters}/MarketParameters.tsx | 71 ++++--------------- .../LoanInfoLlamma/LoanInfoParameters.tsx | 34 --------- .../loan/components/MarketInformationComp.tsx | 4 +- .../PageLoanCreate/LoanFormCreate/index.tsx | 4 +- 6 files changed, 38 insertions(+), 102 deletions(-) rename apps/main/src/{lend/components/DetailsMarket/components => llamalend/features/market-parameters}/MarketParameters.tsx (52%) delete mode 100644 apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx diff --git a/apps/main/src/lend/components/MarketInformationComp.tsx b/apps/main/src/lend/components/MarketInformationComp.tsx index 0120b2b707..73a1fb7012 100644 --- a/apps/main/src/lend/components/MarketInformationComp.tsx +++ b/apps/main/src/lend/components/MarketInformationComp.tsx @@ -6,13 +6,15 @@ import { PageContentProps } from '@/lend/types/lend.types' import { BandsChart } from '@/llamalend/features/bands-chart/BandsChart' import { useBandsData } from '@/llamalend/features/bands-chart/hooks/useBandsData' import { getBandsChartToken } from '@/llamalend/features/bands-chart/utils' -import { useTheme } from '@mui/material' +import { MarketParameters } from '@/llamalend/features/market-parameters/MarketParameters' +import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' +import { Typography, useTheme } from '@mui/material' import Stack from '@mui/material/Stack' import { getLib } from '@ui-kit/features/connect-wallet' import { useUserProfileStore } from '@ui-kit/features/user-profile' import { useNewBandsChart } from '@ui-kit/hooks/useFeatureFlags' +import { t } from '@ui-kit/lib/i18n' import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' -import { MarketParameters } from './DetailsMarket/components/MarketParameters' const { Spacing } = SizesAndSpaces @@ -108,8 +110,21 @@ export const MarketInformationComp = ({ - t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }}> - + t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }} + > + {type === 'borrow' && ( + + {t`Loan Parameters`} + + + )} + + + {t`Prices`} + + )} diff --git a/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx b/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx index e6a0231aae..04222e0c5a 100644 --- a/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx +++ b/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx @@ -19,6 +19,7 @@ import useStore from '@/lend/store/useStore' import { Api, type MarketUrlParams, OneWayMarketTemplate, PageContentProps } from '@/lend/types/lend.types' import { getLoanManagePathname } from '@/lend/utils/utilsRouter' import { DEFAULT_HEALTH_MODE } from '@/llamalend/constants' +import { MarketParameters } from '@/llamalend/features/market-parameters/MarketParameters' import type { HealthMode } from '@/llamalend/llamalend.types' import { useLoanExists } from '@/llamalend/queries/loan-exists' import Accordion from '@ui/Accordion' @@ -37,7 +38,6 @@ import { useNavigate } from '@ui-kit/hooks/router' import usePageVisibleInterval from '@ui-kit/hooks/usePageVisibleInterval' import { t } from '@ui-kit/lib/i18n' import { REFRESH_INTERVAL } from '@ui-kit/lib/model' -import { MarketParameters } from '../../DetailsMarket/components/MarketParameters' const LoanCreate = ({ isLeverage = false, @@ -440,7 +440,7 @@ const LoanCreate = ({ {!isAdvancedMode && ( {t`Market details`}}> - + )} diff --git a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx b/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx similarity index 52% rename from apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx rename to apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx index 6955df2b27..daa8c4d1d8 100644 --- a/apps/main/src/lend/components/DetailsMarket/components/MarketParameters.tsx +++ b/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx @@ -1,15 +1,9 @@ -import { useMarketPricePerShare } from '@/lend/entities/market-details' -import { ChainId } from '@/lend/types/lend.types' -import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' import { useMarketParameters } from '@/llamalend/queries/market-parameters' +import type { IChainId } from '@curvefi/llamalend-api/lib/interfaces' import Stack from '@mui/material/Stack' -import Typography from '@mui/material/Typography' import { FORMAT_OPTIONS, formatNumber, NumberFormatOptions } from '@ui/utils' import { t } from '@ui-kit/lib/i18n' import ActionInfo from '@ui-kit/shared/ui/ActionInfo' -import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' - -const { Spacing } = SizesAndSpaces // In [1]: ltv = lambda x: ((x[0] - 1) / x[0])**2 * (1 - x[1]) // In [2]: ltv((30, 0.11)) @@ -25,100 +19,61 @@ type MarketDetails = { label: string value: string | number | undefined formatOptions: NumberFormatOptions - isError: boolean tooltip?: string } -export const MarketParameters = ({ - chainId, - marketId, - type, -}: { - chainId: ChainId - marketId: string - type: 'borrow' | 'supply' -}) => { +export const MarketParameters = ({ chainId, marketId }: { chainId: IChainId; marketId: string }) => { const { data: parameters, isLoading: isLoadingParameters, isError: isErrorParameters, } = useMarketParameters({ chainId, marketId }) - const { - data: pricePerShare, - isLoading: isLoadingPricePerShare, - error: errorPricePerShare, - } = useMarketPricePerShare({ chainId, marketId }) - - const borrowDetails: MarketDetails[] = [ + const details: MarketDetails[] = [ { label: t`AMM swap fee`, value: parameters?.fee, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, - isError: isErrorParameters, }, { label: t`Admin fee`, value: parameters?.admin_fee, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, - isError: isErrorParameters, }, { label: t`Band width factor`, value: parameters?.A, formatOptions: { useGrouping: false }, - isError: isErrorParameters, }, { label: t`Loan discount`, value: parameters?.loan_discount, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, - isError: isErrorParameters, }, { label: t`Liquidation discount`, value: parameters?.liquidation_discount, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, - isError: isErrorParameters, }, { label: t`Max LTV`, value: getMaxLTV(parameters?.A, parameters?.loan_discount), formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, - isError: isErrorParameters, tooltip: t`Max possible loan at N=4`, }, ] return ( - - {type === 'borrow' && ( - - {t`Loan Parameters`} - {borrowDetails.map(({ label, value, formatOptions, isError, tooltip }) => ( - - ))} - - )} - - - {t`Prices`} - - {type === 'supply' && ( - - )} - + + {details.map(({ label, value, formatOptions, tooltip }) => ( + + ))} ) } diff --git a/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx b/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx deleted file mode 100644 index fec412c47a..0000000000 --- a/apps/main/src/loan/components/LoanInfoLlamma/LoanInfoParameters.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import useStore from '@/loan/store/useStore' -import type { MintMarketTemplate } from '@curvefi/llamalend-api/lib/mintMarkets' -import Stack from '@mui/material/Stack' -import { formatNumber } from '@ui/utils' -import { t } from '@ui-kit/lib/i18n' -import ActionInfo from '@ui-kit/shared/ui/ActionInfo' - -export const LoanInfoParameters = ({ - market, - marketId: marketId, -}: { - market: MintMarketTemplate | null - marketId: string -}) => { - const loanDetails = useStore((state) => state.loans.detailsMapper[marketId]) - const { parameters } = loanDetails ?? {} - - return ( - - - - - - ) -} diff --git a/apps/main/src/loan/components/MarketInformationComp.tsx b/apps/main/src/loan/components/MarketInformationComp.tsx index 851b2efb73..570806632f 100644 --- a/apps/main/src/loan/components/MarketInformationComp.tsx +++ b/apps/main/src/loan/components/MarketInformationComp.tsx @@ -1,6 +1,7 @@ import { BandsChart } from '@/llamalend/features/bands-chart/BandsChart' import { useBandsData } from '@/llamalend/features/bands-chart/hooks/useBandsData' import { getBandsChartToken } from '@/llamalend/features/bands-chart/utils' +import { MarketParameters } from '@/llamalend/features/market-parameters/MarketParameters' import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' import { BandsComp } from '@/loan/components/BandsComp' import ChartOhlcWrapper from '@/loan/components/ChartOhlcWrapper' @@ -14,7 +15,6 @@ import { useUserProfileStore } from '@ui-kit/features/user-profile' import { useNewBandsChart } from '@ui-kit/hooks/useFeatureFlags' import { t } from '@ui-kit/lib/i18n' import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' -import { LoanInfoParameters } from './LoanInfoLlamma/LoanInfoParameters' const { Spacing } = SizesAndSpaces @@ -126,7 +126,7 @@ export const MarketInformationComp = ({ > {t`Loan Parameters`} - + diff --git a/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx b/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx index 4535d0ff62..3ccd558418 100644 --- a/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx +++ b/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx @@ -1,6 +1,7 @@ import { ReactNode, useCallback, useEffect, useRef, useState } from 'react' import { styled } from 'styled-components' import { DEFAULT_HEALTH_MODE } from '@/llamalend/constants' +import { MarketParameters } from '@/llamalend/features/market-parameters/MarketParameters' import AlertFormError from '@/loan/components/AlertFormError' import DialogHealthWarning from '@/loan/components/DialogHealthWarning' import LoanFormConnect from '@/loan/components/LoanFormConnect' @@ -36,7 +37,6 @@ import { useTokenUsdRate } from '@ui-kit/lib/model/entities/token-usd-rate' import { LargeTokenInput } from '@ui-kit/shared/ui/LargeTokenInput' import { TokenLabel } from '@ui-kit/shared/ui/TokenLabel' import { decimal, type Decimal } from '@ui-kit/utils' -import { LoanInfoParameters } from '../../LoanInfoLlamma/LoanInfoParameters' const LoanCreate = ({ collateralAlert, @@ -469,7 +469,7 @@ const LoanCreate = ({ {!isAdvancedMode && ( - + )} From 190ed51a1ce4493c56e0a6b70f9dc746281536c4 Mon Sep 17 00:00:00 2001 From: Alunara Date: Wed, 26 Nov 2025 17:47:02 +0100 Subject: [PATCH 12/23] refactor: remove all stacks from market parameter collections --- apps/main/src/lend/components/MarketInformationComp.tsx | 8 ++++++-- .../components/PageLoanCreate/LoanFormCreate/index.tsx | 5 ++++- .../features/market-parameters/MarketParameters.tsx | 5 ++--- apps/main/src/loan/components/MarketInformationComp.tsx | 8 ++++++-- .../components/PageLoanCreate/LoanFormCreate/index.tsx | 5 ++++- 5 files changed, 22 insertions(+), 9 deletions(-) diff --git a/apps/main/src/lend/components/MarketInformationComp.tsx b/apps/main/src/lend/components/MarketInformationComp.tsx index 73a1fb7012..67aee56fda 100644 --- a/apps/main/src/lend/components/MarketInformationComp.tsx +++ b/apps/main/src/lend/components/MarketInformationComp.tsx @@ -117,13 +117,17 @@ export const MarketInformationComp = ({ {type === 'borrow' && ( {t`Loan Parameters`} - + + + )} {t`Prices`} - + + + diff --git a/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx b/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx index 04222e0c5a..5169e2d340 100644 --- a/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx +++ b/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx @@ -22,6 +22,7 @@ import { DEFAULT_HEALTH_MODE } from '@/llamalend/constants' import { MarketParameters } from '@/llamalend/features/market-parameters/MarketParameters' import type { HealthMode } from '@/llamalend/llamalend.types' import { useLoanExists } from '@/llamalend/queries/loan-exists' +import Stack from '@mui/material/Stack' import Accordion from '@ui/Accordion' import AlertBox from '@ui/AlertBox' import Box from '@ui/Box' @@ -440,7 +441,9 @@ const LoanCreate = ({ {!isAdvancedMode && ( {t`Market details`}}> - + + + )} diff --git a/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx b/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx index daa8c4d1d8..051f8b0e77 100644 --- a/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx +++ b/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx @@ -1,6 +1,5 @@ import { useMarketParameters } from '@/llamalend/queries/market-parameters' import type { IChainId } from '@curvefi/llamalend-api/lib/interfaces' -import Stack from '@mui/material/Stack' import { FORMAT_OPTIONS, formatNumber, NumberFormatOptions } from '@ui/utils' import { t } from '@ui-kit/lib/i18n' import ActionInfo from '@ui-kit/shared/ui/ActionInfo' @@ -64,7 +63,7 @@ export const MarketParameters = ({ chainId, marketId }: { chainId: IChainId; mar ] return ( - + <> {details.map(({ label, value, formatOptions, tooltip }) => ( ))} - + ) } diff --git a/apps/main/src/loan/components/MarketInformationComp.tsx b/apps/main/src/loan/components/MarketInformationComp.tsx index 570806632f..f1a3e7c777 100644 --- a/apps/main/src/loan/components/MarketInformationComp.tsx +++ b/apps/main/src/loan/components/MarketInformationComp.tsx @@ -126,12 +126,16 @@ export const MarketInformationComp = ({ > {t`Loan Parameters`} - + + + {t`Prices`} - + + + diff --git a/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx b/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx index 3ccd558418..80068686ae 100644 --- a/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx +++ b/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx @@ -20,6 +20,7 @@ import { curveProps } from '@/loan/utils/helpers' import { hasV1Deleverage } from '@/loan/utils/leverage' import { getStepStatus, getTokenName } from '@/loan/utils/utilsLoan' import { getLoanManagePathname } from '@/loan/utils/utilsRouter' +import Stack from '@mui/material/Stack' import Accordion from '@ui/Accordion' import AlertBox from '@ui/AlertBox' import Box from '@ui/Box' @@ -469,7 +470,9 @@ const LoanCreate = ({ {!isAdvancedMode && ( - + + + )} From 6b2d166185cd9aaec93c9ed419a6e814f437d9dd Mon Sep 17 00:00:00 2001 From: Alunara Date: Wed, 26 Nov 2025 17:49:21 +0100 Subject: [PATCH 13/23] feat: add back in price per share for lend market supply params --- .../lend/components/MarketInformationComp.tsx | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/apps/main/src/lend/components/MarketInformationComp.tsx b/apps/main/src/lend/components/MarketInformationComp.tsx index 67aee56fda..dcbe8087e4 100644 --- a/apps/main/src/lend/components/MarketInformationComp.tsx +++ b/apps/main/src/lend/components/MarketInformationComp.tsx @@ -10,11 +10,14 @@ import { MarketParameters } from '@/llamalend/features/market-parameters/MarketP import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' import { Typography, useTheme } from '@mui/material' import Stack from '@mui/material/Stack' +import { formatNumber } from '@ui/utils' import { getLib } from '@ui-kit/features/connect-wallet' import { useUserProfileStore } from '@ui-kit/features/user-profile' import { useNewBandsChart } from '@ui-kit/hooks/useFeatureFlags' import { t } from '@ui-kit/lib/i18n' +import ActionInfo from '@ui-kit/shared/ui/ActionInfo' import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' +import { useMarketPricePerShare } from '../entities/market-details' const { Spacing } = SizesAndSpaces @@ -63,6 +66,12 @@ export const MarketInformationComp = ({ const collateralToken = getBandsChartToken(collateralTokenAddress, market?.collateral_token.symbol) const borrowToken = getBandsChartToken(borrowedTokenAddress, market?.borrowed_token.symbol) + const { + data: pricePerShare, + isLoading: isLoadingPricePerShare, + error: errorPricePerShare, + } = useMarketPricePerShare({ chainId: rChainId, marketId: rOwmId }) + return ( <> {networks[rChainId]?.pricesData && !chartExpanded && ( @@ -127,6 +136,14 @@ export const MarketInformationComp = ({ {t`Prices`} + {type === 'supply' && ( + + )} From 17c2bdfdf486a7350d978f93702fbe803238ef97 Mon Sep 17 00:00:00 2001 From: Alunara Date: Wed, 26 Nov 2025 17:54:56 +0100 Subject: [PATCH 14/23] feat: add market misc with id for devs --- apps/main/src/lend/components/MarketInformationComp.tsx | 8 ++++++++ .../llamalend/features/market-parameters/MarketMisc.tsx | 7 +++++++ apps/main/src/loan/components/MarketInformationComp.tsx | 8 ++++++++ 3 files changed, 23 insertions(+) create mode 100644 apps/main/src/llamalend/features/market-parameters/MarketMisc.tsx diff --git a/apps/main/src/lend/components/MarketInformationComp.tsx b/apps/main/src/lend/components/MarketInformationComp.tsx index dcbe8087e4..3fa051204e 100644 --- a/apps/main/src/lend/components/MarketInformationComp.tsx +++ b/apps/main/src/lend/components/MarketInformationComp.tsx @@ -6,6 +6,7 @@ import { PageContentProps } from '@/lend/types/lend.types' import { BandsChart } from '@/llamalend/features/bands-chart/BandsChart' import { useBandsData } from '@/llamalend/features/bands-chart/hooks/useBandsData' import { getBandsChartToken } from '@/llamalend/features/bands-chart/utils' +import { MarketMisc } from '@/llamalend/features/market-parameters/MarketMisc' import { MarketParameters } from '@/llamalend/features/market-parameters/MarketParameters' import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' import { Typography, useTheme } from '@mui/material' @@ -146,6 +147,13 @@ export const MarketInformationComp = ({ )} + + + {t`Market`} + + + + )} diff --git a/apps/main/src/llamalend/features/market-parameters/MarketMisc.tsx b/apps/main/src/llamalend/features/market-parameters/MarketMisc.tsx new file mode 100644 index 0000000000..e807701364 --- /dev/null +++ b/apps/main/src/llamalend/features/market-parameters/MarketMisc.tsx @@ -0,0 +1,7 @@ +import type { LlamaMarketTemplate } from '@/llamalend/llamalend.types' +import { t } from '@ui-kit/lib/i18n' +import ActionInfo from '@ui-kit/shared/ui/ActionInfo' + +export const MarketMisc = ({ market }: { market: LlamaMarketTemplate }) => ( + +) diff --git a/apps/main/src/loan/components/MarketInformationComp.tsx b/apps/main/src/loan/components/MarketInformationComp.tsx index f1a3e7c777..664231e1c2 100644 --- a/apps/main/src/loan/components/MarketInformationComp.tsx +++ b/apps/main/src/loan/components/MarketInformationComp.tsx @@ -1,6 +1,7 @@ import { BandsChart } from '@/llamalend/features/bands-chart/BandsChart' import { useBandsData } from '@/llamalend/features/bands-chart/hooks/useBandsData' import { getBandsChartToken } from '@/llamalend/features/bands-chart/utils' +import { MarketMisc } from '@/llamalend/features/market-parameters/MarketMisc' import { MarketParameters } from '@/llamalend/features/market-parameters/MarketParameters' import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' import { BandsComp } from '@/loan/components/BandsComp' @@ -137,6 +138,13 @@ export const MarketInformationComp = ({ + + + {t`Market`} + + + + )} From faa54bfd517fced7580cdc4f8993af13876dee94 Mon Sep 17 00:00:00 2001 From: Alunara Date: Thu, 27 Nov 2025 16:40:23 +0100 Subject: [PATCH 15/23] refactor: shorten code with ternary --- .../src/llamalend/queries/market-parameters.ts | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/apps/main/src/llamalend/queries/market-parameters.ts b/apps/main/src/llamalend/queries/market-parameters.ts index 1bfa6b13bd..3974d4b3e2 100644 --- a/apps/main/src/llamalend/queries/market-parameters.ts +++ b/apps/main/src/llamalend/queries/market-parameters.ts @@ -9,17 +9,12 @@ export const { useQuery: useMarketParameters } = queryFactory({ queryKey: (params: MarketParams) => [...rootKeys.market(params), 'market-parameters'] as const, queryFn: async ({ marketId }: MarketQuery) => { const market = getLlamaMarket(marketId) - - if (market instanceof MintMarketTemplate) { - // Mint markets don't have their A value in the parameters - // object, but we want it regardless for type similarity - // with lend markets. - const parameters = await market.stats.parameters() - return { ...parameters, A: market.A.toString() } - } else { - const parameters = await market.stats.parameters() - return parameters - } + // Mint markets don't have their A value in the parameters + // object, but we want it regardless for type similarity + // with lend markets. + return market instanceof MintMarketTemplate + ? { ...(await market.stats.parameters()), A: market.A.toString() } + : await market.stats.parameters() }, refetchInterval: '1m', validationSuite: marketIdValidationSuite, From b6d165cf3c0c37c5bfdc8dafc0fd44566cee6b75 Mon Sep 17 00:00:00 2001 From: Alunara Date: Thu, 27 Nov 2025 16:43:57 +0100 Subject: [PATCH 16/23] feat: remove '?' as error value --- apps/main/src/lend/components/MarketInformationComp.tsx | 2 +- .../llamalend/features/market-parameters/MarketParameters.tsx | 2 +- .../src/llamalend/features/market-parameters/MarketPrices.tsx | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/main/src/lend/components/MarketInformationComp.tsx b/apps/main/src/lend/components/MarketInformationComp.tsx index 3fa051204e..c8b7032b98 100644 --- a/apps/main/src/lend/components/MarketInformationComp.tsx +++ b/apps/main/src/lend/components/MarketInformationComp.tsx @@ -140,7 +140,7 @@ export const MarketInformationComp = ({ {type === 'supply' && ( diff --git a/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx b/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx index 051f8b0e77..362c18f4d9 100644 --- a/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx +++ b/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx @@ -68,7 +68,7 @@ export const MarketParameters = ({ chainId, marketId }: { chainId: IChainId; mar diff --git a/apps/main/src/llamalend/features/market-parameters/MarketPrices.tsx b/apps/main/src/llamalend/features/market-parameters/MarketPrices.tsx index 336609119b..82b69a34dc 100644 --- a/apps/main/src/llamalend/features/market-parameters/MarketPrices.tsx +++ b/apps/main/src/llamalend/features/market-parameters/MarketPrices.tsx @@ -22,7 +22,7 @@ export const MarketPrices = ({ chainId, marketId }: { chainId: IChainId; marketI <> Date: Thu, 27 Nov 2025 16:44:10 +0100 Subject: [PATCH 17/23] feat: action infos with error dont show value at all --- packages/curve-ui-kit/src/shared/ui/ActionInfo.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/curve-ui-kit/src/shared/ui/ActionInfo.tsx b/packages/curve-ui-kit/src/shared/ui/ActionInfo.tsx index a8ea60ba84..bff14af230 100644 --- a/packages/curve-ui-kit/src/shared/ui/ActionInfo.tsx +++ b/packages/curve-ui-kit/src/shared/ui/ActionInfo.tsx @@ -168,7 +168,7 @@ const ActionInfo = ({ color={error ? 'error' : (valueColor ?? 'textPrimary')} component="div" > - {loading ? (typeof loading === 'string' ? loading : MOCK_SKELETON) : value} + {loading ? (typeof loading === 'string' ? loading : MOCK_SKELETON) : error ? '' : value} From c5ef6729bd74395cf17a7feca257be3591ac95a4 Mon Sep 17 00:00:00 2001 From: Alunara Date: Thu, 27 Nov 2025 16:44:37 +0100 Subject: [PATCH 18/23] feat: action info won't show error icon when it's (re)loading --- packages/curve-ui-kit/src/shared/ui/ActionInfo.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/curve-ui-kit/src/shared/ui/ActionInfo.tsx b/packages/curve-ui-kit/src/shared/ui/ActionInfo.tsx index bff14af230..dc85ca8296 100644 --- a/packages/curve-ui-kit/src/shared/ui/ActionInfo.tsx +++ b/packages/curve-ui-kit/src/shared/ui/ActionInfo.tsx @@ -176,7 +176,7 @@ const ActionInfo = ({ - {error && ( + {error && !loading && ( From c10f9db13b2d1e1e76909881212cff33306a12b5 Mon Sep 17 00:00:00 2001 From: Alunara Date: Thu, 27 Nov 2025 16:48:38 +0100 Subject: [PATCH 19/23] refactor: inline MarketMisc --- apps/main/src/lend/components/MarketInformationComp.tsx | 3 +-- .../llamalend/features/market-parameters/MarketMisc.tsx | 7 ------- apps/main/src/loan/components/MarketInformationComp.tsx | 4 ++-- 3 files changed, 3 insertions(+), 11 deletions(-) delete mode 100644 apps/main/src/llamalend/features/market-parameters/MarketMisc.tsx diff --git a/apps/main/src/lend/components/MarketInformationComp.tsx b/apps/main/src/lend/components/MarketInformationComp.tsx index c8b7032b98..93e6ff84d1 100644 --- a/apps/main/src/lend/components/MarketInformationComp.tsx +++ b/apps/main/src/lend/components/MarketInformationComp.tsx @@ -6,7 +6,6 @@ import { PageContentProps } from '@/lend/types/lend.types' import { BandsChart } from '@/llamalend/features/bands-chart/BandsChart' import { useBandsData } from '@/llamalend/features/bands-chart/hooks/useBandsData' import { getBandsChartToken } from '@/llamalend/features/bands-chart/utils' -import { MarketMisc } from '@/llamalend/features/market-parameters/MarketMisc' import { MarketParameters } from '@/llamalend/features/market-parameters/MarketParameters' import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' import { Typography, useTheme } from '@mui/material' @@ -151,7 +150,7 @@ export const MarketInformationComp = ({ {t`Market`} - + diff --git a/apps/main/src/llamalend/features/market-parameters/MarketMisc.tsx b/apps/main/src/llamalend/features/market-parameters/MarketMisc.tsx deleted file mode 100644 index e807701364..0000000000 --- a/apps/main/src/llamalend/features/market-parameters/MarketMisc.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import type { LlamaMarketTemplate } from '@/llamalend/llamalend.types' -import { t } from '@ui-kit/lib/i18n' -import ActionInfo from '@ui-kit/shared/ui/ActionInfo' - -export const MarketMisc = ({ market }: { market: LlamaMarketTemplate }) => ( - -) diff --git a/apps/main/src/loan/components/MarketInformationComp.tsx b/apps/main/src/loan/components/MarketInformationComp.tsx index 664231e1c2..e999040c0e 100644 --- a/apps/main/src/loan/components/MarketInformationComp.tsx +++ b/apps/main/src/loan/components/MarketInformationComp.tsx @@ -1,7 +1,6 @@ import { BandsChart } from '@/llamalend/features/bands-chart/BandsChart' import { useBandsData } from '@/llamalend/features/bands-chart/hooks/useBandsData' import { getBandsChartToken } from '@/llamalend/features/bands-chart/utils' -import { MarketMisc } from '@/llamalend/features/market-parameters/MarketMisc' import { MarketParameters } from '@/llamalend/features/market-parameters/MarketParameters' import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' import { BandsComp } from '@/loan/components/BandsComp' @@ -15,6 +14,7 @@ import { useConnection } from '@ui-kit/features/connect-wallet' import { useUserProfileStore } from '@ui-kit/features/user-profile' import { useNewBandsChart } from '@ui-kit/hooks/useFeatureFlags' import { t } from '@ui-kit/lib/i18n' +import ActionInfo from '@ui-kit/shared/ui/ActionInfo' import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' const { Spacing } = SizesAndSpaces @@ -142,7 +142,7 @@ export const MarketInformationComp = ({ {t`Market`} - + From dcdc36a6407e27b6ed4b978bd02841d5ff52c042 Mon Sep 17 00:00:00 2001 From: Alunara Date: Thu, 27 Nov 2025 17:05:49 +0100 Subject: [PATCH 20/23] refactor: create shared MarketParameters component for both mint and lend --- .../lend/components/MarketInformationComp.tsx | 49 +------ .../MarketLoanParameters.tsx | 79 +++++++++++ .../market-parameters/MarketParameters.tsx | 129 +++++++++--------- .../loan/components/MarketInformationComp.tsx | 28 +--- 4 files changed, 143 insertions(+), 142 deletions(-) create mode 100644 apps/main/src/llamalend/features/market-parameters/MarketLoanParameters.tsx diff --git a/apps/main/src/lend/components/MarketInformationComp.tsx b/apps/main/src/lend/components/MarketInformationComp.tsx index 93e6ff84d1..931e8e706c 100644 --- a/apps/main/src/lend/components/MarketInformationComp.tsx +++ b/apps/main/src/lend/components/MarketInformationComp.tsx @@ -7,17 +7,12 @@ import { BandsChart } from '@/llamalend/features/bands-chart/BandsChart' import { useBandsData } from '@/llamalend/features/bands-chart/hooks/useBandsData' import { getBandsChartToken } from '@/llamalend/features/bands-chart/utils' import { MarketParameters } from '@/llamalend/features/market-parameters/MarketParameters' -import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' -import { Typography, useTheme } from '@mui/material' +import { useTheme } from '@mui/material' import Stack from '@mui/material/Stack' -import { formatNumber } from '@ui/utils' import { getLib } from '@ui-kit/features/connect-wallet' import { useUserProfileStore } from '@ui-kit/features/user-profile' import { useNewBandsChart } from '@ui-kit/hooks/useFeatureFlags' -import { t } from '@ui-kit/lib/i18n' -import ActionInfo from '@ui-kit/shared/ui/ActionInfo' import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' -import { useMarketPricePerShare } from '../entities/market-details' const { Spacing } = SizesAndSpaces @@ -66,12 +61,6 @@ export const MarketInformationComp = ({ const collateralToken = getBandsChartToken(collateralTokenAddress, market?.collateral_token.symbol) const borrowToken = getBandsChartToken(borrowedTokenAddress, market?.borrowed_token.symbol) - const { - data: pricePerShare, - isLoading: isLoadingPricePerShare, - error: errorPricePerShare, - } = useMarketPricePerShare({ chainId: rChainId, marketId: rOwmId }) - return ( <> {networks[rChainId]?.pricesData && !chartExpanded && ( @@ -119,41 +108,7 @@ export const MarketInformationComp = ({ - t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }} - > - {type === 'borrow' && ( - - {t`Loan Parameters`} - - - - - )} - - - {t`Prices`} - - - {type === 'supply' && ( - - )} - - - - - {t`Market`} - - - - - + )} diff --git a/apps/main/src/llamalend/features/market-parameters/MarketLoanParameters.tsx b/apps/main/src/llamalend/features/market-parameters/MarketLoanParameters.tsx new file mode 100644 index 0000000000..c98bc5de35 --- /dev/null +++ b/apps/main/src/llamalend/features/market-parameters/MarketLoanParameters.tsx @@ -0,0 +1,79 @@ +import { useMarketParameters } from '@/llamalend/queries/market-parameters' +import type { IChainId } from '@curvefi/llamalend-api/lib/interfaces' +import { FORMAT_OPTIONS, formatNumber, NumberFormatOptions } from '@ui/utils' +import { t } from '@ui-kit/lib/i18n' +import ActionInfo from '@ui-kit/shared/ui/ActionInfo' + +// In [1]: ltv = lambda x: ((x[0] - 1) / x[0])**2 * (1 - x[1]) +// In [2]: ltv((30, 0.11)) +// Out[2]: 0.8316555555555556 +// where x[0] is A, x[1] is loan discount normalised between 0 and 1 (so 11% is 0.11). multiply ltv by 100 to show percentage. +// always show 'max ltv' which is the max possible loan at N=4 (not advisable but hey it exists!). +function getMaxLTV(a: string | undefined, loanDiscount: string | undefined) { + if (typeof a === 'undefined' || typeof loanDiscount === 'undefined') return + return ((+a - 1) / +a) ** 2 * (1 - +loanDiscount / 100) * 100 +} + +type MarketDetails = { + label: string + value: string | number | undefined + formatOptions: NumberFormatOptions + tooltip?: string +} + +export const MarketLoanParameters = ({ chainId, marketId }: { chainId: IChainId; marketId: string }) => { + const { + data: parameters, + isLoading: isLoadingParameters, + error: errorParameters, + } = useMarketParameters({ chainId, marketId }) + + const details: MarketDetails[] = [ + { + label: t`AMM swap fee`, + value: parameters?.fee, + formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, + }, + { + label: t`Admin fee`, + value: parameters?.admin_fee, + formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, + }, + { + label: t`Band width factor`, + value: parameters?.A, + formatOptions: { useGrouping: false }, + }, + { + label: t`Loan discount`, + value: parameters?.loan_discount, + formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, + }, + { + label: t`Liquidation discount`, + value: parameters?.liquidation_discount, + formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, + }, + { + label: t`Max LTV`, + value: getMaxLTV(parameters?.A, parameters?.loan_discount), + formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, + tooltip: t`Max possible loan at N=4`, + }, + ] + + return ( + <> + {details.map(({ label, value, formatOptions, tooltip }) => ( + + ))} + + ) +} diff --git a/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx b/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx index 362c18f4d9..cd8a41be3f 100644 --- a/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx +++ b/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx @@ -1,78 +1,71 @@ -import { useMarketParameters } from '@/llamalend/queries/market-parameters' +// TODO: refactor into llamalend +// eslint-disable-next-line import/no-restricted-paths +import { useMarketPricePerShare } from '@/lend/entities/market-details' +import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' import type { IChainId } from '@curvefi/llamalend-api/lib/interfaces' -import { FORMAT_OPTIONS, formatNumber, NumberFormatOptions } from '@ui/utils' +import { Typography } from '@mui/material' +import Stack from '@mui/material/Stack' +import { formatNumber } from '@ui/utils' import { t } from '@ui-kit/lib/i18n' import ActionInfo from '@ui-kit/shared/ui/ActionInfo' +import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' +import { MarketLoanParameters } from './MarketLoanParameters' -// In [1]: ltv = lambda x: ((x[0] - 1) / x[0])**2 * (1 - x[1]) -// In [2]: ltv((30, 0.11)) -// Out[2]: 0.8316555555555556 -// where x[0] is A, x[1] is loan discount normalised between 0 and 1 (so 11% is 0.11). multiply ltv by 100 to show percentage. -// always show 'max ltv' which is the max possible loan at N=4 (not advisable but hey it exists!). -function getMaxLTV(a: string | undefined, loanDiscount: string | undefined) { - if (typeof a === 'undefined' || typeof loanDiscount === 'undefined') return - return ((+a - 1) / +a) ** 2 * (1 - +loanDiscount / 100) * 100 -} - -type MarketDetails = { - label: string - value: string | number | undefined - formatOptions: NumberFormatOptions - tooltip?: string -} +const { Spacing } = SizesAndSpaces -export const MarketParameters = ({ chainId, marketId }: { chainId: IChainId; marketId: string }) => { +export const MarketParameters = ({ + chainId, + marketId, + marketType, + action, +}: { + chainId: IChainId + marketId: string + marketType: 'lend' | 'mint' + action: 'borrow' | 'supply' +}) => { + const enablePricePerShare = marketType === 'lend' && action === 'supply' const { - data: parameters, - isLoading: isLoadingParameters, - isError: isErrorParameters, - } = useMarketParameters({ chainId, marketId }) - - const details: MarketDetails[] = [ - { - label: t`AMM swap fee`, - value: parameters?.fee, - formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, - }, - { - label: t`Admin fee`, - value: parameters?.admin_fee, - formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, - }, - { - label: t`Band width factor`, - value: parameters?.A, - formatOptions: { useGrouping: false }, - }, - { - label: t`Loan discount`, - value: parameters?.loan_discount, - formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, - }, - { - label: t`Liquidation discount`, - value: parameters?.liquidation_discount, - formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, - }, - { - label: t`Max LTV`, - value: getMaxLTV(parameters?.A, parameters?.loan_discount), - formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, - tooltip: t`Max possible loan at N=4`, - }, - ] + data: pricePerShare, + isLoading: isLoadingPricePerShare, + error: errorPricePerShare, + } = useMarketPricePerShare({ chainId, marketId }, enablePricePerShare) return ( - <> - {details.map(({ label, value, formatOptions, tooltip }) => ( - - ))} - + t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }} + > + {action === 'borrow' && ( + + {t`Loan Parameters`} + + + + + )} + + + {t`Prices`} + + + {enablePricePerShare && ( + + )} + + + + + {t`Market`} + + + + + ) } diff --git a/apps/main/src/loan/components/MarketInformationComp.tsx b/apps/main/src/loan/components/MarketInformationComp.tsx index e999040c0e..c1621a22d1 100644 --- a/apps/main/src/loan/components/MarketInformationComp.tsx +++ b/apps/main/src/loan/components/MarketInformationComp.tsx @@ -2,7 +2,6 @@ import { BandsChart } from '@/llamalend/features/bands-chart/BandsChart' import { useBandsData } from '@/llamalend/features/bands-chart/hooks/useBandsData' import { getBandsChartToken } from '@/llamalend/features/bands-chart/utils' import { MarketParameters } from '@/llamalend/features/market-parameters/MarketParameters' -import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' import { BandsComp } from '@/loan/components/BandsComp' import ChartOhlcWrapper from '@/loan/components/ChartOhlcWrapper' import DetailInfoAddressLookup from '@/loan/components/LoanInfoLlamma/components/DetailInfoAddressLookup' @@ -14,7 +13,6 @@ import { useConnection } from '@ui-kit/features/connect-wallet' import { useUserProfileStore } from '@ui-kit/features/user-profile' import { useNewBandsChart } from '@ui-kit/hooks/useFeatureFlags' import { t } from '@ui-kit/lib/i18n' -import ActionInfo from '@ui-kit/shared/ui/ActionInfo' import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces' const { Spacing } = SizesAndSpaces @@ -121,31 +119,7 @@ export const MarketInformationComp = ({ /> - t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }} - > - - {t`Loan Parameters`} - - - - - - - {t`Prices`} - - - - - - - {t`Market`} - - - - - + )} From a19fd587141996c7d5c5f7d5b942aad3f41e965b Mon Sep 17 00:00:00 2001 From: Alunara Date: Thu, 27 Nov 2025 17:28:10 +0100 Subject: [PATCH 21/23] refactor: inline action infos for market loan parameters --- .../MarketLoanParameters.tsx | 99 +++++++++---------- .../market-parameters/MarketParameters.tsx | 2 +- .../llamalend/queries/market-parameters.ts | 29 +++++- 3 files changed, 72 insertions(+), 58 deletions(-) diff --git a/apps/main/src/llamalend/features/market-parameters/MarketLoanParameters.tsx b/apps/main/src/llamalend/features/market-parameters/MarketLoanParameters.tsx index c98bc5de35..0a4cbfe642 100644 --- a/apps/main/src/llamalend/features/market-parameters/MarketLoanParameters.tsx +++ b/apps/main/src/llamalend/features/market-parameters/MarketLoanParameters.tsx @@ -1,26 +1,19 @@ import { useMarketParameters } from '@/llamalend/queries/market-parameters' import type { IChainId } from '@curvefi/llamalend-api/lib/interfaces' -import { FORMAT_OPTIONS, formatNumber, NumberFormatOptions } from '@ui/utils' import { t } from '@ui-kit/lib/i18n' import ActionInfo from '@ui-kit/shared/ui/ActionInfo' +import { formatNumber, formatPercent } from '@ui-kit/utils' // In [1]: ltv = lambda x: ((x[0] - 1) / x[0])**2 * (1 - x[1]) // In [2]: ltv((30, 0.11)) // Out[2]: 0.8316555555555556 // where x[0] is A, x[1] is loan discount normalised between 0 and 1 (so 11% is 0.11). multiply ltv by 100 to show percentage. // always show 'max ltv' which is the max possible loan at N=4 (not advisable but hey it exists!). -function getMaxLTV(a: string | undefined, loanDiscount: string | undefined) { - if (typeof a === 'undefined' || typeof loanDiscount === 'undefined') return +function getMaxLTV(a: number | undefined, loanDiscount: string | undefined) { + if (a == null || loanDiscount == null) return return ((+a - 1) / +a) ** 2 * (1 - +loanDiscount / 100) * 100 } -type MarketDetails = { - label: string - value: string | number | undefined - formatOptions: NumberFormatOptions - tooltip?: string -} - export const MarketLoanParameters = ({ chainId, marketId }: { chainId: IChainId; marketId: string }) => { const { data: parameters, @@ -28,52 +21,50 @@ export const MarketLoanParameters = ({ chainId, marketId }: { chainId: IChainId; error: errorParameters, } = useMarketParameters({ chainId, marketId }) - const details: MarketDetails[] = [ - { - label: t`AMM swap fee`, - value: parameters?.fee, - formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, - }, - { - label: t`Admin fee`, - value: parameters?.admin_fee, - formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, - }, - { - label: t`Band width factor`, - value: parameters?.A, - formatOptions: { useGrouping: false }, - }, - { - label: t`Loan discount`, - value: parameters?.loan_discount, - formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, - }, - { - label: t`Liquidation discount`, - value: parameters?.liquidation_discount, - formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, - }, - { - label: t`Max LTV`, - value: getMaxLTV(parameters?.A, parameters?.loan_discount), - formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, - tooltip: t`Max possible loan at N=4`, - }, - ] - return ( <> - {details.map(({ label, value, formatOptions, tooltip }) => ( - - ))} + + + + + + + + + + + ) } diff --git a/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx b/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx index cd8a41be3f..a34a4ec61a 100644 --- a/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx +++ b/apps/main/src/llamalend/features/market-parameters/MarketParameters.tsx @@ -1,4 +1,4 @@ -// TODO: refactor into llamalend +// TODO: refactor query into llamalend for both mint and lend markets // eslint-disable-next-line import/no-restricted-paths import { useMarketPricePerShare } from '@/lend/entities/market-details' import { MarketPrices } from '@/llamalend/features/market-parameters/MarketPrices' diff --git a/apps/main/src/llamalend/queries/market-parameters.ts b/apps/main/src/llamalend/queries/market-parameters.ts index 3974d4b3e2..8436b6020d 100644 --- a/apps/main/src/llamalend/queries/market-parameters.ts +++ b/apps/main/src/llamalend/queries/market-parameters.ts @@ -3,18 +3,41 @@ import { queryFactory } from '@ui-kit/lib/model/query' import { marketIdValidationSuite } from '@ui-kit/lib/model/query/market-id-validation' import { rootKeys } from '@ui-kit/lib/model/query/root-keys' import type { MarketQuery, MarketParams } from '@ui-kit/lib/model/query/root-keys' +import { decimal } from '@ui-kit/utils' import { getLlamaMarket } from '../llama.utils' export const { useQuery: useMarketParameters } = queryFactory({ queryKey: (params: MarketParams) => [...rootKeys.market(params), 'market-parameters'] as const, queryFn: async ({ marketId }: MarketQuery) => { const market = getLlamaMarket(marketId) + // Mint markets don't have their A value in the parameters // object, but we want it regardless for type similarity // with lend markets. - return market instanceof MintMarketTemplate - ? { ...(await market.stats.parameters()), A: market.A.toString() } - : await market.stats.parameters() + if (market instanceof MintMarketTemplate) { + const parameters = await market.stats.parameters() + + return { + fee: decimal(parameters.fee), + admin_fee: decimal(parameters.admin_fee), + rate: decimal(parameters.rate), + future_rate: decimal(parameters.future_rate), + liquidation_discount: decimal(parameters.liquidation_discount), + loan_discount: decimal(parameters.loan_discount), + A: market.A, + } + } else { + const parameters = await market.stats.parameters() + + return { + fee: decimal(parameters.fee), + admin_fee: decimal(parameters.admin_fee), + liquidation_discount: decimal(parameters.liquidation_discount), + loan_discount: decimal(parameters.loan_discount), + base_price: decimal(parameters.base_price), + A: Number(await market.A()), + } + } }, refetchInterval: '1m', validationSuite: marketIdValidationSuite, From 542afdfdd89c85f62737d1884469b576e28a2de8 Mon Sep 17 00:00:00 2001 From: Alunara Date: Thu, 27 Nov 2025 17:31:13 +0100 Subject: [PATCH 22/23] refactor: rename market-parameters to market-parameters.query --- .../features/market-parameters/MarketLoanParameters.tsx | 2 +- .../{market-parameters.ts => market-parameters.query.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename apps/main/src/llamalend/queries/{market-parameters.ts => market-parameters.query.ts} (100%) diff --git a/apps/main/src/llamalend/features/market-parameters/MarketLoanParameters.tsx b/apps/main/src/llamalend/features/market-parameters/MarketLoanParameters.tsx index 0a4cbfe642..5a98009fde 100644 --- a/apps/main/src/llamalend/features/market-parameters/MarketLoanParameters.tsx +++ b/apps/main/src/llamalend/features/market-parameters/MarketLoanParameters.tsx @@ -1,4 +1,4 @@ -import { useMarketParameters } from '@/llamalend/queries/market-parameters' +import { useMarketParameters } from '@/llamalend/queries/market-parameters.query' import type { IChainId } from '@curvefi/llamalend-api/lib/interfaces' import { t } from '@ui-kit/lib/i18n' import ActionInfo from '@ui-kit/shared/ui/ActionInfo' diff --git a/apps/main/src/llamalend/queries/market-parameters.ts b/apps/main/src/llamalend/queries/market-parameters.query.ts similarity index 100% rename from apps/main/src/llamalend/queries/market-parameters.ts rename to apps/main/src/llamalend/queries/market-parameters.query.ts From 276d8833ab4767226f6773d44c2119cef81c9300 Mon Sep 17 00:00:00 2001 From: Alunara Date: Thu, 27 Nov 2025 17:35:19 +0100 Subject: [PATCH 23/23] fix: forgot to update MarketParameters component in legacy borrow create forms --- .../lend/components/PageLoanCreate/LoanFormCreate/index.tsx | 5 +---- .../loan/components/PageLoanCreate/LoanFormCreate/index.tsx | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx b/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx index 5169e2d340..05549d74ad 100644 --- a/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx +++ b/apps/main/src/lend/components/PageLoanCreate/LoanFormCreate/index.tsx @@ -22,7 +22,6 @@ import { DEFAULT_HEALTH_MODE } from '@/llamalend/constants' import { MarketParameters } from '@/llamalend/features/market-parameters/MarketParameters' import type { HealthMode } from '@/llamalend/llamalend.types' import { useLoanExists } from '@/llamalend/queries/loan-exists' -import Stack from '@mui/material/Stack' import Accordion from '@ui/Accordion' import AlertBox from '@ui/AlertBox' import Box from '@ui/Box' @@ -441,9 +440,7 @@ const LoanCreate = ({ {!isAdvancedMode && ( {t`Market details`}}> - - - + )} diff --git a/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx b/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx index 80068686ae..0ecb0146cc 100644 --- a/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx +++ b/apps/main/src/loan/components/PageLoanCreate/LoanFormCreate/index.tsx @@ -20,7 +20,6 @@ import { curveProps } from '@/loan/utils/helpers' import { hasV1Deleverage } from '@/loan/utils/leverage' import { getStepStatus, getTokenName } from '@/loan/utils/utilsLoan' import { getLoanManagePathname } from '@/loan/utils/utilsRouter' -import Stack from '@mui/material/Stack' import Accordion from '@ui/Accordion' import AlertBox from '@ui/AlertBox' import Box from '@ui/Box' @@ -470,9 +469,7 @@ const LoanCreate = ({ {!isAdvancedMode && ( - - - + )}