Add perps balances table (#714)
* Add perps balances table * fix: updated svg --------- Co-authored-by: Linkie Link <linkielink.dev@gmail.com>
This commit is contained in:
parent
7707586c57
commit
117de1e3e5
@ -3,6 +3,7 @@ import { getCreditManagerQueryClient } from 'api/cosmwasm-client'
|
||||
import getDepositedVaults from 'api/vaults/getDepositedVaults'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { Positions } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
import { resolvePerpsPositions } from 'utils/resolvers'
|
||||
|
||||
export default async function getAccount(
|
||||
chainConfig: ChainConfig,
|
||||
@ -29,7 +30,7 @@ export default async function getAccount(
|
||||
lends: accountPosition.lends.map((lend) => new BNCoin(lend)),
|
||||
deposits: accountPosition.deposits.map((deposit) => new BNCoin(deposit)),
|
||||
vaults: depositedVaults,
|
||||
perps: accountPosition.perps,
|
||||
perps: resolvePerpsPositions(accountPosition.perps),
|
||||
kind: accountKind,
|
||||
}
|
||||
}
|
||||
|
8
src/components/Icons/Edit.svg
Normal file
8
src/components/Icons/Edit.svg
Normal file
@ -0,0 +1,8 @@
|
||||
<svg viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M14.9999 8.33424L11.6666 5.0009M2.08325 17.9176L4.90356 17.6042C5.24813 17.5659 5.42042 17.5468 5.58146 17.4946C5.72433 17.4484 5.86029 17.383 5.98566 17.3004C6.12696 17.2072 6.24954 17.0846 6.49469 16.8395L17.4999 5.83424C18.4204 4.91376 18.4204 3.42138 17.4999 2.5009C16.5795 1.58043 15.0871 1.58043 14.1666 2.5009L3.16136 13.5061C2.91621 13.7513 2.79363 13.8739 2.70045 14.0152C2.61778 14.1405 2.55243 14.2765 2.50618 14.4194C2.45405 14.5804 2.43491 14.7527 2.39662 15.0973L2.08325 17.9176Z"
|
||||
stroke="currentColor"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
After Width: | Height: | Size: 676 B |
@ -21,6 +21,7 @@ export { default as Compass } from 'components/Icons/Compass.svg'
|
||||
export { default as Copy } from 'components/Icons/Copy.svg'
|
||||
export { default as Cross } from 'components/Icons/Cross.svg'
|
||||
export { default as CrossCircled } from 'components/Icons/CrossCircled.svg'
|
||||
export { default as Edit } from 'components/Icons/Edit.svg'
|
||||
export { default as Enter } from 'components/Icons/Enter.svg'
|
||||
export { default as ExclamationMarkCircled } from 'components/Icons/ExclamationMarkCircled.svg'
|
||||
export { default as ExclamationMarkTriangle } from 'components/Icons/ExclamationMarkTriangle.svg'
|
||||
|
32
src/components/Perps/BalancesTable/Columns/EntryPrice.tsx
Normal file
32
src/components/Perps/BalancesTable/Columns/EntryPrice.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import { FormattedNumber } from 'components/FormattedNumber'
|
||||
import Text from 'components/Text'
|
||||
import TitleAndSubCell from 'components/TitleAndSubCell'
|
||||
import usePrice from 'hooks/usePrice'
|
||||
|
||||
export const ENTRY_PRICE_META = {
|
||||
accessorKey: 'entryPrice',
|
||||
header: () => (
|
||||
<div className='flex flex-col gap-1'>
|
||||
<Text size='xs'>Entry Price</Text>
|
||||
<Text size='xs' className='text-white/40'>
|
||||
Current Price
|
||||
</Text>
|
||||
</div>
|
||||
),
|
||||
}
|
||||
|
||||
type Props = {
|
||||
entryPrice: BigNumber
|
||||
asset: Asset
|
||||
}
|
||||
|
||||
export default function EntryPrice(props: Props) {
|
||||
const price = usePrice(props.asset.denom)
|
||||
|
||||
return (
|
||||
<TitleAndSubCell
|
||||
title={<FormattedNumber amount={props.entryPrice.toNumber()} options={{ prefix: '$' }} />}
|
||||
sub={<FormattedNumber amount={price.toNumber()} options={{ prefix: '$' }} />}
|
||||
/>
|
||||
)
|
||||
}
|
46
src/components/Perps/BalancesTable/Columns/Manage.tsx
Normal file
46
src/components/Perps/BalancesTable/Columns/Manage.tsx
Normal file
@ -0,0 +1,46 @@
|
||||
import React, { useMemo } from 'react'
|
||||
|
||||
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'
|
||||
|
||||
export const MANAGE_META = { id: 'manage', header: 'Manage' }
|
||||
|
||||
interface Props {
|
||||
perpPosition: PerpPositionRow
|
||||
}
|
||||
|
||||
export default function Manage(props: Props) {
|
||||
const currentAccount = useCurrentAccount()
|
||||
|
||||
const closePerpPosition = useStore((s) => s.closePerpPosition)
|
||||
const ITEMS: DropDownItem[] = useMemo(
|
||||
() => [
|
||||
{
|
||||
icon: <Edit />,
|
||||
text: 'Edit Position Size',
|
||||
onClick: () => {},
|
||||
},
|
||||
{
|
||||
icon: <Cross width={16} />,
|
||||
text: 'Close Position',
|
||||
onClick: async () => {
|
||||
if (!currentAccount) return
|
||||
await closePerpPosition({
|
||||
accountId: currentAccount.id,
|
||||
denom: props.perpPosition.asset.denom,
|
||||
})
|
||||
},
|
||||
},
|
||||
],
|
||||
[closePerpPosition, currentAccount, props.perpPosition.asset.denom],
|
||||
)
|
||||
|
||||
return (
|
||||
<div className='flex justify-end'>
|
||||
<DropDownButton items={ITEMS} text='Manage' color='tertiary' />
|
||||
</div>
|
||||
)
|
||||
}
|
16
src/components/Perps/BalancesTable/Columns/PerpName.tsx
Normal file
16
src/components/Perps/BalancesTable/Columns/PerpName.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import AssetImage from 'components/Asset/AssetImage'
|
||||
import TitleAndSubCell from 'components/TitleAndSubCell'
|
||||
|
||||
export const PERP_NAME_META = { accessorKey: 'asset.symbol', header: 'Asset', id: 'symbol' }
|
||||
|
||||
type Props = {
|
||||
asset: Asset
|
||||
}
|
||||
export function PerpName(props: Props) {
|
||||
return (
|
||||
<div className='flex gap-3'>
|
||||
<AssetImage asset={props.asset} size={32} />
|
||||
<TitleAndSubCell title={props.asset.name} sub={`${props.asset.symbol}-USD`} />
|
||||
</div>
|
||||
)
|
||||
}
|
24
src/components/Perps/BalancesTable/Columns/PerpType.tsx
Normal file
24
src/components/Perps/BalancesTable/Columns/PerpType.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import classNames from 'classnames'
|
||||
|
||||
import Text from 'components/Text'
|
||||
|
||||
export const PERP_TYPE_META = { accessorKey: 'type', header: 'Side' }
|
||||
|
||||
type Props = {
|
||||
type: PerpsType
|
||||
}
|
||||
|
||||
export default function PerpType(props: Props) {
|
||||
return (
|
||||
<Text
|
||||
size='xs'
|
||||
className={classNames(
|
||||
'capitalize px-1 py-0.5 rounded-sm inline',
|
||||
props.type === 'short' && 'text-error bg-error/20',
|
||||
props.type === 'long' && 'text-success bg-success/20',
|
||||
)}
|
||||
>
|
||||
{props.type}
|
||||
</Text>
|
||||
)
|
||||
}
|
28
src/components/Perps/BalancesTable/Columns/PnL.tsx
Normal file
28
src/components/Perps/BalancesTable/Columns/PnL.tsx
Normal file
@ -0,0 +1,28 @@
|
||||
import classNames from 'classnames'
|
||||
|
||||
import DisplayCurrency from 'components/DisplayCurrency'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
|
||||
export const PNL_META = { accessorKey: 'pnl', header: 'Total PnL', id: 'pnl' }
|
||||
|
||||
type Props = {
|
||||
pnl: BNCoin
|
||||
}
|
||||
|
||||
export default function PnL(props: Props) {
|
||||
const isNegative = props.pnl.amount.isNegative()
|
||||
return (
|
||||
<span
|
||||
className={classNames(
|
||||
'text-xs',
|
||||
isNegative ? 'text-error' : props.pnl.amount.isZero() ? '' : 'text-success',
|
||||
)}
|
||||
>
|
||||
{isNegative ? '-' : props.pnl.amount.isZero() ? '' : '+'}
|
||||
<DisplayCurrency
|
||||
className='inline'
|
||||
coin={BNCoin.fromDenomAndBigNumber(props.pnl.denom, props.pnl.amount.abs())}
|
||||
/>
|
||||
</span>
|
||||
)
|
||||
}
|
45
src/components/Perps/BalancesTable/Columns/Size.tsx
Normal file
45
src/components/Perps/BalancesTable/Columns/Size.tsx
Normal file
@ -0,0 +1,45 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import { FormattedNumber } from 'components/FormattedNumber'
|
||||
import Text from 'components/Text'
|
||||
import TitleAndSubCell from 'components/TitleAndSubCell'
|
||||
import usePrice from 'hooks/usePrice'
|
||||
import { demagnify } from 'utils/formatters'
|
||||
|
||||
export const SIZE_META = {
|
||||
accessorKey: 'size',
|
||||
header: () => (
|
||||
<div className='flex flex-col gap-1'>
|
||||
<Text size='xs'>Size</Text>
|
||||
<Text size='xs' className='text-white/40'>
|
||||
Value
|
||||
</Text>
|
||||
</div>
|
||||
),
|
||||
}
|
||||
|
||||
type Props = {
|
||||
size: BigNumber
|
||||
asset: Asset
|
||||
}
|
||||
|
||||
export default function Size(props: Props) {
|
||||
const price = usePrice(props.asset.denom)
|
||||
|
||||
const amount = useMemo(
|
||||
() => demagnify(props.size.toString(), props.asset),
|
||||
[props.asset, props.size],
|
||||
)
|
||||
const value = useMemo(() => price.times(amount).toNumber(), [amount, price])
|
||||
return (
|
||||
<TitleAndSubCell
|
||||
title={
|
||||
<FormattedNumber
|
||||
amount={amount}
|
||||
options={{ maxDecimals: amount < 0.0001 ? props.asset.decimals : 4 }}
|
||||
/>
|
||||
}
|
||||
sub={<FormattedNumber amount={value} options={{ prefix: '$' }} />}
|
||||
/>
|
||||
)
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
import { ColumnDef } from '@tanstack/react-table'
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import EntryPrice, { ENTRY_PRICE_META } from 'components/Perps/BalancesTable/Columns/EntryPrice'
|
||||
import Manage, { MANAGE_META } from 'components/Perps/BalancesTable/Columns/Manage'
|
||||
import { PERP_NAME_META, PerpName } from 'components/Perps/BalancesTable/Columns/PerpName'
|
||||
import PerpType, { PERP_TYPE_META } from 'components/Perps/BalancesTable/Columns/PerpType'
|
||||
import PnL, { PNL_META } from 'components/Perps/BalancesTable/Columns/PnL'
|
||||
import Size, { SIZE_META } from 'components/Perps/BalancesTable/Columns/Size'
|
||||
import { PerpPositionRow } from 'components/Perps/BalancesTable/usePerpsBalancesData'
|
||||
|
||||
export default function usePerpsBalancesTable() {
|
||||
return useMemo<ColumnDef<PerpPositionRow>[]>(() => {
|
||||
return [
|
||||
{
|
||||
...PERP_NAME_META,
|
||||
cell: ({ row }) => <PerpName asset={row.original.asset} />,
|
||||
},
|
||||
{
|
||||
...PERP_TYPE_META,
|
||||
cell: ({ row }) => <PerpType type={row.original.type} />,
|
||||
},
|
||||
{
|
||||
...SIZE_META,
|
||||
cell: ({ row }) => <Size size={row.original.size} asset={row.original.asset} />,
|
||||
},
|
||||
{
|
||||
...ENTRY_PRICE_META,
|
||||
cell: ({ row }) => (
|
||||
<EntryPrice entryPrice={row.original.entryPrice} asset={row.original.asset} />
|
||||
),
|
||||
},
|
||||
{
|
||||
...PNL_META,
|
||||
cell: ({ row }) => <PnL pnl={row.original.pnl} />,
|
||||
},
|
||||
{
|
||||
...MANAGE_META,
|
||||
cell: ({ row }) => <Manage perpPosition={row.original} />,
|
||||
},
|
||||
]
|
||||
}, [])
|
||||
}
|
10
src/components/Perps/BalancesTable/index.tsx
Normal file
10
src/components/Perps/BalancesTable/index.tsx
Normal file
@ -0,0 +1,10 @@
|
||||
import usePerpsBalancesColumns from 'components/Perps/BalancesTable/Columns/usePerpsBalancesColumns'
|
||||
import usePerpsBalancesData from 'components/Perps/BalancesTable/usePerpsBalancesData'
|
||||
import Table from 'components/Table'
|
||||
|
||||
export default function PerpsBalancesTable() {
|
||||
const data = usePerpsBalancesData()
|
||||
const columns = usePerpsBalancesColumns()
|
||||
|
||||
return <Table title='Perp Positions' columns={columns} data={data} initialSorting={[]} />
|
||||
}
|
34
src/components/Perps/BalancesTable/usePerpsBalancesData.ts
Normal file
34
src/components/Perps/BalancesTable/usePerpsBalancesData.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import { useMemo } from 'react'
|
||||
|
||||
import usePerpsEnabledAssets from 'hooks/assets/usePerpsEnabledAssets'
|
||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { byDenom } from 'utils/array'
|
||||
|
||||
export default function usePerpsBalancesTable() {
|
||||
const currentAccount = useCurrentAccount()
|
||||
const perpAssets = usePerpsEnabledAssets()
|
||||
|
||||
return useMemo<PerpPositionRow[]>(() => {
|
||||
if (!currentAccount) return []
|
||||
|
||||
return currentAccount.perps.map((position) => {
|
||||
const asset = perpAssets.find(byDenom(position.denom))
|
||||
return {
|
||||
asset,
|
||||
type: position.type,
|
||||
size: position.size,
|
||||
pnl: position.pnl,
|
||||
entryPrice: position.entryPrice,
|
||||
} as PerpPositionRow
|
||||
})
|
||||
}, [currentAccount, perpAssets])
|
||||
}
|
||||
|
||||
export type PerpPositionRow = {
|
||||
asset: Asset
|
||||
type: 'long' | 'short'
|
||||
size: BigNumber
|
||||
pnl: BNCoin
|
||||
entryPrice: BigNumber
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { useState } from 'react'
|
||||
import { useCallback, useState } from 'react'
|
||||
|
||||
import Button from 'components/Button'
|
||||
import Card from 'components/Card'
|
||||
@ -15,12 +15,26 @@ import { AvailableOrderType } from 'components/Trade/TradeModule/SwapForm/OrderT
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import useBaseAsset from 'hooks/assets/useBasetAsset'
|
||||
import usePerpsAsset from 'hooks/perps/usePerpsAsset'
|
||||
import useCurrentAccount from 'hooks/useCurrentAccount'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
export function PerpsModule() {
|
||||
const [selectedOrderType, setSelectedOrderType] = useState<AvailableOrderType>('Market')
|
||||
const [selectedOrderDirection, setSelectedOrderDirection] = useState<OrderDirection>('long')
|
||||
const baseAsset = useBaseAsset()
|
||||
const { perpsAsset } = usePerpsAsset()
|
||||
const openPerpPosition = useStore((s) => s.openPerpPosition)
|
||||
const currentAccount = useCurrentAccount()
|
||||
|
||||
const onConfirm = useCallback(async () => {
|
||||
if (!currentAccount) return
|
||||
await openPerpPosition({
|
||||
accountId: currentAccount.id,
|
||||
coin: BNCoin.fromDenomAndBigNumber(perpsAsset.denom, BN(1000)),
|
||||
})
|
||||
}, [currentAccount, openPerpPosition, perpsAsset.denom])
|
||||
|
||||
if (!perpsAsset) return null
|
||||
|
||||
@ -50,7 +64,7 @@ export function PerpsModule() {
|
||||
<RangeInput max={0} value={0} onChange={() => {}} />
|
||||
<LeverageButtons />
|
||||
<Spacer />
|
||||
<Button>{selectedOrderDirection} ETH</Button>
|
||||
<Button onClick={onConfirm}>{selectedOrderDirection} ETH</Button>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import AccountDetailsCard from 'components/Trade/AccountDetailsCard'
|
||||
import PerpsBalancesTable from './BalancesTable'
|
||||
|
||||
export function PerpsPositions() {
|
||||
return <AccountDetailsCard />
|
||||
return <PerpsBalancesTable />
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ export default function Table<T>(props: Props<T>) {
|
||||
'align-center',
|
||||
)}
|
||||
>
|
||||
<span className='w-5 h-5 text-white'>
|
||||
<span className='w-5 h-5 text-white my-auto'>
|
||||
{header.column.getCanSort()
|
||||
? {
|
||||
asc: <SortAsc size={16} />,
|
||||
|
@ -132,14 +132,17 @@ export default function useHealthComputer(account?: Account) {
|
||||
return null
|
||||
|
||||
return {
|
||||
denoms_data: { params: denomsData, prices: priceData },
|
||||
kind: account.kind,
|
||||
vaults_data: {
|
||||
vault_configs: vaultConfigsData,
|
||||
vault_values: vaultPositionValues,
|
||||
},
|
||||
denoms_data: {
|
||||
params: denomsData,
|
||||
prices: priceData,
|
||||
},
|
||||
positions: positions,
|
||||
kind: account.kind,
|
||||
}
|
||||
} as HealthComputer
|
||||
}, [account, positions, vaultPositionValues, vaultConfigsData, denomsData, priceData])
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -6,13 +6,13 @@ import { PerpsPositions } from 'components/Perps/PerpsPositions'
|
||||
export default function PerpsPage() {
|
||||
return (
|
||||
<div className='flex flex-col w-full h-full gap-4'>
|
||||
<div className='grid w-full grid-cols-[auto_346px] gap-4 pb-4'>
|
||||
<div className='grid grid-cols-1 grid-rows-[min-content_auto_min-content] gap-4 h-[calc(100dvh-93px)] pb-4'>
|
||||
<div className='grid w-full grid-cols-[auto_346px] gap-4'>
|
||||
<div className='flex flex-col gap-4'>
|
||||
<PerpsInfo />
|
||||
<PerpsChart />
|
||||
<PerpsPositions />
|
||||
</div>
|
||||
<PerpsModule />
|
||||
<PerpsPositions />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
@ -117,6 +117,19 @@ export default function createBroadcastSlice(
|
||||
})
|
||||
break
|
||||
|
||||
case 'open-perp':
|
||||
toast.content.push({
|
||||
coins: changes.deposits?.map((deposit) => deposit.toCoin()) ?? [],
|
||||
text: 'Opened perp position',
|
||||
})
|
||||
break
|
||||
case 'close-perp':
|
||||
toast.content.push({
|
||||
coins: changes.deposits?.map((deposit) => deposit.toCoin()) ?? [],
|
||||
text: 'Closed perp position',
|
||||
})
|
||||
break
|
||||
|
||||
case 'swap':
|
||||
if (changes.debts) {
|
||||
toast.content.push({
|
||||
@ -916,5 +929,65 @@ export default function createBroadcastSlice(
|
||||
return { result: undefined, error: e.message }
|
||||
}
|
||||
},
|
||||
openPerpPosition: async (options: { accountId: string; coin: BNCoin }) => {
|
||||
const msg: CreditManagerExecuteMsg = {
|
||||
update_credit_account: {
|
||||
account_id: options.accountId,
|
||||
actions: [
|
||||
{
|
||||
open_perp: options.coin.toSignedCoin(),
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const cmContract = get().chainConfig.contracts.creditManager
|
||||
|
||||
const response = get().executeMsg({
|
||||
messages: [generateExecutionMessage(get().address, cmContract, msg, [])],
|
||||
})
|
||||
|
||||
get().setToast({
|
||||
response,
|
||||
options: {
|
||||
action: 'open-perp',
|
||||
target: 'account',
|
||||
accountId: options.accountId,
|
||||
changes: { deposits: [options.coin] },
|
||||
},
|
||||
})
|
||||
|
||||
return response.then((response) => !!response.result)
|
||||
},
|
||||
closePerpPosition: async (options: { accountId: string; denom: string }) => {
|
||||
const msg: CreditManagerExecuteMsg = {
|
||||
update_credit_account: {
|
||||
account_id: options.accountId,
|
||||
actions: [
|
||||
{
|
||||
close_perp: { denom: options.denom },
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
const cmContract = get().chainConfig.contracts.creditManager
|
||||
|
||||
const response = get().executeMsg({
|
||||
messages: [generateExecutionMessage(get().address, cmContract, msg, [])],
|
||||
})
|
||||
|
||||
get().setToast({
|
||||
response,
|
||||
options: {
|
||||
action: 'close-perp',
|
||||
target: 'account',
|
||||
accountId: options.accountId,
|
||||
changes: { deposits: [] },
|
||||
},
|
||||
})
|
||||
|
||||
return response.then((response) => !!response.result)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -37,4 +37,11 @@ export class BNCoin {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
toSignedCoin(): any {
|
||||
return {
|
||||
denom: this.denom,
|
||||
size: this.amount.toString(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
14
src/types/interfaces/perps.d.ts
vendored
14
src/types/interfaces/perps.d.ts
vendored
@ -1,7 +1,19 @@
|
||||
type OrderDirection = 'long' | 'short' | 'buy' | 'sell'
|
||||
const BNCoin = import('types/classes/BNCoin').BNCoin
|
||||
|
||||
type OrderDirection = PerpsType | ('buy' | 'sell')
|
||||
|
||||
type PerpsType = 'long' | 'short'
|
||||
|
||||
// TODO: 📈Remove this type when healthcomputer is implemented
|
||||
type PositionsWithoutPerps = Omit<
|
||||
import('types/generated/mars-credit-manager/MarsCreditManager.types').Positions,
|
||||
'perps'
|
||||
>
|
||||
|
||||
type PerpsPosition = {
|
||||
denom: string
|
||||
baseDenom: string
|
||||
type: PerpsType
|
||||
size: BigNumber
|
||||
// closingFee: BNCoin
|
||||
}
|
||||
|
4
src/types/interfaces/store/broadcast.d.ts
vendored
4
src/types/interfaces/store/broadcast.d.ts
vendored
@ -72,6 +72,8 @@ interface HandleResponseProps {
|
||||
| 'swap'
|
||||
| 'oracle'
|
||||
| 'hls-staking'
|
||||
| 'open-perp'
|
||||
| 'close-perp'
|
||||
lend?: boolean
|
||||
accountId?: string
|
||||
changes?: {
|
||||
@ -118,6 +120,8 @@ interface BroadcastSlice {
|
||||
execute: (contract: string, msg: ExecuteMsg, funds: Coin[]) => Promise<BroadcastResult>
|
||||
executeMsg: (options: { messages: MsgExecuteContract[] }) => Promise<BroadcastResult>
|
||||
lend: (options: { accountId: string; coin: BNCoin; isMax?: boolean }) => Promise<boolean>
|
||||
closePerpPosition: (options: { accountId: string; denom: string }) => Promise<boolean>
|
||||
openPerpPosition: (options: { accountId: string; coin: BNCoin }) => Promise<boolean>
|
||||
reclaim: (options: { accountId: string; coin: BNCoin; isMax?: boolean }) => Promise<boolean>
|
||||
repay: (options: {
|
||||
accountId: string
|
||||
|
@ -183,8 +183,6 @@ export function convertAccountToPositions(account: Account): PositionsWithoutPer
|
||||
amount: lend.amount.toString(),
|
||||
denom: lend.denom,
|
||||
})),
|
||||
// TODO: 📈 Add correct type mapping
|
||||
perps: account.perps,
|
||||
vaults: account.vaults.map(
|
||||
(vault) =>
|
||||
({
|
||||
|
@ -1,3 +1,6 @@
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { PnL, Positions } from 'types/generated/mars-credit-manager/MarsCreditManager.types'
|
||||
import {
|
||||
AssetParamsBaseForAddr as AssetParams,
|
||||
AssetParamsBaseForAddr,
|
||||
@ -73,3 +76,29 @@ export function resolveHLSStrategies(
|
||||
})
|
||||
return HLSStakingStrategies
|
||||
}
|
||||
|
||||
export function resolvePerpsPositions(perpPositions: Positions['perps']): PerpsPosition[] {
|
||||
return perpPositions.map((position) => {
|
||||
return {
|
||||
denom: position.denom,
|
||||
baseDenom: position.base_denom,
|
||||
size: BN(position.size as any),
|
||||
type: BN(position.size as any).isNegative() ? 'short' : 'long',
|
||||
closingFee: BNCoin.fromCoin(position.pnl.coins.closing_fee),
|
||||
pnl: getPnlCoin(position.pnl.coins.pnl, position.base_denom),
|
||||
entryPrice: BN(position.entry_price),
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function getPnlCoin(pnl: PnL, denom: string): BNCoin {
|
||||
let amount = BN_ZERO
|
||||
|
||||
if ('loss' in (pnl as { loss: Coin })) {
|
||||
amount = BN((pnl as any).loss.amount).times(-1)
|
||||
} else if ('profit' in (pnl as { profit: Coin })) {
|
||||
amount = BN((pnl as any).profit.amount)
|
||||
}
|
||||
|
||||
return BNCoin.fromDenomAndBigNumber(denom, amount)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user