This commit is contained in:
Linkie Link
2023-02-07 17:52:13 +01:00
parent 79db46721f
commit 5d7f86662a
62 changed files with 771 additions and 1156 deletions
@@ -1,6 +1,5 @@
import Tippy from '@tippyjs/react'
import classNames from 'classnames'
import { AnimatedNumber, DisplayCurrency } from 'components/common'
import { AnimatedNumber, DisplayCurrency, TextTooltip } from 'components/common'
import { formatValue } from 'libs/parse'
import { useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
@@ -82,73 +81,66 @@ export const BorrowCapacity = ({
/>
)}
</div>
<Tippy
appendTo={() => document.body}
interactive={true}
animation={false}
render={(attrs) => {
return (
<div className='tippyContainer' {...attrs}>
{t('redbank.borrowingBarTooltip', {
limit: formatValue(
convertToDisplayCurrency({
amount: limit.toString(),
denom: baseCurrency.denom,
}),
2,
2,
true,
'$',
),
liquidation: formatValue(
convertToDisplayCurrency({
amount: max.toString(),
denom: baseCurrency.denom,
}),
2,
2,
true,
'$',
),
})}
</div>
)
}}
>
<div className={styles.progressbarContainer} style={{ height: barHeight }}>
<div className={styles.progressbar}>
<div className={styles.limitLine} style={{ left: `${limitPercentOfMax || 0}%` }} />
<div
className={styles.limitBar}
style={{
right: `${limitPercentOfMax ? 100 - limitPercentOfMax : 100}%`,
}}
></div>
<div className={styles.ltvContainer}>
<TextTooltip
hideUnderline
tooltip={t('redbank.tooltips.borrow.bar', {
limit: formatValue(
convertToDisplayCurrency({
amount: limit.toString(),
denom: baseCurrency.denom,
}),
2,
2,
true,
'$',
),
liquidation: formatValue(
convertToDisplayCurrency({
amount: max.toString(),
denom: baseCurrency.denom,
}),
2,
2,
true,
'$',
),
})}
text={
<div className={styles.progressbarContainer} style={{ height: barHeight }}>
<div className={styles.progressbar}>
<div className={styles.limitLine} style={{ left: `${limitPercentOfMax || 0}%` }} />
<div
className={styles.indicator}
style={{ width: `${percentOfMaxRange || 0.01}%` }}
>
<div className={styles.gradient} />
className={styles.limitBar}
style={{
right: `${limitPercentOfMax ? 100 - limitPercentOfMax : 100}%`,
}}
></div>
<div className={styles.ltvContainer}>
<div
className={styles.indicator}
style={{ width: `${percentOfMaxRange || 0.01}%` }}
>
<div className={styles.gradient} />
</div>
{showPercentageText ? (
<span className={classNames('overline', styles.percentage)}>
{max !== 0 && (
<AnimatedNumber
amount={percentOfMaxRound}
suffix='%'
maxDecimals={roundPercentage ? 0 : undefined}
minDecimals={roundPercentage ? 0 : undefined}
abbreviated={false}
/>
)}
</span>
) : null}
</div>
{showPercentageText ? (
<span className={classNames('overline', styles.percentage)}>
{max !== 0 && (
<AnimatedNumber
amount={percentOfMaxRound}
suffix='%'
maxDecimals={roundPercentage ? 0 : undefined}
minDecimals={roundPercentage ? 0 : undefined}
abbreviated={false}
/>
)}
</span>
) : null}
</div>
</div>
</div>
</Tippy>
}
/>
{!hideValues && (
<div className={`overline ${styles.values} xxxsCaps`}>
<DisplayCurrency
@@ -10,7 +10,7 @@ import { useQueryClient } from '@tanstack/react-query'
import { MARS_SYMBOL, USDC_SYMBOL } from 'constants/appConstants'
import {
useBlockHeight,
useMarketDeposits,
useDepositAndDebt,
useMarsOracle,
useRedBank,
useUserBalance,
@@ -49,7 +49,6 @@ export const CommonContainer = ({ children }: CommonContainerProps) => {
const exchangeRatesState = useStore((s) => s.exchangeRatesState)
const isNetworkLoaded = useStore((s) => s.isNetworkLoaded)
const rpc = useStore((s) => s.chainInfo?.rpc)
const marketAssetLiquidity = useStore((s) => s.marketAssetLiquidity)
const marketDeposits = useStore((s) => s.marketDeposits)
const marketInfo = useStore((s) => s.marketInfo)
const marketIncentiveInfo = useStore((s) => s.marketIncentiveInfo)
@@ -131,7 +130,6 @@ export const CommonContainer = ({ children }: CommonContainerProps) => {
userBalancesState,
exchangeRates,
marketInfo,
marketAssetLiquidity,
marketIncentiveInfo,
userDebts,
userDeposits,
@@ -157,7 +155,7 @@ export const CommonContainer = ({ children }: CommonContainerProps) => {
useMarsOracle()
useSpotPrice(MARS_SYMBOL)
useSpotPrice(USDC_SYMBOL)
useMarketDeposits()
useDepositAndDebt()
useRedBank()
return <>{isNetworkLoaded && children}</>
@@ -1,4 +1,4 @@
import { ChainInfoID, WalletID, WalletManagerProvider } from '@marsprotocol/wallet-connector'
import { WalletID, WalletManagerProvider } from '@marsprotocol/wallet-connector'
import { CircularProgress, SVG } from 'components/common'
import { useEffect, useState } from 'react'
@@ -8,10 +8,12 @@ type Props = {
children?: React.ReactNode
}
const defaultChain = ChainInfoID.OsmosisTestnet
export const CosmosWalletConnectProvider = ({ children }: Props) => {
const [chainInfoOverrides, setChainInfoOverrides] = useState<{ rpc: string; rest: string }>()
const [chainInfoOverrides, setChainInfoOverrides] = useState<{
rpc: string
rest: string
chainID: string
}>()
const [enabledWallets, setEnabledWallets] = useState<WalletID[]>([])
useEffect(() => {
@@ -29,6 +31,7 @@ export const CosmosWalletConnectProvider = ({ children }: Props) => {
setChainInfoOverrides({
rpc: networkConfig.rpcUrl,
rest: networkConfig.restUrl,
chainID: networkConfig.name,
})
setEnabledWallets(networkConfig.wallets)
}
@@ -42,7 +45,7 @@ export const CosmosWalletConnectProvider = ({ children }: Props) => {
<WalletManagerProvider
chainInfoOverrides={chainInfoOverrides}
closeIcon={<SVG.Close />}
defaultChainId={defaultChain}
defaultChainId={chainInfoOverrides.chainID}
enabledWallets={enabledWallets}
persistent
renderLoader={() => (
@@ -17,10 +17,12 @@ export const DisplayCurrency = ({
isApproximation,
className,
}: Props) => {
const displayCurrency = useStore((s) => s.displayCurrency)
const networkConfig = useStore((s) => s.networkConfig)
const convertToDisplayCurrency = useStore((s) => s.convertToDisplayCurrency)
const amount = convertToDisplayCurrency(coin)
const displayCurrency = networkConfig?.displayCurrency
if (!displayCurrency) return null
return (
<div className={className}>
@@ -47,9 +47,9 @@
top: rem-calc(38);
@include padding(6, 6, 5.5);
@include layoutPopover;
width: rem-calc(420);
width: rem-calc(380);
max-width: calc(100vw - 24px);
right: 0;
right: -25%;
z-index: 100;
}
@@ -191,6 +191,8 @@
@media only screen and (min-width: $bpMediumLow) {
.details {
transform: none;
width: rem-calc(420);
right: 0;
}
.detailsBalance {
@@ -46,7 +46,7 @@ export const ConnectedButton = () => {
const viewOnFinder = useCallback(() => {
const explorerUrl = chainInfo ? chainInfo.explorer : ''
window.open(`${explorerUrl}account/${userWalletAddress}`, '_blank')
window.open(`${explorerUrl}/account/${userWalletAddress}`, '_blank')
}, [chainInfo, userWalletAddress])
const onClickAway = useCallback(() => {
@@ -103,7 +103,7 @@ export const ConnectedButton = () => {
className='s faded'
coin={{
amount: baseCurrencyBalance.toString(),
denom: baseCurrency.symbol,
denom: baseCurrency.denom,
}}
/>
</div>
+13 -12
View File
@@ -31,18 +31,19 @@ export const Header = () => {
>
{t('global.redBank')}
</Link>
<Link
passHref
href='/farm'
className={classNames(
!FIELDS_FEATURE && styles.disabled,
styles.nav,
router.pathname.includes('farm') && styles.active,
router.pathname === '/farm' && styles.unclickable,
)}
>
{t('global.fields')}
</Link>
{FIELDS_FEATURE && (
<Link
passHref
href='/farm'
className={classNames(
styles.nav,
router.pathname.includes('farm') && styles.active,
router.pathname === '/farm' && styles.unclickable,
)}
>
{t('global.fields')}
</Link>
)}
<a className={styles.nav} href={networkConfig?.councilUrl} target='_blank' rel='noreferrer'>
{t('global.council')}
</a>
@@ -156,7 +156,7 @@ export const IncentivesButton = () => {
<p className='m'>{t('incentives.successfullyClaimed')}</p>
<TxLink
hash={response?.hash || ''}
link={`${explorerUrl}txs/${response?.hash}`}
link={`${explorerUrl}/txs/${response?.hash}`}
/>
</div>
) : (
+50 -46
View File
@@ -2,6 +2,7 @@ import { useWalletManager, WalletConnectionStatus } from '@marsprotocol/wallet-c
import BigNumber from 'bignumber.js'
import classNames from 'classnames'
import { Button, NumberInput, SVG, Toggle, Tooltip } from 'components/common'
import { FIELDS_FEATURE } from 'constants/appConstants'
import React, { useState } from 'react'
import { useTranslation } from 'react-i18next'
import useStore from 'store'
@@ -88,54 +89,57 @@ export const Settings = () => {
</div>
</div>
</div>
<div className={styles.header}>
<p className={styles.text}>{t('fields.settings')}</p>
</div>
<div className={styles.settings}>
<div className={styles.setting}>
<div className={styles.name}>
{t('common.slippage')}
<Tooltip content={t('fields.tooltips.slippage')} className={styles.tooltip} />
{FIELDS_FEATURE && (
<>
<div className={styles.header}>
<p className={styles.text}>{t('fields.settings')}</p>
</div>
<div className={styles.content}>
{slippages.map((value) => (
<button
key={`slippage-${value}`}
onClick={() => {
useStore.setState({ slippage: value })
}}
className={classNames([
styles.button,
slippage === value && !isCustom ? styles.solid : '',
])}
>
{value * 100}%
</button>
))}
<button
onClick={() => inputRef?.current?.focus()}
className={classNames([
styles.button,
!slippages.includes(slippage) || isCustom ? styles.solid : '',
])}
>
<NumberInput
onRef={setInputRef}
onChange={onInputChange}
onBlur={onInputBlur}
onFocus={onInputFocus}
value={customSlippage}
maxValue={10}
maxDecimals={1}
maxLength={3}
className={styles.customSlippageBtn}
/>
%
</button>
<div className={styles.settings}>
<div className={styles.setting}>
<div className={styles.name}>
{t('common.slippage')}
<Tooltip content={t('fields.tooltips.slippage')} className={styles.tooltip} />
</div>
<div className={styles.content}>
{slippages.map((value) => (
<button
key={`slippage-${value}`}
onClick={() => {
useStore.setState({ slippage: value })
}}
className={classNames([
styles.button,
slippage === value && !isCustom ? styles.solid : '',
])}
>
{value * 100}%
</button>
))}
<button
onClick={() => inputRef?.current?.focus()}
className={classNames([
styles.button,
!slippages.includes(slippage) || isCustom ? styles.solid : '',
])}
>
<NumberInput
onRef={setInputRef}
onChange={onInputChange}
onBlur={onInputBlur}
onFocus={onInputFocus}
value={customSlippage}
maxValue={10}
maxDecimals={1}
maxLength={3}
className={styles.customSlippageBtn}
/>
%
</button>
</div>
</div>
</div>
</div>
</div>
</>
)}
</div>
<div className={styles.clickAway} onClick={() => setShowDetails(false)} role='button' />
</>
+8 -8
View File
@@ -15,23 +15,23 @@ type Props = {
export const Layout = ({ children }: Props) => {
const router = useRouter()
const { status } = useWalletManager()
useAnimations()
const userWalletAddress = useStore((s) => s.userWalletAddress)
const enableAnimations = useStore((s) => s.enableAnimations)
const backgroundClasses = classNames('background', !userWalletAddress && 'night')
const vaultConfigs = useStore((s) => s.vaultConfigs)
const { status } = useWalletManager()
const isConnected = status === WalletConnectionStatus.Connected
const backgroundClasses = classNames('background', !isConnected && 'night')
const vaultConfigs = useStore((s) => s.vaultConfigs)
const wasConnectedBefore =
localStorage.getItem(SESSION_WALLET_KEY) !== null &&
localStorage.getItem(SESSION_WALLET_KEY) !== '[]'
localStorage.getItem(SESSION_WALLET_KEY) &&
localStorage.getItem(SESSION_WALLET_KEY) !== '[]' &&
status !== WalletConnectionStatus.Errored
useEffect(() => {
if (!userWalletAddress) {
if (!isConnected) {
useStore.setState({ availableVaults: vaultConfigs, activeVaults: [] })
}
}, [userWalletAddress, vaultConfigs])
}, [isConnected, vaultConfigs])
return (
<div className={classNames('app', !enableAnimations && 'no-motion')}>
+11 -8
View File
@@ -1,5 +1,6 @@
import classNames from 'classnames'
import { SVG } from 'components/common'
import { FIELDS_FEATURE } from 'constants/appConstants'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useTranslation } from 'react-i18next'
@@ -26,14 +27,16 @@ export const MobileNav = () => {
<SVG.CouncilIcon />
<span>{t('global.council')}</span>
</a>
<Link
href='/farm'
passHref
className={classNames(styles.nav, router.pathname.includes('farm') && styles.active)}
>
<SVG.FieldsIcon />
<span>{t('global.fields')}</span>
</Link>
{FIELDS_FEATURE && (
<Link
href='/farm'
passHref
className={classNames(styles.nav, router.pathname.includes('farm') && styles.active)}
>
<SVG.FieldsIcon />
<span>{t('global.fields')}</span>
</Link>
)}
</nav>
)
}
@@ -0,0 +1,16 @@
@import 'src/styles/master';
.pointer {
cursor: pointer;
}
.tooltip {
border-bottom: 1px dashed $alphaWhite40;
transition: border 0.2s;
cursor: pointer;
&:hover,
&:focus {
border-bottom-color: transparent;
}
}
@@ -1,23 +1,31 @@
import Tippy from '@tippyjs/react'
import styles from './TextTooltip.module.scss'
interface Props {
text: string
tooltip: string
text: string | React.ReactNode
tooltip: string | React.ReactNode
hideUnderline?: boolean
hideStyling?: boolean
}
export const TextTooltip = (props: Props) => {
return (
<Tippy
appendTo={() => document.body}
animation={false}
delay={[400, 0]}
render={(attrs) => {
if (!props.tooltip) return null
return (
<div className='tippyContainer' {...attrs}>
<div className={props.hideStyling ? '' : 'tippyContainer'} {...attrs}>
{props.tooltip}
</div>
)
}}
>
<div>{props.text}</div>
<span className={props.hideUnderline ? styles.pointer : styles.tooltip} style={{}}>
{props.text}
</span>
</Tippy>
)
}
+4 -4
View File
@@ -447,13 +447,13 @@ export const Action = ({
const getTooltip = (): string | undefined => {
switch (activeView) {
case ViewType.Borrow:
return t('redbank.redbankActionBorrowTooltip')
return t('redbank.tooltips.borrow.action')
case ViewType.Deposit:
return t('redbank.redbankActionDepositTooltip')
return t('redbank.tooltips.deposit.action')
case ViewType.Withdraw:
return t('redbank.redbankActionWithdrawTooltip')
return t('redbank.tooltips.withdraw.action')
case ViewType.Repay:
return t('redbank.redbankActionRepayTooltip')
return t('redbank.tooltips.repay.action')
}
}
@@ -24,7 +24,7 @@ export const TxFailedContent = ({ message, hash, handleClose }: Props) => {
<InfoTitle src={TxStatus.FAILURE} subTitle='' title={t('common.transactionFailed')} />
<div className={styles.failure}>
<div className={styles.message}>{message}</div>
{hash ? <TxLink hash={hash} link={`${explorerUrl}txs/${hash}`} /> : null}
{hash ? <TxLink hash={hash} link={`${explorerUrl}/txs/${hash}`} /> : null}
</div>
<div
@@ -67,7 +67,7 @@ export const TxSuccessContent = ({
<div className={styles.label}>{t('common.txHash')}</div>
<TxLink
hash={response?.response.transactionHash || ''}
link={`${explorerUrl}txs/${response?.response.transactionHash}`}
link={`${explorerUrl}/txs/${response?.response.transactionHash}`}
/>
</div>
</div>
@@ -1,6 +1,12 @@
import Tippy from '@tippyjs/react'
import BigNumber from 'bignumber.js'
import { AnimatedNumber, Apy, BorrowCapacity, Card, DisplayCurrency } from 'components/common'
import {
AnimatedNumber,
Apy,
BorrowCapacity,
Card,
DisplayCurrency,
TextTooltip,
} from 'components/common'
import { VaultLogo, VaultName } from 'components/fields'
import { FIELDS_TUTORIAL_KEY } from 'constants/appConstants'
import Link from 'next/link'
@@ -60,8 +66,18 @@ export const ActiveVaultsTableMobile = () => {
<div className='xl' onClick={(e) => e.preventDefault()}>
<span className='faded'>{t('common.apy')} </span>
<span>
<Tippy
content={
<TextTooltip
hideStyling
text={
<span>
<AnimatedNumber
amount={vault.position.apy.net}
className='xl'
suffix='%'
/>
</span>
}
tooltip={
<Apy
apyData={{
borrow: vault.position.apy.borrow,
@@ -70,11 +86,7 @@ export const ActiveVaultsTableMobile = () => {
leverage={vault.position.currentLeverage}
/>
}
>
<span className='tooltip xl'>
<AnimatedNumber amount={vault.position.apy.net} className='xl' suffix='%' />
</span>
</Tippy>
/>
</span>
</div>
<div className='s'>
@@ -1,5 +1,4 @@
import { ColumnDef, createColumnHelper } from '@tanstack/react-table'
import Tippy from '@tippyjs/react'
import BigNumber from 'bignumber.js'
import classNames from 'classnames'
import {
@@ -53,25 +52,14 @@ export const useActiveVaultsColumns = () => {
header: t('fields.position'),
cell: ({ row }) => {
return (
<Tippy
appendTo={() => document.body}
animation={false}
render={(attrs) => {
return (
<div className='tippyContainer' {...attrs}>
{t('fields.tooltips.name', {
asset1: row.original.symbols.primary,
asset2: row.original.symbols.secondary,
...getTimeAndUnit(row.original.lockup),
})}
</div>
)
}}
>
<div>
<VaultName vault={row.original} />
</div>
</Tippy>
<TextTooltip
text={<VaultName vault={row.original} />}
tooltip={t('fields.tooltips.name', {
asset1: row.original.symbols.primary,
asset2: row.original.symbols.secondary,
...getTimeAndUnit(row.original.lockup),
})}
/>
)
},
}),
@@ -97,28 +85,23 @@ export const useActiveVaultsColumns = () => {
}
return (
<Tippy
appendTo={() => document.body}
animation={false}
render={(attrs) => {
return (
<div className='tippyContainer' {...attrs}>
<TokenBalance coin={primaryCoin} maxDecimals={2} showSymbol />
<br />
<TokenBalance coin={secondaryCoin} maxDecimals={2} showSymbol />
</div>
)
}}
>
<div>
<TextTooltip
text={
<DisplayCurrency
coin={{
denom: baseCurrency.denom,
amount: row.original.position.values.total.toString(),
}}
/>
</div>
</Tippy>
}
tooltip={
<>
<TokenBalance coin={primaryCoin} maxDecimals={2} showSymbol />
<br />
<TokenBalance coin={secondaryCoin} maxDecimals={2} showSymbol />
</>
}
/>
)
},
}),
@@ -142,25 +125,20 @@ export const useActiveVaultsColumns = () => {
]
return (
<Tippy
appendTo={() => document.body}
animation={false}
render={(attrs) => {
return (
<div className='tippyContainer' {...attrs}>
<TokenBalance coin={coins[0]} maxDecimals={2} showSymbol />
<br />
<TokenBalance coin={coins[1]} maxDecimals={2} showSymbol />
</div>
)
}}
>
<div>
<TextTooltip
text={
<DisplayCurrency
coin={{ denom: baseCurrency.denom, amount: netValue.toString() }}
/>
</div>
</Tippy>
}
tooltip={
<>
<TokenBalance coin={coins[0]} maxDecimals={2} showSymbol />
<br />
<TokenBalance coin={coins[1]} maxDecimals={2} showSymbol />
</>
}
/>
)
},
}),
@@ -176,33 +154,26 @@ export const useActiveVaultsColumns = () => {
if (!borrowAsset) return
return (
<Tippy
appendTo={() => document.body}
animation={false}
render={(attrs) => {
return (
<div className='tippyContainer' {...attrs}>
<TokenBalance
coin={{
denom: info.row.original.denoms.secondary,
amount: info.row.original.position.amounts.borrowed.toString(),
}}
maxDecimals={2}
showSymbol
/>
</div>
)
}}
>
<div>
<TextTooltip
text={
<DisplayCurrency
coin={{
denom: baseCurrency.denom,
amount: info.row.original.position.values.borrowed.toString(),
}}
/>
</div>
</Tippy>
}
tooltip={
<TokenBalance
coin={{
denom: info.row.original.denoms.secondary,
amount: info.row.original.position.amounts.borrowed.toString(),
}}
maxDecimals={2}
showSymbol
/>
}
/>
)
},
}),
@@ -223,35 +194,30 @@ export const useActiveVaultsColumns = () => {
const vaultCap = row.original.vaultCap
return (
<Tippy
appendTo={() => document.body}
animation={false}
render={(attrs) => {
return (
<div className='tippyContainer' {...attrs}>
<TokenBalance
showSymbol
coin={{
denom: baseCurrency.denom,
amount: vaultCap.max.toString(),
}}
/>
</div>
)
}}
>
<div>
<DisplayCurrency
<TextTooltip
text={
<>
<DisplayCurrency
coin={{
denom: baseCurrency.denom,
amount: vaultCap.max.toString(),
}}
/>
<p className={percentClasses}>
{percent}% {t('common.used')}
</p>
</>
}
tooltip={
<TokenBalance
showSymbol
coin={{
denom: baseCurrency.denom,
amount: vaultCap.max.toString(),
}}
/>
<p className={percentClasses}>
{percent}% {t('common.used')}
</p>
</div>
</Tippy>
}
/>
)
},
}),
@@ -279,20 +245,20 @@ export const useActiveVaultsColumns = () => {
}
return (
<>
<Tippy
appendTo={() => document.body}
animation={false}
content={
<TextTooltip
hideStyling
text={
<>
<AnimatedNumber amount={apy} className='m' suffix='%' />
<p className='s faded'>
{convertApyToDailyApy(row.original.position.apy.net)}%/{t('common.day')}
</p>
</>
}
tooltip={
<Apy apyData={apyData} leverage={row.original.position.currentLeverage} />
}
>
<span className='tooltip'>
<AnimatedNumber amount={apy} className='m' suffix='%' />
<p className='s faded'>
{convertApyToDailyApy(row.original.position.apy.net)}%/{t('common.day')}
</p>
</span>
</Tippy>
/>
</>
)
case 'unlocking':
@@ -1,6 +1,5 @@
import Tippy from '@tippyjs/react'
import BigNumber from 'bignumber.js'
import { AnimatedNumber, Apy, Card, DisplayCurrency } from 'components/common'
import { AnimatedNumber, Apy, Card, DisplayCurrency, TextTooltip } from 'components/common'
import { VaultLogo, VaultName } from 'components/fields'
import { getTimeAndUnit, ltvToLeverage } from 'libs/parse'
import Link from 'next/link'
@@ -52,20 +51,18 @@ export const AvailableVaultsTableMobile = () => {
<div onClick={(e) => e.preventDefault()} className='xl'>
<span className='faded'>{t('common.apy')} </span>
<span>
<Tippy content={<Apy apyData={apyDataNoLev} leverage={1} />}>
<span className='tooltip xl'>
<AnimatedNumber amount={minAPY} suffix='-' />
</span>
</Tippy>
<Tippy
content={
<TextTooltip
hideStyling
text={<AnimatedNumber amount={minAPY} suffix='-' />}
tooltip={<Apy apyData={apyDataNoLev} leverage={1} />}
/>
<TextTooltip
hideStyling
text={<AnimatedNumber amount={maxAPY} suffix='%' />}
tooltip={
<Apy apyData={apyDataLev} leverage={ltvToLeverage(vault.ltv.max)} />
}
>
<span className='tooltip xl'>
<AnimatedNumber amount={maxAPY} suffix='%' />
</span>
</Tippy>
/>
</span>
</div>
<div className='s'>
@@ -1,5 +1,4 @@
import { ColumnDef, createColumnHelper } from '@tanstack/react-table'
import Tippy from '@tippyjs/react'
import BigNumber from 'bignumber.js'
import classNames from 'classnames'
import {
@@ -46,25 +45,14 @@ export const useAvailableVaultsColumns = () => {
header: t('fields.name'),
cell: ({ row }) => {
return (
<Tippy
appendTo={() => document.body}
animation={false}
render={(attrs) => {
return (
<div className='tippyContainer' {...attrs}>
{t('fields.tooltips.name', {
asset1: row.original.symbols.primary,
asset2: row.original.symbols.secondary,
...getTimeAndUnit(row.original.lockup),
})}
</div>
)
}}
>
<div>
<VaultName vault={row.original} />
</div>
</Tippy>
<TextTooltip
text={<VaultName vault={row.original} />}
tooltip={t('fields.tooltips.name', {
asset1: row.original.symbols.primary,
asset2: row.original.symbols.secondary,
...getTimeAndUnit(row.original.lockup),
})}
/>
)
},
}),
@@ -118,21 +106,19 @@ export const useAvailableVaultsColumns = () => {
return (
<>
<Tippy content={<Apy apyData={apyDataNoLev} leverage={1} />}>
<span className='tooltip m'>
<AnimatedNumber amount={minAPY} />
</span>
</Tippy>
<TextTooltip
hideStyling
text={<AnimatedNumber amount={minAPY} />}
tooltip={<Apy apyData={apyDataNoLev} leverage={1} />}
/>
<span>-</span>
<Tippy
content={
<TextTooltip
hideStyling
text={<AnimatedNumber amount={maxAPY} suffix='%' />}
tooltip={
<Apy apyData={apyDataLev} leverage={ltvToLeverage(row.original.ltv.max)} />
}
>
<span className='tooltip ,'>
<AnimatedNumber amount={maxAPY} suffix='%' />
</span>
</Tippy>
/>
<p className='s faded'>
{minDailyAPY}-{maxDailyAPY}%/
@@ -159,35 +145,30 @@ export const useAvailableVaultsColumns = () => {
const vaultCap = row.original.vaultCap
return (
<Tippy
appendTo={() => document.body}
animation={false}
render={(attrs) => {
return (
<div className='tippyContainer' {...attrs}>
<TokenBalance
showSymbol
coin={{
denom: baseCurrency.denom,
amount: vaultCap.max.toString(),
}}
/>
</div>
)
}}
>
<div>
<DisplayCurrency
<TextTooltip
text={
<>
<DisplayCurrency
coin={{
denom: baseCurrency.denom,
amount: vaultCap.max.toString(),
}}
/>
<p className={percentClasses}>
{percent}% {t('common.used')}
</p>
</>
}
tooltip={
<TokenBalance
showSymbol
coin={{
denom: baseCurrency.denom,
amount: vaultCap.max.toString(),
}}
/>
<p className={percentClasses}>
{percent}% {t('common.used')}
</p>
</div>
</Tippy>
}
/>
)
},
}),
@@ -200,23 +181,15 @@ export const useAvailableVaultsColumns = () => {
enableSorting: true,
header: t('common.description'),
cell: ({ row }) => (
<Tippy
appendTo={() => document.body}
animation={false}
render={(attrs) => {
return (
<div className='tippyContainer' {...attrs}>
{t('fields.tooltips.name', {
asset1: row.original.symbols.primary,
asset2: row.original.symbols.secondary,
...getTimeAndUnit(row.original.lockup),
})}
</div>
)
}}
>
<p>{row.original.description}</p>
</Tippy>
<TextTooltip
hideUnderline
text={row.original.description}
tooltip={t('fields.tooltips.name', {
asset1: row.original.symbols.primary,
asset2: row.original.symbols.secondary,
...getTimeAndUnit(row.original.lockup),
})}
/>
),
}),
columnHelper.display({
@@ -1,10 +1,10 @@
import Tippy from '@tippyjs/react'
import classNames from 'classnames'
import {
AnimatedNumber,
Apy,
BorrowCapacity,
DisplayCurrency,
TextTooltip,
TokenBalance,
} from 'components/common'
import { MARS_DECIMALS, MARS_SYMBOL, VAULT_DEPOSIT_BUFFER } from 'constants/appConstants'
@@ -214,11 +214,11 @@ export const BreakdownTable = (props: Props) => {
<div className={styles.stats}>
<div className={styles.apy}>
<span className='faded'>{t('common.apy')}: </span>
<Tippy content={<Apy apyData={apyData} leverage={currentLeverage} />}>
<span className='tooltip'>
<AnimatedNumber amount={apy} suffix='%' abbreviated={false} />
</span>
</Tippy>
<TextTooltip
hideStyling
text={<AnimatedNumber amount={apy} suffix='%' abbreviated={false} />}
tooltip={<Apy apyData={apyData} leverage={currentLeverage} />}
/>
</div>
<div className={styles.price}>
<span className='faded'>{formatValue(1, 0, 0, false, false, ' OSMO ≈ ')}</span>
@@ -12,7 +12,7 @@
.td {
.wrapper {
@include padding(6, 0, 0);
@include padding(3, 0, 0);
display: flex;
flex-wrap: wrap;
justify-content: center;
@@ -1,10 +1,9 @@
import { Row } from '@tanstack/react-table'
import Tippy from '@tippyjs/react/headless'
import classNames from 'classnames/bind'
import { Button, SVG } from 'components/common'
import { Button, SVG, TextTooltip } from 'components/common'
import { getSwapUrl } from 'functions'
import { balanceSum } from 'libs/assetInfo'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useTranslation } from 'react-i18next'
import useStore from 'store'
@@ -17,9 +16,11 @@ interface Props {
export const ActionsRow = ({ row, type }: Props) => {
const { t } = useTranslation()
const router = useRouter()
const chainInfo = useStore((s) => s.chainInfo)
const redBankAssets = useStore((s) => s.redBankAssets)
const hasBalance = Number(row.original.walletBalance ?? 0) > 0
const hasDeposits = Number(row.original.depositBalance ?? 0) > 0
const hasNeverDeposited = Number(balanceSum(redBankAssets, 'depositBalanceBaseCurrency')) === 0
const appUrl = useStore((s) => s.networkConfig?.appUrl) || ''
@@ -32,7 +33,7 @@ export const ActionsRow = ({ row, type }: Props) => {
return (
<tr key={row.id} className={trClasses} onClick={() => row.toggleExpanded()}>
<td key={row.id} className={styles.td} colSpan={10}>
<td key={row.id} className={styles.td} colSpan={7}>
<div className={styles.wrapper}>
{type === 'deposit' && (
<>
@@ -50,41 +51,35 @@ export const ActionsRow = ({ row, type }: Props) => {
size='small'
text={t('common.buy')}
/>
<Tippy
appendTo={() => document.body}
interactive={false}
render={(attrs) => {
return hasBalance ? null : (
<div className='tippyContainer' {...attrs}>
{t('redbank.toDepositAssetOnChain', {
asset: assetSymbol,
chain: chainInfo?.name,
})}
</div>
)
}}
>
<div>
<Link href={`/redbank/deposit/${assetSymbol}`} passHref>
<Button
color='tertiary'
disabled={!hasBalance}
prefix={<SVG.Deposit />}
size='small'
text={t('redbank.deposit')}
/>
</Link>
</div>
</Tippy>
{hasDeposits && (
<Link href={`/redbank/withdraw/${assetSymbol}`} passHref>
<TextTooltip
hideUnderline
text={
<Button
color='tertiary'
prefix={<SVG.Withdraw />}
disabled={!hasBalance}
prefix={<SVG.Deposit />}
size='small'
text={t('redbank.withdraw')}
text={t('redbank.deposit')}
onClick={() => router.push(`/redbank/deposit/${assetSymbol}`)}
/>
</Link>
}
tooltip={
hasBalance
? null
: t('redbank.toDepositAssetOnChain', {
asset: assetSymbol,
chain: chainInfo?.name,
})
}
/>
{hasDeposits && (
<Button
color='tertiary'
prefix={<SVG.Withdraw />}
size='small'
text={t('redbank.withdraw')}
onClick={() => router.push(`/redbank/withdraw/${assetSymbol}`)}
/>
)}
</>
)}
@@ -108,60 +103,48 @@ export const ActionsRow = ({ row, type }: Props) => {
text={t('common.buy')}
/>
)}
<Tippy
appendTo={() => document.body}
interactive={false}
render={(attrs) => {
return !hasBalance || hasNeverDeposited ? (
<div className='tippyContainer' {...attrs}>
{hasBalance
? t('redbank.warning.borrow')
: t('redbank.noFundsForRepay', {
symbol: assetSymbol,
})}
</div>
) : null
}}
>
<div>
<Link href={`/redbank/repay/${assetSymbol}`} passHref>
<Button
disabled={!hasBalance}
color='tertiary'
prefix={<SVG.Deposit />}
size='small'
text={t('common.repay')}
/>
</Link>
</div>
</Tippy>
<TextTooltip
hideUnderline
text={
<Button
disabled={!hasBalance}
color='tertiary'
prefix={<SVG.Deposit />}
size='small'
text={t('common.repay')}
onClick={() => router.push(`/redbank/repay/${assetSymbol}`)}
/>
}
tooltip={
!hasBalance
? t('redbank.noFundsForRepay', {
symbol: assetSymbol,
})
: null
}
/>
</>
)}
<Tippy
appendTo={() => document.body}
interactive={false}
render={(attrs) => {
return row.original.marketLiquidity === '0' || hasNeverDeposited ? (
<div className='tippyContainer' {...attrs}>
{hasNeverDeposited
? t('redbank.warning.borrow')
: t('redbank.notEnoughMarketLiquidity')}
</div>
) : null
}}
>
<div>
<Link href={`/redbank/borrow/${assetSymbol}`} passHref>
<Button
color='tertiary'
prefix={<SVG.Withdraw />}
disabled={row.original.marketLiquidity === '0' || hasNeverDeposited}
size='small'
text={t('common.borrow')}
/>
</Link>
</div>
</Tippy>
<TextTooltip
hideUnderline
text={
<Button
color='tertiary'
prefix={<SVG.Withdraw />}
disabled={row.original.marketLiquidity === '0' || hasNeverDeposited}
size='small'
text={t('common.borrow')}
onClick={() => router.push(`/redbank/borrow/${assetSymbol}`)}
/>
}
tooltip={
row.original.marketLiquidity === '0' || hasNeverDeposited
? hasNeverDeposited
? t('redbank.warning.borrow')
: t('redbank.notEnoughMarketLiquidity')
: null
}
/>
</>
)}
</div>
@@ -30,14 +30,6 @@
@include bgTableHover;
}
}
> .td {
border-bottom: 1px solid $alphaWhite20;
&:nth-child(1),
&:nth-child(2) {
border-bottom: none;
}
}
}
.td {
@@ -14,6 +14,7 @@
@include padding(4, 0);
font-weight: $fontWeightRegular;
opacity: 0.6;
white-space: nowrap;
&:not(.disabled) {
&.canSort {
@@ -24,7 +25,11 @@
.wrapper {
display: flex;
align-items: center;
justify-content: center;
justify-content: flex-end;
&.left {
justify-content: center;
}
svg {
display: none;
@@ -52,14 +57,13 @@
}
.wrapper {
justify-content: flex-end;
svg {
display: block;
}
&.left {
flex-direction: row-reverse;
justify-content: flex-end;
}
}
}
@@ -37,7 +37,7 @@ export const MetricsRow = ({ row, type }: Props) => {
return (
<tr key={row.id} className={trClasses} onClick={() => row.toggleExpanded()}>
<td key={row.id} className={styles.td} colSpan={10}>
<td key={row.id} className={styles.td} colSpan={7}>
<div className={styles.wrapper}>
<div className={styles.body}>
<ValueWithLabel
@@ -1,7 +1,8 @@
import { ColumnDef, createColumnHelper } from '@tanstack/react-table'
import { AnimatedNumber, Button, CellAmount, SVG } from 'components/common'
import { AnimatedNumber, Button, CellAmount, SVG, TextTooltip } from 'components/common'
import Image from 'next/image'
import { useMemo } from 'react'
import { isMobile, isTablet } from 'react-device-detect'
import { useTranslation } from 'react-i18next'
import styles from './useBorrowColumns.module.scss'
@@ -9,6 +10,8 @@ import styles from './useBorrowColumns.module.scss'
export const useBorrowColumns = () => {
const { t } = useTranslation()
const columnHelper = createColumnHelper<RedBankAsset>()
const enableSorting = !isMobile && !isTablet
const defaultBorrowColumns: ColumnDef<RedBankAsset, any>[] = useMemo(
() => [
columnHelper.accessor('color', {
@@ -32,7 +35,10 @@ export const useBorrowColumns = () => {
),
}),
columnHelper.accessor('name', {
header: t('common.asset'),
enableSorting: enableSorting,
header: () => (
<TextTooltip text={t('common.asset')} tooltip={t('redbank.tooltips.borrow.assets')} />
),
id: 'name',
cell: (info) => (
<>
@@ -42,7 +48,13 @@ export const useBorrowColumns = () => {
),
}),
columnHelper.accessor('borrowBalance', {
header: t('common.borrowed'),
enableSorting: enableSorting,
header: () => (
<TextTooltip
text={t('common.borrowed')}
tooltip={t('redbank.tooltips.borrow.borrowed')}
/>
),
cell: (info) => (
<CellAmount
amount={Number(info.row.original.borrowBalance)}
@@ -53,7 +65,11 @@ export const useBorrowColumns = () => {
),
}),
columnHelper.accessor('borrowRate', {
header: t('common.rate'),
enableSorting: enableSorting,
header: () => (
<TextTooltip text={t('common.rate')} tooltip={t('redbank.tooltips.borrow.rate')} />
),
cell: (info) => {
return (
<AnimatedNumber
@@ -67,7 +83,13 @@ export const useBorrowColumns = () => {
},
}),
columnHelper.accessor('marketLiquidity', {
header: t('common.marketLiquidityShort'),
enableSorting: enableSorting,
header: () => (
<TextTooltip
text={t('common.marketLiquidityShort')}
tooltip={t('redbank.tooltips.borrow.marketLiquidity')}
/>
),
cell: (info) => (
<CellAmount
amount={Number(info.row.original.marketLiquidity)}
@@ -1,11 +1,11 @@
import { ColumnDef, createColumnHelper } from '@tanstack/react-table'
import Tippy from '@tippyjs/react'
import classNames from 'classnames'
import { AnimatedNumber, Apr, Button, CellAmount, SVG } from 'components/common'
import { AnimatedNumber, Apr, Button, CellAmount, SVG, TextTooltip } from 'components/common'
import { convertPercentage } from 'functions'
import { formatValue } from 'libs/parse'
import Image from 'next/image'
import { useMemo } from 'react'
import { isMobile, isTablet } from 'react-device-detect'
import { useTranslation } from 'react-i18next'
import styles from './useDepositColumns.module.scss'
@@ -14,6 +14,8 @@ export const useDepositColumns = () => {
const { t } = useTranslation()
const columnHelper = createColumnHelper<RedBankAsset>()
const enableSorting = !isMobile && !isTablet
const defaultDepositColumns: ColumnDef<RedBankAsset, any>[] = useMemo(() => {
return [
columnHelper.accessor('color', {
@@ -37,7 +39,10 @@ export const useDepositColumns = () => {
),
}),
columnHelper.accessor('name', {
header: t('common.asset'),
enableSorting: enableSorting,
header: () => (
<TextTooltip text={t('common.asset')} tooltip={t('redbank.tooltips.deposit.assets')} />
),
id: 'name',
cell: (info) => (
<>
@@ -47,7 +52,13 @@ export const useDepositColumns = () => {
),
}),
columnHelper.accessor('depositBalance', {
header: t('common.deposited'),
enableSorting: enableSorting,
header: () => (
<TextTooltip
text={t('common.deposited')}
tooltip={t('redbank.tooltips.deposit.deposited')}
/>
),
cell: (info) => {
return (
<CellAmount
@@ -60,10 +71,14 @@ export const useDepositColumns = () => {
},
}),
columnHelper.accessor('apy', {
header: t('common.apy'),
enableSorting: enableSorting,
header: () => (
<TextTooltip text={t('common.apy')} tooltip={t('redbank.tooltips.deposit.apy')} />
),
cell: (info) => (
<Tippy content={<Apr data={info.row.original} />}>
<div>
<TextTooltip
hideStyling
text={
<AnimatedNumber
amount={info.getValue() + Number(info.row.original.incentiveInfo?.apy || 0)}
suffix='%'
@@ -71,13 +86,19 @@ export const useDepositColumns = () => {
rounded={false}
className='m'
/>
</div>
</Tippy>
}
tooltip={<Apr data={info.row.original} />}
/>
),
}),
columnHelper.accessor('depositCap', {
enableSorting: true,
header: t('redbank.depositCap'),
enableSorting: enableSorting,
header: () => (
<TextTooltip
text={t('redbank.depositCap')}
tooltip={t('redbank.tooltips.deposit.caps')}
/>
),
cell: ({ row }) => {
const depositLiquidity = Number(row.original.depositLiquidity)
const percent = convertPercentage((depositLiquidity / row.original.depositCap) * 100)
@@ -84,6 +84,9 @@
td {
display: table-cell;
}
td {
pointer-events: none;
}
}
}
}
@@ -1,7 +1,5 @@
import { Coin } from '@cosmjs/stargate'
import { Card, ConnectButton, SVG, Title } from 'components/common'
import { AssetTable, useBorrowColumns, useDepositColumns } from 'components/redbank'
import { findByDenom } from 'functions'
import { useEffect, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import useStore from 'store'
@@ -21,10 +19,7 @@ export const RedbankNotConnected = () => {
// STORE STATE
// ------------------
const whitelistedAssets = useStore((s) => s.whitelistedAssets)
const marketAssetLiquidity = useStore((s) => s.marketAssetLiquidity)
const marketInfo = useStore((s) => s.marketInfo)
const convertToBaseCurrency = useStore((s) => s.convertToBaseCurrency)
// ------------------
// LOCAL STATE
// ------------------
@@ -34,29 +29,24 @@ export const RedbankNotConnected = () => {
const dummyData: RedBankAsset[] = []
if (!whitelistedAssets?.length) return
whitelistedAssets.forEach((asset) => {
const reserveInfo = findByDenom(marketInfo, asset.denom)
const depositApy = reserveInfo?.liquidity_rate || 0
const borrowApy = reserveInfo?.borrow_rate || 0
const liquidity = findByDenom(marketAssetLiquidity, asset.denom) as Coin
dummyData.push({
...asset,
apy: depositApy * 100,
borrowRate: borrowApy * 100,
marketLiquidity: liquidity?.amount.toString() || '0',
apy: 0,
borrowRate: 0,
marketLiquidity: '0',
walletBalance: '0',
borrowBalance: '0',
depositBalance: '0',
isCollateral: true,
borrowBalanceBaseCurrency: 0,
depositBalanceBaseCurrency: 0,
depositCap: 100000000,
depositLiquidity: 1000000,
depositCap: 0,
depositLiquidity: 0,
})
})
setDummyData(dummyData)
}, [marketAssetLiquidity, marketInfo, convertToBaseCurrency, whitelistedAssets])
}, [convertToBaseCurrency, whitelistedAssets])
return (
<div className={styles.notConnected}>
@@ -86,14 +76,14 @@ export const RedbankNotConnected = () => {
<div className={styles.grids}>
<Card
title={t('redbank.depositMarkets')}
tooltip={t('redbank.redBankMarketsDepositedNotConnectedTooltip')}
tooltip={t('redbank.tooltips.deposit.market.unconnected')}
>
<AssetTable columns={defaultDepositColumns} data={dummyData} disabled type='deposit' />
</Card>
<Card
title={t('redbank.borrowMarkets')}
tooltip={t('redbank.redbankMarketsBorrowedNotConnectedTooltip')}
tooltip={t('redbank.tooltips.borrow.market.unconnected')}
>
<AssetTable columns={defaultBorrowColumns} data={dummyData} disabled type='borrow' />
</Card>