From e75cb06eb22d82793f604ae71534395fbb913d90 Mon Sep 17 00:00:00 2001 From: saml33 Date: Thu, 23 Mar 2023 12:26:02 +1100 Subject: [PATCH] add perp liquidations --- components/account/ActivityFeed.tsx | 280 +++++++++++++++++------ components/account/ActivityFeedTable.tsx | 61 ++++- public/locales/en/activity.json | 6 +- public/locales/es/activity.json | 6 +- public/locales/ru/activity.json | 6 +- public/locales/zh/activity.json | 6 +- public/locales/zh_tw/activity.json | 6 +- types/index.ts | 36 ++- 8 files changed, 318 insertions(+), 89 deletions(-) diff --git a/components/account/ActivityFeed.tsx b/components/account/ActivityFeed.tsx index 59b4bd5e..8b7eec8f 100644 --- a/components/account/ActivityFeed.tsx +++ b/components/account/ActivityFeed.tsx @@ -7,10 +7,14 @@ import dayjs from 'dayjs' import useLocalStorageState from 'hooks/useLocalStorageState' import { useTranslation } from 'next-i18next' import Image from 'next/legacy/image' -import { useState } from 'react' +import { useMemo, useState } from 'react' import { PREFERRED_EXPLORER_KEY } from 'utils/constants' import ActivityFeedTable from './ActivityFeedTable' -import { LiquidationActivity } from 'types' +import { + isPerpLiquidation, + LiquidationActivity, + SpotOrPerpLiquidationItem, +} from 'types' const ActivityFeed = () => { const activityFeed = mangoStore((s) => s.activityFeed.feed) @@ -27,7 +31,7 @@ const ActivityFeed = () => { handleShowActivityDetails={handleShowActivityDetails} /> ) : ( - @@ -36,97 +40,231 @@ const ActivityFeed = () => { export default ActivityFeed -const ActivityDetails = ({ +const LiquidationDetails = ({ activity, setShowActivityDetail, }: { activity: LiquidationActivity setShowActivityDetail: (x: LiquidationActivity | undefined) => void }) => { + console.log(activity) const { t } = useTranslation(['common', 'activity', 'settings']) const [preferredExplorer] = useLocalStorageState( PREFERRED_EXPLORER_KEY, EXPLORERS[0] ) - const { block_datetime, activity_type } = activity - const { - asset_amount, - asset_price, - asset_symbol, - liab_amount, - liab_price, - liab_symbol, - signature, - } = activity.activity_details + const { block_datetime } = activity + + const getAssetLiquidatedReturned = (details: SpotOrPerpLiquidationItem) => { + const assets = { + liquidated: { amount: 0, symbol: '', value: 0 }, + returned: { amount: 0, symbol: '', value: 0 }, + } + if (isPerpLiquidation(details)) { + const { + base_transfer, + pnl_settle_limit_transfer, + pnl_transfer, + price, + quote_transfer, + side, + } = details + if (side === 'liqee') { + const returnedAmount = + pnl_settle_limit_transfer + pnl_transfer + quote_transfer + const liquidatedAmount = base_transfer * price + assets.liquidated.amount = liquidatedAmount + assets.liquidated.value = liquidatedAmount + assets.returned.amount = returnedAmount + assets.returned.value = returnedAmount + } else { + const liquidatedAmount = + pnl_settle_limit_transfer + pnl_transfer + quote_transfer + const returnedAmount = base_transfer * price + assets.liquidated.amount = liquidatedAmount + assets.liquidated.value = liquidatedAmount + assets.returned.amount = returnedAmount + assets.returned.value = returnedAmount + } + } else { + const { + side, + liab_amount, + liab_price, + liab_symbol, + asset_amount, + asset_price, + asset_symbol, + } = details + if (side === 'liqee') { + assets.liquidated.amount = asset_amount + assets.liquidated.symbol = asset_symbol + assets.liquidated.value = asset_amount * asset_price + assets.returned.amount = liab_amount + assets.returned.symbol = liab_symbol + assets.returned.value = liab_amount * liab_price + } else { + assets.liquidated.amount = liab_amount + assets.liquidated.symbol = liab_symbol + assets.liquidated.value = liab_amount * liab_price + assets.returned.amount = asset_amount + assets.returned.symbol = asset_symbol + assets.returned.value = asset_amount * asset_price + } + } + return assets + } + + const [ + assetLiquidated, + assetReturned, + assetLiquidatedSymbol, + assetReturnedSymbol, + liquidatedValue, + returnedValue, + ] = useMemo(() => { + if (!activity) return [0, 0, '', '', 0, 0] + const values = getAssetLiquidatedReturned(activity.activity_details) + return [ + values?.liquidated.amount, + values?.returned.amount, + values?.liquidated.symbol, + values?.returned.symbol, + values?.liquidated.value, + values?.returned.value, + ] + }, [activity]) + + console.log( + assetLiquidated, + assetReturned, + assetLiquidatedSymbol, + assetReturnedSymbol + ) + return (
setShowActivityDetail(undefined)} + size="small" >

{t('activity:liquidation-details')}

-
-

{t('date')}

-

- {dayjs(block_datetime).format('ddd D MMM')} -

-

- {dayjs(block_datetime).format('h:mma')} -

-
-
-

{t('activity:liquidation-type')}

-

- {activity_type === 'liquidate_token_with_token' - ? t('spot') - : t('perp')} -

-
-
-

{t('activity:asset-liquidated')}

-

- {' '} - {asset_symbol} - at{' '} - -

-

- -

-
-
-

{t('activity:asset-returned')}

-

- {' '} - {liab_symbol} - at{' '} - -

-

- -

-
-
-
- - - {t('view-transaction')} - + {isPerpLiquidation(activity.activity_details) ? ( + <> +
+

{t('date')}

+

+ {dayjs(block_datetime).format('ddd D MMM')} +

+

+ {dayjs(block_datetime).format('h:mma')} +

+
+
+

{t('activity:liquidation-type')}

+

{t('perp')}

+
+
+

{t('activity:asset-liquidated')}

+

+ {' '} + {assetLiquidatedSymbol} +

+

+ +

+
+
+

{t('activity:asset-returned')}

+

+ {' '} + {assetReturnedSymbol} +

+

+ +

+
+ + ) : ( + <> +
+

{t('date')}

+

+ {dayjs(block_datetime).format('ddd D MMM')} +

+

+ {dayjs(block_datetime).format('h:mma')} +

+
+
+

{t('activity:liquidation-type')}

+

{t('spot')}

+
+
+

{t('activity:asset-liquidated')}

+

+ {' '} + {assetLiquidatedSymbol} + at{' '} + +

+

+ +

+
+
+

{t('activity:asset-returned')}

+

+ {' '} + {assetReturnedSymbol} + at{' '} + +

+

+ +

+
+
+

{t('activity:liquidation-side')}

+

+ {activity.activity_details.side === 'liqor' + ? t('activity:liquidator') + : t('activity:liquidated')} +

+
+
+

{t('transaction')}

+ + + + {t(`settings:${preferredExplorer.name}`)} + + +
+ + )}
) diff --git a/components/account/ActivityFeedTable.tsx b/components/account/ActivityFeedTable.tsx index 80aa8e5a..ae026ee7 100644 --- a/components/account/ActivityFeedTable.tsx +++ b/components/account/ActivityFeedTable.tsx @@ -77,6 +77,31 @@ const getCreditAndDebit = (activity: any) => { debit = { value: formatNumericValue(liab_amount), symbol: liab_symbol } } } + if (activity_type === 'liquidate_perp_base_position_or_positive_pnl') { + const { + base_transfer, + pnl_settle_limit_transfer, + pnl_transfer, + price, + quote_transfer, + side, + } = activity.activity_details + const rawCredit = pnl_settle_limit_transfer + pnl_transfer + quote_transfer + const rawDebit = base_transfer * price + if (side === 'liqee') { + credit = { value: formatNumericValue(rawCredit), symbol: '' } + debit = { + value: formatNumericValue(rawDebit), + symbol: '', + } + } else { + credit = { + value: formatNumericValue(rawDebit), + symbol: '', + } + debit = { value: formatNumericValue(rawCredit), symbol: '' } + } + } if (activity_type === 'deposit') { const { symbol, quantity } = activity.activity_details credit = { value: formatNumericValue(quantity), symbol } @@ -132,9 +157,30 @@ const getValue = (activity: any) => { const { side, liab_amount, liab_price, asset_amount, asset_price } = activity.activity_details if (side === 'liqee') { - value = asset_amount * asset_price + value = + Math.abs(liab_amount) * liab_price - + Math.abs(asset_amount) * asset_price } else { - value = liab_amount * liab_price + value = + Math.abs(asset_amount) * asset_price - + Math.abs(liab_amount) * liab_price + } + } + if (activity_type === 'liquidate_perp_base_position_or_positive_pnl') { + const { + base_transfer, + pnl_settle_limit_transfer, + pnl_transfer, + price, + quote_transfer, + side, + } = activity.activity_details + const rawCredit = pnl_settle_limit_transfer + pnl_transfer + quote_transfer + const rawDebit = base_transfer * price + if (side === 'liqee') { + value = Math.abs(rawCredit) - Math.abs(rawDebit) + } else { + value = Math.abs(rawDebit) - Math.abs(rawCredit) } } if (activity_type === 'deposit' || activity_type === 'withdraw') { @@ -216,8 +262,6 @@ const ActivityFeedTable = ({ {activityFeed.map((activity, index: number) => { const { activity_type, block_datetime } = activity const { signature } = activity.activity_details - const isLiquidation = - activity_type === 'liquidate_token_with_token' const isOpenbook = activity_type === 'openbook_trade' const amounts = getCreditAndDebit(activity) const value = getValue(activity) @@ -226,7 +270,7 @@ const ActivityFeedTable = ({ - {activity_type !== 'liquidate_token_with_token' ? ( + {!isLiquidationFeedItem(activity) ? (

- {isLiquidation ? ( + {isLiquidationFeedItem(activity) ? ( ) : isSwap ? ( <> @@ -471,7 +514,7 @@ const MobileActivityFeedItem = ({ )}

- {isLiquidation ? ( + {isLiquidationFeedItem(activity) ? ( setExpandActivityDetails((prev) => !prev)} > diff --git a/public/locales/en/activity.json b/public/locales/en/activity.json index 0efb0541..cc841910 100644 --- a/public/locales/en/activity.json +++ b/public/locales/en/activity.json @@ -11,11 +11,15 @@ "deposit": "Deposit", "deposits": "Deposits", "filter-results": "Filter", + "liquidate_perp_base_position_or_positive_pnl": "Perp Liquidation", + "liquidate_token_with_token": "Spot Liquidation", + "liquidated": "Liquidated", "liquidation": "Liquidation", "liquidation-type": "Liquidation Type", + "liquidation-side": "Liquidation Side", "liquidations": "Liquidations", "liquidation-details": "Liquidation Details", - "liquidate_token_with_token": "Spot Liquidation", + "liquidator": "Liquidator", "no-activity": "No account activity", "openbook_trade": "Spot Trade", "perps": "Perps", diff --git a/public/locales/es/activity.json b/public/locales/es/activity.json index 0efb0541..cc841910 100644 --- a/public/locales/es/activity.json +++ b/public/locales/es/activity.json @@ -11,11 +11,15 @@ "deposit": "Deposit", "deposits": "Deposits", "filter-results": "Filter", + "liquidate_perp_base_position_or_positive_pnl": "Perp Liquidation", + "liquidate_token_with_token": "Spot Liquidation", + "liquidated": "Liquidated", "liquidation": "Liquidation", "liquidation-type": "Liquidation Type", + "liquidation-side": "Liquidation Side", "liquidations": "Liquidations", "liquidation-details": "Liquidation Details", - "liquidate_token_with_token": "Spot Liquidation", + "liquidator": "Liquidator", "no-activity": "No account activity", "openbook_trade": "Spot Trade", "perps": "Perps", diff --git a/public/locales/ru/activity.json b/public/locales/ru/activity.json index 0efb0541..cc841910 100644 --- a/public/locales/ru/activity.json +++ b/public/locales/ru/activity.json @@ -11,11 +11,15 @@ "deposit": "Deposit", "deposits": "Deposits", "filter-results": "Filter", + "liquidate_perp_base_position_or_positive_pnl": "Perp Liquidation", + "liquidate_token_with_token": "Spot Liquidation", + "liquidated": "Liquidated", "liquidation": "Liquidation", "liquidation-type": "Liquidation Type", + "liquidation-side": "Liquidation Side", "liquidations": "Liquidations", "liquidation-details": "Liquidation Details", - "liquidate_token_with_token": "Spot Liquidation", + "liquidator": "Liquidator", "no-activity": "No account activity", "openbook_trade": "Spot Trade", "perps": "Perps", diff --git a/public/locales/zh/activity.json b/public/locales/zh/activity.json index 0efb0541..cc841910 100644 --- a/public/locales/zh/activity.json +++ b/public/locales/zh/activity.json @@ -11,11 +11,15 @@ "deposit": "Deposit", "deposits": "Deposits", "filter-results": "Filter", + "liquidate_perp_base_position_or_positive_pnl": "Perp Liquidation", + "liquidate_token_with_token": "Spot Liquidation", + "liquidated": "Liquidated", "liquidation": "Liquidation", "liquidation-type": "Liquidation Type", + "liquidation-side": "Liquidation Side", "liquidations": "Liquidations", "liquidation-details": "Liquidation Details", - "liquidate_token_with_token": "Spot Liquidation", + "liquidator": "Liquidator", "no-activity": "No account activity", "openbook_trade": "Spot Trade", "perps": "Perps", diff --git a/public/locales/zh_tw/activity.json b/public/locales/zh_tw/activity.json index 0efb0541..cc841910 100644 --- a/public/locales/zh_tw/activity.json +++ b/public/locales/zh_tw/activity.json @@ -11,11 +11,15 @@ "deposit": "Deposit", "deposits": "Deposits", "filter-results": "Filter", + "liquidate_perp_base_position_or_positive_pnl": "Perp Liquidation", + "liquidate_token_with_token": "Spot Liquidation", + "liquidated": "Liquidated", "liquidation": "Liquidation", "liquidation-type": "Liquidation Type", + "liquidation-side": "Liquidation Side", "liquidations": "Liquidations", "liquidation-details": "Liquidation Details", - "liquidate_token_with_token": "Spot Liquidation", + "liquidator": "Liquidator", "no-activity": "No account activity", "openbook_trade": "Spot Trade", "perps": "Perps", diff --git a/types/index.ts b/types/index.ts index 8ce13fbe..374df21a 100644 --- a/types/index.ts +++ b/types/index.ts @@ -113,7 +113,7 @@ export interface DepositWithdrawFeedItem { wallet_pk: string } -export interface LiquidationFeedItem { +export interface SpotLiquidationFeedItem { asset_amount: number asset_price: number asset_symbol: string @@ -123,12 +123,30 @@ export interface LiquidationFeedItem { liab_symbol: string mango_account: string mango_group: string - side: string + side: 'liqor' | 'liqee' signature: string } +export interface PerpLiquidationFeedItem { + base_transfer: -0.5 + block_datetime: string + counterparty: string + mango_account: string + mango_group: string + pnl_settle_limit_transfer: number + pnl_transfer: number + price: number + quote_transfer: number + side: 'liqor' | 'liqee' + signature: string +} + +export type SpotOrPerpLiquidationItem = + | SpotLiquidationFeedItem + | PerpLiquidationFeedItem + export interface LiquidationActivity { - activity_details: LiquidationFeedItem + activity_details: SpotOrPerpLiquidationItem block_datetime: string activity_type: string symbol: string @@ -143,6 +161,15 @@ export function isLiquidationFeedItem( return false } +export function isPerpLiquidation( + activityDetails: SpotOrPerpLiquidationItem +): activityDetails is PerpLiquidationFeedItem { + if ((activityDetails as PerpLiquidationFeedItem).base_transfer) { + return true + } + return false +} + export interface SwapHistoryItem { block_datetime: string mango_account: string @@ -183,7 +210,8 @@ export type ActivityFeed = { symbol: string activity_details: | DepositWithdrawFeedItem - | LiquidationFeedItem + | SpotLiquidationFeedItem + | PerpLiquidationFeedItem | SwapHistoryItem | PerpTradeHistory | SpotTradeHistory