feat: [console-lite] - fixes in order close out calcs (#934)
* feat: [console-lite] - fixes in order close out calcs * feat: [console-lite] - fixes in order close out calcs - adjust int test * feat: [console-lite] - fixes in order close out calcs - adjust int test * feat: [console-lite] - fixes in order close out calcs - adjust int test * feat: [console-lite] - fixes in order close out calcs - add dash instead 0 * feat: [console-lite] - fixes in order close out calcs - add dash instead 0 Co-authored-by: maciek <maciek@vegaprotocol.io>
This commit is contained in:
parent
45d05b38f9
commit
f0e37e4a2f
@ -5,6 +5,8 @@ import { generateMarketTags } from '../support/mocks/generate-market-tags';
|
||||
import { generateMarketPositions } from '../support/mocks/generate-market-positions';
|
||||
import { generateEstimateOrder } from '../support/mocks/generate-estimate-order';
|
||||
import { generatePartyBalance } from '../support/mocks/generate-party-balance';
|
||||
import { generatePartyMarketData } from '../support/mocks/generate-party-market-data';
|
||||
import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price';
|
||||
|
||||
const connectVegaWallet = () => {
|
||||
const form = 'rest-connector-form';
|
||||
@ -28,6 +30,8 @@ describe('Market trade', () => {
|
||||
aliasQuery(req, 'MarketPositions', generateMarketPositions());
|
||||
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
|
||||
aliasQuery(req, 'PartyBalanceQuery', generatePartyBalance());
|
||||
aliasQuery(req, 'PartyMarketData', generatePartyMarketData());
|
||||
aliasQuery(req, 'MarketMarkPrice', generateMarketMarkPrice());
|
||||
});
|
||||
cy.visit('/markets');
|
||||
cy.wait('@SimpleMarkets').then((response) => {
|
||||
@ -104,7 +108,7 @@ describe('Market trade', () => {
|
||||
.find('dl')
|
||||
.eq(3)
|
||||
.find('dd div')
|
||||
.should('have.text', '-785.81045');
|
||||
.should('have.text', ' - ');
|
||||
cy.getByTestId('place-order').click();
|
||||
cy.getByTestId('dialog-title').should(
|
||||
'have.text',
|
||||
|
@ -0,0 +1,9 @@
|
||||
export const generateMarketMarkPrice = () => {
|
||||
return {
|
||||
market: {
|
||||
decimalPlaces: 5,
|
||||
data: { markPrice: '692748', __typename: 'MarketData' },
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
};
|
@ -0,0 +1,19 @@
|
||||
export const generatePartyMarketData = () => {
|
||||
return {
|
||||
party: {
|
||||
id: '2e1ef32e5804e14232406aebaad719087d326afa5c648b7824d0823d8a46c8d1',
|
||||
accounts: [
|
||||
{
|
||||
type: 'General',
|
||||
balance: '1200000',
|
||||
asset: { id: 'fBTC', decimals: 5, __typename: 'Asset' },
|
||||
market: null,
|
||||
__typename: 'Account',
|
||||
},
|
||||
],
|
||||
marginsConnection: { edges: null, __typename: 'MarginConnection' },
|
||||
positionsConnection: { edges: null, __typename: 'PositionConnection' },
|
||||
__typename: 'Party',
|
||||
},
|
||||
};
|
||||
};
|
@ -1,4 +1,4 @@
|
||||
import React from 'react';
|
||||
import * as React from 'react';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import {
|
||||
render,
|
||||
@ -60,6 +60,7 @@ describe('SimpleMarketList', () => {
|
||||
};
|
||||
await act(async () => {
|
||||
render(
|
||||
// @ts-ignore different versions of react types in apollo and app
|
||||
<MockedProvider mocks={[mocks, filterMock]}>
|
||||
<SimpleMarketList />
|
||||
</MockedProvider>,
|
||||
@ -129,6 +130,7 @@ describe('SimpleMarketList', () => {
|
||||
};
|
||||
await act(async () => {
|
||||
render(
|
||||
// @ts-ignore different versions of react types in apollo and app
|
||||
<MockedProvider mocks={[mocks, filterMock]}>
|
||||
<SimpleMarketList />
|
||||
</MockedProvider>,
|
||||
|
@ -59,6 +59,7 @@ describe('SimpleMarketToolbar', () => {
|
||||
|
||||
it('should be properly rendered', async () => {
|
||||
render(
|
||||
// @ts-ignore different versions of react types in apollo and app
|
||||
<MockedProvider mocks={[filterMock]} addTypename={false}>
|
||||
<WrappedCompForTest />
|
||||
</MockedProvider>,
|
||||
@ -83,6 +84,7 @@ describe('SimpleMarketToolbar', () => {
|
||||
|
||||
it('navigation should work well', async () => {
|
||||
render(
|
||||
// @ts-ignore different versions of react types in apollo and app
|
||||
<MockedProvider mocks={[filterMock]} addTypename={false}>
|
||||
<WrappedCompForTest />
|
||||
</MockedProvider>,
|
||||
|
52
apps/simple-trading-app/src/app/hooks/__generated__/MarketMarkPrice.ts
generated
Normal file
52
apps/simple-trading-app/src/app/hooks/__generated__/MarketMarkPrice.ts
generated
Normal file
@ -0,0 +1,52 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
// ====================================================
|
||||
// GraphQL query operation: MarketMarkPrice
|
||||
// ====================================================
|
||||
|
||||
export interface MarketMarkPrice_market_data {
|
||||
__typename: "MarketData";
|
||||
/**
|
||||
* the mark price (actually an unsigned int)
|
||||
*/
|
||||
markPrice: string;
|
||||
}
|
||||
|
||||
export interface MarketMarkPrice_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
|
||||
* number denominated in the currency of the Market. (uint64)
|
||||
*
|
||||
* Examples:
|
||||
* Currency Balance decimalPlaces Real Balance
|
||||
* GBP 100 0 GBP 100
|
||||
* GBP 100 2 GBP 1.00
|
||||
* GBP 100 4 GBP 0.01
|
||||
* GBP 1 4 GBP 0.0001 ( 0.01p )
|
||||
*
|
||||
* GBX (pence) 100 0 GBP 1.00 (100p )
|
||||
* GBX (pence) 100 2 GBP 0.01 ( 1p )
|
||||
* GBX (pence) 100 4 GBP 0.0001 ( 0.01p )
|
||||
* GBX (pence) 1 4 GBP 0.000001 ( 0.0001p)
|
||||
*/
|
||||
decimalPlaces: number;
|
||||
/**
|
||||
* marketData for the given market
|
||||
*/
|
||||
data: MarketMarkPrice_market_data | null;
|
||||
}
|
||||
|
||||
export interface MarketMarkPrice {
|
||||
/**
|
||||
* An instrument that is trading on the VEGA network
|
||||
*/
|
||||
market: MarketMarkPrice_market | null;
|
||||
}
|
||||
|
||||
export interface MarketMarkPriceVariables {
|
||||
marketId: string;
|
||||
}
|
118
apps/simple-trading-app/src/app/hooks/__generated__/PartyMarketData.ts
generated
Normal file
118
apps/simple-trading-app/src/app/hooks/__generated__/PartyMarketData.ts
generated
Normal file
@ -0,0 +1,118 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { AccountType } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL query operation: PartyMarketData
|
||||
// ====================================================
|
||||
|
||||
export interface PartyMarketData_party_accounts_asset {
|
||||
__typename: "Asset";
|
||||
/**
|
||||
* The id of the asset
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The precision of the asset
|
||||
*/
|
||||
decimals: number;
|
||||
}
|
||||
|
||||
export interface PartyMarketData_party_accounts_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface PartyMarketData_party_accounts {
|
||||
__typename: "Account";
|
||||
/**
|
||||
* Account type (General, Margin, etc)
|
||||
*/
|
||||
type: AccountType;
|
||||
/**
|
||||
* Balance as string - current account balance (approx. as balances can be updated several times per second)
|
||||
*/
|
||||
balance: string;
|
||||
/**
|
||||
* Asset, the 'currency'
|
||||
*/
|
||||
asset: PartyMarketData_party_accounts_asset;
|
||||
/**
|
||||
* Market (only relevant to margin accounts)
|
||||
*/
|
||||
market: PartyMarketData_party_accounts_market | null;
|
||||
}
|
||||
|
||||
export interface PartyMarketData_party_marginsConnection_edges_node_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface PartyMarketData_party_marginsConnection_edges_node {
|
||||
__typename: "MarginLevels";
|
||||
/**
|
||||
* market in which the margin is required for this party
|
||||
*/
|
||||
market: PartyMarketData_party_marginsConnection_edges_node_market;
|
||||
/**
|
||||
* this is the minimal margin required for a party to place a new order on the network (unsigned int actually)
|
||||
*/
|
||||
initialLevel: string;
|
||||
/**
|
||||
* minimal margin for the position to be maintained in the network (unsigned int actually)
|
||||
*/
|
||||
maintenanceLevel: string;
|
||||
/**
|
||||
* if the margin is between maintenance and search, the network will initiate a collateral search (unsigned int actually)
|
||||
*/
|
||||
searchLevel: string;
|
||||
}
|
||||
|
||||
export interface PartyMarketData_party_marginsConnection_edges {
|
||||
__typename: "MarginEdge";
|
||||
node: PartyMarketData_party_marginsConnection_edges_node;
|
||||
}
|
||||
|
||||
export interface PartyMarketData_party_marginsConnection {
|
||||
__typename: "MarginConnection";
|
||||
/**
|
||||
* The margin levels in this connection
|
||||
*/
|
||||
edges: PartyMarketData_party_marginsConnection_edges[] | null;
|
||||
}
|
||||
|
||||
export interface PartyMarketData_party {
|
||||
__typename: "Party";
|
||||
/**
|
||||
* Party identifier
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Collateral accounts relating to a party
|
||||
*/
|
||||
accounts: PartyMarketData_party_accounts[] | null;
|
||||
/**
|
||||
* Margin level for a market
|
||||
*/
|
||||
marginsConnection: PartyMarketData_party_marginsConnection;
|
||||
}
|
||||
|
||||
export interface PartyMarketData {
|
||||
/**
|
||||
* An entity that is trading on the VEGA network
|
||||
*/
|
||||
party: PartyMarketData_party | null;
|
||||
}
|
||||
|
||||
export interface PartyMarketDataVariables {
|
||||
partyId: string;
|
||||
}
|
38
apps/simple-trading-app/src/app/hooks/use-market-data.ts
Normal file
38
apps/simple-trading-app/src/app/hooks/use-market-data.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import { useMemo, useRef } from 'react';
|
||||
import type {
|
||||
MarketMarkPrice,
|
||||
MarketMarkPriceVariables,
|
||||
} from './__generated__/MarketMarkPrice';
|
||||
|
||||
const MARKET_MARK_PRICE = gql`
|
||||
query MarketMarkPrice($marketId: ID!) {
|
||||
market(id: $marketId) {
|
||||
decimalPlaces
|
||||
data {
|
||||
markPrice
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default (marketId: string) => {
|
||||
const memoRef = useRef<MarketMarkPrice | null>(null);
|
||||
const { data } = useQuery<MarketMarkPrice, MarketMarkPriceVariables>(
|
||||
MARKET_MARK_PRICE,
|
||||
{
|
||||
pollInterval: 5000,
|
||||
variables: { marketId },
|
||||
skip: !marketId,
|
||||
}
|
||||
);
|
||||
return useMemo(() => {
|
||||
if (
|
||||
data &&
|
||||
data.market?.data?.markPrice !== memoRef.current?.market?.data?.markPrice
|
||||
) {
|
||||
memoRef.current = data;
|
||||
}
|
||||
return memoRef.current;
|
||||
}, [data, memoRef]);
|
||||
};
|
@ -1,71 +0,0 @@
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import useOrderCloseOut from './use-order-closeout';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket';
|
||||
import type { PartyBalanceQuery } from '../components/deal-ticket/__generated__/PartyBalanceQuery';
|
||||
|
||||
describe('useOrderCloseOut Hook', () => {
|
||||
const order = { size: '2', side: 'SIDE_BUY' };
|
||||
const market = {
|
||||
decimalPlaces: 5,
|
||||
depth: {
|
||||
lastTrade: {
|
||||
price: '1000000',
|
||||
},
|
||||
},
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
settlementAsset: {
|
||||
id: 'assetId',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const partyData = {
|
||||
party: {
|
||||
accounts: [
|
||||
{
|
||||
balance: '200000',
|
||||
asset: {
|
||||
id: 'assetId',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
it('return proper buy value', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useOrderCloseOut({
|
||||
order: order as Order,
|
||||
market: market as DealTicketQuery_market,
|
||||
partyData: partyData as PartyBalanceQuery,
|
||||
})
|
||||
);
|
||||
expect(result.current).toEqual('9.00000');
|
||||
});
|
||||
|
||||
it('return proper sell value', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useOrderCloseOut({
|
||||
order: { ...order, side: 'SIDE_SELL' } as Order,
|
||||
market: market as DealTicketQuery_market,
|
||||
partyData: partyData as PartyBalanceQuery,
|
||||
})
|
||||
);
|
||||
expect(result.current).toEqual('11.00000');
|
||||
});
|
||||
|
||||
it('return proper empty value', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useOrderCloseOut({
|
||||
order: { ...order, side: 'SIDE_SELL' } as Order,
|
||||
market: market as DealTicketQuery_market,
|
||||
})
|
||||
);
|
||||
expect(result.current).toEqual(' - ');
|
||||
});
|
||||
});
|
@ -0,0 +1,99 @@
|
||||
import * as React from 'react';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import useOrderCloseOut from './use-order-closeout';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket';
|
||||
import type { PartyBalanceQuery } from '../components/deal-ticket/__generated__/PartyBalanceQuery';
|
||||
|
||||
jest.mock('@vegaprotocol/wallet', () => ({
|
||||
...jest.requireActual('@vegaprotocol/wallet'),
|
||||
useVegaWallet: jest.fn().mockReturnValue('wallet-pub-key'),
|
||||
}));
|
||||
|
||||
describe('useOrderCloseOut Hook', () => {
|
||||
const order = { size: '2', side: 'SIDE_BUY' };
|
||||
const market = {
|
||||
decimalPlaces: 5,
|
||||
depth: {
|
||||
lastTrade: {
|
||||
price: '1000000',
|
||||
},
|
||||
},
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
settlementAsset: {
|
||||
id: 'assetId',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
const partyData = {
|
||||
party: {
|
||||
accounts: [
|
||||
{
|
||||
balance: '200000',
|
||||
asset: {
|
||||
id: 'assetId',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
it('return proper buy value', () => {
|
||||
const { result } = renderHook(
|
||||
() =>
|
||||
useOrderCloseOut({
|
||||
order: order as Order,
|
||||
market: market as DealTicketQuery_market,
|
||||
partyData: partyData as PartyBalanceQuery,
|
||||
}),
|
||||
{
|
||||
wrapper: ({ children }: { children: React.ReactNode }) => (
|
||||
// @ts-ignore different versions of react types in apollo and app
|
||||
<MockedProvider mocks={[]}>{children}</MockedProvider>
|
||||
),
|
||||
}
|
||||
);
|
||||
expect(result.current).toEqual(' - ');
|
||||
});
|
||||
|
||||
it('return proper sell value', () => {
|
||||
const { result } = renderHook(
|
||||
() =>
|
||||
useOrderCloseOut({
|
||||
order: { ...order, side: 'SIDE_SELL' } as Order,
|
||||
market: market as DealTicketQuery_market,
|
||||
partyData: partyData as PartyBalanceQuery,
|
||||
}),
|
||||
{
|
||||
wrapper: ({ children }: { children: React.ReactNode }) => (
|
||||
// @ts-ignore different versions of react types in apollo and app
|
||||
<MockedProvider mocks={[]}>{children}</MockedProvider>
|
||||
),
|
||||
}
|
||||
);
|
||||
expect(result.current).toEqual('1.00000');
|
||||
});
|
||||
|
||||
it('return proper empty value', () => {
|
||||
const { result } = renderHook(
|
||||
() =>
|
||||
useOrderCloseOut({
|
||||
order: { ...order, side: 'SIDE_SELL' } as Order,
|
||||
market: market as DealTicketQuery_market,
|
||||
}),
|
||||
{
|
||||
wrapper: ({ children }: { children: React.ReactNode }) => (
|
||||
// @ts-ignore different versions of react types in apollo and app
|
||||
<MockedProvider mocks={[]}>{children}</MockedProvider>
|
||||
),
|
||||
}
|
||||
);
|
||||
expect(result.current).toEqual('0.00000');
|
||||
});
|
||||
});
|
@ -3,8 +3,46 @@ import type { Order } from '@vegaprotocol/orders';
|
||||
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket';
|
||||
import type { PartyBalanceQuery } from '../components/deal-ticket/__generated__/PartyBalanceQuery';
|
||||
import { useSettlementAccount } from './use-settlement-account';
|
||||
import { VegaWalletOrderSide } from '@vegaprotocol/wallet';
|
||||
import { useVegaWallet, VegaWalletOrderSide } from '@vegaprotocol/wallet';
|
||||
import { addDecimal, formatNumber } from '@vegaprotocol/react-helpers';
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import useMarketPositions from './use-market-positions';
|
||||
import useMarketData from './use-market-data';
|
||||
import type {
|
||||
PartyMarketData,
|
||||
PartyMarketDataVariables,
|
||||
} from './__generated__/PartyMarketData';
|
||||
|
||||
const CLOSEOUT_PRICE_QUERY = gql`
|
||||
query PartyMarketData($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
accounts {
|
||||
type
|
||||
balance
|
||||
asset {
|
||||
id
|
||||
decimals
|
||||
}
|
||||
market {
|
||||
id
|
||||
}
|
||||
}
|
||||
marginsConnection {
|
||||
edges {
|
||||
node {
|
||||
market {
|
||||
id
|
||||
}
|
||||
initialLevel
|
||||
maintenanceLevel
|
||||
searchLevel
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
order: Order;
|
||||
@ -13,25 +51,65 @@ interface Props {
|
||||
}
|
||||
|
||||
const useOrderCloseOut = ({ order, market, partyData }: Props): string => {
|
||||
const { keypair } = useVegaWallet();
|
||||
const account = useSettlementAccount(
|
||||
market.tradableInstrument.instrument.product.settlementAsset.id,
|
||||
partyData?.party?.accounts || []
|
||||
);
|
||||
if (account?.balance && market.depth.lastTrade) {
|
||||
const price = new BigNumber(
|
||||
addDecimal(market.depth.lastTrade.price, market.decimalPlaces)
|
||||
const { data } = useQuery<PartyMarketData, PartyMarketDataVariables>(
|
||||
CLOSEOUT_PRICE_QUERY,
|
||||
{
|
||||
pollInterval: 5000,
|
||||
variables: { partyId: keypair?.pub || '' },
|
||||
skip: !keypair?.pub,
|
||||
}
|
||||
);
|
||||
const balance = new BigNumber(
|
||||
addDecimal(account.balance, account.asset.decimals)
|
||||
);
|
||||
const { size, side } = order;
|
||||
const bigOne = new BigNumber(1);
|
||||
return formatNumber(
|
||||
side === VegaWalletOrderSide.Buy
|
||||
? bigOne.minus(balance.div(price.times(size))).times(price)
|
||||
: bigOne.plus(balance.div(price.times(size))).times(price),
|
||||
|
||||
const markPriceData = useMarketData(market.id);
|
||||
const marketPositions = useMarketPositions({
|
||||
marketId: market.id,
|
||||
partyId: keypair?.pub || '',
|
||||
});
|
||||
|
||||
const marginMaintenanceLevel = new BigNumber(
|
||||
addDecimal(
|
||||
data?.party?.marginsConnection.edges?.find(
|
||||
(nodes) => nodes.node.market.id === market.id
|
||||
)?.node.maintenanceLevel || 0,
|
||||
market.decimalPlaces
|
||||
)
|
||||
);
|
||||
const positionAccount = data?.party?.accounts?.find(
|
||||
(account) => account.market?.id === market.id
|
||||
);
|
||||
const positionAccountBalance = new BigNumber(
|
||||
addDecimal(
|
||||
positionAccount?.balance || 0,
|
||||
positionAccount?.asset?.decimals || 0
|
||||
)
|
||||
);
|
||||
const generalAccountBalance = new BigNumber(
|
||||
addDecimal(account?.balance || 0, account?.asset.decimals || 0)
|
||||
);
|
||||
const volume = new BigNumber(
|
||||
addDecimal(
|
||||
marketPositions?.openVolume.toNumber() || 0,
|
||||
market.positionDecimalPlaces
|
||||
)
|
||||
)[order.side === VegaWalletOrderSide.Buy ? 'plus' : 'minus'](order.size);
|
||||
const markPrice = new BigNumber(
|
||||
addDecimal(
|
||||
markPriceData?.market?.data?.markPrice || 0,
|
||||
markPriceData?.market?.decimalPlaces || 0
|
||||
)
|
||||
);
|
||||
// regarding formula (marginMaintenanceLevel - positionAccountBalance - generalAccountBalance) / volume + markPrice
|
||||
const marginDifference = marginMaintenanceLevel
|
||||
.minus(positionAccountBalance)
|
||||
.minus(generalAccountBalance);
|
||||
const closeOut = marginDifference.div(volume).plus(markPrice);
|
||||
if (closeOut.isPositive()) {
|
||||
return formatNumber(closeOut, market.decimalPlaces);
|
||||
}
|
||||
return ' - ';
|
||||
};
|
||||
|
@ -58,7 +58,7 @@ describe('useOrderMargin Hook', () => {
|
||||
const calledSize = new BigNumber(mockMarketPositions?.openVolume || 0)
|
||||
.plus(order.size)
|
||||
.toString();
|
||||
expect((useQuery as jest.Mock).mock.calls[0][1].variables.size).toEqual(
|
||||
expect((useQuery as jest.Mock).mock.calls[1][1].variables.size).toEqual(
|
||||
calledSize
|
||||
);
|
||||
});
|
||||
@ -74,7 +74,7 @@ describe('useOrderMargin Hook', () => {
|
||||
);
|
||||
expect(result.current).toEqual('200000');
|
||||
|
||||
expect((useQuery as jest.Mock).mock.calls[0][1].variables.size).toEqual(
|
||||
expect((useQuery as jest.Mock).mock.calls[1][1].variables.size).toEqual(
|
||||
order.size
|
||||
);
|
||||
});
|
||||
@ -99,7 +99,7 @@ describe('useOrderMargin Hook', () => {
|
||||
const calledSize = new BigNumber(mockMarketPositions?.openVolume || 0)
|
||||
.plus(order.size)
|
||||
.toString();
|
||||
expect((useQuery as jest.Mock).mock.calls[0][1].variables.size).toEqual(
|
||||
expect((useQuery as jest.Mock).mock.calls[1][1].variables.size).toEqual(
|
||||
calledSize
|
||||
);
|
||||
});
|
||||
|
@ -12,8 +12,9 @@ import {
|
||||
VegaWalletOrderTimeInForce,
|
||||
VegaWalletOrderType,
|
||||
} from '@vegaprotocol/wallet';
|
||||
import { addDecimal } from '@vegaprotocol/react-helpers';
|
||||
import { addDecimal, removeDecimal } from '@vegaprotocol/react-helpers';
|
||||
import useMarketPositions from './use-market-positions';
|
||||
import useMarketData from './use-market-data';
|
||||
|
||||
export const ESTIMATE_ORDER_QUERY = gql`
|
||||
query EstimateOrder(
|
||||
@ -66,26 +67,35 @@ const types: Record<VegaWalletOrderType, OrderType> = {
|
||||
|
||||
const useOrderMargin = ({ order, market, partyId }: Props) => {
|
||||
const marketPositions = useMarketPositions({ marketId: market.id, partyId });
|
||||
const markPriceData = useMarketData(market.id);
|
||||
const { data } = useQuery<EstimateOrder, EstimateOrderVariables>(
|
||||
ESTIMATE_ORDER_QUERY,
|
||||
{
|
||||
variables: {
|
||||
marketId: market.id,
|
||||
partyId,
|
||||
price: market.depth.lastTrade?.price,
|
||||
size: new BigNumber(marketPositions?.openVolume || 0)
|
||||
[order.side === VegaWalletOrderSide.Buy ? 'plus' : 'minus'](
|
||||
order.size
|
||||
)
|
||||
.toString(),
|
||||
price: markPriceData?.market?.data?.markPrice || '',
|
||||
size: removeDecimal(
|
||||
BigNumber.maximum(
|
||||
0,
|
||||
new BigNumber(marketPositions?.openVolume || 0)[
|
||||
order.side === VegaWalletOrderSide.Buy ? 'plus' : 'minus'
|
||||
](order.size)
|
||||
).toString(),
|
||||
market.positionDecimalPlaces
|
||||
),
|
||||
side: order.side === VegaWalletOrderSide.Buy ? Side.Buy : Side.Sell,
|
||||
timeInForce: times[order.timeInForce],
|
||||
type: types[order.type],
|
||||
},
|
||||
skip:
|
||||
!partyId || !market.id || !order.size || !market.depth.lastTrade?.price,
|
||||
!partyId ||
|
||||
!market.id ||
|
||||
!order.size ||
|
||||
!markPriceData?.market?.data?.markPrice,
|
||||
}
|
||||
);
|
||||
|
||||
if (data?.estimateOrder.marginLevels.initialLevel) {
|
||||
return addDecimal(
|
||||
BigNumber.maximum(
|
||||
|
@ -23,6 +23,9 @@ export function createClient(base?: string) {
|
||||
|
||||
const cache = new InMemoryCache({
|
||||
typePolicies: {
|
||||
Party: {
|
||||
keyFields: false,
|
||||
},
|
||||
Query: {},
|
||||
Account: {
|
||||
keyFields: false,
|
||||
|
@ -4,7 +4,9 @@
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node", "@testing-library/jest-dom"],
|
||||
"jsx": "react"
|
||||
"jsx": "react",
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": [
|
||||
"**/*.test.ts",
|
||||
|
Loading…
Reference in New Issue
Block a user