add functional funding rate + selector (#729)
* add functional funding rate + selector * Edit perps position (#728)
This commit is contained in:
parent
647a287a6b
commit
7629e2442f
77
src/components/Perps/PerpsInfo/FundingRate.tsx
Normal file
77
src/components/Perps/PerpsInfo/FundingRate.tsx
Normal file
@ -0,0 +1,77 @@
|
||||
import { useMemo, useState } from 'react'
|
||||
|
||||
import { FormattedNumber } from 'components/FormattedNumber'
|
||||
import { ChevronDown } from 'components/Icons'
|
||||
import Loading from 'components/Loading'
|
||||
import { Tooltip } from 'components/Tooltip'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import usePerpsMarket from 'hooks/perps/usePerpsMarket'
|
||||
import useToggle from 'hooks/useToggle'
|
||||
|
||||
type Interval = '1H' | '1D' | '1W' | '1M' | '1Y'
|
||||
|
||||
enum Intervals {
|
||||
'1H' = 365 * 24,
|
||||
'1D' = 365,
|
||||
'1W' = 52,
|
||||
'1M' = 12,
|
||||
'1Y' = 1,
|
||||
}
|
||||
|
||||
export default function FundingRate() {
|
||||
const { data: market, isLoading } = usePerpsMarket()
|
||||
const [interval, setInterval] = useState<Interval>('1H')
|
||||
const [show, toggleShow] = useToggle(false)
|
||||
|
||||
const fundingRate = useMemo(() => {
|
||||
return market?.fundingRate.div(Intervals[interval]) ?? BN_ZERO
|
||||
}, [interval, market?.fundingRate])
|
||||
|
||||
if (isLoading) return <Loading className='w-14 h-4' />
|
||||
if (!market) return '-'
|
||||
|
||||
return (
|
||||
<div className='flex gap-1'>
|
||||
<FormattedNumber
|
||||
className='text-sm inline'
|
||||
amount={fundingRate.toNumber()}
|
||||
options={{ minDecimals: 6, maxDecimals: 6, suffix: '%' }}
|
||||
/>
|
||||
<Tooltip
|
||||
content={
|
||||
<div>
|
||||
{Object.keys(Intervals)
|
||||
.filter((key) => isNaN(Number(key)))
|
||||
.map((key) => (
|
||||
<button
|
||||
key={key}
|
||||
onClick={() => {
|
||||
setInterval(key as Interval)
|
||||
toggleShow(false)
|
||||
}}
|
||||
className='w-full text-left px-4 py-2 flex gap-2 items-center hover:bg-white/5 [&:not(:last-child)]:border-b border-white/10'
|
||||
>
|
||||
{key}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
}
|
||||
type='info'
|
||||
placement='bottom'
|
||||
contentClassName='!bg-white/10 border border-white/20 backdrop-blur-xl !p-0'
|
||||
interactive
|
||||
hideArrow
|
||||
visible={show}
|
||||
onClickOutside={() => toggleShow(false)}
|
||||
>
|
||||
<button
|
||||
onClick={() => toggleShow()}
|
||||
className='flex gap-1 bg-white/10 rounded-sm items-center text-[10px] px-1.5 py-0.5'
|
||||
>
|
||||
{interval}
|
||||
<ChevronDown className='h-2 w-2' />
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
}
|
27
src/components/Perps/PerpsInfo/InterestItem.tsx
Normal file
27
src/components/Perps/PerpsInfo/InterestItem.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import React from 'react'
|
||||
|
||||
import AssetSymbol from 'components/Asset/AssetSymbol'
|
||||
import { FormattedNumber } from 'components/FormattedNumber'
|
||||
import Loading from 'components/Loading'
|
||||
import usePerpsMarket from 'hooks/perps/usePerpsMarket'
|
||||
|
||||
interface InterestItemProps {
|
||||
type: 'long' | 'short'
|
||||
}
|
||||
export default function InterestItem(props: InterestItemProps) {
|
||||
const { data: market, isLoading } = usePerpsMarket()
|
||||
|
||||
if (isLoading) return <Loading />
|
||||
if (!market) return null
|
||||
|
||||
return (
|
||||
<div className='flex gap-1 items-center'>
|
||||
<FormattedNumber
|
||||
className='text-sm inline'
|
||||
amount={market.openInterest[props.type].toNumber()}
|
||||
options={{ decimals: market.asset.decimals }}
|
||||
/>
|
||||
<AssetSymbol symbol={market.asset.symbol} />
|
||||
</div>
|
||||
)
|
||||
}
|
@ -1,11 +1,11 @@
|
||||
import React, { useMemo } from 'react'
|
||||
|
||||
import AssetSymbol from 'components/Asset/AssetSymbol'
|
||||
import Card from 'components/Card'
|
||||
import DisplayCurrency from 'components/DisplayCurrency'
|
||||
import Divider from 'components/Divider'
|
||||
import { FormattedNumber } from 'components/FormattedNumber'
|
||||
import Loading from 'components/Loading'
|
||||
import FundingRate from 'components/Perps/PerpsInfo/FundingRate'
|
||||
import InterestItem from 'components/Perps/PerpsInfo/InterestItem'
|
||||
import Text from 'components/Text'
|
||||
import usePerpsMarket from 'hooks/perps/usePerpsMarket'
|
||||
import usePrice from 'hooks/usePrice'
|
||||
@ -25,28 +25,14 @@ export function PerpsInfo() {
|
||||
<InfoItem
|
||||
key='openInterestLong'
|
||||
label='Open Interest (L)'
|
||||
item={<InterestItem market={market} type='long' />}
|
||||
item={<InterestItem type='long' />}
|
||||
/>,
|
||||
<InfoItem
|
||||
key='openInterestShort'
|
||||
label='Open Interest (S)'
|
||||
item={<InterestItem market={market} type='short' />}
|
||||
/>,
|
||||
<InfoItem
|
||||
key='fundingRate'
|
||||
label='Funding rate'
|
||||
item={
|
||||
market ? (
|
||||
<FormattedNumber
|
||||
className='text-sm inline'
|
||||
amount={market.fundingRate.toNumber()}
|
||||
options={{ minDecimals: 6, maxDecimals: 6, suffix: '%' }}
|
||||
/>
|
||||
) : (
|
||||
<Loading />
|
||||
)
|
||||
}
|
||||
item={<InterestItem type='short' />}
|
||||
/>,
|
||||
<InfoItem key='fundingRate' label='Funding rate' item={<FundingRate />} />,
|
||||
]
|
||||
}, [assetPrice, market])
|
||||
|
||||
@ -81,22 +67,3 @@ function InfoItem(props: InfoItemProps) {
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
interface InterestItemProps {
|
||||
market: PerpsMarket | null
|
||||
type: 'long' | 'short'
|
||||
}
|
||||
function InterestItem(props: InterestItemProps) {
|
||||
if (!props.market) return <Loading />
|
||||
|
||||
return (
|
||||
<div className='flex gap-1 items-center'>
|
||||
<FormattedNumber
|
||||
className='text-sm inline'
|
||||
amount={props.market.openInterest[props.type].toNumber()}
|
||||
options={{ decimals: props.market.asset.decimals }}
|
||||
/>
|
||||
<AssetSymbol symbol={props.market.asset.symbol} />
|
||||
</div>
|
||||
)
|
||||
}
|
@ -11,15 +11,20 @@ export default function usePerpsMarket() {
|
||||
const { perpsAsset } = usePerpsAsset()
|
||||
const clients = useClients()
|
||||
|
||||
return useSWR(clients && perpsAsset && `chains/${chainConfig.id}/perps/${perpsAsset.denom}`, () =>
|
||||
getPerpsMarket(clients!, perpsAsset!),
|
||||
return useSWR(
|
||||
clients && perpsAsset && `chains/${chainConfig.id}/perps/${perpsAsset.denom}`,
|
||||
() => getPerpsMarket(clients!, perpsAsset!),
|
||||
{
|
||||
refreshInterval: 1000,
|
||||
dedupingInterval: 1000,
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
async function getPerpsMarket(clients: ContractClients, asset: Asset) {
|
||||
const denomState = await clients.perps.perpDenomState({ denom: asset.denom })
|
||||
return {
|
||||
fundingRate: BN(denomState.rate.abs),
|
||||
fundingRate: BN(denomState.rate as any),
|
||||
asset: asset,
|
||||
openInterest: {
|
||||
long: BN_ZERO,
|
||||
|
Loading…
Reference in New Issue
Block a user