2022-12-21 20:19:00 -08:00
import {
HealthType ,
MangoAccount ,
PerpMarket ,
Serum3Market ,
} from '@blockworks-foundation/mango-v4'
2023-01-24 16:54:24 -08:00
import FormatNumericValue from '@components/shared/FormatNumericValue'
2022-12-21 20:19:00 -08:00
import HealthImpact from '@components/shared/HealthImpact'
import Tooltip from '@components/shared/Tooltip'
import mangoStore from '@store/mangoStore'
2023-04-25 05:41:23 -07:00
import Decimal from 'decimal.js'
2022-12-21 20:19:00 -08:00
import useMangoGroup from 'hooks/useMangoGroup'
import useSelectedMarket from 'hooks/useSelectedMarket'
import { useTranslation } from 'next-i18next'
import { useMemo } from 'react'
import Slippage from './Slippage'
2023-06-29 04:38:32 -07:00
import {
floorToDecimal ,
formatNumericValue ,
2023-06-29 21:37:01 -07:00
// getDecimalCount,
2023-06-29 04:38:32 -07:00
} from 'utils/numbers'
2023-05-14 06:07:06 -07:00
import { formatTokenSymbol } from 'utils/tokens'
2023-06-29 21:37:01 -07:00
// import useOpenPerpPositions from 'hooks/useOpenPerpPositions'
2022-12-21 20:19:00 -08:00
const TradeSummary = ( {
mangoAccount ,
2023-03-17 05:48:38 -07:00
useMargin ,
2022-12-21 20:19:00 -08:00
} : {
mangoAccount : MangoAccount | undefined
2023-03-17 05:48:38 -07:00
useMargin : boolean
2022-12-21 20:19:00 -08:00
} ) = > {
const { t } = useTranslation ( [ 'common' , 'trade' ] )
const { group } = useMangoGroup ( )
const tradeForm = mangoStore ( ( s ) = > s . tradeForm )
2023-04-25 05:41:23 -07:00
const { selectedMarket , quoteBank } = useSelectedMarket ( )
2023-06-29 21:37:01 -07:00
// const openPerpPositions = useOpenPerpPositions()
2023-06-29 04:38:32 -07:00
2023-06-29 21:37:01 -07:00
// this isn't correct yet
// const avgEntryPrice = useMemo(() => {
// if (
// !openPerpPositions.length ||
// !selectedMarket ||
// selectedMarket instanceof Serum3Market
// )
// return
// const openPosition = openPerpPositions.find(
// (pos) => pos.marketIndex === selectedMarket.perpMarketIndex
// )
// if (openPosition && tradeForm.price) {
// const currentAvgPrice =
// openPosition.getAverageEntryPriceUi(selectedMarket)
// const newAvgPrice = (currentAvgPrice + Number(tradeForm.price)) / 2
// return newAvgPrice
// }
// return
// }, [openPerpPositions, selectedMarket, tradeForm])
2022-12-21 20:19:00 -08:00
const maintProjectedHealth = useMemo ( ( ) = > {
2023-03-04 10:53:49 -08:00
if ( ! mangoAccount || ! group ) return 100
2022-12-21 20:19:00 -08:00
let simulatedHealthRatio = 0
try {
if ( selectedMarket instanceof Serum3Market ) {
simulatedHealthRatio =
tradeForm . side === 'sell'
? mangoAccount . simHealthRatioWithSerum3AskUiChanges (
group ,
Number ( tradeForm . baseSize ) ,
selectedMarket . serumMarketExternal ,
HealthType . maint
)
: mangoAccount . simHealthRatioWithSerum3BidUiChanges (
group ,
Number ( tradeForm . quoteSize ) ,
selectedMarket . serumMarketExternal ,
HealthType . maint
)
} else if ( selectedMarket instanceof PerpMarket ) {
simulatedHealthRatio =
tradeForm . side === 'sell'
? mangoAccount . simHealthRatioWithPerpAskUiChanges (
group ,
selectedMarket . perpMarketIndex ,
2023-04-03 22:01:41 -07:00
parseFloat ( tradeForm . baseSize ) || 0
2022-12-21 20:19:00 -08:00
)
: mangoAccount . simHealthRatioWithPerpBidUiChanges (
group ,
selectedMarket . perpMarketIndex ,
2023-04-03 22:01:41 -07:00
parseFloat ( tradeForm . baseSize ) || 0
2022-12-21 20:19:00 -08:00
)
}
} catch ( e ) {
console . warn ( 'Error calculating projected health: ' , e )
}
return simulatedHealthRatio > 100
? 100
: simulatedHealthRatio < 0
? 0
: Math . trunc ( simulatedHealthRatio )
2023-01-02 11:50:09 -08:00
} , [ group , mangoAccount , selectedMarket , tradeForm ] )
2022-12-21 20:19:00 -08:00
2023-03-17 05:48:38 -07:00
const balanceBank = useMemo ( ( ) = > {
if (
! group ||
! selectedMarket ||
selectedMarket instanceof PerpMarket ||
! useMargin
)
return
if ( tradeForm . side === 'buy' ) {
return group . getFirstBankByTokenIndex ( selectedMarket . quoteTokenIndex )
} else {
return group . getFirstBankByTokenIndex ( selectedMarket . baseTokenIndex )
}
} , [ group , selectedMarket , tradeForm . side ] )
2023-05-14 06:07:06 -07:00
const [ balance , borrowAmount ] = useMemo ( ( ) = > {
if ( ! balanceBank || ! mangoAccount ) return [ 0 , 0 ]
2023-03-17 05:48:38 -07:00
let borrowAmount
const balance = mangoAccount . getTokenDepositsUi ( balanceBank )
if ( tradeForm . side === 'buy' ) {
const remainingBalance = balance - parseFloat ( tradeForm . quoteSize )
borrowAmount = remainingBalance < 0 ? Math . abs ( remainingBalance ) : 0
} else {
const remainingBalance = balance - parseFloat ( tradeForm . baseSize )
borrowAmount = remainingBalance < 0 ? Math . abs ( remainingBalance ) : 0
}
2023-05-14 06:07:06 -07:00
return [ balance , borrowAmount ]
2023-03-17 05:48:38 -07:00
} , [ balanceBank , mangoAccount , tradeForm ] )
2023-04-25 05:41:23 -07:00
const orderValue = useMemo ( ( ) = > {
2023-04-28 11:39:22 -07:00
if (
! quoteBank ||
! tradeForm . price ||
2023-05-13 04:41:42 -07:00
! tradeForm . baseSize ||
2023-06-15 05:32:40 -07:00
isNaN ( parseFloat ( tradeForm . price ) ) ||
isNaN ( parseFloat ( tradeForm . baseSize ) )
2023-04-28 11:39:22 -07:00
)
return 0
2023-04-25 05:41:23 -07:00
const basePriceDecimal = new Decimal ( tradeForm . price )
const quotePriceDecimal = new Decimal ( quoteBank . uiPrice )
const sizeDecimal = new Decimal ( tradeForm . baseSize )
2023-05-13 04:41:42 -07:00
return floorToDecimal (
basePriceDecimal . mul ( quotePriceDecimal ) . mul ( sizeDecimal ) ,
2
)
2023-04-25 05:41:23 -07:00
} , [ quoteBank , tradeForm ] )
2022-12-21 20:19:00 -08:00
return (
< div className = "space-y-2 px-3 md:px-4" >
2022-12-30 10:26:45 -08:00
< div className = "flex justify-between text-xs" >
< p > { t ( 'trade:order-value' ) } < / p >
< p className = "text-th-fgd-2" >
2023-05-13 04:41:42 -07:00
{ orderValue ? < FormatNumericValue value = { orderValue } isUsd / > : '– ' }
2022-12-30 10:26:45 -08:00
< / p >
< / div >
2022-12-21 20:19:00 -08:00
< HealthImpact maintProjectedHealth = { maintProjectedHealth } small / >
2023-05-14 06:07:06 -07:00
{ borrowAmount && balanceBank ? (
< >
< div className = "flex justify-between text-xs" >
< Tooltip
content = {
balance
? t ( 'trade:tooltip-borrow-balance' , {
balance : formatNumericValue ( balance ) ,
borrowAmount : formatNumericValue ( borrowAmount ) ,
token : formatTokenSymbol ( balanceBank . name ) ,
rate : formatNumericValue (
balanceBank . getBorrowRateUi ( ) ,
2
) ,
} )
: t ( 'trade:tooltip-borrow-no-balance' , {
borrowAmount : formatNumericValue ( borrowAmount ) ,
token : formatTokenSymbol ( balanceBank . name ) ,
rate : formatNumericValue (
balanceBank . getBorrowRateUi ( ) ,
2
) ,
} )
2023-03-17 05:48:38 -07:00
}
2023-05-14 06:07:06 -07:00
delay = { 100 }
>
< p className = "tooltip-underline" > { t ( 'borrow-amount' ) } < / p >
< / Tooltip >
< p className = "text-right font-mono text-th-fgd-2" >
< FormatNumericValue
value = { borrowAmount }
decimals = { balanceBank . mintDecimals }
/ > { ' ' }
< span className = "font-body text-th-fgd-4" >
{ formatTokenSymbol ( balanceBank . name ) }
< / span >
< / p >
< / div >
< div className = "flex justify-between text-xs" >
< Tooltip
content = { t ( 'loan-origination-fee-tooltip' , {
fee : ` ${ (
balanceBank . loanOriginationFeeRate . toNumber ( ) * 100
) . toFixed ( 3 ) } % ` ,
} ) }
delay = { 100 }
>
< p className = "tooltip-underline" > { t ( 'loan-origination-fee' ) } < / p >
< / Tooltip >
< p className = "text-right font-mono text-th-fgd-2" >
< FormatNumericValue
value = {
borrowAmount * balanceBank . loanOriginationFeeRate . toNumber ( )
}
decimals = { balanceBank . mintDecimals }
/ > { ' ' }
< span className = "font-body text-th-fgd-4" >
{ formatTokenSymbol ( balanceBank . name ) }
< / span >
< / p >
< / div >
< / >
2023-03-17 05:48:38 -07:00
) : null }
2023-05-14 06:07:06 -07:00
{ / * < d i v c l a s s N a m e = " f l e x j u s t i f y - b e t w e e n t e x t - x s " >
2022-12-21 20:19:00 -08:00
< Tooltip content = "The amount of capital you have to use for trades and loans. When your free collateral reaches $0 you won't be able to trade, borrow or withdraw." >
< p className = "tooltip-underline" > { t ( 'free-collateral' ) } < / p >
< / Tooltip >
< p className = "text-th-fgd-2" >
2023-01-24 16:54:24 -08:00
{ group && mangoAccount ? (
< FormatNumericValue
value = { toUiDecimalsForQuote (
mangoAccount . getCollateralValue ( group )
) }
decimals = { 2 }
isUsd
/ >
) : (
'– '
) }
2022-12-21 20:19:00 -08:00
< / p >
2023-05-14 06:07:06 -07:00
< / div > * / }
2022-12-21 20:19:00 -08:00
< Slippage / >
2023-06-29 21:37:01 -07:00
{ / * { a v g E n t r y P r i c e & & s e l e c t e d M a r k e t i n s t a n c e o f P e r p M a r k e t ? (
2023-06-29 04:38:32 -07:00
< div className = "flex justify-between text-xs" >
< p > { t ( 'trade:avg-entry-price' ) } < / p >
< p className = "text-th-fgd-2" >
{ tradeForm . tradeType === 'Market' ? '~' : '' }
< FormatNumericValue
value = { avgEntryPrice }
decimals = { getDecimalCount ( selectedMarket . tickSize ) }
isUsd
/ >
< / p >
< / div >
2023-06-29 21:37:01 -07:00
) : null } * / }
2022-12-21 20:19:00 -08:00
< / div >
)
}
export default TradeSummary