Compare commits

...

54 Commits

Author SHA1 Message Date
Matthew Russell
39cc5743bf
chore: fix candles queries 2022-09-19 13:12:13 -07:00
Bartłomiej Głownia
666c3d3c24 Merge remote-tracking branch 'origin/develop' into feat/subscriptions-update 2022-09-19 15:48:20 +02:00
Bartłomiej Głownia
ab5c0feb39 chore: fix market-selector tests 2022-09-19 14:29:49 +02:00
Bartłomiej Głownia
84d1511972 chore: use markets only in market selector, change Instrument cache policy 2022-09-19 14:12:39 +02:00
Bartłomiej Głownia
e8034b91ae chore: fix market-trade tests 2022-09-19 12:57:17 +02:00
Bartłomiej Głownia
779f2375f5 chore: fix console lite e2e mocks 2022-09-19 11:26:50 +02:00
Bartłomiej Głownia
545b469ddf chore: fix trading orders e2e tests 2022-09-16 17:00:46 +02:00
maciek
e5c9b7fad9 feat: [stagnet3 api update] - remove redundant command in tests 2022-09-16 16:28:53 +02:00
maciek
b97728cf77 Merge remote-tracking branch 'origin/develop' into feat/subscriptions-update 2022-09-16 16:13:43 +02:00
maciek
f291be76cd feat: [stagnet3 api update] - remove redundant command in tests 2022-09-16 16:13:20 +02:00
asiaznik
3cc5cd35cd cypress: trading-fills 2022-09-16 14:44:34 +02:00
Bartłomiej Głownia
d901601986 chore: add pagination hangdling to derived data provier 2022-09-16 14:27:17 +02:00
maciek
5452bcd7a4 feat: [subscription-update] - improve wrongly renamed hook 3 2022-09-16 11:49:23 +02:00
maciek
12c32b440d feat: [subscription-update] - improve wrongly renamed hook 2022-09-16 11:32:54 +02:00
maciek
b122b4a135 Merge remote-tracking branch 'origin/develop' into feat/subscriptions-update 2022-09-16 11:20:34 +02:00
maciek
7170068121 Merge branch 'feat/subscriptions-update' of https://github.com/vegaprotocol/frontend-monorepo into feat/subscriptions-update 2022-09-16 11:20:06 +02:00
maciek
3caf0dc816 feat: [subscription-update] - improve wrongly renamed hook 2022-09-16 11:19:32 +02:00
Bartłomiej Głownia
b1414da420 chore: ignore gql errors, to be reverted after candlesConnectio n will be fixed 2022-09-16 11:05:31 +02:00
Bartłomiej Głownia
094b41e8ef chore: replace market candles with candlesConnection 2022-09-16 10:42:13 +02:00
asiaznik
c3675cb900 cypress: trading-accounts 2022-09-16 10:18:52 +02:00
maciek
29b6f9f3e5 feat: [subscription-update] - uncomment some console-lite tests 2022-09-16 09:03:09 +02:00
Bartłomiej Głownia
569031bef4 chore: fix e2e projects mock types 2022-09-15 17:47:40 +02:00
Bartłomiej Głownia
7fe68e03bc chore: disable simple market list tests 2022-09-15 17:11:01 +02:00
asiaznik
d616b1f4a2 removed mocked response 2022-09-15 16:47:46 +02:00
asiaznik
f9f5177dca increased test timeout to 10s 2022-09-15 15:23:24 +02:00
asiaznik
8e31a98b09 removed redundant waitFor 2022-09-15 15:03:37 +02:00
asiaznik
51a96b4932 changed main-branch-name to develop for pr workflows 2022-09-15 14:41:52 +02:00
asiaznik
c7586f366c added unique key to the list element of simple market toolbar 2022-09-15 14:39:43 +02:00
asiaznik
41939c02b7 added eslint ingore for generated files in liquidity 2022-09-15 13:26:24 +02:00
asiaznik
3107214c93 orders unit tests fixes 2022-09-15 13:21:55 +02:00
asiaznik
0f6e980cb1 fills unit tests fixes 2022-09-15 12:39:07 +02:00
Bartłomiej Głownia
d15d37b485 chore: derivedDataProvider fixes 2022-09-15 11:03:02 +02:00
Bartłomiej Głownia
b83931138c chore: revert order-list.stories.tsx 2022-09-15 10:12:57 +02:00
Bartłomiej Głownia
32d205f0f5 chore: fix possible null types 2022-09-15 09:53:11 +02:00
Bartłomiej Głownia
f1ea57b50e chore: fix Order type 2022-09-15 09:46:38 +02:00
Bartłomiej Głownia
37aafeebe4 chore: update account, fills and orders subscriptions in data providers 2022-09-15 08:19:33 +02:00
Bartłomiej Głownia
7b1bd0384a chore: update account, fills and orders subscriptions in data providers 2022-09-14 18:29:10 +02:00
asiaznik
c84e0e672c Merge branch 'feat/subscriptions-update' of https://github.com/vegaprotocol/frontend-monorepo into feat/subscriptions-update 2022-09-14 16:11:22 +02:00
asiaznik
e2374aad8d removed taker fee mapping (renamed to maker fee) 2022-09-14 16:11:12 +02:00
Bartłomiej Głownia
d429df640c chore: handle updates in derived market provider, update orders 2022-09-14 14:59:46 +02:00
asiaznik
72168be413 fixed positions 2022-09-14 14:18:27 +02:00
asiaznik
9120238303 regen types 2022-09-14 13:58:17 +02:00
asiaznik
ded465a856 regen types, removed market name 2022-09-14 13:57:28 +02:00
asiaznik
48675af654 fixed accounts build errors and unit tests 2022-09-14 12:36:25 +02:00
asiaznik
776985b7fd fixes liquidity data provider 2022-09-14 12:14:49 +02:00
asiaznik
eba2a8ac70 type aligning of assets and proposals 2022-09-14 11:53:45 +02:00
Bartłomiej Głownia
da12f0b5cd chore: update account, fills and orders subscriptions in data providers 2022-09-14 11:41:19 +02:00
asiaznik
be7d6073b6 fixed console-lite unit tests, uncommented quote name 2022-09-14 11:14:57 +02:00
Bartłomiej Głownia
ab20c2314f chore: update account, fills and orders subscriptions in data providers 2022-09-13 20:39:27 +02:00
asiaznik
7cbca79146 fixing types in general - regen 2022-09-13 18:12:29 +02:00
asiaznik
7bf1f26cdf Merge branch 'feat/subscriptions-update' of https://github.com/vegaprotocol/frontend-monorepo into feat/subscriptions-update 2022-09-13 17:46:12 +02:00
asiaznik
f1097b76fc fixing console-lite 2022-09-13 17:45:59 +02:00
Bartłomiej Głownia
9ffe28be0b chore: update account, fills and orders subscriptions in data providers 2022-09-13 17:26:10 +02:00
Bartłomiej Głownia
434df13079 chore: update account, fills and orders subscriptions in data providers 2022-09-13 13:03:57 +02:00
170 changed files with 2959 additions and 3375 deletions

View File

@ -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

View File

@ -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');

View File

@ -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(

View File

@ -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);
}
});
});

View File

@ -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

View File

@ -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';

View File

@ -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;
}

View File

@ -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`

View File

@ -1,5 +0,0 @@
subscription CandleLive($marketId: ID!) {
candles(marketId: $marketId, interval: INTERVAL_I1H) {
close
}
}

View File

@ -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
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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>;

View File

@ -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 || {}),
};

View File

@ -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;

View File

@ -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();

View File

@ -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]"

View File

@ -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

View File

@ -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);

View File

@ -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();
});
});

View File

@ -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;
}

View File

@ -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

View File

@ -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> = {

View File

@ -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 {

View File

@ -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 {

View File

@ -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`

View File

@ -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`

View File

@ -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')}

View File

@ -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;

View File

@ -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[]>

View File

@ -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

View File

@ -38,6 +38,9 @@ export function createClient(base?: string) {
Node: {
keyFields: false,
},
Instrument: {
keyFields: false,
},
},
});

View File

@ -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;
}

View File

@ -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`

View File

@ -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;
}

View File

@ -1,7 +1,6 @@
query MarketsQuery {
markets {
id
name
fees {
factors {
makerFee

View File

@ -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

View File

@ -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
}
}
}

View File

@ -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
}
}
}

View File

@ -18,6 +18,5 @@ query NodesQuery {
online
}
status
name
}
}

View File

@ -30,7 +30,6 @@ export const NodesQueryDocument = gql`
online
}
status
name
}
}
`;

View File

@ -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;
/**

View File

@ -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; }>;

View File

@ -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 {

View File

@ -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>
);
};

View File

@ -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;
}

View File

@ -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');

View File

@ -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());
});
});

View File

@ -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')

View File

@ -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',
},
};

View File

@ -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: {

View File

@ -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',
},
};

View File

@ -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',

View File

@ -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,

View File

@ -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',

View File

@ -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
}
}
}
}
}

View File

@ -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
}
}
}
}
}

View File

@ -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 {

View File

@ -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
}
}
}
}
}

View File

@ -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;

View File

@ -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;
}

View File

@ -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`

View File

@ -2,4 +2,5 @@ const { getJestProjects } = require('@nrwl/jest');
export default {
projects: getJestProjects(),
testTimeout: 10000,
};

View File

@ -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
}
}

View File

@ -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__

View File

@ -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,

View File

@ -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}>

View File

@ -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',

View File

@ -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';

View File

@ -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,
});

View File

@ -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';

View File

@ -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`

View 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>;

View File

@ -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
);

View File

@ -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
}
}
}
}
}

View File

@ -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
}
}
}
}
}

View File

@ -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)),

View File

@ -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';

View File

@ -1,7 +1,6 @@
query DealTicketQuery($marketId: ID!) {
market(id: $marketId) {
id
name
decimalPlaces
positionDecimalPlaces
state

View File

@ -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

View File

@ -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')

View File

@ -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 {

View File

@ -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 {

View File

@ -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
}
}
}
}
`;

View File

@ -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
}
}

View File

@ -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 {

View File

@ -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 {

View File

@ -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__

View File

@ -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
),
})
);
}
);

View File

@ -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,

View File

@ -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',

View File

@ -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({});

View File

@ -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;

View File

@ -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: '',
},
},
},

View File

@ -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;
/**

View File

@ -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[]) : [];

View File

@ -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