Edit perps position (#728)
This commit is contained in:
parent
060a8b8797
commit
647a287a6b
@ -7,6 +7,7 @@ import { MarsIncentivesQueryClient } from 'types/generated/mars-incentives/MarsI
|
||||
import { MarsMockVaultQueryClient } from 'types/generated/mars-mock-vault/MarsMockVault.client'
|
||||
import { MarsOracleOsmosisQueryClient } from 'types/generated/mars-oracle-osmosis/MarsOracleOsmosis.client'
|
||||
import { MarsParamsQueryClient } from 'types/generated/mars-params/MarsParams.client'
|
||||
import { MarsPerpsQueryClient } from 'types/generated/mars-perps/MarsPerps.client'
|
||||
import { MarsRedBankQueryClient } from 'types/generated/mars-red-bank/MarsRedBank.client'
|
||||
import { MarsSwapperOsmosisQueryClient } from 'types/generated/mars-swapper-osmosis/MarsSwapperOsmosis.client'
|
||||
|
||||
@ -18,6 +19,7 @@ let _redBankQueryClient: Map<string, MarsRedBankQueryClient> = new Map()
|
||||
let _paramsQueryClient: Map<string, MarsParamsQueryClient> = new Map()
|
||||
let _incentivesQueryClient: Map<string, MarsIncentivesQueryClient> = new Map()
|
||||
let _swapperOsmosisClient: Map<string, MarsSwapperOsmosisQueryClient> = new Map()
|
||||
let _perpsClient: Map<string, MarsPerpsQueryClient> = new Map()
|
||||
let _ICNSQueryClient: Map<string, ICNSQueryClient> = new Map()
|
||||
|
||||
const getClient = async (rpc: string) => {
|
||||
@ -159,6 +161,22 @@ const getSwapperQueryClient = async (chainConfig: ChainConfig) => {
|
||||
}
|
||||
}
|
||||
|
||||
const getPerpsQueryClient = async (chainConfig: ChainConfig) => {
|
||||
try {
|
||||
const contract = chainConfig.contracts.perps
|
||||
const rpc = chainConfig.endpoints.rpc
|
||||
const key = rpc + contract
|
||||
if (!_perpsClient.get(key)) {
|
||||
const client = await getClient(rpc)
|
||||
_perpsClient.set(key, new MarsPerpsQueryClient(client, contract))
|
||||
}
|
||||
|
||||
return _perpsClient.get(key)!
|
||||
} catch (error) {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
const getICNSQueryClient = async (chainConfig: ChainConfig) => {
|
||||
try {
|
||||
const contract = chainConfig.contracts.params
|
||||
@ -186,4 +204,5 @@ export {
|
||||
getRedBankQueryClient,
|
||||
getSwapperQueryClient,
|
||||
getVaultQueryClient,
|
||||
getPerpsQueryClient,
|
||||
}
|
||||
|
10
src/api/perps/getOpeningFee.ts
Normal file
10
src/api/perps/getOpeningFee.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import { getPerpsQueryClient } from 'api/cosmwasm-client'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
|
||||
export default async function getOpeningFee(chainConfig: ChainConfig, denom: string, size: string) {
|
||||
const perpsClient = await getPerpsQueryClient(chainConfig)
|
||||
|
||||
return perpsClient
|
||||
.openingFee({ denom, size: size as any })
|
||||
.then((resp) => BNCoin.fromCoin(resp.fee))
|
||||
}
|
18
src/components/Asset/AssetAmount.tsx
Normal file
18
src/components/Asset/AssetAmount.tsx
Normal file
@ -0,0 +1,18 @@
|
||||
import { FormattedNumber } from 'components/FormattedNumber'
|
||||
|
||||
type Props = {
|
||||
asset: Asset
|
||||
amount: number
|
||||
}
|
||||
export default function AssetAmount(props: Props) {
|
||||
return (
|
||||
<FormattedNumber
|
||||
amount={props.amount}
|
||||
options={{
|
||||
decimals: props.asset.decimals,
|
||||
maxDecimals: props.asset.decimals,
|
||||
suffix: props.asset.symbol,
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
@ -13,7 +13,7 @@ export default function DropDownButton(props: Props) {
|
||||
const [isOpen, toggleIsOpen] = useToggle(false)
|
||||
return (
|
||||
<Tooltip
|
||||
content={<DropDown {...props} />}
|
||||
content={<DropDown closeMenu={() => toggleIsOpen(false)} {...props} />}
|
||||
type='info'
|
||||
placement='bottom'
|
||||
contentClassName='!bg-white/10 border border-white/20 backdrop-blur-xl !p-0'
|
||||
@ -34,26 +34,35 @@ export default function DropDownButton(props: Props) {
|
||||
|
||||
interface DropDownProps {
|
||||
items: DropDownItem[]
|
||||
closeMenu: () => void
|
||||
}
|
||||
|
||||
function DropDown(props: DropDownProps) {
|
||||
return (
|
||||
<div>
|
||||
{props.items.map((item) => (
|
||||
<DropDownItem key={item.text} {...item} />
|
||||
<DropDownItem key={item.text} item={item} closeMenu={props.closeMenu} />
|
||||
))}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function DropDownItem(props: DropDownItem) {
|
||||
interface DropDownItemProps {
|
||||
closeMenu: () => void
|
||||
item: DropDownItem
|
||||
}
|
||||
|
||||
function DropDownItem(props: DropDownItemProps) {
|
||||
return (
|
||||
<button
|
||||
onClick={props.onClick}
|
||||
onClick={() => {
|
||||
props.item.onClick()
|
||||
props.closeMenu()
|
||||
}}
|
||||
className=' px-4 py-3 flex gap-2 items-center hover:bg-white/5 w-full [&:not(:last-child)]:border-b border-white/10'
|
||||
>
|
||||
<div className='flex justify-center w-5 h-5'>{props.icon}</div>
|
||||
<Text size='sm'>{props.text}</Text>
|
||||
<div className='flex justify-center w-5 h-5'>{props.item.icon}</div>
|
||||
<Text size='sm'>{props.item.text}</Text>
|
||||
</button>
|
||||
)
|
||||
}
|
||||
|
@ -1,9 +1,3 @@
|
||||
<svg viewBox="0 0 13 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M1.8335 6.00065H11.1668M11.1668 6.00065L6.50016 1.33398M11.1668 6.00065L6.50016 10.6673"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.33337 8.00065H12.6667M12.6667 8.00065L8.00004 3.33398M12.6667 8.00065L8.00004 12.6673" stroke="currentColor" stroke-width="0.666667" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 291 B After Width: | Height: | Size: 299 B |
@ -1,10 +1,13 @@
|
||||
import React, { useMemo } from 'react'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
|
||||
import DropDownButton from 'components/Button/DropDownButton'
|
||||
import { Cross, Edit } from 'components/Icons'
|
||||
import { PerpPositionRow } from 'components/Perps/BalancesTable/usePerpsBalancesData'
|
||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||
import useStore from 'store'
|
||||
import { SearchParams } from 'types/enums/searchParams'
|
||||
import { getSearchParamsObject } from 'utils/route'
|
||||
|
||||
export const MANAGE_META = { id: 'manage', header: 'Manage' }
|
||||
|
||||
@ -14,6 +17,7 @@ interface Props {
|
||||
|
||||
export default function Manage(props: Props) {
|
||||
const currentAccount = useCurrentAccount()
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
|
||||
const closePerpPosition = useStore((s) => s.closePerpPosition)
|
||||
const ITEMS: DropDownItem[] = useMemo(
|
||||
@ -21,7 +25,14 @@ export default function Manage(props: Props) {
|
||||
{
|
||||
icon: <Edit />,
|
||||
text: 'Edit Position Size',
|
||||
onClick: () => {},
|
||||
onClick: () => {
|
||||
const params = getSearchParamsObject(searchParams)
|
||||
setSearchParams({
|
||||
...params,
|
||||
[SearchParams.PERPS_MARKET]: props.perpPosition.asset.denom,
|
||||
[SearchParams.PERPS_MANAGE]: 'true',
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: <Cross width={16} />,
|
||||
@ -35,7 +46,13 @@ export default function Manage(props: Props) {
|
||||
},
|
||||
},
|
||||
],
|
||||
[closePerpPosition, currentAccount, props.perpPosition.asset.denom],
|
||||
[
|
||||
closePerpPosition,
|
||||
currentAccount,
|
||||
props.perpPosition.asset.denom,
|
||||
searchParams,
|
||||
setSearchParams,
|
||||
],
|
||||
)
|
||||
|
||||
return (
|
||||
|
@ -14,7 +14,7 @@ export default function TradeDirection(props: Props) {
|
||||
<Text
|
||||
size='xs'
|
||||
className={classNames(
|
||||
'capitalize px-1 py-0.5 rounded-sm inline',
|
||||
'capitalize px-1 py-0.5 rounded-sm inline-block',
|
||||
tradeDirection === 'short' && 'text-error bg-error/20',
|
||||
tradeDirection === 'long' && 'text-success bg-success/20',
|
||||
)}
|
||||
|
19
src/components/Perps/Module/OpeningFee.tsx
Normal file
19
src/components/Perps/Module/OpeningFee.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
|
||||
import { CircularProgress } from 'components/CircularProgress'
|
||||
import DisplayCurrency from 'components/DisplayCurrency'
|
||||
import useOpeningFee from 'hooks/perps/useOpeningFee'
|
||||
|
||||
type Props = {
|
||||
denom: string
|
||||
amount: BigNumber
|
||||
}
|
||||
|
||||
export default function OpeningFee(props: Props) {
|
||||
const { data: openingFee, isLoading } = useOpeningFee(props.denom, props.amount)
|
||||
|
||||
if (isLoading) return <CircularProgress className='h-full' size={12} />
|
||||
if (props.amount.isZero() || !openingFee) return '-'
|
||||
|
||||
return <DisplayCurrency coin={openingFee} />
|
||||
}
|
74
src/components/Perps/Module/PerpsManageModule/index.tsx
Normal file
74
src/components/Perps/Module/PerpsManageModule/index.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
import classNames from 'classnames'
|
||||
import { useState } from 'react'
|
||||
|
||||
import { Cross } from 'components/Icons'
|
||||
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 RangeInput from 'components/RangeInput'
|
||||
import { Spacer } from 'components/Spacer'
|
||||
import Text from 'components/Text'
|
||||
import AssetAmountInput from 'components/Trade/TradeModule/SwapForm/AssetAmountInput'
|
||||
import { TradeDirectionSelector } from 'components/TradeDirectionSelector'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
export function PerpsManageModule() {
|
||||
const [tradeDirection, setTradeDirection] = useState<TradeDirection | null>(null)
|
||||
const [amount, setAmount] = useState<BigNumber | null>(null)
|
||||
|
||||
const {
|
||||
closeManagePerpModule,
|
||||
previousAmount,
|
||||
previousTradeDirection,
|
||||
previousLeverage,
|
||||
leverage,
|
||||
asset,
|
||||
} = usePerpsManageModule(amount)
|
||||
|
||||
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(100000)} // TODO: Implement max calculation
|
||||
amount={amount ?? previousAmount}
|
||||
setAmount={setAmount}
|
||||
asset={asset}
|
||||
maxButtonLabel='Max:'
|
||||
disabled={false}
|
||||
/>
|
||||
<Or />
|
||||
<Text size='sm'>Position Leverage</Text>
|
||||
<RangeInput max={0} value={0} onChange={() => {}} />
|
||||
<LeverageButtons />
|
||||
<Spacer />
|
||||
<PerpsSummary
|
||||
changeTradeDirection
|
||||
amount={amount ?? previousAmount}
|
||||
tradeDirection={tradeDirection ?? previousTradeDirection}
|
||||
asset={asset}
|
||||
leverage={leverage}
|
||||
previousAmount={previousAmount}
|
||||
previousTradeDirection={previousTradeDirection}
|
||||
previousLeverage={previousLeverage}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useSearchParams } from 'react-router-dom'
|
||||
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useAllAssets from 'hooks/assets/useAllAssets'
|
||||
import usePerpPosition from 'hooks/perps/usePerpPosition'
|
||||
import usePerpsAsset from 'hooks/perps/usePerpsAsset'
|
||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||
import usePrice from 'hooks/usePrice'
|
||||
import usePrices from 'hooks/usePrices'
|
||||
import { SearchParams } from 'types/enums/searchParams'
|
||||
import { getAccountNetValue } from 'utils/accounts'
|
||||
import { demagnify } from 'utils/formatters'
|
||||
import { getSearchParamsObject } from 'utils/route'
|
||||
|
||||
export default function usePerpsManageModule(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 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?.size ?? BN_ZERO, [perpPosition?.size])
|
||||
const previousTradeDirection = useMemo(
|
||||
() => perpPosition?.tradeDirection || 'long',
|
||||
[perpPosition?.tradeDirection],
|
||||
)
|
||||
|
||||
const previousLeverage = useMemo(
|
||||
() =>
|
||||
price.times(demagnify(previousAmount, perpsAsset)).div(accountNetValue).plus(1).toNumber(),
|
||||
[accountNetValue, perpsAsset, previousAmount, price],
|
||||
)
|
||||
|
||||
const leverage = useMemo(
|
||||
() =>
|
||||
price
|
||||
.times(demagnify(amount ?? BN_ZERO, perpsAsset))
|
||||
.div(accountNetValue)
|
||||
.plus(1)
|
||||
.toNumber(),
|
||||
[accountNetValue, amount, perpsAsset, price],
|
||||
)
|
||||
|
||||
return {
|
||||
closeManagePerpModule,
|
||||
previousAmount,
|
||||
previousTradeDirection,
|
||||
previousLeverage,
|
||||
leverage,
|
||||
asset: perpsAsset,
|
||||
}
|
||||
}
|
@ -20,6 +20,7 @@ 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 [amount, setAmount] = useState<BigNumber>(BN_ZERO)
|
||||
|
||||
@ -48,7 +49,12 @@ export function PerpsModule() {
|
||||
<RangeInput max={0} value={0} onChange={() => {}} />
|
||||
<LeverageButtons />
|
||||
<Spacer />
|
||||
<PerpsSummary amount={amount} tradeDirection={tradeDirection} asset={perpsAsset} />
|
||||
<PerpsSummary
|
||||
amount={amount}
|
||||
tradeDirection={tradeDirection}
|
||||
asset={perpsAsset}
|
||||
leverage={leverage}
|
||||
/>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
@ -1,16 +1,27 @@
|
||||
import { useCallback } from 'react'
|
||||
import classNames from 'classnames'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
|
||||
import AssetAmount from 'components/Asset/AssetAmount'
|
||||
import ActionButton from 'components/Button/ActionButton'
|
||||
import { ArrowRight } from 'components/Icons'
|
||||
import TradeDirection from 'components/Perps/BalancesTable/Columns/TradeDirection'
|
||||
import OpeningFee from 'components/Perps/Module/OpeningFee'
|
||||
import SummaryLine from 'components/SummaryLine'
|
||||
import Text from 'components/Text'
|
||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||
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
|
||||
changeTradeDirection?: boolean
|
||||
previousAmount?: BigNumber
|
||||
previousTradeDirection?: 'long' | 'short'
|
||||
previousLeverage?: number
|
||||
}
|
||||
|
||||
export default function PerpsSummary(props: Props) {
|
||||
@ -28,20 +39,85 @@ export default function PerpsSummary(props: Props) {
|
||||
})
|
||||
}, [currentAccount, openPerpPosition, props.amount, props.asset.denom, props.tradeDirection])
|
||||
|
||||
const disabled = useMemo(
|
||||
() =>
|
||||
(props.previousAmount && props.previousAmount.isEqualTo(props.amount)) ||
|
||||
props.amount.isZero(),
|
||||
[props.amount, props.previousAmount],
|
||||
)
|
||||
|
||||
return (
|
||||
<div className='border border-white/10 rounded-sm bg-white/5'>
|
||||
<ManageSummary {...props} />
|
||||
<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'>Something</SummaryLine>
|
||||
<SummaryLine label='Fees'>Something</SummaryLine>
|
||||
<SummaryLine label='Total'>Something</SummaryLine>
|
||||
<SummaryLine label='Expected Price'>-</SummaryLine>
|
||||
<SummaryLine label='Fees'>
|
||||
<OpeningFee denom={props.asset.denom} amount={props.amount} />
|
||||
</SummaryLine>
|
||||
<SummaryLine label='Total'>-</SummaryLine>
|
||||
</div>
|
||||
<ActionButton onClick={onConfirm} className='w-full py-2.5'>
|
||||
<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) {
|
||||
const showTradeDirection =
|
||||
props.previousTradeDirection && props.previousTradeDirection !== props.tradeDirection
|
||||
const showAmount =
|
||||
props.previousAmount && props.amount && !props.previousAmount.isEqualTo(props.amount)
|
||||
const showLeverage =
|
||||
props.previousLeverage &&
|
||||
props.leverage &&
|
||||
props.previousLeverage.toFixed(2) !== props.leverage.toFixed(2)
|
||||
|
||||
if (!showTradeDirection && !showLeverage && !showAmount) 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>
|
||||
|
||||
{showTradeDirection && props.previousTradeDirection && (
|
||||
<SummaryLine label='Side' contentClassName='flex gap-1'>
|
||||
<TradeDirection tradeDirection={props.previousTradeDirection} />
|
||||
<ArrowRight width={16} />
|
||||
<TradeDirection tradeDirection={props.tradeDirection} />
|
||||
</SummaryLine>
|
||||
)}
|
||||
|
||||
{showAmount && props.previousAmount && (
|
||||
<SummaryLine label='Size' contentClassName='flex gap-1'>
|
||||
<AssetAmount asset={props.asset} amount={props.previousAmount.toNumber()} />
|
||||
<ArrowRight
|
||||
width={16}
|
||||
className={classNames(
|
||||
props.previousAmount.isGreaterThan(props.amount) ? 'text-error' : 'text-success',
|
||||
)}
|
||||
/>
|
||||
<AssetAmount asset={props.asset} amount={props.amount.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>
|
||||
)
|
||||
}
|
||||
|
@ -50,6 +50,8 @@ export function PerpsInfo() {
|
||||
]
|
||||
}, [assetPrice, market])
|
||||
|
||||
if (!market) return null
|
||||
|
||||
return (
|
||||
<Card contentClassName='bg-white/10 py-3.5 px-4'>
|
||||
<div className='flex gap-4 items-center'>
|
||||
|
@ -6,13 +6,14 @@ const infoLineClasses = 'flex flex-row justify-between flex-1 mb-1 text-xs text-
|
||||
interface SummaryLineProps {
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
contentClassName?: string
|
||||
label: string
|
||||
}
|
||||
export default function SummaryLine(props: SummaryLineProps) {
|
||||
return (
|
||||
<div className={classNames(infoLineClasses, props.className)}>
|
||||
<span className='opacity-40'>{props.label}</span>
|
||||
<span>{props.children}</span>
|
||||
<span className={props.contentClassName}>{props.children}</span>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
16
src/hooks/perps/useOpeningFee.ts
Normal file
16
src/hooks/perps/useOpeningFee.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import BigNumber from 'bignumber.js'
|
||||
import useSWR from 'swr'
|
||||
|
||||
import getOpeningFee from 'api/perps/getOpeningFee'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
import useDebounce from 'hooks/useDebounce'
|
||||
|
||||
export default function useOpeningFee(denom: string, amount: BigNumber) {
|
||||
const chainConfig = useChainConfig()
|
||||
const debouncedAmount = useDebounce<string>(amount.toString(), 500)
|
||||
const enabled = !amount.isZero()
|
||||
|
||||
return useSWR(enabled && `${chainConfig.id}/perps/${denom}/openingFee/${debouncedAmount}`, () =>
|
||||
getOpeningFee(chainConfig, denom, amount.toString()),
|
||||
)
|
||||
}
|
11
src/hooks/perps/usePerpPosition.ts
Normal file
11
src/hooks/perps/usePerpPosition.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { byDenom } from 'utils/array'
|
||||
|
||||
import useCurrentAccount from '../useCurrentAccount'
|
||||
|
||||
export default function usePerpPosition(denom: string): PerpsPosition | undefined {
|
||||
const account = useCurrentAccount()
|
||||
|
||||
return useMemo(() => account?.perps.find(byDenom(denom)), [account?.perps, denom])
|
||||
}
|
@ -6,10 +6,11 @@ import { LocalStorageKeys } from 'constants/localStorageKeys'
|
||||
import usePerpsEnabledAssets from 'hooks/assets/usePerpsEnabledAssets'
|
||||
import useLocalStorage from 'hooks/localStorage/useLocalStorage'
|
||||
import useChainConfig from 'hooks/useChainConfig'
|
||||
import { getSearchParamsObject } from 'utils/route'
|
||||
|
||||
export default function usePerpsAsset() {
|
||||
const chainConfig = useChainConfig()
|
||||
const [searchParams] = useSearchParams()
|
||||
const [searchParams, setSearchParams] = useSearchParams()
|
||||
const perpsAssets = usePerpsEnabledAssets()
|
||||
const perpsAssetInParams = searchParams.get('perpsMarket')
|
||||
const [perpsAssetInLocalStorage, setPerpsAssetInLocalStorage] = useLocalStorage<
|
||||
@ -18,9 +19,12 @@ export default function usePerpsAsset() {
|
||||
|
||||
const updatePerpsAsset = useCallback(
|
||||
(denom: string) => {
|
||||
const params = getSearchParamsObject(searchParams)
|
||||
params.perpsMarket = denom
|
||||
setSearchParams(params)
|
||||
setPerpsAssetInLocalStorage(denom)
|
||||
},
|
||||
[setPerpsAssetInLocalStorage],
|
||||
[searchParams, setPerpsAssetInLocalStorage, setSearchParams],
|
||||
)
|
||||
|
||||
return {
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import useAccounts from 'hooks/accounts/useAccounts'
|
||||
import useAccountId from 'hooks/useAccountId'
|
||||
|
||||
@ -5,5 +7,5 @@ export default function useCurrentAccount(): Account | undefined {
|
||||
const accountId = useAccountId()
|
||||
const { data: accounts } = useAccounts('default', undefined, false)
|
||||
|
||||
return accounts?.find((account) => account.id === accountId)
|
||||
return useMemo(() => accounts?.find((account) => account.id === accountId), [accountId, accounts])
|
||||
}
|
||||
|
17
src/hooks/useDebounce.ts
Normal file
17
src/hooks/useDebounce.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
export default function useDebounce<T>(value: T, delay: number) {
|
||||
const [debouncedValue, setDebouncedValue] = useState(value)
|
||||
|
||||
useEffect(() => {
|
||||
const handler = setTimeout(() => {
|
||||
setDebouncedValue(value)
|
||||
}, delay)
|
||||
|
||||
return () => {
|
||||
clearTimeout(handler)
|
||||
}
|
||||
}, [value, delay])
|
||||
|
||||
return debouncedValue
|
||||
}
|
@ -1,14 +1,22 @@
|
||||
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'>
|
||||
<PerpsModule />
|
||||
<div className='h-full w-[376px] row-span-3 relative'>
|
||||
{isManagingPosition ? <PerpsManageModule /> : <PerpsModule />}
|
||||
</div>
|
||||
<PerpsChart />
|
||||
<PerpsPositions />
|
||||
|
5
src/types/enums/searchParams.ts
Normal file
5
src/types/enums/searchParams.ts
Normal file
@ -0,0 +1,5 @@
|
||||
export enum SearchParams {
|
||||
ACCOUNT_ID = 'accountId',
|
||||
PERPS_MARKET = 'perpsMarket',
|
||||
PERPS_MANAGE = 'perpsManage',
|
||||
}
|
@ -1,275 +0,0 @@
|
||||
// @ts-nocheck
|
||||
/**
|
||||
* This file was automatically generated by @cosmwasm/ts-codegen@0.33.0.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
||||
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
|
||||
*/
|
||||
|
||||
import { MsgExecuteContractEncodeObject } from '@cosmjs/cosmwasm-stargate'
|
||||
import { MsgExecuteContract } from 'cosmjs-types/cosmwasm/wasm/v1/tx'
|
||||
import { toUtf8 } from '@cosmjs/encoding'
|
||||
import {
|
||||
HealthContractBaseForString,
|
||||
IncentivesUnchecked,
|
||||
Decimal,
|
||||
Uint128,
|
||||
OracleBaseForString,
|
||||
ParamsBaseForString,
|
||||
RedBankUnchecked,
|
||||
SwapperBaseForString,
|
||||
ZapperBaseForString,
|
||||
InstantiateMsg,
|
||||
ExecuteMsg,
|
||||
AccountKind,
|
||||
Action,
|
||||
ActionAmount,
|
||||
LiquidateRequestForVaultBaseForString,
|
||||
VaultPositionType,
|
||||
AccountNftBaseForString,
|
||||
OwnerUpdate,
|
||||
CallbackMsg,
|
||||
Addr,
|
||||
HealthState,
|
||||
LiquidateRequestForVaultBaseForAddr,
|
||||
ChangeExpected,
|
||||
Coin,
|
||||
ActionCoin,
|
||||
VaultBaseForString,
|
||||
ConfigUpdates,
|
||||
NftConfigUpdates,
|
||||
VaultBaseForAddr,
|
||||
QueryMsg,
|
||||
VaultPositionAmount,
|
||||
VaultAmount,
|
||||
VaultAmount1,
|
||||
UnlockingPositions,
|
||||
VaultPosition,
|
||||
LockingVaultAmount,
|
||||
VaultUnlockingPosition,
|
||||
ArrayOfAccount,
|
||||
Account,
|
||||
ArrayOfCoinBalanceResponseItem,
|
||||
CoinBalanceResponseItem,
|
||||
ArrayOfSharesResponseItem,
|
||||
SharesResponseItem,
|
||||
ArrayOfDebtShares,
|
||||
DebtShares,
|
||||
ArrayOfVaultPositionResponseItem,
|
||||
VaultPositionResponseItem,
|
||||
ConfigResponse,
|
||||
OwnerResponse,
|
||||
RewardsCollector,
|
||||
ArrayOfCoin,
|
||||
Positions,
|
||||
DebtAmount,
|
||||
VaultPositionValue,
|
||||
CoinValue,
|
||||
VaultUtilizationResponse,
|
||||
} from './MarsCreditManager.types'
|
||||
export interface MarsCreditManagerMessage {
|
||||
contractAddress: string
|
||||
sender: string
|
||||
createCreditAccount: (_funds?: Coin[]) => MsgExecuteContractEncodeObject
|
||||
updateCreditAccount: (
|
||||
{
|
||||
accountId,
|
||||
actions,
|
||||
}: {
|
||||
accountId: string
|
||||
actions: Action[]
|
||||
},
|
||||
_funds?: Coin[],
|
||||
) => MsgExecuteContractEncodeObject
|
||||
repayFromWallet: (
|
||||
{
|
||||
accountId,
|
||||
}: {
|
||||
accountId: string
|
||||
},
|
||||
_funds?: Coin[],
|
||||
) => MsgExecuteContractEncodeObject
|
||||
updateConfig: (
|
||||
{
|
||||
updates,
|
||||
}: {
|
||||
updates: ConfigUpdates
|
||||
},
|
||||
_funds?: Coin[],
|
||||
) => MsgExecuteContractEncodeObject
|
||||
updateOwner: (ownerUpdate: OwnerUpdate, _funds?: Coin[]) => MsgExecuteContractEncodeObject
|
||||
updateNftConfig: (
|
||||
{
|
||||
config,
|
||||
ownership,
|
||||
}: {
|
||||
config?: NftConfigUpdates
|
||||
ownership?: Action
|
||||
},
|
||||
_funds?: Coin[],
|
||||
) => MsgExecuteContractEncodeObject
|
||||
callback: (callbackMsg: CallbackMsg, _funds?: Coin[]) => MsgExecuteContractEncodeObject
|
||||
}
|
||||
export class MarsCreditManagerMessageComposer implements MarsCreditManagerMessage {
|
||||
sender: string
|
||||
contractAddress: string
|
||||
|
||||
constructor(sender: string, contractAddress: string) {
|
||||
this.sender = sender
|
||||
this.contractAddress = contractAddress
|
||||
this.createCreditAccount = this.createCreditAccount.bind(this)
|
||||
this.updateCreditAccount = this.updateCreditAccount.bind(this)
|
||||
this.repayFromWallet = this.repayFromWallet.bind(this)
|
||||
this.updateConfig = this.updateConfig.bind(this)
|
||||
this.updateOwner = this.updateOwner.bind(this)
|
||||
this.updateNftConfig = this.updateNftConfig.bind(this)
|
||||
this.callback = this.callback.bind(this)
|
||||
}
|
||||
|
||||
createCreditAccount = (_funds?: Coin[]): MsgExecuteContractEncodeObject => {
|
||||
return {
|
||||
typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract',
|
||||
value: MsgExecuteContract.fromPartial({
|
||||
sender: this.sender,
|
||||
contract: this.contractAddress,
|
||||
msg: toUtf8(
|
||||
JSON.stringify({
|
||||
create_credit_account: {},
|
||||
}),
|
||||
),
|
||||
funds: _funds,
|
||||
}),
|
||||
}
|
||||
}
|
||||
updateCreditAccount = (
|
||||
{
|
||||
accountId,
|
||||
actions,
|
||||
}: {
|
||||
accountId: string
|
||||
actions: Action[]
|
||||
},
|
||||
_funds?: Coin[],
|
||||
): MsgExecuteContractEncodeObject => {
|
||||
return {
|
||||
typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract',
|
||||
value: MsgExecuteContract.fromPartial({
|
||||
sender: this.sender,
|
||||
contract: this.contractAddress,
|
||||
msg: toUtf8(
|
||||
JSON.stringify({
|
||||
update_credit_account: {
|
||||
account_id: accountId,
|
||||
actions,
|
||||
},
|
||||
}),
|
||||
),
|
||||
funds: _funds,
|
||||
}),
|
||||
}
|
||||
}
|
||||
repayFromWallet = (
|
||||
{
|
||||
accountId,
|
||||
}: {
|
||||
accountId: string
|
||||
},
|
||||
_funds?: Coin[],
|
||||
): MsgExecuteContractEncodeObject => {
|
||||
return {
|
||||
typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract',
|
||||
value: MsgExecuteContract.fromPartial({
|
||||
sender: this.sender,
|
||||
contract: this.contractAddress,
|
||||
msg: toUtf8(
|
||||
JSON.stringify({
|
||||
repay_from_wallet: {
|
||||
account_id: accountId,
|
||||
},
|
||||
}),
|
||||
),
|
||||
funds: _funds,
|
||||
}),
|
||||
}
|
||||
}
|
||||
updateConfig = (
|
||||
{
|
||||
updates,
|
||||
}: {
|
||||
updates: ConfigUpdates
|
||||
},
|
||||
_funds?: Coin[],
|
||||
): MsgExecuteContractEncodeObject => {
|
||||
return {
|
||||
typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract',
|
||||
value: MsgExecuteContract.fromPartial({
|
||||
sender: this.sender,
|
||||
contract: this.contractAddress,
|
||||
msg: toUtf8(
|
||||
JSON.stringify({
|
||||
update_config: {
|
||||
updates,
|
||||
},
|
||||
}),
|
||||
),
|
||||
funds: _funds,
|
||||
}),
|
||||
}
|
||||
}
|
||||
updateOwner = (ownerUpdate: OwnerUpdate, _funds?: Coin[]): MsgExecuteContractEncodeObject => {
|
||||
return {
|
||||
typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract',
|
||||
value: MsgExecuteContract.fromPartial({
|
||||
sender: this.sender,
|
||||
contract: this.contractAddress,
|
||||
msg: toUtf8(
|
||||
JSON.stringify({
|
||||
update_owner: ownerUpdate,
|
||||
}),
|
||||
),
|
||||
funds: _funds,
|
||||
}),
|
||||
}
|
||||
}
|
||||
updateNftConfig = (
|
||||
{
|
||||
config,
|
||||
ownership,
|
||||
}: {
|
||||
config?: NftConfigUpdates
|
||||
ownership?: Action
|
||||
},
|
||||
_funds?: Coin[],
|
||||
): MsgExecuteContractEncodeObject => {
|
||||
return {
|
||||
typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract',
|
||||
value: MsgExecuteContract.fromPartial({
|
||||
sender: this.sender,
|
||||
contract: this.contractAddress,
|
||||
msg: toUtf8(
|
||||
JSON.stringify({
|
||||
update_nft_config: {
|
||||
config,
|
||||
ownership,
|
||||
},
|
||||
}),
|
||||
),
|
||||
funds: _funds,
|
||||
}),
|
||||
}
|
||||
}
|
||||
callback = (callbackMsg: CallbackMsg, _funds?: Coin[]): MsgExecuteContractEncodeObject => {
|
||||
return {
|
||||
typeUrl: '/cosmwasm.wasm.v1.MsgExecuteContract',
|
||||
value: MsgExecuteContract.fromPartial({
|
||||
sender: this.sender,
|
||||
contract: this.contractAddress,
|
||||
msg: toUtf8(
|
||||
JSON.stringify({
|
||||
callback: callbackMsg,
|
||||
}),
|
||||
),
|
||||
funds: _funds,
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
@ -8,12 +8,13 @@
|
||||
import { CosmWasmClient, SigningCosmWasmClient, ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { StdFee } from '@cosmjs/amino'
|
||||
import {
|
||||
Decimal,
|
||||
Uint128,
|
||||
OracleBaseForString,
|
||||
ParamsBaseForString,
|
||||
InstantiateMsg,
|
||||
ExecuteMsg,
|
||||
OwnerUpdate,
|
||||
Decimal,
|
||||
SignedDecimal,
|
||||
QueryMsg,
|
||||
ConfigForString,
|
||||
@ -22,13 +23,17 @@ import {
|
||||
ArrayOfDenomStateResponse,
|
||||
DepositResponse,
|
||||
ArrayOfDepositResponse,
|
||||
TradingFee,
|
||||
Coin,
|
||||
OwnerResponse,
|
||||
PerpDenomState,
|
||||
PnlValues,
|
||||
DenomPnlValues,
|
||||
PnL,
|
||||
PositionResponse,
|
||||
PerpPosition,
|
||||
Coin,
|
||||
PositionPnl,
|
||||
PnlCoins,
|
||||
PnlValues,
|
||||
ArrayOfPositionResponse,
|
||||
PositionsByAccountResponse,
|
||||
ArrayOfUnlockState,
|
||||
@ -74,6 +79,7 @@ export interface MarsPerpsReadOnlyInterface {
|
||||
}) => Promise<ArrayOfPositionResponse>
|
||||
positionsByAccount: ({ accountId }: { accountId: string }) => Promise<PositionsByAccountResponse>
|
||||
totalPnl: () => Promise<SignedDecimal>
|
||||
openingFee: ({ denom, size }: { denom: string; size: SignedDecimal }) => Promise<TradingFee>
|
||||
}
|
||||
export class MarsPerpsQueryClient implements MarsPerpsReadOnlyInterface {
|
||||
client: CosmWasmClient
|
||||
@ -95,6 +101,7 @@ export class MarsPerpsQueryClient implements MarsPerpsReadOnlyInterface {
|
||||
this.positions = this.positions.bind(this)
|
||||
this.positionsByAccount = this.positionsByAccount.bind(this)
|
||||
this.totalPnl = this.totalPnl.bind(this)
|
||||
this.openingFee = this.openingFee.bind(this)
|
||||
}
|
||||
|
||||
owner = async (): Promise<OwnerResponse> => {
|
||||
@ -212,6 +219,20 @@ export class MarsPerpsQueryClient implements MarsPerpsReadOnlyInterface {
|
||||
total_pnl: {},
|
||||
})
|
||||
}
|
||||
openingFee = async ({
|
||||
denom,
|
||||
size,
|
||||
}: {
|
||||
denom: string
|
||||
size: SignedDecimal
|
||||
}): Promise<TradingFee> => {
|
||||
return this.client.queryContractSmart(this.contractAddress, {
|
||||
opening_fee: {
|
||||
denom,
|
||||
size,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
export interface MarsPerpsInterface extends MarsPerpsReadOnlyInterface {
|
||||
contractAddress: string
|
||||
|
@ -9,12 +9,13 @@ import { UseQueryOptions, useQuery, useMutation, UseMutationOptions } from '@tan
|
||||
import { ExecuteResult } from '@cosmjs/cosmwasm-stargate'
|
||||
import { StdFee } from '@cosmjs/amino'
|
||||
import {
|
||||
Decimal,
|
||||
Uint128,
|
||||
OracleBaseForString,
|
||||
ParamsBaseForString,
|
||||
InstantiateMsg,
|
||||
ExecuteMsg,
|
||||
OwnerUpdate,
|
||||
Decimal,
|
||||
SignedDecimal,
|
||||
QueryMsg,
|
||||
ConfigForString,
|
||||
@ -23,13 +24,17 @@ import {
|
||||
ArrayOfDenomStateResponse,
|
||||
DepositResponse,
|
||||
ArrayOfDepositResponse,
|
||||
TradingFee,
|
||||
Coin,
|
||||
OwnerResponse,
|
||||
PerpDenomState,
|
||||
PnlValues,
|
||||
DenomPnlValues,
|
||||
PnL,
|
||||
PositionResponse,
|
||||
PerpPosition,
|
||||
Coin,
|
||||
PositionPnl,
|
||||
PnlCoins,
|
||||
PnlValues,
|
||||
ArrayOfPositionResponse,
|
||||
PositionsByAccountResponse,
|
||||
ArrayOfUnlockState,
|
||||
@ -75,6 +80,8 @@ export const marsPerpsQueryKeys = {
|
||||
] as const,
|
||||
totalPnl: (contractAddress: string | undefined, args?: Record<string, unknown>) =>
|
||||
[{ ...marsPerpsQueryKeys.address(contractAddress)[0], method: 'total_pnl', args }] as const,
|
||||
openingFee: (contractAddress: string | undefined, args?: Record<string, unknown>) =>
|
||||
[{ ...marsPerpsQueryKeys.address(contractAddress)[0], method: 'opening_fee', args }] as const,
|
||||
}
|
||||
export interface MarsPerpsReactQuery<TResponse, TData = TResponse> {
|
||||
client: MarsPerpsQueryClient | undefined
|
||||
@ -85,6 +92,29 @@ export interface MarsPerpsReactQuery<TResponse, TData = TResponse> {
|
||||
initialData?: undefined
|
||||
}
|
||||
}
|
||||
export interface MarsPerpsOpeningFeeQuery<TData> extends MarsPerpsReactQuery<TradingFee, TData> {
|
||||
args: {
|
||||
denom: string
|
||||
size: SignedDecimal
|
||||
}
|
||||
}
|
||||
export function useMarsPerpsOpeningFeeQuery<TData = TradingFee>({
|
||||
client,
|
||||
args,
|
||||
options,
|
||||
}: MarsPerpsOpeningFeeQuery<TData>) {
|
||||
return useQuery<TradingFee, Error, TData>(
|
||||
marsPerpsQueryKeys.openingFee(client?.contractAddress, args),
|
||||
() =>
|
||||
client
|
||||
? client.openingFee({
|
||||
denom: args.denom,
|
||||
size: args.size,
|
||||
})
|
||||
: Promise.reject(new Error('Invalid client')),
|
||||
{ ...options, enabled: !!client && (options?.enabled != undefined ? options.enabled : true) },
|
||||
)
|
||||
}
|
||||
export interface MarsPerpsTotalPnlQuery<TData> extends MarsPerpsReactQuery<SignedDecimal, TData> {}
|
||||
export function useMarsPerpsTotalPnlQuery<TData = SignedDecimal>({
|
||||
client,
|
||||
|
@ -5,14 +5,20 @@
|
||||
* and run the @cosmwasm/ts-codegen generate command to regenerate this file.
|
||||
*/
|
||||
|
||||
export type Decimal = string
|
||||
export type Uint128 = string
|
||||
export type OracleBaseForString = string
|
||||
export type ParamsBaseForString = string
|
||||
export interface InstantiateMsg {
|
||||
base_denom: string
|
||||
closing_fee_rate: Decimal
|
||||
cooldown_period: number
|
||||
credit_manager: string
|
||||
min_position_value: Uint128
|
||||
max_position_in_base_denom?: Uint128 | null
|
||||
min_position_in_base_denom: Uint128
|
||||
opening_fee_rate: Decimal
|
||||
oracle: OracleBaseForString
|
||||
params: ParamsBaseForString
|
||||
}
|
||||
export type ExecuteMsg =
|
||||
| {
|
||||
@ -74,7 +80,6 @@ export type OwnerUpdate =
|
||||
}
|
||||
}
|
||||
| 'clear_emergency_owner'
|
||||
export type Decimal = string
|
||||
export interface SignedDecimal {
|
||||
abs: Decimal
|
||||
negative: boolean
|
||||
@ -142,12 +147,22 @@ export type QueryMsg =
|
||||
| {
|
||||
total_pnl: {}
|
||||
}
|
||||
| {
|
||||
opening_fee: {
|
||||
denom: string
|
||||
size: SignedDecimal
|
||||
}
|
||||
}
|
||||
export interface ConfigForString {
|
||||
base_denom: string
|
||||
closing_fee_rate: Decimal
|
||||
cooldown_period: number
|
||||
credit_manager: string
|
||||
min_position_value: Uint128
|
||||
max_position_in_base_denom?: Uint128 | null
|
||||
min_position_in_base_denom: Uint128
|
||||
opening_fee_rate: Decimal
|
||||
oracle: OracleBaseForString
|
||||
params: ParamsBaseForString
|
||||
}
|
||||
export interface DenomStateResponse {
|
||||
denom: string
|
||||
@ -155,14 +170,11 @@ export interface DenomStateResponse {
|
||||
funding: Funding
|
||||
last_updated: number
|
||||
total_cost_base: SignedDecimal
|
||||
total_size: SignedDecimal
|
||||
}
|
||||
export interface Funding {
|
||||
accumulated_size_weighted_by_index: SignedDecimal
|
||||
constant_factor: SignedDecimal
|
||||
index: SignedDecimal
|
||||
last_funding_accrued_per_unit_in_base_denom: SignedDecimal
|
||||
last_funding_rate: SignedDecimal
|
||||
max_funding_velocity: Decimal
|
||||
rate: SignedDecimal
|
||||
skew_scale: Decimal
|
||||
}
|
||||
export type ArrayOfDenomStateResponse = DenomStateResponse[]
|
||||
@ -172,6 +184,15 @@ export interface DepositResponse {
|
||||
shares: Uint128
|
||||
}
|
||||
export type ArrayOfDepositResponse = DepositResponse[]
|
||||
export interface TradingFee {
|
||||
fee: Coin
|
||||
rate: Decimal
|
||||
}
|
||||
export interface Coin {
|
||||
amount: Uint128
|
||||
denom: string
|
||||
[k: string]: unknown
|
||||
}
|
||||
export interface OwnerResponse {
|
||||
abolished: boolean
|
||||
emergency_owner?: string | null
|
||||
@ -180,19 +201,17 @@ export interface OwnerResponse {
|
||||
proposed?: string | null
|
||||
}
|
||||
export interface PerpDenomState {
|
||||
constant_factor: SignedDecimal
|
||||
denom: string
|
||||
enabled: boolean
|
||||
index: SignedDecimal
|
||||
pnl_values: PnlValues
|
||||
pnl_values: DenomPnlValues
|
||||
rate: SignedDecimal
|
||||
total_cost_base: SignedDecimal
|
||||
total_size: SignedDecimal
|
||||
total_entry_cost: SignedDecimal
|
||||
total_entry_funding: SignedDecimal
|
||||
}
|
||||
export interface PnlValues {
|
||||
export interface DenomPnlValues {
|
||||
accrued_funding: SignedDecimal
|
||||
pnl: SignedDecimal
|
||||
unrealized_pnl: SignedDecimal
|
||||
price_pnl: SignedDecimal
|
||||
}
|
||||
export type PnL =
|
||||
| 'break_even'
|
||||
@ -212,14 +231,22 @@ export interface PerpPosition {
|
||||
current_price: Decimal
|
||||
denom: string
|
||||
entry_price: Decimal
|
||||
pnl: PnL
|
||||
pnl: PositionPnl
|
||||
size: SignedDecimal
|
||||
unrealised_funding_accrued: SignedDecimal
|
||||
}
|
||||
export interface Coin {
|
||||
amount: Uint128
|
||||
denom: string
|
||||
[k: string]: unknown
|
||||
export interface PositionPnl {
|
||||
coins: PnlCoins
|
||||
values: PnlValues
|
||||
}
|
||||
export interface PnlCoins {
|
||||
closing_fee: Coin
|
||||
pnl: PnL
|
||||
}
|
||||
export interface PnlValues {
|
||||
accrued_funding: SignedDecimal
|
||||
closing_fee: SignedDecimal
|
||||
pnl: SignedDecimal
|
||||
price_pnl: SignedDecimal
|
||||
}
|
||||
export type ArrayOfPositionResponse = PositionResponse[]
|
||||
export interface PositionsByAccountResponse {
|
||||
|
@ -1,3 +1,5 @@
|
||||
import { SearchParams } from 'types/enums/searchParams'
|
||||
|
||||
export function getRoute(
|
||||
page: Page,
|
||||
searchParams: URLSearchParams,
|
||||
@ -19,8 +21,8 @@ export function getRoute(
|
||||
)
|
||||
|
||||
if (accountId) {
|
||||
url.searchParams.delete('accountId')
|
||||
url.searchParams.append('accountId', accountId)
|
||||
url.searchParams.delete(SearchParams.ACCOUNT_ID)
|
||||
url.searchParams.append(SearchParams.ACCOUNT_ID, accountId)
|
||||
}
|
||||
|
||||
return url.pathname + url.search
|
||||
@ -53,3 +55,11 @@ export function getPage(pathname: string): Page {
|
||||
|
||||
return 'trade' as Page
|
||||
}
|
||||
|
||||
export function getSearchParamsObject(searchParams: URLSearchParams) {
|
||||
const params: { [key: string]: string } = {}
|
||||
|
||||
Array.from(searchParams?.entries() || []).forEach(([key, value]) => (params[key] = value))
|
||||
|
||||
return params
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user