Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
11 changes: 11 additions & 0 deletions features/earn/shared/v2/vault-card/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,17 @@ export const StatValueIcon = styled.span`
height: 24px;
`;

export const StatSubValue = styled.span`
color: var(--lido-color-textSecondary);
font-size: ${({ theme }) => theme.fontSizesMap.xs}px;
font-weight: 400;
line-height: 24px;

${({ theme }) => theme.mediaQueries.md} {
display: none;
}
`;

export const CardCta = styled.div`
margin-top: 32px;
`;
Expand Down
49 changes: 40 additions & 9 deletions features/earn/shared/v2/vault-card/vault-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
CardTitleBadge,
ChevronsUpIcon,
StatValueIcon,
StatSubValue,
StyledTooltip,
BadgeStyled,
TitleTextStyled,
Expand All @@ -28,6 +29,7 @@ import { EARN_VAULT_DEPOSIT_SLUG } from 'features/earn/consts';
import { FormatPercent } from 'shared/formatters/format-percent';
import { FormatLargeAmount } from 'shared/formatters/format-large-amount';
import { FormatToken } from 'shared/formatters/format-token';
import { FormatPrice } from 'shared/formatters/format-price';
import { Badge } from 'features/earn/shared/badge';
import { getTokenDecimals } from 'utils/token-decimals';
import { useConfig } from 'config/use-config';
Expand All @@ -44,13 +46,17 @@ type VaultStats = {
};

type VaultPosition = {
balance?: bigint;
sharesBalance?: bigint;
claimable?: bigint;
pending?: Array<{ tokenSymbol: string; amount: bigint }>;
isLoading?: boolean;
symbol: string;
sharesSymbol: string;
usdAmount?: number;
icon?: React.ReactNode;
};
} & ( // either both baseAmount and baseSymbol are provided, or none of them
| { baseAmount: bigint | undefined; baseSymbol: string | undefined }
| { baseAmount?: undefined; baseSymbol?: undefined }
);

type VaultCardProps = {
title: string;
Expand Down Expand Up @@ -146,24 +152,49 @@ export const VaultCard: React.FC<VaultCardProps> = ({
</InlineLoader>
</StatValue>
</StatItem>
{!!position?.balance && (
{!!position?.sharesBalance && (
<StatItem>
<StatLabel>My position</StatLabel>
<StatLabel>
My balance
<VaultTip
placement="bottom"
style={{ position: 'relative', zIndex: 2 }}
>
You hold{' '}
<FormatToken
trimEllipsis
amount={position.sharesBalance}
symbol={position.sharesSymbol}
decimals={getTokenDecimals(position.sharesSymbol)}
/>
.{' '}
{position.usdAmount != null
? `Shown in ${position.baseSymbol ?? position.sharesSymbol} and USD at current conversion rates.`
: `Shown in ${position.baseSymbol ?? position.sharesSymbol} at current conversion rates.`}
</VaultTip>
</StatLabel>
<StatValue>
<InlineLoader width={32} isLoading={position.isLoading}>
<FormatToken
trimEllipsis
symbol={position.symbol}
decimals={getTokenDecimals(position.symbol)}
amount={position.balance}
symbol={position.baseSymbol ?? position.sharesSymbol}
decimals={getTokenDecimals(
position.baseSymbol ?? position.sharesSymbol,
)}
amount={position.baseAmount ?? position.sharesBalance}
fallback="—"
data-testid={`${position.symbol}-position-amount`}
data-testid={`${position.sharesSymbol}-position-amount`}
/>
{position.icon && (
<StatValueIcon>{position.icon}</StatValueIcon>
)}
</InlineLoader>
</StatValue>
{!position.isLoading && position.usdAmount != null && (
<StatSubValue>
<FormatPrice amount={position.usdAmount} />
</StatSubValue>
)}
</StatItem>
)}
</CardStats>
Expand Down
13 changes: 10 additions & 3 deletions features/earn/shared/v2/vault-page/content/styles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,16 @@ export const TopSectionDescription = styled.p`
export const TopSectionStatsRow = styled.div`
display: flex;
gap: ${({ theme }) => theme.spaceMap.md}px;
max-width: 300px;
`;

export const TopSectionStatItem = styled.div`
display: flex;
flex-direction: column;
flex: 0 0 160px;
gap: 4px;

&:first-child {
flex: 1;
${({ theme }) => theme.mediaQueries.md} {
flex: 1 0 auto;
}
`;

Expand All @@ -91,6 +91,13 @@ export const TopSectionStatLabel = styled.span`
line-height: 24px;
`;

export const TopSectionStatSubValue = styled.span`
color: var(--lido-color-textSecondary);
font-size: ${({ theme }) => theme.fontSizesMap.xs}px;
font-weight: 400;
line-height: 24px;
`;

export const TopSectionStatValue = styled.span<{ $accent?: boolean }>`
font-weight: 700;
font-size: ${({ theme }) => theme.fontSizesMap.lg}px;
Expand Down
56 changes: 55 additions & 1 deletion features/earn/shared/v2/vault-page/content/top-section.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import type { ComponentType, FC, SVGProps } from 'react';

import { FormatLargeAmount, FormatPercent } from 'shared/formatters';
import {
FormatLargeAmount,
FormatPercent,
FormatToken,
} from 'shared/formatters';
import { FormatPrice } from 'shared/formatters/format-price';
import { InlineLoader } from 'features/earn/shared/inline-loader';
import { VaultTip } from 'features/earn/shared/vault-tip';
import { Badge } from 'features/earn/shared/badge';
import { getTokenDecimals } from 'utils/token-decimals';

import {
TopSectionStyled,
Expand All @@ -15,10 +21,21 @@ import {
TopSectionStatsRow,
TopSectionStatItem,
TopSectionStatLabel,
TopSectionStatSubValue,
TopSectionStatValue,
} from './styles';

type VaultIllustration = ComponentType<SVGProps<SVGSVGElement>>;

export type VaultBalanceProp = {
amount?: bigint;
symbol: string;
sharesAmount?: bigint;
sharesSymbol: string;
usdAmount?: number;
isLoading?: boolean;
};

type TopSectionProps = {
logo: VaultIllustration;
title: string;
Expand All @@ -29,6 +46,7 @@ type TopSectionProps = {
isApxLoading?: boolean;
isTvlLoading?: boolean;
protectedBadgeTooltipText?: React.ReactNode;
balance?: VaultBalanceProp;
};

export const TopSection: FC<TopSectionProps> = (props) => {
Expand All @@ -41,6 +59,7 @@ export const TopSection: FC<TopSectionProps> = (props) => {
isApxLoading,
isTvlLoading,
protectedBadgeTooltipText,
balance,
} = props;

return (
Expand Down Expand Up @@ -77,6 +96,41 @@ export const TopSection: FC<TopSectionProps> = (props) => {
</InlineLoader>
</TopSectionStatValue>
</TopSectionStatItem>
{!!balance?.amount && (
<TopSectionStatItem>
<TopSectionStatLabel>
My balance
<VaultTip placement="bottom">
You hold{' '}
<FormatToken
trimEllipsis
amount={balance.sharesAmount}
symbol={balance.sharesSymbol}
decimals={getTokenDecimals(balance.sharesSymbol)}
/>
.{' '}
{balance.usdAmount != null
? `Shown in ${balance.symbol} and USD at current conversion rates.`
: `Shown in ${balance.symbol} at current conversion rates.`}
</VaultTip>
</TopSectionStatLabel>
<TopSectionStatValue>
<InlineLoader isLoading={balance.isLoading} width={70}>
<FormatToken
trimEllipsis
amount={balance.amount}
symbol={balance.symbol}
decimals={getTokenDecimals(balance.symbol)}
/>
</InlineLoader>
</TopSectionStatValue>
{!balance.isLoading && balance.usdAmount != null && (
<TopSectionStatSubValue>
<FormatPrice amount={balance.usdAmount} />
</TopSectionStatSubValue>
)}
</TopSectionStatItem>
)}
</TopSectionStatsRow>
</TopSectionStyled>
);
Expand Down
3 changes: 3 additions & 0 deletions features/earn/shared/v2/vault-page/vault-page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { useInpageNavigation } from 'providers/inpage-navigation';

import { VaultChart } from '../vault-chart';

import type { VaultBalanceProp } from './content/top-section';
import { SidePanel } from './side-panel';
import { VaultPageContent } from './content';
import { TopSection } from './content/top-section';
Expand Down Expand Up @@ -62,6 +63,7 @@ type Props = {
riskDisclosure: ReactNode;
strategyContent?: ReactNode;
faqContent?: ReactNode;
balance?: VaultBalanceProp;
matomo?: {
performanceTabEvent?: MATOMO_EVENT_TYPE;
strategyTabEvent?: MATOMO_EVENT_TYPE;
Expand Down Expand Up @@ -131,6 +133,7 @@ export const VaultPage: FC<Props> = (props) => {
isApxLoading={props.isApxLoading}
isTvlLoading={props.isTvlLoading}
protectedBadgeTooltipText={protectedBadgeTooltipText}
balance={props.balance}
/>
<VaultPageContent>
<TabsStyled>
Expand Down
4 changes: 2 additions & 2 deletions features/earn/vault-dvv/vault-card-dvv-v2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export const VaultCardDVV = () => {
position={
isWalletConnected
? {
balance: sharesBalance,
symbol: DVV_TOKEN_SYMBOL,
sharesBalance: sharesBalance,
sharesSymbol: DVV_TOKEN_SYMBOL,
isLoading: isLoadingPosition,
}
: undefined
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { RequestsContainer } from 'modules/mellow-meta-vaults/components/request';
import { VaultPosition } from 'features/earn/shared/v2/vault-position/vault-position';
import { TokenEarnEthIcon } from 'assets/earn-v2';

import { useEthVaultAvailable } from '../../hooks/use-vault-available';
import {
Expand All @@ -10,8 +8,6 @@ import {
} from '../hooks';
import { EthVaultDepositPendingRequests } from './deposit-pending-requests';
import { EthVaultDepositClaimableRequest } from './deposit-claimable-request';
import { useEthVaultPosition } from '../../hooks/use-position';
import { ETH_VAULT_TOKEN_SYMBOL } from '../../consts';

export const EthVaultDepositRequests = () => {
const { isEthVaultAvailable } = useEthVaultAvailable();
Expand All @@ -24,34 +20,12 @@ export const EthVaultDepositRequests = () => {
totalClaimableShares,
} = useEthVaultDepositRequests();

const {
data: earnethPositionData,
isLoading: isPositionLoading,
usdBalance: usdAmount,
usdQuery: { isLoading: isPositionLoadingUsd },
} = useEthVaultPosition();

const earnethBalance = earnethPositionData?.earnethSharesBalance ?? 0n;

if (
(earnethBalance === 0n && depositRequests.length === 0) ||
!isEthVaultAvailable
) {
if (depositRequests.length === 0 || !isEthVaultAvailable) {
return null;
}

return (
<RequestsContainer>
<VaultPosition
position={{
symbol: ETH_VAULT_TOKEN_SYMBOL,
token: earnethPositionData?.earnethTokenAddress,
balance: earnethBalance,
icon: <TokenEarnEthIcon />,
isLoading: isPositionLoading || isPositionLoadingUsd,
usdAmount,
}}
/>
<EthVaultDepositPendingRequests
requests={pendingRequests}
cancel={cancel}
Expand Down
3 changes: 2 additions & 1 deletion features/earn/vault-eth/hooks/use-position.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export const useEthVaultPosition = () => {
const data = isEnabled ? earnethBalanceQuery.data : undefined;
const wsteth = earnethToWstethQuery.data;

const { usdAmount, ...usdQuery } = useWstethUsd(
const { usdAmount, ethAmount, ...usdQuery } = useWstethUsd(
wsteth,
publicClientMainnet.chain?.id,
);
Expand All @@ -68,5 +68,6 @@ export const useEthVaultPosition = () => {
earnethSharesBalance: data?.earnethSharesBalance,
usdQuery,
usdBalance: usdAmount ?? 0,
ethAmount,
};
};
18 changes: 12 additions & 6 deletions features/earn/vault-eth/vault-card.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { VaultEthIcon } from 'assets/earn-v2';
import { trackMatomoEvent } from 'utils/track-matomo-event';
import { getTokenIcon } from 'utils/get-token-icon';
import { MATOMO_EARN_EVENTS_TYPES } from 'consts/matomo';
import { VaultCard } from '../shared/v2/vault-card';
import { EARN_VAULT_ETH_SLUG } from '../consts';
Expand All @@ -12,15 +11,20 @@ import {
ETH_VAULT_TITLE,
ETH_VAULT_TOKEN_SYMBOL,
} from './consts';
import { TOKEN_SYMBOLS } from 'consts/tokens';
import { useEthVaultPosition } from './hooks/use-position';
import { ProtectedTooltip } from './protected-tooltip';

export const EthVaultCard = () => {
const { apy, isLoading: isApyLoading } = useEthVaultApy();
const { tvlUsd, isLoading: isTvlLoading } = useEthVaultStats();

const { data: earnethPositionData, isLoading: isPositionLoading } =
useEthVaultPosition();
const {
data: earnethPositionData,
isLoading: isPositionLoading,
ethAmount,
usdBalance,
} = useEthVaultPosition();

const sharesBalance = earnethPositionData?.earnethSharesBalance;

Expand All @@ -37,9 +41,11 @@ export const EthVaultCard = () => {
isLoading: isApyLoading || isTvlLoading,
}}
position={{
balance: sharesBalance,
symbol: ETH_VAULT_TOKEN_SYMBOL,
icon: getTokenIcon(ETH_VAULT_TOKEN_SYMBOL),
sharesBalance,
sharesSymbol: ETH_VAULT_TOKEN_SYMBOL,
baseAmount: ethAmount,
baseSymbol: TOKEN_SYMBOLS.eth,
usdAmount: sharesBalance ? usdBalance : undefined,
isLoading: isPositionLoading,
}}
ctaLabel={sharesBalance && sharesBalance > 0n ? 'Manage' : 'Deposit'}
Expand Down
Loading
Loading