mars-v2-frontend/src/components/perps/Module/Summary.tsx
2024-02-13 17:17:16 +01:00

174 lines
6.0 KiB
TypeScript

import classNames from 'classnames'
import { useCallback, useMemo } from 'react'
import AssetAmount from 'components/common/assets/AssetAmount'
import ActionButton from 'components/common/Button/ActionButton'
import { ArrowRight } from 'components/common/Icons'
import SummaryLine from 'components/common/SummaryLine'
import Text from 'components/common/Text'
import TradeDirection from 'components/perps/BalancesTable/Columns/TradeDirection'
import { ExpectedPrice } from 'components/perps/Module/ExpectedPrice'
import TradingFee from 'components/perps/Module/TradingFee'
import { BN_ZERO } from 'constants/math'
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
import useTradingFeeAndPrice from 'hooks/perps/useTradingFeeAndPrice'
import useStore from 'store'
import { BNCoin } from 'types/classes/BNCoin'
import { formatLeverage } from 'utils/formatters'
type Props = {
leverage: number
amount: BigNumber
tradeDirection: TradeDirection
asset: Asset
previousAmount: BigNumber
previousTradeDirection?: 'long' | 'short'
previousLeverage?: number | null
hasActivePosition: boolean
onTxExecuted: () => void
}
export default function PerpsSummary(props: Props) {
const openPerpPosition = useStore((s) => s.openPerpPosition)
const modifyPerpPosition = useStore((s) => s.modifyPerpPosition)
const closePerpPosition = useStore((s) => s.closePerpPosition)
const currentAccount = useCurrentAccount()
const newAmount = useMemo(
() => (props.previousAmount ?? BN_ZERO).plus(props.amount),
[props.amount, props.previousAmount],
)
const { data: tradingFee } = useTradingFeeAndPrice(
props.asset.denom,
newAmount,
props.previousAmount,
)
const onConfirm = useCallback(async () => {
if (!currentAccount) return
if (!props.previousAmount.isZero() && newAmount.isZero()) {
await closePerpPosition({
accountId: currentAccount.id,
denom: props.asset.denom,
})
return props.onTxExecuted()
}
if (!props.previousAmount.isZero() && !newAmount.isZero()) {
await modifyPerpPosition({
accountId: currentAccount.id,
coin: BNCoin.fromDenomAndBigNumber(props.asset.denom, newAmount),
changeDirection: props.previousAmount.isNegative() !== newAmount.isNegative(),
})
return props.onTxExecuted()
}
await openPerpPosition({
accountId: currentAccount.id,
coin: BNCoin.fromDenomAndBigNumber(props.asset.denom, props.amount),
})
return props.onTxExecuted()
}, [closePerpPosition, currentAccount, modifyPerpPosition, newAmount, openPerpPosition, props])
const disabled = useMemo(() => props.amount.isZero(), [props.amount])
return (
<div className='border border-white/10 rounded-sm bg-white/5'>
<ManageSummary {...props} newAmount={newAmount} />
<div className='py-4 px-3 flex flex-col gap-1'>
<Text size='xs' className='font-bold mb-2'>
Summary
</Text>
<SummaryLine label='Expected Price'>
<ExpectedPrice
denom={props.asset.denom}
newAmount={newAmount}
previousAmount={props.previousAmount}
/>
</SummaryLine>
<SummaryLine
label='Fees'
tooltip={`${tradingFee ? tradingFee.rate.times(100) + '% ' : ''}Trading Fees`}
>
<TradingFee
denom={props.asset.denom}
newAmount={newAmount}
previousAmount={props.previousAmount}
/>
</SummaryLine>
<SummaryLine label='Total'>-</SummaryLine>
</div>
<ActionButton onClick={onConfirm} disabled={disabled} className='w-full py-2.5'>
<span className='capitalize mr-1'>{props.tradeDirection}</span>
{props.asset.symbol}
</ActionButton>
</div>
)
}
function ManageSummary(props: Props & { newAmount: BigNumber }) {
const showTradeDirection =
props.previousAmount && props.previousAmount.isNegative() !== props.newAmount.isNegative()
const showAmount = !props.amount.isZero() && props.previousAmount
const showLeverage =
props.previousLeverage &&
props.leverage &&
props.previousLeverage.toFixed(2) !== props.leverage.toFixed(2)
if ((!showTradeDirection && !showLeverage && !showAmount) || !props.hasActivePosition) return null
return (
<div className='pt-4 px-3 flex flex-col gap-1'>
<Text size='xs' className='font-bold mb-2'>
Your new position
</Text>
{props.newAmount.isZero() && (
<Text size='xs' className='text-white/40 mb-1'>
Your position will be closed
</Text>
)}
{showTradeDirection && props.previousTradeDirection && !props.newAmount.isZero() && (
<SummaryLine label='Side' contentClassName='flex gap-1'>
<TradeDirection tradeDirection={props.previousTradeDirection} />
<ArrowRight width={16} />
<TradeDirection tradeDirection={props.tradeDirection} />
</SummaryLine>
)}
{showAmount && props.newAmount && props.previousAmount && !props.newAmount.isZero() && (
<SummaryLine label='Size' contentClassName='flex gap-1'>
<AssetAmount asset={props.asset} amount={props.previousAmount.abs().toNumber()} />
<ArrowRight
width={16}
className={classNames(
props.previousAmount.abs().isGreaterThan(props.newAmount)
? 'text-error'
: 'text-success',
)}
/>
<AssetAmount
asset={props.asset}
amount={props.previousAmount.plus(props.amount).abs().toNumber()}
/>
</SummaryLine>
)}
{showLeverage && props.previousLeverage && (
<SummaryLine label='Leverage' contentClassName='flex gap-1'>
<span>{formatLeverage(props.previousLeverage)}</span>
<ArrowRight
width={16}
className={classNames(
props.leverage > props.previousLeverage ? 'text-error' : 'text-success',
)}
/>
<span>{formatLeverage(props.leverage)}</span>
</SummaryLine>
)}
</div>
)
}