chore(trading): live update deal ticket market data (#2570)

This commit is contained in:
Bartłomiej Głownia 2023-02-09 15:20:31 +01:00 committed by GitHub
parent 4dd63da62b
commit a5d53eee77
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
70 changed files with 517 additions and 715 deletions

View File

@ -39,10 +39,8 @@ export const MarketList = () => {
const getRowId = useCallback(({ data }: GetRowIdParams) => data.id, []); const getRowId = useCallback(({ data }: GetRowIdParams) => data.id, []);
const localData = data?.markets;
return ( return (
<AsyncRenderer loading={loading} error={error} data={localData}> <AsyncRenderer loading={loading} error={error} data={data}>
<div <div
className="grow w-full" className="grow w-full"
style={{ minHeight: 500, overflow: 'hidden' }} style={{ minHeight: 500, overflow: 'hidden' }}
@ -57,7 +55,7 @@ export const MarketList = () => {
); );
}, },
}} }}
rowData={localData} rowData={data}
defaultColDef={{ defaultColDef={{
resizable: true, resizable: true,
sortable: true, sortable: true,

View File

@ -59,11 +59,9 @@ describe('home', { tags: '@regression' }, () => {
describe('default market found', () => { describe('default market found', () => {
it('redirects to a default market with the landing dialog open', () => { it('redirects to a default market with the landing dialog open', () => {
cy.visit('/'); cy.visit('/');
cy.wait('@Market'); cy.wait('@Markets');
cy.get('main', { timeout: 20000 }).then((el) => { cy.get('main[data-testid^="/markets/"]');
expect(el.attr('data-testid')?.startsWith('/market')).to.equal(true);
}); // Wait for page to be rendered to before checking url
// Overlay should be shown // Overlay should be shown
cy.getByTestId(selectMarketOverlay).should('exist'); cy.getByTestId(selectMarketOverlay).should('exist');
@ -101,7 +99,7 @@ describe('home', { tags: '@regression' }, () => {
// the choose market overlay is no longer showing // the choose market overlay is no longer showing
cy.contains('Select a market to get started').should('not.exist'); cy.contains('Select a market to get started').should('not.exist');
cy.contains('Loading...').should('not.exist'); cy.contains('Loading...').should('not.exist');
cy.url().should('eq', Cypress.config().baseUrl + '/#/markets/market-0'); cy.url().should('eq', Cypress.config().baseUrl + '/#/markets/market-1');
}); });
}); });
@ -125,7 +123,7 @@ describe('home', { tags: '@regression' }, () => {
aliasGQLQuery(req, 'MarketsData', data); aliasGQLQuery(req, 'MarketsData', data);
}); });
cy.visit('/'); cy.visit('/');
cy.wait('@Market'); cy.wait('@Markets');
cy.getByTestId(selectMarketOverlay) cy.getByTestId(selectMarketOverlay)
.get('table') .get('table')
.invoke('outerWidth') .invoke('outerWidth')
@ -233,7 +231,7 @@ describe('home', { tags: '@regression' }, () => {
cy.window().then((window) => { cy.window().then((window) => {
window.localStorage.setItem('marketId', 'market-1'); window.localStorage.setItem('marketId', 'market-1');
cy.visit('/'); cy.visit('/');
cy.wait('@Market'); cy.wait('@Markets');
cy.location('hash').should('equal', '#/markets/market-1'); cy.location('hash').should('equal', '#/markets/market-1');
cy.getByTestId('dialog-content').should('not.exist'); cy.getByTestId('dialog-content').should('not.exist');
}); });
@ -246,7 +244,7 @@ describe('home', { tags: '@regression' }, () => {
aliasGQLQuery(req, 'Market', null); aliasGQLQuery(req, 'Market', null);
}); });
cy.visit('/'); cy.visit('/');
cy.wait('@Market'); cy.wait('@Markets');
cy.location('hash').should('equal', '#/markets/market-not-existing'); cy.location('hash').should('equal', '#/markets/market-not-existing');
cy.getByTestId('dialog-content').should('not.exist'); cy.getByTestId('dialog-content').should('not.exist');
}); });

View File

@ -11,7 +11,7 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
cy.mockTradingPage(); cy.mockTradingPage();
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market'); cy.wait('@Markets');
cy.getByTestId(marketInfoBtn).click(); cy.getByTestId(marketInfoBtn).click();
cy.wait('@MarketInfo'); cy.wait('@MarketInfo');
}); });

View File

@ -237,7 +237,6 @@ describe('market states not accepting orders', { tags: '@smoke' }, function () {
cy.mockSubscription(); cy.mockSubscription();
cy.setVegaWallet(); cy.setVegaWallet();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market');
}); });
it('must display that market is not accepting orders', function () { it('must display that market is not accepting orders', function () {
cy.getByTestId('place-order').click(); cy.getByTestId('place-order').click();

View File

@ -1,6 +1,6 @@
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import { aliasGQLQuery } from '@vegaprotocol/cypress'; import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { marketQuery } from '@vegaprotocol/mock'; import { marketsQuery } from '@vegaprotocol/mock';
import { getDateTimeFormat } from '@vegaprotocol/react-helpers'; import { getDateTimeFormat } from '@vegaprotocol/react-helpers';
describe('markets table', { tags: '@smoke' }, () => { describe('markets table', { tags: '@smoke' }, () => {
@ -13,7 +13,6 @@ describe('markets table', { tags: '@smoke' }, () => {
); );
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/'); cy.visit('/');
cy.wait('@Market');
cy.wait('@Markets'); cy.wait('@Markets');
cy.wait('@MarketsData'); cy.wait('@MarketsData');
cy.wait('@MarketsCandles'); cy.wait('@MarketsCandles');
@ -123,17 +122,24 @@ describe('markets table', { tags: '@smoke' }, () => {
); );
cy.mockGQL((req) => { cy.mockGQL((req) => {
const override = { const override = {
market: { marketsConnection: {
tradableInstrument: { edges: [
instrument: { {
name: `opening auction MARKET`, node: {
tradableInstrument: {
instrument: {
name: `opening auction MARKET`,
},
},
state: Schema.MarketState.STATE_ACTIVE,
tradingMode:
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
},
}, },
}, ],
state: Schema.MarketState.STATE_ACTIVE,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
}, },
}; };
const market = marketQuery(override); const market = marketsQuery(override);
aliasGQLQuery(req, 'Market', market); aliasGQLQuery(req, 'Market', market);
aliasGQLQuery(req, 'ProposalOfMarket', { aliasGQLQuery(req, 'ProposalOfMarket', {
proposal: { terms: { enactmentDatetime: '2023-01-31 12:00:01' } }, proposal: { terms: { enactmentDatetime: '2023-01-31 12:00:01' } },

View File

@ -4,14 +4,15 @@ before(() => {
cy.mockTradingPage(); cy.mockTradingPage();
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/'); cy.visit('/');
cy.wait('@Market'); cy.wait('@Markets');
cy.wait('@MarketsData');
cy.getByTestId('dialog-close').click(); cy.getByTestId('dialog-close').click();
}); });
describe('Desktop view', { tags: '@smoke' }, () => { describe('Desktop view', { tags: '@smoke' }, () => {
describe('Navbar', () => { describe('Navbar', () => {
const links = ['Markets', 'Trading', 'Portfolio']; const links = ['Markets', 'Trading', 'Portfolio'];
const hashes = ['#/markets/all', '#/markets/market-0', '#/portfolio']; const hashes = ['#/markets/all', '#/markets/market-1', '#/portfolio'];
links.forEach((link, index) => { links.forEach((link, index) => {
it(`${link} should be correctly rendered`, () => { it(`${link} should be correctly rendered`, () => {
@ -67,7 +68,7 @@ describe('Mobile view', { tags: '@smoke' }, () => {
cy.getByTestId('button-menu-drawer').click(); cy.getByTestId('button-menu-drawer').click();
cy.getByTestId('menu-drawer').within((el) => { cy.getByTestId('menu-drawer').within((el) => {
cy.wrap(el).getByTestId('Trading').click(); cy.wrap(el).getByTestId('Trading').click();
cy.location('hash').should('equal', '#/markets/market-0'); cy.location('hash').should('equal', '#/markets/market-1');
}); });
}); });
it('Portfolio should be correctly rendered', () => { it('Portfolio should be correctly rendered', () => {

View File

@ -35,7 +35,7 @@ describe('time in force default values', () => {
cy.mockTradingPage(); cy.mockTradingPage();
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market'); cy.wait('@Markets');
}); });
it('must have market order set up to IOC by default', function () { it('must have market order set up to IOC by default', function () {
@ -64,7 +64,7 @@ describe('must submit order', { tags: '@smoke' }, () => {
cy.mockTradingPage(); cy.mockTradingPage();
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market'); cy.wait('@Markets');
}); });
beforeEach(() => { beforeEach(() => {
@ -162,7 +162,7 @@ describe(
); );
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market'); cy.wait('@Markets');
}); });
beforeEach(() => { beforeEach(() => {
@ -231,7 +231,7 @@ describe(
); );
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market'); cy.wait('@Markets');
}); });
beforeEach(() => { beforeEach(() => {
@ -300,7 +300,7 @@ describe(
); );
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market'); cy.wait('@Markets');
}); });
beforeEach(() => { beforeEach(() => {
@ -360,7 +360,7 @@ describe('deal ticket validation', { tags: '@smoke' }, () => {
beforeEach(() => { beforeEach(() => {
cy.mockTradingPage(); cy.mockTradingPage();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market'); cy.wait('@Markets');
}); });
it('must not place an order if wallet is not connected', () => { it('must not place an order if wallet is not connected', () => {
@ -405,7 +405,7 @@ describe('deal ticket size validation', { tags: '@smoke' }, function () {
cy.setVegaWallet(); cy.setVegaWallet();
cy.mockTradingPage(); cy.mockTradingPage();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market'); cy.wait('@Markets');
}); });
it('must warn if order size input has too many digits after the decimal place', function () { it('must warn if order size input has too many digits after the decimal place', function () {
@ -440,7 +440,7 @@ describe('limit order validations', { tags: '@smoke' }, () => {
cy.mockTradingPage(); cy.mockTradingPage();
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market'); cy.wait('@Markets');
cy.getByTestId(toggleLimit).click(); cy.getByTestId(toggleLimit).click();
}); });
@ -452,7 +452,7 @@ describe('limit order validations', { tags: '@smoke' }, () => {
//7002-SORD-018 //7002-SORD-018
cy.getByTestId(orderPriceField) cy.getByTestId(orderPriceField)
.siblings('label') .siblings('label')
.should('have.text', 'Price (BTC)'); .should('have.text', 'Price (DAI)');
}); });
it('must see warning when placing an order with expiry date in past', () => { it('must see warning when placing an order with expiry date in past', () => {
@ -532,7 +532,7 @@ describe('market order validations', { tags: '@smoke' }, () => {
cy.setVegaWallet(); cy.setVegaWallet();
cy.mockTradingPage(); cy.mockTradingPage();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market'); cy.wait('@Markets');
cy.getByTestId(toggleMarket).click(); cy.getByTestId(toggleMarket).click();
}); });
@ -586,7 +586,7 @@ describe('suspended market validation', { tags: '@regression' }, () => {
); );
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market'); cy.wait('@Markets');
}); });
beforeEach(() => { beforeEach(() => {
@ -648,7 +648,7 @@ describe('account validation', { tags: '@regression' }, () => {
market: null, market: null,
asset: { asset: {
__typename: 'Asset', __typename: 'Asset',
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c', id: 'asset-0',
}, },
}, },
}, },
@ -660,7 +660,7 @@ describe('account validation', { tags: '@regression' }, () => {
}); });
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market'); cy.wait('@Markets');
}); });
it('should show an error if your balance is zero', () => { it('should show an error if your balance is zero', () => {
@ -670,7 +670,7 @@ describe('account validation', { tags: '@regression' }, () => {
//7002-SORD-003 //7002-SORD-003
cy.getByTestId('dealticket-error-message-zero-balance').should( cy.getByTestId('dealticket-error-message-zero-balance').should(
'have.text', 'have.text',
'Insufficient balance. Deposit ' + 'tBTC' 'Insufficient balance. Deposit ' + 'tDAI'
); );
cy.getByTestId('deal-ticket-deposit-dialog-button').should('exist'); cy.getByTestId('deal-ticket-deposit-dialog-button').should('exist');
}); });
@ -696,7 +696,7 @@ describe('account validation', { tags: '@regression' }, () => {
}); });
cy.mockSubscription(); cy.mockSubscription();
cy.visit('/#/markets/market-0'); cy.visit('/#/markets/market-0');
cy.wait('@Market'); cy.wait('@Markets');
}); });
it('should display info and button for deposit', () => { it('should display info and button for deposit', () => {
@ -708,7 +708,7 @@ describe('account validation', { tags: '@regression' }, () => {
); );
cy.getByTestId('dealticket-warning-margin').should( cy.getByTestId('dealticket-warning-margin').should(
'contain.text', 'contain.text',
'9,999.99 tBTC currently required, 1,000.00 tBTC available' '9,999.99 tDAI currently required, 1,000.00 tDAI available'
); );
cy.getByTestId('deal-ticket-deposit-dialog-button').click(); cy.getByTestId('deal-ticket-deposit-dialog-button').click();
cy.getByTestId('dialog-content') cy.getByTestId('dialog-content')

View File

@ -15,7 +15,6 @@ import {
marketDataQuery, marketDataQuery,
marketDepthQuery, marketDepthQuery,
marketInfoQuery, marketInfoQuery,
marketQuery,
marketsCandlesQuery, marketsCandlesQuery,
marketsDataQuery, marketsDataQuery,
marketsQuery, marketsQuery,
@ -28,7 +27,7 @@ import {
withdrawalsQuery, withdrawalsQuery,
} from '@vegaprotocol/mock'; } from '@vegaprotocol/mock';
import type { PartialDeep } from 'type-fest'; import type { PartialDeep } from 'type-fest';
import type { MarketDataQuery, MarketQuery } from '@vegaprotocol/market-list'; import type { MarketDataQuery, MarketsQuery } from '@vegaprotocol/market-list';
import type { MarketInfoQuery } from '@vegaprotocol/market-info'; import type { MarketInfoQuery } from '@vegaprotocol/market-info';
type MarketPageMockData = { type MarketPageMockData = {
@ -55,17 +54,18 @@ const marketDataOverride = (
}, },
}); });
const marketQueryOverride = ( const marketsDataOverride = (
data: MarketPageMockData data: MarketPageMockData
): PartialDeep<MarketQuery> => ({ ): PartialDeep<MarketsQuery> => ({
market: { marketsConnection: {
tradableInstrument: { edges: [
instrument: { {
name: `${data.state?.toUpperCase()} MARKET`, node: {
tradingMode: data.tradingMode,
state: data.state,
},
}, },
}, ],
state: data.state,
tradingMode: data.tradingMode,
}, },
}); });
@ -91,10 +91,9 @@ const mockTradingPage = (
aliasGQLQuery(req, 'Statistics', statisticsQuery()); aliasGQLQuery(req, 'Statistics', statisticsQuery());
aliasGQLQuery( aliasGQLQuery(
req, req,
'Market', 'Markets',
marketQuery(marketQueryOverride({ state, tradingMode, trigger })) marketsQuery(marketsDataOverride({ state, tradingMode, trigger }))
); );
aliasGQLQuery(req, 'Markets', marketsQuery());
aliasGQLQuery( aliasGQLQuery(
req, req,
'MarketData', 'MarketData',

View File

@ -59,7 +59,7 @@ export const LiquidityContainer = ({
marketId: string | undefined; marketId: string | undefined;
}) => { }) => {
const gridRef = useRef<AgGridReact | null>(null); const gridRef = useRef<AgGridReact | null>(null);
const market = useMarket(marketId); const { data: market } = useMarket(marketId);
const dataRef = useRef<LiquidityProvisionData[] | null>(null); const dataRef = useRef<LiquidityProvisionData[] | null>(null);
// To be removed when liquidityProvision subscriptions are working // To be removed when liquidityProvision subscriptions are working
@ -129,8 +129,8 @@ export const LiquidityViewContainer = ({
}) => { }) => {
const { pubKey } = useVegaWallet(); const { pubKey } = useVegaWallet();
const gridRef = useRef<AgGridReact | null>(null); const gridRef = useRef<AgGridReact | null>(null);
const market = useMarket(marketId); const { data: market } = useMarket(marketId);
const marketData = useStaticMarketData(marketId); const { data: marketData } = useStaticMarketData(marketId);
const dataRef = useRef<LiquidityProvisionData[] | null>(null); const dataRef = useRef<LiquidityProvisionData[] | null>(null);

View File

@ -9,9 +9,7 @@ import {
} from '@vegaprotocol/react-helpers'; } from '@vegaprotocol/react-helpers';
import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit'; import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit';
import type { import type {
SingleMarketFieldsFragment,
MarketData, MarketData,
Candle,
MarketDataUpdateFieldsFragment, MarketDataUpdateFieldsFragment,
} from '@vegaprotocol/market-list'; } from '@vegaprotocol/market-list';
@ -27,11 +25,6 @@ const calculatePrice = (markPrice?: string, decimalPlaces?: number) => {
: '-'; : '-';
}; };
export interface SingleMarketData extends SingleMarketFieldsFragment {
candles: Candle[];
data: MarketData;
}
const TitleUpdater = ({ const TitleUpdater = ({
marketId, marketId,
marketName, marketName,
@ -89,12 +82,9 @@ export const MarketPage = () => {
[marketId, navigate] [marketId, navigate]
); );
const { data, error, loading } = useDataProvider< const { data, error, loading } = useDataProvider({
SingleMarketFieldsFragment,
never
>({
dataProvider: marketProvider, dataProvider: marketProvider,
variables: useMemo(() => ({ marketId: marketId || '' }), [marketId]), variables: { marketId: marketId || '' },
skip: !marketId, skip: !marketId,
}); });
@ -115,7 +105,7 @@ export const MarketPage = () => {
<Splash> <Splash>
<span className="flex flex-col items-center gap-2"> <span className="flex flex-col items-center gap-2">
<p className="text-sm justify-center"> <p className="text-sm justify-center">
{t('This market URL is not available anymore.')} {t('This market URL is not available any more.')}
</p> </p>
<p className="text-sm justify-center"> <p className="text-sm justify-center">
{t(`Please choose another market from the`)}{' '} {t(`Please choose another market from the`)}{' '}
@ -129,7 +119,7 @@ export const MarketPage = () => {
} }
return ( return (
<AsyncRenderer<SingleMarketFieldsFragment> <AsyncRenderer
loading={loading} loading={loading}
error={error} error={error}
data={data || undefined} data={data || undefined}

View File

@ -21,7 +21,7 @@ import {
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import { AccountsContainer } from '../../components/accounts-container'; import { AccountsContainer } from '../../components/accounts-container';
import type { SingleMarketFieldsFragment } from '@vegaprotocol/market-list'; import type { Market } from '@vegaprotocol/market-list';
import { VegaWalletContainer } from '../../components/vega-wallet-container'; import { VegaWalletContainer } from '../../components/vega-wallet-container';
import { TradeMarketHeader } from './trade-market-header'; import { TradeMarketHeader } from './trade-market-header';
import { NO_MARKET } from './constants'; import { NO_MARKET } from './constants';
@ -63,7 +63,7 @@ const TradingViews = {
type TradingView = keyof typeof TradingViews; type TradingView = keyof typeof TradingViews;
interface TradeGridProps { interface TradeGridProps {
market: SingleMarketFieldsFragment | null; market: Market | null;
onSelect: (marketId: string) => void; onSelect: (marketId: string) => void;
} }
@ -207,7 +207,7 @@ const TradeGridChild = ({ children }: TradeGridChildProps) => {
}; };
interface TradePanelsProps { interface TradePanelsProps {
market: SingleMarketFieldsFragment | null; market: Market | null;
onSelect: (marketId: string) => void; onSelect: (marketId: string) => void;
onMarketClick?: (marketId: string) => void; onMarketClick?: (marketId: string) => void;
} }

View File

@ -2,12 +2,12 @@ import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import { useEnvironment } from '@vegaprotocol/environment'; import { useEnvironment } from '@vegaprotocol/environment';
import { ButtonLink, Link } from '@vegaprotocol/ui-toolkit'; import { ButtonLink, Link } from '@vegaprotocol/ui-toolkit';
import { MarketProposalNotification } from '@vegaprotocol/governance'; import { MarketProposalNotification } from '@vegaprotocol/governance';
import type { Market } from '@vegaprotocol/market-list';
import { import {
getExpiryDate, getExpiryDate,
getMarketExpiryDate, getMarketExpiryDate,
t, t,
} from '@vegaprotocol/react-helpers'; } from '@vegaprotocol/react-helpers';
import type { SingleMarketFieldsFragment } from '@vegaprotocol/market-list';
import { import {
ColumnKind, ColumnKind,
SelectMarketPopover, SelectMarketPopover,
@ -24,7 +24,7 @@ import { MarketLiquiditySupplied } from '../../components/liquidity-supplied';
import { MarketState as State } from '@vegaprotocol/types'; import { MarketState as State } from '@vegaprotocol/types';
interface TradeMarketHeaderProps { interface TradeMarketHeaderProps {
market: SingleMarketFieldsFragment | null; market: Market | null;
onSelect: (marketId: string) => void; onSelect: (marketId: string) => void;
} }
@ -124,7 +124,7 @@ export const TradeMarketHeader = ({
}; };
type ExpiryLabelProps = { type ExpiryLabelProps = {
market: SingleMarketFieldsFragment | null; market: Market | null;
}; };
const ExpiryLabel = ({ market }: ExpiryLabelProps) => { const ExpiryLabel = ({ market }: ExpiryLabelProps) => {
@ -140,7 +140,7 @@ const ExpiryLabel = ({ market }: ExpiryLabelProps) => {
}; };
type ExpiryTooltipContentProps = { type ExpiryTooltipContentProps = {
market: SingleMarketFieldsFragment; market: Market;
explorerUrl?: string; explorerUrl?: string;
}; };

View File

@ -10,7 +10,6 @@ import {
import type { import type {
MarketData, MarketData,
MarketDataUpdateFieldsFragment, MarketDataUpdateFieldsFragment,
SingleMarketFieldsFragment,
} from '@vegaprotocol/market-list'; } from '@vegaprotocol/market-list';
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list'; import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
import { HeaderStat } from '../header'; import { HeaderStat } from '../header';
@ -44,12 +43,12 @@ export const MarketLiquiditySupplied = ({
const variables = useMemo( const variables = useMemo(
() => ({ () => ({
marketId: marketId, marketId: marketId || '',
}), }),
[marketId] [marketId]
); );
const { data } = useDataProvider<SingleMarketFieldsFragment, never>({ const { data } = useDataProvider({
dataProvider: marketProvider, dataProvider: marketProvider,
variables, variables,
skip: !marketId, skip: !marketId,

View File

@ -2,7 +2,7 @@ import throttle from 'lodash/throttle';
import type { import type {
MarketData, MarketData,
MarketDataUpdateFieldsFragment, MarketDataUpdateFieldsFragment,
SingleMarketFieldsFragment, Market,
} from '@vegaprotocol/market-list'; } from '@vegaprotocol/market-list';
import { marketDataProvider } from '@vegaprotocol/market-list'; import { marketDataProvider } from '@vegaprotocol/market-list';
import { t, useDataProvider } from '@vegaprotocol/react-helpers'; import { t, useDataProvider } from '@vegaprotocol/react-helpers';
@ -11,11 +11,7 @@ import { HeaderStat } from '../header';
import { useCallback, useMemo, useRef, useState } from 'react'; import { useCallback, useMemo, useRef, useState } from 'react';
import * as constants from '../constants'; import * as constants from '../constants';
export const MarketState = ({ export const MarketState = ({ market }: { market: Market | null }) => {
market,
}: {
market: SingleMarketFieldsFragment | null;
}) => {
const [marketState, setMarketState] = useState<Schema.MarketState | null>( const [marketState, setMarketState] = useState<Schema.MarketState | null>(
null null
); );

View File

@ -1,37 +1,24 @@
import type { RefObject } from 'react'; import type { RefObject } from 'react';
import { useMemo } from 'react'; import { t } from '@vegaprotocol/react-helpers';
import { t, useDataProvider } from '@vegaprotocol/react-helpers';
import { TradingModeTooltip } from '@vegaprotocol/deal-ticket'; import { TradingModeTooltip } from '@vegaprotocol/deal-ticket';
import { useInView } from 'react-intersection-observer'; import { useInView } from 'react-intersection-observer';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import { HeaderStat } from '../header'; import { HeaderStat } from '../header';
import { Tooltip } from '@vegaprotocol/ui-toolkit'; import { Tooltip } from '@vegaprotocol/ui-toolkit';
import { marketDataProvider } from '@vegaprotocol/market-list'; import { useStaticMarketData } from '@vegaprotocol/market-list';
// This will cause often re-rendering
// Here it may not be a problem because the component is not very complex
// In general, we should avoid using this marketData hook without any throttling
const useMarketData = (marketId?: string, skip?: boolean) => {
const variables = useMemo(() => ({ marketId }), [marketId]);
const { data } = useDataProvider({
dataProvider: marketDataProvider,
variables,
skip: skip || !marketId,
});
return data;
};
const getTradingModeLabel = ( const getTradingModeLabel = (
tradingMode?: Schema.MarketTradingMode, marketTradingMode?: Schema.MarketTradingMode,
trigger?: Schema.AuctionTrigger trigger?: Schema.AuctionTrigger
) => { ) => {
return ( return (
(tradingMode === Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION && (marketTradingMode ===
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
trigger && trigger &&
trigger !== Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED trigger !== Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED
? `${Schema.MarketTradingModeMapping[tradingMode]} - ${Schema.AuctionTriggerMapping[trigger]}` ? `${Schema.MarketTradingModeMapping[marketTradingMode]} - ${Schema.AuctionTriggerMapping[trigger]}`
: Schema.MarketTradingModeMapping[ : Schema.MarketTradingModeMapping[
tradingMode as Schema.MarketTradingMode marketTradingMode as Schema.MarketTradingMode
]) || '-' ]) || '-'
); );
}; };
@ -49,8 +36,8 @@ export const HeaderStatMarketTradingMode = ({
initialTradingMode, initialTradingMode,
initialTrigger, initialTrigger,
}: HeaderStatMarketTradingModeProps) => { }: HeaderStatMarketTradingModeProps) => {
const data = useMarketData(marketId); const { data } = useStaticMarketData(marketId);
const tradingMode = data?.marketTradingMode ?? initialTradingMode; const marketTradingMode = data?.marketTradingMode ?? initialTradingMode;
const trigger = data?.trigger ?? initialTrigger; const trigger = data?.trigger ?? initialTrigger;
return ( return (
@ -61,7 +48,7 @@ export const HeaderStatMarketTradingMode = ({
} }
testId="market-trading-mode" testId="market-trading-mode"
> >
<div>{getTradingModeLabel(tradingMode, trigger)}</div> <div>{getTradingModeLabel(marketTradingMode, trigger)}</div>
</HeaderStat> </HeaderStat>
); );
}; };
@ -75,7 +62,7 @@ export const MarketTradingMode = ({
inViewRoot?: RefObject<Element>; inViewRoot?: RefObject<Element>;
}) => { }) => {
const [ref, inView] = useInView({ root: inViewRoot?.current }); const [ref, inView] = useInView({ root: inViewRoot?.current });
const data = useMarketData(marketId, !inView); const { data } = useStaticMarketData(marketId, !inView);
return ( return (
<Tooltip <Tooltip

View File

@ -8,7 +8,6 @@ import {
import type { import type {
MarketData, MarketData,
MarketDataUpdateFieldsFragment, MarketDataUpdateFieldsFragment,
SingleMarketFieldsFragment,
} from '@vegaprotocol/market-list'; } from '@vegaprotocol/market-list';
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list'; import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
import { HeaderStat } from '../header'; import { HeaderStat } from '../header';
@ -22,7 +21,7 @@ export const MarketVolume = ({ marketId }: { marketId: string }) => {
}), }),
[marketId] [marketId]
); );
const { data } = useDataProvider<SingleMarketFieldsFragment, never>({ const { data } = useDataProvider({
dataProvider: marketProvider, dataProvider: marketProvider,
variables, variables,
skip: !marketId, skip: !marketId,

View File

@ -14,10 +14,7 @@ import {
import { Link as UILink, Sparkline, Tooltip } from '@vegaprotocol/ui-toolkit'; import { Link as UILink, Sparkline, Tooltip } from '@vegaprotocol/ui-toolkit';
import isNil from 'lodash/isNil'; import isNil from 'lodash/isNil';
import type { CandleClose } from '@vegaprotocol/types'; import type { CandleClose } from '@vegaprotocol/types';
import type { import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/market-list';
MarketWithData,
MarketWithCandles,
} from '@vegaprotocol/market-list';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { MarketMarkPrice } from '../market-mark-price'; import { MarketMarkPrice } from '../market-mark-price';
import { Last24hPriceChange } from '../last-24h-price-change'; import { Last24hPriceChange } from '../last-24h-price-change';
@ -25,8 +22,6 @@ import { MarketTradingMode } from '../market-trading-mode';
import { Last24hVolume } from '../last-24h-volume'; import { Last24hVolume } from '../last-24h-volume';
import { Links, Routes } from '../../pages/client-router'; import { Links, Routes } from '../../pages/client-router';
type Market = MarketWithData & MarketWithCandles;
const ellipsisClasses = 'whitespace-nowrap overflow-hidden text-ellipsis'; const ellipsisClasses = 'whitespace-nowrap overflow-hidden text-ellipsis';
export const cellClassNames = `py-1 first:text-left text-right ${ellipsisClasses}`; export const cellClassNames = `py-1 first:text-left text-right ${ellipsisClasses}`;
@ -171,7 +166,7 @@ export type OnCellClickHandler = (
) => void; ) => void;
export const columns = ( export const columns = (
market: Market, market: MarketMaybeWithDataAndCandles,
onSelect: (id: string) => void, onSelect: (id: string) => void,
onCellClick: OnCellClickHandler, onCellClick: OnCellClickHandler,
inViewRoot?: RefObject<HTMLElement> inViewRoot?: RefObject<HTMLElement>
@ -359,7 +354,7 @@ export const columns = (
}; };
export const columnsPositionMarkets = ( export const columnsPositionMarkets = (
market: Market, market: MarketMaybeWithDataAndCandles,
onSelect: (id: string) => void, onSelect: (id: string) => void,
inViewRoot?: RefObject<HTMLElement>, inViewRoot?: RefObject<HTMLElement>,
openVolume?: string, openVolume?: string,

View File

@ -4,13 +4,13 @@ import * as Schema from '@vegaprotocol/types';
import { SelectAllMarketsTableBody } from './select-market'; import { SelectAllMarketsTableBody } from './select-market';
import type { import type {
MarketWithCandles, MarketMaybeWithCandles,
MarketWithData, MarketMaybeWithData,
MarketData, MarketData,
} from '@vegaprotocol/market-list'; } from '@vegaprotocol/market-list';
import { MemoryRouter } from 'react-router-dom'; import { MemoryRouter } from 'react-router-dom';
import { MockedProvider } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing';
type Market = MarketWithCandles & MarketWithData; type Market = MarketMaybeWithCandles & MarketMaybeWithData;
type PartialMarket = Partial< type PartialMarket = Partial<
Omit<Market, 'data'> & { data: Partial<MarketData> } Omit<Market, 'data'> & { data: Partial<MarketData> }
@ -34,9 +34,13 @@ const MARKET_A: PartialMarket = {
settlementAsset: { settlementAsset: {
__typename: 'Asset', __typename: 'Asset',
id: 'asset-ABC', id: 'asset-ABC',
name: '',
decimals: 2, decimals: 2,
symbol: 'ABC', symbol: 'ABC',
}, },
dataSourceSpecForTradingTermination: {
id: '',
},
}, },
metadata: { metadata: {
__typename: 'InstrumentMetadata', __typename: 'InstrumentMetadata',
@ -106,9 +110,13 @@ const MARKET_B: PartialMarket = {
settlementAsset: { settlementAsset: {
__typename: 'Asset', __typename: 'Asset',
id: 'asset-XYZ', id: 'asset-XYZ',
name: 'asset-XYZ',
decimals: 2, decimals: 2,
symbol: 'XYZ', symbol: 'XYZ',
}, },
dataSourceSpecForTradingTermination: {
id: '',
},
}, },
metadata: { metadata: {
__typename: 'InstrumentMetadata', __typename: 'InstrumentMetadata',

View File

@ -17,10 +17,7 @@ import {
SelectMarketTableRowSplash, SelectMarketTableRowSplash,
} from './select-market-table'; } from './select-market-table';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import type { import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/market-list';
MarketWithCandles,
MarketWithData,
} from '@vegaprotocol/market-list';
import type { PositionFieldsFragment } from '@vegaprotocol/positions'; import type { PositionFieldsFragment } from '@vegaprotocol/positions';
import type { Column, OnCellClickHandler } from './select-market-columns'; import type { Column, OnCellClickHandler } from './select-market-columns';
import { import {
@ -30,8 +27,6 @@ import {
} from '@vegaprotocol/environment'; } from '@vegaprotocol/environment';
import { HeaderTitle } from '../header'; import { HeaderTitle } from '../header';
export type Market = MarketWithCandles & MarketWithData;
export const SelectAllMarketsTableBody = ({ export const SelectAllMarketsTableBody = ({
markets, markets,
positions, positions,
@ -41,14 +36,14 @@ export const SelectAllMarketsTableBody = ({
headers = columnHeaders, headers = columnHeaders,
tableColumns = (market) => columns(market, onSelect, onCellClick, inViewRoot), tableColumns = (market) => columns(market, onSelect, onCellClick, inViewRoot),
}: { }: {
markets?: Market[] | null; markets?: MarketMaybeWithDataAndCandles[] | null;
positions?: PositionFieldsFragment[]; positions?: PositionFieldsFragment[];
title?: string; title?: string;
onSelect: (id: string) => void; onSelect: (id: string) => void;
onCellClick: OnCellClickHandler; onCellClick: OnCellClickHandler;
headers?: Column[]; headers?: Column[];
tableColumns?: ( tableColumns?: (
market: Market, market: MarketMaybeWithDataAndCandles,
inViewRoot?: RefObject<HTMLDivElement>, inViewRoot?: RefObject<HTMLDivElement>,
openVolume?: string openVolume?: string
) => Column[]; ) => Column[];

View File

@ -3,13 +3,13 @@ import { MemoryRouter } from 'react-router-dom';
import { MockedProvider } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import type { import type {
MarketWithCandles, MarketMaybeWithCandles,
MarketWithData, MarketMaybeWithData,
MarketData, MarketData,
} from '@vegaprotocol/market-list'; } from '@vegaprotocol/market-list';
import { SelectMarketLandingTable } from './welcome-landing-dialog'; import { SelectMarketLandingTable } from './welcome-landing-dialog';
type Market = MarketWithCandles & MarketWithData; type Market = MarketMaybeWithCandles & MarketMaybeWithData;
type PartialMarket = Partial< type PartialMarket = Partial<
Omit<Market, 'data'> & { data: Partial<MarketData> } Omit<Market, 'data'> & { data: Partial<MarketData> }
>; >;
@ -32,9 +32,13 @@ const MARKET_A: PartialMarket = {
settlementAsset: { settlementAsset: {
__typename: 'Asset', __typename: 'Asset',
id: 'asset-ABC', id: 'asset-ABC',
name: 'asset-ABC',
decimals: 2, decimals: 2,
symbol: 'ABC', symbol: 'ABC',
}, },
dataSourceSpecForTradingTermination: {
id: '',
},
}, },
metadata: { metadata: {
__typename: 'InstrumentMetadata', __typename: 'InstrumentMetadata',
@ -104,9 +108,13 @@ const MARKET_B: PartialMarket = {
settlementAsset: { settlementAsset: {
__typename: 'Asset', __typename: 'Asset',
id: 'asset-XYZ', id: 'asset-XYZ',
name: 'asset-XYZ',
decimals: 2, decimals: 2,
symbol: 'XYZ', symbol: 'XYZ',
}, },
dataSourceSpecForTradingTermination: {
id: '',
},
}, },
metadata: { metadata: {
__typename: 'InstrumentMetadata', __typename: 'InstrumentMetadata',

View File

@ -3,7 +3,8 @@ import { useMarketList } from '@vegaprotocol/market-list';
import { t } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets'; import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import { Link as UILink } from '@vegaprotocol/ui-toolkit'; import { Link as UILink } from '@vegaprotocol/ui-toolkit';
import type { Market, OnCellClickHandler } from '../select-market'; import type { OnCellClickHandler } from '../select-market';
import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/market-list';
import { import {
ColumnKind, ColumnKind,
columns, columns,
@ -19,7 +20,7 @@ export const SelectMarketLandingTable = ({
markets, markets,
onClose, onClose,
}: { }: {
markets: Market[] | null; markets: MarketMaybeWithDataAndCandles[] | null;
onClose: () => void; onClose: () => void;
}) => { }) => {
const params = useParams(); const params = useParams();

View File

@ -14,7 +14,6 @@ export * from '../market-depth/src/lib/market-depth.mock';
export * from '../market-info/src/components/market-info/market-info.mock'; export * from '../market-info/src/components/market-info/market-info.mock';
export * from '../market-list/src/lib/market-candles.mock'; export * from '../market-list/src/lib/market-candles.mock';
export * from '../market-list/src/lib/market-data.mock'; export * from '../market-list/src/lib/market-data.mock';
export * from '../market-list/src/lib/market.mock';
export * from '../market-list/src/lib/markets-candles.mock'; export * from '../market-list/src/lib/markets-candles.mock';
export * from '../market-list/src/lib/markets-data.mock'; export * from '../market-list/src/lib/markets-data.mock';
export * from '../market-list/src/lib/markets.mock'; export * from '../market-list/src/lib/markets.mock';

View File

@ -1,5 +1,5 @@
import type { UseFormRegister } from 'react-hook-form'; import type { UseFormRegister } from 'react-hook-form';
import type { MarketDealTicket } from '@vegaprotocol/market-list'; import type { Market, MarketData } from '@vegaprotocol/market-list';
import { DealTicketMarketAmount } from './deal-ticket-market-amount'; import { DealTicketMarketAmount } from './deal-ticket-market-amount';
import { DealTicketLimitAmount } from './deal-ticket-limit-amount'; import { DealTicketLimitAmount } from './deal-ticket-limit-amount';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
@ -7,7 +7,8 @@ import type { DealTicketFormFields } from './deal-ticket';
export interface DealTicketAmountProps { export interface DealTicketAmountProps {
orderType: Schema.OrderType; orderType: Schema.OrderType;
market: MarketDealTicket; marketData: MarketData;
market: Market;
register: UseFormRegister<DealTicketFormFields>; register: UseFormRegister<DealTicketFormFields>;
sizeError?: string; sizeError?: string;
priceError?: string; priceError?: string;
@ -15,11 +16,12 @@ export interface DealTicketAmountProps {
export const DealTicketAmount = ({ export const DealTicketAmount = ({
orderType, orderType,
marketData,
...props ...props
}: DealTicketAmountProps) => { }: DealTicketAmountProps) => {
switch (orderType) { switch (orderType) {
case Schema.OrderType.TYPE_MARKET: case Schema.OrderType.TYPE_MARKET:
return <DealTicketMarketAmount {...props} />; return <DealTicketMarketAmount {...props} marketData={marketData} />;
case Schema.OrderType.TYPE_LIMIT: case Schema.OrderType.TYPE_LIMIT:
return <DealTicketLimitAmount {...props} />; return <DealTicketLimitAmount {...props} />;
default: { default: {

View File

@ -1,12 +1,9 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit'; import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
import { t, useDataProvider } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import type { import { useThrottledDataProvider } from '@vegaprotocol/react-helpers';
MarketDataUpdateFieldsFragment,
MarketDealTicket,
} from '@vegaprotocol/market-list';
import { useVegaTransactionStore } from '@vegaprotocol/wallet'; import { useVegaTransactionStore } from '@vegaprotocol/wallet';
import { marketDealTicketProvider } from '@vegaprotocol/market-list'; import { useMarket, marketDataProvider } from '@vegaprotocol/market-list';
import { DealTicket } from './deal-ticket'; import { DealTicket } from './deal-ticket';
export interface DealTicketContainerProps { export interface DealTicketContainerProps {
@ -14,31 +11,35 @@ export interface DealTicketContainerProps {
} }
export const DealTicketContainer = ({ marketId }: DealTicketContainerProps) => { export const DealTicketContainer = ({ marketId }: DealTicketContainerProps) => {
const variables = useMemo( const {
() => ({ data: market,
marketId: marketId || '', error: marketError,
}), loading: marketLoading,
[marketId] } = useMarket(marketId);
const {
data: marketData,
error: marketDataError,
loading: marketDataLoading,
} = useThrottledDataProvider(
{
dataProvider: marketDataProvider,
variables: useMemo(() => ({ marketId }), [marketId]),
},
1000
); );
const { data, error, loading } = useDataProvider<
MarketDealTicket,
MarketDataUpdateFieldsFragment
>({
dataProvider: marketDealTicketProvider,
variables,
skip: !marketId,
});
const create = useVegaTransactionStore((state) => state.create); const create = useVegaTransactionStore((state) => state.create);
return ( return (
<AsyncRenderer<MarketDealTicket> <AsyncRenderer
data={data || undefined} data={market && marketData}
loading={loading} loading={marketLoading || marketDataLoading}
error={error} error={marketError || marketDataError}
> >
{data ? ( {market && marketData ? (
<DealTicket <DealTicket
market={data} market={market}
marketData={marketData}
submit={(orderSubmission) => create({ orderSubmission })} submit={(orderSubmission) => create({ orderSubmission })}
/> />
) : ( ) : (

View File

@ -1,7 +1,7 @@
import { Tooltip } from '@vegaprotocol/ui-toolkit'; import { Tooltip } from '@vegaprotocol/ui-toolkit';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet'; import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import type { MarketDealTicket } from '@vegaprotocol/market-list'; import type { Market, MarketData } from '@vegaprotocol/market-list';
import { import {
getFeeDetailsValues, getFeeDetailsValues,
useFeeDealTicketDetails, useFeeDealTicketDetails,
@ -9,7 +9,8 @@ import {
interface DealTicketFeeDetailsProps { interface DealTicketFeeDetailsProps {
order: OrderSubmissionBody['orderSubmission']; order: OrderSubmissionBody['orderSubmission'];
market: MarketDealTicket; market: Market;
marketData: MarketData;
} }
export interface DealTicketFeeDetails { export interface DealTicketFeeDetails {
@ -22,8 +23,9 @@ export interface DealTicketFeeDetails {
export const DealTicketFeeDetails = ({ export const DealTicketFeeDetails = ({
order, order,
market, market,
marketData,
}: DealTicketFeeDetailsProps) => { }: DealTicketFeeDetailsProps) => {
const feeDetails = useFeeDealTicketDetails(order, market); const feeDetails = useFeeDealTicketDetails(order, market, marketData);
const details = getFeeDetailsValues(feeDetails); const details = getFeeDetailsValues(feeDetails);
return ( return (
<div> <div>

View File

@ -3,7 +3,7 @@ import { t, toDecimal, validateAmount } from '@vegaprotocol/react-helpers';
import type { DealTicketAmountProps } from './deal-ticket-amount'; import type { DealTicketAmountProps } from './deal-ticket-amount';
export type DealTicketLimitAmountProps = Omit< export type DealTicketLimitAmountProps = Omit<
DealTicketAmountProps, Omit<DealTicketAmountProps, 'marketData'>,
'orderType' 'orderType'
>; >;

View File

@ -17,11 +17,12 @@ export type DealTicketMarketAmountProps = Omit<
export const DealTicketMarketAmount = ({ export const DealTicketMarketAmount = ({
register, register,
market, market,
marketData,
sizeError, sizeError,
}: DealTicketMarketAmountProps) => { }: DealTicketMarketAmountProps) => {
const quoteName = market.tradableInstrument.instrument.product.quoteName; const quoteName = market.tradableInstrument.instrument.product.quoteName;
const sizeStep = toDecimal(market?.positionDecimalPlaces); const sizeStep = toDecimal(market?.positionDecimalPlaces);
const price = getMarketPrice(market); const price = getMarketPrice(marketData);
const priceFormatted = price const priceFormatted = price
? addDecimalsFormatNumber(price, market.decimalPlaces) ? addDecimalsFormatNumber(price, market.decimalPlaces)
@ -33,7 +34,7 @@ export const DealTicketMarketAmount = ({
<div className="flex-1 text-sm">Size</div> <div className="flex-1 text-sm">Size</div>
<div /> <div />
<div className="flex-2 text-sm text-right"> <div className="flex-2 text-sm text-right">
{isMarketInAuction(market) && ( {isMarketInAuction(marketData.marketTradingMode) && (
<Tooltip <Tooltip
description={t( description={t(
'This market is in auction. The uncrossing price is an indication of what the price is expected to be when the auction ends.' 'This market is in auction. The uncrossing price is an indication of what the price is expected to be when the auction ends.'

View File

@ -7,7 +7,7 @@ import {
act, act,
waitFor, waitFor,
} from '@testing-library/react'; } from '@testing-library/react';
import { generateMarket } from '../../test-helpers'; import { generateMarket, generateMarketData } from '../../test-helpers';
import { DealTicket } from './deal-ticket'; import { DealTicket } from './deal-ticket';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet'; import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
@ -25,6 +25,7 @@ jest.mock('../../hooks/use-has-no-balance', () => {
}); });
const market = generateMarket(); const market = generateMarket();
const marketData = generateMarketData();
const submit = jest.fn(); const submit = jest.fn();
const mockChainId = 'chain-id'; const mockChainId = 'chain-id';
@ -45,7 +46,7 @@ function generateJsx(order?: OrderSubmissionBody['orderSubmission']) {
return ( return (
<MockedProvider mocks={[chainIdMock]}> <MockedProvider mocks={[chainIdMock]}>
<VegaWalletContext.Provider value={{ pubKey: mockChainId } as any}> <VegaWalletContext.Provider value={{ pubKey: mockChainId } as any}>
<DealTicket market={market} submit={submit} /> <DealTicket market={market} marketData={marketData} submit={submit} />
</VegaWalletContext.Provider> </VegaWalletContext.Provider>
</MockedProvider> </MockedProvider>
); );
@ -79,11 +80,10 @@ describe('DealTicket', () => {
expect(screen.getByTestId('order-tif')).toHaveValue( expect(screen.getByTestId('order-tif')).toHaveValue(
Schema.OrderTimeInForce.TIME_IN_FORCE_IOC Schema.OrderTimeInForce.TIME_IN_FORCE_IOC
); );
// Assert last price is shown // Assert last price is shown
expect(screen.getByTestId('last-price')).toHaveTextContent( expect(screen.getByTestId('last-price')).toHaveTextContent(
// eslint-disable-next-line // eslint-disable-next-line
`~${addDecimal(market!.data.markPrice, market.decimalPlaces)} ${ `~${addDecimal(marketData.markPrice, market.decimalPlaces)} ${
market.tradableInstrument.instrument.product.quoteName market.tradableInstrument.instrument.product.quoteName
}` }`
); );

View File

@ -25,14 +25,17 @@ import {
import { ZeroBalanceError } from '../deal-ticket-validation/zero-balance-error'; import { ZeroBalanceError } from '../deal-ticket-validation/zero-balance-error';
import { SummaryValidationType } from '../../constants'; import { SummaryValidationType } from '../../constants';
import { useHasNoBalance } from '../../hooks/use-has-no-balance'; import { useHasNoBalance } from '../../hooks/use-has-no-balance';
import type { MarketDealTicket } from '@vegaprotocol/market-list'; import type { Market, MarketData } from '@vegaprotocol/market-list';
import { import {
usePersistedOrderStore, usePersistedOrderStore,
usePersistedOrderStoreSubscription, usePersistedOrderStoreSubscription,
} from '@vegaprotocol/orders'; } from '@vegaprotocol/orders';
export type TransactionStatus = 'default' | 'pending';
export interface DealTicketProps { export interface DealTicketProps {
market: MarketDealTicket; market: Market;
marketData: MarketData;
submit: (order: OrderSubmissionBody['orderSubmission']) => void; submit: (order: OrderSubmissionBody['orderSubmission']) => void;
} }
@ -42,7 +45,7 @@ export type DealTicketFormFields = OrderSubmissionBody['orderSubmission'] & {
summary: string; summary: string;
}; };
export const DealTicket = ({ market, submit }: DealTicketProps) => { export const DealTicket = ({ market, marketData, submit }: DealTicketProps) => {
const { pubKey, isReadOnly } = useVegaWallet(); const { pubKey, isReadOnly } = useVegaWallet();
const { getPersistedOrder, setPersistedOrder } = usePersistedOrderStore( const { getPersistedOrder, setPersistedOrder } = usePersistedOrderStore(
(store) => ({ (store) => ({
@ -77,12 +80,12 @@ export const DealTicket = ({ market, submit }: DealTicketProps) => {
} }
}); });
const marketStateError = validateMarketState(market.data.marketState); const marketStateError = validateMarketState(marketData.marketState);
const hasNoBalance = useHasNoBalance( const hasNoBalance = useHasNoBalance(
market.tradableInstrument.instrument.product.settlementAsset.id market.tradableInstrument.instrument.product.settlementAsset.id
); );
const marketTradingModeError = validateMarketTradingMode( const marketTradingModeError = validateMarketTradingMode(
market.data.marketTradingMode marketData.marketTradingMode
); );
useEffect(() => { useEffect(() => {
if ( if (
@ -165,13 +168,17 @@ export const DealTicket = ({ market, submit }: DealTicketProps) => {
name="type" name="type"
control={control} control={control}
rules={{ rules={{
validate: validateType(market), validate: validateType(
marketData.marketTradingMode,
marketData.trigger
),
}} }}
render={({ field }) => ( render={({ field }) => (
<TypeSelector <TypeSelector
value={field.value} value={field.value}
onSelect={field.onChange} onSelect={field.onChange}
market={market} market={market}
marketData={marketData}
errorMessage={errors.type?.message} errorMessage={errors.type?.message}
/> />
)} )}
@ -186,6 +193,7 @@ export const DealTicket = ({ market, submit }: DealTicketProps) => {
<DealTicketAmount <DealTicketAmount
orderType={order.type} orderType={order.type}
market={market} market={market}
marketData={marketData}
register={register} register={register}
sizeError={errors.size?.message} sizeError={errors.size?.message}
priceError={errors.price?.message} priceError={errors.price?.message}
@ -194,7 +202,10 @@ export const DealTicket = ({ market, submit }: DealTicketProps) => {
name="timeInForce" name="timeInForce"
control={control} control={control}
rules={{ rules={{
validate: validateTimeInForce(market), validate: validateTimeInForce(
marketData.marketTradingMode,
marketData.trigger
),
}} }}
render={({ field }) => ( render={({ field }) => (
<TimeInForceSelector <TimeInForceSelector
@ -202,6 +213,7 @@ export const DealTicket = ({ market, submit }: DealTicketProps) => {
orderType={order.type} orderType={order.type}
onSelect={field.onChange} onSelect={field.onChange}
market={market} market={market}
marketData={marketData}
errorMessage={errors.timeInForce?.message} errorMessage={errors.timeInForce?.message}
/> />
)} )}
@ -228,10 +240,15 @@ export const DealTicket = ({ market, submit }: DealTicketProps) => {
<SummaryMessage <SummaryMessage
errorMessage={errors.summary?.message} errorMessage={errors.summary?.message}
market={market} market={market}
marketData={marketData}
order={order} order={order}
isReadOnly={isReadOnly} isReadOnly={isReadOnly}
/> />
<DealTicketFeeDetails order={order} market={market} /> <DealTicketFeeDetails
order={order}
market={market}
marketData={marketData}
/>
</form> </form>
); );
}; };
@ -242,17 +259,25 @@ export const DealTicket = ({ market, submit }: DealTicketProps) => {
*/ */
interface SummaryMessageProps { interface SummaryMessageProps {
errorMessage?: string; errorMessage?: string;
market: MarketDealTicket; market: Market;
marketData: MarketData;
order: OrderSubmissionBody['orderSubmission']; order: OrderSubmissionBody['orderSubmission'];
isReadOnly: boolean; isReadOnly: boolean;
} }
const SummaryMessage = memo( const SummaryMessage = memo(
({ errorMessage, market, order, isReadOnly }: SummaryMessageProps) => { ({
errorMessage,
market,
marketData,
order,
isReadOnly,
}: SummaryMessageProps) => {
// Specific error UI for if balance is so we can // Specific error UI for if balance is so we can
// render a deposit dialog // render a deposit dialog
const asset = market.tradableInstrument.instrument.product.settlementAsset; const asset = market.tradableInstrument.instrument.product.settlementAsset;
const { balanceError, balance, margin } = useOrderMarginValidation({ const { balanceError, balance, margin } = useOrderMarginValidation({
market, market,
marketData,
order, order,
}); });
if (isReadOnly) { if (isReadOnly) {
@ -298,7 +323,7 @@ const SummaryMessage = memo(
Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION, Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION, Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION, Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
].includes(market.data.marketTradingMode) ].includes(marketData.marketTradingMode)
) { ) {
return ( return (
<div <div

View File

@ -24,11 +24,10 @@ import {
import { IconNames } from '@blueprintjs/icons'; import { IconNames } from '@blueprintjs/icons';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import type { Market } from '@vegaprotocol/market-list'; import type { Market } from '@vegaprotocol/market-list';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import { marketsProvider } from '@vegaprotocol/market-list'; import { marketsProvider } from '@vegaprotocol/market-list';
interface Props { interface Props {
market: MarketDealTicket; market: Market;
setMarket: (marketId: string) => void; setMarket: (marketId: string) => void;
ItemRenderer?: React.FC<{ ItemRenderer?: React.FC<{
market: Market; market: Market;

View File

@ -8,15 +8,16 @@ import {
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import { DataGrid, t } from '@vegaprotocol/react-helpers'; import { DataGrid, t } from '@vegaprotocol/react-helpers';
import { timeInForceLabel } from '@vegaprotocol/orders'; import { timeInForceLabel } from '@vegaprotocol/orders';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import { compileGridData } from '../trading-mode-tooltip'; import { compileGridData } from '../trading-mode-tooltip';
import { MarketModeValidationType } from '../../constants'; import { MarketModeValidationType } from '../../constants';
import type { Market, StaticMarketData } from '@vegaprotocol/market-list';
interface TimeInForceSelectorProps { interface TimeInForceSelectorProps {
value: Schema.OrderTimeInForce; value: Schema.OrderTimeInForce;
orderType: Schema.OrderType; orderType: Schema.OrderType;
onSelect: (tif: Schema.OrderTimeInForce) => void; onSelect: (tif: Schema.OrderTimeInForce) => void;
market: MarketDealTicket; market: Market;
marketData: StaticMarketData;
errorMessage?: string; errorMessage?: string;
} }
@ -34,6 +35,7 @@ export const TimeInForceSelector = ({
orderType, orderType,
onSelect, onSelect,
market, market,
marketData,
errorMessage, errorMessage,
}: TimeInForceSelectorProps) => { }: TimeInForceSelectorProps) => {
const options = const options =
@ -80,7 +82,7 @@ export const TimeInForceSelector = ({
{t('This market is in auction until it reaches')}{' '} {t('This market is in auction until it reaches')}{' '}
<Tooltip <Tooltip
description={ description={
<DataGrid grid={compileGridData(market, market.data)} /> <DataGrid grid={compileGridData(market, marketData)} />
} }
> >
<span>{t('sufficient liquidity')}</span> <span>{t('sufficient liquidity')}</span>
@ -99,7 +101,7 @@ export const TimeInForceSelector = ({
{t('This market is in auction due to')}{' '} {t('This market is in auction due to')}{' '}
<Tooltip <Tooltip
description={ description={
<DataGrid grid={compileGridData(market, market.data)} /> <DataGrid grid={compileGridData(market, marketData)} />
} }
> >
<span>{t('high price volatility')}</span> <span>{t('high price volatility')}</span>

View File

@ -2,14 +2,15 @@ import { FormGroup, InputError, Tooltip } from '@vegaprotocol/ui-toolkit';
import { DataGrid, t } from '@vegaprotocol/react-helpers'; import { DataGrid, t } from '@vegaprotocol/react-helpers';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import { Toggle } from '@vegaprotocol/ui-toolkit'; import { Toggle } from '@vegaprotocol/ui-toolkit';
import type { MarketDealTicket } from '@vegaprotocol/market-list'; import type { Market, MarketData } from '@vegaprotocol/market-list';
import { compileGridData } from '../trading-mode-tooltip'; import { compileGridData } from '../trading-mode-tooltip';
import { MarketModeValidationType } from '../../constants'; import { MarketModeValidationType } from '../../constants';
interface TypeSelectorProps { interface TypeSelectorProps {
value: Schema.OrderType; value: Schema.OrderType;
onSelect: (type: Schema.OrderType) => void; onSelect: (type: Schema.OrderType) => void;
market: MarketDealTicket; market: Market;
marketData: MarketData;
errorMessage?: string; errorMessage?: string;
} }
@ -22,6 +23,7 @@ export const TypeSelector = ({
value, value,
onSelect, onSelect,
market, market,
marketData,
errorMessage, errorMessage,
}: TypeSelectorProps) => { }: TypeSelectorProps) => {
const renderError = (errorType: MarketModeValidationType) => { const renderError = (errorType: MarketModeValidationType) => {
@ -35,7 +37,7 @@ export const TypeSelector = ({
{t('This market is in auction until it reaches')}{' '} {t('This market is in auction until it reaches')}{' '}
<Tooltip <Tooltip
description={ description={
<DataGrid grid={compileGridData(market, market.data)} /> <DataGrid grid={compileGridData(market, marketData)} />
} }
> >
<span>{t('sufficient liquidity')}</span> <span>{t('sufficient liquidity')}</span>
@ -52,7 +54,7 @@ export const TypeSelector = ({
{t('This market is in auction due to')}{' '} {t('This market is in auction due to')}{' '}
<Tooltip <Tooltip
description={ description={
<DataGrid grid={compileGridData(market, market.data)} /> <DataGrid grid={compileGridData(market, marketData)} />
} }
> >
<span>{t('high price volatility')}</span> <span>{t('high price volatility')}</span>

View File

@ -13,9 +13,9 @@ import type { Market, MarketData } from '@vegaprotocol/market-list';
export const compileGridData = ( export const compileGridData = (
market: Pick< market: Pick<
Market, Market,
'tradableInstrument' | 'id' | 'decimalPlaces' | 'positionDecimalPlaces' 'id' | 'tradableInstrument' | 'decimalPlaces' | 'positionDecimalPlaces'
>, >,
marketData: Pick< marketData?: Pick<
MarketData, MarketData,
| 'marketTradingMode' | 'marketTradingMode'
| 'auctionStart' | 'auctionStart'
@ -25,14 +25,14 @@ export const compileGridData = (
| 'suppliedStake' | 'suppliedStake'
| 'targetStake' | 'targetStake'
| 'trigger' | 'trigger'
>, > | null,
onSelect?: (id: string) => void onSelect?: (id: string) => void
): { label: ReactNode; value?: ReactNode }[] => { ): { label: ReactNode; value?: ReactNode }[] => {
const grid: DataGridProps['grid'] = []; const grid: DataGridProps['grid'] = [];
const isLiquidityMonitoringAuction = const isLiquidityMonitoringAuction =
marketData.marketTradingMode === marketData?.marketTradingMode ===
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION && Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
marketData.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY; marketData?.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY;
const formatStake = (value: string) => { const formatStake = (value: string) => {
const formattedValue = addDecimalsFormatNumber( const formattedValue = addDecimalsFormatNumber(

View File

@ -22,15 +22,16 @@ export const TradingModeTooltip = ({
skip, skip,
}: TradingModeTooltipProps) => { }: TradingModeTooltipProps) => {
const { VEGA_DOCS_URL } = useEnvironment(); const { VEGA_DOCS_URL } = useEnvironment();
const market = useMarket(marketId); const { data: market } = useMarket(marketId);
const marketData = useStaticMarketData(marketId, skip); const { data: marketData } = useStaticMarketData(marketId, skip);
const { marketTradingMode: tradingMode, trigger } = marketData || {}; const { marketTradingMode, trigger } = marketData || {};
const variables = useMemo(() => ({ marketId: marketId || '' }), [marketId]); const variables = useMemo(() => ({ marketId: marketId || '' }), [marketId]);
const { data: proposalData } = useProposalOfMarketQuery({ const { data: proposalData } = useProposalOfMarketQuery({
variables, variables,
skip: skip:
!tradingMode || !marketTradingMode ||
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION !== tradingMode, Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION !==
marketTradingMode,
}); });
if (!market || !marketData) { if (!market || !marketData) {
@ -43,7 +44,7 @@ export const TradingModeTooltip = ({
const compiledGrid = const compiledGrid =
onSelect && compileGridData(market, marketData, onSelect); onSelect && compileGridData(market, marketData, onSelect);
switch (tradingMode) { switch (marketTradingMode) {
case Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS: { case Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS: {
return ( return (
<section data-testid="trading-mode-tooltip"> <section data-testid="trading-mode-tooltip">
@ -67,7 +68,7 @@ export const TradingModeTooltip = ({
className="justify-center font-bold my-2" className="justify-center font-bold my-2"
data-testid="opening-auction-sub-status" data-testid="opening-auction-sub-status"
> >
{`${Schema.MarketTradingModeMapping[tradingMode]}: ${t( {`${Schema.MarketTradingModeMapping[marketTradingMode]}: ${t(
'Not enough liquidity to open' 'Not enough liquidity to open'
)}`} )}`}
</span> </span>
@ -84,7 +85,9 @@ export const TradingModeTooltip = ({
className="justify-center font-bold my-2" className="justify-center font-bold my-2"
data-testid="opening-auction-sub-status" data-testid="opening-auction-sub-status"
> >
{`${Schema.MarketTradingModeMapping[tradingMode]}: ${t( {`${
Schema.MarketTradingModeMapping[marketTradingMode]
}: ${t(
'Closing on %s', 'Closing on %s',
getDateTimeFormat().format(enactmentDate) getDateTimeFormat().format(enactmentDate)
)}`} )}`}

View File

@ -1,6 +1,7 @@
import { MockedProvider } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing';
import { renderHook } from '@testing-library/react'; import { renderHook } from '@testing-library/react';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import type { Market } from '@vegaprotocol/market-list';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet'; import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { useCalculateSlippage } from './use-calculate-slippage'; import { useCalculateSlippage } from './use-calculate-slippage';
@ -74,12 +75,17 @@ describe('useCalculateSlippage Hook', () => {
afterEach(() => { afterEach(() => {
jest.clearAllMocks(); jest.clearAllMocks();
}); });
const market = {
id: 'marketId',
decimalPlaces: 0,
positionDecimalPlaces: 0,
} as Market;
it('long order', () => { it('long order', () => {
const { result } = renderHook( const { result } = renderHook(
() => () =>
useCalculateSlippage({ useCalculateSlippage({
marketId: 'marketId', market,
order: { order: {
size: '10', size: '10',
side: Schema.Side.SIDE_BUY, side: Schema.Side.SIDE_BUY,
@ -96,7 +102,7 @@ describe('useCalculateSlippage Hook', () => {
const { result } = renderHook( const { result } = renderHook(
() => () =>
useCalculateSlippage({ useCalculateSlippage({
marketId: 'marketId', market,
order: { order: {
size: '10', size: '10',
side: Schema.Side.SIDE_SELL, side: Schema.Side.SIDE_SELL,
@ -122,7 +128,7 @@ describe('useCalculateSlippage Hook', () => {
const { result } = renderHook( const { result } = renderHook(
() => () =>
useCalculateSlippage({ useCalculateSlippage({
marketId: 'marketId', market,
order: { order: {
size: '10', size: '10',
side: Schema.Side.SIDE_SELL, side: Schema.Side.SIDE_SELL,

View File

@ -1,36 +1,29 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import { marketDepthProvider } from '@vegaprotocol/market-depth'; import { marketDepthProvider } from '@vegaprotocol/market-depth';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import { marketProvider } from '@vegaprotocol/market-list'; import type { Market } from '@vegaprotocol/market-list';
import type { SingleMarketFieldsFragment } from '@vegaprotocol/market-list';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet'; import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { BigNumber } from 'bignumber.js'; import { BigNumber } from 'bignumber.js';
import { import {
formatNumber, formatNumber,
toBigNum, toBigNum,
useDataProvider,
useThrottledDataProvider, useThrottledDataProvider,
} from '@vegaprotocol/react-helpers'; } from '@vegaprotocol/react-helpers';
interface Props { interface Props {
marketId: string; market: Market;
order: OrderSubmissionBody['orderSubmission']; order: OrderSubmissionBody['orderSubmission'];
} }
export const useCalculateSlippage = ({ marketId, order }: Props) => { export const useCalculateSlippage = ({ market, order }: Props) => {
const variables = useMemo(() => ({ marketId }), [marketId]); const variables = useMemo(() => ({ marketId: market.id }), [market.id]);
const { data } = useThrottledDataProvider( const { data } = useThrottledDataProvider(
{ {
dataProvider: marketDepthProvider, dataProvider: marketDepthProvider,
variables, variables,
}, },
5000 1000
); );
const { data: market } = useDataProvider<SingleMarketFieldsFragment, never>({
dataProvider: marketProvider,
skipUpdates: true,
variables,
});
const volPriceArr = const volPriceArr =
data?.depth[order.side === Schema.Side.SIDE_BUY ? 'sell' : 'buy'] || []; data?.depth[order.side === Schema.Side.SIDE_BUY ? 'sell' : 'buy'] || [];
if (volPriceArr.length && market) { if (volPriceArr.length && market) {

View File

@ -9,7 +9,7 @@ import * as Schema from '@vegaprotocol/types';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import BigNumber from 'bignumber.js'; import BigNumber from 'bignumber.js';
import { useMemo } from 'react'; import { useMemo } from 'react';
import type { MarketDealTicket } from '@vegaprotocol/market-list'; import type { Market, MarketData } from '@vegaprotocol/market-list';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet'; import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { import {
EST_CLOSEOUT_TOOLTIP_TEXT, EST_CLOSEOUT_TOOLTIP_TEXT,
@ -24,14 +24,15 @@ import { getDerivedPrice } from '../utils/get-price';
export const useFeeDealTicketDetails = ( export const useFeeDealTicketDetails = (
order: OrderSubmissionBody['orderSubmission'], order: OrderSubmissionBody['orderSubmission'],
market: MarketDealTicket market: Market,
marketData: MarketData
) => { ) => {
const { pubKey } = useVegaWallet(); const { pubKey } = useVegaWallet();
const slippage = useCalculateSlippage({ marketId: market.id, order }); const slippage = useCalculateSlippage({ market, order });
const derivedPrice = useMemo(() => { const derivedPrice = useMemo(() => {
return getDerivedPrice(order, market); return getDerivedPrice(order, market, marketData);
}, [order, market]); }, [order, market, marketData]);
// Note this isn't currently used anywhere // Note this isn't currently used anywhere
const slippageAdjustedPrice = useMemo(() => { const slippageAdjustedPrice = useMemo(() => {
@ -51,6 +52,7 @@ export const useFeeDealTicketDetails = (
const estMargin = useOrderMargin({ const estMargin = useOrderMargin({
order, order,
market, market,
marketData,
partyId: pubKey || '', partyId: pubKey || '',
derivedPrice, derivedPrice,
}); });
@ -58,6 +60,7 @@ export const useFeeDealTicketDetails = (
const estCloseOut = useOrderCloseOut({ const estCloseOut = useOrderCloseOut({
order, order,
market, market,
marketData,
}); });
const notionalSize = useMemo(() => { const notionalSize = useMemo(() => {
@ -94,7 +97,7 @@ export const useFeeDealTicketDetails = (
}; };
export interface FeeDetails { export interface FeeDetails {
market: MarketDealTicket; market: Market;
symbol: string; symbol: string;
notionalSize: string | null; notionalSize: string | null;
estMargin: OrderMargin | null; estMargin: OrderMargin | null;

View File

@ -1,7 +1,7 @@
import { renderHook } from '@testing-library/react'; import { renderHook } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet'; import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import type { MarketDealTicket } from '@vegaprotocol/market-list'; import type { Market, MarketData } from '@vegaprotocol/market-list';
import { useOrderCloseOut } from './use-order-closeout'; import { useOrderCloseOut } from './use-order-closeout';
jest.mock('@vegaprotocol/wallet', () => ({ jest.mock('@vegaprotocol/wallet', () => ({
@ -18,11 +18,6 @@ describe('useOrderCloseOut', () => {
const order = { size: '2', side: 'SIDE_BUY' }; const order = { size: '2', side: 'SIDE_BUY' };
const market = { const market = {
decimalPlaces: 5, decimalPlaces: 5,
depth: {
lastTrade: {
price: '1000000',
},
},
tradableInstrument: { tradableInstrument: {
instrument: { instrument: {
product: { product: {
@ -32,10 +27,11 @@ describe('useOrderCloseOut', () => {
}, },
}, },
}, },
data: { } as unknown as Market;
markPrice: 100000,
}, const marketData = {
} as unknown as MarketDealTicket; markPrice: 100000,
} as unknown as MarketData;
beforeEach(() => { beforeEach(() => {
jest.clearAllMocks(); jest.clearAllMocks();
@ -47,7 +43,10 @@ describe('useOrderCloseOut', () => {
() => () =>
useOrderCloseOut({ useOrderCloseOut({
order: order as OrderSubmissionBody['orderSubmission'], order: order as OrderSubmissionBody['orderSubmission'],
market: { ...market, data: { ...market.data, markPrice: '0' } }, market,
marketData: {
markPrice: '0',
} as MarketData,
}), }),
{ {
wrapper: MockedProvider, wrapper: MockedProvider,
@ -65,7 +64,8 @@ describe('useOrderCloseOut', () => {
...order, ...order,
side: 'SIDE_SELL', side: 'SIDE_SELL',
} as OrderSubmissionBody['orderSubmission'], } as OrderSubmissionBody['orderSubmission'],
market: market, market,
marketData,
}), }),
{ {
wrapper: MockedProvider, wrapper: MockedProvider,
@ -85,7 +85,8 @@ describe('useOrderCloseOut', () => {
type: 'TYPE_LIMIT', type: 'TYPE_LIMIT',
side: 'SIDE_SELL', side: 'SIDE_SELL',
} as OrderSubmissionBody['orderSubmission'], } as OrderSubmissionBody['orderSubmission'],
market: market, market,
marketData,
}), }),
{ {
wrapper: MockedProvider, wrapper: MockedProvider,
@ -102,7 +103,10 @@ describe('useOrderCloseOut', () => {
...order, ...order,
side: 'SIDE_SELL', side: 'SIDE_SELL',
} as OrderSubmissionBody['orderSubmission'], } as OrderSubmissionBody['orderSubmission'],
market: { ...market, data: { ...market.data, markPrice: '0' } }, market,
marketData: {
markPrice: '0',
} as MarketData,
}), }),
{ {
wrapper: MockedProvider, wrapper: MockedProvider,

View File

@ -2,7 +2,7 @@ import { BigNumber } from 'bignumber.js';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet'; import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { addDecimal } from '@vegaprotocol/react-helpers'; import { addDecimal } from '@vegaprotocol/react-helpers';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import type { MarketDealTicket } from '@vegaprotocol/market-list'; import type { Market, MarketData } from '@vegaprotocol/market-list';
import { import {
useAccountBalance, useAccountBalance,
useMarketAccountBalance, useMarketAccountBalance,
@ -12,10 +12,15 @@ import { useMarketPositions } from './use-market-positions';
interface Props { interface Props {
order: OrderSubmissionBody['orderSubmission']; order: OrderSubmissionBody['orderSubmission'];
market: MarketDealTicket; market: Market;
marketData: MarketData;
} }
export const useOrderCloseOut = ({ order, market }: Props): string | null => { export const useOrderCloseOut = ({
order,
market,
marketData,
}: Props): string | null => {
const { accountBalance, accountDecimals } = useAccountBalance( const { accountBalance, accountDecimals } = useAccountBalance(
market.tradableInstrument.instrument.product.settlementAsset.id market.tradableInstrument.instrument.product.settlementAsset.id
); );
@ -43,9 +48,7 @@ export const useOrderCloseOut = ({ order, market }: Props): string | null => {
const price = const price =
order.type === Schema.OrderType.TYPE_LIMIT && order.price order.type === Schema.OrderType.TYPE_LIMIT && order.price
? new BigNumber(order.price) ? new BigNumber(order.price)
: new BigNumber( : new BigNumber(addDecimal(marketData.markPrice, market.decimalPlaces));
addDecimal(market.data.markPrice || 0, market.decimalPlaces || 0)
);
// regarding formula (marginMaintenanceLevel - positionAccountBalance - generalAccountBalance) / volume + markPrice // regarding formula (marginMaintenanceLevel - positionAccountBalance - generalAccountBalance) / volume + markPrice
const marginDifference = marginMaintenanceLevel const marginDifference = marginMaintenanceLevel
.minus(positionAccountBalance) .minus(positionAccountBalance)

View File

@ -4,18 +4,24 @@ import { toBigNum } from '@vegaprotocol/react-helpers';
import { useAccountBalance } from '@vegaprotocol/accounts'; import { useAccountBalance } from '@vegaprotocol/accounts';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet'; import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { useOrderMargin } from './use-order-margin'; import { useOrderMargin } from './use-order-margin';
import type { MarketDealTicket } from '@vegaprotocol/market-list'; import type { Market, MarketData } from '@vegaprotocol/market-list';
interface Props { interface Props {
market: MarketDealTicket; market: Market;
marketData: MarketData;
order: OrderSubmissionBody['orderSubmission']; order: OrderSubmissionBody['orderSubmission'];
} }
export const useOrderMarginValidation = ({ market, order }: Props) => { export const useOrderMarginValidation = ({
market,
marketData,
order,
}: Props) => {
const { pubKey } = useVegaWallet(); const { pubKey } = useVegaWallet();
const estMargin = useOrderMargin({ const estMargin = useOrderMargin({
order, order,
market, market,
marketData,
partyId: pubKey || '', partyId: pubKey || '',
}); });
const { id: assetId, decimals: assetDecimals } = const { id: assetId, decimals: assetDecimals } =

View File

@ -5,7 +5,7 @@ import type { PositionMargin } from './use-market-positions';
import type { Props } from './use-order-margin'; import type { Props } from './use-order-margin';
import { useOrderMargin } from './use-order-margin'; import { useOrderMargin } from './use-order-margin';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import type { MarketDealTicket } from '@vegaprotocol/market-list'; import type { Market, MarketData } from '@vegaprotocol/market-list';
let mockEstimateData = { let mockEstimateData = {
estimateOrder: { estimateOrder: {
@ -55,11 +55,11 @@ describe('useOrderMargin', () => {
decimalPlaces: 2, decimalPlaces: 2,
positionDecimalPlaces: 0, positionDecimalPlaces: 0,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS, tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
data: { } as unknown as Market,
indicativePrice: '100', marketData: {
markPrice: '200', indicativePrice: '100',
}, markPrice: '200',
} as MarketDealTicket, } as unknown as MarketData,
partyId: 'partyId', partyId: 'partyId',
}; };

View File

@ -4,12 +4,13 @@ import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { removeDecimal } from '@vegaprotocol/react-helpers'; import { removeDecimal } from '@vegaprotocol/react-helpers';
import { useMarketPositions } from './use-market-positions'; import { useMarketPositions } from './use-market-positions';
import { useEstimateOrderQuery } from './__generated__/EstimateOrder'; import { useEstimateOrderQuery } from './__generated__/EstimateOrder';
import type { MarketDealTicket } from '@vegaprotocol/market-list'; import type { Market, MarketData } from '@vegaprotocol/market-list';
import { getDerivedPrice } from '../utils/get-price'; import { getDerivedPrice } from '../utils/get-price';
export interface Props { export interface Props {
order: OrderSubmissionBody['orderSubmission']; order: OrderSubmissionBody['orderSubmission'];
market: MarketDealTicket; market: Market;
marketData: MarketData;
partyId: string; partyId: string;
derivedPrice?: string; derivedPrice?: string;
} }
@ -27,11 +28,13 @@ export interface OrderMargin {
export const useOrderMargin = ({ export const useOrderMargin = ({
order, order,
market, market,
marketData,
partyId, partyId,
derivedPrice, derivedPrice,
}: Props): OrderMargin | null => { }: Props): OrderMargin | null => {
const { balance } = useMarketPositions({ marketId: market.id }) || {}; const { balance } = useMarketPositions({ marketId: market.id }) || {};
const priceForEstimate = derivedPrice || getDerivedPrice(order, market); const priceForEstimate =
derivedPrice || getDerivedPrice(order, market, marketData);
const { data } = useEstimateOrderQuery({ const { data } = useEstimateOrderQuery({
variables: { variables: {

View File

@ -1,68 +1,49 @@
import type { MarketDealTicket } from '@vegaprotocol/market-list'; import type { Market, MarketData } from '@vegaprotocol/market-list';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import merge from 'lodash/merge'; import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest'; import type { PartialDeep } from 'type-fest';
export function generateMarket( export function generateMarket(override?: PartialDeep<Market>): Market {
override?: PartialDeep<MarketDealTicket> const defaultMarket: Market = {
): MarketDealTicket {
const defaultMarket: MarketDealTicket = {
__typename: 'Market', __typename: 'Market',
id: 'market-id', id: 'market-id',
decimalPlaces: 2, decimalPlaces: 2,
positionDecimalPlaces: 1, positionDecimalPlaces: 1,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS, tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
state: Schema.MarketState.STATE_ACTIVE, state: Schema.MarketState.STATE_ACTIVE,
marketTimestamps: {
__typename: 'MarketTimestamps',
close: '',
open: '',
},
tradableInstrument: { tradableInstrument: {
__typename: 'TradableInstrument', __typename: 'TradableInstrument',
instrument: { instrument: {
__typename: 'Instrument', id: '',
id: '1', code: 'BTCUSD.MF21',
name: 'Instrument name', name: 'ACTIVE MARKET',
code: 'instrument-code',
metadata: { metadata: {
__typename: 'InstrumentMetadata', __typename: 'InstrumentMetadata',
tags: [], tags: [],
}, },
product: { product: {
__typename: 'Future',
quoteName: 'quote-name',
dataSourceSpecForTradingTermination: {
id: 'data-source-for-trading-termination-id',
},
settlementAsset: { settlementAsset: {
id: 'asset-0',
symbol: 'tDAI',
name: 'tDAI',
decimals: 5,
__typename: 'Asset', __typename: 'Asset',
id: 'asset-id',
name: 'asset-name',
symbol: 'asset-symbol',
decimals: 2,
}, },
dataSourceSpecForTradingTermination: {
id: '',
},
quoteName: 'BTC',
__typename: 'Future',
}, },
__typename: 'Instrument',
}, },
}, },
data: {
__typename: 'MarketData',
market: {
__typename: 'Market',
id: 'market-id',
},
bestBidPrice: '100',
bestOfferPrice: '100',
markPrice: '200',
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_BATCH,
staticMidPrice: '100',
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
marketState: Schema.MarketState.STATE_ACTIVE,
indicativePrice: '100',
indicativeVolume: '10',
bestStaticBidPrice: '100',
bestStaticOfferPrice: '100',
},
marketTimestamps: {
__typename: 'MarketTimestamps',
open: null,
close: null,
},
fees: { fees: {
factors: { factors: {
makerFee: '0.001', makerFee: '0.001',
@ -70,14 +51,34 @@ export function generateMarket(
liquidityFee: '0.003', liquidityFee: '0.003',
}, },
}, },
depth: {
__typename: 'MarketDepth',
lastTrade: {
__typename: 'Trade',
price: '100',
},
},
}; };
return merge(defaultMarket, override); return merge(defaultMarket, override);
} }
export function generateMarketData(
override?: PartialDeep<MarketData>
): MarketData {
const defaultMarketData: MarketData = {
__typename: 'MarketData',
market: {
id: 'market-id',
__typename: 'Market',
},
auctionStart: '2022-06-21T17:18:43.484055236Z',
auctionEnd: '2022-06-21T17:18:43.484055236Z',
targetStake: '1000000',
suppliedStake: '1000',
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
marketState: Schema.MarketState.STATE_ACTIVE,
staticMidPrice: '0',
indicativePrice: '100',
bestStaticBidPrice: '0',
bestStaticOfferPrice: '0',
indicativeVolume: '10',
bestBidPrice: '0',
bestOfferPrice: '0',
markPrice: '200',
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_BATCH,
};
return merge(defaultMarketData, override);
}

View File

@ -1,24 +1,25 @@
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import { removeDecimal } from '@vegaprotocol/react-helpers'; import { removeDecimal } from '@vegaprotocol/react-helpers';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import { isMarketInAuction } from './is-market-in-auction'; import { isMarketInAuction } from './is-market-in-auction';
import type { MarketData, Market } from '@vegaprotocol/market-list';
/** /**
* Get the market price based on market mode (auction or not auction) * Get the market price based on market mode (auction or not auction)
*/ */
export const getMarketPrice = (market: MarketDealTicket) => { export const getMarketPrice = (marketData: MarketData) => {
if (isMarketInAuction(market)) { const { marketTradingMode, indicativePrice, markPrice } = marketData;
if (isMarketInAuction(marketTradingMode)) {
// 0 can never be a valid uncrossing price // 0 can never be a valid uncrossing price
// as it would require there being orders on the book at that price. // as it would require there being orders on the book at that price.
if ( if (
market.data.indicativePrice && indicativePrice &&
market.data.indicativePrice !== '0' && indicativePrice !== '0' &&
BigInt(market.data.indicativePrice) !== BigInt(0) BigInt(indicativePrice) !== BigInt(0)
) { ) {
return market.data.indicativePrice; return indicativePrice;
} }
} else { } else {
return market.data.markPrice; return markPrice;
} }
return undefined; return undefined;
}; };
@ -33,7 +34,8 @@ export const getDerivedPrice = (
type: Schema.OrderType; type: Schema.OrderType;
price?: string | undefined; price?: string | undefined;
}, },
market: MarketDealTicket market: Market,
marketData: MarketData
) => { ) => {
// If order type is market we should use either the mark price // If order type is market we should use either the mark price
// or the uncrossing price. If order type is limit use the price // or the uncrossing price. If order type is limit use the price
@ -44,7 +46,7 @@ export const getDerivedPrice = (
if (order.type === Schema.OrderType.TYPE_LIMIT && order.price) { if (order.type === Schema.OrderType.TYPE_LIMIT && order.price) {
price = removeDecimal(order.price, market.decimalPlaces); price = removeDecimal(order.price, market.decimalPlaces);
} else { } else {
price = getMarketPrice(market); price = getMarketPrice(marketData);
} }
return price === '0' ? undefined : price; return price === '0' ? undefined : price;

View File

@ -1,13 +1,11 @@
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
export const isMarketInAuction = (market: { export const isMarketInAuction = (
data: { marketTradingMode: Schema.MarketTradingMode
marketTradingMode: Schema.MarketTradingMode; ) => {
};
}) => {
return [ return [
Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION, Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION, Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION, Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
].includes(market.data.marketTradingMode); ].includes(marketTradingMode);
}; };

View File

@ -2,9 +2,9 @@ import { t } from '@vegaprotocol/react-helpers';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
export const validateMarketTradingMode = ( export const validateMarketTradingMode = (
tradingMode: Schema.MarketTradingMode marketTradingMode: Schema.MarketTradingMode
) => { ) => {
if (tradingMode === Schema.MarketTradingMode.TRADING_MODE_NO_TRADING) { if (marketTradingMode === Schema.MarketTradingMode.TRADING_MODE_NO_TRADING) {
return t('Trading terminated'); return t('Trading terminated');
} }

View File

@ -1,19 +1,21 @@
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import { MarketModeValidationType } from '../constants'; import { MarketModeValidationType } from '../constants';
import { isMarketInAuction } from './is-market-in-auction'; import { isMarketInAuction } from './is-market-in-auction';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
export const validateTimeInForce = (market: MarketDealTicket) => { export const validateTimeInForce = (
marketTradingMode: Schema.MarketTradingMode,
trigger: Schema.AuctionTrigger
) => {
return (value: Schema.OrderTimeInForce) => { return (value: Schema.OrderTimeInForce) => {
const isMonitoringAuction = const isMonitoringAuction =
market.data.marketTradingMode === marketTradingMode ===
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION; Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION;
const isPriceTrigger = const isPriceTrigger =
market.data.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE; trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE;
const isLiquidityTrigger = const isLiquidityTrigger =
market.data.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY; trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY;
if (isMarketInAuction(market)) { if (isMarketInAuction(marketTradingMode)) {
if ( if (
[ [
Schema.OrderTimeInForce.TIME_IN_FORCE_FOK, Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,

View File

@ -1,18 +1,23 @@
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import { MarketModeValidationType } from '../constants'; import { MarketModeValidationType } from '../constants';
import { isMarketInAuction } from './is-market-in-auction'; import { isMarketInAuction } from './is-market-in-auction';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
export const validateType = (market: MarketDealTicket) => { export const validateType = (
marketTradingMode: Schema.MarketTradingMode,
trigger: Schema.AuctionTrigger
) => {
return (value: Schema.OrderType) => { return (value: Schema.OrderType) => {
if (isMarketInAuction(market) && value === Schema.OrderType.TYPE_MARKET) { if (
isMarketInAuction(marketTradingMode) &&
value === Schema.OrderType.TYPE_MARKET
) {
const isMonitoringAuction = const isMonitoringAuction =
market.data.marketTradingMode === marketTradingMode ===
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION; Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION;
const isPriceTrigger = const isPriceTrigger =
market.data.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE; trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE;
const isLiquidityTrigger = const isLiquidityTrigger =
market.data.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY; trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY;
if (isMonitoringAuction && isPriceTrigger) { if (isMonitoringAuction && isPriceTrigger) {
return MarketModeValidationType.PriceMonitoringAuction; return MarketModeValidationType.PriceMonitoringAuction;

View File

@ -72,10 +72,14 @@ export const generateFill = (override?: PartialDeep<Trade>) => {
settlementAsset: { settlementAsset: {
__typename: 'Asset', __typename: 'Asset',
id: 'assset-id', id: 'assset-id',
name: 'assset-id',
symbol: 'SYM', symbol: 'SYM',
decimals: 18, decimals: 18,
}, },
quoteName: '', quoteName: '',
dataSourceSpecForTradingTermination: {
id: '',
},
}, },
}, },
}, },

View File

@ -9,8 +9,7 @@ import {
import type { import type {
MarketCandles, MarketCandles,
MarketWithCandles, MarketMaybeWithDataAndCandles,
MarketWithData,
} from '@vegaprotocol/market-list'; } from '@vegaprotocol/market-list';
import { import {
@ -37,21 +36,20 @@ export interface FeeLevels {
fee: string; fee: string;
} }
export type Market = MarketWithData & export type Market = MarketMaybeWithDataAndCandles & {
MarketWithCandles & { feeLevels: FeeLevels[];
feeLevels: FeeLevels[]; target: string;
target: string; dayVolume: string;
dayVolume: string; liquidityCommitted: number;
liquidityCommitted: number; volumeChange: string;
volumeChange: string; tradableInstrument?: {
tradableInstrument?: { instrument?: {
instrument?: { metadata?: {
metadata?: { tags?: string[] | null;
tags?: string[] | null;
};
}; };
}; };
}; };
};
export interface Markets { export interface Markets {
markets: Market[]; markets: Market[];
@ -68,7 +66,7 @@ const getData = (
}; };
export const addData = ( export const addData = (
markets: (MarketWithData & MarketWithCandles)[], markets: MarketMaybeWithDataAndCandles[],
marketsCandles24hAgo: MarketCandles[], marketsCandles24hAgo: MarketCandles[],
marketsLiquidity: LiquidityProvisionMarket[] marketsLiquidity: LiquidityProvisionMarket[]
) => { ) => {
@ -104,7 +102,7 @@ export const liquidityMarketsProvider = makeDataProvider<
getData, getData,
}); });
const liquidityProvisionProvider = makeDerivedDataProvider<Markets, never>( const liquidityProvisionProvider = makeDerivedDataProvider<Market[], never>(
[ [
marketListProvider, marketListProvider,
(callback, client, variables) => (callback, client, variables) =>
@ -115,12 +113,11 @@ const liquidityProvisionProvider = makeDerivedDataProvider<Markets, never>(
liquidityMarketsProvider, liquidityMarketsProvider,
], ],
(parts) => { (parts) => {
const data = addData( return addData(
parts[0] as (MarketWithData & MarketWithCandles)[], parts[0] as MarketMaybeWithDataAndCandles[],
parts[1] as MarketCandles[], parts[1] as MarketCandles[],
parts[2] as LiquidityProvisionMarket[] parts[2] as LiquidityProvisionMarket[]
); );
return { markets: data };
} }
); );

View File

@ -1,98 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type SingleMarketFieldsFragment = { __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<string> | null }, product: { __typename?: 'Future', quoteName: string, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string }, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, depth: { __typename?: 'MarketDepth', lastTrade?: { __typename?: 'Trade', price: string } | null } };
export type MarketQueryVariables = Types.Exact<{
marketId: Types.Scalars['ID'];
}>;
export type MarketQuery = { __typename?: 'Query', market?: { __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<string> | null }, product: { __typename?: 'Future', quoteName: string, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string }, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, depth: { __typename?: 'MarketDepth', lastTrade?: { __typename?: 'Trade', price: string } | null } } | null };
export const SingleMarketFieldsFragmentDoc = gql`
fragment SingleMarketFields on Market {
id
decimalPlaces
positionDecimalPlaces
state
tradingMode
fees {
factors {
makerFee
infrastructureFee
liquidityFee
}
}
tradableInstrument {
instrument {
id
name
code
metadata {
tags
}
product {
... on Future {
dataSourceSpecForTradingTermination {
id
}
settlementAsset {
id
symbol
name
decimals
}
quoteName
}
}
}
}
marketTimestamps {
open
close
}
depth {
lastTrade {
price
}
}
}
`;
export const MarketDocument = gql`
query Market($marketId: ID!) {
market(id: $marketId) {
...SingleMarketFields
}
}
${SingleMarketFieldsFragmentDoc}`;
/**
* __useMarketQuery__
*
* To run a query within a React component, call `useMarketQuery` and pass it any options that fit your needs.
* When your component renders, `useMarketQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useMarketQuery({
* variables: {
* marketId: // value for 'marketId'
* },
* });
*/
export function useMarketQuery(baseOptions: Apollo.QueryHookOptions<MarketQuery, MarketQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<MarketQuery, MarketQueryVariables>(MarketDocument, options);
}
export function useMarketLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<MarketQuery, MarketQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<MarketQuery, MarketQueryVariables>(MarketDocument, options);
}
export type MarketQueryHookResult = ReturnType<typeof useMarketQuery>;
export type MarketLazyQueryHookResult = ReturnType<typeof useMarketLazyQuery>;
export type MarketQueryResult = Apollo.QueryResult<MarketQuery, MarketQueryVariables>;

View File

@ -3,12 +3,12 @@ import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client'; import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client'; import * as Apollo from '@apollo/client';
const defaultOptions = {} as const; const defaultOptions = {} as const;
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<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, decimals: number } } } }, 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<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } };
export type MarketsQueryVariables = Types.Exact<{ [key: string]: never; }>; 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<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, decimals: number } } } }, 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<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } } }> } | null };
export const MarketFieldsFragmentDoc = gql` export const MarketFieldsFragmentDoc = gql`
fragment MarketFields on Market { fragment MarketFields on Market {
@ -37,9 +37,13 @@ export const MarketFieldsFragmentDoc = gql`
settlementAsset { settlementAsset {
id id
symbol symbol
name
decimals decimals
} }
quoteName quoteName
dataSourceSpecForTradingTermination {
id
}
} }
} }
} }

View File

@ -15,7 +15,7 @@ import { AgGridDynamic as AgGrid, ButtonLink } from '@vegaprotocol/ui-toolkit';
import { AgGridColumn } from 'ag-grid-react'; import { AgGridColumn } from 'ag-grid-react';
import type { AgGridReact } from 'ag-grid-react'; import type { AgGridReact } from 'ag-grid-react';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import type { MarketFieldsFragment, MarketWithData } from '../../'; import type { MarketMaybeWithData, MarketFieldsFragment } from '../../';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets'; import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
const { MarketTradingMode, AuctionTrigger } = Schema; const { MarketTradingMode, AuctionTrigger } = Schema;
@ -24,7 +24,7 @@ export const getRowId = ({ data }: { data: { id: string } }) => data.id;
export const MarketListTable = forwardRef< export const MarketListTable = forwardRef<
AgGridReact, AgGridReact,
TypedDataAgGrid<MarketWithData> TypedDataAgGrid<MarketMaybeWithData>
>((props, ref) => { >((props, ref) => {
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore(); const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
return ( return (
@ -51,7 +51,7 @@ export const MarketListTable = forwardRef<
value, value,
data, data,
}: VegaICellRendererParams< }: VegaICellRendererParams<
MarketWithData, MarketMaybeWithData,
'tradableInstrument.instrument.code' 'tradableInstrument.instrument.code'
>) => { >) => {
if (!data) return null; if (!data) return null;
@ -68,7 +68,7 @@ export const MarketListTable = forwardRef<
minWidth={170} minWidth={170}
valueGetter={({ valueGetter={({
data, data,
}: VegaValueGetterParams<MarketWithData, 'data'>) => { }: VegaValueGetterParams<MarketMaybeWithData, 'data'>) => {
if (!data?.data) return undefined; if (!data?.data) return undefined;
const { trigger } = data.data; const { trigger } = data.data;
const { tradingMode } = data; const { tradingMode } = data;
@ -98,14 +98,17 @@ export const MarketListTable = forwardRef<
filter="agNumberColumnFilter" filter="agNumberColumnFilter"
valueGetter={({ valueGetter={({
data, data,
}: VegaValueGetterParams<MarketWithData, 'data.bestBidPrice'>) => { }: VegaValueGetterParams<MarketMaybeWithData, 'data.bestBidPrice'>) => {
return data?.data?.bestBidPrice === undefined return data?.data?.bestBidPrice === undefined
? undefined ? undefined
: toBigNum(data?.data?.bestBidPrice, data.decimalPlaces).toNumber(); : toBigNum(data?.data?.bestBidPrice, data.decimalPlaces).toNumber();
}} }}
valueFormatter={({ valueFormatter={({
data, data,
}: VegaValueFormatterParams<MarketWithData, 'data.bestBidPrice'>) => }: VegaValueFormatterParams<
MarketMaybeWithData,
'data.bestBidPrice'
>) =>
data?.data?.bestBidPrice === undefined data?.data?.bestBidPrice === undefined
? undefined ? undefined
: addDecimalsFormatNumber( : addDecimalsFormatNumber(
@ -122,7 +125,10 @@ export const MarketListTable = forwardRef<
filter="agNumberColumnFilter" filter="agNumberColumnFilter"
valueGetter={({ valueGetter={({
data, data,
}: VegaValueGetterParams<MarketWithData, 'data.bestOfferPrice'>) => { }: VegaValueGetterParams<
MarketMaybeWithData,
'data.bestOfferPrice'
>) => {
return data?.data?.bestOfferPrice === undefined return data?.data?.bestOfferPrice === undefined
? undefined ? undefined
: toBigNum( : toBigNum(
@ -132,7 +138,10 @@ export const MarketListTable = forwardRef<
}} }}
valueFormatter={({ valueFormatter={({
data, data,
}: VegaValueFormatterParams<MarketWithData, 'data.bestOfferPrice'>) => }: VegaValueFormatterParams<
MarketMaybeWithData,
'data.bestOfferPrice'
>) =>
data?.data?.bestOfferPrice === undefined data?.data?.bestOfferPrice === undefined
? undefined ? undefined
: addDecimalsFormatNumber( : addDecimalsFormatNumber(
@ -149,14 +158,14 @@ export const MarketListTable = forwardRef<
filter="agNumberColumnFilter" filter="agNumberColumnFilter"
valueGetter={({ valueGetter={({
data, data,
}: VegaValueGetterParams<MarketWithData, 'data.markPrice'>) => { }: VegaValueGetterParams<MarketMaybeWithData, 'data.markPrice'>) => {
return data?.data?.markPrice === undefined return data?.data?.markPrice === undefined
? undefined ? undefined
: toBigNum(data?.data?.markPrice, data.decimalPlaces).toNumber(); : toBigNum(data?.data?.markPrice, data.decimalPlaces).toNumber();
}} }}
valueFormatter={({ valueFormatter={({
data, data,
}: VegaValueFormatterParams<MarketWithData, 'data.markPrice'>) => }: VegaValueFormatterParams<MarketMaybeWithData, 'data.markPrice'>) =>
data?.data?.bestOfferPrice === undefined data?.data?.bestOfferPrice === undefined
? undefined ? undefined
: addDecimalsFormatNumber(data.data.markPrice, data.decimalPlaces) : addDecimalsFormatNumber(data.data.markPrice, data.decimalPlaces)
@ -168,7 +177,7 @@ export const MarketListTable = forwardRef<
cellRenderer={({ cellRenderer={({
value, value,
}: VegaICellRendererParams< }: VegaICellRendererParams<
MarketWithData, MarketMaybeWithData,
'tradableInstrument.instrument.product.settlementAsset' 'tradableInstrument.instrument.product.settlementAsset'
>) => >) =>
value ? ( value ? (

View File

@ -4,13 +4,13 @@ import { MarketListTable } from './market-list-table';
import { useDataProvider } from '@vegaprotocol/react-helpers'; import { useDataProvider } from '@vegaprotocol/react-helpers';
import type { RowClickedEvent } from 'ag-grid-community'; import type { RowClickedEvent } from 'ag-grid-community';
import { marketsWithDataProvider as dataProvider } from '../../markets-provider'; import { marketsWithDataProvider as dataProvider } from '../../markets-provider';
import type { MarketWithData } from '../../markets-provider'; import type { MarketMaybeWithData } from '../../markets-provider';
interface MarketsContainerProps { interface MarketsContainerProps {
onSelect: (marketId: string) => void; onSelect: (marketId: string) => void;
} }
export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => { export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
const { data, error, loading } = useDataProvider<MarketWithData[], never>({ const { data, error, loading } = useDataProvider({
dataProvider, dataProvider,
skipUpdates: true, skipUpdates: true,
}); });
@ -27,7 +27,7 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
) { ) {
return; return;
} }
onSelect((data as MarketWithData).id); onSelect((data as MarketMaybeWithData).id);
}} }}
/> />
<div className="pointer-events-none absolute inset-0"> <div className="pointer-events-none absolute inset-0">

View File

@ -3,13 +3,11 @@ export * from './utils';
export { marketCandlesProvider } from './market-candles-provider'; export { marketCandlesProvider } from './market-candles-provider';
export type { Candle } from './market-candles-provider'; export type { Candle } from './market-candles-provider';
export * from './market-data-provider'; export * from './market-data-provider';
export * from './market-provider';
export * from './markets-candles-provider'; export * from './markets-candles-provider';
export * from './markets-data-provider'; export * from './markets-data-provider';
export * from './markets-provider'; export * from './markets-provider';
export * from './__generated__/market-candles'; export * from './__generated__/market-candles';
export * from './__generated__/market-data'; export * from './__generated__/market-data';
export * from './__generated__/market';
export * from './__generated__/markets'; export * from './__generated__/markets';
export * from './__generated__/markets-candles'; export * from './__generated__/markets-candles';
export * from './__generated__/markets-data'; export * from './__generated__/markets-data';

View File

@ -54,6 +54,7 @@ export const marketDataProvider = makeDataProvider<
export type StaticMarketData = Pick< export type StaticMarketData = Pick<
MarketData, MarketData,
| 'marketTradingMode' | 'marketTradingMode'
| 'marketState'
| 'auctionStart' | 'auctionStart'
| 'auctionEnd' | 'auctionEnd'
| 'indicativePrice' | 'indicativePrice'
@ -73,6 +74,7 @@ export const staticMarketDataProvider = makeDerivedDataProvider<
} }
const data: StaticMarketData = { const data: StaticMarketData = {
marketTradingMode: marketData.marketTradingMode, marketTradingMode: marketData.marketTradingMode,
marketState: marketData.marketState,
auctionStart: marketData.auctionStart, auctionStart: marketData.auctionStart,
auctionEnd: marketData.auctionEnd, auctionEnd: marketData.auctionEnd,
indicativePrice: marketData.indicativePrice, indicativePrice: marketData.indicativePrice,
@ -91,10 +93,9 @@ export const staticMarketDataProvider = makeDerivedDataProvider<
export const useStaticMarketData = (marketId?: string, skip?: boolean) => { export const useStaticMarketData = (marketId?: string, skip?: boolean) => {
const variables = useMemo(() => ({ marketId }), [marketId]); const variables = useMemo(() => ({ marketId }), [marketId]);
const { data } = useDataProvider({ return useDataProvider({
dataProvider: staticMarketDataProvider, dataProvider: staticMarketDataProvider,
variables, variables,
skip: skip || !marketId, skip: skip || !marketId,
}); });
return data;
}; };

View File

@ -1,41 +0,0 @@
import {
makeDataProvider,
makeDerivedDataProvider,
} from '@vegaprotocol/react-helpers';
import { MarketDocument } from './__generated__/market';
import type {
MarketQuery,
SingleMarketFieldsFragment,
} from './__generated__/market';
import type { MarketData } from './market-data-provider';
import { marketDataProvider } from './market-data-provider';
const getData = (
responseData: MarketQuery | null
): SingleMarketFieldsFragment | null => responseData?.market || null;
export const marketProvider = makeDataProvider<
MarketQuery,
SingleMarketFieldsFragment,
never,
never
>({
query: MarketDocument,
getData,
});
export type MarketDealTicket = SingleMarketFieldsFragment & {
data: MarketData;
};
export type MarketDealTicketAsset =
MarketDealTicket['tradableInstrument']['instrument']['product']['settlementAsset'];
export const marketDealTicketProvider = makeDerivedDataProvider<
MarketDealTicket,
never
>([marketProvider, marketDataProvider], ([market, marketData]) => {
return {
...market,
data: marketData,
};
});

View File

@ -1,53 +0,0 @@
fragment SingleMarketFields on Market {
id
decimalPlaces
positionDecimalPlaces
state
tradingMode
fees {
factors {
makerFee
infrastructureFee
liquidityFee
}
}
tradableInstrument {
instrument {
id
name
code
metadata {
tags
}
product {
... on Future {
dataSourceSpecForTradingTermination {
id
}
settlementAsset {
id
symbol
name
decimals
}
quoteName
}
}
}
}
marketTimestamps {
open
close
}
depth {
lastTrade {
price
}
}
}
query Market($marketId: ID!) {
market(id: $marketId) {
...SingleMarketFields
}
}

View File

@ -1,79 +0,0 @@
import merge from 'lodash/merge';
import * as Schema from '@vegaprotocol/types';
import type { PartialDeep } from 'type-fest';
import type {
MarketQuery,
SingleMarketFieldsFragment,
} from './__generated__/market';
export const marketQuery = (
override?: PartialDeep<MarketQuery>
): MarketQuery => {
const defaultResult: MarketQuery = {
__typename: 'Query',
market: Object.assign({}, singleMarketFieldsFragment),
};
return merge(Object.assign({}, defaultResult), override);
};
const singleMarketFieldsFragment: SingleMarketFieldsFragment = {
__typename: 'Market',
id: 'market-0',
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
state: Schema.MarketState.STATE_ACTIVE,
decimalPlaces: 5,
positionDecimalPlaces: 0,
tradableInstrument: {
instrument: {
id: 'BTCUSD.MF21',
name: 'ACTIVE MARKET',
code: 'BTCUSD.MF21',
metadata: {
tags: [
'formerly:076BB86A5AA41E3E',
'base:BTC',
'quote:USD',
'class:fx/crypto',
'monthly',
'sector:crypto',
],
__typename: 'InstrumentMetadata',
},
product: {
dataSourceSpecForTradingTermination: {
id: 'd253c16c6a17ab88e098479635c611ab503582a1079752d1a49ac15f656f7e7b',
__typename: 'DataSourceSpec',
},
quoteName: 'BTC',
settlementAsset: {
decimals: 5,
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
symbol: 'tBTC',
name: 'tBTC TEST',
__typename: 'Asset',
},
__typename: 'Future',
},
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
marketTimestamps: {
open: '2022-06-21T17:18:43.484055236Z',
close: null,
__typename: 'MarketTimestamps',
},
fees: {
__typename: 'Fees',
factors: {
__typename: 'FeeFactors',
makerFee: '0.0002',
infrastructureFee: '0.0005',
liquidityFee: '0.0005',
},
},
depth: {
__typename: 'MarketDepth',
lastTrade: { price: '100', __typename: 'Trade' },
},
};

View File

@ -9,6 +9,7 @@ import type {
MarketFieldsFragment, MarketFieldsFragment,
} from './__generated__/markets'; } from './__generated__/markets';
import { marketsDataProvider } from './markets-data-provider'; import { marketsDataProvider } from './markets-data-provider';
import { marketDataProvider } from './market-data-provider';
import { marketsCandlesProvider } from './markets-candles-provider'; import { marketsCandlesProvider } from './markets-candles-provider';
import type { MarketData } from './market-data-provider'; import type { MarketData } from './market-data-provider';
import type { MarketCandles } from './markets-candles-provider'; import type { MarketCandles } from './markets-candles-provider';
@ -35,7 +36,7 @@ export const marketsProvider = makeDataProvider<
fetchPolicy: 'cache-first', fetchPolicy: 'cache-first',
}); });
const marketProvider = makeDerivedDataProvider< export const marketProvider = makeDerivedDataProvider<
Market, Market,
never, never,
{ marketId: string } { marketId: string }
@ -49,20 +50,31 @@ const marketProvider = makeDerivedDataProvider<
export const useMarket = (marketId?: string) => { export const useMarket = (marketId?: string) => {
const variables = useMemo(() => ({ marketId: marketId || '' }), [marketId]); const variables = useMemo(() => ({ marketId: marketId || '' }), [marketId]);
const { data } = useDataProvider({ return useDataProvider({
dataProvider: marketProvider, dataProvider: marketProvider,
variables, variables,
skip: !marketId, skip: !marketId,
}); });
return data;
}; };
export type MarketWithData = Market & { data: MarketData };
export const marketWithDataProvider = makeDerivedDataProvider<
MarketWithData,
never,
{ marketId: string }
>([marketProvider, marketDataProvider], ([market, marketData]) => {
return {
...market,
data: marketData,
};
});
export const activeMarketsProvider = makeDerivedDataProvider<Market[], never>( export const activeMarketsProvider = makeDerivedDataProvider<Market[], never>(
[marketsProvider], [marketsProvider],
([markets]) => filterAndSortMarkets(markets) ([markets]) => filterAndSortMarkets(markets)
); );
export type MarketWithCandles = Market & { candles?: Candle[] }; export type MarketMaybeWithCandles = Market & { candles?: Candle[] };
const addCandles = <T extends Market>( const addCandles = <T extends Market>(
markets: T[], markets: T[],
@ -75,7 +87,7 @@ const addCandles = <T extends Market>(
})); }));
export const marketsWithCandlesProvider = makeDerivedDataProvider< export const marketsWithCandlesProvider = makeDerivedDataProvider<
MarketWithCandles[], MarketMaybeWithCandles[],
never never
>( >(
[ [
@ -85,7 +97,7 @@ export const marketsWithCandlesProvider = makeDerivedDataProvider<
(parts) => addCandles(parts[0] as Market[], parts[1] as MarketCandles[]) (parts) => addCandles(parts[0] as Market[], parts[1] as MarketCandles[])
); );
export type MarketWithData = Market & { data?: MarketData }; export type MarketMaybeWithData = Market & { data?: MarketData };
const addData = <T extends Market>(markets: T[], marketsData: MarketData[]) => const addData = <T extends Market>(markets: T[], marketsData: MarketData[]) =>
markets.map((market) => ({ markets.map((market) => ({
@ -94,14 +106,17 @@ const addData = <T extends Market>(markets: T[], marketsData: MarketData[]) =>
})); }));
export const marketsWithDataProvider = makeDerivedDataProvider< export const marketsWithDataProvider = makeDerivedDataProvider<
MarketWithData[], MarketMaybeWithData[],
never never
>([activeMarketsProvider, marketsDataProvider], (parts) => >([activeMarketsProvider, marketsDataProvider], (parts) =>
addData(parts[0] as Market[], parts[1] as MarketData[]) addData(parts[0] as Market[], parts[1] as MarketData[])
); );
export type MarketMaybeWithDataAndCandles = MarketMaybeWithData &
MarketMaybeWithCandles;
export const marketListProvider = makeDerivedDataProvider< export const marketListProvider = makeDerivedDataProvider<
(MarketWithData & MarketWithCandles)[], MarketMaybeWithDataAndCandles[],
never never
>( >(
[ [
@ -109,7 +124,7 @@ export const marketListProvider = makeDerivedDataProvider<
marketsCandlesProvider, marketsCandlesProvider,
], ],
(parts) => (parts) =>
addCandles(parts[0] as MarketWithCandles[], parts[1] as MarketCandles[]) addCandles(parts[0] as MarketMaybeWithData[], parts[1] as MarketCandles[])
); );
export const useMarketList = () => { export const useMarketList = () => {

View File

@ -24,9 +24,13 @@ fragment MarketFields on Market {
settlementAsset { settlementAsset {
id id
symbol symbol
name
decimals decimals
} }
quoteName quoteName
dataSourceSpecForTradingTermination {
id
}
} }
} }
} }

View File

@ -31,8 +31,8 @@ const marketFieldsFragments: MarketFieldsFragment[] = [
state: Schema.MarketState.STATE_ACTIVE, state: Schema.MarketState.STATE_ACTIVE,
marketTimestamps: { marketTimestamps: {
__typename: 'MarketTimestamps', __typename: 'MarketTimestamps',
close: '', close: null,
open: '', open: null,
}, },
fees: { fees: {
__typename: 'Fees', __typename: 'Fees',
@ -56,9 +56,13 @@ const marketFieldsFragments: MarketFieldsFragment[] = [
settlementAsset: { settlementAsset: {
id: 'asset-0', id: 'asset-0',
symbol: 'tDAI', symbol: 'tDAI',
name: 'tDAI',
decimals: 5, decimals: 5,
__typename: 'Asset', __typename: 'Asset',
}, },
dataSourceSpecForTradingTermination: {
id: 'oracleId',
},
quoteName: 'DAI', quoteName: 'DAI',
__typename: 'Future', __typename: 'Future',
}, },
@ -101,9 +105,13 @@ const marketFieldsFragments: MarketFieldsFragment[] = [
settlementAsset: { settlementAsset: {
id: 'asset-1', id: 'asset-1',
symbol: 'XYZalpha', symbol: 'XYZalpha',
name: 'XYZalpha',
decimals: 5, decimals: 5,
__typename: 'Asset', __typename: 'Asset',
}, },
dataSourceSpecForTradingTermination: {
id: 'oracleId',
},
quoteName: 'USD', quoteName: 'USD',
__typename: 'Future', __typename: 'Future',
}, },
@ -145,10 +153,14 @@ const marketFieldsFragments: MarketFieldsFragment[] = [
product: { product: {
settlementAsset: { settlementAsset: {
id: 'asset-2', id: 'asset-2',
name: '',
symbol: 'tUSDC', symbol: 'tUSDC',
decimals: 5, decimals: 5,
__typename: 'Asset', __typename: 'Asset',
}, },
dataSourceSpecForTradingTermination: {
id: 'oracleId',
},
quoteName: 'USDC', quoteName: 'USDC',
__typename: 'Future', __typename: 'Future',
}, },
@ -191,9 +203,13 @@ const marketFieldsFragments: MarketFieldsFragment[] = [
settlementAsset: { settlementAsset: {
id: 'asset-3', id: 'asset-3',
symbol: 'tBTC', symbol: 'tBTC',
name: '',
decimals: 5, decimals: 5,
__typename: 'Asset', __typename: 'Asset',
}, },
dataSourceSpecForTradingTermination: {
id: 'oracleId',
},
quoteName: 'BTC', quoteName: 'BTC',
__typename: 'Future', __typename: 'Future',
}, },

View File

@ -46,6 +46,10 @@ export const generateOrder = (partialOrder?: PartialDeep<Order>) => {
id: 'asset-id', id: 'asset-id',
decimals: 1, decimals: 1,
symbol: 'XYZ', symbol: 'XYZ',
name: 'XYZ',
},
dataSourceSpecForTradingTermination: {
id: '',
}, },
}, },
}, },

View File

@ -10,31 +10,7 @@ import { OrderSubDocument } from './';
import type { MockedResponse } from '@apollo/client/testing'; import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing';
const defaultMarket = { const marketId = 'market-id';
__typename: 'Market',
id: 'market-id',
decimalPlaces: 2,
positionDecimalPlaces: 1,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
state: Schema.MarketState.STATE_ACTIVE,
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
product: {
__typename: 'Future',
quoteName: 'quote-name',
},
},
},
depth: {
__typename: 'MarketDepth',
lastTrade: {
__typename: 'Trade',
price: '100',
},
},
};
const defaultWalletContext = { const defaultWalletContext = {
pubKey: null, pubKey: null,
@ -135,13 +111,13 @@ describe('useOrderSubmit', () => {
expiresAt: new Date('2022-01-01').toISOString(), expiresAt: new Date('2022-01-01').toISOString(),
}; };
await act(async () => { await act(async () => {
result.current.submit({ ...order, marketId: defaultMarket.id }); result.current.submit({ ...order, marketId });
}); });
expect(mockSendTx).toHaveBeenCalledWith(pubKey, { expect(mockSendTx).toHaveBeenCalledWith(pubKey, {
orderSubmission: { orderSubmission: {
type: Schema.OrderType.TYPE_LIMIT, type: Schema.OrderType.TYPE_LIMIT,
marketId: defaultMarket.id, marketId,
size: '10', size: '10',
side: Schema.Side.SIDE_BUY, side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT, timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT,
@ -172,13 +148,13 @@ describe('useOrderSubmit', () => {
expiresAt: new Date('2022-01-01').toISOString(), expiresAt: new Date('2022-01-01').toISOString(),
}; };
await act(async () => { await act(async () => {
result.current.submit({ ...order, marketId: defaultMarket.id }); result.current.submit({ ...order, marketId });
}); });
expect(mockSendTx).toHaveBeenCalledWith(publicKeyObj.publicKey, { expect(mockSendTx).toHaveBeenCalledWith(publicKeyObj.publicKey, {
orderSubmission: { orderSubmission: {
type: Schema.OrderType.TYPE_LIMIT, type: Schema.OrderType.TYPE_LIMIT,
marketId: defaultMarket.id, marketId,
size: '10', size: '10',
side: Schema.Side.SIDE_BUY, side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC, timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,

View File

@ -1,7 +1,4 @@
import type { import type { MarketData, Market } from '@vegaprotocol/market-list';
MarketDataFieldsFragment,
SingleMarketFieldsFragment,
} from '@vegaprotocol/market-list';
import type { Order } from '@vegaprotocol/orders'; import type { Order } from '@vegaprotocol/orders';
import { timeInForceLabel } from '@vegaprotocol/orders'; import { timeInForceLabel } from '@vegaprotocol/orders';
import { addDecimalsFormatNumber, Size, t } from '@vegaprotocol/react-helpers'; import { addDecimalsFormatNumber, Size, t } from '@vegaprotocol/react-helpers';
@ -14,8 +11,8 @@ export const ClosingOrder = ({
marketData, marketData,
}: { }: {
order: IClosingOrder; order: IClosingOrder;
market: SingleMarketFieldsFragment; market: Market;
marketData: MarketDataFieldsFragment; marketData: MarketData;
}) => { }) => {
const asset = market.tradableInstrument.instrument.product.settlementAsset; const asset = market.tradableInstrument.instrument.product.settlementAsset;
const estimatedPrice = const estimatedPrice =
@ -50,7 +47,7 @@ export const ActiveOrders = ({
market, market,
orders, orders,
}: { }: {
market: SingleMarketFieldsFragment; market: Market;
orders: Order[]; orders: Order[];
}) => { }) => {
const asset = market.tradableInstrument.instrument.product.settlementAsset; const asset = market.tradableInstrument.instrument.product.settlementAsset;

View File

@ -11,7 +11,7 @@ import {
removePaginationWrapper, removePaginationWrapper,
} from '@vegaprotocol/react-helpers'; } from '@vegaprotocol/react-helpers';
import * as Schema from '@vegaprotocol/types'; import * as Schema from '@vegaprotocol/types';
import type { MarketWithData } from '@vegaprotocol/market-list'; import type { MarketMaybeWithData } from '@vegaprotocol/market-list';
import { marketsWithDataProvider } from '@vegaprotocol/market-list'; import { marketsWithDataProvider } from '@vegaprotocol/market-list';
import type { import type {
PositionsQuery, PositionsQuery,
@ -36,7 +36,7 @@ interface PositionRejoined {
unrealisedPNL: string; unrealisedPNL: string;
averageEntryPrice: string; averageEntryPrice: string;
updatedAt?: string | null; updatedAt?: string | null;
market: MarketWithData | null; market: MarketMaybeWithData | null;
margins: PositionMarginLevel | null; margins: PositionMarginLevel | null;
} }
@ -253,7 +253,7 @@ const upgradeMarginsConnection = (
export const rejoinPositionData = ( export const rejoinPositionData = (
positions: PositionFieldsFragment[] | null, positions: PositionFieldsFragment[] | null,
marketsData: MarketWithData[] | null, marketsData: MarketMaybeWithData[] | null,
margins: MarginFieldsFragment[] | null margins: MarginFieldsFragment[] | null
): PositionRejoined[] | null => { ): PositionRejoined[] | null => {
if (positions && marketsData && margins) { if (positions && marketsData && margins) {

View File

@ -8,7 +8,10 @@ export const useRequestClosePositionData = (
marketId?: string, marketId?: string,
partyId?: string partyId?: string
) => { ) => {
const marketVariables = useMemo(() => ({ marketId }), [marketId]); const marketVariables = useMemo(
() => ({ marketId: marketId || '' }),
[marketId]
);
const orderVariables = useMemo<OrdersQueryVariables>( const orderVariables = useMemo<OrdersQueryVariables>(
() => ({ partyId: partyId || '' }), () => ({ partyId: partyId || '' }),
[partyId] [partyId]

View File

@ -1,7 +1,6 @@
import { t } from './i18n'; import { t } from './i18n';
import { getDateTimeFormat } from './format'; import { getDateTimeFormat } from './format';
import { isValid, parseISO } from 'date-fns'; import { isValid, parseISO } from 'date-fns';
import { MarketState } from '@vegaprotocol/types'; import { MarketState } from '@vegaprotocol/types';
export const getMarketExpiryDate = ( export const getMarketExpiryDate = (

View File

@ -123,14 +123,15 @@ mockUseGetWithdrawThreshold.mockReturnValue(() =>
let dateNowSpy: jest.SpyInstance<number, []>; let dateNowSpy: jest.SpyInstance<number, []>;
const erc20WithdrawalApproval = { const erc20WithdrawalApproval: WithdrawalApprovalQuery['erc20WithdrawalApproval'] =
assetSource: 'asset-source', {
amount: '100', assetSource: 'asset-source',
nonce: '1', amount: '100',
creation: '1', nonce: '1',
signatures: 'signatures', creation: '1',
targetAddress: 'target-address', signatures: 'signatures',
}; targetAddress: 'target-address',
};
const mockedNetworkParams: MockedResponse<NetworkParamsQuery> = { const mockedNetworkParams: MockedResponse<NetworkParamsQuery> = {
request: { request: {

View File

@ -143,9 +143,13 @@ describe('WithdrawFormContainer', () => {
settlementAsset: { settlementAsset: {
__typename: 'Asset', __typename: 'Asset',
id: 'asset-id', id: 'asset-id',
name: 'asset-id',
symbol: 'tUSDC', symbol: 'tUSDC',
decimals: 5, decimals: 5,
}, },
dataSourceSpecForTradingTermination: {
id: '',
},
quoteName: 'USD', quoteName: 'USD',
}, },
}, },