fix(positions): rework of the liquidation tooltip (#6070)
Co-authored-by: bwallacee <ben@vega.xyz>
This commit is contained in:
parent
891e0d3d2f
commit
01e87443ee
@ -341,6 +341,7 @@ describe('Closed', () => {
|
|||||||
oracleDataMock,
|
oracleDataMock,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
await waitFor(async () => {
|
||||||
const actionCell = screen
|
const actionCell = screen
|
||||||
.getAllByRole('gridcell')
|
.getAllByRole('gridcell')
|
||||||
.find((el) => el.getAttribute('col-id') === 'market-actions');
|
.find((el) => el.getAttribute('col-id') === 'market-actions');
|
||||||
@ -367,6 +368,7 @@ describe('Closed', () => {
|
|||||||
screen.getByRole('menuitem', { name: 'View successor market' })
|
screen.getByRole('menuitem', { name: 'View successor market' })
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('successor market should be visible', async () => {
|
it('successor market should be visible', async () => {
|
||||||
const marketsWithSuccessorID = [
|
const marketsWithSuccessorID = [
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { OrderbookManager } from '@vegaprotocol/market-depth';
|
import { OrderbookManager } from '@vegaprotocol/market-depth';
|
||||||
import { ViewType, useSidebar } from '../sidebar';
|
import { ViewType, useSidebar } from '../sidebar';
|
||||||
import { useDealTicketFormValues } from '@vegaprotocol/deal-ticket';
|
import { useDealTicketFormValues } from '@vegaprotocol/react-helpers';
|
||||||
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
||||||
|
|
||||||
export const OrderbookContainer = ({ marketId }: { marketId: string }) => {
|
export const OrderbookContainer = ({ marketId }: { marketId: string }) => {
|
||||||
|
@ -4,7 +4,9 @@ from vega_sim.null_service import VegaServiceNull
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
from conftest import init_vega, cleanup_container
|
from conftest import init_vega, cleanup_container
|
||||||
from fixtures.market import setup_continuous_market
|
from fixtures.market import setup_continuous_market
|
||||||
from actions.utils import wait_for_toast_confirmation
|
from actions.vega import submit_order
|
||||||
|
from actions.utils import wait_for_toast_confirmation, change_keys
|
||||||
|
from wallet_config import PARTY_C, MM_WALLET
|
||||||
|
|
||||||
order_size = "order-size"
|
order_size = "order-size"
|
||||||
order_price = "order-price"
|
order_price = "order-price"
|
||||||
@ -149,3 +151,27 @@ def test_connect_vega_wallet(continuous_market, page: Page):
|
|||||||
# TODO: accept wallet connection and assert wallet is connected.
|
# TODO: accept wallet connection and assert wallet is connected.
|
||||||
expect(page.get_by_test_id("order-type-Limit")).to_be_checked()
|
expect(page.get_by_test_id("order-type-Limit")).to_be_checked()
|
||||||
expect(page.get_by_test_id("order-price")).to_have_value("101")
|
expect(page.get_by_test_id("order-price")).to_have_value("101")
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||||
|
def test_liquidated_tooltip(continuous_market, vega: VegaServiceNull, page: Page):
|
||||||
|
tdai_id = vega.find_asset_id(symbol="tDAI")
|
||||||
|
vega.mint(
|
||||||
|
PARTY_C.name,
|
||||||
|
asset=tdai_id,
|
||||||
|
amount=20,
|
||||||
|
)
|
||||||
|
vega.wait_fn(1)
|
||||||
|
vega.wait_for_total_catchup()
|
||||||
|
submit_order(vega, PARTY_C.name, continuous_market, "SIDE_BUY", 1, 110)
|
||||||
|
submit_order(vega, "Key 1", continuous_market, "SIDE_SELL", 1, 110)
|
||||||
|
vega.wait_fn(1)
|
||||||
|
vega.wait_for_total_catchup()
|
||||||
|
page.goto(f"/#/markets/{continuous_market}")
|
||||||
|
change_keys(page, vega, PARTY_C.name)
|
||||||
|
submit_order(vega, MM_WALLET.name, continuous_market, "SIDE_BUY", 100, 90)
|
||||||
|
submit_order(vega, "Key 1", continuous_market, "SIDE_SELL", 100, 90)
|
||||||
|
vega.wait_fn(1)
|
||||||
|
vega.wait_for_total_catchup()
|
||||||
|
page.locator('[id="cell-openVolume-0"]').hover()
|
||||||
|
expect(page.get_by_test_id("tooltip-content").first).to_contain_text("")
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
|
||||||
export const positiveClassNames =
|
export const positiveClassNames =
|
||||||
'text-market-green-600 dark:text-market-green';
|
'text-market-green-600 dark:text-market-green';
|
||||||
export const negativeClassNames = 'text-market-red dark:text-market-red';
|
export const negativeClassNames = 'text-market-red dark:text-market-red';
|
||||||
|
|
||||||
|
export const zeroClassNames = 'text-vega-orange dark:text-vega-orange';
|
||||||
|
|
||||||
const isPositive = ({ value }: { value: string | bigint | number }) =>
|
const isPositive = ({ value }: { value: string | bigint | number }) =>
|
||||||
!!value &&
|
!!value &&
|
||||||
((typeof value === 'string' && !value.startsWith('-')) ||
|
((typeof value === 'string' && !value.startsWith('-')) ||
|
||||||
@ -12,6 +16,9 @@ const isNegative = ({ value }: { value: string | bigint | number }) =>
|
|||||||
((typeof value === 'string' && value.startsWith('-')) ||
|
((typeof value === 'string' && value.startsWith('-')) ||
|
||||||
((typeof value === 'number' || typeof value === 'bigint') && value < 0));
|
((typeof value === 'number' || typeof value === 'bigint') && value < 0));
|
||||||
|
|
||||||
|
export const isZero = ({ value }: { value: string | bigint | number }) =>
|
||||||
|
BigNumber(value.toString()).isZero();
|
||||||
|
|
||||||
export const signedNumberCssClass = (value: string | bigint | number) => {
|
export const signedNumberCssClass = (value: string | bigint | number) => {
|
||||||
if (isPositive({ value })) {
|
if (isPositive({ value })) {
|
||||||
return positiveClassNames;
|
return positiveClassNames;
|
||||||
|
@ -2,7 +2,7 @@ import { useVegaTransactionStore } from '@vegaprotocol/web3';
|
|||||||
import {
|
import {
|
||||||
isStopOrderType,
|
isStopOrderType,
|
||||||
useDealTicketFormValues,
|
useDealTicketFormValues,
|
||||||
} from '../../hooks/use-form-values';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import { StopOrder } from './deal-ticket-stop-order';
|
import { StopOrder } from './deal-ticket-stop-order';
|
||||||
import {
|
import {
|
||||||
useStaticMarketData,
|
useStaticMarketData,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Controller, type Control } from 'react-hook-form';
|
import { Controller, type Control } from 'react-hook-form';
|
||||||
import type { Market } from '@vegaprotocol/markets';
|
import type { Market } from '@vegaprotocol/markets';
|
||||||
import type { OrderFormValues } from '../../hooks/use-form-values';
|
import type { OrderFormValues } from '@vegaprotocol/react-helpers';
|
||||||
import { determinePriceStep, useValidateAmount } from '@vegaprotocol/utils';
|
import { determinePriceStep, useValidateAmount } from '@vegaprotocol/utils';
|
||||||
import {
|
import {
|
||||||
TradingFormGroup,
|
TradingFormGroup,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Controller, type Control } from 'react-hook-form';
|
import { Controller, type Control } from 'react-hook-form';
|
||||||
import type { Market } from '@vegaprotocol/markets';
|
import type { Market } from '@vegaprotocol/markets';
|
||||||
import type { OrderFormValues } from '../../hooks/use-form-values';
|
import type { OrderFormValues } from '@vegaprotocol/react-helpers';
|
||||||
import { useValidateAmount } from '@vegaprotocol/utils';
|
import { useValidateAmount } from '@vegaprotocol/utils';
|
||||||
import {
|
import {
|
||||||
TradingFormGroup,
|
TradingFormGroup,
|
||||||
|
@ -5,11 +5,11 @@ import { generateMarket } from '../../test-helpers';
|
|||||||
import { StopOrder } from './deal-ticket-stop-order';
|
import { StopOrder } from './deal-ticket-stop-order';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import { MockedProvider } from '@apollo/client/testing';
|
import { MockedProvider } from '@apollo/client/testing';
|
||||||
import type { StopOrderFormValues } from '../../hooks/use-form-values';
|
|
||||||
import {
|
import {
|
||||||
|
type StopOrderFormValues,
|
||||||
DealTicketType,
|
DealTicketType,
|
||||||
useDealTicketFormValues,
|
useDealTicketFormValues,
|
||||||
} from '../../hooks/use-form-values';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import { useFeatureFlags } from '@vegaprotocol/environment';
|
import { useFeatureFlags } from '@vegaprotocol/environment';
|
||||||
import { formatForInput } from '@vegaprotocol/utils';
|
import { formatForInput } from '@vegaprotocol/utils';
|
||||||
import {
|
import {
|
||||||
|
@ -48,8 +48,8 @@ import {
|
|||||||
DealTicketType,
|
DealTicketType,
|
||||||
dealTicketTypeToOrderType,
|
dealTicketTypeToOrderType,
|
||||||
isStopOrderType,
|
isStopOrderType,
|
||||||
} from '../../hooks/use-form-values';
|
type StopOrderFormValues,
|
||||||
import { type StopOrderFormValues } from '../../hooks/use-form-values';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import { mapFormValuesToStopOrdersSubmission } from '../../utils/map-form-values-to-submission';
|
import { mapFormValuesToStopOrdersSubmission } from '../../utils/map-form-values-to-submission';
|
||||||
import { DealTicketFeeDetails } from './deal-ticket-fee-details';
|
import { DealTicketFeeDetails } from './deal-ticket-fee-details';
|
||||||
import { validateExpiration } from '../../utils';
|
import { validateExpiration } from '../../utils';
|
||||||
|
@ -16,7 +16,7 @@ import type { OrdersQuery } from '@vegaprotocol/orders';
|
|||||||
import {
|
import {
|
||||||
DealTicketType,
|
DealTicketType,
|
||||||
useDealTicketFormValues,
|
useDealTicketFormValues,
|
||||||
} from '../../hooks/use-form-values';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import * as positionsTools from '@vegaprotocol/positions';
|
import * as positionsTools from '@vegaprotocol/positions';
|
||||||
import { OrdersDocument } from '@vegaprotocol/orders';
|
import { OrdersDocument } from '@vegaprotocol/orders';
|
||||||
import { formatForInput } from '@vegaprotocol/utils';
|
import { formatForInput } from '@vegaprotocol/utils';
|
||||||
|
@ -67,14 +67,7 @@ import {
|
|||||||
marginModeDataProvider,
|
marginModeDataProvider,
|
||||||
} from '@vegaprotocol/accounts';
|
} from '@vegaprotocol/accounts';
|
||||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||||
import { type OrderFormValues } from '../../hooks';
|
import { usePositionEstimate } from '../../hooks';
|
||||||
import {
|
|
||||||
DealTicketType,
|
|
||||||
dealTicketTypeToOrderType,
|
|
||||||
isStopOrderType,
|
|
||||||
useDealTicketFormValues,
|
|
||||||
usePositionEstimate,
|
|
||||||
} from '../../hooks';
|
|
||||||
import { DealTicketSizeIceberg } from './deal-ticket-size-iceberg';
|
import { DealTicketSizeIceberg } from './deal-ticket-size-iceberg';
|
||||||
import noop from 'lodash/noop';
|
import noop from 'lodash/noop';
|
||||||
import { isNonPersistentOrder } from '../../utils/time-in-force-persistence';
|
import { isNonPersistentOrder } from '../../utils/time-in-force-persistence';
|
||||||
@ -85,6 +78,13 @@ import { DealTicketPriceTakeProfitStopLoss } from './deal-ticket-price-tp-sl';
|
|||||||
import uniqueId from 'lodash/uniqueId';
|
import uniqueId from 'lodash/uniqueId';
|
||||||
import { determinePriceStep, determineSizeStep } from '@vegaprotocol/utils';
|
import { determinePriceStep, determineSizeStep } from '@vegaprotocol/utils';
|
||||||
import { useMaxSize } from '../../hooks/use-max-size';
|
import { useMaxSize } from '../../hooks/use-max-size';
|
||||||
|
import {
|
||||||
|
DealTicketType,
|
||||||
|
type OrderFormValues,
|
||||||
|
dealTicketTypeToOrderType,
|
||||||
|
isStopOrderType,
|
||||||
|
useDealTicketFormValues,
|
||||||
|
} from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
export const REDUCE_ONLY_TOOLTIP =
|
export const REDUCE_ONLY_TOOLTIP =
|
||||||
'"Reduce only" will ensure that this order will not increase the size of an open position. When the order is matched, it will only trade enough volume to bring your open volume towards 0 but never change the direction of your position. If applied to a limit order that is not instantly filled, the order will be stopped.';
|
'"Reduce only" will ensure that this order will not increase the size of an open position. When the order is matched, it will only trade enough volume to bring your open volume towards 0 but never change the direction of your position. If applied to a limit order that is not instantly filled, the order will be stopped.';
|
||||||
|
@ -15,7 +15,7 @@ import {
|
|||||||
import type { Market, StaticMarketData } from '@vegaprotocol/markets';
|
import type { Market, StaticMarketData } from '@vegaprotocol/markets';
|
||||||
import { compileGridData } from '../trading-mode-tooltip';
|
import { compileGridData } from '../trading-mode-tooltip';
|
||||||
import { MarketModeValidationType } from '../../constants';
|
import { MarketModeValidationType } from '../../constants';
|
||||||
import { DealTicketType } from '../../hooks/use-form-values';
|
import { DealTicketType } from '@vegaprotocol/react-helpers';
|
||||||
import * as RadioGroup from '@radix-ui/react-radio-group';
|
import * as RadioGroup from '@radix-ui/react-radio-group';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useFeatureFlags } from '@vegaprotocol/environment';
|
import { useFeatureFlags } from '@vegaprotocol/environment';
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
export * from './__generated__/EstimateOrder';
|
export * from './__generated__/EstimateOrder';
|
||||||
export * from './use-estimate-fees';
|
export * from './use-estimate-fees';
|
||||||
export * from './use-form-values';
|
|
||||||
export * from './use-position-estimate';
|
export * from './use-position-estimate';
|
||||||
|
@ -6,7 +6,7 @@ import type {
|
|||||||
import type {
|
import type {
|
||||||
OrderFormValues,
|
OrderFormValues,
|
||||||
StopOrderFormValues,
|
StopOrderFormValues,
|
||||||
} from '../hooks/use-form-values';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import { removeDecimal, toNanoSeconds } from '@vegaprotocol/utils';
|
import { removeDecimal, toNanoSeconds } from '@vegaprotocol/utils';
|
||||||
import { isPersistentOrder } from './time-in-force-persistence';
|
import { isPersistentOrder } from './time-in-force-persistence';
|
||||||
|
@ -8,7 +8,7 @@ import {
|
|||||||
} from './map-form-values-to-submission';
|
} from './map-form-values-to-submission';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import { OrderTimeInForce, OrderType } from '@vegaprotocol/types';
|
import { OrderTimeInForce, OrderType } from '@vegaprotocol/types';
|
||||||
import type { OrderFormValues } from '../hooks';
|
import type { OrderFormValues } from '@vegaprotocol/react-helpers';
|
||||||
import { type MarketFieldsFragment } from '@vegaprotocol/markets';
|
import { type MarketFieldsFragment } from '@vegaprotocol/markets';
|
||||||
|
|
||||||
describe('mapFormValuesToOrderSubmission', () => {
|
describe('mapFormValuesToOrderSubmission', () => {
|
||||||
|
@ -28,9 +28,9 @@
|
|||||||
"View settlement asset details": "View settlement asset details",
|
"View settlement asset details": "View settlement asset details",
|
||||||
"Worst case": "Worst case",
|
"Worst case": "Worst case",
|
||||||
"Worst case liquidation price": "Worst case liquidation price",
|
"Worst case liquidation price": "Worst case liquidation price",
|
||||||
"You did not have enough {{assetSymbol}} collateral to meet the maintenance margin requirements for your position, so it was closed by the network.": "You did not have enough {{assetSymbol}} collateral to meet the maintenance margin requirements for your position, so it was closed by the network.",
|
|
||||||
"You received less {{assetSymbol}} in gains that you should have when the market moved in your favour. This occurred because one or more other trader(s) were closed out and did not have enough funds to cover their losses, and the market's insurance pool was empty.": "You received less {{assetSymbol}} in gains that you should have when the market moved in your favour. This occurred because one or more other trader(s) were closed out and did not have enough funds to cover their losses, and the market's insurance pool was empty.",
|
"You received less {{assetSymbol}} in gains that you should have when the market moved in your favour. This occurred because one or more other trader(s) were closed out and did not have enough funds to cover their losses, and the market's insurance pool was empty.": "You received less {{assetSymbol}} in gains that you should have when the market moved in your favour. This occurred because one or more other trader(s) were closed out and did not have enough funds to cover their losses, and the market's insurance pool was empty.",
|
||||||
"Your open orders were cancelled.": "Your open orders were cancelled.",
|
"Your open orders were cancelled.": "Your open orders were cancelled.",
|
||||||
"Your position is distressed.": "Your position is distressed.",
|
"Your position is distressed.": "Your position is distressed.",
|
||||||
"Your position was closed.": "Your position was closed."
|
"Your position was closed.": "Your position was closed.",
|
||||||
|
"You did not have enough {{assetSymbol}} to meet the margin required for your position, so it was liquidated by the network at {{price}}.": "You did not have enough {{assetSymbol}} to meet the margin required for your position, so it was liquidated by the network at {{price}}."
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import { PositionStatus } from '@vegaprotocol/types';
|
|||||||
import type { ICellRendererParams } from 'ag-grid-community';
|
import type { ICellRendererParams } from 'ag-grid-community';
|
||||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||||
import { singleRow } from './positions.mock';
|
import { singleRow } from './positions.mock';
|
||||||
|
import { useLatestTrade } from '@vegaprotocol/trades';
|
||||||
|
|
||||||
jest.mock('./liquidation-price', () => ({
|
jest.mock('./liquidation-price', () => ({
|
||||||
LiquidationPrice: () => (
|
LiquidationPrice: () => (
|
||||||
@ -262,26 +263,15 @@ describe('Positions', () => {
|
|||||||
expect(screen.queryByTestId(/icon-/)).not.toBeInTheDocument();
|
expect(screen.queryByTestId(/icon-/)).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders status with warning tooltip if orders were closed', () => {
|
|
||||||
const props = {
|
|
||||||
data: {
|
|
||||||
...singleRow,
|
|
||||||
status: PositionStatus.POSITION_STATUS_ORDERS_CLOSED,
|
|
||||||
},
|
|
||||||
valueFormatted: '100',
|
|
||||||
} as ICellRendererParams;
|
|
||||||
render(<OpenVolumeCell {...props} />);
|
|
||||||
const content = screen.getByText(props.valueFormatted as string);
|
|
||||||
expect(content).toBeInTheDocument();
|
|
||||||
expect(screen.getByTestId(/icon-/)).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders status with warning tooltip if position was closed out', async () => {
|
it('renders status with warning tooltip if position was closed out', async () => {
|
||||||
const props = {
|
(useLatestTrade as jest.Mock).mockReturnValue({
|
||||||
data: {
|
data: {
|
||||||
...singleRow,
|
type: 'TYPE_NETWORK_CLOSE_OUT_BAD',
|
||||||
status: PositionStatus.POSITION_STATUS_CLOSED_OUT,
|
price: '100',
|
||||||
},
|
},
|
||||||
|
});
|
||||||
|
const props = {
|
||||||
|
data: singleRow,
|
||||||
valueFormatted: '100',
|
valueFormatted: '100',
|
||||||
} as ICellRendererParams;
|
} as ICellRendererParams;
|
||||||
render(<OpenVolumeCell {...props} />);
|
render(<OpenVolumeCell {...props} />);
|
||||||
@ -303,31 +293,23 @@ describe('Positions', () => {
|
|||||||
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument();
|
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it.each([
|
it('renders tooltip when positions has been closed out (liquidated)', async () => {
|
||||||
{
|
(useLatestTrade as jest.Mock).mockReturnValue({
|
||||||
status: PositionStatus.POSITION_STATUS_CLOSED_OUT,
|
data: {
|
||||||
text: 'Your position was closed.',
|
type: 'TYPE_NETWORK_CLOSE_OUT_BAD',
|
||||||
|
price: '100',
|
||||||
},
|
},
|
||||||
{
|
|
||||||
status: PositionStatus.POSITION_STATUS_ORDERS_CLOSED,
|
|
||||||
text: 'Your open orders were cancelled.',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
status: PositionStatus.POSITION_STATUS_DISTRESSED,
|
|
||||||
text: 'Your position is distressed.',
|
|
||||||
},
|
|
||||||
])('renders content for $status', async (data) => {
|
|
||||||
await renderComponent({
|
|
||||||
...singleRow,
|
|
||||||
status: data.status,
|
|
||||||
});
|
});
|
||||||
|
await renderComponent(singleRow);
|
||||||
const cells = screen.getAllByRole('gridcell');
|
const cells = screen.getAllByRole('gridcell');
|
||||||
const cell = cells[1];
|
const cell = cells[1];
|
||||||
const tooltipTrigger = cell.querySelector('[data-state="closed"]');
|
const tooltipTrigger = cell.querySelector('[data-state="closed"]');
|
||||||
expect(tooltipTrigger).not.toBeNull();
|
expect(tooltipTrigger).not.toBeNull();
|
||||||
await userEvent.hover(tooltipTrigger as Element);
|
await userEvent.hover(tooltipTrigger as Element);
|
||||||
const tooltip = within(await screen.findByRole('tooltip'));
|
const tooltip = within(await screen.findByRole('tooltip'));
|
||||||
expect(tooltip.getByText(data.text)).toBeInTheDocument();
|
expect(
|
||||||
|
tooltip.getByText('Your position was closed.')
|
||||||
|
).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -13,6 +13,8 @@ import {
|
|||||||
type VegaValueGetterParams,
|
type VegaValueGetterParams,
|
||||||
type TypedDataAgGrid,
|
type TypedDataAgGrid,
|
||||||
type VegaICellRendererParams,
|
type VegaICellRendererParams,
|
||||||
|
zeroClassNames,
|
||||||
|
isZero,
|
||||||
} from '@vegaprotocol/datagrid';
|
} from '@vegaprotocol/datagrid';
|
||||||
import {
|
import {
|
||||||
ButtonLink,
|
ButtonLink,
|
||||||
@ -36,6 +38,7 @@ import {
|
|||||||
MarketTradingMode,
|
MarketTradingMode,
|
||||||
PositionStatus,
|
PositionStatus,
|
||||||
PositionStatusMapping,
|
PositionStatusMapping,
|
||||||
|
TradeType,
|
||||||
} from '@vegaprotocol/types';
|
} from '@vegaprotocol/types';
|
||||||
import { DocsLinks, useFeatureFlags } from '@vegaprotocol/environment';
|
import { DocsLinks, useFeatureFlags } from '@vegaprotocol/environment';
|
||||||
import { PositionActionsDropdown } from './position-actions-dropdown';
|
import { PositionActionsDropdown } from './position-actions-dropdown';
|
||||||
@ -43,6 +46,7 @@ import { LiquidationPrice } from './liquidation-price';
|
|||||||
import { useT } from '../use-t';
|
import { useT } from '../use-t';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
|
import { useLatestTrade } from '@vegaprotocol/trades';
|
||||||
|
|
||||||
interface Props extends TypedDataAgGrid<Position> {
|
interface Props extends TypedDataAgGrid<Position> {
|
||||||
onClose?: (data: Position) => void;
|
onClose?: (data: Position) => void;
|
||||||
@ -258,7 +262,10 @@ export const PositionsTable = ({
|
|||||||
field: 'openVolume',
|
field: 'openVolume',
|
||||||
type: 'rightAligned',
|
type: 'rightAligned',
|
||||||
cellClass: 'font-mono text-right',
|
cellClass: 'font-mono text-right',
|
||||||
cellClassRules: signedNumberCssClassRules,
|
cellClassRules: {
|
||||||
|
...signedNumberCssClassRules,
|
||||||
|
[zeroClassNames]: isZero,
|
||||||
|
},
|
||||||
filter: 'agNumberColumnFilter',
|
filter: 'agNumberColumnFilter',
|
||||||
sortable: false,
|
sortable: false,
|
||||||
filterValueGetter: ({ data }: { data: Position }) => {
|
filterValueGetter: ({ data }: { data: Position }) => {
|
||||||
@ -616,49 +623,51 @@ export const OpenVolumeCell = ({
|
|||||||
data,
|
data,
|
||||||
}: VegaICellRendererParams<Position, 'openVolume'>) => {
|
}: VegaICellRendererParams<Position, 'openVolume'>) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
|
|
||||||
|
const { data: latestTrade } = useLatestTrade(data?.marketId, data?.partyId);
|
||||||
|
|
||||||
if (!valueFormatted || !data || !data.notional) {
|
if (!valueFormatted || !data || !data.notional) {
|
||||||
return <>-</>;
|
return <>-</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const POSITION_RESOLUTION_LINK = DocsLinks?.POSITION_RESOLUTION ?? '';
|
let positionStatus = PositionStatus.POSITION_STATUS_UNSPECIFIED;
|
||||||
let primaryTooltip;
|
if (latestTrade?.type === TradeType.TYPE_NETWORK_CLOSE_OUT_BAD) {
|
||||||
switch (data.status) {
|
positionStatus = PositionStatus.POSITION_STATUS_CLOSED_OUT;
|
||||||
case PositionStatus.POSITION_STATUS_CLOSED_OUT:
|
|
||||||
primaryTooltip = t('Your position was closed.');
|
|
||||||
break;
|
|
||||||
case PositionStatus.POSITION_STATUS_ORDERS_CLOSED:
|
|
||||||
primaryTooltip = t('Your open orders were cancelled.');
|
|
||||||
break;
|
|
||||||
case PositionStatus.POSITION_STATUS_DISTRESSED:
|
|
||||||
primaryTooltip = t('Your position is distressed.');
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let secondaryTooltip;
|
const POSITION_RESOLUTION_LINK = DocsLinks?.POSITION_RESOLUTION ?? '';
|
||||||
switch (data.status) {
|
|
||||||
case PositionStatus.POSITION_STATUS_CLOSED_OUT:
|
const notional = addDecimalsFormatNumber(
|
||||||
secondaryTooltip = t(
|
data.notional,
|
||||||
`You did not have enough {{assetSymbol}} collateral to meet the maintenance margin requirements for your position, so it was closed by the network.`,
|
data.marketDecimalPlaces
|
||||||
{ assetSymbol: data.assetSymbol }
|
|
||||||
);
|
);
|
||||||
break;
|
|
||||||
case PositionStatus.POSITION_STATUS_ORDERS_CLOSED:
|
const cellContent = (
|
||||||
secondaryTooltip = t(
|
<StackedCell primary={valueFormatted} secondary={notional} />
|
||||||
'The position was distressed, but removing open orders from the book brought the margin level back to a point where the open position could be maintained.'
|
|
||||||
);
|
);
|
||||||
break;
|
|
||||||
case PositionStatus.POSITION_STATUS_DISTRESSED:
|
if (positionStatus !== PositionStatus.POSITION_STATUS_CLOSED_OUT) {
|
||||||
secondaryTooltip = t(
|
// eslint-disable-next-line react/jsx-no-useless-fragment
|
||||||
'The position was distressed, but could not be closed out - orders were removed from the book, and the open volume will be closed out once there is sufficient volume on the book.'
|
return <>{cellContent}</>;
|
||||||
);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
secondaryTooltip = t('Maintained by network');
|
|
||||||
}
|
}
|
||||||
const description = (
|
|
||||||
|
const closeOutPrice = addDecimalsFormatNumber(
|
||||||
|
latestTrade?.price || '0',
|
||||||
|
data.marketDecimalPlaces
|
||||||
|
);
|
||||||
|
const description = positionStatus ===
|
||||||
|
PositionStatus.POSITION_STATUS_CLOSED_OUT && (
|
||||||
<>
|
<>
|
||||||
<p className="mb-2">{primaryTooltip}</p>
|
<p className="mb-2">{t('Your position was closed.')}</p>
|
||||||
<p className="mb-2">{secondaryTooltip}</p>
|
<p className="mb-2">
|
||||||
|
{t(
|
||||||
|
'You did not have enough {{assetSymbol}} to meet the margin required for your position, so it was liquidated by the network at {{price}}.',
|
||||||
|
{
|
||||||
|
assetSymbol: data.assetSymbol,
|
||||||
|
price: closeOutPrice,
|
||||||
|
}
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
<p className="mb-2">
|
<p className="mb-2">
|
||||||
{t('Status: {{status}}', {
|
{t('Status: {{status}}', {
|
||||||
nsSeparator: '*',
|
nsSeparator: '*',
|
||||||
@ -675,20 +684,6 @@ export const OpenVolumeCell = ({
|
|||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
const notional = addDecimalsFormatNumber(
|
|
||||||
data.notional,
|
|
||||||
data.marketDecimalPlaces
|
|
||||||
);
|
|
||||||
|
|
||||||
const cellContent = (
|
|
||||||
<StackedCell primary={valueFormatted} secondary={notional} />
|
|
||||||
);
|
|
||||||
|
|
||||||
if (data.status === PositionStatus.POSITION_STATUS_UNSPECIFIED) {
|
|
||||||
// eslint-disable-next-line react/jsx-no-useless-fragment
|
|
||||||
return <>{cellContent}</>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip description={description}>
|
<Tooltip description={description}>
|
||||||
<div>
|
<div>
|
||||||
|
@ -15,3 +15,12 @@ i18n.use(initReactI18next).init({
|
|||||||
});
|
});
|
||||||
|
|
||||||
global.ResizeObserver = ResizeObserver;
|
global.ResizeObserver = ResizeObserver;
|
||||||
|
|
||||||
|
jest.mock('@vegaprotocol/trades', () => ({
|
||||||
|
...jest.requireActual('@vegaprotocol/trades'),
|
||||||
|
useLatestTrade: jest.fn(() => ({
|
||||||
|
data: undefined,
|
||||||
|
loading: false,
|
||||||
|
error: undefined,
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
@ -9,5 +9,5 @@ export default {
|
|||||||
},
|
},
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||||
coverageDirectory: '../../coverage/libs/react-helpers',
|
coverageDirectory: '../../coverage/libs/react-helpers',
|
||||||
setupFilesAfterEnv: ['./jest.setup.js'],
|
setupFilesAfterEnv: ['./src/setup-tests.ts'],
|
||||||
};
|
};
|
||||||
|
@ -15,3 +15,4 @@ export * from './use-previous';
|
|||||||
export { useScript } from './use-script';
|
export { useScript } from './use-script';
|
||||||
export { useUserAgent } from './use-user-agent';
|
export { useUserAgent } from './use-user-agent';
|
||||||
export * from './use-duration';
|
export * from './use-duration';
|
||||||
|
export * from './use-form-values';
|
||||||
|
17
libs/trades/src/hooks/use-latest-trade.ts
Normal file
17
libs/trades/src/hooks/use-latest-trade.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||||
|
import { tradesProvider } from '../lib/trades-data-provider';
|
||||||
|
import first from 'lodash/first';
|
||||||
|
|
||||||
|
export const useLatestTrade = (marketId?: string, partyId?: string) => {
|
||||||
|
const { data, loading, error } = useDataProvider({
|
||||||
|
dataProvider: tradesProvider,
|
||||||
|
variables: {
|
||||||
|
marketIds: [marketId || ''],
|
||||||
|
partyIds: [partyId || ''],
|
||||||
|
},
|
||||||
|
skip: !marketId || !partyId,
|
||||||
|
});
|
||||||
|
|
||||||
|
const latest = first(data);
|
||||||
|
return { data: latest, loading, error };
|
||||||
|
};
|
@ -1,2 +1,3 @@
|
|||||||
export * from './lib/trades-manager';
|
export * from './lib/trades-manager';
|
||||||
export * from './lib/__generated__/Trades';
|
export * from './lib/__generated__/Trades';
|
||||||
|
export * from './hooks/use-latest-trade';
|
||||||
|
@ -7,10 +7,14 @@ fragment TradeFields on Trade {
|
|||||||
market {
|
market {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
type
|
||||||
}
|
}
|
||||||
|
|
||||||
query Trades($marketId: ID!, $pagination: Pagination) {
|
query Trades($marketIds: [ID!], $partyIds: [ID!], $pagination: Pagination) {
|
||||||
trades(filter: { marketIds: [$marketId] }, pagination: $pagination) {
|
trades(
|
||||||
|
filter: { marketIds: $marketIds, partyIds: $partyIds }
|
||||||
|
pagination: $pagination
|
||||||
|
) {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
...TradeFields
|
...TradeFields
|
||||||
@ -33,10 +37,11 @@ fragment TradeUpdateFields on TradeUpdate {
|
|||||||
createdAt
|
createdAt
|
||||||
marketId
|
marketId
|
||||||
aggressor
|
aggressor
|
||||||
|
type
|
||||||
}
|
}
|
||||||
|
|
||||||
subscription TradesUpdate($marketId: ID!) {
|
subscription TradesUpdate($marketIds: [ID!], $partyIds: [ID!]) {
|
||||||
tradesStream(filter: { marketIds: [$marketId] }) {
|
tradesStream(filter: { marketIds: $marketIds, partyIds: $partyIds }) {
|
||||||
...TradeUpdateFields
|
...TradeUpdateFields
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
37
libs/trades/src/lib/__generated__/Trades.ts
generated
37
libs/trades/src/lib/__generated__/Trades.ts
generated
@ -3,24 +3,26 @@ import * as Types from '@vegaprotocol/types';
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
import * as Apollo from '@apollo/client';
|
import * as Apollo from '@apollo/client';
|
||||||
const defaultOptions = {} as const;
|
const defaultOptions = {} as const;
|
||||||
export type TradeFieldsFragment = { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, aggressor: Types.Side, market: { __typename?: 'Market', id: string } };
|
export type TradeFieldsFragment = { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, aggressor: Types.Side, type: Types.TradeType, market: { __typename?: 'Market', id: string } };
|
||||||
|
|
||||||
export type TradesQueryVariables = Types.Exact<{
|
export type TradesQueryVariables = Types.Exact<{
|
||||||
marketId: Types.Scalars['ID'];
|
marketIds?: Types.InputMaybe<Array<Types.Scalars['ID']> | Types.Scalars['ID']>;
|
||||||
|
partyIds?: Types.InputMaybe<Array<Types.Scalars['ID']> | Types.Scalars['ID']>;
|
||||||
pagination?: Types.InputMaybe<Types.Pagination>;
|
pagination?: Types.InputMaybe<Types.Pagination>;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type TradesQuery = { __typename?: 'Query', trades?: { __typename?: 'TradeConnection', edges: Array<{ __typename?: 'TradeEdge', cursor: string, node: { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, aggressor: Types.Side, market: { __typename?: 'Market', id: string } } }>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } | null };
|
export type TradesQuery = { __typename?: 'Query', trades?: { __typename?: 'TradeConnection', edges: Array<{ __typename?: 'TradeEdge', cursor: string, node: { __typename?: 'Trade', id: string, price: string, size: string, createdAt: any, aggressor: Types.Side, type: Types.TradeType, market: { __typename?: 'Market', id: string } } }>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } | null };
|
||||||
|
|
||||||
export type TradeUpdateFieldsFragment = { __typename?: 'TradeUpdate', id: string, price: string, size: string, createdAt: any, marketId: string, aggressor: Types.Side };
|
export type TradeUpdateFieldsFragment = { __typename?: 'TradeUpdate', id: string, price: string, size: string, createdAt: any, marketId: string, aggressor: Types.Side, type: Types.TradeType };
|
||||||
|
|
||||||
export type TradesUpdateSubscriptionVariables = Types.Exact<{
|
export type TradesUpdateSubscriptionVariables = Types.Exact<{
|
||||||
marketId: Types.Scalars['ID'];
|
marketIds?: Types.InputMaybe<Array<Types.Scalars['ID']> | Types.Scalars['ID']>;
|
||||||
|
partyIds?: Types.InputMaybe<Array<Types.Scalars['ID']> | Types.Scalars['ID']>;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type TradesUpdateSubscription = { __typename?: 'Subscription', tradesStream?: Array<{ __typename?: 'TradeUpdate', id: string, price: string, size: string, createdAt: any, marketId: string, aggressor: Types.Side }> | null };
|
export type TradesUpdateSubscription = { __typename?: 'Subscription', tradesStream?: Array<{ __typename?: 'TradeUpdate', id: string, price: string, size: string, createdAt: any, marketId: string, aggressor: Types.Side, type: Types.TradeType }> | null };
|
||||||
|
|
||||||
export const TradeFieldsFragmentDoc = gql`
|
export const TradeFieldsFragmentDoc = gql`
|
||||||
fragment TradeFields on Trade {
|
fragment TradeFields on Trade {
|
||||||
@ -32,6 +34,7 @@ export const TradeFieldsFragmentDoc = gql`
|
|||||||
market {
|
market {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
type
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const TradeUpdateFieldsFragmentDoc = gql`
|
export const TradeUpdateFieldsFragmentDoc = gql`
|
||||||
@ -42,11 +45,15 @@ export const TradeUpdateFieldsFragmentDoc = gql`
|
|||||||
createdAt
|
createdAt
|
||||||
marketId
|
marketId
|
||||||
aggressor
|
aggressor
|
||||||
|
type
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const TradesDocument = gql`
|
export const TradesDocument = gql`
|
||||||
query Trades($marketId: ID!, $pagination: Pagination) {
|
query Trades($marketIds: [ID!], $partyIds: [ID!], $pagination: Pagination) {
|
||||||
trades(filter: {marketIds: [$marketId]}, pagination: $pagination) {
|
trades(
|
||||||
|
filter: {marketIds: $marketIds, partyIds: $partyIds}
|
||||||
|
pagination: $pagination
|
||||||
|
) {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
...TradeFields
|
...TradeFields
|
||||||
@ -75,12 +82,13 @@ export const TradesDocument = gql`
|
|||||||
* @example
|
* @example
|
||||||
* const { data, loading, error } = useTradesQuery({
|
* const { data, loading, error } = useTradesQuery({
|
||||||
* variables: {
|
* variables: {
|
||||||
* marketId: // value for 'marketId'
|
* marketIds: // value for 'marketIds'
|
||||||
|
* partyIds: // value for 'partyIds'
|
||||||
* pagination: // value for 'pagination'
|
* pagination: // value for 'pagination'
|
||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useTradesQuery(baseOptions: Apollo.QueryHookOptions<TradesQuery, TradesQueryVariables>) {
|
export function useTradesQuery(baseOptions?: Apollo.QueryHookOptions<TradesQuery, TradesQueryVariables>) {
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
return Apollo.useQuery<TradesQuery, TradesQueryVariables>(TradesDocument, options);
|
return Apollo.useQuery<TradesQuery, TradesQueryVariables>(TradesDocument, options);
|
||||||
}
|
}
|
||||||
@ -92,8 +100,8 @@ export type TradesQueryHookResult = ReturnType<typeof useTradesQuery>;
|
|||||||
export type TradesLazyQueryHookResult = ReturnType<typeof useTradesLazyQuery>;
|
export type TradesLazyQueryHookResult = ReturnType<typeof useTradesLazyQuery>;
|
||||||
export type TradesQueryResult = Apollo.QueryResult<TradesQuery, TradesQueryVariables>;
|
export type TradesQueryResult = Apollo.QueryResult<TradesQuery, TradesQueryVariables>;
|
||||||
export const TradesUpdateDocument = gql`
|
export const TradesUpdateDocument = gql`
|
||||||
subscription TradesUpdate($marketId: ID!) {
|
subscription TradesUpdate($marketIds: [ID!], $partyIds: [ID!]) {
|
||||||
tradesStream(filter: {marketIds: [$marketId]}) {
|
tradesStream(filter: {marketIds: $marketIds, partyIds: $partyIds}) {
|
||||||
...TradeUpdateFields
|
...TradeUpdateFields
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,11 +119,12 @@ export const TradesUpdateDocument = gql`
|
|||||||
* @example
|
* @example
|
||||||
* const { data, loading, error } = useTradesUpdateSubscription({
|
* const { data, loading, error } = useTradesUpdateSubscription({
|
||||||
* variables: {
|
* variables: {
|
||||||
* marketId: // value for 'marketId'
|
* marketIds: // value for 'marketIds'
|
||||||
|
* partyIds: // value for 'partyIds'
|
||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useTradesUpdateSubscription(baseOptions: Apollo.SubscriptionHookOptions<TradesUpdateSubscription, TradesUpdateSubscriptionVariables>) {
|
export function useTradesUpdateSubscription(baseOptions?: Apollo.SubscriptionHookOptions<TradesUpdateSubscription, TradesUpdateSubscriptionVariables>) {
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
return Apollo.useSubscription<TradesUpdateSubscription, TradesUpdateSubscriptionVariables>(TradesUpdateDocument, options);
|
return Apollo.useSubscription<TradesUpdateSubscription, TradesUpdateSubscriptionVariables>(TradesUpdateDocument, options);
|
||||||
}
|
}
|
||||||
|
@ -23,10 +23,14 @@ export const MAX_TRADES = 500;
|
|||||||
const getData = (
|
const getData = (
|
||||||
responseData: TradesQuery | null
|
responseData: TradesQuery | null
|
||||||
): (TradeFieldsFragment & Cursor)[] =>
|
): (TradeFieldsFragment & Cursor)[] =>
|
||||||
|
orderBy(
|
||||||
responseData?.trades?.edges.map<TradeFieldsFragment & Cursor>((edge) => ({
|
responseData?.trades?.edges.map<TradeFieldsFragment & Cursor>((edge) => ({
|
||||||
...edge.node,
|
...edge.node,
|
||||||
cursor: edge.cursor,
|
cursor: edge.cursor,
|
||||||
})) || [];
|
})),
|
||||||
|
'createdAt',
|
||||||
|
'desc'
|
||||||
|
) || [];
|
||||||
|
|
||||||
const getDelta = (subscriptionData: TradesUpdateSubscription) =>
|
const getDelta = (subscriptionData: TradesUpdateSubscription) =>
|
||||||
subscriptionData?.tradesStream || [];
|
subscriptionData?.tradesStream || [];
|
||||||
@ -101,7 +105,10 @@ export const tradesProvider = makeDataProvider<
|
|||||||
last: MAX_TRADES,
|
last: MAX_TRADES,
|
||||||
},
|
},
|
||||||
fetchPolicy: 'no-cache',
|
fetchPolicy: 'no-cache',
|
||||||
getSubscriptionVariables: ({ marketId }) => ({ marketId }),
|
getSubscriptionVariables: ({ marketIds, partyIds }) => ({
|
||||||
|
marketIds,
|
||||||
|
partyIds,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const tradesWithMarketProvider = makeDerivedDataProvider<
|
export const tradesWithMarketProvider = makeDerivedDataProvider<
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||||
import { tradesWithMarketProvider } from './trades-data-provider';
|
import { tradesWithMarketProvider } from './trades-data-provider';
|
||||||
import { TradesTable } from './trades-table';
|
import { TradesTable } from './trades-table';
|
||||||
import { useDealTicketFormValues } from '@vegaprotocol/deal-ticket';
|
import { useDealTicketFormValues } from '@vegaprotocol/react-helpers';
|
||||||
import type { useDataGridEvents } from '@vegaprotocol/datagrid';
|
import type { useDataGridEvents } from '@vegaprotocol/datagrid';
|
||||||
import { useT } from './use-t';
|
import { useT } from './use-t';
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ export const TradesManager = ({
|
|||||||
|
|
||||||
const { data, error } = useDataProvider({
|
const { data, error } = useDataProvider({
|
||||||
dataProvider: tradesWithMarketProvider,
|
dataProvider: tradesWithMarketProvider,
|
||||||
variables: { marketId },
|
variables: { marketIds: [marketId] },
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -2,7 +2,7 @@ import { act, render, screen } from '@testing-library/react';
|
|||||||
import { getTimeFormat } from '@vegaprotocol/utils';
|
import { getTimeFormat } from '@vegaprotocol/utils';
|
||||||
import { SELL_CLASS, TradesTable, BUY_CLASS } from './trades-table';
|
import { SELL_CLASS, TradesTable, BUY_CLASS } from './trades-table';
|
||||||
import type { Trade } from './trades-data-provider';
|
import type { Trade } from './trades-data-provider';
|
||||||
import { Side } from '@vegaprotocol/types';
|
import { Side, TradeType } from '@vegaprotocol/types';
|
||||||
|
|
||||||
const trade: Trade = {
|
const trade: Trade = {
|
||||||
__typename: 'Trade',
|
__typename: 'Trade',
|
||||||
@ -17,6 +17,7 @@ const trade: Trade = {
|
|||||||
decimalPlaces: 2,
|
decimalPlaces: 2,
|
||||||
positionDecimalPlaces: 2,
|
positionDecimalPlaces: 2,
|
||||||
} as Trade['market'],
|
} as Trade['market'],
|
||||||
|
type: TradeType.TYPE_DEFAULT,
|
||||||
};
|
};
|
||||||
|
|
||||||
describe('TradesTable', () => {
|
describe('TradesTable', () => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Side } from '@vegaprotocol/types';
|
import { Side, TradeType } from '@vegaprotocol/types';
|
||||||
import merge from 'lodash/merge';
|
import merge from 'lodash/merge';
|
||||||
import type { PartialDeep } from 'type-fest';
|
import type { PartialDeep } from 'type-fest';
|
||||||
import type {
|
import type {
|
||||||
@ -45,6 +45,7 @@ export const tradesUpdateSubscription = (
|
|||||||
createdAt: '2022-04-06T16:19:42.692598951Z',
|
createdAt: '2022-04-06T16:19:42.692598951Z',
|
||||||
marketId: 'market-0',
|
marketId: 'market-0',
|
||||||
aggressor: Side.SIDE_BUY,
|
aggressor: Side.SIDE_BUY,
|
||||||
|
type: TradeType.TYPE_DEFAULT,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -62,6 +63,7 @@ const trades: TradeFieldsFragment[] = [
|
|||||||
id: 'market-0',
|
id: 'market-0',
|
||||||
__typename: 'Market',
|
__typename: 'Market',
|
||||||
},
|
},
|
||||||
|
type: TradeType.TYPE_DEFAULT,
|
||||||
__typename: 'Trade',
|
__typename: 'Trade',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -74,6 +76,7 @@ const trades: TradeFieldsFragment[] = [
|
|||||||
id: 'market-0',
|
id: 'market-0',
|
||||||
__typename: 'Market',
|
__typename: 'Market',
|
||||||
},
|
},
|
||||||
|
type: TradeType.TYPE_DEFAULT,
|
||||||
__typename: 'Trade',
|
__typename: 'Trade',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -86,6 +89,7 @@ const trades: TradeFieldsFragment[] = [
|
|||||||
id: 'market-0',
|
id: 'market-0',
|
||||||
__typename: 'Market',
|
__typename: 'Market',
|
||||||
},
|
},
|
||||||
|
type: TradeType.TYPE_DEFAULT,
|
||||||
__typename: 'Trade',
|
__typename: 'Trade',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -106,6 +106,7 @@ export const DepositStatusMapping: {
|
|||||||
} = {
|
} = {
|
||||||
STATUS_CANCELLED: 'Cancelled',
|
STATUS_CANCELLED: 'Cancelled',
|
||||||
STATUS_FINALIZED: 'Finalized',
|
STATUS_FINALIZED: 'Finalized',
|
||||||
|
STATUS_DUPLICATE_REJECTED: 'Duplicate rejected',
|
||||||
STATUS_OPEN: 'Open',
|
STATUS_OPEN: 'Open',
|
||||||
STATUS_DUPLICATE_REJECTED: 'Rejected due to duplicate',
|
STATUS_DUPLICATE_REJECTED: 'Rejected due to duplicate',
|
||||||
};
|
};
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a number prefixed with either a '-' or a '+'. The open volume field
|
* Returns a number prefixed with either a '-' or a '+'. The open volume field
|
||||||
* already comes with a '-' if negative so we only need to actually prefix if
|
* already comes with a '-' if negative so we only need to actually prefix if
|
||||||
* its a positive value
|
* its a positive value
|
||||||
*/
|
*/
|
||||||
export function volumePrefix(value: string): string {
|
export function volumePrefix(value: string): string {
|
||||||
if (value === '0' || value.startsWith('-')) {
|
const isZero = BigNumber(value).isZero();
|
||||||
|
if (isZero || value.startsWith('-')) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user