From 800dd223ce9ac212e4a970b022764a8d290f68b3 Mon Sep 17 00:00:00 2001 From: Jared Vu Date: Wed, 15 Jan 2025 09:29:07 -0800 Subject: [PATCH] fix(bonsai-core): unopened isolated position struct change (#1436) --- .eslintrc.json | 6 +- src/abacus-ts/calculators/subaccount.ts | 75 ++++++++++++++++--------- src/abacus-ts/types/summaryTypes.ts | 9 +++ 3 files changed, 59 insertions(+), 31 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 3609ee35d..8945e1780 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -53,10 +53,10 @@ "error", { "patterns": [ - "@/abacus-ts/*", + "@/abacus-ts/*/*", "!@/abacus-ts/ontology", - "!@/abacus-ts/lib", - "!@/abacus-ts/summaryTypes" + "!@/abacus-ts/lib/*", + "!@/abacus-ts/types/summaryTypes" ] } ], diff --git a/src/abacus-ts/calculators/subaccount.ts b/src/abacus-ts/calculators/subaccount.ts index a661ef1b1..eed50b49b 100644 --- a/src/abacus-ts/calculators/subaccount.ts +++ b/src/abacus-ts/calculators/subaccount.ts @@ -1,5 +1,6 @@ import BigNumber from 'bignumber.js'; -import { mapValues, orderBy } from 'lodash'; +import { groupBy, map, mapValues, orderBy, pickBy } from 'lodash'; +import { weakMapMemoize } from 'reselect'; import { NUM_PARENT_SUBACCOUNTS } from '@/constants/account'; import { @@ -9,7 +10,11 @@ import { } from '@/types/indexer/indexerApiGen'; import { IndexerWsBaseMarketObject } from '@/types/indexer/indexerManual'; -import { getAssetFromMarketId } from '@/lib/assetUtils'; +import { + getAssetFromMarketId, + getDisplayableAssetFromBaseAsset, + getDisplayableTickerFromMarket, +} from '@/lib/assetUtils'; import { calc } from '@/lib/do'; import { isTruthy } from '@/lib/isTruthy'; import { BIG_NUMBERS, MaybeBigNumber, MustBigNumber, ToBigNumber } from '@/lib/numbers'; @@ -18,6 +23,7 @@ import { isPresent } from '@/lib/typeUtils'; import { ChildSubaccountData, MarketsData, ParentSubaccountData } from '../types/rawTypes'; import { GroupedSubaccountSummary, + PendingIsolatedPosition, SubaccountOrder, SubaccountPosition, SubaccountPositionBase, @@ -76,16 +82,15 @@ export function calculateMarketsNeededForSubaccount(parent: Omit { + const core = calculateSubaccountSummaryCore(subaccountData, markets); + return { + ...core, + ...calculateSubaccountSummaryDerived(core), + }; + } +); function calculateSubaccountSummaryCore( subaccountData: ChildSubaccountData, @@ -295,37 +300,51 @@ export function calculateChildSubaccountSummaries( parent: Omit, markets: MarketsData ): Record { - return Object.fromEntries( - Object.values(parent.childSubaccounts) - .map((subaccount) => { - if (!subaccount) return undefined; - const summary = calculateSubaccountSummary(subaccount, markets); - return [subaccount.subaccountNumber, summary]; - }) - .filter(isTruthy) + return pickBy( + mapValues( + parent.childSubaccounts, + (subaccount) => subaccount && calculateSubaccountSummary(subaccount, markets) + ), + isTruthy ); } /** - * - * UnopenedIsolatedPosition is a modified SubaccountOrder that meets the following criterias: + * @returns a list of pending isolated positions + * PendingIsolatedPosition is exists if there are any orders that meet the following criteria: * - marginMode is ISOLATED * - no existing position exists - * - equity of the childSubaccount is returned with the order + * - childSubaccount has equity */ export function calculateUnopenedIsolatedPositions( childSubaccounts: Record, orders: SubaccountOrder[], positions: SubaccountPosition[] -): Array> { +): PendingIsolatedPosition[] { const setOfOpenPositionMarkets = new Set(positions.map(({ market }) => market)); const filteredOrders = orders.filter( (o) => !setOfOpenPositionMarkets.has(o.marketId) && o.marginMode === 'ISOLATED' ); - return filteredOrders.map((o) => ({ - ...o, - equity: childSubaccounts[o.subaccountNumber]?.equity ?? BIG_NUMBERS.ZERO, - })); + const filteredOrdersMap = groupBy(filteredOrders, 'marketId'); + const marketIdToSubaccountNumber = mapValues( + filteredOrdersMap, + (filteredOrder) => filteredOrder[0]?.subaccountNumber + ); + + return map(filteredOrdersMap, (orderList, marketId) => { + const subaccountNumber = marketIdToSubaccountNumber[marketId]; + if (subaccountNumber == null) return undefined; + const assetId = getAssetFromMarketId(marketId); + + return { + assetId, + displayableAsset: getDisplayableAssetFromBaseAsset(assetId), + marketId, + displayId: getDisplayableTickerFromMarket(marketId), + equity: childSubaccounts[subaccountNumber]?.equity ?? BIG_NUMBERS.ZERO, + orders: orderList, + }; + }).filter(isTruthy); } diff --git a/src/abacus-ts/types/summaryTypes.ts b/src/abacus-ts/types/summaryTypes.ts index 6e80942ca..607be7b3f 100644 --- a/src/abacus-ts/types/summaryTypes.ts +++ b/src/abacus-ts/types/summaryTypes.ts @@ -147,4 +147,13 @@ export type SubaccountOrder = { marginMode: MarginMode | undefined; }; +export type PendingIsolatedPosition = { + marketId: string; + displayId: string; + assetId: string; + displayableAsset: string; + equity: BigNumber; + orders: SubaccountOrder[]; +}; + export type LiveTrade = BaseTrade;