perps: remove modify module and adjust main module (#761)

* perps: remove modify module and adjust main module

* fix build
This commit is contained in:
Bob van der Helm 2024-02-02 14:05:40 +01:00 committed by GitHub
parent 98ab2c635a
commit 19d4d1691d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 125 additions and 177 deletions

View File

@ -29,7 +29,6 @@ export default function Manage(props: Props) {
setSearchParams({
...params,
[SearchParams.PERPS_MARKET]: props.perpPosition.asset.denom,
[SearchParams.PERPS_MANAGE]: 'true',
})
},
},

View File

@ -1,109 +0,0 @@
import classNames from 'classnames'
import debounce from 'lodash.debounce'
import { useEffect, useMemo, useState } from 'react'
import { Cross } from 'components/common/Icons'
import LeverageSlider from 'components/common/LeverageSlider'
import { Spacer } from 'components/common/Spacer'
import Text from 'components/common/Text'
import { TradeDirectionSelector } from 'components/common/TradeDirectionSelector'
import { LeverageButtons } from 'components/perps/Module/LeverageButtons'
import { Or } from 'components/perps/Module/Or'
import usePerpsManageModule from 'components/perps/Module/PerpsManageModule/usePerpsManageModule'
import PerpsSummary from 'components/perps/Module/Summary'
import AssetAmountInput from 'components/trade/TradeModule/SwapForm/AssetAmountInput'
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
import { useUpdatedAccount } from 'hooks/useUpdatedAccount'
import getPerpsPosition from 'utils/getPerpsPosition'
import { BN } from 'utils/helpers'
export function PerpsManageModule() {
const [tradeDirection, setTradeDirection] = useState<TradeDirection | null>(null)
const [amount, setAmount] = useState<BigNumber | null>(null)
const account = useCurrentAccount()
const { simulatePerps, addedPerps } = useUpdatedAccount(account)
const {
closeManagePerpModule,
previousAmount,
previousTradeDirection,
previousLeverage,
leverage,
asset,
} = usePerpsManageModule(amount)
const debouncedUpdateAccount = useMemo(
() =>
debounce((perpsPosition: PerpsPosition) => {
if (
addedPerps &&
perpsPosition.amount === addedPerps.amount &&
perpsPosition.tradeDirection === addedPerps.tradeDirection
)
return
simulatePerps(perpsPosition)
}, 100),
[simulatePerps, addedPerps],
)
useEffect(() => {
const perpsPosition = getPerpsPosition(
asset,
amount ?? previousAmount,
tradeDirection ?? previousTradeDirection,
)
debouncedUpdateAccount(perpsPosition)
}, [
debouncedUpdateAccount,
asset,
amount,
previousAmount,
tradeDirection,
previousTradeDirection,
])
if (!asset) return null
return (
<div
className={classNames(
'px-4 gap-5 flex flex-col h-full pt-6 pb-4 w-full bg-white/5 absolute rounded-base isolate',
'before:content-[" "] before:absolute before:inset-0 before:-z-1 before:rounded-base before:p-[1px] before:border-glas',
)}
>
<div className='flex justify-between mb-3'>
<Text>Manage Position</Text>
<button onClick={closeManagePerpModule} className='mr-1.5'>
<Cross width={16} />
</button>
</div>
<TradeDirectionSelector
direction={tradeDirection ?? previousTradeDirection}
onChangeDirection={setTradeDirection}
/>
<AssetAmountInput
label='Amount'
max={BN(1000000)} // TODO: Implement max calculation
amount={amount ?? previousAmount}
setAmount={setAmount}
asset={asset}
maxButtonLabel='Max:'
disabled={false}
/>
<Or />
<Text size='sm'>Position Leverage</Text>
<LeverageSlider max={0} value={0} onChange={() => {}} type={tradeDirection || 'long'} />
<LeverageButtons />
<Spacer />
<PerpsSummary
changeTradeDirection
amount={amount ?? previousAmount}
tradeDirection={tradeDirection ?? previousTradeDirection}
asset={asset}
leverage={leverage}
previousAmount={previousAmount}
previousTradeDirection={previousTradeDirection}
previousLeverage={previousLeverage}
/>
</div>
)
}

View File

@ -1,5 +1,5 @@
import debounce from 'lodash.debounce'
import { useEffect, useMemo, useState } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'
import Card from 'components/common/Card'
import LeverageSlider from 'components/common/LeverageSlider'
@ -9,6 +9,7 @@ import { TradeDirectionSelector } from 'components/common/TradeDirectionSelector
import { LeverageButtons } from 'components/perps/Module/LeverageButtons'
import { Or } from 'components/perps/Module/Or'
import PerpsSummary from 'components/perps/Module/Summary'
import usePerpsModule from 'components/perps/Module/usePerpsModule'
import AssetSelectorPerps from 'components/trade/TradeModule/AssetSelector/AssetSelectorPerps'
import AssetAmountInput from 'components/trade/TradeModule/SwapForm/AssetAmountInput'
import OrderTypeSelector from 'components/trade/TradeModule/SwapForm/OrderTypeSelector'
@ -24,10 +25,11 @@ export function PerpsModule() {
const [selectedOrderType, setSelectedOrderType] = useState<AvailableOrderType>('Market')
const [tradeDirection, setTradeDirection] = useState<TradeDirection>('long')
const { perpsAsset } = usePerpsAsset()
const [leverage, setLeverage] = useState<number>(1)
const account = useCurrentAccount()
const { simulatePerps, addedPerps } = useUpdatedAccount(account)
const [amount, setAmount] = useState<BigNumber>(BN_ZERO)
const { previousAmount, previousTradeDirection, previousLeverage, leverage, hasActivePosition } =
usePerpsModule(amount)
const debouncedUpdateAccount = useMemo(
() =>
@ -44,46 +46,92 @@ export function PerpsModule() {
)
useEffect(() => {
const perpsPosition = getPerpsPosition(perpsAsset, amount, tradeDirection)
const perpsPosition = getPerpsPosition(
perpsAsset,
amount ?? previousAmount,
tradeDirection ?? previousTradeDirection,
)
debouncedUpdateAccount(perpsPosition)
}, [debouncedUpdateAccount, amount, perpsAsset, tradeDirection])
}, [
debouncedUpdateAccount,
amount,
perpsAsset,
tradeDirection,
previousAmount,
previousTradeDirection,
])
const setLeverage = useCallback((leverage: number) => {
// TODO: Implement leverage setting
}, [])
const onChangeTradeDirection = useCallback(
(tradeDirection: TradeDirection) => {
setAmount(amount.times(-1))
setTradeDirection(tradeDirection)
},
[amount],
)
const onChangeAmount = useCallback(
(amount: BigNumber) => {
if (tradeDirection === 'short') {
setAmount(amount.times(-1))
return
}
setAmount(amount)
},
[tradeDirection],
)
if (!perpsAsset) return null
return (
<Card
contentClassName='px-4 gap-5 flex flex-col h-full pb-4'
title={<AssetSelectorPerps asset={perpsAsset} />}
title={<AssetSelectorPerps asset={perpsAsset} hasActivePosition={hasActivePosition} />}
className='h-full mb-4'
>
<OrderTypeSelector selected={selectedOrderType} onChange={setSelectedOrderType} />
<TradeDirectionSelector direction={tradeDirection} onChangeDirection={setTradeDirection} />
<TradeDirectionSelector
direction={tradeDirection}
onChangeDirection={onChangeTradeDirection}
/>
<AssetAmountInput
label='Amount'
max={BN(1000000)} // TODO: Implement max calculation
amount={amount}
setAmount={setAmount}
amount={amount.abs()}
setAmount={onChangeAmount}
asset={perpsAsset}
maxButtonLabel='Max:'
disabled={false}
/>
<Or />
<Text size='sm'>Position Leverage</Text>
<LeverageSlider
min={1}
max={10}
value={leverage}
onChange={setLeverage}
type={tradeDirection}
/>
<LeverageButtons />
{!hasActivePosition && (
<>
<Or />
<Text size='sm'>Position Leverage</Text>
<LeverageSlider
min={1}
max={10}
value={leverage}
onChange={setLeverage}
type={tradeDirection}
/>
<LeverageButtons />
</>
)}
<Spacer />
<PerpsSummary
amount={amount}
tradeDirection={tradeDirection}
amount={amount ?? previousAmount}
tradeDirection={tradeDirection ?? previousTradeDirection}
asset={perpsAsset}
leverage={leverage}
previousAmount={previousAmount}
previousTradeDirection={previousTradeDirection}
previousLeverage={previousLeverage}
hasActivePosition={hasActivePosition}
/>
</Card>
)

View File

@ -18,10 +18,10 @@ type Props = {
amount: BigNumber
tradeDirection: TradeDirection
asset: Asset
changeTradeDirection?: boolean
previousAmount?: BigNumber
previousTradeDirection?: 'long' | 'short'
previousLeverage?: number
hasActivePosition: boolean
}
export default function PerpsSummary(props: Props) {
@ -70,14 +70,13 @@ export default function PerpsSummary(props: Props) {
function ManageSummary(props: Props) {
const showTradeDirection =
props.previousTradeDirection && props.previousTradeDirection !== props.tradeDirection
const showAmount =
props.previousAmount && props.amount && !props.previousAmount.isEqualTo(props.amount)
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) return null
if ((!showTradeDirection && !showLeverage && !showAmount) || !props.hasActivePosition) return null
return (
<div className='pt-4 px-3 flex flex-col gap-1'>
@ -95,14 +94,17 @@ function ManageSummary(props: Props) {
{showAmount && props.previousAmount && (
<SummaryLine label='Size' contentClassName='flex gap-1'>
<AssetAmount asset={props.asset} amount={props.previousAmount.toNumber()} />
<AssetAmount asset={props.asset} amount={props.previousAmount.abs().toNumber()} />
<ArrowRight
width={16}
className={classNames(
props.previousAmount.isGreaterThan(props.amount) ? 'text-error' : 'text-success',
)}
/>
<AssetAmount asset={props.asset} amount={props.amount.toNumber()} />
<AssetAmount
asset={props.asset}
amount={props.previousAmount.plus(props.amount).abs().toNumber()}
/>
</SummaryLine>
)}

View File

@ -1,5 +1,4 @@
import { useCallback, useMemo } from 'react'
import { useSearchParams } from 'react-router-dom'
import { useMemo } from 'react'
import { BN_ZERO } from 'constants/math'
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
@ -8,34 +7,33 @@ import usePerpPosition from 'hooks/perps/usePerpPosition'
import usePerpsAsset from 'hooks/perps/usePerpsAsset'
import usePrice from 'hooks/usePrice'
import usePrices from 'hooks/usePrices'
import { SearchParams } from 'types/enums/searchParams'
import { getAccountNetValue } from 'utils/accounts'
import { byDenom } from 'utils/array'
import { demagnify } from 'utils/formatters'
import { getSearchParamsObject } from 'utils/route'
export default function usePerpsManageModule(amount: BigNumber | null) {
export default function usePerpsModule(amount: BigNumber | null) {
const { perpsAsset } = usePerpsAsset()
const [searchParams, setSearchParams] = useSearchParams()
const perpPosition = usePerpPosition(perpsAsset.denom)
const { data: prices } = usePrices()
const assets = useAllAssets()
const account = useCurrentAccount()
const price = usePrice(perpsAsset.denom)
const hasActivePosition = useMemo(
() => !!account?.perps.find(byDenom(perpsAsset.denom)),
[account?.perps, perpsAsset.denom],
)
const accountNetValue = useMemo(() => {
if (!account || !prices || !assets) return BN_ZERO
return getAccountNetValue(account, prices, assets)
}, [account, assets, prices])
const closeManagePerpModule = useCallback(() => {
const params = getSearchParamsObject(searchParams)
delete params[SearchParams.PERPS_MANAGE]
setSearchParams({
...params,
})
}, [searchParams, setSearchParams])
const previousAmount = useMemo(() => perpPosition?.amount ?? BN_ZERO, [perpPosition?.amount])
const previousAmount = useMemo(
() =>
(perpPosition?.amount ?? BN_ZERO).times(perpPosition?.tradeDirection === 'short' ? -1 : 1),
[perpPosition?.amount, perpPosition?.tradeDirection],
)
const previousTradeDirection = useMemo(
() => perpPosition?.tradeDirection || 'long',
[perpPosition?.tradeDirection],
@ -43,26 +41,29 @@ export default function usePerpsManageModule(amount: BigNumber | null) {
const previousLeverage = useMemo(
() =>
price.times(demagnify(previousAmount, perpsAsset)).div(accountNetValue).plus(1).toNumber(),
price
.times(demagnify(previousAmount.abs(), perpsAsset))
.div(accountNetValue)
.plus(1)
.toNumber(),
[accountNetValue, perpsAsset, previousAmount, price],
)
const leverage = useMemo(
() =>
price
.times(demagnify(amount ?? BN_ZERO, perpsAsset))
.times(demagnify(previousAmount.plus(amount ?? BN_ZERO).abs(), perpsAsset))
.div(accountNetValue)
.plus(1)
.toNumber(),
[accountNetValue, amount, perpsAsset, price],
[accountNetValue, amount, perpsAsset, previousAmount, price],
)
return {
closeManagePerpModule,
previousAmount,
previousTradeDirection,
previousLeverage,
leverage,
asset: perpsAsset,
hasActivePosition,
}
}

View File

@ -4,25 +4,32 @@ import Button from 'components/common/Button'
import { ChevronDown } from 'components/common/Icons'
import Text from 'components/common/Text'
import AssetOverlay from 'components/trade/TradeModule/AssetSelector/AssetOverlay'
import useCurrentAccount from 'hooks/accounts/useCurrentAccount'
import usePerpsEnabledAssets from 'hooks/assets/usePerpsEnabledAssets'
import usePerpsAsset from 'hooks/perps/usePerpsAsset'
import useStore from 'store'
interface Props {
asset: Asset
hasActivePosition: boolean
}
export default function AssetSelectorPerps(props: Props) {
const assetOverlayState = useStore((s) => s.assetOverlayState)
const { perpsAsset, updatePerpsAsset } = usePerpsAsset()
const currentAccount = useCurrentAccount()
const perpAssets = usePerpsEnabledAssets()
const onChangePerpsAsset = useCallback(
(asset: Asset) => {
updatePerpsAsset(asset.denom)
let hasPosition = false
if (currentAccount && currentAccount.perps.find((perp) => perp.denom === asset.denom)) {
hasPosition = true
}
updatePerpsAsset(asset.denom, hasPosition)
},
[updatePerpsAsset],
[currentAccount, updatePerpsAsset],
)
const handleChangeState = useCallback(() => {
@ -37,9 +44,15 @@ export default function AssetSelectorPerps(props: Props) {
onClick={() => useStore.setState({ assetOverlayState: 'pair' })}
className='flex items-center justify-between w-full py-5 bg-white/5'
>
<Text size='sm' className='text-white/60'>
<span className='text-white'>{perpsAsset.symbol}</span>/USD
</Text>
<div className='flex gap-2 items-center'>
<Text size='sm' className='text-white/60'>
<span className='text-white'>{perpsAsset.symbol}</span>/USD
</Text>
{props.hasActivePosition && (
<div className='px-1.5 py-0.5 bg-white/20 rounded-sm text-white text-xs'>Active</div>
)}
</div>
<div className='flex items-center gap-2'>
<Text>All markets</Text>
<ChevronDown className='w-3 h-3' />

View File

@ -6,6 +6,7 @@ import { LocalStorageKeys } from 'constants/localStorageKeys'
import usePerpsEnabledAssets from 'hooks/assets/usePerpsEnabledAssets'
import useLocalStorage from 'hooks/localStorage/useLocalStorage'
import useChainConfig from 'hooks/useChainConfig'
import { SearchParams } from 'types/enums/searchParams'
import { getSearchParamsObject } from 'utils/route'
export default function usePerpsAsset() {
@ -18,10 +19,12 @@ export default function usePerpsAsset() {
>(chainConfig.id + '/' + LocalStorageKeys.PERPS_ASSET, DEFAULT_SETTINGS.perpsAsset)
const updatePerpsAsset = useCallback(
(denom: string) => {
(denom: string, manage?: boolean) => {
const params = getSearchParamsObject(searchParams)
params.perpsMarket = denom
setSearchParams(params)
setSearchParams({
...params,
[SearchParams.PERPS_MARKET]: denom,
})
setPerpsAssetInLocalStorage(denom)
},
[searchParams, setPerpsAssetInLocalStorage, setSearchParams],

View File

@ -15,8 +15,8 @@ export default function usePerpsMarket() {
clients && perpsAsset && `chains/${chainConfig.id}/perps/${perpsAsset.denom}`,
() => getPerpsMarket(clients!, perpsAsset!),
{
refreshInterval: 1000,
dedupingInterval: 1000,
refreshInterval: 5000,
dedupingInterval: 5000,
},
)
}

View File

@ -1,22 +1,14 @@
import { useSearchParams } from 'react-router-dom'
import { PerpsManageModule } from 'components/perps/Module/PerpsManageModule'
import { PerpsModule } from 'components/perps/Module/PerpsModule'
import { PerpsChart } from 'components/perps/PerpsChart'
import { PerpsInfo } from 'components/perps/PerpsInfo'
import { PerpsPositions } from 'components/perps/PerpsPositions'
import { SearchParams } from 'types/enums/searchParams'
export default function PerpsPage() {
const [searchParams] = useSearchParams()
const isManagingPosition = searchParams.get(SearchParams.PERPS_MANAGE) === 'true'
return (
<div className='grid grid-cols-[auto_376px] grid-rows-[min-content_auto_auto] w-full gap-4'>
<PerpsInfo />
<div className='h-full w-[376px] row-span-3 relative'>
{isManagingPosition ? <PerpsManageModule /> : <PerpsModule />}
<PerpsModule />
</div>
<PerpsChart />
<PerpsPositions />

View File

@ -1,5 +1,4 @@
export enum SearchParams {
ACCOUNT_ID = 'accountId',
PERPS_MARKET = 'perpsMarket',
PERPS_MANAGE = 'perpsManage',
}