From 0872a14f44f21eafca3e9cc0e59903cbe7d1d37b Mon Sep 17 00:00:00 2001 From: Maciek Date: Mon, 2 Oct 2023 16:38:22 +0200 Subject: [PATCH] feat(positions): close position with max possible size (#4940) --- .../src/lib/positions-manager.spec.tsx | 39 +++++++++++++++++++ libs/positions/src/lib/positions-manager.tsx | 6 +-- .../src/lib/positions-table.spec.tsx | 28 +------------ libs/positions/src/lib/positions.mock.ts | 29 ++++++++++++++ libs/utils/src/index.ts | 1 + libs/utils/src/lib/constants.ts | 1 + 6 files changed, 74 insertions(+), 30 deletions(-) create mode 100644 libs/positions/src/lib/positions-manager.spec.tsx create mode 100644 libs/utils/src/lib/constants.ts diff --git a/libs/positions/src/lib/positions-manager.spec.tsx b/libs/positions/src/lib/positions-manager.spec.tsx new file mode 100644 index 000000000..2f02b6f8b --- /dev/null +++ b/libs/positions/src/lib/positions-manager.spec.tsx @@ -0,0 +1,39 @@ +import { render, screen, fireEvent } from '@testing-library/react'; +import { PositionsManager } from './positions-manager'; +import { positionsMarketsProvider } from './positions-data-providers'; +import { singleRow } from './positions.mock'; +import { MockedProvider } from '@apollo/client/testing'; +import { MAXGOINT64 } from '@vegaprotocol/utils'; + +const mockCreate = jest.fn(); +jest.mock('@vegaprotocol/wallet', () => ({ + ...jest.requireActual('@vegaprotocol/wallet'), + useVegaWallet: jest.fn(() => ({ pubKey: 'partyId' })), + useVegaTransactionStore: jest.fn(() => mockCreate), +})); +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const mockUseDataProvider = (args: any) => { + if (args.dataProvider === positionsMarketsProvider) { + return { data: ['market-1', 'market-2'] }; + } + return { data: [singleRow] }; +}; +jest.mock('@vegaprotocol/data-provider', () => ({ + ...jest.requireActual('@vegaprotocol/data-provider'), + useDataProvider: jest.fn((args) => mockUseDataProvider(args)), +})); + +describe('PositionsManager', () => { + it('should close position with max uint64', async () => { + render(, { + wrapper: MockedProvider, + }); + expect(await screen.getByTestId('close-position')).toBeInTheDocument(); + + fireEvent.click(screen.getByTestId('close-position')); + + expect( + mockCreate.mock.lastCall[0].batchMarketInstructions.submissions[0].size + ).toEqual(MAXGOINT64); + }); +}); diff --git a/libs/positions/src/lib/positions-manager.tsx b/libs/positions/src/lib/positions-manager.tsx index 521ae1b45..98bf332cc 100644 --- a/libs/positions/src/lib/positions-manager.tsx +++ b/libs/positions/src/lib/positions-manager.tsx @@ -1,7 +1,7 @@ import { useCallback } from 'react'; import { PositionsTable } from './positions-table'; import * as Schema from '@vegaprotocol/types'; -import { useVegaTransactionStore } from '@vegaprotocol/wallet'; +import { useVegaTransactionStore, useVegaWallet } from '@vegaprotocol/wallet'; import { t } from '@vegaprotocol/i18n'; import { useDataProvider } from '@vegaprotocol/data-provider'; import { @@ -9,7 +9,7 @@ import { positionsMarketsProvider, } from './positions-data-providers'; import type { useDataGridEvents } from '@vegaprotocol/datagrid'; -import { useVegaWallet } from '@vegaprotocol/wallet'; +import { MAXGOINT64 } from '@vegaprotocol/utils'; interface PositionsManagerProps { partyIds: string[]; @@ -46,7 +46,7 @@ export const PositionsManager = ({ side: openVolume.startsWith('-') ? Schema.Side.SIDE_BUY : Schema.Side.SIDE_SELL, - size: openVolume.replace('-', ''), + size: MAXGOINT64, // improvement for avoiding leftovers filled in the meantime when close request has been sent reduceOnly: true, }, ], diff --git a/libs/positions/src/lib/positions-table.spec.tsx b/libs/positions/src/lib/positions-table.spec.tsx index ed2aebf4c..ec6e619bc 100644 --- a/libs/positions/src/lib/positions-table.spec.tsx +++ b/libs/positions/src/lib/positions-table.spec.tsx @@ -6,6 +6,7 @@ import * as Schema from '@vegaprotocol/types'; import { PositionStatus } from '@vegaprotocol/types'; import type { ICellRendererParams } from 'ag-grid-community'; import { addDecimalsFormatNumber } from '@vegaprotocol/utils'; +import { singleRow } from './positions.mock'; jest.mock('./liquidation-price', () => ({ LiquidationPrice: () => ( @@ -13,33 +14,6 @@ jest.mock('./liquidation-price', () => ({ ), })); -const singleRow: Position = { - partyId: 'partyId', - assetId: 'asset-id', - assetSymbol: 'BTC', - averageEntryPrice: '133', - currentLeverage: 1.1, - assetDecimals: 2, // this is settlementAsset.decimals - quantum: '0.1', - lossSocializationAmount: '0', - marginAccountBalance: '12345600', - marketDecimalPlaces: 1, - marketId: 'string', - marketCode: 'ETHBTC.QM21', - marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS, - marketState: Schema.MarketState.STATE_ACTIVE, - markPrice: '123', - notional: '12300', - openVolume: '100', - positionDecimalPlaces: 0, - realisedPNL: '123', - status: PositionStatus.POSITION_STATUS_UNSPECIFIED, - totalBalance: '123456', - unrealisedPNL: '456', - updatedAt: '2022-07-27T15:02:58.400Z', - productType: 'Future', -}; - describe('Positions', () => { const renderComponent = async (rowData: Position) => { await act(async () => { diff --git a/libs/positions/src/lib/positions.mock.ts b/libs/positions/src/lib/positions.mock.ts index 635eda23d..5d906402b 100644 --- a/libs/positions/src/lib/positions.mock.ts +++ b/libs/positions/src/lib/positions.mock.ts @@ -10,6 +10,8 @@ import type { MarginsQuery, MarginFieldsFragment, } from '@vegaprotocol/accounts'; +import type { Position } from './positions-data-providers'; +import * as Schema from '@vegaprotocol/types'; export const positionsQuery = ( override?: PartialDeep @@ -168,3 +170,30 @@ const marginsFields: MarginFieldsFragment[] = [ }, }, ]; + +export const singleRow: Position = { + partyId: 'partyId', + assetId: 'asset-id', + assetSymbol: 'BTC', + averageEntryPrice: '133', + currentLeverage: 1.1, + assetDecimals: 2, // this is settlementAsset.decimals + quantum: '0.1', + lossSocializationAmount: '0', + marginAccountBalance: '12345600', + marketDecimalPlaces: 1, + marketId: 'string', + marketCode: 'ETHBTC.QM21', + marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS, + marketState: Schema.MarketState.STATE_ACTIVE, + markPrice: '123', + notional: '12300', + openVolume: '100', + positionDecimalPlaces: 0, + realisedPNL: '123', + status: PositionStatus.POSITION_STATUS_UNSPECIFIED, + totalBalance: '123456', + unrealisedPNL: '456', + updatedAt: '2022-07-27T15:02:58.400Z', + productType: 'Future', +}; diff --git a/libs/utils/src/index.ts b/libs/utils/src/index.ts index d1e76477f..7babb85f6 100644 --- a/libs/utils/src/index.ts +++ b/libs/utils/src/index.ts @@ -15,3 +15,4 @@ export * from './lib/time'; export * from './lib/validate'; export * from './lib/resolve-network-name'; export * from './lib/is-test-env'; +export * from './lib/constants'; diff --git a/libs/utils/src/lib/constants.ts b/libs/utils/src/lib/constants.ts new file mode 100644 index 000000000..718b3e46f --- /dev/null +++ b/libs/utils/src/lib/constants.ts @@ -0,0 +1 @@ +export const MAXGOINT64 = '9223372036854775807';