chore(2071): deal ticket data update fixing (#2169)
* chore: update of deal ticket data * chore: update of deal ticket data * chore: update of deal ticket data - fix re-render loop * chore: update of deal ticket data - add marketDealTicketProvider * chore: update of deal ticket data - add marketDealTicketProvider * chore: update of deal ticket data - adjust console-lite to the changes * chore: update of deal ticket data - fix failing unit tests * chore: update of deal ticket data - fix failing unit tests * chore: update of deal ticket data - fix linter failings * chore: update of deal ticket data - adjust console-lite-e2e * chore: update of deal ticket data - fix build-spec failings * chore: update of deal ticket data - fix failing e2e tests * chore: update of deal ticket data - fix failing e2e tests * chore: update of deal ticket data - fix failing e2e tests * chore: update of deal ticket data - remove unnecessary gqls * chore: update of deal ticket data - remove unnecessary gqls * chore: update of deal ticket data - remove unnecessary gqls * chore: update of deal ticket data - fix failings build * chore: update of deal ticket data - remove redundant data provider * chore: update of deal ticket data - remove redundant data provider * chore: update of deal ticket data - fix some types
This commit is contained in:
parent
a5aed85b43
commit
b749a05736
@ -1,11 +1,12 @@
|
||||
import { connectVegaWallet } from '../support/vega-wallet';
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import {
|
||||
generateMarket,
|
||||
generateMarketData,
|
||||
generateMarketsCandles,
|
||||
generateMarketsData,
|
||||
generateSimpleMarkets,
|
||||
} from '../support/mocks/generate-markets';
|
||||
import { generateDealTicket } from '../support/mocks/generate-deal-ticket';
|
||||
import { generateMarketTags } from '../support/mocks/generate-market-tags';
|
||||
import { generateMarketPositions } from '../support/mocks/generate-market-positions';
|
||||
import { generateEstimateOrder } from '../support/mocks/generate-estimate-order';
|
||||
@ -27,7 +28,8 @@ describe('market selector', { tags: '@smoke' }, () => {
|
||||
aliasQuery(req, 'Markets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
aliasQuery(req, 'MarketsData', generateMarketsData());
|
||||
aliasQuery(req, 'DealTicket', generateDealTicket());
|
||||
aliasQuery(req, 'MarketData', generateMarketData());
|
||||
aliasQuery(req, 'Market', generateMarket());
|
||||
aliasQuery(req, 'MarketTags', generateMarketTags());
|
||||
aliasQuery(req, 'MarketPositions', generateMarketPositions());
|
||||
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
|
||||
|
@ -5,8 +5,8 @@ import {
|
||||
generateMarketsCandles,
|
||||
generateMarketsData,
|
||||
generateMarket,
|
||||
generateMarketData,
|
||||
} from '../support/mocks/generate-markets';
|
||||
import { generateDealTicket } from '../support/mocks/generate-deal-ticket';
|
||||
import { generateMarketTags } from '../support/mocks/generate-market-tags';
|
||||
import { generateMarketPositions } from '../support/mocks/generate-market-positions';
|
||||
import { generateEstimateOrder } from '../support/mocks/generate-estimate-order';
|
||||
@ -28,7 +28,6 @@ describe('Market trade', { tags: '@smoke' }, () => {
|
||||
aliasQuery(req, 'MarketsCandles', generateMarketsCandles());
|
||||
aliasQuery(req, 'MarketsData', generateMarketsData());
|
||||
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
|
||||
aliasQuery(req, 'DealTicket', generateDealTicket());
|
||||
aliasQuery(req, 'MarketTags', generateMarketTags());
|
||||
aliasQuery(req, 'MarketPositions', generateMarketPositions());
|
||||
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
|
||||
@ -37,6 +36,7 @@ describe('Market trade', { tags: '@smoke' }, () => {
|
||||
aliasQuery(req, 'MarketMarkPrice', generateMarketMarkPrice());
|
||||
aliasQuery(req, 'MarketDepth', generateMarketDepth());
|
||||
aliasQuery(req, 'Market', generateMarket());
|
||||
aliasQuery(req, 'MarketData', generateMarketData());
|
||||
});
|
||||
cy.visit('/markets');
|
||||
cy.wait('@Markets').then((response) => {
|
||||
|
@ -144,4 +144,8 @@ export const singleMarket: SingleMarketFieldsFragment = {
|
||||
},
|
||||
},
|
||||
},
|
||||
depth: {
|
||||
__typename: 'MarketDepth',
|
||||
lastTrade: { price: '9893006', __typename: 'Trade' },
|
||||
},
|
||||
};
|
||||
|
@ -1,52 +0,0 @@
|
||||
import type { DealTicketQuery } from '@vegaprotocol/deal-ticket';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateDealTicket = (
|
||||
override?: PartialDeep<DealTicketQuery>
|
||||
): DealTicketQuery => {
|
||||
const defaultResult: DealTicketQuery = {
|
||||
market: {
|
||||
id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
state: Schema.MarketState.STATE_ACTIVE,
|
||||
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
name: 'AAVEDAI Monthly (30 Jun 2022)',
|
||||
product: {
|
||||
quoteName: 'DAI',
|
||||
settlementAsset: {
|
||||
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
|
||||
symbol: 'tDAI',
|
||||
name: 'tDAI TEST',
|
||||
decimals: 5,
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'Future',
|
||||
},
|
||||
__typename: 'Instrument',
|
||||
},
|
||||
__typename: 'TradableInstrument',
|
||||
},
|
||||
depth: {
|
||||
lastTrade: { price: '9893006', __typename: 'Trade' },
|
||||
__typename: 'MarketDepth',
|
||||
},
|
||||
fees: {
|
||||
factors: {
|
||||
makerFee: '0.0002',
|
||||
infrastructureFee: '0.0005',
|
||||
liquidityFee: '0.001',
|
||||
__typename: 'FeeFactors',
|
||||
},
|
||||
__typename: 'Fees',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
return merge(defaultResult, override);
|
||||
};
|
@ -11,6 +11,7 @@ import type {
|
||||
import { protoMarket, protoCandles, singleMarket } from './commons';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type { MarketQuery } from '@vegaprotocol/market-list';
|
||||
import type { MarketDataQuery } from '@vegaprotocol/market-list';
|
||||
|
||||
export const generateSimpleMarkets = (): MarketsQuery => {
|
||||
const markets: Market[] = [
|
||||
@ -1139,52 +1140,51 @@ export const generateFillsMarkets = () => {
|
||||
};
|
||||
};
|
||||
|
||||
const markets = [
|
||||
{
|
||||
data: {
|
||||
market: {
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
__typename: 'Market',
|
||||
},
|
||||
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
staticMidPrice: '0',
|
||||
indicativePrice: '0',
|
||||
bestStaticBidPrice: '0',
|
||||
bestStaticOfferPrice: '0',
|
||||
indicativeVolume: '0',
|
||||
bestBidPrice: '0',
|
||||
bestOfferPrice: '0',
|
||||
markPrice: '17588787',
|
||||
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
|
||||
__typename: 'MarketData',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
{
|
||||
data: {
|
||||
market: {
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
__typename: 'Market',
|
||||
},
|
||||
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
staticMidPrice: '0',
|
||||
indicativePrice: '0',
|
||||
bestStaticBidPrice: '0',
|
||||
bestStaticOfferPrice: '0',
|
||||
indicativeVolume: '0',
|
||||
bestBidPrice: '0',
|
||||
bestOfferPrice: '0',
|
||||
markPrice: '84377569',
|
||||
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
|
||||
__typename: 'MarketData',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
];
|
||||
export const generateMarketsData = (
|
||||
override?: PartialDeep<MarketsDataQuery>
|
||||
): MarketsDataQuery => {
|
||||
const markets = [
|
||||
{
|
||||
data: {
|
||||
market: {
|
||||
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
|
||||
__typename: 'Market',
|
||||
},
|
||||
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
staticMidPrice: '0',
|
||||
indicativePrice: '0',
|
||||
bestStaticBidPrice: '0',
|
||||
bestStaticOfferPrice: '0',
|
||||
indicativeVolume: '0',
|
||||
bestBidPrice: '0',
|
||||
bestOfferPrice: '0',
|
||||
markPrice: '17588787',
|
||||
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
|
||||
__typename: 'MarketData',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
{
|
||||
data: {
|
||||
market: {
|
||||
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
|
||||
__typename: 'Market',
|
||||
},
|
||||
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
staticMidPrice: '0',
|
||||
indicativePrice: '0',
|
||||
bestStaticBidPrice: '0',
|
||||
bestStaticOfferPrice: '0',
|
||||
indicativeVolume: '0',
|
||||
bestBidPrice: '0',
|
||||
bestOfferPrice: '0',
|
||||
markPrice: '84377569',
|
||||
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
|
||||
__typename: 'MarketData',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
];
|
||||
|
||||
const defaultResult: MarketsDataQuery = {
|
||||
marketsConnection: {
|
||||
__typename: 'MarketConnection',
|
||||
@ -1382,3 +1382,34 @@ export const generateMarket = (): MarketQuery => {
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const generateMarketData = (): MarketDataQuery => {
|
||||
return {
|
||||
marketsConnection: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
data: {
|
||||
market: {
|
||||
id: protoMarket.id,
|
||||
__typename: 'Market',
|
||||
},
|
||||
marketTradingMode:
|
||||
Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
staticMidPrice: '0',
|
||||
indicativePrice: '0',
|
||||
bestStaticBidPrice: '0',
|
||||
bestStaticOfferPrice: '0',
|
||||
indicativeVolume: '0',
|
||||
bestBidPrice: '0',
|
||||
bestOfferPrice: '0',
|
||||
markPrice: '17588787',
|
||||
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
|
||||
__typename: 'MarketData',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
};
|
||||
|
@ -17,7 +17,7 @@ export const generatePartyBalance = (
|
||||
balance: '88474051',
|
||||
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
asset: {
|
||||
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
|
||||
id: 'dai-id',
|
||||
symbol: 'tDAI',
|
||||
name: 'tDAI TEST',
|
||||
decimals: 5,
|
||||
@ -47,7 +47,7 @@ export const generatePartyBalance = (
|
||||
balance: '3412867',
|
||||
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
asset: {
|
||||
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
|
||||
id: 'dai-id',
|
||||
symbol: 'tDAI',
|
||||
name: 'tDAI TEST',
|
||||
decimals: 5,
|
||||
@ -62,7 +62,7 @@ export const generatePartyBalance = (
|
||||
balance: '70007',
|
||||
type: Types.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
asset: {
|
||||
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
|
||||
id: 'dai-id',
|
||||
symbol: 'tDAI',
|
||||
name: 'tDAI TEST',
|
||||
decimals: 5,
|
||||
|
@ -1,20 +1,17 @@
|
||||
import React from 'react';
|
||||
import { render } from '@testing-library/react';
|
||||
import type {
|
||||
AccountFragment,
|
||||
DealTicketMarketFragment,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
import type { AccountFragment } from '@vegaprotocol/deal-ticket';
|
||||
import { DealTicketBalance } from './deal-ticket-balance';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import type { MarketDealTicketAsset } from '@vegaprotocol/market-list';
|
||||
|
||||
const tDAI: DealTicketMarketFragment['tradableInstrument']['instrument']['product']['settlementAsset'] =
|
||||
{
|
||||
__typename: 'Asset',
|
||||
id: '1',
|
||||
symbol: 'tDAI',
|
||||
name: 'TDAI',
|
||||
decimals: 2,
|
||||
};
|
||||
const tDAI: MarketDealTicketAsset = {
|
||||
__typename: 'Asset',
|
||||
id: '1',
|
||||
symbol: 'tDAI',
|
||||
name: 'TDAI',
|
||||
decimals: 2,
|
||||
};
|
||||
|
||||
const accounts: AccountFragment[] = [
|
||||
{
|
||||
|
@ -1,14 +1,12 @@
|
||||
import classNames from 'classnames';
|
||||
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import type {
|
||||
AccountFragment,
|
||||
DealTicketMarketFragment,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
import type { AccountFragment } from '@vegaprotocol/deal-ticket';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import { useSettlementAccount } from '@vegaprotocol/deal-ticket';
|
||||
|
||||
interface DealTicketBalanceProps {
|
||||
settlementAsset: DealTicketMarketFragment['tradableInstrument']['instrument']['product']['settlementAsset'];
|
||||
settlementAsset: MarketDealTicket['tradableInstrument']['instrument']['product']['settlementAsset'];
|
||||
accounts: AccountFragment[];
|
||||
isWalletConnected: boolean;
|
||||
className?: string;
|
||||
|
@ -2,16 +2,21 @@ import { useParams } from 'react-router-dom';
|
||||
import compact from 'lodash/compact';
|
||||
import {
|
||||
DealTicketManager,
|
||||
DealTicketContainer as Container,
|
||||
usePartyBalanceQuery,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
import { Loader } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { t, useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { DealTicketSteps } from './deal-ticket-steps';
|
||||
import { DealTicketBalance } from './deal-ticket-balance';
|
||||
import Baubles from './baubles-decor';
|
||||
import ConnectWallet from '../wallet-connector';
|
||||
import { useMemo } from 'react';
|
||||
import type {
|
||||
MarketDataUpdateFieldsFragment,
|
||||
MarketDealTicket,
|
||||
} from '@vegaprotocol/market-list';
|
||||
import { marketDealTicketProvider } from '@vegaprotocol/market-list';
|
||||
|
||||
const tempEmptyText = (
|
||||
<p>{t('Please select a market from the markets page')}</p>
|
||||
@ -21,52 +26,64 @@ export const DealTicketContainer = () => {
|
||||
const { marketId } = useParams<{ marketId: string }>();
|
||||
const { pubKey } = useVegaWallet();
|
||||
|
||||
const { data: partyData, loading } = usePartyBalanceQuery({
|
||||
const { data: partyData } = usePartyBalanceQuery({
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
});
|
||||
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
marketId: marketId || '',
|
||||
}),
|
||||
[marketId]
|
||||
);
|
||||
const { data, loading } = useDataProvider<
|
||||
MarketDealTicket,
|
||||
MarketDataUpdateFieldsFragment
|
||||
>({
|
||||
dataProvider: marketDealTicketProvider,
|
||||
variables,
|
||||
skip: !marketId,
|
||||
});
|
||||
|
||||
const accounts = compact(partyData?.party?.accountsConnection?.edges).map(
|
||||
(e) => e.node
|
||||
);
|
||||
|
||||
const loader = <Loader />;
|
||||
|
||||
const container = marketId ? (
|
||||
<Container marketId={marketId}>
|
||||
{(data) => {
|
||||
if (!data.market) {
|
||||
return null as unknown as JSX.Element;
|
||||
if (marketId && data) {
|
||||
const balance = (
|
||||
<DealTicketBalance
|
||||
className="mb-4"
|
||||
settlementAsset={
|
||||
data.tradableInstrument.instrument.product?.settlementAsset
|
||||
}
|
||||
accounts={accounts || []}
|
||||
isWalletConnected={!!pubKey}
|
||||
/>
|
||||
);
|
||||
|
||||
const accounts = compact(
|
||||
partyData?.party?.accountsConnection?.edges
|
||||
).map((e) => e.node);
|
||||
const balance = (
|
||||
<DealTicketBalance
|
||||
className="mb-4"
|
||||
settlementAsset={
|
||||
data.market.tradableInstrument.instrument.product?.settlementAsset
|
||||
}
|
||||
accounts={accounts || []}
|
||||
isWalletConnected={!!pubKey}
|
||||
/>
|
||||
);
|
||||
const container = (
|
||||
<DealTicketManager market={data}>
|
||||
{loading ? loader : balance}
|
||||
<DealTicketSteps market={data} />
|
||||
</DealTicketManager>
|
||||
);
|
||||
|
||||
return (
|
||||
<DealTicketManager market={data.market}>
|
||||
{loading ? loader : balance}
|
||||
<DealTicketSteps market={data.market} />
|
||||
</DealTicketManager>
|
||||
);
|
||||
}}
|
||||
</Container>
|
||||
return (
|
||||
<section className="flex p-4 md:p-6">
|
||||
<section className="w-full md:w-1/2 md:min-w-[500px]">
|
||||
{pubKey ? container : <ConnectWallet />}
|
||||
</section>
|
||||
<Baubles />
|
||||
</section>
|
||||
);
|
||||
}
|
||||
return marketId ? (
|
||||
<Splash>
|
||||
<p>{t('Could not load market')}</p>
|
||||
</Splash>
|
||||
) : (
|
||||
tempEmptyText
|
||||
);
|
||||
|
||||
return (
|
||||
<section className="flex p-4 md:p-6">
|
||||
<section className="w-full md:w-1/2 md:min-w-[500px]">
|
||||
{pubKey ? container : <ConnectWallet />}
|
||||
</section>
|
||||
<Baubles />
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
@ -3,7 +3,6 @@ import { useNavigate } from 'react-router-dom';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import compact from 'lodash/compact';
|
||||
import { Stepper } from '../stepper';
|
||||
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
|
||||
import {
|
||||
getDefaultOrder,
|
||||
useOrderCloseOut,
|
||||
@ -42,9 +41,10 @@ import ReviewTrade from './review-trade';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import { DealTicketSlippage } from './deal-ticket-slippage';
|
||||
import { useOrderValidation } from './use-order-validation';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
|
||||
interface DealTicketMarketProps {
|
||||
market: DealTicketMarketFragment;
|
||||
market: MarketDealTicket;
|
||||
}
|
||||
|
||||
export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
|
||||
@ -78,10 +78,8 @@ export const DealTicketSteps = ({ market }: DealTicketMarketProps) => {
|
||||
});
|
||||
const { message: invalidText, isDisabled } = useOrderValidation({
|
||||
market,
|
||||
orderType: order.type,
|
||||
orderTimeInForce: order.timeInForce,
|
||||
order,
|
||||
fieldErrors: errors,
|
||||
estMargin,
|
||||
});
|
||||
const { submit, transaction, finalizedOrder, Dialog } = useOrderSubmit();
|
||||
|
||||
|
@ -5,17 +5,17 @@ import {
|
||||
KeyValueTableRow,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import classNames from 'classnames';
|
||||
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
|
||||
import { DealTicketEstimates } from '@vegaprotocol/deal-ticket';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import { SIDE_NAMES } from './side-selector';
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import { MarketExpires } from '@vegaprotocol/market-info';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import type {
|
||||
MarketTags,
|
||||
MarketTagsVariables,
|
||||
} from './__generated__/MarketTags';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import { MarketExpires } from '@vegaprotocol/market-info';
|
||||
|
||||
export const MARKET_TAGS_QUERY = gql`
|
||||
query MarketTags($marketId: ID!) {
|
||||
@ -32,7 +32,7 @@ export const MARKET_TAGS_QUERY = gql`
|
||||
`;
|
||||
|
||||
interface Props {
|
||||
market: DealTicketMarketFragment;
|
||||
market: MarketDealTicket;
|
||||
isDisabled: boolean;
|
||||
transactionStatus?: string;
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
|
@ -3,12 +3,15 @@ import { renderHook } from '@testing-library/react';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
|
||||
import { MarketStateMapping, Schema } from '@vegaprotocol/types';
|
||||
import {
|
||||
MarketStateMapping,
|
||||
Schema as Types,
|
||||
Schema,
|
||||
} from '@vegaprotocol/types';
|
||||
import type { ValidationProps } from './use-order-validation';
|
||||
import { marketTranslations, useOrderValidation } from './use-order-validation';
|
||||
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import * as DealTicket from '@vegaprotocol/deal-ticket';
|
||||
import BigNumber from 'bignumber.js';
|
||||
|
||||
jest.mock('@vegaprotocol/wallet');
|
||||
jest.mock('@vegaprotocol/deal-ticket', () => {
|
||||
@ -19,7 +22,7 @@ jest.mock('@vegaprotocol/deal-ticket', () => {
|
||||
});
|
||||
|
||||
type SettlementAsset =
|
||||
DealTicketMarketFragment['tradableInstrument']['instrument']['product']['settlementAsset'];
|
||||
MarketDealTicket['tradableInstrument']['instrument']['product']['settlementAsset'];
|
||||
const asset: SettlementAsset = {
|
||||
__typename: 'Asset',
|
||||
id: 'asset-id',
|
||||
@ -28,7 +31,7 @@ const asset: SettlementAsset = {
|
||||
decimals: 2,
|
||||
};
|
||||
|
||||
const market: DealTicketMarketFragment = {
|
||||
const market: MarketDealTicket = {
|
||||
id: 'market-id',
|
||||
decimalPlaces: 2,
|
||||
positionDecimalPlaces: 1,
|
||||
@ -40,10 +43,17 @@ const market: DealTicketMarketFragment = {
|
||||
__typename: 'Instrument',
|
||||
id: 'instrument-id',
|
||||
name: 'instrument-name',
|
||||
code: 'instriment-code',
|
||||
metadata: {
|
||||
tags: [],
|
||||
},
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'quote-name',
|
||||
settlementAsset: asset,
|
||||
dataSourceSpecForTradingTermination: {
|
||||
id: 'dataSource-id',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@ -63,6 +73,25 @@ const market: DealTicketMarketFragment = {
|
||||
liquidityFee: '3',
|
||||
},
|
||||
},
|
||||
data: {
|
||||
__typename: 'MarketData',
|
||||
bestBidPrice: '1605489971',
|
||||
bestOfferPrice: '1606823730',
|
||||
markPrice: '1606823730',
|
||||
trigger: Types.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
|
||||
staticMidPrice: '1606156850',
|
||||
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
indicativeVolume: '0',
|
||||
indicativePrice: '0',
|
||||
bestStaticBidPrice: '1605489971',
|
||||
bestStaticOfferPrice: '1606823730',
|
||||
targetStake: '8561302732',
|
||||
suppliedStake: '727654170336',
|
||||
auctionStart: null,
|
||||
auctionEnd: null,
|
||||
market: { __typename: 'Market', id: 'market-id' },
|
||||
},
|
||||
marketTimestamps: {},
|
||||
};
|
||||
|
||||
const defaultWalletContext = {
|
||||
@ -75,19 +104,19 @@ const defaultWalletContext = {
|
||||
connector: null,
|
||||
};
|
||||
|
||||
const order = {
|
||||
type: Schema.OrderType.TYPE_MARKET,
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
marketId: 'market-id',
|
||||
side: Schema.Side.SIDE_BUY,
|
||||
size: '0.1',
|
||||
};
|
||||
|
||||
const defaultOrder = {
|
||||
market,
|
||||
market: { ...market },
|
||||
step: 0.1,
|
||||
orderType: Schema.OrderType.TYPE_MARKET,
|
||||
orderTimeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
estMargin: {
|
||||
margin: '0,000001',
|
||||
totalFees: '0,000006',
|
||||
fees: {
|
||||
makerFee: '0,000003',
|
||||
liquidityFee: '0,000002',
|
||||
infrastructureFee: '0,000001',
|
||||
},
|
||||
order: {
|
||||
...order,
|
||||
},
|
||||
};
|
||||
|
||||
@ -127,9 +156,9 @@ describe('useOrderValidation', () => {
|
||||
|
||||
it('Returns empty string when given valid data', () => {
|
||||
jest.spyOn(DealTicket, 'useOrderMarginValidation').mockReturnValue({
|
||||
balance: new BigNumber(0),
|
||||
margin: new BigNumber(100),
|
||||
asset,
|
||||
balance: '0',
|
||||
margin: '100',
|
||||
balanceError: false,
|
||||
});
|
||||
|
||||
const { result } = setup();
|
||||
@ -142,9 +171,9 @@ describe('useOrderValidation', () => {
|
||||
|
||||
it('Returns an error message when no keypair found', () => {
|
||||
jest.spyOn(DealTicket, 'useOrderMarginValidation').mockReturnValue({
|
||||
balance: new BigNumber(0),
|
||||
margin: new BigNumber(100),
|
||||
asset,
|
||||
balance: '0',
|
||||
margin: '100',
|
||||
balanceError: false,
|
||||
});
|
||||
const { result } = setup(defaultOrder, { pubKey: null });
|
||||
expect(result.current).toStrictEqual({
|
||||
@ -183,9 +212,10 @@ describe('useOrderValidation', () => {
|
||||
'Returns an error message for market state suspended or pending',
|
||||
({ state }) => {
|
||||
jest.spyOn(DealTicket, 'useOrderMarginValidation').mockReturnValue({
|
||||
balance: new BigNumber(0),
|
||||
margin: new BigNumber(100),
|
||||
asset,
|
||||
balance: '0',
|
||||
margin: '100',
|
||||
balanceError: false,
|
||||
// asset,
|
||||
});
|
||||
const { result } = setup({
|
||||
market: {
|
||||
@ -193,8 +223,11 @@ describe('useOrderValidation', () => {
|
||||
state,
|
||||
tradingMode: Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
|
||||
},
|
||||
orderType: Schema.OrderType.TYPE_LIMIT,
|
||||
orderTimeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT,
|
||||
order: {
|
||||
...order,
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT,
|
||||
},
|
||||
});
|
||||
expect(result.current).toStrictEqual({
|
||||
isDisabled: false,
|
||||
@ -216,7 +249,10 @@ describe('useOrderValidation', () => {
|
||||
({ tradingMode, errorMessage }) => {
|
||||
const { result } = setup({
|
||||
market: { ...defaultOrder.market, tradingMode },
|
||||
orderType: Schema.OrderType.TYPE_MARKET,
|
||||
order: {
|
||||
...order,
|
||||
type: Schema.OrderType.TYPE_MARKET,
|
||||
},
|
||||
});
|
||||
expect(result.current.isDisabled).toBeTruthy();
|
||||
expect(result.current.message).toBe(errorMessage);
|
||||
@ -239,8 +275,11 @@ describe('useOrderValidation', () => {
|
||||
({ tradingMode, orderTimeInForce, errorMessage }) => {
|
||||
const { result } = setup({
|
||||
market: { ...defaultOrder.market, tradingMode },
|
||||
orderType: Schema.OrderType.TYPE_LIMIT,
|
||||
orderTimeInForce,
|
||||
order: {
|
||||
...order,
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
timeInForce: orderTimeInForce,
|
||||
},
|
||||
});
|
||||
expect(result.current).toStrictEqual({
|
||||
isDisabled: true,
|
||||
@ -261,7 +300,10 @@ describe('useOrderValidation', () => {
|
||||
({ fieldName, errorType, section, errorMessage }) => {
|
||||
const { result } = setup({
|
||||
fieldErrors: { [fieldName]: { type: errorType } },
|
||||
orderType: Schema.OrderType.TYPE_LIMIT,
|
||||
order: {
|
||||
...order,
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
},
|
||||
});
|
||||
expect(result.current).toStrictEqual({
|
||||
isDisabled: true,
|
||||
@ -300,9 +342,9 @@ describe('useOrderValidation', () => {
|
||||
|
||||
it('Returns an error message when the estimated margin is higher than collateral', async () => {
|
||||
const invalidatedMockValue = {
|
||||
balance: new BigNumber(100),
|
||||
margin: new BigNumber(200),
|
||||
asset,
|
||||
balance: '100',
|
||||
margin: '200',
|
||||
balanceError: true,
|
||||
};
|
||||
|
||||
jest
|
||||
@ -315,9 +357,9 @@ describe('useOrderValidation', () => {
|
||||
|
||||
const testElement = (
|
||||
<DealTicket.MarginWarning
|
||||
margin={invalidatedMockValue.margin.toString()}
|
||||
balance={invalidatedMockValue.balance.toString()}
|
||||
asset={invalidatedMockValue.asset}
|
||||
margin={invalidatedMockValue.margin}
|
||||
balance={invalidatedMockValue.balance}
|
||||
asset={asset}
|
||||
/>
|
||||
);
|
||||
expect((result.current.message as React.ReactElement)?.props).toEqual(
|
||||
|
@ -6,10 +6,6 @@ import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { MarketStateMapping, Schema } from '@vegaprotocol/types';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||
import type {
|
||||
DealTicketMarketFragment,
|
||||
OrderMargin,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
import {
|
||||
MarketDataGrid,
|
||||
compileGridData,
|
||||
@ -18,6 +14,7 @@ import {
|
||||
ERROR_SIZE_DECIMAL,
|
||||
useOrderMarginValidation,
|
||||
} from '@vegaprotocol/deal-ticket';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
|
||||
export const DEAL_TICKET_SECTION = {
|
||||
TYPE: 'sec-type',
|
||||
@ -32,11 +29,9 @@ export const ERROR_EXPIRATION_IN_THE_PAST = 'ERROR_EXPIRATION_IN_THE_PAST';
|
||||
|
||||
export type ValidationProps = {
|
||||
step?: number;
|
||||
market: DealTicketMarketFragment;
|
||||
orderType: Schema.OrderType;
|
||||
orderTimeInForce: Schema.OrderTimeInForce;
|
||||
market: MarketDealTicket;
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
fieldErrors?: FieldErrors<OrderSubmissionBody['orderSubmission']>;
|
||||
estMargin: OrderMargin | null;
|
||||
};
|
||||
|
||||
export const marketTranslations = (marketState: Schema.MarketState) => {
|
||||
@ -55,9 +50,7 @@ export type DealTicketSection =
|
||||
export const useOrderValidation = ({
|
||||
market,
|
||||
fieldErrors,
|
||||
orderType,
|
||||
orderTimeInForce,
|
||||
estMargin,
|
||||
order,
|
||||
}: ValidationProps): {
|
||||
message: ReactNode | string;
|
||||
isDisabled: boolean;
|
||||
@ -65,7 +58,7 @@ export const useOrderValidation = ({
|
||||
} => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const minSize = toDecimal(market.positionDecimalPlaces);
|
||||
const isInvalidOrderMargin = useOrderMarginValidation({ market, estMargin });
|
||||
const isInvalidOrderMargin = useOrderMarginValidation({ market, order });
|
||||
|
||||
const fieldErrorChecking = useMemo<{
|
||||
message: ReactNode | string;
|
||||
@ -91,7 +84,7 @@ export const useOrderValidation = ({
|
||||
|
||||
if (
|
||||
fieldErrors?.price?.type === 'required' &&
|
||||
orderType !== Schema.OrderType.TYPE_MARKET
|
||||
order.type !== Schema.OrderType.TYPE_MARKET
|
||||
) {
|
||||
return {
|
||||
isDisabled: true,
|
||||
@ -102,7 +95,7 @@ export const useOrderValidation = ({
|
||||
|
||||
if (
|
||||
fieldErrors?.price?.type === 'min' &&
|
||||
orderType !== Schema.OrderType.TYPE_MARKET
|
||||
order.type !== Schema.OrderType.TYPE_MARKET
|
||||
) {
|
||||
return {
|
||||
isDisabled: true,
|
||||
@ -151,7 +144,7 @@ export const useOrderValidation = ({
|
||||
fieldErrors?.price?.type,
|
||||
fieldErrors?.expiresAt?.type,
|
||||
fieldErrors?.expiresAt?.message,
|
||||
orderType,
|
||||
order.type,
|
||||
minSize,
|
||||
market.positionDecimalPlaces,
|
||||
]);
|
||||
@ -210,7 +203,7 @@ export const useOrderValidation = ({
|
||||
}
|
||||
|
||||
if (isMarketInAuction(market)) {
|
||||
if (orderType === Schema.OrderType.TYPE_MARKET) {
|
||||
if (order.type === Schema.OrderType.TYPE_MARKET) {
|
||||
if (
|
||||
market.tradingMode ===
|
||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
|
||||
@ -269,12 +262,12 @@ export const useOrderValidation = ({
|
||||
};
|
||||
}
|
||||
if (
|
||||
orderType === Schema.OrderType.TYPE_LIMIT &&
|
||||
order.type === Schema.OrderType.TYPE_LIMIT &&
|
||||
[
|
||||
Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
Schema.OrderTimeInForce.TIME_IN_FORCE_IOC,
|
||||
Schema.OrderTimeInForce.TIME_IN_FORCE_GFN,
|
||||
].includes(orderTimeInForce)
|
||||
].includes(order.timeInForce)
|
||||
) {
|
||||
if (
|
||||
market.tradingMode ===
|
||||
@ -343,17 +336,14 @@ export const useOrderValidation = ({
|
||||
return fieldErrorChecking;
|
||||
}
|
||||
|
||||
if (
|
||||
isInvalidOrderMargin.balance.isGreaterThan(0) &&
|
||||
isInvalidOrderMargin.balance.isLessThan(isInvalidOrderMargin.margin)
|
||||
) {
|
||||
if (isInvalidOrderMargin.balanceError) {
|
||||
return {
|
||||
isDisabled: false,
|
||||
message: (
|
||||
<MarginWarning
|
||||
margin={isInvalidOrderMargin.margin.toString()}
|
||||
balance={isInvalidOrderMargin.balance.toString()}
|
||||
asset={isInvalidOrderMargin.asset}
|
||||
margin={isInvalidOrderMargin.margin}
|
||||
balance={isInvalidOrderMargin.balance}
|
||||
asset={market.tradableInstrument.instrument.product.settlementAsset}
|
||||
/>
|
||||
),
|
||||
section: DEAL_TICKET_SECTION.PRICE,
|
||||
@ -386,8 +376,8 @@ export const useOrderValidation = ({
|
||||
market,
|
||||
fieldErrorChecking,
|
||||
isInvalidOrderMargin,
|
||||
orderType,
|
||||
orderTimeInForce,
|
||||
order.type,
|
||||
order.timeInForce,
|
||||
]);
|
||||
|
||||
return { message, isDisabled, section };
|
||||
|
@ -499,6 +499,7 @@ describe('deal ticket size validation', { tags: '@smoke' }, function () {
|
||||
describe('limit order validations', { tags: '@smoke' }, () => {
|
||||
before(() => {
|
||||
cy.mockTradingPage();
|
||||
cy.mockGQLSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
connectVegaWallet();
|
||||
cy.wait('@Market');
|
||||
@ -634,6 +635,7 @@ describe('suspended market validation', { tags: '@regression' }, () => {
|
||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
||||
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY
|
||||
);
|
||||
cy.mockGQLSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
cy.wait('@Market');
|
||||
connectVegaWallet();
|
||||
@ -682,11 +684,15 @@ describe('account validation', { tags: '@regression' }, () => {
|
||||
'EstimateOrder',
|
||||
generateEstimateOrder({
|
||||
estimateOrder: {
|
||||
marginLevels: { __typename: 'MarginLevels', initialLevel: '1000' },
|
||||
marginLevels: {
|
||||
__typename: 'MarginLevels',
|
||||
initialLevel: '1000000000',
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
});
|
||||
cy.mockGQLSubscription();
|
||||
cy.visit('/#/markets/market-0');
|
||||
connectVegaWallet();
|
||||
cy.wait('@Market');
|
||||
@ -712,7 +718,7 @@ describe('account validation', { tags: '@regression' }, () => {
|
||||
);
|
||||
cy.getByTestId('dealticket-warning-margin').should(
|
||||
'contain.text',
|
||||
'0.01 tBTC currently required, 0.001 tBTC available'
|
||||
'10,000 tBTC currently required, 1,000 tBTC available'
|
||||
);
|
||||
cy.getByTestId('deal-ticket-deposit-dialog-button').click();
|
||||
cy.getByTestId('dialog-content')
|
||||
|
@ -101,6 +101,19 @@ export const generateAccounts = (
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
__typename: 'AccountEdge',
|
||||
node: {
|
||||
__typename: 'AccountBalance',
|
||||
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
balance: '100000000',
|
||||
market: null,
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
|
@ -164,6 +164,30 @@ export const generateAssets = (override?: PartialDeep<AssetsQuery>) => {
|
||||
__typename: 'Asset',
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
|
||||
symbol: 'tBTC',
|
||||
decimals: 5,
|
||||
name: 'tBTC TEST',
|
||||
source: {
|
||||
maxFaucetAmountMint: '5000000000',
|
||||
__typename: 'BuiltinAsset',
|
||||
},
|
||||
quantum: '1',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
infrastructureFeeAccount: {
|
||||
balance: '0',
|
||||
__typename: 'AccountBalance',
|
||||
},
|
||||
globalRewardPoolAccount: null,
|
||||
takerFeeRewardAccount: null,
|
||||
makerFeeRewardAccount: null,
|
||||
lpFeeRewardAccount: null,
|
||||
marketProposerRewardAccount: null,
|
||||
__typename: 'Asset',
|
||||
},
|
||||
},
|
||||
// NOTE: These assets ids and contract addresses are real assets on Sepolia, this is needed
|
||||
// because we don't currently mock our seplia infura provider. If we change network these will
|
||||
// need to be updated
|
||||
|
@ -1,54 +0,0 @@
|
||||
import type { DealTicketQuery } from '@vegaprotocol/deal-ticket';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateDealTicketQuery = (
|
||||
override?: PartialDeep<DealTicketQuery>
|
||||
): DealTicketQuery => {
|
||||
const defaultResult: DealTicketQuery = {
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: 'market-0',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
state: Schema.MarketState.STATE_ACTIVE,
|
||||
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
fees: {
|
||||
factors: {
|
||||
makerFee: '0.0002',
|
||||
infrastructureFee: '0.0005',
|
||||
liquidityFee: '0.0005',
|
||||
},
|
||||
},
|
||||
tradableInstrument: {
|
||||
__typename: 'TradableInstrument',
|
||||
instrument: {
|
||||
__typename: 'Instrument',
|
||||
id: 'tBTC TEST',
|
||||
name: 'ETHBTC Quarterly (30 Jun 2022)',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: 'BTC',
|
||||
settlementAsset: {
|
||||
__typename: 'Asset',
|
||||
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
|
||||
symbol: 'tBTC',
|
||||
name: 'tBTC TEST',
|
||||
decimals: 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
depth: {
|
||||
__typename: 'MarketDepth',
|
||||
lastTrade: {
|
||||
__typename: 'Trade',
|
||||
price: '100',
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
@ -13,7 +13,7 @@ export const generateMarket = (
|
||||
const defaultResult: MarketQuery = {
|
||||
market: {
|
||||
id: 'market-0',
|
||||
tradingMode: Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
||||
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
state: Schema.MarketState.STATE_ACTIVE,
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 0,
|
||||
@ -38,12 +38,12 @@ export const generateMarket = (
|
||||
id: 'd253c16c6a17ab88e098479635c611ab503582a1079752d1a49ac15f656f7e7b',
|
||||
__typename: 'DataSourceSpec',
|
||||
},
|
||||
quoteName: 'BTCUSD Monthly',
|
||||
quoteName: 'BTC',
|
||||
settlementAsset: {
|
||||
decimals: 0,
|
||||
id: '000',
|
||||
symbol: 'USD',
|
||||
name: 'United States Dollar',
|
||||
decimals: 5,
|
||||
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
|
||||
symbol: 'tBTC',
|
||||
name: 'tBTC TEST',
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'Future',
|
||||
@ -61,12 +61,16 @@ export const generateMarket = (
|
||||
__typename: 'Fees',
|
||||
factors: {
|
||||
__typename: 'FeeFactors',
|
||||
makerFee: '',
|
||||
infrastructureFee: '',
|
||||
liquidityFee: '',
|
||||
makerFee: '0.0002',
|
||||
infrastructureFee: '0.0005',
|
||||
liquidityFee: '0.0005',
|
||||
},
|
||||
},
|
||||
__typename: 'Market',
|
||||
depth: {
|
||||
__typename: 'MarketDepth',
|
||||
lastTrade: { price: '100', __typename: 'Trade' },
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -6,7 +6,6 @@ import { generateAsset, generateAssets } from './mocks/generate-assets';
|
||||
import { generateCandles } from './mocks/generate-candles';
|
||||
import { generateChainId } from './mocks/generate-chain-id';
|
||||
import { generateChart } from './mocks/generate-chart';
|
||||
import { generateDealTicketQuery } from './mocks/generate-deal-ticket-query';
|
||||
import { generateMarket, generateMarketData } from './mocks/generate-market';
|
||||
import { generateMarketDepth } from './mocks/generate-market-depth';
|
||||
import { generateMarketInfoQuery } from './mocks/generate-market-info-query';
|
||||
@ -48,6 +47,7 @@ const mockTradingPage = (
|
||||
},
|
||||
},
|
||||
state: state,
|
||||
tradingMode: tradingMode,
|
||||
},
|
||||
})
|
||||
);
|
||||
@ -69,19 +69,6 @@ const mockTradingPage = (
|
||||
aliasQuery(req, 'Accounts', generateAccounts());
|
||||
aliasQuery(req, 'Positions', generatePositions());
|
||||
aliasQuery(req, 'Margins', generateMargins());
|
||||
aliasQuery(
|
||||
req,
|
||||
'DealTicket',
|
||||
generateDealTicketQuery({
|
||||
market: {
|
||||
state,
|
||||
tradingMode: tradingMode,
|
||||
data: {
|
||||
trigger: trigger,
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
||||
aliasQuery(req, 'Assets', generateAssets());
|
||||
aliasQuery(req, 'Asset', generateAsset());
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { t, useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import { compileGridData, TradingModeTooltip } from '@vegaprotocol/deal-ticket';
|
||||
import type { Schema as Types } from '@vegaprotocol/types';
|
||||
import {
|
||||
@ -21,13 +21,11 @@ interface Props {
|
||||
onSelect?: (marketId: string) => void;
|
||||
}
|
||||
|
||||
type TradingModeMarket = Omit<DealTicketMarketFragment, 'depth'>;
|
||||
|
||||
export const MarketTradingModeComponent = ({ marketId, onSelect }: Props) => {
|
||||
const [tradingMode, setTradingMode] =
|
||||
useState<Types.MarketTradingMode | null>(null);
|
||||
const [trigger, setTrigger] = useState<Types.AuctionTrigger | null>(null);
|
||||
const [market, setMarket] = useState<TradingModeMarket | null>(null);
|
||||
const [market, setMarket] = useState<MarketDealTicket | null>(null);
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
marketId: marketId,
|
||||
@ -49,7 +47,7 @@ export const MarketTradingModeComponent = ({ marketId, onSelect }: Props) => {
|
||||
setMarket({
|
||||
...data,
|
||||
data: marketData,
|
||||
} as TradingModeMarket);
|
||||
} as MarketDealTicket);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
15
libs/accounts/src/lib/get-settlement-account.ts
Normal file
15
libs/accounts/src/lib/get-settlement-account.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import type { Account } from './accounts-data-provider';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
|
||||
interface Props {
|
||||
accounts: Account[] | null;
|
||||
assetId: string;
|
||||
}
|
||||
|
||||
export const getSettlementAccount = ({ accounts, assetId }: Props) =>
|
||||
accounts?.find((account) => {
|
||||
return (
|
||||
account.asset.id === assetId &&
|
||||
account.type === Schema.AccountType.ACCOUNT_TYPE_GENERAL
|
||||
);
|
||||
}) || null;
|
@ -4,3 +4,5 @@ export * from './accounts-table';
|
||||
export * from './asset-balance';
|
||||
export * from './accounts-manager';
|
||||
export * from './breakdown-table';
|
||||
export * from './use-account-balance';
|
||||
export * from './get-settlement-account';
|
||||
|
43
libs/accounts/src/lib/use-account-balance.tsx
Normal file
43
libs/accounts/src/lib/use-account-balance.tsx
Normal file
@ -0,0 +1,43 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { accountsDataProvider } from './accounts-data-provider';
|
||||
import type { Account } from './accounts-data-provider';
|
||||
import { getSettlementAccount } from './get-settlement-account';
|
||||
|
||||
export const useAccountBalance = (assetId: string) => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const [accountBalance, setAccountBalance] = useState<string>('');
|
||||
const [accountDecimals, setAccountDecimals] = useState<number | null>(null);
|
||||
const variables = useMemo(() => {
|
||||
return { partyId: pubKey || '' };
|
||||
}, [pubKey]);
|
||||
const update = useCallback(
|
||||
({ data }: { data: Account[] | null }) => {
|
||||
const account = getSettlementAccount({ accounts: data, assetId });
|
||||
if (accountBalance !== account?.balance) {
|
||||
setAccountBalance(account?.balance || '');
|
||||
}
|
||||
if (accountDecimals !== account?.asset.decimals) {
|
||||
setAccountDecimals(account?.asset.decimals || null);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
[accountBalance, accountDecimals, assetId]
|
||||
);
|
||||
|
||||
useDataProvider({
|
||||
dataProvider: accountsDataProvider,
|
||||
variables,
|
||||
skip: !pubKey || !assetId,
|
||||
update,
|
||||
});
|
||||
|
||||
return useMemo(
|
||||
() => ({
|
||||
accountBalance,
|
||||
accountDecimals,
|
||||
}),
|
||||
[accountBalance, accountDecimals]
|
||||
);
|
||||
};
|
@ -1,54 +0,0 @@
|
||||
fragment DealTicketMarket on Market {
|
||||
id
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
state
|
||||
tradingMode
|
||||
data {
|
||||
market {
|
||||
id
|
||||
}
|
||||
indicativePrice
|
||||
indicativeVolume
|
||||
targetStake
|
||||
suppliedStake
|
||||
auctionStart
|
||||
auctionEnd
|
||||
trigger
|
||||
}
|
||||
fees {
|
||||
factors {
|
||||
makerFee
|
||||
infrastructureFee
|
||||
liquidityFee
|
||||
}
|
||||
}
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
id
|
||||
name
|
||||
product {
|
||||
... on Future {
|
||||
quoteName
|
||||
settlementAsset {
|
||||
id
|
||||
symbol
|
||||
decimals
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
depth {
|
||||
lastTrade {
|
||||
price
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query DealTicket($marketId: ID!) {
|
||||
market(id: $marketId) {
|
||||
...DealTicketMarket
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type DealTicketMarketFragment = { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, data?: { __typename?: 'MarketData', indicativePrice: string, indicativeVolume: string, targetStake?: string | null, suppliedStake?: string | null, auctionStart?: string | null, auctionEnd?: string | null, trigger: Types.AuctionTrigger, market: { __typename?: 'Market', id: string } } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, decimals: number, name: string } } } }, depth: { __typename?: 'MarketDepth', lastTrade?: { __typename?: 'Trade', price: string } | null } };
|
||||
|
||||
export type DealTicketQueryVariables = Types.Exact<{
|
||||
marketId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type DealTicketQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, data?: { __typename?: 'MarketData', indicativePrice: string, indicativeVolume: string, targetStake?: string | null, suppliedStake?: string | null, auctionStart?: string | null, auctionEnd?: string | null, trigger: Types.AuctionTrigger, market: { __typename?: 'Market', id: string } } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, decimals: number, name: string } } } }, depth: { __typename?: 'MarketDepth', lastTrade?: { __typename?: 'Trade', price: string } | null } } | null };
|
||||
|
||||
export const DealTicketMarketFragmentDoc = gql`
|
||||
fragment DealTicketMarket on Market {
|
||||
id
|
||||
decimalPlaces
|
||||
positionDecimalPlaces
|
||||
state
|
||||
tradingMode
|
||||
data {
|
||||
market {
|
||||
id
|
||||
}
|
||||
indicativePrice
|
||||
indicativeVolume
|
||||
targetStake
|
||||
suppliedStake
|
||||
auctionStart
|
||||
auctionEnd
|
||||
trigger
|
||||
}
|
||||
fees {
|
||||
factors {
|
||||
makerFee
|
||||
infrastructureFee
|
||||
liquidityFee
|
||||
}
|
||||
}
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
id
|
||||
name
|
||||
product {
|
||||
... on Future {
|
||||
quoteName
|
||||
settlementAsset {
|
||||
id
|
||||
symbol
|
||||
decimals
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
depth {
|
||||
lastTrade {
|
||||
price
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const DealTicketDocument = gql`
|
||||
query DealTicket($marketId: ID!) {
|
||||
market(id: $marketId) {
|
||||
...DealTicketMarket
|
||||
}
|
||||
}
|
||||
${DealTicketMarketFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __useDealTicketQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useDealTicketQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useDealTicketQuery` 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 } = useDealTicketQuery({
|
||||
* variables: {
|
||||
* marketId: // value for 'marketId'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useDealTicketQuery(baseOptions: Apollo.QueryHookOptions<DealTicketQuery, DealTicketQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<DealTicketQuery, DealTicketQueryVariables>(DealTicketDocument, options);
|
||||
}
|
||||
export function useDealTicketLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DealTicketQuery, DealTicketQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<DealTicketQuery, DealTicketQueryVariables>(DealTicketDocument, options);
|
||||
}
|
||||
export type DealTicketQueryHookResult = ReturnType<typeof useDealTicketQuery>;
|
||||
export type DealTicketLazyQueryHookResult = ReturnType<typeof useDealTicketLazyQuery>;
|
||||
export type DealTicketQueryResult = Apollo.QueryResult<DealTicketQuery, DealTicketQueryVariables>;
|
@ -1,13 +1,13 @@
|
||||
import type { UseFormRegister } from 'react-hook-form';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import { DealTicketMarketAmount } from './deal-ticket-market-amount';
|
||||
import { DealTicketLimitAmount } from './deal-ticket-limit-amount';
|
||||
import type { DealTicketMarketFragment } from './__generated__/DealTicket';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import type { DealTicketFormFields } from './deal-ticket';
|
||||
|
||||
export interface DealTicketAmountProps {
|
||||
orderType: Schema.OrderType;
|
||||
market: DealTicketMarketFragment;
|
||||
market: MarketDealTicket;
|
||||
register: UseFormRegister<DealTicketFormFields>;
|
||||
sizeError?: string;
|
||||
priceError?: string;
|
||||
|
@ -1,30 +1,41 @@
|
||||
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 { marketDealTicketProvider } from '@vegaprotocol/market-list';
|
||||
import { DealTicketManager } from './deal-ticket-manager';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { useDealTicketQuery } from './__generated__/DealTicket';
|
||||
import type { DealTicketQuery } from './__generated__/DealTicket';
|
||||
|
||||
export interface DealTicketContainerProps {
|
||||
marketId: string;
|
||||
children?(props: DealTicketQuery): JSX.Element;
|
||||
}
|
||||
|
||||
export const DealTicketContainer = ({
|
||||
marketId,
|
||||
children,
|
||||
}: DealTicketContainerProps) => {
|
||||
const { data, loading, error } = useDealTicketQuery({
|
||||
variables: { marketId },
|
||||
export const DealTicketContainer = ({ marketId }: DealTicketContainerProps) => {
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
marketId: marketId || '',
|
||||
}),
|
||||
[marketId]
|
||||
);
|
||||
const { data, error, loading } = useDataProvider<
|
||||
MarketDealTicket,
|
||||
MarketDataUpdateFieldsFragment
|
||||
>({
|
||||
dataProvider: marketDealTicketProvider,
|
||||
variables,
|
||||
skip: !marketId,
|
||||
});
|
||||
|
||||
return (
|
||||
<AsyncRenderer<DealTicketQuery> data={data} loading={loading} error={error}>
|
||||
{data && data.market ? (
|
||||
children ? (
|
||||
children(data)
|
||||
) : (
|
||||
<DealTicketManager market={data.market} />
|
||||
)
|
||||
<AsyncRenderer<MarketDealTicket>
|
||||
data={data || undefined}
|
||||
loading={loading}
|
||||
error={error}
|
||||
>
|
||||
{data ? (
|
||||
<DealTicketManager market={data} />
|
||||
) : (
|
||||
<Splash>
|
||||
<p>{t('Could not load market')}</p>
|
||||
|
@ -1,9 +1,15 @@
|
||||
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 {
|
||||
getFeeDetailsValues,
|
||||
useFeeDealTicketDetails,
|
||||
} from '../../hooks/use-fee-deal-ticket-details';
|
||||
|
||||
interface DealTicketFeeDetailsProps {
|
||||
details: DealTicketFeeDetails[];
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
market: MarketDealTicket;
|
||||
}
|
||||
|
||||
export interface DealTicketFeeDetails {
|
||||
@ -14,8 +20,11 @@ export interface DealTicketFeeDetails {
|
||||
}
|
||||
|
||||
export const DealTicketFeeDetails = ({
|
||||
details,
|
||||
order,
|
||||
market,
|
||||
}: DealTicketFeeDetailsProps) => {
|
||||
const feeDetails = useFeeDealTicketDetails(order, market);
|
||||
const details = getFeeDetailsValues(feeDetails);
|
||||
return (
|
||||
<div>
|
||||
{details.map(({ label, value, labelDescription, quoteName }) => (
|
||||
|
@ -1,14 +1,14 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import { VegaTxStatus } from '@vegaprotocol/wallet';
|
||||
import { DealTicket } from './deal-ticket';
|
||||
import type { DealTicketMarketFragment } from './__generated__/DealTicket';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import { useOrderSubmit, OrderFeedback } from '@vegaprotocol/orders';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import { Icon, Intent } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
|
||||
export interface DealTicketManagerProps {
|
||||
market: DealTicketMarketFragment;
|
||||
market: MarketDealTicket;
|
||||
children?: ReactNode | ReactNode[];
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ export const DealTicketMarketAmount = ({
|
||||
price = market.data.indicativePrice;
|
||||
}
|
||||
} else {
|
||||
price = market.depth.lastTrade?.price;
|
||||
price = market.depth?.lastTrade?.price;
|
||||
}
|
||||
|
||||
const priceFormatted = price
|
||||
|
@ -1,8 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
import { VegaWalletContext } from '@vegaprotocol/wallet';
|
||||
import { fireEvent, render, screen, act } from '@testing-library/react';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import { DealTicket } from './deal-ticket';
|
||||
import type { DealTicketMarketFragment } from './__generated__/DealTicket';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
@ -10,7 +10,7 @@ import { MockedProvider } from '@apollo/client/testing';
|
||||
import type { ChainIdQuery } from '@vegaprotocol/react-helpers';
|
||||
import { ChainIdDocument, addDecimal } from '@vegaprotocol/react-helpers';
|
||||
|
||||
const market: DealTicketMarketFragment = {
|
||||
const market = {
|
||||
__typename: 'Market',
|
||||
id: 'market-id',
|
||||
decimalPlaces: 2,
|
||||
@ -50,7 +50,7 @@ const market: DealTicketMarketFragment = {
|
||||
price: '100',
|
||||
},
|
||||
},
|
||||
};
|
||||
} as MarketDealTicket;
|
||||
const submit = jest.fn();
|
||||
const transactionStatus = 'default';
|
||||
|
||||
@ -109,7 +109,7 @@ describe('DealTicket', () => {
|
||||
// Assert last price is shown
|
||||
expect(screen.getByTestId('last-price')).toHaveTextContent(
|
||||
// eslint-disable-next-line
|
||||
`~${addDecimal(market.depth.lastTrade!.price, market.decimalPlaces)} ${
|
||||
`~${addDecimal(market!.depth!.lastTrade!.price, market.decimalPlaces)} ${
|
||||
market.tradableInstrument.instrument.product.settlementAsset.symbol
|
||||
}`
|
||||
);
|
||||
|
@ -2,11 +2,6 @@ import { removeDecimal, t } from '@vegaprotocol/react-helpers';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import { memo, useCallback, useEffect } from 'react';
|
||||
import { Controller, useForm } from 'react-hook-form';
|
||||
|
||||
import {
|
||||
getFeeDetailsValues,
|
||||
useFeeDealTicketDetails,
|
||||
} from '../../hooks/use-fee-deal-ticket-details';
|
||||
import { DealTicketAmount } from './deal-ticket-amount';
|
||||
import { DealTicketButton } from './deal-ticket-button';
|
||||
import { DealTicketFeeDetails } from './deal-ticket-fee-details';
|
||||
@ -14,8 +9,6 @@ import { ExpirySelector } from './expiry-selector';
|
||||
import { SideSelector } from './side-selector';
|
||||
import { TimeInForceSelector } from './time-in-force-selector';
|
||||
import { TypeSelector } from './type-selector';
|
||||
|
||||
import type { DealTicketMarketFragment } from './__generated__/DealTicket';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { InputError } from '@vegaprotocol/ui-toolkit';
|
||||
@ -31,12 +24,13 @@ import {
|
||||
} from '../../utils';
|
||||
import { ZeroBalanceError } from '../deal-ticket-validation/zero-balance-error';
|
||||
import { AccountValidationType } from '../../constants';
|
||||
import type BigNumber from 'bignumber.js';
|
||||
import { useHasNoBalance } from '../../hooks/use-has-no-balance';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
|
||||
export type TransactionStatus = 'default' | 'pending';
|
||||
|
||||
export interface DealTicketProps {
|
||||
market: DealTicketMarketFragment;
|
||||
market: MarketDealTicket;
|
||||
submit: (order: OrderSubmissionBody['orderSubmission']) => void;
|
||||
transactionStatus: TransactionStatus;
|
||||
defaultOrder?: OrderSubmissionBody['orderSubmission'];
|
||||
@ -67,17 +61,11 @@ export const DealTicket = ({
|
||||
});
|
||||
|
||||
const order = watch();
|
||||
const feeDetails = useFeeDealTicketDetails(order, market);
|
||||
const details = getFeeDetailsValues(feeDetails);
|
||||
|
||||
// When order state changes persist it in local storage
|
||||
useEffect(() => setPersistedOrder(order), [order, setPersistedOrder]);
|
||||
|
||||
const accountData = useOrderMarginValidation({
|
||||
market,
|
||||
estMargin: feeDetails.estMargin,
|
||||
});
|
||||
|
||||
const hasNoBalance = useHasNoBalance(
|
||||
market.tradableInstrument.instrument.product.settlementAsset.id
|
||||
);
|
||||
const onSubmit = useCallback(
|
||||
(order: OrderSubmissionBody['orderSubmission']) => {
|
||||
if (!pubKey) {
|
||||
@ -91,7 +79,7 @@ export const DealTicket = ({
|
||||
return;
|
||||
}
|
||||
|
||||
if (accountData.balance.isZero()) {
|
||||
if (hasNoBalance) {
|
||||
setError('summary', { message: AccountValidationType.NoCollateral });
|
||||
return;
|
||||
}
|
||||
@ -117,7 +105,7 @@ export const DealTicket = ({
|
||||
[
|
||||
submit,
|
||||
pubKey,
|
||||
accountData,
|
||||
hasNoBalance,
|
||||
market.positionDecimalPlaces,
|
||||
market.decimalPlaces,
|
||||
market.state,
|
||||
@ -195,9 +183,9 @@ export const DealTicket = ({
|
||||
<SummaryMessage
|
||||
errorMessage={errors.summary?.message}
|
||||
market={market}
|
||||
accountData={accountData}
|
||||
order={order}
|
||||
/>
|
||||
<DealTicketFeeDetails details={details} />
|
||||
<DealTicketFeeDetails order={order} market={market} />
|
||||
</form>
|
||||
);
|
||||
};
|
||||
@ -208,22 +196,18 @@ export const DealTicket = ({
|
||||
*/
|
||||
interface SummaryMessageProps {
|
||||
errorMessage?: string;
|
||||
market: DealTicketMarketFragment;
|
||||
accountData: {
|
||||
balance: BigNumber;
|
||||
margin: BigNumber;
|
||||
asset: {
|
||||
id: string;
|
||||
symbol: string;
|
||||
decimals: number;
|
||||
name: string;
|
||||
};
|
||||
};
|
||||
market: MarketDealTicket;
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
}
|
||||
const SummaryMessage = memo(
|
||||
({ errorMessage, market, accountData }: SummaryMessageProps) => {
|
||||
({ errorMessage, market, order }: 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,
|
||||
order,
|
||||
});
|
||||
if (errorMessage === AccountValidationType.NoCollateral) {
|
||||
return (
|
||||
<ZeroBalanceError
|
||||
@ -246,17 +230,8 @@ const SummaryMessage = memo(
|
||||
|
||||
// If there is no blocking error but user doesn't have enough
|
||||
// balance render the margin warning, but still allow submission
|
||||
if (
|
||||
accountData.balance.isGreaterThan(0) &&
|
||||
accountData.balance.isLessThan(accountData.margin)
|
||||
) {
|
||||
return (
|
||||
<MarginWarning
|
||||
balance={accountData.balance.toString()}
|
||||
margin={accountData.margin.toString()}
|
||||
asset={accountData.asset}
|
||||
/>
|
||||
);
|
||||
if (balanceError) {
|
||||
return <MarginWarning balance={balance} margin={margin} asset={asset} />;
|
||||
}
|
||||
|
||||
// Show auction mode warning
|
||||
|
@ -1,4 +1,3 @@
|
||||
export * from './__generated__/DealTicket';
|
||||
export * from './deal-ticket-amount';
|
||||
export * from './deal-ticket-container';
|
||||
export * from './deal-ticket-limit-amount';
|
||||
|
@ -8,7 +8,6 @@ import React, {
|
||||
} from 'react';
|
||||
import * as DialogPrimitives from '@radix-ui/react-dialog';
|
||||
import classNames from 'classnames';
|
||||
import type { DealTicketMarketFragment } from './';
|
||||
import {
|
||||
ButtonLink,
|
||||
Icon,
|
||||
@ -25,10 +24,11 @@ import {
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { 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: DealTicketMarketFragment;
|
||||
market: MarketDealTicket;
|
||||
setMarket: (marketId: string) => void;
|
||||
ItemRenderer?: React.FC<{
|
||||
market: Market;
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { timeInForceLabel } from '@vegaprotocol/orders';
|
||||
import type { DealTicketMarketFragment } from './__generated__/DealTicket';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import { compileGridData, MarketDataGrid } from '../trading-mode-tooltip';
|
||||
import { MarketModeValidationType } from '../../constants';
|
||||
|
||||
@ -16,7 +16,7 @@ interface TimeInForceSelectorProps {
|
||||
value: Schema.OrderTimeInForce;
|
||||
orderType: Schema.OrderType;
|
||||
onSelect: (tif: Schema.OrderTimeInForce) => void;
|
||||
market: DealTicketMarketFragment;
|
||||
market: MarketDealTicket;
|
||||
errorMessage?: string;
|
||||
}
|
||||
|
||||
|
@ -2,14 +2,14 @@ import { FormGroup, InputError, Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import { Toggle } from '@vegaprotocol/ui-toolkit';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import { compileGridData, MarketDataGrid } from '../trading-mode-tooltip';
|
||||
import type { DealTicketMarketFragment } from './__generated__/DealTicket';
|
||||
import { MarketModeValidationType } from '../../constants';
|
||||
|
||||
interface TypeSelectorProps {
|
||||
value: Schema.OrderType;
|
||||
onSelect: (type: Schema.OrderType) => void;
|
||||
market: DealTicketMarketFragment;
|
||||
market: MarketDealTicket;
|
||||
errorMessage?: string;
|
||||
}
|
||||
|
||||
|
@ -7,11 +7,11 @@ import { Schema } from '@vegaprotocol/types';
|
||||
import { Link as UILink } from '@vegaprotocol/ui-toolkit';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { MarketDataGridProps } from './market-data-grid';
|
||||
import type { DealTicketMarketFragment } from '../deal-ticket/__generated__/DealTicket';
|
||||
import { Link } from 'react-router-dom';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
|
||||
export const compileGridData = (
|
||||
market: Omit<DealTicketMarketFragment, 'depth'>,
|
||||
market: MarketDealTicket,
|
||||
onSelect?: (id: string) => void
|
||||
): { label: ReactNode; value?: ReactNode }[] => {
|
||||
const grid: MarketDataGridProps['grid'] = [];
|
||||
|
@ -8,7 +8,8 @@ import { 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 { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import {
|
||||
EST_CLOSEOUT_TOOLTIP_TEXT,
|
||||
EST_MARGIN_TOOLTIP_TEXT,
|
||||
@ -18,21 +19,18 @@ import { usePartyBalanceQuery } from './__generated__/PartyBalance';
|
||||
import { useCalculateSlippage } from './use-calculate-slippage';
|
||||
import { useOrderCloseOut } from './use-order-closeout';
|
||||
import { useOrderMargin } from './use-order-margin';
|
||||
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import type { DealTicketMarketFragment } from '../components';
|
||||
import type { OrderMargin } from './use-order-margin';
|
||||
|
||||
export const useFeeDealTicketDetails = (
|
||||
order: OrderSubmissionBody['orderSubmission'],
|
||||
market: DealTicketMarketFragment
|
||||
market: MarketDealTicket
|
||||
) => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
|
||||
const slippage = useCalculateSlippage({ marketId: market.id, order });
|
||||
|
||||
const price = useMemo(() => {
|
||||
const estPrice = order.price || market.depth.lastTrade?.price;
|
||||
const estPrice = order.price || market.depth?.lastTrade?.price;
|
||||
if (estPrice) {
|
||||
if (slippage && parseFloat(slippage) !== 0) {
|
||||
const isLong = order.side === Schema.Side.SIDE_BUY;
|
||||
@ -44,7 +42,7 @@ export const useFeeDealTicketDetails = (
|
||||
return order.price;
|
||||
}
|
||||
return null;
|
||||
}, [market.depth.lastTrade?.price, order.price, order.side, slippage]);
|
||||
}, [market.depth?.lastTrade?.price, order.price, order.side, slippage]);
|
||||
|
||||
const estMargin: OrderMargin | null = useOrderMargin({
|
||||
order,
|
||||
@ -72,7 +70,18 @@ export const useFeeDealTicketDetails = (
|
||||
|
||||
const quoteName = market.tradableInstrument.instrument.product.quoteName;
|
||||
|
||||
return {
|
||||
return useMemo(() => {
|
||||
return {
|
||||
market,
|
||||
quoteName,
|
||||
notionalSize,
|
||||
estMargin,
|
||||
estCloseOut,
|
||||
slippage,
|
||||
price,
|
||||
partyData: partyBalance,
|
||||
};
|
||||
}, [
|
||||
market,
|
||||
quoteName,
|
||||
notionalSize,
|
||||
@ -80,12 +89,12 @@ export const useFeeDealTicketDetails = (
|
||||
estCloseOut,
|
||||
slippage,
|
||||
price,
|
||||
partyData: partyBalance,
|
||||
};
|
||||
partyBalance,
|
||||
]);
|
||||
};
|
||||
|
||||
export interface FeeDetails {
|
||||
market: DealTicketMarketFragment;
|
||||
market: MarketDealTicket;
|
||||
quoteName: string;
|
||||
notionalSize: string | null;
|
||||
estMargin: OrderMargin | null;
|
||||
|
11
libs/deal-ticket/src/hooks/use-has-no-balance.tsx
Normal file
11
libs/deal-ticket/src/hooks/use-has-no-balance.tsx
Normal file
@ -0,0 +1,11 @@
|
||||
import { useAccountBalance } from '@vegaprotocol/accounts';
|
||||
import { toBigNum } from '@vegaprotocol/react-helpers';
|
||||
|
||||
export const useHasNoBalance = (assetId: string) => {
|
||||
const { accountBalance, accountDecimals } = useAccountBalance(assetId);
|
||||
const balance =
|
||||
accountBalance && accountDecimals !== null
|
||||
? toBigNum(accountBalance, accountDecimals)
|
||||
: toBigNum('0', 0);
|
||||
return balance.isZero();
|
||||
};
|
@ -2,9 +2,9 @@ import * as React from 'react';
|
||||
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 { PartyBalanceQuery } from './__generated__/PartyBalance';
|
||||
import { useOrderCloseOut } from './use-order-closeout';
|
||||
import type { DealTicketMarketFragment } from '../components/deal-ticket/__generated__/DealTicket';
|
||||
|
||||
jest.mock('@vegaprotocol/wallet', () => ({
|
||||
...jest.requireActual('@vegaprotocol/wallet'),
|
||||
@ -53,7 +53,7 @@ describe('useOrderCloseOut', () => {
|
||||
() =>
|
||||
useOrderCloseOut({
|
||||
order: order as OrderSubmissionBody['orderSubmission'],
|
||||
market: market as DealTicketMarketFragment,
|
||||
market: market as MarketDealTicket,
|
||||
partyData: partyData as PartyBalanceQuery,
|
||||
}),
|
||||
{
|
||||
@ -73,7 +73,7 @@ describe('useOrderCloseOut', () => {
|
||||
...order,
|
||||
side: 'SIDE_SELL',
|
||||
} as OrderSubmissionBody['orderSubmission'],
|
||||
market: market as DealTicketMarketFragment,
|
||||
market: market as MarketDealTicket,
|
||||
partyData: partyData as PartyBalanceQuery,
|
||||
}),
|
||||
{
|
||||
@ -93,7 +93,7 @@ describe('useOrderCloseOut', () => {
|
||||
...order,
|
||||
side: 'SIDE_SELL',
|
||||
} as OrderSubmissionBody['orderSubmission'],
|
||||
market: market as DealTicketMarketFragment,
|
||||
market: market as MarketDealTicket,
|
||||
}),
|
||||
{
|
||||
wrapper: ({ children }: { children: React.ReactNode }) => (
|
||||
|
@ -7,13 +7,13 @@ import { useMarketPositions } from './use-market-positions';
|
||||
import { useMarketDataMarkPrice } from './use-market-data-mark-price';
|
||||
import { usePartyMarketDataQuery } from './__generated__/PartyMarketData';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import type { DealTicketMarketFragment } from '../components/deal-ticket/__generated__/DealTicket';
|
||||
import type { PartyBalanceQuery } from './__generated__/PartyBalance';
|
||||
import { useSettlementAccount } from './use-settlement-account';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
|
||||
interface Props {
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
market: DealTicketMarketFragment;
|
||||
market: MarketDealTicket;
|
||||
partyData?: PartyBalanceQuery;
|
||||
}
|
||||
|
||||
|
@ -1,53 +1,43 @@
|
||||
import { useMemo } from 'react';
|
||||
import compact from 'lodash/compact';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import { toBigNum } from '@vegaprotocol/react-helpers';
|
||||
import type { DealTicketMarketFragment } from '../components/deal-ticket/__generated__/DealTicket';
|
||||
import type { OrderMargin } from './use-order-margin';
|
||||
import { usePartyBalanceQuery } from './__generated__/PartyBalance';
|
||||
import { useSettlementAccount } from './use-settlement-account';
|
||||
import { useAccountBalance } from '@vegaprotocol/accounts';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import { useOrderMargin } from './use-order-margin';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
|
||||
interface Props {
|
||||
market: DealTicketMarketFragment;
|
||||
estMargin: OrderMargin | null;
|
||||
market: MarketDealTicket;
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
}
|
||||
|
||||
export const useOrderMarginValidation = ({ market, estMargin }: Props) => {
|
||||
export const useOrderMarginValidation = ({ market, order }: Props) => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
|
||||
const { data: partyBalance } = usePartyBalanceQuery({
|
||||
variables: { partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
fetchPolicy: 'no-cache',
|
||||
const estMargin: OrderMargin | null = useOrderMargin({
|
||||
order,
|
||||
market,
|
||||
partyId: pubKey || '',
|
||||
});
|
||||
const { id: assetId, decimals: assetDecimals } =
|
||||
market.tradableInstrument.instrument.product.settlementAsset;
|
||||
|
||||
const accounts = compact(partyBalance?.party?.accountsConnection?.edges).map(
|
||||
(e) => e.node
|
||||
);
|
||||
const settlementAccount = useSettlementAccount(
|
||||
market.tradableInstrument.instrument.product.settlementAsset.id,
|
||||
accounts,
|
||||
Schema.AccountType.ACCOUNT_TYPE_GENERAL
|
||||
);
|
||||
const assetDecimals =
|
||||
market.tradableInstrument.instrument.product.settlementAsset.decimals;
|
||||
const balance = settlementAccount
|
||||
? toBigNum(
|
||||
settlementAccount.balance || 0,
|
||||
settlementAccount.asset.decimals || 0
|
||||
)
|
||||
: toBigNum('0', assetDecimals);
|
||||
const { accountBalance, accountDecimals } = useAccountBalance(assetId);
|
||||
const balance =
|
||||
accountBalance && accountDecimals !== null
|
||||
? toBigNum(accountBalance, accountDecimals)
|
||||
: toBigNum('0', assetDecimals);
|
||||
const margin = toBigNum(estMargin?.margin || 0, assetDecimals);
|
||||
const asset = market.tradableInstrument.instrument.product.settlementAsset;
|
||||
|
||||
const memoizedValue = useMemo(() => {
|
||||
// return only simple types (bool, string) for make memo sensible
|
||||
const balanceError = balance.isGreaterThan(0) && balance.isLessThan(margin);
|
||||
const balanceAsString = balance.toString();
|
||||
const marginAsString = margin.toString();
|
||||
return useMemo(() => {
|
||||
return {
|
||||
balance,
|
||||
margin,
|
||||
asset,
|
||||
balance: balanceAsString,
|
||||
margin: marginAsString,
|
||||
balanceError,
|
||||
};
|
||||
}, [balance, margin, asset]);
|
||||
|
||||
return memoizedValue;
|
||||
}, [balanceAsString, marginAsString, balanceError]);
|
||||
};
|
||||
|
@ -2,9 +2,9 @@ import { renderHook } from '@testing-library/react';
|
||||
import { useQuery } from '@apollo/client';
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import type { PositionMargin } from './use-market-positions';
|
||||
import { useOrderMargin } from './use-order-margin';
|
||||
import type { DealTicketMarketFragment } from '../components/deal-ticket/__generated__/DealTicket';
|
||||
|
||||
let mockEstimateData = {
|
||||
estimateOrder: {
|
||||
@ -72,7 +72,7 @@ describe('useOrderMargin', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useOrderMargin({
|
||||
order: order as OrderSubmissionBody['orderSubmission'],
|
||||
market: market as DealTicketMarketFragment,
|
||||
market: market as MarketDealTicket,
|
||||
partyId,
|
||||
})
|
||||
);
|
||||
@ -86,7 +86,7 @@ describe('useOrderMargin', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useOrderMargin({
|
||||
order: order as OrderSubmissionBody['orderSubmission'],
|
||||
market: market as DealTicketMarketFragment,
|
||||
market: market as MarketDealTicket,
|
||||
partyId,
|
||||
})
|
||||
);
|
||||
@ -98,7 +98,7 @@ describe('useOrderMargin', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useOrderMargin({
|
||||
order: order as OrderSubmissionBody['orderSubmission'],
|
||||
market: market as DealTicketMarketFragment,
|
||||
market: market as MarketDealTicket,
|
||||
partyId,
|
||||
})
|
||||
);
|
||||
@ -125,7 +125,7 @@ describe('useOrderMargin', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useOrderMargin({
|
||||
order: order as OrderSubmissionBody['orderSubmission'],
|
||||
market: market as DealTicketMarketFragment,
|
||||
market: market as MarketDealTicket,
|
||||
partyId,
|
||||
})
|
||||
);
|
||||
|
@ -2,15 +2,15 @@ import { BigNumber } from 'bignumber.js';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import { removeDecimal } from '@vegaprotocol/react-helpers';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
import { useMarketPositions } from './use-market-positions';
|
||||
import { useMarketDataMarkPrice } from './use-market-data-mark-price';
|
||||
import type { EstimateOrderQuery } from './__generated__/EstimateOrder';
|
||||
import { useEstimateOrderQuery } from './__generated__/EstimateOrder';
|
||||
import type { DealTicketMarketFragment } from '../components/deal-ticket/__generated__/DealTicket';
|
||||
|
||||
interface Props {
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
market: DealTicketMarketFragment;
|
||||
market: MarketDealTicket;
|
||||
partyId: string;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useLocalStorage } from '@vegaprotocol/react-helpers';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import { useMemo } from 'react';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
|
||||
type OrderData = OrderSubmissionBody['orderSubmission'] | null;
|
||||
|
||||
@ -9,8 +9,12 @@ export const usePersistedOrder = (market: {
|
||||
}): [OrderData, (value: OrderData) => void] => {
|
||||
const [value, setValue] = useLocalStorage(`deal-ticket-order-${market.id}`);
|
||||
const order = value != null ? (JSON.parse(value) as OrderData) : null;
|
||||
const setOrder = useCallback(
|
||||
(order: OrderData) => setValue(JSON.stringify(order)),
|
||||
[setValue]
|
||||
);
|
||||
return useMemo<[OrderData, (value: OrderData) => void]>(
|
||||
() => [order, (order: OrderData) => setValue(JSON.stringify(order))],
|
||||
[order, setValue]
|
||||
() => [order, setOrder],
|
||||
[order, setOrder]
|
||||
);
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import type { DealTicketMarketFragment } from '../components';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
|
||||
export const isMarketInAuction = (market: DealTicketMarketFragment) => {
|
||||
export const isMarketInAuction = (market: MarketDealTicket) => {
|
||||
return [
|
||||
Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
|
||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import type { DealTicketMarketFragment } from '../components';
|
||||
import { MarketModeValidationType } from '../constants';
|
||||
import { isMarketInAuction } from './is-market-in-auction';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
|
||||
export const validateTimeInForce = (market: DealTicketMarketFragment) => {
|
||||
export const validateTimeInForce = (market: MarketDealTicket) => {
|
||||
return (value: Schema.OrderTimeInForce) => {
|
||||
const isMonitoringAuction =
|
||||
market.tradingMode ===
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { Schema } from '@vegaprotocol/types';
|
||||
import type { DealTicketMarketFragment } from '../components';
|
||||
import { MarketModeValidationType } from '../constants';
|
||||
import { isMarketInAuction } from './is-market-in-auction';
|
||||
import type { MarketDealTicket } from '@vegaprotocol/market-list';
|
||||
|
||||
export const validateType = (market: DealTicketMarketFragment) => {
|
||||
export const validateType = (market: MarketDealTicket) => {
|
||||
return (value: Schema.OrderType) => {
|
||||
if (isMarketInAuction(market) && value === Schema.OrderType.TYPE_MARKET) {
|
||||
const isMonitoringAuction =
|
||||
|
@ -3,14 +3,14 @@ import { Schema 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?: string | null, close?: string | null } };
|
||||
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?: string | null, close?: string | null }, 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?: string | null, close?: string | null } } | null };
|
||||
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?: string | null, close?: string | null }, depth: { __typename?: 'MarketDepth', lastTrade?: { __typename?: 'Trade', price: string } | null } } | null };
|
||||
|
||||
export const SingleMarketFieldsFragmentDoc = gql`
|
||||
fragment SingleMarketFields on Market {
|
||||
@ -54,6 +54,11 @@ export const SingleMarketFieldsFragmentDoc = gql`
|
||||
open
|
||||
close
|
||||
}
|
||||
depth {
|
||||
lastTrade {
|
||||
price
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const MarketDocument = gql`
|
||||
|
@ -1,9 +1,14 @@
|
||||
import { makeDataProvider } from '@vegaprotocol/react-helpers';
|
||||
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
|
||||
@ -18,3 +23,19 @@ export const marketProvider = makeDataProvider<
|
||||
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,
|
||||
};
|
||||
});
|
||||
|
@ -39,6 +39,11 @@ fragment SingleMarketFields on Market {
|
||||
open
|
||||
close
|
||||
}
|
||||
depth {
|
||||
lastTrade {
|
||||
price
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query Market($marketId: ID!) {
|
||||
|
Loading…
Reference in New Issue
Block a user