From 9c01a69e737462da62201c21c4e5ca0f45fcfffe Mon Sep 17 00:00:00 2001 From: Madalina Raicu Date: Tue, 22 Aug 2023 12:22:00 +0100 Subject: [PATCH] chore: update schema for perpetuals and spots --- .../links/market-link/Market.graphql | 6 + .../links/market-link/__generated__/Market.ts | 8 +- .../app/components/markets/market-details.tsx | 31 ++- .../app/components/markets/markets-table.tsx | 20 +- .../components/order-details/Order.graphql | 3 + .../order-details/__generated__/Order.ts | 7 +- .../price-in-market/price-in-market.tsx | 2 + .../routes/oracles/OraclesForMarkets.graphql | 8 + .../__generated__/OraclesForMarkets.ts | 12 +- .../oracles/components/oracle-markets.tsx | 14 +- .../oracles/components/oracle-signers.tsx | 3 + .../routes/parties/id/Party-assets.graphql | 3 + .../parties/id/__generated__/Party-assets.ts | 7 +- .../proposal-market-data.tsx | 35 +++- .../dashboard/market-list/market-list.tsx | 50 +++-- .../src/app/components/detail/detail.tsx | 21 +- .../src/app/lib/utils.tsx | 3 + .../src/integration/closed-markets.cy.ts | 91 +++++---- .../market/market-header-stats.tsx | 20 +- apps/trading/client-pages/market/market.tsx | 35 ++-- apps/trading/client-pages/markets/closed.tsx | 44 +++-- .../portfolio/account-history-container.tsx | 30 ++- .../liquidity-container.tsx | 15 +- .../liquidity-header/liquidity-header.tsx | 13 +- .../market-selector/asset-dropdown.tsx | 4 +- .../market-selector/market-selector-item.tsx | 19 +- .../market-selector/market-selector.tsx | 11 +- .../use-market-selector-list.ts | 9 +- .../deal-ticket/deal-ticket-fee-details.tsx | 31 ++- .../deal-ticket/deal-ticket-limit-amount.tsx | 5 +- .../deal-ticket/deal-ticket-market-amount.tsx | 6 +- .../deal-ticket/deal-ticket-stop-order.tsx | 30 ++- .../components/deal-ticket/deal-ticket.tsx | 18 +- .../compile-grid-data.tsx | 28 ++- libs/fills/src/lib/fills-table.tsx | 16 +- .../src/lib/orderbook-manager.tsx | 6 +- .../markets/src/lib/OracleMarketsSpec.graphql | 18 ++ .../lib/__generated__/OracleMarketsSpec.ts | 22 ++- libs/markets/src/lib/__generated__/markets.ts | 30 ++- .../components/market-info/MarketInfo.graphql | 25 +++ .../market-info/__generated__/MarketInfo.ts | 27 ++- .../market-info/market-info-accordion.tsx | 65 +++++- .../market-info/market-info-panels.tsx | 187 ++++++++++++------ .../markets-container/market-list-table.tsx | 13 +- .../markets-container/oracle-status.tsx | 39 ++-- .../markets-container/use-column-defs.tsx | 12 +- .../oracle-full-profile.tsx | 46 +++-- .../src/lib/hooks/use-market-oracle.ts | 14 +- .../src/lib/hooks/use-oracle-markets.ts | 12 +- libs/markets/src/lib/markets.graphql | 26 +++ libs/markets/src/lib/markets.mock.ts | 2 +- .../src/lib/positions-data-providers.ts | 8 + .../proposals-hooks/use-update-proposal.ts | 1 + libs/types/src/__generated__/types.ts | 2 + libs/types/src/global-types-mappings.ts | 32 ++- .../src/lib/use-vega-transaction-toasts.tsx | 36 ++-- 56 files changed, 938 insertions(+), 343 deletions(-) diff --git a/apps/explorer/src/app/components/links/market-link/Market.graphql b/apps/explorer/src/app/components/links/market-link/Market.graphql index 677b6b8e9..84bb5e9c0 100644 --- a/apps/explorer/src/app/components/links/market-link/Market.graphql +++ b/apps/explorer/src/app/components/links/market-link/Market.graphql @@ -13,6 +13,12 @@ query ExplorerMarket($id: ID!) { decimals } } + ... on Perpetual { + quoteName + settlementAsset { + decimals + } + } } } } diff --git a/apps/explorer/src/app/components/links/market-link/__generated__/Market.ts b/apps/explorer/src/app/components/links/market-link/__generated__/Market.ts index 6a7ff6b22..c6f1a44cd 100644 --- a/apps/explorer/src/app/components/links/market-link/__generated__/Market.ts +++ b/apps/explorer/src/app/components/links/market-link/__generated__/Market.ts @@ -8,7 +8,7 @@ export type ExplorerMarketQueryVariables = Types.Exact<{ }>; -export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } | { __typename?: 'Perpetual' } | { __typename?: 'Spot' } } } } | null }; +export type ExplorerMarketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } | { __typename?: 'Perpetual', quoteName: string, settlementAsset: { __typename?: 'Asset', decimals: number } } | { __typename?: 'Spot' } } } } | null }; export const ExplorerMarketDocument = gql` @@ -27,6 +27,12 @@ export const ExplorerMarketDocument = gql` decimals } } + ... on Perpetual { + quoteName + settlementAsset { + decimals + } + } } } } diff --git a/apps/explorer/src/app/components/markets/market-details.tsx b/apps/explorer/src/app/components/markets/market-details.tsx index de0cdec22..a45403154 100644 --- a/apps/explorer/src/app/components/markets/market-details.tsx +++ b/apps/explorer/src/app/components/markets/market-details.tsx @@ -24,14 +24,27 @@ import isEqual from 'lodash/isEqual'; export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => { if (!market) return null; - const settlementData = market.tradableInstrument.instrument.product - .dataSourceSpecForSettlementData.data as DataSourceDefinition; - const terminationData = market.tradableInstrument.instrument.product - .dataSourceSpecForTradingTermination.data as DataSourceDefinition; + // TODO - check settlementScheduleData for Perpetuals + + const settlementData = + 'dataSourceSpecForSettlementData' in + market.tradableInstrument.instrument.product + ? (market.tradableInstrument.instrument.product + .dataSourceSpecForSettlementData.data as DataSourceDefinition) + : undefined; + const terminationData = + 'dataSourceSpecForTradingTermination' in + market.tradableInstrument.instrument.product + ? (market.tradableInstrument.instrument.product + .dataSourceSpecForTradingTermination.data as DataSourceDefinition) + : undefined; const getSigners = (data: DataSourceDefinition) => { if (data.sourceType.__typename === 'DataSourceDefinitionExternal') { - const signers = data.sourceType.sourceType.signers || []; + const signers = + ('signers' in data.sourceType.sourceType && + data.sourceType.sourceType.signers) || + []; return signers.map(({ signer }, i) => { return ( @@ -43,10 +56,10 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => { return []; }; - const showTwoOracles = isEqual( - getSigners(settlementData), - getSigners(terminationData) - ); + const showTwoOracles = + settlementData && + terminationData && + isEqual(getSigners(settlementData), getSigners(terminationData)); const headerClassName = 'font-alpha calt text-xl mt-4 border-b-2 pb-2'; diff --git a/apps/explorer/src/app/components/markets/markets-table.tsx b/apps/explorer/src/app/components/markets/markets-table.tsx index 32665f6d2..b4c3eae1b 100644 --- a/apps/explorer/src/app/components/markets/markets-table.tsx +++ b/apps/explorer/src/app/components/markets/markets-table.tsx @@ -73,8 +73,7 @@ export const MarketsTable = ({ data }: MarketsTableProps) => { MarketFieldsFragment, 'tradableInstrument.instrument.product.settlementAsset.symbol' >) => { - const value = - data?.tradableInstrument.instrument.product.settlementAsset; + const value = data && getAsset(data); return value ? ( { @@ -138,3 +137,20 @@ export const MarketsTable = ({ data }: MarketsTableProps) => { /> ); }; + +const getAsset = ( + data: MarketFieldsFragment +): { + decimals: number | undefined; + symbol: string; + id: string; +} => { + // TODO to handle baseAsset for Spots + return 'settlementAsset' in data.tradableInstrument.instrument.product + ? data?.tradableInstrument?.instrument?.product?.settlementAsset + : { + decimals: 0, + symbol: '', + id: '', + }; +}; diff --git a/apps/explorer/src/app/components/order-details/Order.graphql b/apps/explorer/src/app/components/order-details/Order.graphql index 6d0cae1d9..dab81b1bf 100644 --- a/apps/explorer/src/app/components/order-details/Order.graphql +++ b/apps/explorer/src/app/components/order-details/Order.graphql @@ -31,6 +31,9 @@ fragment ExplorerDeterministicOrderFields on Order { ... on Future { quoteName } + ... on Perpetual { + quoteName + } } } } diff --git a/apps/explorer/src/app/components/order-details/__generated__/Order.ts b/apps/explorer/src/app/components/order-details/__generated__/Order.ts index 4890b0818..a9f7fce39 100644 --- a/apps/explorer/src/app/components/order-details/__generated__/Order.ts +++ b/apps/explorer/src/app/components/order-details/__generated__/Order.ts @@ -3,7 +3,7 @@ import * as Types from '@vegaprotocol/types'; import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; const defaultOptions = {} as const; -export type ExplorerDeterministicOrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual' } | { __typename?: 'Spot' } } } } }; +export type ExplorerDeterministicOrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } }; export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{ orderId: Types.Scalars['ID']; @@ -11,7 +11,7 @@ export type ExplorerDeterministicOrderQueryVariables = Types.Exact<{ }>; -export type ExplorerDeterministicOrderQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual' } | { __typename?: 'Spot' } } } } } }; +export type ExplorerDeterministicOrderQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, reference: string, status: Types.OrderStatus, version: string, createdAt: any, updatedAt?: any | null, expiresAt?: any | null, timeInForce: Types.OrderTimeInForce, price: string, side: Types.Side, remaining: string, size: string, rejectionReason?: Types.OrderRejectionReason | null, peggedOrder?: { __typename?: 'PeggedOrder', reference: Types.PeggedReference, offset: string } | null, party: { __typename?: 'Party', id: string }, market: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } } }; export const ExplorerDeterministicOrderFieldsFragmentDoc = gql` fragment ExplorerDeterministicOrderFields on Order { @@ -47,6 +47,9 @@ export const ExplorerDeterministicOrderFieldsFragmentDoc = gql` ... on Future { quoteName } + ... on Perpetual { + quoteName + } } } } diff --git a/apps/explorer/src/app/components/price-in-market/price-in-market.tsx b/apps/explorer/src/app/components/price-in-market/price-in-market.tsx index bfa9d932d..540fb760d 100644 --- a/apps/explorer/src/app/components/price-in-market/price-in-market.tsx +++ b/apps/explorer/src/app/components/price-in-market/price-in-market.tsx @@ -33,6 +33,8 @@ const PriceInMarket = ({ label = addDecimalsFormatNumber(price, data.market.decimalPlaces); } else if ( decimalSource === 'SETTLEMENT_ASSET' && + data.market && + 'settlementAsset' in data.market.tradableInstrument.instrument.product && data.market?.tradableInstrument.instrument.product.settlementAsset ) { label = addDecimalsFormatNumber( diff --git a/apps/explorer/src/app/routes/oracles/OraclesForMarkets.graphql b/apps/explorer/src/app/routes/oracles/OraclesForMarkets.graphql index 2bde4804a..465673335 100644 --- a/apps/explorer/src/app/routes/oracles/OraclesForMarkets.graphql +++ b/apps/explorer/src/app/routes/oracles/OraclesForMarkets.graphql @@ -11,6 +11,14 @@ fragment ExplorerOracleForMarketsMarket on Market { id } } + ... on Perpetual { + dataSourceSpecForSettlementData { + id + } + dataSourceSpecForSettlementSchedule { + id + } + } } } } diff --git a/apps/explorer/src/app/routes/oracles/__generated__/OraclesForMarkets.ts b/apps/explorer/src/app/routes/oracles/__generated__/OraclesForMarkets.ts index efdc24da2..735ef2990 100644 --- a/apps/explorer/src/app/routes/oracles/__generated__/OraclesForMarkets.ts +++ b/apps/explorer/src/app/routes/oracles/__generated__/OraclesForMarkets.ts @@ -3,12 +3,12 @@ import * as Types from '@vegaprotocol/types'; import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; const defaultOptions = {} as const; -export type ExplorerOracleForMarketsMarketFragment = { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Perpetual' } | { __typename?: 'Spot' } } } }; +export type ExplorerOracleForMarketsMarketFragment = { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Perpetual', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForSettlementSchedule: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Spot' } } } }; export type ExplorerOracleFormMarketsQueryVariables = Types.Exact<{ [key: string]: never; }>; -export type ExplorerOracleFormMarketsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Perpetual' } | { __typename?: 'Spot' } } } } }> } | null }; +export type ExplorerOracleFormMarketsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Perpetual', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForSettlementSchedule: { __typename?: 'DataSourceSpec', id: string } } | { __typename?: 'Spot' } } } } }> } | null }; export const ExplorerOracleForMarketsMarketFragmentDoc = gql` fragment ExplorerOracleForMarketsMarket on Market { @@ -24,6 +24,14 @@ export const ExplorerOracleForMarketsMarketFragmentDoc = gql` id } } + ... on Perpetual { + dataSourceSpecForSettlementData { + id + } + dataSourceSpecForSettlementSchedule { + id + } + } } } } diff --git a/apps/explorer/src/app/routes/oracles/components/oracle-markets.tsx b/apps/explorer/src/app/routes/oracles/components/oracle-markets.tsx index a77486b47..0923a1b87 100644 --- a/apps/explorer/src/app/routes/oracles/components/oracle-markets.tsx +++ b/apps/explorer/src/app/routes/oracles/components/oracle-markets.tsx @@ -10,7 +10,7 @@ interface OracleMarketsProps { } /** - * Slightly misleadlingly names, OracleMarkets lists the market (almost always singular) + * Slightly misleadingly names, OracleMarkets lists the market (almost always singular) * to which an oracle is attached. It also checks what it triggers, by checking on the * market whether it is attached to the dataSourceSpecForSettlementData or ..TradingTermination */ @@ -27,8 +27,10 @@ export function OracleMarkets({ id }: OracleMarketsProps) { const m = markets.find((m) => { const p = m.tradableInstrument.instrument.product; if ( - p.dataSourceSpecForSettlementData.id === id || - p.dataSourceSpecForTradingTermination.id === id + ('dataSourceSpecForSettlementData' in p && + p.dataSourceSpecForSettlementData.id === id) || + ('dataSourceSpecForTradingTermination' in p && + p.dataSourceSpecForTradingTermination.id === id) ) { return true; } @@ -37,9 +39,11 @@ export function OracleMarkets({ id }: OracleMarketsProps) { if (m && m.id) { const type = + 'dataSourceSpecForSettlementData' in + m.tradableInstrument.instrument.product && id === - m.tradableInstrument.instrument.product.dataSourceSpecForSettlementData - .id + m.tradableInstrument.instrument.product + .dataSourceSpecForSettlementData.id ? 'Settlement for' : 'Termination for'; return ( diff --git a/apps/explorer/src/app/routes/oracles/components/oracle-signers.tsx b/apps/explorer/src/app/routes/oracles/components/oracle-signers.tsx index 3e8bdf325..3df060c82 100644 --- a/apps/explorer/src/app/routes/oracles/components/oracle-signers.tsx +++ b/apps/explorer/src/app/routes/oracles/components/oracle-signers.tsx @@ -67,6 +67,9 @@ export function OracleSigners({ sourceType }: OracleDetailsSignersProps) { if (sourceType.__typename !== 'DataSourceDefinitionExternal') { return null; } + if (!('signers' in sourceType.sourceType)) { + return null; + } const signers = sourceType.sourceType.signers; if (!signers || signers.length === 0) { diff --git a/apps/explorer/src/app/routes/parties/id/Party-assets.graphql b/apps/explorer/src/app/routes/parties/id/Party-assets.graphql index 72ae0fa38..6413b494e 100644 --- a/apps/explorer/src/app/routes/parties/id/Party-assets.graphql +++ b/apps/explorer/src/app/routes/parties/id/Party-assets.graphql @@ -23,6 +23,9 @@ fragment ExplorerPartyAssetsAccounts on AccountBalance { ... on Future { quoteName } + ... on Perpetual { + quoteName + } } } } diff --git a/apps/explorer/src/app/routes/parties/id/__generated__/Party-assets.ts b/apps/explorer/src/app/routes/parties/id/__generated__/Party-assets.ts index 2aa401ae7..dd5efccd3 100644 --- a/apps/explorer/src/app/routes/parties/id/__generated__/Party-assets.ts +++ b/apps/explorer/src/app/routes/parties/id/__generated__/Party-assets.ts @@ -3,14 +3,14 @@ import * as Types from '@vegaprotocol/types'; import { gql } from '@apollo/client'; import * as Apollo from '@apollo/client'; const defaultOptions = {} as const; -export type ExplorerPartyAssetsAccountsFragment = { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual' } | { __typename?: 'Spot' } } } } | null }; +export type ExplorerPartyAssetsAccountsFragment = { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } | null }; export type ExplorerPartyAssetsQueryVariables = Types.Exact<{ partyId: Types.Scalars['ID']; }>; -export type ExplorerPartyAssetsQuery = { __typename?: 'Query', partiesConnection?: { __typename?: 'PartyConnection', edges: Array<{ __typename?: 'PartyEdge', node: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string, linkings: { __typename?: 'StakesConnection', edges?: Array<{ __typename?: 'StakeLinkingEdge', node: { __typename?: 'StakeLinking', amount: string } } | null> | null } }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual' } | { __typename?: 'Spot' } } } } | null } } | null> | null } | null } }> } | null }; +export type ExplorerPartyAssetsQuery = { __typename?: 'Query', partiesConnection?: { __typename?: 'PartyConnection', edges: Array<{ __typename?: 'PartyEdge', node: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string, linkings: { __typename?: 'StakesConnection', edges?: Array<{ __typename?: 'StakeLinkingEdge', node: { __typename?: 'StakeLinking', amount: string } } | null> | null } }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } }, market?: { __typename?: 'Market', id: string, decimalPlaces: number, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, product: { __typename?: 'Future', quoteName: string } | { __typename?: 'Perpetual', quoteName: string } | { __typename?: 'Spot' } } } } | null } } | null> | null } | null } }> } | null }; export const ExplorerPartyAssetsAccountsFragmentDoc = gql` fragment ExplorerPartyAssetsAccounts on AccountBalance { @@ -38,6 +38,9 @@ export const ExplorerPartyAssetsAccountsFragmentDoc = gql` ... on Future { quoteName } + ... on Perpetual { + quoteName + } } } } diff --git a/apps/governance/src/routes/proposals/components/proposal-market-data/proposal-market-data.tsx b/apps/governance/src/routes/proposals/components/proposal-market-data/proposal-market-data.tsx index bf491b2b3..906d987b5 100644 --- a/apps/governance/src/routes/proposals/components/proposal-market-data/proposal-market-data.tsx +++ b/apps/governance/src/routes/proposals/components/proposal-market-data/proposal-market-data.tsx @@ -58,27 +58,46 @@ export const ProposalMarketData = ({ return null; } - const settlementData = marketData.tradableInstrument.instrument.product - .dataSourceSpecForSettlementData.data as DataSourceDefinition; + const settlementData = + 'dataSourceSpecForSettlementData' in + marketData.tradableInstrument.instrument.product && + (marketData.tradableInstrument.instrument.product + .dataSourceSpecForSettlementData.data as DataSourceDefinition); const parentSettlementData = + parentMarketData && + 'dataSourceSpecForSettlementData' in + parentMarketData.tradableInstrument.instrument.product && parentMarketData?.tradableInstrument.instrument?.product ?.dataSourceSpecForSettlementData?.data; - const terminationData = marketData.tradableInstrument.instrument.product - .dataSourceSpecForTradingTermination.data as DataSourceDefinition; + + const terminationData = + 'dataSourceSpecForTradingTermination' in + marketData.tradableInstrument.instrument.product && + (marketData.tradableInstrument.instrument.product + .dataSourceSpecForTradingTermination.data as DataSourceDefinition); const parentTerminationData = + parentMarketData && + 'dataSourceSpecForTradingTermination' in + parentMarketData.tradableInstrument.instrument.product && parentMarketData?.tradableInstrument.instrument?.product ?.dataSourceSpecForTradingTermination?.data; + // TODO add settlementScheduleData for Perp Proposal + const isParentSettlementDataEqual = parentSettlementData !== undefined && isEqual(settlementData, parentSettlementData); + const isParentTerminationDataEqual = parentTerminationData !== undefined && isEqual(terminationData, parentTerminationData); const getSigners = (data: DataSourceDefinition) => { if (data.sourceType.__typename === 'DataSourceDefinitionExternal') { - const signers = data.sourceType.sourceType.signers || []; + const signers = + ('signers' in data.sourceType.sourceType && + data.sourceType.sourceType.signers) || + []; return signers.map(({ signer }) => { return ( @@ -129,7 +148,9 @@ export const ProposalMarketData = ({ /> } /> - {isEqual( + {settlementData && + terminationData && + isEqual( getSigners(settlementData), getSigners(terminationData) ) ? ( @@ -246,7 +267,7 @@ export const ProposalMarketData = ({ /> ))} { + // TODO to handle baseAsset for Spots + return 'settlementAsset' in data.tradableInstrument.instrument.product + ? data?.tradableInstrument?.instrument?.product?.settlementAsset + : { + decimals: undefined, + symbol: undefined, + }; +}; export const MarketList = () => { const { data, error, loading } = useMarketsLiquidity(); @@ -51,12 +67,7 @@ export const MarketList = () => { return ( <> {value} - - { - data?.tradableInstrument?.instrument?.product?.settlementAsset - ?.symbol - } - + {get(getAsset(data), 'symbol')} ); }, @@ -87,12 +98,7 @@ export const MarketList = () => { value, data, }: VegaValueFormatterParams) => - value && data - ? formatWithAsset( - value, - data.tradableInstrument.instrument.product.settlementAsset - ) - : '-', + value && data ? formatWithAsset(value, getAsset(data)) : '-', }, { @@ -123,8 +129,7 @@ export const MarketList = () => { value && data ? `${addDecimalsFormatNumber( value, - data.tradableInstrument.instrument.product.settlementAsset - .decimals + getAsset(data).decimals || 0 )} (${displayChange(data.volumeChange)})` : '-', headerTooltip: t('The trade volume over the last 24h'), @@ -138,10 +143,7 @@ export const MarketList = () => { data, }: VegaValueFormatterParams) => data && value - ? formatWithAsset( - value.toString(), - data.tradableInstrument.instrument.product.settlementAsset - ) + ? formatWithAsset(value.toString(), getAsset(data)) : '-', headerTooltip: t('The amount of funds allocated to provide liquidity'), }, @@ -153,12 +155,7 @@ export const MarketList = () => { value, data, }: VegaValueFormatterParams) => - data && value - ? formatWithAsset( - value, - data.tradableInstrument.instrument.product.settlementAsset - ) - : '-', + data && value ? formatWithAsset(value, getAsset(data)) : '-', headerTooltip: t( 'The ideal committed liquidity to operate the market. If total commitment currently below this level then LPs can set the fee level with new commitment.' ), @@ -230,10 +227,7 @@ export const MarketList = () => { }) => ( diff --git a/apps/liquidity-provision-dashboard/src/app/components/detail/detail.tsx b/apps/liquidity-provision-dashboard/src/app/components/detail/detail.tsx index b88eff8d0..32130ba51 100644 --- a/apps/liquidity-provision-dashboard/src/app/components/detail/detail.tsx +++ b/apps/liquidity-provision-dashboard/src/app/components/detail/detail.tsx @@ -16,13 +16,26 @@ import { Market } from './market'; import { Header } from './header'; import { LPProvidersGrid } from './providers'; +const getAsset = ( + data: MarketWithData +): { + decimals?: number | undefined; + symbol?: string | undefined; +} => { + // TODO to handle baseAsset for Spots + return 'settlementAsset' in data.tradableInstrument.instrument.product + ? data?.tradableInstrument?.instrument?.product?.settlementAsset + : { + decimals: 0, + symbol: '', + }; +}; + const formatMarket = (market: MarketWithData) => { return { name: market?.tradableInstrument.instrument.name, - symbol: - market?.tradableInstrument.instrument.product.settlementAsset.symbol, - settlementAsset: - market?.tradableInstrument.instrument.product.settlementAsset, + symbol: getAsset(market).symbol, + settlementAsset: getAsset(market), targetStake: market?.data?.targetStake, tradingMode: market?.data?.marketTradingMode, trigger: market?.data?.trigger, diff --git a/apps/liquidity-provision-dashboard/src/app/lib/utils.tsx b/apps/liquidity-provision-dashboard/src/app/lib/utils.tsx index 727ca9f52..f83683be6 100644 --- a/apps/liquidity-provision-dashboard/src/app/lib/utils.tsx +++ b/apps/liquidity-provision-dashboard/src/app/lib/utils.tsx @@ -7,6 +7,7 @@ const marketTradingModeStyle = { [Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION]: '#0046CD', [Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION]: '#CF0064', [Schema.MarketTradingMode.TRADING_MODE_NO_TRADING]: '#CF0064', + [Schema.MarketTradingMode.TRADING_MODE_SUSPENDED_VIA_GOVERNANCE]: '#CF0064', }; export const getColorForStatus = (status: Schema.MarketTradingMode) => @@ -18,6 +19,8 @@ const marketTradingModeIntent = { [Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION]: Intent.Primary, [Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION]: Intent.Danger, [Schema.MarketTradingMode.TRADING_MODE_NO_TRADING]: Intent.Danger, + [Schema.MarketTradingMode.TRADING_MODE_SUSPENDED_VIA_GOVERNANCE]: + Intent.Danger, }; export const intentForStatus = (status: Schema.MarketTradingMode) => { diff --git a/apps/trading-e2e/src/integration/closed-markets.cy.ts b/apps/trading-e2e/src/integration/closed-markets.cy.ts index d689963d8..f0d3fbb67 100644 --- a/apps/trading-e2e/src/integration/closed-markets.cy.ts +++ b/apps/trading-e2e/src/integration/closed-markets.cy.ts @@ -271,31 +271,34 @@ describe('Closed markets', { tags: '@smoke' }, () => { .find('[col-id="state"]') .should('have.text', MarketStateMapping[settledMarket.state]); + const terminationId = + 'dataSourceSpecForTradingTermination' in product + ? product.dataSourceSpecForTradingTermination.id + : ''; + // 6001-MARK-004 // 6001-MARK-005 // 6001-MARK-009 // 6001-MARK-008 // 6001-MARK-010 - cy.get(rowSelector) - .first() - .find('[col-id="settlementDate"]') - .find('[data-testid="link"]') - .should(($el) => { - const href = $el.attr('href'); - expect(href).to.match( - new RegExp( - `/oracles/${product.dataSourceSpecForTradingTermination.id}` + terminationId && + cy + .get(rowSelector) + .first() + .find('[col-id="settlementDate"]') + .find('[data-testid="link"]') + .should(($el) => { + const href = $el.attr('href'); + expect(href).to.match(new RegExp(`/oracles/${terminationId}`)); + }) + .should('have.text', '4 days ago') + .should( + 'have.attr', + 'title', + getDateTimeFormat().format( + new Date(settledMarket.marketTimestamps.close) ) ); - }) - .should('have.text', '4 days ago') - .should( - 'have.attr', - 'title', - getDateTimeFormat().format( - new Date(settledMarket.marketTimestamps.close) - ) - ); // 6001-MARK-011 cy.get(rowSelector) @@ -331,33 +334,43 @@ describe('Closed markets', { tags: '@smoke' }, () => { ) ); + const settlementDataId = + 'dataSourceSpecForSettlementData' in product + ? product.dataSourceSpecForSettlementData.id + : ''; + // 6001-MARK-014 // 6001-MARK-015 // 6001-MARK-016 - cy.get(rowSelector) - .first() - .find('[col-id="settlementDataOracleId"]') - .find('[data-testid="link"]') - .should(($el) => { - const href = $el.attr('href'); - expect(href).to.match( - new RegExp(`/oracles/${product.dataSourceSpecForSettlementData.id}`) + settlementDataId && + cy + .get(rowSelector) + .first() + .find('[col-id="settlementDataOracleId"]') + .find('[data-testid="link"]') + .should(($el) => { + const href = $el.attr('href'); + expect(href).to.match(new RegExp(`/oracles/${settlementDataId}`)); + }) + .should( + 'have.text', + addDecimalsFormatNumber( + // @ts-ignore cannot deep un-partial + specDataConnection.externalData.data.data[0].value, + settlementDataPropertyKey.numberDecimalPlaces + ) ); - }) - .should( - 'have.text', - addDecimalsFormatNumber( - // @ts-ignore cannot deep un-partial - specDataConnection.externalData.data.data[0].value, - settlementDataPropertyKey.numberDecimalPlaces - ) - ); + + const settlementAssetSymbol = + 'settlementAsset' in product ? product.settlementAsset.symbol : ''; // 6001-MARK-018 - cy.get(rowSelector) - .first() - .find('[col-id="settlementAsset"]') - .should('have.text', product.settlementAsset.symbol); + settlementAssetSymbol && + cy + .get(rowSelector) + .first() + .find('[col-id="settlementAsset"]') + .should('have.text', settlementAssetSymbol); // 6001-MARK-020 cy.get('.ag-pinned-right-cols-container') diff --git a/apps/trading/client-pages/market/market-header-stats.tsx b/apps/trading/client-pages/market/market-header-stats.tsx index 55e6bd458..c0d668b08 100644 --- a/apps/trading/client-pages/market/market-header-stats.tsx +++ b/apps/trading/client-pages/market/market-header-stats.tsx @@ -2,7 +2,7 @@ import { useAssetDetailsDialogStore } from '@vegaprotocol/assets'; import { useEnvironment } from '@vegaprotocol/environment'; import { ButtonLink, Link } from '@vegaprotocol/ui-toolkit'; import { MarketProposalNotification } from '@vegaprotocol/proposals'; -import type { Market } from '@vegaprotocol/markets'; +import type { Market, MarketFieldsFragment } from '@vegaprotocol/markets'; import { getExpiryDate, getMarketExpiryDate } from '@vegaprotocol/utils'; import { t } from '@vegaprotocol/i18n'; import { Last24hPriceChange, Last24hVolume } from '@vegaprotocol/markets'; @@ -21,7 +21,8 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => { const { VEGA_EXPLORER_URL } = useEnvironment(); const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore(); - const asset = market?.tradableInstrument.instrument.product?.settlementAsset; + // TODO to handle baseAsset for Spots + const asset = market && getAsset(market); return ( <> @@ -114,8 +115,11 @@ const ExpiryTooltipContent = ({ }: ExpiryTooltipContentProps) => { if (market?.marketTimestamps.close === null) { const oracleId = + 'dataSourceSpecForTradingTermination' in market.tradableInstrument.instrument.product - .dataSourceSpecForTradingTermination?.id; + ? market.tradableInstrument.instrument.product + .dataSourceSpecForTradingTermination?.id + : undefined; const metadataExpiryDate = getMarketExpiryDate( market.tradableInstrument.instrument.metadata.tags @@ -152,3 +156,13 @@ const ExpiryTooltipContent = ({ return null; }; + +const getAsset = (market: MarketFieldsFragment) => { + return 'settlementAsset' in market.tradableInstrument.instrument.product + ? market?.tradableInstrument.instrument.product?.settlementAsset + : { + id: '', + symbol: '', + decimals: 0, + }; +}; diff --git a/apps/trading/client-pages/market/market.tsx b/apps/trading/client-pages/market/market.tsx index 2175a48c2..deb75ca76 100644 --- a/apps/trading/client-pages/market/market.tsx +++ b/apps/trading/client-pages/market/market.tsx @@ -4,6 +4,7 @@ import { t } from '@vegaprotocol/i18n'; import { useScreenDimensions } from '@vegaprotocol/react-helpers'; import { useThrottledDataProvider } from '@vegaprotocol/data-provider'; import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit'; +import type { MarketFieldsFragment } from '@vegaprotocol/markets'; import { marketDataProvider, useMarket } from '@vegaprotocol/markets'; import { useGlobalStore, usePageTitleStore } from '../../stores'; import { TradeGrid } from './trade-grid'; @@ -79,26 +80,14 @@ export const MarketPage = () => { } }, [init, view, setView]); + const pinnedAsset = getAsset(data); + const tradeView = useMemo(() => { if (largeScreen) { - return ( - - ); + return ; } - return ( - - ); - }, [largeScreen, data]); + return ; + }, [largeScreen, data, pinnedAsset]); if (!data && marketId) { return ( @@ -134,3 +123,15 @@ export const MarketPage = () => { ); }; + +const getAsset = (market: MarketFieldsFragment | null) => { + return market && + 'settlementAsset' in market.tradableInstrument.instrument.product + ? market?.tradableInstrument.instrument.product?.settlementAsset + : { + id: '', + symbol: '', + decimals: 0, + name: '', + }; +}; diff --git a/apps/trading/client-pages/markets/closed.tsx b/apps/trading/client-pages/markets/closed.tsx index cc5b2267c..e787a8329 100644 --- a/apps/trading/client-pages/markets/closed.tsx +++ b/apps/trading/client-pages/markets/closed.tsx @@ -11,15 +11,13 @@ import { } from '@vegaprotocol/datagrid'; import { useMemo } from 'react'; import { t } from '@vegaprotocol/i18n'; +import type { Asset } from '@vegaprotocol/types'; import { MarketState, MarketStateMapping } from '@vegaprotocol/types'; import { addDecimalsFormatNumber, getMarketExpiryDate, } from '@vegaprotocol/utils'; -import type { - DataSourceFilterFragment, - MarketMaybeWithData, -} from '@vegaprotocol/markets'; +import type { DataSourceFilterFragment } from '@vegaprotocol/markets'; import { MarketActionsDropdown, closedMarketsWithDataProvider, @@ -32,8 +30,10 @@ import { SettlementPriceCell } from './settlement-price-cell'; import { useDataProvider } from '@vegaprotocol/data-provider'; import { SuccessorMarketRenderer } from './successor-market-cell'; -type SettlementAsset = - MarketMaybeWithData['tradableInstrument']['instrument']['product']['settlementAsset']; +type SettlementAsset = Pick< + Asset, + 'decimals' | 'name' | 'quantum' | 'id' | 'symbol' +>; interface Row { id: string; @@ -48,7 +48,7 @@ interface Row { markPrice: string | undefined; settlementDataOracleId: string; settlementDataSpecBinding: string; - setlementDataSourceFilter: DataSourceFilterFragment | undefined; + settlementDataSourceFilter: DataSourceFilterFragment | undefined; tradingTerminationOracleId: string; settlementAsset: SettlementAsset; productType: string; @@ -64,15 +64,18 @@ export const Closed = () => { const instrument = market.tradableInstrument.instrument; const spec = + 'dataSourceSpecForSettlementData' in instrument.product && instrument.product.dataSourceSpecForSettlementData.data.sourceType .__typename === 'DataSourceDefinitionExternal' ? instrument.product.dataSourceSpecForSettlementData.data.sourceType .sourceType : undefined; - const filters = spec?.filters || []; + const filters = (spec && 'filters' in spec && spec.filters) || []; const settlementDataSpecBinding = - instrument.product.dataSourceSpecBinding.settlementDataProperty; + 'dataSourceSpecBinding' in instrument.product + ? instrument.product.dataSourceSpecBinding.settlementDataProperty + : ''; const filter = filters?.find((filter) => { return filter.key.name === settlementDataSpecBinding; }); @@ -89,12 +92,25 @@ export const Closed = () => { bestOfferPrice: market.data?.bestOfferPrice, markPrice: market.data?.markPrice, settlementDataOracleId: - instrument.product.dataSourceSpecForSettlementData.id, + 'dataSourceSpecForSettlementData' in instrument.product + ? instrument.product.dataSourceSpecForSettlementData.id + : '', settlementDataSpecBinding, - setlementDataSourceFilter: filter, + settlementDataSourceFilter: filter, tradingTerminationOracleId: - instrument.product.dataSourceSpecForTradingTermination.id, - settlementAsset: instrument.product.settlementAsset, + 'dataSourceSpecForTradingTermination' in instrument.product + ? instrument.product.dataSourceSpecForTradingTermination.id + : '', + settlementAsset: + 'settlementAsset' in instrument.product + ? instrument.product.settlementAsset + : { + id: '', + decimals: 0, + quantum: '0', + name: '', + symbol: '', + }, productType: instrument.product.__typename || '', }; @@ -233,7 +249,7 @@ const ClosedMarketsDataGrid = ({ ), }, diff --git a/apps/trading/client-pages/portfolio/account-history-container.tsx b/apps/trading/client-pages/portfolio/account-history-container.tsx index a179b1573..76df21ecf 100644 --- a/apps/trading/client-pages/portfolio/account-history-container.tsx +++ b/apps/trading/client-pages/portfolio/account-history-container.tsx @@ -130,11 +130,16 @@ const AccountHistoryManager = ({ DateRange.RANGE_1M ); const [market, setMarket] = useState(null); + const marketFilterCb = useCallback( - (item: Market) => - !asset?.id || - item.tradableInstrument.instrument.product.settlementAsset.id === - asset?.id, + (item: Market) => { + // TODO to handle baseAsset for Spots + const itemAsset = + 'settlementAsset' in item.tradableInstrument.instrument.product + ? item.tradableInstrument.instrument.product.settlementAsset + : undefined; + return !asset?.id || itemAsset?.id === asset?.id; + }, [asset?.id] ); const markets = useMemo(() => { @@ -153,8 +158,12 @@ const AccountHistoryManager = ({ const resolveMarket = useCallback( (m: Market) => { setMarket(m); - const newAssetId = - m.tradableInstrument.instrument.product.settlementAsset.id; + // TODO to handle baseAsset for Spots + const itemAsset = + 'settlementAsset' in m.tradableInstrument.instrument.product + ? m.tradableInstrument.instrument.product.settlementAsset + : undefined; + const newAssetId = itemAsset?.id; const newAsset = assets.find((item) => item.id === newAssetId); if ((!asset || (assets && newAssetId !== asset.id)) && newAsset) { setAssetId(newAsset.id); @@ -259,10 +268,15 @@ const AccountHistoryManager = ({ }, [markets, market, accountType, resolveMarket]); useEffect(() => { + // TODO to handle baseAsset for Spots + const itemAsset = + market && + 'settlementAsset' in market.tradableInstrument.instrument.product + ? market?.tradableInstrument.instrument.product.settlementAsset + : undefined; if ( accountType !== Schema.AccountType.ACCOUNT_TYPE_MARGIN || - market?.tradableInstrument.instrument.product.settlementAsset.id !== - asset?.id + itemAsset?.id !== asset?.id ) { setMarket(null); } diff --git a/apps/trading/components/liquidity-container/liquidity-container.tsx b/apps/trading/components/liquidity-container/liquidity-container.tsx index 371e36c5b..006ae15bd 100644 --- a/apps/trading/components/liquidity-container/liquidity-container.tsx +++ b/apps/trading/components/liquidity-container/liquidity-container.tsx @@ -42,12 +42,15 @@ export const LiquidityContainer = ({ skip: !marketId, }); - const assetDecimalPlaces = - market?.tradableInstrument.instrument.product.settlementAsset.decimals || 0; - const quantum = - market?.tradableInstrument.instrument.product.settlementAsset.quantum || 0; - const symbol = - market?.tradableInstrument.instrument.product.settlementAsset.symbol; + // TODO to handle baseAsset for Spots + const itemAsset = + market && 'settlementAsset' in market.tradableInstrument.instrument.product + ? market.tradableInstrument.instrument.product.settlementAsset + : undefined; + + const assetDecimalPlaces = itemAsset?.decimals || 0; + const quantum = itemAsset?.quantum || 0; + const symbol = itemAsset?.symbol; const { params } = useNetworkParams([ NetworkParams.market_liquidity_stakeToCcyVolume, diff --git a/apps/trading/components/liquidity-header/liquidity-header.tsx b/apps/trading/components/liquidity-header/liquidity-header.tsx index 7b97b20e3..4ebdffd6d 100644 --- a/apps/trading/components/liquidity-header/liquidity-header.tsx +++ b/apps/trading/components/liquidity-header/liquidity-header.tsx @@ -24,10 +24,15 @@ export const LiquidityHeader = () => { const { data: marketData } = useStaticMarketData(marketId); const targetStake = marketData?.targetStake; const suppliedStake = marketData?.suppliedStake; - const assetDecimalPlaces = - market?.tradableInstrument.instrument.product.settlementAsset.decimals || 0; - const symbol = - market?.tradableInstrument.instrument.product.settlementAsset.symbol; + + // TODO to handle baseAsset for Spots + const asset = + market && 'settlementAsset' in market.tradableInstrument.instrument.product + ? market.tradableInstrument.instrument.product.settlementAsset + : undefined; + + const assetDecimalPlaces = asset?.decimals || 0; + const symbol = asset?.symbol; const { params } = useNetworkParams([ NetworkParams.market_liquidity_stakeToCcyVolume, diff --git a/apps/trading/components/market-selector/asset-dropdown.tsx b/apps/trading/components/market-selector/asset-dropdown.tsx index 308bba84e..638bb7f89 100644 --- a/apps/trading/components/market-selector/asset-dropdown.tsx +++ b/apps/trading/components/market-selector/asset-dropdown.tsx @@ -33,7 +33,7 @@ export const AssetDropdown = ({ } > - {assets?.map((a) => { + {assets?.filter(Boolean).map((a) => { return ( a.id === assetId); + const asset = assets.find((a) => a?.id === assetId); text = asset ? asset.symbol : t('Asset (1)'); } else if (checkedAssets.length > 1) { text = t(`${checkedAssets.length} Assets`); diff --git a/apps/trading/components/market-selector/market-selector-item.tsx b/apps/trading/components/market-selector/market-selector-item.tsx index 8d5479024..baf4d32aa 100644 --- a/apps/trading/components/market-selector/market-selector-item.tsx +++ b/apps/trading/components/market-selector/market-selector-item.tsx @@ -108,14 +108,17 @@ const MarketData = ({

)} -
- {price} {instrument.product.settlementAsset.symbol} -
+ {/* TODO to handle baseAsset for Spots */} + {instrument.product && 'settlementAsset' in instrument.product && ( +
+ {price} {instrument.product.settlementAsset.symbol} +
+ )}
d.tradableInstrument.instrument.product.settlementAsset - ), + data?.map((d) => { + // TODO to handle baseAsset for Spots + const asset = + 'settlementAsset' in d.tradableInstrument.instrument.product + ? d.tradableInstrument.instrument.product.settlementAsset + : { id: '', symbol: '' }; + return asset; + }), 'id' )} checkedAssets={filter.assets} diff --git a/apps/trading/components/market-selector/use-market-selector-list.ts b/apps/trading/components/market-selector/use-market-selector-list.ts index a9626fd66..c672bc64a 100644 --- a/apps/trading/components/market-selector/use-market-selector-list.ts +++ b/apps/trading/components/market-selector/use-market-selector-list.ts @@ -39,9 +39,12 @@ export const useMarketSelectorList = ({ }) .filter((m) => { if (assets.length === 0) return true; - return assets.includes( - m.tradableInstrument.instrument.product.settlementAsset.id - ); + // TODO to handle baseAsset for Spots + const asset = + 'settlementAsset' in m.tradableInstrument.instrument.product + ? m.tradableInstrument.instrument.product.settlementAsset + : { id: '', symbol: '' }; + return assets.includes(asset?.id); }) // filter based on search term .filter((m) => { diff --git a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-fee-details.tsx b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-fee-details.tsx index 7df3041f3..e12a7ccf7 100644 --- a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-fee-details.tsx +++ b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-fee-details.tsx @@ -7,7 +7,7 @@ import { FeesBreakdown } from '@vegaprotocol/markets'; import type { OrderSubmissionBody } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet'; -import type { Market } from '@vegaprotocol/markets'; +import type { Market, MarketFieldsFragment } from '@vegaprotocol/markets'; import type { EstimatePositionQuery } from '@vegaprotocol/positions'; import { AccountBreakdownDialog } from '@vegaprotocol/accounts'; @@ -90,11 +90,10 @@ export const DealTicketFeeDetails = ({ notionalSize, }: DealTicketFeeDetailsProps) => { const feeEstimate = useEstimateFees(order); - const { settlementAsset: asset } = - market.tradableInstrument.instrument.product; + const asset = getAsset(market); const { decimals: assetDecimals, quantum } = asset; const marketDecimals = market.decimalPlaces; - const quoteName = market.tradableInstrument.instrument.product.quoteName; + const quoteName = getQuote(market); return ( <> @@ -164,8 +163,7 @@ export const DealTicketMarginDetails = ({ const marginEstimate = positionEstimate?.margin; const totalBalance = BigInt(generalAccountBalance || '0') + BigInt(marginAccountBalance || '0'); - const { settlementAsset: asset } = - market.tradableInstrument.instrument.product; + const asset = getAsset(market); const { decimals: assetDecimals, quantum } = asset; let marginRequiredBestCase: string | undefined = undefined; let marginRequiredWorstCase: string | undefined = undefined; @@ -304,7 +302,7 @@ export const DealTicketMarginDetails = ({ [] ); - const quoteName = market.tradableInstrument.instrument.product.quoteName; + const quoteName = getQuote(market); return ( <> @@ -376,3 +374,22 @@ export const DealTicketMarginDetails = ({ ); }; + +const getAsset = (market: MarketFieldsFragment) => { + // TODO update with baseAsset for Spots + return 'settlementAsset' in market.tradableInstrument.instrument.product + ? market.tradableInstrument.instrument.product.settlementAsset + : { + quantum: '0', + decimals: 0, + symbol: '', + id: '', + }; +}; + +const getQuote = (market: MarketFieldsFragment) => { + // TODO update with quoteAsset for Spots + return 'quoteName' in market.tradableInstrument.instrument.product + ? market.tradableInstrument.instrument.product.quoteName + : ''; +}; diff --git a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-limit-amount.tsx b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-limit-amount.tsx index 6e307ce4e..4a7fd0a60 100644 --- a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-limit-amount.tsx +++ b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-limit-amount.tsx @@ -17,7 +17,10 @@ export const DealTicketLimitAmount = ({ }: DealTicketLimitAmountProps) => { const priceStep = toDecimal(market?.decimalPlaces); const sizeStep = toDecimal(market?.positionDecimalPlaces); - const quoteName = market.tradableInstrument.instrument.product.quoteName; + const quoteName = + 'quoteName' in market.tradableInstrument.instrument.product + ? market.tradableInstrument.instrument.product.quoteName + : ''; const renderError = () => { if (sizeError) { diff --git a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-market-amount.tsx b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-market-amount.tsx index 9b3e77e66..3ca8fa16f 100644 --- a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-market-amount.tsx +++ b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-market-amount.tsx @@ -9,6 +9,7 @@ import { isMarketInAuction } from '@vegaprotocol/markets'; import type { DealTicketAmountProps } from './deal-ticket-amount'; import { Controller } from 'react-hook-form'; import classNames from 'classnames'; +import get from 'lodash/get'; export type DealTicketMarketAmountProps = Omit; @@ -19,7 +20,10 @@ export const DealTicketMarketAmount = ({ marketPrice, sizeError, }: DealTicketMarketAmountProps) => { - const quoteName = market.tradableInstrument.instrument.product.quoteName; + const quoteName = get( + market.tradableInstrument.instrument.product, + 'quoteName' + ); const sizeStep = toDecimal(market?.positionDecimalPlaces); const price = marketPrice; diff --git a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-stop-order.tsx b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-stop-order.tsx index 5e048d14e..55b43fb46 100644 --- a/libs/deal-ticket/src/components/deal-ticket/deal-ticket-stop-order.tsx +++ b/libs/deal-ticket/src/components/deal-ticket/deal-ticket-stop-order.tsx @@ -150,8 +150,30 @@ export const StopOrder = ({ market, marketPrice, submit }: StopOrderProps) => { return () => subscription.unsubscribe(); }, [watch, market.id, updateStoredFormValues]); - const { quoteName, settlementAsset: asset } = - market.tradableInstrument.instrument.product; + let quoteName, + asset: { + id: string; + symbol: string; + name: string; + decimals: number; + quantum: string; + } | null = null; + + if (market.tradableInstrument.instrument.product.__typename === 'Future') { + quoteName = market.tradableInstrument.instrument.product.quoteName; + asset = market.tradableInstrument.instrument.product.settlementAsset; + } + + if (market.tradableInstrument.instrument.product.__typename === 'Perpetual') { + quoteName = market.tradableInstrument.instrument.product.quoteName; + asset = market.tradableInstrument.instrument.product.settlementAsset; + } + + if (market.tradableInstrument.instrument.product.__typename === 'Spot') { + // TODO add baseAsset and quoteAsset for Spots + // quoteName = market.tradableInstrument.instrument.product.quoteAsset; + // asset = market.tradableInstrument.instrument.product.baseAsset; + } const sizeStep = toDecimal(market?.positionDecimalPlaces); const priceStep = toDecimal(market?.decimalPlaces); @@ -254,7 +276,7 @@ export const StopOrder = ({ market, marketPrice, submit }: StopOrderProps) => { data-testid="triggerPrice" type="number" step={priceStep} - appendElement={asset.symbol} + appendElement={asset?.symbol} value={value || ''} {...props} /> @@ -570,7 +592,7 @@ export const StopOrder = ({ market, marketPrice, submit }: StopOrderProps) => { type, }} notionalSize={notionalSize} - assetSymbol={asset.symbol} + assetSymbol={asset?.symbol || ''} market={market} /> diff --git a/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx b/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx index b6d2f6172..2dfd939ed 100644 --- a/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx +++ b/libs/deal-ticket/src/components/deal-ticket/deal-ticket.tsx @@ -45,6 +45,7 @@ import { SummaryValidationType } from '../../constants'; import type { Market, MarketData, + MarketFieldsFragment, StaticMarketData, } from '@vegaprotocol/markets'; import { MarginWarning } from '../deal-ticket-validation/margin-warning'; @@ -145,7 +146,7 @@ export const DealTicket = ({ }); const lastSubmitTime = useRef(0); - const asset = market.tradableInstrument.instrument.product.settlementAsset; + const asset = getAsset(market); const { accountBalance: marginAccountBalance, loading: loadingMarginAccountBalance, @@ -249,8 +250,7 @@ export const DealTicket = ({ fetchPolicy: 'no-cache', }); - const assetSymbol = - market.tradableInstrument.instrument.product.settlementAsset.symbol; + const assetSymbol = getAsset(market).symbol; const summaryError = useMemo(() => { if (!pubKey) { @@ -658,3 +658,15 @@ const SummaryMessage = memo( return null; } ); + +const getAsset = (market: MarketFieldsFragment) => { + // TODO add baseAsset for Spot + return 'settlementAsset' in market.tradableInstrument.instrument.product + ? market.tradableInstrument.instrument.product.settlementAsset + : { + id: '', + symbol: '', + name: '', + decimals: 0, + }; +}; diff --git a/libs/deal-ticket/src/components/trading-mode-tooltip/compile-grid-data.tsx b/libs/deal-ticket/src/components/trading-mode-tooltip/compile-grid-data.tsx index f4ea00394..d339d2298 100644 --- a/libs/deal-ticket/src/components/trading-mode-tooltip/compile-grid-data.tsx +++ b/libs/deal-ticket/src/components/trading-mode-tooltip/compile-grid-data.tsx @@ -8,7 +8,11 @@ import { Link as UILink } from '@vegaprotocol/ui-toolkit'; import type { SimpleGridProps } from '@vegaprotocol/ui-toolkit'; import type { ReactNode } from 'react'; import { Link } from 'react-router-dom'; -import type { Market, MarketData } from '@vegaprotocol/markets'; +import type { + Market, + MarketData, + MarketFieldsFragment, +} from '@vegaprotocol/markets'; export const compileGridData = ( market: Pick< @@ -40,10 +44,9 @@ export const compileGridData = ( const formatStake = (value: string) => { const formattedValue = addDecimalsFormatNumber( value, - market.tradableInstrument.instrument.product.settlementAsset.decimals + getAsset(market).decimals ); - const asset = - market.tradableInstrument.instrument.product.settlementAsset.symbol; + const asset = getAsset(market).symbol; return `${formattedValue} ${asset}`; }; @@ -118,3 +121,20 @@ export const compileGridData = ( return grid; }; + +const getAsset = ( + market: Pick< + MarketFieldsFragment, + 'id' | 'tradableInstrument' | 'decimalPlaces' | 'positionDecimalPlaces' + > +) => { + // TODO update with baseAsset for Spots + return 'settlementAsset' in market.tradableInstrument.instrument.product + ? market.tradableInstrument.instrument.product.settlementAsset + : { + quantum: '0', + decimals: 0, + symbol: '', + id: '', + }; +}; diff --git a/libs/fills/src/lib/fills-table.tsx b/libs/fills/src/lib/fills-table.tsx index 65351ae48..2bb75719c 100644 --- a/libs/fills/src/lib/fills-table.tsx +++ b/libs/fills/src/lib/fills-table.tsx @@ -142,7 +142,10 @@ const formatPrice = ({ return '-'; } const asset = - data?.market.tradableInstrument.instrument.product.settlementAsset.symbol; + 'settlementAsset' in data.market.tradableInstrument.instrument.product + ? data?.market.tradableInstrument.instrument.product.settlementAsset + .symbol + : ''; const valueFormatted = addDecimalsFormatNumber( value, data?.market.decimalPlaces @@ -193,7 +196,9 @@ const formatTotal = ({ return '-'; } const { symbol: assetSymbol, decimals: assetDecimals } = - data?.market.tradableInstrument.instrument.product.settlementAsset ?? {}; + ('settlementAsset' in data.market.tradableInstrument.instrument.product + ? data?.market.tradableInstrument.instrument.product.settlementAsset + : null) ?? {}; const size = new BigNumber( addDecimal(data?.size, data?.market.positionDecimalPlaces) ); @@ -219,7 +224,12 @@ const formatFee = (partyId: string) => { Trade, 'market.tradableInstrument.instrument.product' >) => { - if (!value?.settlementAsset || !data) { + if ( + !value || + !('settlementAsset' in value) || + !value?.settlementAsset || + !data + ) { return '-'; } const asset = value.settlementAsset; diff --git a/libs/market-depth/src/lib/orderbook-manager.tsx b/libs/market-depth/src/lib/orderbook-manager.tsx index 2f6a0b003..6bef2725a 100644 --- a/libs/market-depth/src/lib/orderbook-manager.tsx +++ b/libs/market-depth/src/lib/orderbook-manager.tsx @@ -66,7 +66,11 @@ export const OrderbookManager = ({ asks={data?.depth.sell ?? []} decimalPlaces={market?.decimalPlaces ?? 0} positionDecimalPlaces={market?.positionDecimalPlaces ?? 0} - assetSymbol={market?.tradableInstrument.instrument.product.quoteName} + assetSymbol={ + market && 'quoteName' in market.tradableInstrument.instrument.product + ? market?.tradableInstrument.instrument.product.quoteName + : '' + } onClick={onClick} midPrice={marketData?.midPrice} /> diff --git a/libs/markets/src/lib/OracleMarketsSpec.graphql b/libs/markets/src/lib/OracleMarketsSpec.graphql index 357ab27f1..2fd346979 100644 --- a/libs/markets/src/lib/OracleMarketsSpec.graphql +++ b/libs/markets/src/lib/OracleMarketsSpec.graphql @@ -26,6 +26,24 @@ fragment OracleMarketSpecFields on Market { tradingTerminationProperty } } + ... on Perpetual { + dataSourceSpecForSettlementData { + id + data { + ...DataSourceSpec + } + } + dataSourceSpecForSettlementSchedule { + id + data { + ...DataSourceSpec + } + } + dataSourceSpecBinding { + settlementDataProperty + settlementScheduleProperty + } + } } } } diff --git a/libs/markets/src/lib/__generated__/OracleMarketsSpec.ts b/libs/markets/src/lib/__generated__/OracleMarketsSpec.ts index 8d527aaed..5894d5c78 100644 --- a/libs/markets/src/lib/__generated__/OracleMarketsSpec.ts +++ b/libs/markets/src/lib/__generated__/OracleMarketsSpec.ts @@ -4,12 +4,12 @@ import { gql } from '@apollo/client'; import { DataSourceSpecFragmentDoc } from './markets'; import * as Apollo from '@apollo/client'; const defaultOptions = {} as const; -export type OracleMarketSpecFieldsFragment = { __typename?: 'Market', id: string, state: Types.MarketState, tradingMode: Types.MarketTradingMode, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, product: { __typename?: 'Future', 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'Perpetual' } | { __typename?: 'Spot' } } } }; +export type OracleMarketSpecFieldsFragment = { __typename?: 'Market', id: string, state: Types.MarketState, tradingMode: Types.MarketTradingMode, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, product: { __typename?: 'Future', 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'Perpetual', 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementSchedule: { __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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecPerpetualBinding', settlementDataProperty: string, settlementScheduleProperty: string } } | { __typename?: 'Spot' } } } }; export type OracleMarketsSpecQueryVariables = Types.Exact<{ [key: string]: never; }>; -export type OracleMarketsSpecQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, state: Types.MarketState, tradingMode: Types.MarketTradingMode, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, product: { __typename?: 'Future', 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'Perpetual' } | { __typename?: 'Spot' } } } } }> } | null }; +export type OracleMarketsSpecQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, state: Types.MarketState, tradingMode: Types.MarketTradingMode, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, product: { __typename?: 'Future', 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'Perpetual', 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementSchedule: { __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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecPerpetualBinding', settlementDataProperty: string, settlementScheduleProperty: string } } | { __typename?: 'Spot' } } } } }> } | null }; export const OracleMarketSpecFieldsFragmentDoc = gql` fragment OracleMarketSpecFields on Market { @@ -40,6 +40,24 @@ export const OracleMarketSpecFieldsFragmentDoc = gql` tradingTerminationProperty } } + ... on Perpetual { + dataSourceSpecForSettlementData { + id + data { + ...DataSourceSpec + } + } + dataSourceSpecForSettlementSchedule { + id + data { + ...DataSourceSpec + } + } + dataSourceSpecBinding { + settlementDataProperty + settlementScheduleProperty + } + } } } } diff --git a/libs/markets/src/lib/__generated__/markets.ts b/libs/markets/src/lib/__generated__/markets.ts index cf3a7afe4..b096ff791 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } }; -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?: 'EthCallSpec' } } | { __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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'Perpetual' } | { __typename?: 'Spot' } } }, 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?: 'EthCallSpec' } } | { __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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'Perpetual', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number, quantum: string }, dataSourceSpecForSettlementSchedule: { __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?: 'EthCallSpec' } } | { __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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecPerpetualBinding', settlementDataProperty: string, settlementScheduleProperty: string } } | { __typename?: 'Spot' } } }, 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, 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?: 'EthCallSpec' } } | { __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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'Perpetual' } | { __typename?: 'Spot' } } }, 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?: 'EthCallSpec' } } | { __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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'Perpetual', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number, quantum: string }, dataSourceSpecForSettlementSchedule: { __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?: 'EthCallSpec' } } | { __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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecPerpetualBinding', settlementDataProperty: string, settlementScheduleProperty: string } } | { __typename?: 'Spot' } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } } }> } | null }; export const DataSourceFilterFragmentDoc = gql` fragment DataSourceFilter on Filter { @@ -97,6 +97,32 @@ export const MarketFieldsFragmentDoc = gql` tradingTerminationProperty } } + ... on Perpetual { + settlementAsset { + id + symbol + name + decimals + quantum + } + quoteName + dataSourceSpecForSettlementSchedule { + id + data { + ...DataSourceSpec + } + } + dataSourceSpecForSettlementData { + id + data { + ...DataSourceSpec + } + } + dataSourceSpecBinding { + settlementDataProperty + settlementScheduleProperty + } + } } } } diff --git a/libs/markets/src/lib/components/market-info/MarketInfo.graphql b/libs/markets/src/lib/components/market-info/MarketInfo.graphql index 0801a8ad2..956ae9482 100644 --- a/libs/markets/src/lib/components/market-info/MarketInfo.graphql +++ b/libs/markets/src/lib/components/market-info/MarketInfo.graphql @@ -125,6 +125,31 @@ query MarketInfo($marketId: ID!) { tradingTerminationProperty } } + ... on Perpetual { + quoteName + settlementAsset { + id + symbol + name + decimals + } + dataSourceSpecForSettlementData { + id + data { + ...DataSource + } + } + dataSourceSpecForSettlementSchedule { + id + data { + ...DataSource + } + } + dataSourceSpecBinding { + settlementDataProperty + settlementScheduleProperty + } + } } } riskModel { 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 13341d58b..dcde5915d 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, 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } }, 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'Perpetual' } | { __typename?: 'Spot' } }, 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } }, 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } | { __typename?: 'Perpetual', 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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } }, dataSourceSpecForSettlementSchedule: { __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?: 'EthCallSpec' } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger' } } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecPerpetualBinding', settlementDataProperty: string, settlementScheduleProperty: string } } | { __typename?: 'Spot' } }, 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 { @@ -141,6 +141,31 @@ export const MarketInfoDocument = gql` tradingTerminationProperty } } + ... on Perpetual { + quoteName + settlementAsset { + id + symbol + name + decimals + } + dataSourceSpecForSettlementData { + id + data { + ...DataSource + } + } + dataSourceSpecForSettlementSchedule { + id + data { + ...DataSource + } + } + dataSourceSpecBinding { + settlementDataProperty + settlementScheduleProperty + } + } } } riskModel { diff --git a/libs/markets/src/lib/components/market-info/market-info-accordion.tsx b/libs/markets/src/lib/components/market-info/market-info-accordion.tsx index 3d91df600..6f67cadc2 100644 --- a/libs/markets/src/lib/components/market-info/market-info-accordion.tsx +++ b/libs/markets/src/lib/components/market-info/market-info-accordion.tsx @@ -88,14 +88,31 @@ export const MarketInfoAccordion = ({ market.accountsConnection?.edges ); - const settlementData = market.tradableInstrument.instrument.product - .dataSourceSpecForSettlementData.data as DataSourceDefinition; - const terminationData = market.tradableInstrument.instrument.product - .dataSourceSpecForTradingTermination.data as DataSourceDefinition; + const settlementData = + 'dataSourceSpecForSettlementData' in + market.tradableInstrument.instrument.product + ? (market.tradableInstrument.instrument.product + .dataSourceSpecForSettlementData.data as DataSourceDefinition) + : undefined; + const terminationData = + 'dataSourceSpecForTradingTermination' in + market.tradableInstrument.instrument.product + ? (market.tradableInstrument.instrument.product + .dataSourceSpecForTradingTermination.data as DataSourceDefinition) + : undefined; + const settlementScheduleData = + 'dataSourceSpecForSettlementSchedule' in + market.tradableInstrument.instrument.product + ? (market.tradableInstrument.instrument.product + .dataSourceSpecForSettlementSchedule.data as DataSourceDefinition) + : undefined; const getSigners = (data: DataSourceDefinition) => { if (data.sourceType.__typename === 'DataSourceDefinitionExternal') { - const signers = data.sourceType.sourceType.signers || []; + const signers = + ('signers' in data.sourceType.sourceType && + data.sourceType.sourceType.signers) || + []; return signers.map(({ signer }, i) => { return ( @@ -158,7 +175,9 @@ export const MarketInfoAccordion = ({ title={t('Instrument')} content={} /> - {isEqual(getSigners(settlementData), getSigners(terminationData)) ? ( + {settlementData && + terminationData && + isEqual(getSigners(settlementData), getSigners(terminationData)) ? ( } /> - )} + {settlementData && + settlementScheduleData && + isEqual( + getSigners(settlementData), + getSigners(settlementScheduleData) + ) ? ( + + } + /> + ) : ( + <> + + } + /> + + } + /> + + )} } /> 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 1c84223d3..0a15dc00f 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 @@ -52,6 +52,7 @@ import type { MarketTradingMode } from '@vegaprotocol/types'; import type { Signer } from '@vegaprotocol/types'; import classNames from 'classnames'; import compact from 'lodash/compact'; +import get from 'lodash/get'; type MarketInfoProps = { market: MarketInfo; @@ -80,9 +81,17 @@ export const CurrentFeesInfoPanel = ({ market }: MarketInfoProps) => ( export const MarketPriceInfoPanel = ({ market }: MarketInfoProps) => { const assetSymbol = - market?.tradableInstrument.instrument.product?.settlementAsset.symbol || ''; + market?.tradableInstrument.instrument.product && + 'settlementAsset' in market.tradableInstrument.instrument.product + ? market?.tradableInstrument.instrument.product?.settlementAsset.symbol + : market?.tradableInstrument.instrument.product && + 'baseAsset' in market.tradableInstrument.instrument.product + ? get(market?.tradableInstrument.instrument.product?.baseAsset, 'symbol') + : ''; const quoteUnit = - market?.tradableInstrument.instrument.product?.quoteName || ''; + 'quoteName' in market.tradableInstrument.instrument.product + ? market?.tradableInstrument.instrument.product?.quoteName + : ''; const { data } = useDataProvider({ dataProvider: marketDataProvider, variables: { marketId: market.id }, @@ -94,7 +103,10 @@ export const MarketPriceInfoPanel = ({ market }: MarketInfoProps) => { markPrice: data?.markPrice, bestBidPrice: data?.bestBidPrice, bestOfferPrice: data?.bestOfferPrice, - quoteUnit: market.tradableInstrument.instrument.product.quoteName, + quoteUnit: get( + market.tradableInstrument.instrument.product, + 'quoteName' + ), }} decimalPlaces={market.decimalPlaces} /> @@ -145,17 +157,16 @@ export const InsurancePoolInfoPanel = ({ Get >; } & MarketInfoProps) => { - const assetSymbol = - market?.tradableInstrument.instrument.product?.settlementAsset.symbol || ''; + const assetSymbol = getAssetSymbol(market); + const assetDecimals = getAssetDecimals(market); + return ( ); }; @@ -197,8 +208,7 @@ export const KeyDetailsInfoPanel = ({ skip: !parentMarket?.proposal?.id, }); - const assetDecimals = - market.tradableInstrument.instrument.product.settlementAsset.decimals; + const assetDecimals = getAssetDecimals(market); return ( @@ -387,7 +395,7 @@ export const InstrumentInfoPanel = ({ marketName: market.tradableInstrument.instrument.name, code: market.tradableInstrument.instrument.code, productType: market.tradableInstrument.instrument.product.__typename, - quoteName: market.tradableInstrument.instrument.product.quoteName, + quoteName: get(market.tradableInstrument.instrument.product, 'quoteName'), }} parentData={ parentMarket && { @@ -395,22 +403,22 @@ export const InstrumentInfoPanel = ({ code: parentMarket?.tradableInstrument?.instrument?.code, productType: parentMarket?.tradableInstrument?.instrument?.product?.__typename, - quoteName: - parentMarket?.tradableInstrument?.instrument?.product?.quoteName, + quoteName: get( + parentMarket?.tradableInstrument?.instrument?.product, + 'quoteName' + ), } } /> ); export const SettlementAssetInfoPanel = ({ market }: MarketInfoProps) => { - const assetSymbol = - market?.tradableInstrument.instrument.product?.settlementAsset.symbol || ''; - const quoteUnit = - market?.tradableInstrument.instrument.product?.quoteName || ''; - const assetId = useMemo( - () => market?.tradableInstrument.instrument.product?.settlementAsset.id, - [market] + const assetSymbol = getAssetSymbol(market); + const quoteUnit = get( + market?.tradableInstrument.instrument.product, + 'quoteName' ); + const assetId = useMemo(() => getAssetId(market), [market]); const { data: asset } = useAssetDataProvider(assetId ?? ''); return asset ? ( @@ -594,10 +602,14 @@ export const PriceMonitoringBoundsInfoPanel = ({ ], }); - const quoteUnit = - market?.tradableInstrument.instrument.product?.quoteName || ''; - const parentQuoteUnit = - parentMarket?.tradableInstrument.instrument.product?.quoteName || ''; + const quoteUnit = get( + market?.tradableInstrument.instrument.product, + 'quoteName' + ); + const parentQuoteUnit = get( + parentMarket?.tradableInstrument.instrument.product, + 'quoteName' + ); const isParentQuoteUnitEqual = quoteUnit === parentQuoteUnit; const trigger = @@ -688,10 +700,8 @@ export const LiquidityMonitoringParametersInfoPanel = ({ }; export const LiquidityInfoPanel = ({ market, children }: MarketInfoProps) => { - const assetDecimals = - market.tradableInstrument.instrument.product.settlementAsset.decimals; - const assetSymbol = - market?.tradableInstrument.instrument.product?.settlementAsset.symbol || ''; + const assetDecimals = getAssetDecimals(market); + const assetSymbol = getAssetSymbol(market); const { data } = useDataProvider({ dataProvider: marketDataProvider, variables: { marketId: market.id }, @@ -717,9 +727,14 @@ export const LiquidityPriceRangeInfoPanel = ({ parentMarket, }: MarketInfoProps) => { const quoteUnit = - market?.tradableInstrument.instrument.product?.quoteName || ''; + ('quoteName' in market.tradableInstrument.instrument.product && + market?.tradableInstrument.instrument.product?.quoteName) || + ''; const parentQuoteUnit = - parentMarket?.tradableInstrument.instrument.product?.quoteName || ''; + (parentMarket && + 'quoteName' in parentMarket.tradableInstrument.instrument.product && + parentMarket?.tradableInstrument.instrument.product?.quoteName) || + ''; const liquidityPriceRange = formatNumberPercentage( new BigNumber(market.lpPriceRange).times(100) @@ -809,7 +824,9 @@ export const OracleInfoPanel = ({ market, type, parentMarket, -}: MarketInfoProps & { type: 'settlementData' | 'termination' }) => { +}: MarketInfoProps & { + type: 'settlementData' | 'termination' | 'settlementSchedule'; +}) => { // If this is a successor market, this component will only receive parent market // data if the termination or settlement data is different from the parent. const product = market.tradableInstrument.instrument.product; @@ -818,26 +835,52 @@ export const OracleInfoPanel = ({ const { data } = useOracleProofs(ORACLE_PROOFS_URL); const dataSourceSpecId = - type === 'settlementData' + type === 'settlementData' && 'dataSourceSpecForSettlementData' in product ? product.dataSourceSpecForSettlementData.id - : product.dataSourceSpecForTradingTermination.id; + : type === 'termination' && + 'dataSourceSpecForTradingTermination' in product + ? product.dataSourceSpecForTradingTermination.id + : type === 'settlementSchedule' && + 'dataSourceSpecForSettlementScheduleData' in product + ? get(product.dataSourceSpecForSettlementScheduleData, 'id') + : ''; - const parentDataSourceSpecId = - type === 'settlementData' - ? parentProduct?.dataSourceSpecForSettlementData?.id - : parentProduct?.dataSourceSpecForTradingTermination?.id; + const parentDataSourceSpecId = !parentProduct + ? undefined + : type === 'settlementData' && + 'dataSourceSpecForSettlementData' in parentProduct + ? parentProduct.dataSourceSpecForSettlementData.id + : type === 'termination' && + 'dataSourceSpecForTradingTermination' in parentProduct + ? parentProduct.dataSourceSpecForTradingTermination.id + : type === 'settlementSchedule' && + 'dataSourceSpecForSettlementScheduleData' in parentProduct + ? get(parentProduct.dataSourceSpecForSettlementScheduleData, 'id') + : ''; - const dataSourceSpec = ( - type === 'settlementData' + const dataSourceSpec = + type === 'settlementData' && 'dataSourceSpecForSettlementData' in product ? product.dataSourceSpecForSettlementData.data - : product.dataSourceSpecForTradingTermination.data - ) as DataSourceDefinition; + : type === 'termination' && + 'dataSourceSpecForTradingTermination' in product + ? product.dataSourceSpecForTradingTermination.data + : type === 'settlementSchedule' && + 'dataSourceSpecForSettlementScheduleData' in product + ? get(product.dataSourceSpecForSettlementScheduleData, 'data') + : null; - const parentDataSourceSpec = - type === 'settlementData' - ? parentProduct?.dataSourceSpecForSettlementData?.data - : (parentProduct?.dataSourceSpecForTradingTermination - ?.data as DataSourceDefinition); + const parentDataSourceSpec = !parentProduct + ? undefined + : type === 'settlementData' && + 'dataSourceSpecForSettlementData' in parentProduct + ? parentProduct.dataSourceSpecForSettlementData.data + : type === 'termination' && + 'dataSourceSpecForTradingTermination' in parentProduct + ? parentProduct.dataSourceSpecForTradingTermination.data + : type === 'settlementSchedule' && + 'dataSourceSpecForSettlementScheduleData' in parentProduct + ? get(parentProduct.dataSourceSpecForSettlementScheduleData, 'data') + : null; const isParentDataSourceSpecEqual = parentDataSourceSpec !== undefined && @@ -867,11 +910,7 @@ export const OracleInfoPanel = ({ {type === 'settlementData' ? t('View settlement data specification') @@ -891,7 +930,7 @@ export const DataSourceProof = ({ }: { data: DataSourceDefinition; providers: Provider[] | undefined; - type: 'settlementData' | 'termination'; + type: 'settlementData' | 'termination' | 'settlementSchedule'; dataSourceSpecId: string; parentData?: DataSourceDefinition; parentDataSourceSpecId?: string; @@ -899,14 +938,20 @@ export const DataSourceProof = ({ // If this is a successor market, we'll only pass parent data to child // components for comparison if the data differs from the parent market. if (data.sourceType.__typename === 'DataSourceDefinitionExternal') { - const signers = data.sourceType.sourceType.signers || []; + const signers = + ('signers' in data.sourceType.sourceType && + data.sourceType.sourceType.signers) || + []; let parentSigners: Signer[]; if ( parentData && parentData.sourceType.__typename === 'DataSourceDefinitionExternal' ) { - parentSigners = parentData.sourceType.sourceType?.signers || []; + parentSigners = + ('signers' in parentData.sourceType.sourceType && + parentData.sourceType.sourceType?.signers) || + []; } if (!providers?.length) { @@ -1007,7 +1052,7 @@ const OracleLink = ({ }: { providers: Provider[]; signer: SignerKind; - type: 'settlementData' | 'termination'; + type: 'settlementData' | 'termination' | 'settlementSchedule'; dataSourceSpecId: string; parentSigner?: SignerKind; parentDataSourceSpecId?: string; @@ -1060,7 +1105,7 @@ const OracleLink = ({ const NoOracleProof = ({ type, }: { - type: 'settlementData' | 'termination'; + type: 'settlementData' | 'termination' | 'settlementSchedule'; }) => { return (

@@ -1092,3 +1137,27 @@ const OracleProfile = (props: {

); }; + +export const getAssetSymbol = (market: MarketInfo) => { + return 'settlementAsset' in market.tradableInstrument.instrument.product + ? market?.tradableInstrument.instrument.product.settlementAsset.symbol + : 'baseAsset' in market.tradableInstrument.instrument.product + ? get(market?.tradableInstrument.instrument.product.baseAsset, 'symbol') + : ''; +}; + +export const getAssetDecimals = (market: MarketInfo) => { + return 'settlementAsset' in market.tradableInstrument.instrument.product + ? market?.tradableInstrument.instrument.product.settlementAsset.decimals + : 'baseAsset' in market.tradableInstrument.instrument.product + ? get(market?.tradableInstrument.instrument.product.baseAsset, 'decimals') + : ''; +}; + +export const getAssetId = (market: MarketInfo) => { + return 'settlementAsset' in market.tradableInstrument.instrument.product + ? market?.tradableInstrument.instrument.product.settlementAsset.id + : 'baseAsset' in market.tradableInstrument.instrument.product + ? get(market?.tradableInstrument.instrument.product.baseAsset, 'id') + : ''; +}; diff --git a/libs/markets/src/lib/components/markets-container/market-list-table.tsx b/libs/markets/src/lib/components/markets-container/market-list-table.tsx index a16613077..07427e76e 100644 --- a/libs/markets/src/lib/components/markets-container/market-list-table.tsx +++ b/libs/markets/src/lib/components/markets-container/market-list-table.tsx @@ -19,18 +19,7 @@ interface MarketNameCellProps { const MarketName = (props: MarketNameCellProps) => ( <> - {props.data ? ( - - ) : null} + {props.data ? : null} ); diff --git a/libs/markets/src/lib/components/markets-container/oracle-status.tsx b/libs/markets/src/lib/components/markets-container/oracle-status.tsx index 3165c6ce7..4b8017a83 100644 --- a/libs/markets/src/lib/components/markets-container/oracle-status.tsx +++ b/libs/markets/src/lib/components/markets-container/oracle-status.tsx @@ -3,28 +3,29 @@ import { useEnvironment } from '@vegaprotocol/environment'; import { Icon } from '@vegaprotocol/ui-toolkit'; import type { IconName } from '@blueprintjs/icons'; import { getMatchingOracleProvider, useOracleProofs } from '../../hooks'; -import type { Market } from '../../markets-provider'; +import type { MarketMaybeWithData } from '../../markets-provider'; import { getVerifiedStatusIcon } from '../oracle-basic-profile'; -export const OracleStatus = ({ - dataSourceSpecForSettlementData, - dataSourceSpecForTradingTermination, -}: Pick< - Market['tradableInstrument']['instrument']['product'], - 'dataSourceSpecForSettlementData' | 'dataSourceSpecForTradingTermination' ->) => { +export const OracleStatus = ({ market }: { market: MarketMaybeWithData }) => { + const product = market.tradableInstrument.instrument.product || undefined; const { ORACLE_PROOFS_URL } = useEnvironment(); const { data: providers } = useOracleProofs(ORACLE_PROOFS_URL); return useMemo(() => { if (providers) { - const settlementDataProvider = getMatchingOracleProvider( - dataSourceSpecForSettlementData.data, - providers - ); - const tradingTerminationDataProvider = getMatchingOracleProvider( - dataSourceSpecForTradingTermination.data, - providers - ); + const settlementDataProvider = + product.__typename === 'Future' + ? getMatchingOracleProvider( + product.dataSourceSpecForSettlementData.data, + providers + ) + : undefined; + const tradingTerminationDataProvider = + product.__typename === 'Future' + ? getMatchingOracleProvider( + product.dataSourceSpecForTradingTermination.data, + providers + ) + : undefined; let maliciousOracleProvider = null; if (settlementDataProvider?.oracle.status !== 'GOOD') { maliciousOracleProvider = settlementDataProvider; @@ -36,9 +37,5 @@ export const OracleStatus = ({ return ; } return null; - }, [ - providers, - dataSourceSpecForSettlementData, - dataSourceSpecForTradingTermination, - ]); + }, [providers, product]); }; diff --git a/libs/markets/src/lib/components/markets-container/use-column-defs.tsx b/libs/markets/src/lib/components/markets-container/use-column-defs.tsx index 4271debcd..76bad3f5a 100644 --- a/libs/markets/src/lib/components/markets-container/use-column-defs.tsx +++ b/libs/markets/src/lib/components/markets-container/use-column-defs.tsx @@ -167,7 +167,11 @@ export const useColumnDefs = ({ onMarketClick }: Props) => { 'tradableInstrument.instrument.product.settlementAsset.symbol' >) => { const value = - data?.tradableInstrument.instrument.product.settlementAsset; + data && + 'settlementAsset' in data.tradableInstrument.instrument.product + ? data?.tradableInstrument.instrument.product.settlementAsset + : undefined; + return value ? ( { @@ -193,7 +197,11 @@ export const useColumnDefs = ({ onMarketClick }: Props) => { ); diff --git a/libs/markets/src/lib/components/oracle-full-profile/oracle-full-profile.tsx b/libs/markets/src/lib/components/oracle-full-profile/oracle-full-profile.tsx index 7e06ec87e..5c8a1b4fc 100644 --- a/libs/markets/src/lib/components/oracle-full-profile/oracle-full-profile.tsx +++ b/libs/markets/src/lib/components/oracle-full-profile/oracle-full-profile.tsx @@ -252,26 +252,32 @@ export const OracleFullProfile = ({ > {MarketStateMapping[market.state]} -
- { - - {t('Settlement')} - - } -
-
- { - - {t('Termination')} - - } -
+ {'dataSourceSpecForSettlementData' in + market.tradableInstrument.instrument.product && ( +
+ { + + {t('Settlement')} + + } +
+ )} + {'dataSourceSpecForTradingTermination' in + market.tradableInstrument.instrument.product && ( +
+ { + + {t('Termination')} + + } +
+ )} ))} diff --git a/libs/markets/src/lib/hooks/use-market-oracle.ts b/libs/markets/src/lib/hooks/use-market-oracle.ts index fbedcf12e..57d9ef251 100644 --- a/libs/markets/src/lib/hooks/use-market-oracle.ts +++ b/libs/markets/src/lib/hooks/use-market-oracle.ts @@ -5,6 +5,7 @@ import { useMarket } from '../markets-provider'; import { useMemo } from 'react'; import type { Provider } from '../oracle-schema'; import type { DataSourceSpecFragment } from '../__generated__'; +import get from 'lodash/get'; export const getMatchingOracleProvider = ( dataSourceSpec: DataSourceSpecFragment, @@ -20,7 +21,8 @@ export const getMatchingOracleProvider = ( } if ( - dataSourceSpec.sourceType.__typename === 'DataSourceDefinitionExternal' + dataSourceSpec.sourceType.__typename === 'DataSourceDefinitionExternal' && + 'signers' in dataSourceSpec.sourceType.sourceType ) { return dataSourceSpec.sourceType.sourceType.signers?.some( (signer) => @@ -38,7 +40,8 @@ export const useMarketOracle = ( marketId: string, dataSourceType: | 'dataSourceSpecForSettlementData' - | 'dataSourceSpecForTradingTermination' = 'dataSourceSpecForSettlementData' + | 'dataSourceSpecForTradingTermination' + | 'dataSourceSpecForSettlementSchedule' = 'dataSourceSpecForSettlementData' ): { data?: { provider: NonNullable>; @@ -57,8 +60,11 @@ export const useMarketOracle = ( if (!providers || !market) { return { data: undefined }; } - const dataSourceSpec = - market.tradableInstrument.instrument.product[dataSourceType]; + const dataSourceSpec = get( + market.tradableInstrument.instrument.product, + dataSourceType + ); + const provider = getMatchingOracleProvider(dataSourceSpec.data, providers); if (provider) { return { data: { provider, dataSourceSpecId: dataSourceSpec.id } }; diff --git a/libs/markets/src/lib/hooks/use-oracle-markets.ts b/libs/markets/src/lib/hooks/use-oracle-markets.ts index 19879c2e8..59100917d 100644 --- a/libs/markets/src/lib/hooks/use-oracle-markets.ts +++ b/libs/markets/src/lib/hooks/use-oracle-markets.ts @@ -20,11 +20,17 @@ export const useOracleMarkets = ( ?.map((edge) => edge.node) ?.filter((node) => { const p = node.tradableInstrument.instrument.product; - const sourceType = p.dataSourceSpecForSettlementData.data.sourceType; - if (sourceType.__typename !== 'DataSourceDefinitionExternal') { + const sourceType = + 'dataSourceSpecForSettlementData' in p + ? p.dataSourceSpecForSettlementData.data.sourceType + : undefined; + if (sourceType?.__typename !== 'DataSourceDefinitionExternal') { return false; } - const signers = sourceType?.sourceType.signers; + const signers = + 'signers' in sourceType.sourceType + ? sourceType?.sourceType.signers + : null; const signerKeys = signers?.filter(Boolean).map((signer) => { if (signer.signer.__typename === 'ETHAddress') { return signer.signer.address; diff --git a/libs/markets/src/lib/markets.graphql b/libs/markets/src/lib/markets.graphql index 84e25a6e2..c69388dab 100644 --- a/libs/markets/src/lib/markets.graphql +++ b/libs/markets/src/lib/markets.graphql @@ -78,6 +78,32 @@ fragment MarketFields on Market { tradingTerminationProperty } } + ... on Perpetual { + settlementAsset { + id + symbol + name + decimals + quantum + } + quoteName + dataSourceSpecForSettlementSchedule { + id + data { + ...DataSourceSpec + } + } + dataSourceSpecForSettlementData { + id + data { + ...DataSourceSpec + } + } + dataSourceSpecBinding { + settlementDataProperty + settlementScheduleProperty + } + } } } } diff --git a/libs/markets/src/lib/markets.mock.ts b/libs/markets/src/lib/markets.mock.ts index 01af90c17..bd18db36f 100644 --- a/libs/markets/src/lib/markets.mock.ts +++ b/libs/markets/src/lib/markets.mock.ts @@ -150,7 +150,7 @@ export const createMarketFragment = ( __typename: 'Market', }; - return merge(defaultFragment, override); + return merge(defaultFragment, override) as MarketFieldsFragment; }; const marketFieldsFragments: MarketFieldsFragment[] = [ diff --git a/libs/positions/src/lib/positions-data-providers.ts b/libs/positions/src/lib/positions-data-providers.ts index 572a551fd..61c1c6623 100644 --- a/libs/positions/src/lib/positions-data-providers.ts +++ b/libs/positions/src/lib/positions-data-providers.ts @@ -61,9 +61,17 @@ export const getMetrics = ( if (!data || !data?.length) { return []; } + const metrics: Position[] = []; data.forEach((position) => { const market = position.market; + if ( + !market || + !('settlementAsset' in market.tradableInstrument.instrument.product) + ) { + return; + } + if (!market) { return; } diff --git a/libs/proposals/src/lib/proposals-hooks/use-update-proposal.ts b/libs/proposals/src/lib/proposals-hooks/use-update-proposal.ts index 57f484f69..e2ed7ff42 100644 --- a/libs/proposals/src/lib/proposals-hooks/use-update-proposal.ts +++ b/libs/proposals/src/lib/proposals-hooks/use-update-proposal.ts @@ -104,6 +104,7 @@ const fieldGetters = { undefined; return ( proposed && + 'quoteName' in change.updateMarketConfiguration.instrument.product && change.updateMarketConfiguration.instrument.product.quoteName.length > 0 ); } diff --git a/libs/types/src/__generated__/types.ts b/libs/types/src/__generated__/types.ts index 5a6a8821a..d4d9ad98c 100644 --- a/libs/types/src/__generated__/types.ts +++ b/libs/types/src/__generated__/types.ts @@ -1791,6 +1791,8 @@ export type Market = { liquidityMonitoringParameters: LiquidityMonitoringParameters; /** The list of the liquidity provision commitments for this market */ liquidityProvisionsConnection?: Maybe; + /** Optional: Liquidity SLA parameters for the market */ + liquiditySLAParameters?: Maybe; /** Liquidity Provision order price range */ lpPriceRange: Scalars['String']; /** Timestamps for state changes in the market */ diff --git a/libs/types/src/global-types-mappings.ts b/libs/types/src/global-types-mappings.ts index 4458530e2..84960ab49 100644 --- a/libs/types/src/global-types-mappings.ts +++ b/libs/types/src/global-types-mappings.ts @@ -1,6 +1,6 @@ import type { ConditionOperator, PeggedReference } from './__generated__/types'; +import type { AccountType } from './__generated__/types'; import type { - AccountType, AuctionTrigger, DataSourceSpecStatus, DepositStatus, @@ -47,6 +47,7 @@ export const AccountTypeMapping: { ACCOUNT_TYPE_SETTLEMENT: 'Settlement', ACCOUNT_TYPE_HOLDING: 'Holding', ACCOUNT_TYPE_LP_LIQUIDITY_FEES: 'LP Liquidity Fees', + ACCOUNT_TYPE_NETWORK_TREASURY: 'Network Treasury', }; /** @@ -73,6 +74,7 @@ export const AuctionTriggerMapping: { AUCTION_TRIGGER_OPENING: 'opening', AUCTION_TRIGGER_PRICE: 'price', AUCTION_TRIGGER_UNSPECIFIED: 'unspecified', + AUCTION_TRIGGER_GOVERNANCE_SUSPENSION: 'governance suspension', }; /** @@ -117,6 +119,7 @@ export const MarketStateMapping: { STATE_SETTLED: 'Settled', STATE_SUSPENDED: 'Suspended', STATE_TRADING_TERMINATED: 'Trading Terminated', + STATE_SUSPENDED_VIA_GOVERNANCE: 'Suspended via governance', }; /** @@ -130,6 +133,7 @@ export const MarketTradingModeMapping: { TRADING_MODE_MONITORING_AUCTION: 'Monitoring auction', TRADING_MODE_NO_TRADING: 'No trading', TRADING_MODE_OPENING_AUCTION: 'Opening auction', + TRADING_MODE_SUSPENDED_VIA_GOVERNANCE: 'Suspended via governance', }; export const NodeStatusMapping: { @@ -348,6 +352,10 @@ export const ProposalRejectionReasonMapping: { PROPOSAL_ERROR_INVALID_SPOT: 'Invalid spot', PROPOSAL_ERROR_INVALID_SUCCESSOR_MARKET: 'Invalid successor market', PROPOSAL_ERROR_SPOT_PRODUCT_DISABLED: 'Spot product disabled', + PROPOSAL_ERROR_INVALID_MARKET_STATE_UPDATE: 'Invalid market state update', + PROPOSAL_ERROR_INVALID_PERPETUAL_PRODUCT: 'Invalid perpetual product', + PROPOSAL_ERROR_INVALID_SLA_PARAMS: 'Invalid SLA params', + PROPOSAL_ERROR_MISSING_SLA_PARAMS: 'Missing SLA params', }; /** @@ -449,6 +457,17 @@ export const TransferTypeMapping: TransferTypeMap = { TRANSFER_TYPE_HOLDING_LOCK: 'Holding locked', TRANSFER_TYPE_HOLDING_RELEASE: 'Holding released', TRANSFER_TYPE_SPOT: 'Spot', + TRANSFER_TYPE_LIQUIDITY_FEE_ALLOCATE: 'Liquidity fee allocated', + TRANSFER_TYPE_LIQUIDITY_FEE_NET_DISTRIBUTE: 'Liquidity fee net distributed', + TRANSFER_TYPE_LIQUIDITY_FEE_UNPAID_COLLECT: 'Liquidity fee unpaid collected', + TRANSFER_TYPE_PERPETUALS_FUNDING_WIN: 'Perpetuals funding gain', + TRANSFER_TYPE_PERPPETUALS_FUNDING_LOSS: 'Perpetuals funding loss', + TRANSFER_TYPE_REWARDS_VESTED: 'Rewards vested', + TRANSFER_TYPE_SLA_PENALTY_BOND_APPLY: 'SLA penalty bond applied', + TRANSFER_TYPE_SLA_PENALTY_LP_FEE_APPLY: 'SLA penalty LP fee applied', + TRANSFER_TYPE_SLA_PERFORMANCE_BONUS_DISTRIBUTE: + 'SLA performance bonus distributed', + TRANSFER_TYPE_SUCCESSOR_INSURANCE_FRACTION: 'Successor insurance fraction', }; export const DescriptionTransferTypeMapping: TransferTypeMap = { @@ -479,6 +498,17 @@ export const DescriptionTransferTypeMapping: TransferTypeMap = { TRANSFER_TYPE_HOLDING_LOCK: 'Holdings locked', TRANSFER_TYPE_HOLDING_RELEASE: 'Holdings released', TRANSFER_TYPE_SPOT: 'Spot', + TRANSFER_TYPE_LIQUIDITY_FEE_ALLOCATE: 'Liquidity fee allocated', + TRANSFER_TYPE_LIQUIDITY_FEE_NET_DISTRIBUTE: 'Liquidity fee net distributed', + TRANSFER_TYPE_LIQUIDITY_FEE_UNPAID_COLLECT: 'Liquidity fee unpaid collected', + TRANSFER_TYPE_PERPETUALS_FUNDING_WIN: 'Perpetuals funding gain', + TRANSFER_TYPE_PERPPETUALS_FUNDING_LOSS: 'Perpetuals funding loss', + TRANSFER_TYPE_REWARDS_VESTED: 'Rewards vested', + TRANSFER_TYPE_SLA_PENALTY_BOND_APPLY: 'SLA penalty bond applied', + TRANSFER_TYPE_SLA_PENALTY_LP_FEE_APPLY: 'SLA penalty LP fee applied', + TRANSFER_TYPE_SLA_PERFORMANCE_BONUS_DISTRIBUTE: + 'SLA performance bonus distributed', + TRANSFER_TYPE_SUCCESSOR_INSURANCE_FRACTION: 'Successor insurance fraction', }; type DispatchMetricLabel = { diff --git a/libs/web3/src/lib/use-vega-transaction-toasts.tsx b/libs/web3/src/lib/use-vega-transaction-toasts.tsx index 2138c8a2d..d34b37f0e 100644 --- a/libs/web3/src/lib/use-vega-transaction-toasts.tsx +++ b/libs/web3/src/lib/use-vega-transaction-toasts.tsx @@ -49,6 +49,7 @@ import { useOrderByIdQuery, useStopOrderByIdQuery, } from '@vegaprotocol/orders'; +import type { MarketFieldsFragment } from '@vegaprotocol/markets'; import { useMarketsMapProvider } from '@vegaprotocol/markets'; import type { Side } from '@vegaprotocol/types'; import { OrderStatusMapping } from '@vegaprotocol/types'; @@ -131,6 +132,21 @@ const SizeAtPrice = ({ side, size, price, meta }: SizeAtPriceProps) => { ); }; +const getAsset = ( + data: MarketFieldsFragment +): { + decimals: number | undefined; + symbol: string; +} => { + // TODO to handle baseAsset for Spots + return 'settlementAsset' in data.tradableInstrument.instrument.product + ? data?.tradableInstrument?.instrument?.product?.settlementAsset + : { + decimals: 0, + symbol: '', + }; +}; + const SubmitOrderDetails = ({ data, order, @@ -161,9 +177,7 @@ const SubmitOrderDetails = ({ meta={{ positionDecimalPlaces: market.positionDecimalPlaces, decimalPlaces: market.decimalPlaces, - asset: - market.tradableInstrument.instrument.product.settlementAsset - .symbol, + asset: getAsset(market).symbol, }} side={side} size={size} @@ -203,9 +217,7 @@ const SubmitStopOrderDetails = ({ data }: { data: StopOrdersSubmission }) => { meta={{ positionDecimalPlaces: market.positionDecimalPlaces, decimalPlaces: market.decimalPlaces, - asset: - market.tradableInstrument.instrument.product.settlementAsset - .symbol, + asset: getAsset(market).symbol, }} side={side} size={size} @@ -252,8 +264,7 @@ const EditOrderDetails = ({ meta={{ positionDecimalPlaces: market.positionDecimalPlaces, decimalPlaces: market.decimalPlaces, - asset: - market.tradableInstrument.instrument.product.settlementAsset.symbol, + asset: getAsset(market).symbol, }} /> ); @@ -266,8 +277,7 @@ const EditOrderDetails = ({ meta={{ positionDecimalPlaces: market.positionDecimalPlaces, decimalPlaces: market.decimalPlaces, - asset: - market.tradableInstrument.instrument.product.settlementAsset.symbol, + asset: getAsset(market).symbol, }} /> ); @@ -313,8 +323,7 @@ const CancelOrderDetails = ({ meta={{ positionDecimalPlaces: market.positionDecimalPlaces, decimalPlaces: market.decimalPlaces, - asset: - market.tradableInstrument.instrument.product.settlementAsset.symbol, + asset: getAsset(market).symbol, }} /> ); @@ -355,8 +364,7 @@ const CancelStopOrderDetails = ({ stopOrderId }: { stopOrderId: string }) => { meta={{ positionDecimalPlaces: market.positionDecimalPlaces, decimalPlaces: market.decimalPlaces, - asset: - market.tradableInstrument.instrument.product.settlementAsset.symbol, + asset: getAsset(market).symbol, }} />