Skip to content

Commit 8fc40e6

Browse files
committed
feat: add base Boost tab
1 parent 8eb6d14 commit 8fc40e6

File tree

23 files changed

+938
-88
lines changed

23 files changed

+938
-88
lines changed

apps/evm/src/components/SelectTokenTextField/TokenList/index.tsx

Lines changed: 27 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
import { Typography } from '@mui/material';
33
import { type InputHTMLAttributes, useMemo, useState } from 'react';
44

5-
import { cn } from '@venusprotocol/ui';
65
import { TokenIconWithSymbol } from 'components/TokenIconWithSymbol';
76
import { useTranslation } from 'libs/translations';
87
import type { Token, TokenBalance } from 'types';
@@ -18,6 +17,7 @@ import { useStyles } from './styles';
1817
export interface TokenListProps {
1918
tokenBalances: OptionalTokenBalance[];
2019
onTokenClick: (token: Token) => void;
20+
displayCommonTokenButtons: boolean;
2121
'data-testid'?: string;
2222
}
2323

@@ -26,17 +26,16 @@ const commonTokenSymbols = ['XVS', 'BNB', 'USDT', 'BTCB'];
2626
export const TokenList: React.FC<TokenListProps> = ({
2727
tokenBalances,
2828
onTokenClick,
29+
displayCommonTokenButtons,
2930
'data-testid': testId,
3031
}) => {
3132
const { t } = useTranslation();
3233
const parentStyles = useParentStyles();
3334
const styles = useStyles();
3435

35-
const commonTokenBalances = useMemo(
36-
() =>
37-
tokenBalances.filter(tokenBalance => commonTokenSymbols.includes(tokenBalance.token.symbol)),
38-
[tokenBalances],
39-
);
36+
const commonTokenBalances = displayCommonTokenButtons
37+
? tokenBalances.filter(tokenBalance => commonTokenSymbols.includes(tokenBalance.token.symbol))
38+
: [];
4039

4140
const [searchValue, setSearchValue] = useState('');
4241

@@ -85,30 +84,29 @@ export const TokenList: React.FC<TokenListProps> = ({
8584

8685
return (
8786
<div css={styles.container}>
88-
<div className={cn(commonTokenBalances.length > 2 && 'mb-5 pl-3 pr-3 pt-3')}>
87+
<div className="mb-5 pl-3 pr-3 pt-3">
88+
<TextField
89+
css={styles.searchField}
90+
size="xs"
91+
autoFocus
92+
value={searchValue}
93+
onChange={handleSearchInputChange}
94+
placeholder={t('selectTokenTextField.searchInput.placeholder')}
95+
leftIconSrc="magnifier"
96+
/>
97+
8998
{commonTokenBalances.length > 2 && (
90-
<>
91-
<TextField
92-
css={styles.searchField}
93-
size="xs"
94-
autoFocus
95-
value={searchValue}
96-
onChange={handleSearchInputChange}
97-
placeholder={t('selectTokenTextField.searchInput.placeholder')}
98-
leftIconSrc="magnifier"
99-
/>
100-
<div css={styles.commonTokenList}>
101-
{commonTokenBalances.map(commonTokenBalance => (
102-
<SenaryButton
103-
onClick={() => onTokenClick(commonTokenBalance.token)}
104-
css={styles.commonTokenButton}
105-
key={`select-token-text-field-common-token-${commonTokenBalance.token.symbol}`}
106-
>
107-
<TokenIconWithSymbol css={parentStyles.token} token={commonTokenBalance.token} />
108-
</SenaryButton>
109-
))}
110-
</div>
111-
</>
99+
<div css={styles.commonTokenList}>
100+
{commonTokenBalances.map(commonTokenBalance => (
101+
<SenaryButton
102+
onClick={() => onTokenClick(commonTokenBalance.token)}
103+
css={styles.commonTokenButton}
104+
key={`select-token-text-field-common-token-${commonTokenBalance.token.symbol}`}
105+
>
106+
<TokenIconWithSymbol css={parentStyles.token} token={commonTokenBalance.token} />
107+
</SenaryButton>
108+
))}
109+
</div>
112110
)}
113111
</div>
114112

apps/evm/src/components/SelectTokenTextField/index.tsx

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
import { Typography } from '@mui/material';
33
import { useState } from 'react';
44

5-
import { TokenIconWithSymbol } from 'components/TokenIconWithSymbol';
65
import type { Token } from 'types';
76

8-
import { TertiaryButton } from '@venusprotocol/ui';
7+
import { TertiaryButton, cn } from '@venusprotocol/ui';
98
import { Icon } from '../Icon';
9+
import { TokenIcon } from '../TokenIcon';
1010
import { TokenTextField, type TokenTextFieldProps } from '../TokenTextField';
1111
import TokenList from './TokenList';
1212
import { useStyles } from './styles';
@@ -18,9 +18,12 @@ import {
1818
import type { OptionalTokenBalance } from './types';
1919

2020
export interface SelectTokenTextFieldProps extends Omit<TokenTextFieldProps, 'max' | 'token'> {
21-
selectedToken: Token;
2221
tokenBalances: OptionalTokenBalance[];
22+
selectedToken: Token;
2323
onChangeSelectedToken: (token: Token) => void;
24+
token?: Token;
25+
selectedTokenLabel?: string;
26+
displayCommonTokenButtons?: boolean;
2427
'data-testid'?: string;
2528
}
2629

@@ -35,6 +38,8 @@ export const SelectTokenTextField: React.FC<SelectTokenTextFieldProps> = ({
3538
rightMaxButton,
3639
'data-testid': testId,
3740
description,
41+
selectedTokenLabel,
42+
displayCommonTokenButtons = false,
3843
...otherTokenTextFieldProps
3944
}) => {
4045
const styles = useStyles();
@@ -64,7 +69,19 @@ export const SelectTokenTextField: React.FC<SelectTokenTextFieldProps> = ({
6469
disabled={disabled}
6570
data-testid={!!testId && getTokenSelectButtonTestId({ parentTestId: testId })}
6671
>
67-
<TokenIconWithSymbol token={selectedToken} css={styles.token} />
72+
<div className="flex items-center gap-x-2">
73+
<TokenIcon token={selectedToken} className="h-5 w-5" />
74+
75+
<div className="text-left">
76+
<div className={cn(!!selectedTokenLabel && 'leading-3')}>
77+
{selectedToken.symbol}
78+
</div>
79+
80+
{!!selectedTokenLabel && (
81+
<p className="text-xs text-grey leading-3 font-normal">{selectedTokenLabel}</p>
82+
)}
83+
</div>
84+
</div>
6885

6986
<Icon
7087
css={styles.getArrowIcon({ isTokenListShown })}
@@ -95,6 +112,7 @@ export const SelectTokenTextField: React.FC<SelectTokenTextFieldProps> = ({
95112
tokenBalances={tokenBalances}
96113
data-testid={testId}
97114
onTokenClick={handleChangeSelectedToken}
115+
displayCommonTokenButtons={displayCommonTokenButtons}
98116
/>
99117
)}
100118
</div>

apps/evm/src/components/Slider/index.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export interface SliderProps {
77
step: number;
88
max: number;
99
min?: number;
10+
disabled?: boolean;
1011
className?: string;
1112
}
1213

@@ -16,6 +17,7 @@ export const Slider: React.FC<SliderProps> = ({
1617
min = 0,
1718
max,
1819
step,
20+
disabled = false,
1921
className,
2022
}) => (
2123
<SliderPrimitive.Root
@@ -27,6 +29,7 @@ export const Slider: React.FC<SliderProps> = ({
2729
step={step}
2830
onValueChange={([newValue]) => onChange(newValue)}
2931
className={cn('relative flex w-full touch-none items-center select-none', className)}
32+
disabled={disabled}
3033
>
3134
<SliderPrimitive.Track
3235
data-slot="slider-track"
@@ -37,7 +40,10 @@ export const Slider: React.FC<SliderProps> = ({
3740

3841
<SliderPrimitive.Thumb
3942
data-slot="slider-thumb"
40-
className="block size-5 shrink-0 outline-none cursor-pointer rounded-full border-offWhite border-4 bg-blue shadow-sm transition-[color,box-shadow]"
43+
className={cn(
44+
'block size-5 shrink-0 outline-none rounded-full border-offWhite border-4 bg-blue shadow-sm transition-[color,box-shadow]',
45+
!disabled && 'cursor-pointer',
46+
)}
4147
/>
4248
</SliderPrimitive.Root>
4349
);

apps/evm/src/components/TextField/index.tsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ export interface TextFieldProps extends Omit<InputHTMLAttributes<HTMLInputElemen
1515
hasError?: boolean;
1616
leftIconSrc?: IconName | Token;
1717
rightAdornment?: React.ReactElement;
18-
size?: 'xs' | 'md';
19-
variant?: 'primary' | 'secondary';
18+
size?: 'xxs' | 'xs' | 'md';
19+
variant?: 'primary' | 'secondary' | 'tertiary';
2020
}
2121

2222
export const TextField: React.FC<TextFieldProps> = forwardRef<HTMLInputElement, TextFieldProps>(
@@ -70,6 +70,9 @@ export const TextField: React.FC<TextFieldProps> = forwardRef<HTMLInputElement,
7070
let inputContainerCn = cn(
7171
'flex items-center h-15 pr-2 pl-4 py-2 border border-lightGrey rounded-xl bg-background transition-[border-color] hover:border-offWhite focus-within:border-blue focus-within:hover:border-blue',
7272
size === 'xs' && 'h-10 py-1 rounded-lg',
73+
size === 'xxs' && 'h-8 py-1 rounded-[4px] px-3',
74+
variant === 'tertiary' &&
75+
'bg-lightGrey text-grey hover:text-offWhite hover:border-transparent focus-within:text-offWhite',
7376
disabled && 'border-lightGrey bg-cards',
7477
hasError && 'border-red focus-within:border-red',
7578
);
@@ -101,7 +104,7 @@ export const TextField: React.FC<TextFieldProps> = forwardRef<HTMLInputElement,
101104
className={cn(
102105
'bg-transparent flex-1 h-full font-semibold leading-6 w-full placeholder:text-grey outline-none',
103106
!!rightAdornment && 'mr-1',
104-
size === 'xs' && 'text-sm',
107+
(size === 'xs' || size === 'xxs') && 'text-sm',
105108
)}
106109
max={max}
107110
min={min}

apps/evm/src/components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,4 @@ export * from './EModeIcon';
6161
export * from './MarketStatus';
6262
export * from './Slider';
6363
export * from './IsolatedEModeGroupTooltip';
64+
export * from './TokenIcon';

apps/evm/src/containers/SwapDetails/index.tsx

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { TertiaryButton, cn } from '@venusprotocol/ui';
22

33
import { Icon, LabeledInlineContent, Modal, TextField, type TextFieldProps } from 'components';
4+
import PLACEHOLDER_KEY from 'constants/placeholderKey';
45
import {
56
DEFAULT_SLIPPAGE_TOLERANCE_PERCENTAGE,
67
HIGH_PRICE_IMPACT_THRESHOLD_PERCENTAGE,
@@ -19,16 +20,16 @@ export const slippageToleranceOptions = ['0.1', String(DEFAULT_SLIPPAGE_TOLERANC
1920
const MAX_SLIPPAGE_TOLERANCE_DECIMALS = 2;
2021

2122
export interface SwapDetailsProps {
22-
exchangeRate: BigNumber;
2323
fromToken: Token;
2424
toToken: Token;
25-
priceImpactPercentage: number;
25+
exchangeRate?: BigNumber;
26+
priceImpactPercentage?: number;
2627
}
2728

2829
export const SwapDetails: React.FC<SwapDetailsProps> = ({
29-
exchangeRate,
3030
fromToken,
3131
toToken,
32+
exchangeRate,
3233
priceImpactPercentage,
3334
}) => {
3435
const { t } = useTranslation();
@@ -78,13 +79,15 @@ export const SwapDetails: React.FC<SwapDetailsProps> = ({
7879

7980
return (
8081
<>
81-
<div className="space-y-3">
82+
<div className="space-y-2">
8283
<LabeledInlineContent label={t('swapDetails.exchangeRate.label')}>
83-
{t('swapDetails.exchangeRate.value', {
84-
fromTokenSymbol: fromToken.symbol,
85-
toTokenSymbol: toToken.symbol,
86-
rate: readableExchangeRate,
87-
})}
84+
{exchangeRate !== undefined
85+
? t('swapDetails.exchangeRate.value', {
86+
fromTokenSymbol: fromToken.symbol,
87+
toTokenSymbol: toToken.symbol,
88+
rate: readableExchangeRate,
89+
})
90+
: PLACEHOLDER_KEY}
8891
</LabeledInlineContent>
8992

9093
<LabeledInlineContent label={t('swapDetails.slippageTolerance.label')}>
@@ -106,7 +109,9 @@ export const SwapDetails: React.FC<SwapDetailsProps> = ({
106109
<span
107110
className={cn(
108111
'align-sub',
109-
priceImpactPercentage >= HIGH_PRICE_IMPACT_THRESHOLD_PERCENTAGE && 'text-red',
112+
priceImpactPercentage !== undefined &&
113+
priceImpactPercentage >= HIGH_PRICE_IMPACT_THRESHOLD_PERCENTAGE &&
114+
'text-red',
110115
)}
111116
>
112117
{readablePriceImpact}

apps/evm/src/hooks/useDelegateApproval/index.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export interface UseDelegateApprovalInput {
1111

1212
export interface UseDelegateApprovalOutput {
1313
updatePoolDelegateStatus: ({ approvedStatus }: { approvedStatus: boolean }) => Promise<unknown>;
14-
isUseUpdatePoolDelegateStatusLoading: boolean;
14+
isDelegateStatusLoading: boolean;
1515
isDelegateApproved: boolean | undefined;
1616
isDelegateApprovedLoading: boolean;
1717
}
@@ -23,12 +23,10 @@ const useDelegateApproval = ({
2323
}: UseDelegateApprovalInput): UseDelegateApprovalOutput => {
2424
const { accountAddress } = useAccountAddress();
2525

26-
const {
27-
mutateAsync: updatePoolDelegateStatusMutation,
28-
isPending: isUseUpdatePoolDelegateStatusLoading,
29-
} = useUpdatePoolDelegateStatus({
30-
waitForConfirmation: true,
31-
});
26+
const { mutateAsync: updatePoolDelegateStatusMutation, isPending: isDelegateStatusLoading } =
27+
useUpdatePoolDelegateStatus({
28+
waitForConfirmation: true,
29+
});
3230

3331
const updatePoolDelegateStatus = (input: { approvedStatus: boolean }) =>
3432
updatePoolDelegateStatusMutation({
@@ -53,7 +51,7 @@ const useDelegateApproval = ({
5351

5452
return {
5553
updatePoolDelegateStatus,
56-
isUseUpdatePoolDelegateStatusLoading,
54+
isDelegateStatusLoading,
5755
isDelegateApproved,
5856
isDelegateApprovedLoading,
5957
};

apps/evm/src/hooks/useFormatTokensToReadableValue.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import { type FormatTokensToReadableValueInput, formatTokensToReadableValue } fr
55

66
export type UseFormatTokensToReadableValueInput = FormatTokensToReadableValueInput;
77

8+
/**
9+
* @deprecated Use formatTokensToReadableValue instead
10+
*/
811
const useFormatTokensToReadableValue = (params: UseFormatTokensToReadableValueInput) =>
912
useMemo(() => (params.value ? formatTokensToReadableValue(params) : PLACEHOLDER_KEY), [params]);
1013

apps/evm/src/libs/translations/translations/en.json

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,8 +657,12 @@
657657
},
658658
"operationForm": {
659659
"availableAmount": "Available",
660+
"boost": {
661+
"supply": "Supply"
662+
},
660663
"boostTabAltText": "Rocket icon",
661664
"boostTabTitle": "Boost",
665+
"borrowBalance": "Borrow balance ({{ tokenSymbol }})",
662666
"borrowTabTitle": "Borrow",
663667
"error": {
664668
"borrowCapReached": "The borrow cap of {{assetBorrowCap}} has been reached for this pool. You can not borrow from this market anymore until loans are repaid or its borrow cap is increased.",
@@ -676,6 +680,10 @@
676680
"unwrappingUnsupported": "Unwrapping unsupported",
677681
"wrappingUnsupported": "Wrapping unsupported"
678682
},
683+
"leverage": {
684+
"label": "Leverage",
685+
"tooltip": "TRANSLATION NEEDED"
686+
},
679687
"receiveNativeToken": {
680688
"label": "Receive {{tokenSymbol}}",
681689
"tooltip": "Unwrap borrowed {{wrappedNativeTokenSymbol}} to {{nativeTokenSymbol}}"
@@ -701,6 +709,7 @@
701709
"supply": {
702710
"collateral": "Collateral"
703711
},
712+
"supplyBalance": "Supply balance ({{ tokenSymbol }})",
704713
"supplyTabTitle": "Supply",
705714
"swapDetails": {
706715
"label": {

0 commit comments

Comments
 (0)