diff --git a/libs/fills/src/lib/fills-data-provider.ts b/libs/fills/src/lib/fills-data-provider.ts index 2470d6a76..2bef7d182 100644 --- a/libs/fills/src/lib/fills-data-provider.ts +++ b/libs/fills/src/lib/fills-data-provider.ts @@ -131,6 +131,10 @@ const update = ( export type Trade = Fills_party_tradesConnection_edges_node; export type TradeWithMarket = Omit & { market?: Market }; +export type TradeWithMarketEdge = { + cursor: Fills_party_tradesConnection_edges['cursor']; + node: TradeWithMarket; +}; const getData = ( responseData: Fills @@ -155,13 +159,35 @@ export const fillsProvider = makeDataProvider({ }, }); -export const fillsWithMarketProvider = makeDerivedDataProvider( +export const fillsWithMarketProvider = makeDerivedDataProvider< + TradeWithMarketEdge[], + TradeWithMarket[] +>( [fillsProvider, marketsProvider], - (parts): TradeWithMarket[] => - (parts[0] as Fills_party_tradesConnection_edges[]).map((edge) => ({ - ...edge.node, - market: (parts[1] as Market[]).find( - (market) => market.id === edge.node.market.id - ), - })) + (partsData): TradeWithMarketEdge[] => + (partsData[0] as Fills_party_tradesConnection_edges[]).map((edge) => ({ + cursor: edge.cursor, + node: { + ...edge.node, + market: (partsData[1] as Market[]).find( + (market) => market.id === edge.node.market.id + ), + }, + })), + (parts): TradeWithMarket[] | undefined => { + if (!parts[0].isUpdate) { + return; + } + // map FillsSub_trades[] from subscription to updated TradeWithMarket[] + return (parts[0].delta as ReturnType).map( + (deltaTrade) => ({ + ...((parts[0].data as ReturnType)?.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 + ), + }) + ); + } ); diff --git a/libs/fills/src/lib/fills-manager.tsx b/libs/fills/src/lib/fills-manager.tsx index a8852d0fb..298a70253 100644 --- a/libs/fills/src/lib/fills-manager.tsx +++ b/libs/fills/src/lib/fills-manager.tsx @@ -8,10 +8,11 @@ import { AsyncRenderer } from '@vegaprotocol/ui-toolkit'; import { FillsTable } from './fills-table'; import type { BodyScrollEvent, BodyScrollEndEvent } from 'ag-grid-community'; -import type { TradeWithMarket } from './fills-data-provider'; -import { fillsProvider } 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; @@ -19,9 +20,7 @@ interface FillsManagerProps { export const FillsManager = ({ partyId }: FillsManagerProps) => { const gridRef = useRef(null); - const dataRef = useRef<(Fills_party_tradesConnection_edges | null)[] | null>( - null - ); + const dataRef = useRef(null); const totalCountRef = useRef(undefined); const newRows = useRef(0); const scrolledToTop = useRef(true); @@ -45,8 +44,8 @@ export const FillsManager = ({ partyId }: FillsManagerProps) => { data, delta, }: { - data: (Fills_party_tradesConnection_edges | null)[]; - delta: FillsSub_trades[]; + data: TradeWithMarketEdge[]; + delta: TradeWithMarket[]; }) => { if (!gridRef.current?.api) { return false; @@ -71,7 +70,7 @@ export const FillsManager = ({ partyId }: FillsManagerProps) => { data, totalCount, }: { - data: (Fills_party_tradesConnection_edges | null)[]; + data: TradeWithMarketEdge[]; totalCount?: number; }) => { dataRef.current = data; @@ -84,13 +83,13 @@ export const FillsManager = ({ partyId }: FillsManagerProps) => { const variables = useMemo(() => ({ partyId }), [partyId]); const { data, error, loading, load, totalCount } = useDataProvider< - (TradeWithMarket | null)[], - FillsSub_trades[] - >({ dataProvider: fillsProvider, update, insert, variables }); + TradeWithMarketEdge[], + TradeWithMarket[] + >({ dataProvider: fillsWithMarketProvider, update, insert, variables }); totalCountRef.current = totalCount; dataRef.current = data; - const getRows = makeInfiniteScrollGetRows( + const getRows = makeInfiniteScrollGetRows( newRows, dataRef, totalCountRef, diff --git a/libs/market-list/src/lib/__generated__/MarketFields.ts b/libs/market-list/src/lib/__generated__/MarketFields.ts index 0bc400ec3..307906bd2 100644 --- a/libs/market-list/src/lib/__generated__/MarketFields.ts +++ b/libs/market-list/src/lib/__generated__/MarketFields.ts @@ -47,6 +47,10 @@ export interface MarketFields_tradableInstrument_instrument_product_settlementAs * 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 MarketFields_tradableInstrument_instrument_product { diff --git a/libs/market-list/src/lib/__generated__/Markets.ts b/libs/market-list/src/lib/__generated__/Markets.ts index 472312c9b..34813ea19 100644 --- a/libs/market-list/src/lib/__generated__/Markets.ts +++ b/libs/market-list/src/lib/__generated__/Markets.ts @@ -47,6 +47,10 @@ export interface Markets_marketsConnection_edges_node_tradableInstrument_instrum * 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 Markets_marketsConnection_edges_node_tradableInstrument_instrument_product { diff --git a/libs/market-list/src/lib/markets-provider.ts b/libs/market-list/src/lib/markets-provider.ts index 1b37980f4..5560a1d4f 100644 --- a/libs/market-list/src/lib/markets-provider.ts +++ b/libs/market-list/src/lib/markets-provider.ts @@ -45,6 +45,7 @@ const MARKET_DATA_FRAGMENT = gql` ... on Future { settlementAsset { symbol + decimals } quoteName } diff --git a/libs/orders/src/lib/components/order-data-provider/order-data-provider.ts b/libs/orders/src/lib/components/order-data-provider/order-data-provider.ts index f31fdf58d..8ae1caf33 100644 --- a/libs/orders/src/lib/components/order-data-provider/order-data-provider.ts +++ b/libs/orders/src/lib/components/order-data-provider/order-data-provider.ts @@ -161,10 +161,11 @@ export const ordersWithMarketProvider = makeDerivedDataProvider< ), }, })), - (parts) => { + (parts): OrderWithMarket[] | undefined => { if (!parts[0].isUpdate) { return; } + // map OrderSub_orders[] from subscription to updated OrderWithMarket[] return (parts[0].delta as ReturnType).map( (deltaOrder) => ({ ...((parts[0].data as ReturnType)?.find( diff --git a/libs/positions/src/lib/positions-data-providers.ts b/libs/positions/src/lib/positions-data-providers.ts index 5baf57258..57cedcfd1 100644 --- a/libs/positions/src/lib/positions-data-providers.ts +++ b/libs/positions/src/lib/positions-data-providers.ts @@ -268,15 +268,15 @@ export const positionsDataProvider = makeDataProvider< subscriptionData.positions, }); -export const positionsMetricsDataProvider = makeDerivedDataProvider( - [positionsDataProvider, accountsDataProvider], - ([positions, accounts]) => { - return sortBy( - getMetrics( - positions as Positions_party | null, - accounts as AccountFieldsFragment[] | null - ), - 'updatedAt' - ).reverse(); - } -); +export const positionsMetricsDataProvider = makeDerivedDataProvider< + Position[], + never +>([positionsDataProvider, accountsDataProvider], ([positions, accounts]) => { + return sortBy( + getMetrics( + positions as Positions_party | null, + accounts as AccountFieldsFragment[] | null + ), + 'updatedAt' + ).reverse(); +}); diff --git a/libs/react-helpers/src/lib/generic-data-provider.spec.ts b/libs/react-helpers/src/lib/generic-data-provider.spec.ts index fbcff1568..7970dc2b7 100644 --- a/libs/react-helpers/src/lib/generic-data-provider.spec.ts +++ b/libs/react-helpers/src/lib/generic-data-provider.spec.ts @@ -5,6 +5,7 @@ import { } from './generic-data-provider'; import type { CombineDerivedData, + CombineDerivedDelta, Query, UpdateCallback, Update, @@ -82,9 +83,15 @@ const combineData = jest.fn< Parameters> >(); +const combineDelta = jest.fn< + ReturnType>, + Parameters> +>(); + const derivedSubscribe = makeDerivedDataProvider( [subscribe, secondSubscribe], - combineData + combineData, + combineDelta ); const first = 100; diff --git a/libs/trades/src/index.ts b/libs/trades/src/index.ts index 9d3e4aee3..c1d822ac2 100644 --- a/libs/trades/src/index.ts +++ b/libs/trades/src/index.ts @@ -1,4 +1,3 @@ export * from './lib/trades-container'; -export * from './lib/__generated__/TradeFields'; export * from './lib/__generated__/Trades'; export * from './lib/__generated__/TradesSub'; diff --git a/libs/trades/src/lib/__generated__/TradeFields.ts b/libs/trades/src/lib/__generated__/TradeFields.ts deleted file mode 100644 index 60678676c..000000000 --- a/libs/trades/src/lib/__generated__/TradeFields.ts +++ /dev/null @@ -1,64 +0,0 @@ -/* tslint:disable */ -/* eslint-disable */ -// @generated -// This file was automatically generated and should not be edited. - -// ==================================================== -// GraphQL fragment: TradeFields -// ==================================================== - -export interface TradeFields_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; -} - -export interface TradeFields { - __typename: "Trade"; - /** - * The hash of the trade data - */ - id: 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; - /** - * RFC3339Nano time for when the trade occurred - */ - createdAt: string; - /** - * The market the trade occurred on - */ - market: TradeFields_market; -} diff --git a/libs/trades/src/lib/__generated__/Trades.ts b/libs/trades/src/lib/__generated__/Trades.ts index 0b502cafd..2e051cd62 100644 --- a/libs/trades/src/lib/__generated__/Trades.ts +++ b/libs/trades/src/lib/__generated__/Trades.ts @@ -15,30 +15,6 @@ export interface Trades_market_tradesConnection_edges_node_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; } export interface Trades_market_tradesConnection_edges_node { diff --git a/libs/trades/src/lib/trades-data-provider.ts b/libs/trades/src/lib/trades-data-provider.ts index 68f1c000f..94621ee21 100644 --- a/libs/trades/src/lib/trades-data-provider.ts +++ b/libs/trades/src/lib/trades-data-provider.ts @@ -1,16 +1,18 @@ import { gql } from '@apollo/client'; import { makeDataProvider, + makeDerivedDataProvider, defaultAppend as append, } from '@vegaprotocol/react-helpers'; import type { PageInfo } from '@vegaprotocol/react-helpers'; -import type { TradeFields } from './__generated__/TradeFields'; +import type { Market } from '@vegaprotocol/market-list'; +import { marketsProvider } from '@vegaprotocol/market-list'; import type { Trades, Trades_market_tradesConnection_edges, Trades_market_tradesConnection_edges_node, } from './__generated__/Trades'; -import type { TradesSub } from './__generated__/TradesSub'; +import type { TradesSub, TradesSub_trades } from './__generated__/TradesSub'; import orderBy from 'lodash/orderBy'; import produce from 'immer'; @@ -29,8 +31,6 @@ export const TRADES_QUERY = gql` createdAt market { id - decimalPlaces - positionDecimalPlaces } } cursor @@ -60,7 +60,7 @@ export const TRADES_SUB = gql` const update = ( data: (Trades_market_tradesConnection_edges | null)[], - delta: TradeFields[] + delta: TradesSub_trades[] ) => { return produce(data, (draft) => { orderBy(delta, 'createdAt', 'desc').forEach((node) => { @@ -82,18 +82,25 @@ const update = ( }); }; +export type Trade = Trades_market_tradesConnection_edges_node; +export type TradeWithMarket = Omit & { market?: Market }; +export type TradeWithMarketEdge = { + cursor: Trades_market_tradesConnection_edges['cursor']; + node: TradeWithMarket; +}; + const getData = ( responseData: Trades ): Trades_market_tradesConnection_edges[] | null => - responseData.market ? responseData.market.tradesConnection.edges : null; + responseData?.market?.tradesConnection?.edges || null; -const getDelta = (subscriptionData: TradesSub): TradeFields[] => +const getDelta = (subscriptionData: TradesSub): TradesSub_trades[] => subscriptionData?.trades || []; const getPageInfo = (responseData: Trades): PageInfo | null => - responseData.market?.tradesConnection.pageInfo || null; + responseData.market?.tradesConnection?.pageInfo || null; -export const tradesDataProvider = makeDataProvider({ +export const tradesProvider = makeDataProvider({ query: TRADES_QUERY, subscriptionQuery: TRADES_SUB, update, @@ -105,3 +112,36 @@ export const tradesDataProvider = makeDataProvider({ first: 100, }, }); + +export const tradesWithMarketProvider = makeDerivedDataProvider< + TradeWithMarketEdge[], + TradeWithMarket[] +>( + [tradesProvider, marketsProvider], + (partsData): TradeWithMarketEdge[] | null => + (partsData[0] as ReturnType)?.map((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).map( + (deltaTrade) => ({ + ...((parts[0].data as ReturnType)?.find( + (trade) => trade.node.id === deltaTrade.id + )?.node as Trades_market_tradesConnection_edges_node), + market: (parts[1].data as Market[]).find( + (market) => market.id === deltaTrade.marketId + ), + }) + ); + } +);