mirror of
https://github.com/cerc-io/mars-interface.git
synced 2024-12-22 20:27:44 +00:00
releave v.1.4.0
This commit is contained in:
parent
d028d61a11
commit
6b86879fad
@ -7,7 +7,7 @@ import {
|
||||
WalletConnectionStatus,
|
||||
} from '@marsprotocol/wallet-connector'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { MARS_SYMBOL, USDC_SYMBOL } from 'constants/appConstants'
|
||||
import { MARS_SYMBOL } from 'constants/appConstants'
|
||||
import { IS_TESTNET } from 'constants/env'
|
||||
import {
|
||||
useBlockHeight,
|
||||
@ -155,7 +155,6 @@ export const CommonContainer = ({ children }: CommonContainerProps) => {
|
||||
useUserDebt()
|
||||
useMarsOracle()
|
||||
useSpotPrice(MARS_SYMBOL)
|
||||
useSpotPrice(USDC_SYMBOL)
|
||||
useDepositAndDebt()
|
||||
useRedBank()
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Coin } from '@cosmjs/stargate'
|
||||
import { AnimatedNumber } from 'components/common'
|
||||
import { useEffect, useState } from 'react'
|
||||
import useStore from 'store'
|
||||
|
||||
interface Props {
|
||||
@ -20,7 +21,15 @@ export const DisplayCurrency = ({
|
||||
const networkConfig = useStore((s) => s.networkConfig)
|
||||
const convertToDisplayCurrency = useStore((s) => s.convertToDisplayCurrency)
|
||||
const amount = convertToDisplayCurrency(coin)
|
||||
const displayCurrency = networkConfig?.displayCurrency
|
||||
const [displayCurrency, setDisplayCurrency] = useState<DisplayCurrency>(
|
||||
networkConfig?.displayCurrency,
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!networkConfig) return
|
||||
if (displayCurrency.denom !== networkConfig?.displayCurrency.denom)
|
||||
setDisplayCurrency(networkConfig?.displayCurrency)
|
||||
}, [networkConfig?.displayCurrency, displayCurrency.denom, networkConfig])
|
||||
|
||||
if (!displayCurrency) return null
|
||||
|
||||
|
@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
import { DocURL } from 'types/enums/docURL'
|
||||
|
||||
import { version } from '../../../../package.json'
|
||||
import packageInfo from '../../../../package.json'
|
||||
import styles from './Footer.module.scss'
|
||||
|
||||
export const Footer = () => {
|
||||
@ -211,7 +211,7 @@ export const Footer = () => {
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.version}>
|
||||
<p className='faded xs'>Mars Protocol v{version}</p>
|
||||
<p className='faded xs'>Mars Protocol v{packageInfo.version}</p>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
@ -18,6 +18,10 @@
|
||||
outline: none;
|
||||
background: $alphaBlack10;
|
||||
|
||||
.marsAmount {
|
||||
margin: 0 space(1);
|
||||
}
|
||||
|
||||
svg {
|
||||
margin-top: space(-0.5);
|
||||
height: rem-calc(19);
|
||||
|
@ -153,13 +153,15 @@ export const IncentivesButton = () => {
|
||||
}}
|
||||
>
|
||||
<SVG.Logo />
|
||||
<DisplayCurrency
|
||||
className={styles.balance}
|
||||
coin={{
|
||||
amount: unclaimedRewards,
|
||||
denom: marsDenom,
|
||||
}}
|
||||
/>
|
||||
<span>
|
||||
<AnimatedNumber
|
||||
amount={Number(unclaimedRewards) / 1e6}
|
||||
minDecimals={2}
|
||||
maxDecimals={2}
|
||||
className={styles.marsAmount}
|
||||
/>
|
||||
{MARS_SYMBOL}
|
||||
</span>
|
||||
</button>
|
||||
|
||||
{showDetails && (
|
||||
|
@ -43,6 +43,17 @@
|
||||
flex: 0 0 100%;
|
||||
flex-wrap: wrap;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.select {
|
||||
border-radius: $borderRadiusS;
|
||||
border: rem-calc(1) solid $alphaBlack20;
|
||||
@include padding(1, 2);
|
||||
color: $colorSecondaryDark;
|
||||
background-color: $fontColorLightPrimary;
|
||||
outline: none;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.name {
|
||||
@include margin(1, 0);
|
||||
@ -62,12 +73,16 @@
|
||||
}
|
||||
}
|
||||
|
||||
&.reduceMotion {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.content {
|
||||
@include margin(1, 0);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex: 1;
|
||||
justify-content: flex-end;
|
||||
justify-content: space-between;
|
||||
gap: space(2);
|
||||
|
||||
.button {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { useWalletManager, WalletConnectionStatus } from '@marsprotocol/wallet-connector'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import classNames from 'classnames'
|
||||
import { Button, NumberInput, SVG, Toggle, Tooltip } from 'components/common'
|
||||
@ -12,15 +13,39 @@ import styles from './Settings.module.scss'
|
||||
export const Settings = () => {
|
||||
const { t } = useTranslation()
|
||||
const inputPlaceholder = '...'
|
||||
|
||||
const queryClient = useQueryClient()
|
||||
const slippages = [0.02, 0.03]
|
||||
const [showDetails, setShowDetails] = useState(false)
|
||||
const slippage = useStore((s) => s.slippage)
|
||||
const networkConfig = useStore((s) => s.networkConfig)
|
||||
const baseCurrency = useStore((s) => s.baseCurrency)
|
||||
const whitelistedAssets = useStore((s) => s.whitelistedAssets)
|
||||
const otherAssets = useStore((s) => s.otherAssets)
|
||||
const assets: Asset[] = [...whitelistedAssets, ...otherAssets]
|
||||
const [customSlippage, setCustomSlippage] = useState<string>(inputPlaceholder)
|
||||
const [inputRef, setInputRef] = useState<React.RefObject<HTMLInputElement>>()
|
||||
const [isCustom, setIsCustom] = useState(false)
|
||||
const enableAnimations = useStore((s) => s.enableAnimations)
|
||||
const { status } = useWalletManager()
|
||||
const exchangeRates = useStore((s) => s.exchangeRates)
|
||||
const [displayCurrency, setDisplayCurrency] = useState<DisplayCurrency>(() => {
|
||||
const currency = {
|
||||
denom: baseCurrency.denom,
|
||||
prefix: '',
|
||||
suffix: baseCurrency.symbol,
|
||||
decimals: 2,
|
||||
}
|
||||
const currentCurrency = assets.find(
|
||||
(asset) => asset.denom === networkConfig?.displayCurrency.denom,
|
||||
)
|
||||
|
||||
if (currentCurrency) {
|
||||
currency.denom = currentCurrency.denom
|
||||
currency.prefix = ''
|
||||
currency.suffix = currentCurrency.symbol
|
||||
}
|
||||
return currency
|
||||
})
|
||||
|
||||
const onInputChange = (value: number) => {
|
||||
setCustomSlippage(value.toString())
|
||||
@ -57,6 +82,24 @@ export const Settings = () => {
|
||||
localStorage.setItem('enableAnimations', reduce ? 'false' : 'true')
|
||||
}
|
||||
|
||||
const changeDisplayCurrency = (denom: string) => {
|
||||
const selectedAsset = assets.find((asset) => asset.denom === denom)
|
||||
if (!selectedAsset || !networkConfig || !exchangeRates?.length) return
|
||||
const newDisplayCurrency = {
|
||||
denom: selectedAsset.denom,
|
||||
prefix: '',
|
||||
suffix: selectedAsset.symbol,
|
||||
decimals: 2,
|
||||
}
|
||||
const exchangeRate = exchangeRates.find((rate) => rate.denom === newDisplayCurrency.denom)
|
||||
if (!exchangeRate) return
|
||||
setDisplayCurrency(newDisplayCurrency)
|
||||
useStore.setState({ networkConfig: { ...networkConfig, displayCurrency: newDisplayCurrency } })
|
||||
useStore.setState({ baseToDisplayCurrencyRatio: 1 / Number(exchangeRate.amount) })
|
||||
localStorage.setItem('displayCurrency', JSON.stringify(newDisplayCurrency))
|
||||
queryClient.invalidateQueries()
|
||||
}
|
||||
|
||||
if (status !== WalletConnectionStatus.Connected) return null
|
||||
|
||||
return (
|
||||
@ -75,7 +118,7 @@ export const Settings = () => {
|
||||
<p className={styles.text}>{t('common.settings')}</p>
|
||||
</div>
|
||||
<div className={styles.settings}>
|
||||
<div className={styles.setting}>
|
||||
<div className={`${styles.setting} ${styles.reduceMotion}`}>
|
||||
<div className={styles.name}>
|
||||
{t('common.reduceMotion')}
|
||||
<Tooltip content={t('common.tooltips.reduceMotion')} className={styles.tooltip} />
|
||||
@ -88,6 +131,31 @@ export const Settings = () => {
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles.setting}>
|
||||
<div className={styles.name}>
|
||||
{t('common.displayCurrency')}
|
||||
<Tooltip
|
||||
content={t('common.tooltips.displayCurrency', {
|
||||
baseCurrencySymbol: baseCurrency.symbol,
|
||||
})}
|
||||
className={styles.tooltip}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.content}>
|
||||
<select
|
||||
onChange={(e) => changeDisplayCurrency(e.target.value)}
|
||||
className={classNames([styles.select, 's'])}
|
||||
tabIndex={2}
|
||||
value={displayCurrency.denom}
|
||||
>
|
||||
{assets.map((currency) => (
|
||||
<option key={currency.denom} value={currency.denom}>
|
||||
{`${currency.name} (${currency.symbol})`}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{FIELDS_FEATURE && (
|
||||
<>
|
||||
|
@ -1,4 +1,5 @@
|
||||
import Tippy from '@tippyjs/react'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import styles from './TextTooltip.module.scss'
|
||||
|
||||
@ -7,6 +8,7 @@ interface Props {
|
||||
tooltip: string | React.ReactNode
|
||||
hideUnderline?: boolean
|
||||
hideStyling?: boolean
|
||||
className?: string
|
||||
}
|
||||
export const TextTooltip = (props: Props) => {
|
||||
return (
|
||||
@ -23,7 +25,13 @@ export const TextTooltip = (props: Props) => {
|
||||
)
|
||||
}}
|
||||
>
|
||||
<span className={props.hideUnderline ? styles.pointer : styles.tooltip} style={{}}>
|
||||
<span
|
||||
className={classNames(
|
||||
props.hideUnderline ? styles.pointer : styles.tooltip,
|
||||
props.className,
|
||||
)}
|
||||
style={{}}
|
||||
>
|
||||
{props.text}
|
||||
</span>
|
||||
</Tippy>
|
||||
|
@ -66,7 +66,7 @@ export const Tutorial = (props: Props) => {
|
||||
}
|
||||
|
||||
const maxLeverage = props.availableVault
|
||||
? formatValue(ltvToLeverage(props.availableVault?.ltv.max), 2, 2)
|
||||
? formatValue(ltvToLeverage(props.availableVault?.ltv.contract), 2, 2)
|
||||
: ''
|
||||
|
||||
const content = (
|
||||
|
@ -15,11 +15,16 @@ export const EditContent = (props: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const convertValueToAmount = useStore((s) => s.convertValueToAmount)
|
||||
|
||||
const borrowKey =
|
||||
props.position.borrowDenom === props.vault.denoms.primary
|
||||
? 'borrowedPrimary'
|
||||
: 'borrowedSecondary'
|
||||
|
||||
const primaryAmount = props.position.amounts.primary - (props.prevPosition?.amounts.primary || 0)
|
||||
const secondaryAmount =
|
||||
props.position.amounts.secondary - (props.prevPosition?.amounts.secondary || 0)
|
||||
const borrowedAmount =
|
||||
props.position.amounts.borrowed - (props.prevPosition?.amounts.borrowed || 0)
|
||||
props.position.amounts[borrowKey] - (props.prevPosition?.amounts[borrowKey] || 0)
|
||||
|
||||
const depositPrimary = (
|
||||
<TokenBalance
|
||||
@ -43,10 +48,10 @@ export const EditContent = (props: Props) => {
|
||||
/>
|
||||
)
|
||||
|
||||
const borrowSecondary = (
|
||||
const borrow = (
|
||||
<TokenBalance
|
||||
coin={{
|
||||
denom: props.vault.denoms.secondary,
|
||||
denom: props.position.borrowDenom || props.vault.denoms.secondary,
|
||||
amount: borrowedAmount.toString(),
|
||||
}}
|
||||
className={styles.marginRight}
|
||||
@ -78,14 +83,14 @@ export const EditContent = (props: Props) => {
|
||||
return (
|
||||
<li>
|
||||
<span className={styles.marginRight}>{t('redbank.borrow')}</span>
|
||||
{borrowSecondary}
|
||||
{borrow}
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
const getSwapMessage = () => {
|
||||
const primaryValue = props.position.values.primary
|
||||
const secondaryValue = props.position.values.secondary + props.position.values.borrowed
|
||||
const primaryValue = props.position.values.primary + props.position.values.borrowedPrimary
|
||||
const secondaryValue = props.position.values.secondary + props.position.values.borrowedSecondary
|
||||
const difference = Math.abs(primaryValue - secondaryValue)
|
||||
if (difference < SWAP_THRESHOLD) return null
|
||||
|
||||
|
@ -15,14 +15,21 @@ export const UnlockContent = (props: Props) => {
|
||||
<>
|
||||
<li>{t('fields.removeLiquidity', { vault: props.vault.provider })}</li>
|
||||
<li>
|
||||
<span className={styles.marginRight}>{t('redbank.repay')}</span>
|
||||
<TokenBalance
|
||||
coin={{
|
||||
denom: props.vault.denoms.secondary,
|
||||
amount: props.position.amounts.borrowed.toString(),
|
||||
}}
|
||||
showSymbol
|
||||
/>
|
||||
{props.position.borrowDenom && (
|
||||
<>
|
||||
<span className={styles.marginRight}>{t('redbank.repay')}</span>
|
||||
<TokenBalance
|
||||
coin={{
|
||||
denom: props.position.borrowDenom,
|
||||
amount: Math.max(
|
||||
props.position.amounts.borrowedPrimary,
|
||||
props.position.amounts.borrowedSecondary,
|
||||
).toString(),
|
||||
}}
|
||||
showSymbol
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
<span className={styles.marginRight}>{t('redbank.withdraw')}</span>
|
||||
|
@ -123,7 +123,10 @@ export const ActiveVaultsTableMobile = () => {
|
||||
<DisplayCurrency
|
||||
coin={{
|
||||
denom: baseCurrency.denom,
|
||||
amount: vault.position.values.borrowed.toString(),
|
||||
amount: (vault.position.borrowDenom === vault.denoms.primary
|
||||
? vault.position.amounts.borrowedPrimary
|
||||
: vault.position.amounts.borrowedSecondary
|
||||
).toString(),
|
||||
}}
|
||||
className={styles.inline}
|
||||
/>
|
||||
@ -136,9 +139,13 @@ export const ActiveVaultsTableMobile = () => {
|
||||
<div className={styles.borrowCapacity}>
|
||||
<BorrowCapacity
|
||||
showPercentageText={true}
|
||||
max={getLiqBorrowValue(vault, maxBorrowValue)}
|
||||
max={getLiqBorrowValue(vault, vault.position.values.net)}
|
||||
limit={maxBorrowValue}
|
||||
balance={vault.position.values.borrowed}
|
||||
balance={
|
||||
vault.position.borrowDenom === vault.denoms.primary
|
||||
? vault.position.values.borrowedPrimary
|
||||
: vault.position.values.borrowedSecondary
|
||||
}
|
||||
showTitle={false}
|
||||
barHeight={'16px'}
|
||||
hideValues
|
||||
|
@ -75,13 +75,16 @@ export const useActiveVaultsColumns = () => {
|
||||
cell: ({ row }) => {
|
||||
const primaryCoin = {
|
||||
denom: row.original.denoms.primary,
|
||||
amount: row.original.position.amounts.primary.toString(),
|
||||
amount: (
|
||||
row.original.position.amounts.primary + row.original.position.amounts.borrowedPrimary
|
||||
).toString(),
|
||||
}
|
||||
|
||||
const secondaryCoin = {
|
||||
denom: row.original.denoms.secondary,
|
||||
amount: (
|
||||
row.original.position.amounts.secondary + row.original.position.amounts.borrowed
|
||||
row.original.position.amounts.secondary +
|
||||
row.original.position.amounts.borrowedSecondary
|
||||
).toString(),
|
||||
}
|
||||
|
||||
@ -97,9 +100,13 @@ export const useActiveVaultsColumns = () => {
|
||||
}
|
||||
tooltip={
|
||||
<>
|
||||
<TokenBalance coin={primaryCoin} maxDecimals={2} showSymbol />
|
||||
{Number(primaryCoin.amount) > 0 && (
|
||||
<TokenBalance coin={primaryCoin} maxDecimals={2} showSymbol />
|
||||
)}
|
||||
<br />
|
||||
<TokenBalance coin={secondaryCoin} maxDecimals={2} showSymbol />
|
||||
{Number(secondaryCoin.amount) > 0 && (
|
||||
<TokenBalance coin={secondaryCoin} maxDecimals={2} showSymbol />
|
||||
)}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
@ -134,41 +141,50 @@ export const useActiveVaultsColumns = () => {
|
||||
}
|
||||
tooltip={
|
||||
<>
|
||||
<TokenBalance coin={coins[0]} maxDecimals={2} showSymbol />
|
||||
{Number(coins[0].amount) > 0 && (
|
||||
<TokenBalance coin={coins[0]} maxDecimals={2} showSymbol />
|
||||
)}
|
||||
<br />
|
||||
<TokenBalance coin={coins[1]} maxDecimals={2} showSymbol />
|
||||
{Number(coins[1].amount) > 0 && (
|
||||
<TokenBalance coin={coins[1]} maxDecimals={2} showSymbol />
|
||||
)}{' '}
|
||||
</>
|
||||
}
|
||||
/>
|
||||
)
|
||||
},
|
||||
}),
|
||||
columnHelper.accessor('position.values.borrowed', {
|
||||
columnHelper.accessor('position.values.borrowedPrimary', {
|
||||
enableSorting: true,
|
||||
header: () => (
|
||||
<TextTooltip text={t('common.borrowed')} tooltip={t('fields.tooltips.borrowValue')} />
|
||||
),
|
||||
cell: (info) => {
|
||||
cell: ({ row }) => {
|
||||
const borrowAsset = whitelistedAssets.find(
|
||||
(asset) => asset.denom === info.row.original.denoms.secondary,
|
||||
(asset) => asset.denom === row.original.position.borrowDenom,
|
||||
)
|
||||
if (!borrowAsset) return
|
||||
|
||||
const borrowKey =
|
||||
row.original.position.borrowDenom === row.original.denoms.primary
|
||||
? 'borrowedPrimary'
|
||||
: 'borrowedSecondary'
|
||||
|
||||
return (
|
||||
<TextTooltip
|
||||
text={
|
||||
<DisplayCurrency
|
||||
coin={{
|
||||
denom: baseCurrency.denom,
|
||||
amount: info.row.original.position.values.borrowed.toString(),
|
||||
amount: row.original.position.values[borrowKey].toString(),
|
||||
}}
|
||||
/>
|
||||
}
|
||||
tooltip={
|
||||
<TokenBalance
|
||||
coin={{
|
||||
denom: info.row.original.denoms.secondary,
|
||||
amount: info.row.original.position.amounts.borrowed.toString(),
|
||||
denom: borrowAsset.denom,
|
||||
amount: row.original.position.amounts[borrowKey].toString(),
|
||||
}}
|
||||
maxDecimals={2}
|
||||
showSymbol
|
||||
@ -291,7 +307,7 @@ export const useActiveVaultsColumns = () => {
|
||||
</p>
|
||||
<p className='s faded'>
|
||||
{formatValue(
|
||||
ltvToLeverage(row.original.ltv.max),
|
||||
ltvToLeverage(row.original.ltv.contract),
|
||||
2,
|
||||
2,
|
||||
false,
|
||||
@ -303,7 +319,7 @@ export const useActiveVaultsColumns = () => {
|
||||
)
|
||||
},
|
||||
}),
|
||||
columnHelper.accessor('position.amounts.borrowed', {
|
||||
columnHelper.accessor('position.amounts.borrowedPrimary', {
|
||||
enableSorting: false,
|
||||
header: () => (
|
||||
<TextTooltip
|
||||
@ -313,13 +329,19 @@ export const useActiveVaultsColumns = () => {
|
||||
),
|
||||
cell: ({ row }) => {
|
||||
const maxBorrowValue = getMaxBorrowValue(row.original, row.original.position)
|
||||
const borrowKey =
|
||||
row.original.position.borrowDenom === row.original.denoms.primary
|
||||
? 'borrowedPrimary'
|
||||
: 'borrowedSecondary'
|
||||
|
||||
const liqBorrowValue = getLiqBorrowValue(row.original, row.original.position.values.net)
|
||||
|
||||
return (
|
||||
<BorrowCapacity
|
||||
showPercentageText={true}
|
||||
max={getLiqBorrowValue(row.original, maxBorrowValue)}
|
||||
max={liqBorrowValue}
|
||||
limit={maxBorrowValue}
|
||||
balance={row.original.position.values.borrowed}
|
||||
balance={row.original.position.values[borrowKey]}
|
||||
showTitle={false}
|
||||
barHeight={'16px'}
|
||||
hideValues
|
||||
|
@ -24,11 +24,20 @@ export const AvailableVaultsTableMobile = () => {
|
||||
>
|
||||
<div className={styles.container}>
|
||||
{availableVaults.map((vault, i) => {
|
||||
const borrowAsset = redBankAssets.find((asset) => asset.denom === vault.denoms.secondary)
|
||||
const maxBorrowRate = Number(borrowAsset?.borrowRate ?? 0) * vault.ltv.max
|
||||
const primaryBorrowAsset = redBankAssets.find(
|
||||
(asset) => asset.denom === vault.denoms.primary,
|
||||
)
|
||||
const secondaryBorrowAsset = redBankAssets.find(
|
||||
(asset) => asset.denom === vault.denoms.secondary,
|
||||
)
|
||||
const borrowRate = Math.min(
|
||||
Number(primaryBorrowAsset?.borrowRate ?? 0),
|
||||
Number(secondaryBorrowAsset?.borrowRate ?? 0),
|
||||
)
|
||||
const maxBorrowRate = borrowRate * (ltvToLeverage(vault.ltv.contract) - 1)
|
||||
const minAPY = new BigNumber(vault.apy || 0).toNumber()
|
||||
|
||||
const leverage = ltvToLeverage(vault.ltv.max)
|
||||
const leverage = ltvToLeverage(vault.ltv.contract)
|
||||
const maxAPY =
|
||||
new BigNumber(minAPY).times(leverage).decimalPlaces(2).toNumber() - maxBorrowRate
|
||||
const apyDataNoLev = { total: vault.apy || 0, borrow: 0 }
|
||||
@ -60,7 +69,10 @@ export const AvailableVaultsTableMobile = () => {
|
||||
hideStyling
|
||||
text={<AnimatedNumber amount={maxAPY} suffix='%' />}
|
||||
tooltip={
|
||||
<Apy apyData={apyDataLev} leverage={ltvToLeverage(vault.ltv.max)} />
|
||||
<Apy
|
||||
apyData={apyDataLev}
|
||||
leverage={ltvToLeverage(vault.ltv.contract)}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</span>
|
||||
|
@ -69,7 +69,7 @@ export const useAvailableVaultsColumns = () => {
|
||||
return (
|
||||
<>
|
||||
<p className='m'>
|
||||
{formatValue(ltvToLeverage(row.original.ltv.max), 2, 2, false, false, 'x')}
|
||||
{formatValue(ltvToLeverage(row.original.ltv.contract), 2, 2, false, false, 'x')}
|
||||
</p>
|
||||
<p className='s faded'>{t('global.max_lower')}</p>
|
||||
</>
|
||||
@ -87,12 +87,20 @@ export const useAvailableVaultsColumns = () => {
|
||||
return <Loading />
|
||||
}
|
||||
|
||||
const maxLeverage = ltvToLeverage(row.original.ltv.max)
|
||||
const borrowAsset = redBankAssets.find(
|
||||
const maxLeverage = ltvToLeverage(row.original.ltv.contract)
|
||||
const primaryBorrowAsset = redBankAssets.find(
|
||||
(asset) => asset.denom === row.original.denoms.primary,
|
||||
)
|
||||
const secondaryBorrowAsset = redBankAssets.find(
|
||||
(asset) => asset.denom === row.original.denoms.secondary,
|
||||
)
|
||||
const maxBorrowRate =
|
||||
Number(borrowAsset?.borrowRate ?? 0) * (ltvToLeverage(row.original.ltv.max) - 1)
|
||||
|
||||
const borrowRate = Math.min(
|
||||
Number(primaryBorrowAsset?.borrowRate ?? 0),
|
||||
Number(secondaryBorrowAsset?.borrowRate ?? 0),
|
||||
)
|
||||
|
||||
const maxBorrowRate = borrowRate * (ltvToLeverage(row.original.ltv.contract) - 1)
|
||||
|
||||
const minAPY = new BigNumber(row.original.apy).toNumber()
|
||||
|
||||
@ -128,7 +136,7 @@ export const useAvailableVaultsColumns = () => {
|
||||
/>
|
||||
}
|
||||
tooltip={
|
||||
<Apy apyData={apyDataLev} leverage={ltvToLeverage(row.original.ltv.max)} />
|
||||
<Apy apyData={apyDataLev} leverage={ltvToLeverage(row.original.ltv.contract)} />
|
||||
}
|
||||
/>
|
||||
|
||||
|
@ -18,7 +18,11 @@ export const BreakdownGraph = (props: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const convertToDisplayCurrency = useStore((s) => s.convertToDisplayCurrency)
|
||||
const baseCurrency = useStore((s) => s.baseCurrency)
|
||||
const yAxisLimit = Math.max(props.position.values.net, props.position.values.borrowed)
|
||||
const borrowKey =
|
||||
props.position.borrowDenom === props.vault.denoms.primary
|
||||
? 'borrowedPrimary'
|
||||
: 'borrowedSecondary'
|
||||
const yAxisLimit = Math.max(props.position.values.net, props.position.values[borrowKey])
|
||||
|
||||
const containerClasses = classNames([
|
||||
styles.container,
|
||||
@ -40,7 +44,7 @@ export const BreakdownGraph = (props: Props) => {
|
||||
denom: props.vault.denoms.primary,
|
||||
}),
|
||||
convertToDisplayCurrency({
|
||||
amount: props.position.values.borrowed.toString(),
|
||||
amount: props.position.values[borrowKey].toString(),
|
||||
denom: props.vault.denoms.primary,
|
||||
}),
|
||||
],
|
||||
@ -123,7 +127,11 @@ export const BreakdownGraph = (props: Props) => {
|
||||
<div className={`${styles.bar3}`} style={{ height: `${getBarHeightPercentage(3)}%` }}>
|
||||
<AssetBar
|
||||
type='debt'
|
||||
symbol={props.vault.symbols.secondary}
|
||||
symbol={
|
||||
borrowKey === 'borrowedPrimary'
|
||||
? props.vault.symbols.primary
|
||||
: props.vault.symbols.secondary
|
||||
}
|
||||
height={getBarHeightPercentage(3)}
|
||||
showLabel={hasSpaceForLabel('debt')}
|
||||
/>
|
||||
|
@ -29,6 +29,10 @@
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
|
||||
td {
|
||||
min-width: space(12);
|
||||
}
|
||||
|
||||
tr {
|
||||
td:nth-child(2) {
|
||||
width: 20px;
|
||||
|
@ -47,10 +47,16 @@ export const BreakdownTable = (props: Props) => {
|
||||
|
||||
const primaryPrice = usePrice(props.vault.denoms.primary)
|
||||
const secondaryPrice = usePrice(props.vault.denoms.secondary)
|
||||
const primaryRedBankAsset = useRedBankAsset(props.vault.denoms.primary)
|
||||
const secondaryRedBankAsset = useRedBankAsset(props.vault.denoms.secondary)
|
||||
const primaryChange = props.newPosition.amounts.primary - props.prevPosition.amounts.primary
|
||||
const secondaryChange = props.newPosition.amounts.secondary - props.prevPosition.amounts.secondary
|
||||
const borrowedChange = props.newPosition.amounts.borrowed - props.prevPosition.amounts.borrowed
|
||||
const borrowKey =
|
||||
props.newPosition.borrowDenom === props.vault.denoms.primary
|
||||
? 'borrowedPrimary'
|
||||
: 'borrowedSecondary'
|
||||
const borrowedChange =
|
||||
props.newPosition.amounts[borrowKey] - props.prevPosition.amounts[borrowKey]
|
||||
|
||||
const containerClasses = classNames([
|
||||
props.className,
|
||||
@ -71,15 +77,15 @@ export const BreakdownTable = (props: Props) => {
|
||||
denom = props.vault.denoms.secondary
|
||||
break
|
||||
case AmountType.DEBT:
|
||||
amount = props.newPosition.amounts.borrowed
|
||||
amount = props.newPosition.amounts[borrowKey]
|
||||
denom = props.vault.denoms.secondary
|
||||
break
|
||||
case AmountType.POSITION_PRIMARY:
|
||||
amount = props.newPosition.amounts.primary
|
||||
amount = props.newPosition.amounts.primary + props.newPosition.amounts.borrowedPrimary
|
||||
denom = props.vault.denoms.primary
|
||||
break
|
||||
case AmountType.POSITION_SECONDARY:
|
||||
amount = props.newPosition.amounts.secondary + props.newPosition.amounts.borrowed
|
||||
amount = props.newPosition.amounts.secondary + props.newPosition.amounts.borrowedSecondary
|
||||
denom = props.vault.denoms.secondary
|
||||
break
|
||||
}
|
||||
@ -122,7 +128,9 @@ export const BreakdownTable = (props: Props) => {
|
||||
)
|
||||
}
|
||||
|
||||
const getValueText = (type: 'net' | 'borrowed' | 'total') => (
|
||||
const getValueText = (
|
||||
type: 'primary' | 'secondary' | 'net' | 'borrowedPrimary' | 'borrowedSecondary' | 'total',
|
||||
) => (
|
||||
<DisplayCurrency
|
||||
prefixClass='s faded'
|
||||
valueClass='m faded'
|
||||
@ -152,7 +160,8 @@ export const BreakdownTable = (props: Props) => {
|
||||
)
|
||||
}
|
||||
|
||||
const isReducingDebt = props.newPosition.amounts.borrowed < props.prevPosition.amounts.borrowed
|
||||
const isReducingDebt =
|
||||
props.newPosition.amounts[borrowKey] < props.prevPosition.amounts[borrowKey]
|
||||
if (isReducingDebt) {
|
||||
return (
|
||||
<>
|
||||
@ -208,8 +217,12 @@ export const BreakdownTable = (props: Props) => {
|
||||
/* APY CALCULATION */
|
||||
const currentLeverage = props.newPosition.currentLeverage
|
||||
|
||||
const trueBorrowRate =
|
||||
Number(secondaryRedBankAsset?.borrowRate ?? 0) * (Number(currentLeverage) - 1)
|
||||
const borrowRate = Number(
|
||||
borrowKey === 'borrowedPrimary'
|
||||
? primaryRedBankAsset?.borrowRate
|
||||
: secondaryRedBankAsset?.borrowRate,
|
||||
)
|
||||
const trueBorrowRate = borrowRate * (Number(currentLeverage) - 1)
|
||||
|
||||
const apy = (props.vault.apy || 0) * currentLeverage - trueBorrowRate
|
||||
|
||||
@ -291,9 +304,11 @@ export const BreakdownTable = (props: Props) => {
|
||||
<tr className={styles.debtRow}>
|
||||
<td className={`${styles.showDesktop} faded`}>{t('common.debt')}</td>
|
||||
<td className={styles.alignRight}>{getTokenBalance(AmountType.DEBT)}</td>
|
||||
<td>{secondaryAsset?.symbol}</td>
|
||||
<td>
|
||||
{borrowKey === 'borrowedPrimary' ? primaryAsset?.symbol : secondaryAsset?.symbol}
|
||||
</td>
|
||||
<td>{getChangeText(borrowedChange, 'secondary', true)}</td>
|
||||
<td>{getValueText('borrowed')}</td>
|
||||
<td>{getValueText(borrowKey)}</td>
|
||||
</tr>
|
||||
|
||||
<tr className={`${styles.labelRow} faded`}>
|
||||
@ -320,11 +335,14 @@ export const BreakdownTable = (props: Props) => {
|
||||
</tbody>
|
||||
</table>
|
||||
{!props.isRepay && <div className={styles.reduceMessage}>{getWarningMessage()}</div>}
|
||||
|
||||
<BorrowCapacity
|
||||
className={styles.borrowCapacity}
|
||||
limit={maxBorrowValue}
|
||||
max={getLiqBorrowValue(props.vault, maxBorrowValue)}
|
||||
balance={props.newPosition.values.borrowed}
|
||||
max={getLiqBorrowValue(props.vault, props.newPosition.values.net)}
|
||||
balance={
|
||||
props.newPosition.values.borrowedPrimary + props.newPosition.values.borrowedSecondary
|
||||
}
|
||||
barHeight={'24px'}
|
||||
showPercentageText
|
||||
/>
|
||||
|
@ -2,6 +2,7 @@ import classNames from 'classnames'
|
||||
import { Tutorial } from 'components/common'
|
||||
import { TokenInput } from 'components/fields'
|
||||
import { FIELDS_TUTORIAL_KEY } from 'constants/appConstants'
|
||||
import { useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import useStore from 'store'
|
||||
|
||||
@ -9,33 +10,106 @@ import styles from './BorrowInput.module.scss'
|
||||
|
||||
interface Props {
|
||||
vault: Vault
|
||||
borrowAmount: number
|
||||
borrowedPrimaryAmount: number
|
||||
borrowedSecondaryAmount: number
|
||||
maxAmount: number
|
||||
onChange: (amount: number) => void
|
||||
prevPosition?: Position
|
||||
onChangePrimary: (amount: number) => void
|
||||
onChangeSecondary: (amount: number) => void
|
||||
}
|
||||
|
||||
export const BorrowInput = (props: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const redBankAssets = useStore((s) => s.redBankAssets)
|
||||
const showTutorial = !localStorage.getItem(FIELDS_TUTORIAL_KEY)
|
||||
const asset = redBankAssets.find((asset) => asset.denom === props.vault.denoms.secondary)
|
||||
const primaryAsset = redBankAssets.find((asset) => asset.denom === props.vault.denoms.primary)
|
||||
const secondaryAsset = redBankAssets.find((asset) => asset.denom === props.vault.denoms.secondary)
|
||||
const containerClasses = classNames([styles.container])
|
||||
const input: Input = {
|
||||
visible: true,
|
||||
const [cachedPrimaryAmount, setCachedPrimaryAmount] = useState(props.borrowedPrimaryAmount)
|
||||
const [cachedSecondaryAmount, setCachedSecondaryAmount] = useState(props.borrowedSecondaryAmount)
|
||||
|
||||
const primaryInputVisisble =
|
||||
props.borrowedPrimaryAmount > 0 ||
|
||||
props.prevPosition?.borrowDenom === props.vault.denoms.primary
|
||||
? true
|
||||
: false
|
||||
|
||||
const [primaryInput, setPrimaryInput] = useState<Input>({
|
||||
visible: primaryInputVisisble,
|
||||
denom: props.vault.denoms.primary,
|
||||
symbol: props.vault.symbols.primary,
|
||||
})
|
||||
|
||||
const [secondaryInput, setSecondaryInput] = useState<Input>({
|
||||
visible: !primaryInputVisisble,
|
||||
denom: props.vault.denoms.secondary,
|
||||
symbol: props.vault.symbols.secondary,
|
||||
})
|
||||
|
||||
const selectInput = (symbol: string) => {
|
||||
if (symbol === primaryInput.symbol) {
|
||||
primaryInput.visible = true
|
||||
secondaryInput.visible = false
|
||||
setCachedSecondaryAmount(props.borrowedSecondaryAmount)
|
||||
props.onChangePrimary(cachedPrimaryAmount)
|
||||
} else {
|
||||
primaryInput.visible = false
|
||||
secondaryInput.visible = true
|
||||
setCachedPrimaryAmount(props.borrowedPrimaryAmount)
|
||||
props.onChangeSecondary(cachedSecondaryAmount)
|
||||
}
|
||||
|
||||
setPrimaryInput({ ...primaryInput })
|
||||
setSecondaryInput({ ...secondaryInput })
|
||||
}
|
||||
|
||||
const onChangePrimary = (amount: number) => {
|
||||
setCachedPrimaryAmount(amount)
|
||||
props.onChangePrimary(amount)
|
||||
}
|
||||
|
||||
const onChangeSecondary = (amount: number) => {
|
||||
setCachedSecondaryAmount(amount)
|
||||
props.onChangeSecondary(amount)
|
||||
}
|
||||
|
||||
const tokenInput = (
|
||||
<TokenInput
|
||||
input={input}
|
||||
amount={props.borrowAmount}
|
||||
maxAmount={props.maxAmount}
|
||||
maxAmountLabel={t('global.max')}
|
||||
onChange={props.onChange}
|
||||
tokens={[props.vault.symbols.secondary]}
|
||||
borrowRate={asset?.borrowRate}
|
||||
/>
|
||||
<>
|
||||
{primaryInput.visible && (
|
||||
<TokenInput
|
||||
input={primaryInput}
|
||||
amount={props.borrowedPrimaryAmount}
|
||||
onChange={onChangePrimary}
|
||||
tokens={
|
||||
props.prevPosition?.borrowDenom === props.vault.denoms.primary
|
||||
? [primaryInput.symbol]
|
||||
: [primaryInput.symbol, secondaryInput.symbol]
|
||||
}
|
||||
onSelect={selectInput}
|
||||
maxAmountLabel={t('global.max')}
|
||||
maxAmount={props.maxAmount}
|
||||
borrowRate={primaryAsset?.borrowRate}
|
||||
disableGasWarning
|
||||
/>
|
||||
)}
|
||||
{secondaryInput.visible && (
|
||||
<TokenInput
|
||||
input={secondaryInput}
|
||||
amount={props.borrowedSecondaryAmount}
|
||||
onChange={onChangeSecondary}
|
||||
tokens={
|
||||
props.prevPosition?.borrowDenom === props.vault.denoms.secondary
|
||||
? [secondaryInput.symbol]
|
||||
: [primaryInput.symbol, secondaryInput.symbol]
|
||||
}
|
||||
onSelect={selectInput}
|
||||
maxAmountLabel={t('global.max')}
|
||||
maxAmount={props.maxAmount}
|
||||
borrowRate={secondaryAsset?.borrowRate}
|
||||
disableGasWarning
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
return (
|
||||
|
@ -2,7 +2,7 @@ import BigNumber from 'bignumber.js'
|
||||
import classNames from 'classnames'
|
||||
import { InputSlider, Tutorial } from 'components/common'
|
||||
import { FIELDS_TUTORIAL_KEY } from 'constants/appConstants'
|
||||
import { formatValue, ltvToLeverage } from 'libs/parse'
|
||||
import { formatValue, leverageToLtv, ltvToLeverage } from 'libs/parse'
|
||||
import React from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import colors from 'styles/_assets.module.scss'
|
||||
@ -29,7 +29,7 @@ export const LeverageSlider = (props: Props) => {
|
||||
isLeverage
|
||||
value={props.leverage}
|
||||
maxValue={props.leverageMax}
|
||||
leverageMax={ltvToLeverage(props.vault.ltv.max)}
|
||||
leverageMax={ltvToLeverage(props.vault.ltv.contract)}
|
||||
leverageLimit={props.leverageLimit}
|
||||
onChange={props.onChange}
|
||||
sliderColor={colors.secondary}
|
||||
@ -51,8 +51,11 @@ export const LeverageSlider = (props: Props) => {
|
||||
) : (
|
||||
<>{slider}</>
|
||||
)}
|
||||
{leverageToLtv(props.leverage) > props.vault.ltv.max && (
|
||||
<span className={styles.warning}>{t('fields.messages.closeToMaxLtv')}</span>
|
||||
)}
|
||||
{props.leverage >= props.leverageLimit &&
|
||||
props.leverageLimit < ltvToLeverage(props.vault.ltv.max) && (
|
||||
props.leverageLimit < ltvToLeverage(props.vault.ltv.contract) && (
|
||||
<span className={styles.warning}>
|
||||
{t('fields.messages.unableToIncreaseLeverage', {
|
||||
leverage: formatValue(props.leverageLimit, 2, 2),
|
||||
|
@ -54,6 +54,6 @@
|
||||
@media only screen and (min-width: $bpMediumHigh) {
|
||||
.grid {
|
||||
grid-template-areas: 'supply leverage borrow';
|
||||
grid-template-columns: auto 2fr 1fr;
|
||||
grid-auto-columns: auto;
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,9 @@ export const PositionInput = (props: Props) => {
|
||||
const marketAssetLiquidity = useStore((s) => s.marketAssetLiquidity)
|
||||
const convertToBaseCurrency = useStore((s) => s.convertToBaseCurrency)
|
||||
const convertValueToAmount = useStore((s) => s.convertValueToAmount)
|
||||
const [maxAllowedLeverage, setMaxAllowedLeverage] = useState(ltvToLeverage(props.vault.ltv.max))
|
||||
const [maxAllowedLeverage, setMaxAllowedLeverage] = useState(
|
||||
ltvToLeverage(props.vault.ltv.contract),
|
||||
)
|
||||
const tutorialStep = useStore((s) => s.tutorialSteps['fields'])
|
||||
const showTutorial = !localStorage.getItem(FIELDS_TUTORIAL_KEY)
|
||||
|
||||
@ -33,13 +35,26 @@ export const PositionInput = (props: Props) => {
|
||||
denom: props.vault.denoms.secondary,
|
||||
amount: position.amounts.secondary.toString(),
|
||||
})
|
||||
const borrowValue = convertToBaseCurrency({
|
||||
denom: props.vault.denoms.secondary,
|
||||
amount: position.amounts.borrowed.toString(),
|
||||
const borrowedPrimaryValue = convertToBaseCurrency({
|
||||
denom: props.vault.denoms.primary,
|
||||
amount: position.amounts.borrowedPrimary.toString(),
|
||||
})
|
||||
position.values.borrowed = borrowValue
|
||||
position.values.total = borrowValue + primaryValue + secondaryValue
|
||||
const borrowedSecondaryValue = convertToBaseCurrency({
|
||||
denom: props.vault.denoms.secondary,
|
||||
amount: position.amounts.borrowedSecondary.toString(),
|
||||
})
|
||||
position.values.borrowedPrimary = borrowedPrimaryValue
|
||||
position.values.borrowedSecondary = borrowedSecondaryValue
|
||||
position.values.total =
|
||||
borrowedPrimaryValue + borrowedSecondaryValue + primaryValue + secondaryValue
|
||||
position.values.net = primaryValue + secondaryValue
|
||||
|
||||
if (borrowedPrimaryValue > 0) {
|
||||
props.position.borrowDenom = props.vault.denoms.primary
|
||||
} else if (borrowedSecondaryValue > 0) {
|
||||
props.position.borrowDenom = props.vault.denoms.secondary
|
||||
}
|
||||
|
||||
return position
|
||||
}
|
||||
|
||||
@ -53,20 +68,27 @@ export const PositionInput = (props: Props) => {
|
||||
computeBorrowAmount()
|
||||
}
|
||||
|
||||
const onBorrowChange = (amount: number) => {
|
||||
const onBorrowChange = (amount: number, type: 'primary' | 'secondary') => {
|
||||
props.position.borrowDenom =
|
||||
type === 'primary' ? props.vault.denoms.primary : props.vault.denoms.secondary
|
||||
const borrowValue = convertToBaseCurrency({
|
||||
denom: props.vault.denoms.secondary,
|
||||
denom: props.position.borrowDenom,
|
||||
amount: amount.toString(),
|
||||
})
|
||||
props.position.amounts.borrowed = amount
|
||||
props.position.values.borrowed = borrowValue
|
||||
const borrowKey = type === 'primary' ? 'borrowedPrimary' : 'borrowedSecondary'
|
||||
const secondaryBorrowKey = type !== 'primary' ? 'borrowedPrimary' : 'borrowedSecondary'
|
||||
props.position.amounts[borrowKey] = amount
|
||||
props.position.amounts[secondaryBorrowKey] = 0
|
||||
props.position.values[borrowKey] = borrowValue
|
||||
props.position.values[secondaryBorrowKey] = 0
|
||||
props.position.currentLeverage = getLeverageFromValues(props.position.values)
|
||||
props.setPosition({ ...updateValues(props.position) })
|
||||
computeBorrowAmount()
|
||||
}
|
||||
|
||||
const computeMaxAllowedLeverage = () => {
|
||||
const maxBorrowValue = convertToBaseCurrency({
|
||||
denom: props.vault.denoms.secondary,
|
||||
denom: props.position.borrowDenom || props.vault.denoms.secondary,
|
||||
amount: computeMaxBorrowAmount().toString(),
|
||||
})
|
||||
|
||||
@ -76,16 +98,20 @@ export const PositionInput = (props: Props) => {
|
||||
props.position.values.primary,
|
||||
props.position.values.secondary,
|
||||
)
|
||||
: ltvToLeverage(props.vault.ltv.max)
|
||||
: ltvToLeverage(props.vault.ltv.contract)
|
||||
}
|
||||
|
||||
const computeBorrowAmount = (leverage?: number) => {
|
||||
const supplyBorrowRatio = leverage ? leverage - 1 : props.position.currentLeverage - 1
|
||||
const supplyValue = props.position.values.primary + props.position.values.secondary
|
||||
const borrowValue = new BigNumber(supplyValue).times(supplyBorrowRatio).toNumber()
|
||||
const borrowDenom = props.position.borrowDenom
|
||||
? props.position.borrowDenom
|
||||
: props.vault.denoms.secondary
|
||||
|
||||
const borrowAmount = Math.floor(
|
||||
convertValueToAmount({
|
||||
denom: props.vault.denoms.secondary,
|
||||
denom: borrowDenom,
|
||||
amount: borrowValue.toString(),
|
||||
}),
|
||||
)
|
||||
@ -97,12 +123,15 @@ export const PositionInput = (props: Props) => {
|
||||
: props.position.currentLeverage
|
||||
const maxAllowedLeverage = computeMaxAllowedLeverage()
|
||||
|
||||
const borrowKey =
|
||||
borrowDenom === props.vault.denoms.primary ? 'borrowedPrimary' : 'borrowedSecondary'
|
||||
|
||||
if (targetLeverage > maxAllowedLeverage) {
|
||||
const borrowAmount = computeMaxBorrowAmount()
|
||||
props.position.amounts.borrowed = borrowAmount
|
||||
props.position.amounts[borrowKey] = borrowAmount
|
||||
props.position.currentLeverage = maxAllowedLeverage
|
||||
} else {
|
||||
props.position.amounts.borrowed = borrowAmount
|
||||
props.position.amounts[borrowKey] = borrowAmount
|
||||
props.position.currentLeverage = targetLeverage
|
||||
}
|
||||
|
||||
@ -111,25 +140,28 @@ export const PositionInput = (props: Props) => {
|
||||
}
|
||||
|
||||
const computeMaxBorrowAmount = () => {
|
||||
const borrowDenom = props.position.borrowDenom || props.vault.denoms.secondary
|
||||
|
||||
const maxAmount = Math.floor(
|
||||
convertValueToAmount({
|
||||
denom: props.vault.denoms.secondary,
|
||||
denom: borrowDenom,
|
||||
amount: getMaxBorrowValue(props.vault, props.position).toString(),
|
||||
}),
|
||||
)
|
||||
|
||||
const marketLiquidity = Number(
|
||||
marketAssetLiquidity.find((market) => market.denom === props.vault.denoms.secondary)
|
||||
?.amount || 0,
|
||||
marketAssetLiquidity.find((market) => market.denom === borrowDenom)?.amount || 0,
|
||||
)
|
||||
const borrowKey =
|
||||
borrowDenom === props.vault.denoms.primary ? 'borrowedPrimary' : 'borrowedSecondary'
|
||||
|
||||
const maxBorrowAmount = Math.min(
|
||||
maxAmount,
|
||||
(props.prevPosition?.amounts.borrowed || 0) + marketLiquidity,
|
||||
(props.prevPosition?.amounts[borrowKey] || 0) + marketLiquidity,
|
||||
)
|
||||
|
||||
if (props.prevPosition) {
|
||||
return Math.max(maxBorrowAmount, props.prevPosition.amounts.borrowed)
|
||||
return Math.max(maxBorrowAmount, props.prevPosition.amounts[borrowKey])
|
||||
}
|
||||
|
||||
return maxBorrowAmount
|
||||
@ -154,7 +186,7 @@ export const PositionInput = (props: Props) => {
|
||||
leverage={props.position.currentLeverage || 1}
|
||||
leverageLimit={maxAllowedLeverage}
|
||||
leverageMax={Math.max(
|
||||
ltvToLeverage(props.vault.ltv.max),
|
||||
ltvToLeverage(props.vault.ltv.contract),
|
||||
props.prevPosition?.currentLeverage || 1,
|
||||
)}
|
||||
onChange={computeBorrowAmount}
|
||||
@ -162,10 +194,13 @@ export const PositionInput = (props: Props) => {
|
||||
</Highlight>
|
||||
<Highlight show={tutorialStep === 3 || !showTutorial} className={styles.borrow}>
|
||||
<BorrowInput
|
||||
borrowAmount={props.position.amounts.borrowed}
|
||||
onChange={onBorrowChange}
|
||||
borrowedPrimaryAmount={props.position.amounts.borrowedPrimary}
|
||||
borrowedSecondaryAmount={props.position.amounts.borrowedSecondary}
|
||||
onChangePrimary={(amount) => onBorrowChange(amount, 'primary')}
|
||||
onChangeSecondary={(amount) => onBorrowChange(amount, 'secondary')}
|
||||
maxAmount={computeMaxBorrowAmount()}
|
||||
vault={props.vault}
|
||||
prevPosition={props.prevPosition}
|
||||
/>
|
||||
</Highlight>
|
||||
</div>
|
||||
|
@ -5,6 +5,7 @@
|
||||
flex-direction: column;
|
||||
gap: space(2);
|
||||
flex: 1;
|
||||
min-width: rem-calc(160);
|
||||
|
||||
.input {
|
||||
display: flex;
|
||||
|
@ -16,6 +16,7 @@ interface Props {
|
||||
maxAmount?: number
|
||||
maxAmountLabel: string
|
||||
borrowRate?: number
|
||||
disableGasWarning?: boolean
|
||||
onChange: (amount: number) => void
|
||||
onSelect?: (denom: string) => void
|
||||
}
|
||||
@ -62,7 +63,10 @@ export const TokenInput = (props: Props) => {
|
||||
10 ** asset.decimals
|
||||
|
||||
const showGasWarning =
|
||||
props.maxAmount && props.amount >= props.maxAmount && asset.denom === baseCurrency.denom
|
||||
props.maxAmount &&
|
||||
props.amount >= props.maxAmount &&
|
||||
asset.denom === baseCurrency.denom &&
|
||||
!props.disableGasWarning
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
|
@ -19,18 +19,28 @@ interface Props {
|
||||
export const RepayInput = (props: Props) => {
|
||||
const { t } = useTranslation()
|
||||
const convertToBaseCurrency = useStore((s) => s.convertToBaseCurrency)
|
||||
const debtAmount = props.prevPosition.amounts.borrowed
|
||||
const borrowKey =
|
||||
props.position.borrowDenom === props.vault.denoms.primary
|
||||
? 'borrowedPrimary'
|
||||
: 'borrowedSecondary'
|
||||
const supplyKey = borrowKey === 'borrowedPrimary' ? 'primary' : 'secondary'
|
||||
const debtAmount = props.prevPosition.amounts[borrowKey]
|
||||
const userBalances = useStore((s) => s.userBalances)
|
||||
|
||||
const borrowSymbol =
|
||||
props.position.borrowDenom === props.vault.denoms.primary
|
||||
? props.vault.symbols.primary
|
||||
: props.vault.symbols.secondary
|
||||
|
||||
const walletBalance = Number(
|
||||
(findByDenom(userBalances, props.vault.denoms.secondary) as Coin)?.amount || 0,
|
||||
)
|
||||
|
||||
const maxRepayAmount = Math.min(walletBalance, debtAmount)
|
||||
const amount = props.prevPosition.amounts.borrowed - props.position.amounts.borrowed
|
||||
const amount = props.prevPosition.amounts[borrowKey] - props.position.amounts[borrowKey]
|
||||
const maxValue = Math.max(
|
||||
getLeverageFromValues(props.prevPosition.values),
|
||||
ltvToLeverage(props.vault.ltv.max),
|
||||
ltvToLeverage(props.vault.ltv.contract),
|
||||
)
|
||||
|
||||
const updateValues = (position: Position) => {
|
||||
@ -42,21 +52,29 @@ export const RepayInput = (props: Props) => {
|
||||
denom: props.vault.denoms.secondary,
|
||||
amount: position.amounts.secondary.toString(),
|
||||
})
|
||||
const borrowValue = convertToBaseCurrency({
|
||||
denom: props.vault.denoms.secondary,
|
||||
amount: position.amounts.borrowed.toString(),
|
||||
const borrowedPrimaryValue = convertToBaseCurrency({
|
||||
denom: props.vault.denoms.primary,
|
||||
amount: position.amounts.borrowedPrimary.toString(),
|
||||
})
|
||||
const borrowedSecondaryValue = convertToBaseCurrency({
|
||||
denom: props.vault.denoms.secondary,
|
||||
amount: position.amounts.borrowedSecondary.toString(),
|
||||
})
|
||||
position.values.primary = primaryValue
|
||||
position.values.secondary = secondaryValue
|
||||
position.values.borrowed = borrowValue
|
||||
position.values.total = borrowValue + primaryValue + secondaryValue
|
||||
position.values.borrowedPrimary = borrowedPrimaryValue
|
||||
position.values.borrowedSecondary = borrowedSecondaryValue
|
||||
position.values.total =
|
||||
borrowedPrimaryValue + borrowedSecondaryValue + primaryValue + secondaryValue
|
||||
position.values.net = primaryValue + secondaryValue
|
||||
position.currentLeverage = getLeverageFromValues(position.values)
|
||||
|
||||
return position
|
||||
}
|
||||
|
||||
const handleChange = (amount: number) => {
|
||||
props.position.amounts.borrowed = props.prevPosition.amounts.borrowed - amount
|
||||
props.position.amounts.secondary = props.prevPosition.amounts.secondary + amount
|
||||
props.position.amounts[borrowKey] = props.prevPosition.amounts[borrowKey] - amount
|
||||
props.position.amounts[supplyKey] = props.prevPosition.amounts[supplyKey] + amount
|
||||
props.setPosition({ ...updateValues(props.position) })
|
||||
}
|
||||
|
||||
@ -66,21 +84,22 @@ export const RepayInput = (props: Props) => {
|
||||
<p className={styles.headline}>{t('fields.repayDebt')}</p>
|
||||
<TokenInput
|
||||
amount={amount}
|
||||
tokens={[props.vault.symbols.secondary]}
|
||||
tokens={[borrowSymbol]}
|
||||
input={{
|
||||
denom: props.vault.denoms.secondary,
|
||||
symbol: props.vault.symbols.secondary,
|
||||
denom: props.position.borrowDenom || props.vault.denoms.secondary,
|
||||
symbol: borrowSymbol,
|
||||
visible: true,
|
||||
}}
|
||||
maxAmount={maxRepayAmount}
|
||||
maxAmountLabel={t('global.max')}
|
||||
onChange={handleChange}
|
||||
disableGasWarning
|
||||
/>
|
||||
</div>
|
||||
<RepayLeverage
|
||||
value={props.position.currentLeverage}
|
||||
maxValue={maxValue}
|
||||
leverageMax={ltvToLeverage(props.vault.ltv.max)}
|
||||
leverageMax={ltvToLeverage(props.vault.ltv.contract)}
|
||||
/>
|
||||
<div>
|
||||
<strong className='m'>{t('fields.repayingDebtFromWallet')}</strong>
|
||||
|
@ -91,6 +91,12 @@ export const AssetTable = ({ data, columns, type, disabled = false }: Props) =>
|
||||
</thead>
|
||||
<tbody>
|
||||
{table.getRowModel().rows.map((row) => {
|
||||
if (
|
||||
(type === 'deposit' && !row.original.depositEnabled) ||
|
||||
(type === 'borrow' && !row.original.borrowEnabled)
|
||||
)
|
||||
return null
|
||||
|
||||
if (row.depth === 1) {
|
||||
return (
|
||||
<React.Fragment key={`${row.id}_subrow`}>
|
||||
|
@ -86,14 +86,16 @@ export const MetricsRow = ({ row, type }: Props) => {
|
||||
valueClass='s'
|
||||
labelClass='xs faded'
|
||||
/>
|
||||
<ValueWithLabel
|
||||
percent={utilizationRatePercent}
|
||||
label={t('redbank.utilizationRate')}
|
||||
orientation='left'
|
||||
prefixClass='xxs faded prefix'
|
||||
valueClass='s'
|
||||
labelClass='xs faded'
|
||||
/>
|
||||
{row.original.borrowEnabled && (
|
||||
<ValueWithLabel
|
||||
percent={utilizationRatePercent}
|
||||
label={t('redbank.utilizationRate')}
|
||||
orientation='left'
|
||||
prefixClass='xxs faded prefix'
|
||||
valueClass='s'
|
||||
labelClass='xs faded'
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
@ -70,17 +70,15 @@ export const useBorrowColumns = () => {
|
||||
header: () => (
|
||||
<TextTooltip text={t('common.rate')} tooltip={t('redbank.tooltips.borrow.rate')} />
|
||||
),
|
||||
cell: (info) => {
|
||||
return (
|
||||
<AnimatedNumber
|
||||
amount={info.getValue()}
|
||||
suffix='%'
|
||||
abbreviated={false}
|
||||
rounded={false}
|
||||
className='m'
|
||||
/>
|
||||
)
|
||||
},
|
||||
cell: (info) => (
|
||||
<AnimatedNumber
|
||||
amount={info.getValue()}
|
||||
suffix='%'
|
||||
abbreviated={false}
|
||||
rounded={false}
|
||||
className='m'
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('marketLiquidity', {
|
||||
enableSorting: enableSorting,
|
||||
@ -100,15 +98,13 @@ export const useBorrowColumns = () => {
|
||||
}),
|
||||
columnHelper.display({
|
||||
id: 'actions',
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<Button
|
||||
color='quaternary'
|
||||
prefix={row.getIsExpanded() ? <SVG.Collapse /> : <SVG.Expand />}
|
||||
variant='round'
|
||||
/>
|
||||
)
|
||||
},
|
||||
cell: ({ row }) => (
|
||||
<Button
|
||||
color='quaternary'
|
||||
prefix={row.getIsExpanded() ? <SVG.Collapse /> : <SVG.Expand />}
|
||||
variant='round'
|
||||
/>
|
||||
),
|
||||
}),
|
||||
],
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
@ -18,6 +18,10 @@
|
||||
&.axlUSDC {
|
||||
background-image: $colorGradientAxlUSDC;
|
||||
}
|
||||
|
||||
&.stATOM {
|
||||
background-image: $colorGradientStATOM;
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
@ -25,3 +29,8 @@
|
||||
margin: auto;
|
||||
width: rem-calc(32);
|
||||
}
|
||||
|
||||
.notBorrowable {
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
|
@ -59,37 +59,45 @@ export const useDepositColumns = () => {
|
||||
tooltip={t('redbank.tooltips.deposit.deposited')}
|
||||
/>
|
||||
),
|
||||
cell: (info) => {
|
||||
return (
|
||||
<CellAmount
|
||||
amount={Number(info.row.original.depositBalance)}
|
||||
decimals={info.row.original.decimals}
|
||||
denom={info.row.original.denom}
|
||||
noBalanceText={t('common.noDeposit')}
|
||||
/>
|
||||
)
|
||||
},
|
||||
cell: (info) => (
|
||||
<CellAmount
|
||||
amount={Number(info.row.original.depositBalance)}
|
||||
decimals={info.row.original.decimals}
|
||||
denom={info.row.original.denom}
|
||||
noBalanceText={t('common.noDeposit')}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('apy', {
|
||||
enableSorting: enableSorting,
|
||||
header: () => (
|
||||
<TextTooltip text={t('common.apr')} tooltip={t('redbank.tooltips.deposit.apy')} />
|
||||
),
|
||||
cell: (info) => (
|
||||
<TextTooltip
|
||||
hideStyling
|
||||
text={
|
||||
<AnimatedNumber
|
||||
amount={info.getValue() + Number(info.row.original.incentiveInfo?.apy || 0)}
|
||||
suffix='%'
|
||||
abbreviated={false}
|
||||
rounded={false}
|
||||
className='m'
|
||||
/>
|
||||
}
|
||||
tooltip={<Apr data={info.row.original} />}
|
||||
/>
|
||||
),
|
||||
cell: (info) =>
|
||||
info.row.original.borrowEnabled ? (
|
||||
<TextTooltip
|
||||
hideStyling
|
||||
text={
|
||||
<AnimatedNumber
|
||||
amount={info.getValue() + Number(info.row.original.incentiveInfo?.apy || 0)}
|
||||
suffix='%'
|
||||
abbreviated={false}
|
||||
rounded={false}
|
||||
className='m'
|
||||
/>
|
||||
}
|
||||
tooltip={<Apr data={info.row.original} />}
|
||||
/>
|
||||
) : (
|
||||
<TextTooltip
|
||||
text='–'
|
||||
hideUnderline
|
||||
className={styles.notBorrowable}
|
||||
tooltip={t('redbank.tooltips.deposit.notBorrowable', {
|
||||
symbol: info.row.original.symbol,
|
||||
})}
|
||||
/>
|
||||
),
|
||||
}),
|
||||
columnHelper.accessor('depositCap', {
|
||||
enableSorting: enableSorting,
|
||||
@ -108,7 +116,6 @@ export const useDepositColumns = () => {
|
||||
'faded',
|
||||
percent >= 100 ? 'colorInfoLoss' : '',
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className='number'>
|
||||
@ -129,15 +136,13 @@ export const useDepositColumns = () => {
|
||||
}),
|
||||
columnHelper.display({
|
||||
id: 'actions',
|
||||
cell: ({ row }) => {
|
||||
return (
|
||||
<Button
|
||||
color='quaternary'
|
||||
prefix={row.getIsExpanded() ? <SVG.Collapse /> : <SVG.Expand />}
|
||||
variant='round'
|
||||
/>
|
||||
)
|
||||
},
|
||||
cell: ({ row }) => (
|
||||
<Button
|
||||
color='quaternary'
|
||||
prefix={row.getIsExpanded() ? <SVG.Collapse /> : <SVG.Expand />}
|
||||
variant='round'
|
||||
/>
|
||||
),
|
||||
}),
|
||||
]
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
|
@ -42,6 +42,8 @@ export const RedbankNotConnected = () => {
|
||||
depositBalanceBaseCurrency: 0,
|
||||
depositCap: 0,
|
||||
depositLiquidity: 0,
|
||||
borrowEnabled: true,
|
||||
depositEnabled: true,
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -14,7 +14,6 @@ export const ASSETS: { [denom: string]: Asset } = {
|
||||
denom: 'uosmo',
|
||||
color: colors.osmo,
|
||||
decimals: 6,
|
||||
hasOraclePrice: true,
|
||||
logo: osmo,
|
||||
poolId: 678,
|
||||
},
|
||||
@ -25,7 +24,6 @@ export const ASSETS: { [denom: string]: Asset } = {
|
||||
color: colors.atom,
|
||||
logo: atom,
|
||||
decimals: 6,
|
||||
hasOraclePrice: true,
|
||||
},
|
||||
juno: {
|
||||
symbol: 'JUNO',
|
||||
@ -34,7 +32,6 @@ export const ASSETS: { [denom: string]: Asset } = {
|
||||
color: colors.juno,
|
||||
logo: juno,
|
||||
decimals: 6,
|
||||
hasOraclePrice: true,
|
||||
},
|
||||
}
|
||||
|
||||
@ -46,7 +43,6 @@ const OTHER_ASSETS: { [denom: string]: OtherAsset } = {
|
||||
color: colors.mars,
|
||||
logo: mars,
|
||||
decimals: 6,
|
||||
hasOraclePrice: true,
|
||||
poolId: 768,
|
||||
},
|
||||
axlusdc: {
|
||||
@ -57,7 +53,6 @@ const OTHER_ASSETS: { [denom: string]: OtherAsset } = {
|
||||
color: colors.axlusdc,
|
||||
logo: axlusdc,
|
||||
decimals: 6,
|
||||
hasOraclePrice: false,
|
||||
poolId: 674,
|
||||
},
|
||||
}
|
||||
@ -70,6 +65,7 @@ export const NETWORK_CONFIG: NetworkConfig = {
|
||||
rpcUrl: URL_RPC ?? 'https://rpc-test.osmosis.zone/',
|
||||
restUrl: URL_REST ?? 'https://lcd-test.osmosis.zone/',
|
||||
apolloAprUrl: 'https://api.apollo.farm/api/vault_infos/v2/osmo-test-4',
|
||||
priceApiUrl: 'https://api-osmosis.imperator.co/tokens/v2/OSMO',
|
||||
contracts: {
|
||||
redBank: 'osmo1t0dl6r27phqetfu0geaxrng0u9zn8qgrdwztapt5xr32adtwptaq6vwg36',
|
||||
incentives: 'osmo1zxs8fry3m8j94pqg7h4muunyx86en27cl0xgk76fc839xg2qnn6qtpjs48',
|
||||
@ -93,30 +89,6 @@ export const NETWORK_CONFIG: NetworkConfig = {
|
||||
}
|
||||
|
||||
export const VAULT_CONFIGS: Vault[] = [
|
||||
{
|
||||
address: 'osmo1zktjv92f76epswjvyxzzt3yyskpw7k6jsyu0kmq4zzc5fphrjumqlahctp',
|
||||
name: 'OSMO-ATOM LP (1 day)',
|
||||
denoms: {
|
||||
primary: 'uosmo',
|
||||
secondary: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2',
|
||||
lpToken: 'gamm/pool/1',
|
||||
},
|
||||
symbols: {
|
||||
primary: 'OSMO',
|
||||
secondary: 'ATOM',
|
||||
},
|
||||
color: '#DD5B65',
|
||||
lockup: 86400,
|
||||
provider: 'Apollo vault',
|
||||
description:
|
||||
'Up to 2.67× leveraged yield farming with auto compounding of the OSMO-ATOM LP tokens.',
|
||||
ltv: {
|
||||
max: 0.625,
|
||||
contract: 0.63,
|
||||
liq: 0.65,
|
||||
},
|
||||
apy: 0,
|
||||
},
|
||||
{
|
||||
address: 'osmo1tp2m6g39h8mvhnu3plqjyen5s63023gj8w873l8wvly0cd77l6hsaa73wt',
|
||||
name: 'OSMO-ATOM LP (14 day)',
|
||||
@ -133,11 +105,11 @@ export const VAULT_CONFIGS: Vault[] = [
|
||||
lockup: 86400 * 14,
|
||||
provider: 'Apollo vault',
|
||||
description:
|
||||
'Up to 2.67× leveraged yield farming with auto compounding of the OSMO-ATOM LP tokens.',
|
||||
'Up to 1.43× leveraged yield farming with auto compounding of the OSMO-ATOM LP tokens.',
|
||||
ltv: {
|
||||
max: 0.625,
|
||||
contract: 0.63,
|
||||
liq: 0.65,
|
||||
max: 0.295,
|
||||
contract: 0.3,
|
||||
liq: 0.4,
|
||||
},
|
||||
apy: 0,
|
||||
},
|
||||
@ -157,11 +129,11 @@ export const VAULT_CONFIGS: Vault[] = [
|
||||
lockup: 86400 * 1,
|
||||
provider: 'Apollo vault',
|
||||
description:
|
||||
'Up to 1.67× leveraged yield farming with auto compounding of the OSMO-JUNO LP tokens.',
|
||||
'Up to 1.43× leveraged yield farming with auto compounding of the OSMO-JUNO LP tokens.',
|
||||
ltv: {
|
||||
max: 0.4,
|
||||
contract: 0.4115,
|
||||
liq: 0.441,
|
||||
max: 0.295,
|
||||
contract: 0.3,
|
||||
liq: 0.4,
|
||||
},
|
||||
apy: 0,
|
||||
},
|
||||
@ -181,11 +153,11 @@ export const VAULT_CONFIGS: Vault[] = [
|
||||
lockup: 86400 * 14,
|
||||
provider: 'Apollo vault',
|
||||
description:
|
||||
'Up to 1.67× leveraged yield farming with auto compounding of the OSMO-JUNO LP tokens.',
|
||||
'Up to 1.43× leveraged yield farming with auto compounding of the OSMO-JUNO LP tokens.',
|
||||
ltv: {
|
||||
max: 0.4,
|
||||
contract: 4.115,
|
||||
liq: 0.441,
|
||||
max: 0.295,
|
||||
contract: 0.3,
|
||||
liq: 0.4,
|
||||
},
|
||||
apy: 0,
|
||||
},
|
||||
|
@ -4,6 +4,7 @@ import atom from 'images/atom.svg'
|
||||
import axlusdc from 'images/axlusdc.svg'
|
||||
import mars from 'images/mars.svg'
|
||||
import osmo from 'images/osmo.svg'
|
||||
import statom from 'images/statom.svg'
|
||||
import colors from 'styles/_assets.module.scss'
|
||||
|
||||
export const ASSETS: { [denom: string]: Asset } = {
|
||||
@ -13,17 +14,15 @@ export const ASSETS: { [denom: string]: Asset } = {
|
||||
denom: 'uosmo',
|
||||
color: colors.osmo,
|
||||
decimals: 6,
|
||||
hasOraclePrice: true,
|
||||
logo: osmo,
|
||||
},
|
||||
axlusdc: {
|
||||
symbol: 'axlUSDC',
|
||||
name: 'Axelar USDC',
|
||||
denom: 'ibc/D189335C6E4A68B513C10AB227BF1C1D38C746766278BA3EEB4FB14124F1D858',
|
||||
color: colors.axlUSDC,
|
||||
color: colors.axlusdc,
|
||||
logo: axlusdc,
|
||||
decimals: 6,
|
||||
hasOraclePrice: true,
|
||||
poolId: 678,
|
||||
},
|
||||
atom: {
|
||||
@ -33,7 +32,16 @@ export const ASSETS: { [denom: string]: Asset } = {
|
||||
color: colors.atom,
|
||||
logo: atom,
|
||||
decimals: 6,
|
||||
hasOraclePrice: true,
|
||||
},
|
||||
statom: {
|
||||
symbol: 'stATOM',
|
||||
name: 'Stride Atom',
|
||||
denom: 'ibc/C140AFD542AE77BD7DCC83F13FDD8C5E5BB8C4929785E6EC2F4C636F98F17901',
|
||||
color: colors.statom,
|
||||
logo: statom,
|
||||
decimals: 6,
|
||||
poolId: 803,
|
||||
poolBase: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2',
|
||||
},
|
||||
}
|
||||
|
||||
@ -45,7 +53,6 @@ const OTHER_ASSETS: { [denom: string]: OtherAsset } = {
|
||||
color: colors.mars,
|
||||
logo: mars,
|
||||
decimals: 6,
|
||||
hasOraclePrice: true,
|
||||
poolId: 907,
|
||||
},
|
||||
}
|
||||
@ -57,6 +64,7 @@ export const NETWORK_CONFIG: NetworkConfig = {
|
||||
rpcUrl: URL_RPC ?? 'https://rpc-osmosis.blockapsis.com/',
|
||||
restUrl: URL_REST ?? 'https://lcd-osmosis.blockapsis.com/',
|
||||
apolloAprUrl: 'https://api.apollo.farm/api/vault_infos/v2/osmosis-1',
|
||||
priceApiUrl: 'https://api-osmosis.imperator.co/tokens/v2/OSMO',
|
||||
contracts: {
|
||||
redBank: 'osmo1c3ljch9dfw5kf52nfwpxd2zmj2ese7agnx0p9tenkrryasrle5sqf3ftpg',
|
||||
incentives: 'osmo1nkahswfr8shg8rlxqwup0vgahp0dk4x8w6tkv3rra8rratnut36sk22vrm',
|
||||
@ -66,7 +74,7 @@ export const NETWORK_CONFIG: NetworkConfig = {
|
||||
},
|
||||
assets: {
|
||||
base: ASSETS.osmo,
|
||||
whitelist: [ASSETS.osmo, ASSETS.atom, ASSETS.axlusdc],
|
||||
whitelist: [ASSETS.osmo, ASSETS.atom, ASSETS.axlusdc, ASSETS.statom],
|
||||
other: [OTHER_ASSETS.mars],
|
||||
},
|
||||
displayCurrency: {
|
||||
@ -129,7 +137,7 @@ export const VAULT_CONFIGS: Vault[] = [
|
||||
description:
|
||||
'Up to 2.78× leveraged yield farming with auto compounding of the OSMO-axlUSDC LP tokens.',
|
||||
ltv: {
|
||||
max: 0.64,
|
||||
max: 0.645,
|
||||
contract: 0.65,
|
||||
liq: 0.66,
|
||||
},
|
||||
|
@ -5,6 +5,7 @@ export const FORUM_URL = 'https://forum.marsprotocol.io/'
|
||||
export const MARS_SYMBOL = 'MARS'
|
||||
export const MARS_DECIMALS = 6
|
||||
export const USDC_SYMBOL = 'axlUSDC'
|
||||
export const STATOM_SYMBOL = 'stATOM'
|
||||
|
||||
/* borrow capacity */
|
||||
export const DEFAULT_SLIPPAGE = 0.01
|
||||
|
@ -4,7 +4,8 @@ export const DEFAULT_POSITION: Position = {
|
||||
amounts: {
|
||||
primary: 0,
|
||||
secondary: 0,
|
||||
borrowed: 0,
|
||||
borrowedPrimary: 0,
|
||||
borrowedSecondary: 0,
|
||||
lp: {
|
||||
amount: '0',
|
||||
primary: 0,
|
||||
@ -15,7 +16,8 @@ export const DEFAULT_POSITION: Position = {
|
||||
values: {
|
||||
primary: 0,
|
||||
secondary: 0,
|
||||
borrowed: 0,
|
||||
borrowedPrimary: 0,
|
||||
borrowedSecondary: 0,
|
||||
total: 0,
|
||||
net: 0,
|
||||
},
|
||||
@ -26,4 +28,5 @@ export const DEFAULT_POSITION: Position = {
|
||||
},
|
||||
ltv: 0.5,
|
||||
currentLeverage: 1,
|
||||
borrowDenom: null,
|
||||
}
|
||||
|
@ -8,7 +8,10 @@ export const getClosePositionActions = (
|
||||
const swapMessage: Action[] = []
|
||||
|
||||
// Increase the borrow amount by factor to account for an increase of borrow over time
|
||||
const borrowAmount = Math.ceil(vault.position.amounts.borrowed * 1.001)
|
||||
const borrowAmount = Math.ceil(
|
||||
Math.max(vault.position.amounts.borrowedPrimary, vault.position.amounts.borrowedSecondary) *
|
||||
1.001,
|
||||
)
|
||||
const secondaryAmount = vault.position.amounts.lp.secondary
|
||||
|
||||
if (secondaryAmount < borrowAmount) {
|
||||
@ -46,11 +49,11 @@ export const getClosePositionActions = (
|
||||
},
|
||||
},
|
||||
...swapMessage,
|
||||
...(vault.position.amounts.borrowed
|
||||
...(Math.max(vault.position.amounts.borrowedPrimary, vault.position.amounts.borrowedSecondary)
|
||||
? [
|
||||
{
|
||||
repay: {
|
||||
denom: vault.denoms.secondary,
|
||||
denom: vault.position.borrowDenom || vault.denoms.secondary,
|
||||
amount: 'account_balance' as ActionAmount,
|
||||
},
|
||||
},
|
||||
|
@ -1,7 +1,7 @@
|
||||
export const getCoinFromPosition = (
|
||||
position: Position,
|
||||
vault: Vault,
|
||||
type: 'primary' | 'secondary' | 'borrowed',
|
||||
type: 'primary' | 'secondary' | 'borrowedPrimary' | 'borrowedSecondary',
|
||||
) => {
|
||||
const denom = type === 'primary' ? vault.denoms.primary : vault.denoms.secondary
|
||||
return {
|
||||
|
@ -3,7 +3,17 @@ import BigNumber from 'bignumber.js'
|
||||
export const getLeverageFromValues = (values: {
|
||||
primary: number
|
||||
secondary: number
|
||||
borrowed: number
|
||||
borrowedPrimary: number
|
||||
borrowedSecondary: number
|
||||
net: number
|
||||
total: number
|
||||
}) => Number(new BigNumber(values.borrowed).div(values.net || 1).plus(1))
|
||||
}) =>
|
||||
Number(
|
||||
new BigNumber(
|
||||
values.borrowedPrimary > values.borrowedSecondary
|
||||
? values.borrowedPrimary
|
||||
: values.borrowedSecondary,
|
||||
)
|
||||
.div(values.net || 1)
|
||||
.plus(1),
|
||||
)
|
||||
|
@ -1,3 +1,8 @@
|
||||
export const getLiqBorrowValue = (vault: Vault, maxBorrowValue: number) => {
|
||||
return ((vault.ltv.liq - vault.ltv.max) / vault.ltv.max + 1) * maxBorrowValue
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { ltvToLeverage } from 'libs/parse'
|
||||
|
||||
export const getLiqBorrowValue = (vault: Vault, netValue: number) => {
|
||||
const liqLev = ltvToLeverage(vault.ltv.liq)
|
||||
|
||||
return new BigNumber(netValue).times(liqLev - 1).toNumber()
|
||||
}
|
||||
|
@ -9,5 +9,5 @@ export const getMaxAllowedLeverage = (
|
||||
new BigNumber(borrowValue)
|
||||
.div(new BigNumber(primaryValue).plus(secondaryValue))
|
||||
.plus(1)
|
||||
.toPrecision(2),
|
||||
.toPrecision(4),
|
||||
)
|
||||
|
@ -2,5 +2,8 @@ import BigNumber from 'bignumber.js'
|
||||
import { ltvToLeverage } from 'libs/parse'
|
||||
|
||||
export const getMaxBorrowValue = (vault: Vault, position: Position): number => {
|
||||
return new BigNumber(ltvToLeverage(vault.ltv.max)).minus(1).times(position.values.net).toNumber()
|
||||
return new BigNumber(ltvToLeverage(vault.ltv.contract))
|
||||
.minus(1)
|
||||
.times(position.values.net)
|
||||
.toNumber()
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import { vault } from 'mocks/vault'
|
||||
|
||||
describe('getMaxBorrowValue', () => {
|
||||
test('should return 0 when netValue = 0', () => {
|
||||
vault.ltv.max = 0.5
|
||||
vault.ltv.contract = 0.5
|
||||
position.values.net = 0
|
||||
|
||||
const maxBorrowValue = getMaxBorrowValue(vault, position)
|
||||
@ -17,7 +17,7 @@ describe('getMaxBorrowValue', () => {
|
||||
})
|
||||
|
||||
test('should return 0 when maxLTV = 0', () => {
|
||||
vault.ltv.max = 0
|
||||
vault.ltv.contract = 0
|
||||
position.values.net = 100
|
||||
|
||||
const maxBorrowValue = getMaxBorrowValue(vault, position)
|
||||
@ -25,7 +25,7 @@ describe('getMaxBorrowValue', () => {
|
||||
})
|
||||
|
||||
test('should return 1x netValue when maxLTV = 0.5', () => {
|
||||
vault.ltv.max = 0.5
|
||||
vault.ltv.contract = 0.5
|
||||
position.values.net = 100
|
||||
|
||||
const maxBorrowValue = getMaxBorrowValue(vault, position)
|
||||
@ -33,7 +33,7 @@ describe('getMaxBorrowValue', () => {
|
||||
})
|
||||
|
||||
test('should return 4.5x netValue when maxLTV = ', () => {
|
||||
vault.ltv.max = 0.75
|
||||
vault.ltv.contract = 0.75
|
||||
position.values.net = 100
|
||||
|
||||
const maxBorrowValue = getMaxBorrowValue(vault, position)
|
||||
@ -62,7 +62,8 @@ describe('getLeverageFromValues', () => {
|
||||
const values = {
|
||||
primary: 0,
|
||||
secondary: 0,
|
||||
borrowed: 0,
|
||||
borrowedPrimary: 0,
|
||||
borrowedSecondary: 0,
|
||||
net: 0,
|
||||
total: 0,
|
||||
}
|
||||
@ -73,14 +74,14 @@ describe('getLeverageFromValues', () => {
|
||||
})
|
||||
|
||||
test('should return 1.5 when borrowed = 50 and net = 100', () => {
|
||||
values.borrowed = 50
|
||||
values.borrowedPrimary = 50
|
||||
values.net = 100
|
||||
const leverage = getLeverageFromValues(values)
|
||||
expect(leverage).toBe(1.5)
|
||||
})
|
||||
|
||||
test('should return 2.25 when borrowed = 125 and net = 100', () => {
|
||||
values.borrowed = 125
|
||||
values.borrowedPrimary = 125
|
||||
values.net = 100
|
||||
const leverage = getLeverageFromValues(values)
|
||||
expect(leverage).toBe(2.25)
|
||||
|
@ -3,9 +3,10 @@ import { Coin } from '@cosmjs/proto-signing'
|
||||
export const updateExchangeRate = (coin: Coin, exchangeRates: Coin[]) => {
|
||||
const assetIndex = exchangeRates.findIndex((xAsset) => xAsset.denom === coin.denom)
|
||||
if (assetIndex > -1) {
|
||||
exchangeRates[assetIndex] = coin
|
||||
if (coin.amount !== '0.00') exchangeRates[assetIndex] = coin
|
||||
} else {
|
||||
exchangeRates.push(coin)
|
||||
}
|
||||
|
||||
return exchangeRates
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ export { useRepayPosition } from './useRepayPosition'
|
||||
export { useRequestUnlockPosition } from './useRequestUnlockPosition'
|
||||
export { useSpotPrice } from './useSpotPrice'
|
||||
export { useUnlockMessages } from './useUnlockMessages'
|
||||
export { useUsdPrice } from './useUsdPrice'
|
||||
export { useUserBalance } from './useUserBalance'
|
||||
export { useUserDebt } from './useUserDebt'
|
||||
export { useUserDeposit } from './useUserDeposit'
|
||||
|
@ -15,6 +15,8 @@ export interface DepositAndDebtData {
|
||||
JUNODebt: string
|
||||
axlUSDCDeposits: string
|
||||
axlUSDCDebt: string
|
||||
stATOMDeposits: string
|
||||
stATOMDebt: string
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,15 +27,20 @@ export const useEditPosition = (props: Props) => {
|
||||
props.position.amounts.primary - (props.prevPosition?.amounts.primary || 0)
|
||||
const secondaryAmount =
|
||||
props.position.amounts.secondary - (props.prevPosition?.amounts.secondary || 0)
|
||||
const borrowedAmount =
|
||||
props.position.amounts.borrowed - (props.prevPosition?.amounts.borrowed || 0)
|
||||
const borrowedPrimaryAmount =
|
||||
props.position.amounts.borrowedPrimary - (props.prevPosition?.amounts.borrowedPrimary || 0)
|
||||
|
||||
const borrowedSecondaryAmount =
|
||||
props.position.amounts.borrowedSecondary -
|
||||
(props.prevPosition?.amounts.borrowedSecondary || 0)
|
||||
|
||||
const editPosition = {
|
||||
...props.position,
|
||||
amounts: {
|
||||
primary: primaryAmount,
|
||||
secondary: secondaryAmount,
|
||||
borrowed: borrowedAmount,
|
||||
borrowedPrimary: borrowedPrimaryAmount,
|
||||
borrowedSecondary: borrowedSecondaryAmount,
|
||||
lp: {
|
||||
amount: '0',
|
||||
primary: 0,
|
||||
@ -47,15 +52,15 @@ export const useEditPosition = (props: Props) => {
|
||||
|
||||
const primaryBaseAmount = convertToBaseCurrency({
|
||||
denom: props.vault.denoms.primary,
|
||||
amount: primaryAmount.toString(),
|
||||
amount: (primaryAmount + borrowedPrimaryAmount).toString(),
|
||||
})
|
||||
const secondaryBaseAmount = convertToBaseCurrency({
|
||||
denom: props.vault.denoms.secondary,
|
||||
amount: (secondaryAmount + borrowedAmount).toString(),
|
||||
amount: (secondaryAmount + borrowedSecondaryAmount).toString(),
|
||||
})
|
||||
|
||||
let primaryAfterSwap = primaryAmount
|
||||
let secondaryAfterSwap = secondaryAmount + borrowedAmount
|
||||
let primaryAfterSwap = primaryAmount + borrowedPrimaryAmount
|
||||
let secondaryAfterSwap = secondaryAmount + borrowedSecondaryAmount
|
||||
|
||||
// If difference is larger than threshold, initiate a swap
|
||||
const difference = primaryBaseAmount - secondaryBaseAmount
|
||||
@ -105,7 +110,8 @@ export const useEditPosition = (props: Props) => {
|
||||
}, [
|
||||
props.position.amounts.primary,
|
||||
props.position.amounts.secondary,
|
||||
props.position.amounts.borrowed,
|
||||
props.position.amounts.borrowedPrimary,
|
||||
props.position.amounts.borrowedSecondary,
|
||||
])
|
||||
|
||||
const { data: minLpToReceive } = useProvideLiquidity({
|
||||
@ -128,9 +134,12 @@ export const useEditPosition = (props: Props) => {
|
||||
amount: editPosition.amounts.secondary.toString(),
|
||||
}
|
||||
|
||||
const borrow = editPosition.amounts.borrowed && {
|
||||
denom: props.vault.denoms.secondary,
|
||||
amount: editPosition.amounts.borrowed.toString(),
|
||||
const borrow = editPosition.borrowDenom && {
|
||||
denom: editPosition.borrowDenom,
|
||||
amount: Math.max(
|
||||
editPosition.amounts.borrowedPrimary,
|
||||
editPosition.amounts.borrowedSecondary,
|
||||
).toString(),
|
||||
}
|
||||
|
||||
if (primary) coins.supply.push(primary)
|
||||
@ -139,12 +148,12 @@ export const useEditPosition = (props: Props) => {
|
||||
|
||||
const primaryBaseAmount = convertToBaseCurrency({
|
||||
denom: props.vault.denoms.primary,
|
||||
amount: String(editPosition.amounts.primary),
|
||||
amount: String(editPosition.amounts.primary + editPosition.amounts.borrowedPrimary),
|
||||
})
|
||||
|
||||
const secondaryBaseAmount = convertToBaseCurrency({
|
||||
denom: props.vault.denoms.secondary,
|
||||
amount: String(editPosition.amounts.secondary + editPosition.amounts.borrowed),
|
||||
amount: String(editPosition.amounts.secondary + editPosition.amounts.borrowedSecondary),
|
||||
})
|
||||
|
||||
const swapMessage: Action[] = []
|
||||
|
@ -14,16 +14,29 @@ export const useRepayPosition = (props: Props) => {
|
||||
const [amount, setAmount] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
setAmount(props.prevPosition.amounts.borrowed - props.repayPosition.amounts.borrowed)
|
||||
}, [props.repayPosition.amounts.borrowed, props.prevPosition.amounts.borrowed])
|
||||
const borrowKey =
|
||||
props.prevPosition.borrowDenom === props.activeVault.denoms.primary
|
||||
? 'borrowedPrimary'
|
||||
: 'borrowedSecondary'
|
||||
setAmount(props.prevPosition.amounts[borrowKey] - props.repayPosition.amounts[borrowKey])
|
||||
}, [
|
||||
props.repayPosition.amounts.borrowedPrimary,
|
||||
props.repayPosition.amounts.borrowedSecondary,
|
||||
props.prevPosition.amounts.borrowedPrimary,
|
||||
props.prevPosition.amounts.borrowedSecondary,
|
||||
props.activeVault.denoms.primary,
|
||||
props.prevPosition.amounts,
|
||||
props.prevPosition.borrowDenom,
|
||||
props.repayPosition.amounts,
|
||||
])
|
||||
|
||||
const [actions, funds] = useMemo(() => {
|
||||
if (!amount) return [[], []]
|
||||
return getRepayActionsAndFunds({
|
||||
denom: props.activeVault.denoms.secondary,
|
||||
denom: props.activeVault.position.borrowDenom || props.activeVault.denoms.secondary,
|
||||
amount: amount.toString(),
|
||||
})
|
||||
}, [amount, props.activeVault.denoms.secondary])
|
||||
}, [amount, props.activeVault.denoms.secondary, props.activeVault.position.borrowDenom])
|
||||
|
||||
const { data: fee } = useEstimateFarmFee({
|
||||
accountId: props.prevPosition.accountId,
|
||||
|
@ -9,15 +9,16 @@ const poolsEndpoint = 'osmosis/gamm/v1beta1/pools/'
|
||||
|
||||
export const useSpotPrice = (symbol: string) => {
|
||||
const networkConfig = useStore((s) => s.networkConfig)
|
||||
const displayCurrency = networkConfig?.displayCurrency
|
||||
const lcd = useStore((s) => s.chainInfo?.rest)
|
||||
const exchangeRates = useStore((s) => s.exchangeRates)
|
||||
|
||||
const asset = useAsset({ symbol })
|
||||
|
||||
const displayCurrency = networkConfig?.displayCurrency
|
||||
const poolBase = asset?.poolBase
|
||||
? exchangeRates?.find((ratesAsset) => ratesAsset.denom === asset.poolBase)
|
||||
: true
|
||||
|
||||
useQuery<PoolResponse>(
|
||||
[QUERY_KEYS.MARS_PRICE, asset?.poolId],
|
||||
[QUERY_KEYS.SPOT_PRICE, asset?.poolId],
|
||||
async () => {
|
||||
return fetch(`${lcd}${poolsEndpoint}${asset?.poolId}`).then(async (response) => {
|
||||
const data = await response.json()
|
||||
@ -25,7 +26,7 @@ export const useSpotPrice = (symbol: string) => {
|
||||
})
|
||||
},
|
||||
{
|
||||
enabled: !!lcd && !!asset && !!asset.poolId,
|
||||
enabled: !!lcd && !!asset && !!asset.poolId && !!poolBase,
|
||||
staleTime: 30000,
|
||||
refetchInterval: 30000,
|
||||
onSuccess: (data) => {
|
||||
@ -44,11 +45,22 @@ export const useSpotPrice = (symbol: string) => {
|
||||
.div(targetAssetAmount)
|
||||
.multipliedBy(otherAssetWeight.div(targetAssetWeight))
|
||||
|
||||
if (displayCurrency.denom === asset.denom) {
|
||||
const hasDisplayCurrency = exchangeRates?.find(
|
||||
(ratesAsset) => ratesAsset.denom === displayCurrency.denom,
|
||||
)
|
||||
|
||||
if (displayCurrency.denom === asset.denom && !hasDisplayCurrency) {
|
||||
useStore.setState({ baseToDisplayCurrencyRatio: 1 / rate.toNumber() })
|
||||
} else {
|
||||
const coin = { denom: asset.denom, amount: rate.toString() }
|
||||
useStore.setState({ exchangeRates: updateExchangeRate(coin, exchangeRates || []) })
|
||||
|
||||
if (typeof poolBase === 'object') {
|
||||
const baseRate = Number(rate.toString()) * Number(poolBase.amount)
|
||||
coin.amount = baseRate.toString()
|
||||
useStore.setState({ exchangeRates: updateExchangeRate(coin, exchangeRates || []) })
|
||||
} else {
|
||||
useStore.setState({ exchangeRates: updateExchangeRate(coin, exchangeRates || []) })
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
|
46
src/hooks/queries/useUsdPrice.tsx
Normal file
46
src/hooks/queries/useUsdPrice.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { updateExchangeRate } from 'functions'
|
||||
import useStore from 'store'
|
||||
import { QUERY_KEYS } from 'types/enums/queryKeys'
|
||||
|
||||
interface CoinPriceData {
|
||||
price: number
|
||||
denom: string
|
||||
symbol: string
|
||||
liquidity: number
|
||||
liquidity_24h_change: number
|
||||
volume_24h: number
|
||||
volume_24h_change: number
|
||||
name: string
|
||||
price_24h_change: number
|
||||
exponent: number
|
||||
display: string
|
||||
}
|
||||
|
||||
export const useUsdPrice = () => {
|
||||
const apiUrl = useStore((s) => s.networkConfig?.priceApiUrl ?? '')
|
||||
const exchangeRates = useStore((s) => s.exchangeRates ?? [])
|
||||
const networkConfig = useStore((s) => s.networkConfig)
|
||||
const displayCurrency = networkConfig?.displayCurrency
|
||||
|
||||
useQuery<CoinPriceData[]>(
|
||||
[QUERY_KEYS.USD_PRICE],
|
||||
async () => {
|
||||
const res = await fetch(apiUrl)
|
||||
return res.json()
|
||||
},
|
||||
{
|
||||
enabled: !!apiUrl && !!exchangeRates.length && !!displayCurrency,
|
||||
staleTime: 30000,
|
||||
refetchInterval: 30000,
|
||||
onSuccess: (data) => {
|
||||
const coin = { denom: 'usd', amount: (1 / data[0].price).toString() }
|
||||
if (displayCurrency.denom === coin.denom) {
|
||||
useStore.setState({ baseToDisplayCurrencyRatio: data[0].price })
|
||||
}
|
||||
|
||||
updateExchangeRate(coin, exchangeRates)
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
38
src/images/statom.svg
Normal file
38
src/images/statom.svg
Normal file
@ -0,0 +1,38 @@
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 2500 2500" style="enable-background:new 0 0 2500 2500;" xml:space="preserve">
|
||||
<circle style="fill:#E50571;" cx="1250" cy="1250" r="1250"/>
|
||||
<circle style="fill:#FFFFFF;" cx="1250" cy="1250" r="128.6"/>
|
||||
<path style="fill:#FFFFFF;" d="M1709.1,1253.5c336.5-233.9,543.2-454.9,491.6-544.9c-33.3-58.1-168.1-50.8-359.4,8.1
|
||||
c-13-22.6-36.8-37.7-64.1-37.7c-41.2,0-74.6,34.5-74.6,77.2c0,2.8,0.2,5.6,0.4,8.3c-69.8,26.5-144.5,58.1-222.5,94.3
|
||||
c-35.3-409.1-124.1-699.3-228-699.3c-103.7,0-192.4,289.3-227.8,697.4c-370.9-173.9-665.9-242-718-152.1
|
||||
c-32.5,56.3,35.9,164.2,173.9,294.7c-1.5,6.1-2.3,12.5-2.3,19.1c0,42.6,33.4,77.2,74.6,77.2c10.5,0,20.5-2.3,29.6-6.3
|
||||
c62.9,52.3,134.6,106.9,213.5,162.2c-336.6,233.9-543.3,454.9-491.6,544.9c51.7,90.1,347.6,22.7,720.2-150.2
|
||||
c7.9,91.7,18.5,177.4,31.4,255.2c-19.5,13.9-32.3,37.2-32.3,63.5c0,37.3,25.6,68.4,59.6,75.6c43.9,188.9,103.6,305.1,169.3,305.1
|
||||
c103.8,0,192.4-289.4,227.8-697.6c371,174,665.9,242.2,717.9,152.3C2250.4,1710.6,2044.5,1488.8,1709.1,1253.5z M1725.6,811.8
|
||||
c13.4,13.3,31.6,21.5,51.7,21.5c37.1,0,67.9-28,73.6-64.8c190.7-59.8,268.1-52.8,295.1-45.4c9.1,2.5,15,11.2,14,20.6
|
||||
c-5.1,56-104.2,157-104.2,157c-132.1,131.9-271.4,241.7-387.7,324.4c-54.8-37.5-112.7-75.2-173.3-112.6
|
||||
c-2-69.4-5.4-136.8-10.2-201.5C1576.7,870.1,1656.5,837.6,1725.6,811.8z M1398,1397.6c-47.4,29.1-96.7,57-146.1,83.3
|
||||
c-33.6-18.8-52-30.1-52-30.1c-46.3-25-92.5-52-137.6-79.9c-2.2-85.5-2.7-164-2.4-227.6c71-43.2,136.9-81.4,190.9-112.1
|
||||
c76.2,41.6,145,81.1,199.8,113.2c0.4,34.7-0.1,54.1-0.1,54.1c1.7,55.9,1.3,112.8-0.5,169.1C1417,1387.3,1398,1397.6,1398,1397.6z
|
||||
M1448,1421.5c-2.5,53.4-6.2,105.5-10.4,154.9c-54.3-25.8-101-49.7-138.3-69.6c24.9-13.7,50-27.8,75.2-42.2
|
||||
C1399.3,1450.2,1423.8,1435.9,1448,1421.5z M1203.7,1506c-45.2,23.2-90.1,44.9-133,65c-3-49.4-5.2-98.4-6.8-145.8
|
||||
c21.7,13.1,43.8,26.1,66.1,39C1154.8,1478.5,1179.3,1492.4,1203.7,1506z M1009,1337.3c-43.2-27.8-85-56-124.2-83.4
|
||||
c41.7-27.4,83.5-53.9,124.1-79.1c-0.4,25.7-0.6,51.7-0.6,77.9C1008.2,1281.1,1008.5,1309.3,1009,1337.3z M1066.8,934.6
|
||||
c44.8,22.5,88.9,45.4,131.2,68c-22.3,12.4-44.8,25-67.3,37.9c-23.7,13.6-47.2,27.3-70.2,41.1c0.8-61.8,2.1-99.1,2.1-99.1
|
||||
C1063.9,966.2,1065.4,950.3,1066.8,934.6z M1304.9,1000.9c54.2-30.2,87.3-47.7,87.3-47.7c16.4-7.6,32.4-15,48-22.1
|
||||
c4.9,59.5,7.5,111.6,9,153.5c-24.3-14.6-48.9-29.2-73.9-43.7C1351.8,1027.3,1328.3,1013.9,1304.9,1000.9z M1496.2,1171.4
|
||||
c53.4,31.9,85.3,51.8,85.3,51.8c15.2,10.6,30,21.1,44.5,31.4c-49.7,34.2-93.9,62.7-129.8,85c0.5-28.7,0.8-57.8,0.8-87.1
|
||||
C1496.9,1225.3,1496.7,1198.2,1496.2,1171.4z M1238.2,214.2c6.7-6.6,17.1-7.4,24.7-2c45.9,32.5,84.4,168.5,84.4,168.5
|
||||
c48.7,180.9,74.7,357.1,88.4,499.3c-59.3,28.4-120.2,59.3-182.3,92.6c-61.6-33.4-122.2-64.5-181.2-93
|
||||
C1124.6,369.7,1208.5,243.6,1238.2,214.2z M619.2,1054c5.3-10.6,8.4-22.7,8.4-35.5c0-42.6-33.4-77.2-74.6-77.2
|
||||
c-16.7,0-32,5.7-44.5,15.2C364.1,818,351.7,750.1,351.7,750.1l-0.1-0.3c-10-23.7,11.1-29.4,11.1-29.4
|
||||
c93.5-17.6,224.7,22.6,224.7,22.6c123.5,28.1,280.4,94.2,432.9,168.6c-4.7,64.4-8.1,131.3-10.1,200.3
|
||||
c-59.6,36.5-116.7,73.2-170.8,109.8C736.8,1148.2,656.4,1084.2,619.2,1054z M736.1,1711.7c-280.1,100.9-369.7,68.8-369.7,68.8h0
|
||||
c-25.7-3.2-19.9-24.4-19.9-24.4c31.5-89.7,132-183.2,132-183.2c86.2-92.8,222-195.4,362.8-290c53.6,36.5,110.1,73.2,169,109.7
|
||||
c2,69.5,5.4,136.9,10.2,201.7C859.5,1666.9,736.1,1711.7,736.1,1711.7z M1393.7,1929c-51.8,293.2-124.2,355-124.2,355
|
||||
c-15.4,20.6-30.9,5.1-30.9,5.1c-62.1-72-93.2-205.8-93.2-205.8c-4.9-15.7-9.5-32.1-13.8-49.3c24.5-12.7,41.3-38.8,41.3-69
|
||||
c0-41.1-31-74.7-70.2-77c-12.9-83.4-22.1-174.2-28.5-265.2c57.8-27.8,117.3-58,177.7-90.4c61.7,33.4,122.3,64.5,181.2,93.1
|
||||
C1416.1,1800.5,1393.7,1929,1393.7,1929z M2147.6,1782.8c-51.1,23.4-188.1-11.5-188.1-11.5c-180.4-48.4-345.3-113.9-475.1-173.2
|
||||
c4.9-65.8,8.4-134.4,10.5-205.1c59.6-36.5,116.7-73.3,170.8-109.9c414.9,300.9,482,436.8,492.5,477.1
|
||||
C2160.7,1769.5,2156.1,1778.9,2147.6,1782.8z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 3.9 KiB |
@ -1,5 +1,6 @@
|
||||
// @index(['./*.ts'], f => `export { ${f.name.split('.')[0]} } from '${f.path}'`)
|
||||
export { position } from './position'
|
||||
export { redBankAssets } from './redBankAssets'
|
||||
export { redBankData } from './redBankData'
|
||||
export { vault } from './vault'
|
||||
// @endindex
|
||||
|
@ -4,7 +4,8 @@ export const position: Position = {
|
||||
amounts: {
|
||||
primary: 0,
|
||||
secondary: 0,
|
||||
borrowed: 0,
|
||||
borrowedPrimary: 0,
|
||||
borrowedSecondary: 0,
|
||||
lp: {
|
||||
amount: '0',
|
||||
primary: 0,
|
||||
@ -15,7 +16,8 @@ export const position: Position = {
|
||||
values: {
|
||||
primary: 0,
|
||||
secondary: 0,
|
||||
borrowed: 0,
|
||||
borrowedPrimary: 0,
|
||||
borrowedSecondary: 0,
|
||||
total: 0,
|
||||
net: 0,
|
||||
},
|
||||
@ -26,4 +28,5 @@ export const position: Position = {
|
||||
},
|
||||
ltv: 0.5,
|
||||
currentLeverage: 1,
|
||||
borrowDenom: null,
|
||||
}
|
||||
|
@ -11,13 +11,14 @@ export const redBankAssets: RedBankAsset[] = [
|
||||
depositBalanceBaseCurrency: 0,
|
||||
depositCap: 1_000_000,
|
||||
depositLiquidity: 5_000,
|
||||
hasOraclePrice: true,
|
||||
isCollateral: true,
|
||||
logo: '',
|
||||
marketLiquidity: '5000',
|
||||
name: 'Atom',
|
||||
symbol: 'ATOM',
|
||||
walletBalance: '100',
|
||||
borrowEnabled: true,
|
||||
depositEnabled: true,
|
||||
},
|
||||
{
|
||||
borrowRate: 30,
|
||||
@ -31,12 +32,13 @@ export const redBankAssets: RedBankAsset[] = [
|
||||
depositBalanceBaseCurrency: 0,
|
||||
depositCap: 1_000_000,
|
||||
depositLiquidity: 5_000,
|
||||
hasOraclePrice: true,
|
||||
isCollateral: true,
|
||||
logo: '',
|
||||
marketLiquidity: '5000',
|
||||
name: 'Osmo',
|
||||
symbol: 'OSMO',
|
||||
walletBalance: '100',
|
||||
borrowEnabled: true,
|
||||
depositEnabled: true,
|
||||
},
|
||||
]
|
||||
|
150
src/mocks/redBankData.ts
Normal file
150
src/mocks/redBankData.ts
Normal file
@ -0,0 +1,150 @@
|
||||
export const redBankData: RedBankData = {
|
||||
//@ts-ignore
|
||||
rbwasmkey: {
|
||||
OSMOMarket: {
|
||||
denom: 'uosmo',
|
||||
max_loan_to_value: '0.59',
|
||||
liquidation_threshold: '0.61',
|
||||
liquidation_bonus: '0.15',
|
||||
reserve_factor: '0.2',
|
||||
interest_rate_model: {
|
||||
optimal_utilization_rate: '0.6',
|
||||
base: '0',
|
||||
slope_1: '0.15',
|
||||
slope_2: '3',
|
||||
},
|
||||
borrow_index: '1.007594298500875037',
|
||||
liquidity_index: '1.002246982368900673',
|
||||
borrow_rate: '0.093460151948703559',
|
||||
liquidity_rate: '0.027951360007279224',
|
||||
indexes_last_updated: 1678369905,
|
||||
collateral_total_scaled: '9114923539298761562',
|
||||
debt_total_scaled: '3389444761162622058',
|
||||
deposit_enabled: true,
|
||||
borrow_enabled: true,
|
||||
deposit_cap: '10000000000000',
|
||||
},
|
||||
OSMOMarketIncentive: {
|
||||
denom: 'uosmo',
|
||||
emission_per_second: '231482',
|
||||
start_time: 1675793700,
|
||||
duration: 2592000,
|
||||
index: '0.000000139928505817',
|
||||
last_updated: 1678369905,
|
||||
},
|
||||
ATOMMarket: {
|
||||
denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2',
|
||||
max_loan_to_value: '0.68',
|
||||
liquidation_threshold: '0.7',
|
||||
liquidation_bonus: '0.15',
|
||||
reserve_factor: '0.2',
|
||||
interest_rate_model: {
|
||||
optimal_utilization_rate: '0.6',
|
||||
base: '0',
|
||||
slope_1: '0.15',
|
||||
slope_2: '3',
|
||||
},
|
||||
borrow_index: '1.007258580949970929',
|
||||
liquidity_index: '1.002076728614660732',
|
||||
borrow_rate: '0.09442052103774879',
|
||||
liquidity_rate: '0.028528751337727877',
|
||||
indexes_last_updated: 1678368967,
|
||||
collateral_total_scaled: '349274630628750224',
|
||||
debt_total_scaled: '131236134520805186',
|
||||
deposit_enabled: true,
|
||||
borrow_enabled: true,
|
||||
deposit_cap: '350000000000',
|
||||
},
|
||||
ATOMMarketIncentive: {
|
||||
denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2',
|
||||
emission_per_second: '106095',
|
||||
start_time: 1675793700,
|
||||
duration: 2592000,
|
||||
index: '0.000001514531327288',
|
||||
last_updated: 1678369638,
|
||||
},
|
||||
stATOMMarket: {
|
||||
denom: 'ibc/C140AFD542AE77BD7DCC83F13FDD8C5E5BB8C4929785E6EC2F4C636F98F17901',
|
||||
max_loan_to_value: '0.68',
|
||||
liquidation_threshold: '0.7',
|
||||
liquidation_bonus: '0.15',
|
||||
reserve_factor: '0.2',
|
||||
interest_rate_model: {
|
||||
optimal_utilization_rate: '0.6',
|
||||
base: '0',
|
||||
slope_1: '0.15',
|
||||
slope_2: '3',
|
||||
},
|
||||
borrow_index: '1.007258580949970929',
|
||||
liquidity_index: '1.002076728614660732',
|
||||
borrow_rate: '0.09442052103774879',
|
||||
liquidity_rate: '0.028528751337727877',
|
||||
indexes_last_updated: 1678368967,
|
||||
collateral_total_scaled: '349274630628750224',
|
||||
debt_total_scaled: '131236134520805186',
|
||||
deposit_enabled: true,
|
||||
borrow_enabled: false,
|
||||
deposit_cap: '350000000000',
|
||||
},
|
||||
stATOMMarketIncentive: {
|
||||
denom: 'ibc/C140AFD542AE77BD7DCC83F13FDD8C5E5BB8C4929785E6EC2F4C636F98F17901',
|
||||
emission_per_second: '106095',
|
||||
start_time: 1675793700,
|
||||
duration: 2592000,
|
||||
index: '0.000001514531327288',
|
||||
last_updated: 1678369638,
|
||||
},
|
||||
axlUSDCMarket: {
|
||||
denom: 'ibc/D189335C6E4A68B513C10AB227BF1C1D38C746766278BA3EEB4FB14124F1D858',
|
||||
max_loan_to_value: '0.74',
|
||||
liquidation_threshold: '0.75',
|
||||
liquidation_bonus: '0.1',
|
||||
reserve_factor: '0.2',
|
||||
interest_rate_model: {
|
||||
optimal_utilization_rate: '0.8',
|
||||
base: '0',
|
||||
slope_1: '0.2',
|
||||
slope_2: '2',
|
||||
},
|
||||
borrow_index: '1.010875731969102527',
|
||||
liquidity_index: '1.00525118991986623',
|
||||
borrow_rate: '0.193514001505802393',
|
||||
liquidity_rate: '0.11983254009212061',
|
||||
indexes_last_updated: 1678369620,
|
||||
collateral_total_scaled: '1494717184985439254',
|
||||
debt_total_scaled: '1158255523619905561',
|
||||
deposit_enabled: true,
|
||||
borrow_enabled: true,
|
||||
deposit_cap: '1500000000000',
|
||||
},
|
||||
axlUSDCMarketIncentive: {
|
||||
denom: 'ibc/D189335C6E4A68B513C10AB227BF1C1D38C746766278BA3EEB4FB14124F1D858',
|
||||
emission_per_second: '48225',
|
||||
start_time: 1675793700,
|
||||
duration: 2592000,
|
||||
index: '0.000000143742920378',
|
||||
last_updated: 1678369620,
|
||||
},
|
||||
collateral: [
|
||||
{
|
||||
denom: 'ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2',
|
||||
amount_scaled: '2559593418324',
|
||||
amount: '2564911',
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
denom: 'ibc/D189335C6E4A68B513C10AB227BF1C1D38C746766278BA3EEB4FB14124F1D858',
|
||||
amount_scaled: '20000000000000',
|
||||
amount: '20105061',
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
denom: 'uosmo',
|
||||
amount_scaled: '48000037051741',
|
||||
amount: '48107901',
|
||||
enabled: true,
|
||||
},
|
||||
],
|
||||
unclaimedRewards: '4679062',
|
||||
},
|
||||
}
|
@ -65,6 +65,11 @@ const EditVault = (props: Props) => {
|
||||
[prevPosition.values.total, position.values.total],
|
||||
)
|
||||
|
||||
const borrowKey =
|
||||
props.activeVault.position.borrowDenom === props.activeVault.denoms.primary
|
||||
? 'borrowedPrimary'
|
||||
: 'borrowedSecondary'
|
||||
|
||||
const { repayActions, repayFunds, repayFee } = useRepayPosition({
|
||||
prevPosition,
|
||||
repayPosition,
|
||||
@ -131,7 +136,8 @@ const EditVault = (props: Props) => {
|
||||
const actionButtons = useMemo(
|
||||
() => (
|
||||
<>
|
||||
{prevPosition.amounts.borrowed > 0 && (
|
||||
{(prevPosition.amounts.borrowedPrimary > 0 ||
|
||||
prevPosition.amounts.borrowedSecondary > 0) && (
|
||||
<Button
|
||||
onClick={() => setIsRepay(!isRepay)}
|
||||
text={isRepay ? t('fields.managePosition') : t('fields.repayDebt')}
|
||||
@ -158,7 +164,8 @@ const EditVault = (props: Props) => {
|
||||
setIsRepay,
|
||||
lockupTimeAndUnit.time,
|
||||
lockupTimeAndUnit.unit,
|
||||
prevPosition.amounts.borrowed,
|
||||
prevPosition.amounts.borrowedPrimary,
|
||||
prevPosition.amounts.borrowedSecondary,
|
||||
],
|
||||
)
|
||||
|
||||
@ -200,9 +207,13 @@ const EditVault = (props: Props) => {
|
||||
!isRepay &&
|
||||
(prevPosition.amounts.primary > position.amounts.primary ||
|
||||
prevPosition.amounts.secondary > position.amounts.secondary ||
|
||||
prevPosition.amounts.borrowed > position.amounts.borrowed)
|
||||
prevPosition.amounts.borrowedPrimary > position.amounts.borrowedPrimary ||
|
||||
prevPosition.amounts.borrowedSecondary > position.amounts.borrowedSecondary)
|
||||
|
||||
const isNotRepaying = isRepay && repayPosition.amounts.borrowed >= prevPosition.amounts.borrowed
|
||||
const isNotRepaying =
|
||||
isRepay &&
|
||||
repayPosition.amounts.borrowedPrimary >= prevPosition.amounts.borrowedPrimary &&
|
||||
repayPosition.amounts.borrowedSecondary >= prevPosition.amounts.borrowedSecondary
|
||||
const isWithoutFee = (!isRepay && !editFee) || (isRepay && !repayFee)
|
||||
const isSameAmounts =
|
||||
(isEqual(prevPosition.amounts, position.amounts) && !isRepay) ||
|
||||
@ -280,7 +291,7 @@ const EditVault = (props: Props) => {
|
||||
type={isRepay ? 'repay' : showUnlockBtn ? 'unlock' : 'edit'}
|
||||
position={position}
|
||||
prevPosition={prevPosition}
|
||||
repayAmount={prevPosition.amounts.borrowed - repayPosition.amounts.borrowed}
|
||||
repayAmount={prevPosition.amounts[borrowKey] - repayPosition.amounts[borrowKey]}
|
||||
vault={props.activeVault}
|
||||
className={styles.tooltip}
|
||||
/>
|
||||
|
@ -56,6 +56,11 @@ const RepayVault = (props: Props) => {
|
||||
|
||||
const disableConfirmBtn = !repayFee || isSameAmounts
|
||||
|
||||
const borrowKey =
|
||||
props.activeVault.position.borrowDenom === props.activeVault.denoms.primary
|
||||
? 'borrowedPrimary'
|
||||
: 'borrowedSecondary'
|
||||
|
||||
return (
|
||||
<>
|
||||
<Notification
|
||||
@ -102,7 +107,7 @@ const RepayVault = (props: Props) => {
|
||||
type={'repay'}
|
||||
position={repayPosition}
|
||||
prevPosition={prevPosition}
|
||||
repayAmount={prevPosition.amounts.borrowed - repayPosition.amounts.borrowed}
|
||||
repayAmount={prevPosition.amounts[borrowKey] - repayPosition.amounts[borrowKey]}
|
||||
vault={props.activeVault}
|
||||
className={styles.tooltip}
|
||||
/>
|
||||
|
@ -115,6 +115,11 @@ const commonSlice = (
|
||||
config.NETWORK_CONFIG.rpcUrl = serializeUrl(config.NETWORK_CONFIG.rpcUrl)
|
||||
config.NETWORK_CONFIG.restUrl = serializeUrl(config.NETWORK_CONFIG.restUrl)
|
||||
|
||||
const storageDisplayCurrency = localStorage.getItem('displayCurrency')
|
||||
if (storageDisplayCurrency) {
|
||||
config.NETWORK_CONFIG.displayCurrency = JSON.parse(storageDisplayCurrency)
|
||||
}
|
||||
|
||||
set({
|
||||
otherAssets: config.NETWORK_CONFIG.assets.other,
|
||||
whitelistedAssets: config.NETWORK_CONFIG.assets.whitelist,
|
||||
|
@ -25,9 +25,16 @@ const oraclesSlice = (set: NamedSet<Store>, get: GetState<Store>): OraclesSlice
|
||||
const baseCurrency = get().baseCurrency
|
||||
const networkConfig = get().networkConfig
|
||||
const displayCurrency = networkConfig?.displayCurrency
|
||||
const assets = [...whitelistedAssets, ...otherAssets]
|
||||
const exchangeRatesState = get().exchangeRatesState
|
||||
const assets: Asset[] = [...whitelistedAssets, ...otherAssets]
|
||||
|
||||
if (!coin || !exchangeRates || !assets.length || !displayCurrency) {
|
||||
if (
|
||||
!coin ||
|
||||
exchangeRatesState === State.INITIALISING ||
|
||||
!exchangeRates?.find((rate) => rate.denom === displayCurrency.denom) ||
|
||||
!assets.length ||
|
||||
!displayCurrency
|
||||
) {
|
||||
return 0
|
||||
}
|
||||
|
||||
@ -88,13 +95,19 @@ const oraclesSlice = (set: NamedSet<Store>, get: GetState<Store>): OraclesSlice
|
||||
|
||||
const wasmQueryResults = data.prices
|
||||
const exchangeRates: Coin[] = get().exchangeRates ?? []
|
||||
const baseCurrency = get().baseCurrency
|
||||
const networkConfig = get().networkConfig
|
||||
const displayCurrency = networkConfig?.displayCurrency
|
||||
|
||||
get()
|
||||
.whitelistedAssets?.filter((asset: Asset) => !!asset.denom)
|
||||
.forEach((asset: Asset) => {
|
||||
const denom = asset.denom
|
||||
const hasBaseCurrency = exchangeRates?.find(
|
||||
(ratesAsset) => ratesAsset.denom === baseCurrency.denom,
|
||||
)
|
||||
|
||||
if (denom === get().baseCurrency.denom) {
|
||||
if (denom === baseCurrency.denom && !hasBaseCurrency) {
|
||||
exchangeRates.push({ denom, amount: '1' })
|
||||
return
|
||||
}
|
||||
@ -106,6 +119,11 @@ const oraclesSlice = (set: NamedSet<Store>, get: GetState<Store>): OraclesSlice
|
||||
denom,
|
||||
amount: typeof exchangeRateResult === 'string' ? exchangeRateResult || '0.00' : '0.00',
|
||||
}
|
||||
if (asset.denom === displayCurrency.denom) {
|
||||
set({
|
||||
baseToDisplayCurrencyRatio: 1 / Number(exchangeRate.amount),
|
||||
})
|
||||
}
|
||||
updateExchangeRate(exchangeRate, exchangeRates)
|
||||
})
|
||||
set({
|
||||
|
@ -119,6 +119,8 @@ const redBankSlice = (set: NamedSet<Store>, get: GetState<Store>): RedBankSlice
|
||||
incentiveInfo,
|
||||
isCollateral: true,
|
||||
depositCap: depositCap,
|
||||
borrowEnabled: marketInfo?.borrow_enabled ?? false,
|
||||
depositEnabled: marketInfo?.deposit_enabled ?? false,
|
||||
}
|
||||
redBankAsset.subRows = [{ ...redBankAsset }]
|
||||
redBankAssets.push(redBankAsset)
|
||||
|
@ -324,25 +324,50 @@ export const vaultsSlice = (set: NamedSet<Store>, get: GetState<Store>): VaultsS
|
||||
(unlockTime) => unlockTime?.vaultAddress === curr.address,
|
||||
)?.unlockAtTimestamp
|
||||
|
||||
let primarySupplyAmount = Number(
|
||||
let primaryAmount = Number(
|
||||
findByDenom(primaryAndSecondaryAmount.coins, curr.denoms.primary)?.amount || 0,
|
||||
)
|
||||
const secondaryAmount = Number(
|
||||
let secondaryAmount = Number(
|
||||
findByDenom(primaryAndSecondaryAmount.coins, curr.denoms.secondary)?.amount || 0,
|
||||
)
|
||||
const borrowedAmount = Number(creditAccountPosition.debts[0]?.amount || 0)
|
||||
|
||||
if (borrowedAmount > secondaryAmount) {
|
||||
const swappedToPrimary = Math.round(
|
||||
get().convertToBaseCurrency({
|
||||
denom: curr.denoms.secondary,
|
||||
amount: (borrowedAmount - secondaryAmount).toString(),
|
||||
}),
|
||||
)
|
||||
primarySupplyAmount -= swappedToPrimary
|
||||
let borrowedPrimaryAmount = 0
|
||||
let borrowedSecondaryAmount = 0
|
||||
|
||||
const debt = creditAccountPosition.debts[0]
|
||||
if (debt) {
|
||||
if (debt.denom === curr.denoms.primary) {
|
||||
borrowedPrimaryAmount = Number(debt.amount)
|
||||
} else {
|
||||
borrowedSecondaryAmount = Number(debt.amount)
|
||||
}
|
||||
}
|
||||
|
||||
const secondarySupplyAmount = Math.max(secondaryAmount - borrowedAmount, 0)
|
||||
const borrowedDenom: string = creditAccountPosition.debts[0]?.denom || ''
|
||||
|
||||
if (borrowedPrimaryAmount > primaryAmount) {
|
||||
const swapped = Math.round(
|
||||
get().convertToBaseCurrency({
|
||||
denom: borrowedDenom,
|
||||
amount: (borrowedPrimaryAmount - primaryAmount).toString(),
|
||||
}),
|
||||
)
|
||||
secondaryAmount -= swapped
|
||||
}
|
||||
|
||||
if (borrowedSecondaryAmount > secondaryAmount) {
|
||||
const swapped = Math.round(
|
||||
get().convertToBaseCurrency({
|
||||
denom: borrowedDenom,
|
||||
amount: (borrowedSecondaryAmount - secondaryAmount).toString(),
|
||||
}),
|
||||
)
|
||||
primaryAmount -= swapped
|
||||
}
|
||||
|
||||
const primarySupplyAmount = Math.max(primaryAmount - borrowedPrimaryAmount, 0)
|
||||
const secondarySupplyAmount = Math.max(secondaryAmount - borrowedSecondaryAmount, 0)
|
||||
const borrowedAmount = Math.max(borrowedPrimaryAmount, borrowedSecondaryAmount)
|
||||
|
||||
const convertToBaseCurrency = get().convertToBaseCurrency
|
||||
const redBankAssets = get().redBankAssets
|
||||
@ -357,14 +382,15 @@ export const vaultsSlice = (set: NamedSet<Store>, get: GetState<Store>): VaultsS
|
||||
})
|
||||
|
||||
const borrowedValue = convertToBaseCurrency({
|
||||
denom: curr.denoms.secondary,
|
||||
denom: borrowedDenom,
|
||||
amount: borrowedAmount.toString(),
|
||||
})
|
||||
|
||||
const values = {
|
||||
primary: primaryValue,
|
||||
secondary: secondaryValue,
|
||||
borrowed: borrowedValue,
|
||||
borrowedPrimary: borrowedDenom === curr.denoms.primary ? borrowedValue : 0,
|
||||
borrowedSecondary: borrowedDenom === curr.denoms.secondary ? borrowedValue : 0,
|
||||
net: primaryValue + secondaryValue,
|
||||
total: primaryValue + secondaryValue + borrowedValue,
|
||||
}
|
||||
@ -390,7 +416,8 @@ export const vaultsSlice = (set: NamedSet<Store>, get: GetState<Store>): VaultsS
|
||||
amounts: {
|
||||
primary: primarySupplyAmount,
|
||||
secondary: secondarySupplyAmount,
|
||||
borrowed: borrowedAmount,
|
||||
borrowedPrimary: borrowedDenom === curr.denoms.primary ? borrowedAmount : 0,
|
||||
borrowedSecondary: borrowedDenom === curr.denoms.secondary ? borrowedAmount : 0,
|
||||
lp: {
|
||||
amount: vaultTokenAmounts.unlocking,
|
||||
primary: Number(
|
||||
@ -416,6 +443,7 @@ export const vaultsSlice = (set: NamedSet<Store>, get: GetState<Store>): VaultsS
|
||||
ltv: leverageToLtv(leverage),
|
||||
...(unlockTime ? { unlockAtTimestamp: unlockTime } : {}),
|
||||
status: getPositionStatus(unlockTime),
|
||||
borrowDenom: borrowedDenom,
|
||||
}
|
||||
|
||||
prev.activeVaults.push({ ...curr, position })
|
||||
|
@ -7,6 +7,7 @@
|
||||
atom: $colorTokenATOM;
|
||||
axlusdc: $colorTokenAxlUSDC;
|
||||
juno: $colorTokenJUNO;
|
||||
statom: $colorTokenStATOM;
|
||||
|
||||
/* COLORS */
|
||||
success: $colorInfoProfit;
|
||||
|
@ -1,43 +1,45 @@
|
||||
@use 'sass:math';
|
||||
$rem-base: 15px;
|
||||
$rem-base: 16px;
|
||||
|
||||
/* Colors */
|
||||
$colorWhite: #ffffff;
|
||||
$colorGrey: #3a3c49;
|
||||
$colorGreyLight: #bfbfbf;
|
||||
$colorGreyHighlight: #4c4c4c;
|
||||
$colorGreyMedium: #5f697a;
|
||||
$colorGreyDark: #1a1c25;
|
||||
$colorWhite: #f5f5f5;
|
||||
$colorGrey: #bdbdbd;
|
||||
$colorGreyLight: #e0e0e0;
|
||||
$colorGreyHighlight: #efefef;
|
||||
$colorGreyMedium: #9e9e9e;
|
||||
$colorGreyDark: #616161;
|
||||
|
||||
/* CI Colors */
|
||||
$colorPrimary: #14a693;
|
||||
$colorPrimaryHighlight: #15bfa9;
|
||||
$colorPrimaryAlpha: rgba(20, 166, 147, 0.15);
|
||||
$colorSecondary: #524bb1;
|
||||
$colorSecondaryHighlight: #6962cc;
|
||||
$colorSecondaryDark: #440b37;
|
||||
$colorSecondaryAlpha: rgba(68, 11, 55, 0.7);
|
||||
$colorAccent: #2c1b2f;
|
||||
$colorAccentHighlight: #421f32;
|
||||
$colorAccentDark: #341a2a;
|
||||
$colorAccentInverted: #345dff;
|
||||
$colorPrimary: #0000ff;
|
||||
$colorPrimaryHighlight: #6962cc;
|
||||
$colorPrimaryAlpha: rgba(0, 0, 255, 0.05);
|
||||
$colorSecondary: #212121;
|
||||
$colorSecondaryHighlight: #424242;
|
||||
$colorSecondaryDark: #111111;
|
||||
$colorSecondaryAlpha: rgba(17, 17, 17, 0.15);
|
||||
$colorAccent: $colorGreyMedium;
|
||||
$colorAccentHighlight: $colorGreyMedium;
|
||||
$colorAccentDark: $colorGreyDark;
|
||||
$colorAccentInverted: $colorGreyLight;
|
||||
|
||||
/* Info Colors */
|
||||
$colorInfoProfit: #41a4a9;
|
||||
$colorInfoLoss: #f96363;
|
||||
$colorInfoWarning: #c83333;
|
||||
$colorInfoVoteAgainst: #eb9e49;
|
||||
$colorInfoProfit: #c4e7e9;
|
||||
$colorInfoLoss: #c8aaaa;
|
||||
$colorInfoWarning: #ffb5b5;
|
||||
$colorInfoVoteAgainst: #6c5a46;
|
||||
|
||||
/* Token Colors */
|
||||
$colorTokenMARS: #a03b45;
|
||||
$colorTokenMARS: #dd5b65;
|
||||
$colorTokenOSMO: #9f1ab9;
|
||||
$colorTokenATOM: #6f7390;
|
||||
$colorTokenAxlUSDC: #478edc;
|
||||
$colorTokenJUNO: black;
|
||||
$colorTokenStATOM: #e50571;
|
||||
|
||||
$colorGradientOSMO: linear-gradient(to bottom, #3a02e2, #e700ca);
|
||||
$colorGradientATOM: linear-gradient(to bottom, #2e3148, #6f7390);
|
||||
$colorGradientAxlUSDC: linear-gradient(to bottom, #1f5c9e, #478edc);
|
||||
$colorGradientStATOM: linear-gradient(to bottom, #e50571, #fb5da9);
|
||||
|
||||
/* Alpha Colors */
|
||||
$alphaWhite10: rgba(255, 255, 255, 0.1);
|
||||
@ -60,32 +62,29 @@ $alphaBlack80: rgba(0, 0, 0, 0.8);
|
||||
$alphaBlack90: rgba(0, 0, 0, 0.9);
|
||||
|
||||
/* Background Colors */
|
||||
$backgroundBody: #562a3b;
|
||||
$backgroundBodyDark: #141621;
|
||||
$backgroundInTile: $alphaBlack30;
|
||||
$backgroundFooter: $alphaBlack20;
|
||||
$backgroundBody: $colorGrey;
|
||||
$backgroundBodyDark: $backgroundBody;
|
||||
$backgroundInTile: transparent;
|
||||
$backgroundFooter: transparent;
|
||||
|
||||
/* Slider Colors */
|
||||
$sliderThumb: $colorWhite;
|
||||
$sliderMark: $colorGreyLight;
|
||||
$sliderThumb: $colorGreyDark;
|
||||
$sliderMark: $colorGreyDark;
|
||||
|
||||
/* Tooltip Colors */
|
||||
$tooltipIconColor: $alphaWhite20;
|
||||
$tableSort: $alphaWhite20;
|
||||
$tableSortActive: $colorWhite;
|
||||
$tableHeader: $alphaWhite50;
|
||||
$tooltipIconColor: $alphaBlack60;
|
||||
|
||||
/* Table Colors */
|
||||
$tableBorder: $alphaWhite10;
|
||||
$tableBorderEnd: $alphaWhite80;
|
||||
$tableSort: $alphaWhite20;
|
||||
$tableSortActive: $colorWhite;
|
||||
$tableHeader: $alphaWhite40;
|
||||
$tableLabel: $alphaWhite60;
|
||||
$tableBorder: $alphaBlack30;
|
||||
$tableBorderEnd: $alphaBlack80;
|
||||
$tableSort: $alphaBlack20;
|
||||
$tableSortActive: $alphaBlack90;
|
||||
$tableHeader: $alphaBlack40;
|
||||
$tableLabel: $colorSecondaryDark;
|
||||
|
||||
/* Graph Colors */
|
||||
$graphLiquidationsLine: $alphaWhite70;
|
||||
$graphAxis: $alphaWhite40;
|
||||
$graphLiquidationsLine: $alphaBlack70;
|
||||
$graphAxis: $alphaBlack40;
|
||||
|
||||
/* Shadows */
|
||||
$shadowInset: inset 0px 2px 2px rgba(0, 0, 0, 0.25);
|
||||
@ -96,43 +95,40 @@ $shadowInset: inset 0px 2px 2px rgba(0, 0, 0, 0.25);
|
||||
|
||||
/* Devider */
|
||||
@mixin devider10 {
|
||||
border-bottom: 1px solid $alphaWhite10;
|
||||
border-bottom: 1px solid $alphaBlack10;
|
||||
}
|
||||
|
||||
@mixin devider20 {
|
||||
border-bottom: 1px solid $alphaWhite20;
|
||||
border-bottom: 1px solid $alphaBlack20;
|
||||
}
|
||||
|
||||
@mixin devider40 {
|
||||
border-bottom: 1px solid $alphaWhite40;
|
||||
border-bottom: 1px solid $alphaBlack40;
|
||||
}
|
||||
|
||||
@mixin devider60 {
|
||||
border-bottom: 1px solid $alphaWhite60;
|
||||
border-bottom: 1px solid $alphaBlack60;
|
||||
}
|
||||
|
||||
/* Backgrounds */
|
||||
@mixin bgBody {
|
||||
background-color: $backgroundBody;
|
||||
background-size: 100% auto;
|
||||
background-image: url('../images/bg.svg');
|
||||
background-position: center top;
|
||||
}
|
||||
|
||||
@mixin bgTableHover {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
@mixin bgBodyDark {
|
||||
background-color: $backgroundBodyDark;
|
||||
}
|
||||
|
||||
@mixin bgTableHover {
|
||||
background-color: rgba($colorPrimary, 0.2);
|
||||
}
|
||||
|
||||
@mixin bgProposalActive {
|
||||
background: linear-gradient(90deg, #10aa93 2.6%, #248aa9 97.92%);
|
||||
}
|
||||
|
||||
@mixin bgProposalHover {
|
||||
background-color: #05252f;
|
||||
background-color: $colorGreyMedium;
|
||||
}
|
||||
|
||||
@mixin bgTile($deg: 99.79) {
|
||||
@ -144,7 +140,7 @@ $shadowInset: inset 0px 2px 2px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
@mixin bgInTile {
|
||||
background: $alphaBlack30;
|
||||
background: $backgroundInTile;
|
||||
}
|
||||
|
||||
@mixin bgOverlay {
|
||||
@ -161,11 +157,11 @@ $shadowInset: inset 0px 2px 2px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
@mixin bgTileDevider {
|
||||
background-color: $alphaWhite60;
|
||||
background-color: $alphaBlack60;
|
||||
}
|
||||
|
||||
@mixin bgDevider {
|
||||
background-color: $alphaWhite20;
|
||||
background-color: $alphaBlack20;
|
||||
}
|
||||
|
||||
@mixin bgInput {
|
||||
@ -174,68 +170,60 @@ $shadowInset: inset 0px 2px 2px rgba(0, 0, 0, 0.25);
|
||||
|
||||
@mixin bgPrimary {
|
||||
background-color: $colorPrimary;
|
||||
color: $colorWhite;
|
||||
}
|
||||
|
||||
@mixin bgSecondary {
|
||||
background-color: $colorSecondary;
|
||||
color: $colorWhite;
|
||||
}
|
||||
|
||||
@mixin bgTertiary {
|
||||
background-color: rgba(82, 75, 177, 0.5);
|
||||
background-color: $alphaBlack60;
|
||||
color: $colorWhite;
|
||||
}
|
||||
|
||||
@mixin bgLimit {
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
#15bfa9 20.9%,
|
||||
#5e4bb1 49.68%,
|
||||
#382685 82.55%,
|
||||
#c83333 100%
|
||||
);
|
||||
background: $colorPrimary;
|
||||
}
|
||||
|
||||
@mixin bgLimitOpacity {
|
||||
background: linear-gradient(
|
||||
to right,
|
||||
#15bfa830 20.9%,
|
||||
#5e4bb130 49.68%,
|
||||
#38268530 82.55%,
|
||||
#c8333330 100%
|
||||
);
|
||||
background: $colorPrimary;
|
||||
}
|
||||
|
||||
@mixin bgHatched {
|
||||
background-image: linear-gradient(
|
||||
135deg,
|
||||
transparent 33.33%,
|
||||
#826d6b 33.33%,
|
||||
#826d6b 50%,
|
||||
transparent 50%,
|
||||
transparent 83.33%,
|
||||
#826d6b 83.33%,
|
||||
#826d6b 100%
|
||||
#1a1c25 33.33%,
|
||||
rgba(255, 255, 255, 0.2) 33.33%,
|
||||
rgba(255, 255, 255, 0.2) 50%,
|
||||
#1a1c25 50%,
|
||||
#1a1c25 83.33%,
|
||||
rgba(255, 255, 255, 0.2) 83.33%,
|
||||
rgba(255, 255, 255, 0.2) 100%
|
||||
);
|
||||
background-size: 5px 5px;
|
||||
}
|
||||
|
||||
/* GLOWS */
|
||||
/* GLOWS */
|
||||
@mixin glowXS {
|
||||
filter: blur(1px);
|
||||
display: none;
|
||||
}
|
||||
@mixin glowS {
|
||||
filter: blur(3px);
|
||||
display: none;
|
||||
}
|
||||
@mixin glowM {
|
||||
filter: blur(4px);
|
||||
display: none;
|
||||
}
|
||||
@mixin glowL {
|
||||
filter: blur(5px);
|
||||
display: none;
|
||||
}
|
||||
@mixin glowXL {
|
||||
filter: blur(8px);
|
||||
display: none;
|
||||
}
|
||||
@mixin glowXXL {
|
||||
filter: blur(24px);
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Typography */
|
||||
@ -243,11 +231,11 @@ $fontWeightLight: 300;
|
||||
$fontWeightRegular: 400;
|
||||
$fontWeightSemibold: 600;
|
||||
|
||||
$fontColorDarkPrimary: $colorSecondaryDark;
|
||||
$fontColorDarkSecondary: rgba(68, 8, 55, 0.7);
|
||||
$fontColorLightPrimary: $colorWhite;
|
||||
$fontColorLightSecondary: $alphaWhite60;
|
||||
$fontColorLightTertiary: rgba(255, 255, 255, 0.4);
|
||||
$fontColorDarkPrimary: $colorWhite;
|
||||
$fontColorDarkSecondary: $colorSecondaryDark;
|
||||
$fontColorLightPrimary: $colorSecondaryDark;
|
||||
$fontColorLightSecondary: $alphaBlack30;
|
||||
$fontColorLightTertiary: $colorSecondaryDark;
|
||||
$fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoH1 {
|
||||
@ -263,8 +251,6 @@ $fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoH2caps {
|
||||
@include typoH2;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(9);
|
||||
}
|
||||
|
||||
@mixin typoH3 {
|
||||
@ -274,8 +260,6 @@ $fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoH3caps {
|
||||
font-size: rem-calc(30.42);
|
||||
line-height: space(10);
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@mixin typoH4 {
|
||||
@ -286,8 +270,6 @@ $fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoH4caps {
|
||||
@include typoH4;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(3);
|
||||
}
|
||||
|
||||
@mixin typoXXL {
|
||||
@ -297,9 +279,7 @@ $fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoXXLcaps {
|
||||
@include typoXXL;
|
||||
font-weight: $fontWeightRegular;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(3);
|
||||
font-weight: $fontWeightLight;
|
||||
}
|
||||
|
||||
@mixin typoXL {
|
||||
@ -309,8 +289,6 @@ $fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoXLcaps {
|
||||
@include typoXL;
|
||||
letter-spacing: rem-calc(5);
|
||||
text-transform: uppercase;
|
||||
font-weight: $fontWeightLight;
|
||||
}
|
||||
|
||||
@ -322,8 +300,6 @@ $fontColorLtv: $colorWhite;
|
||||
@mixin typoLcaps {
|
||||
@include typoL;
|
||||
font-weight: $fontWeightSemibold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(3);
|
||||
}
|
||||
|
||||
@mixin typoM {
|
||||
@ -333,7 +309,6 @@ $fontColorLtv: $colorWhite;
|
||||
|
||||
@mixin typoMcaps {
|
||||
@include typoM;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@mixin typoS {
|
||||
@ -344,8 +319,6 @@ $fontColorLtv: $colorWhite;
|
||||
@mixin typoScaps {
|
||||
@include typoS;
|
||||
font-weight: $fontWeightSemibold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(3);
|
||||
}
|
||||
|
||||
@mixin typoXS {
|
||||
@ -356,8 +329,6 @@ $fontColorLtv: $colorWhite;
|
||||
@mixin typoXScaps {
|
||||
@include typoXS;
|
||||
font-weight: $fontWeightSemibold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(3);
|
||||
}
|
||||
|
||||
@mixin typoXXS {
|
||||
@ -368,8 +339,6 @@ $fontColorLtv: $colorWhite;
|
||||
@mixin typoXXScaps {
|
||||
@include typoXXS;
|
||||
font-weight: $fontWeightSemibold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(2);
|
||||
}
|
||||
|
||||
@mixin typoXXXS {
|
||||
@ -380,20 +349,15 @@ $fontColorLtv: $colorWhite;
|
||||
@mixin typoXXXScaps {
|
||||
@include typoXXXS;
|
||||
font-weight: $fontWeightSemibold;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(2);
|
||||
}
|
||||
|
||||
@mixin typoButton {
|
||||
font-family: Inter, sans-serif;
|
||||
@include typoS;
|
||||
font-weight: $fontWeightSemibold;
|
||||
}
|
||||
|
||||
@mixin typoNav {
|
||||
@include typoL;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: rem-calc(5);
|
||||
}
|
||||
|
||||
@mixin typoNetwork {
|
||||
@ -467,100 +431,70 @@ $spacingBase: 4;
|
||||
|
||||
/* LAYOUTS */
|
||||
@mixin layoutTile {
|
||||
@include bgTile;
|
||||
border: rem-calc(7) solid $colorAccentHighlight;
|
||||
border-radius: $borderRadiusXL;
|
||||
padding: space(1);
|
||||
background: $colorGreyHighlight;
|
||||
border: 2px solid $colorWhite;
|
||||
box-shadow: 0 0 0 3px $colorGreyHighlight, 12px 12px 0 0 rgb(0 0 0 / 50%) !important;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
@mixin layoutTooltip {
|
||||
@include padding(2, 4);
|
||||
@include bgTooltip;
|
||||
@include typoS;
|
||||
box-shadow: 0 rem-calc(3) rem-calc(4) rgba(0, 0, 0, 0.14),
|
||||
0 rem-calc(3) rem-calc(3) rgba(0, 0, 0, 0.12), 0 rem-calc(1) rem-calc(8) rgba(0, 0, 0, 0.2);
|
||||
border-radius: $borderRadiusL;
|
||||
max-width: rem-calc(350);
|
||||
padding: space(3);
|
||||
background: $colorGreyLight;
|
||||
border: 1px solid $colorSecondaryDark;
|
||||
}
|
||||
|
||||
@mixin layoutPopover {
|
||||
@include bgPopover;
|
||||
box-shadow: 0 rem-calc(2) rem-calc(2) rgba(0, 0, 0, 0.14),
|
||||
0 rem-calc(1) rem-calc(5) rgba(0, 0, 0, 0.2);
|
||||
border-radius: $borderRadiusL;
|
||||
padding: space(3);
|
||||
background: $colorGreyLight;
|
||||
border: 1px solid $colorSecondaryDark;
|
||||
}
|
||||
|
||||
@mixin layoutIncentiveButton {
|
||||
--border-width: 3px;
|
||||
background-color: #946582;
|
||||
position: relative;
|
||||
border: none;
|
||||
margin: rem-calc(3) rem-calc(11) 0 0;
|
||||
height: rem-calc(28);
|
||||
|
||||
&:hover {
|
||||
border: none;
|
||||
background-color: darken(#946582, 10%);
|
||||
}
|
||||
|
||||
&::after {
|
||||
border-radius: $borderRadiusXXL;
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: calc(-1 * var(--border-width));
|
||||
left: calc(-1 * var(--border-width));
|
||||
z-index: -1;
|
||||
width: calc(100% + var(--border-width) * 2);
|
||||
height: calc(100% + var(--border-width) * 2);
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(105, 98, 204, 0.8) 0%,
|
||||
rgba(105, 98, 204, 1) 40%,
|
||||
rgba(255, 255, 255, 1) 50%,
|
||||
rgba(105, 98, 204, 1) 60%,
|
||||
rgba(105, 98, 204, 0.8) 100%
|
||||
);
|
||||
background-size: 300% 300%;
|
||||
background-position: 0 50%;
|
||||
animation: moveGradient 6s alternate infinite;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin layoutLogo {
|
||||
> svg {
|
||||
width: rem-calc(50);
|
||||
height: rem-calc(50);
|
||||
width: rem-calc(57);
|
||||
height: rem-calc(57);
|
||||
|
||||
path {
|
||||
stroke: $fontColorLightPrimary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin layoutGlobal {
|
||||
opacity: 1 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
$buttonBorder: $alphaWhite40;
|
||||
$buttonBorderHover: $colorWhite;
|
||||
$buttonBorder: $alphaBlack40;
|
||||
$buttonBorderHover: $colorSecondaryDark;
|
||||
|
||||
@mixin buttonS {
|
||||
@include typoS;
|
||||
@include padding(1.5, 5);
|
||||
min-height: rem-calc(32);
|
||||
height: rem-calc(32);
|
||||
}
|
||||
|
||||
@mixin buttonM {
|
||||
@include typoM;
|
||||
@include padding(2.5, 6);
|
||||
min-height: rem-calc(40);
|
||||
height: rem-calc(40);
|
||||
}
|
||||
|
||||
@mixin buttonL {
|
||||
@include typoL;
|
||||
@include padding(2.5, 6);
|
||||
min-height: rem-calc(56);
|
||||
height: rem-calc(56);
|
||||
}
|
||||
|
||||
@mixin buttonSolidPrimary {
|
||||
&.primary {
|
||||
background-color: $colorPrimary;
|
||||
color: $colorWhite;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
@ -576,6 +510,7 @@ $buttonBorderHover: $colorWhite;
|
||||
@mixin buttonSolidSecondary {
|
||||
&.secondary {
|
||||
background-color: $colorSecondary;
|
||||
color: $colorWhite;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
@ -590,34 +525,33 @@ $buttonBorderHover: $colorWhite;
|
||||
|
||||
@mixin buttonSolidTertiary {
|
||||
&.tertiary {
|
||||
background-color: $colorSecondaryAlpha;
|
||||
border: 1px solid $alphaWhite60;
|
||||
background-color: $colorSecondaryDark;
|
||||
color: $colorWhite;
|
||||
border: 1px solid $alphaBlack30;
|
||||
|
||||
&:hover,
|
||||
&:focus {
|
||||
border: 1px solid $fontColorLightPrimary;
|
||||
background-color: $colorSecondaryDark;
|
||||
border: 1px solid $alphaBlack20;
|
||||
}
|
||||
|
||||
&:active {
|
||||
border: 1px solid $fontColorLightPrimary;
|
||||
background-color: lighten($colorSecondaryDark, 10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Border Radius */
|
||||
$borderRadiusXXXS: rem-calc(3);
|
||||
$borderRadiusXXS: rem-calc(4);
|
||||
$borderRadiusXS: rem-calc(5);
|
||||
$borderRadiusS: rem-calc(8);
|
||||
$borderRadiusM: rem-calc(9);
|
||||
$borderRadiusL: rem-calc(12);
|
||||
$borderRadiusXL: rem-calc(16);
|
||||
$borderRadiusXXL: rem-calc(20);
|
||||
$borderRadiusXXXL: rem-calc(30);
|
||||
$borderRadiusXXXXL: rem-calc(100);
|
||||
$borderRadiusRound: 50%;
|
||||
$borderRadiusXXXS: 0;
|
||||
$borderRadiusXXS: 0;
|
||||
$borderRadiusXS: 0;
|
||||
$borderRadiusS: 0;
|
||||
$borderRadiusM: 0;
|
||||
$borderRadiusL: 0;
|
||||
$borderRadiusXL: 0;
|
||||
$borderRadiusXXL: 0;
|
||||
$borderRadiusXXXL: 0;
|
||||
$borderRadiusXXXXL: 0;
|
||||
$borderRadiusRound: 0;
|
||||
|
||||
/* Dimensions */
|
||||
$headerHeight: rem-calc(86);
|
||||
|
@ -2,7 +2,7 @@ export enum QUERY_KEYS {
|
||||
BLOCK_HEIGHT = 'blockHeight',
|
||||
MARS_BALANCE = 'marsBalance',
|
||||
MARS_ORACLE = 'marsOracle',
|
||||
MARS_PRICE = 'marsPrice',
|
||||
SPOT_PRICE = 'spotPrice',
|
||||
REDBANK = 'redbank',
|
||||
USER_BALANCE = 'userBalance',
|
||||
USER_DEBT = 'userDebt',
|
||||
@ -15,4 +15,5 @@ export enum QUERY_KEYS {
|
||||
ESTIMATE_FARM_FEE = 'estimateFarmFee',
|
||||
PROVIDE_LIQUIDITY = 'provideLiquidity',
|
||||
UNLOCK_MESSAGE = 'unlockMessage',
|
||||
USD_PRICE = 'usdPrice',
|
||||
}
|
||||
|
6
src/types/interfaces/asset.d.ts
vendored
6
src/types/interfaces/asset.d.ts
vendored
@ -2,12 +2,12 @@ interface Asset {
|
||||
color: string
|
||||
name: string
|
||||
denom: string
|
||||
symbol: 'OSMO' | 'ATOM' | 'JUNO' | 'axlUSDC'
|
||||
symbol: 'OSMO' | 'ATOM' | 'JUNO' | 'axlUSDC' | 'stATOM'
|
||||
contract_addr?: string
|
||||
logo: string
|
||||
decimals: number
|
||||
hasOraclePrice: boolean
|
||||
poolId?: number
|
||||
poolBase?: string
|
||||
}
|
||||
|
||||
interface OtherAsset extends Omit<Asset, 'symbol'> {
|
||||
@ -33,6 +33,8 @@ interface RedBankAsset extends Asset {
|
||||
incentiveInfo?: IncentiveInfo
|
||||
depositCap: number
|
||||
depositLiquidity: numnber
|
||||
borrowEnabled: boolean
|
||||
depositEnabled: boolean
|
||||
// This is a hack, subRows can only contain same data model
|
||||
subRows?: DepositAsset[]
|
||||
}
|
||||
|
7
src/types/interfaces/fields.d.ts
vendored
7
src/types/interfaces/fields.d.ts
vendored
@ -38,7 +38,8 @@ interface Position {
|
||||
amounts: {
|
||||
primary: number
|
||||
secondary: number
|
||||
borrowed: number
|
||||
borrowedPrimary: number
|
||||
borrowedSecondary: number
|
||||
lp: {
|
||||
amount: string // Need to be string as number can be extremely large
|
||||
primary: number
|
||||
@ -49,7 +50,8 @@ interface Position {
|
||||
values: {
|
||||
primary: number
|
||||
secondary: number
|
||||
borrowed: number
|
||||
borrowedPrimary: number
|
||||
borrowedSecondary: number
|
||||
total: number
|
||||
net: number
|
||||
}
|
||||
@ -61,6 +63,7 @@ interface Position {
|
||||
ltv: number
|
||||
currentLeverage: number
|
||||
unlockAtTimestamp?: number
|
||||
borrowDenom: string | null
|
||||
}
|
||||
|
||||
interface PositionBarItem {
|
||||
|
15
src/types/interfaces/networkConfig.d.ts
vendored
15
src/types/interfaces/networkConfig.d.ts
vendored
@ -4,6 +4,7 @@ interface NetworkConfig {
|
||||
rpcUrl: string
|
||||
restUrl: string
|
||||
apolloAprUrl: string
|
||||
priceApiUrl: string
|
||||
contracts: {
|
||||
redBank: string
|
||||
incentives: string
|
||||
@ -16,12 +17,14 @@ interface NetworkConfig {
|
||||
whitelist: Asset[]
|
||||
other: OtherAsset[]
|
||||
}
|
||||
displayCurrency: {
|
||||
denom: string
|
||||
prefix: string
|
||||
suffix: string
|
||||
decimals: number
|
||||
}
|
||||
displayCurrency: displayCurrency
|
||||
appUrl: string
|
||||
wallets: import('@marsprotocol/wallet-connector').WalletID[]
|
||||
}
|
||||
|
||||
interface DisplayCurrency {
|
||||
denom: string
|
||||
prefix: string
|
||||
suffix: string
|
||||
decimals: number
|
||||
}
|
||||
|
10
src/types/interfaces/redbank.d.ts
vendored
10
src/types/interfaces/redbank.d.ts
vendored
@ -1,5 +1,5 @@
|
||||
interface RedBankData {
|
||||
balance: {
|
||||
balance?: {
|
||||
balance: import('@cosmjs/stargate').Coin[]
|
||||
}
|
||||
rbwasmkey: {
|
||||
@ -11,6 +11,8 @@ interface RedBankData {
|
||||
JUNOMarketIncentive: MarketIncentive
|
||||
axlUSDCMarket: Market
|
||||
axlUSDCMarketIncentive: MarketIncentive
|
||||
stATOMMarket: Market
|
||||
stATOMMarketIncentive: MarketIncentive
|
||||
collateral: UserCollateral[]
|
||||
unclaimedRewards: string
|
||||
}
|
||||
@ -44,7 +46,9 @@ interface InterestRateModel {
|
||||
|
||||
interface MarketIncentive {
|
||||
denom: string
|
||||
emission_per_second: number
|
||||
index: number
|
||||
emission_per_second: string
|
||||
index: string
|
||||
last_updated: number
|
||||
start_time: number
|
||||
duration: number
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user