Compare commits
54 Commits
develop
...
feat/subs-
Author | SHA1 | Date | |
---|---|---|---|
|
39cc5743bf | ||
|
666c3d3c24 | ||
|
ab5c0feb39 | ||
|
84d1511972 | ||
|
e8034b91ae | ||
|
779f2375f5 | ||
|
545b469ddf | ||
|
e5c9b7fad9 | ||
|
b97728cf77 | ||
|
f291be76cd | ||
|
3cc5cd35cd | ||
|
d901601986 | ||
|
5452bcd7a4 | ||
|
12c32b440d | ||
|
b122b4a135 | ||
|
7170068121 | ||
|
3caf0dc816 | ||
|
b1414da420 | ||
|
094b41e8ef | ||
|
c3675cb900 | ||
|
29b6f9f3e5 | ||
|
569031bef4 | ||
|
7fe68e03bc | ||
|
d616b1f4a2 | ||
|
f9f5177dca | ||
|
8e31a98b09 | ||
|
51a96b4932 | ||
|
c7586f366c | ||
|
41939c02b7 | ||
|
3107214c93 | ||
|
0f6e980cb1 | ||
|
d15d37b485 | ||
|
b83931138c | ||
|
32d205f0f5 | ||
|
f1ea57b50e | ||
|
37aafeebe4 | ||
|
7b1bd0384a | ||
|
c84e0e672c | ||
|
e2374aad8d | ||
|
d429df640c | ||
|
72168be413 | ||
|
9120238303 | ||
|
ded465a856 | ||
|
48675af654 | ||
|
776985b7fd | ||
|
eba2a8ac70 | ||
|
da12f0b5cd | ||
|
be7d6073b6 | ||
|
ab20c2314f | ||
|
7cbca79146 | ||
|
7bf1f26cdf | ||
|
f1097b76fc | ||
|
9ffe28be0b | ||
|
434df13079 |
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -55,7 +55,7 @@ jobs:
|
||||
- name: Derive appropriate SHAs for base and head for `nx affected` commands
|
||||
uses: nrwl/nx-set-shas@v2
|
||||
with:
|
||||
main-branch-name: master
|
||||
main-branch-name: develop
|
||||
- name: Use Node.js 16
|
||||
id: Node
|
||||
uses: actions/setup-node@v3
|
||||
|
@ -1,14 +1,19 @@
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import type { Markets } from '@vegaprotocol/market-list';
|
||||
import {
|
||||
generateLongListMarkets,
|
||||
generateSimpleMarkets,
|
||||
generateMarketsData,
|
||||
generateMarketsCandles,
|
||||
} from '../support/mocks/generate-markets';
|
||||
|
||||
describe('market list', () => {
|
||||
describe('simple url', () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
|
||||
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
|
||||
});
|
||||
cy.visit('/markets');
|
||||
});
|
||||
@ -62,7 +67,7 @@ describe('market list', () => {
|
||||
describe('url params should select filters', () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
});
|
||||
});
|
||||
|
||||
@ -73,10 +78,11 @@ describe('market list', () => {
|
||||
|
||||
it('last asset (if exists)', () => {
|
||||
cy.visit('/markets');
|
||||
cy.wait('@SimpleMarkets').then((filters) => {
|
||||
if (filters?.response?.body?.data?.markets?.length) {
|
||||
cy.wait('@Markets').then((filters) => {
|
||||
const data: Markets | undefined = filters?.response?.body?.data;
|
||||
if (data.marketsConnection.edges.length) {
|
||||
const asset =
|
||||
filters.response.body.data.markets[0].tradableInstrument.instrument
|
||||
data.marketsConnection.edges[0].node.tradableInstrument.instrument
|
||||
.product.settlementAsset.symbol;
|
||||
cy.visit(`/markets/Suspended/Future/${asset}`);
|
||||
cy.getByTestId('market-assets-menu')
|
||||
@ -98,7 +104,9 @@ describe('market list', () => {
|
||||
it('handles 1000 markets', () => {
|
||||
cy.viewport(1440, 900);
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'SimpleMarkets', generateLongListMarkets(1000));
|
||||
aliasQuery(req, 'Markets', generateLongListMarkets(1000));
|
||||
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
|
||||
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
|
||||
});
|
||||
performance.mark('start-1k');
|
||||
cy.visit('/markets');
|
||||
|
@ -1,6 +1,10 @@
|
||||
import { connectVegaWallet } from '../support/connect-wallet';
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import { generateSimpleMarkets } from '../support/mocks/generate-markets';
|
||||
import {
|
||||
generateMarketsCandles,
|
||||
generateMarketsData,
|
||||
generateSimpleMarkets,
|
||||
} from '../support/mocks/generate-markets';
|
||||
import { generateDealTicket } from '../support/mocks/generate-deal-ticket';
|
||||
import { generateMarketTags } from '../support/mocks/generate-market-tags';
|
||||
import { generateMarketPositions } from '../support/mocks/generate-market-positions';
|
||||
@ -10,12 +14,15 @@ import { generatePartyMarketData } from '../support/mocks/generate-party-market-
|
||||
import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price';
|
||||
import { generateMarketNames } from '../support/mocks/generate-market-names';
|
||||
import { generateMarketDepth } from '../support/mocks/generate-market-depth';
|
||||
import type { Market, Markets } from '@vegaprotocol/market-list';
|
||||
|
||||
describe('market selector', () => {
|
||||
let markets;
|
||||
let markets: Market[];
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
|
||||
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
|
||||
aliasQuery(req, 'DealTicketQuery', generateDealTicket());
|
||||
aliasQuery(req, 'MarketTags', generateMarketTags());
|
||||
aliasQuery(req, 'MarketPositions', generateMarketPositions());
|
||||
@ -28,9 +35,10 @@ describe('market selector', () => {
|
||||
});
|
||||
|
||||
cy.visit('/markets');
|
||||
cy.wait('@SimpleMarkets').then((response) => {
|
||||
if (response.response.body.data?.markets?.length) {
|
||||
markets = response.response.body.data.markets;
|
||||
cy.wait('@Markets').then((response) => {
|
||||
const data: Markets | undefined = response?.response?.body?.data;
|
||||
if (data.marketsConnection.edges.length) {
|
||||
markets = data.marketsConnection.edges.map((edge) => edge.node);
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -116,7 +124,7 @@ describe('market selector', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('mobile view', () => {
|
||||
it.only('mobile view', () => {
|
||||
if (markets?.length) {
|
||||
cy.viewport('iphone-xr');
|
||||
cy.visit(`/trading/${markets[0].id}`);
|
||||
@ -128,7 +136,7 @@ describe('market selector', () => {
|
||||
cy.getByTestId('market-pane')
|
||||
.children()
|
||||
.find('[role="button"]')
|
||||
.should('have.length', 3);
|
||||
.should('have.length', 9);
|
||||
cy.get('div[role="dialog"]').should('have.class', 'w-screen');
|
||||
cy.getByTestId('dialog-close').click();
|
||||
cy.get('input[placeholder="Search"]').should(
|
||||
|
@ -1,7 +1,8 @@
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import {
|
||||
generateSimpleMarkets,
|
||||
generateMarkets,
|
||||
generateMarketsCandles,
|
||||
generateMarketsData,
|
||||
} from '../support/mocks/generate-markets';
|
||||
import { generateDealTicket } from '../support/mocks/generate-deal-ticket';
|
||||
import { generateMarketTags } from '../support/mocks/generate-market-tags';
|
||||
@ -12,12 +13,15 @@ import { generatePartyMarketData } from '../support/mocks/generate-party-market-
|
||||
import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price';
|
||||
import { generateMarketDepth } from '../support/mocks/generate-market-depth';
|
||||
import { connectVegaWallet } from '../support/connect-wallet';
|
||||
import type { Markets, Market } from '@vegaprotocol/market-list';
|
||||
|
||||
describe('Market trade', () => {
|
||||
let markets;
|
||||
let markets: Market[];
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'Markets', generateMarkets());
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
|
||||
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
|
||||
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'DealTicketQuery', generateDealTicket());
|
||||
aliasQuery(req, 'MarketTags', generateMarketTags());
|
||||
@ -29,9 +33,10 @@ describe('Market trade', () => {
|
||||
aliasQuery(req, 'MarketDepth', generateMarketDepth());
|
||||
});
|
||||
cy.visit('/markets');
|
||||
cy.wait('@SimpleMarkets').then((response) => {
|
||||
if (response.response.body.data?.markets?.length) {
|
||||
markets = response.response.body.data.markets;
|
||||
cy.wait('@Markets').then((response) => {
|
||||
const data: Markets | undefined = response?.response?.body?.data;
|
||||
if (data.marketsConnection.edges.length) {
|
||||
markets = data.marketsConnection.edges.map((edge) => edge.node);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -1,4 +1,7 @@
|
||||
const protoCandles = [
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
import { MarketState, MarketTradingMode } from '@vegaprotocol/types';
|
||||
|
||||
export const protoCandles = [
|
||||
{ open: '9556163', close: '9587028', __typename: 'Candle' },
|
||||
{
|
||||
open: '9587028',
|
||||
@ -73,11 +76,29 @@ const protoCandles = [
|
||||
},
|
||||
];
|
||||
|
||||
export const protoMarket = {
|
||||
export const protoMarket: Market = {
|
||||
id: 'first-btcusd-id',
|
||||
state: 'STATE_ACTIVE',
|
||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
marketTimestamps: {
|
||||
__typename: 'MarketTimestamps',
|
||||
close: '',
|
||||
open: '',
|
||||
},
|
||||
fees: {
|
||||
__typename: 'Fees',
|
||||
factors: {
|
||||
__typename: 'FeeFactors',
|
||||
makerFee: '',
|
||||
infrastructureFee: '',
|
||||
liquidityFee: '',
|
||||
},
|
||||
},
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
id: '',
|
||||
code: 'AAVEDAI.MF21',
|
||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||
metadata: {
|
||||
@ -94,12 +115,11 @@ export const protoMarket = {
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'DAI',
|
||||
settlementAsset: { symbol: 'tDAI', __typename: 'Asset' },
|
||||
settlementAsset: { symbol: 'tDAI', __typename: 'Asset', decimals: 5 },
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
candles: protoCandles,
|
||||
__typename: 'Market',
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,5 @@
|
||||
import '@testing-library/jest-dom';
|
||||
import 'jest-canvas-mock';
|
||||
import { defaultFallbackInView } from 'react-intersection-observer';
|
||||
import ResizeObserver from 'resize-observer-polyfill';
|
||||
|
||||
|
@ -68,5 +68,5 @@ export interface Deposits {
|
||||
/**
|
||||
* The list of all assets in use in the Vega network or the specified asset if ID is provided
|
||||
*/
|
||||
assetsConnection: Deposits_assetsConnection;
|
||||
assetsConnection: Deposits_assetsConnection | null;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ const defaultOptions = {} as const;
|
||||
export type DepositsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type DepositsQuery = { __typename?: 'Query', assetsConnection: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } } | null> | null } };
|
||||
export type DepositsQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } } | null> | null } | null };
|
||||
|
||||
|
||||
export const DepositsDocument = gql`
|
||||
|
@ -1,5 +0,0 @@
|
||||
subscription CandleLive($marketId: ID!) {
|
||||
candles(marketId: $marketId, interval: INTERVAL_I1H) {
|
||||
close
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
fragment SimpleMarketDataFields on MarketData {
|
||||
market {
|
||||
id
|
||||
state
|
||||
}
|
||||
}
|
||||
|
||||
query SimpleMarkets($CandleSince: String!) {
|
||||
markets {
|
||||
id
|
||||
name
|
||||
state
|
||||
data {
|
||||
...SimpleMarketDataFields
|
||||
}
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
code
|
||||
metadata {
|
||||
tags
|
||||
}
|
||||
product {
|
||||
__typename
|
||||
... on Future {
|
||||
quoteName
|
||||
settlementAsset {
|
||||
symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
candles(interval: INTERVAL_I1H, since: $CandleSince) {
|
||||
open
|
||||
close
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subscription SimpleMarketDataSub {
|
||||
marketData {
|
||||
...SimpleMarketDataFields
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { MarketState } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL fragment: SimpleMarketDataFields
|
||||
// ====================================================
|
||||
|
||||
export interface SimpleMarketDataFields_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Current state of the market
|
||||
*/
|
||||
state: MarketState;
|
||||
}
|
||||
|
||||
export interface SimpleMarketDataFields {
|
||||
__typename: "MarketData";
|
||||
/**
|
||||
* market ID of the associated mark price
|
||||
*/
|
||||
market: SimpleMarketDataFields_market;
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { MarketState } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL subscription operation: SimpleMarketDataSub
|
||||
// ====================================================
|
||||
|
||||
export interface SimpleMarketDataSub_marketData_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Current state of the market
|
||||
*/
|
||||
state: MarketState;
|
||||
}
|
||||
|
||||
export interface SimpleMarketDataSub_marketData {
|
||||
__typename: "MarketData";
|
||||
/**
|
||||
* market ID of the associated mark price
|
||||
*/
|
||||
market: SimpleMarketDataSub_marketData_market;
|
||||
}
|
||||
|
||||
export interface SimpleMarketDataSub {
|
||||
/**
|
||||
* Subscribe to the mark price changes
|
||||
*/
|
||||
marketData: SimpleMarketDataSub_marketData;
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { MarketState } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL query operation: SimpleMarkets
|
||||
// ====================================================
|
||||
|
||||
export interface SimpleMarkets_markets_tradableInstrument_instrument_metadata {
|
||||
__typename: "InstrumentMetadata";
|
||||
/**
|
||||
* An arbitrary list of tags to associated to associate to the Instrument (string list)
|
||||
*/
|
||||
tags: string[] | null;
|
||||
}
|
||||
|
||||
export interface SimpleMarkets_markets_tradableInstrument_instrument_product_settlementAsset {
|
||||
__typename: "Asset";
|
||||
/**
|
||||
* The symbol of the asset (e.g: GBP)
|
||||
*/
|
||||
symbol: string;
|
||||
}
|
||||
|
||||
export interface SimpleMarkets_markets_tradableInstrument_instrument_product {
|
||||
__typename: "Future";
|
||||
/**
|
||||
* String representing the quote (e.g. BTCUSD -> USD is quote)
|
||||
*/
|
||||
quoteName: string;
|
||||
/**
|
||||
* The name of the asset (string)
|
||||
*/
|
||||
settlementAsset: SimpleMarkets_markets_tradableInstrument_instrument_product_settlementAsset;
|
||||
}
|
||||
|
||||
export interface SimpleMarkets_markets_tradableInstrument_instrument {
|
||||
__typename: "Instrument";
|
||||
/**
|
||||
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
|
||||
*/
|
||||
code: string;
|
||||
/**
|
||||
* Full and fairly descriptive name for the instrument
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* Metadata for this instrument
|
||||
*/
|
||||
metadata: SimpleMarkets_markets_tradableInstrument_instrument_metadata;
|
||||
/**
|
||||
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
|
||||
*/
|
||||
product: SimpleMarkets_markets_tradableInstrument_instrument_product;
|
||||
}
|
||||
|
||||
export interface SimpleMarkets_markets_tradableInstrument {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of, or reference to, a fully specified instrument.
|
||||
*/
|
||||
instrument: SimpleMarkets_markets_tradableInstrument_instrument;
|
||||
}
|
||||
|
||||
export interface SimpleMarkets_markets_candles {
|
||||
__typename: "Candle";
|
||||
/**
|
||||
* Open price (uint64)
|
||||
*/
|
||||
open: string;
|
||||
/**
|
||||
* Close price (uint64)
|
||||
*/
|
||||
close: string;
|
||||
}
|
||||
|
||||
export interface SimpleMarkets_markets {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* Current state of the market
|
||||
*/
|
||||
state: MarketState;
|
||||
/**
|
||||
* An instance of, or reference to, a tradable instrument.
|
||||
*/
|
||||
tradableInstrument: SimpleMarkets_markets_tradableInstrument;
|
||||
/**
|
||||
* Candles on a market, for the 'last' n candles, at 'interval' seconds as specified by parameters
|
||||
*/
|
||||
candles: (SimpleMarkets_markets_candles | null)[] | null;
|
||||
}
|
||||
|
||||
export interface SimpleMarkets {
|
||||
/**
|
||||
* One or more instruments that are trading on the VEGA network
|
||||
*/
|
||||
markets: SimpleMarkets_markets[] | null;
|
||||
}
|
||||
|
||||
export interface SimpleMarketsVariables {
|
||||
CandleSince: string;
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type SimpleMarketDataFieldsFragment = { __typename?: 'MarketData', market: { __typename?: 'Market', id: string, state: Types.MarketState } };
|
||||
|
||||
export type SimpleMarketsQueryVariables = Types.Exact<{
|
||||
CandleSince: Types.Scalars['String'];
|
||||
}>;
|
||||
|
||||
|
||||
export type SimpleMarketsQuery = { __typename?: 'Query', markets?: Array<{ __typename?: 'Market', id: string, name: string, state: Types.MarketState, data?: { __typename?: 'MarketData', market: { __typename?: 'Market', id: string, state: Types.MarketState } } | null, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', symbol: string } } } }, candles?: Array<{ __typename?: 'Candle', open: string, close: string } | null> | null }> | null };
|
||||
|
||||
export type SimpleMarketDataSubSubscriptionVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type SimpleMarketDataSubSubscription = { __typename?: 'Subscription', marketData: { __typename?: 'MarketData', market: { __typename?: 'Market', id: string, state: Types.MarketState } } };
|
||||
|
||||
export const SimpleMarketDataFieldsFragmentDoc = gql`
|
||||
fragment SimpleMarketDataFields on MarketData {
|
||||
market {
|
||||
id
|
||||
state
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const SimpleMarketsDocument = gql`
|
||||
query SimpleMarkets($CandleSince: String!) {
|
||||
markets {
|
||||
id
|
||||
name
|
||||
state
|
||||
data {
|
||||
...SimpleMarketDataFields
|
||||
}
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
code
|
||||
metadata {
|
||||
tags
|
||||
}
|
||||
product {
|
||||
__typename
|
||||
... on Future {
|
||||
quoteName
|
||||
settlementAsset {
|
||||
symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
candles(interval: INTERVAL_I1H, since: $CandleSince) {
|
||||
open
|
||||
close
|
||||
}
|
||||
}
|
||||
}
|
||||
${SimpleMarketDataFieldsFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __useSimpleMarketsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useSimpleMarketsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useSimpleMarketsQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useSimpleMarketsQuery({
|
||||
* variables: {
|
||||
* CandleSince: // value for 'CandleSince'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useSimpleMarketsQuery(baseOptions: Apollo.QueryHookOptions<SimpleMarketsQuery, SimpleMarketsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<SimpleMarketsQuery, SimpleMarketsQueryVariables>(SimpleMarketsDocument, options);
|
||||
}
|
||||
export function useSimpleMarketsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<SimpleMarketsQuery, SimpleMarketsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<SimpleMarketsQuery, SimpleMarketsQueryVariables>(SimpleMarketsDocument, options);
|
||||
}
|
||||
export type SimpleMarketsQueryHookResult = ReturnType<typeof useSimpleMarketsQuery>;
|
||||
export type SimpleMarketsLazyQueryHookResult = ReturnType<typeof useSimpleMarketsLazyQuery>;
|
||||
export type SimpleMarketsQueryResult = Apollo.QueryResult<SimpleMarketsQuery, SimpleMarketsQueryVariables>;
|
||||
export const SimpleMarketDataSubDocument = gql`
|
||||
subscription SimpleMarketDataSub {
|
||||
marketData {
|
||||
...SimpleMarketDataFields
|
||||
}
|
||||
}
|
||||
${SimpleMarketDataFieldsFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __useSimpleMarketDataSubSubscription__
|
||||
*
|
||||
* To run a query within a React component, call `useSimpleMarketDataSubSubscription` and pass it any options that fit your needs.
|
||||
* When your component renders, `useSimpleMarketDataSubSubscription` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the subscription, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useSimpleMarketDataSubSubscription({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useSimpleMarketDataSubSubscription(baseOptions?: Apollo.SubscriptionHookOptions<SimpleMarketDataSubSubscription, SimpleMarketDataSubSubscriptionVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useSubscription<SimpleMarketDataSubSubscription, SimpleMarketDataSubSubscriptionVariables>(SimpleMarketDataSubDocument, options);
|
||||
}
|
||||
export type SimpleMarketDataSubSubscriptionHookResult = ReturnType<typeof useSimpleMarketDataSubSubscription>;
|
||||
export type SimpleMarketDataSubSubscriptionResult = Apollo.SubscriptionResult<SimpleMarketDataSubSubscription>;
|
@ -2,8 +2,8 @@ import { t } from '@vegaprotocol/react-helpers';
|
||||
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import { IS_MARKET_TRADABLE } from '../../constants';
|
||||
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
|
||||
import colors from 'tailwindcss/colors';
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
|
||||
export const STATES_FILTER = [
|
||||
{ value: 'all', text: t('All') },
|
||||
@ -192,7 +192,7 @@ export const agGridDarkVariables = `
|
||||
`;
|
||||
|
||||
export const ROW_CLASS_RULES = {
|
||||
'cursor-pointer': ({ data }: { data: SimpleMarkets_markets }) =>
|
||||
'cursor-pointer': ({ data }: { data: Market }) =>
|
||||
IS_MARKET_TRADABLE(data || {}),
|
||||
};
|
||||
|
||||
|
@ -1,94 +0,0 @@
|
||||
import produce from 'immer';
|
||||
import { gql } from '@apollo/client';
|
||||
import { makeDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
SimpleMarkets,
|
||||
SimpleMarkets_markets,
|
||||
} from './__generated__/SimpleMarkets';
|
||||
import type {
|
||||
SimpleMarketDataSub,
|
||||
SimpleMarketDataSub_marketData,
|
||||
} from './__generated__/SimpleMarketDataSub';
|
||||
|
||||
export const MARKETS_QUERY = gql`
|
||||
query SimpleMarkets($CandleSince: String!) {
|
||||
markets {
|
||||
id
|
||||
state
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
code
|
||||
name
|
||||
metadata {
|
||||
tags
|
||||
}
|
||||
product {
|
||||
__typename
|
||||
... on Future {
|
||||
quoteName
|
||||
settlementAsset {
|
||||
symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
candles(interval: INTERVAL_I1H, since: $CandleSince) {
|
||||
open
|
||||
close
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const MARKET_DATA_SUB = gql`
|
||||
subscription SimpleMarketDataSub {
|
||||
marketData {
|
||||
market {
|
||||
id
|
||||
state
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const CANDLE_SUB = gql`
|
||||
subscription CandleLive($marketId: ID!) {
|
||||
candles(marketId: $marketId, interval: INTERVAL_I1H) {
|
||||
close
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const update = (
|
||||
data: SimpleMarkets_markets[],
|
||||
delta: SimpleMarketDataSub_marketData
|
||||
) => {
|
||||
return produce(data, (draft) => {
|
||||
const index = draft.findIndex((m) => m.id === delta.market.id);
|
||||
if (index !== -1) {
|
||||
draft[index].state = delta.market.state;
|
||||
}
|
||||
// @TODO - else push new market to draft
|
||||
});
|
||||
};
|
||||
|
||||
const getData = (responseData: SimpleMarkets) => responseData.markets;
|
||||
const getDelta = (
|
||||
subscriptionData: SimpleMarketDataSub
|
||||
): SimpleMarketDataSub_marketData => subscriptionData.marketData;
|
||||
|
||||
export const dataProvider = makeDataProvider<
|
||||
SimpleMarkets,
|
||||
SimpleMarkets_markets[],
|
||||
SimpleMarketDataSub,
|
||||
SimpleMarketDataSub_marketData
|
||||
>({
|
||||
query: MARKETS_QUERY,
|
||||
subscriptionQuery: MARKET_DATA_SUB,
|
||||
update,
|
||||
getData,
|
||||
getDelta,
|
||||
});
|
||||
|
||||
export default dataProvider;
|
@ -4,21 +4,14 @@ import {
|
||||
render,
|
||||
screen,
|
||||
waitFor,
|
||||
cleanup,
|
||||
getAllByRole,
|
||||
fireEvent,
|
||||
} from '@testing-library/react';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { BrowserRouter } from 'react-router-dom';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import SimpleMarketList from './simple-market-list';
|
||||
import { MARKETS_QUERY } from './data-provider';
|
||||
import type {
|
||||
SimpleMarkets_markets,
|
||||
SimpleMarkets,
|
||||
} from './__generated__/SimpleMarkets';
|
||||
import type { SimpleMarketDataSub_marketData } from './__generated__/SimpleMarketDataSub';
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
|
||||
const mockedNavigate = jest.fn();
|
||||
|
||||
@ -28,20 +21,9 @@ jest.mock('react-router-dom', () => ({
|
||||
useParams: () => ({}),
|
||||
}));
|
||||
|
||||
jest.mock('date-fns', () => ({
|
||||
subDays: () => new Date('2022-06-02T11:11:21.721Z'),
|
||||
}));
|
||||
|
||||
let updateMock: ({
|
||||
delta,
|
||||
}: {
|
||||
delta: SimpleMarketDataSub_marketData;
|
||||
}) => boolean;
|
||||
|
||||
let mockData = [
|
||||
let marketsMock = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'Market 1',
|
||||
id: 'MARKET_A',
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
@ -57,8 +39,7 @@ let mockData = [
|
||||
},
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Market 2',
|
||||
id: 'MARKET_B',
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
@ -73,20 +54,24 @@ let mockData = [
|
||||
},
|
||||
},
|
||||
},
|
||||
] as unknown as SimpleMarkets_markets[];
|
||||
] as unknown as Market[];
|
||||
|
||||
const mockUseDataProvider = ({ update }: { update: () => boolean }) => {
|
||||
updateMock = update;
|
||||
return { data: mockData, loading: false, error: false };
|
||||
const LIB = '@vegaprotocol/market-list';
|
||||
const useMarketList = () => {
|
||||
return {
|
||||
data: {
|
||||
markets: marketsMock,
|
||||
},
|
||||
loading: false,
|
||||
error: false,
|
||||
};
|
||||
};
|
||||
|
||||
jest.mock('@vegaprotocol/react-helpers', () => ({
|
||||
...jest.requireActual('@vegaprotocol/react-helpers'),
|
||||
useDataProvider: jest.fn((args) => mockUseDataProvider(args)),
|
||||
jest.mock(LIB, () => ({
|
||||
...jest.requireActual(LIB),
|
||||
useMarketList: jest.fn(() => useMarketList()),
|
||||
}));
|
||||
|
||||
const mockIsTradable = jest.fn((_arg) => true);
|
||||
|
||||
jest.mock('../../constants', () => ({
|
||||
...jest.requireActual('../../constants'),
|
||||
IS_MARKET_TRADABLE: jest.fn((arg) => mockIsTradable(arg)),
|
||||
@ -95,25 +80,11 @@ jest.mock('../../constants', () => ({
|
||||
describe('SimpleMarketList', () => {
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
cleanup();
|
||||
});
|
||||
|
||||
const mocks: MockedResponse<SimpleMarkets> = {
|
||||
request: {
|
||||
query: MARKETS_QUERY,
|
||||
variables: {
|
||||
CandleSince: '2022-06-02T11:11:21.721Z',
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data: { markets: mockData },
|
||||
},
|
||||
};
|
||||
|
||||
it('should be properly rendered with some data', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MockedProvider mocks={[mocks]}>
|
||||
<MockedProvider mocks={[]}>
|
||||
<SimpleMarketList />
|
||||
</MockedProvider>,
|
||||
{ wrapper: BrowserRouter }
|
||||
@ -124,95 +95,49 @@ describe('SimpleMarketList', () => {
|
||||
expect(
|
||||
document.querySelector('.ag-center-cols-container')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
await waitFor(() => {
|
||||
const container = document.querySelector('.ag-center-cols-container');
|
||||
expect(getAllByRole(container as HTMLDivElement, 'row')).toHaveLength(2);
|
||||
});
|
||||
});
|
||||
|
||||
it('update should return proper boolean value', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MockedProvider mocks={[mocks]}>
|
||||
<SimpleMarketList />
|
||||
</MockedProvider>,
|
||||
{ wrapper: BrowserRouter }
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
document.querySelector('.ag-center-cols-container')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
await expect(
|
||||
updateMock({
|
||||
delta: {
|
||||
__typename: 'MarketData',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '2',
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
},
|
||||
},
|
||||
})
|
||||
).toEqual(true);
|
||||
|
||||
await expect(
|
||||
updateMock({
|
||||
delta: {
|
||||
__typename: 'MarketData',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '2',
|
||||
state: MarketState.STATE_SUSPENDED,
|
||||
},
|
||||
},
|
||||
})
|
||||
).toEqual(false);
|
||||
});
|
||||
|
||||
it('click on row should be properly handled', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MockedProvider mocks={[mocks]}>
|
||||
<MockedProvider mocks={[]}>
|
||||
<SimpleMarketList />
|
||||
</MockedProvider>,
|
||||
{ wrapper: BrowserRouter }
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(
|
||||
document.querySelector('.ag-center-cols-container')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
mockIsTradable.mockClear();
|
||||
const container = document.querySelector('.ag-center-cols-container');
|
||||
const firstRow = getAllByRole(container as HTMLDivElement, 'row')[0];
|
||||
expect(firstRow).toHaveAttribute('row-id', '1');
|
||||
fireEvent.click(firstRow);
|
||||
expect(firstRow).toHaveAttribute('row-id', marketsMock[0].id);
|
||||
await act(async () => {
|
||||
fireEvent.click(firstRow);
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(mockIsTradable).toHaveBeenCalledWith({
|
||||
...mockData[0],
|
||||
percentChange: '-',
|
||||
});
|
||||
expect(mockedNavigate).toHaveBeenCalledWith(`/trading/${mockData[0].id}`);
|
||||
expect(mockIsTradable).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
id: marketsMock[0].id,
|
||||
percentChange: '-',
|
||||
})
|
||||
);
|
||||
expect(mockedNavigate).toHaveBeenCalledWith(
|
||||
`/trading/${marketsMock[0].id}`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should be properly renderer as empty', async () => {
|
||||
mockData = [];
|
||||
marketsMock = [];
|
||||
await act(async () => {
|
||||
render(
|
||||
<MockedProvider mocks={[mocks]}>
|
||||
<MockedProvider mocks={[]}>
|
||||
<SimpleMarketList />
|
||||
</MockedProvider>,
|
||||
{ wrapper: BrowserRouter }
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
});
|
||||
await waitFor(() => {
|
||||
expect(screen.getByText('No data to display')).toBeInTheDocument();
|
||||
|
@ -1,29 +1,16 @@
|
||||
import React, {
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
} from 'react';
|
||||
import { useCallback, useContext, useEffect, useMemo, useRef } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { subDays } from 'date-fns';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
useDataProvider,
|
||||
useScreenDimensions,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { ThemeContext } from '@vegaprotocol/react-helpers';
|
||||
import type { MarketState } from '@vegaprotocol/types';
|
||||
import useMarketsFilterData from '../../hooks/use-markets-filter-data';
|
||||
import useColumnDefinitions from '../../hooks/use-column-definitions';
|
||||
import dataProvider from './data-provider';
|
||||
import * as constants from './constants';
|
||||
import SimpleMarketToolbar from './simple-market-toolbar';
|
||||
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
|
||||
import type { SimpleMarketDataSub_marketData } from './__generated__/SimpleMarketDataSub';
|
||||
import { IS_MARKET_TRADABLE } from '../../constants';
|
||||
import type {
|
||||
CellKeyDownEvent,
|
||||
@ -33,8 +20,10 @@ import type {
|
||||
GetRowIdParams,
|
||||
TabToNextCellParams,
|
||||
} from 'ag-grid-community/dist/lib/entities/iCallbackParams';
|
||||
import type { Market, MarketsListData } from '@vegaprotocol/market-list';
|
||||
import { useMarketList } from '@vegaprotocol/market-list';
|
||||
|
||||
export type SimpleMarketsType = SimpleMarkets_markets & {
|
||||
export type MarketWithPercentChange = Market & {
|
||||
percentChange?: number | '-';
|
||||
};
|
||||
|
||||
@ -51,27 +40,9 @@ const SimpleMarketList = () => {
|
||||
const theme = useContext(ThemeContext);
|
||||
const statusesRef = useRef<Record<string, MarketState | ''>>({});
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
CandleSince: subDays(Date.now(), 1).toJSON(),
|
||||
}),
|
||||
[]
|
||||
);
|
||||
const update = useCallback(
|
||||
({ delta }: { delta: SimpleMarketDataSub_marketData }) =>
|
||||
statusesRef.current[delta.market.id] === delta.market.state,
|
||||
[statusesRef]
|
||||
);
|
||||
|
||||
const { data, error, loading } = useDataProvider({
|
||||
dataProvider,
|
||||
update,
|
||||
variables,
|
||||
});
|
||||
const localData: Array<SimpleMarketsType> = useMarketsFilterData(
|
||||
data || [],
|
||||
params
|
||||
);
|
||||
const { data, error, loading } = useMarketList();
|
||||
const localData = useMarketsFilterData(data as MarketsListData, params);
|
||||
|
||||
const handleOnGridReady = useCallback(() => {
|
||||
gridRef.current?.api?.sizeColumnsToFit();
|
||||
@ -79,7 +50,7 @@ const SimpleMarketList = () => {
|
||||
|
||||
useEffect(() => {
|
||||
const statuses: Record<string, MarketState | ''> = {};
|
||||
data?.forEach((market) => {
|
||||
data?.markets?.forEach((market) => {
|
||||
statuses[market.id] = market.state || '';
|
||||
});
|
||||
statusesRef.current = statuses;
|
||||
@ -95,7 +66,7 @@ const SimpleMarketList = () => {
|
||||
const getRowId = useCallback(({ data }: GetRowIdParams) => data.id, []);
|
||||
|
||||
const handleRowClicked = useCallback(
|
||||
({ data }: { data: SimpleMarketsType }) => {
|
||||
({ data }: { data: Market }) => {
|
||||
if (IS_MARKET_TRADABLE(data)) {
|
||||
navigate(`/trading/${data.id}`);
|
||||
}
|
||||
@ -135,7 +106,7 @@ const SimpleMarketList = () => {
|
||||
|
||||
return (
|
||||
<div className="h-full p-4 md:p-6 grid grid-rows-[min-content,1fr]">
|
||||
<SimpleMarketToolbar data={data || []} />
|
||||
<SimpleMarketToolbar data={data?.markets || []} />
|
||||
<AsyncRenderer loading={loading} error={error} data={localData}>
|
||||
<AgGrid
|
||||
className="mb-32 min-h-[300px]"
|
||||
|
@ -2,10 +2,10 @@ import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { MockedProvider } from '@apollo/react-testing';
|
||||
import SimpleMarketPercentChange from './simple-market-percent-change';
|
||||
import type { SimpleMarkets_markets_candles } from './__generated__/SimpleMarkets';
|
||||
import type { Candle } from '@vegaprotocol/market-list';
|
||||
|
||||
describe('SimpleMarketPercentChange should parse proper change', () => {
|
||||
let candles: (SimpleMarkets_markets_candles | null)[] | null;
|
||||
let candles: (Candle | null)[] | null;
|
||||
const setValue = () => undefined;
|
||||
it('empty array', () => {
|
||||
candles = [];
|
||||
@ -34,11 +34,7 @@ describe('SimpleMarketPercentChange should parse proper change', () => {
|
||||
expect(screen.getByText('-')).toBeInTheDocument();
|
||||
});
|
||||
it('an appreciated one', () => {
|
||||
candles = [
|
||||
{ open: '50' } as SimpleMarkets_markets_candles,
|
||||
{ close: '100' } as SimpleMarkets_markets_candles,
|
||||
null,
|
||||
];
|
||||
candles = [{ open: '50' } as Candle, { close: '100' } as Candle, null];
|
||||
render(
|
||||
<MockedProvider>
|
||||
<SimpleMarketPercentChange
|
||||
@ -54,11 +50,7 @@ describe('SimpleMarketPercentChange should parse proper change', () => {
|
||||
);
|
||||
});
|
||||
it('a depreciated one', () => {
|
||||
candles = [
|
||||
{ open: '100' } as SimpleMarkets_markets_candles,
|
||||
{ close: '50' } as SimpleMarkets_markets_candles,
|
||||
null,
|
||||
];
|
||||
candles = [{ open: '100' } as Candle, { close: '50' } as Candle, null];
|
||||
render(
|
||||
<MockedProvider>
|
||||
<SimpleMarketPercentChange
|
||||
|
@ -1,26 +1,20 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { InView } from 'react-intersection-observer';
|
||||
import { useSubscription } from '@apollo/client';
|
||||
import type { SimpleMarkets_markets_candles } from './__generated__/SimpleMarkets';
|
||||
import type {
|
||||
CandleLive,
|
||||
CandleLiveVariables,
|
||||
} from './__generated__/CandleLive';
|
||||
import { CANDLE_SUB } from './data-provider';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import type { Candle } from '@vegaprotocol/market-list';
|
||||
import { marketCandlesProvider } from '@vegaprotocol/market-list';
|
||||
import { Interval } from '@vegaprotocol/types';
|
||||
|
||||
interface Props {
|
||||
candles: (SimpleMarkets_markets_candles | null)[] | null;
|
||||
candles: (Candle | null)[] | null;
|
||||
marketId: string;
|
||||
setValue: (arg: unknown) => void;
|
||||
}
|
||||
|
||||
const EMPTY_VALUE = ' - ';
|
||||
|
||||
const getChange = (
|
||||
candles: (SimpleMarkets_markets_candles | null)[] | null,
|
||||
lastClose?: string
|
||||
) => {
|
||||
const getChange = (candles: (Candle | null)[] | null, lastClose?: string) => {
|
||||
if (candles) {
|
||||
const first = parseInt(candles.find((item) => item?.open)?.open || '-1');
|
||||
const last =
|
||||
@ -74,11 +68,14 @@ const SimpleMarketPercentChangeWrapper = (props: Props) => {
|
||||
};
|
||||
|
||||
const SimpleMarketPercentChange = ({ candles, marketId, setValue }: Props) => {
|
||||
const { data: { candles: { close = undefined } = {} } = {} } =
|
||||
useSubscription<CandleLive, CandleLiveVariables>(CANDLE_SUB, {
|
||||
variables: { marketId },
|
||||
});
|
||||
const change = getChange(candles, close);
|
||||
const { data } = useDataProvider({
|
||||
dataProvider: marketCandlesProvider,
|
||||
variables: { marketId, interval: Interval.INTERVAL_I1D },
|
||||
});
|
||||
|
||||
const close = data?.map((m) => m.close);
|
||||
|
||||
const change = getChange(candles, close?.[0]);
|
||||
const colorClasses = getClassColor(change);
|
||||
useEffect(() => {
|
||||
const value = parseFloat(change);
|
||||
|
@ -1,36 +1,36 @@
|
||||
import React from 'react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import type { MarketNames_markets } from '@vegaprotocol/deal-ticket';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import MarketNameRenderer from './simple-market-renderer';
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
|
||||
describe('SimpleMarketRenderer', () => {
|
||||
const market = {
|
||||
id: 'marketId',
|
||||
id: 'MARKET_A',
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'Market code',
|
||||
name: 'Market Name',
|
||||
code: 'MARKET_A_CODE',
|
||||
name: 'MARKET_A_NAME',
|
||||
product: {
|
||||
quoteName: 'Quote name',
|
||||
quoteName: 'MARKET_A_QUOTE_NAME',
|
||||
},
|
||||
metadata: {
|
||||
tags: null,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as MarketNames_markets;
|
||||
} as Market;
|
||||
|
||||
it('should properly render not mobile', () => {
|
||||
render(<MarketNameRenderer market={market} isMobile={false} />);
|
||||
expect(screen.getByText('Market Name')).toBeInTheDocument();
|
||||
expect(screen.getByText('Quote name')).toBeInTheDocument();
|
||||
expect(screen.getByText('MARKET_A_NAME')).toBeInTheDocument();
|
||||
expect(screen.getByText('MARKET_A_QUOTE_NAME')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should properly render mobile', () => {
|
||||
render(<MarketNameRenderer market={market} isMobile={true} />);
|
||||
expect(screen.getByText('Market code')).toBeInTheDocument();
|
||||
expect(screen.getByText('Quote name')).toBeInTheDocument();
|
||||
expect(screen.getByText('MARKET_A_CODE')).toBeInTheDocument();
|
||||
expect(screen.getByText('MARKET_A_QUOTE_NAME')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
@ -1,10 +1,9 @@
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import type { MarketNames_markets } from '@vegaprotocol/deal-ticket';
|
||||
import SimpleMarketExpires from './simple-market-expires';
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
|
||||
interface Props {
|
||||
market: MarketNames_markets;
|
||||
market: Market;
|
||||
isMobile?: boolean;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { useNavigate, useParams, Link } from 'react-router-dom';
|
||||
import {
|
||||
@ -17,10 +17,10 @@ import {
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import useMarketFiltersData from '../../hooks/use-markets-filter';
|
||||
import { STATES_FILTER } from './constants';
|
||||
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
|
||||
import type { Markets_marketsConnection_edges_node } from '@vegaprotocol/market-list';
|
||||
|
||||
interface Props {
|
||||
data: SimpleMarkets_markets[];
|
||||
data: Markets_marketsConnection_edges_node[];
|
||||
}
|
||||
|
||||
const SimpleMarketToolbar = ({ data }: Props) => {
|
||||
@ -98,7 +98,7 @@ const SimpleMarketToolbar = ({ data }: Props) => {
|
||||
</Link>
|
||||
</li>
|
||||
{products.map((product, i) => (
|
||||
<li key={product} className="mx-2 whitespace-nowrap">
|
||||
<li key={`${product}-${i}`} className="mx-2 whitespace-nowrap">
|
||||
<Link
|
||||
to={`/markets/${
|
||||
params.state || MarketState.STATE_ACTIVE
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { SimpleMarkets_markets } from '../components/simple-market-list/__generated__/SimpleMarkets';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
|
||||
export const DATE_FORMAT = 'dd MMMM yyyy HH:mm';
|
||||
export const EXPIRE_DATE_FORMAT = 'MMM dd';
|
||||
@ -9,7 +9,7 @@ export const TRADABLE_STATES = {
|
||||
[MarketState.STATE_ACTIVE]: true,
|
||||
};
|
||||
|
||||
export const IS_MARKET_TRADABLE = (market: SimpleMarkets_markets) =>
|
||||
export const IS_MARKET_TRADABLE = (market: Market) =>
|
||||
Boolean((market.state ?? '') in TRADABLE_STATES && market?.id);
|
||||
|
||||
export const MARKET_STATES_MAP: Record<MarketState | '', string> = {
|
||||
|
@ -103,7 +103,7 @@ export interface PartyMarketData_party {
|
||||
/**
|
||||
* Margin levels for a market
|
||||
*/
|
||||
marginsConnection: PartyMarketData_party_marginsConnection;
|
||||
marginsConnection: PartyMarketData_party_marginsConnection | null;
|
||||
}
|
||||
|
||||
export interface PartyMarketData {
|
||||
|
@ -91,7 +91,7 @@ export interface MarketPositions_party {
|
||||
/**
|
||||
* Trading positions relating to a party
|
||||
*/
|
||||
positionsConnection: MarketPositions_party_positionsConnection;
|
||||
positionsConnection: MarketPositions_party_positionsConnection | null;
|
||||
}
|
||||
|
||||
export interface MarketPositions {
|
||||
|
@ -8,7 +8,7 @@ export type MarketPositionsQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type MarketPositionsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, accounts?: Array<{ __typename?: 'Account', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', decimals: number }, market?: { __typename?: 'Market', id: string } | null }> | null, positionsConnection: { __typename?: 'PositionConnection', edges?: Array<{ __typename?: 'PositionEdge', node: { __typename?: 'Position', openVolume: string, market: { __typename?: 'Market', id: string } } }> | null } } | null };
|
||||
export type MarketPositionsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, accounts?: Array<{ __typename?: 'Account', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', decimals: number }, market?: { __typename?: 'Market', id: string } | null }> | null, positionsConnection?: { __typename?: 'PositionConnection', edges?: Array<{ __typename?: 'PositionEdge', node: { __typename?: 'Position', openVolume: string, market: { __typename?: 'Market', id: string } } }> | null } | null } | null };
|
||||
|
||||
|
||||
export const MarketPositionsDocument = gql`
|
||||
|
@ -8,7 +8,7 @@ export type PartyMarketDataQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type PartyMarketDataQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, accounts?: Array<{ __typename?: 'Account', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string, decimals: number }, market?: { __typename?: 'Market', id: string } | null }> | null, marginsConnection: { __typename?: 'MarginConnection', edges?: Array<{ __typename?: 'MarginEdge', node: { __typename?: 'MarginLevels', initialLevel: string, maintenanceLevel: string, searchLevel: string, market: { __typename?: 'Market', id: string } } }> | null } } | null };
|
||||
export type PartyMarketDataQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, accounts?: Array<{ __typename?: 'Account', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string, decimals: number }, market?: { __typename?: 'Market', id: string } | null }> | null, marginsConnection?: { __typename?: 'MarginConnection', edges?: Array<{ __typename?: 'MarginEdge', node: { __typename?: 'MarginLevels', initialLevel: string, maintenanceLevel: string, searchLevel: string, market: { __typename?: 'Market', id: string } } }> | null } | null } | null };
|
||||
|
||||
|
||||
export const PartyMarketDataDocument = gql`
|
||||
|
@ -1,14 +1,13 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import type { SimpleMarkets_markets } from '../components/simple-market-list/__generated__/SimpleMarkets';
|
||||
import MarketNameRenderer from '../components/simple-market-list/simple-market-renderer';
|
||||
import SimpleMarketPercentChange from '../components/simple-market-list/simple-market-percent-change';
|
||||
import { Icon } from '@vegaprotocol/ui-toolkit';
|
||||
import type { ValueSetterParams } from 'ag-grid-community';
|
||||
import type { SimpleMarketsType } from '../components/simple-market-list/simple-market-list';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { IS_MARKET_TRADABLE, MARKET_STATES_MAP } from '../constants';
|
||||
import type { Candle, Market } from '@vegaprotocol/market-list';
|
||||
|
||||
interface Props {
|
||||
isMobile: boolean;
|
||||
@ -24,7 +23,7 @@ const useColumnDefinitions = ({ isMobile }: Props) => {
|
||||
minWidth: isMobile ? 160 : 350,
|
||||
field: 'tradableInstrument.instrument.name',
|
||||
cellClass: 'overflow-visible',
|
||||
cellRenderer: ({ data }: { data: SimpleMarketsType }) => (
|
||||
cellRenderer: ({ data }: { data: Market }) => (
|
||||
<MarketNameRenderer market={data} isMobile={isMobile} />
|
||||
),
|
||||
},
|
||||
@ -35,7 +34,7 @@ const useColumnDefinitions = ({ isMobile }: Props) => {
|
||||
minWidth: isMobile ? 50 : 80,
|
||||
cellClass: 'uppercase flex h-full items-center',
|
||||
field: 'tradableInstrument.instrument.product.settlementAsset.symbol',
|
||||
cellRenderer: ({ data }: { data: SimpleMarketsType }) => (
|
||||
cellRenderer: ({ data }: { data: Market }) => (
|
||||
<div
|
||||
className="grid h-full items-center text-center"
|
||||
title={
|
||||
@ -70,7 +69,7 @@ const useColumnDefinitions = ({ isMobile }: Props) => {
|
||||
data,
|
||||
setValue,
|
||||
}: {
|
||||
data: SimpleMarketsType;
|
||||
data: { id: string; candles: Candle[] };
|
||||
setValue: (arg: unknown) => void;
|
||||
}) => (
|
||||
<SimpleMarketPercentChange
|
||||
@ -96,7 +95,7 @@ const useColumnDefinitions = ({ isMobile }: Props) => {
|
||||
field: 'state',
|
||||
headerClass: 'uppercase',
|
||||
minWidth: 100,
|
||||
cellRenderer: ({ data }: { data: SimpleMarkets_markets }) => (
|
||||
cellRenderer: ({ data }: { data: Market }) => (
|
||||
<div className="uppercase flex h-full items-center justify-center">
|
||||
<div className="border text-center px-2 md:px-6 leading-4 md:leading-6">
|
||||
{MARKET_STATES_MAP[data.state || '']}
|
||||
@ -110,7 +109,7 @@ const useColumnDefinitions = ({ isMobile }: Props) => {
|
||||
headerClass: 'uppercase',
|
||||
sortable: false,
|
||||
width: isMobile ? 35 : 100,
|
||||
cellRenderer: ({ data }: { data: SimpleMarkets_markets }) => (
|
||||
cellRenderer: ({ data }: { data: Market }) => (
|
||||
<div className="h-full flex h-full items-center justify-end">
|
||||
<div className="uppercase text-center pr-2">
|
||||
{!isMobile && t('Trade')}
|
||||
|
@ -1,37 +1,52 @@
|
||||
import type { SimpleMarkets_markets } from '../components/simple-market-list/__generated__/SimpleMarkets';
|
||||
import { useMemo } from 'react';
|
||||
import type { RouterParams } from '../components/simple-market-list/simple-market-list';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import type { MarketsListData } from '@vegaprotocol/market-list';
|
||||
|
||||
const useMarketsFilterData = (
|
||||
data: SimpleMarkets_markets[] = [],
|
||||
params: RouterParams
|
||||
) => {
|
||||
return data.filter((item) => {
|
||||
if (
|
||||
params.product &&
|
||||
params.product !== item.tradableInstrument.instrument.product.__typename
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
params.asset &&
|
||||
params.asset !== 'all' &&
|
||||
params.asset !==
|
||||
item.tradableInstrument.instrument.product.settlementAsset.symbol
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const state =
|
||||
params.state === 'all'
|
||||
? ''
|
||||
: params.state
|
||||
? params.state
|
||||
: MarketState.STATE_ACTIVE;
|
||||
if (state && state !== item.state) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
const useMarketsFilterData = (data: MarketsListData, params: RouterParams) => {
|
||||
return useMemo(() => {
|
||||
const markets =
|
||||
data?.markets?.filter((item) => {
|
||||
if (
|
||||
params.product &&
|
||||
params.product !==
|
||||
item.tradableInstrument.instrument.product.__typename
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
params.asset &&
|
||||
params.asset !== 'all' &&
|
||||
params.asset !==
|
||||
item.tradableInstrument.instrument.product.settlementAsset.symbol
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const state =
|
||||
params.state === 'all'
|
||||
? ''
|
||||
: params.state
|
||||
? params.state
|
||||
: MarketState.STATE_ACTIVE;
|
||||
if (state && state !== item.state) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}) || [];
|
||||
|
||||
return markets.map((market) => ({
|
||||
...market,
|
||||
candles: (data?.marketsCandles || [])
|
||||
.filter((c) => c.marketId === market.id)
|
||||
.map((c) => c.candles),
|
||||
}));
|
||||
}, [
|
||||
data?.marketsCandles,
|
||||
data?.markets,
|
||||
params.product,
|
||||
params.asset,
|
||||
params.state,
|
||||
]);
|
||||
};
|
||||
|
||||
export default useMarketsFilterData;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
import { useEffect, useState } from 'react';
|
||||
import type { SimpleMarkets_markets } from '../components/simple-market-list/__generated__/SimpleMarkets';
|
||||
|
||||
const useMarketFilters = (data: SimpleMarkets_markets[]) => {
|
||||
const useMarketFilters = (data: Market[]) => {
|
||||
const [products, setProducts] = useState<string[]>([]);
|
||||
const [assetsPerProduct, setAssetsPerProduct] = useState<
|
||||
Record<string, string[]>
|
||||
|
@ -74,7 +74,7 @@ const useOrderCloseOut = ({ order, market, partyData }: Props): string => {
|
||||
|
||||
const marginMaintenanceLevel = new BigNumber(
|
||||
addDecimal(
|
||||
data?.party?.marginsConnection.edges?.find(
|
||||
data?.party?.marginsConnection?.edges?.find(
|
||||
(nodes) => nodes.node.market.id === market.id
|
||||
)?.node.maintenanceLevel || 0,
|
||||
market.decimalPlaces
|
||||
|
@ -38,6 +38,9 @@ export function createClient(base?: string) {
|
||||
Node: {
|
||||
keyFields: false,
|
||||
},
|
||||
Instrument: {
|
||||
keyFields: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -96,5 +96,5 @@ export interface AssetsQuery {
|
||||
/**
|
||||
* The list of all assets in use in the Vega network or the specified asset if ID is provided
|
||||
*/
|
||||
assetsConnection: AssetsQuery_assetsConnection;
|
||||
assetsConnection: AssetsQuery_assetsConnection | null;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ const defaultOptions = {} as const;
|
||||
export type AssetsQueryQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type AssetsQueryQuery = { __typename?: 'Query', assetsConnection: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string }, infrastructureFeeAccount: { __typename?: 'Account', type: Types.AccountType, balance: string, market?: { __typename?: 'Market', id: string } | null } } } | null> | null } };
|
||||
export type AssetsQueryQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string }, infrastructureFeeAccount: { __typename?: 'Account', type: Types.AccountType, balance: string, market?: { __typename?: 'Market', id: string } | null } } } | null> | null } | null };
|
||||
|
||||
|
||||
export const AssetsQueryDocument = gql`
|
||||
|
@ -265,7 +265,7 @@ export interface ProposalsQuery_proposalsConnection_edges_node {
|
||||
*/
|
||||
datetime: string;
|
||||
/**
|
||||
* Reason for the proposal to be rejected by the core
|
||||
* Why the proposal was rejected by the core
|
||||
*/
|
||||
rejectionReason: ProposalRejectionReason | null;
|
||||
/**
|
||||
@ -302,5 +302,5 @@ export interface ProposalsQuery {
|
||||
/**
|
||||
* All governance proposals in the Vega network
|
||||
*/
|
||||
proposalsConnection: ProposalsQuery_proposalsConnection;
|
||||
proposalsConnection: ProposalsQuery_proposalsConnection | null;
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
query MarketsQuery {
|
||||
markets {
|
||||
id
|
||||
name
|
||||
fees {
|
||||
factors {
|
||||
makerFee
|
||||
|
@ -6,14 +6,13 @@ const defaultOptions = {} as const;
|
||||
export type MarketsQueryQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type MarketsQueryQuery = { __typename?: 'Query', markets?: Array<{ __typename?: 'Market', id: string, name: string, decimalPlaces: number, tradingMode: Types.MarketTradingMode, state: Types.MarketState, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, id: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', settlementAsset: { __typename?: 'Asset', id: string, name: string, decimals: number, globalRewardPoolAccount?: { __typename?: 'Account', balance: string } | null } } }, riskModel: { __typename?: 'LogNormalRiskModel', tau: number, riskAversionParameter: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } }, marginCalculator?: { __typename?: 'MarginCalculator', scalingFactors: { __typename?: 'ScalingFactors', searchLevel: number, initialMargin: number, collateralRelease: number } } | null }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: number, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, proposal?: { __typename?: 'Proposal', id?: string | null } | null, accounts?: Array<{ __typename?: 'Account', balance: string, type: Types.AccountType, asset: { __typename?: 'Asset', id: string, name: string } }> | null, data?: { __typename?: 'MarketData', markPrice: string, bestBidPrice: string, bestBidVolume: string, bestOfferPrice: string, bestOfferVolume: string, bestStaticBidPrice: string, bestStaticBidVolume: string, bestStaticOfferPrice: string, bestStaticOfferVolume: string, midPrice: string, staticMidPrice: string, timestamp: string, openInterest: string, auctionEnd?: string | null, auctionStart?: string | null, indicativePrice: string, indicativeVolume: string, trigger: Types.AuctionTrigger, extensionTrigger: Types.AuctionTrigger, targetStake?: string | null, suppliedStake?: string | null, marketValueProxy: string, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', auctionExtensionSecs: number, probability: number } }> | null, liquidityProviderFeeShare?: Array<{ __typename?: 'LiquidityProviderFeeShare', equityLikeShare: string, averageEntryValuation: string, party: { __typename?: 'Party', id: string } }> | null } | null }> | null };
|
||||
export type MarketsQueryQuery = { __typename?: 'Query', markets?: Array<{ __typename?: 'Market', id: string, decimalPlaces: number, tradingMode: Types.MarketTradingMode, state: Types.MarketState, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, id: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', settlementAsset: { __typename?: 'Asset', id: string, name: string, decimals: number, globalRewardPoolAccount?: { __typename?: 'Account', balance: string } | null } } }, riskModel: { __typename?: 'LogNormalRiskModel', tau: number, riskAversionParameter: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } }, marginCalculator?: { __typename?: 'MarginCalculator', scalingFactors: { __typename?: 'ScalingFactors', searchLevel: number, initialMargin: number, collateralRelease: number } } | null }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: number, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, proposal?: { __typename?: 'Proposal', id?: string | null } | null, accounts?: Array<{ __typename?: 'Account', balance: string, type: Types.AccountType, asset: { __typename?: 'Asset', id: string, name: string } }> | null, data?: { __typename?: 'MarketData', markPrice: string, bestBidPrice: string, bestBidVolume: string, bestOfferPrice: string, bestOfferVolume: string, bestStaticBidPrice: string, bestStaticBidVolume: string, bestStaticOfferPrice: string, bestStaticOfferVolume: string, midPrice: string, staticMidPrice: string, timestamp: string, openInterest: string, auctionEnd?: string | null, auctionStart?: string | null, indicativePrice: string, indicativeVolume: string, trigger: Types.AuctionTrigger, extensionTrigger: Types.AuctionTrigger, targetStake?: string | null, suppliedStake?: string | null, marketValueProxy: string, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', auctionExtensionSecs: number, probability: number } }> | null, liquidityProviderFeeShare?: Array<{ __typename?: 'LiquidityProviderFeeShare', equityLikeShare: string, averageEntryValuation: string, party: { __typename?: 'Party', id: string } }> | null } | null }> | null };
|
||||
|
||||
|
||||
export const MarketsQueryDocument = gql`
|
||||
query MarketsQuery {
|
||||
markets {
|
||||
id
|
||||
name
|
||||
fees {
|
||||
factors {
|
||||
makerFee
|
||||
|
@ -1,22 +1,26 @@
|
||||
query OracleSpecs {
|
||||
oracleSpecs {
|
||||
status
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
pubKeys
|
||||
filters {
|
||||
key {
|
||||
name
|
||||
type
|
||||
oracleSpecsConnection {
|
||||
edges {
|
||||
node {
|
||||
status
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
pubKeys
|
||||
filters {
|
||||
key {
|
||||
name
|
||||
type
|
||||
}
|
||||
conditions {
|
||||
value
|
||||
operator
|
||||
}
|
||||
}
|
||||
data {
|
||||
pubKeys
|
||||
}
|
||||
}
|
||||
conditions {
|
||||
value
|
||||
operator
|
||||
}
|
||||
}
|
||||
data {
|
||||
pubKeys
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,29 +6,33 @@ const defaultOptions = {} as const;
|
||||
export type OracleSpecsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type OracleSpecsQuery = { __typename?: 'Query', oracleSpecs?: Array<{ __typename?: 'OracleSpec', status: Types.OracleSpecStatus, id: string, createdAt: string, updatedAt?: string | null, pubKeys?: Array<string> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null, data: Array<{ __typename?: 'OracleData', pubKeys?: Array<string> | null }> }> | null };
|
||||
export type OracleSpecsQuery = { __typename?: 'Query', oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', status: Types.OracleSpecStatus, id: string, createdAt: string, updatedAt?: string | null, pubKeys?: Array<string> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null, data: Array<{ __typename?: 'OracleData', pubKeys?: Array<string> | null }> } } | null> | null } | null };
|
||||
|
||||
|
||||
export const OracleSpecsDocument = gql`
|
||||
query OracleSpecs {
|
||||
oracleSpecs {
|
||||
status
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
pubKeys
|
||||
filters {
|
||||
key {
|
||||
name
|
||||
type
|
||||
oracleSpecsConnection {
|
||||
edges {
|
||||
node {
|
||||
status
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
pubKeys
|
||||
filters {
|
||||
key {
|
||||
name
|
||||
type
|
||||
}
|
||||
conditions {
|
||||
value
|
||||
operator
|
||||
}
|
||||
}
|
||||
data {
|
||||
pubKeys
|
||||
}
|
||||
}
|
||||
conditions {
|
||||
value
|
||||
operator
|
||||
}
|
||||
}
|
||||
data {
|
||||
pubKeys
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,5 @@ query NodesQuery {
|
||||
online
|
||||
}
|
||||
status
|
||||
name
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,6 @@ export const NodesQueryDocument = gql`
|
||||
online
|
||||
}
|
||||
status
|
||||
name
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -48,7 +48,7 @@ export interface ProposalFields_terms_change_NewMarket_instrument_futureProduct_
|
||||
export interface ProposalFields_terms_change_NewMarket_instrument_futureProduct {
|
||||
__typename: "FutureProduct";
|
||||
/**
|
||||
* Product asset ID
|
||||
* Product asset
|
||||
*/
|
||||
settlementAsset: ProposalFields_terms_change_NewMarket_instrument_futureProduct_settlementAsset;
|
||||
}
|
||||
@ -293,7 +293,7 @@ export interface ProposalFields {
|
||||
*/
|
||||
datetime: string;
|
||||
/**
|
||||
* Reason for the proposal to be rejected by the core
|
||||
* Why the proposal was rejected by the core
|
||||
*/
|
||||
rejectionReason: ProposalRejectionReason | null;
|
||||
/**
|
||||
|
@ -10,7 +10,7 @@ export type ProposalQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ProposalQuery = { __typename?: 'Query', proposal: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: string, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: string, enactmentDatetime?: string | null, change: { __typename: 'NewAsset', name: string, symbol: string, source: { __typename: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename: 'ERC20', contractAddress: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', decimalPlaces: number, metadata?: Array<string> | null, instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null } } } };
|
||||
export type ProposalQuery = { __typename?: 'Query', proposal?: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: string, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: string, enactmentDatetime?: string | null, change: { __typename: 'NewAsset', name: string, symbol: string, source: { __typename: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename: 'ERC20', contractAddress: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', decimalPlaces: number, metadata?: Array<string> | null, instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null } } } | null };
|
||||
|
||||
export type ProposalsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
@ -48,7 +48,7 @@ export interface Proposal_proposal_terms_change_NewMarket_instrument_futureProdu
|
||||
export interface Proposal_proposal_terms_change_NewMarket_instrument_futureProduct {
|
||||
__typename: "FutureProduct";
|
||||
/**
|
||||
* Product asset ID
|
||||
* Product asset
|
||||
*/
|
||||
settlementAsset: Proposal_proposal_terms_change_NewMarket_instrument_futureProduct_settlementAsset;
|
||||
}
|
||||
@ -293,7 +293,7 @@ export interface Proposal_proposal {
|
||||
*/
|
||||
datetime: string;
|
||||
/**
|
||||
* Reason for the proposal to be rejected by the core
|
||||
* Why the proposal was rejected by the core
|
||||
*/
|
||||
rejectionReason: ProposalRejectionReason | null;
|
||||
/**
|
||||
@ -318,7 +318,7 @@ export interface Proposal {
|
||||
/**
|
||||
* A governance proposal located by either its ID or reference. If both are set, ID is used.
|
||||
*/
|
||||
proposal: Proposal_proposal;
|
||||
proposal: Proposal_proposal | null;
|
||||
}
|
||||
|
||||
export interface ProposalVariables {
|
||||
|
@ -37,7 +37,7 @@ export const ProposalContainer = () => {
|
||||
|
||||
return (
|
||||
<AsyncRenderer loading={loading} error={error} data={data}>
|
||||
{data && <Proposal proposal={data.proposal} />}
|
||||
{data && data.proposal && <Proposal proposal={data.proposal} />}
|
||||
</AsyncRenderer>
|
||||
);
|
||||
};
|
||||
|
@ -48,7 +48,7 @@ export interface Proposals_proposalsConnection_edges_node_terms_change_NewMarket
|
||||
export interface Proposals_proposalsConnection_edges_node_terms_change_NewMarket_instrument_futureProduct {
|
||||
__typename: "FutureProduct";
|
||||
/**
|
||||
* Product asset ID
|
||||
* Product asset
|
||||
*/
|
||||
settlementAsset: Proposals_proposalsConnection_edges_node_terms_change_NewMarket_instrument_futureProduct_settlementAsset;
|
||||
}
|
||||
@ -293,7 +293,7 @@ export interface Proposals_proposalsConnection_edges_node {
|
||||
*/
|
||||
datetime: string;
|
||||
/**
|
||||
* Reason for the proposal to be rejected by the core
|
||||
* Why the proposal was rejected by the core
|
||||
*/
|
||||
rejectionReason: ProposalRejectionReason | null;
|
||||
/**
|
||||
@ -334,5 +334,5 @@ export interface Proposals {
|
||||
/**
|
||||
* All governance proposals in the Vega network
|
||||
*/
|
||||
proposalsConnection: Proposals_proposalsConnection;
|
||||
proposalsConnection: Proposals_proposalsConnection | null;
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ beforeEach(() => {
|
||||
|
||||
describe('accounts', () => {
|
||||
it('renders accounts', () => {
|
||||
const tradingAccountRowId = '[row-id="ACCOUNT_TYPE_GENERAL-tEURO-null"]';
|
||||
const tradingAccountRowId = '[row-id="ACCOUNT_TYPE_GENERAL-asset-id-null"]';
|
||||
cy.getByTestId('Collateral').click();
|
||||
cy.getByTestId('tab-accounts').contains('Please connect Vega wallet');
|
||||
|
||||
|
@ -1,76 +1,14 @@
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import { generateFill, generateFills } from '../support/mocks/generate-fills';
|
||||
import { Side } from '@vegaprotocol/types';
|
||||
import { generateFills } from '../support/mocks/generate-fills';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import { connectVegaWallet } from '../support/vega-wallet';
|
||||
import { mockTradingPage } from '../support/trading';
|
||||
import { generateNetworkParameters } from '../support/mocks/generate-network-parameters';
|
||||
|
||||
const fills = [
|
||||
generateFill({
|
||||
buyer: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
},
|
||||
}),
|
||||
generateFill({
|
||||
id: '1',
|
||||
seller: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
},
|
||||
aggressor: Side.SIDE_SELL,
|
||||
buyerFee: {
|
||||
infrastructureFee: '5000',
|
||||
},
|
||||
market: {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'Apples Daily v3',
|
||||
},
|
||||
},
|
||||
positionDecimalPlaces: 2,
|
||||
},
|
||||
}),
|
||||
generateFill({
|
||||
id: '2',
|
||||
seller: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
},
|
||||
aggressor: Side.SIDE_BUY,
|
||||
}),
|
||||
generateFill({
|
||||
id: '3',
|
||||
aggressor: Side.SIDE_SELL,
|
||||
market: {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'ETHBTC Quarterly (30 Jun 2022)',
|
||||
},
|
||||
},
|
||||
},
|
||||
buyer: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
},
|
||||
}),
|
||||
];
|
||||
const result = generateFills({
|
||||
party: {
|
||||
tradesConnection: {
|
||||
edges: fills.map((f, i) => {
|
||||
return {
|
||||
__typename: 'TradeEdge',
|
||||
node: f,
|
||||
cursor: i.toString(),
|
||||
};
|
||||
}),
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
describe('fills', () => {
|
||||
beforeEach(() => {
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'Fills', result);
|
||||
aliasQuery(req, 'NetworkParamsQuery', generateNetworkParameters());
|
||||
mockTradingPage(req, MarketState.STATE_ACTIVE);
|
||||
aliasQuery(req, 'Fills', generateFills());
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -86,11 +86,11 @@ describe('orders', () => {
|
||||
|
||||
it('orders are sorted by most recent order', () => {
|
||||
const expectedOrderList = [
|
||||
'AAVEDAI.MF21',
|
||||
'TSLA.QM21',
|
||||
'BTCUSD.MF21',
|
||||
'UNIDAI.MF21',
|
||||
'UNIDAI.MF21',
|
||||
'SOLUSD',
|
||||
'AAPL.MF21',
|
||||
'ETHBTC.QM21',
|
||||
'ETHBTC.QM21',
|
||||
];
|
||||
|
||||
cy.getByTestId('tab-orders')
|
||||
|
@ -23,12 +23,7 @@ export const generateFills = (override?: PartialDeep<Fills>): Fills => {
|
||||
infrastructureFee: '5000',
|
||||
},
|
||||
market: {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'Apples Daily v3',
|
||||
},
|
||||
},
|
||||
positionDecimalPlaces: 2,
|
||||
id: 'market-1',
|
||||
},
|
||||
}),
|
||||
generateFill({
|
||||
@ -42,11 +37,7 @@ export const generateFills = (override?: PartialDeep<Fills>): Fills => {
|
||||
id: '3',
|
||||
aggressor: Side.SIDE_SELL,
|
||||
market: {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'ETHBTC Quarterly (30 Jun 2022)',
|
||||
},
|
||||
},
|
||||
id: 'market-2',
|
||||
},
|
||||
buyer: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
@ -115,27 +106,7 @@ export const generateFill = (
|
||||
},
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'market-id',
|
||||
positionDecimalPlaces: 0,
|
||||
decimalPlaces: 5,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
__typename: 'Instrument',
|
||||
id: 'instrument-id',
|
||||
code: 'instrument-code',
|
||||
name: 'UNIDAI Monthly (30 Jun 2022)',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
settlementAsset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id',
|
||||
symbol: 'SYM',
|
||||
decimals: 18,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
id: 'market-0',
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -71,13 +71,6 @@ export const generateMarketInfoQuery = (
|
||||
],
|
||||
},
|
||||
},
|
||||
riskFactors: {
|
||||
__typename: 'RiskFactor',
|
||||
market:
|
||||
'54b78c1b877e106842ae156332ccec740ad98d6bad43143ac6a029501dd7c6e0',
|
||||
short: '0.008571790367285281',
|
||||
long: '0.008508132993273576',
|
||||
},
|
||||
data: {
|
||||
__typename: 'MarketData',
|
||||
market: {
|
||||
@ -120,7 +113,7 @@ export const generateMarketInfoQuery = (
|
||||
},
|
||||
__typename: 'LiquidityMonitoringParameters',
|
||||
},
|
||||
candles: [],
|
||||
candlesConnection: null,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
|
@ -18,7 +18,7 @@ export const generateMarket = (override?: PartialDeep<Market>): Market => {
|
||||
positionDecimalPlaces: 0,
|
||||
data: {
|
||||
market: {
|
||||
id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35',
|
||||
id: 'market-0',
|
||||
__typename: 'Market',
|
||||
},
|
||||
auctionStart: '2022-08-12T11:13:47.611014117Z',
|
||||
@ -75,20 +75,29 @@ export const generateMarket = (override?: PartialDeep<Market>): Market => {
|
||||
close: null,
|
||||
__typename: 'MarketTimestamps',
|
||||
},
|
||||
candles: [
|
||||
{
|
||||
open: '2095312844',
|
||||
close: '2090090607',
|
||||
volume: '4847',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
{
|
||||
open: '2090090000',
|
||||
close: '2090090607',
|
||||
volume: '4847',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
],
|
||||
candlesConnection: {
|
||||
__typename: 'CandleDataConnection',
|
||||
edges: [
|
||||
{
|
||||
__typename: 'CandleEdge',
|
||||
node: {
|
||||
open: '2095312844',
|
||||
close: '2090090607',
|
||||
volume: '4847',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'CandleEdge',
|
||||
node: {
|
||||
open: '2090090000',
|
||||
close: '2090090607',
|
||||
volume: '4847',
|
||||
__typename: 'Candle',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
|
@ -48,8 +48,10 @@ export const generateMarkets = (override?: PartialDeep<Markets>): Markets => {
|
||||
product: {
|
||||
settlementAsset: {
|
||||
symbol: 'tDAI',
|
||||
decimals: 5,
|
||||
__typename: 'Asset',
|
||||
},
|
||||
quoteName: 'DAI',
|
||||
__typename: 'Future',
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
@ -90,8 +92,10 @@ export const generateMarkets = (override?: PartialDeep<Markets>): Markets => {
|
||||
product: {
|
||||
settlementAsset: {
|
||||
symbol: 'XYZalpha',
|
||||
decimals: 5,
|
||||
__typename: 'Asset',
|
||||
},
|
||||
quoteName: 'USD',
|
||||
__typename: 'Future',
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
@ -132,8 +136,10 @@ export const generateMarkets = (override?: PartialDeep<Markets>): Markets => {
|
||||
product: {
|
||||
settlementAsset: {
|
||||
symbol: 'tUSDC',
|
||||
decimals: 5,
|
||||
__typename: 'Asset',
|
||||
},
|
||||
quoteName: 'USDC',
|
||||
__typename: 'Future',
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
@ -174,8 +180,10 @@ export const generateMarkets = (override?: PartialDeep<Markets>): Markets => {
|
||||
product: {
|
||||
settlementAsset: {
|
||||
symbol: 'tBTC',
|
||||
decimals: 5,
|
||||
__typename: 'Asset',
|
||||
},
|
||||
quoteName: 'BTC',
|
||||
__typename: 'Future',
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
@ -311,7 +319,7 @@ export const generateMarketsCandles = (
|
||||
{
|
||||
__typename: 'CandleEdge',
|
||||
node: {
|
||||
__typename: 'CandleNode',
|
||||
__typename: 'Candle',
|
||||
open: '100',
|
||||
close: '100',
|
||||
high: '110',
|
||||
@ -331,7 +339,7 @@ export const generateMarketsCandles = (
|
||||
{
|
||||
__typename: 'CandleEdge',
|
||||
node: {
|
||||
__typename: 'CandleNode',
|
||||
__typename: 'Candle',
|
||||
open: '100',
|
||||
close: '100',
|
||||
high: '110',
|
||||
@ -351,7 +359,7 @@ export const generateMarketsCandles = (
|
||||
{
|
||||
__typename: 'CandleEdge',
|
||||
node: {
|
||||
__typename: 'CandleNode',
|
||||
__typename: 'Candle',
|
||||
open: '100',
|
||||
close: '100',
|
||||
high: '110',
|
||||
@ -371,7 +379,7 @@ export const generateMarketsCandles = (
|
||||
{
|
||||
__typename: 'CandleEdge',
|
||||
node: {
|
||||
__typename: 'CandleNode',
|
||||
__typename: 'Candle',
|
||||
open: '100',
|
||||
close: '100',
|
||||
high: '110',
|
||||
|
@ -18,18 +18,7 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
id: '066468C06549101DAF7BC51099E1412A0067DC08C246B7D8013C9D0CBF1E8EE7',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
id: '',
|
||||
__typename: 'Instrument',
|
||||
code: 'AAVEDAI.MF21',
|
||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||
},
|
||||
},
|
||||
id: 'market-0',
|
||||
},
|
||||
size: '10',
|
||||
type: OrderType.TYPE_LIMIT,
|
||||
@ -48,18 +37,7 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
id: '48DB6767E4E4E0F649C5A13ABFADE39F8451C27DA828DAF14B7A1E8E5EBDAD99',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
id: '',
|
||||
__typename: 'Instrument',
|
||||
code: 'TSLA.QM21',
|
||||
name: 'Tesla Quarterly (30 Jun 2022)',
|
||||
},
|
||||
},
|
||||
id: 'market-1',
|
||||
},
|
||||
size: '1',
|
||||
type: OrderType.TYPE_LIMIT,
|
||||
@ -78,19 +56,7 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
id: '4e93702990712c41f6995fcbbd94f60bb372ad12d64dfa7d96d205c49f790336',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'c6f4337b31ed57a961969c3ba10297b369d01b9e75a4cbb96db4fc62886444e6',
|
||||
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
id: '',
|
||||
__typename: 'Instrument',
|
||||
code: 'BTCUSD.MF21',
|
||||
name: 'BTCUSD Monthly (30 Jun 2022)',
|
||||
},
|
||||
},
|
||||
id: 'market-2',
|
||||
},
|
||||
size: '1',
|
||||
type: OrderType.TYPE_LIMIT,
|
||||
@ -109,18 +75,7 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
id: '94737d2bafafa4bc3b80a56ef084ae52a983b91aa067c31e243c61a0f962a836',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'a316fa51dab97d76a1472c2f22906f4e461728e04355096788165d5b13999ed5',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
id: '',
|
||||
__typename: 'Instrument',
|
||||
code: 'UNIDAI.MF21',
|
||||
name: 'UNIDAI Monthly (30 Jun 2022)',
|
||||
},
|
||||
},
|
||||
id: 'market-3',
|
||||
},
|
||||
size: '1',
|
||||
type: OrderType.TYPE_LIMIT,
|
||||
@ -139,18 +94,7 @@ export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
|
||||
id: '94aead3ca92dc932efcb503631b03a410e2a5d4606cae6083e2406dc38e52f78',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'a316fa51dab97d76a1472c2f22906f4e461728e04355096788165d5b13999ed5',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
id: '',
|
||||
__typename: 'Instrument',
|
||||
code: 'UNIDAI.MF21',
|
||||
name: 'UNIDAI Monthly (30 Jun 2022)',
|
||||
},
|
||||
},
|
||||
id: 'market-3',
|
||||
},
|
||||
size: '10',
|
||||
type: OrderType.TYPE_LIMIT,
|
||||
|
@ -13,9 +13,7 @@ export const generateTrades = (override?: PartialDeep<Trades>): Trades => {
|
||||
size: '24',
|
||||
createdAt: '2022-04-06T16:19:42.692598951Z',
|
||||
market: {
|
||||
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
id: 'market-0',
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Trade',
|
||||
@ -26,9 +24,7 @@ export const generateTrades = (override?: PartialDeep<Trades>): Trades => {
|
||||
size: '7',
|
||||
createdAt: '2022-04-07T06:59:44.835686754Z',
|
||||
market: {
|
||||
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
id: 'market-0',
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Trade',
|
||||
@ -39,9 +35,7 @@ export const generateTrades = (override?: PartialDeep<Trades>): Trades => {
|
||||
size: '18',
|
||||
createdAt: '2022-04-07T17:56:47.997938583Z',
|
||||
market: {
|
||||
id: '0c3c1490db767f926d24fb674b4235a9aa339614915a4ab96cbfc0e1ad83c0ff',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
id: 'market-0',
|
||||
__typename: 'Market',
|
||||
},
|
||||
__typename: 'Trade',
|
||||
|
@ -1,7 +1,6 @@
|
||||
query Market($marketId: ID!, $interval: Interval!, $since: String!) {
|
||||
market(id: $marketId) {
|
||||
id
|
||||
name
|
||||
tradingMode
|
||||
state
|
||||
decimalPlaces
|
||||
@ -51,10 +50,14 @@ query Market($marketId: ID!, $interval: Interval!, $since: String!) {
|
||||
open
|
||||
close
|
||||
}
|
||||
candles(interval: $interval, since: $since) {
|
||||
open
|
||||
close
|
||||
volume
|
||||
candlesConnection(interval: $interval, since: $since) {
|
||||
edges {
|
||||
node {
|
||||
open
|
||||
close
|
||||
volume
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,10 +65,14 @@ const MARKET_QUERY = gql`
|
||||
open
|
||||
close
|
||||
}
|
||||
candles(interval: $interval, since: $since) {
|
||||
open
|
||||
close
|
||||
volume
|
||||
candlesConnection(interval: $interval, since: $since) {
|
||||
edges {
|
||||
node {
|
||||
open
|
||||
close
|
||||
volume
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
25
apps/trading/pages/markets/__generated__/Market.ts
generated
25
apps/trading/pages/markets/__generated__/Market.ts
generated
@ -20,7 +20,7 @@ export interface Market_market_data_market {
|
||||
export interface Market_market_data {
|
||||
__typename: "MarketData";
|
||||
/**
|
||||
* market ID of the associated mark price
|
||||
* market of the associated mark price
|
||||
*/
|
||||
market: Market_market_data_market;
|
||||
/**
|
||||
@ -169,7 +169,7 @@ export interface Market_market_marketTimestamps {
|
||||
close: string | null;
|
||||
}
|
||||
|
||||
export interface Market_market_candles {
|
||||
export interface Market_market_candlesConnection_edges_node {
|
||||
__typename: "Candle";
|
||||
/**
|
||||
* Open price (uint64)
|
||||
@ -185,6 +185,19 @@ export interface Market_market_candles {
|
||||
volume: string;
|
||||
}
|
||||
|
||||
export interface Market_market_candlesConnection_edges {
|
||||
__typename: "CandleEdge";
|
||||
node: Market_market_candlesConnection_edges_node;
|
||||
}
|
||||
|
||||
export interface Market_market_candlesConnection {
|
||||
__typename: "CandleDataConnection";
|
||||
/**
|
||||
* The candles
|
||||
*/
|
||||
edges: (Market_market_candlesConnection_edges | null)[] | null;
|
||||
}
|
||||
|
||||
export interface Market_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
@ -202,14 +215,14 @@ export interface Market_market {
|
||||
/**
|
||||
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
|
||||
* number denominated in the currency of the market. (uint64)
|
||||
*
|
||||
*
|
||||
* Examples:
|
||||
* Currency Balance decimalPlaces Real Balance
|
||||
* GBP 100 0 GBP 100
|
||||
* GBP 100 2 GBP 1.00
|
||||
* GBP 100 4 GBP 0.01
|
||||
* GBP 1 4 GBP 0.0001 ( 0.01p )
|
||||
*
|
||||
*
|
||||
* GBX (pence) 100 0 GBP 1.00 (100p )
|
||||
* GBX (pence) 100 2 GBP 0.01 ( 1p )
|
||||
* GBX (pence) 100 4 GBP 0.0001 ( 0.01p )
|
||||
@ -236,9 +249,9 @@ export interface Market_market {
|
||||
*/
|
||||
marketTimestamps: Market_market_marketTimestamps;
|
||||
/**
|
||||
* Candles on a market, for the 'last' n candles, at 'interval' seconds as specified by parameters
|
||||
* Candles on a market, for the 'last' n candles, at 'interval' seconds as specified by parameters using cursor based pagination
|
||||
*/
|
||||
candles: (Market_market_candles | null)[] | null;
|
||||
candlesConnection: Market_market_candlesConnection | null;
|
||||
}
|
||||
|
||||
export interface Market {
|
||||
|
@ -10,14 +10,13 @@ export type MarketQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type MarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, name: string, tradingMode: Types.MarketTradingMode, state: Types.MarketState, decimalPlaces: number, positionDecimalPlaces: number, data?: { __typename?: 'MarketData', auctionStart?: string | null, auctionEnd?: string | null, markPrice: string, indicativeVolume: string, indicativePrice: string, suppliedStake?: string | null, targetStake?: string | null, bestBidVolume: string, bestOfferVolume: string, bestStaticBidVolume: string, bestStaticOfferVolume: string, trigger: Types.AuctionTrigger, market: { __typename?: 'Market', id: string } } | null, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, oracleSpecForTradingTermination: { __typename?: 'OracleSpec', id: string }, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open?: string | null, close?: string | null }, candles?: Array<{ __typename?: 'Candle', open: string, close: string, volume: string } | null> | null } | null };
|
||||
export type MarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, tradingMode: Types.MarketTradingMode, state: Types.MarketState, decimalPlaces: number, positionDecimalPlaces: number, data?: { __typename?: 'MarketData', auctionStart?: string | null, auctionEnd?: string | null, markPrice: string, indicativeVolume: string, indicativePrice: string, suppliedStake?: string | null, targetStake?: string | null, bestBidVolume: string, bestOfferVolume: string, bestStaticBidVolume: string, bestStaticOfferVolume: string, trigger: Types.AuctionTrigger, market: { __typename?: 'Market', id: string } } | null, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, oracleSpecForTradingTermination: { __typename?: 'OracleSpec', id: string }, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open?: string | null, close?: string | null }, candlesConnection?: { __typename?: 'CandleDataConnection', edges?: Array<{ __typename?: 'CandleEdge', node: { __typename?: 'Candle', open: string, close: string, volume: string } } | null> | null } | null } | null };
|
||||
|
||||
|
||||
export const MarketDocument = gql`
|
||||
query Market($marketId: ID!, $interval: Interval!, $since: String!) {
|
||||
market(id: $marketId) {
|
||||
id
|
||||
name
|
||||
tradingMode
|
||||
state
|
||||
decimalPlaces
|
||||
@ -57,6 +56,7 @@ export const MarketDocument = gql`
|
||||
id
|
||||
symbol
|
||||
name
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -66,10 +66,14 @@ export const MarketDocument = gql`
|
||||
open
|
||||
close
|
||||
}
|
||||
candles(interval: $interval, since: $since) {
|
||||
open
|
||||
close
|
||||
volume
|
||||
candlesConnection(interval: $interval, since: $since) {
|
||||
edges {
|
||||
node {
|
||||
open
|
||||
close
|
||||
volume
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -121,8 +121,8 @@ export const TradeMarketHeader = ({
|
||||
const { setAssetDetailsDialogOpen, setAssetDetailsDialogSymbol } =
|
||||
useAssetDetailsDialogStore();
|
||||
|
||||
const candlesClose: string[] = (market?.candles || [])
|
||||
.map((candle) => candle?.close)
|
||||
const candlesClose: string[] = (market?.candlesConnection?.edges || [])
|
||||
.map((candle) => candle?.node.close)
|
||||
.filter((c): c is CandleClose => c !== null);
|
||||
const symbol =
|
||||
market.tradableInstrument.instrument.product?.settlementAsset?.symbol;
|
||||
|
@ -68,5 +68,5 @@ export interface DepositPage {
|
||||
/**
|
||||
* The list of all assets in use in the Vega network or the specified asset if ID is provided
|
||||
*/
|
||||
assetsConnection: DepositPage_assetsConnection;
|
||||
assetsConnection: DepositPage_assetsConnection | null;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ const defaultOptions = {} as const;
|
||||
export type DepositPageQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type DepositPageQuery = { __typename?: 'Query', assetsConnection: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } } | null> | null } };
|
||||
export type DepositPageQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } } | null> | null } | null };
|
||||
|
||||
|
||||
export const DepositPageDocument = gql`
|
||||
|
@ -2,4 +2,5 @@ const { getJestProjects } = require('@nrwl/jest');
|
||||
|
||||
export default {
|
||||
projects: getJestProjects(),
|
||||
testTimeout: 10000,
|
||||
};
|
||||
|
@ -20,13 +20,30 @@ query Accounts($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
accounts {
|
||||
...AccountFields
|
||||
type
|
||||
balance
|
||||
market {
|
||||
id
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
asset {
|
||||
id
|
||||
symbol
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subscription AccountEvents($partyId: ID!) {
|
||||
accounts(partyId: $partyId) {
|
||||
...AccountFields
|
||||
type
|
||||
balance
|
||||
assetId
|
||||
marketId
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ export type AccountEventsSubscriptionVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type AccountEventsSubscription = { __typename?: 'Subscription', accounts: { __typename?: 'Account', type: Types.AccountType, balance: string, market?: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string } } } | null, asset: { __typename?: 'Asset', id: string, symbol: string, decimals: number } } };
|
||||
export type AccountEventsSubscription = { __typename?: 'Subscription', accounts: Array<{ __typename?: 'AccountUpdate', type: Types.AccountType, balance: string, assetId: string, marketId?: string | null }> };
|
||||
|
||||
export const AccountFieldsFragmentDoc = gql`
|
||||
fragment AccountFields on Account {
|
||||
@ -43,11 +43,25 @@ export const AccountsDocument = gql`
|
||||
party(id: $partyId) {
|
||||
id
|
||||
accounts {
|
||||
...AccountFields
|
||||
type
|
||||
balance
|
||||
market {
|
||||
id
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
asset {
|
||||
id
|
||||
symbol
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${AccountFieldsFragmentDoc}`;
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useAccountsQuery__
|
||||
@ -79,10 +93,13 @@ export type AccountsQueryResult = Apollo.QueryResult<AccountsQuery, AccountsQuer
|
||||
export const AccountEventsDocument = gql`
|
||||
subscription AccountEvents($partyId: ID!) {
|
||||
accounts(partyId: $partyId) {
|
||||
...AccountFields
|
||||
type
|
||||
balance
|
||||
assetId
|
||||
marketId
|
||||
}
|
||||
}
|
||||
${AccountFieldsFragmentDoc}`;
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useAccountEventsSubscription__
|
@ -1,30 +1,47 @@
|
||||
import produce from 'immer';
|
||||
import type { IterableElement } from 'type-fest';
|
||||
import {
|
||||
AccountsDocument,
|
||||
AccountEventsDocument,
|
||||
} from './__generated__/Accounts';
|
||||
} from './__generated___/Accounts';
|
||||
import type {
|
||||
AccountFieldsFragment,
|
||||
AccountsQuery,
|
||||
AccountEventsSubscription,
|
||||
} from './__generated__/Accounts';
|
||||
} from './__generated___/Accounts';
|
||||
import { makeDataProvider } from '@vegaprotocol/react-helpers';
|
||||
|
||||
export const getId = (data: AccountFieldsFragment) =>
|
||||
`${data.type}-${data.asset.symbol}-${data.market?.id ?? 'null'}`;
|
||||
function isAccount(
|
||||
account:
|
||||
| AccountFieldsFragment
|
||||
| IterableElement<AccountEventsSubscription['accounts']>
|
||||
): account is AccountFieldsFragment {
|
||||
return (account as AccountFieldsFragment).__typename === 'Account';
|
||||
}
|
||||
|
||||
export const getId = (
|
||||
account:
|
||||
| AccountFieldsFragment
|
||||
| IterableElement<AccountEventsSubscription['accounts']>
|
||||
) =>
|
||||
isAccount(account)
|
||||
? `${account.type}-${account.asset.id}-${account.market?.id ?? 'null'}`
|
||||
: `${account.type}-${account.assetId}-${account.marketId}`;
|
||||
|
||||
const update = (
|
||||
data: AccountFieldsFragment[],
|
||||
delta: AccountFieldsFragment
|
||||
deltas: AccountEventsSubscription['accounts']
|
||||
) => {
|
||||
return produce(data, (draft) => {
|
||||
const id = getId(delta);
|
||||
const index = draft.findIndex((a) => getId(a) === id);
|
||||
if (index !== -1) {
|
||||
draft[index] = delta;
|
||||
} else {
|
||||
draft.push(delta);
|
||||
}
|
||||
deltas.forEach((delta) => {
|
||||
const id = getId(delta);
|
||||
const index = draft.findIndex((a) => getId(a) === id);
|
||||
if (index !== -1) {
|
||||
draft[index].balance = delta.balance;
|
||||
} else {
|
||||
// #TODO handle new account
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
@ -36,13 +53,13 @@ const getData = (
|
||||
|
||||
const getDelta = (
|
||||
subscriptionData: AccountEventsSubscription
|
||||
): AccountFieldsFragment => subscriptionData.accounts;
|
||||
): AccountEventsSubscription['accounts'] => subscriptionData.accounts;
|
||||
|
||||
export const accountsDataProvider = makeDataProvider<
|
||||
AccountsQuery,
|
||||
AccountFieldsFragment[],
|
||||
AccountEventsSubscription,
|
||||
AccountFieldsFragment
|
||||
AccountEventsSubscription['accounts']
|
||||
>({
|
||||
query: AccountsDocument,
|
||||
subscriptionQuery: AccountEventsDocument,
|
||||
|
@ -3,7 +3,10 @@ import { produce } from 'immer';
|
||||
import merge from 'lodash/merge';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { useDataProvider, addSummaryRows } from '@vegaprotocol/react-helpers';
|
||||
import type { AccountFieldsFragment } from './__generated__/Accounts';
|
||||
import type {
|
||||
AccountFieldsFragment,
|
||||
AccountEventsSubscription,
|
||||
} from './__generated___/Accounts';
|
||||
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import {
|
||||
@ -21,26 +24,29 @@ export const AccountsManager = ({ partyId }: AccountsManagerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const variables = useMemo(() => ({ partyId }), [partyId]);
|
||||
const update = useCallback(
|
||||
({ delta }: { delta: AccountFieldsFragment }) => {
|
||||
({ delta: deltas }: { delta: AccountEventsSubscription['accounts'] }) => {
|
||||
const update: AccountFieldsFragment[] = [];
|
||||
const add: AccountFieldsFragment[] = [];
|
||||
if (!gridRef.current?.api) {
|
||||
return false;
|
||||
}
|
||||
const rowNode = gridRef.current.api.getRowNode(getId(delta));
|
||||
if (rowNode) {
|
||||
const updatedData = produce<AccountFieldsFragment>(
|
||||
rowNode.data,
|
||||
(draft: AccountFieldsFragment) => {
|
||||
merge(draft, delta);
|
||||
const api = gridRef.current.api;
|
||||
deltas.forEach((delta) => {
|
||||
const rowNode = api.getRowNode(getId(delta));
|
||||
if (rowNode) {
|
||||
const updatedData = produce<AccountFieldsFragment>(
|
||||
rowNode.data,
|
||||
(draft: AccountFieldsFragment) => {
|
||||
merge(draft, delta);
|
||||
}
|
||||
);
|
||||
if (updatedData !== rowNode.data) {
|
||||
update.push(updatedData);
|
||||
}
|
||||
);
|
||||
if (updatedData !== rowNode.data) {
|
||||
update.push(updatedData);
|
||||
} else {
|
||||
// #TODO handle new account (or leave it to data provider to handle it)
|
||||
}
|
||||
} else {
|
||||
add.push(delta);
|
||||
}
|
||||
});
|
||||
if (update.length || add.length) {
|
||||
gridRef.current.api.applyTransactionAsync({
|
||||
update,
|
||||
@ -62,7 +68,7 @@ export const AccountsManager = ({ partyId }: AccountsManagerProps) => {
|
||||
);
|
||||
const { data, error, loading } = useDataProvider<
|
||||
AccountFieldsFragment[],
|
||||
AccountFieldsFragment
|
||||
AccountEventsSubscription['accounts']
|
||||
>({ dataProvider: accountsDataProvider, update, variables });
|
||||
return (
|
||||
<AsyncRenderer loading={loading} error={error} data={data}>
|
||||
|
@ -1,11 +1,11 @@
|
||||
import AccountsTable from './accounts-table';
|
||||
import { act, render, screen, waitFor } from '@testing-library/react';
|
||||
import type { AccountFieldsFragment } from './__generated__/Accounts';
|
||||
import { AccountType } from '@vegaprotocol/types';
|
||||
import type { AccountFieldsFragment } from './__generated___/Accounts';
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
|
||||
const singleRow: AccountFieldsFragment = {
|
||||
__typename: 'Account',
|
||||
type: AccountType.ACCOUNT_TYPE_MARGIN,
|
||||
type: Types.AccountType.ACCOUNT_TYPE_MARGIN,
|
||||
balance: '125600000',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
|
@ -14,7 +14,7 @@ import type { SummaryRow } from '@vegaprotocol/react-helpers';
|
||||
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridColumn } from 'ag-grid-react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { AccountFieldsFragment } from './__generated__/Accounts';
|
||||
import type { AccountFieldsFragment } from './__generated___/Accounts';
|
||||
import { getId } from './accounts-data-provider';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import type { AccountType } from '@vegaprotocol/types';
|
||||
|
@ -3,8 +3,6 @@ import {
|
||||
addDecimalsFormatNumber,
|
||||
useDataProvider,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import type { AccountFieldsFragment } from './__generated__/Accounts';
|
||||
|
||||
import { accountsDataProvider } from './accounts-data-provider';
|
||||
|
||||
interface AssetBalanceProps {
|
||||
@ -14,10 +12,7 @@ interface AssetBalanceProps {
|
||||
|
||||
export const AssetBalance = ({ partyId, assetSymbol }: AssetBalanceProps) => {
|
||||
const variables = useMemo(() => ({ partyId }), [partyId]);
|
||||
const { data } = useDataProvider<
|
||||
AccountFieldsFragment[],
|
||||
AccountFieldsFragment
|
||||
>({
|
||||
const { data } = useDataProvider({
|
||||
dataProvider: accountsDataProvider,
|
||||
variables,
|
||||
});
|
||||
|
@ -1,4 +1,4 @@
|
||||
export * from './__generated__/Accounts';
|
||||
export * from './__generated___/Accounts';
|
||||
export * from './accounts-container';
|
||||
export * from './accounts-data-provider';
|
||||
export * from './accounts-manager';
|
||||
|
2
libs/assets/src/lib/__generated__/Assets.ts
generated
2
libs/assets/src/lib/__generated__/Assets.ts
generated
@ -6,7 +6,7 @@ const defaultOptions = {} as const;
|
||||
export type AssetsConnectionQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type AssetsConnectionQuery = { __typename?: 'Query', assetsConnection: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string, lifetimeLimit: string, withdrawThreshold: string } } } | null> | null } };
|
||||
export type AssetsConnectionQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string, lifetimeLimit: string, withdrawThreshold: string } } } | null> | null } | null };
|
||||
|
||||
|
||||
export const AssetsConnectionDocument = gql`
|
||||
|
60
libs/assets/src/lib/__generated___/Assets.ts
Normal file
60
libs/assets/src/lib/__generated___/Assets.ts
Normal file
@ -0,0 +1,60 @@
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type AssetsConnectionQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type AssetsConnectionQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string, lifetimeLimit: string, withdrawThreshold: string } } } | null> | null } | null };
|
||||
|
||||
|
||||
export const AssetsConnectionDocument = gql`
|
||||
query AssetsConnection {
|
||||
assetsConnection {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
symbol
|
||||
decimals
|
||||
quantum
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
lifetimeLimit
|
||||
withdrawThreshold
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useAssetsConnectionQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useAssetsConnectionQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useAssetsConnectionQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useAssetsConnectionQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useAssetsConnectionQuery(baseOptions?: Apollo.QueryHookOptions<AssetsConnectionQuery, AssetsConnectionQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<AssetsConnectionQuery, AssetsConnectionQueryVariables>(AssetsConnectionDocument, options);
|
||||
}
|
||||
export function useAssetsConnectionLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<AssetsConnectionQuery, AssetsConnectionQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<AssetsConnectionQuery, AssetsConnectionQueryVariables>(AssetsConnectionDocument, options);
|
||||
}
|
||||
export type AssetsConnectionQueryHookResult = ReturnType<typeof useAssetsConnectionQuery>;
|
||||
export type AssetsConnectionLazyQueryHookResult = ReturnType<typeof useAssetsConnectionLazyQuery>;
|
||||
export type AssetsConnectionQueryResult = Apollo.QueryResult<AssetsConnectionQuery, AssetsConnectionQueryVariables>;
|
@ -54,7 +54,7 @@ export const AssetDetailsDialog = ({
|
||||
const { data } = useAssetsConnectionQuery();
|
||||
const symbol =
|
||||
typeof assetSymbol === 'string' ? assetSymbol : assetSymbol.symbol;
|
||||
const asset = data?.assetsConnection.edges?.find(
|
||||
const asset = data?.assetsConnection?.edges?.find(
|
||||
(e) => e?.node.symbol === symbol
|
||||
);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
fragment CandleFields on Candle {
|
||||
timestamp
|
||||
periodStart
|
||||
high
|
||||
low
|
||||
open
|
||||
@ -18,8 +18,12 @@ query Candles($marketId: ID!, $interval: Interval!, $since: String!) {
|
||||
code
|
||||
}
|
||||
}
|
||||
candles(interval: $interval, since: $since) {
|
||||
...CandleFields
|
||||
candlesConnection(interval: $interval, since: $since) {
|
||||
edges {
|
||||
node {
|
||||
...CandleFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@ import { Schema as Types } from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type CandleFieldsFragment = { __typename?: 'Candle', timestamp: string, high: string, low: string, open: string, close: string, volume: string };
|
||||
export type CandleFieldsFragment = { __typename?: 'Candle', periodStart: string, high: string, low: string, open: string, close: string, volume: string };
|
||||
|
||||
export type CandlesQueryVariables = Types.Exact<{
|
||||
marketId: Types.Scalars['ID'];
|
||||
@ -12,7 +12,7 @@ export type CandlesQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type CandlesQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string } }, candles?: Array<{ __typename?: 'Candle', timestamp: string, high: string, low: string, open: string, close: string, volume: string } | null> | null } | null };
|
||||
export type CandlesQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string } }, candlesConnection?: { __typename?: 'CandleDataConnection', edges?: Array<{ __typename?: 'CandleEdge', node: { __typename?: 'Candle', periodStart: string, high: string, low: string, open: string, close: string, volume: string } } | null> | null } | null } | null };
|
||||
|
||||
export type CandlesEventsSubscriptionVariables = Types.Exact<{
|
||||
marketId: Types.Scalars['ID'];
|
||||
@ -20,11 +20,11 @@ export type CandlesEventsSubscriptionVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type CandlesEventsSubscription = { __typename?: 'Subscription', candles: { __typename?: 'Candle', timestamp: string, high: string, low: string, open: string, close: string, volume: string } };
|
||||
export type CandlesEventsSubscription = { __typename?: 'Subscription', candles: { __typename?: 'Candle', periodStart: string, high: string, low: string, open: string, close: string, volume: string } };
|
||||
|
||||
export const CandleFieldsFragmentDoc = gql`
|
||||
fragment CandleFields on Candle {
|
||||
timestamp
|
||||
periodStart
|
||||
high
|
||||
low
|
||||
open
|
||||
@ -44,8 +44,12 @@ export const CandlesDocument = gql`
|
||||
code
|
||||
}
|
||||
}
|
||||
candles(interval: $interval, since: $since) {
|
||||
...CandleFields
|
||||
candlesConnection(interval: $interval, since: $since) {
|
||||
edges {
|
||||
node {
|
||||
...CandleFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +1,22 @@
|
||||
import compact from 'lodash/compact';
|
||||
import type { ApolloClient } from '@apollo/client';
|
||||
import type { Candle, DataSource } from 'pennant';
|
||||
import { Interval as PennantInterval } from 'pennant';
|
||||
|
||||
import { addDecimal } from '@vegaprotocol/react-helpers';
|
||||
import { ChartDocument } from './__generated__/Chart';
|
||||
import type { ChartQuery, ChartQueryVariables } from './__generated__/Chart';
|
||||
import { ChartDocument } from './__generated___/Chart';
|
||||
import type { ChartQuery, ChartQueryVariables } from './__generated___/Chart';
|
||||
import {
|
||||
CandlesDocument,
|
||||
CandlesEventsDocument,
|
||||
} from './__generated__/Candles';
|
||||
} from './__generated___/Candles';
|
||||
import type {
|
||||
CandlesQuery,
|
||||
CandlesQueryVariables,
|
||||
CandleFieldsFragment,
|
||||
CandlesEventsSubscription,
|
||||
CandlesEventsSubscriptionVariables,
|
||||
} from './__generated__/Candles';
|
||||
} from './__generated___/Candles';
|
||||
import type { Subscription } from 'zen-observable-ts';
|
||||
import { Interval } from '@vegaprotocol/types';
|
||||
|
||||
@ -142,14 +143,15 @@ export class VegaDataSource implements DataSource {
|
||||
},
|
||||
fetchPolicy: 'no-cache',
|
||||
});
|
||||
console.log(data);
|
||||
|
||||
if (data && data.market && data.market.candles) {
|
||||
if (data && data.market && data.market.candlesConnection) {
|
||||
const decimalPlaces = data.market.decimalPlaces;
|
||||
|
||||
const candles = data.market.candles
|
||||
const candles = compact(data.market.candlesConnection.edges)
|
||||
.map((e) => e.node)
|
||||
.filter((d): d is CandleFieldsFragment => d !== null)
|
||||
.map((d) => parseCandle(d, decimalPlaces));
|
||||
|
||||
return candles;
|
||||
} else {
|
||||
return [];
|
||||
@ -198,8 +200,9 @@ function parseCandle(
|
||||
candle: CandleFieldsFragment,
|
||||
decimalPlaces: number
|
||||
): Candle {
|
||||
console.log(candle);
|
||||
return {
|
||||
date: new Date(Number(candle.timestamp) / 1_000_000),
|
||||
date: new Date(candle.periodStart),
|
||||
high: Number(addDecimal(candle.high, decimalPlaces)),
|
||||
low: Number(addDecimal(candle.low, decimalPlaces)),
|
||||
open: Number(addDecimal(candle.open, decimalPlaces)),
|
||||
|
@ -1,4 +1,4 @@
|
||||
export * from './__generated__/Candles';
|
||||
export * from './__generated__/Chart';
|
||||
export * from './__generated___/Candles';
|
||||
export * from './__generated___/Chart';
|
||||
export * from './candles-chart';
|
||||
export * from './data-source';
|
||||
|
@ -1,7 +1,6 @@
|
||||
query DealTicketQuery($marketId: ID!) {
|
||||
market(id: $marketId) {
|
||||
id
|
||||
name
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
state
|
||||
|
@ -8,14 +8,13 @@ export type DealTicketQueryQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type DealTicketQueryQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, name: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string } } } }, depth: { __typename?: 'MarketDepth', lastTrade?: { __typename?: 'Trade', price: string } | null } } | null };
|
||||
export type DealTicketQueryQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string } } } }, depth: { __typename?: 'MarketDepth', lastTrade?: { __typename?: 'Trade', price: string } | null } } | null };
|
||||
|
||||
|
||||
export const DealTicketQueryDocument = gql`
|
||||
query DealTicketQuery($marketId: ID!) {
|
||||
market(id: $marketId) {
|
||||
id
|
||||
name
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
state
|
||||
|
@ -7,7 +7,6 @@ import React, {
|
||||
useMemo,
|
||||
} from 'react';
|
||||
import * as DialogPrimitives from '@radix-ui/react-dialog';
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import classNames from 'classnames';
|
||||
import type { DealTicketQuery_market } from './';
|
||||
import {
|
||||
@ -21,41 +20,20 @@ import {
|
||||
t,
|
||||
useScreenDimensions,
|
||||
useOutsideClick,
|
||||
useDataProvider,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
MarketNames,
|
||||
MarketNames_markets,
|
||||
} from './__generated__/MarketNames';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
|
||||
export const MARKET_NAMES_QUERY = gql`
|
||||
query MarketNames {
|
||||
markets {
|
||||
id
|
||||
state
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
code
|
||||
name
|
||||
metadata {
|
||||
tags
|
||||
}
|
||||
product {
|
||||
... on Future {
|
||||
quoteName
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
import { marketsProvider } from '@vegaprotocol/market-list';
|
||||
|
||||
interface Props {
|
||||
market: DealTicketQuery_market;
|
||||
setMarket: (marketId: string) => void;
|
||||
ItemRenderer?: React.FC<{ market: MarketNames_markets; isMobile?: boolean }>;
|
||||
ItemRenderer?: React.FC<{
|
||||
market: Market;
|
||||
isMobile?: boolean;
|
||||
}>;
|
||||
}
|
||||
|
||||
function escapeRegExp(str: string) {
|
||||
@ -67,8 +45,7 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
|
||||
const contRef = useRef<HTMLDivElement | null>(null);
|
||||
const inputRef = useRef<HTMLInputElement | null>(null);
|
||||
const arrowButtonRef = useRef<HTMLButtonElement | null>(null);
|
||||
const [skip, setSkip] = useState(true);
|
||||
const [results, setResults] = useState<MarketNames_markets[]>([]);
|
||||
const [results, setResults] = useState<Market[]>([]);
|
||||
const [showPane, setShowPane] = useState(false);
|
||||
const [lookup, setLookup] = useState(
|
||||
market.tradableInstrument.instrument.name || ''
|
||||
@ -77,8 +54,9 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
|
||||
null
|
||||
);
|
||||
|
||||
const { data, loading, error } = useQuery<MarketNames>(MARKET_NAMES_QUERY, {
|
||||
skip,
|
||||
const { data, loading, error } = useDataProvider({
|
||||
dataProvider: marketsProvider,
|
||||
noUpdate: true,
|
||||
});
|
||||
|
||||
const outsideClickCb = useCallback(() => {
|
||||
@ -96,11 +74,8 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
|
||||
} = event;
|
||||
setLookup(value);
|
||||
setShowPane(true);
|
||||
if (value) {
|
||||
setSkip(false);
|
||||
}
|
||||
},
|
||||
[setLookup, setShowPane, setSkip]
|
||||
[setLookup, setShowPane]
|
||||
);
|
||||
|
||||
const handleMarketSelect = useCallback(
|
||||
@ -117,11 +92,7 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
|
||||
);
|
||||
|
||||
const handleItemKeyDown = useCallback(
|
||||
(
|
||||
event: React.KeyboardEvent,
|
||||
market: MarketNames_markets,
|
||||
index: number
|
||||
) => {
|
||||
(event: React.KeyboardEvent, market: Market, index: number) => {
|
||||
switch (event.key) {
|
||||
case 'ArrowDown':
|
||||
if (index < results.length - 1) {
|
||||
@ -170,9 +141,8 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
|
||||
|
||||
const openPane = useCallback(() => {
|
||||
setShowPane(!showPane);
|
||||
setSkip(false);
|
||||
inputRef.current?.focus();
|
||||
}, [showPane, setShowPane, setSkip, inputRef]);
|
||||
}, [showPane, setShowPane, inputRef]);
|
||||
|
||||
const handleDialogOnchange = useCallback(
|
||||
(isOpen: boolean) => {
|
||||
@ -274,8 +244,8 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
|
||||
|
||||
useEffect(() => {
|
||||
setResults(
|
||||
data?.markets?.filter(
|
||||
(item: MarketNames_markets) =>
|
||||
data?.filter(
|
||||
(item) =>
|
||||
item.state === MarketState.STATE_ACTIVE &&
|
||||
item.tradableInstrument.instrument.name.match(
|
||||
new RegExp(escapeRegExp(lookup), 'i')
|
||||
|
@ -79,7 +79,7 @@ export interface DepositsQuery_party {
|
||||
/**
|
||||
* The list of all deposits for a party by the party
|
||||
*/
|
||||
depositsConnection: DepositsQuery_party_depositsConnection;
|
||||
depositsConnection: DepositsQuery_party_depositsConnection | null;
|
||||
}
|
||||
|
||||
export interface DepositsQuery {
|
||||
|
@ -7,12 +7,26 @@
|
||||
// GraphQL subscription operation: BlockTime
|
||||
// ====================================================
|
||||
|
||||
export interface BlockTime_busEvents_event_MarketEvent {
|
||||
__typename: "MarketEvent" | "TransferResponses" | "PositionResolution" | "Order" | "Trade" | "Account" | "Party" | "MarginLevels" | "Proposal" | "Vote" | "MarketData" | "NodeSignature" | "LossSocialization" | "SettlePosition" | "Market" | "Asset" | "MarketTick" | "SettleDistressed" | "AuctionEvent" | "RiskFactor" | "Deposit" | "Withdrawal" | "OracleSpec" | "LiquidityProvision";
|
||||
}
|
||||
|
||||
export interface BlockTime_busEvents_event_TimeUpdate {
|
||||
__typename: "TimeUpdate";
|
||||
/**
|
||||
* RFC3339Nano time of new block time
|
||||
*/
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
export type BlockTime_busEvents_event = BlockTime_busEvents_event_MarketEvent | BlockTime_busEvents_event_TimeUpdate;
|
||||
|
||||
export interface BlockTime_busEvents {
|
||||
__typename: "BusEvent";
|
||||
/**
|
||||
* the ID for this event
|
||||
* the payload - the wrapped event
|
||||
*/
|
||||
eventId: string;
|
||||
event: BlockTime_busEvents_event;
|
||||
}
|
||||
|
||||
export interface BlockTime {
|
||||
|
@ -14,7 +14,11 @@ export const STATS_QUERY = gql`
|
||||
export const TIME_UPDATE_SUBSCRIPTION = gql`
|
||||
subscription BlockTime {
|
||||
busEvents(types: TimeUpdate, batchSize: 1) {
|
||||
eventId
|
||||
event {
|
||||
... on TimeUpdate {
|
||||
timestamp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
@ -24,7 +24,6 @@ fragment FillFields on Trade {
|
||||
}
|
||||
market {
|
||||
id
|
||||
name
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
tradableInstrument {
|
||||
@ -67,6 +66,25 @@ query Fills($partyId: ID!, $marketId: ID, $pagination: Pagination) {
|
||||
|
||||
subscription FillsSub($partyId: ID!) {
|
||||
trades(partyId: $partyId) {
|
||||
...FillFields
|
||||
id
|
||||
createdAt
|
||||
price
|
||||
size
|
||||
buyOrder
|
||||
sellOrder
|
||||
aggressor
|
||||
buyerId
|
||||
sellerId
|
||||
buyerFee {
|
||||
makerFee
|
||||
infrastructureFee
|
||||
liquidityFee
|
||||
}
|
||||
sellerFee {
|
||||
makerFee
|
||||
infrastructureFee
|
||||
liquidityFee
|
||||
}
|
||||
marketId
|
||||
}
|
||||
}
|
||||
|
108
libs/fills/src/lib/__generated__/Fills.ts
generated
108
libs/fills/src/lib/__generated__/Fills.ts
generated
@ -9,6 +9,14 @@ import { Pagination, Side } from "@vegaprotocol/types";
|
||||
// GraphQL query operation: Fills
|
||||
// ====================================================
|
||||
|
||||
export interface Fills_party_tradesConnection_edges_node_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface Fills_party_tradesConnection_edges_node_buyer {
|
||||
__typename: "Party";
|
||||
/**
|
||||
@ -57,100 +65,16 @@ export interface Fills_party_tradesConnection_edges_node_sellerFee {
|
||||
liquidityFee: string;
|
||||
}
|
||||
|
||||
export interface Fills_party_tradesConnection_edges_node_market_tradableInstrument_instrument_product_settlementAsset {
|
||||
__typename: "Asset";
|
||||
/**
|
||||
* The ID of the asset
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The symbol of the asset (e.g: GBP)
|
||||
*/
|
||||
symbol: 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 Fills_party_tradesConnection_edges_node_market_tradableInstrument_instrument_product {
|
||||
__typename: "Future";
|
||||
/**
|
||||
* The name of the asset (string)
|
||||
*/
|
||||
settlementAsset: Fills_party_tradesConnection_edges_node_market_tradableInstrument_instrument_product_settlementAsset;
|
||||
}
|
||||
|
||||
export interface Fills_party_tradesConnection_edges_node_market_tradableInstrument_instrument {
|
||||
__typename: "Instrument";
|
||||
/**
|
||||
* Uniquely identify an instrument across all instruments available on Vega (string)
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
|
||||
*/
|
||||
code: string;
|
||||
/**
|
||||
* Full and fairly descriptive name for the instrument
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
|
||||
*/
|
||||
product: Fills_party_tradesConnection_edges_node_market_tradableInstrument_instrument_product;
|
||||
}
|
||||
|
||||
export interface Fills_party_tradesConnection_edges_node_market_tradableInstrument {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of, or reference to, a fully specified instrument.
|
||||
*/
|
||||
instrument: Fills_party_tradesConnection_edges_node_market_tradableInstrument_instrument;
|
||||
}
|
||||
|
||||
export interface Fills_party_tradesConnection_edges_node_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: 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;
|
||||
/**
|
||||
* An instance of, or reference to, a tradable instrument.
|
||||
*/
|
||||
tradableInstrument: Fills_party_tradesConnection_edges_node_market_tradableInstrument;
|
||||
}
|
||||
|
||||
export interface Fills_party_tradesConnection_edges_node {
|
||||
__typename: "Trade";
|
||||
/**
|
||||
* The hash of the trade data
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The market the trade occurred on
|
||||
*/
|
||||
market: Fills_party_tradesConnection_edges_node_market;
|
||||
/**
|
||||
* RFC3339Nano time for when the trade occurred
|
||||
*/
|
||||
@ -160,7 +84,7 @@ export interface Fills_party_tradesConnection_edges_node {
|
||||
*/
|
||||
price: string;
|
||||
/**
|
||||
* The number of contracts trades, will always be <= the remaining size of both orders immediately before the trade (uint64)
|
||||
* The number of units traded, will always be <= the remaining size of both orders immediately before the trade (uint64)
|
||||
*/
|
||||
size: string;
|
||||
/**
|
||||
@ -191,10 +115,6 @@ export interface Fills_party_tradesConnection_edges_node {
|
||||
* The fee paid by the seller side of the trade
|
||||
*/
|
||||
sellerFee: Fills_party_tradesConnection_edges_node_sellerFee;
|
||||
/**
|
||||
* The market the trade occurred on
|
||||
*/
|
||||
market: Fills_party_tradesConnection_edges_node_market;
|
||||
}
|
||||
|
||||
export interface Fills_party_tradesConnection_edges {
|
||||
@ -229,7 +149,7 @@ export interface Fills_party {
|
||||
* Party identifier
|
||||
*/
|
||||
id: string;
|
||||
tradesConnection: Fills_party_tradesConnection;
|
||||
tradesConnection: Fills_party_tradesConnection | null;
|
||||
}
|
||||
|
||||
export interface Fills {
|
||||
|
148
libs/fills/src/lib/__generated__/FillsSub.ts
generated
148
libs/fills/src/lib/__generated__/FillsSub.ts
generated
@ -3,28 +3,12 @@
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { Side } from "@vegaprotocol/types";
|
||||
import { Side, TradeType } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL subscription operation: FillsSub
|
||||
// ====================================================
|
||||
|
||||
export interface FillsSub_trades_buyer {
|
||||
__typename: "Party";
|
||||
/**
|
||||
* Party identifier
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface FillsSub_trades_seller {
|
||||
__typename: "Party";
|
||||
/**
|
||||
* Party identifier
|
||||
*/
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface FillsSub_trades_buyerFee {
|
||||
__typename: "TradeFee";
|
||||
/**
|
||||
@ -57,112 +41,16 @@ export interface FillsSub_trades_sellerFee {
|
||||
liquidityFee: string;
|
||||
}
|
||||
|
||||
export interface FillsSub_trades_market_tradableInstrument_instrument_product_settlementAsset {
|
||||
__typename: "Asset";
|
||||
/**
|
||||
* The ID of the asset
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The symbol of the asset (e.g: GBP)
|
||||
*/
|
||||
symbol: 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 FillsSub_trades_market_tradableInstrument_instrument_product {
|
||||
__typename: "Future";
|
||||
/**
|
||||
* The name of the asset (string)
|
||||
*/
|
||||
settlementAsset: FillsSub_trades_market_tradableInstrument_instrument_product_settlementAsset;
|
||||
}
|
||||
|
||||
export interface FillsSub_trades_market_tradableInstrument_instrument {
|
||||
__typename: "Instrument";
|
||||
/**
|
||||
* Uniquely identify an instrument across all instruments available on Vega (string)
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
|
||||
*/
|
||||
code: string;
|
||||
/**
|
||||
* Full and fairly descriptive name for the instrument
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
|
||||
*/
|
||||
product: FillsSub_trades_market_tradableInstrument_instrument_product;
|
||||
}
|
||||
|
||||
export interface FillsSub_trades_market_tradableInstrument {
|
||||
__typename: "TradableInstrument";
|
||||
/**
|
||||
* An instance of, or reference to, a fully specified instrument.
|
||||
*/
|
||||
instrument: FillsSub_trades_market_tradableInstrument_instrument;
|
||||
}
|
||||
|
||||
export interface FillsSub_trades_market {
|
||||
__typename: "Market";
|
||||
/**
|
||||
* Market ID
|
||||
*/
|
||||
id: 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;
|
||||
/**
|
||||
* An instance of, or reference to, a tradable instrument.
|
||||
*/
|
||||
tradableInstrument: FillsSub_trades_market_tradableInstrument;
|
||||
}
|
||||
|
||||
export interface FillsSub_trades {
|
||||
__typename: "Trade";
|
||||
__typename: "TradeUpdate";
|
||||
/**
|
||||
* The hash of the trade data
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* RFC3339Nano time for when the trade occurred
|
||||
* The market the trade occurred on
|
||||
*/
|
||||
createdAt: string;
|
||||
/**
|
||||
* The price of the trade (probably initially the passive order price, other determination algorithms are possible though) (uint64)
|
||||
*/
|
||||
price: string;
|
||||
/**
|
||||
* The number of contracts trades, will always be <= the remaining size of both orders immediately before the trade (uint64)
|
||||
*/
|
||||
size: string;
|
||||
marketId: string;
|
||||
/**
|
||||
* The order that bought
|
||||
*/
|
||||
@ -171,18 +59,34 @@ export interface FillsSub_trades {
|
||||
* The order that sold
|
||||
*/
|
||||
sellOrder: string;
|
||||
/**
|
||||
* The party that bought
|
||||
*/
|
||||
buyerId: string;
|
||||
/**
|
||||
* The party that sold
|
||||
*/
|
||||
sellerId: string;
|
||||
/**
|
||||
* The aggressor indicates whether this trade was related to a BUY or SELL
|
||||
*/
|
||||
aggressor: Side;
|
||||
/**
|
||||
* The party that bought
|
||||
* The price of the trade (probably initially the passive order price, other determination algorithms are possible though) (uint64)
|
||||
*/
|
||||
buyer: FillsSub_trades_buyer;
|
||||
price: string;
|
||||
/**
|
||||
* The party that sold
|
||||
* The number of units traded, will always be <= the remaining size of both orders immediately before the trade (uint64)
|
||||
*/
|
||||
seller: FillsSub_trades_seller;
|
||||
size: string;
|
||||
/**
|
||||
* RFC3339Nano time for when the trade occurred
|
||||
*/
|
||||
createdAt: string;
|
||||
/**
|
||||
* The type of trade
|
||||
*/
|
||||
type: TradeType;
|
||||
/**
|
||||
* The fee paid by the buyer side of the trade
|
||||
*/
|
||||
@ -191,10 +95,6 @@ export interface FillsSub_trades {
|
||||
* The fee paid by the seller side of the trade
|
||||
*/
|
||||
sellerFee: FillsSub_trades_sellerFee;
|
||||
/**
|
||||
* The market the trade occurred on
|
||||
*/
|
||||
market: FillsSub_trades_market;
|
||||
}
|
||||
|
||||
export interface FillsSub {
|
||||
|
@ -3,7 +3,7 @@ import { Schema as Types } from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type FillFieldsFragment = { __typename?: 'Trade', id: string, createdAt: string, price: string, size: string, buyOrder: string, sellOrder: string, aggressor: Types.Side, buyer: { __typename?: 'Party', id: string }, seller: { __typename?: 'Party', id: string }, buyerFee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, sellerFee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, market: { __typename?: 'Market', id: string, name: string, decimalPlaces: number, positionDecimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, code: string, product: { __typename?: 'Future', settlementAsset: { __typename?: 'Asset', id: string, symbol: string, decimals: number } } } } } };
|
||||
export type FillFieldsFragment = { __typename?: 'Trade', id: string, createdAt: string, price: string, size: string, buyOrder: string, sellOrder: string, aggressor: Types.Side, buyer: { __typename?: 'Party', id: string }, seller: { __typename?: 'Party', id: string }, buyerFee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, sellerFee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, code: string, product: { __typename?: 'Future', settlementAsset: { __typename?: 'Asset', id: string, symbol: string, decimals: number } } } } } };
|
||||
|
||||
export type FillsQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
@ -12,14 +12,14 @@ export type FillsQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type FillsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, tradesConnection: { __typename?: 'TradeConnection', edges: Array<{ __typename?: 'TradeEdge', cursor: string, node: { __typename?: 'Trade', id: string, createdAt: string, price: string, size: string, buyOrder: string, sellOrder: string, aggressor: Types.Side, buyer: { __typename?: 'Party', id: string }, seller: { __typename?: 'Party', id: string }, buyerFee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, sellerFee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, market: { __typename?: 'Market', id: string, name: string, decimalPlaces: number, positionDecimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, code: string, product: { __typename?: 'Future', settlementAsset: { __typename?: 'Asset', id: string, symbol: string, decimals: number } } } } } } }>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } } | null };
|
||||
export type FillsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, tradesConnection?: { __typename?: 'TradeConnection', edges: Array<{ __typename?: 'TradeEdge', cursor: string, node: { __typename?: 'Trade', id: string, createdAt: string, price: string, size: string, buyOrder: string, sellOrder: string, aggressor: Types.Side, buyer: { __typename?: 'Party', id: string }, seller: { __typename?: 'Party', id: string }, buyerFee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, sellerFee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, code: string, product: { __typename?: 'Future', settlementAsset: { __typename?: 'Asset', id: string, symbol: string, decimals: number } } } } } } }>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } | null } | null };
|
||||
|
||||
export type FillsSubSubscriptionVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type FillsSubSubscription = { __typename?: 'Subscription', trades?: Array<{ __typename?: 'Trade', id: string, createdAt: string, price: string, size: string, buyOrder: string, sellOrder: string, aggressor: Types.Side, buyer: { __typename?: 'Party', id: string }, seller: { __typename?: 'Party', id: string }, buyerFee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, sellerFee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, market: { __typename?: 'Market', id: string, name: string, decimalPlaces: number, positionDecimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, code: string, product: { __typename?: 'Future', settlementAsset: { __typename?: 'Asset', id: string, symbol: string, decimals: number } } } } } }> | null };
|
||||
export type FillsSubSubscription = { __typename?: 'Subscription', trades?: Array<{ __typename?: 'TradeUpdate', id: string, createdAt: string, price: string, size: string, buyOrder: string, sellOrder: string, aggressor: Types.Side, buyerId: string, sellerId: string, marketId: string, buyerFee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string }, sellerFee: { __typename?: 'TradeFee', makerFee: string, infrastructureFee: string, liquidityFee: string } }> | null };
|
||||
|
||||
export const FillFieldsFragmentDoc = gql`
|
||||
fragment FillFields on Trade {
|
||||
@ -48,7 +48,6 @@ export const FillFieldsFragmentDoc = gql`
|
||||
}
|
||||
market {
|
||||
id
|
||||
name
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
tradableInstrument {
|
||||
@ -123,10 +122,29 @@ export type FillsQueryResult = Apollo.QueryResult<FillsQuery, FillsQueryVariable
|
||||
export const FillsSubDocument = gql`
|
||||
subscription FillsSub($partyId: ID!) {
|
||||
trades(partyId: $partyId) {
|
||||
...FillFields
|
||||
id
|
||||
createdAt
|
||||
price
|
||||
size
|
||||
buyOrder
|
||||
sellOrder
|
||||
aggressor
|
||||
buyerId
|
||||
sellerId
|
||||
buyerFee {
|
||||
makerFee
|
||||
infrastructureFee
|
||||
liquidityFee
|
||||
}
|
||||
sellerFee {
|
||||
makerFee
|
||||
infrastructureFee
|
||||
liquidityFee
|
||||
}
|
||||
marketId
|
||||
}
|
||||
}
|
||||
${FillFieldsFragmentDoc}`;
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useFillsSubSubscription__
|
||||
|
@ -3,75 +3,52 @@ import orderBy from 'lodash/orderBy';
|
||||
import { gql } from '@apollo/client';
|
||||
import {
|
||||
makeDataProvider,
|
||||
makeDerivedDataProvider,
|
||||
defaultAppend as append,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
import { marketsProvider } from '@vegaprotocol/market-list';
|
||||
import type { PageInfo } from '@vegaprotocol/react-helpers';
|
||||
import type { FillFields } from './__generated__/FillFields';
|
||||
import type {
|
||||
Fills,
|
||||
Fills_party_tradesConnection_edges,
|
||||
Fills_party_tradesConnection_edges_node,
|
||||
} from './__generated__/Fills';
|
||||
import type { FillsSub } from './__generated__/FillsSub';
|
||||
|
||||
const FILL_FRAGMENT = gql`
|
||||
fragment FillFields on Trade {
|
||||
id
|
||||
createdAt
|
||||
price
|
||||
size
|
||||
buyOrder
|
||||
sellOrder
|
||||
aggressor
|
||||
buyer {
|
||||
id
|
||||
}
|
||||
seller {
|
||||
id
|
||||
}
|
||||
buyerFee {
|
||||
makerFee
|
||||
infrastructureFee
|
||||
liquidityFee
|
||||
}
|
||||
sellerFee {
|
||||
makerFee
|
||||
infrastructureFee
|
||||
liquidityFee
|
||||
}
|
||||
market {
|
||||
id
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
id
|
||||
code
|
||||
name
|
||||
product {
|
||||
... on Future {
|
||||
settlementAsset {
|
||||
id
|
||||
symbol
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
import type { FillsSub, FillsSub_trades } from './__generated__/FillsSub';
|
||||
|
||||
export const FILLS_QUERY = gql`
|
||||
${FILL_FRAGMENT}
|
||||
query Fills($partyId: ID!, $marketId: ID, $pagination: Pagination) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
tradesConnection(marketId: $marketId, pagination: $pagination) {
|
||||
edges {
|
||||
node {
|
||||
...FillFields
|
||||
id
|
||||
market {
|
||||
id
|
||||
}
|
||||
createdAt
|
||||
price
|
||||
size
|
||||
buyOrder
|
||||
sellOrder
|
||||
aggressor
|
||||
buyer {
|
||||
id
|
||||
}
|
||||
seller {
|
||||
id
|
||||
}
|
||||
buyerFee {
|
||||
makerFee
|
||||
infrastructureFee
|
||||
liquidityFee
|
||||
}
|
||||
sellerFee {
|
||||
makerFee
|
||||
infrastructureFee
|
||||
liquidityFee
|
||||
}
|
||||
}
|
||||
cursor
|
||||
}
|
||||
@ -87,17 +64,36 @@ export const FILLS_QUERY = gql`
|
||||
`;
|
||||
|
||||
export const FILLS_SUB = gql`
|
||||
${FILL_FRAGMENT}
|
||||
subscription FillsSub($partyId: ID!) {
|
||||
trades(partyId: $partyId) {
|
||||
...FillFields
|
||||
id
|
||||
marketId
|
||||
buyOrder
|
||||
sellOrder
|
||||
buyerId
|
||||
sellerId
|
||||
aggressor
|
||||
price
|
||||
size
|
||||
createdAt
|
||||
type
|
||||
buyerFee {
|
||||
makerFee
|
||||
infrastructureFee
|
||||
liquidityFee
|
||||
}
|
||||
sellerFee {
|
||||
makerFee
|
||||
infrastructureFee
|
||||
liquidityFee
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const update = (
|
||||
data: (Fills_party_tradesConnection_edges | null)[],
|
||||
delta: FillFields[]
|
||||
delta: FillsSub_trades[]
|
||||
) => {
|
||||
return produce(data, (draft) => {
|
||||
orderBy(delta, 'createdAt').forEach((node) => {
|
||||
@ -112,24 +108,43 @@ const update = (
|
||||
} else {
|
||||
const firstNode = draft[0]?.node;
|
||||
if (firstNode && node.createdAt >= firstNode.createdAt) {
|
||||
draft.unshift({ node, cursor: '', __typename: 'TradeEdge' });
|
||||
const { buyerId, sellerId, marketId, ...trade } = node;
|
||||
draft.unshift({
|
||||
node: {
|
||||
...trade,
|
||||
__typename: 'Trade',
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: marketId,
|
||||
},
|
||||
buyer: { id: buyerId, __typename: 'Party' },
|
||||
seller: { id: buyerId, __typename: 'Party' },
|
||||
},
|
||||
cursor: '',
|
||||
__typename: 'TradeEdge',
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const getData = (
|
||||
responseData: Fills
|
||||
): Fills_party_tradesConnection_edges[] | null =>
|
||||
responseData.party?.tradesConnection.edges || null;
|
||||
export type Trade = Fills_party_tradesConnection_edges_node;
|
||||
export type TradeWithMarket = Omit<Trade, 'market'> & { market?: Market };
|
||||
export type TradeWithMarketEdge = {
|
||||
cursor: Fills_party_tradesConnection_edges['cursor'];
|
||||
node: TradeWithMarket;
|
||||
};
|
||||
|
||||
const getData = (responseData: Fills): Fills_party_tradesConnection_edges[] =>
|
||||
responseData.party?.tradesConnection?.edges || [];
|
||||
|
||||
const getPageInfo = (responseData: Fills): PageInfo | null =>
|
||||
responseData.party?.tradesConnection.pageInfo || null;
|
||||
responseData.party?.tradesConnection?.pageInfo || null;
|
||||
|
||||
const getDelta = (subscriptionData: FillsSub) => subscriptionData.trades || [];
|
||||
|
||||
export const fillsDataProvider = makeDataProvider({
|
||||
export const fillsProvider = makeDataProvider({
|
||||
query: FILLS_QUERY,
|
||||
subscriptionQuery: FILLS_SUB,
|
||||
update,
|
||||
@ -141,3 +156,39 @@ export const fillsDataProvider = makeDataProvider({
|
||||
first: 100,
|
||||
},
|
||||
});
|
||||
|
||||
export const fillsWithMarketProvider = makeDerivedDataProvider<
|
||||
(TradeWithMarketEdge | null)[],
|
||||
TradeWithMarket[]
|
||||
>(
|
||||
[fillsProvider, marketsProvider],
|
||||
(partsData): (TradeWithMarketEdge | null)[] =>
|
||||
(partsData[0] as ReturnType<typeof getData>)?.map(
|
||||
(edge) =>
|
||||
edge && {
|
||||
cursor: edge.cursor,
|
||||
node: {
|
||||
...edge.node,
|
||||
market: (partsData[1] as Market[]).find(
|
||||
(market) => market.id === edge.node.market.id
|
||||
),
|
||||
},
|
||||
}
|
||||
) || null,
|
||||
(parts): TradeWithMarket[] | undefined => {
|
||||
if (!parts[0].isUpdate) {
|
||||
return;
|
||||
}
|
||||
// map FillsSub_trades[] from subscription to updated TradeWithMarket[]
|
||||
return (parts[0].delta as ReturnType<typeof getDelta>).map(
|
||||
(deltaTrade) => ({
|
||||
...((parts[0].data as ReturnType<typeof getData>)?.find(
|
||||
(trade) => trade.node.id === deltaTrade.id
|
||||
)?.node as Fills_party_tradesConnection_edges_node),
|
||||
market: (parts[1].data as Market[]).find(
|
||||
(market) => market.id === deltaTrade.marketId
|
||||
),
|
||||
})
|
||||
);
|
||||
}
|
||||
);
|
||||
|
@ -8,9 +8,11 @@ import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { FillsTable } from './fills-table';
|
||||
import type { BodyScrollEvent, BodyScrollEndEvent } from 'ag-grid-community';
|
||||
|
||||
import { fillsDataProvider as dataProvider } from './fills-data-provider';
|
||||
import type { Fills_party_tradesConnection_edges } from './__generated__/Fills';
|
||||
import type { FillsSub_trades } from './__generated__/FillsSub';
|
||||
import type {
|
||||
TradeWithMarket,
|
||||
TradeWithMarketEdge,
|
||||
} from './fills-data-provider';
|
||||
import { fillsWithMarketProvider } from './fills-data-provider';
|
||||
|
||||
interface FillsManagerProps {
|
||||
partyId: string;
|
||||
@ -18,9 +20,7 @@ interface FillsManagerProps {
|
||||
|
||||
export const FillsManager = ({ partyId }: FillsManagerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const dataRef = useRef<(Fills_party_tradesConnection_edges | null)[] | null>(
|
||||
null
|
||||
);
|
||||
const dataRef = useRef<(TradeWithMarketEdge | null)[] | null>(null);
|
||||
const totalCountRef = useRef<number | undefined>(undefined);
|
||||
const newRows = useRef(0);
|
||||
const scrolledToTop = useRef(true);
|
||||
@ -44,8 +44,8 @@ export const FillsManager = ({ partyId }: FillsManagerProps) => {
|
||||
data,
|
||||
delta,
|
||||
}: {
|
||||
data: (Fills_party_tradesConnection_edges | null)[];
|
||||
delta: FillsSub_trades[];
|
||||
data: (TradeWithMarketEdge | null)[] | null;
|
||||
delta: TradeWithMarket[];
|
||||
}) => {
|
||||
if (!gridRef.current?.api) {
|
||||
return false;
|
||||
@ -70,7 +70,7 @@ export const FillsManager = ({ partyId }: FillsManagerProps) => {
|
||||
data,
|
||||
totalCount,
|
||||
}: {
|
||||
data: (Fills_party_tradesConnection_edges | null)[];
|
||||
data: (TradeWithMarketEdge | null)[] | null;
|
||||
totalCount?: number;
|
||||
}) => {
|
||||
dataRef.current = data;
|
||||
@ -83,13 +83,13 @@ export const FillsManager = ({ partyId }: FillsManagerProps) => {
|
||||
const variables = useMemo(() => ({ partyId }), [partyId]);
|
||||
|
||||
const { data, error, loading, load, totalCount } = useDataProvider<
|
||||
(Fills_party_tradesConnection_edges | null)[],
|
||||
FillsSub_trades[]
|
||||
>({ dataProvider, update, insert, variables });
|
||||
(TradeWithMarketEdge | null)[],
|
||||
TradeWithMarket[]
|
||||
>({ dataProvider: fillsWithMarketProvider, update, insert, variables });
|
||||
totalCountRef.current = totalCount;
|
||||
dataRef.current = data;
|
||||
|
||||
const getRows = makeInfiniteScrollGetRows<Fills_party_tradesConnection_edges>(
|
||||
const getRows = makeInfiniteScrollGetRows<TradeWithMarketEdge>(
|
||||
newRows,
|
||||
dataRef,
|
||||
totalCountRef,
|
||||
|
@ -2,10 +2,10 @@ import { render, screen, waitFor } from '@testing-library/react';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/react-helpers';
|
||||
import { Side } from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type { TradeWithMarket } from './fills-data-provider';
|
||||
|
||||
import { FillsTable } from './fills-table';
|
||||
import { generateFill } from './test-helpers';
|
||||
import type { FillFields } from './__generated__/FillFields';
|
||||
|
||||
const waitForGridToBeInTheDOM = () => {
|
||||
return waitFor(() => {
|
||||
@ -21,7 +21,7 @@ const waitForDataToHaveLoaded = () => {
|
||||
};
|
||||
|
||||
describe('FillsTable', () => {
|
||||
let defaultFill: PartialDeep<FillFields>;
|
||||
let defaultFill: PartialDeep<TradeWithMarket>;
|
||||
|
||||
beforeEach(() => {
|
||||
defaultFill = {
|
||||
@ -87,7 +87,7 @@ describe('FillsTable', () => {
|
||||
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
const expectedValues = [
|
||||
buyerFill.market.tradableInstrument.instrument.name,
|
||||
buyerFill.market?.tradableInstrument.instrument.name || '',
|
||||
'+3.00000',
|
||||
'1.00 BTC',
|
||||
'3.00 BTC',
|
||||
@ -124,7 +124,7 @@ describe('FillsTable', () => {
|
||||
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
const expectedValues = [
|
||||
buyerFill.market.tradableInstrument.instrument.name,
|
||||
buyerFill.market?.tradableInstrument.instrument.name || '',
|
||||
'+3.00000',
|
||||
'1.00 BTC',
|
||||
'3.00 BTC',
|
||||
@ -161,7 +161,7 @@ describe('FillsTable', () => {
|
||||
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
const expectedValues = [
|
||||
buyerFill.market.tradableInstrument.instrument.name,
|
||||
buyerFill.market?.tradableInstrument.instrument.name || '',
|
||||
'-3.00000',
|
||||
'1.00 BTC',
|
||||
'3.00 BTC',
|
||||
|
@ -1,14 +1,7 @@
|
||||
import type { Story, Meta } from '@storybook/react';
|
||||
import type { Props } from './fills-table';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { AsyncRenderer, Button } from '@vegaprotocol/ui-toolkit';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { makeInfiniteScrollGetRows } from '@vegaprotocol/react-helpers';
|
||||
import { FillsTable } from './fills-table';
|
||||
import { generateFills, generateFill } from './test-helpers';
|
||||
import type { Fills_party_tradesConnection_edges } from './__generated__/Fills';
|
||||
import type { FillsSub_trades } from './__generated__/FillsSub';
|
||||
import type { BodyScrollEvent, BodyScrollEndEvent } from 'ag-grid-community';
|
||||
import { generateFill } from './test-helpers';
|
||||
|
||||
export default {
|
||||
component: FillsTable,
|
||||
@ -18,330 +11,9 @@ export default {
|
||||
const Template: Story<Props> = (args) => <FillsTable {...args} />;
|
||||
export const Default = Template.bind({});
|
||||
|
||||
const createdAt = new Date('2005-04-02 21:37:00').getTime();
|
||||
const fills = generateFills();
|
||||
Default.args = {
|
||||
partyId: 'party-id',
|
||||
rowData: fills.party?.tradesConnection.edges.map((e) => e.node) || [],
|
||||
rowData: Array(5)
|
||||
.fill(null)
|
||||
.map(() => generateFill()),
|
||||
};
|
||||
|
||||
const getData = (
|
||||
start: number,
|
||||
end: number
|
||||
): Fills_party_tradesConnection_edges[] =>
|
||||
new Array(end - start).fill(null).map((v, i) => ({
|
||||
__typename: 'TradeEdge',
|
||||
node: generateFill({
|
||||
id: (start + i).toString(),
|
||||
createdAt: new Date(createdAt - 1000 * (start + i)).toISOString(),
|
||||
}),
|
||||
cursor: (start + i).toString(),
|
||||
}));
|
||||
|
||||
const totalCount = 550;
|
||||
const partyId = 'partyId';
|
||||
|
||||
const useDataProvider = ({
|
||||
insert,
|
||||
}: {
|
||||
insert: ({
|
||||
insertionData,
|
||||
data,
|
||||
totalCount,
|
||||
}: {
|
||||
insertionData: Fills_party_tradesConnection_edges[];
|
||||
data: Fills_party_tradesConnection_edges[];
|
||||
totalCount?: number;
|
||||
}) => boolean;
|
||||
}) => {
|
||||
const data = [...getData(0, 100), ...new Array(totalCount - 100).fill(null)];
|
||||
return {
|
||||
data,
|
||||
error: null,
|
||||
loading: false,
|
||||
load: (start?: number, end?: number) => {
|
||||
if (start === undefined) {
|
||||
start = data.findIndex((v) => !v);
|
||||
}
|
||||
if (end === undefined) {
|
||||
end = start + 100;
|
||||
}
|
||||
end = Math.min(end, totalCount);
|
||||
const insertionData = getData(start, end);
|
||||
data.splice(start, end - start, ...insertionData);
|
||||
insert({ data, totalCount, insertionData });
|
||||
return Promise.resolve(insertionData);
|
||||
},
|
||||
totalCount,
|
||||
};
|
||||
};
|
||||
|
||||
interface PaginationManagerProps {
|
||||
pagination: boolean;
|
||||
}
|
||||
|
||||
const PaginationManager = ({ pagination }: PaginationManagerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const dataRef = useRef<Fills_party_tradesConnection_edges[] | null>(null);
|
||||
const totalCountRef = useRef<number | undefined>(undefined);
|
||||
const newRows = useRef(0);
|
||||
const scrolledToTop = useRef(true);
|
||||
|
||||
const addNewRows = useCallback(() => {
|
||||
if (newRows.current === 0) {
|
||||
return;
|
||||
}
|
||||
if (totalCountRef.current !== undefined) {
|
||||
totalCountRef.current += newRows.current;
|
||||
}
|
||||
newRows.current = 0;
|
||||
if (!gridRef.current?.api) {
|
||||
return;
|
||||
}
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
}, []);
|
||||
|
||||
const update = useCallback(
|
||||
({
|
||||
data,
|
||||
delta,
|
||||
}: {
|
||||
data: Fills_party_tradesConnection_edges[];
|
||||
delta: FillsSub_trades[];
|
||||
}) => {
|
||||
if (!gridRef.current?.api) {
|
||||
return false;
|
||||
}
|
||||
if (!scrolledToTop.current) {
|
||||
const createdAt = dataRef.current?.[0].node.createdAt;
|
||||
if (createdAt) {
|
||||
newRows.current += delta.filter(
|
||||
(trade) => trade.createdAt > createdAt
|
||||
).length;
|
||||
}
|
||||
}
|
||||
dataRef.current = data;
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
return true;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const insert = useCallback(
|
||||
({
|
||||
data,
|
||||
totalCount,
|
||||
}: {
|
||||
data: Fills_party_tradesConnection_edges[];
|
||||
totalCount?: number;
|
||||
}) => {
|
||||
dataRef.current = data;
|
||||
totalCountRef.current = totalCount;
|
||||
return true;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const { data, error, loading, load, totalCount } = useDataProvider({
|
||||
insert,
|
||||
});
|
||||
|
||||
totalCountRef.current = totalCount;
|
||||
dataRef.current = data;
|
||||
|
||||
const getRows = makeInfiniteScrollGetRows<Fills_party_tradesConnection_edges>(
|
||||
newRows,
|
||||
dataRef,
|
||||
totalCountRef,
|
||||
load
|
||||
);
|
||||
|
||||
const onBodyScrollEnd = (event: BodyScrollEndEvent) => {
|
||||
if (event.top === 0) {
|
||||
addNewRows();
|
||||
}
|
||||
};
|
||||
|
||||
const onBodyScroll = (event: BodyScrollEvent) => {
|
||||
scrolledToTop.current = event.top <= 0;
|
||||
};
|
||||
|
||||
// id and onclick is needed only for mocked data
|
||||
let id = 0;
|
||||
const onClick = () => {
|
||||
if (!dataRef.current) {
|
||||
return;
|
||||
}
|
||||
const node = generateFill({
|
||||
id: (--id).toString(),
|
||||
createdAt: new Date(createdAt - 1000 * id).toISOString(),
|
||||
});
|
||||
update({
|
||||
data: [
|
||||
{ cursor: '0', node, __typename: 'TradeEdge' },
|
||||
...dataRef.current,
|
||||
],
|
||||
delta: [node],
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onClick={onClick} size="sm">
|
||||
Add row on top
|
||||
</Button>
|
||||
<AsyncRenderer loading={loading} error={error} data={data}>
|
||||
<FillsTable
|
||||
rowModelType="infinite"
|
||||
pagination={pagination}
|
||||
ref={gridRef}
|
||||
partyId={partyId}
|
||||
datasource={{ getRows }}
|
||||
onBodyScrollEnd={onBodyScrollEnd}
|
||||
onBodyScroll={onBodyScroll}
|
||||
/>
|
||||
</AsyncRenderer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const PaginationTemplate: Story<PaginationManagerProps> = (args) => (
|
||||
<PaginationManager {...args} />
|
||||
);
|
||||
|
||||
export const Pagination = PaginationTemplate.bind({});
|
||||
Pagination.args = { pagination: true };
|
||||
|
||||
export const PaginationScroll = PaginationTemplate.bind({});
|
||||
PaginationScroll.args = { pagination: false };
|
||||
|
||||
const InfiniteScrollManager = () => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const dataRef = useRef<(Fills_party_tradesConnection_edges | null)[] | null>(
|
||||
null
|
||||
);
|
||||
const totalCountRef = useRef<number | undefined>(undefined);
|
||||
const newRows = useRef(0);
|
||||
const scrolledToTop = useRef(true);
|
||||
|
||||
const addNewRows = useCallback(() => {
|
||||
if (newRows.current === 0) {
|
||||
return;
|
||||
}
|
||||
if (totalCountRef.current !== undefined) {
|
||||
totalCountRef.current += newRows.current;
|
||||
}
|
||||
newRows.current = 0;
|
||||
if (!gridRef.current?.api) {
|
||||
return;
|
||||
}
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
}, []);
|
||||
|
||||
const update = useCallback(
|
||||
({
|
||||
data,
|
||||
delta,
|
||||
}: {
|
||||
data: (Fills_party_tradesConnection_edges | null)[];
|
||||
delta: FillsSub_trades[];
|
||||
}) => {
|
||||
if (!gridRef.current?.api) {
|
||||
return false;
|
||||
}
|
||||
if (!scrolledToTop.current) {
|
||||
const createdAt = dataRef.current?.[0]?.node.createdAt;
|
||||
if (createdAt) {
|
||||
newRows.current += delta.filter(
|
||||
(trade) => trade.createdAt > createdAt
|
||||
).length;
|
||||
}
|
||||
}
|
||||
dataRef.current = data;
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
return true;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const insert = useCallback(
|
||||
({
|
||||
data,
|
||||
totalCount,
|
||||
}: {
|
||||
data: Fills_party_tradesConnection_edges[];
|
||||
totalCount?: number;
|
||||
}) => {
|
||||
dataRef.current = data;
|
||||
totalCountRef.current = totalCount;
|
||||
return true;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const { data, error, loading, load, totalCount } = useDataProvider({
|
||||
insert,
|
||||
});
|
||||
totalCountRef.current = totalCount;
|
||||
dataRef.current = data;
|
||||
|
||||
const getRows = makeInfiniteScrollGetRows<Fills_party_tradesConnection_edges>(
|
||||
newRows,
|
||||
dataRef,
|
||||
totalCountRef,
|
||||
load
|
||||
);
|
||||
|
||||
const onBodyScrollEnd = (event: BodyScrollEndEvent) => {
|
||||
if (event.top === 0) {
|
||||
addNewRows();
|
||||
}
|
||||
};
|
||||
|
||||
const onBodyScroll = (event: BodyScrollEvent) => {
|
||||
scrolledToTop.current = event.top <= 0;
|
||||
};
|
||||
|
||||
// id and onclick is needed only for mocked data
|
||||
let id = 0;
|
||||
const onClick = () => {
|
||||
if (!dataRef.current) {
|
||||
return;
|
||||
}
|
||||
const node = generateFill({
|
||||
id: (--id).toString(),
|
||||
createdAt: new Date(createdAt - 1000 * id).toISOString(),
|
||||
});
|
||||
update({
|
||||
data: [
|
||||
{ cursor: '0', node, __typename: 'TradeEdge' },
|
||||
...dataRef.current,
|
||||
],
|
||||
delta: [node],
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Button onClick={onClick} size="sm">
|
||||
Add row on top
|
||||
</Button>
|
||||
<AsyncRenderer loading={loading} error={error} data={data}>
|
||||
<FillsTable
|
||||
ref={gridRef}
|
||||
partyId={partyId}
|
||||
datasource={{ getRows }}
|
||||
rowModelType="infinite"
|
||||
onBodyScroll={onBodyScroll}
|
||||
onBodyScrollEnd={onBodyScrollEnd}
|
||||
/>
|
||||
</AsyncRenderer>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const InfiniteScrollTemplate: Story<Record<string, never>> = () => (
|
||||
<InfiniteScrollManager />
|
||||
);
|
||||
|
||||
export const InfiniteScroll = InfiniteScrollTemplate.bind({});
|
||||
|
@ -15,11 +15,8 @@ import { forwardRef } from 'react';
|
||||
import type { ValueFormatterParams } from 'ag-grid-community';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
|
||||
import type {
|
||||
FillFields,
|
||||
FillFields_market_tradableInstrument_instrument_product,
|
||||
} from './__generated__/FillFields';
|
||||
import type { Fills_party_tradesConnection_edges_node } from './__generated__/Fills';
|
||||
import type { TradeWithMarket } from './fills-data-provider';
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export type Props = (AgGridReactProps | AgReactUiProps) & {
|
||||
@ -30,7 +27,7 @@ type AccountsTableValueFormatterParams = Omit<
|
||||
ValueFormatterParams,
|
||||
'data' | 'value'
|
||||
> & {
|
||||
data: Fills_party_tradesConnection_edges_node | null;
|
||||
data: TradeWithMarket | null;
|
||||
};
|
||||
|
||||
export const FillsTable = forwardRef<AgGridReact, Props>(
|
||||
@ -52,7 +49,7 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
|
||||
headerName={t('Size')}
|
||||
type="rightAligned"
|
||||
field="size"
|
||||
cellClass={({ data }: { data: FillFields }) => {
|
||||
cellClass={({ data }: { data: TradeWithMarket }) => {
|
||||
return classNames('text-right', {
|
||||
[positiveClassNames]: data?.buyer.id === partyId,
|
||||
[negativeClassNames]: data?.seller.id,
|
||||
@ -89,7 +86,7 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
|
||||
valueFormatter={({
|
||||
value,
|
||||
}: AccountsTableValueFormatterParams & {
|
||||
value: Fills_party_tradesConnection_edges_node['createdAt'];
|
||||
value: TradeWithMarket['createdAt'];
|
||||
}) => {
|
||||
if (value === undefined) {
|
||||
return value;
|
||||
@ -106,9 +103,9 @@ const formatPrice = ({
|
||||
value,
|
||||
data,
|
||||
}: AccountsTableValueFormatterParams & {
|
||||
value?: Fills_party_tradesConnection_edges_node['price'];
|
||||
value?: TradeWithMarket['price'];
|
||||
}) => {
|
||||
if (value === undefined || !data) {
|
||||
if (value === undefined || !data || !data?.market) {
|
||||
return undefined;
|
||||
}
|
||||
const asset =
|
||||
@ -125,9 +122,9 @@ const formatSize = (partyId: string) => {
|
||||
value,
|
||||
data,
|
||||
}: AccountsTableValueFormatterParams & {
|
||||
value?: Fills_party_tradesConnection_edges_node['size'];
|
||||
value?: TradeWithMarket['size'];
|
||||
}) => {
|
||||
if (value === undefined || !data) {
|
||||
if (value === undefined || !data || !data?.market) {
|
||||
return undefined;
|
||||
}
|
||||
let prefix;
|
||||
@ -149,9 +146,9 @@ const formatTotal = ({
|
||||
value,
|
||||
data,
|
||||
}: AccountsTableValueFormatterParams & {
|
||||
value?: Fills_party_tradesConnection_edges_node['price'];
|
||||
value?: TradeWithMarket['price'];
|
||||
}) => {
|
||||
if (value === undefined || !data) {
|
||||
if (value === undefined || !data || !data?.market) {
|
||||
return undefined;
|
||||
}
|
||||
const asset =
|
||||
@ -171,7 +168,7 @@ const formatRole = (partyId: string) => {
|
||||
value,
|
||||
data,
|
||||
}: AccountsTableValueFormatterParams & {
|
||||
value?: Fills_party_tradesConnection_edges_node['aggressor'];
|
||||
value?: TradeWithMarket['aggressor'];
|
||||
}) => {
|
||||
if (value === undefined) {
|
||||
return value;
|
||||
@ -201,7 +198,7 @@ const formatFee = (partyId: string) => {
|
||||
value,
|
||||
data,
|
||||
}: AccountsTableValueFormatterParams & {
|
||||
value?: FillFields_market_tradableInstrument_instrument_product;
|
||||
value?: Market['tradableInstrument']['instrument']['product'];
|
||||
}) => {
|
||||
if (value === undefined) {
|
||||
return value;
|
||||
|
@ -1,90 +1,10 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type {
|
||||
Fills,
|
||||
Fills_party_tradesConnection_edges_node,
|
||||
} from './__generated__/Fills';
|
||||
import { Side } from '@vegaprotocol/types';
|
||||
import { MarketState, MarketTradingMode, Side } from '@vegaprotocol/types';
|
||||
import type { TradeWithMarket } from './fills-data-provider';
|
||||
|
||||
export const generateFills = (override?: PartialDeep<Fills>): Fills => {
|
||||
const fills: Fills_party_tradesConnection_edges_node[] = [
|
||||
generateFill({
|
||||
buyer: {
|
||||
id: 'party-id',
|
||||
},
|
||||
}),
|
||||
generateFill({
|
||||
id: '1',
|
||||
seller: {
|
||||
id: 'party-id',
|
||||
},
|
||||
aggressor: Side.SIDE_SELL,
|
||||
buyerFee: {
|
||||
infrastructureFee: '5000',
|
||||
},
|
||||
market: {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'Apples Daily v3',
|
||||
},
|
||||
},
|
||||
positionDecimalPlaces: 2,
|
||||
},
|
||||
}),
|
||||
generateFill({
|
||||
id: '2',
|
||||
seller: {
|
||||
id: 'party-id',
|
||||
},
|
||||
aggressor: Side.SIDE_BUY,
|
||||
}),
|
||||
generateFill({
|
||||
id: '3',
|
||||
aggressor: Side.SIDE_SELL,
|
||||
market: {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'ETHBTC Quarterly (30 Jun 2022)',
|
||||
},
|
||||
},
|
||||
},
|
||||
buyer: {
|
||||
id: 'party-id',
|
||||
},
|
||||
}),
|
||||
];
|
||||
|
||||
const defaultResult: Fills = {
|
||||
party: {
|
||||
id: 'buyer-id',
|
||||
tradesConnection: {
|
||||
__typename: 'TradeConnection',
|
||||
edges: fills.map((f) => {
|
||||
return {
|
||||
__typename: 'TradeEdge',
|
||||
node: f,
|
||||
cursor: '3',
|
||||
};
|
||||
}),
|
||||
pageInfo: {
|
||||
__typename: 'PageInfo',
|
||||
startCursor: '1',
|
||||
endCursor: '2',
|
||||
hasNextPage: false,
|
||||
hasPreviousPage: false,
|
||||
},
|
||||
},
|
||||
__typename: 'Party',
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
|
||||
export const generateFill = (
|
||||
override?: PartialDeep<Fills_party_tradesConnection_edges_node>
|
||||
) => {
|
||||
const defaultFill: Fills_party_tradesConnection_edges_node = {
|
||||
export const generateFill = (override?: PartialDeep<TradeWithMarket>) => {
|
||||
const defaultFill: TradeWithMarket = {
|
||||
__typename: 'Trade',
|
||||
id: '0',
|
||||
createdAt: '2005-04-02T19:37:00.000Z',
|
||||
@ -118,6 +38,22 @@ export const generateFill = (
|
||||
id: 'market-id',
|
||||
positionDecimalPlaces: 0,
|
||||
decimalPlaces: 5,
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
fees: {
|
||||
__typename: 'Fees',
|
||||
factors: {
|
||||
__typename: 'FeeFactors',
|
||||
infrastructureFee: '0.1',
|
||||
liquidityFee: '0.1',
|
||||
makerFee: '0.1',
|
||||
},
|
||||
},
|
||||
marketTimestamps: {
|
||||
__typename: 'MarketTimestamps',
|
||||
open: '2005-04-02T19:37:00.000Z',
|
||||
close: '2005-04-02T19:37:00.000Z',
|
||||
},
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
@ -125,14 +61,18 @@ export const generateFill = (
|
||||
id: 'instrument-id',
|
||||
code: 'instrument-code',
|
||||
name: 'UNIDAI Monthly (30 Jun 2022)',
|
||||
metadata: {
|
||||
__typename: 'InstrumentMetadata',
|
||||
tags: ['tag-a'],
|
||||
},
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
settlementAsset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id',
|
||||
symbol: 'SYM',
|
||||
decimals: 18,
|
||||
},
|
||||
quoteName: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -28,7 +28,7 @@ export interface ProposalEvent_busEvents_event_Proposal {
|
||||
*/
|
||||
state: ProposalState;
|
||||
/**
|
||||
* Reason for the proposal to be rejected by the core
|
||||
* Why the proposal was rejected by the core
|
||||
*/
|
||||
rejectionReason: ProposalRejectionReason | null;
|
||||
/**
|
||||
|
@ -16,14 +16,15 @@ type Proposal = {
|
||||
type ProposalEdge = {
|
||||
node: Proposal;
|
||||
};
|
||||
type ProposalEdges = {
|
||||
edges: (ProposalEdge | null)[] | null;
|
||||
};
|
||||
type ProposalsConnection = {
|
||||
proposalsConnection: {
|
||||
edges: (ProposalEdge | null)[] | null;
|
||||
};
|
||||
proposalsConnection: ProposalEdges | null;
|
||||
};
|
||||
|
||||
export const getProposals = (data?: ProposalsConnection) => {
|
||||
const proposals = data?.proposalsConnection.edges
|
||||
const proposals = data?.proposalsConnection?.edges
|
||||
?.filter((e) => e?.node)
|
||||
.map((e) => e?.node);
|
||||
return proposals ? (proposals as Proposal[]) : [];
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*", "__generated__"],
|
||||
"ignorePatterns": ["!**/*", "__generated__", "__generated___"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user