Mp 3328 compare accounts via use updated account for withdraw (#407)
* Compare Accounts via useUpdatedAccount for withdraw * fix: onChangeAsset fixed * Mp 3250 update health bars (#403) * [Story] Add HealthBar * Update tooltip * Fixes after rebase * Fixes after rebase * Fixes after rebase * Finish health bar + gauge * Finish health bar + gauge * Finish health bar + gauge * feat: added an svg mask to the HealthBar * fix: added transitions * tidy: value sanity * fix: fixed the AccountStats * tidy: design update * fix: div adjustments * update healthguagepercentage function * make tooltiparrow responsive --------- Co-authored-by: Linkie Link <linkielink.dev@gmail.com> * Compare Accounts via useUpdatedAccount for withdraw * Mp 3250 update health bars (#403) * [Story] Add HealthBar * Update tooltip * Fixes after rebase * Fixes after rebase * Fixes after rebase * Finish health bar + gauge * Finish health bar + gauge * Finish health bar + gauge * feat: added an svg mask to the HealthBar * fix: added transitions * tidy: value sanity * fix: fixed the AccountStats * tidy: design update * fix: div adjustments * update healthguagepercentage function * make tooltiparrow responsive --------- Co-authored-by: Linkie Link <linkielink.dev@gmail.com> * Mp 3250 update health bars (#403) * [Story] Add HealthBar * Update tooltip * Fixes after rebase * Fixes after rebase * Fixes after rebase * Finish health bar + gauge * Finish health bar + gauge * Finish health bar + gauge * feat: added an svg mask to the HealthBar * fix: added transitions * tidy: value sanity * fix: fixed the AccountStats * tidy: design update * fix: div adjustments * update healthguagepercentage function * make tooltiparrow responsive --------- Co-authored-by: Linkie Link <linkielink.dev@gmail.com> * fix: merge error --------- Co-authored-by: Yusuf Seyrek <yusuf@delphilabs.io> Co-authored-by: Bob van der Helm <34470358+bobthebuidlr@users.noreply.github.com>
This commit is contained in:
parent
e15de26efd
commit
22830289cf
@ -1,7 +1,7 @@
|
||||
import classNames from 'classnames'
|
||||
|
||||
import Card from 'components/Card'
|
||||
import AccordionContent, { Item } from 'components/AccordionContent'
|
||||
import Card from 'components/Card'
|
||||
|
||||
interface Props {
|
||||
items: Item[]
|
||||
@ -14,7 +14,7 @@ export default function Accordion(props: Props) {
|
||||
return (
|
||||
<Card className='w-full'>
|
||||
{props.items.map((item, index) => (
|
||||
<AccordionContent key={item.title} item={item} index={index} />
|
||||
<AccordionContent key={index} item={item} index={index} />
|
||||
))}
|
||||
</Card>
|
||||
)
|
||||
@ -23,7 +23,7 @@ export default function Accordion(props: Props) {
|
||||
return (
|
||||
<div className={classNames('w-full', props.className)}>
|
||||
{props.items.map((item, index) => (
|
||||
<Card key={item.title} className='mb-4'>
|
||||
<Card key={index} className='mb-4'>
|
||||
<AccordionContent item={item} index={index} />
|
||||
</Card>
|
||||
))}
|
||||
|
@ -143,7 +143,7 @@ export default function AccountBalancesTable(props: Props) {
|
||||
<FormattedNumber
|
||||
className='text-xs text-right'
|
||||
amount={Number(BN(amount).abs())}
|
||||
options={{ maxDecimals: 2, abbreviated: true }}
|
||||
options={{ maxDecimals: 4, abbreviated: true }}
|
||||
animate
|
||||
/>
|
||||
)
|
||||
@ -240,7 +240,7 @@ export default function AccountBalancesTable(props: Props) {
|
||||
<Text
|
||||
tag='span'
|
||||
size='sm'
|
||||
className='flex items-center font-normal text-white/40'
|
||||
className='flex items-center font-normal text-white/70'
|
||||
>
|
||||
{flexRender(header.column.columnDef.header, header.getContext())}
|
||||
</Text>
|
||||
|
@ -3,17 +3,21 @@ import { useMemo } from 'react'
|
||||
|
||||
import AccountBalancesTable from 'components/Account/AccountBalancesTable'
|
||||
import AccountComposition from 'components/Account/AccountComposition'
|
||||
import { glowElement } from 'components/Button/utils'
|
||||
import Card from 'components/Card'
|
||||
import DisplayCurrency from 'components/DisplayCurrency'
|
||||
import { FormattedNumber } from 'components/FormattedNumber'
|
||||
import { HealthGauge } from 'components/HealthGauge'
|
||||
import { ChevronLeft, ChevronRight } from 'components/Icons'
|
||||
import { Cross, ThreeDots } from 'components/Icons'
|
||||
import Text from 'components/Text'
|
||||
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
||||
import { REDUCE_MOTION_KEY } from 'constants/localStore'
|
||||
import { ORACLE_DENOM } from 'constants/oracle'
|
||||
import useBorrowMarketAssetsTableData from 'hooks/useBorrowMarketAssetsTableData'
|
||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||
import useHealthComputer from 'hooks/useHealthComputer'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
import useLocalStorage from 'hooks/useLocalStorage'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import useToggle from 'hooks/useToggle'
|
||||
import useStore from 'store'
|
||||
@ -40,6 +44,7 @@ interface Props {
|
||||
|
||||
function AccountDetails(props: Props) {
|
||||
const { account } = props
|
||||
const [reduceMotion] = useLocalStorage<boolean>(REDUCE_MOTION_KEY, DEFAULT_SETTINGS.reduceMotion)
|
||||
const updatedAccount = useStore((s) => s.updatedAccount)
|
||||
const [isExpanded, setIsExpanded] = useToggle()
|
||||
const { health } = useHealthComputer(account)
|
||||
@ -75,27 +80,19 @@ function AccountDetails(props: Props) {
|
||||
className={classNames(
|
||||
isExpanded ? 'right-6' : '-right-80',
|
||||
'w-100 flex items-start gap-6 absolute top-6',
|
||||
'transition-all duration-300',
|
||||
!reduceMotion && 'transition-all duration-300',
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
'flex flex-wrap w-16 group/details relative',
|
||||
'flex flex-wrap w-16 group relative',
|
||||
'border rounded-base border-white/20',
|
||||
'bg-white/5 backdrop-blur-sticky transition-colors duration-300',
|
||||
'bg-white/5 backdrop-blur-sticky',
|
||||
!reduceMotion && 'transition-colors duration-300',
|
||||
'hover:bg-white/10 hover:cursor-pointer ',
|
||||
)}
|
||||
onClick={() => setIsExpanded(!isExpanded)}
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
'absolute block opacity-0 top-1/2 transition-[opacity]',
|
||||
'group-hover/details:opacity-100 duration-300 delay-100',
|
||||
isExpanded ? '-right-4' : '-right-3',
|
||||
)}
|
||||
>
|
||||
{isExpanded ? <ChevronRight className='w-2' /> : <ChevronLeft className='w-2' />}
|
||||
</div>
|
||||
<div className='flex flex-wrap justify-center w-full py-4'>
|
||||
<HealthGauge health={health} />
|
||||
<Text size='2xs' className='mb-0.5 mt-1 w-full text-center text-white/50'>
|
||||
@ -130,13 +127,25 @@ function AccountDetails(props: Props) {
|
||||
animate
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className={classNames(
|
||||
'flex justify-center items-center w-full h-6 opacity-50',
|
||||
!reduceMotion && 'transition-[opacity] duration-300',
|
||||
'absolute -bottom-6',
|
||||
'group-hover:opacity-100',
|
||||
)}
|
||||
>
|
||||
{isExpanded ? <Cross className='w-2' /> : <ThreeDots className='h-1' />}
|
||||
</div>
|
||||
|
||||
{glowElement(!reduceMotion)}
|
||||
</div>
|
||||
<div className='flex w-80 backdrop-blur-sticky'>
|
||||
<Card className='w-full bg-white/5' title={`Account ${account.id}`}>
|
||||
<Card className='w-full bg-white/5' title={`Credit Account ${account.id}`}>
|
||||
<AccountComposition account={account} />
|
||||
<Text className='w-full px-4 py-2 bg-white/10 text-white/40'>Balances</Text>
|
||||
<Text className='w-full px-4 py-2 text-white bg-white/10'>Balances</Text>
|
||||
<AccountBalancesTable
|
||||
account={account}
|
||||
account={updatedAccount ? updatedAccount : account}
|
||||
borrowingData={borrowAssetsData}
|
||||
lendingData={lendingAssetsData}
|
||||
/>
|
||||
|
@ -42,6 +42,8 @@ export default function AccountFund() {
|
||||
[walletBalances, baseAsset],
|
||||
)
|
||||
|
||||
const balances = walletBalances.map((coin) => new BNCoin(coin))
|
||||
|
||||
const selectedDenoms = useMemo(() => {
|
||||
return walletAssetModal?.selectedDenoms ?? []
|
||||
}, [walletAssetModal?.selectedDenoms])
|
||||
@ -117,7 +119,7 @@ export default function AccountFund() {
|
||||
{fundingAssets.map((coin) => {
|
||||
const asset = getAssetByDenom(coin.denom) as Asset
|
||||
|
||||
const balance = walletBalances.find(byDenom(coin.denom))?.amount ?? '0'
|
||||
const balance = balances.find(byDenom(coin.denom))?.amount ?? BN_ZERO
|
||||
return (
|
||||
<div
|
||||
key={asset.symbol}
|
||||
@ -127,8 +129,8 @@ export default function AccountFund() {
|
||||
asset={asset}
|
||||
onChange={(amount) => updateFundingAssets(amount, asset.denom)}
|
||||
amount={coin.amount ?? BN_ZERO}
|
||||
max={BN(balance)}
|
||||
balances={walletBalances}
|
||||
max={balance}
|
||||
balances={balances}
|
||||
maxText='Max'
|
||||
disabled={isFunding}
|
||||
/>
|
||||
|
@ -6,7 +6,7 @@ import AccountFund from 'components/Account/AccountFund'
|
||||
import AccountStats from 'components/Account/AccountStats'
|
||||
import Button from 'components/Button'
|
||||
import Card from 'components/Card'
|
||||
import { ArrowCircledTopRight, ArrowDownLine, ArrowUpLine, TrashBin } from 'components/Icons'
|
||||
import { ArrowDownLine, ArrowUpLine, TrashBin } from 'components/Icons'
|
||||
import Radio from 'components/Radio'
|
||||
import SwitchAutoLend from 'components/Switch/SwitchAutoLend'
|
||||
import Text from 'components/Text'
|
||||
@ -117,7 +117,7 @@ export default function AccountList(props: Props) {
|
||||
disabled={positionBalance.isLessThanOrEqualTo(0)}
|
||||
/>
|
||||
<Button
|
||||
className='w-full'
|
||||
className='w-full col-span-2'
|
||||
color='tertiary'
|
||||
leftIcon={<TrashBin />}
|
||||
text='Delete'
|
||||
@ -126,13 +126,6 @@ export default function AccountList(props: Props) {
|
||||
deleteAccountHandler()
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
className='w-full'
|
||||
color='tertiary'
|
||||
leftIcon={<ArrowCircledTopRight />}
|
||||
text='Transfer'
|
||||
onClick={() => {}}
|
||||
/>
|
||||
<SwitchAutoLend
|
||||
className='col-span-2 pt-4 border border-transparent border-t-white/10'
|
||||
accountId={account.id}
|
||||
|
@ -98,7 +98,7 @@ export default function AccountMenuContent(props: Props) {
|
||||
>
|
||||
{hasCreditAccounts
|
||||
? isAccountSelected
|
||||
? `Account ${accountId}`
|
||||
? `Credit Account ${accountId}`
|
||||
: 'Select Account'
|
||||
: 'Create Account'}
|
||||
</Button>
|
||||
@ -114,7 +114,7 @@ export default function AccountMenuContent(props: Props) {
|
||||
)}
|
||||
>
|
||||
<Text size='lg' className='font-bold'>
|
||||
Accounts
|
||||
Credit Accounts
|
||||
</Text>
|
||||
<Button
|
||||
color='secondary'
|
||||
|
@ -46,9 +46,13 @@ function Content() {
|
||||
className={classNames('grid w-full grid-cols-1 gap-4', 'md:grid-cols-2', 'lg:grid-cols-3')}
|
||||
>
|
||||
{account.map((account: Account, index: number) => (
|
||||
<Card className='w-full h-fit bg-white/5' title={`Account ${account.id}`} key={index}>
|
||||
<Card
|
||||
className='w-full h-fit bg-white/5'
|
||||
title={`Credit Account ${account.id}`}
|
||||
key={index}
|
||||
>
|
||||
<AccountComposition account={account} />
|
||||
<Text className='w-full px-4 py-2 bg-white/10 text-white/40'>Balances</Text>
|
||||
<Text className='w-full px-4 py-2 text-white bg-white/10'>Balances</Text>
|
||||
<AccountBalancesTable
|
||||
account={account}
|
||||
borrowingData={borrowAssetsData}
|
||||
@ -71,7 +75,7 @@ function Fallback() {
|
||||
<div className='p-4'>
|
||||
<Loading className='h-4 w-50' />
|
||||
</div>
|
||||
<Text className='w-full px-4 py-2 mt-3 bg-white/10 text-white/40'>Balances</Text>
|
||||
<Text className='w-full px-4 py-2 mt-3 text-white bg-white/10'>Balances</Text>
|
||||
<Loading className='w-full h-4' />
|
||||
</Card>
|
||||
))}
|
||||
|
@ -15,6 +15,7 @@ import useHealthComputer from 'hooks/useHealthComputer'
|
||||
import useIsOpenArray from 'hooks/useIsOpenArray'
|
||||
import useLendingMarketAssetsTableData from 'hooks/useLendingMarketAssetsTableData'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { calculateAccountBalanceValue, calculateAccountLeverage } from 'utils/accounts'
|
||||
import { formatLeverage } from 'utils/formatters'
|
||||
@ -26,6 +27,7 @@ interface Props {
|
||||
export default function AccountSummary(props: Props) {
|
||||
const [isOpen, toggleOpen] = useIsOpenArray(2, true)
|
||||
const { data: prices } = usePrices()
|
||||
const updatedAccount = useStore((s) => s.updatedAccount)
|
||||
const accountBalance = useMemo(
|
||||
() => (props.account ? calculateAccountBalanceValue(props.account, prices) : BN_ZERO),
|
||||
[props.account, prices],
|
||||
@ -48,7 +50,6 @@ export default function AccountSummary(props: Props) {
|
||||
[props.account, prices],
|
||||
)
|
||||
if (!props.account) return null
|
||||
|
||||
return (
|
||||
<div className='h-[546px] min-w-[370px] basis-[370px] overflow-y-scroll scrollbar-hide'>
|
||||
<Card className='mb-4 h-min min-w-fit bg-white/10' contentClassName='flex'>
|
||||
@ -68,7 +69,7 @@ export default function AccountSummary(props: Props) {
|
||||
<Accordion
|
||||
items={[
|
||||
{
|
||||
title: `Subaccount ${props.account.id} Composition`,
|
||||
title: `Credit Account ${props.account.id} Composition`,
|
||||
renderContent: () =>
|
||||
props.account ? <AccountComposition account={props.account} /> : null,
|
||||
isOpen: isOpen[0],
|
||||
@ -80,7 +81,7 @@ export default function AccountSummary(props: Props) {
|
||||
renderContent: () =>
|
||||
props.account ? (
|
||||
<AccountBalancesTable
|
||||
account={props.account}
|
||||
account={updatedAccount ? updatedAccount : props.account}
|
||||
borrowingData={borrowAssetsData}
|
||||
lendingData={lendingAssetsData}
|
||||
/>
|
||||
|
@ -50,12 +50,12 @@ export default function BorrowTable(props: Props) {
|
||||
const asset = row.original.asset
|
||||
|
||||
return (
|
||||
<div className='flex flex-1 items-center gap-3'>
|
||||
<div className='flex items-center flex-1 gap-3'>
|
||||
<AssetImage asset={asset} size={32} />
|
||||
<TitleAndSubCell
|
||||
title={asset.symbol}
|
||||
sub={asset.name}
|
||||
className='min-w-15 text-left'
|
||||
className='text-left min-w-15'
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { useMemo } from 'react'
|
||||
import classNames from 'classnames'
|
||||
|
||||
import { FormattedNumber } from 'components/FormattedNumber'
|
||||
import { DEFAULT_SETTINGS } from 'constants/defaultSettings'
|
||||
@ -13,6 +14,7 @@ interface Props {
|
||||
coin: BNCoin
|
||||
className?: string
|
||||
isApproximation?: boolean
|
||||
parantheses?: boolean
|
||||
}
|
||||
|
||||
export default function DisplayCurrency(props: Props) {
|
||||
@ -39,7 +41,10 @@ export default function DisplayCurrency(props: Props) {
|
||||
|
||||
return (
|
||||
<FormattedNumber
|
||||
className={props.className}
|
||||
className={classNames(
|
||||
props.className,
|
||||
props.parantheses && 'before:content-["("] after:content-[")"]',
|
||||
)}
|
||||
amount={convertToDisplayAmount(props.coin, displayCurrency, prices).toNumber()}
|
||||
options={{
|
||||
minDecimals: isUSD ? 2 : 0,
|
||||
|
20
src/components/Icons/ThreeDots.svg
Normal file
20
src/components/Icons/ThreeDots.svg
Normal file
@ -0,0 +1,20 @@
|
||||
<svg viewBox="0 0 16 4" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M8.8335 2.00004C8.8335 1.5398 8.4604 1.16671 8.00016 1.16671C7.53993 1.16671 7.16683 1.5398 7.16683 2.00004C7.16683 2.46028 7.53993 2.83337 8.00016 2.83337C8.4604 2.83337 8.8335 2.46028 8.8335 2.00004Z"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M3.00016 2.00004C3.00016 1.5398 2.62707 1.16671 2.16683 1.16671C1.70659 1.16671 1.3335 1.5398 1.3335 2.00004C1.3335 2.46028 1.70659 2.83337 2.16683 2.83337C2.62707 2.83337 3.00016 2.46028 3.00016 2.00004Z"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<path
|
||||
d="M14.6668 2.00004C14.6668 1.5398 14.2937 1.16671 13.8335 1.16671C13.3733 1.16671 13.0002 1.5398 13.0002 2.00004C13.0002 2.46028 13.3733 2.83337 13.8335 2.83337C14.2937 2.83337 14.6668 2.46028 14.6668 2.00004Z"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
After Width: | Height: | Size: 1000 B |
@ -46,6 +46,7 @@ export { default as StarFilled } from 'components/Icons/StarFilled.svg'
|
||||
export { default as StarOutlined } from 'components/Icons/StarOutlined.svg'
|
||||
export { default as Subtract } from 'components/Icons/Subtract.svg'
|
||||
export { default as SwapIcon } from 'components/Icons/SwapIcon.svg'
|
||||
export { default as ThreeDots } from 'components/Icons/ThreeDots.svg'
|
||||
export { default as TooltipArrow } from 'components/Icons/TooltipArrow.svg'
|
||||
export { default as TrashBin } from 'components/Icons/TrashBin.svg'
|
||||
export { default as VerticalThreeLine } from 'components/Icons/VerticalThreeLine.svg'
|
||||
|
@ -108,19 +108,19 @@ function AccountDeleteModal(props: Props) {
|
||||
onClose={closeDeleteAccountModal}
|
||||
header={
|
||||
<span className='flex items-center'>
|
||||
<Text>{`Delete Account ${modal.id}`}</Text>
|
||||
<Text>{`Delete Credit Account ${modal.id}`}</Text>
|
||||
</span>
|
||||
}
|
||||
modalClassName='max-w-modal-sm'
|
||||
headerClassName='gradient-header p-4 border-b-white/5 border-b'
|
||||
contentClassName='w-full'
|
||||
>
|
||||
<div className='w-full border-b border-white/5 p-4 gradient-header'>
|
||||
<div className='w-full p-4 border-b border-white/5 gradient-header'>
|
||||
<Text className='text-white/50' size='sm'>
|
||||
The following assets within your credit account will be sent to your wallet.
|
||||
</Text>
|
||||
</div>
|
||||
<div className='max-h-100 flex w-full flex-col gap-4 overflow-y-scroll p-4 scrollbar-hide'>
|
||||
<div className='flex flex-col w-full gap-4 p-4 overflow-y-scroll max-h-100 scrollbar-hide'>
|
||||
{depositsAndLends.map((position, index) => {
|
||||
const coin = BNCoin.fromDenomAndBigNumber(position.denom, position.amount)
|
||||
const asset = getAssetByDenom(position.denom)
|
||||
|
@ -5,7 +5,9 @@ import AccountSummary from 'components/Account/AccountSummary'
|
||||
import AssetImage from 'components/AssetImage'
|
||||
import Button from 'components/Button'
|
||||
import Card from 'components/Card'
|
||||
import DisplayCurrency from 'components/DisplayCurrency'
|
||||
import Divider from 'components/Divider'
|
||||
import { FormattedNumber } from 'components/FormattedNumber'
|
||||
import { ArrowRight } from 'components/Icons'
|
||||
import Modal from 'components/Modal'
|
||||
import Switch from 'components/Switch'
|
||||
@ -21,6 +23,7 @@ import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
||||
import { getDepositsAndLendsAfterCoinSpent } from 'hooks/useUpdatedAccount/functions'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { formatPercent, formatValue } from 'utils/formatters'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
@ -127,8 +130,14 @@ function BorrowModal(props: Props) {
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!account) return
|
||||
if (isRepay) {
|
||||
setMax(BN(getDebtAmount(modal)))
|
||||
const depositBalance = account.deposits.find(byDenom(asset.denom))?.amount ?? BN_ZERO
|
||||
const lendBalance = account.lends.find(byDenom(asset.denom))?.amount ?? BN_ZERO
|
||||
const maxBalance = depositBalance.plus(lendBalance)
|
||||
const totalDebt = BN(getDebtAmount(modal))
|
||||
const maxRepayAmount = BigNumber.min(maxBalance, totalDebt)
|
||||
setMax(maxRepayAmount)
|
||||
return
|
||||
}
|
||||
|
||||
@ -138,7 +147,7 @@ function BorrowModal(props: Props) {
|
||||
)
|
||||
|
||||
setMax(BigNumber.min(maxBorrowAmount, modal.marketData?.liquidity?.amount || 0))
|
||||
}, [isRepay, modal, asset.denom, computeMaxBorrowAmount, borrowToWallet])
|
||||
}, [account, isRepay, modal, asset.denom, computeMaxBorrowAmount, borrowToWallet])
|
||||
|
||||
useEffect(() => {
|
||||
if (amount.isGreaterThan(max)) {
|
||||
@ -174,19 +183,37 @@ function BorrowModal(props: Props) {
|
||||
title={formatPercent(modal.marketData.borrowRate || '0')}
|
||||
sub={'Borrow rate'}
|
||||
/>
|
||||
<div className='h-100 w-[1px] bg-white/10'></div>
|
||||
<div className='h-100 w-[1px] bg-white/10' />
|
||||
<TitleAndSubCell
|
||||
title={formatValue(getDebtAmount(modal), {
|
||||
abbreviated: true,
|
||||
abbreviated: false,
|
||||
decimals: asset.decimals,
|
||||
maxDecimals: asset.decimals,
|
||||
})}
|
||||
sub={'Borrowed'}
|
||||
/>
|
||||
<div className='h-100 w-[1px] bg-white/10'></div>
|
||||
<TitleAndSubCell
|
||||
title={`${liquidityAmountString} (${liquidityValueString})`}
|
||||
sub={'Liquidity available'}
|
||||
/>
|
||||
<div className='h-100 w-[1px] bg-white/10' />
|
||||
<div className='flex flex-col gap-0.5'>
|
||||
<div className='flex gap-2'>
|
||||
<FormattedNumber
|
||||
className='text-xs'
|
||||
amount={modal.marketData?.liquidity?.amount.toNumber() ?? 0}
|
||||
options={{ decimals: asset.decimals, abbreviated: true, suffix: ` ${asset.symbol}` }}
|
||||
animate
|
||||
/>
|
||||
<DisplayCurrency
|
||||
className='text-xs'
|
||||
coin={BNCoin.fromDenomAndBigNumber(
|
||||
asset.denom,
|
||||
modal.marketData?.liquidity?.amount ?? BN_ZERO,
|
||||
)}
|
||||
parantheses
|
||||
/>
|
||||
</div>
|
||||
<Text size='xs' className='text-white/50' tag='span'>
|
||||
Liquidity available
|
||||
</Text>
|
||||
</div>
|
||||
</div>
|
||||
<div className='flex items-start flex-1 gap-6 p-6'>
|
||||
<Card
|
||||
|
@ -44,6 +44,8 @@ export default function FundAccount(props: Props) {
|
||||
[walletBalances, baseAsset],
|
||||
)
|
||||
|
||||
const balances = walletBalances.map((coin) => new BNCoin(coin))
|
||||
|
||||
const selectedDenoms = useMemo(() => {
|
||||
return walletAssetModal?.selectedDenoms ?? []
|
||||
}, [walletAssetModal?.selectedDenoms])
|
||||
@ -113,15 +115,15 @@ export default function FundAccount(props: Props) {
|
||||
{fundingAssets.map((coin) => {
|
||||
const asset = getAssetByDenom(coin.denom) as Asset
|
||||
|
||||
const balance = walletBalances.find(byDenom(coin.denom))?.amount ?? '0'
|
||||
const balance = balances.find(byDenom(coin.denom))?.amount ?? BN_ZERO
|
||||
return (
|
||||
<TokenInputWithSlider
|
||||
key={coin.denom}
|
||||
asset={asset}
|
||||
onChange={(amount) => updateFundingAssets(amount, asset.denom)}
|
||||
amount={coin.amount ?? BN_ZERO}
|
||||
max={BN(balance)}
|
||||
balances={walletBalances}
|
||||
max={balance}
|
||||
balances={balances}
|
||||
maxText='Max'
|
||||
disabled={isFunding}
|
||||
className='w-full mb-4'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { useState } from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
import Button from 'components/Button'
|
||||
import Divider from 'components/Divider'
|
||||
@ -14,7 +14,9 @@ import useToggle from 'hooks/useToggle'
|
||||
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { cloneAccount, getMergedBalances, removeDepostisAndLends } from 'utils/accounts'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { getEnabledMarketAssets } from 'utils/assets'
|
||||
|
||||
interface Props {
|
||||
account: Account
|
||||
@ -29,9 +31,12 @@ export default function WithdrawFromAccount(props: Props) {
|
||||
const [isConfirming, setIsConfirming] = useToggle()
|
||||
const [currentAsset, setCurrentAsset] = useState(defaultAsset)
|
||||
const [amount, setAmount] = useState(BN_ZERO)
|
||||
const { updatedAccount, removeDeposits, removeLends, addDebts } = useUpdatedAccount(account)
|
||||
const { simulateWithdraw } = useUpdatedAccount(account)
|
||||
const { computeMaxWithdrawAmount } = useHealthComputer(account)
|
||||
const { computeMaxBorrowAmount } = useHealthComputer(updatedAccount)
|
||||
const accountClone = cloneAccount(account)
|
||||
const borrowAccount = removeDepostisAndLends(accountClone, currentAsset.denom)
|
||||
const { computeMaxBorrowAmount } = useHealthComputer(borrowAccount)
|
||||
const balances = getMergedBalances(account, getEnabledMarketAssets())
|
||||
const maxWithdrawAmount = computeMaxWithdrawAmount(currentAsset.denom)
|
||||
const maxWithdrawWithBorrowAmount = computeMaxBorrowAmount(currentAsset.denom, 'wallet').plus(
|
||||
maxWithdrawAmount,
|
||||
@ -49,14 +54,12 @@ export default function WithdrawFromAccount(props: Props) {
|
||||
|
||||
function onChangeAmount(val: BigNumber) {
|
||||
setAmount(val)
|
||||
removeDeposits([BNCoin.fromDenomAndBigNumber(currentAsset.denom, withdrawAmount)])
|
||||
addDebts([BNCoin.fromDenomAndBigNumber(currentAsset.denom, debtAmount)])
|
||||
removeLends([BNCoin.fromDenomAndBigNumber(currentAsset.denom, reclaimAmount)])
|
||||
}
|
||||
|
||||
function resetState() {
|
||||
setCurrentAsset(defaultAsset)
|
||||
setAmount(BN_ZERO)
|
||||
onChangeAmount(BN_ZERO)
|
||||
}
|
||||
|
||||
async function onConfirm() {
|
||||
@ -88,19 +91,35 @@ export default function WithdrawFromAccount(props: Props) {
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const coin = BNCoin.fromDenomAndBigNumber(currentAsset.denom, withdrawAmount.plus(debtAmount))
|
||||
simulateWithdraw(withdrawWithBorrowing, coin)
|
||||
}, [
|
||||
amount,
|
||||
withdrawWithBorrowing,
|
||||
currentAsset.denom,
|
||||
debtAmount,
|
||||
simulateWithdraw,
|
||||
withdrawAmount,
|
||||
])
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className='flex flex-wrap w-full'>
|
||||
<TokenInputWithSlider
|
||||
asset={currentAsset}
|
||||
onChange={onChangeAmount}
|
||||
onChangeAsset={setCurrentAsset}
|
||||
onChangeAsset={(asset) => {
|
||||
setAmount(BN_ZERO)
|
||||
setWithdrawWithBorrowing(false)
|
||||
setCurrentAsset(asset)
|
||||
}}
|
||||
amount={amount}
|
||||
max={max}
|
||||
className='w-full'
|
||||
balances={account.deposits}
|
||||
balances={balances}
|
||||
accountId={account.id}
|
||||
hasSelect={account.deposits.length > 1}
|
||||
hasSelect
|
||||
maxText='Max'
|
||||
disabled={isConfirming}
|
||||
/>
|
||||
|
@ -22,8 +22,8 @@ export default function FundAndWithdrawModal() {
|
||||
<span className='flex items-center gap-4 px-4'>
|
||||
<Text>
|
||||
{isFunding
|
||||
? `Fund Account ${currentAccount?.id ?? '0'}`
|
||||
: `Withdraw from Account ${currentAccount?.id ?? '0'}`}
|
||||
? `Fund Credit Account ${currentAccount?.id ?? '0'}`
|
||||
: `Withdraw from Credit Account ${currentAccount?.id ?? '0'}`}
|
||||
</Text>
|
||||
</span>
|
||||
}
|
||||
|
@ -178,7 +178,7 @@ export default function VaultDeposit(props: Props) {
|
||||
strokeWidth={3}
|
||||
/>
|
||||
</div>
|
||||
<div className='flex h-full flex-1 flex-col justify-between gap-6'>
|
||||
<div className='flex flex-col justify-between flex-1 h-full gap-6'>
|
||||
<TokenInput
|
||||
onChange={onChangePrimaryDeposit}
|
||||
amount={primaryCoin.amount}
|
||||
|
@ -5,6 +5,7 @@ import DisplayCurrency from 'components/DisplayCurrency'
|
||||
import { ChevronDown, ChevronRight } from 'components/Icons'
|
||||
import Text from 'components/Text'
|
||||
import { ASSETS } from 'constants/assets'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { formatValue } from 'utils/formatters'
|
||||
|
||||
@ -26,7 +27,7 @@ export default function Option(props: Props) {
|
||||
|
||||
if (isCoin) {
|
||||
const asset = ASSETS.find((asset) => asset.denom === props.denom) ?? ASSETS[0]
|
||||
const balance = props.amount ?? '0'
|
||||
const balance = props.amount ?? BN_ZERO
|
||||
|
||||
if (props.isDisplay) {
|
||||
return (
|
||||
@ -60,12 +61,12 @@ export default function Option(props: Props) {
|
||||
)}
|
||||
onClick={() => handleOnClick(asset.denom)}
|
||||
>
|
||||
<div className='row-span-2 flex h-full items-center justify-center'>
|
||||
<div className='flex items-center justify-center h-full row-span-2'>
|
||||
<AssetImage asset={asset} size={32} />
|
||||
</div>
|
||||
<Text className='col-span-2 pb-1'>{asset.symbol}</Text>
|
||||
<Text size='sm' className='col-span-2 pb-1 text-right font-bold'>
|
||||
{formatValue(balance, {
|
||||
<Text size='sm' className='col-span-2 pb-1 font-bold text-right'>
|
||||
{formatValue(balance.toString(), {
|
||||
decimals: asset.decimals,
|
||||
maxDecimals: 4,
|
||||
minDecimals: 0,
|
||||
@ -76,8 +77,8 @@ export default function Option(props: Props) {
|
||||
{formatValue(5, { maxDecimals: 2, minDecimals: 0, prefix: 'APY ', suffix: '%' })}
|
||||
</Text>
|
||||
<DisplayCurrency
|
||||
className='col-span-2 text-right text-sm text-white/50'
|
||||
coin={new BNCoin({ denom: asset.denom, amount: balance })}
|
||||
className='col-span-2 text-sm text-right text-white/50'
|
||||
coin={BNCoin.fromDenomAndBigNumber(asset.denom, balance)}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
|
@ -53,7 +53,7 @@ export default function Select(props: Props) {
|
||||
return (
|
||||
<div className={classNames('flex flex-col flex-wrap', props.containerClassName)}>
|
||||
{props.label && (
|
||||
<Text size='sm' className='mb-2 w-full'>
|
||||
<Text size='sm' className='w-full mb-2'>
|
||||
{props.label}
|
||||
</Text>
|
||||
)}
|
||||
@ -98,9 +98,9 @@ export default function Select(props: Props) {
|
||||
setShow={setShowDropdown}
|
||||
hasBackdropIsolation
|
||||
>
|
||||
<div className='relative isolate w-full overflow-hidden rounded-sm'>
|
||||
<div className='relative w-full overflow-hidden rounded-sm isolate'>
|
||||
{props.title && (
|
||||
<Text size='lg' className='block bg-white/25 p-4 font-bold'>
|
||||
<Text size='lg' className='block p-4 font-bold bg-white/25'>
|
||||
{props.title}
|
||||
</Text>
|
||||
)}
|
||||
|
@ -11,7 +11,7 @@ interface Props {
|
||||
|
||||
export default function TitleAndSubCell(props: Props) {
|
||||
return (
|
||||
<div className={classNames('flex flex-col gap-[0.5]', props.containerClassName)}>
|
||||
<div className={classNames('flex flex-col gap-0.5', props.containerClassName)}>
|
||||
<Text size='xs' className={props.className} tag='span'>
|
||||
{props.title}
|
||||
</Text>
|
||||
|
@ -4,6 +4,7 @@ import { useEffect, useState } from 'react'
|
||||
import Slider from 'components/Slider'
|
||||
import TokenInput from 'components/TokenInput'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
interface Props {
|
||||
@ -12,7 +13,7 @@ interface Props {
|
||||
max: BigNumber
|
||||
onChange: (amount: BigNumber) => void
|
||||
accountId?: string
|
||||
balances?: Coin[]
|
||||
balances?: BNCoin[]
|
||||
className?: string
|
||||
disabled?: boolean
|
||||
hasSelect?: boolean
|
||||
|
@ -21,7 +21,7 @@ interface Props {
|
||||
max: BigNumber
|
||||
onChange: (amount: BigNumber) => void
|
||||
accountId?: string
|
||||
balances?: Coin[]
|
||||
balances?: BNCoin[]
|
||||
className?: string
|
||||
disabled?: boolean
|
||||
hasSelect?: boolean
|
||||
@ -63,12 +63,12 @@ export default function TokenInput(props: Props) {
|
||||
options={props.balances}
|
||||
defaultValue={props.asset.denom}
|
||||
onChange={onChangeAsset}
|
||||
title={props.accountId ? `Account ${props.accountId}` : 'Your Wallet'}
|
||||
title={props.accountId ? `Credit Account ${props.accountId}` : 'Your Wallet'}
|
||||
className='h-full border-r border-white/20 bg-white/5'
|
||||
displayClassName='rounded-l-sm'
|
||||
/>
|
||||
) : (
|
||||
<div className='flex min-w-fit items-center gap-2 border-r border-white/20 bg-white/5 p-3'>
|
||||
<div className='flex items-center gap-2 p-3 border-r min-w-fit border-white/20 bg-white/5'>
|
||||
<AssetImage asset={props.asset} size={20} />
|
||||
<Text>{props.asset.symbol}</Text>
|
||||
</div>
|
||||
@ -80,7 +80,7 @@ export default function TokenInput(props: Props) {
|
||||
onChange={props.onChange}
|
||||
amount={props.amount}
|
||||
max={props.max}
|
||||
className='flex-1 border-none p-3'
|
||||
className='flex-1 p-3 border-none'
|
||||
/>
|
||||
{props.onDelete && (
|
||||
<div role='button' className='grid items-center pr-2' onClick={props.onDelete}>
|
||||
@ -101,7 +101,7 @@ export default function TokenInput(props: Props) {
|
||||
</div>
|
||||
|
||||
<div className='flex'>
|
||||
<div className='flex flex-1 items-center'>
|
||||
<div className='flex items-center flex-1'>
|
||||
{props.maxText && (
|
||||
<>
|
||||
<Text size='xs' className='mr-1 text-white' monospace>
|
||||
|
@ -131,8 +131,8 @@ export const ASSETS: Asset[] = [
|
||||
forceFetchPrice: false,
|
||||
},
|
||||
{
|
||||
symbol: 'gamm/pool/12',
|
||||
name: 'gamm/pool/12',
|
||||
symbol: 'OSMO-ATOM',
|
||||
name: 'OSMO-ATOM LP',
|
||||
id: 'gamm/pool/12',
|
||||
denom: 'gamm/pool/12',
|
||||
color: '',
|
||||
|
@ -55,7 +55,8 @@ export function useUpdatedAccount(account?: Account) {
|
||||
const simulateBorrow = useCallback(
|
||||
(target: 'wallet' | 'deposit' | 'lend', coin: BNCoin) => {
|
||||
if (!account) return
|
||||
resetAccount()
|
||||
removeDeposits([])
|
||||
removeLends([])
|
||||
addDebts([coin])
|
||||
if (target === 'deposit') addDeposits([coin])
|
||||
if (target === 'lend') addLends([coin])
|
||||
@ -67,8 +68,6 @@ export function useUpdatedAccount(account?: Account) {
|
||||
(isLendAction: boolean, coin: BNCoin) => {
|
||||
if (!account) return
|
||||
|
||||
resetAccount()
|
||||
|
||||
if (isLendAction) {
|
||||
addLends([coin])
|
||||
removeDeposits([coin])
|
||||
@ -84,8 +83,8 @@ export function useUpdatedAccount(account?: Account) {
|
||||
const simulateRepay = useCallback(
|
||||
(coin: BNCoin) => {
|
||||
if (!account) return
|
||||
removeDebts([coin])
|
||||
const { deposits, lends } = getDepositsAndLendsAfterCoinSpent(coin, account)
|
||||
removeDebts([coin])
|
||||
removeDeposits([deposits])
|
||||
removeLends([lends])
|
||||
},
|
||||
@ -95,22 +94,32 @@ export function useUpdatedAccount(account?: Account) {
|
||||
const simulateDeposits = useCallback(
|
||||
(target: 'deposit' | 'lend', coins: BNCoin[]) => {
|
||||
if (!account) return
|
||||
resetAccount()
|
||||
addDeposits([])
|
||||
addLends([])
|
||||
if (target === 'deposit') addDeposits(coins)
|
||||
if (target === 'lend') addLends(coins)
|
||||
},
|
||||
[account, addDeposits, addLends],
|
||||
)
|
||||
|
||||
const resetAccount = () => {
|
||||
addDeposits([])
|
||||
removeDeposits([])
|
||||
addDebts([])
|
||||
removeDebts([])
|
||||
addVaultValues([])
|
||||
addLends([])
|
||||
removeLends([])
|
||||
}
|
||||
const simulateWithdraw = useCallback(
|
||||
(withdrawWithBorrowing: boolean, coin: BNCoin) => {
|
||||
if (!account) return
|
||||
removeDeposits([])
|
||||
removeLends([])
|
||||
addDebts([])
|
||||
|
||||
const { deposits, lends } = getDepositsAndLendsAfterCoinSpent(coin, account)
|
||||
const totalBalance = deposits.amount.plus(lends.amount)
|
||||
removeDeposits([deposits])
|
||||
removeLends([lends])
|
||||
if (withdrawWithBorrowing) {
|
||||
addDebts([BNCoin.fromDenomAndBigNumber(coin.denom, coin.amount.minus(totalBalance))])
|
||||
}
|
||||
},
|
||||
[account, removeDeposits, removeLends, addDebts],
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
if (!account) return
|
||||
|
||||
@ -157,5 +166,6 @@ export function useUpdatedAccount(account?: Account) {
|
||||
simulateDeposits,
|
||||
simulateLending,
|
||||
simulateRepay,
|
||||
simulateWithdraw,
|
||||
}
|
||||
}
|
||||
|
@ -118,7 +118,7 @@ export default function createBroadcastSlice(
|
||||
handleResponseMessages(
|
||||
response,
|
||||
`Borrowed ${formatAmountWithSymbol(options.coin)} to ${
|
||||
options.borrowToWallet ? 'Wallet' : `Account ${options.accountId}`
|
||||
options.borrowToWallet ? 'Wallet' : `Credit Account ${options.accountId}`
|
||||
}`,
|
||||
)
|
||||
return !!response.result
|
||||
@ -135,7 +135,7 @@ export default function createBroadcastSlice(
|
||||
if (response.result) {
|
||||
set({ createAccountModal: false })
|
||||
const id = getSingleValueFromBroadcastResult(response.result, 'wasm', 'token_id')
|
||||
set({ fundAccountModal: true, toast: { message: `Account ${id} created` } })
|
||||
set({ fundAccountModal: true, toast: { message: `Credit Account ${id} created` } })
|
||||
return id
|
||||
} else {
|
||||
set({
|
||||
@ -175,7 +175,7 @@ export default function createBroadcastSlice(
|
||||
],
|
||||
})
|
||||
|
||||
handleResponseMessages(response, `Account ${options.accountId} deleted`)
|
||||
handleResponseMessages(response, `Credit Account ${options.accountId} deleted`)
|
||||
|
||||
return !!response.result
|
||||
},
|
||||
@ -236,7 +236,10 @@ export default function createBroadcastSlice(
|
||||
const depositString = options.coins
|
||||
.map((coin) => formatAmountWithSymbol(coin.toCoin()))
|
||||
.join(' and ')
|
||||
handleResponseMessages(response, `Deposited ${depositString} to Account ${options.accountId}`)
|
||||
handleResponseMessages(
|
||||
response,
|
||||
`Deposited ${depositString} to Credit Credit Account ${options.accountId}`,
|
||||
)
|
||||
return !!response.result
|
||||
},
|
||||
unlock: async (options: { accountId: string; vault: DepositedVault; amount: string }) => {
|
||||
@ -351,7 +354,7 @@ export default function createBroadcastSlice(
|
||||
.join('and ')
|
||||
handleResponseMessages(
|
||||
response,
|
||||
`Withdrew ${withdrawString} from Account ${options.accountId}`,
|
||||
`Withdrew ${withdrawString} from Credit Account ${options.accountId}`,
|
||||
)
|
||||
return !!response.result
|
||||
},
|
||||
@ -385,7 +388,9 @@ export default function createBroadcastSlice(
|
||||
|
||||
handleResponseMessages(
|
||||
response,
|
||||
`Repayed ${formatAmountWithSymbol(options.coin.toCoin())} to Account ${options.accountId}`,
|
||||
`Repayed ${formatAmountWithSymbol(options.coin.toCoin())} to Credit Account ${
|
||||
options.accountId
|
||||
}`,
|
||||
)
|
||||
return !!response.result
|
||||
},
|
||||
|
@ -2,6 +2,9 @@ import { ActionCoin } from 'types/generated/mars-credit-manager/MarsCreditManage
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
export class BNCoin {
|
||||
static fromDenom(denom: string, arg1: string): BNCoin {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
public denom: string
|
||||
public amount: BigNumber
|
||||
|
||||
|
2
src/types/interfaces/asset.d.ts
vendored
2
src/types/interfaces/asset.d.ts
vendored
@ -13,7 +13,7 @@ interface Asset {
|
||||
| 'WETH.axl'
|
||||
| 'OSMO-USDC.n'
|
||||
| '$'
|
||||
| 'gamm/pool/12'
|
||||
| 'OSMO-ATOM'
|
||||
id:
|
||||
| 'OSMO'
|
||||
| 'ATOM'
|
||||
|
2
src/types/interfaces/select.d.ts
vendored
2
src/types/interfaces/select.d.ts
vendored
@ -2,5 +2,5 @@ interface SelectOption {
|
||||
value?: string
|
||||
label?: string | ReactNode
|
||||
denom?: string
|
||||
amount?: string
|
||||
amount?: BigNumber
|
||||
}
|
||||
|
@ -205,6 +205,29 @@ export function cloneAccount(account: Account): Account {
|
||||
}
|
||||
}
|
||||
|
||||
export function removeDepostisAndLends(account: Account, denom: string) {
|
||||
const deposits = account.deposits.filter((deposit) => deposit.denom !== denom)
|
||||
const lends = account.lends.filter((lend) => lend.denom !== denom)
|
||||
|
||||
deposits.push(BNCoin.fromDenomAndBigNumber(denom, BN_ZERO))
|
||||
lends.push(BNCoin.fromDenomAndBigNumber(denom, BN_ZERO))
|
||||
|
||||
return {
|
||||
...account,
|
||||
deposits,
|
||||
lends,
|
||||
}
|
||||
}
|
||||
|
||||
export function getMergedBalances(account: Account, assets: Asset[]) {
|
||||
const balances: BNCoin[] = []
|
||||
assets.forEach((asset) => {
|
||||
const balance = accumulateAmounts(asset.denom, [...account.deposits, ...account.lends])
|
||||
balances.push(BNCoin.fromDenomAndBigNumber(asset.denom, balance))
|
||||
})
|
||||
return balances
|
||||
}
|
||||
|
||||
export function computeHealthGaugePercentage(health: number) {
|
||||
const ATTENTION_CUTOFF = 10
|
||||
const HEALTHY_CUTOFF = 30
|
||||
|
Loading…
Reference in New Issue
Block a user