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 localData = data?.markets;
return (
<AsyncRenderer loading={loading} error={error} data={localData}>
<AsyncRenderer loading={loading} error={error} data={data}>
<div
className="grow w-full"
style={{ minHeight: 500, overflow: 'hidden' }}
@ -57,7 +55,7 @@ export const MarketList = () => {
);
},
}}
rowData={localData}
rowData={data}
defaultColDef={{
resizable: true,
sortable: true,

View File

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

View File

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

View File

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

View File

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

View File

@ -4,14 +4,15 @@ before(() => {
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/');
cy.wait('@Market');
cy.wait('@Markets');
cy.wait('@MarketsData');
cy.getByTestId('dialog-close').click();
});
describe('Desktop view', { tags: '@smoke' }, () => {
describe('Navbar', () => {
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) => {
it(`${link} should be correctly rendered`, () => {
@ -67,7 +68,7 @@ describe('Mobile view', { tags: '@smoke' }, () => {
cy.getByTestId('button-menu-drawer').click();
cy.getByTestId('menu-drawer').within((el) => {
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', () => {

View File

@ -35,7 +35,7 @@ describe('time in force default values', () => {
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Market');
cy.wait('@Markets');
});
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.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Market');
cy.wait('@Markets');
});
beforeEach(() => {
@ -162,7 +162,7 @@ describe(
);
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Market');
cy.wait('@Markets');
});
beforeEach(() => {
@ -231,7 +231,7 @@ describe(
);
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Market');
cy.wait('@Markets');
});
beforeEach(() => {
@ -300,7 +300,7 @@ describe(
);
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Market');
cy.wait('@Markets');
});
beforeEach(() => {
@ -360,7 +360,7 @@ describe('deal ticket validation', { tags: '@smoke' }, () => {
beforeEach(() => {
cy.mockTradingPage();
cy.visit('/#/markets/market-0');
cy.wait('@Market');
cy.wait('@Markets');
});
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.mockTradingPage();
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 () {
@ -440,7 +440,7 @@ describe('limit order validations', { tags: '@smoke' }, () => {
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Market');
cy.wait('@Markets');
cy.getByTestId(toggleLimit).click();
});
@ -452,7 +452,7 @@ describe('limit order validations', { tags: '@smoke' }, () => {
//7002-SORD-018
cy.getByTestId(orderPriceField)
.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', () => {
@ -532,7 +532,7 @@ describe('market order validations', { tags: '@smoke' }, () => {
cy.setVegaWallet();
cy.mockTradingPage();
cy.visit('/#/markets/market-0');
cy.wait('@Market');
cy.wait('@Markets');
cy.getByTestId(toggleMarket).click();
});
@ -586,7 +586,7 @@ describe('suspended market validation', { tags: '@regression' }, () => {
);
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Market');
cy.wait('@Markets');
});
beforeEach(() => {
@ -648,7 +648,7 @@ describe('account validation', { tags: '@regression' }, () => {
market: null,
asset: {
__typename: 'Asset',
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
id: 'asset-0',
},
},
},
@ -660,7 +660,7 @@ describe('account validation', { tags: '@regression' }, () => {
});
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Market');
cy.wait('@Markets');
});
it('should show an error if your balance is zero', () => {
@ -670,7 +670,7 @@ describe('account validation', { tags: '@regression' }, () => {
//7002-SORD-003
cy.getByTestId('dealticket-error-message-zero-balance').should(
'have.text',
'Insufficient balance. Deposit ' + 'tBTC'
'Insufficient balance. Deposit ' + 'tDAI'
);
cy.getByTestId('deal-ticket-deposit-dialog-button').should('exist');
});
@ -696,7 +696,7 @@ describe('account validation', { tags: '@regression' }, () => {
});
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Market');
cy.wait('@Markets');
});
it('should display info and button for deposit', () => {
@ -708,7 +708,7 @@ describe('account validation', { tags: '@regression' }, () => {
);
cy.getByTestId('dealticket-warning-margin').should(
'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('dialog-content')

View File

@ -15,7 +15,6 @@ import {
marketDataQuery,
marketDepthQuery,
marketInfoQuery,
marketQuery,
marketsCandlesQuery,
marketsDataQuery,
marketsQuery,
@ -28,7 +27,7 @@ import {
withdrawalsQuery,
} from '@vegaprotocol/mock';
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';
type MarketPageMockData = {
@ -55,17 +54,18 @@ const marketDataOverride = (
},
});
const marketQueryOverride = (
const marketsDataOverride = (
data: MarketPageMockData
): PartialDeep<MarketQuery> => ({
market: {
tradableInstrument: {
instrument: {
name: `${data.state?.toUpperCase()} MARKET`,
): PartialDeep<MarketsQuery> => ({
marketsConnection: {
edges: [
{
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,
'Market',
marketQuery(marketQueryOverride({ state, tradingMode, trigger }))
'Markets',
marketsQuery(marketsDataOverride({ state, tradingMode, trigger }))
);
aliasGQLQuery(req, 'Markets', marketsQuery());
aliasGQLQuery(
req,
'MarketData',

View File

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

View File

@ -9,9 +9,7 @@ import {
} from '@vegaprotocol/react-helpers';
import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit';
import type {
SingleMarketFieldsFragment,
MarketData,
Candle,
MarketDataUpdateFieldsFragment,
} 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 = ({
marketId,
marketName,
@ -89,12 +82,9 @@ export const MarketPage = () => {
[marketId, navigate]
);
const { data, error, loading } = useDataProvider<
SingleMarketFieldsFragment,
never
>({
const { data, error, loading } = useDataProvider({
dataProvider: marketProvider,
variables: useMemo(() => ({ marketId: marketId || '' }), [marketId]),
variables: { marketId: marketId || '' },
skip: !marketId,
});
@ -115,7 +105,7 @@ export const MarketPage = () => {
<Splash>
<span className="flex flex-col items-center gap-2">
<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 className="text-sm justify-center">
{t(`Please choose another market from the`)}{' '}
@ -129,7 +119,7 @@ export const MarketPage = () => {
}
return (
<AsyncRenderer<SingleMarketFieldsFragment>
<AsyncRenderer
loading={loading}
error={error}
data={data || undefined}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,37 +1,24 @@
import type { RefObject } from 'react';
import { useMemo } from 'react';
import { t, useDataProvider } from '@vegaprotocol/react-helpers';
import { t } from '@vegaprotocol/react-helpers';
import { TradingModeTooltip } from '@vegaprotocol/deal-ticket';
import { useInView } from 'react-intersection-observer';
import * as Schema from '@vegaprotocol/types';
import { HeaderStat } from '../header';
import { Tooltip } from '@vegaprotocol/ui-toolkit';
import { marketDataProvider } 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;
};
import { useStaticMarketData } from '@vegaprotocol/market-list';
const getTradingModeLabel = (
tradingMode?: Schema.MarketTradingMode,
marketTradingMode?: Schema.MarketTradingMode,
trigger?: Schema.AuctionTrigger
) => {
return (
(tradingMode === Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
(marketTradingMode ===
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
trigger &&
trigger !== Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED
? `${Schema.MarketTradingModeMapping[tradingMode]} - ${Schema.AuctionTriggerMapping[trigger]}`
? `${Schema.MarketTradingModeMapping[marketTradingMode]} - ${Schema.AuctionTriggerMapping[trigger]}`
: Schema.MarketTradingModeMapping[
tradingMode as Schema.MarketTradingMode
marketTradingMode as Schema.MarketTradingMode
]) || '-'
);
};
@ -49,8 +36,8 @@ export const HeaderStatMarketTradingMode = ({
initialTradingMode,
initialTrigger,
}: HeaderStatMarketTradingModeProps) => {
const data = useMarketData(marketId);
const tradingMode = data?.marketTradingMode ?? initialTradingMode;
const { data } = useStaticMarketData(marketId);
const marketTradingMode = data?.marketTradingMode ?? initialTradingMode;
const trigger = data?.trigger ?? initialTrigger;
return (
@ -61,7 +48,7 @@ export const HeaderStatMarketTradingMode = ({
}
testId="market-trading-mode"
>
<div>{getTradingModeLabel(tradingMode, trigger)}</div>
<div>{getTradingModeLabel(marketTradingMode, trigger)}</div>
</HeaderStat>
);
};
@ -75,7 +62,7 @@ export const MarketTradingMode = ({
inViewRoot?: RefObject<Element>;
}) => {
const [ref, inView] = useInView({ root: inViewRoot?.current });
const data = useMarketData(marketId, !inView);
const { data } = useStaticMarketData(marketId, !inView);
return (
<Tooltip

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,8 @@ import { useMarketList } from '@vegaprotocol/market-list';
import { t } from '@vegaprotocol/react-helpers';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
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 {
ColumnKind,
columns,
@ -19,7 +20,7 @@ export const SelectMarketLandingTable = ({
markets,
onClose,
}: {
markets: Market[] | null;
markets: MarketMaybeWithDataAndCandles[] | null;
onClose: () => void;
}) => {
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-list/src/lib/market-candles.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-data.mock';
export * from '../market-list/src/lib/markets.mock';

View File

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

View File

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

View File

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

View File

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

View File

@ -17,11 +17,12 @@ export type DealTicketMarketAmountProps = Omit<
export const DealTicketMarketAmount = ({
register,
market,
marketData,
sizeError,
}: DealTicketMarketAmountProps) => {
const quoteName = market.tradableInstrument.instrument.product.quoteName;
const sizeStep = toDecimal(market?.positionDecimalPlaces);
const price = getMarketPrice(market);
const price = getMarketPrice(marketData);
const priceFormatted = price
? addDecimalsFormatNumber(price, market.decimalPlaces)
@ -33,7 +34,7 @@ export const DealTicketMarketAmount = ({
<div className="flex-1 text-sm">Size</div>
<div />
<div className="flex-2 text-sm text-right">
{isMarketInAuction(market) && (
{isMarketInAuction(marketData.marketTradingMode) && (
<Tooltip
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.'

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,18 +4,24 @@ import { toBigNum } from '@vegaprotocol/react-helpers';
import { useAccountBalance } from '@vegaprotocol/accounts';
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { useOrderMargin } from './use-order-margin';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import type { Market, MarketData } from '@vegaprotocol/market-list';
interface Props {
market: MarketDealTicket;
market: Market;
marketData: MarketData;
order: OrderSubmissionBody['orderSubmission'];
}
export const useOrderMarginValidation = ({ market, order }: Props) => {
export const useOrderMarginValidation = ({
market,
marketData,
order,
}: Props) => {
const { pubKey } = useVegaWallet();
const estMargin = useOrderMargin({
order,
market,
marketData,
partyId: pubKey || '',
});
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 { useOrderMargin } from './use-order-margin';
import * as Schema from '@vegaprotocol/types';
import type { MarketDealTicket } from '@vegaprotocol/market-list';
import type { Market, MarketData } from '@vegaprotocol/market-list';
let mockEstimateData = {
estimateOrder: {
@ -55,11 +55,11 @@ describe('useOrderMargin', () => {
decimalPlaces: 2,
positionDecimalPlaces: 0,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
data: {
indicativePrice: '100',
markPrice: '200',
},
} as MarketDealTicket,
} as unknown as Market,
marketData: {
indicativePrice: '100',
markPrice: '200',
} as unknown as MarketData,
partyId: 'partyId',
};

View File

@ -4,12 +4,13 @@ import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
import { removeDecimal } from '@vegaprotocol/react-helpers';
import { useMarketPositions } from './use-market-positions';
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';
export interface Props {
order: OrderSubmissionBody['orderSubmission'];
market: MarketDealTicket;
market: Market;
marketData: MarketData;
partyId: string;
derivedPrice?: string;
}
@ -27,11 +28,13 @@ export interface OrderMargin {
export const useOrderMargin = ({
order,
market,
marketData,
partyId,
derivedPrice,
}: Props): OrderMargin | null => {
const { balance } = useMarketPositions({ marketId: market.id }) || {};
const priceForEstimate = derivedPrice || getDerivedPrice(order, market);
const priceForEstimate =
derivedPrice || getDerivedPrice(order, market, marketData);
const { data } = useEstimateOrderQuery({
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 merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
export function generateMarket(
override?: PartialDeep<MarketDealTicket>
): MarketDealTicket {
const defaultMarket: MarketDealTicket = {
export function generateMarket(override?: PartialDeep<Market>): Market {
const defaultMarket: Market = {
__typename: 'Market',
id: 'market-id',
decimalPlaces: 2,
positionDecimalPlaces: 1,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
state: Schema.MarketState.STATE_ACTIVE,
marketTimestamps: {
__typename: 'MarketTimestamps',
close: '',
open: '',
},
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
id: '1',
name: 'Instrument name',
code: 'instrument-code',
id: '',
code: 'BTCUSD.MF21',
name: 'ACTIVE MARKET',
metadata: {
__typename: 'InstrumentMetadata',
tags: [],
},
product: {
__typename: 'Future',
quoteName: 'quote-name',
dataSourceSpecForTradingTermination: {
id: 'data-source-for-trading-termination-id',
},
settlementAsset: {
id: 'asset-0',
symbol: 'tDAI',
name: 'tDAI',
decimals: 5,
__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: {
factors: {
makerFee: '0.001',
@ -70,14 +51,34 @@ export function generateMarket(
liquidityFee: '0.003',
},
},
depth: {
__typename: 'MarketDepth',
lastTrade: {
__typename: 'Trade',
price: '100',
},
},
};
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 * as Schema from '@vegaprotocol/types';
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)
*/
export const getMarketPrice = (market: MarketDealTicket) => {
if (isMarketInAuction(market)) {
export const getMarketPrice = (marketData: MarketData) => {
const { marketTradingMode, indicativePrice, markPrice } = marketData;
if (isMarketInAuction(marketTradingMode)) {
// 0 can never be a valid uncrossing price
// as it would require there being orders on the book at that price.
if (
market.data.indicativePrice &&
market.data.indicativePrice !== '0' &&
BigInt(market.data.indicativePrice) !== BigInt(0)
indicativePrice &&
indicativePrice !== '0' &&
BigInt(indicativePrice) !== BigInt(0)
) {
return market.data.indicativePrice;
return indicativePrice;
}
} else {
return market.data.markPrice;
return markPrice;
}
return undefined;
};
@ -33,7 +34,8 @@ export const getDerivedPrice = (
type: Schema.OrderType;
price?: string | undefined;
},
market: MarketDealTicket
market: Market,
marketData: MarketData
) => {
// If order type is market we should use either the mark 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) {
price = removeDecimal(order.price, market.decimalPlaces);
} else {
price = getMarketPrice(market);
price = getMarketPrice(marketData);
}
return price === '0' ? undefined : price;

View File

@ -1,13 +1,11 @@
import * as Schema from '@vegaprotocol/types';
export const isMarketInAuction = (market: {
data: {
marketTradingMode: Schema.MarketTradingMode;
};
}) => {
export const isMarketInAuction = (
marketTradingMode: Schema.MarketTradingMode
) => {
return [
Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
Schema.MarketTradingMode.TRADING_MODE_MONITORING_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';
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');
}

View File

@ -1,19 +1,21 @@
import * as Schema from '@vegaprotocol/types';
import { MarketModeValidationType } from '../constants';
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) => {
const isMonitoringAuction =
market.data.marketTradingMode ===
marketTradingMode ===
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION;
const isPriceTrigger =
market.data.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE;
trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE;
const isLiquidityTrigger =
market.data.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY;
trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY;
if (isMarketInAuction(market)) {
if (isMarketInAuction(marketTradingMode)) {
if (
[
Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,

View File

@ -1,18 +1,23 @@
import * as Schema from '@vegaprotocol/types';
import { MarketModeValidationType } from '../constants';
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) => {
if (isMarketInAuction(market) && value === Schema.OrderType.TYPE_MARKET) {
if (
isMarketInAuction(marketTradingMode) &&
value === Schema.OrderType.TYPE_MARKET
) {
const isMonitoringAuction =
market.data.marketTradingMode ===
marketTradingMode ===
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION;
const isPriceTrigger =
market.data.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE;
trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_PRICE;
const isLiquidityTrigger =
market.data.trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY;
trigger === Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY;
if (isMonitoringAuction && isPriceTrigger) {
return MarketModeValidationType.PriceMonitoringAuction;

View File

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

View File

@ -9,8 +9,7 @@ import {
import type {
MarketCandles,
MarketWithCandles,
MarketWithData,
MarketMaybeWithDataAndCandles,
} from '@vegaprotocol/market-list';
import {
@ -37,21 +36,20 @@ export interface FeeLevels {
fee: string;
}
export type Market = MarketWithData &
MarketWithCandles & {
feeLevels: FeeLevels[];
target: string;
dayVolume: string;
liquidityCommitted: number;
volumeChange: string;
tradableInstrument?: {
instrument?: {
metadata?: {
tags?: string[] | null;
};
export type Market = MarketMaybeWithDataAndCandles & {
feeLevels: FeeLevels[];
target: string;
dayVolume: string;
liquidityCommitted: number;
volumeChange: string;
tradableInstrument?: {
instrument?: {
metadata?: {
tags?: string[] | null;
};
};
};
};
export interface Markets {
markets: Market[];
@ -68,7 +66,7 @@ const getData = (
};
export const addData = (
markets: (MarketWithData & MarketWithCandles)[],
markets: MarketMaybeWithDataAndCandles[],
marketsCandles24hAgo: MarketCandles[],
marketsLiquidity: LiquidityProvisionMarket[]
) => {
@ -104,7 +102,7 @@ export const liquidityMarketsProvider = makeDataProvider<
getData,
});
const liquidityProvisionProvider = makeDerivedDataProvider<Markets, never>(
const liquidityProvisionProvider = makeDerivedDataProvider<Market[], never>(
[
marketListProvider,
(callback, client, variables) =>
@ -115,12 +113,11 @@ const liquidityProvisionProvider = makeDerivedDataProvider<Markets, never>(
liquidityMarketsProvider,
],
(parts) => {
const data = addData(
parts[0] as (MarketWithData & MarketWithCandles)[],
return addData(
parts[0] as MarketMaybeWithDataAndCandles[],
parts[1] as MarketCandles[],
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 * as Apollo from '@apollo/client';
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 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`
fragment MarketFields on Market {
@ -37,9 +37,13 @@ export const MarketFieldsFragmentDoc = gql`
settlementAsset {
id
symbol
name
decimals
}
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 type { AgGridReact } from 'ag-grid-react';
import * as Schema from '@vegaprotocol/types';
import type { MarketFieldsFragment, MarketWithData } from '../../';
import type { MarketMaybeWithData, MarketFieldsFragment } from '../../';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
const { MarketTradingMode, AuctionTrigger } = Schema;
@ -24,7 +24,7 @@ export const getRowId = ({ data }: { data: { id: string } }) => data.id;
export const MarketListTable = forwardRef<
AgGridReact,
TypedDataAgGrid<MarketWithData>
TypedDataAgGrid<MarketMaybeWithData>
>((props, ref) => {
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
return (
@ -51,7 +51,7 @@ export const MarketListTable = forwardRef<
value,
data,
}: VegaICellRendererParams<
MarketWithData,
MarketMaybeWithData,
'tradableInstrument.instrument.code'
>) => {
if (!data) return null;
@ -68,7 +68,7 @@ export const MarketListTable = forwardRef<
minWidth={170}
valueGetter={({
data,
}: VegaValueGetterParams<MarketWithData, 'data'>) => {
}: VegaValueGetterParams<MarketMaybeWithData, 'data'>) => {
if (!data?.data) return undefined;
const { trigger } = data.data;
const { tradingMode } = data;
@ -98,14 +98,17 @@ export const MarketListTable = forwardRef<
filter="agNumberColumnFilter"
valueGetter={({
data,
}: VegaValueGetterParams<MarketWithData, 'data.bestBidPrice'>) => {
}: VegaValueGetterParams<MarketMaybeWithData, 'data.bestBidPrice'>) => {
return data?.data?.bestBidPrice === undefined
? undefined
: toBigNum(data?.data?.bestBidPrice, data.decimalPlaces).toNumber();
}}
valueFormatter={({
data,
}: VegaValueFormatterParams<MarketWithData, 'data.bestBidPrice'>) =>
}: VegaValueFormatterParams<
MarketMaybeWithData,
'data.bestBidPrice'
>) =>
data?.data?.bestBidPrice === undefined
? undefined
: addDecimalsFormatNumber(
@ -122,7 +125,10 @@ export const MarketListTable = forwardRef<
filter="agNumberColumnFilter"
valueGetter={({
data,
}: VegaValueGetterParams<MarketWithData, 'data.bestOfferPrice'>) => {
}: VegaValueGetterParams<
MarketMaybeWithData,
'data.bestOfferPrice'
>) => {
return data?.data?.bestOfferPrice === undefined
? undefined
: toBigNum(
@ -132,7 +138,10 @@ export const MarketListTable = forwardRef<
}}
valueFormatter={({
data,
}: VegaValueFormatterParams<MarketWithData, 'data.bestOfferPrice'>) =>
}: VegaValueFormatterParams<
MarketMaybeWithData,
'data.bestOfferPrice'
>) =>
data?.data?.bestOfferPrice === undefined
? undefined
: addDecimalsFormatNumber(
@ -149,14 +158,14 @@ export const MarketListTable = forwardRef<
filter="agNumberColumnFilter"
valueGetter={({
data,
}: VegaValueGetterParams<MarketWithData, 'data.markPrice'>) => {
}: VegaValueGetterParams<MarketMaybeWithData, 'data.markPrice'>) => {
return data?.data?.markPrice === undefined
? undefined
: toBigNum(data?.data?.markPrice, data.decimalPlaces).toNumber();
}}
valueFormatter={({
data,
}: VegaValueFormatterParams<MarketWithData, 'data.markPrice'>) =>
}: VegaValueFormatterParams<MarketMaybeWithData, 'data.markPrice'>) =>
data?.data?.bestOfferPrice === undefined
? undefined
: addDecimalsFormatNumber(data.data.markPrice, data.decimalPlaces)
@ -168,7 +177,7 @@ export const MarketListTable = forwardRef<
cellRenderer={({
value,
}: VegaICellRendererParams<
MarketWithData,
MarketMaybeWithData,
'tradableInstrument.instrument.product.settlementAsset'
>) =>
value ? (

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -10,31 +10,7 @@ import { OrderSubDocument } from './';
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
const defaultMarket = {
__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 marketId = 'market-id';
const defaultWalletContext = {
pubKey: null,
@ -135,13 +111,13 @@ describe('useOrderSubmit', () => {
expiresAt: new Date('2022-01-01').toISOString(),
};
await act(async () => {
result.current.submit({ ...order, marketId: defaultMarket.id });
result.current.submit({ ...order, marketId });
});
expect(mockSendTx).toHaveBeenCalledWith(pubKey, {
orderSubmission: {
type: Schema.OrderType.TYPE_LIMIT,
marketId: defaultMarket.id,
marketId,
size: '10',
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT,
@ -172,13 +148,13 @@ describe('useOrderSubmit', () => {
expiresAt: new Date('2022-01-01').toISOString(),
};
await act(async () => {
result.current.submit({ ...order, marketId: defaultMarket.id });
result.current.submit({ ...order, marketId });
});
expect(mockSendTx).toHaveBeenCalledWith(publicKeyObj.publicKey, {
orderSubmission: {
type: Schema.OrderType.TYPE_LIMIT,
marketId: defaultMarket.id,
marketId,
size: '10',
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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