Skip to content

feat: new position details on crvusd/lend #1097

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 74 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
74 commits
Select commit Hold shift + click to select a range
62ea26d
refactor: integrate i18n for PegKeeperStatistics labels
OnlyJousting Jun 9, 2025
49a1627
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jun 9, 2025
e4b7725
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jun 10, 2025
a7efca0
feat: init position details
OnlyJousting Jun 11, 2025
eb972d7
feat: add support for number[] in Metric
OnlyJousting Jun 12, 2025
cf8bed1
feat: set up borrow information for crvUSD
OnlyJousting Jun 12, 2025
b9055d0
refactor: assemble position details in own wrapper
OnlyJousting Jun 12, 2025
d5bdbd7
feat: init position details on lend
OnlyJousting Jun 16, 2025
8962392
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jun 16, 2025
965d509
styling: tweak healthbar
OnlyJousting Jun 17, 2025
6595129
fix: lend average rate calculation
OnlyJousting Jun 17, 2025
9bc2e3f
feat: add soft-liquidation warning
OnlyJousting Jun 17, 2025
bfc190d
feat: add the option to hide the metric components tooltip
OnlyJousting Jun 18, 2025
e33bdb9
feat: init collateral metric tooltip
OnlyJousting Jun 18, 2025
4c7e9ac
feat: collateral metric tooltip
OnlyJousting Jun 19, 2025
7817109
refactor: remove 'liquidation-range' metric
OnlyJousting Jun 23, 2025
f96f0f8
refactor: revert changes to Metric component to support an array of v…
OnlyJousting Jun 23, 2025
a5b14ba
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jun 23, 2025
a23db23
refactor: update metric component usage according to Metric changes
OnlyJousting Jun 23, 2025
d402ab0
fix: enable copy on click when hideTooltip is true
OnlyJousting Jun 23, 2025
1ac700e
refactor: handle custom metric tooltips
OnlyJousting Jun 23, 2025
866a1cf
feat: added liquidation threshold metric tooltip
OnlyJousting Jun 23, 2025
0bc6a82
feat: add pnl tooltip
OnlyJousting Jun 24, 2025
c9a4feb
feat: set up rate
OnlyJousting Jun 24, 2025
c72eb46
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jun 24, 2025
3054c48
feat: set crvusd rate loading state
OnlyJousting Jun 24, 2025
554d954
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jun 25, 2025
70fa6d6
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jun 25, 2025
46fc2ec
feat: add range to liquidation
OnlyJousting Jun 25, 2025
7e8f442
feat: only show new position details on beta
OnlyJousting Jun 25, 2025
d181804
refactor: set PositionDetails props in hooks
OnlyJousting Jun 25, 2025
d449413
refactor: move lending snapshots hook to ui-kit
OnlyJousting Jun 25, 2025
52d3c33
fix: remove unintended changes to Metric
OnlyJousting Jun 25, 2025
f23a6a0
refactor: apply review comments
OnlyJousting Jun 25, 2025
0e9758e
fix: update market and llamma props to allow null values
OnlyJousting Jun 25, 2025
aa6b83b
fix: update import path for getSnapshots in useLendingSnapshots and a…
OnlyJousting Jun 25, 2025
da58a5a
refactor: remove app switches
OnlyJousting Jun 25, 2025
49885ff
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jun 26, 2025
02dcede
refactor: adopt changes to metric component
OnlyJousting Jun 26, 2025
a61d4f2
feat: set health value color based on current health
OnlyJousting Jun 26, 2025
ba61d43
fix: remove redundant abbreviation setting in BorrowInformation compo…
OnlyJousting Jun 26, 2025
48f40ca
refactor: rename borrowRate to borrowAPR for consistency across compo…
OnlyJousting Jun 26, 2025
a4b6049
refactor: update BorrowInformation Metric labels capitalization
OnlyJousting Jun 26, 2025
6b45b1c
feat: new market details for loan
OnlyJousting Jun 27, 2025
136b85e
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jul 14, 2025
3e3a6c5
refactor: use lending-snapshots from llamalend directory
OnlyJousting Jul 14, 2025
91d417d
Revert "refactor: use lending-snapshots from llamalend directory"
OnlyJousting Jul 14, 2025
1867f98
refactor: move lend and crvusd snapshots queries to ui-kit
OnlyJousting Jul 14, 2025
3db86e9
feat: init new lend market details
OnlyJousting Jul 15, 2025
0e59dde
refactor: stop using default import and rename to BorrowPositionDetails
OnlyJousting Jul 15, 2025
c21391c
feat: init lendPositionDetails
OnlyJousting Jul 16, 2025
e8913c0
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jul 16, 2025
e724f5d
feat: finalise lendPositionDetails
OnlyJousting Jul 16, 2025
fd504c7
feat: init new market position and details section layout
OnlyJousting Jul 17, 2025
94eacaf
feat: init beta layout
OnlyJousting Jul 18, 2025
58ea2d2
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jul 18, 2025
b0548c9
feat: prepare new lend market information section
OnlyJousting Jul 19, 2025
58d0d18
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jul 19, 2025
cacf408
feat: add menu to toggle between position and market bands
OnlyJousting Jul 22, 2025
7690cfe
feat: match health value color with bar colors
OnlyJousting Jul 23, 2025
88755cb
feat: wire up /create, /manage, /vault on lend
OnlyJousting Jul 23, 2025
f6fdfb3
fix: use apy rather then apr when displaying supply rates
OnlyJousting Jul 23, 2025
93006b5
fix: lend chart expanded view
OnlyJousting Jul 23, 2025
c9c6c06
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jul 23, 2025
4eac47c
feat: add userLoanDetails and capAndAvailable queries
OnlyJousting Jul 24, 2025
d18cb21
Merge branch 'feat/new-lending-position-details' of https://github.co…
OnlyJousting Jul 24, 2025
e652997
fix: remove removed MarketDetails prop from vault
OnlyJousting Jul 24, 2025
faefa21
fix: pnl tooltip values
OnlyJousting Jul 24, 2025
8780baa
feat: add user-market-balances query and invalidate queries on vault …
OnlyJousting Jul 24, 2025
7517ba3
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jul 24, 2025
5ebd9bf
feat: invalidate queries after create or manage actions
OnlyJousting Jul 25, 2025
bcd8e67
refactor: aggregate invalidate user queries on actions
OnlyJousting Jul 25, 2025
5af4ee3
refactor: consolidate market-related queries into market-details enti…
OnlyJousting Jul 25, 2025
a1c5b4f
Merge branch 'main' into feat/new-lending-position-details
OnlyJousting Jul 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/main/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const nextConfiguration = {
permanent: false
}, {
source: '/llamalend/:network',
destination: '/llamalend/ethereum/markets/',
destination: '/llamalend/:network/markets/',
permanent: false
}, {
source: '/crvusd/:network',
Expand Down
66 changes: 66 additions & 0 deletions apps/main/src/lend/components/BandsComp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { useState } from 'react'
import { styled } from 'styled-components'
import DetailsLoanChartBalances from '@/lend/components/DetailsMarket/components/DetailsLoanChartBalances'
import DetailsUserLoanChartBandBalances from '@/lend/components/DetailsUser/components/DetailsUserLoanChartBandBalances'
import { PageContentProps } from '@/lend/types/lend.types'
import { Stack } from '@mui/material'
import Button from '@ui/Button'
import { t } from '@ui-kit/lib/i18n'

type BandsCompProps = {
pageProps: PageContentProps
page: 'create' | 'manage'
}

export const BandsComp = ({ pageProps, page }: BandsCompProps) => {
const { rChainId, rOwmId, market } = pageProps
const [selectedBand, setSelectedBand] = useState<'user' | 'market'>(page === 'create' ? 'market' : 'user')

const SelectorMenu =
page === 'create' ? null : (
<SelectorRow>
<SelectorButton
variant={'text'}
className={selectedBand === 'user' ? 'active' : ''}
onClick={() => setSelectedBand('user')}
>
{t`Position Bands`}
</SelectorButton>
<SelectorButton
variant={'text'}
className={selectedBand === 'market' ? 'active' : ''}
onClick={() => setSelectedBand('market')}
>
{t`Market Bands`}
</SelectorButton>
</SelectorRow>
)

return (
<Stack>
{selectedBand === 'user' && <DetailsUserLoanChartBandBalances {...pageProps} selectorMenu={SelectorMenu} />}
{selectedBand === 'market' && (
<DetailsLoanChartBalances rChainId={rChainId} rOwmId={rOwmId} market={market} selectorMenu={SelectorMenu} />
)}
</Stack>
)
}

const SelectorRow = styled.div`
display: flex;
flex-direction: row;
margin-bottom: var(--spacing-2);
`

const SelectorButton = styled(Button)`
color: inherit;
font: var(--font);
font-size: var(--font-size-2);
font-weight: bold;
text-transform: none;
opacity: 0.7;
&.active {
opacity: 1;
border-bottom: 2px solid var(--page--text-color);
}
`
4 changes: 2 additions & 2 deletions apps/main/src/lend/components/ChartBandBalances/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Dispatch, useMemo } from 'react'
import { Dispatch, ReactNode, useMemo } from 'react'
import {
Bar,
Brush,
Expand Down Expand Up @@ -43,7 +43,7 @@ const ChartBandBalances = ({
oraclePrice: string | undefined
oraclePriceBand: number | null | undefined
showLiquidationIndicator: boolean
title: string
title: string | ReactNode
setBrushIndex: Dispatch<BrushStartEndIndex>
}) => {
const { borrowed_token, collateral_token } = market ?? {}
Expand Down
9 changes: 5 additions & 4 deletions apps/main/src/lend/components/ChartOhlcWrapper/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { useUserProfileStore } from '@ui-kit/features/user-profile'
import { t } from '@ui-kit/lib/i18n'
import { ChartOhlcWrapperProps, LendingMarketTokens } from './types'

const ChartOhlcWrapper = ({ rChainId, userActiveKey, rOwmId }: ChartOhlcWrapperProps) => {
const ChartOhlcWrapper = ({ rChainId, userActiveKey, rOwmId, betaBackgroundColor }: ChartOhlcWrapperProps) => {
const market = useOneWayMarket(rChainId, rOwmId).data
const borrowMoreActiveKey = useStore((state) => state.loanBorrowMore.activeKey)
const loanRepayActiveKey = useStore((state) => state.loanRepay.activeKey)
Expand Down Expand Up @@ -347,7 +347,8 @@ const ChartOhlcWrapper = ({ rChainId, userActiveKey, rOwmId }: ChartOhlcWrapperP
chartType: 'crvusd',
chartStatus: currentChart.fetchStatus,
chartHeight,
chartExpanded: false,
chartExpanded,
betaBackgroundColor,
themeType: theme,
ohlcData: currentChart.data,
volumeData: chartLlammaOhlc.volumeData,
Expand All @@ -374,7 +375,7 @@ const ChartOhlcWrapper = ({ rChainId, userActiveKey, rOwmId }: ChartOhlcWrapperP
return chartExpanded ? (
<ExpandedWrapper activityHidden={activityHidden}>
<Wrapper variant={'secondary'} chartExpanded={chartExpanded}>
<ChartWrapper {...ChartWrapperProps} />
<ChartWrapper {...ChartWrapperProps} chartExpanded={chartExpanded} />
</Wrapper>
<LpEventsWrapperExpanded>
{market && <PoolActivity poolAddress={market.addresses.amm} chainId={rChainId} coins={coins} />}
Expand Down Expand Up @@ -407,7 +408,7 @@ const ChartOhlcWrapper = ({ rChainId, userActiveKey, rOwmId }: ChartOhlcWrapperP
{poolInfo === 'poolActivity' && market && (
<PoolActivity poolAddress={market.addresses.amm} chainId={rChainId} coins={coins} />
)}
{poolInfo === 'chart' && <ChartWrapper {...ChartWrapperProps} />}
{poolInfo === 'chart' && <ChartWrapper {...ChartWrapperProps} chartExpanded={chartExpanded} />}
</Wrapper>
)
}
Expand Down
5 changes: 3 additions & 2 deletions apps/main/src/lend/components/ChartOhlcWrapper/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ export interface TradesDataProps {
chainId: ChainId
}

export interface ChartOhlcWrapperProps {
export type ChartOhlcWrapperProps = {
rChainId: ChainId
userActiveKey: string
rOwmId: string
userActiveKey: string
betaBackgroundColor?: string
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import lodash from 'lodash'
import { useMemo, useState } from 'react'
import { ReactNode, useMemo, useState } from 'react'
import ChartBandBalances from '@/lend/components/ChartBandBalances'
import type { BrushStartEndIndex } from '@/lend/components/ChartBandBalances/types'
import { DEFAULT_BAND_CHART_DATA } from '@/lend/components/DetailsUser/utils'
Expand All @@ -11,7 +11,10 @@ const DetailsLoanChartBalances = ({
rChainId,
rOwmId,
market,
}: Pick<PageContentProps, 'rChainId' | 'rOwmId' | 'market'>) => {
selectorMenu,
}: Pick<PageContentProps, 'rChainId' | 'rOwmId' | 'market'> & {
selectorMenu?: ReactNode
}) => {
const statsBandsResp = useStore((state) => state.markets.statsBandsMapper[rChainId]?.[rOwmId])
const loanPricesResp = useStore((state) => state.markets.pricesMapper[rChainId]?.[rOwmId])

Expand Down Expand Up @@ -62,7 +65,7 @@ const DetailsLoanChartBalances = ({
oraclePrice={oraclePrice}
oraclePriceBand={oraclePriceBand}
showLiquidationIndicator={false}
title={t`Bands`}
title={selectorMenu ?? t`Bands`}
setBrushIndex={setBrushIndex}
/>
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import lodash from 'lodash'
import { useEffect, useMemo, useState } from 'react'
import { ReactNode, useEffect, useMemo, useState } from 'react'
import ChartBandBalances from '@/lend/components/ChartBandBalances'
import type { BrushStartEndIndex } from '@/lend/components/ChartBandBalances/types'
import { DEFAULT_BAND_CHART_DATA } from '@/lend/components/DetailsUser/utils'
Expand All @@ -14,7 +14,10 @@ const DetailsUserLoanChartBandBalances = ({
rOwmId,
api,
market,
}: Pick<PageContentProps, 'api' | 'rChainId' | 'rOwmId' | 'market'>) => {
selectorMenu,
}: Pick<PageContentProps, 'api' | 'rChainId' | 'rOwmId' | 'market'> & {
selectorMenu?: ReactNode
}) => {
const loansPrices = useStore((state) => state.markets.pricesMapper[rChainId]?.[rOwmId])
const loansStatsBands = useStore((state) => state.markets.statsBandsMapper[rChainId]?.[rOwmId])
const userActiveKey = helpers.getUserActiveKey(api, market!)
Expand Down Expand Up @@ -70,7 +73,7 @@ const DetailsUserLoanChartBandBalances = ({
oraclePrice={oraclePrice}
oraclePriceBand={oraclePriceBand}
showLiquidationIndicator={!!liquidationBand}
title={t`Bands`}
title={selectorMenu ?? t`Bands`}
setBrushIndex={setBrushIndex}
/>
)
Expand Down
67 changes: 67 additions & 0 deletions apps/main/src/lend/components/MarketInformationComp.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
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 { Stack, useTheme } from '@mui/material'
import { useUserProfileStore } from '@ui-kit/features/user-profile'
import { t } from '@ui-kit/lib/i18n'
import { SizesAndSpaces } from '@ui-kit/themes/design/1_sizes_spaces'

const { Spacing } = SizesAndSpaces

type MarketInformationCompProps = {
pageProps: PageContentProps
chartExpanded: boolean
userActiveKey: string
type: 'borrow' | 'supply'
page?: 'create' | 'manage'
}

/**
* Reusable component for OHLC charts, Bands (if applicable), and market parameters. For /create, /manage, /vault pages.
*/
export const MarketInformationComp = ({
pageProps,
chartExpanded,
userActiveKey,
type,
page = 'manage',
}: MarketInformationCompProps) => {
const { rChainId, rOwmId, market } = pageProps
const theme = useTheme()
const isAdvancedMode = useUserProfileStore((state) => state.isAdvancedMode)

return (
<>
<Stack sx={{ backgroundColor: (t) => t.design.Layer[1].Fill, gap: Spacing.md, padding: Spacing.md }}>
{networks[rChainId]?.pricesData && !chartExpanded && (
<ChartOhlcWrapper
rChainId={rChainId}
rOwmId={rOwmId}
userActiveKey={userActiveKey}
betaBackgroundColor={theme.design.Layer[1].Fill}
/>
)}
</Stack>
{type === 'borrow' && isAdvancedMode && (
<Stack sx={{ backgroundColor: (t) => t.design.Layer[1].Fill, gap: Spacing.md, padding: Spacing.md }}>
<BandsComp pageProps={pageProps} page={page} />
</Stack>
)}
{market && isAdvancedMode && (
<Stack flexDirection="row" sx={{ backgroundColor: (t) => t.design.Layer[1].Fill }}>
<Stack sx={{ flexGrow: 1, padding: Spacing.md }}>
<DetailsContracts rChainId={rChainId} market={market} type={type} />
</Stack>
<Stack sx={{ backgroundColor: (t) => t.design.Layer[2].Fill, padding: Spacing.md, minWidth: '18.75rem' }}>
<SubTitle>{t`Parameters`}</SubTitle>
<MarketParameters rChainId={rChainId} rOwmId={rOwmId} type={type} />
</Stack>
</Stack>
)}
</>
)
}
34 changes: 34 additions & 0 deletions apps/main/src/lend/components/MarketInformationTabs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { ReactNode, useState } from 'react'
import { Box } from '@mui/material'
import { t } from '@ui-kit/lib/i18n'
import { TabsSwitcher } from '@ui-kit/shared/ui/TabsSwitcher'

type TabValue = 'borrow' | 'lend'

type MarketInformationTabsProps = {
currentTab: TabValue
hrefs: {
borrow: string
lend: string
}
children: ReactNode
}

/**
* Used in Lend markets to compose with PositionDetails if there is a user position (borrow or supply)
* for this market or with MarketDetails if there is no user position.
*/
export const MarketInformationTabs = ({ currentTab, hrefs, children }: MarketInformationTabsProps) => {
const TABS: { value: TabValue; label: string; href: string }[] = [
{ value: 'borrow', label: t`Borrow`, href: hrefs.borrow },
{ value: 'lend', label: t`Lend`, href: hrefs.lend },
]
const [tab, setTab] = useState<TabValue>(currentTab)

return (
<Box>
<TabsSwitcher value={tab} onChange={setTab} variant="contained" size="small" options={TABS} />
<Box sx={{ backgroundColor: (t) => t.design.Layer[1].Fill }}>{children}</Box>
</Box>
)
}
Loading