feat: fix positions and margins providers update (#2753)

This commit is contained in:
Bartłomiej Głownia 2023-01-27 09:39:39 +01:00 committed by GitHub
parent 613262f7a5
commit 98b5260d93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 140 additions and 207 deletions

View File

@ -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 = ({
</div>
) : (
<table className="relative text-sm w-full whitespace-nowrap">
{pubKey && (party?.positionsConnection?.edges?.length ?? 0) > 0 ? (
{pubKey && (positions?.length ?? 0) > 0 ? (
<>
<TableTitle>{t('My markets')}</TableTitle>
<SelectAllMarketsTableBody
inViewRoot={inViewRoot}
markets={markets}
positions={party?.positionsConnection?.edges
?.filter((edge) => edge.node)
.map((edge) => edge.node)}
positions={positions || undefined}
onSelect={onSelectMarket}
onCellClick={onCellClick}
headers={columnHeadersPositionMarkets}

View File

@ -96,7 +96,7 @@ const EthTxPendingToastContent = ({ tx }: EthTxToastContentProps) => {
return (
<div>
<h3 className="font-bold">{t('Awaiting confirmation')}</h3>
<p>{t('Please wait for your transaction to be confirmed')}</p>
<p>{t('Please wait for your transaction to be confirmed.')}</p>
<EtherscanLink tx={tx} />
<EthTransactionDetails tx={tx} />
</div>
@ -138,7 +138,7 @@ const EthTxConfirmedToastContent = ({ tx }: EthTxToastContentProps) => {
return (
<div>
<h3 className="font-bold">{t('Transaction confirmed')}</h3>
<p>{t('Your transaction has been confirmed')}</p>
<p>{t('Your transaction has been confirmed.')}</p>
<EtherscanLink tx={tx} />
<EthTransactionDetails tx={tx} />
</div>
@ -153,7 +153,7 @@ const EthTxCompletedToastContent = ({ tx }: EthTxToastContentProps) => {
{t('Processing')} {isDeposit && t('deposit')}
</h3>
<p>
{t('Your transaction has been completed.')}
{t('Your transaction has been completed.')}{' '}
{isDeposit && t('Waiting for deposit confirmation.')}
</p>
<EtherscanLink tx={tx} />

View File

@ -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']
>({

View File

@ -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);

View File

@ -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,

View File

@ -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<string>('');
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,

View File

@ -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<string>('');
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,