From 97cbc698345d9459767b0de4c7eb4b44f86f25cb Mon Sep 17 00:00:00 2001 From: asiaznik Date: Wed, 19 Jul 2023 17:56:01 +0200 Subject: [PATCH] feat(trading): successor markets feature flag support --- .../client-pages/market/trade-grid.tsx | 2 +- .../client-pages/market/trade-panels.tsx | 3 +- .../market-successor-banner.spec.tsx | 43 +--- .../market-banner/market-successor-banner.tsx | 12 +- libs/environment/src/hooks/use-environment.ts | 25 +-- libs/environment/src/types.ts | 4 + .../src/utils/validate-environment.ts | 12 +- libs/markets/src/lib/SuccessorMarket.graphql | 36 ++++ .../src/lib/__generated__/SuccessorMarket.ts | 184 ++++++++++++++++++ libs/markets/src/lib/__generated__/index.ts | 1 + libs/markets/src/lib/__generated__/markets.ts | 5 +- .../components/market-info/MarketInfo.graphql | 1 - .../market-info/__generated__/MarketInfo.ts | 3 +- .../market-info/market-info-panels.tsx | 44 +++-- libs/markets/src/lib/hooks/index.ts | 1 + .../src/lib/hooks/use-successor-market.ts | 30 +++ libs/markets/src/lib/markets.graphql | 1 - 17 files changed, 319 insertions(+), 88 deletions(-) create mode 100644 libs/markets/src/lib/SuccessorMarket.graphql create mode 100644 libs/markets/src/lib/__generated__/SuccessorMarket.ts create mode 100644 libs/markets/src/lib/hooks/use-successor-market.ts diff --git a/apps/trading/client-pages/market/trade-grid.tsx b/apps/trading/client-pages/market/trade-grid.tsx index e94e9648b..a54e5d42a 100644 --- a/apps/trading/client-pages/market/trade-grid.tsx +++ b/apps/trading/client-pages/market/trade-grid.tsx @@ -318,7 +318,7 @@ export const TradeGrid = ({ market, pinnedAsset }: TradeGridProps) => {
- + {FLAGS.SUCCESSOR_MARKETS && }
{sidebarOpen && ( diff --git a/apps/trading/client-pages/market/trade-panels.tsx b/apps/trading/client-pages/market/trade-panels.tsx index 491f9ff08..569fe71e0 100644 --- a/apps/trading/client-pages/market/trade-panels.tsx +++ b/apps/trading/client-pages/market/trade-panels.tsx @@ -22,6 +22,7 @@ import * as DialogPrimitives from '@radix-ui/react-dialog'; import { HeaderTitle } from '../../components/header'; import { MarketSelector } from './market-selector'; import { MarketSuccessorBanner } from '../../components/market-banner'; +import { FLAGS } from '@vegaprotocol/environment'; interface TradePanelsProps { market: Market | null; @@ -93,7 +94,7 @@ export const TradePanels = ({
- + {FLAGS.SUCCESSOR_MARKETS && }
diff --git a/apps/trading/components/market-banner/market-successor-banner.spec.tsx b/apps/trading/components/market-banner/market-successor-banner.spec.tsx index c16b97894..a7b5ff07e 100644 --- a/apps/trading/components/market-banner/market-successor-banner.spec.tsx +++ b/apps/trading/components/market-banner/market-successor-banner.spec.tsx @@ -1,6 +1,5 @@ import { render, screen } from '@testing-library/react'; import { MockedProvider } from '@apollo/react-testing'; -import * as dataProviders from '@vegaprotocol/data-provider'; import { MarketSuccessorBanner } from './market-successor-banner'; import * as Types from '@vegaprotocol/types'; import * as allUtils from '@vegaprotocol/utils'; @@ -19,7 +18,6 @@ const market = { marketTimestamps: { close: null, }, - successorMarketID: 'successorMarketID', } as unknown as Market; let mockDataSuccessorMarket: PartialDeep | null = null; @@ -45,6 +43,12 @@ jest.mock('@vegaprotocol/utils', () => ({ let mockCandles = {}; jest.mock('@vegaprotocol/markets', () => ({ ...jest.requireActual('@vegaprotocol/markets'), + useSuccessorMarket: (marketId: string) => + marketId + ? { + data: mockDataSuccessorMarket, + } + : { data: undefined }, useCandles: () => mockCandles, })); @@ -70,35 +74,12 @@ describe('MarketSuccessorBanner', () => { expect(container).toBeEmptyDOMElement(); }); - it('when no successorMarketID', () => { - const amendedMarket = { - ...market, - successorMarketID: null, - }; - const { container } = render( - , - { - wrapper: MockedProvider, - } - ); - expect(container).toBeEmptyDOMElement(); - expect(dataProviders.useDataProvider).lastCalledWith( - expect.objectContaining({ skip: true }) - ); - }); - it('no successor market data', () => { mockDataSuccessorMarket = null; const { container } = render(, { wrapper: MockedProvider, }); expect(container).toBeEmptyDOMElement(); - expect(dataProviders.useDataProvider).lastCalledWith( - expect.objectContaining({ - variables: { marketId: 'successorMarketID' }, - skip: false, - }) - ); }); it('successor market not in continuous mode', () => { @@ -110,12 +91,6 @@ describe('MarketSuccessorBanner', () => { wrapper: MockedProvider, }); expect(container).toBeEmptyDOMElement(); - expect(dataProviders.useDataProvider).lastCalledWith( - expect.objectContaining({ - variables: { marketId: 'successorMarketID' }, - skip: false, - }) - ); expect(allUtils.getMarketExpiryDate).toHaveBeenCalled(); }); @@ -128,12 +103,6 @@ describe('MarketSuccessorBanner', () => { wrapper: MockedProvider, }); expect(container).toBeEmptyDOMElement(); - expect(dataProviders.useDataProvider).lastCalledWith( - expect.objectContaining({ - variables: { marketId: 'successorMarketID' }, - skip: false, - }) - ); expect(allUtils.getMarketExpiryDate).toHaveBeenCalled(); }); }); diff --git a/apps/trading/components/market-banner/market-successor-banner.tsx b/apps/trading/components/market-banner/market-successor-banner.tsx index 1ea870a1f..315b18571 100644 --- a/apps/trading/components/market-banner/market-successor-banner.tsx +++ b/apps/trading/components/market-banner/market-successor-banner.tsx @@ -1,11 +1,10 @@ import { useState } from 'react'; import { isBefore, formatDuration, intervalToDuration } from 'date-fns'; -import { useDataProvider } from '@vegaprotocol/data-provider'; import type { Market } from '@vegaprotocol/markets'; import { calcCandleVolume, - marketProvider, useCandles, + useSuccessorMarket, } from '@vegaprotocol/markets'; import { ExternalLink, @@ -30,13 +29,8 @@ export const MarketSuccessorBanner = ({ }: { market: Market | null; }) => { - const { data: successorData } = useDataProvider({ - dataProvider: marketProvider, - variables: { - marketId: market?.successorMarketID || '', - }, - skip: !market?.successorMarketID, - }); + const { data: successorData } = useSuccessorMarket(market?.id); + const [visible, setVisible] = useState(true); const expiry = market diff --git a/libs/environment/src/hooks/use-environment.ts b/libs/environment/src/hooks/use-environment.ts index ca1352167..872551dc5 100644 --- a/libs/environment/src/hooks/use-environment.ts +++ b/libs/environment/src/hooks/use-environment.ts @@ -12,7 +12,7 @@ import { NodeCheckDocument, NodeCheckTimeUpdateDocument, } from '../utils/__generated__/NodeCheck'; -import type { Environment, FeatureFlags } from '../types'; +import type { CosmicELevatorFlags, Environment, FeatureFlags } from '../types'; import { Networks } from '../types'; import { compileErrors } from '../utils/compile-errors'; import { envSchema } from '../utils/validate-environment'; @@ -377,18 +377,13 @@ function compileEnvVars() { } function compileFeatureFlags(): FeatureFlags { - const CONSOLE_FLAGS = { - CONSOLE_ICEBERG_ORDERS: TRUTHY.includes( - windowOrDefault('NX_CONSOLE_ICEBERG_ORDERS') - ), - CONSOLE_STOP_ORDERS: TRUTHY.includes( - windowOrDefault('NX_CONSOLE_STOP_ORDERS') - ), - CONSOLE_SUCCESSOR_MARKETS: TRUTHY.includes( - windowOrDefault('NX_CONSOLE_SUCCESSOR_MARKETS') - ), - CONSOLE_PRODUCT_PERPETUALS: TRUTHY.includes( - windowOrDefault('NX_CONSOLE_PRODUCT_PERPETUALS') + const TRUTHY = ['1', 'true']; + const COSMIC_ELEVATOR_FLAGS: CosmicELevatorFlags = { + ICEBERG_ORDERS: TRUTHY.includes(windowOrDefault('NX_ICEBERG_ORDERS')), + STOP_ORDERS: TRUTHY.includes(windowOrDefault('NX_STOP_ORDERS')), + SUCCESSOR_MARKETS: TRUTHY.includes(windowOrDefault('NX_SUCCESSOR_MARKETS')), + PRODUCT_PERPETUALS: TRUTHY.includes( + windowOrDefault('NX_PRODUCT_PERPETUALS') ), }; const EXPLORER_FLAGS = { @@ -417,7 +412,7 @@ function compileFeatureFlags(): FeatureFlags { ), }; return { - ...CONSOLE_FLAGS, + ...COSMIC_ELEVATOR_FLAGS, ...EXPLORER_FLAGS, ...GOVERNANCE_FLAGS, }; @@ -473,5 +468,3 @@ export function windowOrDefault(key: string, defaultValue?: string) { } return defaultValue || undefined; } - -const TRUTHY = ['1', 'true']; diff --git a/libs/environment/src/types.ts b/libs/environment/src/types.ts index 6e9a3f94a..e54400090 100644 --- a/libs/environment/src/types.ts +++ b/libs/environment/src/types.ts @@ -16,5 +16,9 @@ export enum Networks { } export type Environment = z.infer; export type FeatureFlags = z.infer; +export type CosmicELevatorFlags = Pick< + FeatureFlags, + 'ICEBERG_ORDERS' | 'STOP_ORDERS' | 'SUCCESSOR_MARKETS' | 'PRODUCT_PERPETUALS' +>; export type Configuration = z.infer; export const CUSTOM_NODE_KEY = 'custom' as const; diff --git a/libs/environment/src/utils/validate-environment.ts b/libs/environment/src/utils/validate-environment.ts index bc3580dbb..f094dd34f 100644 --- a/libs/environment/src/utils/validate-environment.ts +++ b/libs/environment/src/utils/validate-environment.ts @@ -70,11 +70,11 @@ export const envSchema = z } ); -const CONSOLE_FLAGS = { - CONSOLE_SUCCESSOR_MARKETS: z.optional(z.boolean()), - CONSOLE_STOP_ORDERS: z.optional(z.boolean()), - CONSOLE_ICEBERG_ORDERS: z.optional(z.boolean()), - CONSOLE_PRODUCT_PERPETUALS: z.optional(z.boolean()), +const COSMIC_ELEVATOR_FLAGS = { + SUCCESSOR_MARKETS: z.optional(z.boolean()), + STOP_ORDERS: z.optional(z.boolean()), + ICEBERG_ORDERS: z.optional(z.boolean()), + PRODUCT_PERPETUALS: z.optional(z.boolean()), }; const EXPLORER_FLAGS = { @@ -95,7 +95,7 @@ const GOVERNANCE_FLAGS = { }; export const featureFlagsSchema = z.object({ - ...CONSOLE_FLAGS, + ...COSMIC_ELEVATOR_FLAGS, ...EXPLORER_FLAGS, ...GOVERNANCE_FLAGS, }); diff --git a/libs/markets/src/lib/SuccessorMarket.graphql b/libs/markets/src/lib/SuccessorMarket.graphql new file mode 100644 index 000000000..0cd72858f --- /dev/null +++ b/libs/markets/src/lib/SuccessorMarket.graphql @@ -0,0 +1,36 @@ +query SuccessorMarketId($marketId: ID!) { + market(id: $marketId) { + successorMarketID + } +} + +query ParentMarketId($marketId: ID!) { + market(id: $marketId) { + parentMarketID + } +} + +query SuccessorMarketIds { + marketsConnection { + edges { + node { + id + successorMarketID + } + } + } +} + +query SuccessorMarket($marketId: ID!) { + market(id: $marketId) { + id + state + tradingMode + positionDecimalPlaces + tradableInstrument { + instrument { + name + } + } + } +} diff --git a/libs/markets/src/lib/__generated__/SuccessorMarket.ts b/libs/markets/src/lib/__generated__/SuccessorMarket.ts new file mode 100644 index 000000000..439ef675c --- /dev/null +++ b/libs/markets/src/lib/__generated__/SuccessorMarket.ts @@ -0,0 +1,184 @@ +import * as Types from '@vegaprotocol/types'; + +import { gql } from '@apollo/client'; +import * as Apollo from '@apollo/client'; +const defaultOptions = {} as const; +export type SuccessorMarketIdQueryVariables = Types.Exact<{ + marketId: Types.Scalars['ID']; +}>; + + +export type SuccessorMarketIdQuery = { __typename?: 'Query', market?: { __typename?: 'Market', successorMarketID?: string | null } | null }; + +export type ParentMarketIdQueryVariables = Types.Exact<{ + marketId: Types.Scalars['ID']; +}>; + + +export type ParentMarketIdQuery = { __typename?: 'Query', market?: { __typename?: 'Market', parentMarketID?: string | null } | null }; + +export type SuccessorMarketIdsQueryVariables = Types.Exact<{ [key: string]: never; }>; + + +export type SuccessorMarketIdsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, successorMarketID?: string | null } }> } | null }; + +export type SuccessorMarketQueryVariables = Types.Exact<{ + marketId: Types.Scalars['ID']; +}>; + + +export type SuccessorMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, state: Types.MarketState, tradingMode: Types.MarketTradingMode, positionDecimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string } } } | null }; + + +export const SuccessorMarketIdDocument = gql` + query SuccessorMarketId($marketId: ID!) { + market(id: $marketId) { + successorMarketID + } +} + `; + +/** + * __useSuccessorMarketIdQuery__ + * + * To run a query within a React component, call `useSuccessorMarketIdQuery` and pass it any options that fit your needs. + * When your component renders, `useSuccessorMarketIdQuery` 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 } = useSuccessorMarketIdQuery({ + * variables: { + * marketId: // value for 'marketId' + * }, + * }); + */ +export function useSuccessorMarketIdQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(SuccessorMarketIdDocument, options); + } +export function useSuccessorMarketIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(SuccessorMarketIdDocument, options); + } +export type SuccessorMarketIdQueryHookResult = ReturnType; +export type SuccessorMarketIdLazyQueryHookResult = ReturnType; +export type SuccessorMarketIdQueryResult = Apollo.QueryResult; +export const ParentMarketIdDocument = gql` + query ParentMarketId($marketId: ID!) { + market(id: $marketId) { + parentMarketID + } +} + `; + +/** + * __useParentMarketIdQuery__ + * + * To run a query within a React component, call `useParentMarketIdQuery` and pass it any options that fit your needs. + * When your component renders, `useParentMarketIdQuery` 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 } = useParentMarketIdQuery({ + * variables: { + * marketId: // value for 'marketId' + * }, + * }); + */ +export function useParentMarketIdQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(ParentMarketIdDocument, options); + } +export function useParentMarketIdLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(ParentMarketIdDocument, options); + } +export type ParentMarketIdQueryHookResult = ReturnType; +export type ParentMarketIdLazyQueryHookResult = ReturnType; +export type ParentMarketIdQueryResult = Apollo.QueryResult; +export const SuccessorMarketIdsDocument = gql` + query SuccessorMarketIds { + marketsConnection { + edges { + node { + id + successorMarketID + } + } + } +} + `; + +/** + * __useSuccessorMarketIdsQuery__ + * + * To run a query within a React component, call `useSuccessorMarketIdsQuery` and pass it any options that fit your needs. + * When your component renders, `useSuccessorMarketIdsQuery` 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 } = useSuccessorMarketIdsQuery({ + * variables: { + * }, + * }); + */ +export function useSuccessorMarketIdsQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(SuccessorMarketIdsDocument, options); + } +export function useSuccessorMarketIdsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(SuccessorMarketIdsDocument, options); + } +export type SuccessorMarketIdsQueryHookResult = ReturnType; +export type SuccessorMarketIdsLazyQueryHookResult = ReturnType; +export type SuccessorMarketIdsQueryResult = Apollo.QueryResult; +export const SuccessorMarketDocument = gql` + query SuccessorMarket($marketId: ID!) { + market(id: $marketId) { + id + state + tradingMode + positionDecimalPlaces + tradableInstrument { + instrument { + name + } + } + } +} + `; + +/** + * __useSuccessorMarketQuery__ + * + * To run a query within a React component, call `useSuccessorMarketQuery` and pass it any options that fit your needs. + * When your component renders, `useSuccessorMarketQuery` 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 } = useSuccessorMarketQuery({ + * variables: { + * marketId: // value for 'marketId' + * }, + * }); + */ +export function useSuccessorMarketQuery(baseOptions: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(SuccessorMarketDocument, options); + } +export function useSuccessorMarketLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(SuccessorMarketDocument, options); + } +export type SuccessorMarketQueryHookResult = ReturnType; +export type SuccessorMarketLazyQueryHookResult = ReturnType; +export type SuccessorMarketQueryResult = Apollo.QueryResult; \ No newline at end of file diff --git a/libs/markets/src/lib/__generated__/index.ts b/libs/markets/src/lib/__generated__/index.ts index b3b15c3d8..64afea3f8 100644 --- a/libs/markets/src/lib/__generated__/index.ts +++ b/libs/markets/src/lib/__generated__/index.ts @@ -5,3 +5,4 @@ export * from './markets-candles'; export * from './markets-data'; export * from './OracleMarketsSpec'; export * from './OracleSpecDataConnection'; +export * from './SuccessorMarket' \ No newline at end of file diff --git a/libs/markets/src/lib/__generated__/markets.ts b/libs/markets/src/lib/__generated__/markets.ts index 5d5653db7..addf669a7 100644 --- a/libs/markets/src/lib/__generated__/markets.ts +++ b/libs/markets/src/lib/__generated__/markets.ts @@ -7,12 +7,12 @@ export type DataSourceFilterFragment = { __typename?: 'Filter', key: { __typenam export type DataSourceSpecFragment = { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } }; -export type MarketFieldsFragment = { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, successorMarketID?: string | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number, quantum: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } }; +export type MarketFieldsFragment = { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number, quantum: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } }; export type MarketsQueryVariables = Types.Exact<{ [key: string]: never; }>; -export type MarketsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, successorMarketID?: string | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number, quantum: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } } }> } | null }; +export type MarketsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number, quantum: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } } }> } | null }; export const DataSourceFilterFragmentDoc = gql` fragment DataSourceFilter on Filter { @@ -104,7 +104,6 @@ export const MarketFieldsFragmentDoc = gql` open close } - successorMarketID } ${DataSourceSpecFragmentDoc}`; export const MarketsDocument = gql` diff --git a/libs/markets/src/lib/components/market-info/MarketInfo.graphql b/libs/markets/src/lib/components/market-info/MarketInfo.graphql index aa04b051c..0801a8ad2 100644 --- a/libs/markets/src/lib/components/market-info/MarketInfo.graphql +++ b/libs/markets/src/lib/components/market-info/MarketInfo.graphql @@ -152,6 +152,5 @@ query MarketInfo($marketId: ID!) { } } } - parentMarketID } } diff --git a/libs/markets/src/lib/components/market-info/__generated__/MarketInfo.ts b/libs/markets/src/lib/components/market-info/__generated__/MarketInfo.ts index 6da0c4ef6..51c75dc13 100644 --- a/libs/markets/src/lib/components/market-info/__generated__/MarketInfo.ts +++ b/libs/markets/src/lib/components/market-info/__generated__/MarketInfo.ts @@ -10,7 +10,7 @@ export type MarketInfoQueryVariables = Types.Exact<{ }>; -export type MarketInfoQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, lpPriceRange: string, parentMarketID?: string | null, proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string } } } | null> | null } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, riskFactors?: { __typename?: 'RiskFactor', market: string, short: string, long: string } | null, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } } } }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } }, 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 } } | null }; +export type MarketInfoQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, lpPriceRange: string, proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string } } } | null> | null } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, riskFactors?: { __typename?: 'RiskFactor', market: string, short: string, long: string } | null, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } } } }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } }, 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 } } | null }; export const DataSourceFragmentDoc = gql` fragment DataSource on DataSourceDefinition { @@ -168,7 +168,6 @@ export const MarketInfoDocument = gql` } } } - parentMarketID } } ${DataSourceFragmentDoc}`; diff --git a/libs/markets/src/lib/components/market-info/market-info-panels.tsx b/libs/markets/src/lib/components/market-info/market-info-panels.tsx index 92e4cd255..185d16814 100644 --- a/libs/markets/src/lib/components/market-info/market-info-panels.tsx +++ b/libs/markets/src/lib/components/market-info/market-info-panels.tsx @@ -23,12 +23,13 @@ import BigNumber from 'bignumber.js'; import type { DataSourceDefinition, SignerKind } from '@vegaprotocol/types'; import { ConditionOperatorMapping } from '@vegaprotocol/types'; import { MarketTradingModeMapping } from '@vegaprotocol/types'; -import { useEnvironment } from '@vegaprotocol/environment'; +import { FLAGS, useEnvironment } from '@vegaprotocol/environment'; import type { Provider } from '../../oracle-schema'; import { OracleBasicProfile } from '../../components/oracle-basic-profile'; import { useOracleProofs } from '../../hooks'; import { OracleDialog } from '../oracle-dialog/oracle-dialog'; import { useDataProvider } from '@vegaprotocol/data-provider'; +import { useParentMarketIdQuery } from '../../__generated__'; type MarketInfoProps = { market: MarketInfo; @@ -137,20 +138,41 @@ export const InsurancePoolInfoPanel = ({ }; export const KeyDetailsInfoPanel = ({ market }: MarketInfoProps) => { + const { data: parentData } = useParentMarketIdQuery({ + variables: { + marketId: market.id, + }, + skip: !FLAGS.SUCCESSOR_MARKETS, + }); const assetDecimals = market.tradableInstrument.instrument.product.settlementAsset.decimals; + return ( ); }; diff --git a/libs/markets/src/lib/hooks/index.ts b/libs/markets/src/lib/hooks/index.ts index 28dbecf18..69690a555 100644 --- a/libs/markets/src/lib/hooks/index.ts +++ b/libs/markets/src/lib/hooks/index.ts @@ -3,3 +3,4 @@ export * from './use-oracle-markets'; export * from './use-oracle-proofs'; export * from './use-oracle-spec-binding-data'; export * from './use-candles'; +export * from './use-successor-market'; diff --git a/libs/markets/src/lib/hooks/use-successor-market.ts b/libs/markets/src/lib/hooks/use-successor-market.ts new file mode 100644 index 000000000..cb4ad0d38 --- /dev/null +++ b/libs/markets/src/lib/hooks/use-successor-market.ts @@ -0,0 +1,30 @@ +import { + useSuccessorMarketIdQuery, + useSuccessorMarketQuery, +} from '../__generated__'; + +export const useSuccessorMarket = (marketId?: string) => { + const { + data: idData, + loading: idLoading, + error: idError, + } = useSuccessorMarketIdQuery({ + variables: { + marketId: marketId || '', + }, + skip: !marketId, + }); + const successorMarketId = idData?.market?.successorMarketID; + const { data, loading, error } = useSuccessorMarketQuery({ + variables: { + marketId: successorMarketId || '', + }, + skip: !successorMarketId, + }); + const successorData = data?.market; + return { + data: successorData, + loading: loading || idLoading, + error: error || idError, + }; +}; diff --git a/libs/markets/src/lib/markets.graphql b/libs/markets/src/lib/markets.graphql index 799ef906d..84e25a6e2 100644 --- a/libs/markets/src/lib/markets.graphql +++ b/libs/markets/src/lib/markets.graphql @@ -85,7 +85,6 @@ fragment MarketFields on Market { open close } - successorMarketID } query Markets {