wire up borrow modal; use maint health

This commit is contained in:
tjs 2022-08-15 18:18:23 -04:00
parent 65f08d6b43
commit 6ead35fd8a
7 changed files with 175 additions and 124 deletions

View File

@ -1,59 +0,0 @@
import ContentBox from '../shared/ContentBox'
import mangoStore from '../../store/state'
import AccountActions from './AccountActions'
import {
HealthType,
toUiDecimalsForQuote,
} from '@blockworks-foundation/mango-v4'
import { formatDecimal } from '../../utils/numbers'
const MangoAccount = () => {
const mangoAccount = mangoStore((s) => s.mangoAccount.current)
return (
<ContentBox showBackground>
<div className="flex-col space-y-2">
<div className="flex items-center justify-between">
<div className="text-th-fgd-4">Account Value</div>
<div className="text-th-fgd-3">
$
{mangoAccount
? formatDecimal(
toUiDecimalsForQuote(mangoAccount.getEquity().toNumber()),
2
)
: (0).toFixed(2)}
</div>
</div>
<div className="flex items-center justify-between">
<div className="text-th-fgd-4">Free Collateral</div>
<div className="text-th-fgd-3">
$
{mangoAccount
? formatDecimal(
toUiDecimalsForQuote(
mangoAccount.getCollateralValue().toNumber()
),
2
)
: (0).toFixed(2)}
</div>
</div>
<div className="flex items-center justify-between">
<div className="text-th-fgd-4">Health</div>
<div className="text-th-fgd-3">
{mangoAccount
? mangoAccount.getHealthRatioUi(HealthType.init)
: 100}
%
</div>
</div>
</div>
<div className="mt-6">
<AccountActions />
</div>
</ContentBox>
)
}
export default MangoAccount

View File

@ -49,7 +49,7 @@ const MangoAccountSummary = () => {
<p className="text-sm text-th-fgd-3">{t('health')}</p>
<p className="text-sm font-bold text-th-fgd-1">
{mangoAccount
? mangoAccount.getHealthRatioUi(HealthType.init)
? mangoAccount.getHealthRatioUi(HealthType.maint)
: 100}
%
</p>

View File

@ -1,9 +1,12 @@
import { toUiDecimals } from '@blockworks-foundation/mango-v4'
import { ChevronDownIcon } from '@heroicons/react/solid'
import { useTranslation } from 'next-i18next'
import Image from 'next/image'
import React, { ChangeEvent, useState } from 'react'
// import mangoStore from '../../store/state'
import React, { ChangeEvent, useCallback, useMemo, useState } from 'react'
import mangoStore from '../../store/state'
import { ModalProps } from '../../types/modal'
import { notify } from '../../utils/notifications'
import { formatFixedDecimals } from '../../utils/numbers'
import ButtonGroup from '../forms/ButtonGroup'
// import { notify } from '../../utils/notifications'
import Input from '../forms/Input'
@ -13,7 +16,7 @@ import DepositTokenList from '../shared/DepositTokenList'
import Loading from '../shared/Loading'
import Modal from '../shared/Modal'
import { EnterBottomExitBottom, FadeInFadeOut } from '../shared/Transitions'
import LeverageSlider from '../swap/LeverageSlider'
import { BorrowLeverageSlider } from '../swap/LeverageSlider'
interface BorrowModalProps {
token?: string
@ -29,20 +32,87 @@ function BorrowModal({ isOpen, onClose, token }: ModalCombinedProps) {
const [showTokenList, setShowTokenList] = useState(false)
const [sizePercentage, setSizePercentage] = useState('')
const handleSizePercentage = (percentage: string) => {
setSizePercentage(percentage)
const mangoAccount = mangoStore((s) => s.mangoAccount.current)
// TODO: calc max
const max = 100
const amount = (Number(percentage) / 100) * max
setInputAmount(amount.toFixed())
}
const bank = useMemo(() => {
const group = mangoStore.getState().group
return group?.banksMap.get(selectedToken)
}, [selectedToken])
const healthImpact = useMemo(() => {
const group = mangoStore.getState().group
if (!group || !bank || !mangoAccount) return 0
return mangoAccount
.simHealthRatioWithTokenPositionChanges(group, [
{ tokenName: bank.name, tokenAmount: parseFloat(inputAmount) * -1 },
])
.toNumber()
}, [mangoAccount, bank, inputAmount])
const tokenMax = useMemo(() => {
const group = mangoStore.getState().group
if (!group || !bank) return 0
const amount = mangoAccount
?.getMaxWithdrawWithBorrowForToken(group, selectedToken)
.toNumber()
return amount ? toUiDecimals(amount, bank.mintDecimals) : 0
}, [mangoAccount, bank, selectedToken])
const setMax = useCallback(() => {
setInputAmount(tokenMax.toString())
}, [tokenMax])
const handleSizePercentage = useCallback(
(percentage: string) => {
setSizePercentage(percentage)
const amount = (Number(percentage) / 100) * (tokenMax || 0)
setInputAmount(amount.toString())
},
[tokenMax]
)
const handleSelectToken = (token: string) => {
setSelectedToken(token)
setShowTokenList(false)
}
const handleWithdraw = async () => {
const client = mangoStore.getState().client
const group = mangoStore.getState().group
const mangoAccount = mangoStore.getState().mangoAccount.current
const actions = mangoStore.getState().actions
if (!mangoAccount || !group) return
setSubmitting(true)
try {
const tx = await client.tokenWithdraw(
group,
mangoAccount,
selectedToken,
parseFloat(inputAmount),
true
)
notify({
title: 'Transaction confirmed',
type: 'success',
txid: tx,
})
actions.reloadAccount()
} catch (e: any) {
console.log(e)
notify({
title: 'Transaction failed',
description: e.message,
txid: e?.txid,
type: 'error',
})
} finally {
setSubmitting(false)
onClose()
}
}
return (
<Modal isOpen={isOpen} onClose={onClose}>
<EnterBottomExitBottom
@ -61,14 +131,13 @@ function BorrowModal({ isOpen, onClose, token }: ModalCombinedProps) {
<div className="grid grid-cols-2 pb-6">
<div className="col-span-2 flex justify-between">
<Label text={t('token')} />
<LinkButton
className="mb-2 no-underline"
onClick={() => console.log('Set max input amount')}
>
<LinkButton className="mb-2 no-underline" onClick={setMax}>
<span className="mr-1 font-normal text-th-fgd-3">
{t('max')}
</span>
<span className="text-th-fgd-1">0</span>
<span className="text-th-fgd-1 underline">
{formatFixedDecimals(tokenMax)}
</span>
</LinkButton>
</div>
<div className="col-span-1 rounded-lg rounded-r-none border border-r-0 border-th-bkg-4 bg-th-bkg-1">
@ -116,22 +185,25 @@ function BorrowModal({ isOpen, onClose, token }: ModalCombinedProps) {
<p className="text-th-fgd-3">{t('leverage')}</p>
<p className="text-th-fgd-3">0.00x</p>
</div>
<LeverageSlider onChange={(x) => setInputAmount(x)} />
<BorrowLeverageSlider
tokenMax={tokenMax}
onChange={(x) => setInputAmount(x)}
/>
</div>
</div>
<div className="space-y-2 border-y border-th-bkg-3 py-4">
<div className="flex justify-between">
<p>{t('health-impact')}</p>
<p className="text-th-red">-12%</p>
<p className="text-th-red">{healthImpact}</p>
</div>
<div className="flex justify-between">
{/* <div className="flex justify-between">
<p>{t('borrow-value')}</p>
<p className="text-th-fgd-1">$1,000.00</p>
</div>
</div> */}
</div>
</div>
<Button
onClick={() => console.log('hanlde borrow')}
onClick={handleWithdraw}
className="flex w-full items-center justify-center"
disabled={!inputAmount}
size="large"

View File

@ -32,20 +32,30 @@ function WithdrawModal({ isOpen, onClose, token }: ModalCombinedProps) {
const mangoAccount = mangoStore((s) => s.mangoAccount.current)
const tokenMax = useMemo(() => {
const bank = useMemo(() => {
const group = mangoStore.getState().group
const bank = group?.banksMap.get(selectedToken)
console.log(group, bank)
return group?.banksMap.get(selectedToken)
}, [selectedToken])
if (!group || !bank) return 0
const tokenMax = useMemo(() => {
if (!bank) return 0
const amount = mangoAccount?.getUi(bank)
return amount ? floorToDecimal(amount, bank.mintDecimals) : 0
}, [mangoAccount, selectedToken])
}, [mangoAccount, bank])
const healthImpact = useMemo(() => {
const group = mangoStore.getState().group
if (!group || !bank || !mangoAccount) return 0
return mangoAccount
.simHealthRatioWithTokenPositionChanges(group, [
{ tokenName: bank.name, tokenAmount: parseFloat(inputAmount) * -1 },
])
.toNumber()
}, [mangoAccount, bank, inputAmount])
const handleSizePercentage = useCallback(
(percentage: string) => {
setSizePercentage(percentage)
const amount = (Number(percentage) / 100) * (tokenMax || 0)
setInputAmount(amount.toString())
},
@ -65,7 +75,7 @@ function WithdrawModal({ isOpen, onClose, token }: ModalCombinedProps) {
mangoAccount,
selectedToken,
parseFloat(inputAmount),
true
false
)
notify({
title: 'Transaction confirmed',
@ -163,16 +173,16 @@ function WithdrawModal({ isOpen, onClose, token }: ModalCombinedProps) {
/>
</div>
</div>
{/* <div className="space-y-2 border-y border-th-bkg-3 py-4">
<div className="flex justify-between">
<p>{t('health-impact')}</p>
<p className="text-th-red">-12%</p>
</div>
<div className="flex justify-between">
<div className="space-y-2 border-y border-th-bkg-3 py-4">
<div className="flex justify-between">
<p>{t('health-impact')}</p>
<p className="text-th-red">{healthImpact}</p>
</div>
{/* <div className="flex justify-between">
<p>{t('withdrawal-value')}</p>
<p className="text-th-fgd-1">$1,000.00</p>
</div> */}
</div>
</div> */}
</div>
<div className="mt-4 flex justify-center">
<Button

View File

@ -9,34 +9,12 @@ type LeverageSliderProps = {
}
const LeverageSlider = ({
inputToken,
outputToken,
leverageMax,
onChange,
}: LeverageSliderProps) => {
const mangoAccount = mangoStore((s) => s.mangoAccount.current)
const group = mangoStore((s) => s.group)
const leverageMax = useMemo(() => {
if (!mangoAccount || !group || !inputToken || !outputToken) return '100'
const bank = group.banksMap.get(inputToken)!
const availableDeposits = bank.uiDeposits() - bank.uiBorrows()
let max
if (outputToken) {
max = toUiDecimals(
mangoAccount
.getMaxSourceForTokenSwap(group, inputToken, outputToken, 0.9)
.toNumber(),
bank?.mintDecimals!
)
} else {
max = availableDeposits
}
return Math.min(availableDeposits, max)
}, [mangoAccount, inputToken, outputToken, group])
}: {
leverageMax: number
onChange: (x: any) => any
}) => {
const handleSliderChange = (e: ChangeEvent<HTMLInputElement>) => {
onChange(e.target.value)
}
@ -57,4 +35,54 @@ const LeverageSlider = ({
)
}
export const SwapLeverageSlider = ({
inputToken,
outputToken,
onChange,
}: LeverageSliderProps) => {
const mangoAccount = mangoStore((s) => s.mangoAccount.current)
const group = mangoStore((s) => s.group)
const leverageMax = useMemo(() => {
if (!mangoAccount || !group || !inputToken || !outputToken) return 100
const bank = group.banksMap.get(inputToken)!
const availableDeposits = bank.uiDeposits() - bank.uiBorrows()
let max
if (outputToken) {
max = toUiDecimals(
mangoAccount
.getMaxSourceForTokenSwap(group, inputToken, outputToken, 0.9)
.toNumber(),
bank?.mintDecimals!
)
} else {
max = availableDeposits
}
return Math.min(availableDeposits, max)
}, [mangoAccount, inputToken, outputToken, group])
return (
<>
<LeverageSlider leverageMax={leverageMax} onChange={onChange} />
</>
)
}
export const BorrowLeverageSlider = ({
tokenMax,
onChange,
}: {
tokenMax: number
onChange: (x: any) => any
}) => {
return (
<>
<LeverageSlider leverageMax={tokenMax} onChange={onChange} />
</>
)
}
export default LeverageSlider

View File

@ -9,7 +9,7 @@ import JupiterRoutes from './JupiterRoutes'
import TokenSelect from '../TokenSelect'
import useDebounce from '../shared/useDebounce'
import { floorToDecimal, numberFormat } from '../../utils/numbers'
import LeverageSlider from './LeverageSlider'
import { SwapLeverageSlider } from './LeverageSlider'
import Input from '../forms/Input'
import { useTranslation } from 'next-i18next'
import SelectToken from './SelectToken'
@ -284,7 +284,7 @@ const Swap = () => {
<p className="text-th-fgd-3">{t('leverage')}</p>
<p className="text-th-fgd-3">0.00x</p>
</div>
<LeverageSlider
<SwapLeverageSlider
inputToken={inputToken}
outputToken={outputToken}
onChange={(x) => setAmountIn(x)}

View File

@ -220,7 +220,7 @@ const Index: NextPage = () => {
<p className="text-th-fgd-3">{t('health')}</p>
<p className="text-2xl font-bold text-th-fgd-1">
{mangoAccount
? mangoAccount.getHealthRatioUi(HealthType.init)
? mangoAccount.getHealthRatioUi(HealthType.maint)
: 100}
%
</p>