chore(trading): live update deal ticket market data (#2570)
This commit is contained in:
parent
4dd63da62b
commit
a5d53eee77
@ -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,
|
||||
|
@ -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');
|
||||
});
|
||||
|
@ -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');
|
||||
});
|
||||
|
@ -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();
|
||||
|
@ -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' } },
|
||||
|
@ -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', () => {
|
||||
|
@ -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')
|
||||
|
@ -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',
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
);
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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',
|
||||
|
@ -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[];
|
||||
|
@ -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',
|
||||
|
@ -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();
|
||||
|
@ -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';
|
||||
|
@ -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: {
|
||||
|
@ -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 })}
|
||||
/>
|
||||
) : (
|
||||
|
@ -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>
|
||||
|
@ -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'
|
||||
>;
|
||||
|
||||
|
@ -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.'
|
||||
|
@ -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
|
||||
}`
|
||||
);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
)}`}
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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 } =
|
||||
|
@ -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',
|
||||
};
|
||||
|
||||
|
@ -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: {
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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');
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -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 };
|
||||
}
|
||||
);
|
||||
|
||||
|
98
libs/market-list/src/lib/__generated__/market.ts
generated
98
libs/market-list/src/lib/__generated__/market.ts
generated
@ -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>;
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 ? (
|
||||
|
@ -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">
|
||||
|
@ -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';
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
});
|
@ -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
|
||||
}
|
||||
}
|
@ -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' },
|
||||
},
|
||||
};
|
@ -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 = () => {
|
||||
|
@ -24,9 +24,13 @@ fragment MarketFields on Market {
|
||||
settlementAsset {
|
||||
id
|
||||
symbol
|
||||
name
|
||||
decimals
|
||||
}
|
||||
quoteName
|
||||
dataSourceSpecForTradingTermination {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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',
|
||||
},
|
||||
|
@ -46,6 +46,10 @@ export const generateOrder = (partialOrder?: PartialDeep<Order>) => {
|
||||
id: 'asset-id',
|
||||
decimals: 1,
|
||||
symbol: 'XYZ',
|
||||
name: 'XYZ',
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
id: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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]
|
||||
|
@ -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 = (
|
||||
|
@ -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: {
|
||||
|
@ -143,9 +143,13 @@ describe('WithdrawFormContainer', () => {
|
||||
settlementAsset: {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id',
|
||||
name: 'asset-id',
|
||||
symbol: 'tUSDC',
|
||||
decimals: 5,
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
id: '',
|
||||
},
|
||||
quoteName: 'USD',
|
||||
},
|
||||
},
|
||||
|
Loading…
Reference in New Issue
Block a user