* feat(#473): add positions metrics data provider * feat(#473) add positions stats * feat(#473) add positions stats * feat(#473): add positions stats * feat(#473): add positions stats * feat(#473): position metrics, test and refactoring * feat(#473): add unit tests to positions table * feat(#473): fix spelling, order positions by updated at desc * feat(#473): protect from division by 0 * feat(#473): fix trading positions e2e tests * feat(#473): fix e2e data mocks * feat(#473): post code review clean up * feat(#993): dependencies handling in data provider * feat(#993): fix e2e tests data mocks * feat(#993): remove position metrics mocks, add market data market id * feat(#993): add missing mocks, fix combine function * feat(#993): set loading initially to true, add unit tests * feat(#993): cleanup, add comments * feat(#993): remove undefined from client type * feat(#993): cosmetic changes * feat:(#993): pass informaton about update callback cause
This commit is contained in:
parent
171babc2c9
commit
93a5f911f5
@ -94,6 +94,12 @@ export const dataProvider = makeDataProvider<
|
||||
SimpleMarkets_markets[],
|
||||
SimpleMarketDataSub,
|
||||
SimpleMarketDataSub_marketData
|
||||
>(MARKETS_QUERY, MARKET_DATA_SUB, update, getData, getDelta);
|
||||
>({
|
||||
query: MARKETS_QUERY,
|
||||
subscriptionQuery: MARKET_DATA_SUB,
|
||||
update,
|
||||
getData,
|
||||
getDelta,
|
||||
});
|
||||
|
||||
export default dataProvider;
|
||||
|
@ -23,6 +23,50 @@ export const generateAccounts = (
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'Account',
|
||||
type: AccountType.General,
|
||||
balance: '100000000',
|
||||
market: null,
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id-2',
|
||||
symbol: 'tDAI',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'Account',
|
||||
type: AccountType.Margin,
|
||||
balance: '1000',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
name: '',
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id',
|
||||
symbol: 'tEURO',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'Account',
|
||||
type: AccountType.Margin,
|
||||
balance: '1000',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
name: '',
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id-2',
|
||||
symbol: 'tDAI',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
40
apps/trading-e2e/src/support/mocks/generate-market-depth.ts
Normal file
40
apps/trading-e2e/src/support/mocks/generate-market-depth.ts
Normal file
@ -0,0 +1,40 @@
|
||||
import merge from 'lodash/merge';
|
||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries
|
||||
import type { MarketDepth } from '../../../../../libs/market-depth/src/lib/__generated__/MarketDepth';
|
||||
|
||||
export const generateMarketDepth = (
|
||||
override?: PartialDeep<MarketDepth>
|
||||
): MarketDepth => {
|
||||
const defaultResult: MarketDepth = {
|
||||
market: {
|
||||
id: 'market-0',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
data: {
|
||||
marketTradingMode: MarketTradingMode.Continuous,
|
||||
staticMidPrice: '0',
|
||||
indicativePrice: '0',
|
||||
bestStaticBidPrice: '0',
|
||||
bestStaticOfferPrice: '0',
|
||||
indicativeVolume: '0',
|
||||
market: {
|
||||
id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35',
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'MarketData',
|
||||
},
|
||||
depth: {
|
||||
__typename: 'MarketDepth',
|
||||
buy: [],
|
||||
sell: [],
|
||||
lastTrade: null,
|
||||
sequenceNumber: '',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
@ -18,6 +18,11 @@ export const generateMarket = (override?: PartialDeep<Market>): Market => {
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
data: {
|
||||
auctionEnd: '',
|
||||
auctionStart: '',
|
||||
indicativePrice: '',
|
||||
suppliedStake: '',
|
||||
targetStake: '',
|
||||
market: {
|
||||
id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35',
|
||||
__typename: 'Market',
|
||||
|
@ -5,14 +5,34 @@ import {
|
||||
MarketTradingMode,
|
||||
} from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type { Markets, Markets_markets } from '@vegaprotocol/market-list';
|
||||
import type { MarketList, MarketList_markets } from '@vegaprotocol/market-list';
|
||||
|
||||
export const generateMarkets = (override?: PartialDeep<Markets>): Markets => {
|
||||
const markets: Markets_markets[] = [
|
||||
export const generateMarkets = (
|
||||
override?: PartialDeep<MarketList>
|
||||
): MarketList => {
|
||||
const markets: MarketList_markets[] = [
|
||||
{
|
||||
id: 'market-0',
|
||||
name: 'ACTIVE MARKET',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradingMode: MarketTradingMode.Continuous,
|
||||
state: MarketState.Active,
|
||||
marketTimestamps: {
|
||||
__typename: 'MarketTimestamps',
|
||||
close: '',
|
||||
open: '',
|
||||
},
|
||||
candles: [],
|
||||
fees: {
|
||||
__typename: 'Fees',
|
||||
factors: {
|
||||
__typename: 'FeeFactors',
|
||||
makerFee: '',
|
||||
infrastructureFee: '',
|
||||
liquidityFee: '',
|
||||
},
|
||||
},
|
||||
data: {
|
||||
market: {
|
||||
id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35',
|
||||
@ -20,6 +40,7 @@ export const generateMarkets = (override?: PartialDeep<Markets>): Markets => {
|
||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
__typename: 'Market',
|
||||
},
|
||||
indicativeVolume: '0',
|
||||
bestBidPrice: '0',
|
||||
bestOfferPrice: '0',
|
||||
markPrice: '4612690058',
|
||||
@ -29,6 +50,11 @@ export const generateMarkets = (override?: PartialDeep<Markets>): Markets => {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'BTCUSD.MF21',
|
||||
name: '',
|
||||
metadata: {
|
||||
__typename: 'InstrumentMetadata',
|
||||
tags: [],
|
||||
},
|
||||
product: {
|
||||
settlementAsset: {
|
||||
symbol: 'tDAI',
|
||||
@ -46,6 +72,24 @@ export const generateMarkets = (override?: PartialDeep<Markets>): Markets => {
|
||||
id: 'market-1',
|
||||
name: 'SUSPENDED MARKET',
|
||||
decimalPlaces: 2,
|
||||
positionDecimalPlaces: 0,
|
||||
tradingMode: MarketTradingMode.Continuous,
|
||||
state: MarketState.Active,
|
||||
marketTimestamps: {
|
||||
__typename: 'MarketTimestamps',
|
||||
close: '',
|
||||
open: '',
|
||||
},
|
||||
candles: [],
|
||||
fees: {
|
||||
__typename: 'Fees',
|
||||
factors: {
|
||||
__typename: 'FeeFactors',
|
||||
makerFee: '',
|
||||
infrastructureFee: '',
|
||||
liquidityFee: '',
|
||||
},
|
||||
},
|
||||
data: {
|
||||
market: {
|
||||
id: '34d95e10faa00c21d19d382d6d7e6fc9722a96985369f0caec041b0f44b775ed',
|
||||
@ -55,6 +99,7 @@ export const generateMarkets = (override?: PartialDeep<Markets>): Markets => {
|
||||
},
|
||||
bestBidPrice: '0',
|
||||
bestOfferPrice: '0',
|
||||
indicativeVolume: '0',
|
||||
markPrice: '8441',
|
||||
trigger: AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
|
||||
__typename: 'MarketData',
|
||||
@ -62,6 +107,11 @@ export const generateMarkets = (override?: PartialDeep<Markets>): Markets => {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'SOLUSD',
|
||||
name: '',
|
||||
metadata: {
|
||||
__typename: 'InstrumentMetadata',
|
||||
tags: [],
|
||||
},
|
||||
product: {
|
||||
settlementAsset: {
|
||||
symbol: 'XYZalpha',
|
||||
|
@ -1,163 +0,0 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type {
|
||||
PositionsMetrics,
|
||||
PositionsMetrics_party_positionsConnection_edges_node,
|
||||
} from '@vegaprotocol/positions';
|
||||
import { MarketTradingMode, AccountType } from '@vegaprotocol/types';
|
||||
|
||||
export const generatePositionsMetrics = (
|
||||
override?: PartialDeep<PositionsMetrics>
|
||||
): PositionsMetrics => {
|
||||
const nodes: PositionsMetrics_party_positionsConnection_edges_node[] = [
|
||||
{
|
||||
realisedPNL: '0',
|
||||
openVolume: '6',
|
||||
unrealisedPNL: '895000',
|
||||
averageEntryPrice: '1129935',
|
||||
updatedAt: '2022-07-28T15:09:34.441143Z',
|
||||
market: {
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
name: 'UNIDAI Monthly (30 Jun 2022)',
|
||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
data: {
|
||||
markPrice: '17588787',
|
||||
__typename: 'MarketData',
|
||||
},
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'UNIDAI Monthly (30 Jun 2022)',
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Position',
|
||||
},
|
||||
{
|
||||
realisedPNL: '0',
|
||||
openVolume: '1',
|
||||
unrealisedPNL: '-22519',
|
||||
averageEntryPrice: '84400088',
|
||||
updatedAt: '2022-07-28T14:53:54.725477Z',
|
||||
market: {
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
name: 'Tesla Quarterly (30 Jun 2022)',
|
||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
data: {
|
||||
markPrice: '84377569',
|
||||
__typename: 'MarketData',
|
||||
},
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'Tesla Quarterly (30 Jun 2022)',
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Position',
|
||||
},
|
||||
];
|
||||
|
||||
const defaultResult: PositionsMetrics = {
|
||||
party: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
accounts: [
|
||||
{
|
||||
__typename: 'Account',
|
||||
type: AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
balance: '100000000',
|
||||
market: null,
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id-2',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'Account',
|
||||
type: AccountType.ACCOUNT_TYPE_MARGIN,
|
||||
balance: '1000',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'Account',
|
||||
type: AccountType.ACCOUNT_TYPE_MARGIN,
|
||||
balance: '1000',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id-2',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
],
|
||||
marginsConnection: {
|
||||
__typename: 'MarginConnection',
|
||||
edges: [
|
||||
{
|
||||
__typename: 'MarginEdge',
|
||||
node: {
|
||||
__typename: 'MarginLevels',
|
||||
maintenanceLevel: '0',
|
||||
searchLevel: '0',
|
||||
initialLevel: '0',
|
||||
collateralReleaseLevel: '0',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
symbol: 'tDAI',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'MarginEdge',
|
||||
node: {
|
||||
__typename: 'MarginLevels',
|
||||
maintenanceLevel: '0',
|
||||
searchLevel: '0',
|
||||
initialLevel: '0',
|
||||
collateralReleaseLevel: '0',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376 ',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
symbol: 'tEURO',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
positionsConnection: {
|
||||
__typename: 'PositionConnection',
|
||||
edges: nodes.map((node) => ({ __typename: 'PositionEdge', node })),
|
||||
},
|
||||
__typename: 'Party',
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
@ -2,76 +2,103 @@ import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type {
|
||||
Positions,
|
||||
Positions_party_positions,
|
||||
Positions_party_positionsConnection_edges_node,
|
||||
} from '@vegaprotocol/positions';
|
||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
|
||||
export const generatePositions = (
|
||||
override?: PartialDeep<Positions>
|
||||
): Positions => {
|
||||
const positions: Positions_party_positions[] = [
|
||||
const nodes: Positions_party_positionsConnection_edges_node[] = [
|
||||
{
|
||||
__typename: 'Position',
|
||||
realisedPNL: '0',
|
||||
openVolume: '6',
|
||||
unrealisedPNL: '895000',
|
||||
averageEntryPrice: '1129935',
|
||||
updatedAt: '2022-07-28T15:09:34.441143Z',
|
||||
marginsConnection: {
|
||||
__typename: 'MarginConnection',
|
||||
edges: [
|
||||
{
|
||||
__typename: 'MarginEdge',
|
||||
node: {
|
||||
__typename: 'MarginLevels',
|
||||
maintenanceLevel: '0',
|
||||
searchLevel: '0',
|
||||
initialLevel: '0',
|
||||
collateralReleaseLevel: '0',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
symbol: 'tDAI',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
market: {
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
name: 'UNIDAI Monthly (30 Jun 2022)',
|
||||
marketTradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
data: {
|
||||
markPrice: '17588787',
|
||||
marketTradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
__typename: 'MarketData',
|
||||
market: { __typename: 'Market', id: '123' },
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
},
|
||||
},
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
id: '',
|
||||
name: 'UNIDAI Monthly (30 Jun 2022)',
|
||||
metadata: {
|
||||
tags: [
|
||||
'formerly:3C58ED2A4A6C5D7E',
|
||||
'base:UNI',
|
||||
'quote:DAI',
|
||||
'class:fx/crypto',
|
||||
'monthly',
|
||||
'sector:defi',
|
||||
],
|
||||
__typename: 'InstrumentMetadata',
|
||||
},
|
||||
code: 'UNIDAI.MF21',
|
||||
product: {
|
||||
settlementAsset: {
|
||||
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
|
||||
symbol: 'tDAI',
|
||||
name: 'tDAI TEST',
|
||||
decimals: 5,
|
||||
__typename: 'Asset',
|
||||
},
|
||||
quoteName: 'DAI',
|
||||
__typename: 'Future',
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Position',
|
||||
},
|
||||
{
|
||||
realisedPNL: '0',
|
||||
openVolume: '1',
|
||||
unrealisedPNL: '-22519',
|
||||
averageEntryPrice: '84400088',
|
||||
updatedAt: '2022-07-28T14:53:54.725477Z',
|
||||
marginsConnection: {
|
||||
__typename: 'MarginConnection',
|
||||
edges: [
|
||||
{
|
||||
__typename: 'MarginEdge',
|
||||
node: {
|
||||
__typename: 'MarginLevels',
|
||||
maintenanceLevel: '0',
|
||||
searchLevel: '0',
|
||||
initialLevel: '0',
|
||||
collateralReleaseLevel: '0',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
},
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
symbol: 'tEURO',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
market: {
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
name: 'Tesla Quarterly (30 Jun 2022)',
|
||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
data: {
|
||||
markPrice: '84377569',
|
||||
marketTradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
__typename: 'MarketData',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
@ -82,32 +109,7 @@ export const generatePositions = (
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
id: '',
|
||||
name: 'Tesla Quarterly (30 Jun 2022)',
|
||||
metadata: {
|
||||
tags: [
|
||||
'formerly:5A86B190C384997F',
|
||||
'quote:EURO',
|
||||
'ticker:TSLA',
|
||||
'class:equities/single-stock-futures',
|
||||
'sector:tech',
|
||||
'listing_venue:NASDAQ',
|
||||
'country:US',
|
||||
],
|
||||
__typename: 'InstrumentMetadata',
|
||||
},
|
||||
code: 'TSLA.QM21',
|
||||
product: {
|
||||
settlementAsset: {
|
||||
id: '8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4',
|
||||
symbol: 'tEURO',
|
||||
name: 'tEURO TEST',
|
||||
decimals: 5,
|
||||
__typename: 'Asset',
|
||||
},
|
||||
quoteName: 'EURO',
|
||||
__typename: 'Future',
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
@ -118,11 +120,19 @@ export const generatePositions = (
|
||||
},
|
||||
];
|
||||
|
||||
const defaultResult = {
|
||||
const defaultResult: Positions = {
|
||||
party: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
positions,
|
||||
__typename: 'Party',
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
positionsConnection: {
|
||||
__typename: 'PositionConnection',
|
||||
edges: nodes.map((node) => {
|
||||
return {
|
||||
__typename: 'PositionEdge',
|
||||
node,
|
||||
};
|
||||
}),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -6,10 +6,10 @@ import { generateCandles } from './mocks/generate-candles';
|
||||
import { generateChart } from './mocks/generate-chart';
|
||||
import { generateDealTicketQuery } from './mocks/generate-deal-ticket-query';
|
||||
import { generateMarket } from './mocks/generate-market';
|
||||
import { generateMarketDepth } from './mocks/generate-market-depth';
|
||||
import { generateMarketInfoQuery } from './mocks/generate-market-info-query';
|
||||
import { generateOrders } from './mocks/generate-orders';
|
||||
import { generatePositions } from './mocks/generate-positions';
|
||||
import { generatePositionsMetrics } from './mocks/generate-positions-metrics';
|
||||
import { generateTrades } from './mocks/generate-trades';
|
||||
|
||||
export const mockTradingPage = (
|
||||
@ -26,10 +26,10 @@ export const mockTradingPage = (
|
||||
},
|
||||
})
|
||||
);
|
||||
aliasQuery(req, 'MarketDepth', generateMarketDepth());
|
||||
aliasQuery(req, 'Orders', generateOrders());
|
||||
aliasQuery(req, 'Accounts', generateAccounts());
|
||||
aliasQuery(req, 'Positions', generatePositions());
|
||||
aliasQuery(req, 'PositionsMetrics', generatePositionsMetrics());
|
||||
aliasQuery(
|
||||
req,
|
||||
'DealTicketQuery',
|
||||
|
@ -17,7 +17,7 @@ import { useGlobalStore } from '../stores';
|
||||
import {
|
||||
AssetDetailsDialog,
|
||||
useAssetDetailsDialogStore,
|
||||
} from '@vegaprotocol/market-list';
|
||||
} from '@vegaprotocol/assets';
|
||||
|
||||
function AppBody({ Component, pageProps }: AppProps) {
|
||||
const store = useGlobalStore();
|
||||
|
@ -31,7 +31,7 @@ import { useGlobalStore } from '../../stores';
|
||||
import { AccountsContainer } from '@vegaprotocol/accounts';
|
||||
import { DepthChartContainer } from '@vegaprotocol/market-depth';
|
||||
import { CandlesChartContainer } from '@vegaprotocol/candles-chart';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/market-list';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import {
|
||||
Tab,
|
||||
|
@ -78,4 +78,10 @@ export const accountsDataProvider = makeDataProvider<
|
||||
Accounts_party_accounts[],
|
||||
AccountSubscribe,
|
||||
AccountSubscribe_accounts
|
||||
>(ACCOUNTS_QUERY, ACCOUNTS_SUB, update, getData, getDelta);
|
||||
>({
|
||||
query: ACCOUNTS_QUERY,
|
||||
subscriptionQuery: ACCOUNTS_SUB,
|
||||
update,
|
||||
getData,
|
||||
getDelta,
|
||||
});
|
||||
|
@ -16,7 +16,7 @@ import { AgGridColumn } from 'ag-grid-react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { Accounts_party_accounts } from './__generated__/Accounts';
|
||||
import { getId } from './accounts-data-provider';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/market-list';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import type { AccountType } from '@vegaprotocol/types';
|
||||
import { AccountTypeMapping } from '@vegaprotocol/types';
|
||||
|
||||
|
12
libs/assets/.babelrc
Normal file
12
libs/assets/.babelrc
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@nrwl/react/babel",
|
||||
{
|
||||
"runtime": "automatic",
|
||||
"useBuiltIns": "usage"
|
||||
}
|
||||
]
|
||||
],
|
||||
"plugins": []
|
||||
}
|
18
libs/assets/.eslintrc.json
Normal file
18
libs/assets/.eslintrc.json
Normal file
@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*", "__generated__"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
7
libs/assets/README.md
Normal file
7
libs/assets/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# assets
|
||||
|
||||
This library was generated with [Nx](https://nx.dev).
|
||||
|
||||
## Running unit tests
|
||||
|
||||
Run `nx test assets` to execute the unit tests via [Jest](https://jestjs.io).
|
10
libs/assets/jest.config.js
Normal file
10
libs/assets/jest.config.js
Normal file
@ -0,0 +1,10 @@
|
||||
module.exports = {
|
||||
displayName: 'assets',
|
||||
preset: '../../jest.preset.js',
|
||||
transform: {
|
||||
'^.+\\.[tj]sx?$': 'babel-jest',
|
||||
},
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
||||
coverageDirectory: '../../coverage/libs/assets',
|
||||
setupFilesAfterEnv: ['./src/setup-tests.ts'],
|
||||
};
|
4
libs/assets/package.json
Normal file
4
libs/assets/package.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"name": "@vegaprotocol/assets",
|
||||
"version": "0.0.1"
|
||||
}
|
43
libs/assets/project.json
Normal file
43
libs/assets/project.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"root": "libs/assets",
|
||||
"sourceRoot": "libs/assets/src",
|
||||
"projectType": "library",
|
||||
"tags": [],
|
||||
"targets": {
|
||||
"build": {
|
||||
"executor": "@nrwl/web:rollup",
|
||||
"outputs": ["{options.outputPath}"],
|
||||
"options": {
|
||||
"outputPath": "dist/libs/assets",
|
||||
"tsConfig": "libs/assets/tsconfig.lib.json",
|
||||
"project": "libs/assets/package.json",
|
||||
"entryFile": "libs/assets/src/index.ts",
|
||||
"external": ["react/jsx-runtime"],
|
||||
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
|
||||
"compiler": "babel",
|
||||
"assets": [
|
||||
{
|
||||
"glob": "libs/assets/README.md",
|
||||
"input": ".",
|
||||
"output": "."
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nrwl/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["libs/assets/**/*.{ts,tsx,js,jsx}"]
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nrwl/jest:jest",
|
||||
"outputs": ["coverage/libs/assets"],
|
||||
"options": {
|
||||
"jestConfig": "libs/assets/jest.config.js",
|
||||
"passWithNoTests": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
1
libs/assets/src/index.ts
Normal file
1
libs/assets/src/index.ts
Normal file
@ -0,0 +1 @@
|
||||
export * from './lib';
|
1
libs/assets/src/setup-tests.ts
Normal file
1
libs/assets/src/setup-tests.ts
Normal file
@ -0,0 +1 @@
|
||||
import '@testing-library/jest-dom';
|
25
libs/assets/tsconfig.json
Normal file
25
libs/assets/tsconfig.json
Normal file
@ -0,0 +1,25 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"allowJs": true,
|
||||
"esModuleInterop": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"strict": true,
|
||||
"noImplicitOverride": true,
|
||||
"noPropertyAccessFromIndexSignature": true,
|
||||
"noImplicitReturns": true,
|
||||
"noFallthroughCasesInSwitch": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.lib.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
22
libs/assets/tsconfig.lib.json
Normal file
22
libs/assets/tsconfig.lib.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": ["node"]
|
||||
},
|
||||
"files": [
|
||||
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
|
||||
"../../node_modules/@nrwl/react/typings/image.d.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.js",
|
||||
"**/*.test.js",
|
||||
"**/*.spec.jsx",
|
||||
"**/*.test.jsx"
|
||||
],
|
||||
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
|
||||
}
|
19
libs/assets/tsconfig.spec.json
Normal file
19
libs/assets/tsconfig.spec.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": [
|
||||
"**/*.test.ts",
|
||||
"**/*.spec.ts",
|
||||
"**/*.test.tsx",
|
||||
"**/*.spec.tsx",
|
||||
"**/*.test.js",
|
||||
"**/*.spec.js",
|
||||
"**/*.test.jsx",
|
||||
"**/*.spec.jsx",
|
||||
"**/*.d.ts"
|
||||
]
|
||||
}
|
@ -25,7 +25,7 @@ import type { ReactNode } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { Controller, useForm, useWatch } from 'react-hook-form';
|
||||
import { DepositLimits } from './deposit-limits';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/market-list';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
|
||||
interface FormFields {
|
||||
asset: string;
|
||||
|
@ -129,15 +129,15 @@ const getPageInfo = (responseData: Fills): PageInfo | null =>
|
||||
|
||||
const getDelta = (subscriptionData: FillsSub) => subscriptionData.trades || [];
|
||||
|
||||
export const fillsDataProvider = makeDataProvider(
|
||||
FILLS_QUERY,
|
||||
FILLS_SUB,
|
||||
export const fillsDataProvider = makeDataProvider({
|
||||
query: FILLS_QUERY,
|
||||
subscriptionQuery: FILLS_SUB,
|
||||
update,
|
||||
getData,
|
||||
getDelta,
|
||||
{
|
||||
pagination: {
|
||||
getPageInfo,
|
||||
append,
|
||||
first: 100,
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
|
@ -102,8 +102,11 @@ const update: Update<
|
||||
}
|
||||
*/
|
||||
sequenceNumbers[delta.market.id] = sequenceNumber;
|
||||
const updatedData = { ...data };
|
||||
data.data = delta.market.data;
|
||||
const updatedData = {
|
||||
...data,
|
||||
data: delta.market.data,
|
||||
depth: { ...data.depth },
|
||||
};
|
||||
if (delta.buy) {
|
||||
updatedData.depth.buy = updateLevels(data.depth.buy ?? [], delta.buy);
|
||||
}
|
||||
@ -124,12 +127,12 @@ const getData = (responseData: MarketDepth) => {
|
||||
const getDelta = (subscriptionData: MarketDepthSubscription) =>
|
||||
subscriptionData.marketDepthUpdate;
|
||||
|
||||
export const marketDepthDataProvider = makeDataProvider(
|
||||
MARKET_DEPTH_QUERY,
|
||||
MARKET_DEPTH_SUBSCRIPTION_QUERY,
|
||||
export const marketDepthDataProvider = makeDataProvider({
|
||||
query: MARKET_DEPTH_QUERY,
|
||||
subscriptionQuery: MARKET_DEPTH_SUBSCRIPTION_QUERY,
|
||||
update,
|
||||
getData,
|
||||
getDelta
|
||||
);
|
||||
getDelta,
|
||||
});
|
||||
|
||||
export default marketDepthDataProvider;
|
||||
|
@ -1,5 +1,4 @@
|
||||
export * from './markets-container';
|
||||
export * from './asset-details-dialog';
|
||||
export * from './select-market-columns';
|
||||
export * from './select-market-table';
|
||||
export * from './select-market';
|
||||
|
@ -21,7 +21,7 @@ import type {
|
||||
MarketList_markets,
|
||||
MarketList_markets_data,
|
||||
} from '../../__generated__';
|
||||
import { useAssetDetailsDialogStore } from '../asset-details-dialog';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
|
||||
type Props = AgGridReactProps | AgReactUiProps;
|
||||
|
||||
|
@ -20,7 +20,7 @@ import { columns } from './select-market-columns';
|
||||
import type { MarketList } from '../__generated__';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import type { Positions } from '@vegaprotocol/positions';
|
||||
import { POSITION_QUERY } from '@vegaprotocol/positions';
|
||||
import { POSITIONS_QUERY } from '@vegaprotocol/positions';
|
||||
import { mapDataToMarketList } from '../utils/market-utils';
|
||||
import {
|
||||
SelectMarketTableHeader,
|
||||
@ -120,7 +120,7 @@ export const SelectMarketPopover = ({
|
||||
const [open, setOpen] = useState(false);
|
||||
const { data } = useMarkets();
|
||||
const variables = useMemo(() => ({ partyId: keypair?.pub }), [keypair?.pub]);
|
||||
const { data: marketDataPositions } = useQuery<Positions>(POSITION_QUERY, {
|
||||
const { data: marketDataPositions } = useQuery<Positions>(POSITIONS_QUERY, {
|
||||
variables,
|
||||
skip: !keypair?.pub,
|
||||
});
|
||||
@ -130,14 +130,15 @@ export const SelectMarketPopover = ({
|
||||
markets:
|
||||
data?.markets
|
||||
?.filter((market) =>
|
||||
marketDataPositions?.party?.positions?.find(
|
||||
(position) => position.market.id === market.id
|
||||
marketDataPositions?.party?.positionsConnection.edges?.find(
|
||||
(edge) => edge.node.market.id === market.id
|
||||
)
|
||||
)
|
||||
.map((market) => {
|
||||
const position = marketDataPositions?.party?.positions?.find(
|
||||
(position) => position.market.id === market.id
|
||||
);
|
||||
const position =
|
||||
marketDataPositions?.party?.positionsConnection.edges?.find(
|
||||
(edge) => edge.node.market.id === market.id
|
||||
)?.node;
|
||||
return {
|
||||
...market,
|
||||
openVolume:
|
||||
|
@ -114,4 +114,10 @@ export const marketsDataProvider = makeDataProvider<
|
||||
MarketList_markets[],
|
||||
MarketDataSub,
|
||||
MarketDataSub_marketData
|
||||
>(MARKET_LIST_QUERY, MARKET_DATA_SUB, update, getData, getDelta);
|
||||
>({
|
||||
query: MARKET_LIST_QUERY,
|
||||
subscriptionQuery: MARKET_DATA_SUB,
|
||||
update,
|
||||
getData,
|
||||
getDelta,
|
||||
});
|
||||
|
@ -115,15 +115,15 @@ const getDelta = (subscriptionData: OrderSub) => subscriptionData.orders || [];
|
||||
const getPageInfo = (responseData: Orders): PageInfo | null =>
|
||||
responseData.party?.ordersConnection.pageInfo || null;
|
||||
|
||||
export const ordersDataProvider = makeDataProvider(
|
||||
ORDERS_QUERY,
|
||||
ORDERS_SUB,
|
||||
export const ordersDataProvider = makeDataProvider({
|
||||
query: ORDERS_QUERY,
|
||||
subscriptionQuery: ORDERS_SUB,
|
||||
update,
|
||||
getData,
|
||||
getDelta,
|
||||
{
|
||||
pagination: {
|
||||
getPageInfo,
|
||||
append,
|
||||
first: 100,
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
|
@ -1,6 +1,4 @@
|
||||
export * from './lib/positions-table';
|
||||
export * from './lib/positions-container';
|
||||
export { positionsMetricsDataProvider } from './lib/positions-metrics-data-provider';
|
||||
export * from './lib/positions-data-provider';
|
||||
export * from './lib/__generated__/PositionsMetrics';
|
||||
export * from './lib/positions-data-providers';
|
||||
export * from './lib/__generated__/Positions';
|
||||
|
122
libs/positions/src/lib/__generated__/PositionDetails.ts
generated
122
libs/positions/src/lib/__generated__/PositionDetails.ts
generated
@ -1,122 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { MarketTradingMode } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL fragment: PositionDetails
|
||||
// ====================================================
|
||||
|
||||
export interface PositionDetails_market_data_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface PositionDetails_market_data {
|
||||
__typename: "MarketData";
|
||||
/**
|
||||
* the mark price (an unsigned integer)
|
||||
*/
|
||||
markPrice: string;
|
||||
/**
|
||||
* what state the market is in (auction, continuous, etc)
|
||||
*/
|
||||
marketTradingMode: MarketTradingMode;
|
||||
/**
|
||||
* market ID of the associated mark price
|
||||
*/
|
||||
market: PositionDetails_market_data_market;
|
||||
}
|
||||
|
||||
export interface PositionDetails_market_tradableInstrument_instrument {
|
||||
__typename: "Instrument";
|
||||
/**
|
||||
* Full and fairly descriptive name for the instrument
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
|
||||
*/
|
||||
code: string;
|
||||
}
|
||||
|
||||
export interface PositionDetails_market_tradableInstrument {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of, or reference to, a fully specified instrument.
|
||||
*/
|
||||
instrument: PositionDetails_market_tradableInstrument_instrument;
|
||||
}
|
||||
|
||||
export interface PositionDetails_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Market full name
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* marketData for the given market
|
||||
*/
|
||||
data: PositionDetails_market_data | null;
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* positionDecimalPlaces indicates the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||
* This sets how big the smallest order / position on the market can be.
|
||||
*/
|
||||
positionDecimalPlaces: number;
|
||||
/**
|
||||
* An instance of, or reference to, a tradable instrument.
|
||||
*/
|
||||
tradableInstrument: PositionDetails_market_tradableInstrument;
|
||||
}
|
||||
|
||||
export interface PositionDetails {
|
||||
__typename: "Position";
|
||||
/**
|
||||
* Realised Profit and Loss (int64)
|
||||
*/
|
||||
realisedPNL: string;
|
||||
/**
|
||||
* Open volume (uint64)
|
||||
*/
|
||||
openVolume: string;
|
||||
/**
|
||||
* Unrealised Profit and Loss (int64)
|
||||
*/
|
||||
unrealisedPNL: string;
|
||||
/**
|
||||
* Average entry price for this position
|
||||
*/
|
||||
averageEntryPrice: string;
|
||||
/**
|
||||
* Market relating to this position
|
||||
*/
|
||||
market: PositionDetails_market;
|
||||
}
|
@ -6,10 +6,68 @@
|
||||
import { MarketTradingMode } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL subscription operation: PositionsMetricsSubscription
|
||||
// GraphQL fragment: PositionFields
|
||||
// ====================================================
|
||||
|
||||
export interface PositionsMetricsSubscription_positions_market_tradableInstrument_instrument {
|
||||
export interface PositionFields_marginsConnection_edges_node_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface PositionFields_marginsConnection_edges_node_asset {
|
||||
__typename: "Asset";
|
||||
/**
|
||||
* The symbol of the asset (e.g: GBP)
|
||||
*/
|
||||
symbol: string;
|
||||
}
|
||||
|
||||
export interface PositionFields_marginsConnection_edges_node {
|
||||
__typename: "MarginLevels";
|
||||
/**
|
||||
* market in which the margin is required for this party
|
||||
*/
|
||||
market: PositionFields_marginsConnection_edges_node_market;
|
||||
/**
|
||||
* minimal margin for the position to be maintained in the network (unsigned integer)
|
||||
*/
|
||||
maintenanceLevel: string;
|
||||
/**
|
||||
* if the margin is between maintenance and search, the network will initiate a collateral search (unsigned integer)
|
||||
*/
|
||||
searchLevel: string;
|
||||
/**
|
||||
* this is the minimum margin required for a party to place a new order on the network (unsigned integer)
|
||||
*/
|
||||
initialLevel: string;
|
||||
/**
|
||||
* If the margin of the party is greater than this level, then collateral will be released from the margin account into
|
||||
* the general account of the party for the given asset.
|
||||
*/
|
||||
collateralReleaseLevel: string;
|
||||
/**
|
||||
* asset for the current margins
|
||||
*/
|
||||
asset: PositionFields_marginsConnection_edges_node_asset;
|
||||
}
|
||||
|
||||
export interface PositionFields_marginsConnection_edges {
|
||||
__typename: "MarginEdge";
|
||||
node: PositionFields_marginsConnection_edges_node;
|
||||
}
|
||||
|
||||
export interface PositionFields_marginsConnection {
|
||||
__typename: "MarginConnection";
|
||||
/**
|
||||
* The margin levels in this connection
|
||||
*/
|
||||
edges: PositionFields_marginsConnection_edges[] | null;
|
||||
}
|
||||
|
||||
export interface PositionFields_market_tradableInstrument_instrument {
|
||||
__typename: "Instrument";
|
||||
/**
|
||||
* Full and fairly descriptive name for the instrument
|
||||
@ -17,23 +75,35 @@ export interface PositionsMetricsSubscription_positions_market_tradableInstrumen
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface PositionsMetricsSubscription_positions_market_tradableInstrument {
|
||||
export interface PositionFields_market_tradableInstrument {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of, or reference to, a fully specified instrument.
|
||||
*/
|
||||
instrument: PositionsMetricsSubscription_positions_market_tradableInstrument_instrument;
|
||||
instrument: PositionFields_market_tradableInstrument_instrument;
|
||||
}
|
||||
|
||||
export interface PositionsMetricsSubscription_positions_market_data {
|
||||
export interface PositionFields_market_data_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface PositionFields_market_data {
|
||||
__typename: "MarketData";
|
||||
/**
|
||||
* the mark price (an unsigned integer)
|
||||
*/
|
||||
markPrice: string;
|
||||
/**
|
||||
* market ID of the associated mark price
|
||||
*/
|
||||
market: PositionFields_market_data_market;
|
||||
}
|
||||
|
||||
export interface PositionsMetricsSubscription_positions_market {
|
||||
export interface PositionFields_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
@ -74,14 +144,14 @@ export interface PositionsMetricsSubscription_positions_market {
|
||||
/**
|
||||
* An instance of, or reference to, a tradable instrument.
|
||||
*/
|
||||
tradableInstrument: PositionsMetricsSubscription_positions_market_tradableInstrument;
|
||||
tradableInstrument: PositionFields_market_tradableInstrument;
|
||||
/**
|
||||
* marketData for the given market
|
||||
*/
|
||||
data: PositionsMetricsSubscription_positions_market_data | null;
|
||||
data: PositionFields_market_data | null;
|
||||
}
|
||||
|
||||
export interface PositionsMetricsSubscription_positions {
|
||||
export interface PositionFields {
|
||||
__typename: "Position";
|
||||
/**
|
||||
* Realised Profit and Loss (int64)
|
||||
@ -103,19 +173,12 @@ export interface PositionsMetricsSubscription_positions {
|
||||
* RFC3339Nano time the position was updated
|
||||
*/
|
||||
updatedAt: string | null;
|
||||
/**
|
||||
* Margins of the party for the given position
|
||||
*/
|
||||
marginsConnection: PositionFields_marginsConnection;
|
||||
/**
|
||||
* Market relating to this position
|
||||
*/
|
||||
market: PositionsMetricsSubscription_positions_market;
|
||||
}
|
||||
|
||||
export interface PositionsMetricsSubscription {
|
||||
/**
|
||||
* Subscribe to the positions updates
|
||||
*/
|
||||
positions: PositionsMetricsSubscription_positions;
|
||||
}
|
||||
|
||||
export interface PositionsMetricsSubscriptionVariables {
|
||||
partyId: string;
|
||||
market: PositionFields_market;
|
||||
}
|
@ -1,110 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { MarketTradingMode } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL fragment: PositionMetricsFields
|
||||
// ====================================================
|
||||
|
||||
export interface PositionMetricsFields_market_tradableInstrument_instrument {
|
||||
__typename: "Instrument";
|
||||
/**
|
||||
* Full and fairly descriptive name for the instrument
|
||||
*/
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface PositionMetricsFields_market_tradableInstrument {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of, or reference to, a fully specified instrument.
|
||||
*/
|
||||
instrument: PositionMetricsFields_market_tradableInstrument_instrument;
|
||||
}
|
||||
|
||||
export interface PositionMetricsFields_market_data {
|
||||
__typename: "MarketData";
|
||||
/**
|
||||
* the mark price (an unsigned integer)
|
||||
*/
|
||||
markPrice: string;
|
||||
}
|
||||
|
||||
export interface PositionMetricsFields_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Market full name
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* positionDecimalPlaces indicates the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||
* This sets how big the smallest order / position on the market can be.
|
||||
*/
|
||||
positionDecimalPlaces: number;
|
||||
/**
|
||||
* Current mode of execution of the market
|
||||
*/
|
||||
tradingMode: MarketTradingMode;
|
||||
/**
|
||||
* An instance of, or reference to, a tradable instrument.
|
||||
*/
|
||||
tradableInstrument: PositionMetricsFields_market_tradableInstrument;
|
||||
/**
|
||||
* marketData for the given market
|
||||
*/
|
||||
data: PositionMetricsFields_market_data | null;
|
||||
}
|
||||
|
||||
export interface PositionMetricsFields {
|
||||
__typename: "Position";
|
||||
/**
|
||||
* Realised Profit and Loss (int64)
|
||||
*/
|
||||
realisedPNL: string;
|
||||
/**
|
||||
* Open volume (uint64)
|
||||
*/
|
||||
openVolume: string;
|
||||
/**
|
||||
* Unrealised Profit and Loss (int64)
|
||||
*/
|
||||
unrealisedPNL: string;
|
||||
/**
|
||||
* Average entry price for this position
|
||||
*/
|
||||
averageEntryPrice: string;
|
||||
/**
|
||||
* RFC3339Nano time the position was updated
|
||||
*/
|
||||
updatedAt: string | null;
|
||||
/**
|
||||
* Market relating to this position
|
||||
*/
|
||||
market: PositionMetricsFields_market;
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { MarketTradingMode } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL subscription operation: PositionSubscribe
|
||||
// ====================================================
|
||||
|
||||
export interface PositionSubscribe_positions_market_data_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface PositionSubscribe_positions_market_data {
|
||||
__typename: "MarketData";
|
||||
/**
|
||||
* the mark price (an unsigned integer)
|
||||
*/
|
||||
markPrice: string;
|
||||
/**
|
||||
* what state the market is in (auction, continuous, etc)
|
||||
*/
|
||||
marketTradingMode: MarketTradingMode;
|
||||
/**
|
||||
* market ID of the associated mark price
|
||||
*/
|
||||
market: PositionSubscribe_positions_market_data_market;
|
||||
}
|
||||
|
||||
export interface PositionSubscribe_positions_market_tradableInstrument_instrument {
|
||||
__typename: "Instrument";
|
||||
/**
|
||||
* Full and fairly descriptive name for the instrument
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
|
||||
*/
|
||||
code: string;
|
||||
}
|
||||
|
||||
export interface PositionSubscribe_positions_market_tradableInstrument {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of, or reference to, a fully specified instrument.
|
||||
*/
|
||||
instrument: PositionSubscribe_positions_market_tradableInstrument_instrument;
|
||||
}
|
||||
|
||||
export interface PositionSubscribe_positions_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Market full name
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* marketData for the given market
|
||||
*/
|
||||
data: PositionSubscribe_positions_market_data | null;
|
||||
/**
|
||||
* 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;
|
||||
/**
|
||||
* positionDecimalPlaces indicates the number of decimal places that an integer must be shifted in order to get a correct size (uint64).
|
||||
* i.e. 0 means there are no fractional orders for the market, and order sizes are always whole sizes.
|
||||
* 2 means sizes given as 10^2 * desired size, e.g. a desired size of 1.23 is represented as 123 in this market.
|
||||
* This sets how big the smallest order / position on the market can be.
|
||||
*/
|
||||
positionDecimalPlaces: number;
|
||||
/**
|
||||
* An instance of, or reference to, a tradable instrument.
|
||||
*/
|
||||
tradableInstrument: PositionSubscribe_positions_market_tradableInstrument;
|
||||
}
|
||||
|
||||
export interface PositionSubscribe_positions {
|
||||
__typename: "Position";
|
||||
/**
|
||||
* Realised Profit and Loss (int64)
|
||||
*/
|
||||
realisedPNL: string;
|
||||
/**
|
||||
* Open volume (uint64)
|
||||
*/
|
||||
openVolume: string;
|
||||
/**
|
||||
* Unrealised Profit and Loss (int64)
|
||||
*/
|
||||
unrealisedPNL: string;
|
||||
/**
|
||||
* Average entry price for this position
|
||||
*/
|
||||
averageEntryPrice: string;
|
||||
/**
|
||||
* Market relating to this position
|
||||
*/
|
||||
market: PositionSubscribe_positions_market;
|
||||
}
|
||||
|
||||
export interface PositionSubscribe {
|
||||
/**
|
||||
* Subscribe to the positions updates
|
||||
*/
|
||||
positions: PositionSubscribe_positions;
|
||||
}
|
||||
|
||||
export interface PositionSubscribeVariables {
|
||||
partyId: string;
|
||||
}
|
147
libs/positions/src/lib/__generated__/Positions.ts
generated
147
libs/positions/src/lib/__generated__/Positions.ts
generated
@ -9,7 +9,7 @@ import { MarketTradingMode } from "@vegaprotocol/types";
|
||||
// GraphQL query operation: Positions
|
||||
// ====================================================
|
||||
|
||||
export interface Positions_party_positions_market_data_market {
|
||||
export interface Positions_party_positionsConnection_edges_node_marginsConnection_edges_node_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
@ -17,43 +17,93 @@ export interface Positions_party_positions_market_data_market {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface Positions_party_positions_market_data {
|
||||
export interface Positions_party_positionsConnection_edges_node_marginsConnection_edges_node_asset {
|
||||
__typename: "Asset";
|
||||
/**
|
||||
* The symbol of the asset (e.g: GBP)
|
||||
*/
|
||||
symbol: string;
|
||||
}
|
||||
|
||||
export interface Positions_party_positionsConnection_edges_node_marginsConnection_edges_node {
|
||||
__typename: "MarginLevels";
|
||||
/**
|
||||
* market in which the margin is required for this party
|
||||
*/
|
||||
market: Positions_party_positionsConnection_edges_node_marginsConnection_edges_node_market;
|
||||
/**
|
||||
* minimal margin for the position to be maintained in the network (unsigned integer)
|
||||
*/
|
||||
maintenanceLevel: string;
|
||||
/**
|
||||
* if the margin is between maintenance and search, the network will initiate a collateral search (unsigned integer)
|
||||
*/
|
||||
searchLevel: string;
|
||||
/**
|
||||
* this is the minimum margin required for a party to place a new order on the network (unsigned integer)
|
||||
*/
|
||||
initialLevel: string;
|
||||
/**
|
||||
* If the margin of the party is greater than this level, then collateral will be released from the margin account into
|
||||
* the general account of the party for the given asset.
|
||||
*/
|
||||
collateralReleaseLevel: string;
|
||||
/**
|
||||
* asset for the current margins
|
||||
*/
|
||||
asset: Positions_party_positionsConnection_edges_node_marginsConnection_edges_node_asset;
|
||||
}
|
||||
|
||||
export interface Positions_party_positionsConnection_edges_node_marginsConnection_edges {
|
||||
__typename: "MarginEdge";
|
||||
node: Positions_party_positionsConnection_edges_node_marginsConnection_edges_node;
|
||||
}
|
||||
|
||||
export interface Positions_party_positionsConnection_edges_node_marginsConnection {
|
||||
__typename: "MarginConnection";
|
||||
/**
|
||||
* The margin levels in this connection
|
||||
*/
|
||||
edges: Positions_party_positionsConnection_edges_node_marginsConnection_edges[] | null;
|
||||
}
|
||||
|
||||
export interface Positions_party_positionsConnection_edges_node_market_tradableInstrument_instrument {
|
||||
__typename: "Instrument";
|
||||
/**
|
||||
* Full and fairly descriptive name for the instrument
|
||||
*/
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface Positions_party_positionsConnection_edges_node_market_tradableInstrument {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of, or reference to, a fully specified instrument.
|
||||
*/
|
||||
instrument: Positions_party_positionsConnection_edges_node_market_tradableInstrument_instrument;
|
||||
}
|
||||
|
||||
export interface Positions_party_positionsConnection_edges_node_market_data_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface Positions_party_positionsConnection_edges_node_market_data {
|
||||
__typename: "MarketData";
|
||||
/**
|
||||
* the mark price (an unsigned integer)
|
||||
*/
|
||||
markPrice: string;
|
||||
/**
|
||||
* what state the market is in (auction, continuous, etc)
|
||||
*/
|
||||
marketTradingMode: MarketTradingMode;
|
||||
/**
|
||||
* market ID of the associated mark price
|
||||
*/
|
||||
market: Positions_party_positions_market_data_market;
|
||||
market: Positions_party_positionsConnection_edges_node_market_data_market;
|
||||
}
|
||||
|
||||
export interface Positions_party_positions_market_tradableInstrument_instrument {
|
||||
__typename: "Instrument";
|
||||
/**
|
||||
* Full and fairly descriptive name for the instrument
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
|
||||
*/
|
||||
code: string;
|
||||
}
|
||||
|
||||
export interface Positions_party_positions_market_tradableInstrument {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of, or reference to, a fully specified instrument.
|
||||
*/
|
||||
instrument: Positions_party_positions_market_tradableInstrument_instrument;
|
||||
}
|
||||
|
||||
export interface Positions_party_positions_market {
|
||||
export interface Positions_party_positionsConnection_edges_node_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
@ -63,10 +113,6 @@ export interface Positions_party_positions_market {
|
||||
* Market full name
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* marketData for the given market
|
||||
*/
|
||||
data: Positions_party_positions_market_data | null;
|
||||
/**
|
||||
* 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)
|
||||
@ -91,13 +137,21 @@ export interface Positions_party_positions_market {
|
||||
* This sets how big the smallest order / position on the market can be.
|
||||
*/
|
||||
positionDecimalPlaces: number;
|
||||
/**
|
||||
* Current mode of execution of the market
|
||||
*/
|
||||
tradingMode: MarketTradingMode;
|
||||
/**
|
||||
* An instance of, or reference to, a tradable instrument.
|
||||
*/
|
||||
tradableInstrument: Positions_party_positions_market_tradableInstrument;
|
||||
tradableInstrument: Positions_party_positionsConnection_edges_node_market_tradableInstrument;
|
||||
/**
|
||||
* marketData for the given market
|
||||
*/
|
||||
data: Positions_party_positionsConnection_edges_node_market_data | null;
|
||||
}
|
||||
|
||||
export interface Positions_party_positions {
|
||||
export interface Positions_party_positionsConnection_edges_node {
|
||||
__typename: "Position";
|
||||
/**
|
||||
* Realised Profit and Loss (int64)
|
||||
@ -115,10 +169,31 @@ export interface Positions_party_positions {
|
||||
* Average entry price for this position
|
||||
*/
|
||||
averageEntryPrice: string;
|
||||
/**
|
||||
* RFC3339Nano time the position was updated
|
||||
*/
|
||||
updatedAt: string | null;
|
||||
/**
|
||||
* Margins of the party for the given position
|
||||
*/
|
||||
marginsConnection: Positions_party_positionsConnection_edges_node_marginsConnection;
|
||||
/**
|
||||
* Market relating to this position
|
||||
*/
|
||||
market: Positions_party_positions_market;
|
||||
market: Positions_party_positionsConnection_edges_node_market;
|
||||
}
|
||||
|
||||
export interface Positions_party_positionsConnection_edges {
|
||||
__typename: "PositionEdge";
|
||||
node: Positions_party_positionsConnection_edges_node;
|
||||
}
|
||||
|
||||
export interface Positions_party_positionsConnection {
|
||||
__typename: "PositionConnection";
|
||||
/**
|
||||
* The positions in this connection
|
||||
*/
|
||||
edges: Positions_party_positionsConnection_edges[] | null;
|
||||
}
|
||||
|
||||
export interface Positions_party {
|
||||
@ -130,7 +205,7 @@ export interface Positions_party {
|
||||
/**
|
||||
* Trading positions relating to a party
|
||||
*/
|
||||
positions: Positions_party_positions[] | null;
|
||||
positionsConnection: Positions_party_positionsConnection;
|
||||
}
|
||||
|
||||
export interface Positions {
|
||||
|
@ -3,25 +3,13 @@
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { AccountType, MarketTradingMode } from "@vegaprotocol/types";
|
||||
import { MarketTradingMode } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL query operation: PositionsMetrics
|
||||
// GraphQL subscription operation: PositionsSubscription
|
||||
// ====================================================
|
||||
|
||||
export interface PositionsMetrics_party_accounts_asset {
|
||||
__typename: "Asset";
|
||||
/**
|
||||
* The ID of the asset
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The precision of the asset. Should match the decimal precision of the asset on its native chain, e.g: for ERC20 assets, it is often 18
|
||||
*/
|
||||
decimals: number;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_accounts_market {
|
||||
export interface PositionsSubscription_positions_marginsConnection_edges_node_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
@ -29,35 +17,7 @@ export interface PositionsMetrics_party_accounts_market {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_accounts {
|
||||
__typename: "Account";
|
||||
/**
|
||||
* Account type (General, Margin, etc)
|
||||
*/
|
||||
type: AccountType;
|
||||
/**
|
||||
* Asset, the 'currency'
|
||||
*/
|
||||
asset: PositionsMetrics_party_accounts_asset;
|
||||
/**
|
||||
* Balance as string - current account balance (approx. as balances can be updated several times per second)
|
||||
*/
|
||||
balance: string;
|
||||
/**
|
||||
* Market (only relevant to margin accounts)
|
||||
*/
|
||||
market: PositionsMetrics_party_accounts_market | null;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_marginsConnection_edges_node_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_marginsConnection_edges_node_asset {
|
||||
export interface PositionsSubscription_positions_marginsConnection_edges_node_asset {
|
||||
__typename: "Asset";
|
||||
/**
|
||||
* The symbol of the asset (e.g: GBP)
|
||||
@ -65,12 +25,12 @@ export interface PositionsMetrics_party_marginsConnection_edges_node_asset {
|
||||
symbol: string;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_marginsConnection_edges_node {
|
||||
export interface PositionsSubscription_positions_marginsConnection_edges_node {
|
||||
__typename: "MarginLevels";
|
||||
/**
|
||||
* market in which the margin is required for this party
|
||||
*/
|
||||
market: PositionsMetrics_party_marginsConnection_edges_node_market;
|
||||
market: PositionsSubscription_positions_marginsConnection_edges_node_market;
|
||||
/**
|
||||
* minimal margin for the position to be maintained in the network (unsigned integer)
|
||||
*/
|
||||
@ -91,23 +51,23 @@ export interface PositionsMetrics_party_marginsConnection_edges_node {
|
||||
/**
|
||||
* asset for the current margins
|
||||
*/
|
||||
asset: PositionsMetrics_party_marginsConnection_edges_node_asset;
|
||||
asset: PositionsSubscription_positions_marginsConnection_edges_node_asset;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_marginsConnection_edges {
|
||||
export interface PositionsSubscription_positions_marginsConnection_edges {
|
||||
__typename: "MarginEdge";
|
||||
node: PositionsMetrics_party_marginsConnection_edges_node;
|
||||
node: PositionsSubscription_positions_marginsConnection_edges_node;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_marginsConnection {
|
||||
export interface PositionsSubscription_positions_marginsConnection {
|
||||
__typename: "MarginConnection";
|
||||
/**
|
||||
* The margin levels in this connection
|
||||
*/
|
||||
edges: PositionsMetrics_party_marginsConnection_edges[] | null;
|
||||
edges: PositionsSubscription_positions_marginsConnection_edges[] | null;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_positionsConnection_edges_node_market_tradableInstrument_instrument {
|
||||
export interface PositionsSubscription_positions_market_tradableInstrument_instrument {
|
||||
__typename: "Instrument";
|
||||
/**
|
||||
* Full and fairly descriptive name for the instrument
|
||||
@ -115,23 +75,35 @@ export interface PositionsMetrics_party_positionsConnection_edges_node_market_tr
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_positionsConnection_edges_node_market_tradableInstrument {
|
||||
export interface PositionsSubscription_positions_market_tradableInstrument {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of, or reference to, a fully specified instrument.
|
||||
*/
|
||||
instrument: PositionsMetrics_party_positionsConnection_edges_node_market_tradableInstrument_instrument;
|
||||
instrument: PositionsSubscription_positions_market_tradableInstrument_instrument;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_positionsConnection_edges_node_market_data {
|
||||
export interface PositionsSubscription_positions_market_data_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface PositionsSubscription_positions_market_data {
|
||||
__typename: "MarketData";
|
||||
/**
|
||||
* the mark price (an unsigned integer)
|
||||
*/
|
||||
markPrice: string;
|
||||
/**
|
||||
* market ID of the associated mark price
|
||||
*/
|
||||
market: PositionsSubscription_positions_market_data_market;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_positionsConnection_edges_node_market {
|
||||
export interface PositionsSubscription_positions_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
@ -172,14 +144,14 @@ export interface PositionsMetrics_party_positionsConnection_edges_node_market {
|
||||
/**
|
||||
* An instance of, or reference to, a tradable instrument.
|
||||
*/
|
||||
tradableInstrument: PositionsMetrics_party_positionsConnection_edges_node_market_tradableInstrument;
|
||||
tradableInstrument: PositionsSubscription_positions_market_tradableInstrument;
|
||||
/**
|
||||
* marketData for the given market
|
||||
*/
|
||||
data: PositionsMetrics_party_positionsConnection_edges_node_market_data | null;
|
||||
data: PositionsSubscription_positions_market_data | null;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_positionsConnection_edges_node {
|
||||
export interface PositionsSubscription_positions {
|
||||
__typename: "Position";
|
||||
/**
|
||||
* Realised Profit and Loss (int64)
|
||||
@ -201,52 +173,23 @@ export interface PositionsMetrics_party_positionsConnection_edges_node {
|
||||
* RFC3339Nano time the position was updated
|
||||
*/
|
||||
updatedAt: string | null;
|
||||
/**
|
||||
* Margins of the party for the given position
|
||||
*/
|
||||
marginsConnection: PositionsSubscription_positions_marginsConnection;
|
||||
/**
|
||||
* Market relating to this position
|
||||
*/
|
||||
market: PositionsMetrics_party_positionsConnection_edges_node_market;
|
||||
market: PositionsSubscription_positions_market;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_positionsConnection_edges {
|
||||
__typename: "PositionEdge";
|
||||
node: PositionsMetrics_party_positionsConnection_edges_node;
|
||||
export interface PositionsSubscription {
|
||||
/**
|
||||
* Subscribe to the positions updates
|
||||
*/
|
||||
positions: PositionsSubscription_positions;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party_positionsConnection {
|
||||
__typename: "PositionConnection";
|
||||
/**
|
||||
* The positions in this connection
|
||||
*/
|
||||
edges: PositionsMetrics_party_positionsConnection_edges[] | null;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics_party {
|
||||
__typename: "Party";
|
||||
/**
|
||||
* Party identifier
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Collateral accounts relating to a party
|
||||
*/
|
||||
accounts: PositionsMetrics_party_accounts[] | null;
|
||||
/**
|
||||
* Margin levels for a market
|
||||
*/
|
||||
marginsConnection: PositionsMetrics_party_marginsConnection;
|
||||
/**
|
||||
* Trading positions relating to a party
|
||||
*/
|
||||
positionsConnection: PositionsMetrics_party_positionsConnection;
|
||||
}
|
||||
|
||||
export interface PositionsMetrics {
|
||||
/**
|
||||
* An entity that is trading on the Vega network
|
||||
*/
|
||||
party: PositionsMetrics_party | null;
|
||||
}
|
||||
|
||||
export interface PositionsMetricsVariables {
|
||||
export interface PositionsSubscriptionVariables {
|
||||
partyId: string;
|
||||
}
|
@ -1,88 +0,0 @@
|
||||
import produce from 'immer';
|
||||
import { gql } from '@apollo/client';
|
||||
import type {
|
||||
Positions,
|
||||
Positions_party_positions,
|
||||
} from './__generated__/Positions';
|
||||
import { makeDataProvider } from '@vegaprotocol/react-helpers';
|
||||
|
||||
import type {
|
||||
PositionSubscribe,
|
||||
PositionSubscribe_positions,
|
||||
} from './__generated__/PositionSubscribe';
|
||||
|
||||
const POSITIONS_FRAGMENT = gql`
|
||||
fragment PositionDetails on Position {
|
||||
realisedPNL
|
||||
openVolume
|
||||
unrealisedPNL
|
||||
averageEntryPrice
|
||||
market {
|
||||
id
|
||||
name
|
||||
data {
|
||||
markPrice
|
||||
marketTradingMode
|
||||
market {
|
||||
id
|
||||
}
|
||||
}
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const POSITION_QUERY = gql`
|
||||
${POSITIONS_FRAGMENT}
|
||||
query Positions($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
positions {
|
||||
...PositionDetails
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const POSITIONS_SUB = gql`
|
||||
${POSITIONS_FRAGMENT}
|
||||
subscription PositionSubscribe($partyId: ID!) {
|
||||
positions(partyId: $partyId) {
|
||||
...PositionDetails
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const update = (
|
||||
data: Positions_party_positions[],
|
||||
delta: PositionSubscribe_positions
|
||||
) => {
|
||||
return produce(data, (draft) => {
|
||||
const index = draft.findIndex((m) => m.market.id === delta.market.id);
|
||||
if (index !== -1) {
|
||||
draft[index] = delta;
|
||||
} else {
|
||||
draft.push(delta);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const getData = (responseData: Positions): Positions_party_positions[] | null =>
|
||||
responseData.party ? responseData.party.positions : null;
|
||||
const getDelta = (
|
||||
subscriptionData: PositionSubscribe
|
||||
): PositionSubscribe_positions => subscriptionData.positions;
|
||||
|
||||
export const positionsDataProvider = makeDataProvider<
|
||||
Positions,
|
||||
Positions_party_positions[],
|
||||
PositionSubscribe,
|
||||
PositionSubscribe_positions
|
||||
>(POSITION_QUERY, POSITIONS_SUB, update, getData, getDelta);
|
@ -1,8 +1,9 @@
|
||||
import { AccountType, MarketTradingMode } from '@vegaprotocol/types';
|
||||
import type { PositionsMetrics } from './__generated__/PositionsMetrics';
|
||||
import { getMetrics } from './positions-metrics-data-provider';
|
||||
import type { Accounts } from '@vegaprotocol/accounts';
|
||||
import type { Positions } from './__generated__/Positions';
|
||||
import { getMetrics } from './positions-data-providers';
|
||||
|
||||
const data: PositionsMetrics = {
|
||||
const accounts: Accounts = {
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
id: '02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65',
|
||||
@ -12,6 +13,7 @@ const data: PositionsMetrics = {
|
||||
type: AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
symbol: 'tDAI',
|
||||
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
|
||||
decimals: 5,
|
||||
},
|
||||
@ -23,12 +25,14 @@ const data: PositionsMetrics = {
|
||||
type: AccountType.ACCOUNT_TYPE_MARGIN,
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
symbol: 'tDAI',
|
||||
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
|
||||
decimals: 5,
|
||||
},
|
||||
balance: '33353727',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||
id: '5e6035fe6a6df78c9ec44b333c231e63d357acef0a0620d2c243f5865d1dc0d8',
|
||||
},
|
||||
},
|
||||
@ -37,16 +41,37 @@ const data: PositionsMetrics = {
|
||||
type: AccountType.ACCOUNT_TYPE_MARGIN,
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
symbol: 'tDAI',
|
||||
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
|
||||
decimals: 5,
|
||||
},
|
||||
balance: '3274050',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
name: 'UNIDAI Monthly (30 Jun 2022)',
|
||||
id: '10c4b1114d2f6fda239b73d018bca55888b6018f0ac70029972a17fea0a6a56e',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const data: Positions = {
|
||||
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',
|
||||
marginsConnection: {
|
||||
__typename: 'MarginConnection',
|
||||
edges: [
|
||||
@ -68,6 +93,45 @@ const data: PositionsMetrics = {
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||
id: '5e6035fe6a6df78c9ec44b333c231e63d357acef0a0620d2c243f5865d1dc0d8',
|
||||
decimalPlaces: 5,
|
||||
tradingMode: MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
__typename: 'Instrument',
|
||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||
},
|
||||
},
|
||||
data: {
|
||||
__typename: 'MarketData',
|
||||
markPrice: '9431775',
|
||||
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',
|
||||
marginsConnection: {
|
||||
__typename: 'MarginConnection',
|
||||
edges: [
|
||||
{
|
||||
__typename: 'MarginEdge',
|
||||
node: {
|
||||
@ -88,48 +152,6 @@ const data: PositionsMetrics = {
|
||||
},
|
||||
],
|
||||
},
|
||||
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',
|
||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||
id: '5e6035fe6a6df78c9ec44b333c231e63d357acef0a0620d2c243f5865d1dc0d8',
|
||||
decimalPlaces: 5,
|
||||
tradingMode: MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
__typename: 'Instrument',
|
||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||
},
|
||||
},
|
||||
data: {
|
||||
__typename: 'MarketData',
|
||||
markPrice: '9431775',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
__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',
|
||||
@ -147,6 +169,10 @@ const data: PositionsMetrics = {
|
||||
data: {
|
||||
__typename: 'MarketData',
|
||||
markPrice: '869762',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '10c4b1114d2f6fda239b73d018bca55888b6018f0ac70029972a17fea0a6a56e',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -158,12 +184,12 @@ const data: PositionsMetrics = {
|
||||
|
||||
describe('getMetrics', () => {
|
||||
it('returns positions metrics', () => {
|
||||
const metrics = getMetrics(data.party);
|
||||
const metrics = getMetrics(data.party, accounts.party?.accounts ?? null);
|
||||
expect(metrics.length).toEqual(2);
|
||||
});
|
||||
|
||||
it('calculates metrics', () => {
|
||||
const metrics = getMetrics(data.party);
|
||||
const metrics = getMetrics(data.party, accounts.party?.accounts ?? null);
|
||||
|
||||
expect(metrics[0].assetSymbol).toEqual('tDAI');
|
||||
expect(metrics[0].averageEntryPrice).toEqual('8993727');
|
@ -2,16 +2,19 @@ import { gql } from '@apollo/client';
|
||||
import produce from 'immer';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import sortBy from 'lodash/sortBy';
|
||||
import type {
|
||||
PositionsMetrics,
|
||||
PositionsMetrics_party,
|
||||
} from './__generated__/PositionsMetrics';
|
||||
import { makeDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import type { Accounts_party_accounts } from '@vegaprotocol/accounts';
|
||||
import { accountsDataProvider } from '@vegaprotocol/accounts';
|
||||
import { toBigNum } from '@vegaprotocol/react-helpers';
|
||||
import type { Positions, Positions_party } from './__generated__/Positions';
|
||||
import {
|
||||
makeDataProvider,
|
||||
makeDerivedDataProvider,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
|
||||
import type {
|
||||
PositionsMetricsSubscription,
|
||||
PositionsMetricsSubscription_positions,
|
||||
} from './__generated__/PositionsMetricsSubscription';
|
||||
PositionsSubscription,
|
||||
PositionsSubscription_positions,
|
||||
} from './__generated__/PositionsSubscription';
|
||||
|
||||
import { AccountType } from '@vegaprotocol/types';
|
||||
import type { MarketTradingMode } from '@vegaprotocol/types';
|
||||
@ -40,51 +43,17 @@ export interface Position {
|
||||
}
|
||||
|
||||
export interface Data {
|
||||
party: PositionsMetrics_party | null;
|
||||
party: Positions_party | null;
|
||||
positions: Position[] | null;
|
||||
}
|
||||
|
||||
const POSITIONS_METRICS_FRAGMENT = gql`
|
||||
fragment PositionMetricsFields on Position {
|
||||
const POSITION_FIELDS = gql`
|
||||
fragment PositionFields on Position {
|
||||
realisedPNL
|
||||
openVolume
|
||||
unrealisedPNL
|
||||
averageEntryPrice
|
||||
updatedAt
|
||||
market {
|
||||
id
|
||||
name
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
tradingMode
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
}
|
||||
}
|
||||
data {
|
||||
markPrice
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const POSITION_METRICS_QUERY = gql`
|
||||
${POSITIONS_METRICS_FRAGMENT}
|
||||
query PositionsMetrics($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
accounts {
|
||||
type
|
||||
asset {
|
||||
id
|
||||
decimals
|
||||
}
|
||||
balance
|
||||
market {
|
||||
id
|
||||
}
|
||||
}
|
||||
marginsConnection {
|
||||
edges {
|
||||
node {
|
||||
@ -101,10 +70,36 @@ const POSITION_METRICS_QUERY = gql`
|
||||
}
|
||||
}
|
||||
}
|
||||
market {
|
||||
id
|
||||
name
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
tradingMode
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
}
|
||||
}
|
||||
data {
|
||||
markPrice
|
||||
market {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const POSITIONS_QUERY = gql`
|
||||
${POSITION_FIELDS}
|
||||
query Positions($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
positionsConnection {
|
||||
edges {
|
||||
node {
|
||||
...PositionMetricsFields
|
||||
...PositionFields
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -112,33 +107,36 @@ const POSITION_METRICS_QUERY = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export const POSITIONS_METRICS_SUBSCRIPTION = gql`
|
||||
${POSITIONS_METRICS_FRAGMENT}
|
||||
subscription PositionsMetricsSubscription($partyId: ID!) {
|
||||
export const POSITIONS_SUBSCRIPTION = gql`
|
||||
${POSITION_FIELDS}
|
||||
subscription PositionsSubscription($partyId: ID!) {
|
||||
positions(partyId: $partyId) {
|
||||
...PositionMetricsFields
|
||||
...PositionFields
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const getMetrics = (data: PositionsMetrics_party | null): Position[] => {
|
||||
if (!data || !data.positionsConnection.edges) {
|
||||
export const getMetrics = (
|
||||
data: Positions_party | null,
|
||||
accounts: Accounts_party_accounts[] | null
|
||||
): Position[] => {
|
||||
if (!data || !data?.positionsConnection.edges) {
|
||||
return [];
|
||||
}
|
||||
const metrics: Position[] = [];
|
||||
data.positionsConnection.edges.forEach((position) => {
|
||||
data?.positionsConnection.edges.forEach((position) => {
|
||||
const market = position.node.market;
|
||||
const marketData = market.data;
|
||||
const marginLevel = data.marginsConnection.edges?.find(
|
||||
const marginLevel = position.node.marginsConnection.edges?.find(
|
||||
(margin) => margin.node.market.id === market.id
|
||||
)?.node;
|
||||
const marginAccount = data.accounts?.find(
|
||||
(account) => account.market?.id === market.id
|
||||
);
|
||||
const marginAccount = accounts?.find((account) => {
|
||||
return account.market?.id === market.id;
|
||||
});
|
||||
if (!marginAccount || !marginLevel || !marketData) {
|
||||
return;
|
||||
}
|
||||
const generalAccount = data.accounts?.find(
|
||||
const generalAccount = accounts?.find(
|
||||
(account) =>
|
||||
account.asset.id === marginAccount.asset.id &&
|
||||
account.type === AccountType.ACCOUNT_TYPE_GENERAL
|
||||
@ -146,20 +144,20 @@ export const getMetrics = (data: PositionsMetrics_party | null): Position[] => {
|
||||
const assetDecimals = marginAccount.asset.decimals;
|
||||
const { positionDecimalPlaces, decimalPlaces: marketDecimalPlaces } =
|
||||
market;
|
||||
const openVolume = new BigNumber(position.node.openVolume).dividedBy(
|
||||
10 ** positionDecimalPlaces
|
||||
const openVolume = toBigNum(
|
||||
position.node.openVolume,
|
||||
positionDecimalPlaces
|
||||
);
|
||||
|
||||
const marginAccountBalance = marginAccount
|
||||
? new BigNumber(marginAccount.balance).dividedBy(10 ** assetDecimals)
|
||||
: new BigNumber(0);
|
||||
const generalAccountBalance = generalAccount
|
||||
? new BigNumber(generalAccount.balance).dividedBy(10 ** assetDecimals)
|
||||
: new BigNumber(0);
|
||||
|
||||
const markPrice = new BigNumber(marketData.markPrice).dividedBy(
|
||||
10 ** marketDecimalPlaces
|
||||
const marginAccountBalance = toBigNum(
|
||||
marginAccount.balance ?? 0,
|
||||
assetDecimals
|
||||
);
|
||||
const generalAccountBalance = toBigNum(
|
||||
generalAccount?.balance ?? 0,
|
||||
assetDecimals
|
||||
);
|
||||
const markPrice = toBigNum(marketData.markPrice, marketDecimalPlaces);
|
||||
|
||||
const notional = (
|
||||
openVolume.isGreaterThan(0) ? openVolume : openVolume.multipliedBy(-1)
|
||||
@ -172,13 +170,13 @@ export const getMetrics = (data: PositionsMetrics_party | null): Position[] => {
|
||||
? new BigNumber(0)
|
||||
: marginAccountBalance.dividedBy(totalBalance).multipliedBy(100);
|
||||
|
||||
const marginMaintenance = new BigNumber(
|
||||
marginLevel.maintenanceLevel
|
||||
).multipliedBy(marketDecimalPlaces);
|
||||
const marginSearch = new BigNumber(marginLevel.searchLevel).multipliedBy(
|
||||
const marginMaintenance = toBigNum(
|
||||
marginLevel.maintenanceLevel,
|
||||
marketDecimalPlaces
|
||||
);
|
||||
const marginInitial = new BigNumber(marginLevel.initialLevel).multipliedBy(
|
||||
const marginSearch = toBigNum(marginLevel.searchLevel, marketDecimalPlaces);
|
||||
const marginInitial = toBigNum(
|
||||
marginLevel.initialLevel,
|
||||
marketDecimalPlaces
|
||||
);
|
||||
|
||||
@ -232,54 +230,50 @@ export const getMetrics = (data: PositionsMetrics_party | null): Position[] => {
|
||||
};
|
||||
|
||||
export const update = (
|
||||
data: Data,
|
||||
delta: PositionsMetricsSubscription_positions
|
||||
data: Positions_party,
|
||||
delta: PositionsSubscription_positions | null
|
||||
) => {
|
||||
if (!data.party?.positionsConnection.edges) {
|
||||
return data;
|
||||
return produce(data, (draft) => {
|
||||
if (!draft.positionsConnection.edges || !delta) {
|
||||
return;
|
||||
}
|
||||
const edges = produce(data.party.positionsConnection.edges, (draft) => {
|
||||
const index = draft.findIndex(
|
||||
const index = draft.positionsConnection.edges.findIndex(
|
||||
(edge) => edge.node.market.id === delta.market.id
|
||||
);
|
||||
if (index !== -1) {
|
||||
draft[index].node = delta;
|
||||
draft.positionsConnection.edges[index].node = delta;
|
||||
} else {
|
||||
draft.push({ __typename: 'PositionEdge', node: delta });
|
||||
draft.positionsConnection.edges.push({
|
||||
__typename: 'PositionEdge',
|
||||
node: delta,
|
||||
});
|
||||
}
|
||||
});
|
||||
const party = produce(data.party, (draft) => {
|
||||
draft.positionsConnection.edges = edges;
|
||||
});
|
||||
if (party === data.party) {
|
||||
return data;
|
||||
}
|
||||
return {
|
||||
party,
|
||||
positions: getMetrics(party),
|
||||
};
|
||||
};
|
||||
|
||||
const getData = (responseData: PositionsMetrics): Data => {
|
||||
return {
|
||||
party: responseData.party,
|
||||
positions: sortBy(getMetrics(responseData.party), 'updatedAt').reverse(),
|
||||
};
|
||||
};
|
||||
|
||||
const getDelta = (
|
||||
subscriptionData: PositionsMetricsSubscription
|
||||
): PositionsMetricsSubscription_positions => subscriptionData.positions;
|
||||
|
||||
export const positionsMetricsDataProvider = makeDataProvider<
|
||||
PositionsMetrics,
|
||||
Data,
|
||||
PositionsMetricsSubscription,
|
||||
PositionsMetricsSubscription_positions
|
||||
>(
|
||||
POSITION_METRICS_QUERY,
|
||||
POSITIONS_METRICS_SUBSCRIPTION,
|
||||
export const positionDataProvider = makeDataProvider<
|
||||
Positions,
|
||||
Positions_party,
|
||||
PositionsSubscription,
|
||||
PositionsSubscription_positions
|
||||
>({
|
||||
query: POSITIONS_QUERY,
|
||||
subscriptionQuery: POSITIONS_SUBSCRIPTION,
|
||||
update,
|
||||
getData,
|
||||
getDelta
|
||||
getData: (responseData: Positions) => responseData.party,
|
||||
getDelta: (subscriptionData: PositionsSubscription) =>
|
||||
subscriptionData.positions,
|
||||
});
|
||||
|
||||
export const positionsMetricsDataProvider = makeDerivedDataProvider<Position[]>(
|
||||
[positionDataProvider, accountsDataProvider],
|
||||
([positions, accounts]) => {
|
||||
return sortBy(
|
||||
getMetrics(
|
||||
positions as Positions_party | null,
|
||||
accounts as Accounts_party_accounts[] | null
|
||||
),
|
||||
'updatedAt'
|
||||
).reverse();
|
||||
}
|
||||
);
|
@ -1,12 +1,11 @@
|
||||
import { useRef, useCallback, useMemo } from 'react';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import type { PositionsMetricsSubscription_positions } from './__generated__/PositionsMetricsSubscription';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import PositionsTable from './positions-table';
|
||||
import type { GetRowsParams } from './positions-table';
|
||||
import { positionsMetricsDataProvider as dataProvider } from './positions-metrics-data-provider';
|
||||
import type { Data, Position } from './positions-metrics-data-provider';
|
||||
import { positionsMetricsDataProvider as dataProvider } from './positions-data-providers';
|
||||
import type { Position } from './positions-data-providers';
|
||||
|
||||
interface PositionsManagerProps {
|
||||
partyId: string;
|
||||
@ -16,19 +15,20 @@ export const PositionsManager = ({ partyId }: PositionsManagerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const variables = useMemo(() => ({ partyId }), [partyId]);
|
||||
const dataRef = useRef<Position[] | null>(null);
|
||||
const update = useCallback(({ data }: { data: Data }) => {
|
||||
const update = useCallback(({ data }: { data: Position[] | null }) => {
|
||||
if (!gridRef.current?.api) {
|
||||
return false;
|
||||
}
|
||||
dataRef.current = data.positions;
|
||||
dataRef.current = data;
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
return true;
|
||||
}, []);
|
||||
const { data, error, loading } = useDataProvider<
|
||||
Data,
|
||||
PositionsMetricsSubscription_positions
|
||||
>({ dataProvider, update, variables });
|
||||
dataRef.current = data?.positions || null;
|
||||
const { data, error, loading } = useDataProvider<Position[], never>({
|
||||
dataProvider,
|
||||
update,
|
||||
variables,
|
||||
});
|
||||
dataRef.current = data;
|
||||
const getRows = async ({
|
||||
successCallback,
|
||||
startRow,
|
||||
@ -44,8 +44,8 @@ export const PositionsManager = ({ partyId }: PositionsManagerProps) => {
|
||||
return (
|
||||
<AsyncRenderer loading={loading} error={error} data={data}>
|
||||
<PositionsTable
|
||||
rowModelType={data?.positions?.length ? 'infinite' : 'clientSide'}
|
||||
rowData={data?.positions?.length ? undefined : []}
|
||||
rowModelType={data?.length ? 'infinite' : 'clientSide'}
|
||||
rowData={data?.length ? undefined : []}
|
||||
datasource={{ getRows }}
|
||||
/>
|
||||
</AsyncRenderer>
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type { RenderResult } from '@testing-library/react';
|
||||
import { act, render, screen } from '@testing-library/react';
|
||||
import PositionsTable from './positions-table';
|
||||
import type { Position } from './positions-metrics-data-provider';
|
||||
import type { Position } from './positions-data-providers';
|
||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
|
||||
const singleRow: Position = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { Story, Meta } from '@storybook/react';
|
||||
import { PositionsTable } from './positions-table';
|
||||
import type { Position } from './positions-metrics-data-provider';
|
||||
import type { Position } from './positions-data-providers';
|
||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
|
||||
export default {
|
||||
@ -14,7 +14,7 @@ export const Primary = Template.bind({});
|
||||
const longPosition: Position = {
|
||||
marketName: 'BTC/USD (31 july 2022)',
|
||||
averageEntryPrice: '1134564',
|
||||
capitalUtilisation: 10.0,
|
||||
capitalUtilisation: 10,
|
||||
currentLeverage: 11,
|
||||
assetDecimals: 2,
|
||||
marketDecimalPlaces: 2,
|
||||
@ -46,7 +46,7 @@ const longPosition: Position = {
|
||||
const shortPosition: Position = {
|
||||
marketName: 'ETH/USD (31 august 2022)',
|
||||
averageEntryPrice: '23976',
|
||||
capitalUtilisation: 87.0,
|
||||
capitalUtilisation: 87,
|
||||
currentLeverage: 7,
|
||||
assetDecimals: 2,
|
||||
marketDecimalPlaces: 2,
|
||||
|
@ -13,7 +13,7 @@ import { AgGridDynamic as AgGrid, ProgressBar } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridColumn } from 'ag-grid-react';
|
||||
import type { AgGridReact, AgGridReactProps } from 'ag-grid-react';
|
||||
import type { IDatasource, IGetRowsParams } from 'ag-grid-community';
|
||||
import type { Position } from './positions-metrics-data-provider';
|
||||
import type { Position } from './positions-data-providers';
|
||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
||||
import { Intent } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
|
@ -59,20 +59,29 @@ export function useDataProvider<Data, Delta>({
|
||||
return Promise.reject();
|
||||
}, []);
|
||||
const callback = useCallback<UpdateCallback<Data, Delta>>(
|
||||
({ data, error, loading, delta, insertionData, totalCount }) => {
|
||||
({
|
||||
data,
|
||||
error,
|
||||
loading,
|
||||
delta,
|
||||
insertionData,
|
||||
totalCount,
|
||||
isInsert,
|
||||
isUpdate,
|
||||
}) => {
|
||||
setError(error);
|
||||
setLoading(loading);
|
||||
if (!error && !loading) {
|
||||
// if update or insert function returns true it means that component handles updates
|
||||
// component can use flush() which will call callback without delta and cause data state update
|
||||
if (initialized.current && data) {
|
||||
if (delta && update && update({ delta, data })) {
|
||||
if (isUpdate && update && (!delta || update({ delta, data }))) {
|
||||
return;
|
||||
}
|
||||
if (
|
||||
insertionData &&
|
||||
isInsert &&
|
||||
insert &&
|
||||
insert({ insertionData, data, totalCount })
|
||||
(!insertionData || insert({ insertionData, data, totalCount }))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
@ -1,5 +1,10 @@
|
||||
import { makeDataProvider, defaultAppend } from './generic-data-provider';
|
||||
import {
|
||||
makeDataProvider,
|
||||
makeDerivedDataProvider,
|
||||
defaultAppend,
|
||||
} from './generic-data-provider';
|
||||
import type {
|
||||
CombineDerivedData,
|
||||
Query,
|
||||
UpdateCallback,
|
||||
Update,
|
||||
@ -28,118 +33,158 @@ type QueryData = {
|
||||
totalCount?: number;
|
||||
};
|
||||
|
||||
type CombinedData = {
|
||||
totalCount?: number;
|
||||
};
|
||||
|
||||
type SubscriptionData = QueryData;
|
||||
type Delta = Data;
|
||||
|
||||
describe('data provider', () => {
|
||||
const update = jest.fn<
|
||||
const update = jest.fn<
|
||||
ReturnType<Update<Data, Delta>>,
|
||||
Parameters<Update<Data, Delta>>
|
||||
>();
|
||||
>();
|
||||
|
||||
const callback = jest.fn<
|
||||
const callback = jest.fn<
|
||||
ReturnType<UpdateCallback<Data, Delta>>,
|
||||
Parameters<UpdateCallback<Data, Delta>>
|
||||
>();
|
||||
>();
|
||||
|
||||
const query: Query<QueryData> = {
|
||||
const query: Query<QueryData> = {
|
||||
kind: 'Document',
|
||||
definitions: [],
|
||||
};
|
||||
const subscriptionQuery: Query<SubscriptionData> = query;
|
||||
};
|
||||
const subscriptionQuery: Query<SubscriptionData> = query;
|
||||
|
||||
const subscribe = makeDataProvider<QueryData, Data, SubscriptionData, Delta>(
|
||||
const subscribe = makeDataProvider<QueryData, Data, SubscriptionData, Delta>({
|
||||
query,
|
||||
subscriptionQuery,
|
||||
update,
|
||||
(r) => r.data,
|
||||
(r) => r.data
|
||||
);
|
||||
getData: (r) => r.data,
|
||||
getDelta: (r) => r.data,
|
||||
});
|
||||
|
||||
const first = 100;
|
||||
const paginatedSubscribe = makeDataProvider<
|
||||
const secondSubscribe = makeDataProvider<
|
||||
QueryData,
|
||||
Data,
|
||||
SubscriptionData,
|
||||
Delta
|
||||
>(
|
||||
>({
|
||||
query,
|
||||
subscriptionQuery,
|
||||
update,
|
||||
(r) => r.data,
|
||||
(r) => r.data,
|
||||
{
|
||||
getData: (r) => r.data,
|
||||
getDelta: (r) => r.data,
|
||||
});
|
||||
|
||||
const combineData = jest.fn<
|
||||
ReturnType<CombineDerivedData<CombinedData>>,
|
||||
Parameters<CombineDerivedData<CombinedData>>
|
||||
>();
|
||||
|
||||
const derivedSubscribe = makeDerivedDataProvider(
|
||||
[subscribe, secondSubscribe],
|
||||
combineData
|
||||
);
|
||||
|
||||
const first = 100;
|
||||
const paginatedSubscribe = makeDataProvider<
|
||||
QueryData,
|
||||
Data,
|
||||
SubscriptionData,
|
||||
Delta
|
||||
>({
|
||||
query,
|
||||
subscriptionQuery,
|
||||
update,
|
||||
getData: (r) => r.data,
|
||||
getDelta: (r) => r.data,
|
||||
pagination: {
|
||||
first,
|
||||
append: defaultAppend,
|
||||
getPageInfo: (r) => r?.pageInfo ?? null,
|
||||
getTotalCount: (r) => r?.totalCount,
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
const generateData = (start = 0, size = first) => {
|
||||
const generateData = (start = 0, size = first) => {
|
||||
return new Array(size).fill(null).map((v, i) => ({
|
||||
cursor: (i + start + 1).toString(),
|
||||
node: {
|
||||
id: (i + start + 1).toString(),
|
||||
},
|
||||
}));
|
||||
};
|
||||
};
|
||||
|
||||
const clientSubscribeUnsubscribe = jest.fn();
|
||||
const clientSubscribeSubscribe = jest.fn<
|
||||
const clientSubscribeUnsubscribe = jest.fn();
|
||||
const clientSubscribeSubscribe = jest.fn<
|
||||
Subscription,
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
[(value: FetchResult<SubscriptionData>) => void, (error: any) => void]
|
||||
>(() => ({
|
||||
>(() => ({
|
||||
unsubscribe: clientSubscribeUnsubscribe,
|
||||
closed: false,
|
||||
}));
|
||||
}));
|
||||
|
||||
const clientSubscribe = jest.fn<
|
||||
const clientSubscribe = jest.fn<
|
||||
Observable<FetchResult<SubscriptionData>>,
|
||||
[SubscriptionOptions<OperationVariables, SubscriptionData>]
|
||||
>(
|
||||
>(
|
||||
() =>
|
||||
({
|
||||
subscribe: clientSubscribeSubscribe,
|
||||
} as unknown as Observable<FetchResult<SubscriptionData>>)
|
||||
);
|
||||
);
|
||||
|
||||
const clientQueryPromise: {
|
||||
resolve?: (
|
||||
const clientQueryPromises: {
|
||||
resolve: (
|
||||
value:
|
||||
| ApolloQueryResult<QueryData>
|
||||
| PromiseLike<ApolloQueryResult<QueryData>>
|
||||
) => void;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
reject?: (reason?: any) => void;
|
||||
} = {};
|
||||
reject: (reason?: any) => void;
|
||||
}[] = [];
|
||||
|
||||
const clientQuery = jest.fn<
|
||||
const clientQuery = jest.fn<
|
||||
Promise<ApolloQueryResult<QueryData>>,
|
||||
[QueryOptions<OperationVariables, QueryData>]
|
||||
>(() => {
|
||||
>(() => {
|
||||
return new Promise((resolve, reject) => {
|
||||
clientQueryPromise.resolve = resolve;
|
||||
clientQueryPromise.reject = reject;
|
||||
});
|
||||
clientQueryPromises.push({ resolve, reject });
|
||||
});
|
||||
});
|
||||
|
||||
const client = {
|
||||
const client = {
|
||||
query: clientQuery,
|
||||
subscribe: clientSubscribe,
|
||||
} as unknown as ApolloClient<object>;
|
||||
} as unknown as ApolloClient<object>;
|
||||
|
||||
const resolveQuery = async (data: QueryData) => {
|
||||
if (clientQueryPromise.resolve) {
|
||||
const resolveQuery = async (data: QueryData) => {
|
||||
const clientQueryPromise = clientQueryPromises.shift();
|
||||
if (clientQueryPromise) {
|
||||
await clientQueryPromise.resolve({
|
||||
data,
|
||||
loading: false,
|
||||
networkStatus: 8,
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
const rejectQuery = async (reason: Error) => {
|
||||
const clientQueryPromise = clientQueryPromises.shift();
|
||||
if (clientQueryPromise) {
|
||||
await clientQueryPromise.reject(reason);
|
||||
}
|
||||
};
|
||||
|
||||
const clearPendingQueries = () => {
|
||||
while (clientQueryPromises.length) {
|
||||
clientQueryPromises.pop();
|
||||
}
|
||||
};
|
||||
|
||||
describe('data provider', () => {
|
||||
it('memoize instance and unsubscribe if no subscribers', () => {
|
||||
const subscription1 = subscribe(jest.fn(), client);
|
||||
const subscription2 = subscribe(jest.fn(), client);
|
||||
@ -201,6 +246,7 @@ describe('data provider', () => {
|
||||
});
|
||||
|
||||
it('refetch data on reload', async () => {
|
||||
clearPendingQueries();
|
||||
clientQuery.mockClear();
|
||||
clientSubscribeUnsubscribe.mockClear();
|
||||
clientSubscribeSubscribe.mockClear();
|
||||
@ -241,8 +287,9 @@ describe('data provider', () => {
|
||||
subscription.unsubscribe();
|
||||
});
|
||||
|
||||
it('fills data with nulls if paginaton is enabled', async () => {
|
||||
it('fills data with nulls if pagination is enabled', async () => {
|
||||
callback.mockClear();
|
||||
clearPendingQueries();
|
||||
const totalCount = 1000;
|
||||
const data: Item[] = new Array(first).fill(null).map((v, i) => ({
|
||||
cursor: i.toString(),
|
||||
@ -276,7 +323,7 @@ describe('data provider', () => {
|
||||
});
|
||||
|
||||
// load next page
|
||||
subscription.load();
|
||||
subscription.load && subscription.load();
|
||||
let lastQueryArgs =
|
||||
clientQuery.mock.calls[clientQuery.mock.calls.length - 1][0];
|
||||
expect(lastQueryArgs?.variables?.pagination).toEqual({
|
||||
@ -292,7 +339,7 @@ describe('data provider', () => {
|
||||
});
|
||||
|
||||
// load page with skip
|
||||
subscription.load(500, 600);
|
||||
subscription.load && subscription.load(500, 600);
|
||||
lastQueryArgs =
|
||||
clientQuery.mock.calls[clientQuery.mock.calls.length - 1][0];
|
||||
expect(lastQueryArgs?.variables?.pagination).toEqual({
|
||||
@ -309,7 +356,7 @@ describe('data provider', () => {
|
||||
});
|
||||
|
||||
// load in the gap
|
||||
subscription.load(400, 500);
|
||||
subscription.load && subscription.load(400, 500);
|
||||
lastQueryArgs =
|
||||
clientQuery.mock.calls[clientQuery.mock.calls.length - 1][0];
|
||||
expect(lastQueryArgs?.variables?.pagination).toEqual({
|
||||
@ -326,7 +373,7 @@ describe('data provider', () => {
|
||||
});
|
||||
|
||||
// load page after last block
|
||||
subscription.load(700, 800);
|
||||
subscription.load && subscription.load(700, 800);
|
||||
lastQueryArgs =
|
||||
clientQuery.mock.calls[clientQuery.mock.calls.length - 1][0];
|
||||
expect(lastQueryArgs?.variables?.pagination).toEqual({
|
||||
@ -343,7 +390,7 @@ describe('data provider', () => {
|
||||
});
|
||||
|
||||
// load last page shorter than expected
|
||||
subscription.load(950, 1050);
|
||||
subscription.load && subscription.load(950, 1050);
|
||||
lastQueryArgs =
|
||||
clientQuery.mock.calls[clientQuery.mock.calls.length - 1][0];
|
||||
expect(lastQueryArgs?.variables?.pagination).toEqual({
|
||||
@ -363,11 +410,11 @@ describe('data provider', () => {
|
||||
|
||||
// load next page when pageInfo.hasNextPage === false
|
||||
const clientQueryCallsLength = clientQuery.mock.calls.length;
|
||||
subscription.load();
|
||||
subscription.load && subscription.load();
|
||||
expect(clientQuery.mock.calls.length).toBe(clientQueryCallsLength);
|
||||
|
||||
// load last page longer than expected
|
||||
subscription.load(960, 1000);
|
||||
subscription.load && subscription.load(960, 1000);
|
||||
lastQueryArgs =
|
||||
clientQuery.mock.calls[clientQuery.mock.calls.length - 1][0];
|
||||
expect(lastQueryArgs?.variables?.pagination).toEqual({
|
||||
@ -403,7 +450,7 @@ describe('data provider', () => {
|
||||
expect(lastCallbackArgs[0].totalCount).toBe(undefined);
|
||||
|
||||
// load next page
|
||||
subscription.load();
|
||||
subscription.load && subscription.load();
|
||||
await resolveQuery({
|
||||
data: generateData(100),
|
||||
pageInfo: {
|
||||
@ -415,7 +462,7 @@ describe('data provider', () => {
|
||||
expect(lastCallbackArgs[0].totalCount).toBe(undefined);
|
||||
|
||||
// load last page
|
||||
subscription.load();
|
||||
subscription.load && subscription.load();
|
||||
await resolveQuery({
|
||||
data: generateData(200, 50),
|
||||
pageInfo: {
|
||||
@ -443,3 +490,77 @@ describe('data provider', () => {
|
||||
subscription.unsubscribe();
|
||||
});
|
||||
});
|
||||
|
||||
describe('derived data provider', () => {
|
||||
it('memoize instance and unsubscribe if no subscribers', () => {
|
||||
clientSubscribeSubscribe.mockClear();
|
||||
clientSubscribeUnsubscribe.mockClear();
|
||||
const variables = {};
|
||||
const subscription1 = derivedSubscribe(jest.fn(), client, variables);
|
||||
const subscription2 = derivedSubscribe(jest.fn(), client, variables);
|
||||
expect(clientSubscribeSubscribe.mock.calls.length).toEqual(2);
|
||||
subscription1.unsubscribe();
|
||||
expect(clientSubscribeUnsubscribe.mock.calls.length).toEqual(0);
|
||||
subscription2.unsubscribe();
|
||||
expect(clientSubscribeUnsubscribe.mock.calls.length).toEqual(2);
|
||||
});
|
||||
|
||||
it('calls callback on each meaningful update, uses combineData function', async () => {
|
||||
clearPendingQueries();
|
||||
const part1: Item[] = [];
|
||||
const part2: Item[] = [];
|
||||
const callback = jest.fn<
|
||||
ReturnType<UpdateCallback<CombinedData, never>>,
|
||||
Parameters<UpdateCallback<CombinedData, never>>
|
||||
>();
|
||||
const subscription = derivedSubscribe(callback, client);
|
||||
const data = { totalCount: 0 };
|
||||
combineData.mockReturnValueOnce(data);
|
||||
expect(callback.mock.calls.length).toBe(0);
|
||||
await resolveQuery({ data: part1 });
|
||||
expect(combineData.mock.calls.length).toBe(0);
|
||||
expect(callback.mock.calls.length).toBe(0);
|
||||
await resolveQuery({ data: part2 });
|
||||
expect(combineData.mock.calls.length).toBe(1);
|
||||
expect(combineData.mock.calls[0][0][0]).toBe(part1);
|
||||
expect(combineData.mock.calls[0][0][1]).toBe(part2);
|
||||
expect(callback.mock.calls.length).toBe(1);
|
||||
expect(callback.mock.calls[0][0].data).toBe(data);
|
||||
expect(callback.mock.calls[0][0].loading).toBe(false);
|
||||
subscription.unsubscribe();
|
||||
});
|
||||
|
||||
it('callback with error if any dependency has error, reloads all dependencies on reload', async () => {
|
||||
combineData.mockClear();
|
||||
const part1: Item[] = [];
|
||||
const part2: Item[] = [];
|
||||
const callback = jest.fn<
|
||||
ReturnType<UpdateCallback<CombinedData, never>>,
|
||||
Parameters<UpdateCallback<CombinedData, never>>
|
||||
>();
|
||||
const subscription = derivedSubscribe(callback, client);
|
||||
const data = { totalCount: 0 };
|
||||
combineData.mockReturnValueOnce(data);
|
||||
expect(callback.mock.calls.length).toBe(0);
|
||||
await resolveQuery({ data: part1 });
|
||||
expect(combineData.mock.calls.length).toBe(0);
|
||||
expect(callback.mock.calls.length).toBe(0);
|
||||
const error = new Error('');
|
||||
await rejectQuery(error);
|
||||
expect(combineData.mock.calls.length).toBe(0);
|
||||
expect(callback.mock.calls.length).toBe(1);
|
||||
expect(callback.mock.calls[0][0].error).toBe(error);
|
||||
expect(callback.mock.calls[0][0].loading).toBe(false);
|
||||
subscription.reload();
|
||||
expect(callback.mock.calls.length).toBe(3);
|
||||
expect(callback.mock.calls[2][0].loading).toBe(true);
|
||||
await resolveQuery({ data: part1 });
|
||||
expect(callback.mock.calls.length).toBe(3);
|
||||
await resolveQuery({ data: part2 });
|
||||
expect(callback.mock.calls.length).toBe(4);
|
||||
expect(callback.mock.calls[3][0].data).toStrictEqual(data);
|
||||
expect(callback.mock.calls[3][0].loading).toBe(false);
|
||||
expect(callback.mock.calls[3][0].error).toBeUndefined();
|
||||
subscription.unsubscribe();
|
||||
});
|
||||
});
|
||||
|
@ -9,16 +9,23 @@ import type { Subscription } from 'zen-observable-ts';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import type { Pagination as PaginationWithoutSkip } from '@vegaprotocol/types';
|
||||
|
||||
interface UpdateData<Data, Delta> {
|
||||
delta?: Delta;
|
||||
insertionData?: Data | null;
|
||||
isUpdate?: boolean;
|
||||
isInsert?: boolean;
|
||||
}
|
||||
export interface UpdateCallback<Data, Delta> {
|
||||
(arg: {
|
||||
(
|
||||
arg: UpdateData<Data, Delta> & {
|
||||
data: Data | null;
|
||||
error?: Error;
|
||||
loading: boolean;
|
||||
loaded: boolean;
|
||||
pageInfo: PageInfo | null;
|
||||
delta?: Delta;
|
||||
insertionData?: Data | null;
|
||||
totalCount?: number;
|
||||
}): void;
|
||||
}
|
||||
): void;
|
||||
}
|
||||
|
||||
export interface Load<Data> {
|
||||
@ -44,7 +51,7 @@ export interface Subscribe<Data, Delta> {
|
||||
unsubscribe: () => void;
|
||||
reload: (forceReset?: boolean) => void;
|
||||
flush: () => void;
|
||||
load: Load<Data>;
|
||||
load?: Load<Data>;
|
||||
};
|
||||
}
|
||||
|
||||
@ -124,51 +131,66 @@ export function defaultAppend<Data>(
|
||||
return { data, totalCount };
|
||||
}
|
||||
|
||||
/**
|
||||
* @param subscriptionQuery query that will be used for subscription
|
||||
* @param update function that will be execued on each onNext, it should update data base on delta, it can reload data provider
|
||||
* @param getData transforms received query data to format that will be stored in data provider
|
||||
* @param getDelta transforms delta data to format that will be stored in data provider
|
||||
* @param fetchPolicy
|
||||
* @returns subscribe function
|
||||
*/
|
||||
function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
query: Query<QueryData>,
|
||||
subscriptionQuery: Query<SubscriptionData>,
|
||||
update: Update<Data, Delta>,
|
||||
getData: GetData<QueryData, Data>,
|
||||
getDelta: GetDelta<SubscriptionData, Delta>,
|
||||
interface DataProviderParams<QueryData, Data, SubscriptionData, Delta> {
|
||||
query: Query<QueryData>;
|
||||
subscriptionQuery: Query<SubscriptionData>;
|
||||
update: Update<Data, Delta>;
|
||||
getData: GetData<QueryData, Data>;
|
||||
getDelta: GetDelta<SubscriptionData, Delta>;
|
||||
pagination?: {
|
||||
getPageInfo: GetPageInfo<QueryData>;
|
||||
getTotalCount?: GetTotalCount<QueryData>;
|
||||
append: Append<Data>;
|
||||
first: number;
|
||||
},
|
||||
fetchPolicy: FetchPolicy = 'no-cache'
|
||||
): Subscribe<Data, Delta> {
|
||||
};
|
||||
fetchPolicy?: FetchPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param subscriptionQuery query that will be used for subscription
|
||||
* @param update function that will be executed on each onNext, it should update data base on delta, it can reload data provider
|
||||
* @param getData transforms received query data to format that will be stored in data provider
|
||||
* @param getDelta transforms delta data to format that will be stored in data provider
|
||||
* @param fetchPolicy
|
||||
* @returns subscribe function
|
||||
*/
|
||||
function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>({
|
||||
query,
|
||||
subscriptionQuery,
|
||||
update,
|
||||
getData,
|
||||
getDelta,
|
||||
pagination,
|
||||
fetchPolicy,
|
||||
}: DataProviderParams<QueryData, Data, SubscriptionData, Delta>): Subscribe<
|
||||
Data,
|
||||
Delta
|
||||
> {
|
||||
// list of callbacks passed through subscribe call
|
||||
const callbacks: UpdateCallback<Data, Delta>[] = [];
|
||||
// subscription is started before initial query, all deltas that will arrive before initial query response are put on queue
|
||||
const updateQueue: Delta[] = [];
|
||||
|
||||
let variables: OperationVariables | undefined = undefined;
|
||||
let variables: OperationVariables | undefined;
|
||||
let data: Data | null = null;
|
||||
let error: Error | undefined = undefined;
|
||||
let loading = false;
|
||||
let client: ApolloClient<object> | undefined = undefined;
|
||||
let subscription: Subscription | undefined = undefined;
|
||||
let error: Error | undefined;
|
||||
let loading = true;
|
||||
let loaded = false;
|
||||
let client: ApolloClient<object>;
|
||||
let subscription: Subscription | undefined;
|
||||
let pageInfo: PageInfo | null = null;
|
||||
let totalCount: number | undefined;
|
||||
|
||||
// notify single callback about current state, delta is passes optionally only if notify was invoked onNext
|
||||
const notify = (
|
||||
callback: UpdateCallback<Data, Delta>,
|
||||
updateData?: { delta?: Delta; insertionData?: Data | null }
|
||||
updateData?: UpdateData<Data, Delta>
|
||||
) => {
|
||||
callback({
|
||||
data,
|
||||
error,
|
||||
loading,
|
||||
loaded,
|
||||
pageInfo,
|
||||
totalCount,
|
||||
...updateData,
|
||||
@ -176,15 +198,12 @@ function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
};
|
||||
|
||||
// notify all callbacks
|
||||
const notifyAll = (updateData?: {
|
||||
delta?: Delta;
|
||||
insertionData?: Data | null;
|
||||
}) => {
|
||||
const notifyAll = (updateData?: UpdateData<Data, Delta>) => {
|
||||
callbacks.forEach((callback) => notify(callback, updateData));
|
||||
};
|
||||
|
||||
const load = async (start?: number, end?: number) => {
|
||||
if (!client || !pagination || !pageInfo || !(data instanceof Array)) {
|
||||
if (!pagination || !pageInfo || !(data instanceof Array)) {
|
||||
return Promise.reject();
|
||||
}
|
||||
const paginationVariables: Pagination = {
|
||||
@ -221,7 +240,7 @@ function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
...variables,
|
||||
pagination: paginationVariables,
|
||||
},
|
||||
fetchPolicy,
|
||||
fetchPolicy: fetchPolicy || 'no-cache',
|
||||
});
|
||||
const insertionData = getData(res.data);
|
||||
const insertionPageInfo = pagination.getPageInfo(res.data);
|
||||
@ -236,7 +255,7 @@ function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
totalCount =
|
||||
(pagination.getTotalCount && pagination.getTotalCount(res.data)) ??
|
||||
totalCount;
|
||||
notifyAll({ insertionData });
|
||||
notifyAll({ insertionData, isInsert: true });
|
||||
return insertionData;
|
||||
};
|
||||
|
||||
@ -280,6 +299,7 @@ function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
}
|
||||
}
|
||||
}
|
||||
loaded = true;
|
||||
} catch (e) {
|
||||
// if error will occur data provider stops subscription
|
||||
error = e as Error;
|
||||
@ -310,7 +330,7 @@ function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
};
|
||||
|
||||
const initialize = async () => {
|
||||
if (subscription || loading) {
|
||||
if (subscription) {
|
||||
return;
|
||||
}
|
||||
loading = true;
|
||||
@ -339,7 +359,7 @@ function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
return;
|
||||
}
|
||||
data = updatedData;
|
||||
notifyAll({ delta });
|
||||
notifyAll({ delta, isUpdate: true });
|
||||
}
|
||||
},
|
||||
() => reload()
|
||||
@ -347,7 +367,7 @@ function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
await initialFetch();
|
||||
};
|
||||
|
||||
const reset = (clean = true) => {
|
||||
const reset = () => {
|
||||
if (subscription) {
|
||||
subscription.unsubscribe();
|
||||
subscription = undefined;
|
||||
@ -355,6 +375,7 @@ function makeDataProviderInternal<QueryData, Data, SubscriptionData, Delta>(
|
||||
data = null;
|
||||
error = undefined;
|
||||
loading = false;
|
||||
loaded = false;
|
||||
notifyAll();
|
||||
};
|
||||
|
||||
@ -417,13 +438,13 @@ const memoize = <Data, Delta>(
|
||||
* @param pagination pagination related functions { getPageInfo, getTotalCount, append, first }
|
||||
* @returns Subscribe<Data, Delta> subscribe function
|
||||
* @example
|
||||
* const marketMidPriceProvider = makeDataProvider<QueryData, Data, SubscriptionData, Delta>(
|
||||
* gql`query MarketMidPrice($marketId: ID!) { market(id: $marketId) { data { midPrice } } }`,
|
||||
* gql`subscription MarketMidPriceSubscription($marketId: ID!) { marketDepthUpdate(marketId: $marketId) { market { data { midPrice } } } }`,
|
||||
* (draft: Draft<Data>, delta: Delta, reload: (forceReset?: boolean) => void) => { draft.midPrice = delta.midPrice }
|
||||
* (data:QueryData) => data.market.data.midPrice
|
||||
* (delta:SubscriptionData) => delta.marketData.market
|
||||
* )
|
||||
* const marketMidPriceProvider = makeDataProvider<QueryData, Data, SubscriptionData, Delta>({
|
||||
* query: gql`query MarketMidPrice($marketId: ID!) { market(id: $marketId) { data { midPrice } } }`,
|
||||
* subscriptionQuery: gql`subscription MarketMidPriceSubscription($marketId: ID!) { marketDepthUpdate(marketId: $marketId) { market { data { midPrice } } } }`,
|
||||
* update: (draft: Draft<Data>, delta: Delta, reload: (forceReset?: boolean) => void) => { draft.midPrice = delta.midPrice }
|
||||
* getData: (data:QueryData) => data.market.data.midPrice
|
||||
* getDelta: (delta:SubscriptionData) => delta.marketData.market
|
||||
* })
|
||||
*
|
||||
* const { unsubscribe, flush, reload } = marketMidPriceProvider(
|
||||
* ({ data, error, loading, delta }) => { ... },
|
||||
@ -433,29 +454,142 @@ const memoize = <Data, Delta>(
|
||||
*
|
||||
*/
|
||||
export function makeDataProvider<QueryData, Data, SubscriptionData, Delta>(
|
||||
query: Query<QueryData>,
|
||||
subscriptionQuery: Query<SubscriptionData>,
|
||||
update: Update<Data, Delta>,
|
||||
getData: GetData<QueryData, Data>,
|
||||
getDelta: GetDelta<SubscriptionData, Delta>,
|
||||
pagination?: {
|
||||
getPageInfo: GetPageInfo<QueryData>;
|
||||
getTotalCount?: GetTotalCount<QueryData>;
|
||||
append: Append<Data>;
|
||||
first: number;
|
||||
},
|
||||
fetchPolicy: FetchPolicy = 'no-cache'
|
||||
params: DataProviderParams<QueryData, Data, SubscriptionData, Delta>
|
||||
): Subscribe<Data, Delta> {
|
||||
const getInstance = memoize<Data, Delta>(() =>
|
||||
makeDataProviderInternal(
|
||||
query,
|
||||
subscriptionQuery,
|
||||
update,
|
||||
getData,
|
||||
getDelta,
|
||||
pagination,
|
||||
fetchPolicy
|
||||
)
|
||||
makeDataProviderInternal(params)
|
||||
);
|
||||
return (callback, client, variables) =>
|
||||
getInstance(variables)(callback, client, variables);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dependency subscribe needs to use any as Data and Delta because it's unknown what dependencies will be used.
|
||||
* This effects in parts in combine function has any[] type
|
||||
*/
|
||||
type DependencySubscribe = Subscribe<any, any>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
type DependencyUpdateCallback = Parameters<DependencySubscribe>['0'];
|
||||
export type CombineDerivedData<Data> = (
|
||||
parts: Parameters<DependencyUpdateCallback>['0']['data'][]
|
||||
) => Data | null;
|
||||
|
||||
function makeDerivedDataProviderInternal<Data>(
|
||||
dependencies: DependencySubscribe[],
|
||||
combineData: CombineDerivedData<Data>
|
||||
): Subscribe<Data, never> {
|
||||
let subscriptions: ReturnType<DependencySubscribe>[] | undefined;
|
||||
let client: ApolloClient<object>;
|
||||
const callbacks: UpdateCallback<Data, never>[] = [];
|
||||
let variables: OperationVariables | undefined;
|
||||
const parts: Parameters<DependencyUpdateCallback>['0'][] = [];
|
||||
let data: Data | null = null;
|
||||
let error: Error | undefined;
|
||||
let loading = true;
|
||||
let loaded = false;
|
||||
|
||||
// notify single callback about current state, delta is passes optionally only if notify was invoked onNext
|
||||
const notify = (callback: UpdateCallback<Data, never>) => {
|
||||
callback({
|
||||
data,
|
||||
error,
|
||||
loading,
|
||||
loaded,
|
||||
pageInfo: null,
|
||||
});
|
||||
};
|
||||
|
||||
// notify all callbacks
|
||||
const notifyAll = () =>
|
||||
callbacks.forEach((callback) => {
|
||||
notify(callback);
|
||||
});
|
||||
|
||||
const combine = () => {
|
||||
let newError: Error | undefined;
|
||||
let newLoading = false;
|
||||
let newLoaded = true;
|
||||
dependencies
|
||||
.map((dependency, i) => parts[i])
|
||||
.forEach((part) => {
|
||||
newError = newError || (part && part.error);
|
||||
newLoading = newLoading || !part || part.loading;
|
||||
newLoaded = newLoaded && part && part.loaded;
|
||||
});
|
||||
|
||||
const newData = newLoaded
|
||||
? combineData(parts.map((part) => part.data))
|
||||
: data;
|
||||
if (
|
||||
newLoading !== loading ||
|
||||
newError !== error ||
|
||||
newLoaded !== loaded ||
|
||||
newData !== data
|
||||
) {
|
||||
loading = newLoading;
|
||||
error = newError;
|
||||
loaded = newLoaded;
|
||||
data = newData;
|
||||
notifyAll();
|
||||
}
|
||||
};
|
||||
|
||||
const initialize = () => {
|
||||
if (subscriptions) {
|
||||
return;
|
||||
}
|
||||
subscriptions = dependencies.map((dependency, i) =>
|
||||
dependency(
|
||||
(updateData) => {
|
||||
parts[i] = updateData;
|
||||
combine();
|
||||
},
|
||||
client,
|
||||
variables
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
// remove callback from list, and unsubscribe if there is no more callbacks registered
|
||||
const unsubscribe = (callback: UpdateCallback<Data, never>) => {
|
||||
callbacks.splice(callbacks.indexOf(callback), 1);
|
||||
if (callbacks.length === 0) {
|
||||
subscriptions?.forEach((subscription) => subscription.unsubscribe());
|
||||
subscriptions = undefined;
|
||||
data = null;
|
||||
error = undefined;
|
||||
loading = true;
|
||||
loaded = false;
|
||||
}
|
||||
};
|
||||
|
||||
return (callback, c, v) => {
|
||||
callbacks.push(callback);
|
||||
if (callbacks.length === 1) {
|
||||
client = c;
|
||||
variables = v;
|
||||
initialize();
|
||||
} else {
|
||||
notify(callback);
|
||||
}
|
||||
return {
|
||||
unsubscribe: () => unsubscribe(callback),
|
||||
reload: (forceReset) =>
|
||||
subscriptions &&
|
||||
subscriptions.forEach((subscription) =>
|
||||
subscription.reload(forceReset)
|
||||
),
|
||||
flush: () => notify(callback),
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
// Derived data provider has no subscription, hence there is no delta (never)
|
||||
export function makeDerivedDataProvider<Data>(
|
||||
dependencies: DependencySubscribe[],
|
||||
combineData: CombineDerivedData<Data>
|
||||
): Subscribe<Data, never> {
|
||||
const getInstance = memoize<Data, never>(() =>
|
||||
makeDerivedDataProviderInternal(dependencies, combineData)
|
||||
);
|
||||
return (callback, client, variables) =>
|
||||
getInstance(variables)(callback, client, variables);
|
||||
|
@ -97,15 +97,15 @@ const getDelta = (subscriptionData: TradesSub): TradeFields[] =>
|
||||
const getPageInfo = (responseData: Trades): PageInfo | null =>
|
||||
responseData.market?.tradesConnection.pageInfo || null;
|
||||
|
||||
export const tradesDataProvider = makeDataProvider(
|
||||
TRADES_QUERY,
|
||||
TRADES_SUB,
|
||||
export const tradesDataProvider = makeDataProvider({
|
||||
query: TRADES_QUERY,
|
||||
subscriptionQuery: TRADES_SUB,
|
||||
update,
|
||||
getData,
|
||||
getDelta,
|
||||
{
|
||||
pagination: {
|
||||
getPageInfo,
|
||||
append,
|
||||
first: 100,
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
|
@ -70,6 +70,8 @@
|
||||
"react-window": "^1.8.7",
|
||||
"react-window-infinite-loader": "^1.0.7",
|
||||
"recharts": "^2.1.2",
|
||||
"regenerator-runtime": "0.13.7",
|
||||
"tslib": "^2.0.0",
|
||||
"uuid": "^8.3.2",
|
||||
"web-vitals": "^2.1.4",
|
||||
"zod": "^3.17.3",
|
||||
@ -104,6 +106,7 @@
|
||||
"@svgr/webpack": "^5.4.0",
|
||||
"@testing-library/jest-dom": "^5.16.2",
|
||||
"@testing-library/react": "13.3.0",
|
||||
"@testing-library/react-hooks": "7.0.2",
|
||||
"@testing-library/user-event": "^14.4.1",
|
||||
"@types/classnames": "^2.3.1",
|
||||
"@types/faker": "^5.5.8",
|
||||
@ -148,8 +151,8 @@
|
||||
"mock-apollo-client": "^1.2.0",
|
||||
"npmlog": "^6.0.2",
|
||||
"nx": "13.10.1",
|
||||
"prettier": "^2.5.1",
|
||||
"postcss": "^8.4.6",
|
||||
"prettier": "^2.5.1",
|
||||
"react-test-renderer": "17.0.2",
|
||||
"recast": "^0.21.1",
|
||||
"regenerator-runtime": "0.13.7",
|
||||
@ -157,11 +160,11 @@
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"sass": "1.49.9",
|
||||
"storybook-addon-themes": "^6.1.0",
|
||||
"ts-jest": "27.0.5",
|
||||
"tailwindcss": "^3.0.23",
|
||||
"ts-jest": "27.0.5",
|
||||
"tslib": "^2.0.0",
|
||||
"type-fest": "^2.12.2",
|
||||
"typescript": "~4.5.2",
|
||||
"tslib": "^2.0.0",
|
||||
"url-loader": "^3.0.0"
|
||||
},
|
||||
"lint-staged": {
|
||||
|
@ -17,6 +17,7 @@
|
||||
"resolveJsonModule": true,
|
||||
"paths": {
|
||||
"@vegaprotocol/accounts": ["libs/accounts/src/index.ts"],
|
||||
"@vegaprotocol/assets": ["libs/assets/src/index.ts"],
|
||||
"@vegaprotocol/candles-chart": ["libs/candles-chart/src/index.ts"],
|
||||
"@vegaprotocol/cypress": ["libs/cypress/src/index.ts"],
|
||||
"@vegaprotocol/deal-ticket": ["libs/deal-ticket/src/index.ts"],
|
||||
|
@ -2,6 +2,7 @@
|
||||
"version": 2,
|
||||
"projects": {
|
||||
"accounts": "libs/accounts",
|
||||
"assets": "libs/assets",
|
||||
"candles-chart": "libs/candles-chart",
|
||||
"console-lite": "apps/console-lite",
|
||||
"console-lite-e2e": "apps/console-lite-e2e",
|
||||
|
36
yarn.lock
36
yarn.lock
@ -5628,6 +5628,17 @@
|
||||
lodash "^4.17.15"
|
||||
redent "^3.0.0"
|
||||
|
||||
"@testing-library/react-hooks@7.0.2":
|
||||
version "7.0.2"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react-hooks/-/react-hooks-7.0.2.tgz#3388d07f562d91e7f2431a4a21b5186062ecfee0"
|
||||
integrity sha512-dYxpz8u9m4q1TuzfcUApqi8iFfR6R0FaMbr2hjZJy1uC8z+bO/K4v8Gs9eogGKYQop7QsrBTFkv/BCF7MzD2Cg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@types/react" ">=16.9.0"
|
||||
"@types/react-dom" ">=16.9.0"
|
||||
"@types/react-test-renderer" ">=16.9.0"
|
||||
react-error-boundary "^3.1.0"
|
||||
|
||||
"@testing-library/react@13.3.0":
|
||||
version "13.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/react/-/react-13.3.0.tgz#bf298bfbc5589326bbcc8052b211f3bb097a97c5"
|
||||
@ -6135,7 +6146,7 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-dom@18.0.6", "@types/react-dom@^18.0.0", "@types/react-dom@^18.0.5":
|
||||
"@types/react-dom@18.0.6", "@types/react-dom@>=16.9.0", "@types/react-dom@^18.0.0", "@types/react-dom@^18.0.5":
|
||||
version "18.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.0.6.tgz#36652900024842b74607a17786b6662dd1e103a1"
|
||||
integrity sha512-/5OFZgfIPSwy+YuIBP/FgJnQnsxhZhjjrnxudMddeblOouIodEQ75X14Rr4wGSG/bknL+Omy9iWlLo1u/9GzAA==
|
||||
@ -6166,6 +6177,13 @@
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-test-renderer@>=16.9.0":
|
||||
version "18.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-test-renderer/-/react-test-renderer-18.0.0.tgz#7b7f69ca98821ea5501b21ba24ea7b6139da2243"
|
||||
integrity sha512-C7/5FBJ3g3sqUahguGi03O79b8afNeSD6T8/GU50oQrJCU0bVCCGQHaGKUbg2Ce8VQEEqTw8/HiS6lXHHdgkdQ==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react-virtualized-auto-sizer@^1.0.0", "@types/react-virtualized-auto-sizer@^1.0.1":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.1.tgz#b3187dae1dfc4c15880c9cfc5b45f2719ea6ebd4"
|
||||
@ -6206,6 +6224,15 @@
|
||||
"@types/scheduler" "*"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/react@>=16.9.0":
|
||||
version "18.0.17"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.17.tgz#4583d9c322d67efe4b39a935d223edcc7050ccf4"
|
||||
integrity sha512-38ETy4tL+rn4uQQi7mB81G7V1g0u2ryquNmsVIOKUAEIDK+3CUjZ6rSRpdvS99dNBnkLFL83qfmtLacGOTIhwQ==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
"@types/scheduler" "*"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/resolve@1.17.1":
|
||||
version "1.17.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6"
|
||||
@ -18140,6 +18167,13 @@ react-element-to-jsx-string@^14.3.4:
|
||||
is-plain-object "5.0.0"
|
||||
react-is "17.0.2"
|
||||
|
||||
react-error-boundary@^3.1.0:
|
||||
version "3.1.4"
|
||||
resolved "https://registry.yarnpkg.com/react-error-boundary/-/react-error-boundary-3.1.4.tgz#255db92b23197108757a888b01e5b729919abde0"
|
||||
integrity sha512-uM9uPzZJTF6wRQORmSrvOIgt4lJ9MC1sNgEOj2XGsDTRE4kmpWxg7ENK9EWNKJRMAOY9z0MuF4yIfl6gp4sotA==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
|
||||
react-fast-compare@^3.0.1, react-fast-compare@^3.2.0:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.0.tgz#641a9da81b6a6320f270e89724fb45a0b39e43bb"
|
||||
|
Loading…
Reference in New Issue
Block a user