From c1254c918600397e3c02ad45ee4e94c134965fbf Mon Sep 17 00:00:00 2001 From: saml33 Date: Fri, 4 Nov 2022 18:55:21 +0000 Subject: [PATCH] add health impact to trade form --- components/HealthImpactTokenChange.tsx | 38 ++++++++++++++++++++ components/modals/BorrowModal.tsx | 9 +++-- components/modals/DepositModal.tsx | 5 ++- components/modals/WithdrawModal.tsx | 8 ++--- components/shared/HealthImpact.tsx | 36 +++++-------------- components/swap/SwapForm.tsx | 40 ++------------------- components/trade/AdvancedTradeForm.tsx | 49 ++++++++++++++++++++++++++ 7 files changed, 111 insertions(+), 74 deletions(-) create mode 100644 components/HealthImpactTokenChange.tsx diff --git a/components/HealthImpactTokenChange.tsx b/components/HealthImpactTokenChange.tsx new file mode 100644 index 00000000..c6c1d6f3 --- /dev/null +++ b/components/HealthImpactTokenChange.tsx @@ -0,0 +1,38 @@ +import { HealthType } from '@blockworks-foundation/mango-v4' +import { PublicKey } from '@solana/web3.js' +import { useMemo } from 'react' +import mangoStore from '@store/mangoStore' +import HealthImpact from './shared/HealthImpact' + +const HealthImpactTokenChange = ({ + uiAmount, + isDeposit, + mintPk, +}: { + uiAmount: number + isDeposit?: boolean + mintPk: PublicKey +}) => { + const maintProjectedHealth = useMemo(() => { + const mangoAccount = mangoStore.getState().mangoAccount.current + const group = mangoStore.getState().group + if (!group || !mangoAccount) return 0 + const uiTokenAmount = isDeposit ? uiAmount : uiAmount * -1 + const projectedHealth = + mangoAccount.simHealthRatioWithTokenPositionUiChanges( + group, + [{ mintPk, uiTokenAmount }], + HealthType.maint + ) + + return projectedHealth! > 100 + ? 100 + : projectedHealth! < 0 + ? 0 + : Math.trunc(projectedHealth!) + }, [mintPk, uiAmount, isDeposit]) + + return +} + +export default HealthImpactTokenChange diff --git a/components/modals/BorrowModal.tsx b/components/modals/BorrowModal.tsx index 32229119..13d871ff 100644 --- a/components/modals/BorrowModal.tsx +++ b/components/modals/BorrowModal.tsx @@ -17,8 +17,7 @@ import { floorToDecimal, formatFixedDecimals } from '../../utils/numbers' import ActionTokenList from '../account/ActionTokenList' import ButtonGroup from '../forms/ButtonGroup' import Label from '../forms/Label' -import Button, { LinkButton } from '../shared/Button' -import HealthImpact from '../shared/HealthImpact' +import Button from '../shared/Button' import InlineNotification from '../shared/InlineNotification' import Loading from '../shared/Loading' import Modal from '../shared/Modal' @@ -26,6 +25,7 @@ import { EnterBottomExitBottom, FadeInFadeOut } from '../shared/Transitions' import { withValueLimit } from '../swap/SwapForm' import { getMaxWithdrawForBank } from '../swap/useTokenMax' import MaxAmountButton from '@components/shared/MaxAmountButton' +import HealthImpactTokenChange from '@components/HealthImpactTokenChange' interface BorrowModalProps { token?: string @@ -256,7 +256,10 @@ function BorrowModal({ isOpen, onClose, token }: ModalCombinedProps) { */}
- +

{t('borrow-value')}

diff --git a/components/modals/DepositModal.tsx b/components/modals/DepositModal.tsx index 83db09ba..244b6267 100644 --- a/components/modals/DepositModal.tsx +++ b/components/modals/DepositModal.tsx @@ -21,8 +21,6 @@ import ActionTokenList from '../account/ActionTokenList' import ButtonGroup from '../forms/ButtonGroup' import Label from '../forms/Label' import Button from '../shared/Button' -import HealthImpact from '../shared/HealthImpact' -import InfoTooltip from '../shared/InfoTooltip' import InlineNotification from '../shared/InlineNotification' import Loading from '../shared/Loading' import Modal from '../shared/Modal' @@ -30,6 +28,7 @@ import { EnterBottomExitBottom, FadeInFadeOut } from '../shared/Transitions' import { withValueLimit } from '../swap/SwapForm' import MaxAmountButton from '@components/shared/MaxAmountButton' import Tooltip from '@components/shared/Tooltip' +import HealthImpactTokenChange from '@components/HealthImpactTokenChange' interface DepositModalProps { token?: string @@ -311,7 +310,7 @@ function DepositModal({ isOpen, onClose, token }: ModalCombinedProps) {

-
- diff --git a/components/shared/HealthImpact.tsx b/components/shared/HealthImpact.tsx index 3177cd4e..807b8b1a 100644 --- a/components/shared/HealthImpact.tsx +++ b/components/shared/HealthImpact.tsx @@ -1,18 +1,14 @@ import { HealthType } from '@blockworks-foundation/mango-v4' import { ArrowRightIcon } from '@heroicons/react/20/solid' -import { PublicKey } from '@solana/web3.js' import { useTranslation } from 'next-i18next' import { useMemo } from 'react' import mangoStore from '@store/mangoStore' +import Tooltip from './Tooltip' const HealthImpact = ({ - uiAmount, - isDeposit, - mintPk, + maintProjectedHealth, }: { - uiAmount: number - isDeposit?: boolean - mintPk: PublicKey + maintProjectedHealth: number }) => { const { t } = useTranslation('common') const group = mangoStore.getState().group @@ -23,27 +19,13 @@ const HealthImpact = ({ return mangoAccount.getHealthRatioUi(group, HealthType.maint) }, [mangoAccount]) - const maintProjectedHealth = useMemo(() => { - const group = mangoStore.getState().group - if (!group || !mangoAccount) return 0 - const uiTokenAmount = isDeposit ? uiAmount : uiAmount * -1 - const projectedHealth = - mangoAccount.simHealthRatioWithTokenPositionUiChanges( - group, - [{ mintPk, uiTokenAmount }], - HealthType.maint - ) - - return projectedHealth! > 100 - ? 100 - : projectedHealth! < 0 - ? 0 - : Math.trunc(projectedHealth!) - }, [mangoAccount, mintPk, uiAmount, isDeposit]) - return ( -
-

{t('health-impact')}

+
+ +

+ {t('health-impact')} +

+

{currentMaintHealth}%

diff --git a/components/swap/SwapForm.tsx b/components/swap/SwapForm.tsx index 7308bc08..0334c3c2 100644 --- a/components/swap/SwapForm.tsx +++ b/components/swap/SwapForm.tsx @@ -2,11 +2,9 @@ import { useState, useCallback, useEffect, useMemo } from 'react' import { PublicKey } from '@solana/web3.js' import { ArrowDownIcon, - ArrowRightIcon, Cog8ToothIcon, MagnifyingGlassIcon, ExclamationCircleIcon, - HeartIcon, LinkIcon, } from '@heroicons/react/20/solid' import { RouteInfo } from '@jup-ag/core' @@ -22,7 +20,7 @@ import { SwapLeverageSlider } from './LeverageSlider' import { useTranslation } from 'next-i18next' import SwapFormTokenList from './SwapFormTokenList' import { Transition } from '@headlessui/react' -import Button, { IconButton, LinkButton } from '../shared/Button' +import Button, { IconButton } from '../shared/Button' import ButtonGroup from '../forms/ButtonGroup' import Loading from '../shared/Loading' import { EnterBottomExitBottom } from '../shared/Transitions' @@ -35,8 +33,8 @@ import { OUTPUT_TOKEN_DEFAULT, } from '../../utils/constants' import { useTokenMax } from './useTokenMax' -import Tooltip from '@components/shared/Tooltip' import MaxAmountButton from '@components/shared/MaxAmountButton' +import HealthImpact from '@components/shared/HealthImpact' const MAX_DIGITS = 11 export const withValueLimit = (values: NumberFormatValues): boolean => { @@ -368,39 +366,7 @@ const SwapForm = () => { id="swap-step-four" className={`border-t border-th-bkg-3 px-6 py-4 transition-all`} > -
-
- - -

{t('health-impact')}

-
-
-
-

{currentMaintHealth}%

- -

15 - ? 'text-th-orange' - : maintProjectedHealth! <= 15 - ? 'text-th-red' - : 'text-th-green' - } text-sm`} - > - {maintProjectedHealth!}%{' '} - = currentMaintHealth! - ? 'text-th-green' - : 'text-th-red' - }`} - > - ({maintProjectedHealth! >= currentMaintHealth! ? '+' : ''} - {maintProjectedHealth! - currentMaintHealth!}%) - -

-
-
+
) diff --git a/components/trade/AdvancedTradeForm.tsx b/components/trade/AdvancedTradeForm.tsx index f0a9b41a..865bbd53 100644 --- a/components/trade/AdvancedTradeForm.tsx +++ b/components/trade/AdvancedTradeForm.tsx @@ -1,4 +1,5 @@ import { + HealthType, PerpMarket, PerpOrderSide, PerpOrderType, @@ -29,6 +30,7 @@ import { Market } from '@project-serum/serum' import TabUnderline from '@components/shared/TabUnderline' import { group } from 'console' import PerpSlider from './PerpSlider' +import HealthImpact from '@components/shared/HealthImpact' const TABS: [string, number][] = [ ['Limit', 0], @@ -287,6 +289,50 @@ const AdvancedTradeForm = () => { } }, [t]) + const maintProjectedHealth = useMemo(() => { + const group = mangoStore.getState().group + const mangoAccount = mangoStore.getState().mangoAccount.current + if (!mangoAccount || !group || !tradeForm.baseSize) return 100 + + let simulatedHealthRatio: number + + if (selectedMarket instanceof Serum3Market) { + simulatedHealthRatio = + tradeForm.side === 'sell' + ? mangoAccount.simHealthRatioWithSerum3AskUiChanges( + group, + parseFloat(tradeForm.baseSize), + selectedMarket.serumMarketExternal, + HealthType.maint + ) + : mangoAccount.simHealthRatioWithSerum3BidUiChanges( + group, + parseFloat(tradeForm.baseSize), + selectedMarket.serumMarketExternal, + HealthType.maint + ) + } else { + simulatedHealthRatio = + tradeForm.side === 'sell' + ? mangoAccount.simHealthRatioWithPerpAskUiChanges( + group, + selectedMarket!.perpMarketIndex, + parseFloat(tradeForm.baseSize) + ) + : mangoAccount.simHealthRatioWithPerpBidUiChanges( + group, + selectedMarket!.perpMarketIndex, + parseFloat(tradeForm.baseSize) + ) + } + + return simulatedHealthRatio! > 100 + ? 100 + : simulatedHealthRatio! < 0 + ? 0 + : Math.trunc(simulatedHealthRatio!) + }, [selectedMarket, tradeForm]) + return (
@@ -478,6 +524,9 @@ const AdvancedTradeForm = () => { )}
+
+ +
) }