Mp 3330 compare accounts via use updated account for vaults (#415)
* feat: added simulateTrade * MP-3330: added vault positions to the useUpdated Account * tidy: format * tidy: refactor * Health indicator change preview (#410) * fix: adjusted the AccountDetail width * feat: added health indicator updates * Update src/components/Account/AccountDetails.tsx Co-authored-by: Yusuf Seyrek <yusufseyrek@users.noreply.github.com> * fix: created a function for the back- and foregroundColors * fix: updated tailwind conf * fix: fixed the useHealthColorAndLabel function --------- Co-authored-by: Yusuf Seyrek <yusufseyrek@users.noreply.github.com> Co-authored-by: Bob van der Helm <34470358+bobthebuidlr@users.noreply.github.com> * fix: added updatedAccount to AccountSummary (#414) Co-authored-by: Bob van der Helm <34470358+bobthebuidlr@users.noreply.github.com> * fix: added a new way of calulating values to vaults * fix: refactored the displayCurrency * fix: fixed the subtitles, to not nest <p> tags * MP-3330: added comparison to the vault mechanics * fix: fixed tests * fix: updated the borrow slider percentage on vaults * fix: addressed change request * update displayValue stuff * fixed wrong display conversions * fix: fixed the display price and renamed getDepositsAndLendsAfterCoinSpent * fix test and update DisplayCurrency * tidy: refactor * tidy: rename method --------- Co-authored-by: Yusuf Seyrek <yusufseyrek@users.noreply.github.com> Co-authored-by: Bob van der Helm <34470358+bobthebuidlr@users.noreply.github.com>
This commit is contained in:
parent
b7019023f0
commit
f1ee4bd7f3
@ -59,6 +59,7 @@ describe('<VaultBorrowings />', () => {
|
|||||||
onChangeBorrowings: jest.fn(),
|
onChangeBorrowings: jest.fn(),
|
||||||
depositActions: [],
|
depositActions: [],
|
||||||
depositCapReachedCoins: [],
|
depositCapReachedCoins: [],
|
||||||
|
displayCurrency: 'uosmo',
|
||||||
}
|
}
|
||||||
|
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
@ -80,7 +81,7 @@ describe('<VaultBorrowings />', () => {
|
|||||||
it('should render DisplayCurrency correctly', () => {
|
it('should render DisplayCurrency correctly', () => {
|
||||||
expect(mockedDisplayCurrency).toHaveBeenCalledTimes(1)
|
expect(mockedDisplayCurrency).toHaveBeenCalledTimes(1)
|
||||||
expect(mockedDisplayCurrency).toHaveBeenCalledWith(
|
expect(mockedDisplayCurrency).toHaveBeenCalledWith(
|
||||||
{ coin: new BNCoin({ denom: 'uosmo', amount: '0' }) },
|
{ coin: new BNCoin({ denom: 'usd', amount: '0' }) },
|
||||||
expect.anything(),
|
expect.anything(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -32,9 +32,7 @@ export default function AccordionContent(props: Props) {
|
|||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<Text>{title}</Text>
|
<Text>{title}</Text>
|
||||||
<Text size='xs' className='mt-1 text-white/60'>
|
{renderSubTitle()}
|
||||||
{renderSubTitle()}
|
|
||||||
</Text>
|
|
||||||
</div>
|
</div>
|
||||||
<div className='block pr-1 group-[[open]]:hidden'>
|
<div className='block pr-1 group-[[open]]:hidden'>
|
||||||
{isOpen ? <ChevronDown className='h-1.5' /> : <ChevronRight className='w-1.5' />}
|
{isOpen ? <ChevronDown className='h-1.5' /> : <ChevronRight className='w-1.5' />}
|
||||||
|
@ -17,20 +17,20 @@ import { FormattedNumber } from 'components/FormattedNumber'
|
|||||||
import { SortAsc, SortDesc, SortNone } from 'components/Icons'
|
import { SortAsc, SortDesc, SortNone } from 'components/Icons'
|
||||||
import Text from 'components/Text'
|
import Text from 'components/Text'
|
||||||
import { ASSETS } from 'constants/assets'
|
import { ASSETS } from 'constants/assets'
|
||||||
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
import { BN_ZERO } from 'constants/math'
|
||||||
import { DISPLAY_CURRENCY_KEY } from 'constants/localStore'
|
|
||||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||||
import useLocalStorage from 'hooks/useLocalStorage'
|
|
||||||
import usePrices from 'hooks/usePrices'
|
import usePrices from 'hooks/usePrices'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import { byDenom } from 'utils/array'
|
import { byDenom } from 'utils/array'
|
||||||
import { getAssetByDenom } from 'utils/assets'
|
import { getAssetByDenom } from 'utils/assets'
|
||||||
import { convertLiquidityRateToAPR, convertToDisplayAmount, demagnify } from 'utils/formatters'
|
import { convertLiquidityRateToAPR, demagnify, getCoinValue } from 'utils/formatters'
|
||||||
import { BN } from 'utils/helpers'
|
import { BN } from 'utils/helpers'
|
||||||
import { convertAprToApy } from 'utils/parsers'
|
import { convertAprToApy } from 'utils/parsers'
|
||||||
import { getPage, getRoute } from 'utils/route'
|
import { getPage, getRoute } from 'utils/route'
|
||||||
|
|
||||||
|
import { ORACLE_DENOM } from '../../constants/oracle'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
account: Account
|
account: Account
|
||||||
lendingData: LendingMarketTableData[]
|
lendingData: LendingMarketTableData[]
|
||||||
@ -38,11 +38,20 @@ interface Props {
|
|||||||
tableBodyClassName?: string
|
tableBodyClassName?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface PositionValue {
|
||||||
|
type: 'deposits' | 'borrowing' | 'lending'
|
||||||
|
symbol: string
|
||||||
|
size: number
|
||||||
|
value: string
|
||||||
|
denom: string
|
||||||
|
amount: BigNumber
|
||||||
|
apy: number
|
||||||
|
}
|
||||||
|
|
||||||
function calculatePositionValues(
|
function calculatePositionValues(
|
||||||
type: 'deposits' | 'borrowing' | 'lending',
|
type: 'deposits' | 'borrowing' | 'lending',
|
||||||
asset: Asset,
|
asset: Asset,
|
||||||
prices: BNCoin[],
|
prices: BNCoin[],
|
||||||
displayCurrencyDenom: string,
|
|
||||||
position: BNCoin,
|
position: BNCoin,
|
||||||
apy: number,
|
apy: number,
|
||||||
) {
|
) {
|
||||||
@ -51,22 +60,29 @@ function calculatePositionValues(
|
|||||||
type,
|
type,
|
||||||
symbol: asset.symbol,
|
symbol: asset.symbol,
|
||||||
size: demagnify(amount, asset),
|
size: demagnify(amount, asset),
|
||||||
value: convertToDisplayAmount(
|
value: getCoinValue(BNCoin.fromDenomAndBigNumber(denom, amount), prices).toString(),
|
||||||
BNCoin.fromDenomAndBigNumber(denom, amount),
|
|
||||||
displayCurrencyDenom,
|
|
||||||
prices,
|
|
||||||
).toString(),
|
|
||||||
denom,
|
denom,
|
||||||
amount: type === 'borrowing' ? amount.negated() : amount,
|
amount: type === 'borrowing' ? amount.negated() : amount,
|
||||||
apy,
|
apy,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function calculateVaultValues(vault: DepositedVault, apy: number) {
|
||||||
|
const { name } = vault
|
||||||
|
const totalValue = vault.values.primary.plus(vault.values.secondary)
|
||||||
|
|
||||||
|
return {
|
||||||
|
type: 'vault',
|
||||||
|
symbol: name,
|
||||||
|
size: 0,
|
||||||
|
value: totalValue.toString(),
|
||||||
|
denom: vault.denoms.lp,
|
||||||
|
amount: BN_ZERO,
|
||||||
|
apy,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function AccountBalancesTable(props: Props) {
|
export default function AccountBalancesTable(props: Props) {
|
||||||
const [displayCurrency] = useLocalStorage<string>(
|
|
||||||
DISPLAY_CURRENCY_KEY,
|
|
||||||
DEFAULT_SETTINGS.displayCurrency,
|
|
||||||
)
|
|
||||||
const { data: prices } = usePrices()
|
const { data: prices } = usePrices()
|
||||||
const currentAccount = useCurrentAccount()
|
const currentAccount = useCurrentAccount()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
@ -77,31 +93,38 @@ export default function AccountBalancesTable(props: Props) {
|
|||||||
const accountDeposits = props.account?.deposits ?? []
|
const accountDeposits = props.account?.deposits ?? []
|
||||||
const accountLends = props.account?.lends ?? []
|
const accountLends = props.account?.lends ?? []
|
||||||
const accountDebts = props.account?.debts ?? []
|
const accountDebts = props.account?.debts ?? []
|
||||||
|
const accountVaults = props.account?.vaults ?? []
|
||||||
|
|
||||||
const deposits = accountDeposits.map((deposit) => {
|
const deposits: PositionValue[] = []
|
||||||
const asset = ASSETS.find((asset) => asset.denom === deposit.denom) ?? ASSETS[0]
|
accountDeposits.forEach((deposit) => {
|
||||||
|
const asset = ASSETS.find(byDenom(deposit.denom))
|
||||||
|
if (!asset) return
|
||||||
const apy = 0
|
const apy = 0
|
||||||
return calculatePositionValues('deposits', asset, prices, displayCurrency, deposit, apy)
|
deposits.push(calculatePositionValues('deposits', asset, prices, deposit, apy))
|
||||||
})
|
})
|
||||||
|
|
||||||
const lends = accountLends.map((lending) => {
|
const lends = accountLends.map((lending) => {
|
||||||
const asset = ASSETS.find((asset) => asset.denom === lending.denom) ?? ASSETS[0]
|
const asset = ASSETS.find(byDenom(lending.denom)) ?? ASSETS[0]
|
||||||
const apr = convertLiquidityRateToAPR(
|
const apr = convertLiquidityRateToAPR(
|
||||||
props.lendingData.find((market) => market.asset.denom === lending.denom)
|
props.lendingData.find((market) => market.asset.denom === lending.denom)
|
||||||
?.marketLiquidityRate ?? 0,
|
?.marketLiquidityRate ?? 0,
|
||||||
)
|
)
|
||||||
const apy = convertAprToApy(apr, 365)
|
const apy = convertAprToApy(apr, 365)
|
||||||
return calculatePositionValues('lending', asset, prices, displayCurrency, lending, apy)
|
return calculatePositionValues('lending', asset, prices, lending, apy)
|
||||||
|
})
|
||||||
|
|
||||||
|
const vaults = accountVaults.map((vault) => {
|
||||||
|
const apy = (vault.apy ?? 0) * 100
|
||||||
|
return calculateVaultValues(vault, apy)
|
||||||
})
|
})
|
||||||
const debts = accountDebts.map((debt) => {
|
const debts = accountDebts.map((debt) => {
|
||||||
const asset = ASSETS.find(byDenom(debt.denom)) ?? ASSETS[0]
|
const asset = ASSETS.find(byDenom(debt.denom)) ?? ASSETS[0]
|
||||||
const apy =
|
const apy =
|
||||||
props.borrowingData.find((market) => market.asset.denom === debt.denom)?.borrowRate ?? 0
|
props.borrowingData.find((market) => market.asset.denom === debt.denom)?.borrowRate ?? 0
|
||||||
return calculatePositionValues('borrowing', asset, prices, displayCurrency, debt, apy * -100)
|
return calculatePositionValues('borrowing', asset, prices, debt, apy * -100)
|
||||||
})
|
})
|
||||||
|
return [...deposits, ...lends, ...vaults, ...debts]
|
||||||
return [...deposits, ...lends, ...debts]
|
}, [prices, props.account, props.borrowingData, props.lendingData])
|
||||||
}, [displayCurrency, prices, props.account, props.borrowingData, props.lendingData])
|
|
||||||
|
|
||||||
const columns = React.useMemo<ColumnDef<AccountBalanceRow>[]>(
|
const columns = React.useMemo<ColumnDef<AccountBalanceRow>[]>(
|
||||||
() => [
|
() => [
|
||||||
@ -114,6 +137,7 @@ export default function AccountBalancesTable(props: Props) {
|
|||||||
<Text size='xs'>
|
<Text size='xs'>
|
||||||
{row.original.symbol}
|
{row.original.symbol}
|
||||||
{row.original.type === 'lending' && <span className='ml-1 text-profit'>(lent)</span>}
|
{row.original.type === 'lending' && <span className='ml-1 text-profit'>(lent)</span>}
|
||||||
|
{row.original.type === 'vault' && <span className='ml-1 text-profit'>(farm)</span>}
|
||||||
</Text>
|
</Text>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -124,8 +148,8 @@ export default function AccountBalancesTable(props: Props) {
|
|||||||
id: 'value',
|
id: 'value',
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const coin = new BNCoin({
|
const coin = new BNCoin({
|
||||||
denom: row.original.denom,
|
denom: ORACLE_DENOM,
|
||||||
amount: row.original.amount.toString(),
|
amount: row.original.value.toString(),
|
||||||
})
|
})
|
||||||
return <DisplayCurrency coin={coin} className='text-xs text-right' />
|
return <DisplayCurrency coin={coin} className='text-xs text-right' />
|
||||||
},
|
},
|
||||||
@ -135,6 +159,8 @@ export default function AccountBalancesTable(props: Props) {
|
|||||||
accessorKey: 'size',
|
accessorKey: 'size',
|
||||||
header: 'Size',
|
header: 'Size',
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
|
if (row.original.amount.isEqualTo(BN_ZERO))
|
||||||
|
return <span className='w-full text-xs text-center'>–</span>
|
||||||
const amount = demagnify(
|
const amount = demagnify(
|
||||||
row.original.amount,
|
row.original.amount,
|
||||||
getAssetByDenom(row.original.denom) ?? ASSETS[0],
|
getAssetByDenom(row.original.denom) ?? ASSETS[0],
|
||||||
@ -154,7 +180,7 @@ export default function AccountBalancesTable(props: Props) {
|
|||||||
accessorKey: 'apy',
|
accessorKey: 'apy',
|
||||||
header: 'APY',
|
header: 'APY',
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
if (row.original.apy === 0)
|
if (row.original.type === 'deposit')
|
||||||
return <span className='w-full text-xs text-center'>–</span>
|
return <span className='w-full text-xs text-center'>–</span>
|
||||||
return (
|
return (
|
||||||
<FormattedNumber
|
<FormattedNumber
|
||||||
@ -210,7 +236,7 @@ export default function AccountBalancesTable(props: Props) {
|
|||||||
<thead className='border-b border-white/5'>
|
<thead className='border-b border-white/5'>
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
<tr key={headerGroup.id}>
|
<tr key={headerGroup.id}>
|
||||||
{headerGroup.headers.map((header, index) => {
|
{headerGroup.headers.map((header) => {
|
||||||
return (
|
return (
|
||||||
<th
|
<th
|
||||||
key={header.id}
|
key={header.id}
|
||||||
@ -262,7 +288,7 @@ export default function AccountBalancesTable(props: Props) {
|
|||||||
<td
|
<td
|
||||||
key={cell.id}
|
key={cell.id}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
cell.column.id === 'symbol' ? `border-l ${borderClass}` : 'pl-4 text-right',
|
cell.column.id === 'symbol' ? `border-l ${borderClass}` : 'text-right',
|
||||||
'p-2',
|
'p-2',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
@ -51,12 +51,12 @@ function AccountDetails(props: Props) {
|
|||||||
const { health: updatedHealth } = useHealthComputer(updatedAccount || account)
|
const { health: updatedHealth } = useHealthComputer(updatedAccount || account)
|
||||||
const { data: prices } = usePrices()
|
const { data: prices } = usePrices()
|
||||||
const accountBalanceValue = useMemo(
|
const accountBalanceValue = useMemo(
|
||||||
() => calculateAccountBalanceValue(updatedAccount ? updatedAccount : account, prices),
|
() => calculateAccountBalanceValue(updatedAccount ?? account, prices),
|
||||||
[updatedAccount, account, prices],
|
[updatedAccount, account, prices],
|
||||||
)
|
)
|
||||||
const coin = BNCoin.fromDenomAndBigNumber(ORACLE_DENOM, accountBalanceValue)
|
const coin = BNCoin.fromDenomAndBigNumber(ORACLE_DENOM, accountBalanceValue)
|
||||||
const leverage = useMemo(
|
const leverage = useMemo(
|
||||||
() => calculateAccountLeverage(updatedAccount ? updatedAccount : account, prices),
|
() => calculateAccountLeverage(updatedAccount ?? account, prices),
|
||||||
[account, updatedAccount, prices],
|
[account, updatedAccount, prices],
|
||||||
)
|
)
|
||||||
const { availableAssets: borrowAvailableAssets, accountBorrowedAssets } =
|
const { availableAssets: borrowAvailableAssets, accountBorrowedAssets } =
|
||||||
|
@ -8,7 +8,9 @@ import useLocalStorage from 'hooks/useLocalStorage'
|
|||||||
import usePrices from 'hooks/usePrices'
|
import usePrices from 'hooks/usePrices'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import { getDisplayCurrencies } from 'utils/assets'
|
import { getDisplayCurrencies } from 'utils/assets'
|
||||||
import { convertToDisplayAmount } from 'utils/formatters'
|
import { getCoinValue } from 'utils/formatters'
|
||||||
|
import { BN } from 'utils/helpers'
|
||||||
|
import { ORACLE_DENOM } from 'constants/oracle'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
coin: BNCoin
|
coin: BNCoin
|
||||||
@ -39,13 +41,27 @@ export default function DisplayCurrency(props: Props) {
|
|||||||
? ''
|
? ''
|
||||||
: ` ${displayCurrencyAsset.symbol ? ` ${displayCurrencyAsset.symbol}` : ''}`
|
: ` ${displayCurrencyAsset.symbol ? ` ${displayCurrencyAsset.symbol}` : ''}`
|
||||||
|
|
||||||
|
const amount = useMemo(() => {
|
||||||
|
const coinValue = getCoinValue(props.coin, prices)
|
||||||
|
|
||||||
|
if (displayCurrency === ORACLE_DENOM) return coinValue.toNumber()
|
||||||
|
|
||||||
|
const displayDecimals = displayCurrencyAsset.decimals
|
||||||
|
const displayPrice = getCoinValue(
|
||||||
|
BNCoin.fromDenomAndBigNumber(displayCurrency, BN(1).shiftedBy(displayDecimals)),
|
||||||
|
prices,
|
||||||
|
)
|
||||||
|
|
||||||
|
return coinValue.div(displayPrice).toNumber()
|
||||||
|
}, [displayCurrency, displayCurrencyAsset.decimals, prices, props.coin])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormattedNumber
|
<FormattedNumber
|
||||||
className={classNames(
|
className={classNames(
|
||||||
props.className,
|
props.className,
|
||||||
props.parentheses && 'before:content-["("] after:content-[")"]',
|
props.parentheses && 'before:content-["("] after:content-[")"]',
|
||||||
)}
|
)}
|
||||||
amount={convertToDisplayAmount(props.coin, displayCurrency, prices).toNumber()}
|
amount={amount}
|
||||||
options={{
|
options={{
|
||||||
minDecimals: isUSD ? 2 : 0,
|
minDecimals: isUSD ? 2 : 0,
|
||||||
maxDecimals: 2,
|
maxDecimals: 2,
|
||||||
|
@ -6,7 +6,7 @@ import useVaults from 'hooks/useVaults'
|
|||||||
|
|
||||||
function Content() {
|
function Content() {
|
||||||
const { data: vaults } = useVaults()
|
const { data: vaults } = useVaults()
|
||||||
|
if (!vaults) return null
|
||||||
const featuredVaults = vaults.filter((vault) => vault.isFeatured)
|
const featuredVaults = vaults.filter((vault) => vault.isFeatured)
|
||||||
|
|
||||||
if (!featuredVaults.length) return null
|
if (!featuredVaults.length) return null
|
||||||
@ -14,7 +14,7 @@ function Content() {
|
|||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
title='Featured vaults'
|
title='Featured vaults'
|
||||||
className='mb-4 h-fit w-full bg-white/5'
|
className='w-full mb-4 h-fit bg-white/5'
|
||||||
contentClassName='grid grid-cols-3'
|
contentClassName='grid grid-cols-3'
|
||||||
>
|
>
|
||||||
{featuredVaults.map((vault) => (
|
{featuredVaults.map((vault) => (
|
||||||
|
@ -5,11 +5,11 @@ import Card from 'components/Card'
|
|||||||
import { VaultTable } from 'components/Earn/Farm/VaultTable'
|
import { VaultTable } from 'components/Earn/Farm/VaultTable'
|
||||||
import VaultUnlockBanner from 'components/Earn/Farm/VaultUnlockBanner'
|
import VaultUnlockBanner from 'components/Earn/Farm/VaultUnlockBanner'
|
||||||
import { IS_TESTNET } from 'constants/env'
|
import { IS_TESTNET } from 'constants/env'
|
||||||
|
import { BN_ZERO } from 'constants/math'
|
||||||
import { TESTNET_VAULTS_META_DATA, VAULTS_META_DATA } from 'constants/vaults'
|
import { TESTNET_VAULTS_META_DATA, VAULTS_META_DATA } from 'constants/vaults'
|
||||||
import useDepositedVaults from 'hooks/useDepositedVaults'
|
import useDepositedVaults from 'hooks/useDepositedVaults'
|
||||||
import useVaults from 'hooks/useVaults'
|
import useVaults from 'hooks/useVaults'
|
||||||
import { VaultStatus } from 'types/enums/vault'
|
import { VaultStatus } from 'types/enums/vault'
|
||||||
import { BN_ZERO } from 'constants/math'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
type: 'available' | 'deposited'
|
type: 'available' | 'deposited'
|
||||||
@ -26,6 +26,7 @@ function Content(props: Props) {
|
|||||||
const { deposited, available } = useMemo(() => {
|
const { deposited, available } = useMemo(() => {
|
||||||
return vaultsMetaData.reduce(
|
return vaultsMetaData.reduce(
|
||||||
(prev: { deposited: DepositedVault[]; available: Vault[] }, curr) => {
|
(prev: { deposited: DepositedVault[]; available: Vault[] }, curr) => {
|
||||||
|
if (!vaults) return prev
|
||||||
const vault = vaults.find((vault) => vault.address === curr.address)
|
const vault = vaults.find((vault) => vault.address === curr.address)
|
||||||
const depositedVault = depositedVaults?.find((vault) => vault.address === curr.address)
|
const depositedVault = depositedVaults?.find((vault) => vault.address === curr.address)
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ function Content(props: Props) {
|
|||||||
<>
|
<>
|
||||||
{!isAvailable && <VaultUnlockBanner vaults={unlockedVaults} />}
|
{!isAvailable && <VaultUnlockBanner vaults={unlockedVaults} />}
|
||||||
<Card
|
<Card
|
||||||
className='h-fit w-full bg-white/5'
|
className='w-full h-fit bg-white/5'
|
||||||
title={isAvailable ? 'Available vaults' : 'Deposited'}
|
title={isAvailable ? 'Available vaults' : 'Deposited'}
|
||||||
>
|
>
|
||||||
<VaultTable data={vaultsToDisplay} />
|
<VaultTable data={vaultsToDisplay} />
|
||||||
@ -85,7 +86,7 @@ function Fallback() {
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className='h-fit w-full bg-white/5' title='Available vaults'>
|
<Card className='w-full h-fit bg-white/5' title='Available vaults'>
|
||||||
<VaultTable data={mockVaults} isLoading />
|
<VaultTable data={mockVaults} isLoading />
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
|
@ -9,10 +9,12 @@ import AssetListTable from 'components/MarketAssetTable'
|
|||||||
import MarketAssetTableRow from 'components/MarketAssetTable/MarketAssetTableRow'
|
import MarketAssetTableRow from 'components/MarketAssetTable/MarketAssetTableRow'
|
||||||
import MarketDetails from 'components/MarketAssetTable/MarketDetails'
|
import MarketDetails from 'components/MarketAssetTable/MarketDetails'
|
||||||
import TitleAndSubCell from 'components/TitleAndSubCell'
|
import TitleAndSubCell from 'components/TitleAndSubCell'
|
||||||
import useDisplayCurrencyPrice from 'hooks/useDisplayCurrencyPrice'
|
|
||||||
import { convertLiquidityRateToAPR, demagnify } from 'utils/formatters'
|
import { convertLiquidityRateToAPR, demagnify } from 'utils/formatters'
|
||||||
import { BN } from 'utils/helpers'
|
import { BN } from 'utils/helpers'
|
||||||
|
|
||||||
|
import { BN_ZERO } from '../../../constants/math'
|
||||||
|
import AmountAndValue from '../../AmountAndValue'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
title: string
|
title: string
|
||||||
data: LendingMarketTableData[]
|
data: LendingMarketTableData[]
|
||||||
@ -20,7 +22,6 @@ interface Props {
|
|||||||
|
|
||||||
export default function LendingMarketsTable(props: Props) {
|
export default function LendingMarketsTable(props: Props) {
|
||||||
const { title, data } = props
|
const { title, data } = props
|
||||||
const { symbol: displayCurrencySymbol } = useDisplayCurrencyPrice()
|
|
||||||
const shouldShowAccountDeposit = !!data[0]?.accountLentValue
|
const shouldShowAccountDeposit = !!data[0]?.accountLentValue
|
||||||
|
|
||||||
const rowRenderer = useCallback(
|
const rowRenderer = useCallback(
|
||||||
@ -49,12 +50,12 @@ export default function LendingMarketsTable(props: Props) {
|
|||||||
const asset = row.original.asset
|
const asset = row.original.asset
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-1 items-center gap-3'>
|
<div className='flex items-center flex-1 gap-3'>
|
||||||
<AssetImage asset={asset} size={32} />
|
<AssetImage asset={asset} size={32} />
|
||||||
<TitleAndSubCell
|
<TitleAndSubCell
|
||||||
title={asset.symbol}
|
title={asset.symbol}
|
||||||
sub={asset.name}
|
sub={asset.name}
|
||||||
className='min-w-15 text-left'
|
className='text-left min-w-15'
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -66,14 +67,12 @@ export default function LendingMarketsTable(props: Props) {
|
|||||||
accessorKey: 'accountDepositValue',
|
accessorKey: 'accountDepositValue',
|
||||||
header: 'Deposited',
|
header: 'Deposited',
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const accountDepositValue = row.original.accountLentValue as BigNumber
|
const amount = row.original.accountLentAmount
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FormattedNumber
|
<AmountAndValue
|
||||||
className='text-xs'
|
asset={row.original.asset}
|
||||||
animate
|
amount={amount ? BN(amount) : BN_ZERO}
|
||||||
amount={accountDepositValue.toNumber()}
|
|
||||||
options={{ suffix: ` ${displayCurrencySymbol}` }}
|
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
@ -135,7 +134,7 @@ export default function LendingMarketsTable(props: Props) {
|
|||||||
),
|
),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[displayCurrencySymbol, shouldShowAccountDeposit],
|
[shouldShowAccountDeposit],
|
||||||
)
|
)
|
||||||
|
|
||||||
return <AssetListTable title={title} rowRenderer={rowRenderer} columns={columns} data={data} />
|
return <AssetListTable title={title} rowRenderer={rowRenderer} columns={columns} data={data} />
|
||||||
|
@ -12,6 +12,7 @@ interface Props {
|
|||||||
options?: FormatOptions
|
options?: FormatOptions
|
||||||
className?: string
|
className?: string
|
||||||
animate?: boolean
|
animate?: boolean
|
||||||
|
parentheses?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export const FormattedNumber = React.memo(
|
export const FormattedNumber = React.memo(
|
||||||
@ -39,13 +40,25 @@ export const FormattedNumber = React.memo(
|
|||||||
reduceMotion
|
reduceMotion
|
||||||
)
|
)
|
||||||
return (
|
return (
|
||||||
<p className={classNames('number', props.className)}>
|
<p
|
||||||
|
className={classNames(
|
||||||
|
'number',
|
||||||
|
props.parentheses && 'before:content-["("] after:content-[")"]',
|
||||||
|
props.className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
{formatValue(props.amount.toString(), props.options)}
|
{formatValue(props.amount.toString(), props.options)}
|
||||||
</p>
|
</p>
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<animated.p className={classNames('number', props.className)}>
|
<animated.p
|
||||||
|
className={classNames(
|
||||||
|
'number',
|
||||||
|
props.parentheses && 'before:content-["("] after:content-[")"]',
|
||||||
|
props.className,
|
||||||
|
)}
|
||||||
|
>
|
||||||
{springAmount.number.to((num) => formatValue(num, props.options))}
|
{springAmount.number.to((num) => formatValue(num, props.options))}
|
||||||
</animated.p>
|
</animated.p>
|
||||||
)
|
)
|
||||||
|
@ -133,7 +133,7 @@ export default function AssetSelectTable(props: Props) {
|
|||||||
<td
|
<td
|
||||||
key={cell.id}
|
key={cell.id}
|
||||||
className={classNames(
|
className={classNames(
|
||||||
cell.column.id === 'select' ? `` : 'pl-4 text-right',
|
cell.column.id === 'select' ? `` : 'text-right',
|
||||||
'px-4 py-3',
|
'px-4 py-3',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
@ -20,7 +20,7 @@ import useCurrentAccount from 'hooks/useCurrentAccount'
|
|||||||
import useHealthComputer from 'hooks/useHealthComputer'
|
import useHealthComputer from 'hooks/useHealthComputer'
|
||||||
import useToggle from 'hooks/useToggle'
|
import useToggle from 'hooks/useToggle'
|
||||||
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
||||||
import { getDepositsAndLendsAfterCoinSpent } from 'hooks/useUpdatedAccount/functions'
|
import { getDepositAndLendCoinsToSpend } from 'hooks/useUpdatedAccount/functions'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import { byDenom } from 'utils/array'
|
import { byDenom } from 'utils/array'
|
||||||
@ -77,7 +77,7 @@ function BorrowModal(props: Props) {
|
|||||||
if (!asset) return
|
if (!asset) return
|
||||||
setIsConfirming(true)
|
setIsConfirming(true)
|
||||||
let result
|
let result
|
||||||
const { lends } = getDepositsAndLendsAfterCoinSpent(
|
const { lend } = getDepositAndLendCoinsToSpend(
|
||||||
BNCoin.fromDenomAndBigNumber(asset.denom, amount),
|
BNCoin.fromDenomAndBigNumber(asset.denom, amount),
|
||||||
account,
|
account,
|
||||||
)
|
)
|
||||||
@ -85,8 +85,8 @@ function BorrowModal(props: Props) {
|
|||||||
result = await repay({
|
result = await repay({
|
||||||
accountId: account.id,
|
accountId: account.id,
|
||||||
coin: BNCoin.fromDenomAndBigNumber(asset.denom, amount),
|
coin: BNCoin.fromDenomAndBigNumber(asset.denom, amount),
|
||||||
accountBalance: max.isEqualTo(amount),
|
accountBalance: percentage === 100,
|
||||||
lends,
|
lend,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
result = await borrow({
|
result = await borrow({
|
||||||
|
@ -14,7 +14,7 @@ import useToggle from 'hooks/useToggle'
|
|||||||
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import { cloneAccount, getMergedBalances, removeDepositsAndLends } from 'utils/accounts'
|
import { cloneAccount, getMergedBalancesForAsset, removeDepositsAndLends } from 'utils/accounts'
|
||||||
import { byDenom } from 'utils/array'
|
import { byDenom } from 'utils/array'
|
||||||
import { getEnabledMarketAssets } from 'utils/assets'
|
import { getEnabledMarketAssets } from 'utils/assets'
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ export default function WithdrawFromAccount(props: Props) {
|
|||||||
const accountClone = cloneAccount(account)
|
const accountClone = cloneAccount(account)
|
||||||
const borrowAccount = removeDepositsAndLends(accountClone, currentAsset.denom)
|
const borrowAccount = removeDepositsAndLends(accountClone, currentAsset.denom)
|
||||||
const { computeMaxBorrowAmount } = useHealthComputer(borrowAccount)
|
const { computeMaxBorrowAmount } = useHealthComputer(borrowAccount)
|
||||||
const balances = getMergedBalances(account, getEnabledMarketAssets())
|
const balances = getMergedBalancesForAsset(account, getEnabledMarketAssets())
|
||||||
const maxWithdrawAmount = computeMaxWithdrawAmount(currentAsset.denom)
|
const maxWithdrawAmount = computeMaxWithdrawAmount(currentAsset.denom)
|
||||||
const maxWithdrawWithBorrowAmount = computeMaxBorrowAmount(currentAsset.denom, 'wallet').plus(
|
const maxWithdrawWithBorrowAmount = computeMaxBorrowAmount(currentAsset.denom, 'wallet').plus(
|
||||||
maxWithdrawAmount,
|
maxWithdrawAmount,
|
||||||
|
@ -19,6 +19,8 @@ import { Action } from 'types/generated/mars-credit-manager/MarsCreditManager.ty
|
|||||||
import { byDenom } from 'utils/array'
|
import { byDenom } from 'utils/array'
|
||||||
import { findCoinByDenom, getAssetByDenom } from 'utils/assets'
|
import { findCoinByDenom, getAssetByDenom } from 'utils/assets'
|
||||||
import { formatPercent } from 'utils/formatters'
|
import { formatPercent } from 'utils/formatters'
|
||||||
|
import { getValueFromBNCoins, mergeBNCoinArrays } from 'utils/helpers'
|
||||||
|
import { ORACLE_DENOM } from 'constants/oracle'
|
||||||
|
|
||||||
export interface VaultBorrowingsProps {
|
export interface VaultBorrowingsProps {
|
||||||
borrowings: BNCoin[]
|
borrowings: BNCoin[]
|
||||||
@ -28,18 +30,29 @@ export interface VaultBorrowingsProps {
|
|||||||
vault: Vault
|
vault: Vault
|
||||||
depositActions: Action[]
|
depositActions: Action[]
|
||||||
onChangeBorrowings: (borrowings: BNCoin[]) => void
|
onChangeBorrowings: (borrowings: BNCoin[]) => void
|
||||||
|
displayCurrency: string
|
||||||
depositCapReachedCoins: BNCoin[]
|
depositCapReachedCoins: BNCoin[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
||||||
const { data: marketAssets } = useMarketAssets()
|
const { data: marketAssets } = useMarketAssets()
|
||||||
const { data: prices } = usePrices()
|
const { data: prices } = usePrices()
|
||||||
const baseCurrency = useStore((s) => s.baseCurrency)
|
|
||||||
const vaultModal = useStore((s) => s.vaultModal)
|
const vaultModal = useStore((s) => s.vaultModal)
|
||||||
const depositIntoVault = useStore((s) => s.depositIntoVault)
|
const depositIntoVault = useStore((s) => s.depositIntoVault)
|
||||||
const [isConfirming, setIsConfirming] = useState(false)
|
const [isConfirming, setIsConfirming] = useState(false)
|
||||||
const updatedAccount = useStore((s) => s.updatedAccount)
|
const updatedAccount = useStore((s) => s.updatedAccount)
|
||||||
const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount)
|
const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount)
|
||||||
|
const [percentage, setPercentage] = useState<number>(0)
|
||||||
|
|
||||||
|
const calculateSliderPercentage = (maxBorrowAmounts: BNCoin[], borrowings: BNCoin[]) => {
|
||||||
|
if (borrowings.length === 1) {
|
||||||
|
const amount = borrowings[0].amount
|
||||||
|
if (amount.isZero()) return 0
|
||||||
|
const max = maxBorrowAmounts.find(byDenom(borrowings[0].denom))?.amount || BN_ZERO
|
||||||
|
return amount.times(100).dividedBy(max).toNumber()
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
const maxBorrowAmounts: BNCoin[] = useMemo(() => {
|
const maxBorrowAmounts: BNCoin[] = useMemo(() => {
|
||||||
return props.borrowings.map((borrowing) => {
|
return props.borrowings.map((borrowing) => {
|
||||||
@ -53,25 +66,10 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
|||||||
})
|
})
|
||||||
}, [props.borrowings, computeMaxBorrowAmount, props.vault.address])
|
}, [props.borrowings, computeMaxBorrowAmount, props.vault.address])
|
||||||
|
|
||||||
const borrowingValue = useMemo(() => {
|
const totalValue = useMemo(
|
||||||
return props.borrowings.reduce((prev, curr) => {
|
() => getValueFromBNCoins(mergeBNCoinArrays(props.deposits, props.borrowings), prices),
|
||||||
const price = prices.find((price) => price.denom === curr.denom)?.amount
|
[props.borrowings, props.deposits, prices],
|
||||||
if (!price) return prev
|
)
|
||||||
|
|
||||||
return prev.plus(curr.amount.multipliedBy(price))
|
|
||||||
}, BN_ZERO as BigNumber)
|
|
||||||
}, [props.borrowings, prices])
|
|
||||||
|
|
||||||
const totalValue = useMemo(() => {
|
|
||||||
const depositValue = props.deposits.reduce((prev, curr) => {
|
|
||||||
const price = prices.find((price) => price.denom === curr.denom)?.amount
|
|
||||||
if (!price) return prev
|
|
||||||
const value = curr.amount.multipliedBy(price)
|
|
||||||
return prev.plus(value)
|
|
||||||
}, BN_ZERO as BigNumber)
|
|
||||||
|
|
||||||
return depositValue.plus(borrowingValue)
|
|
||||||
}, [props.deposits, borrowingValue, prices])
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const selectedBorrowDenoms = vaultModal?.selectedBorrowDenoms || []
|
const selectedBorrowDenoms = vaultModal?.selectedBorrowDenoms || []
|
||||||
@ -81,25 +79,24 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
|||||||
) {
|
) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedBorrowings = selectedBorrowDenoms.map((denom) => {
|
const updatedBorrowings = selectedBorrowDenoms.map((denom) => {
|
||||||
const amount = findCoinByDenom(denom, props.borrowings)?.amount || BN_ZERO
|
const amount = findCoinByDenom(denom, props.borrowings)?.amount || BN_ZERO
|
||||||
|
|
||||||
return new BNCoin({
|
return new BNCoin({
|
||||||
denom,
|
denom,
|
||||||
amount: amount.toString(),
|
amount: amount.toString(),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
props.onChangeBorrowings(updatedBorrowings)
|
props.onChangeBorrowings(updatedBorrowings)
|
||||||
}, [vaultModal, props])
|
setPercentage(calculateSliderPercentage(maxBorrowAmounts, updatedBorrowings))
|
||||||
|
}, [vaultModal, props, maxBorrowAmounts])
|
||||||
const [percentage, setPercentage] = useState<number>(0)
|
|
||||||
|
|
||||||
function onChangeSlider(value: number) {
|
function onChangeSlider(value: number) {
|
||||||
if (props.borrowings.length !== 1) return
|
if (props.borrowings.length !== 1) return
|
||||||
|
|
||||||
const denom = props.borrowings[0].denom
|
const denom = props.borrowings[0].denom
|
||||||
const currentAmount = props.borrowings[0].amount
|
const currentAmount = props.borrowings[0].amount
|
||||||
const maxAmount = maxBorrowAmounts.find((coin) => coin.denom === denom)?.amount ?? BN_ZERO
|
const maxAmount = maxBorrowAmounts.find(byDenom(denom))?.amount ?? BN_ZERO
|
||||||
const newBorrowings: BNCoin[] = [
|
const newBorrowings: BNCoin[] = [
|
||||||
new BNCoin({
|
new BNCoin({
|
||||||
denom,
|
denom,
|
||||||
@ -123,7 +120,8 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
|||||||
function onDelete(denom: string) {
|
function onDelete(denom: string) {
|
||||||
const index = props.borrowings.findIndex((coin) => coin.denom === denom)
|
const index = props.borrowings.findIndex((coin) => coin.denom === denom)
|
||||||
props.borrowings.splice(index, 1)
|
props.borrowings.splice(index, 1)
|
||||||
props.onChangeBorrowings([...props.borrowings])
|
const newBorrowings = [...props.borrowings]
|
||||||
|
props.onChangeBorrowings(newBorrowings)
|
||||||
if (!vaultModal) return
|
if (!vaultModal) return
|
||||||
|
|
||||||
useStore.setState({
|
useStore.setState({
|
||||||
@ -132,6 +130,7 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
|||||||
selectedBorrowDenoms: props.borrowings.map((coin) => coin.denom),
|
selectedBorrowDenoms: props.borrowings.map((coin) => coin.denom),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
setPercentage(calculateSliderPercentage(maxBorrowAmounts, newBorrowings))
|
||||||
}
|
}
|
||||||
|
|
||||||
function addAsset() {
|
function addAsset() {
|
||||||
@ -140,6 +139,7 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
|||||||
selectedDenoms: props.borrowings.map((coin) => coin.denom),
|
selectedDenoms: props.borrowings.map((coin) => coin.denom),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
setPercentage(calculateSliderPercentage(maxBorrowAmounts, props.borrowings))
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onConfirm() {
|
async function onConfirm() {
|
||||||
@ -209,7 +209,7 @@ export default function VaultBorrowings(props: VaultBorrowingsProps) {
|
|||||||
<div className='flex justify-between'>
|
<div className='flex justify-between'>
|
||||||
<Text className='text-white/50'>{`${props.primaryAsset.symbol}-${props.secondaryAsset.symbol} Position Value`}</Text>
|
<Text className='text-white/50'>{`${props.primaryAsset.symbol}-${props.secondaryAsset.symbol} Position Value`}</Text>
|
||||||
<DisplayCurrency
|
<DisplayCurrency
|
||||||
coin={new BNCoin({ denom: baseCurrency.denom, amount: totalValue.toString() })}
|
coin={new BNCoin({ denom: ORACLE_DENOM, amount: totalValue.toString() })}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{props.borrowings.map((coin) => {
|
{props.borrowings.map((coin) => {
|
||||||
|
@ -1,47 +1,60 @@
|
|||||||
|
import classNames from 'classnames'
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
|
|
||||||
import DisplayCurrency from 'components/DisplayCurrency'
|
import DisplayCurrency from 'components/DisplayCurrency'
|
||||||
import usePrices from 'hooks/usePrices'
|
import Text from 'components/Text'
|
||||||
import useStore from 'store'
|
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
|
||||||
import { formatAmountWithSymbol } from 'utils/formatters'
|
|
||||||
import { BN_ZERO } from 'constants/math'
|
import { BN_ZERO } from 'constants/math'
|
||||||
|
import usePrices from 'hooks/usePrices'
|
||||||
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
|
import { formatAmountWithSymbol, getCoinValue } from 'utils/formatters'
|
||||||
|
import { ORACLE_DENOM } from 'constants/oracle'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
borrowings: BNCoin[]
|
borrowings: BNCoin[]
|
||||||
|
displayCurrency: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function VaultDepositSubTitle(props: Props) {
|
export default function VaultBorrowingsSubTitle(props: Props) {
|
||||||
const baseCurrency = useStore((s) => s.baseCurrency)
|
|
||||||
const { data: prices } = usePrices()
|
const { data: prices } = usePrices()
|
||||||
|
|
||||||
const [borrowingTexts, borrowingValue] = useMemo(() => {
|
const borrowingValue = useMemo(() => {
|
||||||
const texts: string[] = []
|
|
||||||
let borrowingValue = BN_ZERO
|
let borrowingValue = BN_ZERO
|
||||||
props.borrowings.map((coin) => {
|
props.borrowings.map((coin) => {
|
||||||
const price = prices.find((p) => p.denom === coin.denom)?.amount
|
const price = prices.find((p) => p.denom === coin.denom)?.amount
|
||||||
if (!price || coin.amount.isZero()) return
|
if (!price || coin.amount.isZero()) return
|
||||||
borrowingValue = borrowingValue.plus(coin.amount.multipliedBy(price))
|
borrowingValue = getCoinValue(coin, prices)
|
||||||
texts.push(
|
|
||||||
formatAmountWithSymbol({
|
|
||||||
denom: coin.denom,
|
|
||||||
amount: coin.amount.toString(),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
return [texts, borrowingValue]
|
return borrowingValue
|
||||||
}, [props.borrowings, prices])
|
}, [props.borrowings, prices])
|
||||||
|
|
||||||
|
const borrowingTexts = useMemo(
|
||||||
|
() =>
|
||||||
|
props.borrowings.map((borrowing, index) => (
|
||||||
|
<Text
|
||||||
|
key={index}
|
||||||
|
size='xs'
|
||||||
|
className={classNames(
|
||||||
|
'inline mt-1 text-white/60',
|
||||||
|
index !== 0 && 'ml-1 before:pr-1 before:content-["+"]',
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{formatAmountWithSymbol(borrowing.toCoin())}
|
||||||
|
</Text>
|
||||||
|
)),
|
||||||
|
[props.borrowings],
|
||||||
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{borrowingTexts.join(' + ')}
|
{props.borrowings.length > 0 && borrowingTexts}
|
||||||
{borrowingTexts.length > 0 && (
|
{props.borrowings.length > 0 && (
|
||||||
<>
|
<DisplayCurrency
|
||||||
{` = `}
|
className={classNames(
|
||||||
<DisplayCurrency
|
'text-xs mt-1 text-white/60 ml-1 inline',
|
||||||
coin={new BNCoin({ denom: baseCurrency.denom, amount: borrowingValue.toString() })}
|
'before:content-["="] before:pr-1',
|
||||||
/>
|
)}
|
||||||
</>
|
coin={new BNCoin({ denom: ORACLE_DENOM, amount: borrowingValue.toString() })}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import BigNumber from 'bignumber.js'
|
import BigNumber from 'bignumber.js'
|
||||||
|
import { useMemo, useState } from 'react'
|
||||||
|
|
||||||
|
import DisplayCurrency from 'components/DisplayCurrency'
|
||||||
import Button from 'components/Button'
|
import Button from 'components/Button'
|
||||||
import DepositCapMessage from 'components/DepositCapMessage'
|
import DepositCapMessage from 'components/DepositCapMessage'
|
||||||
import DisplayCurrency from 'components/DisplayCurrency'
|
|
||||||
import Divider from 'components/Divider'
|
import Divider from 'components/Divider'
|
||||||
import { Gauge } from 'components/Gauge'
|
import { Gauge } from 'components/Gauge'
|
||||||
import { ArrowRight, ExclamationMarkCircled } from 'components/Icons'
|
import { ArrowRight, ExclamationMarkCircled } from 'components/Icons'
|
||||||
@ -10,14 +11,14 @@ import Slider from 'components/Slider'
|
|||||||
import Switch from 'components/Switch'
|
import Switch from 'components/Switch'
|
||||||
import Text from 'components/Text'
|
import Text from 'components/Text'
|
||||||
import TokenInput from 'components/TokenInput'
|
import TokenInput from 'components/TokenInput'
|
||||||
|
import { ASSETS } from 'constants/assets'
|
||||||
import { BN_ZERO } from 'constants/math'
|
import { BN_ZERO } from 'constants/math'
|
||||||
import usePrice from 'hooks/usePrice'
|
import usePrices from 'hooks/usePrices'
|
||||||
import { useMemo, useState } from 'react'
|
|
||||||
import useStore from 'store'
|
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import { accumulateAmounts } from 'utils/accounts'
|
import { accumulateAmounts } from 'utils/accounts'
|
||||||
import { findCoinByDenom } from 'utils/assets'
|
import { byDenom } from 'utils/array'
|
||||||
import { BN } from 'utils/helpers'
|
import { BN, getValueFromBNCoins } from 'utils/helpers'
|
||||||
|
import { ORACLE_DENOM } from 'constants/oracle'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
deposits: BNCoin[]
|
deposits: BNCoin[]
|
||||||
@ -28,13 +29,14 @@ interface Props {
|
|||||||
onChangeDeposits: (deposits: BNCoin[]) => void
|
onChangeDeposits: (deposits: BNCoin[]) => void
|
||||||
onChangeIsCustomRatio: (isCustomRatio: boolean) => void
|
onChangeIsCustomRatio: (isCustomRatio: boolean) => void
|
||||||
toggleOpen: (index: number) => void
|
toggleOpen: (index: number) => void
|
||||||
|
displayCurrency: string
|
||||||
depositCapReachedCoins: BNCoin[]
|
depositCapReachedCoins: BNCoin[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function VaultDeposit(props: Props) {
|
export default function VaultDeposit(props: Props) {
|
||||||
const { deposits, primaryAsset, secondaryAsset, account, onChangeDeposits } = props
|
const { deposits, primaryAsset, secondaryAsset, account, onChangeDeposits, displayCurrency } =
|
||||||
const baseCurrency = useStore((s) => s.baseCurrency)
|
props
|
||||||
|
const displayCurrencyAsset = ASSETS.find(byDenom(displayCurrency)) ?? ASSETS[0]
|
||||||
const [availablePrimaryAmount, availableSecondaryAmount] = useMemo(
|
const [availablePrimaryAmount, availableSecondaryAmount] = useMemo(
|
||||||
() => [
|
() => [
|
||||||
accumulateAmounts(primaryAsset.denom, [...account.deposits, ...account.lends]),
|
accumulateAmounts(primaryAsset.denom, [...account.deposits, ...account.lends]),
|
||||||
@ -42,37 +44,35 @@ export default function VaultDeposit(props: Props) {
|
|||||||
],
|
],
|
||||||
[account.deposits, account.lends, primaryAsset.denom, secondaryAsset.denom],
|
[account.deposits, account.lends, primaryAsset.denom, secondaryAsset.denom],
|
||||||
)
|
)
|
||||||
|
const { data: prices } = usePrices()
|
||||||
const primaryPrice = usePrice(primaryAsset.denom)
|
const primaryPrice = prices.find(byDenom(primaryAsset.denom))?.amount ?? BN_ZERO
|
||||||
const secondaryPrice = usePrice(secondaryAsset.denom)
|
const secondaryPrice = prices.find(byDenom(secondaryAsset.denom))?.amount ?? BN_ZERO
|
||||||
|
|
||||||
const primaryCoin = useMemo(() => {
|
const primaryCoin = useMemo(() => {
|
||||||
const amount = findCoinByDenom(primaryAsset.denom, deposits)?.amount.toString() || '0'
|
const amount = deposits.find(byDenom(primaryAsset.denom))?.amount ?? BN_ZERO
|
||||||
return new BNCoin({ denom: primaryAsset.denom, amount })
|
return new BNCoin({ denom: primaryAsset.denom, amount: amount.toString() })
|
||||||
}, [deposits, primaryAsset.denom])
|
}, [deposits, primaryAsset.denom])
|
||||||
|
|
||||||
const secondaryCoin = useMemo(() => {
|
const secondaryCoin = useMemo(() => {
|
||||||
const amount = findCoinByDenom(secondaryAsset.denom, deposits)?.amount.toString() || '0'
|
const amount = deposits.find(byDenom(secondaryAsset.denom))?.amount ?? BN_ZERO
|
||||||
return new BNCoin({ denom: secondaryAsset.denom, amount })
|
return new BNCoin({ denom: secondaryAsset.denom, amount: amount.toString() })
|
||||||
}, [deposits, secondaryAsset.denom])
|
}, [deposits, secondaryAsset.denom])
|
||||||
|
|
||||||
const primaryValue = useMemo(
|
const primaryValue = useMemo(
|
||||||
() => primaryCoin.amount.multipliedBy(primaryPrice),
|
() => getValueFromBNCoins([primaryCoin], prices),
|
||||||
[primaryCoin, primaryPrice],
|
[primaryCoin, prices],
|
||||||
)
|
|
||||||
const secondaryValue = useMemo(
|
|
||||||
() => secondaryCoin.amount.multipliedBy(secondaryPrice),
|
|
||||||
[secondaryCoin, secondaryPrice],
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const totalValue = useMemo(
|
const totalValue = useMemo(
|
||||||
() => primaryValue.plus(secondaryValue),
|
() => getValueFromBNCoins([primaryCoin, secondaryCoin], prices),
|
||||||
[primaryValue, secondaryValue],
|
[primaryCoin, secondaryCoin, prices],
|
||||||
)
|
)
|
||||||
|
|
||||||
const primaryValuePercentage = useMemo(() => {
|
const primaryValuePercentage = useMemo(() => {
|
||||||
const value = primaryValue.dividedBy(totalValue).multipliedBy(100).decimalPlaces(2).toNumber()
|
const value = primaryValue.dividedBy(totalValue).multipliedBy(100).decimalPlaces(2).toNumber()
|
||||||
return isNaN(value) ? 50 : value
|
return isNaN(value) ? 50 : value
|
||||||
}, [primaryValue, totalValue])
|
}, [primaryValue, totalValue])
|
||||||
|
|
||||||
const secondaryValuePercentage = useMemo(
|
const secondaryValuePercentage = useMemo(
|
||||||
() => new BigNumber(100).minus(primaryValuePercentage).integerValue(2).toNumber() ?? 50,
|
() => new BigNumber(100).minus(primaryValuePercentage).integerValue(2).toNumber() ?? 50,
|
||||||
[primaryValuePercentage],
|
[primaryValuePercentage],
|
||||||
@ -237,9 +237,7 @@ export default function VaultDeposit(props: Props) {
|
|||||||
</div>
|
</div>
|
||||||
<div className='flex justify-between'>
|
<div className='flex justify-between'>
|
||||||
<Text className='text-white/50'>{`${primaryAsset.symbol}-${secondaryAsset.symbol} Deposit Value`}</Text>
|
<Text className='text-white/50'>{`${primaryAsset.symbol}-${secondaryAsset.symbol} Deposit Value`}</Text>
|
||||||
<DisplayCurrency
|
<DisplayCurrency coin={BNCoin.fromDenomAndBigNumber(ORACLE_DENOM, totalValue)} />
|
||||||
coin={new BNCoin({ denom: baseCurrency.denom, amount: totalValue.toString() })}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => props.toggleOpen(1)}
|
onClick={() => props.toggleOpen(1)}
|
||||||
@ -250,4 +248,4 @@ export default function VaultDeposit(props: Props) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,35 +1,56 @@
|
|||||||
import BigNumber from 'bignumber.js'
|
import BigNumber from 'bignumber.js'
|
||||||
|
import classNames from 'classnames'
|
||||||
|
import { useMemo } from 'react'
|
||||||
|
|
||||||
import DisplayCurrency from 'components/DisplayCurrency'
|
import DisplayCurrency from 'components/DisplayCurrency'
|
||||||
import usePrice from 'hooks/usePrice'
|
import Text from 'components/Text'
|
||||||
import useStore from 'store'
|
import usePrices from 'hooks/usePrices'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import { formatAmountWithSymbol } from 'utils/formatters'
|
import { formatAmountWithSymbol } from 'utils/formatters'
|
||||||
|
import { getValueFromBNCoins } from 'utils/helpers'
|
||||||
|
import { ORACLE_DENOM } from 'constants/oracle'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
primaryAmount: BigNumber
|
primaryAmount: BigNumber
|
||||||
secondaryAmount: BigNumber
|
secondaryAmount: BigNumber
|
||||||
primaryAsset: Asset
|
primaryAsset: Asset
|
||||||
secondaryAsset: Asset
|
secondaryAsset: Asset
|
||||||
|
displayCurrency: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function VaultDepositSubTitle(props: Props) {
|
export default function VaultDepositSubTitle(props: Props) {
|
||||||
const baseCurrency = useStore((s) => s.baseCurrency)
|
const { data: prices } = usePrices()
|
||||||
const primaryPrice = usePrice(props.primaryAsset.denom)
|
const primaryText = useMemo(
|
||||||
const secondaryPrice = usePrice(props.secondaryAsset.denom)
|
() => (
|
||||||
const primaryText = formatAmountWithSymbol({
|
<Text size='xs' className='inline mt-1 text-white/60'>
|
||||||
denom: props.primaryAsset.denom,
|
{formatAmountWithSymbol({
|
||||||
amount: props.primaryAmount.toString(),
|
denom: props.primaryAsset.denom,
|
||||||
})
|
amount: props.primaryAmount.toString(),
|
||||||
const secondaryText = formatAmountWithSymbol({
|
})}
|
||||||
denom: props.secondaryAsset.denom,
|
</Text>
|
||||||
amount: props.secondaryAmount.toString(),
|
),
|
||||||
})
|
[props.primaryAmount, props.primaryAsset.denom],
|
||||||
|
)
|
||||||
|
|
||||||
const positionValue = props.primaryAmount
|
const secondaryText = useMemo(
|
||||||
.multipliedBy(primaryPrice)
|
() => (
|
||||||
.plus(props.secondaryAmount.multipliedBy(secondaryPrice))
|
<Text size='xs' className='inline mt-1 text-white/60 ml-1 before:pr-1 before:content-["+"]'>
|
||||||
.toNumber()
|
{formatAmountWithSymbol({
|
||||||
|
denom: props.secondaryAsset.denom,
|
||||||
|
amount: props.secondaryAmount.toString(),
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
),
|
||||||
|
[props.secondaryAmount, props.secondaryAsset.denom],
|
||||||
|
)
|
||||||
|
|
||||||
|
const positionValue = getValueFromBNCoins(
|
||||||
|
[
|
||||||
|
BNCoin.fromDenomAndBigNumber(props.primaryAsset.denom, props.primaryAmount),
|
||||||
|
BNCoin.fromDenomAndBigNumber(props.secondaryAsset.denom, props.secondaryAmount),
|
||||||
|
],
|
||||||
|
prices,
|
||||||
|
)
|
||||||
|
|
||||||
const showPrimaryText = !props.primaryAmount.isZero()
|
const showPrimaryText = !props.primaryAmount.isZero()
|
||||||
const showSecondaryText = !props.secondaryAmount.isZero()
|
const showSecondaryText = !props.secondaryAmount.isZero()
|
||||||
@ -37,15 +58,15 @@ export default function VaultDepositSubTitle(props: Props) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{showPrimaryText && primaryText}
|
{showPrimaryText && primaryText}
|
||||||
{showPrimaryText && showSecondaryText && ' + '}
|
|
||||||
{showSecondaryText && secondaryText}
|
{showSecondaryText && secondaryText}
|
||||||
{(showPrimaryText || showSecondaryText) && (
|
{(showPrimaryText || showSecondaryText) && (
|
||||||
<>
|
<DisplayCurrency
|
||||||
{` = `}
|
className={classNames(
|
||||||
<DisplayCurrency
|
'text-xs mt-1 text-white/60 ml-1 inline',
|
||||||
coin={new BNCoin({ denom: baseCurrency.denom, amount: positionValue.toString() })}
|
'before:content-["="] before:pr-1',
|
||||||
/>
|
)}
|
||||||
</>
|
coin={new BNCoin({ denom: ORACLE_DENOM, amount: positionValue.toString() })}
|
||||||
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
@ -6,16 +6,20 @@ import VaultBorrowings from 'components/Modals/Vault/VaultBorrowings'
|
|||||||
import VaultBorrowingsSubTitle from 'components/Modals/Vault/VaultBorrowingsSubTitle'
|
import VaultBorrowingsSubTitle from 'components/Modals/Vault/VaultBorrowingsSubTitle'
|
||||||
import VaultDeposit from 'components/Modals/Vault/VaultDeposits'
|
import VaultDeposit from 'components/Modals/Vault/VaultDeposits'
|
||||||
import VaultDepositSubTitle from 'components/Modals/Vault/VaultDepositsSubTitle'
|
import VaultDepositSubTitle from 'components/Modals/Vault/VaultDepositsSubTitle'
|
||||||
|
import Text from 'components/Text'
|
||||||
|
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
||||||
|
import { DISPLAY_CURRENCY_KEY } from 'constants/localStore'
|
||||||
import { BN_ZERO } from 'constants/math'
|
import { BN_ZERO } from 'constants/math'
|
||||||
import useDepositVault from 'hooks/broadcast/useDepositVault'
|
import useDepositVault from 'hooks/broadcast/useDepositVault'
|
||||||
import useDisplayAsset from 'hooks/useDisplayAsset'
|
import useDisplayAsset from 'hooks/useDisplayAsset'
|
||||||
import useIsOpenArray from 'hooks/useIsOpenArray'
|
import useIsOpenArray from 'hooks/useIsOpenArray'
|
||||||
|
import useLocalStorage from 'hooks/useLocalStorage'
|
||||||
import usePrices from 'hooks/usePrices'
|
import usePrices from 'hooks/usePrices'
|
||||||
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import { byDenom } from 'utils/array'
|
import { getCoinValue, magnify } from 'utils/formatters'
|
||||||
import { convertToDisplayAmount, magnify } from 'utils/formatters'
|
|
||||||
import { getCapLeftWithBuffer } from 'utils/generic'
|
import { getCapLeftWithBuffer } from 'utils/generic'
|
||||||
|
import { mergeBNCoinArrays } from 'utils/helpers'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
vault: Vault | DepositedVault
|
vault: Vault | DepositedVault
|
||||||
@ -26,17 +30,14 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default function VaultModalContent(props: Props) {
|
export default function VaultModalContent(props: Props) {
|
||||||
const {
|
const { addDebts, addedDebts, removedDeposits, removedLends, simulateVaultDeposit } =
|
||||||
addDebts,
|
useUpdatedAccount(props.account)
|
||||||
removeDeposits,
|
|
||||||
addedDebts,
|
|
||||||
removedDeposits,
|
|
||||||
removedLends,
|
|
||||||
removeLends,
|
|
||||||
addVaultValues,
|
|
||||||
} = useUpdatedAccount(props.account)
|
|
||||||
|
|
||||||
const { data: prices } = usePrices()
|
const { data: prices } = usePrices()
|
||||||
|
const [displayCurrency] = useLocalStorage<string>(
|
||||||
|
DISPLAY_CURRENCY_KEY,
|
||||||
|
DEFAULT_SETTINGS.displayCurrency,
|
||||||
|
)
|
||||||
const [isOpen, toggleOpen] = useIsOpenArray(2, false)
|
const [isOpen, toggleOpen] = useIsOpenArray(2, false)
|
||||||
const [isCustomRatio, setIsCustomRatio] = useState(false)
|
const [isCustomRatio, setIsCustomRatio] = useState(false)
|
||||||
const [selectedCoins, setSelectedCoins] = useState<BNCoin[]>([])
|
const [selectedCoins, setSelectedCoins] = useState<BNCoin[]>([])
|
||||||
@ -53,9 +54,8 @@ export default function VaultModalContent(props: Props) {
|
|||||||
|
|
||||||
if (totalValue.isGreaterThan(capLeft)) {
|
if (totalValue.isGreaterThan(capLeft)) {
|
||||||
const amount = magnify(
|
const amount = magnify(
|
||||||
convertToDisplayAmount(
|
getCoinValue(
|
||||||
BNCoin.fromDenomAndBigNumber(props.vault.cap.denom, capLeft),
|
BNCoin.fromDenomAndBigNumber(props.vault.cap.denom, capLeft),
|
||||||
displayAsset.denom,
|
|
||||||
prices,
|
prices,
|
||||||
).toString(),
|
).toString(),
|
||||||
displayAsset,
|
displayAsset,
|
||||||
@ -68,76 +68,58 @@ export default function VaultModalContent(props: Props) {
|
|||||||
|
|
||||||
const handleDepositSelect = useCallback(
|
const handleDepositSelect = useCallback(
|
||||||
(selectedCoins: BNCoin[]) => {
|
(selectedCoins: BNCoin[]) => {
|
||||||
const reclaims: BNCoin[] = []
|
simulateVaultDeposit(props.vault.address, selectedCoins)
|
||||||
const deposits: BNCoin[] = []
|
|
||||||
|
|
||||||
selectedCoins.forEach((selectedCoin) => {
|
|
||||||
const { denom, amount: selectedAmount } = selectedCoin
|
|
||||||
const accountDepositForSelectedCoin: BigNumber =
|
|
||||||
props.account.deposits.find(byDenom(denom))?.amount ?? BN_ZERO
|
|
||||||
|
|
||||||
if (selectedAmount.gt(accountDepositForSelectedCoin)) {
|
|
||||||
reclaims.push(
|
|
||||||
BNCoin.fromDenomAndBigNumber(
|
|
||||||
denom,
|
|
||||||
selectedAmount.minus(accountDepositForSelectedCoin),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
deposits.push(BNCoin.fromDenomAndBigNumber(denom, accountDepositForSelectedCoin))
|
|
||||||
} else {
|
|
||||||
deposits.push(selectedCoin)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
removeLends(reclaims)
|
|
||||||
removeDeposits(deposits)
|
|
||||||
setSelectedCoins(selectedCoins)
|
setSelectedCoins(selectedCoins)
|
||||||
},
|
},
|
||||||
[props.account.deposits, removeDeposits, removeLends],
|
[props.vault.address, simulateVaultDeposit],
|
||||||
)
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
addVaultValues([
|
|
||||||
{
|
|
||||||
address: props.vault.address,
|
|
||||||
value: totalValue,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
}, [totalValue, addVaultValues, props.vault.address])
|
|
||||||
|
|
||||||
const onChangeIsCustomRatio = useCallback(
|
const onChangeIsCustomRatio = useCallback(
|
||||||
(isCustomRatio: boolean) => setIsCustomRatio(isCustomRatio),
|
(isCustomRatio: boolean) => setIsCustomRatio(isCustomRatio),
|
||||||
[setIsCustomRatio],
|
[setIsCustomRatio],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const deposits = useMemo(
|
||||||
|
() => mergeBNCoinArrays(removedDeposits, removedLends),
|
||||||
|
[removedDeposits, removedLends],
|
||||||
|
)
|
||||||
|
|
||||||
function getDepositSubTitle() {
|
function getDepositSubTitle() {
|
||||||
if (isOpen[0] && props.isDeposited)
|
if (isOpen[0] && props.isDeposited)
|
||||||
return 'The amounts you enter below will be added to your current position.'
|
return (
|
||||||
|
<Text size='xs' className='mt-1 text-white/60'>
|
||||||
|
The amounts you enter below will be added to your current position.
|
||||||
|
</Text>
|
||||||
|
)
|
||||||
|
|
||||||
if (isOpen[0]) return null
|
if (isOpen[0]) return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VaultDepositSubTitle
|
<VaultDepositSubTitle
|
||||||
primaryAmount={
|
primaryAmount={
|
||||||
removedDeposits.find((coin) => coin.denom === props.primaryAsset.denom)?.amount || BN_ZERO
|
deposits.find((coin) => coin.denom === props.primaryAsset.denom)?.amount || BN_ZERO
|
||||||
}
|
}
|
||||||
secondaryAmount={
|
secondaryAmount={
|
||||||
removedDeposits.find((coin) => coin.denom === props.secondaryAsset.denom)?.amount ||
|
deposits.find((coin) => coin.denom === props.secondaryAsset.denom)?.amount || BN_ZERO
|
||||||
BN_ZERO
|
|
||||||
}
|
}
|
||||||
primaryAsset={props.primaryAsset}
|
primaryAsset={props.primaryAsset}
|
||||||
secondaryAsset={props.secondaryAsset}
|
secondaryAsset={props.secondaryAsset}
|
||||||
|
displayCurrency={displayCurrency}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
function getBorrowingsSubTitle() {
|
function getBorrowingsSubTitle() {
|
||||||
if (isOpen[1] && props.isDeposited)
|
if (isOpen[1] && props.isDeposited)
|
||||||
return 'The amounts you enter below will be added to your current position.'
|
return (
|
||||||
|
<Text size='xs' className='mt-1 text-white/60'>
|
||||||
|
The amounts you enter below will be added to your current position.
|
||||||
|
</Text>
|
||||||
|
)
|
||||||
|
|
||||||
if (isOpen[1]) return null
|
if (isOpen[1]) return null
|
||||||
|
|
||||||
return <VaultBorrowingsSubTitle borrowings={addedDebts} />
|
return <VaultBorrowingsSubTitle borrowings={addedDebts} displayCurrency={displayCurrency} />
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -156,6 +138,7 @@ export default function VaultModalContent(props: Props) {
|
|||||||
toggleOpen={toggleOpen}
|
toggleOpen={toggleOpen}
|
||||||
isCustomRatio={isCustomRatio}
|
isCustomRatio={isCustomRatio}
|
||||||
onChangeIsCustomRatio={onChangeIsCustomRatio}
|
onChangeIsCustomRatio={onChangeIsCustomRatio}
|
||||||
|
displayCurrency={displayCurrency}
|
||||||
depositCapReachedCoins={depositCapReachedCoins}
|
depositCapReachedCoins={depositCapReachedCoins}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
@ -168,13 +151,14 @@ export default function VaultModalContent(props: Props) {
|
|||||||
renderContent: () => (
|
renderContent: () => (
|
||||||
<VaultBorrowings
|
<VaultBorrowings
|
||||||
borrowings={addedDebts}
|
borrowings={addedDebts}
|
||||||
deposits={removedDeposits}
|
deposits={deposits}
|
||||||
primaryAsset={props.primaryAsset}
|
primaryAsset={props.primaryAsset}
|
||||||
secondaryAsset={props.secondaryAsset}
|
secondaryAsset={props.secondaryAsset}
|
||||||
onChangeBorrowings={addDebts}
|
onChangeBorrowings={addDebts}
|
||||||
vault={props.vault}
|
vault={props.vault}
|
||||||
depositActions={depositActions}
|
depositActions={depositActions}
|
||||||
depositCapReachedCoins={depositCapReachedCoins}
|
depositCapReachedCoins={depositCapReachedCoins}
|
||||||
|
displayCurrency={displayCurrency}
|
||||||
/>
|
/>
|
||||||
),
|
),
|
||||||
title: 'Borrow',
|
title: 'Borrow',
|
||||||
|
@ -4,8 +4,8 @@ import DisplayCurrency from 'components/DisplayCurrency'
|
|||||||
import { FormattedNumber } from 'components/FormattedNumber'
|
import { FormattedNumber } from 'components/FormattedNumber'
|
||||||
import TitleAndSubCell from 'components/TitleAndSubCell'
|
import TitleAndSubCell from 'components/TitleAndSubCell'
|
||||||
import { BN_ZERO } from 'constants/math'
|
import { BN_ZERO } from 'constants/math'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
|
||||||
import { PRICE_ORACLE_DECIMALS } from 'constants/query'
|
import { PRICE_ORACLE_DECIMALS } from 'constants/query'
|
||||||
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import { BN } from 'utils/helpers'
|
import { BN } from 'utils/helpers'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -28,7 +28,7 @@ export default function VaultModalContentHeader({ vault }: Props) {
|
|||||||
}, [vault])
|
}, [vault])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex gap-6 border-b border-white/5 px-6 py-4 gradient-header'>
|
<div className='flex gap-6 px-6 py-4 border-b border-white/5 gradient-header'>
|
||||||
{vault.apy && (
|
{vault.apy && (
|
||||||
<>
|
<>
|
||||||
<TitleAndSubCell
|
<TitleAndSubCell
|
||||||
@ -39,14 +39,13 @@ export default function VaultModalContentHeader({ vault }: Props) {
|
|||||||
options={{ suffix: '%', decimals: -2 }}
|
options={{ suffix: '%', decimals: -2 }}
|
||||||
animate
|
animate
|
||||||
/>
|
/>
|
||||||
(
|
|
||||||
<FormattedNumber
|
<FormattedNumber
|
||||||
className='ml-2 text-xs'
|
className='ml-2 text-xs'
|
||||||
amount={vault.apy / 365}
|
amount={vault.apy / 365}
|
||||||
options={{ suffix: '%/day', decimals: -2 }}
|
options={{ suffix: '%/day', decimals: -2 }}
|
||||||
|
parentheses
|
||||||
animate
|
animate
|
||||||
/>
|
/>
|
||||||
)
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
sub={'Deposit APY'}
|
sub={'Deposit APY'}
|
||||||
|
@ -19,7 +19,9 @@ import useStore from 'store'
|
|||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import { byDenom } from 'utils/array'
|
import { byDenom } from 'utils/array'
|
||||||
import { defaultFee } from 'utils/constants'
|
import { defaultFee } from 'utils/constants'
|
||||||
import { convertToDisplayAmount, formatAmountWithSymbol } from 'utils/formatters'
|
import { formatAmountWithSymbol, getCoinValue } from 'utils/formatters'
|
||||||
|
|
||||||
|
import { ORACLE_DENOM } from '../constants/oracle'
|
||||||
|
|
||||||
const renderIncentives = (unclaimedRewards: BNCoin[]) => {
|
const renderIncentives = (unclaimedRewards: BNCoin[]) => {
|
||||||
if (unclaimedRewards.length === 0)
|
if (unclaimedRewards.length === 0)
|
||||||
@ -58,14 +60,14 @@ export default function RewardsCenter() {
|
|||||||
const totalRewardsCoin = useMemo(() => {
|
const totalRewardsCoin = useMemo(() => {
|
||||||
let total = 0
|
let total = 0
|
||||||
unclaimedRewards.forEach((reward) => {
|
unclaimedRewards.forEach((reward) => {
|
||||||
total = total + convertToDisplayAmount(reward, displayCurrency, prices).toNumber()
|
total = total + getCoinValue(reward, prices).toNumber()
|
||||||
})
|
})
|
||||||
|
|
||||||
return new BNCoin({
|
return new BNCoin({
|
||||||
denom: displayCurrency,
|
denom: ORACLE_DENOM,
|
||||||
amount: total.toString(),
|
amount: total.toString(),
|
||||||
})
|
})
|
||||||
}, [displayCurrency, prices, unclaimedRewards])
|
}, [prices, unclaimedRewards])
|
||||||
|
|
||||||
const hasIncentives = unclaimedRewards.length > 0
|
const hasIncentives = unclaimedRewards.length > 0
|
||||||
|
|
||||||
|
@ -73,8 +73,6 @@ export default function Slider(props: Props) {
|
|||||||
setShowTooltip(false)
|
setShowTooltip(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// draggable workaround - to solve node compatibility issues
|
|
||||||
// TODO: find a replacement for react-draggable
|
|
||||||
const DraggableElement: any = Draggable
|
const DraggableElement: any = Draggable
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -63,7 +63,6 @@ export const MOCK_DEPOSITED_VAULT_POSITION = {
|
|||||||
unlocking: BN_ZERO,
|
unlocking: BN_ZERO,
|
||||||
},
|
},
|
||||||
status: VaultStatus.ACTIVE,
|
status: VaultStatus.ACTIVE,
|
||||||
apy: null,
|
|
||||||
ltv: {
|
ltv: {
|
||||||
liq: 0,
|
liq: 0,
|
||||||
max: 0,
|
max: 0,
|
||||||
|
@ -4,6 +4,7 @@ import { useMemo, useState } from 'react'
|
|||||||
import getMinLpToReceive from 'api/vaults/getMinLpToReceive'
|
import getMinLpToReceive from 'api/vaults/getMinLpToReceive'
|
||||||
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
||||||
import { SLIPPAGE_KEY } from 'constants/localStore'
|
import { SLIPPAGE_KEY } from 'constants/localStore'
|
||||||
|
import { BN_ZERO } from 'constants/math'
|
||||||
import useLocalStorage from 'hooks/useLocalStorage'
|
import useLocalStorage from 'hooks/useLocalStorage'
|
||||||
import usePrices from 'hooks/usePrices'
|
import usePrices from 'hooks/usePrices'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
@ -13,7 +14,6 @@ import {
|
|||||||
getVaultDepositCoinsAndValue,
|
getVaultDepositCoinsAndValue,
|
||||||
getVaultSwapActions,
|
getVaultSwapActions,
|
||||||
} from 'utils/vaults'
|
} from 'utils/vaults'
|
||||||
import { BN_ZERO } from 'constants/math'
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
vault: Vault
|
vault: Vault
|
||||||
@ -21,6 +21,7 @@ interface Props {
|
|||||||
deposits: BNCoin[]
|
deposits: BNCoin[]
|
||||||
borrowings: BNCoin[]
|
borrowings: BNCoin[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function useDepositVault(props: Props): {
|
export default function useDepositVault(props: Props): {
|
||||||
actions: Action[]
|
actions: Action[]
|
||||||
minLpToReceive: string
|
minLpToReceive: string
|
||||||
@ -38,12 +39,16 @@ export default function useDepositVault(props: Props): {
|
|||||||
() => props.deposits.filter((deposit) => deposit.amount.gt(0)),
|
() => props.deposits.filter((deposit) => deposit.amount.gt(0)),
|
||||||
[props.deposits],
|
[props.deposits],
|
||||||
)
|
)
|
||||||
|
const reclaims: BNCoin[] = useMemo(
|
||||||
|
() => props.reclaims.filter((reclaim) => reclaim.amount.gt(0)),
|
||||||
|
[props.reclaims],
|
||||||
|
)
|
||||||
|
|
||||||
const debouncedGetMinLpToReceive = useMemo(() => debounce(getMinLpToReceive, 500), [])
|
const debouncedGetMinLpToReceive = useMemo(() => debounce(getMinLpToReceive, 500), [])
|
||||||
|
|
||||||
const { primaryCoin, secondaryCoin, totalValue } = useMemo(
|
const { primaryCoin, secondaryCoin, totalValue } = useMemo(
|
||||||
() => getVaultDepositCoinsAndValue(props.vault, deposits, borrowings, prices),
|
() => getVaultDepositCoinsAndValue(props.vault, deposits, borrowings, reclaims, prices),
|
||||||
[deposits, borrowings, props.vault, prices],
|
[reclaims, deposits, borrowings, props.vault, prices],
|
||||||
)
|
)
|
||||||
|
|
||||||
const reclaimActions: Action[] = useMemo(() => {
|
const reclaimActions: Action[] = useMemo(() => {
|
||||||
|
@ -177,7 +177,6 @@ export default function useHealthComputer(account?: Account) {
|
|||||||
},
|
},
|
||||||
[healthComputer],
|
[healthComputer],
|
||||||
)
|
)
|
||||||
|
|
||||||
const health = useMemo(() => {
|
const health = useMemo(() => {
|
||||||
if (healthFactor > 10) return 100
|
if (healthFactor > 10) return 100
|
||||||
if (healthFactor < 0) return 0
|
if (healthFactor < 0) return 0
|
||||||
|
@ -40,6 +40,7 @@ export function removeCoins(coinsToRemove: BNCoin[], currentCoins: BNCoin[]) {
|
|||||||
export function addValueToVaults(
|
export function addValueToVaults(
|
||||||
vaultValues: VaultValue[],
|
vaultValues: VaultValue[],
|
||||||
vaults: DepositedVault[],
|
vaults: DepositedVault[],
|
||||||
|
availableVaults: Vault[],
|
||||||
): DepositedVault[] {
|
): DepositedVault[] {
|
||||||
const currentVaultAddresses = vaults.map((vault) => vault.address)
|
const currentVaultAddresses = vaults.map((vault) => vault.address)
|
||||||
|
|
||||||
@ -55,10 +56,12 @@ export function addValueToVaults(
|
|||||||
const vaultMetaData = getVaultMetaData(vaultValue.address)
|
const vaultMetaData = getVaultMetaData(vaultValue.address)
|
||||||
|
|
||||||
if (!vaultMetaData) return
|
if (!vaultMetaData) return
|
||||||
|
const apy = availableVaults.find((vault) => vault.address === vaultValue.address)?.apy ?? null
|
||||||
|
|
||||||
vaults.push({
|
vaults.push({
|
||||||
...vaultMetaData,
|
...vaultMetaData,
|
||||||
...MOCK_DEPOSITED_VAULT_POSITION,
|
...MOCK_DEPOSITED_VAULT_POSITION,
|
||||||
|
apy,
|
||||||
values: {
|
values: {
|
||||||
primary: halfValue,
|
primary: halfValue,
|
||||||
secondary: halfValue,
|
secondary: halfValue,
|
||||||
@ -70,10 +73,10 @@ export function addValueToVaults(
|
|||||||
return vaults
|
return vaults
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDepositsAndLendsAfterCoinSpent(coin: BNCoin, account?: Account) {
|
export function getDepositAndLendCoinsToSpend(coin: BNCoin, account?: Account) {
|
||||||
const makeOutput = (depositsAmount: BigNumber, lendsAmount: BigNumber) => ({
|
const makeOutput = (depositsAmount: BigNumber, lendsAmount: BigNumber) => ({
|
||||||
deposits: BNCoin.fromDenomAndBigNumber(coin.denom, depositsAmount),
|
deposit: BNCoin.fromDenomAndBigNumber(coin.denom, depositsAmount),
|
||||||
lends: BNCoin.fromDenomAndBigNumber(coin.denom, lendsAmount),
|
lend: BNCoin.fromDenomAndBigNumber(coin.denom, lendsAmount),
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!account) return makeOutput(BN_ZERO, BN_ZERO)
|
if (!account) return makeOutput(BN_ZERO, BN_ZERO)
|
||||||
|
@ -1,16 +1,19 @@
|
|||||||
import { useCallback, useEffect, useState } from 'react'
|
import { useCallback, useEffect, useState } from 'react'
|
||||||
|
|
||||||
import { BN_ZERO } from 'constants/math'
|
import { BN_ZERO } from 'constants/math'
|
||||||
|
import usePrices from 'hooks/usePrices'
|
||||||
import {
|
import {
|
||||||
addCoins,
|
addCoins,
|
||||||
addValueToVaults,
|
addValueToVaults,
|
||||||
getDepositsAndLendsAfterCoinSpent,
|
getDepositAndLendCoinsToSpend,
|
||||||
removeCoins,
|
removeCoins,
|
||||||
} from 'hooks/useUpdatedAccount/functions'
|
} from 'hooks/useUpdatedAccount/functions'
|
||||||
|
import useVaults from 'hooks/useVaults'
|
||||||
import useStore from 'store'
|
import useStore from 'store'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import { cloneAccount } from 'utils/accounts'
|
import { cloneAccount } from 'utils/accounts'
|
||||||
import { byDenom } from 'utils/array'
|
import { byDenom } from 'utils/array'
|
||||||
|
import { getValueFromBNCoins } from 'utils/helpers'
|
||||||
|
|
||||||
export interface VaultValue {
|
export interface VaultValue {
|
||||||
address: string
|
address: string
|
||||||
@ -18,6 +21,8 @@ export interface VaultValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function useUpdatedAccount(account?: Account) {
|
export function useUpdatedAccount(account?: Account) {
|
||||||
|
const { data: availableVaults } = useVaults(false)
|
||||||
|
const { data: prices } = usePrices()
|
||||||
const [updatedAccount, setUpdatedAccount] = useState<Account | undefined>(
|
const [updatedAccount, setUpdatedAccount] = useState<Account | undefined>(
|
||||||
account ? cloneAccount(account) : undefined,
|
account ? cloneAccount(account) : undefined,
|
||||||
)
|
)
|
||||||
@ -84,10 +89,10 @@ export function useUpdatedAccount(account?: Account) {
|
|||||||
const simulateRepay = useCallback(
|
const simulateRepay = useCallback(
|
||||||
(coin: BNCoin) => {
|
(coin: BNCoin) => {
|
||||||
if (!account) return
|
if (!account) return
|
||||||
const { deposits, lends } = getDepositsAndLendsAfterCoinSpent(coin, account)
|
const { deposit, lend } = getDepositAndLendCoinsToSpend(coin, account)
|
||||||
removeDebts([coin])
|
removeDebts([coin])
|
||||||
removeDeposits([deposits])
|
removeDeposits([deposit])
|
||||||
removeLends([lends])
|
removeLends([lend])
|
||||||
},
|
},
|
||||||
[account, removeDebts, removeDeposits, removeLends],
|
[account, removeDebts, removeDeposits, removeLends],
|
||||||
)
|
)
|
||||||
@ -110,10 +115,10 @@ export function useUpdatedAccount(account?: Account) {
|
|||||||
removeLends([])
|
removeLends([])
|
||||||
addDebts([])
|
addDebts([])
|
||||||
|
|
||||||
const { deposits, lends } = getDepositsAndLendsAfterCoinSpent(coin, account)
|
const { deposit, lend } = getDepositAndLendCoinsToSpend(coin, account)
|
||||||
const totalBalance = deposits.amount.plus(lends.amount)
|
const totalBalance = deposit.amount.plus(lend.amount)
|
||||||
removeDeposits([deposits])
|
removeDeposits([deposit])
|
||||||
removeLends([lends])
|
removeLends([lend])
|
||||||
if (withdrawWithBorrowing) {
|
if (withdrawWithBorrowing) {
|
||||||
addDebts([BNCoin.fromDenomAndBigNumber(coin.denom, coin.amount.minus(totalBalance))])
|
addDebts([BNCoin.fromDenomAndBigNumber(coin.denom, coin.amount.minus(totalBalance))])
|
||||||
}
|
}
|
||||||
@ -129,10 +134,10 @@ export function useUpdatedAccount(account?: Account) {
|
|||||||
addDeposits([])
|
addDeposits([])
|
||||||
addLends([])
|
addLends([])
|
||||||
|
|
||||||
const { deposits, lends } = getDepositsAndLendsAfterCoinSpent(removeCoin, account)
|
const { deposit, lend } = getDepositAndLendCoinsToSpend(removeCoin, account)
|
||||||
|
|
||||||
removeDeposits([deposits])
|
removeDeposits([deposit])
|
||||||
removeLends([lends])
|
removeLends([lend])
|
||||||
if (target === 'deposit') addDeposits([addCoin])
|
if (target === 'deposit') addDeposits([addCoin])
|
||||||
if (target === 'lend') addLends([addCoin])
|
if (target === 'lend') addLends([addCoin])
|
||||||
|
|
||||||
@ -141,13 +146,38 @@ export function useUpdatedAccount(account?: Account) {
|
|||||||
[account, addDebts, addDeposits, addLends, removeDeposits, removeLends],
|
[account, addDebts, addDeposits, addLends, removeDeposits, removeLends],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const simulateVaultDeposit = useCallback(
|
||||||
|
(address: string, coins: BNCoin[]) => {
|
||||||
|
if (!account) return
|
||||||
|
|
||||||
|
const value = getValueFromBNCoins(coins, prices)
|
||||||
|
const totalDeposits: BNCoin[] = []
|
||||||
|
const totalLends: BNCoin[] = []
|
||||||
|
|
||||||
|
coins.forEach((coin) => {
|
||||||
|
const { deposit, lend } = getDepositAndLendCoinsToSpend(coin, account)
|
||||||
|
totalDeposits.push(deposit)
|
||||||
|
totalLends.push(lend)
|
||||||
|
})
|
||||||
|
|
||||||
|
addVaultValues([{ address, value }])
|
||||||
|
removeDeposits(totalDeposits)
|
||||||
|
removeLends(totalLends)
|
||||||
|
},
|
||||||
|
[account, prices],
|
||||||
|
)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!account) return
|
if (!account) return
|
||||||
|
|
||||||
const accountCopy = cloneAccount(account)
|
const accountCopy = cloneAccount(account)
|
||||||
accountCopy.deposits = addCoins(addedDeposits, [...accountCopy.deposits])
|
accountCopy.deposits = addCoins(addedDeposits, [...accountCopy.deposits])
|
||||||
accountCopy.debts = addCoins(addedDebts, [...accountCopy.debts])
|
accountCopy.debts = addCoins(addedDebts, [...accountCopy.debts])
|
||||||
accountCopy.vaults = addValueToVaults(addedVaultValues, [...accountCopy.vaults])
|
accountCopy.vaults = addValueToVaults(
|
||||||
|
addedVaultValues,
|
||||||
|
[...accountCopy.vaults],
|
||||||
|
availableVaults ?? [],
|
||||||
|
)
|
||||||
accountCopy.deposits = removeCoins(removedDeposits, [...accountCopy.deposits])
|
accountCopy.deposits = removeCoins(removedDeposits, [...accountCopy.deposits])
|
||||||
accountCopy.debts = removeCoins(removedDebts, [...accountCopy.debts])
|
accountCopy.debts = removeCoins(removedDebts, [...accountCopy.debts])
|
||||||
accountCopy.lends = addCoins(addedLends, [...accountCopy.lends])
|
accountCopy.lends = addCoins(addedLends, [...accountCopy.lends])
|
||||||
@ -165,6 +195,7 @@ export function useUpdatedAccount(account?: Account) {
|
|||||||
addedVaultValues,
|
addedVaultValues,
|
||||||
addedLends,
|
addedLends,
|
||||||
removedLends,
|
removedLends,
|
||||||
|
availableVaults,
|
||||||
])
|
])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -188,6 +219,7 @@ export function useUpdatedAccount(account?: Account) {
|
|||||||
simulateLending,
|
simulateLending,
|
||||||
simulateRepay,
|
simulateRepay,
|
||||||
simulateTrade,
|
simulateTrade,
|
||||||
|
simulateVaultDeposit,
|
||||||
simulateWithdraw,
|
simulateWithdraw,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@ import useSWR from 'swr'
|
|||||||
|
|
||||||
import getVaults from 'api/vaults/getVaults'
|
import getVaults from 'api/vaults/getVaults'
|
||||||
|
|
||||||
export default function useVaults(address?: string) {
|
export default function useVaults(suspense: boolean = true, address?: string) {
|
||||||
return useSWR(`vaults${address}`, () => getVaults(), {
|
return useSWR(`vaults${address}`, () => getVaults(), {
|
||||||
suspense: true,
|
suspense,
|
||||||
revalidateOnFocus: false,
|
revalidateOnFocus: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -362,7 +362,7 @@ export default function createBroadcastSlice(
|
|||||||
accountId: string
|
accountId: string
|
||||||
coin: BNCoin
|
coin: BNCoin
|
||||||
accountBalance?: boolean
|
accountBalance?: boolean
|
||||||
lends?: BNCoin
|
lend?: BNCoin
|
||||||
}) => {
|
}) => {
|
||||||
const actions: Action[] = [
|
const actions: Action[] = [
|
||||||
{
|
{
|
||||||
@ -372,8 +372,8 @@ export default function createBroadcastSlice(
|
|||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
if (options.lends && options.lends.amount.isGreaterThan(0))
|
if (options.lend && options.lend.amount.isGreaterThan(0))
|
||||||
actions.unshift({ reclaim: options.lends.toActionCoin() })
|
actions.unshift({ reclaim: options.lend.toActionCoin() })
|
||||||
|
|
||||||
const msg: CreditManagerExecuteMsg = {
|
const msg: CreditManagerExecuteMsg = {
|
||||||
update_credit_account: {
|
update_credit_account: {
|
||||||
|
2
src/types/interfaces/store/broadcast.d.ts
vendored
2
src/types/interfaces/store/broadcast.d.ts
vendored
@ -29,7 +29,7 @@ interface BroadcastSlice {
|
|||||||
accountId: string
|
accountId: string
|
||||||
coin: BNCoin
|
coin: BNCoin
|
||||||
accountBalance?: boolean
|
accountBalance?: boolean
|
||||||
lends?: BNCoin
|
lend?: BNCoin
|
||||||
}) => Promise<boolean>
|
}) => Promise<boolean>
|
||||||
swap: (options: {
|
swap: (options: {
|
||||||
accountId: string
|
accountId: string
|
||||||
|
@ -45,7 +45,7 @@ export const calculateAccountValue = (
|
|||||||
acc.plus(vaultPosition.values.primary).plus(vaultPosition.values.secondary),
|
acc.plus(vaultPosition.values.primary).plus(vaultPosition.values.secondary),
|
||||||
BN_ZERO,
|
BN_ZERO,
|
||||||
) || BN_ZERO
|
) || BN_ZERO
|
||||||
).shiftedBy(-6)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return account[type]?.reduce((acc, position) => {
|
return account[type]?.reduce((acc, position) => {
|
||||||
@ -85,13 +85,8 @@ export const calculateAccountApr = (
|
|||||||
})
|
})
|
||||||
|
|
||||||
vaults?.forEach((vault) => {
|
vaults?.forEach((vault) => {
|
||||||
const asset = getAssetByDenom(vault.denoms.lp)
|
const vaultValue = vault.values.primary.plus(vault.values.secondary)
|
||||||
if (!asset) return BN_ZERO
|
const positionInterest = vaultValue.multipliedBy(convertApyToApr(vault?.apy ?? 0, 365))
|
||||||
const price = prices.find(byDenom(vault.denoms.lp))?.amount ?? 0
|
|
||||||
const amount = BN(vault.amounts.locked).shiftedBy(-asset.decimals)
|
|
||||||
const positionInterest = amount
|
|
||||||
.multipliedBy(price)
|
|
||||||
.multipliedBy(convertApyToApr(vault?.apy ?? 0, 365))
|
|
||||||
totalVaultsInterestValue = totalVaultsInterestValue.plus(positionInterest)
|
totalVaultsInterestValue = totalVaultsInterestValue.plus(positionInterest)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -219,7 +214,7 @@ export function removeDepositsAndLends(account: Account, denom: string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getMergedBalances(account: Account, assets: Asset[]) {
|
export function getMergedBalancesForAsset(account: Account, assets: Asset[]) {
|
||||||
const balances: BNCoin[] = []
|
const balances: BNCoin[] = []
|
||||||
assets.forEach((asset) => {
|
assets.forEach((asset) => {
|
||||||
const balance = accumulateAmounts(asset.denom, [...account.deposits, ...account.lends])
|
const balance = accumulateAmounts(asset.denom, [...account.deposits, ...account.lends])
|
||||||
|
@ -177,16 +177,14 @@ export function demagnify(amount: number | string | BigNumber, asset: Asset | Ps
|
|||||||
return value.isZero() ? 0 : value.shiftedBy(-1 * asset.decimals).toNumber()
|
return value.isZero() ? 0 : value.shiftedBy(-1 * asset.decimals).toNumber()
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertToDisplayAmount(coin: BNCoin, displayCurrency: string, prices: BNCoin[]) {
|
export function getCoinValue(coin: BNCoin, prices: BNCoin[]) {
|
||||||
const price = prices.find((price) => price.denom === coin.denom)
|
|
||||||
const asset = getAllAssets().find((asset) => asset.denom === coin.denom)
|
const asset = getAllAssets().find((asset) => asset.denom === coin.denom)
|
||||||
const displayPrice = prices.find((price) => price.denom === displayCurrency)
|
const coinPrice = prices.find((price) => price.denom === coin.denom)
|
||||||
|
|
||||||
if (!price || !displayPrice || !asset) return BN_ZERO
|
if (!coinPrice || !asset) return BN_ZERO
|
||||||
|
|
||||||
const decimals = asset.denom === ORACLE_DENOM ? 0 : asset.decimals * -1
|
const decimals = asset.denom === ORACLE_DENOM ? 0 : asset.decimals * -1
|
||||||
|
return coin.amount.shiftedBy(decimals).multipliedBy(coinPrice.amount)
|
||||||
return coin.amount.shiftedBy(decimals).multipliedBy(price.amount).dividedBy(displayPrice.amount)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertLiquidityRateToAPR(rate: number) {
|
export function convertLiquidityRateToAPR(rate: number) {
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
import BigNumber from 'bignumber.js'
|
import BigNumber from 'bignumber.js'
|
||||||
import throttle from 'lodash.throttle'
|
import throttle from 'lodash.throttle'
|
||||||
|
|
||||||
|
import { BN_ZERO } from 'constants/math'
|
||||||
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
|
import { getCoinValue } from 'utils/formatters'
|
||||||
|
|
||||||
BigNumber.config({ EXPONENTIAL_AT: 1e9 })
|
BigNumber.config({ EXPONENTIAL_AT: 1e9 })
|
||||||
|
|
||||||
export function BN(n: BigNumber.Value) {
|
export function BN(n: BigNumber.Value) {
|
||||||
return new BigNumber(n)
|
return new BigNumber(n)
|
||||||
}
|
}
|
||||||
@ -23,3 +28,31 @@ export function asyncThrottle<F extends (...args: any[]) => Promise<any>>(func:
|
|||||||
throttled(resolve, reject, args)
|
throttled(resolve, reject, args)
|
||||||
}) as ReturnType<F>
|
}) as ReturnType<F>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function mergeBNCoinArrays(array1: BNCoin[], array2: BNCoin[]) {
|
||||||
|
const merged: BNCoin[] = []
|
||||||
|
|
||||||
|
array1.forEach((coin) => {
|
||||||
|
merged.push(new BNCoin(coin.toCoin()))
|
||||||
|
})
|
||||||
|
|
||||||
|
array2.forEach((coin) => {
|
||||||
|
const index = merged.findIndex((i) => i.denom === coin.denom)
|
||||||
|
if (index === -1) {
|
||||||
|
merged.push(new BNCoin(coin.toCoin()))
|
||||||
|
} else {
|
||||||
|
merged[index].amount = merged[index].amount.plus(coin.amount)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return merged
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getValueFromBNCoins(coins: BNCoin[], prices: BNCoin[]): BigNumber {
|
||||||
|
let totalValue = BN_ZERO
|
||||||
|
|
||||||
|
coins.forEach((coin) => {
|
||||||
|
totalValue = totalValue.plus(getCoinValue(coin, prices))
|
||||||
|
})
|
||||||
|
|
||||||
|
return totalValue
|
||||||
|
}
|
||||||
|
@ -17,9 +17,8 @@ export const convertAprToApy = (apr: number, numberOfCompoundingPeriods: number)
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const convertApyToApr = (apy: number, numberOfCompoundingPeriods: number): number => {
|
export const convertApyToApr = (apy: number, numberOfCompoundingPeriods: number): number => {
|
||||||
return (
|
const periodicRate = (1 + apy) ** (1 / numberOfCompoundingPeriods) - 1
|
||||||
(Math.pow(1 + apy / 100, numberOfCompoundingPeriods) - 1) * 100 * numberOfCompoundingPeriods
|
return periodicRate * numberOfCompoundingPeriods
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const combineBNCoins = (coins: BNCoin[]): BNCoin[] => {
|
export const combineBNCoins = (coins: BNCoin[]): BNCoin[] => {
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
|
import { ASSETS } from 'constants/assets'
|
||||||
import { IS_TESTNET } from 'constants/env'
|
import { IS_TESTNET } from 'constants/env'
|
||||||
import { BN_ZERO } from 'constants/math'
|
import { BN_ZERO } from 'constants/math'
|
||||||
import { TESTNET_VAULTS_META_DATA, VAULTS_META_DATA } from 'constants/vaults'
|
import { TESTNET_VAULTS_META_DATA, VAULTS_META_DATA } from 'constants/vaults'
|
||||||
import { BNCoin } from 'types/classes/BNCoin'
|
import { BNCoin } from 'types/classes/BNCoin'
|
||||||
import { Action } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
import { Action } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||||
|
import { getAssetByDenom } from 'utils/assets'
|
||||||
import { getTokenPrice, getTokenValue } from 'utils/tokens'
|
import { getTokenPrice, getTokenValue } from 'utils/tokens'
|
||||||
|
|
||||||
|
import { getValueFromBNCoins, mergeBNCoinArrays } from './helpers'
|
||||||
|
|
||||||
export function getVaultsMetaData() {
|
export function getVaultsMetaData() {
|
||||||
return IS_TESTNET ? TESTNET_VAULTS_META_DATA : VAULTS_META_DATA
|
return IS_TESTNET ? TESTNET_VAULTS_META_DATA : VAULTS_META_DATA
|
||||||
}
|
}
|
||||||
@ -18,23 +22,25 @@ export function getVaultDepositCoinsAndValue(
|
|||||||
vault: Vault,
|
vault: Vault,
|
||||||
deposits: BNCoin[],
|
deposits: BNCoin[],
|
||||||
borrowings: BNCoin[],
|
borrowings: BNCoin[],
|
||||||
|
reclaims: BNCoin[],
|
||||||
prices: BNCoin[],
|
prices: BNCoin[],
|
||||||
) {
|
) {
|
||||||
const totalValue = [...deposits, ...borrowings].reduce((prev, bnCoin) => {
|
const depositsAndReclaims = mergeBNCoinArrays(deposits, reclaims)
|
||||||
const price = prices.find((coin) => coin.denom === bnCoin.denom)?.amount
|
const borrowingsAndDepositsAndReclaims = mergeBNCoinArrays(borrowings, depositsAndReclaims)
|
||||||
if (!price) return prev
|
const totalValue = getValueFromBNCoins(borrowingsAndDepositsAndReclaims, prices)
|
||||||
|
|
||||||
return prev.plus(bnCoin.amount.multipliedBy(price))
|
|
||||||
}, BN_ZERO)
|
|
||||||
|
|
||||||
const halfValue = totalValue.dividedBy(2)
|
const halfValue = totalValue.dividedBy(2)
|
||||||
|
|
||||||
|
const primaryAsset = getAssetByDenom(vault.denoms.primary) ?? ASSETS[0]
|
||||||
|
const secondaryAsset = getAssetByDenom(vault.denoms.secondary) ?? ASSETS[0]
|
||||||
|
|
||||||
const primaryDepositAmount = halfValue
|
const primaryDepositAmount = halfValue
|
||||||
.dividedBy(getTokenPrice(vault.denoms.primary, prices))
|
.dividedBy(getTokenPrice(primaryAsset.denom, prices))
|
||||||
|
.shiftedBy(primaryAsset.decimals)
|
||||||
.integerValue()
|
.integerValue()
|
||||||
|
|
||||||
const secondaryDepositAmount = halfValue
|
const secondaryDepositAmount = halfValue
|
||||||
.dividedBy(getTokenPrice(vault.denoms.secondary, prices))
|
.dividedBy(getTokenPrice(secondaryAsset.denom, prices))
|
||||||
|
.shiftedBy(secondaryAsset.decimals)
|
||||||
.integerValue()
|
.integerValue()
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -46,7 +52,7 @@ export function getVaultDepositCoinsAndValue(
|
|||||||
denom: vault.denoms.secondary,
|
denom: vault.denoms.secondary,
|
||||||
amount: secondaryDepositAmount.toString(),
|
amount: secondaryDepositAmount.toString(),
|
||||||
}),
|
}),
|
||||||
totalValue: totalValue.integerValue(),
|
totalValue: totalValue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,12 +121,14 @@ export function getVaultSwapActions(
|
|||||||
value = value.minus(swapValue)
|
value = value.minus(swapValue)
|
||||||
amount = amount.minus(swapAmount)
|
amount = amount.minus(swapAmount)
|
||||||
primaryLeftoverValue = primaryLeftoverValue.minus(swapValue)
|
primaryLeftoverValue = primaryLeftoverValue.minus(swapValue)
|
||||||
swapActions.push(getSwapAction(bnCoin.denom, vault.denoms.primary, swapAmount, slippage))
|
if (swapAmount.isGreaterThan(BN_ZERO))
|
||||||
|
swapActions.push(getSwapAction(bnCoin.denom, vault.denoms.primary, swapAmount, slippage))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (secondaryLeftoverValue.isGreaterThan(0)) {
|
if (secondaryLeftoverValue.isGreaterThan(0)) {
|
||||||
secondaryLeftoverValue = secondaryLeftoverValue.minus(value)
|
secondaryLeftoverValue = secondaryLeftoverValue.minus(value)
|
||||||
swapActions.push(getSwapAction(bnCoin.denom, vault.denoms.secondary, amount, slippage))
|
if (amount.isGreaterThan(BN_ZERO))
|
||||||
|
swapActions.push(getSwapAction(bnCoin.denom, vault.denoms.secondary, amount, slippage))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user