Skip to content

Commit

Permalink
Merge pull request #154 from curvefi/task/combine-apr-into-one
Browse files Browse the repository at this point in the history
task: combine APR into one item
  • Loading branch information
amytsang committed Apr 23, 2024
2 parents f997a9d + f3bab18 commit 6dfe6d9
Show file tree
Hide file tree
Showing 22 changed files with 529 additions and 245 deletions.
6 changes: 3 additions & 3 deletions apps/lend/src/components/DetailInfoRate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ const DetailInfoRate = ({
const ratesResp = useStore((state) => state.markets.ratesMapper[rChainId]?.[rOwmId])

const { rates, error } = ratesResp ?? {}
const futureRate = isBorrow ? futureRates?.borrowApy : futureRates?.lendApy
const futureRate = isBorrow ? futureRates?.borrowApy : futureRates?.lendApr

return (
<DetailInfo
loading={typeof ratesResp === 'undefined'}
loadingSkeleton={[100, 20]}
label={isBorrow ? t`Borrow APY:` : t`Lend APY:`}
label={isBorrow ? t`Borrow APY:` : t`Lend APR:`}
>
<span>
{error ? (
'?'
) : (
<strong>
{formatNumber(isBorrow ? rates?.borrowApy : rates?.lendApy, {
{formatNumber(isBorrow ? rates?.borrowApy : rates?.lendApr, {
...FORMAT_OPTIONS.PERCENT,
defaultValue: '-',
})}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const DetailsLoan = ({ type, ...pageProps }: PageContentProps & { type: MarketLi
[
{ title: t`Collateral`, value: <CellToken {...cellProps} type="collateral" /> },
{ title: t`Borrow`, value: <CellToken {...cellProps} type="borrowed" /> },
{ title: t`Lend APY`, value: <CellRate {...cellProps} type="supply" /> },
{ title: t`Lend APR`, value: <CellRate {...cellProps} type="supply" /> },
{ title: t`Borrow APY`, value: <CellRate {...cellProps} type="borrow" className="paddingLeft" /> },
{ title: t`Available`, value: <CellCap {...cellProps} type="available" /> },
],
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react'
import { t } from '@lingui/macro'
import styled from 'styled-components'

import { breakpoints } from '@/ui/utils'

Expand All @@ -14,13 +15,11 @@ import {
import Box from '@/ui/Box'
import CellCap from '@/components/SharedCellData/CellCap'
import CellLoanTotalDebt from '@/components/SharedCellData/CellLoanTotalDebt'
import CellRate from '@/components/SharedCellData/CellRate'
import CellToken from '@/components/SharedCellData/CellToken'
import CellSupplyTotalLiquidity from '@/components/SharedCellData/CellSupplyTotalLiquidity'
import DetailsSupplyRewards from '@/components/DetailsMarket/components/DetailsSupplyRewards'
import DetailsContracts from '@/components/DetailsMarket/components/DetailsContracts'
import MarketParameters from '@/components/DetailsMarket/components/MarketParameters'
import styled from 'styled-components'

const DetailsSupply = ({ type, ...pageProps }: PageContentProps & { type: MarketListType }) => {
const { rChainId, rOwmId, owmDataCachedOrApi, borrowed_token, collateral_token } = pageProps
Expand All @@ -35,11 +34,10 @@ const DetailsSupply = ({ type, ...pageProps }: PageContentProps & { type: Market
const details = [
[
{ title: t`Supply token`, value: <CellToken {...cellProps} type="borrowed" /> },
{ title: t`Lend APY`, value: <CellRate {...cellProps} type="supply" /> },
{ title: 'TVL', value: <CellSupplyTotalLiquidity {...cellProps} /> },
{ title: t`Available`, value: <CellCap {...cellProps} type="available" /> },
],
[
{ title: t`Available`, value: <CellCap {...cellProps} type="available" /> },
{ title: t`Total Debt`, value: <CellLoanTotalDebt {...cellProps} /> },
{ title: t`Total supplied`, value: <CellCap {...cellProps} type="cap" /> },
{ title: t`Utilization %`, value: <CellCap {...cellProps} type="utilization" /> },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,52 +1,76 @@
import { t } from '@lingui/macro'
import React from 'react'
import { t } from '@lingui/macro'
import styled, { css } from 'styled-components'

import { handleClickCopy, shortenTokenName } from '@/utils/helpers'
import { breakpoints, FORMAT_OPTIONS, formatNumber } from '@/ui/utils'
import networks from '@/networks'
import useStore from '@/store/useStore'
import useSupplyTotalApr from '@/hooks/useSupplyTotalApr'

import Box from '@/ui/Box'
import Chip from '@/ui/Typography/Chip'
import DetailsSupplyRewardsCrv from '@/components/DetailsMarket/components/DetailsSupplyRewardsCrv'
import ChipInactive from 'main/src/components/ChipInactive'
import ExternalLink from '@/ui/Link/ExternalLink'
import Icon from '@/ui/Icon'
import IconButton from '@/ui/IconButton'
import Tooltip from '@/ui/Tooltip'
import TextCaption from '@/ui/TextCaption'

// TODO: refactor to UI
const DetailsSupplyRewards = ({ rChainId, rOwmId }: { rChainId: ChainId; rOwmId: string }) => {
const rewardsResp = useStore((state) => state.markets.rewardsMapper[rChainId]?.[rOwmId])

const { rewards } = rewardsResp ?? {}
const { other, crv } = rewards ?? {}

const haveCrv = typeof crv !== 'undefined' && +(crv?.[0] ?? '0') > 0
const haveOther = typeof other !== 'undefined' && other.length > 0
const { invalidGaugeAddress, totalApr, tooltipValues } = useSupplyTotalApr(rChainId, rOwmId)

return (
<RewardsWrapper>
<Box flex fillWidth margin="var(--spacing-narrow) 0 0 0">
<RewardsTitle>{t`Rewards tAPR`}</RewardsTitle>{' '}
<Tooltip placement="bottom" tooltip={t`Token APR based on current prices of tokens and reward rates.`}>
<Icon name="InformationSquare" size={16} />
</Tooltip>
</Box>

{haveCrv && (
<CrvEmissionWrapper>
<Chip size="sm" isBold>{t`CRV Emission:`}</Chip>
<DetailsSupplyRewardsCrv isBold rChainId={rChainId} rOwmId={rOwmId} />
</CrvEmissionWrapper>
<RewardsTitle>
<TextCaption isCaps isBold>
Total APR
</TextCaption>
<br />
{totalApr.minMax}
</RewardsTitle>

{/* BASE */}
<RewardsItem $marginBottom={2}>
<span>{t`LEND APR`}</span>
<span>
{tooltipValues?.lendApr} {tooltipValues?.lendApy && <TextCaption>({tooltipValues.lendApy})</TextCaption>}
</span>
</RewardsItem>

{/* CRV */}
{tooltipValues?.crv && (
<RewardsItem $marginBottom={1}>
<span>{t`CRV APR (unboosted)`}</span>
{tooltipValues.crv}
</RewardsItem>
)}
{tooltipValues?.crvBoosted && (
<RewardsItem $marginBottom={2}>
<span>{t`CRV APR (max boosted x2.50)`}</span>
{tooltipValues.crvBoosted}
</RewardsItem>
)}

{haveOther && (
<Box>
<Chip isBold>{t`Incentives:`}</Chip>
{other?.map(({ apy, symbol, tokenAddress }) => {
{/* INCENTIVES */}
{invalidGaugeAddress ? (
<RewardsItem>
<span>{t`Incentives APR`}</span>
<ChipInactive>No gauge</ChipInactive>
</RewardsItem>
) : tooltipValues?.incentivesObj && (tooltipValues.incentivesObj || []).length > 0 ? (
<>
<RewardsItem>
<span>{t`Incentives APR`}</span>
</RewardsItem>
{tooltipValues.incentivesObj.map(({ apy, symbol, tokenAddress }) => {
return (
<StyledStyledStats key={symbol} flex flexJustifyContent="space-between" padding>
<Box
key={symbol}
flex
flexAlignItems="baseline"
flexJustifyContent="space-between"
padding="0 0 0 var(--spacing-1)"
>
<Box flex flexAlignItems="center">
<StyledExternalLink href={networks[rChainId].scanTokenPath(tokenAddress)}>
<TokenWrapper flex flexAlignItems="center" padding="var(--spacing-1) 0">
Expand All @@ -58,14 +82,12 @@ const DetailsSupplyRewards = ({ rChainId, rOwmId }: { rChainId: ChainId; rOwmId:
<Icon name="Copy" size={16} />
</StyledIconButton>
</Box>
<Chip isBold isNumber size="md">
{formatNumber(apy, FORMAT_OPTIONS.PERCENT)}{' '}
</Chip>
</StyledStyledStats>
<Chip size="md">{formatNumber(apy, FORMAT_OPTIONS.PERCENT)} </Chip>
</Box>
)
})}
</Box>
)}
</>
) : null}

<BoostingLink $noStyles href="https://resources.curve.fi/reward-gauges/boosting-your-crv-rewards">
{t`Learn more about Boosting your CRV rewards`}
Expand All @@ -74,9 +96,18 @@ const DetailsSupplyRewards = ({ rChainId, rOwmId }: { rChainId: ChainId; rOwmId:
)
}

const CrvEmissionWrapper = styled.div`
const RewardsItem = styled.div<{ $marginBottom?: number }>`
align-items: flex-end;
display: flex;
flex-direction: column;
flex-direction: row;
font-size: var(--font-size-3);
justify-content: space-between;
${({ $marginBottom }) => $marginBottom && `margin-bottom: var(--spacing-${$marginBottom})`};
> span:first-of-type {
font-weight: 500;
font-size: var(--font-size-2);
}
@media (min-width: ${breakpoints.sm}rem) {
align-items: flex-end;
Expand All @@ -99,74 +130,46 @@ const actionStyles = css`
background-color: var(--button_icon--hover--background-color);
}
`
export const StyledIconButton = styled(IconButton)`
const StyledIconButton = styled(IconButton)`
${actionStyles}
`

export const StyledStats = styled(Box)<{
isBorderBottom?: boolean
padding?: boolean
}>`
align-items: center;
display: flex;
padding: var(--spacing-1);
font-weight: 500;
${({ padding }) => {
if (padding) {
return 'padding: 0.25rem 0;'
}
}}
${({ isBorderBottom }) => {
if (isBorderBottom) {
return 'border-bottom: 1px solid var(--border-600);'
}
}}
`

const RewardsWrapper = styled.div`
border: 1px solid var(--border-600);
display: flex;
flex-direction: column;
grid-row-gap: var(--spacing-3);
padding: var(--spacing-narrow);
padding-top: var(--spacing-normal);
padding-top: var(--spacing-2);
margin-top: var(--spacing-normal);
@media (min-width: ${breakpoints.sm}rem) {
padding: var(--spacing-normal);
}
`

const RewardsTitle = styled.h4`
margin-bottom: var(--spacing-1);
const RewardsTitle = styled.h3`
margin-bottom: var(--spacing-3);
`

export const TokenWrapper = styled(Box)`
const TokenWrapper = styled(Box)`
text-transform: initial;
svg {
padding-top: 0.3125rem;
}
`

export const StyledStyledStats = styled(StyledStats)`
padding: 0 var(--spacing-1);
`

export const StyledExternalLink = styled(ExternalLink)`
const StyledExternalLink = styled(ExternalLink)`
color: inherit;
font-weight: 500;
text-decoration: underline;
`

const BoostingLink = styled(ExternalLink)`
color: inherit;
display: block;
font-weight: 500;
text-transform: initial;
font-size: var(--font-size-2);
margin-top: var(--spacing-3);
`

export default DetailsSupplyRewards
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const MarketParameters = ({
const marketDetails: { label: string; value: string | number | undefined; formatOptions?: NumberFormatOptions; title?: string; isError: string; isRow?: boolean }[][] = type === 'borrow' ?
[
[
{ label: t`Fee`, value: parameters?.fee, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 3 }, isError: parametersError },
{ 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`A`, value: parameters?.A, formatOptions: { useGrouping: false }, isError: parametersError },
{ label: t`Loan discount`, value: parameters?.loan_discount, formatOptions: { ...FORMAT_OPTIONS.PERCENT, maximumSignificantDigits: 2 }, isError: parametersError },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ const DetailsUserSupply = (pageProps: PageContentProps) => {
const stats: Detail[][] = [
[
{ title: t`Supply Token`, value: <CellToken {...cellProps} type="borrowed" /> },
{ title: t`Lend APY`, value: <CellRate {...cellProps} type="supply" /> },
{ title: t`Lend APR`, value: <CellRate {...cellProps} type="supply" /> },
],
[
{
Expand Down
25 changes: 19 additions & 6 deletions apps/lend/src/components/PageMarketList/Page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import type {
import { t } from '@lingui/macro'
import React, { useEffect, useState } from 'react'
import { useLocation, useNavigate, useParams, useSearchParams } from 'react-router-dom'
import styled from 'styled-components'

import { ROUTE } from '@/constants'
import { getPath } from '@/utils/utilsRouter'
Expand All @@ -28,7 +29,7 @@ const Page: NextPage = () => {
const location = useLocation()
const navigate = useNavigate()
const [searchParams] = useSearchParams()
const { routerParams, api } = usePageOnMount(params, location, navigate)
const { pageLoaded, routerParams, api } = usePageOnMount(params, location, navigate)
const { rChainId } = routerParams

const isLoadingApi = useStore((state) => state.isLoadingApi)
Expand Down Expand Up @@ -58,7 +59,7 @@ const Page: NextPage = () => {
utilization: { name: t`Utilization %` },
capUtilization: { name: t`Supplied / Utilization` },
rateBorrow: { name: t`Borrow APY` },
rateLend: { name: t`Lend APY` },
rateLend: { name: t`Lend APR` },
myDebt: { name: t`My debt` },
myHealth: { name: t`My health` },
myWalletCollateral: { name: t`Wallet balance` },
Expand Down Expand Up @@ -98,7 +99,7 @@ const Page: NextPage = () => {

useEffect(() => {
setLoaded(false)
if (!isLoadingApi) {
if (pageLoaded && !isLoadingApi) {
const paramFilterKey = (searchParams.get('filter') || 'all').toLowerCase()
const paramFilterTypeKey = (searchParams.get('type') || 'borrow').toLowerCase()
const paramHideSmallPools = searchParams.get('hideSmallMarkets') || 'true'
Expand Down Expand Up @@ -126,12 +127,12 @@ const Page: NextPage = () => {
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isLoadingApi, searchParams])
}, [pageLoaded, isLoadingApi, searchParams])

return (
<>
<DocumentHead title={t`Markets`} />
<AppPageContainer>
<StyledAppPageContainer $maxWidth={parsedSearchParams?.filterTypeKey === 'supply' ? '850px' : ''}>
{rChainId && parsedSearchParams && (
<MarketList
rChainId={rChainId}
Expand All @@ -146,12 +147,24 @@ const Page: NextPage = () => {
updatePath={updatePath}
/>
)}
</AppPageContainer>
</StyledAppPageContainer>
<Settings showScrollButton />
</>
)
}

const StyledAppPageContainer = styled(AppPageContainer)<{ $maxWidth: string }>`
${({ $maxWidth }) => {
if ($maxWidth) {
return `
max-width: ${$maxWidth};
margin-left: auto;
margin-right: auto;
`
}
}}
`

function _querySymbol(searchPath: string) {
return searchPath === '?' ? '' : '&'
}
Expand Down
Loading

0 comments on commit 6dfe6d9

Please sign in to comment.