From 98b5260d93893076d360b20dfa78479274974bdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20G=C5=82ownia?= Date: Fri, 27 Jan 2023 09:39:39 +0100 Subject: [PATCH] feat: fix positions and margins providers update (#2753) --- .../select-market/select-market.tsx | 14 +- .../hooks/use-ethereum-transaction-toasts.tsx | 6 +- .../positions/src/lib/margin-data-provider.ts | 72 ++++----- .../src/lib/positions-data-providers.spec.ts | 152 +++++++----------- .../src/lib/positions-data-providers.ts | 55 +++---- libs/positions/src/lib/use-market-margin.tsx | 28 +--- .../lib/use-market-position-open-volume.tsx | 20 +-- 7 files changed, 140 insertions(+), 207 deletions(-) diff --git a/apps/trading/components/select-market/select-market.tsx b/apps/trading/components/select-market/select-market.tsx index 4847c6466..ae465ab7d 100644 --- a/apps/trading/components/select-market/select-market.tsx +++ b/apps/trading/components/select-market/select-market.tsx @@ -112,7 +112,7 @@ export const SelectMarketPopover = ({ } = useMarketList(); const variables = useMemo(() => ({ partyId: pubKey }), [pubKey]); const { - data: party, + data: positions, loading: positionsLoading, reload, } = useDataProvider({ @@ -132,11 +132,9 @@ export const SelectMarketPopover = ({ const markets = useMemo( () => data?.filter((market) => - party?.positionsConnection?.edges?.find( - (edge) => edge.node.market.id === market.id - ) + positions?.find((node) => node.market.id === market.id) ), - [data, party] + [data, positions] ); useEffect(() => { @@ -172,15 +170,13 @@ export const SelectMarketPopover = ({ ) : ( - {pubKey && (party?.positionsConnection?.edges?.length ?? 0) > 0 ? ( + {pubKey && (positions?.length ?? 0) > 0 ? ( <> {t('My markets')} edge.node) - .map((edge) => edge.node)} + positions={positions || undefined} onSelect={onSelectMarket} onCellClick={onCellClick} headers={columnHeadersPositionMarkets} diff --git a/apps/trading/lib/hooks/use-ethereum-transaction-toasts.tsx b/apps/trading/lib/hooks/use-ethereum-transaction-toasts.tsx index a881d5e8b..8e9e566bd 100644 --- a/apps/trading/lib/hooks/use-ethereum-transaction-toasts.tsx +++ b/apps/trading/lib/hooks/use-ethereum-transaction-toasts.tsx @@ -96,7 +96,7 @@ const EthTxPendingToastContent = ({ tx }: EthTxToastContentProps) => { return (

{t('Awaiting confirmation')}

-

{t('Please wait for your transaction to be confirmed')}

+

{t('Please wait for your transaction to be confirmed.')}

@@ -138,7 +138,7 @@ const EthTxConfirmedToastContent = ({ tx }: EthTxToastContentProps) => { return (

{t('Transaction confirmed')}

-

{t('Your transaction has been confirmed')}

+

{t('Your transaction has been confirmed.')}

@@ -153,7 +153,7 @@ const EthTxCompletedToastContent = ({ tx }: EthTxToastContentProps) => { {t('Processing')} {isDeposit && t('deposit')}

- {t('Your transaction has been completed.')} + {t('Your transaction has been completed.')}{' '} {isDeposit && t('Waiting for deposit confirmation.')}

diff --git a/libs/positions/src/lib/margin-data-provider.ts b/libs/positions/src/lib/margin-data-provider.ts index 0ebc32f19..7a15b4e1d 100644 --- a/libs/positions/src/lib/margin-data-provider.ts +++ b/libs/positions/src/lib/margin-data-provider.ts @@ -1,64 +1,62 @@ import produce from 'immer'; -import { makeDataProvider } from '@vegaprotocol/react-helpers'; +import { + makeDataProvider, + removePaginationWrapper, +} from '@vegaprotocol/react-helpers'; import { MarginsSubscriptionDocument, MarginsDocument, } from './__generated__/Positions'; import type { MarginsQuery, + MarginFieldsFragment, MarginsSubscriptionSubscription, } from './__generated__/Positions'; const update = ( - data: MarginsQuery['party'], + data: MarginFieldsFragment[], delta: MarginsSubscriptionSubscription['margins'] ) => { return produce(data, (draft) => { const { marketId } = delta; - if (marketId && draft?.marginsConnection?.edges) { - const index = draft.marginsConnection.edges.findIndex( - (edge) => edge.node.market.id === marketId - ); - if (index !== -1) { - const currNode = draft.marginsConnection.edges[index].node; - draft.marginsConnection.edges[index].node = { - ...currNode, - maintenanceLevel: delta.maintenanceLevel, - searchLevel: delta.searchLevel, - initialLevel: delta.initialLevel, - collateralReleaseLevel: delta.collateralReleaseLevel, - }; - } else { - draft.marginsConnection.edges.unshift({ - __typename: 'MarginEdge', - node: { - __typename: 'MarginLevels', - market: { - __typename: 'Market', - id: delta.marketId, - }, - maintenanceLevel: delta.maintenanceLevel, - searchLevel: delta.searchLevel, - initialLevel: delta.initialLevel, - collateralReleaseLevel: delta.collateralReleaseLevel, - asset: { - __typename: 'Asset', - id: delta.asset, - }, - }, - }); - } + const index = draft.findIndex((node) => node.market.id === marketId); + if (index !== -1) { + const currNode = draft[index]; + draft[index] = { + ...currNode, + maintenanceLevel: delta.maintenanceLevel, + searchLevel: delta.searchLevel, + initialLevel: delta.initialLevel, + collateralReleaseLevel: delta.collateralReleaseLevel, + }; + } else { + draft.unshift({ + __typename: 'MarginLevels', + market: { + __typename: 'Market', + id: delta.marketId, + }, + maintenanceLevel: delta.maintenanceLevel, + searchLevel: delta.searchLevel, + initialLevel: delta.initialLevel, + collateralReleaseLevel: delta.collateralReleaseLevel, + asset: { + __typename: 'Asset', + id: delta.asset, + }, + }); } }); }; -const getData = (responseData: MarginsQuery) => responseData.party; +const getData = (responseData: MarginsQuery) => + removePaginationWrapper(responseData.party?.marginsConnection?.edges) || []; const getDelta = (subscriptionData: MarginsSubscriptionSubscription) => subscriptionData.margins; export const marginsDataProvider = makeDataProvider< MarginsQuery, - MarginsQuery['party'], + MarginFieldsFragment[], MarginsSubscriptionSubscription, MarginsSubscriptionSubscription['margins'] >({ diff --git a/libs/positions/src/lib/positions-data-providers.spec.ts b/libs/positions/src/lib/positions-data-providers.spec.ts index 97e367c97..9dbbd80c9 100644 --- a/libs/positions/src/lib/positions-data-providers.spec.ts +++ b/libs/positions/src/lib/positions-data-providers.spec.ts @@ -1,7 +1,10 @@ import * as Schema from '@vegaprotocol/types'; import type { Account } from '@vegaprotocol/accounts'; import type { MarketWithData } from '@vegaprotocol/market-list'; -import type { PositionsQuery, MarginsQuery } from './__generated__/Positions'; +import type { + PositionFieldsFragment, + MarginFieldsFragment, +} from './__generated__/Positions'; import { getMetrics, rejoinPositionData } from './positions-data-providers'; const accounts = [ @@ -63,47 +66,32 @@ const accounts = [ }, ] as Account[]; -const positions: PositionsQuery = { - party: { - __typename: 'Party', - id: '02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65', - positionsConnection: { - __typename: 'PositionConnection', - edges: [ - { - __typename: 'PositionEdge', - node: { - __typename: 'Position', - openVolume: '100', - averageEntryPrice: '8993727', - updatedAt: '2022-07-28T14:53:54.725477Z', - realisedPNL: '0', - unrealisedPNL: '43804770', - market: { - __typename: 'Market', - id: '5e6035fe6a6df78c9ec44b333c231e63d357acef0a0620d2c243f5865d1dc0d8', - }, - }, - }, - { - __typename: 'PositionEdge', - node: { - __typename: 'Position', - openVolume: '-100', - realisedPNL: '0', - unrealisedPNL: '-9112700', - averageEntryPrice: '840158', - updatedAt: '2022-07-28T15:09:34.441143Z', - market: { - __typename: 'Market', - id: '10c4b1114d2f6fda239b73d018bca55888b6018f0ac70029972a17fea0a6a56e', - }, - }, - }, - ], +const positions: PositionFieldsFragment[] = [ + { + __typename: 'Position', + openVolume: '100', + averageEntryPrice: '8993727', + updatedAt: '2022-07-28T14:53:54.725477Z', + realisedPNL: '0', + unrealisedPNL: '43804770', + market: { + __typename: 'Market', + id: '5e6035fe6a6df78c9ec44b333c231e63d357acef0a0620d2c243f5865d1dc0d8', }, }, -}; + { + __typename: 'Position', + openVolume: '-100', + realisedPNL: '0', + unrealisedPNL: '-9112700', + averageEntryPrice: '840158', + updatedAt: '2022-07-28T15:09:34.441143Z', + market: { + __typename: 'Market', + id: '10c4b1114d2f6fda239b73d018bca55888b6018f0ac70029972a17fea0a6a56e', + }, + }, +]; const marketsData = [ { @@ -162,60 +150,44 @@ const marketsData = [ }, ] as MarketWithData[]; -const margins: MarginsQuery = { - party: { - id: '02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65', - marginsConnection: { - edges: [ - { - __typename: 'MarginEdge', - node: { - __typename: 'MarginLevels', - maintenanceLevel: '0', - searchLevel: '0', - initialLevel: '0', - collateralReleaseLevel: '0', - market: { - __typename: 'Market', - id: '5e6035fe6a6df78c9ec44b333c231e63d357acef0a0620d2c243f5865d1dc0d8', - }, - asset: { - __typename: 'Asset', - id: 'tDAI-id', - }, - }, - }, - { - __typename: 'MarginEdge', - node: { - __typename: 'MarginLevels', - maintenanceLevel: '0', - searchLevel: '0', - initialLevel: '0', - collateralReleaseLevel: '0', - market: { - __typename: 'Market', - id: '10c4b1114d2f6fda239b73d018bca55888b6018f0ac70029972a17fea0a6a56e', - }, - asset: { - __typename: 'Asset', - id: 'tDAI-id', - }, - }, - }, - ], - __typename: 'MarginConnection', +const margins: MarginFieldsFragment[] = [ + { + __typename: 'MarginLevels', + maintenanceLevel: '0', + searchLevel: '0', + initialLevel: '0', + collateralReleaseLevel: '0', + market: { + __typename: 'Market', + id: '5e6035fe6a6df78c9ec44b333c231e63d357acef0a0620d2c243f5865d1dc0d8', + }, + asset: { + __typename: 'Asset', + id: 'tDAI-id', }, - __typename: 'Party', }, -}; - + { + __typename: 'MarginLevels', + maintenanceLevel: '0', + searchLevel: '0', + initialLevel: '0', + collateralReleaseLevel: '0', + market: { + __typename: 'Market', + id: '10c4b1114d2f6fda239b73d018bca55888b6018f0ac70029972a17fea0a6a56e', + }, + asset: { + __typename: 'Asset', + id: 'tDAI-id', + }, + }, +]; describe('getMetrics && rejoinPositionData', () => { it('returns positions metrics', () => { const positionsRejoined = rejoinPositionData( - positions.party, + positions, marketsData, - margins.party + margins ); const metrics = getMetrics(positionsRejoined, accounts || null); expect(metrics.length).toEqual(2); @@ -223,9 +195,9 @@ describe('getMetrics && rejoinPositionData', () => { it('calculates metrics', () => { const positionsRejoined = rejoinPositionData( - positions.party, + positions, marketsData, - margins.party + margins ); const metrics = getMetrics(positionsRejoined, accounts || null); diff --git a/libs/positions/src/lib/positions-data-providers.ts b/libs/positions/src/lib/positions-data-providers.ts index d48b69a8a..4fcce32da 100644 --- a/libs/positions/src/lib/positions-data-providers.ts +++ b/libs/positions/src/lib/positions-data-providers.ts @@ -8,14 +8,15 @@ import { toBigNum } from '@vegaprotocol/react-helpers'; import { makeDataProvider, makeDerivedDataProvider, + removePaginationWrapper, } from '@vegaprotocol/react-helpers'; import * as Schema from '@vegaprotocol/types'; import type { MarketWithData } from '@vegaprotocol/market-list'; import { marketsWithDataProvider } from '@vegaprotocol/market-list'; import type { PositionsQuery, + PositionFieldsFragment, PositionsSubscriptionSubscription, - MarginsQuery, MarginFieldsFragment, } from './__generated__/Positions'; import { @@ -170,20 +171,17 @@ export const getMetrics = ( }; export const update = ( - data: PositionsQuery['party'], + data: PositionFieldsFragment[], deltas: PositionsSubscriptionSubscription['positions'] ) => { return produce(data, (draft) => { deltas.forEach((delta) => { - if (!draft?.positionsConnection?.edges || !delta) { - return; - } - const index = draft.positionsConnection.edges.findIndex( - (edge) => edge.node.market.id === delta.marketId + const index = draft.findIndex( + (node) => node.market.id === delta.marketId ); if (index !== -1) { - const currNode = draft.positionsConnection.edges[index].node; - draft.positionsConnection.edges[index].node = { + const currNode = draft[index]; + draft[index] = { ...currNode, realisedPNL: delta.realisedPNL, unrealisedPNL: delta.unrealisedPNL, @@ -192,15 +190,12 @@ export const update = ( updatedAt: delta.updatedAt, }; } else { - draft.positionsConnection.edges.unshift({ - __typename: 'PositionEdge', - node: { - ...delta, - __typename: 'Position', - market: { - __typename: 'Market', - id: delta.marketId, - }, + draft.unshift({ + ...delta, + __typename: 'Position', + market: { + __typename: 'Market', + id: delta.marketId, }, }); } @@ -210,29 +205,29 @@ export const update = ( export const positionsDataProvider = makeDataProvider< PositionsQuery, - PositionsQuery['party'], + PositionFieldsFragment[], PositionsSubscriptionSubscription, PositionsSubscriptionSubscription['positions'] >({ query: PositionsDocument, subscriptionQuery: PositionsSubscriptionDocument, update, - getData: (responseData: PositionsQuery) => responseData.party, + getData: (responseData: PositionsQuery) => + removePaginationWrapper(responseData.party?.positionsConnection?.edges) || + [], getDelta: (subscriptionData: PositionsSubscriptionSubscription) => subscriptionData.positions, }); const upgradeMarginsConnection = ( marketId: string, - margins: MarginsQuery['party'] | null + margins: MarginFieldsFragment[] | null ) => { - if (marketId && margins?.marginsConnection?.edges) { + if (marketId && margins) { const index = - margins.marginsConnection.edges.findIndex( - (edge) => edge.node.market.id === marketId - ) ?? -1; + margins.findIndex((node) => node.market.id === marketId) ?? -1; if (index >= 0) { - const marginLevel = margins.marginsConnection.edges[index].node; + const marginLevel = margins[index]; return { maintenanceLevel: marginLevel.maintenanceLevel, searchLevel: marginLevel.searchLevel, @@ -244,12 +239,12 @@ const upgradeMarginsConnection = ( }; export const rejoinPositionData = ( - positions: PositionsQuery['party'] | null, + positions: PositionFieldsFragment[] | null, marketsData: MarketWithData[] | null, - margins: MarginsQuery['party'] | null + margins: MarginFieldsFragment[] | null ): PositionRejoined[] | null => { - if (positions?.positionsConnection?.edges && marketsData && margins) { - return positions.positionsConnection.edges.map(({ node }) => { + if (positions && marketsData && margins) { + return positions.map((node) => { return { realisedPNL: node.realisedPNL, openVolume: node.openVolume, diff --git a/libs/positions/src/lib/use-market-margin.tsx b/libs/positions/src/lib/use-market-margin.tsx index 8452dab60..5fa1d951c 100644 --- a/libs/positions/src/lib/use-market-margin.tsx +++ b/libs/positions/src/lib/use-market-margin.tsx @@ -2,30 +2,17 @@ import { useCallback, useState } from 'react'; import { useVegaWallet } from '@vegaprotocol/wallet'; import { useDataProvider } from '@vegaprotocol/react-helpers'; import { marginsDataProvider } from './margin-data-provider'; -import type { - MarginsQuery, - MarginsSubscriptionSubscription, -} from './__generated__/Positions'; - -const getMarketMarginPosition = ({ - data, - marketId, -}: { - data: MarginsQuery['party'] | null; - marketId: string; -}) => { - const positions = - data?.marginsConnection?.edges?.map((item) => item.node) ?? []; - return positions.find((item) => item.market.id === marketId); -}; +import type { MarginFieldsFragment } from './__generated__/Positions'; export const useMarketMargin = (marketId: string) => { const { pubKey } = useVegaWallet(); const [marginLevel, setMarginLevel] = useState(''); const update = useCallback( - ({ data }: { data: MarginsQuery['party'] | null }) => { - const marginMarketPosition = getMarketMarginPosition({ data, marketId }); + ({ data }: { data: MarginFieldsFragment[] | null }) => { + const marginMarketPosition = data?.find( + (item) => item.market.id === marketId + ); if (marginMarketPosition?.maintenanceLevel) { setMarginLevel(marginMarketPosition?.maintenanceLevel || ''); } @@ -34,10 +21,7 @@ export const useMarketMargin = (marketId: string) => { [setMarginLevel, marketId] ); - useDataProvider< - MarginsQuery['party'], - MarginsSubscriptionSubscription['margins'] - >({ + useDataProvider({ dataProvider: marginsDataProvider, variables: { partyId: pubKey || '' }, skip: !pubKey || !marketId, diff --git a/libs/positions/src/lib/use-market-position-open-volume.tsx b/libs/positions/src/lib/use-market-position-open-volume.tsx index c2764d53a..b1af71c9c 100644 --- a/libs/positions/src/lib/use-market-position-open-volume.tsx +++ b/libs/positions/src/lib/use-market-position-open-volume.tsx @@ -3,28 +3,16 @@ import { useVegaWallet } from '@vegaprotocol/wallet'; import { positionsDataProvider } from './positions-data-providers'; import { useDataProvider } from '@vegaprotocol/react-helpers'; import type { - PositionsQuery, + PositionFieldsFragment, PositionsSubscriptionSubscription, } from './__generated__/Positions'; -const getMarketPosition = ({ - data, - marketId, -}: { - data: PositionsQuery['party']; - marketId: string; -}) => { - const positions = - data?.positionsConnection?.edges?.map((item) => item.node) ?? []; - return positions.find((item) => item.market.id === marketId); -}; - export const useMarketPositionOpenVolume = (marketId: string) => { const { pubKey } = useVegaWallet(); const [openVolume, setOpenVolume] = useState(''); const update = useCallback( - ({ data }: { data: PositionsQuery['party'] | undefined }) => { - const position = getMarketPosition({ data, marketId }); + ({ data }: { data: PositionFieldsFragment[] | null }) => { + const position = data?.find((node) => node.market.id === marketId); if (position?.openVolume) { setOpenVolume(position?.openVolume || ''); } @@ -34,7 +22,7 @@ export const useMarketPositionOpenVolume = (marketId: string) => { ); useDataProvider< - PositionsQuery['party'], + PositionFieldsFragment[], PositionsSubscriptionSubscription['positions'] >({ dataProvider: positionsDataProvider,