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 React, { useMemo } from 'react'
|
||||||
|
|
||||||
import AssetSymbol from 'components/Asset/AssetSymbol'
|
|
||||||
import Card from 'components/Card'
|
import Card from 'components/Card'
|
||||||
import DisplayCurrency from 'components/DisplayCurrency'
|
import DisplayCurrency from 'components/DisplayCurrency'
|
||||||
import Divider from 'components/Divider'
|
import Divider from 'components/Divider'
|
||||||
import { FormattedNumber } from 'components/FormattedNumber'
|
|
||||||
import Loading from 'components/Loading'
|
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 Text from 'components/Text'
|
||||||
import usePerpsMarket from 'hooks/perps/usePerpsMarket'
|
import usePerpsMarket from 'hooks/perps/usePerpsMarket'
|
||||||
import usePrice from 'hooks/usePrice'
|
import usePrice from 'hooks/usePrice'
|
||||||
@ -25,28 +25,14 @@ export function PerpsInfo() {
|
|||||||
<InfoItem
|
<InfoItem
|
||||||
key='openInterestLong'
|
key='openInterestLong'
|
||||||
label='Open Interest (L)'
|
label='Open Interest (L)'
|
||||||
item={<InterestItem market={market} type='long' />}
|
item={<InterestItem type='long' />}
|
||||||
/>,
|
/>,
|
||||||
<InfoItem
|
<InfoItem
|
||||||
key='openInterestShort'
|
key='openInterestShort'
|
||||||
label='Open Interest (S)'
|
label='Open Interest (S)'
|
||||||
item={<InterestItem market={market} type='short' />}
|
item={<InterestItem 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 />
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>,
|
/>,
|
||||||
|
<InfoItem key='fundingRate' label='Funding rate' item={<FundingRate />} />,
|
||||||
]
|
]
|
||||||
}, [assetPrice, market])
|
}, [assetPrice, market])
|
||||||
|
|
||||||
@ -81,22 +67,3 @@ function InfoItem(props: InfoItemProps) {
|
|||||||
</div>
|
</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 { perpsAsset } = usePerpsAsset()
|
||||||
const clients = useClients()
|
const clients = useClients()
|
||||||
|
|
||||||
return useSWR(clients && perpsAsset && `chains/${chainConfig.id}/perps/${perpsAsset.denom}`, () =>
|
return useSWR(
|
||||||
getPerpsMarket(clients!, perpsAsset!),
|
clients && perpsAsset && `chains/${chainConfig.id}/perps/${perpsAsset.denom}`,
|
||||||
|
() => getPerpsMarket(clients!, perpsAsset!),
|
||||||
|
{
|
||||||
|
refreshInterval: 1000,
|
||||||
|
dedupingInterval: 1000,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getPerpsMarket(clients: ContractClients, asset: Asset) {
|
async function getPerpsMarket(clients: ContractClients, asset: Asset) {
|
||||||
const denomState = await clients.perps.perpDenomState({ denom: asset.denom })
|
const denomState = await clients.perps.perpDenomState({ denom: asset.denom })
|
||||||
return {
|
return {
|
||||||
fundingRate: BN(denomState.rate.abs),
|
fundingRate: BN(denomState.rate as any),
|
||||||
asset: asset,
|
asset: asset,
|
||||||
openInterest: {
|
openInterest: {
|
||||||
long: BN_ZERO,
|
long: BN_ZERO,
|
||||||
|
Loading…
Reference in New Issue
Block a user