feat(trading): calculate required margin base on open volume, active … (#2957)
Co-authored-by: mattrussell36 <mattrussell36@users.noreply.github.com>
This commit is contained in:
parent
9d3fc04597
commit
6705eb4398
@ -4,9 +4,8 @@ import {
|
|||||||
getMarketExpiryDateFormatted,
|
getMarketExpiryDateFormatted,
|
||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import type { MarketInfoNoCandlesQuery } from '@vegaprotocol/market-info';
|
import type { MarketInfoWithData } from '@vegaprotocol/market-info';
|
||||||
import { MarketInfoTable } from '@vegaprotocol/market-info';
|
import { MarketInfoTable } from '@vegaprotocol/market-info';
|
||||||
import pick from 'lodash/pick';
|
|
||||||
import {
|
import {
|
||||||
MarketStateMapping,
|
MarketStateMapping,
|
||||||
MarketTradingModeMapping,
|
MarketTradingModeMapping,
|
||||||
@ -17,11 +16,7 @@ import BigNumber from 'bignumber.js';
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { Link } from 'react-router-dom';
|
import { Link } from 'react-router-dom';
|
||||||
|
|
||||||
export const MarketDetails = ({
|
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||||
market,
|
|
||||||
}: {
|
|
||||||
market: MarketInfoNoCandlesQuery['market'];
|
|
||||||
}) => {
|
|
||||||
const quoteUnit = market?.tradableInstrument.instrument.product.quoteName;
|
const quoteUnit = market?.tradableInstrument.instrument.product.quoteName;
|
||||||
const assetId = useMemo(
|
const assetId = useMemo(
|
||||||
() => market?.tradableInstrument.instrument.product?.settlementAsset.id,
|
() => market?.tradableInstrument.instrument.product?.settlementAsset.id,
|
||||||
@ -32,7 +27,9 @@ export const MarketDetails = ({
|
|||||||
if (!market) return null;
|
if (!market) return null;
|
||||||
|
|
||||||
const keyDetails = {
|
const keyDetails = {
|
||||||
...pick(market, 'decimalPlaces', 'positionDecimalPlaces', 'tradingMode'),
|
decimalPlaces: market.decimalPlaces,
|
||||||
|
positionDecimalPlaces: market.positionDecimalPlaces,
|
||||||
|
tradingMode: market.tradingMode,
|
||||||
state: MarketStateMapping[market.state],
|
state: MarketStateMapping[market.state],
|
||||||
};
|
};
|
||||||
const assetDecimals =
|
const assetDecimals =
|
||||||
|
@ -12,6 +12,7 @@ export const Proposals = () => {
|
|||||||
|
|
||||||
const { data, loading, error } = useDataProvider({
|
const { data, loading, error } = useDataProvider({
|
||||||
dataProvider: proposalsDataProvider,
|
dataProvider: proposalsDataProvider,
|
||||||
|
variables: {},
|
||||||
});
|
});
|
||||||
|
|
||||||
useDocumentTitle([t('Governance Proposals')]);
|
useDocumentTitle([t('Governance Proposals')]);
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
import { AsyncRenderer, Button } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer, Button } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useMemo, useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { MarketDetails } from '../../components/markets/market-details';
|
import { MarketDetails } from '../../components/markets/market-details';
|
||||||
import { useScrollToLocation } from '../../hooks/scroll-to-location';
|
import { useScrollToLocation } from '../../hooks/scroll-to-location';
|
||||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||||
import compact from 'lodash/compact';
|
import compact from 'lodash/compact';
|
||||||
import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog';
|
import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog';
|
||||||
import { marketInfoNoCandlesDataProvider } from '@vegaprotocol/market-info';
|
import { marketInfoProvider } from '@vegaprotocol/market-info';
|
||||||
import { PageTitle } from '../../components/page-helpers/page-title';
|
import { PageTitle } from '../../components/page-helpers/page-title';
|
||||||
|
|
||||||
export const MarketPage = () => {
|
export const MarketPage = () => {
|
||||||
@ -16,24 +16,17 @@ export const MarketPage = () => {
|
|||||||
|
|
||||||
const { marketId } = useParams<{ marketId: string }>();
|
const { marketId } = useParams<{ marketId: string }>();
|
||||||
|
|
||||||
const variables = useMemo(
|
|
||||||
() => ({
|
|
||||||
marketId,
|
|
||||||
}),
|
|
||||||
[marketId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { data, loading, error } = useDataProvider({
|
const { data, loading, error } = useDataProvider({
|
||||||
dataProvider: marketInfoNoCandlesDataProvider,
|
dataProvider: marketInfoProvider,
|
||||||
skipUpdates: true,
|
skipUpdates: true,
|
||||||
variables,
|
variables: {
|
||||||
|
marketId: marketId || '',
|
||||||
|
skip: !marketId,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
useDocumentTitle(
|
useDocumentTitle(
|
||||||
compact([
|
compact(['Market details', data?.tradableInstrument.instrument.name])
|
||||||
'Market details',
|
|
||||||
data?.market?.tradableInstrument.instrument.name,
|
|
||||||
])
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
const [dialogOpen, setDialogOpen] = useState<boolean>(false);
|
||||||
@ -43,10 +36,10 @@ export const MarketPage = () => {
|
|||||||
<section className="relative">
|
<section className="relative">
|
||||||
<PageTitle
|
<PageTitle
|
||||||
data-testid="markets-heading"
|
data-testid="markets-heading"
|
||||||
title={data?.market?.tradableInstrument.instrument.name || ''}
|
title={data?.tradableInstrument.instrument.name || ''}
|
||||||
actions={
|
actions={
|
||||||
<Button
|
<Button
|
||||||
disabled={!data?.market}
|
disabled={!data}
|
||||||
size="xs"
|
size="xs"
|
||||||
onClick={() => setDialogOpen(true)}
|
onClick={() => setDialogOpen(true)}
|
||||||
>
|
>
|
||||||
@ -60,14 +53,14 @@ export const MarketPage = () => {
|
|||||||
loading={loading}
|
loading={loading}
|
||||||
error={error}
|
error={error}
|
||||||
>
|
>
|
||||||
<MarketDetails market={data?.market} />
|
{data && <MarketDetails market={data} />}
|
||||||
</AsyncRenderer>
|
</AsyncRenderer>
|
||||||
</section>
|
</section>
|
||||||
<JsonViewerDialog
|
<JsonViewerDialog
|
||||||
open={dialogOpen}
|
open={dialogOpen}
|
||||||
onChange={(isOpen) => setDialogOpen(isOpen)}
|
onChange={(isOpen) => setDialogOpen(isOpen)}
|
||||||
title={data?.market?.tradableInstrument.instrument.name || ''}
|
title={data?.tradableInstrument.instrument.name || ''}
|
||||||
content={data?.market}
|
content={data}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -13,6 +13,7 @@ export const MarketsPage = () => {
|
|||||||
|
|
||||||
const { data, loading, error } = useDataProvider({
|
const { data, loading, error } = useDataProvider({
|
||||||
dataProvider: marketsProvider,
|
dataProvider: marketsProvider,
|
||||||
|
variables: undefined,
|
||||||
skipUpdates: true,
|
skipUpdates: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { useMemo } from 'react';
|
|
||||||
import { makeDerivedDataProvider } from '@vegaprotocol/utils';
|
import { makeDerivedDataProvider } from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
@ -43,7 +42,7 @@ const useMarketDetails = (marketId: string | undefined) => {
|
|||||||
const { data, loading, error } = useDataProvider({
|
const { data, loading, error } = useDataProvider({
|
||||||
dataProvider: lpDataProvider,
|
dataProvider: lpDataProvider,
|
||||||
skipUpdates: true,
|
skipUpdates: true,
|
||||||
variables: useMemo(() => ({ marketId }), [marketId]),
|
variables: { marketId: marketId || '' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const liquidityProviders = data?.liquidityProviders || [];
|
const liquidityProviders = data?.liquidityProviders || [];
|
||||||
|
@ -39,14 +39,11 @@ export const Last24hVolume = ({
|
|||||||
[marketId, yTimestamp]
|
[marketId, yTimestamp]
|
||||||
);
|
);
|
||||||
|
|
||||||
const variables24hAgo = useMemo(
|
const variables24hAgo = {
|
||||||
() => ({
|
marketId: marketId,
|
||||||
marketId: marketId,
|
interval: Schema.Interval.INTERVAL_I1D,
|
||||||
interval: Schema.Interval.INTERVAL_I1D,
|
since: yTimestamp,
|
||||||
since: yTimestamp,
|
};
|
||||||
}),
|
|
||||||
[marketId, yTimestamp]
|
|
||||||
);
|
|
||||||
|
|
||||||
const throttledSetCandles = useRef(
|
const throttledSetCandles = useRef(
|
||||||
throttle((data: Candle[]) => {
|
throttle((data: Candle[]) => {
|
||||||
@ -64,7 +61,7 @@ export const Last24hVolume = ({
|
|||||||
[throttledSetCandles]
|
[throttledSetCandles]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data, error } = useDataProvider<Candle[], Candle>({
|
const { data, error } = useDataProvider({
|
||||||
dataProvider: marketCandlesProvider,
|
dataProvider: marketCandlesProvider,
|
||||||
variables: variables,
|
variables: variables,
|
||||||
update,
|
update,
|
||||||
@ -88,7 +85,7 @@ export const Last24hVolume = ({
|
|||||||
[throttledSetVolumeChange]
|
[throttledSetVolumeChange]
|
||||||
);
|
);
|
||||||
|
|
||||||
useDataProvider<Candle[], Candle>({
|
useDataProvider({
|
||||||
dataProvider: marketCandlesProvider,
|
dataProvider: marketCandlesProvider,
|
||||||
update: updateCandle24hAgo,
|
update: updateCandle24hAgo,
|
||||||
variables: variables24hAgo,
|
variables: variables24hAgo,
|
||||||
|
@ -26,20 +26,20 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
|
|||||||
|
|
||||||
it('market price', () => {
|
it('market price', () => {
|
||||||
cy.getByTestId(marketTitle).contains('Market price').click();
|
cy.getByTestId(marketTitle).contains('Market price').click();
|
||||||
validateMarketDataRow(0, 'Mark Price', '0.05749');
|
validateMarketDataRow(0, 'Mark Price', '46,126.90058');
|
||||||
validateMarketDataRow(1, 'Best Bid Price', '6.81765 ');
|
validateMarketDataRow(1, 'Best Bid Price', '44,126.90058 ');
|
||||||
validateMarketDataRow(2, 'Best Offer Price', '6.81769 ');
|
validateMarketDataRow(2, 'Best Offer Price', '48,126.90058 ');
|
||||||
validateMarketDataRow(3, 'Quote Unit', 'BTC');
|
validateMarketDataRow(3, 'Quote Unit', 'BTC');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('market volume displayed', () => {
|
it('market volume displayed', () => {
|
||||||
cy.getByTestId(marketTitle).contains('Market volume').click();
|
cy.getByTestId(marketTitle).contains('Market volume').click();
|
||||||
validateMarketDataRow(0, '24 Hour Volume', '-');
|
validateMarketDataRow(0, '24 Hour Volume', '1');
|
||||||
validateMarketDataRow(1, 'Open Interest', '0');
|
validateMarketDataRow(1, 'Open Interest', '0');
|
||||||
validateMarketDataRow(2, 'Best Bid Volume', '5');
|
validateMarketDataRow(2, 'Best Bid Volume', '1');
|
||||||
validateMarketDataRow(3, 'Best Offer Volume', '1');
|
validateMarketDataRow(3, 'Best Offer Volume', '3');
|
||||||
validateMarketDataRow(4, 'Best Static Bid Volume', '5');
|
validateMarketDataRow(4, 'Best Static Bid Volume', '2');
|
||||||
validateMarketDataRow(5, 'Best Static Offer Volume', '1');
|
validateMarketDataRow(5, 'Best Static Offer Volume', '4');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('insurance pool displayed', () => {
|
it('insurance pool displayed', () => {
|
||||||
@ -149,9 +149,9 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
|
|||||||
.contains(/Liquidity(?! m)/)
|
.contains(/Liquidity(?! m)/)
|
||||||
.click();
|
.click();
|
||||||
|
|
||||||
validateMarketDataRow(0, 'Target Stake', '0.56789 tBTC');
|
validateMarketDataRow(0, 'Target Stake', '10.00 tBTC');
|
||||||
validateMarketDataRow(1, 'Supplied Stake', '0.56767 tBTC');
|
validateMarketDataRow(1, 'Supplied Stake', '0.01 tBTC');
|
||||||
validateMarketDataRow(2, 'Market Value Proxy', '6.77678 tBTC');
|
validateMarketDataRow(2, 'Market Value Proxy', '20.00 tBTC');
|
||||||
|
|
||||||
cy.getByTestId('view-liquidity-link').should(
|
cy.getByTestId('view-liquidity-link').should(
|
||||||
'have.text',
|
'have.text',
|
||||||
@ -163,8 +163,8 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
|
|||||||
cy.getByTestId(marketTitle).contains('Liquidity price range').click();
|
cy.getByTestId(marketTitle).contains('Liquidity price range').click();
|
||||||
|
|
||||||
validateMarketDataRow(0, 'Liquidity Price Range', '2.00% of mid price');
|
validateMarketDataRow(0, 'Liquidity Price Range', '2.00% of mid price');
|
||||||
validateMarketDataRow(1, 'Lowest Price', '0.05634 BTC');
|
validateMarketDataRow(1, 'Lowest Price', '45,204.362 BTC');
|
||||||
validateMarketDataRow(2, 'Highest Price', '0.05864 BTC');
|
validateMarketDataRow(2, 'Highest Price', '47,049.438 BTC');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('oracle displayed', () => {
|
it('oracle displayed', () => {
|
||||||
|
@ -38,7 +38,7 @@ describe('accounts', { tags: '@smoke' }, () => {
|
|||||||
cy.getByTestId('tab-accounts')
|
cy.getByTestId('tab-accounts')
|
||||||
.get(tradingAccountRowId)
|
.get(tradingAccountRowId)
|
||||||
.find('[col-id="deposited"]')
|
.find('[col-id="deposited"]')
|
||||||
.should('have.text', '1,001.00');
|
.should('have.text', '100,001.01');
|
||||||
});
|
});
|
||||||
describe('sorting by ag-grid columns should work well', () => {
|
describe('sorting by ag-grid columns should work well', () => {
|
||||||
it('sorting by asset', () => {
|
it('sorting by asset', () => {
|
||||||
@ -58,24 +58,24 @@ describe('accounts', { tags: '@smoke' }, () => {
|
|||||||
cy.getByTestId('Collateral').click();
|
cy.getByTestId('Collateral').click();
|
||||||
const marketsSortedDefault = [
|
const marketsSortedDefault = [
|
||||||
'1,000.00002',
|
'1,000.00002',
|
||||||
'1,001.00',
|
'100,001.01',
|
||||||
'1,000.01',
|
|
||||||
'1,000.01',
|
'1,000.01',
|
||||||
|
'1,000.00',
|
||||||
'1,000.00001',
|
'1,000.00001',
|
||||||
];
|
];
|
||||||
const marketsSortedAsc = [
|
const marketsSortedAsc = [
|
||||||
|
'1,000.00',
|
||||||
'1,000.00001',
|
'1,000.00001',
|
||||||
'1,000.00002',
|
'1,000.00002',
|
||||||
'1,000.01',
|
'1,000.01',
|
||||||
'1,000.01',
|
'100,001.01',
|
||||||
'1,001.00',
|
|
||||||
];
|
];
|
||||||
const marketsSortedDesc = [
|
const marketsSortedDesc = [
|
||||||
'1,001.00',
|
'100,001.01',
|
||||||
'1,000.01',
|
|
||||||
'1,000.01',
|
'1,000.01',
|
||||||
'1,000.00002',
|
'1,000.00002',
|
||||||
'1,000.00001',
|
'1,000.00001',
|
||||||
|
'1,000.00',
|
||||||
];
|
];
|
||||||
checkSorting(
|
checkSorting(
|
||||||
'deposited',
|
'deposited',
|
||||||
@ -87,9 +87,9 @@ describe('accounts', { tags: '@smoke' }, () => {
|
|||||||
|
|
||||||
it('sorting by used', () => {
|
it('sorting by used', () => {
|
||||||
cy.getByTestId('Collateral').click();
|
cy.getByTestId('Collateral').click();
|
||||||
const marketsSortedDefault = ['0.00', '1.00', '0.01', '0.01', '0.00'];
|
const marketsSortedDefault = ['0.00', '1.01', '0.01', '0.00', '0.00'];
|
||||||
const marketsSortedAsc = ['0.00', '0.00', '0.01', '0.01', '1.00'];
|
const marketsSortedAsc = ['0.00', '0.00', '0.00', '0.01', '1.01'];
|
||||||
const marketsSortedDesc = ['1.00', '0.01', '0.01', '0.00', '0.00'];
|
const marketsSortedDesc = ['1.01', '0.01', '0.00', '0.00', '0.00'];
|
||||||
checkSorting(
|
checkSorting(
|
||||||
'used',
|
'used',
|
||||||
marketsSortedDefault,
|
marketsSortedDefault,
|
||||||
@ -102,24 +102,24 @@ describe('accounts', { tags: '@smoke' }, () => {
|
|||||||
cy.getByTestId('Collateral').click();
|
cy.getByTestId('Collateral').click();
|
||||||
const marketsSortedDefault = [
|
const marketsSortedDefault = [
|
||||||
'1,000.00002',
|
'1,000.00002',
|
||||||
'1,000.00',
|
'100,000.00',
|
||||||
'1,000.00',
|
'1,000.00',
|
||||||
'1,000.00',
|
'1,000.00',
|
||||||
'1,000.00001',
|
'1,000.00001',
|
||||||
];
|
];
|
||||||
const marketsSortedAsc = [
|
const marketsSortedAsc = [
|
||||||
'1,000.00',
|
|
||||||
'1,000.00',
|
'1,000.00',
|
||||||
'1,000.00',
|
'1,000.00',
|
||||||
'1,000.00001',
|
'1,000.00001',
|
||||||
'1,000.00002',
|
'1,000.00002',
|
||||||
|
'100,000.00',
|
||||||
];
|
];
|
||||||
const marketsSortedDesc = [
|
const marketsSortedDesc = [
|
||||||
|
'100,000.00',
|
||||||
'1,000.00002',
|
'1,000.00002',
|
||||||
'1,000.00001',
|
'1,000.00001',
|
||||||
'1,000.00',
|
'1,000.00',
|
||||||
'1,000.00',
|
'1,000.00',
|
||||||
'1,000.00',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
checkSorting(
|
checkSorting(
|
||||||
|
@ -2,7 +2,11 @@ import * as Schema from '@vegaprotocol/types';
|
|||||||
import { aliasGQLQuery, mockConnectWallet } from '@vegaprotocol/cypress';
|
import { aliasGQLQuery, mockConnectWallet } from '@vegaprotocol/cypress';
|
||||||
import { testOrderSubmission } from '../support/order-validation';
|
import { testOrderSubmission } from '../support/order-validation';
|
||||||
import type { OrderSubmission } from '@vegaprotocol/wallet';
|
import type { OrderSubmission } from '@vegaprotocol/wallet';
|
||||||
import { accountsQuery, estimateOrderQuery } from '@vegaprotocol/mock';
|
import {
|
||||||
|
accountsQuery,
|
||||||
|
estimateOrderQuery,
|
||||||
|
amendGeneralAccountBalance,
|
||||||
|
} from '@vegaprotocol/mock';
|
||||||
import { createOrder } from '../support/create-order';
|
import { createOrder } from '../support/create-order';
|
||||||
|
|
||||||
const orderSizeField = 'order-size';
|
const orderSizeField = 'order-size';
|
||||||
@ -583,6 +587,10 @@ describe('suspended market validation', { tags: '@regression' }, () => {
|
|||||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
||||||
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY
|
Schema.AuctionTrigger.AUCTION_TRIGGER_LIQUIDITY
|
||||||
);
|
);
|
||||||
|
const accounts = accountsQuery();
|
||||||
|
cy.mockGQL((req) => {
|
||||||
|
aliasGQLQuery(req, 'Accounts', accounts);
|
||||||
|
});
|
||||||
cy.mockSubscription();
|
cy.mockSubscription();
|
||||||
cy.visit('/#/markets/market-0');
|
cy.visit('/#/markets/market-0');
|
||||||
cy.wait('@Markets');
|
cy.wait('@Markets');
|
||||||
@ -632,30 +640,10 @@ describe('account validation', { tags: '@regression' }, () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.setVegaWallet();
|
cy.setVegaWallet();
|
||||||
cy.mockTradingPage();
|
cy.mockTradingPage();
|
||||||
|
const accounts = accountsQuery();
|
||||||
|
amendGeneralAccountBalance(accounts, 'market-0', '0');
|
||||||
cy.mockGQL((req) => {
|
cy.mockGQL((req) => {
|
||||||
aliasGQLQuery(
|
aliasGQLQuery(req, 'Accounts', accounts);
|
||||||
req,
|
|
||||||
'Accounts',
|
|
||||||
accountsQuery({
|
|
||||||
party: {
|
|
||||||
accountsConnection: {
|
|
||||||
edges: [
|
|
||||||
{
|
|
||||||
node: {
|
|
||||||
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
|
|
||||||
balance: '0',
|
|
||||||
market: null,
|
|
||||||
asset: {
|
|
||||||
__typename: 'Asset',
|
|
||||||
id: 'asset-0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
cy.mockSubscription();
|
cy.mockSubscription();
|
||||||
cy.visit('/#/markets/market-0');
|
cy.visit('/#/markets/market-0');
|
||||||
@ -679,19 +667,13 @@ describe('account validation', { tags: '@regression' }, () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
cy.setVegaWallet();
|
cy.setVegaWallet();
|
||||||
cy.mockTradingPage();
|
cy.mockTradingPage();
|
||||||
|
const accounts = accountsQuery();
|
||||||
|
amendGeneralAccountBalance(accounts, 'market-0', '100000000');
|
||||||
cy.mockGQL((req) => {
|
cy.mockGQL((req) => {
|
||||||
aliasGQLQuery(
|
aliasGQLQuery(req, 'Accounts', accounts);
|
||||||
req,
|
});
|
||||||
'EstimateOrder',
|
cy.mockGQL((req) => {
|
||||||
estimateOrderQuery({
|
aliasGQLQuery(req, 'EstimateOrder', estimateOrderQuery());
|
||||||
estimateOrder: {
|
|
||||||
marginLevels: {
|
|
||||||
__typename: 'MarginLevels',
|
|
||||||
initialLevel: '1000000000',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
cy.mockSubscription();
|
cy.mockSubscription();
|
||||||
cy.visit('/#/markets/market-0');
|
cy.visit('/#/markets/market-0');
|
||||||
@ -707,7 +689,7 @@ describe('account validation', { tags: '@regression' }, () => {
|
|||||||
);
|
);
|
||||||
cy.getByTestId('dealticket-warning-margin').should(
|
cy.getByTestId('dealticket-warning-margin').should(
|
||||||
'contain.text',
|
'contain.text',
|
||||||
'9,999.99 tDAI is currently required. You have only 1,000.00 tDAI available.Deposit tDAI'
|
'You may not have enough margin available to open this position. 2,354.72283 tDAI is currently required. You have only 1,000.01 tDAI available.'
|
||||||
);
|
);
|
||||||
cy.getByTestId('deal-ticket-deposit-dialog-button').click();
|
cy.getByTestId('deal-ticket-deposit-dialog-button').click();
|
||||||
cy.getByTestId('dialog-content')
|
cy.getByTestId('dialog-content')
|
||||||
|
@ -31,7 +31,7 @@ describe('orders list', { tags: '@smoke' }, () => {
|
|||||||
cy.visit('/#/markets/market-0');
|
cy.visit('/#/markets/market-0');
|
||||||
cy.getByTestId('Orders').click();
|
cy.getByTestId('Orders').click();
|
||||||
cy.wait('@Orders').then(() => {
|
cy.wait('@Orders').then(() => {
|
||||||
expect(subscriptionMocks.OrdersUpdate).to.be.calledTwice;
|
expect(subscriptionMocks.OrdersUpdate).to.be.calledThrice;
|
||||||
});
|
});
|
||||||
cy.wait('@Markets');
|
cy.wait('@Markets');
|
||||||
});
|
});
|
||||||
@ -136,7 +136,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
|
|||||||
cy.visit('/#/markets/market-0');
|
cy.visit('/#/markets/market-0');
|
||||||
cy.getByTestId('Orders').click();
|
cy.getByTestId('Orders').click();
|
||||||
cy.wait('@Orders').then(() => {
|
cy.wait('@Orders').then(() => {
|
||||||
expect(subscriptionMocks.OrdersUpdate).to.be.calledTwice;
|
expect(subscriptionMocks.OrdersUpdate).to.be.calledThrice;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
const orderId = '1234567890';
|
const orderId = '1234567890';
|
||||||
@ -354,7 +354,7 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
|
|||||||
cy.visit('/#/markets/market-0');
|
cy.visit('/#/markets/market-0');
|
||||||
cy.getByTestId('Orders').click();
|
cy.getByTestId('Orders').click();
|
||||||
cy.wait('@Orders').then(() => {
|
cy.wait('@Orders').then(() => {
|
||||||
expect(subscriptionMocks.OrdersUpdate).to.be.calledTwice;
|
expect(subscriptionMocks.OrdersUpdate).to.be.calledThrice;
|
||||||
});
|
});
|
||||||
cy.mockVegaWalletTransaction();
|
cy.mockVegaWalletTransaction();
|
||||||
});
|
});
|
||||||
|
@ -164,10 +164,10 @@ describe('positions', { tags: '@smoke' }, () => {
|
|||||||
|
|
||||||
cy.get('[col-id="liquidationPrice"]').should('contain.text', '0'); // liquidation price
|
cy.get('[col-id="liquidationPrice"]').should('contain.text', '0'); // liquidation price
|
||||||
|
|
||||||
cy.get('[col-id="currentLeverage"]').should('contain.text', '138.446.1');
|
cy.get('[col-id="currentLeverage"]').should('contain.text', '2.846.1');
|
||||||
|
|
||||||
cy.get('[col-id="marginAccountBalance"]') // margin allocated
|
cy.get('[col-id="marginAccountBalance"]') // margin allocated
|
||||||
.should('contain.text', '1,000');
|
.should('contain.text', '0.01');
|
||||||
|
|
||||||
cy.get('[col-id="unrealisedPNL"]').each(($unrealisedPnl) => {
|
cy.get('[col-id="unrealisedPNL"]').each(($unrealisedPnl) => {
|
||||||
cy.wrap($unrealisedPnl).invoke('text').should('not.be.empty');
|
cy.wrap($unrealisedPnl).invoke('text').should('not.be.empty');
|
||||||
|
@ -7,13 +7,13 @@ import type { onMessage } from '@vegaprotocol/cypress';
|
|||||||
import type { PartialDeep } from 'type-fest';
|
import type { PartialDeep } from 'type-fest';
|
||||||
import { orderUpdateSubscription } from '@vegaprotocol/mock';
|
import { orderUpdateSubscription } from '@vegaprotocol/mock';
|
||||||
|
|
||||||
let sendOrderUpdate: (data: OrdersUpdateSubscription) => void;
|
const sendOrderUpdate: ((data: OrdersUpdateSubscription) => void)[] = [];
|
||||||
const getOnOrderUpdate = () => {
|
const getOnOrderUpdate = () => {
|
||||||
const onOrderUpdate: onMessage<
|
const onOrderUpdate: onMessage<
|
||||||
OrdersUpdateSubscription,
|
OrdersUpdateSubscription,
|
||||||
OrdersUpdateSubscriptionVariables
|
OrdersUpdateSubscriptionVariables
|
||||||
> = (send) => {
|
> = (send) => {
|
||||||
sendOrderUpdate = send;
|
sendOrderUpdate.push(send);
|
||||||
};
|
};
|
||||||
return onOrderUpdate;
|
return onOrderUpdate;
|
||||||
};
|
};
|
||||||
@ -31,5 +31,5 @@ export function updateOrder(
|
|||||||
if (!sendOrderUpdate) {
|
if (!sendOrderUpdate) {
|
||||||
throw new Error('OrderSub not called');
|
throw new Error('OrderSub not called');
|
||||||
}
|
}
|
||||||
sendOrderUpdate(update);
|
sendOrderUpdate.forEach((send) => send(update));
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,6 @@ import {
|
|||||||
} from '@vegaprotocol/mock';
|
} from '@vegaprotocol/mock';
|
||||||
import type { PartialDeep } from 'type-fest';
|
import type { PartialDeep } from 'type-fest';
|
||||||
import type { MarketDataQuery, MarketsQuery } from '@vegaprotocol/market-list';
|
import type { MarketDataQuery, MarketsQuery } from '@vegaprotocol/market-list';
|
||||||
import type { MarketInfoQuery } from '@vegaprotocol/market-info';
|
|
||||||
|
|
||||||
type MarketPageMockData = {
|
type MarketPageMockData = {
|
||||||
state: Schema.MarketState;
|
state: Schema.MarketState;
|
||||||
@ -69,18 +68,6 @@ const marketsDataOverride = (
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const marketInfoOverride = (
|
|
||||||
data: MarketPageMockData
|
|
||||||
): PartialDeep<MarketInfoQuery> => ({
|
|
||||||
market: {
|
|
||||||
state: data.state,
|
|
||||||
tradingMode: data.tradingMode,
|
|
||||||
data: {
|
|
||||||
trigger: data.trigger,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const mockTradingPage = (
|
const mockTradingPage = (
|
||||||
req: CyHttpMessages.IncomingHttpRequest,
|
req: CyHttpMessages.IncomingHttpRequest,
|
||||||
state: Schema.MarketState = Schema.MarketState.STATE_ACTIVE,
|
state: Schema.MarketState = Schema.MarketState.STATE_ACTIVE,
|
||||||
@ -109,11 +96,7 @@ const mockTradingPage = (
|
|||||||
aliasGQLQuery(req, 'Margins', marginsQuery());
|
aliasGQLQuery(req, 'Margins', marginsQuery());
|
||||||
aliasGQLQuery(req, 'Assets', assetsQuery());
|
aliasGQLQuery(req, 'Assets', assetsQuery());
|
||||||
aliasGQLQuery(req, 'Asset', assetQuery());
|
aliasGQLQuery(req, 'Asset', assetQuery());
|
||||||
aliasGQLQuery(
|
aliasGQLQuery(req, 'MarketInfo', marketInfoQuery());
|
||||||
req,
|
|
||||||
'MarketInfo',
|
|
||||||
marketInfoQuery(marketInfoOverride({ state, tradingMode, trigger }))
|
|
||||||
);
|
|
||||||
aliasGQLQuery(req, 'Trades', tradesQuery());
|
aliasGQLQuery(req, 'Trades', tradesQuery());
|
||||||
aliasGQLQuery(req, 'Chart', chartQuery());
|
aliasGQLQuery(req, 'Chart', chartQuery());
|
||||||
aliasGQLQuery(req, 'Candles', candlesQuery());
|
aliasGQLQuery(req, 'Candles', candlesQuery());
|
||||||
|
@ -12,6 +12,7 @@ export const Home = () => {
|
|||||||
// should be the oldest market that is currently trading in us mode(i.e. not in auction).
|
// should be the oldest market that is currently trading in us mode(i.e. not in auction).
|
||||||
const { data, error, loading } = useDataProvider({
|
const { data, error, loading } = useDataProvider({
|
||||||
dataProvider: marketsWithDataProvider,
|
dataProvider: marketsWithDataProvider,
|
||||||
|
variables: undefined,
|
||||||
});
|
});
|
||||||
const update = useGlobalStore((store) => store.update);
|
const update = useGlobalStore((store) => store.update);
|
||||||
const marketId = useGlobalStore((store) => store.marketId);
|
const marketId = useGlobalStore((store) => store.marketId);
|
||||||
|
@ -47,7 +47,8 @@ export const Liquidity = () => {
|
|||||||
const useReloadLiquidityData = (marketId: string | undefined) => {
|
const useReloadLiquidityData = (marketId: string | undefined) => {
|
||||||
const { reload } = useDataProvider({
|
const { reload } = useDataProvider({
|
||||||
dataProvider: liquidityProvisionsDataProvider,
|
dataProvider: liquidityProvisionsDataProvider,
|
||||||
variables: useMemo(() => ({ marketId }), [marketId]),
|
variables: { marketId: marketId || '' },
|
||||||
|
skip: !marketId,
|
||||||
});
|
});
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const interval = setInterval(reload, 10000);
|
const interval = setInterval(reload, 10000);
|
||||||
@ -77,7 +78,8 @@ export const LiquidityContainer = ({
|
|||||||
const { data, loading, error } = useDataProvider({
|
const { data, loading, error } = useDataProvider({
|
||||||
dataProvider: lpAggregatedDataProvider,
|
dataProvider: lpAggregatedDataProvider,
|
||||||
update,
|
update,
|
||||||
variables: useMemo(() => ({ marketId }), [marketId]),
|
variables: { marketId: marketId || '' },
|
||||||
|
skip: !marketId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const assetDecimalPlaces =
|
const assetDecimalPlaces =
|
||||||
@ -161,7 +163,8 @@ export const LiquidityViewContainer = ({
|
|||||||
} = useDataProvider({
|
} = useDataProvider({
|
||||||
dataProvider: lpAggregatedDataProvider,
|
dataProvider: lpAggregatedDataProvider,
|
||||||
update,
|
update,
|
||||||
variables: useMemo(() => ({ marketId }), [marketId]),
|
variables: { marketId: marketId || '' },
|
||||||
|
skip: !marketId,
|
||||||
});
|
});
|
||||||
|
|
||||||
const targetStake = marketData?.targetStake;
|
const targetStake = marketData?.targetStake;
|
||||||
|
@ -7,10 +7,6 @@ import {
|
|||||||
useThrottledDataProvider,
|
useThrottledDataProvider,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import type {
|
|
||||||
MarketData,
|
|
||||||
MarketDataUpdateFieldsFragment,
|
|
||||||
} from '@vegaprotocol/market-list';
|
|
||||||
|
|
||||||
import { marketProvider, marketDataProvider } from '@vegaprotocol/market-list';
|
import { marketProvider, marketDataProvider } from '@vegaprotocol/market-list';
|
||||||
import { useGlobalStore, usePageTitleStore } from '../../stores';
|
import { useGlobalStore, usePageTitleStore } from '../../stores';
|
||||||
@ -35,13 +31,10 @@ const TitleUpdater = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const pageTitle = usePageTitleStore((store) => store.pageTitle);
|
const pageTitle = usePageTitleStore((store) => store.pageTitle);
|
||||||
const updateTitle = usePageTitleStore((store) => store.updateTitle);
|
const updateTitle = usePageTitleStore((store) => store.updateTitle);
|
||||||
const { data: marketData } = useThrottledDataProvider<
|
const { data: marketData } = useThrottledDataProvider(
|
||||||
MarketData,
|
|
||||||
MarketDataUpdateFieldsFragment
|
|
||||||
>(
|
|
||||||
{
|
{
|
||||||
dataProvider: marketDataProvider,
|
dataProvider: marketDataProvider,
|
||||||
variables: useMemo(() => ({ marketId }), [marketId]),
|
variables: { marketId: marketId || '' },
|
||||||
skip: !marketId,
|
skip: !marketId,
|
||||||
},
|
},
|
||||||
1000
|
1000
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import type { RefObject } from 'react';
|
import type { RefObject } from 'react';
|
||||||
import { useMemo } from 'react';
|
|
||||||
import { useInView } from 'react-intersection-observer';
|
import { useInView } from 'react-intersection-observer';
|
||||||
import { isNumeric } from '@vegaprotocol/utils';
|
import { isNumeric } from '@vegaprotocol/utils';
|
||||||
import {
|
import {
|
||||||
@ -9,7 +8,6 @@ import {
|
|||||||
import { PriceChangeCell } from '@vegaprotocol/datagrid';
|
import { PriceChangeCell } from '@vegaprotocol/datagrid';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import type { CandleClose } from '@vegaprotocol/types';
|
import type { CandleClose } from '@vegaprotocol/types';
|
||||||
import type { Candle } from '@vegaprotocol/market-list';
|
|
||||||
import { marketCandlesProvider } from '@vegaprotocol/market-list';
|
import { marketCandlesProvider } from '@vegaprotocol/market-list';
|
||||||
import { THROTTLE_UPDATE_TIME } from '../constants';
|
import { THROTTLE_UPDATE_TIME } from '../constants';
|
||||||
|
|
||||||
@ -30,19 +28,14 @@ export const Last24hPriceChange = ({
|
|||||||
}: Props) => {
|
}: Props) => {
|
||||||
const [ref, inView] = useInView({ root: inViewRoot?.current });
|
const [ref, inView] = useInView({ root: inViewRoot?.current });
|
||||||
const yesterday = useYesterday();
|
const yesterday = useYesterday();
|
||||||
const variables = useMemo(
|
const { data, error } = useThrottledDataProvider(
|
||||||
() => ({
|
|
||||||
marketId: marketId,
|
|
||||||
interval: Schema.Interval.INTERVAL_I1H,
|
|
||||||
since: new Date(yesterday).toISOString(),
|
|
||||||
}),
|
|
||||||
[marketId, yesterday]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { data, error } = useThrottledDataProvider<Candle[], Candle>(
|
|
||||||
{
|
{
|
||||||
dataProvider: marketCandlesProvider,
|
dataProvider: marketCandlesProvider,
|
||||||
variables,
|
variables: {
|
||||||
|
marketId: marketId || '',
|
||||||
|
interval: Schema.Interval.INTERVAL_I1H,
|
||||||
|
since: new Date(yesterday).toISOString(),
|
||||||
|
},
|
||||||
skip: !marketId || !inView,
|
skip: !marketId || !inView,
|
||||||
},
|
},
|
||||||
THROTTLE_UPDATE_TIME
|
THROTTLE_UPDATE_TIME
|
||||||
|
@ -10,8 +10,6 @@ import {
|
|||||||
useYesterday,
|
useYesterday,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import { useMemo } from 'react';
|
|
||||||
import type { Candle } from '@vegaprotocol/market-list';
|
|
||||||
import { THROTTLE_UPDATE_TIME } from '../constants';
|
import { THROTTLE_UPDATE_TIME } from '../constants';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
@ -32,19 +30,14 @@ export const Last24hVolume = ({
|
|||||||
const yesterday = useYesterday();
|
const yesterday = useYesterday();
|
||||||
const [ref, inView] = useInView({ root: inViewRoot?.current });
|
const [ref, inView] = useInView({ root: inViewRoot?.current });
|
||||||
|
|
||||||
const variables = useMemo(
|
const { data } = useThrottledDataProvider(
|
||||||
() => ({
|
|
||||||
marketId: marketId,
|
|
||||||
interval: Schema.Interval.INTERVAL_I1H,
|
|
||||||
since: new Date(yesterday).toISOString(),
|
|
||||||
}),
|
|
||||||
[marketId, yesterday]
|
|
||||||
);
|
|
||||||
|
|
||||||
const { data } = useThrottledDataProvider<Candle[], Candle>(
|
|
||||||
{
|
{
|
||||||
dataProvider: marketCandlesProvider,
|
dataProvider: marketCandlesProvider,
|
||||||
variables,
|
variables: {
|
||||||
|
marketId: marketId || '',
|
||||||
|
interval: Schema.Interval.INTERVAL_I1H,
|
||||||
|
since: new Date(yesterday).toISOString(),
|
||||||
|
},
|
||||||
skip: !(inView && marketId),
|
skip: !(inView && marketId),
|
||||||
},
|
},
|
||||||
THROTTLE_UPDATE_TIME
|
THROTTLE_UPDATE_TIME
|
||||||
|
@ -4,10 +4,7 @@ import {
|
|||||||
useDataProvider,
|
useDataProvider,
|
||||||
useNetworkParams,
|
useNetworkParams,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import type {
|
import type { MarketData } from '@vegaprotocol/market-list';
|
||||||
MarketData,
|
|
||||||
MarketDataUpdateFieldsFragment,
|
|
||||||
} from '@vegaprotocol/market-list';
|
|
||||||
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
||||||
import { HeaderStat } from '../header';
|
import { HeaderStat } from '../header';
|
||||||
import {
|
import {
|
||||||
@ -70,7 +67,7 @@ export const MarketLiquiditySupplied = ({
|
|||||||
[noUpdate]
|
[noUpdate]
|
||||||
);
|
);
|
||||||
|
|
||||||
useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({
|
useDataProvider({
|
||||||
dataProvider: marketDataProvider,
|
dataProvider: marketDataProvider,
|
||||||
update,
|
update,
|
||||||
variables,
|
variables,
|
||||||
|
@ -1,13 +1,8 @@
|
|||||||
import type { RefObject } from 'react';
|
import type { RefObject } from 'react';
|
||||||
import { useMemo } from 'react';
|
|
||||||
import { useInView } from 'react-intersection-observer';
|
import { useInView } from 'react-intersection-observer';
|
||||||
import { addDecimalsFormatNumber, isNumeric } from '@vegaprotocol/utils';
|
import { addDecimalsFormatNumber, isNumeric } from '@vegaprotocol/utils';
|
||||||
import { useThrottledDataProvider } from '@vegaprotocol/react-helpers';
|
import { useThrottledDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
import { PriceCell } from '@vegaprotocol/datagrid';
|
import { PriceCell } from '@vegaprotocol/datagrid';
|
||||||
import type {
|
|
||||||
MarketData,
|
|
||||||
MarketDataUpdateFieldsFragment,
|
|
||||||
} from '@vegaprotocol/market-list';
|
|
||||||
import { marketDataProvider } from '@vegaprotocol/market-list';
|
import { marketDataProvider } from '@vegaprotocol/market-list';
|
||||||
import { THROTTLE_UPDATE_TIME } from '../constants';
|
import { THROTTLE_UPDATE_TIME } from '../constants';
|
||||||
|
|
||||||
@ -27,15 +22,10 @@ export const MarketMarkPrice = ({
|
|||||||
asPriceCell,
|
asPriceCell,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const [ref, inView] = useInView({ root: inViewRoot?.current });
|
const [ref, inView] = useInView({ root: inViewRoot?.current });
|
||||||
const variables = useMemo(() => ({ marketId }), [marketId]);
|
const { data } = useThrottledDataProvider(
|
||||||
|
|
||||||
const { data } = useThrottledDataProvider<
|
|
||||||
MarketData,
|
|
||||||
MarketDataUpdateFieldsFragment
|
|
||||||
>(
|
|
||||||
{
|
{
|
||||||
dataProvider: marketDataProvider,
|
dataProvider: marketDataProvider,
|
||||||
variables,
|
variables: { marketId: marketId || '' },
|
||||||
skip: !inView,
|
skip: !inView,
|
||||||
},
|
},
|
||||||
THROTTLE_UPDATE_TIME
|
THROTTLE_UPDATE_TIME
|
||||||
|
@ -1,15 +1,11 @@
|
|||||||
import throttle from 'lodash/throttle';
|
import throttle from 'lodash/throttle';
|
||||||
import type {
|
import type { MarketData, Market } from '@vegaprotocol/market-list';
|
||||||
MarketData,
|
|
||||||
MarketDataUpdateFieldsFragment,
|
|
||||||
Market,
|
|
||||||
} from '@vegaprotocol/market-list';
|
|
||||||
import { marketDataProvider } from '@vegaprotocol/market-list';
|
import { marketDataProvider } from '@vegaprotocol/market-list';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import { HeaderStat } from '../header';
|
import { HeaderStat } from '../header';
|
||||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
import { useCallback, useRef, useState } from 'react';
|
||||||
import * as constants from '../constants';
|
import * as constants from '../constants';
|
||||||
|
|
||||||
export const MarketState = ({ market }: { market: Market | null }) => {
|
export const MarketState = ({ market }: { market: Market | null }) => {
|
||||||
@ -33,14 +29,10 @@ export const MarketState = ({ market }: { market: Market | null }) => {
|
|||||||
[throttledSetMarketState]
|
[throttledSetMarketState]
|
||||||
);
|
);
|
||||||
|
|
||||||
const variables = useMemo(
|
useDataProvider({
|
||||||
() => ({ marketId: market?.id || '' }),
|
|
||||||
[market?.id]
|
|
||||||
);
|
|
||||||
useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({
|
|
||||||
dataProvider: marketDataProvider,
|
dataProvider: marketDataProvider,
|
||||||
update,
|
update,
|
||||||
variables,
|
variables: { marketId: market?.id || '' },
|
||||||
skip: !market?.id,
|
skip: !market?.id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,24 +1,16 @@
|
|||||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
import { useCallback, useRef, useState } from 'react';
|
||||||
import throttle from 'lodash/throttle';
|
import throttle from 'lodash/throttle';
|
||||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
import type {
|
import type { MarketData } from '@vegaprotocol/market-list';
|
||||||
MarketData,
|
|
||||||
MarketDataUpdateFieldsFragment,
|
|
||||||
} from '@vegaprotocol/market-list';
|
|
||||||
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
||||||
import { HeaderStat } from '../header';
|
import { HeaderStat } from '../header';
|
||||||
import * as constants from '../constants';
|
import * as constants from '../constants';
|
||||||
|
|
||||||
export const MarketVolume = ({ marketId }: { marketId: string }) => {
|
export const MarketVolume = ({ marketId }: { marketId: string }) => {
|
||||||
const [marketVolume, setMarketVolume] = useState<string>('-');
|
const [marketVolume, setMarketVolume] = useState<string>('-');
|
||||||
const variables = useMemo(
|
const variables = { marketId };
|
||||||
() => ({
|
|
||||||
marketId: marketId,
|
|
||||||
}),
|
|
||||||
[marketId]
|
|
||||||
);
|
|
||||||
const { data } = useDataProvider({
|
const { data } = useDataProvider({
|
||||||
dataProvider: marketProvider,
|
dataProvider: marketProvider,
|
||||||
variables,
|
variables,
|
||||||
@ -46,7 +38,7 @@ export const MarketVolume = ({ marketId }: { marketId: string }) => {
|
|||||||
[data?.positionDecimalPlaces, throttledSetMarketVolume]
|
[data?.positionDecimalPlaces, throttledSetMarketVolume]
|
||||||
);
|
);
|
||||||
|
|
||||||
useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({
|
useDataProvider({
|
||||||
dataProvider: marketDataProvider,
|
dataProvider: marketDataProvider,
|
||||||
update,
|
update,
|
||||||
variables,
|
variables,
|
||||||
|
@ -106,14 +106,13 @@ export const SelectMarketPopover = ({
|
|||||||
loading: marketsLoading,
|
loading: marketsLoading,
|
||||||
reload: marketListReload,
|
reload: marketListReload,
|
||||||
} = useMarketList();
|
} = useMarketList();
|
||||||
const variables = useMemo(() => ({ partyId: pubKey }), [pubKey]);
|
|
||||||
const {
|
const {
|
||||||
data: positions,
|
data: positions,
|
||||||
loading: positionsLoading,
|
loading: positionsLoading,
|
||||||
reload,
|
reload,
|
||||||
} = useDataProvider({
|
} = useDataProvider({
|
||||||
dataProvider: positionsDataProvider,
|
dataProvider: positionsDataProvider,
|
||||||
variables,
|
variables: { partyId: pubKey || '' },
|
||||||
skip: !pubKey,
|
skip: !pubKey,
|
||||||
});
|
});
|
||||||
const onSelectMarket = useCallback(
|
const onSelectMarket = useCallback(
|
||||||
|
@ -20,6 +20,7 @@ export const WelcomeDialog = () => {
|
|||||||
const [riskAccepted] = useLocalStorage(constants.RISK_ACCEPTED_KEY);
|
const [riskAccepted] = useLocalStorage(constants.RISK_ACCEPTED_KEY);
|
||||||
const { data } = useDataProvider({
|
const { data } = useDataProvider({
|
||||||
dataProvider: activeMarketsProvider,
|
dataProvider: activeMarketsProvider,
|
||||||
|
variables: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { update, shouldDisplayWelcomeDialog } = useGlobalStore((store) => ({
|
const { update, shouldDisplayWelcomeDialog } = useGlobalStore((store) => ({
|
||||||
|
@ -18,6 +18,7 @@ import type {
|
|||||||
AccountFieldsFragment,
|
AccountFieldsFragment,
|
||||||
AccountsQuery,
|
AccountsQuery,
|
||||||
AccountEventsSubscription,
|
AccountEventsSubscription,
|
||||||
|
AccountsQueryVariables,
|
||||||
} from './__generated__/Accounts';
|
} from './__generated__/Accounts';
|
||||||
import type { Market } from '@vegaprotocol/market-list';
|
import type { Market } from '@vegaprotocol/market-list';
|
||||||
import type { Asset } from '@vegaprotocol/assets';
|
import type { Asset } from '@vegaprotocol/assets';
|
||||||
@ -85,7 +86,8 @@ export const accountsOnlyDataProvider = makeDataProvider<
|
|||||||
AccountsQuery,
|
AccountsQuery,
|
||||||
AccountFieldsFragment[],
|
AccountFieldsFragment[],
|
||||||
AccountEventsSubscription,
|
AccountEventsSubscription,
|
||||||
AccountEventsSubscription['accounts']
|
AccountEventsSubscription['accounts'],
|
||||||
|
AccountsQueryVariables
|
||||||
>({
|
>({
|
||||||
query: AccountsDocument,
|
query: AccountsDocument,
|
||||||
subscriptionQuery: AccountEventsDocument,
|
subscriptionQuery: AccountEventsDocument,
|
||||||
@ -159,8 +161,16 @@ const getAssetAccountAggregation = (
|
|||||||
return { ...balanceAccount, breakdown };
|
return { ...balanceAccount, breakdown };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const accountsDataProvider = makeDerivedDataProvider<Account[], never>(
|
export const accountsDataProvider = makeDerivedDataProvider<
|
||||||
[accountsOnlyDataProvider, marketsProvider, assetsProvider],
|
Account[],
|
||||||
|
never,
|
||||||
|
AccountsQueryVariables
|
||||||
|
>(
|
||||||
|
[
|
||||||
|
accountsOnlyDataProvider,
|
||||||
|
(callback, client) => marketsProvider(callback, client, undefined),
|
||||||
|
(callback, client) => assetsProvider(callback, client, undefined),
|
||||||
|
],
|
||||||
([accounts, markets, assets]): Account[] | null => {
|
([accounts, markets, assets]): Account[] | null => {
|
||||||
return accounts
|
return accounts
|
||||||
? accounts
|
? accounts
|
||||||
@ -194,7 +204,8 @@ export const accountsDataProvider = makeDerivedDataProvider<Account[], never>(
|
|||||||
|
|
||||||
export const aggregatedAccountsDataProvider = makeDerivedDataProvider<
|
export const aggregatedAccountsDataProvider = makeDerivedDataProvider<
|
||||||
AccountFields[],
|
AccountFields[],
|
||||||
never
|
never,
|
||||||
|
AccountsQueryVariables
|
||||||
>(
|
>(
|
||||||
[accountsDataProvider],
|
[accountsDataProvider],
|
||||||
(parts) => parts[0] && getAccountData(parts[0] as Account[])
|
(parts) => parts[0] && getAccountData(parts[0] as Account[])
|
||||||
|
@ -31,10 +31,7 @@ export const AccountManager = ({
|
|||||||
}: AccountManagerProps) => {
|
}: AccountManagerProps) => {
|
||||||
const gridRef = useRef<AgGridReact | null>(null);
|
const gridRef = useRef<AgGridReact | null>(null);
|
||||||
const variables = useMemo(() => ({ partyId }), [partyId]);
|
const variables = useMemo(() => ({ partyId }), [partyId]);
|
||||||
const { data, loading, error, reload } = useDataProvider<
|
const { data, loading, error, reload } = useDataProvider({
|
||||||
AccountFields[],
|
|
||||||
never
|
|
||||||
>({
|
|
||||||
dataProvider: aggregatedAccountsDataProvider,
|
dataProvider: aggregatedAccountsDataProvider,
|
||||||
variables,
|
variables,
|
||||||
});
|
});
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
import { forwardRef, useMemo, useState } from 'react';
|
import { forwardRef, useMemo, useState } from 'react';
|
||||||
import { addDecimalsFormatNumber, isNumeric } from '@vegaprotocol/utils';
|
import {
|
||||||
|
addDecimalsFormatNumber,
|
||||||
|
isNumeric,
|
||||||
|
toBigNum,
|
||||||
|
} from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import type {
|
import type {
|
||||||
VegaICellRendererParams,
|
VegaICellRendererParams,
|
||||||
VegaValueFormatterParams,
|
VegaValueFormatterParams,
|
||||||
|
VegaValueGetterParams,
|
||||||
} from '@vegaprotocol/datagrid';
|
} from '@vegaprotocol/datagrid';
|
||||||
import { Button, ButtonLink, Dialog } from '@vegaprotocol/ui-toolkit';
|
import { Button, ButtonLink, Dialog } from '@vegaprotocol/ui-toolkit';
|
||||||
import { TooltipCellComponent } from '@vegaprotocol/ui-toolkit';
|
import { TooltipCellComponent } from '@vegaprotocol/ui-toolkit';
|
||||||
@ -117,17 +122,23 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
|||||||
headerTooltip={t(
|
headerTooltip={t(
|
||||||
'This is the total amount of collateral used plus the amount available in your general account.'
|
'This is the total amount of collateral used plus the amount available in your general account.'
|
||||||
)}
|
)}
|
||||||
|
valueGetter={({
|
||||||
|
data,
|
||||||
|
}: VegaValueGetterParams<AccountFields, 'deposited'>) => {
|
||||||
|
return !data?.deposited
|
||||||
|
? undefined
|
||||||
|
: toBigNum(data.deposited, data.asset.decimals).toNumber();
|
||||||
|
}}
|
||||||
maxWidth={300}
|
maxWidth={300}
|
||||||
cellRenderer={({
|
cellRenderer={({
|
||||||
data,
|
data,
|
||||||
value,
|
|
||||||
node,
|
node,
|
||||||
}: VegaICellRendererParams<AccountFields, 'deposited'>) => {
|
}: VegaICellRendererParams<AccountFields, 'deposited'>) => {
|
||||||
const valueFormatted =
|
const valueFormatted =
|
||||||
data &&
|
data &&
|
||||||
data.asset &&
|
data.asset &&
|
||||||
isNumeric(value) &&
|
isNumeric(data.deposited) &&
|
||||||
addDecimalsFormatNumber(value, data.asset.decimals);
|
addDecimalsFormatNumber(data.deposited, data.asset.decimals);
|
||||||
return node.rowPinned ? (
|
return node.rowPinned ? (
|
||||||
<CenteredGridCellWrapper className="h-[30px] justify-end">
|
<CenteredGridCellWrapper className="h-[30px] justify-end">
|
||||||
{valueFormatted}
|
{valueFormatted}
|
||||||
@ -144,17 +155,23 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
|||||||
headerTooltip={t(
|
headerTooltip={t(
|
||||||
'This is the amount of collateral used from your general account.'
|
'This is the amount of collateral used from your general account.'
|
||||||
)}
|
)}
|
||||||
|
valueGetter={({
|
||||||
|
data,
|
||||||
|
}: VegaValueGetterParams<AccountFields, 'used'>) => {
|
||||||
|
return !data?.used
|
||||||
|
? undefined
|
||||||
|
: toBigNum(data.used, data.asset.decimals).toNumber();
|
||||||
|
}}
|
||||||
maxWidth={300}
|
maxWidth={300}
|
||||||
cellRenderer={({
|
cellRenderer={({
|
||||||
data,
|
data,
|
||||||
value,
|
|
||||||
node,
|
node,
|
||||||
}: VegaICellRendererParams<AccountFields, 'used'>) => {
|
}: VegaICellRendererParams<AccountFields, 'used'>) => {
|
||||||
const valueFormatted =
|
const valueFormatted =
|
||||||
data &&
|
data &&
|
||||||
data.asset &&
|
data.asset &&
|
||||||
isNumeric(value) &&
|
isNumeric(data.used) &&
|
||||||
addDecimalsFormatNumber(value, data.asset.decimals);
|
addDecimalsFormatNumber(data.used, data.asset.decimals);
|
||||||
return node.rowPinned ? (
|
return node.rowPinned ? (
|
||||||
<CenteredGridCellWrapper className="h-[30px] justify-end">
|
<CenteredGridCellWrapper className="h-[30px] justify-end">
|
||||||
{valueFormatted}
|
{valueFormatted}
|
||||||
@ -171,26 +188,31 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
|||||||
headerTooltip={t(
|
headerTooltip={t(
|
||||||
'This is the amount of collateral available in your general account.'
|
'This is the amount of collateral available in your general account.'
|
||||||
)}
|
)}
|
||||||
|
valueGetter={({
|
||||||
|
data,
|
||||||
|
}: VegaValueGetterParams<AccountFields, 'available'>) => {
|
||||||
|
return !data?.available
|
||||||
|
? undefined
|
||||||
|
: toBigNum(data.available, data.asset.decimals).toNumber();
|
||||||
|
}}
|
||||||
valueFormatter={({
|
valueFormatter={({
|
||||||
value,
|
|
||||||
data,
|
data,
|
||||||
}: VegaValueFormatterParams<AccountFields, 'available'>) =>
|
}: VegaValueFormatterParams<AccountFields, 'available'>) =>
|
||||||
data &&
|
data &&
|
||||||
data.asset &&
|
data.asset &&
|
||||||
isNumeric(value) &&
|
isNumeric(data.available) &&
|
||||||
addDecimalsFormatNumber(value, data.asset.decimals)
|
addDecimalsFormatNumber(data.available, data.asset.decimals)
|
||||||
}
|
}
|
||||||
maxWidth={300}
|
maxWidth={300}
|
||||||
cellRenderer={({
|
cellRenderer={({
|
||||||
data,
|
data,
|
||||||
value,
|
|
||||||
node,
|
node,
|
||||||
}: VegaICellRendererParams<AccountFields, 'available'>) => {
|
}: VegaICellRendererParams<AccountFields, 'available'>) => {
|
||||||
const valueFormatted =
|
const valueFormatted =
|
||||||
data &&
|
data &&
|
||||||
data.asset &&
|
data.asset &&
|
||||||
isNumeric(value) &&
|
isNumeric(data.available) &&
|
||||||
addDecimalsFormatNumber(value, data.asset.decimals);
|
addDecimalsFormatNumber(data.available, data.asset.decimals);
|
||||||
return node.rowPinned ? (
|
return node.rowPinned ? (
|
||||||
<CenteredGridCellWrapper className="h-[30px] justify-end">
|
<CenteredGridCellWrapper className="h-[30px] justify-end">
|
||||||
{valueFormatted}
|
{valueFormatted}
|
||||||
|
@ -43,10 +43,6 @@ export const accountFields: AccountFieldsFragment[] = [
|
|||||||
__typename: 'AccountBalance',
|
__typename: 'AccountBalance',
|
||||||
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
|
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||||
balance: '100000000',
|
balance: '100000000',
|
||||||
market: {
|
|
||||||
id: 'market-0',
|
|
||||||
__typename: 'Market',
|
|
||||||
},
|
|
||||||
asset: {
|
asset: {
|
||||||
__typename: 'Asset',
|
__typename: 'Asset',
|
||||||
id: 'asset-id-2',
|
id: 'asset-id-2',
|
||||||
@ -75,7 +71,7 @@ export const accountFields: AccountFieldsFragment[] = [
|
|||||||
},
|
},
|
||||||
asset: {
|
asset: {
|
||||||
__typename: 'Asset',
|
__typename: 'Asset',
|
||||||
id: 'asset-id-2',
|
id: 'asset-0',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -94,7 +90,7 @@ export const accountFields: AccountFieldsFragment[] = [
|
|||||||
{
|
{
|
||||||
__typename: 'AccountBalance',
|
__typename: 'AccountBalance',
|
||||||
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
|
type: Schema.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||||
balance: '100000000',
|
balance: '10000000000',
|
||||||
market: null,
|
market: null,
|
||||||
asset: {
|
asset: {
|
||||||
__typename: 'Asset',
|
__typename: 'Asset',
|
||||||
@ -141,3 +137,25 @@ export const accountEventsSubscription = (
|
|||||||
};
|
};
|
||||||
return merge(defaultResult, override);
|
return merge(defaultResult, override);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const amendGeneralAccountBalance = (
|
||||||
|
accounts: AccountsQuery,
|
||||||
|
marketId: string,
|
||||||
|
balance: string
|
||||||
|
) => {
|
||||||
|
if (accounts.party?.accountsConnection?.edges) {
|
||||||
|
const marginAccount = accounts.party.accountsConnection.edges.find(
|
||||||
|
(edge) => edge?.node.market?.id === marketId
|
||||||
|
);
|
||||||
|
if (marginAccount) {
|
||||||
|
const generalAccount = accounts.party.accountsConnection.edges.find(
|
||||||
|
(edge) =>
|
||||||
|
edge?.node.asset.id === marginAccount.node.asset.id &&
|
||||||
|
!edge?.node.market
|
||||||
|
);
|
||||||
|
if (generalAccount) {
|
||||||
|
generalAccount.node.balance = balance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -20,7 +20,7 @@ export const TransferContainer = () => {
|
|||||||
const { param } = useNetworkParam(NetworkParams.transfer_fee_factor);
|
const { param } = useNetworkParam(NetworkParams.transfer_fee_factor);
|
||||||
const { data } = useDataProvider({
|
const { data } = useDataProvider({
|
||||||
dataProvider: accountsDataProvider,
|
dataProvider: accountsDataProvider,
|
||||||
variables: { partyId: pubKey },
|
variables: { partyId: pubKey || '' },
|
||||||
skip: !pubKey,
|
skip: !pubKey,
|
||||||
});
|
});
|
||||||
const create = useVegaTransactionStore((store) => store.create);
|
const create = useVegaTransactionStore((store) => store.create);
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
import { makeDataProvider } from '@vegaprotocol/utils';
|
import { makeDataProvider } from '@vegaprotocol/utils';
|
||||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
import { useMemo } from 'react';
|
|
||||||
|
|
||||||
import type { AssetQuery, AssetFieldsFragment } from './__generated__/Asset';
|
import type {
|
||||||
|
AssetQuery,
|
||||||
|
AssetFieldsFragment,
|
||||||
|
AssetQueryVariables,
|
||||||
|
} from './__generated__/Asset';
|
||||||
import { AssetDocument } from './__generated__/Asset';
|
import { AssetDocument } from './__generated__/Asset';
|
||||||
|
|
||||||
export type Asset = AssetFieldsFragment;
|
export type Asset = AssetFieldsFragment;
|
||||||
@ -15,21 +18,21 @@ export const getData = (responseData: AssetQuery | null | undefined) => {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const assetProvider = makeDataProvider<AssetQuery, Asset, never, never>({
|
export const assetProvider = makeDataProvider<
|
||||||
|
AssetQuery,
|
||||||
|
Asset,
|
||||||
|
never,
|
||||||
|
never,
|
||||||
|
AssetQueryVariables
|
||||||
|
>({
|
||||||
query: AssetDocument,
|
query: AssetDocument,
|
||||||
getData,
|
getData,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const useAssetDataProvider = (assetId: string) => {
|
export const useAssetDataProvider = (assetId: string) => {
|
||||||
const variables = useMemo(
|
|
||||||
() => ({
|
|
||||||
assetId,
|
|
||||||
}),
|
|
||||||
[assetId]
|
|
||||||
);
|
|
||||||
return useDataProvider({
|
return useDataProvider({
|
||||||
dataProvider: assetProvider,
|
dataProvider: assetProvider,
|
||||||
variables,
|
variables: { assetId: assetId || '' },
|
||||||
skip: !assetId,
|
skip: !assetId,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -40,4 +40,5 @@ export const enabledAssetsProvider = makeDerivedDataProvider<
|
|||||||
export const useAssetsDataProvider = () =>
|
export const useAssetsDataProvider = () =>
|
||||||
useDataProvider({
|
useDataProvider({
|
||||||
dataProvider: assetsProvider,
|
dataProvider: assetsProvider,
|
||||||
|
variables: undefined,
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { formatNumber } from '@vegaprotocol/utils';
|
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { Notification, Intent } from '@vegaprotocol/ui-toolkit';
|
import { Notification, Intent } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useDepositDialog } from '@vegaprotocol/deposits';
|
import { useDepositDialog } from '@vegaprotocol/deposits';
|
||||||
@ -19,14 +19,14 @@ export const MarginWarning = ({ margin, balance, asset }: Props) => {
|
|||||||
<Notification
|
<Notification
|
||||||
intent={Intent.Warning}
|
intent={Intent.Warning}
|
||||||
testId="dealticket-warning-margin"
|
testId="dealticket-warning-margin"
|
||||||
message={`You may not have enough margin available to open this position. ${formatNumber(
|
message={`You may not have enough margin available to open this position. ${addDecimalsFormatNumber(
|
||||||
margin,
|
margin,
|
||||||
asset.decimals
|
asset.decimals
|
||||||
)} ${asset.symbol} ${t(
|
)} ${asset.symbol} ${t(
|
||||||
'is currently required. You have only'
|
'is currently required. You have only'
|
||||||
)} ${formatNumber(balance, asset.decimals)} ${asset.symbol} ${t(
|
)} ${addDecimalsFormatNumber(balance, asset.decimals)} ${
|
||||||
'available.'
|
asset.symbol
|
||||||
)}`}
|
} ${t('available.')}`}
|
||||||
buttonProps={{
|
buttonProps={{
|
||||||
text: t(`Deposit ${asset.symbol}`),
|
text: t(`Deposit ${asset.symbol}`),
|
||||||
action: () => openDepositDialog(asset.id),
|
action: () => openDepositDialog(asset.id),
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { useMemo } from 'react';
|
|
||||||
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import { useThrottledDataProvider } from '@vegaprotocol/react-helpers';
|
import { useThrottledDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
@ -29,7 +28,7 @@ export const DealTicketContainer = ({
|
|||||||
} = useThrottledDataProvider(
|
} = useThrottledDataProvider(
|
||||||
{
|
{
|
||||||
dataProvider: marketDataProvider,
|
dataProvider: marketDataProvider,
|
||||||
variables: useMemo(() => ({ marketId }), [marketId]),
|
variables: { marketId },
|
||||||
},
|
},
|
||||||
1000
|
1000
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
import { useMemo } from 'react';
|
|
||||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||||
import type { Market, MarketData } from '@vegaprotocol/market-list';
|
import type { Market, MarketData } from '@vegaprotocol/market-list';
|
||||||
import {
|
import {
|
||||||
@ -12,22 +11,51 @@ interface DealTicketFeeDetailsProps {
|
|||||||
order: OrderSubmissionBody['orderSubmission'];
|
order: OrderSubmissionBody['orderSubmission'];
|
||||||
market: Market;
|
market: Market;
|
||||||
marketData: MarketData;
|
marketData: MarketData;
|
||||||
|
margin: string;
|
||||||
|
totalMargin: string;
|
||||||
|
balance: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface DealTicketFeeDetails {
|
export interface DealTicketFeeDetailProps {
|
||||||
label: string;
|
label: string;
|
||||||
value?: string | number | null;
|
value?: string | number | null;
|
||||||
labelDescription?: string | ReactNode;
|
labelDescription?: string | ReactNode;
|
||||||
symbol?: string;
|
symbol?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const DealTicketFeeDetail = ({
|
||||||
|
label,
|
||||||
|
value,
|
||||||
|
labelDescription,
|
||||||
|
symbol,
|
||||||
|
}: DealTicketFeeDetailProps) => (
|
||||||
|
<div className="text-xs mt-2 flex justify-between items-center gap-4 flex-wrap">
|
||||||
|
<div>
|
||||||
|
<Tooltip description={labelDescription}>
|
||||||
|
<div>{label}</div>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
<div className="text-neutral-500 dark:text-neutral-300">{`${value ?? '-'} ${
|
||||||
|
symbol || ''
|
||||||
|
}`}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
export const DealTicketFeeDetails = ({
|
export const DealTicketFeeDetails = ({
|
||||||
order,
|
order,
|
||||||
market,
|
market,
|
||||||
marketData,
|
marketData,
|
||||||
|
margin,
|
||||||
|
totalMargin,
|
||||||
|
balance,
|
||||||
}: DealTicketFeeDetailsProps) => {
|
}: DealTicketFeeDetailsProps) => {
|
||||||
const feeDetails = useFeeDealTicketDetails(order, market, marketData);
|
const feeDetails = useFeeDealTicketDetails(order, market, marketData);
|
||||||
const details = useMemo(() => getFeeDetailsValues(feeDetails), [feeDetails]);
|
const details = getFeeDetailsValues({
|
||||||
|
...feeDetails,
|
||||||
|
margin,
|
||||||
|
totalMargin,
|
||||||
|
balance,
|
||||||
|
});
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{details.map(({ label, value, labelDescription, symbol }) => (
|
{details.map(({ label, value, labelDescription, symbol }) => (
|
||||||
|
@ -21,8 +21,7 @@ import {
|
|||||||
Intent,
|
Intent,
|
||||||
Notification,
|
Notification,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import { useOrderMarginValidation } from '../../hooks/use-order-margin-validation';
|
|
||||||
import { MarginWarning } from '../deal-ticket-validation/margin-warning';
|
|
||||||
import {
|
import {
|
||||||
validateExpiration,
|
validateExpiration,
|
||||||
validateMarketState,
|
validateMarketState,
|
||||||
@ -32,11 +31,16 @@ import {
|
|||||||
} from '../../utils';
|
} from '../../utils';
|
||||||
import { ZeroBalanceError } from '../deal-ticket-validation/zero-balance-error';
|
import { ZeroBalanceError } from '../deal-ticket-validation/zero-balance-error';
|
||||||
import { SummaryValidationType } from '../../constants';
|
import { SummaryValidationType } from '../../constants';
|
||||||
import { useHasNoBalance } from '../../hooks/use-has-no-balance';
|
import { useInitialMargin } from '../../hooks/use-initial-margin';
|
||||||
import type { Market, MarketData } from '@vegaprotocol/market-list';
|
import type { Market, MarketData } from '@vegaprotocol/market-list';
|
||||||
|
import { MarginWarning } from '../deal-ticket-validation/margin-warning';
|
||||||
|
import {
|
||||||
|
useMarketAccountBalance,
|
||||||
|
useAccountBalance,
|
||||||
|
} from '@vegaprotocol/accounts';
|
||||||
|
|
||||||
import { OrderTimeInForce, OrderType } from '@vegaprotocol/types';
|
import { OrderTimeInForce, OrderType } from '@vegaprotocol/types';
|
||||||
import { useOrderForm } from '../../hooks/use-order-form';
|
import { useOrderForm } from '../../hooks/use-order-form';
|
||||||
import type { OrderObj } from '@vegaprotocol/orders';
|
|
||||||
|
|
||||||
export interface DealTicketProps {
|
export interface DealTicketProps {
|
||||||
market: Market;
|
market: Market;
|
||||||
@ -67,17 +71,41 @@ export const DealTicket = ({
|
|||||||
update,
|
update,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
} = useOrderForm(market.id);
|
} = useOrderForm(market.id);
|
||||||
const marketStateError = validateMarketState(marketData.marketState);
|
const asset = market.tradableInstrument.instrument.product.settlementAsset;
|
||||||
const hasNoBalance = useHasNoBalance(
|
const { accountBalance: marginAccountBalance } = useMarketAccountBalance(
|
||||||
market.tradableInstrument.instrument.product.settlementAsset.id
|
market.id
|
||||||
);
|
);
|
||||||
|
const { accountBalance: generalAccountBalance } = useAccountBalance(asset.id);
|
||||||
|
const balance = (
|
||||||
|
BigInt(marginAccountBalance) + BigInt(generalAccountBalance)
|
||||||
|
).toString();
|
||||||
|
|
||||||
|
const marketStateError = validateMarketState(marketData.marketState);
|
||||||
|
const hasNoBalance = generalAccountBalance === '0';
|
||||||
const marketTradingModeError = validateMarketTradingMode(
|
const marketTradingModeError = validateMarketTradingMode(
|
||||||
marketData.marketTradingMode
|
marketData.marketTradingMode
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const normalizedOrder =
|
||||||
|
order &&
|
||||||
|
normalizeOrderSubmission(
|
||||||
|
order,
|
||||||
|
market.decimalPlaces,
|
||||||
|
market.positionDecimalPlaces
|
||||||
|
);
|
||||||
|
|
||||||
|
const { margin, totalMargin } = useInitialMargin(
|
||||||
|
market.id,
|
||||||
|
normalizedOrder?.size,
|
||||||
|
order?.side
|
||||||
|
);
|
||||||
|
|
||||||
const checkForErrors = useCallback(() => {
|
const checkForErrors = useCallback(() => {
|
||||||
if (!pubKey) {
|
if (!pubKey) {
|
||||||
setError('summary', { message: t('No public key selected') });
|
setError('summary', {
|
||||||
|
message: t('No public key selected'),
|
||||||
|
type: SummaryValidationType.NoPubKey,
|
||||||
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,6 +142,7 @@ export const DealTicket = ({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (
|
if (
|
||||||
|
(pubKey && errors.summary?.type === SummaryValidationType.NoPubKey) ||
|
||||||
(!hasNoBalance &&
|
(!hasNoBalance &&
|
||||||
errors.summary?.type === SummaryValidationType.NoCollateral) ||
|
errors.summary?.type === SummaryValidationType.NoCollateral) ||
|
||||||
(marketStateError === true &&
|
(marketStateError === true &&
|
||||||
@ -125,6 +154,7 @@ export const DealTicket = ({
|
|||||||
}
|
}
|
||||||
checkForErrors();
|
checkForErrors();
|
||||||
}, [
|
}, [
|
||||||
|
pubKey,
|
||||||
hasNoBalance,
|
hasNoBalance,
|
||||||
marketStateError,
|
marketStateError,
|
||||||
marketTradingModeError,
|
marketTradingModeError,
|
||||||
@ -254,9 +284,10 @@ export const DealTicket = ({
|
|||||||
)}
|
)}
|
||||||
<SummaryMessage
|
<SummaryMessage
|
||||||
errorMessage={errors.summary?.message}
|
errorMessage={errors.summary?.message}
|
||||||
market={market}
|
asset={asset}
|
||||||
marketData={marketData}
|
marketTradingMode={marketData.marketTradingMode}
|
||||||
order={order}
|
balance={balance}
|
||||||
|
margin={totalMargin}
|
||||||
isReadOnly={isReadOnly}
|
isReadOnly={isReadOnly}
|
||||||
pubKey={pubKey}
|
pubKey={pubKey}
|
||||||
onClickCollateral={onClickCollateral}
|
onClickCollateral={onClickCollateral}
|
||||||
@ -266,9 +297,16 @@ export const DealTicket = ({
|
|||||||
variant={order.side === Schema.Side.SIDE_BUY ? 'ternary' : 'secondary'}
|
variant={order.side === Schema.Side.SIDE_BUY ? 'ternary' : 'secondary'}
|
||||||
/>
|
/>
|
||||||
<DealTicketFeeDetails
|
<DealTicketFeeDetails
|
||||||
order={order}
|
order={normalizeOrderSubmission(
|
||||||
|
order,
|
||||||
|
market.decimalPlaces,
|
||||||
|
market.positionDecimalPlaces
|
||||||
|
)}
|
||||||
market={market}
|
market={market}
|
||||||
marketData={marketData}
|
marketData={marketData}
|
||||||
|
margin={margin}
|
||||||
|
totalMargin={totalMargin}
|
||||||
|
balance={marginAccountBalance}
|
||||||
/>
|
/>
|
||||||
</form>
|
</form>
|
||||||
);
|
);
|
||||||
@ -280,9 +318,10 @@ export const DealTicket = ({
|
|||||||
*/
|
*/
|
||||||
interface SummaryMessageProps {
|
interface SummaryMessageProps {
|
||||||
errorMessage?: string;
|
errorMessage?: string;
|
||||||
market: Market;
|
asset: { id: string; symbol: string; name: string; decimals: number };
|
||||||
marketData: MarketData;
|
marketTradingMode: MarketData['marketTradingMode'];
|
||||||
order: OrderObj;
|
balance: string;
|
||||||
|
margin: string;
|
||||||
isReadOnly: boolean;
|
isReadOnly: boolean;
|
||||||
pubKey: string | null;
|
pubKey: string | null;
|
||||||
onClickCollateral?: () => void;
|
onClickCollateral?: () => void;
|
||||||
@ -290,22 +329,17 @@ interface SummaryMessageProps {
|
|||||||
const SummaryMessage = memo(
|
const SummaryMessage = memo(
|
||||||
({
|
({
|
||||||
errorMessage,
|
errorMessage,
|
||||||
market,
|
asset,
|
||||||
marketData,
|
marketTradingMode,
|
||||||
order,
|
balance,
|
||||||
|
margin,
|
||||||
isReadOnly,
|
isReadOnly,
|
||||||
pubKey,
|
pubKey,
|
||||||
onClickCollateral,
|
onClickCollateral,
|
||||||
}: SummaryMessageProps) => {
|
}: SummaryMessageProps) => {
|
||||||
// Specific error UI for if balance is so we can
|
// Specific error UI for if balance is so we can
|
||||||
// render a deposit dialog
|
// render a deposit dialog
|
||||||
const asset = market.tradableInstrument.instrument.product.settlementAsset;
|
|
||||||
const assetSymbol = asset.symbol;
|
const assetSymbol = asset.symbol;
|
||||||
const { balanceError, balance, margin } = useOrderMarginValidation({
|
|
||||||
market,
|
|
||||||
marketData,
|
|
||||||
order,
|
|
||||||
});
|
|
||||||
const openVegaWalletDialog = useVegaWalletDialogStore(
|
const openVegaWalletDialog = useVegaWalletDialogStore(
|
||||||
(store) => store.openVegaWalletDialog
|
(store) => store.openVegaWalletDialog
|
||||||
);
|
);
|
||||||
@ -349,7 +383,7 @@ const SummaryMessage = memo(
|
|||||||
return (
|
return (
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
<ZeroBalanceError
|
<ZeroBalanceError
|
||||||
asset={market.tradableInstrument.instrument.product.settlementAsset}
|
asset={asset}
|
||||||
onClickCollateral={onClickCollateral}
|
onClickCollateral={onClickCollateral}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -370,21 +404,16 @@ const SummaryMessage = memo(
|
|||||||
|
|
||||||
// If there is no blocking error but user doesn't have enough
|
// If there is no blocking error but user doesn't have enough
|
||||||
// balance render the margin warning, but still allow submission
|
// balance render the margin warning, but still allow submission
|
||||||
if (balanceError) {
|
if (BigInt(balance) < BigInt(margin)) {
|
||||||
return (
|
return <MarginWarning balance={balance} margin={margin} asset={asset} />;
|
||||||
<div className="mb-2">
|
|
||||||
<MarginWarning balance={balance} margin={margin} asset={asset} />
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show auction mode warning
|
// Show auction mode warning
|
||||||
if (
|
if (
|
||||||
[
|
[
|
||||||
Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
|
Schema.MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
|
||||||
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
Schema.MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
||||||
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
|
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
|
||||||
].includes(marketData.marketTradingMode)
|
].includes(marketTradingMode)
|
||||||
) {
|
) {
|
||||||
return (
|
return (
|
||||||
<div className="mb-2">
|
<div className="mb-2">
|
||||||
|
@ -55,6 +55,7 @@ export const MarketSelector = ({ market, setMarket, ItemRenderer }: Props) => {
|
|||||||
|
|
||||||
const { data, loading, error } = useDataProvider({
|
const { data, loading, error } = useDataProvider({
|
||||||
dataProvider: marketsProvider,
|
dataProvider: marketsProvider,
|
||||||
|
variables: undefined,
|
||||||
skipUpdates: true,
|
skipUpdates: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -7,6 +7,15 @@ export const EST_MARGIN_TOOLTIP_TEXT = (settlementAsset: string) =>
|
|||||||
For example, for a notional size of $500, if the margin requirement is 10%, then the estimated margin would be approximately $50.`,
|
For example, for a notional size of $500, if the margin requirement is 10%, then the estimated margin would be approximately $50.`,
|
||||||
[settlementAsset]
|
[settlementAsset]
|
||||||
);
|
);
|
||||||
|
export const EST_TOTAL_MARGIN_TOOLTIP_TEXT = t(
|
||||||
|
'Estimated total margin that will cover open position, active orders and this order.'
|
||||||
|
);
|
||||||
|
export const MARGIN_ACCOUNT_TOOLTIP_TEXT = t('Margin account balance');
|
||||||
|
export const MARGIN_DIFF_TOOLTIP_TEXT = (settlementAsset: string) =>
|
||||||
|
t(
|
||||||
|
"The additional margin required for your new position (taking into account volume and open orders), compared to your current margin. Measured in the market's settlement asset ($s).",
|
||||||
|
[settlementAsset]
|
||||||
|
);
|
||||||
export const CONTRACTS_MARGIN_TOOLTIP_TEXT = t(
|
export const CONTRACTS_MARGIN_TOOLTIP_TEXT = t(
|
||||||
'The number of contracts determines how many units of the futures contract to buy or sell. For example, this is similar to buying one share of a listed company. The value of 1 contract is equivalent to the price of the contract. For example, if the current price is $50, then one contract is worth $50.'
|
'The number of contracts determines how many units of the futures contract to buy or sell. For example, this is similar to buying one share of a listed company. The value of 1 contract is equivalent to the price of the contract. For example, if the current price is $50, then one contract is worth $50.'
|
||||||
);
|
);
|
||||||
@ -41,6 +50,7 @@ export enum MarketModeValidationType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum SummaryValidationType {
|
export enum SummaryValidationType {
|
||||||
|
NoPubKey = 'NoPubKey',
|
||||||
NoCollateral = 'NoCollateral',
|
NoCollateral = 'NoCollateral',
|
||||||
TradingMode = 'MarketTradingMode',
|
TradingMode = 'MarketTradingMode',
|
||||||
MarketState = 'MarketState',
|
MarketState = 'MarketState',
|
||||||
|
@ -4,5 +4,3 @@ export * from './use-fee-deal-ticket-details';
|
|||||||
export * from './use-market-positions';
|
export * from './use-market-positions';
|
||||||
export * from './use-maximum-position-size';
|
export * from './use-maximum-position-size';
|
||||||
export * from './use-order-closeout';
|
export * from './use-order-closeout';
|
||||||
export * from './use-order-margin';
|
|
||||||
export * from './use-order-margin-validation';
|
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { useMemo } from 'react';
|
|
||||||
import { marketDepthProvider } from '@vegaprotocol/market-depth';
|
import { marketDepthProvider } from '@vegaprotocol/market-depth';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import type { Market } from '@vegaprotocol/market-list';
|
import type { Market } from '@vegaprotocol/market-list';
|
||||||
@ -13,11 +12,10 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const useCalculateSlippage = ({ market, order }: Props) => {
|
export const useCalculateSlippage = ({ market, order }: Props) => {
|
||||||
const variables = useMemo(() => ({ marketId: market.id }), [market.id]);
|
|
||||||
const { data } = useThrottledDataProvider(
|
const { data } = useThrottledDataProvider(
|
||||||
{
|
{
|
||||||
dataProvider: marketDepthProvider,
|
dataProvider: marketDepthProvider,
|
||||||
variables,
|
variables: { marketId: market.id },
|
||||||
},
|
},
|
||||||
1000
|
1000
|
||||||
);
|
);
|
||||||
|
@ -3,24 +3,26 @@ import {
|
|||||||
addDecimal,
|
addDecimal,
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
formatNumber,
|
formatNumber,
|
||||||
|
toBigNum,
|
||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { t } from '@vegaprotocol/i18n';
|
import { t } from '@vegaprotocol/i18n';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
import BigNumber from 'bignumber.js';
|
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import type { Market, MarketData } from '@vegaprotocol/market-list';
|
import type { Market, MarketData } from '@vegaprotocol/market-list';
|
||||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||||
import {
|
import {
|
||||||
EST_CLOSEOUT_TOOLTIP_TEXT,
|
EST_CLOSEOUT_TOOLTIP_TEXT,
|
||||||
EST_MARGIN_TOOLTIP_TEXT,
|
// EST_MARGIN_TOOLTIP_TEXT,
|
||||||
|
EST_TOTAL_MARGIN_TOOLTIP_TEXT,
|
||||||
NOTIONAL_SIZE_TOOLTIP_TEXT,
|
NOTIONAL_SIZE_TOOLTIP_TEXT,
|
||||||
|
MARGIN_ACCOUNT_TOOLTIP_TEXT,
|
||||||
|
MARGIN_DIFF_TOOLTIP_TEXT,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { useCalculateSlippage } from './use-calculate-slippage';
|
|
||||||
import { useOrderCloseOut } from './use-order-closeout';
|
import { useOrderCloseOut } from './use-order-closeout';
|
||||||
import { useOrderMargin } from './use-order-margin';
|
import { useMarketAccountBalance } from '@vegaprotocol/accounts';
|
||||||
import type { OrderMargin } from './use-order-margin';
|
|
||||||
import { getDerivedPrice } from '../utils/get-price';
|
import { getDerivedPrice } from '../utils/get-price';
|
||||||
|
import { useEstimateOrderQuery } from './__generated__/EstimateOrder';
|
||||||
|
import type { EstimateOrderQuery } from './__generated__/EstimateOrder';
|
||||||
|
|
||||||
export const useFeeDealTicketDetails = (
|
export const useFeeDealTicketDetails = (
|
||||||
order: OrderSubmissionBody['orderSubmission'],
|
order: OrderSubmissionBody['orderSubmission'],
|
||||||
@ -28,33 +30,23 @@ export const useFeeDealTicketDetails = (
|
|||||||
marketData: MarketData
|
marketData: MarketData
|
||||||
) => {
|
) => {
|
||||||
const { pubKey } = useVegaWallet();
|
const { pubKey } = useVegaWallet();
|
||||||
const slippage = useCalculateSlippage({ market, order });
|
const { accountBalance } = useMarketAccountBalance(market.id);
|
||||||
|
|
||||||
const derivedPrice = useMemo(() => {
|
const price = useMemo(() => {
|
||||||
return getDerivedPrice(order, market, marketData);
|
return getDerivedPrice(order, marketData);
|
||||||
}, [order, market, marketData]);
|
}, [order, marketData]);
|
||||||
|
|
||||||
// Note this isn't currently used anywhere
|
const { data: estMargin } = useEstimateOrderQuery({
|
||||||
const slippageAdjustedPrice = useMemo(() => {
|
variables: {
|
||||||
if (derivedPrice) {
|
marketId: market.id,
|
||||||
if (slippage && parseFloat(slippage) !== 0) {
|
partyId: pubKey || '',
|
||||||
const isLong = order.side === Schema.Side.SIDE_BUY;
|
price,
|
||||||
const multiplier = new BigNumber(1)[isLong ? 'plus' : 'minus'](
|
size: order.size,
|
||||||
parseFloat(slippage) / 100
|
side: order.side,
|
||||||
);
|
timeInForce: order.timeInForce,
|
||||||
return new BigNumber(derivedPrice).multipliedBy(multiplier).toNumber();
|
type: order.type,
|
||||||
}
|
},
|
||||||
return derivedPrice;
|
skip: !pubKey || !market || !order.size || !price,
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}, [derivedPrice, order.side, slippage]);
|
|
||||||
|
|
||||||
const estMargin = useOrderMargin({
|
|
||||||
order,
|
|
||||||
market,
|
|
||||||
marketData,
|
|
||||||
partyId: pubKey || '',
|
|
||||||
derivedPrice,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const estCloseOut = useOrderCloseOut({
|
const estCloseOut = useOrderCloseOut({
|
||||||
@ -64,13 +56,13 @@ export const useFeeDealTicketDetails = (
|
|||||||
});
|
});
|
||||||
|
|
||||||
const notionalSize = useMemo(() => {
|
const notionalSize = useMemo(() => {
|
||||||
if (derivedPrice && order.size) {
|
if (price && order.size) {
|
||||||
return new BigNumber(order.size)
|
return toBigNum(order.size, market.positionDecimalPlaces)
|
||||||
.multipliedBy(addDecimal(derivedPrice, market.decimalPlaces))
|
.multipliedBy(addDecimal(price, market.decimalPlaces))
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}, [derivedPrice, order.size, market.decimalPlaces]);
|
}, [price, order.size, market.decimalPlaces, market.positionDecimalPlaces]);
|
||||||
|
|
||||||
const assetSymbol =
|
const assetSymbol =
|
||||||
market.tradableInstrument.instrument.product.settlementAsset.symbol;
|
market.tradableInstrument.instrument.product.settlementAsset.symbol;
|
||||||
@ -80,37 +72,40 @@ export const useFeeDealTicketDetails = (
|
|||||||
market,
|
market,
|
||||||
assetSymbol,
|
assetSymbol,
|
||||||
notionalSize,
|
notionalSize,
|
||||||
estMargin,
|
accountBalance,
|
||||||
|
estimateOrder: estMargin?.estimateOrder,
|
||||||
estCloseOut,
|
estCloseOut,
|
||||||
slippage,
|
|
||||||
slippageAdjustedPrice,
|
|
||||||
};
|
};
|
||||||
}, [
|
}, [
|
||||||
market,
|
market,
|
||||||
assetSymbol,
|
assetSymbol,
|
||||||
notionalSize,
|
notionalSize,
|
||||||
|
accountBalance,
|
||||||
estMargin,
|
estMargin,
|
||||||
estCloseOut,
|
estCloseOut,
|
||||||
slippage,
|
|
||||||
slippageAdjustedPrice,
|
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface FeeDetails {
|
export interface FeeDetails {
|
||||||
|
balance: string;
|
||||||
market: Market;
|
market: Market;
|
||||||
assetSymbol: string;
|
assetSymbol: string;
|
||||||
notionalSize: string | null;
|
notionalSize: string | null;
|
||||||
estMargin: OrderMargin | null;
|
|
||||||
estCloseOut: string | null;
|
estCloseOut: string | null;
|
||||||
slippage: string | null;
|
estimateOrder: EstimateOrderQuery['estimateOrder'] | undefined;
|
||||||
|
margin: string;
|
||||||
|
totalMargin: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getFeeDetailsValues = ({
|
export const getFeeDetailsValues = ({
|
||||||
|
balance,
|
||||||
assetSymbol,
|
assetSymbol,
|
||||||
notionalSize,
|
|
||||||
estMargin,
|
|
||||||
estCloseOut,
|
estCloseOut,
|
||||||
|
estimateOrder,
|
||||||
|
margin,
|
||||||
market,
|
market,
|
||||||
|
notionalSize,
|
||||||
|
totalMargin,
|
||||||
}: FeeDetails) => {
|
}: FeeDetails) => {
|
||||||
const assetDecimals =
|
const assetDecimals =
|
||||||
market.tradableInstrument.instrument.product.settlementAsset.decimals;
|
market.tradableInstrument.instrument.product.settlementAsset.decimals;
|
||||||
@ -129,7 +124,12 @@ export const getFeeDetailsValues = ({
|
|||||||
? addDecimalsFormatNumber(value, assetDecimals)
|
? addDecimalsFormatNumber(value, assetDecimals)
|
||||||
: '-';
|
: '-';
|
||||||
};
|
};
|
||||||
return [
|
const details: {
|
||||||
|
label: string;
|
||||||
|
value?: string | null;
|
||||||
|
symbol: string;
|
||||||
|
labelDescription: React.ReactNode;
|
||||||
|
}[] = [
|
||||||
{
|
{
|
||||||
label: t('Notional'),
|
label: t('Notional'),
|
||||||
value: formatValueWithMarketDp(notionalSize),
|
value: formatValueWithMarketDp(notionalSize),
|
||||||
@ -139,8 +139,8 @@ export const getFeeDetailsValues = ({
|
|||||||
{
|
{
|
||||||
label: t('Fees'),
|
label: t('Fees'),
|
||||||
value:
|
value:
|
||||||
estMargin?.totalFees &&
|
estimateOrder?.totalFeeAmount &&
|
||||||
`~${formatValueWithAssetDp(estMargin?.totalFees)}`,
|
`~${formatValueWithAssetDp(estimateOrder?.totalFeeAmount)}`,
|
||||||
labelDescription: (
|
labelDescription: (
|
||||||
<>
|
<>
|
||||||
<span>
|
<span>
|
||||||
@ -149,7 +149,7 @@ export const getFeeDetailsValues = ({
|
|||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
<FeesBreakdown
|
<FeesBreakdown
|
||||||
fees={estMargin?.fees}
|
fees={estimateOrder?.fee}
|
||||||
feeFactors={market.fees.factors}
|
feeFactors={market.fees.factors}
|
||||||
symbol={assetSymbol}
|
symbol={assetSymbol}
|
||||||
decimals={assetDecimals}
|
decimals={assetDecimals}
|
||||||
@ -158,18 +158,46 @@ export const getFeeDetailsValues = ({
|
|||||||
),
|
),
|
||||||
symbol: assetSymbol,
|
symbol: assetSymbol,
|
||||||
},
|
},
|
||||||
|
/*
|
||||||
{
|
{
|
||||||
label: t('Margin'),
|
label: t('Initial margin'),
|
||||||
value:
|
value: margin && `~${formatValueWithAssetDp(margin)}`,
|
||||||
estMargin?.margin && `~${formatValueWithAssetDp(estMargin?.margin)}`,
|
|
||||||
symbol: assetSymbol,
|
symbol: assetSymbol,
|
||||||
labelDescription: EST_MARGIN_TOOLTIP_TEXT(assetSymbol),
|
labelDescription: EST_MARGIN_TOOLTIP_TEXT(assetSymbol),
|
||||||
},
|
},
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
label: t('Liquidation'),
|
label: t('Margin required'),
|
||||||
value: estCloseOut && `~${formatValueWithMarketDp(estCloseOut)}`,
|
value: `~${formatValueWithAssetDp(
|
||||||
symbol: market.tradableInstrument.instrument.product.quoteName,
|
balance
|
||||||
labelDescription: EST_CLOSEOUT_TOOLTIP_TEXT(quoteName),
|
? (BigInt(totalMargin) - BigInt(balance)).toString()
|
||||||
|
: totalMargin
|
||||||
|
)}`,
|
||||||
|
symbol: assetSymbol,
|
||||||
|
labelDescription: MARGIN_DIFF_TOOLTIP_TEXT(assetSymbol),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
if (balance) {
|
||||||
|
details.push({
|
||||||
|
label: t('Projected margin'),
|
||||||
|
value: `~${formatValueWithAssetDp(totalMargin)}`,
|
||||||
|
symbol: assetSymbol,
|
||||||
|
labelDescription: EST_TOTAL_MARGIN_TOOLTIP_TEXT,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
details.push({
|
||||||
|
label: t('Current margin allocation'),
|
||||||
|
value: balance
|
||||||
|
? `~${formatValueWithAssetDp(balance)}`
|
||||||
|
: `${formatValueWithAssetDp(balance)}`,
|
||||||
|
symbol: assetSymbol,
|
||||||
|
labelDescription: MARGIN_ACCOUNT_TOOLTIP_TEXT,
|
||||||
|
});
|
||||||
|
details.push({
|
||||||
|
label: t('Liquidation'),
|
||||||
|
value: estCloseOut && `~${formatValueWithMarketDp(estCloseOut)}`,
|
||||||
|
symbol: market.tradableInstrument.instrument.product.quoteName,
|
||||||
|
labelDescription: EST_CLOSEOUT_TOOLTIP_TEXT(quoteName),
|
||||||
|
});
|
||||||
|
return details;
|
||||||
};
|
};
|
||||||
|
@ -1,11 +0,0 @@
|
|||||||
import { useAccountBalance } from '@vegaprotocol/accounts';
|
|
||||||
import { toBigNum } from '@vegaprotocol/utils';
|
|
||||||
|
|
||||||
export const useHasNoBalance = (assetId: string) => {
|
|
||||||
const { accountBalance, accountDecimals } = useAccountBalance(assetId);
|
|
||||||
const balance =
|
|
||||||
accountBalance && accountDecimals !== null
|
|
||||||
? toBigNum(accountBalance, accountDecimals)
|
|
||||||
: toBigNum('0', 0);
|
|
||||||
return balance.isZero();
|
|
||||||
};
|
|
70
libs/deal-ticket/src/hooks/use-initial-margin.ts
Normal file
70
libs/deal-ticket/src/hooks/use-initial-margin.ts
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
|
import { marketDataProvider } from '@vegaprotocol/market-list';
|
||||||
|
import {
|
||||||
|
calculateMargins,
|
||||||
|
// getDerivedPrice,
|
||||||
|
volumeAndMarginProvider,
|
||||||
|
} from '@vegaprotocol/positions';
|
||||||
|
import { Side } from '@vegaprotocol/types';
|
||||||
|
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||||
|
import { marketInfoProvider } from '@vegaprotocol/market-info';
|
||||||
|
|
||||||
|
export const useInitialMargin = (
|
||||||
|
marketId: OrderSubmissionBody['orderSubmission']['marketId'],
|
||||||
|
size?: OrderSubmissionBody['orderSubmission']['size'],
|
||||||
|
side?: OrderSubmissionBody['orderSubmission']['side']
|
||||||
|
) => {
|
||||||
|
const { pubKey: partyId } = useVegaWallet();
|
||||||
|
const commonVariables = { marketId, partyId: partyId || '' };
|
||||||
|
const { data: marketData } = useDataProvider({
|
||||||
|
dataProvider: marketDataProvider,
|
||||||
|
variables: { marketId },
|
||||||
|
});
|
||||||
|
const { data: activeVolumeAndMargin } = useDataProvider({
|
||||||
|
dataProvider: volumeAndMarginProvider,
|
||||||
|
variables: commonVariables,
|
||||||
|
skip: !partyId,
|
||||||
|
});
|
||||||
|
const { data: marketInfo } = useDataProvider({
|
||||||
|
dataProvider: marketInfoProvider,
|
||||||
|
variables: commonVariables,
|
||||||
|
});
|
||||||
|
let totalMargin = '0';
|
||||||
|
let margin = '0';
|
||||||
|
if (marketInfo?.riskFactors && marketData && size && side) {
|
||||||
|
const {
|
||||||
|
positionDecimalPlaces,
|
||||||
|
decimalPlaces,
|
||||||
|
tradableInstrument,
|
||||||
|
riskFactors,
|
||||||
|
} = marketInfo;
|
||||||
|
const { marginCalculator, instrument } = tradableInstrument;
|
||||||
|
const { decimals } = instrument.product.settlementAsset;
|
||||||
|
margin = totalMargin = calculateMargins({
|
||||||
|
side,
|
||||||
|
size,
|
||||||
|
price: marketData.markPrice, // getDerivedPrice(order, marketData), same in positions-data-providers
|
||||||
|
positionDecimalPlaces,
|
||||||
|
decimalPlaces,
|
||||||
|
decimals,
|
||||||
|
scalingFactors: marginCalculator?.scalingFactors,
|
||||||
|
riskFactors,
|
||||||
|
}).initialMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activeVolumeAndMargin) {
|
||||||
|
let sellMargin = BigInt(activeVolumeAndMargin.sellInitialMargin);
|
||||||
|
let buyMargin = BigInt(activeVolumeAndMargin.buyInitialMargin);
|
||||||
|
if (side === Side.SIDE_SELL) {
|
||||||
|
sellMargin += BigInt(totalMargin);
|
||||||
|
} else {
|
||||||
|
buyMargin += BigInt(totalMargin);
|
||||||
|
}
|
||||||
|
totalMargin =
|
||||||
|
sellMargin > buyMargin ? sellMargin.toString() : buyMargin.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return useMemo(() => ({ totalMargin, margin }), [totalMargin, margin]);
|
||||||
|
};
|
@ -1,48 +0,0 @@
|
|||||||
import { useMemo } from 'react';
|
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
|
||||||
import { toBigNum } from '@vegaprotocol/utils';
|
|
||||||
import { useAccountBalance } from '@vegaprotocol/accounts';
|
|
||||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
|
||||||
import { useOrderMargin } from './use-order-margin';
|
|
||||||
import type { Market, MarketData } from '@vegaprotocol/market-list';
|
|
||||||
|
|
||||||
interface Props {
|
|
||||||
market: Market;
|
|
||||||
marketData: MarketData;
|
|
||||||
order: OrderSubmissionBody['orderSubmission'];
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useOrderMarginValidation = ({
|
|
||||||
market,
|
|
||||||
marketData,
|
|
||||||
order,
|
|
||||||
}: Props) => {
|
|
||||||
const { pubKey } = useVegaWallet();
|
|
||||||
const estMargin = useOrderMargin({
|
|
||||||
order,
|
|
||||||
market,
|
|
||||||
marketData,
|
|
||||||
partyId: pubKey || '',
|
|
||||||
});
|
|
||||||
const { id: assetId, decimals: assetDecimals } =
|
|
||||||
market.tradableInstrument.instrument.product.settlementAsset;
|
|
||||||
|
|
||||||
const { accountBalance, accountDecimals } = useAccountBalance(assetId);
|
|
||||||
const balance =
|
|
||||||
accountBalance && accountDecimals !== null
|
|
||||||
? toBigNum(accountBalance, accountDecimals)
|
|
||||||
: toBigNum('0', assetDecimals);
|
|
||||||
const margin = toBigNum(estMargin?.margin || 0, assetDecimals);
|
|
||||||
|
|
||||||
// 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: balanceAsString,
|
|
||||||
margin: marginAsString,
|
|
||||||
balanceError,
|
|
||||||
};
|
|
||||||
}, [balanceAsString, marginAsString, balanceError]);
|
|
||||||
};
|
|
@ -1,116 +0,0 @@
|
|||||||
import { renderHook } from '@testing-library/react';
|
|
||||||
import { useQuery } from '@apollo/client';
|
|
||||||
import { BigNumber } from 'bignumber.js';
|
|
||||||
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 { Market, MarketData } from '@vegaprotocol/market-list';
|
|
||||||
|
|
||||||
let mockEstimateData = {
|
|
||||||
estimateOrder: {
|
|
||||||
fee: {
|
|
||||||
makerFee: '100000.000',
|
|
||||||
infrastructureFee: '100000.000',
|
|
||||||
liquidityFee: '100000.000',
|
|
||||||
},
|
|
||||||
marginLevels: {
|
|
||||||
initialLevel: '200000',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
jest.mock('@apollo/client', () => ({
|
|
||||||
...jest.requireActual('@apollo/client'),
|
|
||||||
useQuery: jest.fn(() => ({ data: mockEstimateData })),
|
|
||||||
}));
|
|
||||||
|
|
||||||
let mockMarketPositions: PositionMargin = {
|
|
||||||
openVolume: '1',
|
|
||||||
balance: '100000',
|
|
||||||
};
|
|
||||||
|
|
||||||
jest.mock('./use-market-positions', () => ({
|
|
||||||
useMarketPositions: ({
|
|
||||||
marketId,
|
|
||||||
partyId,
|
|
||||||
}: {
|
|
||||||
marketId: string;
|
|
||||||
partyId: string;
|
|
||||||
}) => mockMarketPositions,
|
|
||||||
}));
|
|
||||||
|
|
||||||
describe('useOrderMargin', () => {
|
|
||||||
const marketId = 'marketId';
|
|
||||||
const args: Props = {
|
|
||||||
order: {
|
|
||||||
marketId,
|
|
||||||
size: '2',
|
|
||||||
side: Schema.Side.SIDE_BUY,
|
|
||||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_IOC,
|
|
||||||
type: Schema.OrderType.TYPE_MARKET,
|
|
||||||
},
|
|
||||||
market: {
|
|
||||||
id: marketId,
|
|
||||||
decimalPlaces: 2,
|
|
||||||
positionDecimalPlaces: 0,
|
|
||||||
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
|
||||||
} as unknown as Market,
|
|
||||||
marketData: {
|
|
||||||
indicativePrice: '100',
|
|
||||||
markPrice: '200',
|
|
||||||
} as unknown as MarketData,
|
|
||||||
partyId: 'partyId',
|
|
||||||
};
|
|
||||||
|
|
||||||
afterEach(() => {
|
|
||||||
jest.clearAllMocks();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should calculate margin correctly', () => {
|
|
||||||
const { result } = renderHook(() => useOrderMargin(args));
|
|
||||||
expect(result.current?.margin).toEqual('100000');
|
|
||||||
expect((useQuery as jest.Mock).mock.calls[0][1].variables.size).toEqual(
|
|
||||||
args.order.size
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should calculate fees correctly', () => {
|
|
||||||
const { result } = renderHook(() => useOrderMargin(args));
|
|
||||||
expect(result.current?.totalFees).toEqual('300000');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should not subtract initialMargin if there is no position', () => {
|
|
||||||
mockMarketPositions = null;
|
|
||||||
const { result } = renderHook(() => useOrderMargin(args));
|
|
||||||
expect(result.current?.margin).toEqual('200000');
|
|
||||||
|
|
||||||
expect((useQuery as jest.Mock).mock.calls[0][1].variables.size).toEqual(
|
|
||||||
args.order.size
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return empty value if API fails', () => {
|
|
||||||
mockEstimateData = {
|
|
||||||
estimateOrder: {
|
|
||||||
fee: {
|
|
||||||
makerFee: '100000.000',
|
|
||||||
infrastructureFee: '100000.000',
|
|
||||||
liquidityFee: '100000.000',
|
|
||||||
},
|
|
||||||
marginLevels: {
|
|
||||||
initialLevel: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
const { result } = renderHook(() => useOrderMargin(args));
|
|
||||||
expect(result.current).toEqual(null);
|
|
||||||
|
|
||||||
const calledSize = new BigNumber(mockMarketPositions?.openVolume || 0)
|
|
||||||
.plus(args.order.size)
|
|
||||||
.toString();
|
|
||||||
expect((useQuery as jest.Mock).mock.calls[0][1].variables.size).toEqual(
|
|
||||||
calledSize
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,76 +0,0 @@
|
|||||||
import { useMemo } from 'react';
|
|
||||||
import { BigNumber } from 'bignumber.js';
|
|
||||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
|
||||||
import { removeDecimal } from '@vegaprotocol/utils';
|
|
||||||
import { useMarketPositions } from './use-market-positions';
|
|
||||||
import { useEstimateOrderQuery } from './__generated__/EstimateOrder';
|
|
||||||
import type { Market, MarketData } from '@vegaprotocol/market-list';
|
|
||||||
import { getDerivedPrice } from '../utils/get-price';
|
|
||||||
|
|
||||||
export interface Props {
|
|
||||||
order: OrderSubmissionBody['orderSubmission'];
|
|
||||||
market: Market;
|
|
||||||
marketData: MarketData;
|
|
||||||
partyId: string;
|
|
||||||
derivedPrice?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface OrderMargin {
|
|
||||||
margin: string;
|
|
||||||
totalFees: string | null;
|
|
||||||
fees: {
|
|
||||||
makerFee: string;
|
|
||||||
liquidityFee: string;
|
|
||||||
infrastructureFee: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export const useOrderMargin = ({
|
|
||||||
order,
|
|
||||||
market,
|
|
||||||
marketData,
|
|
||||||
partyId,
|
|
||||||
derivedPrice,
|
|
||||||
}: Props): OrderMargin | null => {
|
|
||||||
const { balance } = useMarketPositions({ marketId: market.id }) || {};
|
|
||||||
const priceForEstimate =
|
|
||||||
derivedPrice || getDerivedPrice(order, market, marketData);
|
|
||||||
|
|
||||||
const { data } = useEstimateOrderQuery({
|
|
||||||
variables: {
|
|
||||||
marketId: market.id,
|
|
||||||
partyId,
|
|
||||||
price: priceForEstimate,
|
|
||||||
size: removeDecimal(order.size, market.positionDecimalPlaces),
|
|
||||||
side: order.side,
|
|
||||||
timeInForce: order.timeInForce,
|
|
||||||
type: order.type,
|
|
||||||
},
|
|
||||||
skip: !partyId || !market.id || !order.size || !priceForEstimate,
|
|
||||||
});
|
|
||||||
const { makerFee, liquidityFee, infrastructureFee } = data?.estimateOrder
|
|
||||||
.fee || { makerFee: '', liquidityFee: '', infrastructureFee: '' };
|
|
||||||
const { initialLevel } = data?.estimateOrder.marginLevels ?? {};
|
|
||||||
return useMemo(() => {
|
|
||||||
if (initialLevel) {
|
|
||||||
const margin = BigNumber.maximum(
|
|
||||||
0,
|
|
||||||
new BigNumber(initialLevel).minus(balance || 0)
|
|
||||||
).toString();
|
|
||||||
const fees = new BigNumber(makerFee)
|
|
||||||
.plus(liquidityFee)
|
|
||||||
.plus(infrastructureFee)
|
|
||||||
.toString();
|
|
||||||
return {
|
|
||||||
margin,
|
|
||||||
totalFees: fees,
|
|
||||||
fees: {
|
|
||||||
makerFee,
|
|
||||||
liquidityFee,
|
|
||||||
infrastructureFee,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}, [initialLevel, makerFee, liquidityFee, infrastructureFee, balance]);
|
|
||||||
};
|
|
@ -64,20 +64,27 @@ export function generateMarketData(
|
|||||||
id: 'market-id',
|
id: 'market-id',
|
||||||
__typename: 'Market',
|
__typename: 'Market',
|
||||||
},
|
},
|
||||||
auctionStart: '2022-06-21T17:18:43.484055236Z',
|
|
||||||
auctionEnd: '2022-06-21T17:18:43.484055236Z',
|
auctionEnd: '2022-06-21T17:18:43.484055236Z',
|
||||||
targetStake: '1000000',
|
auctionStart: '2022-06-21T17:18:43.484055236Z',
|
||||||
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',
|
bestBidPrice: '0',
|
||||||
|
bestBidVolume: '0',
|
||||||
bestOfferPrice: '0',
|
bestOfferPrice: '0',
|
||||||
|
bestOfferVolume: '0',
|
||||||
|
bestStaticBidPrice: '0',
|
||||||
|
bestStaticBidVolume: '0',
|
||||||
|
bestStaticOfferPrice: '0',
|
||||||
|
bestStaticOfferVolume: '0',
|
||||||
|
indicativePrice: '100',
|
||||||
|
indicativeVolume: '10',
|
||||||
|
marketState: Schema.MarketState.STATE_ACTIVE,
|
||||||
|
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||||
|
marketValueProxy: '',
|
||||||
markPrice: '200',
|
markPrice: '200',
|
||||||
|
midPrice: '0',
|
||||||
|
openInterest: '',
|
||||||
|
staticMidPrice: '0',
|
||||||
|
suppliedStake: '1000',
|
||||||
|
targetStake: '1000000',
|
||||||
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_BATCH,
|
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_BATCH,
|
||||||
};
|
};
|
||||||
return merge(defaultMarketData, override);
|
return merge(defaultMarketData, override);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { removeDecimal } from '@vegaprotocol/utils';
|
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import { isMarketInAuction } from './is-market-in-auction';
|
import { isMarketInAuction } from './is-market-in-auction';
|
||||||
import type { MarketData, Market } from '@vegaprotocol/market-list';
|
import type { MarketData } from '@vegaprotocol/market-list';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the market price based on market mode (auction or not auction)
|
* Get the market price based on market mode (auction or not auction)
|
||||||
@ -34,7 +33,6 @@ export const getDerivedPrice = (
|
|||||||
type: Schema.OrderType;
|
type: Schema.OrderType;
|
||||||
price?: string | undefined;
|
price?: string | undefined;
|
||||||
},
|
},
|
||||||
market: Market,
|
|
||||||
marketData: MarketData
|
marketData: MarketData
|
||||||
) => {
|
) => {
|
||||||
// If order type is market we should use either the mark price
|
// If order type is market we should use either the mark price
|
||||||
@ -44,7 +42,7 @@ export const getDerivedPrice = (
|
|||||||
// Use the market price if order is a market order
|
// Use the market price if order is a market order
|
||||||
let price;
|
let price;
|
||||||
if (order.type === Schema.OrderType.TYPE_LIMIT && order.price) {
|
if (order.type === Schema.OrderType.TYPE_LIMIT && order.price) {
|
||||||
price = removeDecimal(order.price, market.decimalPlaces);
|
price = order.price;
|
||||||
} else {
|
} else {
|
||||||
price = getMarketPrice(marketData);
|
price = getMarketPrice(marketData);
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ export const DepositContainer = ({ assetId }: { assetId?: string }) => {
|
|||||||
const { VEGA_ENV } = useEnvironment();
|
const { VEGA_ENV } = useEnvironment();
|
||||||
const { data, loading, error } = useDataProvider({
|
const { data, loading, error } = useDataProvider({
|
||||||
dataProvider: enabledAssetsProvider,
|
dataProvider: enabledAssetsProvider,
|
||||||
|
variables: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -13,6 +13,7 @@ import type { PageInfo, Edge } from '@vegaprotocol/utils';
|
|||||||
import { FillsDocument, FillsEventDocument } from './__generated__/Fills';
|
import { FillsDocument, FillsEventDocument } from './__generated__/Fills';
|
||||||
import type {
|
import type {
|
||||||
FillsQuery,
|
FillsQuery,
|
||||||
|
FillsQueryVariables,
|
||||||
FillFieldsFragment,
|
FillFieldsFragment,
|
||||||
FillEdgeFragment,
|
FillEdgeFragment,
|
||||||
FillsEventSubscription,
|
FillsEventSubscription,
|
||||||
@ -62,13 +63,19 @@ export type TradeEdge = Edge<Trade>;
|
|||||||
const getData = (responseData: FillsQuery | null): FillEdgeFragment[] =>
|
const getData = (responseData: FillsQuery | null): FillEdgeFragment[] =>
|
||||||
responseData?.party?.tradesConnection?.edges || [];
|
responseData?.party?.tradesConnection?.edges || [];
|
||||||
|
|
||||||
const getPageInfo = (responseData: FillsQuery): PageInfo | null =>
|
const getPageInfo = (responseData: FillsQuery | null): PageInfo | null =>
|
||||||
responseData.party?.tradesConnection?.pageInfo || null;
|
responseData?.party?.tradesConnection?.pageInfo || null;
|
||||||
|
|
||||||
const getDelta = (subscriptionData: FillsEventSubscription) =>
|
const getDelta = (subscriptionData: FillsEventSubscription) =>
|
||||||
subscriptionData.trades || [];
|
subscriptionData.trades || [];
|
||||||
|
|
||||||
export const fillsProvider = makeDataProvider({
|
export const fillsProvider = makeDataProvider<
|
||||||
|
Parameters<typeof getData>['0'],
|
||||||
|
ReturnType<typeof getData>,
|
||||||
|
Parameters<typeof getDelta>['0'],
|
||||||
|
ReturnType<typeof getDelta>,
|
||||||
|
FillsQueryVariables
|
||||||
|
>({
|
||||||
query: FillsDocument,
|
query: FillsDocument,
|
||||||
subscriptionQuery: FillsEventDocument,
|
subscriptionQuery: FillsEventDocument,
|
||||||
update,
|
update,
|
||||||
@ -83,9 +90,13 @@ export const fillsProvider = makeDataProvider({
|
|||||||
|
|
||||||
export const fillsWithMarketProvider = makeDerivedDataProvider<
|
export const fillsWithMarketProvider = makeDerivedDataProvider<
|
||||||
(TradeEdge | null)[],
|
(TradeEdge | null)[],
|
||||||
Trade[]
|
Trade[],
|
||||||
|
FillsQueryVariables
|
||||||
>(
|
>(
|
||||||
[fillsProvider, marketsProvider],
|
[
|
||||||
|
fillsProvider,
|
||||||
|
(callback, client) => marketsProvider(callback, client, undefined),
|
||||||
|
],
|
||||||
(partsData): (TradeEdge | null)[] =>
|
(partsData): (TradeEdge | null)[] =>
|
||||||
(partsData[0] as ReturnType<typeof getData>)?.map(
|
(partsData[0] as ReturnType<typeof getData>)?.map(
|
||||||
(edge) =>
|
(edge) =>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import type { RefObject } from 'react';
|
import type { RefObject } from 'react';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { useCallback, useMemo, useRef } from 'react';
|
import { useCallback, useRef } from 'react';
|
||||||
import { makeInfiniteScrollGetRows } from '@vegaprotocol/utils';
|
import { makeInfiniteScrollGetRows } from '@vegaprotocol/utils';
|
||||||
import { useDataProvider, updateGridData } from '@vegaprotocol/react-helpers';
|
import { useDataProvider, updateGridData } from '@vegaprotocol/react-helpers';
|
||||||
import type { Trade, TradeEdge } from './fills-data-provider';
|
import type { Trade, TradeEdge } from './fills-data-provider';
|
||||||
@ -73,16 +73,11 @@ export const useFillsList = ({
|
|||||||
[gridRef]
|
[gridRef]
|
||||||
);
|
);
|
||||||
|
|
||||||
const variables = useMemo(() => ({ partyId, marketId }), [partyId, marketId]);
|
const { data, error, loading, load, totalCount, reload } = useDataProvider({
|
||||||
|
|
||||||
const { data, error, loading, load, totalCount, reload } = useDataProvider<
|
|
||||||
(TradeEdge | null)[],
|
|
||||||
Trade[]
|
|
||||||
>({
|
|
||||||
dataProvider: fillsWithMarketProvider,
|
dataProvider: fillsWithMarketProvider,
|
||||||
update,
|
update,
|
||||||
insert,
|
insert,
|
||||||
variables,
|
variables: { partyId, marketId: marketId || '' },
|
||||||
});
|
});
|
||||||
totalCountRef.current = totalCount;
|
totalCountRef.current = totalCount;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ export const update = (
|
|||||||
data: ReturnType<typeof getData> | null,
|
data: ReturnType<typeof getData> | null,
|
||||||
delta: ReturnType<typeof getData>,
|
delta: ReturnType<typeof getData>,
|
||||||
reload: () => void,
|
reload: () => void,
|
||||||
variables?: LedgerEntriesQueryVariables
|
variables: LedgerEntriesQueryVariables
|
||||||
) => {
|
) => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return data;
|
return data;
|
||||||
@ -110,8 +110,8 @@ export const ledgerEntriesProvider = makeDerivedDataProvider<
|
|||||||
>(
|
>(
|
||||||
[
|
[
|
||||||
ledgerEntriesOnlyProvider,
|
ledgerEntriesOnlyProvider,
|
||||||
(callback, client) => assetsProvider(callback, client),
|
(callback, client) => assetsProvider(callback, client, undefined),
|
||||||
marketsProvider,
|
(callback, client) => marketsProvider(callback, client, undefined),
|
||||||
],
|
],
|
||||||
([entries, assets, markets]) => {
|
([entries, assets, markets]) => {
|
||||||
return entries.map((edge: AggregatedLedgerEntriesEdge) => {
|
return entries.map((edge: AggregatedLedgerEntriesEdge) => {
|
||||||
|
@ -14,11 +14,14 @@ import {
|
|||||||
|
|
||||||
import type {
|
import type {
|
||||||
MarketLpQuery,
|
MarketLpQuery,
|
||||||
|
MarketLpQueryVariables,
|
||||||
LiquidityProviderFeeShareFieldsFragment,
|
LiquidityProviderFeeShareFieldsFragment,
|
||||||
LiquidityProviderFeeShareQuery,
|
LiquidityProviderFeeShareQuery,
|
||||||
|
LiquidityProviderFeeShareQueryVariables,
|
||||||
LiquidityProviderFeeShareUpdateSubscription,
|
LiquidityProviderFeeShareUpdateSubscription,
|
||||||
LiquidityProvisionFieldsFragment,
|
LiquidityProvisionFieldsFragment,
|
||||||
LiquidityProvisionsQuery,
|
LiquidityProvisionsQuery,
|
||||||
|
LiquidityProvisionsQueryVariables,
|
||||||
LiquidityProvisionsUpdateSubscription,
|
LiquidityProvisionsUpdateSubscription,
|
||||||
} from './__generated__/MarketLiquidity';
|
} from './__generated__/MarketLiquidity';
|
||||||
import type { IterableElement } from 'type-fest';
|
import type { IterableElement } from 'type-fest';
|
||||||
@ -27,7 +30,8 @@ export const liquidityProvisionsDataProvider = makeDataProvider<
|
|||||||
LiquidityProvisionsQuery,
|
LiquidityProvisionsQuery,
|
||||||
LiquidityProvisionFieldsFragment[],
|
LiquidityProvisionFieldsFragment[],
|
||||||
LiquidityProvisionsUpdateSubscription,
|
LiquidityProvisionsUpdateSubscription,
|
||||||
LiquidityProvisionsUpdateSubscription['liquidityProvisions']
|
LiquidityProvisionsUpdateSubscription['liquidityProvisions'],
|
||||||
|
LiquidityProvisionsQueryVariables
|
||||||
>({
|
>({
|
||||||
query: LiquidityProvisionsDocument,
|
query: LiquidityProvisionsDocument,
|
||||||
subscriptionQuery: LiquidityProvisionsUpdateDocument,
|
subscriptionQuery: LiquidityProvisionsUpdateDocument,
|
||||||
@ -99,7 +103,8 @@ export const marketLiquidityDataProvider = makeDataProvider<
|
|||||||
MarketLpQuery,
|
MarketLpQuery,
|
||||||
MarketLpQuery,
|
MarketLpQuery,
|
||||||
never,
|
never,
|
||||||
never
|
never,
|
||||||
|
MarketLpQueryVariables
|
||||||
>({
|
>({
|
||||||
query: MarketLpDocument,
|
query: MarketLpDocument,
|
||||||
getData: (responseData: MarketLpQuery | null) => {
|
getData: (responseData: MarketLpQuery | null) => {
|
||||||
@ -111,7 +116,8 @@ export const liquidityFeeShareDataProvider = makeDataProvider<
|
|||||||
LiquidityProviderFeeShareQuery,
|
LiquidityProviderFeeShareQuery,
|
||||||
LiquidityProviderFeeShareFieldsFragment[],
|
LiquidityProviderFeeShareFieldsFragment[],
|
||||||
LiquidityProviderFeeShareUpdateSubscription,
|
LiquidityProviderFeeShareUpdateSubscription,
|
||||||
LiquidityProviderFeeShareUpdateSubscription['marketsData'][0]['liquidityProviderFeeShare']
|
LiquidityProviderFeeShareUpdateSubscription['marketsData'][0]['liquidityProviderFeeShare'],
|
||||||
|
LiquidityProviderFeeShareQueryVariables
|
||||||
>({
|
>({
|
||||||
query: LiquidityProviderFeeShareDocument,
|
query: LiquidityProviderFeeShareDocument,
|
||||||
subscriptionQuery: LiquidityProviderFeeShareUpdateDocument,
|
subscriptionQuery: LiquidityProviderFeeShareUpdateDocument,
|
||||||
@ -147,7 +153,11 @@ export const liquidityFeeShareDataProvider = makeDataProvider<
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const lpAggregatedDataProvider = makeDerivedDataProvider(
|
export const lpAggregatedDataProvider = makeDerivedDataProvider<
|
||||||
|
ReturnType<typeof getLiquidityProvision>,
|
||||||
|
never,
|
||||||
|
MarketLpQueryVariables
|
||||||
|
>(
|
||||||
[
|
[
|
||||||
liquidityProvisionsDataProvider,
|
liquidityProvisionsDataProvider,
|
||||||
marketLiquidityDataProvider,
|
marketLiquidityDataProvider,
|
||||||
|
@ -5,12 +5,10 @@ import { useDataProvider, useYesterday } from '@vegaprotocol/react-helpers';
|
|||||||
import type {
|
import type {
|
||||||
MarketCandles,
|
MarketCandles,
|
||||||
MarketMaybeWithDataAndCandles,
|
MarketMaybeWithDataAndCandles,
|
||||||
|
MarketsCandlesQueryVariables,
|
||||||
} from '@vegaprotocol/market-list';
|
} from '@vegaprotocol/market-list';
|
||||||
|
|
||||||
import {
|
import { marketListProvider } from '@vegaprotocol/market-list';
|
||||||
marketsCandlesProvider,
|
|
||||||
marketListProvider,
|
|
||||||
} from '@vegaprotocol/market-list';
|
|
||||||
|
|
||||||
import type { LiquidityProvisionMarketsQuery } from './__generated__/MarketsLiquidity';
|
import type { LiquidityProvisionMarketsQuery } from './__generated__/MarketsLiquidity';
|
||||||
import { LiquidityProvisionMarketsDocument } from './__generated__/MarketsLiquidity';
|
import { LiquidityProvisionMarketsDocument } from './__generated__/MarketsLiquidity';
|
||||||
@ -97,15 +95,18 @@ export const liquidityMarketsProvider = makeDataProvider<
|
|||||||
getData,
|
getData,
|
||||||
});
|
});
|
||||||
|
|
||||||
const liquidityProvisionProvider = makeDerivedDataProvider<Market[], never>(
|
const liquidityProvisionProvider = makeDerivedDataProvider<
|
||||||
|
Market[],
|
||||||
|
never,
|
||||||
|
Exclude<MarketsCandlesQueryVariables, 'interval'>
|
||||||
|
>(
|
||||||
[
|
[
|
||||||
marketListProvider,
|
|
||||||
(callback, client, variables) =>
|
(callback, client, variables) =>
|
||||||
marketsCandlesProvider(callback, client, {
|
marketListProvider(callback, client, {
|
||||||
...variables,
|
since: variables.since,
|
||||||
interval: Schema.Interval.INTERVAL_I1D,
|
interval: Schema.Interval.INTERVAL_I1D,
|
||||||
}),
|
}),
|
||||||
liquidityMarketsProvider,
|
(callback, client) => liquidityMarketsProvider(callback, client, undefined),
|
||||||
],
|
],
|
||||||
(parts) => {
|
(parts) => {
|
||||||
return addData(
|
return addData(
|
||||||
|
@ -31,7 +31,7 @@ describe('market depth provider update', () => {
|
|||||||
sequenceNumber: '',
|
sequenceNumber: '',
|
||||||
previousSequenceNumber: '',
|
previousSequenceNumber: '',
|
||||||
};
|
};
|
||||||
const updatedData = update(data, [delta], reload);
|
const updatedData = update(data, [delta], reload, { marketId: '1' });
|
||||||
expect(updatedData).toBe(data);
|
expect(updatedData).toBe(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -54,8 +54,12 @@ describe('market depth provider update', () => {
|
|||||||
previousSequenceNumber: '',
|
previousSequenceNumber: '',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
expect(update(data, delta.slice(0, 1), reload)).toBe(data);
|
expect(update(data, delta.slice(0, 1), reload, { marketId: '1' })).toBe(
|
||||||
expect(update(data, delta.slice(1, 2), reload)).toBe(data);
|
data
|
||||||
|
);
|
||||||
|
expect(update(data, delta.slice(1, 2), reload, { marketId: '1' })).toBe(
|
||||||
|
data
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('restarts and captureException when there is gap in updates', () => {
|
it('restarts and captureException when there is gap in updates', () => {
|
||||||
@ -72,7 +76,7 @@ describe('market depth provider update', () => {
|
|||||||
previousSequenceNumber: '12',
|
previousSequenceNumber: '12',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const updatedData = update(data, delta, reload);
|
const updatedData = update(data, delta, reload, { marketId: '1' });
|
||||||
expect(updatedData).toBe(data);
|
expect(updatedData).toBe(data);
|
||||||
expect(reload).toBeCalled();
|
expect(reload).toBeCalled();
|
||||||
expect(mockCaptureException).toBeCalled();
|
expect(mockCaptureException).toBeCalled();
|
||||||
|
@ -9,12 +9,14 @@ import {
|
|||||||
} from './__generated__/MarketDepth';
|
} from './__generated__/MarketDepth';
|
||||||
import type {
|
import type {
|
||||||
MarketDepthQuery,
|
MarketDepthQuery,
|
||||||
|
MarketDepthQueryVariables,
|
||||||
MarketDepthUpdateSubscription,
|
MarketDepthUpdateSubscription,
|
||||||
} from './__generated__/MarketDepth';
|
} from './__generated__/MarketDepth';
|
||||||
|
|
||||||
export const update: Update<
|
export const update: Update<
|
||||||
ReturnType<typeof getData>,
|
ReturnType<typeof getData>,
|
||||||
ReturnType<typeof getDelta>
|
ReturnType<typeof getDelta>,
|
||||||
|
MarketDepthQueryVariables
|
||||||
> = (data, deltas, reload) => {
|
> = (data, deltas, reload) => {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return data;
|
return data;
|
||||||
@ -61,12 +63,19 @@ export const update: Update<
|
|||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getData = (responseData: MarketDepthQuery | null) => responseData?.market;
|
const getData = (responseData: MarketDepthQuery | null) =>
|
||||||
|
responseData?.market || null;
|
||||||
|
|
||||||
const getDelta = (subscriptionData: MarketDepthUpdateSubscription) =>
|
const getDelta = (subscriptionData: MarketDepthUpdateSubscription) =>
|
||||||
subscriptionData.marketsDepthUpdate;
|
subscriptionData.marketsDepthUpdate;
|
||||||
|
|
||||||
export const marketDepthProvider = makeDataProvider({
|
export const marketDepthProvider = makeDataProvider<
|
||||||
|
MarketDepthQuery,
|
||||||
|
ReturnType<typeof getData>,
|
||||||
|
MarketDepthUpdateSubscription,
|
||||||
|
ReturnType<typeof getDelta>,
|
||||||
|
MarketDepthQueryVariables
|
||||||
|
>({
|
||||||
query: MarketDepthDocument,
|
query: MarketDepthDocument,
|
||||||
subscriptionQuery: MarketDepthUpdateDocument,
|
subscriptionQuery: MarketDepthUpdateDocument,
|
||||||
update,
|
update,
|
||||||
|
@ -7,12 +7,13 @@ import { useDataProvider } from '@vegaprotocol/react-helpers';
|
|||||||
import { marketDepthProvider } from './market-depth-provider';
|
import { marketDepthProvider } from './market-depth-provider';
|
||||||
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
||||||
import type { MarketData } from '@vegaprotocol/market-list';
|
import type { MarketData } from '@vegaprotocol/market-list';
|
||||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import type {
|
import type {
|
||||||
MarketDepthUpdateSubscription,
|
MarketDepthUpdateSubscription,
|
||||||
MarketDepthQuery,
|
MarketDepthQuery,
|
||||||
PriceLevelFieldsFragment,
|
MarketDepthQueryVariables,
|
||||||
} from './__generated__/MarketDepth';
|
} from './__generated__/MarketDepth';
|
||||||
|
import type { PriceLevelFieldsFragment } from './__generated__/MarketDepth';
|
||||||
import {
|
import {
|
||||||
compactRows,
|
compactRows,
|
||||||
updateCompactedRows,
|
updateCompactedRows,
|
||||||
@ -28,7 +29,7 @@ interface OrderbookManagerProps {
|
|||||||
|
|
||||||
export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
|
export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
|
||||||
const [resolution, setResolution] = useState(1);
|
const [resolution, setResolution] = useState(1);
|
||||||
const variables = useMemo(() => ({ marketId }), [marketId]);
|
const variables = { marketId };
|
||||||
const resolutionRef = useRef(resolution);
|
const resolutionRef = useRef(resolution);
|
||||||
const [orderbookData, setOrderbookData] = useState<OrderbookData>({
|
const [orderbookData, setOrderbookData] = useState<OrderbookData>({
|
||||||
rows: null,
|
rows: null,
|
||||||
@ -79,8 +80,8 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
|
|||||||
delta: deltas,
|
delta: deltas,
|
||||||
data: rawData,
|
data: rawData,
|
||||||
}: {
|
}: {
|
||||||
delta?: MarketDepthUpdateSubscription['marketsDepthUpdate'];
|
delta?: MarketDepthUpdateSubscription['marketsDepthUpdate'] | null;
|
||||||
data?: MarketDepthQuery['market'];
|
data: NonNullable<MarketDepthQuery['market']> | null | undefined;
|
||||||
}) => {
|
}) => {
|
||||||
if (!dataRef.current.rows) {
|
if (!dataRef.current.rows) {
|
||||||
return false;
|
return false;
|
||||||
@ -103,7 +104,11 @@ export const OrderbookManager = ({ marketId }: OrderbookManagerProps) => {
|
|||||||
[marketId, updateOrderbookData]
|
[marketId, updateOrderbookData]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data, error, loading, flush, reload } = useDataProvider({
|
const { data, error, loading, flush, reload } = useDataProvider<
|
||||||
|
MarketDepthQuery['market'] | undefined,
|
||||||
|
MarketDepthUpdateSubscription['marketsDepthUpdate'] | null,
|
||||||
|
MarketDepthQueryVariables
|
||||||
|
>({
|
||||||
dataProvider: marketDepthProvider,
|
dataProvider: marketDepthProvider,
|
||||||
update,
|
update,
|
||||||
variables,
|
variables,
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { totalFeesPercentage } from '@vegaprotocol/market-list';
|
import { totalFeesPercentage } from '@vegaprotocol/market-list';
|
||||||
|
import type { TradeFee, FeeFactors } from '@vegaprotocol/types';
|
||||||
import {
|
import {
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
formatNumberPercentage,
|
formatNumberPercentage,
|
||||||
@ -7,12 +8,7 @@ import { t } from '@vegaprotocol/i18n';
|
|||||||
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
|
|
||||||
import type { Market } from '@vegaprotocol/market-list';
|
export const FeesCell = ({ feeFactors }: { feeFactors: FeeFactors }) => (
|
||||||
export const FeesCell = ({
|
|
||||||
feeFactors,
|
|
||||||
}: {
|
|
||||||
feeFactors: Market['fees']['factors'];
|
|
||||||
}) => (
|
|
||||||
<Tooltip description={<FeesBreakdownPercentage feeFactors={feeFactors} />}>
|
<Tooltip description={<FeesBreakdownPercentage feeFactors={feeFactors} />}>
|
||||||
<span>{totalFeesPercentage(feeFactors) ?? '-'}</span>
|
<span>{totalFeesPercentage(feeFactors) ?? '-'}</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@ -21,7 +17,7 @@ export const FeesCell = ({
|
|||||||
export const FeesBreakdownPercentage = ({
|
export const FeesBreakdownPercentage = ({
|
||||||
feeFactors,
|
feeFactors,
|
||||||
}: {
|
}: {
|
||||||
feeFactors?: Market['fees']['factors'];
|
feeFactors?: FeeFactors;
|
||||||
}) => {
|
}) => {
|
||||||
if (!feeFactors) return null;
|
if (!feeFactors) return null;
|
||||||
return (
|
return (
|
||||||
@ -54,12 +50,8 @@ export const FeesBreakdown = ({
|
|||||||
symbol,
|
symbol,
|
||||||
decimals,
|
decimals,
|
||||||
}: {
|
}: {
|
||||||
fees?: {
|
fees?: TradeFee;
|
||||||
infrastructureFee: string;
|
feeFactors?: FeeFactors;
|
||||||
liquidityFee: string;
|
|
||||||
makerFee: string;
|
|
||||||
};
|
|
||||||
feeFactors?: Market['fees']['factors'];
|
|
||||||
symbol?: string;
|
symbol?: string;
|
||||||
decimals: number;
|
decimals: number;
|
||||||
}) => {
|
}) => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
query MarketInfo($marketId: ID!, $interval: Interval!, $since: String!) {
|
query MarketInfo($marketId: ID!) {
|
||||||
market(id: $marketId) {
|
market(id: $marketId) {
|
||||||
id
|
id
|
||||||
decimalPlaces
|
decimalPlaces
|
||||||
@ -32,7 +32,6 @@ query MarketInfo($marketId: ID!, $interval: Interval!, $since: String!) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tradingMode
|
|
||||||
fees {
|
fees {
|
||||||
factors {
|
factors {
|
||||||
makerFee
|
makerFee
|
||||||
@ -54,35 +53,6 @@ query MarketInfo($marketId: ID!, $interval: Interval!, $since: String!) {
|
|||||||
short
|
short
|
||||||
long
|
long
|
||||||
}
|
}
|
||||||
data {
|
|
||||||
market {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
markPrice
|
|
||||||
midPrice
|
|
||||||
bestBidVolume
|
|
||||||
bestOfferVolume
|
|
||||||
bestStaticBidVolume
|
|
||||||
bestStaticOfferVolume
|
|
||||||
bestBidPrice
|
|
||||||
bestOfferPrice
|
|
||||||
trigger
|
|
||||||
openInterest
|
|
||||||
suppliedStake
|
|
||||||
openInterest
|
|
||||||
targetStake
|
|
||||||
marketValueProxy
|
|
||||||
priceMonitoringBounds {
|
|
||||||
minValidPrice
|
|
||||||
maxValidPrice
|
|
||||||
trigger {
|
|
||||||
horizonSecs
|
|
||||||
probability
|
|
||||||
auctionExtensionSecs
|
|
||||||
}
|
|
||||||
referencePrice
|
|
||||||
}
|
|
||||||
}
|
|
||||||
liquidityMonitoringParameters {
|
liquidityMonitoringParameters {
|
||||||
triggeringRatio
|
triggeringRatio
|
||||||
targetStakeParameters {
|
targetStakeParameters {
|
||||||
@ -90,13 +60,6 @@ query MarketInfo($marketId: ID!, $interval: Interval!, $since: String!) {
|
|||||||
scalingFactor
|
scalingFactor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
candlesConnection(interval: $interval, since: $since) {
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
volume
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tradableInstrument {
|
tradableInstrument {
|
||||||
instrument {
|
instrument {
|
||||||
id
|
id
|
||||||
@ -144,10 +107,12 @@ query MarketInfo($marketId: ID!, $interval: Interval!, $since: String!) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
marginCalculator {
|
||||||
depth {
|
scalingFactors {
|
||||||
lastTrade {
|
searchLevel
|
||||||
price
|
initialMargin
|
||||||
|
collateralRelease
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,147 +0,0 @@
|
|||||||
query MarketInfoNoCandles($marketId: ID!) {
|
|
||||||
market(id: $marketId) {
|
|
||||||
id
|
|
||||||
decimalPlaces
|
|
||||||
positionDecimalPlaces
|
|
||||||
state
|
|
||||||
tradingMode
|
|
||||||
lpPriceRange
|
|
||||||
proposal {
|
|
||||||
id
|
|
||||||
rationale {
|
|
||||||
title
|
|
||||||
description
|
|
||||||
}
|
|
||||||
}
|
|
||||||
marketTimestamps {
|
|
||||||
open
|
|
||||||
close
|
|
||||||
}
|
|
||||||
openingAuction {
|
|
||||||
durationSecs
|
|
||||||
volume
|
|
||||||
}
|
|
||||||
accountsConnection {
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
type
|
|
||||||
asset {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
balance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tradingMode
|
|
||||||
fees {
|
|
||||||
factors {
|
|
||||||
makerFee
|
|
||||||
infrastructureFee
|
|
||||||
liquidityFee
|
|
||||||
}
|
|
||||||
}
|
|
||||||
priceMonitoringSettings {
|
|
||||||
parameters {
|
|
||||||
triggers {
|
|
||||||
horizonSecs
|
|
||||||
probability
|
|
||||||
auctionExtensionSecs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
riskFactors {
|
|
||||||
market
|
|
||||||
short
|
|
||||||
long
|
|
||||||
}
|
|
||||||
data {
|
|
||||||
market {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
markPrice
|
|
||||||
midPrice
|
|
||||||
bestBidVolume
|
|
||||||
bestOfferVolume
|
|
||||||
bestStaticBidVolume
|
|
||||||
bestStaticOfferVolume
|
|
||||||
bestBidPrice
|
|
||||||
bestOfferPrice
|
|
||||||
trigger
|
|
||||||
openInterest
|
|
||||||
suppliedStake
|
|
||||||
openInterest
|
|
||||||
targetStake
|
|
||||||
marketValueProxy
|
|
||||||
priceMonitoringBounds {
|
|
||||||
minValidPrice
|
|
||||||
maxValidPrice
|
|
||||||
trigger {
|
|
||||||
horizonSecs
|
|
||||||
probability
|
|
||||||
auctionExtensionSecs
|
|
||||||
}
|
|
||||||
referencePrice
|
|
||||||
}
|
|
||||||
}
|
|
||||||
liquidityMonitoringParameters {
|
|
||||||
triggeringRatio
|
|
||||||
targetStakeParameters {
|
|
||||||
timeWindow
|
|
||||||
scalingFactor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tradableInstrument {
|
|
||||||
instrument {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
code
|
|
||||||
metadata {
|
|
||||||
tags
|
|
||||||
}
|
|
||||||
product {
|
|
||||||
... on Future {
|
|
||||||
quoteName
|
|
||||||
settlementAsset {
|
|
||||||
id
|
|
||||||
symbol
|
|
||||||
name
|
|
||||||
decimals
|
|
||||||
}
|
|
||||||
dataSourceSpecForSettlementData {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
dataSourceSpecForTradingTermination {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
dataSourceSpecBinding {
|
|
||||||
settlementDataProperty
|
|
||||||
tradingTerminationProperty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
riskModel {
|
|
||||||
... on LogNormalRiskModel {
|
|
||||||
tau
|
|
||||||
riskAversionParameter
|
|
||||||
params {
|
|
||||||
r
|
|
||||||
sigma
|
|
||||||
mu
|
|
||||||
}
|
|
||||||
}
|
|
||||||
... on SimpleRiskModel {
|
|
||||||
params {
|
|
||||||
factorLong
|
|
||||||
factorShort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
depth {
|
|
||||||
lastTrade {
|
|
||||||
price
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -5,16 +5,14 @@ import * as Apollo from '@apollo/client';
|
|||||||
const defaultOptions = {} as const;
|
const defaultOptions = {} as const;
|
||||||
export type MarketInfoQueryVariables = Types.Exact<{
|
export type MarketInfoQueryVariables = Types.Exact<{
|
||||||
marketId: Types.Scalars['ID'];
|
marketId: Types.Scalars['ID'];
|
||||||
interval: Types.Interval;
|
|
||||||
since: Types.Scalars['String'];
|
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type MarketInfoQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, lpPriceRange: string, proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string } } } | null> | null } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, riskFactors?: { __typename?: 'RiskFactor', market: string, short: string, long: string } | null, data?: { __typename?: 'MarketData', markPrice: string, midPrice: string, bestBidVolume: string, bestOfferVolume: string, bestStaticBidVolume: string, bestStaticOfferVolume: string, bestBidPrice: string, bestOfferPrice: string, trigger: Types.AuctionTrigger, openInterest: string, suppliedStake?: string | null, targetStake?: string | null, marketValueProxy: string, market: { __typename?: 'Market', id: string }, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null } | null, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, candlesConnection?: { __typename?: 'CandleDataConnection', edges?: Array<{ __typename?: 'CandleEdge', node: { __typename?: 'Candle', volume: string } } | null> | null } | null, 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 }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } }, riskModel: { __typename?: 'LogNormalRiskModel', tau: number, riskAversionParameter: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } } }, depth: { __typename?: 'MarketDepth', lastTrade?: { __typename?: 'Trade', price: string } | null } } | null };
|
export type MarketInfoQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, lpPriceRange: string, proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string } } } | null> | null } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, riskFactors?: { __typename?: 'RiskFactor', market: string, short: string, long: string } | null, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } }, riskModel: { __typename?: 'LogNormalRiskModel', tau: number, riskAversionParameter: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } }, marginCalculator?: { __typename?: 'MarginCalculator', scalingFactors: { __typename?: 'ScalingFactors', searchLevel: number, initialMargin: number, collateralRelease: number } } | null } } | null };
|
||||||
|
|
||||||
|
|
||||||
export const MarketInfoDocument = gql`
|
export const MarketInfoDocument = gql`
|
||||||
query MarketInfo($marketId: ID!, $interval: Interval!, $since: String!) {
|
query MarketInfo($marketId: ID!) {
|
||||||
market(id: $marketId) {
|
market(id: $marketId) {
|
||||||
id
|
id
|
||||||
decimalPlaces
|
decimalPlaces
|
||||||
@ -48,7 +46,6 @@ export const MarketInfoDocument = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tradingMode
|
|
||||||
fees {
|
fees {
|
||||||
factors {
|
factors {
|
||||||
makerFee
|
makerFee
|
||||||
@ -70,35 +67,6 @@ export const MarketInfoDocument = gql`
|
|||||||
short
|
short
|
||||||
long
|
long
|
||||||
}
|
}
|
||||||
data {
|
|
||||||
market {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
markPrice
|
|
||||||
midPrice
|
|
||||||
bestBidVolume
|
|
||||||
bestOfferVolume
|
|
||||||
bestStaticBidVolume
|
|
||||||
bestStaticOfferVolume
|
|
||||||
bestBidPrice
|
|
||||||
bestOfferPrice
|
|
||||||
trigger
|
|
||||||
openInterest
|
|
||||||
suppliedStake
|
|
||||||
openInterest
|
|
||||||
targetStake
|
|
||||||
marketValueProxy
|
|
||||||
priceMonitoringBounds {
|
|
||||||
minValidPrice
|
|
||||||
maxValidPrice
|
|
||||||
trigger {
|
|
||||||
horizonSecs
|
|
||||||
probability
|
|
||||||
auctionExtensionSecs
|
|
||||||
}
|
|
||||||
referencePrice
|
|
||||||
}
|
|
||||||
}
|
|
||||||
liquidityMonitoringParameters {
|
liquidityMonitoringParameters {
|
||||||
triggeringRatio
|
triggeringRatio
|
||||||
targetStakeParameters {
|
targetStakeParameters {
|
||||||
@ -106,13 +74,6 @@ export const MarketInfoDocument = gql`
|
|||||||
scalingFactor
|
scalingFactor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
candlesConnection(interval: $interval, since: $since) {
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
volume
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tradableInstrument {
|
tradableInstrument {
|
||||||
instrument {
|
instrument {
|
||||||
id
|
id
|
||||||
@ -160,10 +121,12 @@ export const MarketInfoDocument = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
marginCalculator {
|
||||||
depth {
|
scalingFactors {
|
||||||
lastTrade {
|
searchLevel
|
||||||
price
|
initialMargin
|
||||||
|
collateralRelease
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,8 +146,6 @@ export const MarketInfoDocument = gql`
|
|||||||
* const { data, loading, error } = useMarketInfoQuery({
|
* const { data, loading, error } = useMarketInfoQuery({
|
||||||
* variables: {
|
* variables: {
|
||||||
* marketId: // value for 'marketId'
|
* marketId: // value for 'marketId'
|
||||||
* interval: // value for 'interval'
|
|
||||||
* since: // value for 'since'
|
|
||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
|
@ -1,190 +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 MarketInfoNoCandlesQueryVariables = Types.Exact<{
|
|
||||||
marketId: Types.Scalars['ID'];
|
|
||||||
}>;
|
|
||||||
|
|
||||||
|
|
||||||
export type MarketInfoNoCandlesQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, lpPriceRange: string, proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string } } } | null> | null } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, riskFactors?: { __typename?: 'RiskFactor', market: string, short: string, long: string } | null, data?: { __typename?: 'MarketData', markPrice: string, midPrice: string, bestBidVolume: string, bestOfferVolume: string, bestStaticBidVolume: string, bestStaticOfferVolume: string, bestBidPrice: string, bestOfferPrice: string, trigger: Types.AuctionTrigger, openInterest: string, suppliedStake?: string | null, targetStake?: string | null, marketValueProxy: string, market: { __typename?: 'Market', id: string }, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null } | null, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } }, riskModel: { __typename?: 'LogNormalRiskModel', tau: number, riskAversionParameter: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } } }, depth: { __typename?: 'MarketDepth', lastTrade?: { __typename?: 'Trade', price: string } | null } } | null };
|
|
||||||
|
|
||||||
|
|
||||||
export const MarketInfoNoCandlesDocument = gql`
|
|
||||||
query MarketInfoNoCandles($marketId: ID!) {
|
|
||||||
market(id: $marketId) {
|
|
||||||
id
|
|
||||||
decimalPlaces
|
|
||||||
positionDecimalPlaces
|
|
||||||
state
|
|
||||||
tradingMode
|
|
||||||
lpPriceRange
|
|
||||||
proposal {
|
|
||||||
id
|
|
||||||
rationale {
|
|
||||||
title
|
|
||||||
description
|
|
||||||
}
|
|
||||||
}
|
|
||||||
marketTimestamps {
|
|
||||||
open
|
|
||||||
close
|
|
||||||
}
|
|
||||||
openingAuction {
|
|
||||||
durationSecs
|
|
||||||
volume
|
|
||||||
}
|
|
||||||
accountsConnection {
|
|
||||||
edges {
|
|
||||||
node {
|
|
||||||
type
|
|
||||||
asset {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
balance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tradingMode
|
|
||||||
fees {
|
|
||||||
factors {
|
|
||||||
makerFee
|
|
||||||
infrastructureFee
|
|
||||||
liquidityFee
|
|
||||||
}
|
|
||||||
}
|
|
||||||
priceMonitoringSettings {
|
|
||||||
parameters {
|
|
||||||
triggers {
|
|
||||||
horizonSecs
|
|
||||||
probability
|
|
||||||
auctionExtensionSecs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
riskFactors {
|
|
||||||
market
|
|
||||||
short
|
|
||||||
long
|
|
||||||
}
|
|
||||||
data {
|
|
||||||
market {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
markPrice
|
|
||||||
midPrice
|
|
||||||
bestBidVolume
|
|
||||||
bestOfferVolume
|
|
||||||
bestStaticBidVolume
|
|
||||||
bestStaticOfferVolume
|
|
||||||
bestBidPrice
|
|
||||||
bestOfferPrice
|
|
||||||
trigger
|
|
||||||
openInterest
|
|
||||||
suppliedStake
|
|
||||||
openInterest
|
|
||||||
targetStake
|
|
||||||
marketValueProxy
|
|
||||||
priceMonitoringBounds {
|
|
||||||
minValidPrice
|
|
||||||
maxValidPrice
|
|
||||||
trigger {
|
|
||||||
horizonSecs
|
|
||||||
probability
|
|
||||||
auctionExtensionSecs
|
|
||||||
}
|
|
||||||
referencePrice
|
|
||||||
}
|
|
||||||
}
|
|
||||||
liquidityMonitoringParameters {
|
|
||||||
triggeringRatio
|
|
||||||
targetStakeParameters {
|
|
||||||
timeWindow
|
|
||||||
scalingFactor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tradableInstrument {
|
|
||||||
instrument {
|
|
||||||
id
|
|
||||||
name
|
|
||||||
code
|
|
||||||
metadata {
|
|
||||||
tags
|
|
||||||
}
|
|
||||||
product {
|
|
||||||
... on Future {
|
|
||||||
quoteName
|
|
||||||
settlementAsset {
|
|
||||||
id
|
|
||||||
symbol
|
|
||||||
name
|
|
||||||
decimals
|
|
||||||
}
|
|
||||||
dataSourceSpecForSettlementData {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
dataSourceSpecForTradingTermination {
|
|
||||||
id
|
|
||||||
}
|
|
||||||
dataSourceSpecBinding {
|
|
||||||
settlementDataProperty
|
|
||||||
tradingTerminationProperty
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
riskModel {
|
|
||||||
... on LogNormalRiskModel {
|
|
||||||
tau
|
|
||||||
riskAversionParameter
|
|
||||||
params {
|
|
||||||
r
|
|
||||||
sigma
|
|
||||||
mu
|
|
||||||
}
|
|
||||||
}
|
|
||||||
... on SimpleRiskModel {
|
|
||||||
params {
|
|
||||||
factorLong
|
|
||||||
factorShort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
depth {
|
|
||||||
lastTrade {
|
|
||||||
price
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* __useMarketInfoNoCandlesQuery__
|
|
||||||
*
|
|
||||||
* To run a query within a React component, call `useMarketInfoNoCandlesQuery` and pass it any options that fit your needs.
|
|
||||||
* When your component renders, `useMarketInfoNoCandlesQuery` 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 } = useMarketInfoNoCandlesQuery({
|
|
||||||
* variables: {
|
|
||||||
* marketId: // value for 'marketId'
|
|
||||||
* },
|
|
||||||
* });
|
|
||||||
*/
|
|
||||||
export function useMarketInfoNoCandlesQuery(baseOptions: Apollo.QueryHookOptions<MarketInfoNoCandlesQuery, MarketInfoNoCandlesQueryVariables>) {
|
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
|
||||||
return Apollo.useQuery<MarketInfoNoCandlesQuery, MarketInfoNoCandlesQueryVariables>(MarketInfoNoCandlesDocument, options);
|
|
||||||
}
|
|
||||||
export function useMarketInfoNoCandlesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<MarketInfoNoCandlesQuery, MarketInfoNoCandlesQueryVariables>) {
|
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
|
||||||
return Apollo.useLazyQuery<MarketInfoNoCandlesQuery, MarketInfoNoCandlesQueryVariables>(MarketInfoNoCandlesDocument, options);
|
|
||||||
}
|
|
||||||
export type MarketInfoNoCandlesQueryHookResult = ReturnType<typeof useMarketInfoNoCandlesQuery>;
|
|
||||||
export type MarketInfoNoCandlesLazyQueryHookResult = ReturnType<typeof useMarketInfoNoCandlesLazyQuery>;
|
|
||||||
export type MarketInfoNoCandlesQueryResult = Apollo.QueryResult<MarketInfoNoCandlesQuery, MarketInfoNoCandlesQueryVariables>;
|
|
@ -2,5 +2,4 @@ export * from './info-key-value-table';
|
|||||||
export * from './info-market';
|
export * from './info-market';
|
||||||
export * from './tooltip-mapping';
|
export * from './tooltip-mapping';
|
||||||
export * from './__generated__/MarketInfo';
|
export * from './__generated__/MarketInfo';
|
||||||
export * from './__generated__/MarketInfoNoCandles';
|
|
||||||
export * from './market-info-data-provider';
|
export * from './market-info-data-provider';
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { AssetDetailsTable, useAssetDataProvider } from '@vegaprotocol/assets';
|
import { AssetDetailsTable, useAssetDataProvider } from '@vegaprotocol/assets';
|
||||||
import { useEnvironment } from '@vegaprotocol/environment';
|
import { useEnvironment } from '@vegaprotocol/environment';
|
||||||
import { totalFeesPercentage } from '@vegaprotocol/market-list';
|
import {
|
||||||
|
totalFeesPercentage,
|
||||||
|
calcCandleVolume,
|
||||||
|
} from '@vegaprotocol/market-list';
|
||||||
import {
|
import {
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
formatNumber,
|
formatNumber,
|
||||||
@ -20,31 +23,20 @@ import {
|
|||||||
Splash,
|
Splash,
|
||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import pick from 'lodash/pick';
|
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { generatePath, Link } from 'react-router-dom';
|
import { generatePath, Link } from 'react-router-dom';
|
||||||
|
|
||||||
import { MarketInfoTable } from './info-key-value-table';
|
import { MarketInfoTable } from './info-key-value-table';
|
||||||
import { marketInfoDataProvider } from './market-info-data-provider';
|
import { marketInfoWithDataAndCandlesProvider } from './market-info-data-provider';
|
||||||
|
|
||||||
import type { MarketInfoQuery } from './__generated__/MarketInfo';
|
import type { MarketInfoWithDataAndCandles } from './market-info-data-provider';
|
||||||
import { MarketProposalNotification } from '@vegaprotocol/proposals';
|
import { MarketProposalNotification } from '@vegaprotocol/proposals';
|
||||||
|
|
||||||
export interface InfoProps {
|
export interface InfoProps {
|
||||||
market: MarketInfoQuery['market'];
|
market: MarketInfoWithDataAndCandles;
|
||||||
onSelect: (id: string) => void;
|
onSelect: (id: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const calcCandleVolume = (
|
|
||||||
m: MarketInfoQuery['market']
|
|
||||||
): string | undefined => {
|
|
||||||
return m?.candlesConnection?.edges
|
|
||||||
?.reduce((acc: BigNumber, c) => {
|
|
||||||
return acc.plus(new BigNumber(c?.node?.volume ?? 0));
|
|
||||||
}, new BigNumber(m?.candlesConnection?.edges[0]?.node.volume ?? 0))
|
|
||||||
?.toString();
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface MarketInfoContainerProps {
|
export interface MarketInfoContainerProps {
|
||||||
marketId: string;
|
marketId: string;
|
||||||
onSelect?: (id: string) => void;
|
onSelect?: (id: string) => void;
|
||||||
@ -67,15 +59,15 @@ export const MarketInfoContainer = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const { data, loading, error, reload } = useDataProvider({
|
const { data, loading, error, reload } = useDataProvider({
|
||||||
dataProvider: marketInfoDataProvider,
|
dataProvider: marketInfoWithDataAndCandlesProvider,
|
||||||
skipUpdates: true,
|
skipUpdates: true,
|
||||||
variables,
|
variables,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AsyncRenderer data={data} loading={loading} error={error} reload={reload}>
|
<AsyncRenderer data={data} loading={loading} error={error} reload={reload}>
|
||||||
{data && data.market ? (
|
{data ? (
|
||||||
<Info market={data.market} onSelect={(id) => onSelect?.(id)} />
|
<Info market={data} onSelect={(id) => onSelect?.(id)} />
|
||||||
) : (
|
) : (
|
||||||
<Splash>
|
<Splash>
|
||||||
<p>{t('Could not load market')}</p>
|
<p>{t('Could not load market')}</p>
|
||||||
@ -88,7 +80,6 @@ export const MarketInfoContainer = ({
|
|||||||
export const Info = ({ market, onSelect }: InfoProps) => {
|
export const Info = ({ market, onSelect }: InfoProps) => {
|
||||||
const { VEGA_TOKEN_URL, VEGA_EXPLORER_URL } = useEnvironment();
|
const { VEGA_TOKEN_URL, VEGA_EXPLORER_URL } = useEnvironment();
|
||||||
const headerClassName = 'uppercase text-lg';
|
const headerClassName = 'uppercase text-lg';
|
||||||
const dayVolume = calcCandleVolume(market);
|
|
||||||
const assetSymbol =
|
const assetSymbol =
|
||||||
market?.tradableInstrument.instrument.product?.settlementAsset.symbol || '';
|
market?.tradableInstrument.instrument.product?.settlementAsset.symbol || '';
|
||||||
const quoteUnit =
|
const quoteUnit =
|
||||||
@ -105,6 +96,8 @@ export const Info = ({ market, onSelect }: InfoProps) => {
|
|||||||
market.accountsConnection?.edges
|
market.accountsConnection?.edges
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const last24hourVolume = market.candles && calcCandleVolume(market.candles);
|
||||||
|
|
||||||
const marketDataPanels = [
|
const marketDataPanels = [
|
||||||
{
|
{
|
||||||
title: t('Current fees'),
|
title: t('Current fees'),
|
||||||
@ -131,13 +124,9 @@ export const Info = ({ market, onSelect }: InfoProps) => {
|
|||||||
<>
|
<>
|
||||||
<MarketInfoTable
|
<MarketInfoTable
|
||||||
data={{
|
data={{
|
||||||
...pick(
|
markPrice: market.data?.markPrice,
|
||||||
market.data,
|
bestBidPrice: market.data?.bestBidPrice,
|
||||||
'name',
|
bestOfferPrice: market.data?.bestOfferPrice,
|
||||||
'markPrice',
|
|
||||||
'bestBidPrice',
|
|
||||||
'bestOfferPrice'
|
|
||||||
),
|
|
||||||
quoteUnit: market.tradableInstrument.instrument.product.quoteName,
|
quoteUnit: market.tradableInstrument.instrument.product.quoteName,
|
||||||
}}
|
}}
|
||||||
decimalPlaces={market.decimalPlaces}
|
decimalPlaces={market.decimalPlaces}
|
||||||
@ -157,16 +146,17 @@ export const Info = ({ market, onSelect }: InfoProps) => {
|
|||||||
<MarketInfoTable
|
<MarketInfoTable
|
||||||
data={{
|
data={{
|
||||||
'24hourVolume':
|
'24hourVolume':
|
||||||
dayVolume && dayVolume !== '0' ? formatNumber(dayVolume) : '-',
|
last24hourVolume && last24hourVolume !== '0'
|
||||||
...pick(
|
? addDecimalsFormatNumber(
|
||||||
market.data,
|
last24hourVolume,
|
||||||
'openInterest',
|
market.positionDecimalPlaces
|
||||||
'name',
|
)
|
||||||
'bestBidVolume',
|
: '-',
|
||||||
'bestOfferVolume',
|
openInterest: market.data?.openInterest,
|
||||||
'bestStaticBidVolume',
|
bestBidVolume: market.data?.bestBidVolume,
|
||||||
'bestStaticOfferVolume'
|
bestOfferVolume: market.data?.bestOfferVolume,
|
||||||
),
|
bestStaticBidVolume: market.data?.bestStaticBidVolume,
|
||||||
|
bestStaticOfferVolume: market.data?.bestStaticOfferVolume,
|
||||||
}}
|
}}
|
||||||
decimalPlaces={market.positionDecimalPlaces}
|
decimalPlaces={market.positionDecimalPlaces}
|
||||||
/>
|
/>
|
||||||
@ -192,7 +182,9 @@ export const Info = ({ market, onSelect }: InfoProps) => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
const keyDetails = {
|
const keyDetails = {
|
||||||
...pick(market, 'decimalPlaces', 'positionDecimalPlaces', 'tradingMode'),
|
decimalPlaces: market.decimalPlaces,
|
||||||
|
positionDecimalPlaces: market.positionDecimalPlaces,
|
||||||
|
tradingMode: market.tradingMode,
|
||||||
state: Schema.MarketStateMapping[market.state],
|
state: Schema.MarketStateMapping[market.state],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,25 +1,68 @@
|
|||||||
import { makeDataProvider } from '@vegaprotocol/utils';
|
import { makeDataProvider, makeDerivedDataProvider } from '@vegaprotocol/utils';
|
||||||
import type { MarketInfoQuery } from './__generated__/MarketInfo';
|
import type {
|
||||||
|
MarketInfoQuery,
|
||||||
|
MarketInfoQueryVariables,
|
||||||
|
} from './__generated__/MarketInfo';
|
||||||
|
import {
|
||||||
|
marketDataProvider,
|
||||||
|
marketCandlesProvider,
|
||||||
|
} from '@vegaprotocol/market-list';
|
||||||
|
import type {
|
||||||
|
MarketData,
|
||||||
|
Candle,
|
||||||
|
MarketCandlesQueryVariables,
|
||||||
|
} from '@vegaprotocol/market-list';
|
||||||
import { MarketInfoDocument } from './__generated__/MarketInfo';
|
import { MarketInfoDocument } from './__generated__/MarketInfo';
|
||||||
import type { MarketInfoNoCandlesQuery } from './__generated__/MarketInfoNoCandles';
|
|
||||||
import { MarketInfoNoCandlesDocument } from './__generated__/MarketInfoNoCandles';
|
|
||||||
|
|
||||||
export const marketInfoDataProvider = makeDataProvider<
|
export type MarketInfo = NonNullable<MarketInfoQuery['market']>;
|
||||||
MarketInfoQuery,
|
export type MarketInfoWithData = MarketInfo & { data?: MarketData };
|
||||||
|
|
||||||
|
export type MarketInfoWithDataAndCandles = MarketInfoWithData & {
|
||||||
|
candles?: Candle[];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getData = (responseData: MarketInfoQuery | null) =>
|
||||||
|
responseData?.market || null;
|
||||||
|
|
||||||
|
export const marketInfoProvider = makeDataProvider<
|
||||||
MarketInfoQuery,
|
MarketInfoQuery,
|
||||||
|
MarketInfoQuery['market'],
|
||||||
never,
|
never,
|
||||||
never
|
never,
|
||||||
|
MarketInfoQueryVariables
|
||||||
>({
|
>({
|
||||||
query: MarketInfoDocument,
|
query: MarketInfoDocument,
|
||||||
getData: (responseData: MarketInfoQuery | null) => responseData,
|
getData,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const marketInfoNoCandlesDataProvider = makeDataProvider<
|
export const marketInfoWithDataProvider = makeDerivedDataProvider<
|
||||||
MarketInfoNoCandlesQuery,
|
MarketInfoWithData,
|
||||||
MarketInfoNoCandlesQuery,
|
|
||||||
never,
|
never,
|
||||||
never
|
MarketInfoQueryVariables
|
||||||
>({
|
>([marketInfoProvider, marketDataProvider], (parts) => {
|
||||||
query: MarketInfoNoCandlesDocument,
|
const market: MarketInfo | null = parts[0];
|
||||||
getData: (responseData: MarketInfoNoCandlesQuery | null) => responseData,
|
const marketData: MarketData | null = parts[1];
|
||||||
|
return (
|
||||||
|
market && {
|
||||||
|
...market,
|
||||||
|
data: marketData || undefined,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
export const marketInfoWithDataAndCandlesProvider = makeDerivedDataProvider<
|
||||||
|
MarketInfoWithDataAndCandles,
|
||||||
|
never,
|
||||||
|
MarketCandlesQueryVariables
|
||||||
|
>([marketInfoProvider, marketDataProvider, marketCandlesProvider], (parts) => {
|
||||||
|
const market: MarketInfo | null = parts[0];
|
||||||
|
const marketData: MarketData | null = parts[1];
|
||||||
|
const candles: Candle[] | null = parts[2];
|
||||||
|
return (
|
||||||
|
market && {
|
||||||
|
...market,
|
||||||
|
data: marketData || undefined,
|
||||||
|
candles: candles || undefined,
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
@ -93,40 +93,6 @@ export const marketInfoQuery = (
|
|||||||
long: '0.008508132993273576',
|
long: '0.008508132993273576',
|
||||||
},
|
},
|
||||||
lpPriceRange: '0.02',
|
lpPriceRange: '0.02',
|
||||||
data: {
|
|
||||||
__typename: 'MarketData',
|
|
||||||
market: {
|
|
||||||
__typename: 'Market',
|
|
||||||
id: '54b78c1b877e106842ae156332ccec740ad98d6bad43143ac6a029501dd7c6e0',
|
|
||||||
},
|
|
||||||
midPrice: '5749',
|
|
||||||
markPrice: '5749',
|
|
||||||
suppliedStake: '56767',
|
|
||||||
marketValueProxy: '677678',
|
|
||||||
targetStake: '56789',
|
|
||||||
bestBidVolume: '5',
|
|
||||||
bestOfferVolume: '1',
|
|
||||||
bestStaticBidVolume: '5',
|
|
||||||
bestStaticOfferVolume: '1',
|
|
||||||
openInterest: '0',
|
|
||||||
bestBidPrice: '681765',
|
|
||||||
bestOfferPrice: '681769',
|
|
||||||
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
|
|
||||||
priceMonitoringBounds: [
|
|
||||||
{
|
|
||||||
minValidPrice: '654701',
|
|
||||||
maxValidPrice: '797323',
|
|
||||||
trigger: {
|
|
||||||
horizonSecs: 43200,
|
|
||||||
probability: 0.9999999,
|
|
||||||
auctionExtensionSecs: 600,
|
|
||||||
__typename: 'PriceMonitoringTrigger',
|
|
||||||
},
|
|
||||||
referencePrice: '722625',
|
|
||||||
__typename: 'PriceMonitoringBounds',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
liquidityMonitoringParameters: {
|
liquidityMonitoringParameters: {
|
||||||
triggeringRatio: '0',
|
triggeringRatio: '0',
|
||||||
targetStakeParameters: {
|
targetStakeParameters: {
|
||||||
@ -136,7 +102,6 @@ export const marketInfoQuery = (
|
|||||||
},
|
},
|
||||||
__typename: 'LiquidityMonitoringParameters',
|
__typename: 'LiquidityMonitoringParameters',
|
||||||
},
|
},
|
||||||
candlesConnection: null,
|
|
||||||
tradableInstrument: {
|
tradableInstrument: {
|
||||||
__typename: 'TradableInstrument',
|
__typename: 'TradableInstrument',
|
||||||
instrument: {
|
instrument: {
|
||||||
@ -192,13 +157,6 @@ export const marketInfoQuery = (
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
depth: {
|
|
||||||
__typename: 'MarketDepth',
|
|
||||||
lastTrade: {
|
|
||||||
__typename: 'Trade',
|
|
||||||
price: '100',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,40 +3,59 @@ import * as Types from '@vegaprotocol/types';
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
import * as Apollo from '@apollo/client';
|
import * as Apollo from '@apollo/client';
|
||||||
const defaultOptions = {} as const;
|
const defaultOptions = {} as const;
|
||||||
export type MarketDataUpdateFieldsFragment = { __typename?: 'ObservableMarketData', marketId: string, bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, marketState: Types.MarketState, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null };
|
export type MarketDataUpdateFieldsFragment = { __typename?: 'ObservableMarketData', marketId: string, auctionEnd?: string | null, auctionStart?: string | null, bestBidPrice: string, bestBidVolume: string, bestOfferPrice: string, bestOfferVolume: string, bestStaticBidPrice: string, bestStaticBidVolume: string, bestStaticOfferPrice: string, bestStaticOfferVolume: string, indicativePrice: string, indicativeVolume: string, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, marketValueProxy: string, markPrice: string, midPrice: string, openInterest: string, staticMidPrice: string, suppliedStake?: string | null, targetStake?: string | null, trigger: Types.AuctionTrigger, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null };
|
||||||
|
|
||||||
export type MarketDataUpdateSubscriptionVariables = Types.Exact<{
|
export type MarketDataUpdateSubscriptionVariables = Types.Exact<{
|
||||||
marketId: Types.Scalars['ID'];
|
marketId: Types.Scalars['ID'];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type MarketDataUpdateSubscription = { __typename?: 'Subscription', marketsData: Array<{ __typename?: 'ObservableMarketData', marketId: string, bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, marketState: Types.MarketState, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null }> };
|
export type MarketDataUpdateSubscription = { __typename?: 'Subscription', marketsData: Array<{ __typename?: 'ObservableMarketData', marketId: string, auctionEnd?: string | null, auctionStart?: string | null, bestBidPrice: string, bestBidVolume: string, bestOfferPrice: string, bestOfferVolume: string, bestStaticBidPrice: string, bestStaticBidVolume: string, bestStaticOfferPrice: string, bestStaticOfferVolume: string, indicativePrice: string, indicativeVolume: string, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, marketValueProxy: string, markPrice: string, midPrice: string, openInterest: string, staticMidPrice: string, suppliedStake?: string | null, targetStake?: string | null, trigger: Types.AuctionTrigger, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null }> };
|
||||||
|
|
||||||
export type MarketDataFieldsFragment = { __typename?: 'MarketData', bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, marketState: Types.MarketState, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null, auctionStart?: string | null, auctionEnd?: string | null, market: { __typename?: 'Market', id: string } };
|
export type MarketDataFieldsFragment = { __typename?: 'MarketData', auctionEnd?: string | null, auctionStart?: string | null, bestBidPrice: string, bestBidVolume: string, bestOfferPrice: string, bestOfferVolume: string, bestStaticBidPrice: string, bestStaticBidVolume: string, bestStaticOfferPrice: string, bestStaticOfferVolume: string, indicativePrice: string, indicativeVolume: string, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, marketValueProxy: string, markPrice: string, midPrice: string, openInterest: string, staticMidPrice: string, suppliedStake?: string | null, targetStake?: string | null, trigger: Types.AuctionTrigger, market: { __typename?: 'Market', id: string }, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null };
|
||||||
|
|
||||||
export type MarketDataQueryVariables = Types.Exact<{
|
export type MarketDataQueryVariables = Types.Exact<{
|
||||||
marketId: Types.Scalars['ID'];
|
marketId: Types.Scalars['ID'];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type MarketDataQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', data?: { __typename?: 'MarketData', bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, marketState: Types.MarketState, indicativeVolume: string, indicativePrice: string, bestStaticBidPrice: string, bestStaticOfferPrice: string, targetStake?: string | null, suppliedStake?: string | null, auctionStart?: string | null, auctionEnd?: string | null, market: { __typename?: 'Market', id: string } } | null } }> } | null };
|
export type MarketDataQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', data?: { __typename?: 'MarketData', auctionEnd?: string | null, auctionStart?: string | null, bestBidPrice: string, bestBidVolume: string, bestOfferPrice: string, bestOfferVolume: string, bestStaticBidPrice: string, bestStaticBidVolume: string, bestStaticOfferPrice: string, bestStaticOfferVolume: string, indicativePrice: string, indicativeVolume: string, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, marketValueProxy: string, markPrice: string, midPrice: string, openInterest: string, staticMidPrice: string, suppliedStake?: string | null, targetStake?: string | null, trigger: Types.AuctionTrigger, market: { __typename?: 'Market', id: string }, priceMonitoringBounds?: Array<{ __typename?: 'PriceMonitoringBounds', minValidPrice: string, maxValidPrice: string, referencePrice: string, trigger: { __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number } }> | null } | null } }> } | null };
|
||||||
|
|
||||||
export const MarketDataUpdateFieldsFragmentDoc = gql`
|
export const MarketDataUpdateFieldsFragmentDoc = gql`
|
||||||
fragment MarketDataUpdateFields on ObservableMarketData {
|
fragment MarketDataUpdateFields on ObservableMarketData {
|
||||||
marketId
|
marketId
|
||||||
|
auctionEnd
|
||||||
|
auctionStart
|
||||||
bestBidPrice
|
bestBidPrice
|
||||||
|
bestBidVolume
|
||||||
bestOfferPrice
|
bestOfferPrice
|
||||||
markPrice
|
bestOfferVolume
|
||||||
trigger
|
|
||||||
staticMidPrice
|
|
||||||
marketTradingMode
|
|
||||||
marketState
|
|
||||||
indicativeVolume
|
|
||||||
indicativePrice
|
|
||||||
bestStaticBidPrice
|
bestStaticBidPrice
|
||||||
|
bestStaticBidVolume
|
||||||
bestStaticOfferPrice
|
bestStaticOfferPrice
|
||||||
targetStake
|
bestStaticOfferVolume
|
||||||
|
indicativePrice
|
||||||
|
indicativeVolume
|
||||||
|
marketState
|
||||||
|
marketTradingMode
|
||||||
|
marketValueProxy
|
||||||
|
markPrice
|
||||||
|
midPrice
|
||||||
|
openInterest
|
||||||
|
priceMonitoringBounds {
|
||||||
|
minValidPrice
|
||||||
|
maxValidPrice
|
||||||
|
trigger {
|
||||||
|
horizonSecs
|
||||||
|
probability
|
||||||
|
auctionExtensionSecs
|
||||||
|
}
|
||||||
|
referencePrice
|
||||||
|
}
|
||||||
|
staticMidPrice
|
||||||
suppliedStake
|
suppliedStake
|
||||||
|
targetStake
|
||||||
|
trigger
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const MarketDataFieldsFragmentDoc = gql`
|
export const MarketDataFieldsFragmentDoc = gql`
|
||||||
@ -44,21 +63,38 @@ export const MarketDataFieldsFragmentDoc = gql`
|
|||||||
market {
|
market {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
bestBidPrice
|
|
||||||
bestOfferPrice
|
|
||||||
markPrice
|
|
||||||
trigger
|
|
||||||
staticMidPrice
|
|
||||||
marketTradingMode
|
|
||||||
marketState
|
|
||||||
indicativeVolume
|
|
||||||
indicativePrice
|
|
||||||
bestStaticBidPrice
|
|
||||||
bestStaticOfferPrice
|
|
||||||
targetStake
|
|
||||||
suppliedStake
|
|
||||||
auctionStart
|
|
||||||
auctionEnd
|
auctionEnd
|
||||||
|
auctionStart
|
||||||
|
bestBidPrice
|
||||||
|
bestBidVolume
|
||||||
|
bestOfferPrice
|
||||||
|
bestOfferVolume
|
||||||
|
bestStaticBidPrice
|
||||||
|
bestStaticBidVolume
|
||||||
|
bestStaticOfferPrice
|
||||||
|
bestStaticOfferVolume
|
||||||
|
indicativePrice
|
||||||
|
indicativeVolume
|
||||||
|
marketState
|
||||||
|
marketTradingMode
|
||||||
|
marketValueProxy
|
||||||
|
markPrice
|
||||||
|
midPrice
|
||||||
|
openInterest
|
||||||
|
priceMonitoringBounds {
|
||||||
|
minValidPrice
|
||||||
|
maxValidPrice
|
||||||
|
trigger {
|
||||||
|
horizonSecs
|
||||||
|
probability
|
||||||
|
auctionExtensionSecs
|
||||||
|
}
|
||||||
|
referencePrice
|
||||||
|
}
|
||||||
|
staticMidPrice
|
||||||
|
suppliedStake
|
||||||
|
targetStake
|
||||||
|
trigger
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
export const MarketDataUpdateDocument = gql`
|
export const MarketDataUpdateDocument = gql`
|
||||||
|
@ -13,13 +13,14 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
|||||||
const { data, error, loading, reload } = useDataProvider({
|
const { data, error, loading, reload } = useDataProvider({
|
||||||
dataProvider,
|
dataProvider,
|
||||||
skipUpdates: true,
|
skipUpdates: true,
|
||||||
|
variables: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-full relative">
|
<div className="h-full relative">
|
||||||
<MarketListTable
|
<MarketListTable
|
||||||
rowData={error ? [] : data}
|
rowData={error ? [] : data}
|
||||||
noRowsOverlayComponent={() => null}
|
suppressLoadingOverlay
|
||||||
|
suppressNoRowsOverlay
|
||||||
onRowClicked={(rowEvent: RowClickedEvent) => {
|
onRowClicked={(rowEvent: RowClickedEvent) => {
|
||||||
const { data, event } = rowEvent;
|
const { data, event } = rowEvent;
|
||||||
// filters out clicks on the symbol column because it should display asset details
|
// filters out clicks on the symbol column because it should display asset details
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { makeDataProvider } from '@vegaprotocol/utils';
|
import { makeDataProvider } from '@vegaprotocol/utils';
|
||||||
import type {
|
import type {
|
||||||
MarketCandlesQuery,
|
MarketCandlesQuery,
|
||||||
|
MarketCandlesQueryVariables,
|
||||||
MarketCandlesUpdateSubscription,
|
MarketCandlesUpdateSubscription,
|
||||||
MarketCandlesFieldsFragment,
|
MarketCandlesFieldsFragment,
|
||||||
} from './__generated__/market-candles';
|
} from './__generated__/market-candles';
|
||||||
@ -36,7 +37,8 @@ export const marketCandlesProvider = makeDataProvider<
|
|||||||
MarketCandlesQuery,
|
MarketCandlesQuery,
|
||||||
Candle[],
|
Candle[],
|
||||||
MarketCandlesUpdateSubscription,
|
MarketCandlesUpdateSubscription,
|
||||||
Candle
|
Candle,
|
||||||
|
MarketCandlesQueryVariables
|
||||||
>({
|
>({
|
||||||
query: MarketCandlesDocument,
|
query: MarketCandlesDocument,
|
||||||
subscriptionQuery: MarketCandlesUpdateDocument,
|
subscriptionQuery: MarketCandlesUpdateDocument,
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import { useMemo } from 'react';
|
|
||||||
import { makeDataProvider, makeDerivedDataProvider } from '@vegaprotocol/utils';
|
import { makeDataProvider, makeDerivedDataProvider } from '@vegaprotocol/utils';
|
||||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
import {
|
import {
|
||||||
@ -11,6 +10,7 @@ import type {
|
|||||||
MarketDataFieldsFragment,
|
MarketDataFieldsFragment,
|
||||||
MarketDataUpdateSubscription,
|
MarketDataUpdateSubscription,
|
||||||
MarketDataUpdateFieldsFragment,
|
MarketDataUpdateFieldsFragment,
|
||||||
|
MarketDataQueryVariables,
|
||||||
} from './__generated__/market-data';
|
} from './__generated__/market-data';
|
||||||
|
|
||||||
export type MarketData = MarketDataFieldsFragment;
|
export type MarketData = MarketDataFieldsFragment;
|
||||||
@ -29,7 +29,7 @@ const update = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getData = (responseData: MarketDataQuery | null): MarketData | null =>
|
const getData = (responseData: MarketDataQuery | null): MarketData | null =>
|
||||||
responseData?.marketsConnection?.edges[0].node.data || null;
|
responseData?.marketsConnection?.edges[0]?.node?.data || null;
|
||||||
|
|
||||||
const getDelta = (
|
const getDelta = (
|
||||||
subscriptionData: MarketDataUpdateSubscription
|
subscriptionData: MarketDataUpdateSubscription
|
||||||
@ -39,7 +39,8 @@ export const marketDataProvider = makeDataProvider<
|
|||||||
MarketDataQuery,
|
MarketDataQuery,
|
||||||
MarketData,
|
MarketData,
|
||||||
MarketDataUpdateSubscription,
|
MarketDataUpdateSubscription,
|
||||||
MarketDataUpdateFieldsFragment
|
MarketDataUpdateFieldsFragment,
|
||||||
|
MarketDataQueryVariables
|
||||||
>({
|
>({
|
||||||
query: MarketDataDocument,
|
query: MarketDataDocument,
|
||||||
subscriptionQuery: MarketDataUpdateDocument,
|
subscriptionQuery: MarketDataUpdateDocument,
|
||||||
@ -48,6 +49,12 @@ export const marketDataProvider = makeDataProvider<
|
|||||||
getDelta,
|
getDelta,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const markPriceProvider = makeDerivedDataProvider<
|
||||||
|
string,
|
||||||
|
never,
|
||||||
|
MarketDataQueryVariables
|
||||||
|
>([marketDataProvider], ([marketData]) => (marketData as MarketData).markPrice);
|
||||||
|
|
||||||
export type StaticMarketData = Pick<
|
export type StaticMarketData = Pick<
|
||||||
MarketData,
|
MarketData,
|
||||||
| 'marketTradingMode'
|
| 'marketTradingMode'
|
||||||
@ -63,7 +70,8 @@ export type StaticMarketData = Pick<
|
|||||||
|
|
||||||
export const staticMarketDataProvider = makeDerivedDataProvider<
|
export const staticMarketDataProvider = makeDerivedDataProvider<
|
||||||
StaticMarketData,
|
StaticMarketData,
|
||||||
never
|
never,
|
||||||
|
MarketDataQueryVariables
|
||||||
>([marketDataProvider], (parts, variables, prevData) => {
|
>([marketDataProvider], (parts, variables, prevData) => {
|
||||||
const marketData = parts[0] as ReturnType<typeof getData>;
|
const marketData = parts[0] as ReturnType<typeof getData>;
|
||||||
if (!marketData) {
|
if (!marketData) {
|
||||||
@ -89,10 +97,9 @@ export const staticMarketDataProvider = makeDerivedDataProvider<
|
|||||||
});
|
});
|
||||||
|
|
||||||
export const useStaticMarketData = (marketId?: string, skip?: boolean) => {
|
export const useStaticMarketData = (marketId?: string, skip?: boolean) => {
|
||||||
const variables = useMemo(() => ({ marketId }), [marketId]);
|
|
||||||
return useDataProvider({
|
return useDataProvider({
|
||||||
dataProvider: staticMarketDataProvider,
|
dataProvider: staticMarketDataProvider,
|
||||||
variables,
|
variables: { marketId: marketId || '' },
|
||||||
skip: skip || !marketId,
|
skip: skip || !marketId,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@ -1,18 +1,37 @@
|
|||||||
fragment MarketDataUpdateFields on ObservableMarketData {
|
fragment MarketDataUpdateFields on ObservableMarketData {
|
||||||
marketId
|
marketId
|
||||||
|
auctionEnd
|
||||||
|
auctionStart
|
||||||
bestBidPrice
|
bestBidPrice
|
||||||
|
bestBidVolume
|
||||||
bestOfferPrice
|
bestOfferPrice
|
||||||
markPrice
|
bestOfferVolume
|
||||||
trigger
|
|
||||||
staticMidPrice
|
|
||||||
marketTradingMode
|
|
||||||
marketState
|
|
||||||
indicativeVolume
|
|
||||||
indicativePrice
|
|
||||||
bestStaticBidPrice
|
bestStaticBidPrice
|
||||||
|
bestStaticBidVolume
|
||||||
bestStaticOfferPrice
|
bestStaticOfferPrice
|
||||||
targetStake
|
bestStaticOfferVolume
|
||||||
|
indicativePrice
|
||||||
|
indicativeVolume
|
||||||
|
marketState
|
||||||
|
marketTradingMode
|
||||||
|
marketValueProxy
|
||||||
|
markPrice
|
||||||
|
midPrice
|
||||||
|
openInterest
|
||||||
|
priceMonitoringBounds {
|
||||||
|
minValidPrice
|
||||||
|
maxValidPrice
|
||||||
|
trigger {
|
||||||
|
horizonSecs
|
||||||
|
probability
|
||||||
|
auctionExtensionSecs
|
||||||
|
}
|
||||||
|
referencePrice
|
||||||
|
}
|
||||||
|
staticMidPrice
|
||||||
suppliedStake
|
suppliedStake
|
||||||
|
targetStake
|
||||||
|
trigger
|
||||||
}
|
}
|
||||||
|
|
||||||
subscription MarketDataUpdate($marketId: ID!) {
|
subscription MarketDataUpdate($marketId: ID!) {
|
||||||
@ -25,21 +44,38 @@ fragment MarketDataFields on MarketData {
|
|||||||
market {
|
market {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
bestBidPrice
|
|
||||||
bestOfferPrice
|
|
||||||
markPrice
|
|
||||||
trigger
|
|
||||||
staticMidPrice
|
|
||||||
marketTradingMode
|
|
||||||
marketState
|
|
||||||
indicativeVolume
|
|
||||||
indicativePrice
|
|
||||||
bestStaticBidPrice
|
|
||||||
bestStaticOfferPrice
|
|
||||||
targetStake
|
|
||||||
suppliedStake
|
|
||||||
auctionStart
|
|
||||||
auctionEnd
|
auctionEnd
|
||||||
|
auctionStart
|
||||||
|
bestBidPrice
|
||||||
|
bestBidVolume
|
||||||
|
bestOfferPrice
|
||||||
|
bestOfferVolume
|
||||||
|
bestStaticBidPrice
|
||||||
|
bestStaticBidVolume
|
||||||
|
bestStaticOfferPrice
|
||||||
|
bestStaticOfferVolume
|
||||||
|
indicativePrice
|
||||||
|
indicativeVolume
|
||||||
|
marketState
|
||||||
|
marketTradingMode
|
||||||
|
marketValueProxy
|
||||||
|
markPrice
|
||||||
|
midPrice
|
||||||
|
openInterest
|
||||||
|
priceMonitoringBounds {
|
||||||
|
minValidPrice
|
||||||
|
maxValidPrice
|
||||||
|
trigger {
|
||||||
|
horizonSecs
|
||||||
|
probability
|
||||||
|
auctionExtensionSecs
|
||||||
|
}
|
||||||
|
referencePrice
|
||||||
|
}
|
||||||
|
staticMidPrice
|
||||||
|
suppliedStake
|
||||||
|
targetStake
|
||||||
|
trigger
|
||||||
}
|
}
|
||||||
|
|
||||||
query MarketData($marketId: ID!) {
|
query MarketData($marketId: ID!) {
|
||||||
|
@ -44,34 +44,62 @@ const marketDataFields: MarketDataFieldsFragment = {
|
|||||||
id: 'market-0',
|
id: 'market-0',
|
||||||
__typename: 'Market',
|
__typename: 'Market',
|
||||||
},
|
},
|
||||||
auctionStart: '2022-06-21T17:18:43.484055236Z',
|
|
||||||
auctionEnd: '2022-06-21T17:18:43.484055236Z',
|
auctionEnd: '2022-06-21T17:18:43.484055236Z',
|
||||||
targetStake: '1000000',
|
auctionStart: '2022-06-21T17:18:43.484055236Z',
|
||||||
suppliedStake: '1000',
|
bestBidPrice: '4412690058',
|
||||||
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
bestBidVolume: '1',
|
||||||
marketState: Schema.MarketState.STATE_ACTIVE,
|
bestOfferPrice: '4812690058',
|
||||||
staticMidPrice: '0',
|
bestOfferVolume: '3',
|
||||||
|
bestStaticBidPrice: '4512690058',
|
||||||
|
bestStaticBidVolume: '2',
|
||||||
|
bestStaticOfferPrice: '4712690058',
|
||||||
|
bestStaticOfferVolume: '4',
|
||||||
indicativePrice: '0',
|
indicativePrice: '0',
|
||||||
bestStaticBidPrice: '0',
|
|
||||||
bestStaticOfferPrice: '0',
|
|
||||||
indicativeVolume: '0',
|
indicativeVolume: '0',
|
||||||
bestBidPrice: '0',
|
marketState: Schema.MarketState.STATE_ACTIVE,
|
||||||
bestOfferPrice: '0',
|
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||||
|
marketValueProxy: '2000000',
|
||||||
markPrice: '4612690058',
|
markPrice: '4612690058',
|
||||||
|
midPrice: '4612690000',
|
||||||
|
openInterest: '0',
|
||||||
|
priceMonitoringBounds: [
|
||||||
|
{
|
||||||
|
minValidPrice: '654701',
|
||||||
|
maxValidPrice: '797323',
|
||||||
|
trigger: {
|
||||||
|
horizonSecs: 43200,
|
||||||
|
probability: 0.9999999,
|
||||||
|
auctionExtensionSecs: 600,
|
||||||
|
__typename: 'PriceMonitoringTrigger',
|
||||||
|
},
|
||||||
|
referencePrice: '722625',
|
||||||
|
__typename: 'PriceMonitoringBounds',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
staticMidPrice: '4612690001',
|
||||||
|
suppliedStake: '1000',
|
||||||
|
targetStake: '1000000',
|
||||||
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
|
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
|
||||||
};
|
};
|
||||||
|
|
||||||
const marketDataUpdateFields: MarketDataUpdateFieldsFragment = {
|
const marketDataUpdateFields: MarketDataUpdateFieldsFragment = {
|
||||||
marketId: 'market-0',
|
|
||||||
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
|
||||||
marketState: Schema.MarketState.STATE_ACTIVE,
|
|
||||||
staticMidPrice: '0',
|
|
||||||
indicativePrice: '0',
|
|
||||||
bestStaticBidPrice: '0',
|
|
||||||
bestStaticOfferPrice: '0',
|
|
||||||
indicativeVolume: '0',
|
|
||||||
bestBidPrice: '0',
|
bestBidPrice: '0',
|
||||||
|
bestBidVolume: '0',
|
||||||
bestOfferPrice: '0',
|
bestOfferPrice: '0',
|
||||||
|
bestOfferVolume: '0',
|
||||||
|
bestStaticBidPrice: '0',
|
||||||
|
bestStaticBidVolume: '0',
|
||||||
|
bestStaticOfferPrice: '0',
|
||||||
|
bestStaticOfferVolume: '0',
|
||||||
|
indicativePrice: '0',
|
||||||
|
indicativeVolume: '0',
|
||||||
|
marketId: 'market-0',
|
||||||
|
marketState: Schema.MarketState.STATE_ACTIVE,
|
||||||
|
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||||
|
marketValueProxy: '',
|
||||||
markPrice: '4612690058',
|
markPrice: '4612690058',
|
||||||
|
midPrice: '0',
|
||||||
|
openInterest: '0',
|
||||||
|
staticMidPrice: '0',
|
||||||
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
|
trigger: Schema.AuctionTrigger.AUCTION_TRIGGER_UNSPECIFIED,
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { makeDataProvider } from '@vegaprotocol/utils';
|
import { makeDataProvider } from '@vegaprotocol/utils';
|
||||||
import { MarketsCandlesDocument } from './__generated__/markets-candles';
|
import { MarketsCandlesDocument } from './__generated__/markets-candles';
|
||||||
import type { MarketsCandlesQuery } from './__generated__/markets-candles';
|
import type {
|
||||||
|
MarketsCandlesQuery,
|
||||||
|
MarketsCandlesQueryVariables,
|
||||||
|
} from './__generated__/markets-candles';
|
||||||
import type { Candle } from './market-candles-provider';
|
import type { Candle } from './market-candles-provider';
|
||||||
|
|
||||||
export interface MarketCandles {
|
export interface MarketCandles {
|
||||||
@ -22,7 +25,8 @@ export const marketsCandlesProvider = makeDataProvider<
|
|||||||
MarketsCandlesQuery,
|
MarketsCandlesQuery,
|
||||||
MarketCandles[],
|
MarketCandles[],
|
||||||
never,
|
never,
|
||||||
never
|
never,
|
||||||
|
MarketsCandlesQueryVariables
|
||||||
>({
|
>({
|
||||||
query: MarketsCandlesDocument,
|
query: MarketsCandlesDocument,
|
||||||
getData,
|
getData,
|
||||||
|
@ -4,6 +4,8 @@ import type {
|
|||||||
MarketsQuery,
|
MarketsQuery,
|
||||||
MarketFieldsFragment,
|
MarketFieldsFragment,
|
||||||
} from './__generated__/markets';
|
} from './__generated__/markets';
|
||||||
|
import type { MarketsCandlesQueryVariables } from './__generated__/markets-candles';
|
||||||
|
|
||||||
import { marketsDataProvider } from './markets-data-provider';
|
import { marketsDataProvider } from './markets-data-provider';
|
||||||
import { marketDataProvider } from './market-data-provider';
|
import { marketDataProvider } from './market-data-provider';
|
||||||
import { marketsCandlesProvider } from './markets-candles-provider';
|
import { marketsCandlesProvider } from './markets-candles-provider';
|
||||||
@ -37,7 +39,7 @@ export const marketProvider = makeDerivedDataProvider<
|
|||||||
never,
|
never,
|
||||||
{ marketId: string }
|
{ marketId: string }
|
||||||
>(
|
>(
|
||||||
[marketsProvider],
|
[(callback, client) => marketsProvider(callback, client, undefined)],
|
||||||
([markets], variables) =>
|
([markets], variables) =>
|
||||||
((markets as ReturnType<typeof getData>) || []).find(
|
((markets as ReturnType<typeof getData>) || []).find(
|
||||||
(market) => market.id === variables?.marketId
|
(market) => market.id === variables?.marketId
|
||||||
@ -84,10 +86,11 @@ const addCandles = <T extends Market>(
|
|||||||
|
|
||||||
export const marketsWithCandlesProvider = makeDerivedDataProvider<
|
export const marketsWithCandlesProvider = makeDerivedDataProvider<
|
||||||
MarketMaybeWithCandles[],
|
MarketMaybeWithCandles[],
|
||||||
never
|
never,
|
||||||
|
MarketsCandlesQueryVariables
|
||||||
>(
|
>(
|
||||||
[
|
[
|
||||||
(callback, client) => activeMarketsProvider(callback, client),
|
(callback, client) => activeMarketsProvider(callback, client, undefined),
|
||||||
marketsCandlesProvider,
|
marketsCandlesProvider,
|
||||||
],
|
],
|
||||||
(parts) => addCandles(parts[0] as Market[], parts[1] as MarketCandles[])
|
(parts) => addCandles(parts[0] as Market[], parts[1] as MarketCandles[])
|
||||||
@ -113,10 +116,11 @@ export type MarketMaybeWithDataAndCandles = MarketMaybeWithData &
|
|||||||
|
|
||||||
export const marketListProvider = makeDerivedDataProvider<
|
export const marketListProvider = makeDerivedDataProvider<
|
||||||
MarketMaybeWithDataAndCandles[],
|
MarketMaybeWithDataAndCandles[],
|
||||||
never
|
never,
|
||||||
|
MarketsCandlesQueryVariables
|
||||||
>(
|
>(
|
||||||
[
|
[
|
||||||
(callback, client) => marketsWithDataProvider(callback, client),
|
(callback, client) => marketsWithDataProvider(callback, client, undefined),
|
||||||
marketsCandlesProvider,
|
marketsCandlesProvider,
|
||||||
],
|
],
|
||||||
(parts) =>
|
(parts) =>
|
||||||
|
@ -76,7 +76,9 @@ const orderMatchFilters = (
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getData = (responseData: OrdersQuery | null) =>
|
const getData = (
|
||||||
|
responseData: OrdersQuery | null
|
||||||
|
): Edge<OrderFieldsFragment>[] =>
|
||||||
responseData?.party?.ordersConnection?.edges || [];
|
responseData?.party?.ordersConnection?.edges || [];
|
||||||
|
|
||||||
const getDelta = (subscriptionData: OrdersUpdateSubscription) =>
|
const getDelta = (subscriptionData: OrdersUpdateSubscription) =>
|
||||||
@ -142,14 +144,19 @@ export const update = (
|
|||||||
__typename: 'Order',
|
__typename: 'Order',
|
||||||
},
|
},
|
||||||
cursor: '',
|
cursor: '',
|
||||||
__typename: 'OrderEdge',
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ordersProvider = makeDataProvider({
|
export const ordersProvider = makeDataProvider<
|
||||||
|
OrdersQuery,
|
||||||
|
ReturnType<typeof getData>,
|
||||||
|
OrdersUpdateSubscription,
|
||||||
|
ReturnType<typeof getDelta>,
|
||||||
|
OrdersQueryVariables
|
||||||
|
>({
|
||||||
query: OrdersDocument,
|
query: OrdersDocument,
|
||||||
subscriptionQuery: OrdersUpdateDocument,
|
subscriptionQuery: OrdersUpdateDocument,
|
||||||
update,
|
update,
|
||||||
@ -168,7 +175,10 @@ export const ordersWithMarketProvider = makeDerivedDataProvider<
|
|||||||
Order[],
|
Order[],
|
||||||
OrdersQueryVariables
|
OrdersQueryVariables
|
||||||
>(
|
>(
|
||||||
[ordersProvider, marketsProvider],
|
[
|
||||||
|
ordersProvider,
|
||||||
|
(callback, client) => marketsProvider(callback, client, undefined),
|
||||||
|
],
|
||||||
(partsData): OrderEdge[] =>
|
(partsData): OrderEdge[] =>
|
||||||
((partsData[0] as ReturnType<typeof getData>) || []).map((edge) => ({
|
((partsData[0] as ReturnType<typeof getData>) || []).map((edge) => ({
|
||||||
cursor: edge.cursor,
|
cursor: edge.cursor,
|
||||||
@ -183,7 +193,13 @@ export const ordersWithMarketProvider = makeDerivedDataProvider<
|
|||||||
combineInsertionData<Order>
|
combineInsertionData<Order>
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasActiveOrderProviderInternal = makeDataProvider({
|
const hasActiveOrderProviderInternal = makeDataProvider<
|
||||||
|
OrdersQuery,
|
||||||
|
boolean,
|
||||||
|
OrdersUpdateSubscription,
|
||||||
|
ReturnType<typeof getDelta>,
|
||||||
|
OrdersQueryVariables
|
||||||
|
>({
|
||||||
query: OrdersDocument,
|
query: OrdersDocument,
|
||||||
subscriptionQuery: OrdersUpdateDocument,
|
subscriptionQuery: OrdersUpdateDocument,
|
||||||
update: (
|
update: (
|
||||||
|
@ -9,6 +9,8 @@ import type {
|
|||||||
} from 'ag-grid-community';
|
} from 'ag-grid-community';
|
||||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
import { Button } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
|
import type { GridReadyEvent } from 'ag-grid-community';
|
||||||
|
|
||||||
import { OrderListTable } from '../order-list/order-list';
|
import { OrderListTable } from '../order-list/order-list';
|
||||||
import { useOrderListData } from './use-order-list-data';
|
import { useOrderListData } from './use-order-list-data';
|
||||||
import { useHasActiveOrder } from '../../order-hooks/use-has-active-order';
|
import { useHasActiveOrder } from '../../order-hooks/use-has-active-order';
|
||||||
@ -156,6 +158,16 @@ export const OrderListManager = ({
|
|||||||
},
|
},
|
||||||
[create]
|
[create]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const onGridReady = useCallback(
|
||||||
|
(event: GridReadyEvent) => {
|
||||||
|
event.api.setDatasource({
|
||||||
|
getRows,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[getRows]
|
||||||
|
);
|
||||||
|
|
||||||
const cancelAll = useCallback(
|
const cancelAll = useCallback(
|
||||||
(marketId?: string) => {
|
(marketId?: string) => {
|
||||||
create({
|
create({
|
||||||
@ -177,7 +189,7 @@ export const OrderListManager = ({
|
|||||||
<OrderListTable
|
<OrderListTable
|
||||||
ref={gridRef}
|
ref={gridRef}
|
||||||
rowModelType="infinite"
|
rowModelType="infinite"
|
||||||
datasource={{ getRows }}
|
onGridReady={onGridReady}
|
||||||
onBodyScrollEnd={onBodyScrollEnd}
|
onBodyScrollEnd={onBodyScrollEnd}
|
||||||
onBodyScroll={onBodyScroll}
|
onBodyScroll={onBodyScroll}
|
||||||
onFilterChanged={onFilterChanged}
|
onFilterChanged={onFilterChanged}
|
||||||
|
@ -139,18 +139,15 @@ export const useOrderListData = ({
|
|||||||
});
|
});
|
||||||
totalCountRef.current = totalCount;
|
totalCountRef.current = totalCount;
|
||||||
|
|
||||||
const getRows = makeInfiniteScrollGetRows<OrderEdge>(
|
const getRows = useRef(
|
||||||
dataRef,
|
makeInfiniteScrollGetRows<OrderEdge>(dataRef, totalCountRef, load, newRows)
|
||||||
totalCountRef,
|
|
||||||
load,
|
|
||||||
newRows
|
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
loading,
|
loading,
|
||||||
error,
|
error,
|
||||||
data,
|
data,
|
||||||
addNewRows,
|
addNewRows,
|
||||||
getRows,
|
getRows: getRows.current,
|
||||||
reload,
|
reload,
|
||||||
makeBottomPlaceholders,
|
makeBottomPlaceholders,
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
export * from './__generated__/OrdersSubscription';
|
export * from './__generated__/OrdersSubscription';
|
||||||
export * from './use-has-active-order';
|
export * from './use-has-active-order';
|
||||||
export * from './use-order-cancel';
|
export * from './use-order-cancel';
|
||||||
export * from './use-order-submit';
|
|
||||||
export * from './use-order-edit';
|
export * from './use-order-edit';
|
||||||
|
export * from './use-order-submit';
|
||||||
export * from './use-order-update';
|
export * from './use-order-update';
|
||||||
|
export * from './use-pending-orders-volume';
|
||||||
export * from './use-order-store';
|
export * from './use-order-store';
|
||||||
|
74
libs/orders/src/lib/order-hooks/use-pending-orders-volume.ts
Normal file
74
libs/orders/src/lib/order-hooks/use-pending-orders-volume.ts
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
import { useState, useCallback } from 'react';
|
||||||
|
import { OrderStatus, Side } from '@vegaprotocol/types';
|
||||||
|
import { ordersProvider } from '../components/order-data-provider/order-data-provider';
|
||||||
|
import type { OrderFieldsFragment } from '../components/order-data-provider/__generated__/Orders';
|
||||||
|
import type { Edge } from '@vegaprotocol/utils';
|
||||||
|
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
const sumVolume = (orders: (Edge<OrderFieldsFragment> | null)[], side: Side) =>
|
||||||
|
orders
|
||||||
|
.reduce(
|
||||||
|
(sum, order) =>
|
||||||
|
order?.node.side === side
|
||||||
|
? sum +
|
||||||
|
BigInt(
|
||||||
|
order?.node.status === OrderStatus.STATUS_PARTIALLY_FILLED
|
||||||
|
? order?.node.remaining
|
||||||
|
: order?.node.size
|
||||||
|
)
|
||||||
|
: sum,
|
||||||
|
BigInt(0)
|
||||||
|
)
|
||||||
|
.toString();
|
||||||
|
|
||||||
|
export const useActiveOrdersVolumeAndMargin = (
|
||||||
|
partyId: string | null | undefined,
|
||||||
|
marketId: string
|
||||||
|
) => {
|
||||||
|
const [buyVolume, setBuyVolume] = useState<string | undefined>();
|
||||||
|
const [sellVolume, setSellVolume] = useState<string | undefined>();
|
||||||
|
const [buyInitialMargin, setBuyInitialMargin] = useState<
|
||||||
|
string | undefined
|
||||||
|
>();
|
||||||
|
const [sellInitialMargin, setSellInitialMargin] = useState<
|
||||||
|
string | undefined
|
||||||
|
>();
|
||||||
|
const update = useCallback(
|
||||||
|
({ data }: { data: (Edge<OrderFieldsFragment> | null)[] | null }) => {
|
||||||
|
if (!data) {
|
||||||
|
setBuyVolume(undefined);
|
||||||
|
setSellVolume(undefined);
|
||||||
|
setBuyInitialMargin(undefined);
|
||||||
|
setSellInitialMargin(undefined);
|
||||||
|
} else {
|
||||||
|
setBuyVolume(sumVolume(data, Side.SIDE_BUY));
|
||||||
|
setSellVolume(sumVolume(data, Side.SIDE_SELL));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
useDataProvider({
|
||||||
|
dataProvider: ordersProvider,
|
||||||
|
update,
|
||||||
|
variables: {
|
||||||
|
partyId: partyId || '',
|
||||||
|
marketId,
|
||||||
|
filter: {
|
||||||
|
status: [
|
||||||
|
OrderStatus.STATUS_ACTIVE,
|
||||||
|
OrderStatus.STATUS_PARTIALLY_FILLED,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
skip: !partyId,
|
||||||
|
});
|
||||||
|
return buyVolume || sellVolume
|
||||||
|
? {
|
||||||
|
buyVolume,
|
||||||
|
sellVolume,
|
||||||
|
buyInitialMargin,
|
||||||
|
sellInitialMargin,
|
||||||
|
}
|
||||||
|
: undefined;
|
||||||
|
};
|
@ -1,8 +1,11 @@
|
|||||||
export * from './lib/__generated__/Positions';
|
export * from './lib/__generated__/Positions';
|
||||||
export * from './lib/positions-container';
|
export * from './lib/positions-container';
|
||||||
export * from './lib/positions-data-providers';
|
export * from './lib/positions-data-providers';
|
||||||
|
export * from './lib/margin-data-provider';
|
||||||
|
export * from './lib/margin-calculator';
|
||||||
export * from './lib/positions-table';
|
export * from './lib/positions-table';
|
||||||
export * from './lib/use-close-position';
|
export * from './lib/use-close-position';
|
||||||
export * from './lib/use-positions-data';
|
|
||||||
export * from './lib/use-market-position-open-volume';
|
|
||||||
export * from './lib/use-market-margin';
|
export * from './lib/use-market-margin';
|
||||||
|
export * from './lib/use-market-position-open-volume';
|
||||||
|
export * from './lib/use-open-volume';
|
||||||
|
export * from './lib/use-positions-data';
|
||||||
|
@ -5,9 +5,9 @@ import * as Apollo from '@apollo/client';
|
|||||||
const defaultOptions = {} as const;
|
const defaultOptions = {} as const;
|
||||||
export type PositionFieldsFragment = { __typename?: 'Position', realisedPNL: string, openVolume: string, unrealisedPNL: string, averageEntryPrice: string, updatedAt?: any | null, positionStatus: Types.PositionStatus, lossSocializationAmount: string, market: { __typename?: 'Market', id: string } };
|
export type PositionFieldsFragment = { __typename?: 'Position', realisedPNL: string, openVolume: string, unrealisedPNL: string, averageEntryPrice: string, updatedAt?: any | null, positionStatus: Types.PositionStatus, lossSocializationAmount: string, market: { __typename?: 'Market', id: string } };
|
||||||
|
|
||||||
export type PositionsQueryVariables = Types.Exact<{
|
export type PositionsQueryVariables = {
|
||||||
partyId: Types.Scalars['ID'];
|
partyId: Types.Scalars['ID'];
|
||||||
}>;
|
};
|
||||||
|
|
||||||
|
|
||||||
export type PositionsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, positionsConnection?: { __typename?: 'PositionConnection', edges?: Array<{ __typename?: 'PositionEdge', node: { __typename?: 'Position', realisedPNL: string, openVolume: string, unrealisedPNL: string, averageEntryPrice: string, updatedAt?: any | null, positionStatus: Types.PositionStatus, lossSocializationAmount: string, market: { __typename?: 'Market', id: string } } }> | null } | null } | null };
|
export type PositionsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, positionsConnection?: { __typename?: 'PositionConnection', edges?: Array<{ __typename?: 'PositionEdge', node: { __typename?: 'Position', realisedPNL: string, openVolume: string, unrealisedPNL: string, averageEntryPrice: string, updatedAt?: any | null, positionStatus: Types.PositionStatus, lossSocializationAmount: string, market: { __typename?: 'Market', id: string } } }> | null } | null } | null };
|
||||||
|
95
libs/positions/src/lib/margin-calculator.ts
Normal file
95
libs/positions/src/lib/margin-calculator.ts
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
import { toBigNum } from '@vegaprotocol/utils';
|
||||||
|
import { Side, MarketTradingMode, OrderType } from '@vegaprotocol/types';
|
||||||
|
import type { ScalingFactors, RiskFactor } from '@vegaprotocol/types';
|
||||||
|
import type { MarketData } from '@vegaprotocol/market-list';
|
||||||
|
|
||||||
|
export const isMarketInAuction = (marketTradingMode: MarketTradingMode) => {
|
||||||
|
return [
|
||||||
|
MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
|
||||||
|
MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
|
||||||
|
MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
|
||||||
|
].includes(marketTradingMode);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the market price based on market mode (auction or not auction)
|
||||||
|
*/
|
||||||
|
export const getMarketPrice = ({
|
||||||
|
marketTradingMode,
|
||||||
|
indicativePrice,
|
||||||
|
markPrice,
|
||||||
|
}: Pick<MarketData, 'marketTradingMode' | 'indicativePrice' | 'markPrice'>) => {
|
||||||
|
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 (
|
||||||
|
indicativePrice &&
|
||||||
|
indicativePrice !== '0' &&
|
||||||
|
BigInt(indicativePrice) !== BigInt(0)
|
||||||
|
) {
|
||||||
|
return indicativePrice;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return markPrice;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the price for an order, order limit this is the user
|
||||||
|
* entered value, for market this will be the mark price or
|
||||||
|
* if in auction the indicative uncrossing price
|
||||||
|
*/
|
||||||
|
export const getDerivedPrice = (
|
||||||
|
order: {
|
||||||
|
type?: OrderType | null;
|
||||||
|
price?: string;
|
||||||
|
},
|
||||||
|
marketData: Pick<
|
||||||
|
MarketData,
|
||||||
|
'marketTradingMode' | 'indicativePrice' | 'markPrice'
|
||||||
|
>
|
||||||
|
) => {
|
||||||
|
// If order type is market we should use either the mark price
|
||||||
|
// or the uncrossing price. If order type is limit use the price
|
||||||
|
// the user has input
|
||||||
|
|
||||||
|
// Use the market price if order is a market order
|
||||||
|
if (order.type === OrderType.TYPE_LIMIT && order.price) {
|
||||||
|
return order.price;
|
||||||
|
}
|
||||||
|
return getMarketPrice(marketData);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const calculateMargins = ({
|
||||||
|
size,
|
||||||
|
side,
|
||||||
|
price,
|
||||||
|
decimals,
|
||||||
|
positionDecimalPlaces,
|
||||||
|
decimalPlaces,
|
||||||
|
scalingFactors,
|
||||||
|
riskFactors,
|
||||||
|
}: {
|
||||||
|
size: string;
|
||||||
|
side: Side;
|
||||||
|
positionDecimalPlaces: number;
|
||||||
|
decimalPlaces: number;
|
||||||
|
decimals: number;
|
||||||
|
price: string;
|
||||||
|
scalingFactors?: ScalingFactors;
|
||||||
|
riskFactors: RiskFactor;
|
||||||
|
}) => {
|
||||||
|
const maintenanceMargin = toBigNum(size, positionDecimalPlaces)
|
||||||
|
.multipliedBy(
|
||||||
|
side === Side.SIDE_SELL ? riskFactors.short : riskFactors.long
|
||||||
|
)
|
||||||
|
.multipliedBy(toBigNum(price, decimalPlaces));
|
||||||
|
return {
|
||||||
|
maintenanceMargin: maintenanceMargin
|
||||||
|
.multipliedBy(Math.pow(10, decimals))
|
||||||
|
.toFixed(0),
|
||||||
|
initialMargin: maintenanceMargin
|
||||||
|
.multipliedBy(scalingFactors?.initialMargin ?? 1)
|
||||||
|
.multipliedBy(Math.pow(10, decimals))
|
||||||
|
.toFixed(0),
|
||||||
|
};
|
||||||
|
};
|
@ -1,5 +1,9 @@
|
|||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import { makeDataProvider, removePaginationWrapper } from '@vegaprotocol/utils';
|
import {
|
||||||
|
makeDataProvider,
|
||||||
|
makeDerivedDataProvider,
|
||||||
|
removePaginationWrapper,
|
||||||
|
} from '@vegaprotocol/utils';
|
||||||
import {
|
import {
|
||||||
MarginsSubscriptionDocument,
|
MarginsSubscriptionDocument,
|
||||||
MarginsDocument,
|
MarginsDocument,
|
||||||
@ -8,6 +12,7 @@ import type {
|
|||||||
MarginsQuery,
|
MarginsQuery,
|
||||||
MarginFieldsFragment,
|
MarginFieldsFragment,
|
||||||
MarginsSubscriptionSubscription,
|
MarginsSubscriptionSubscription,
|
||||||
|
MarginsQueryVariables,
|
||||||
} from './__generated__/Positions';
|
} from './__generated__/Positions';
|
||||||
|
|
||||||
const update = (
|
const update = (
|
||||||
@ -56,7 +61,8 @@ export const marginsDataProvider = makeDataProvider<
|
|||||||
MarginsQuery,
|
MarginsQuery,
|
||||||
MarginFieldsFragment[],
|
MarginFieldsFragment[],
|
||||||
MarginsSubscriptionSubscription,
|
MarginsSubscriptionSubscription,
|
||||||
MarginsSubscriptionSubscription['margins']
|
MarginsSubscriptionSubscription['margins'],
|
||||||
|
MarginsQueryVariables
|
||||||
>({
|
>({
|
||||||
query: MarginsDocument,
|
query: MarginsDocument,
|
||||||
subscriptionQuery: MarginsSubscriptionDocument,
|
subscriptionQuery: MarginsSubscriptionDocument,
|
||||||
@ -64,3 +70,15 @@ export const marginsDataProvider = makeDataProvider<
|
|||||||
getData,
|
getData,
|
||||||
getDelta,
|
getDelta,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const marketMarginDataProvider = makeDerivedDataProvider<
|
||||||
|
MarginFieldsFragment,
|
||||||
|
never,
|
||||||
|
MarginsQueryVariables & { marketId: string }
|
||||||
|
>(
|
||||||
|
[marginsDataProvider],
|
||||||
|
(data, { marketId }) =>
|
||||||
|
(data[0] as MarginFieldsFragment[]).find(
|
||||||
|
(margin) => margin.market.id === marketId
|
||||||
|
) || null
|
||||||
|
);
|
||||||
|
@ -11,19 +11,32 @@ import {
|
|||||||
removePaginationWrapper,
|
removePaginationWrapper,
|
||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import * as Schema from '@vegaprotocol/types';
|
import * as Schema from '@vegaprotocol/types';
|
||||||
import type { MarketMaybeWithData } from '@vegaprotocol/market-list';
|
import type {
|
||||||
|
MarketMaybeWithData,
|
||||||
|
MarketDataQueryVariables,
|
||||||
|
} from '@vegaprotocol/market-list';
|
||||||
import { marketsWithDataProvider } from '@vegaprotocol/market-list';
|
import { marketsWithDataProvider } from '@vegaprotocol/market-list';
|
||||||
import type {
|
import type {
|
||||||
PositionsQuery,
|
PositionsQuery,
|
||||||
PositionFieldsFragment,
|
PositionFieldsFragment,
|
||||||
PositionsSubscriptionSubscription,
|
PositionsSubscriptionSubscription,
|
||||||
MarginFieldsFragment,
|
MarginFieldsFragment,
|
||||||
|
PositionsQueryVariables,
|
||||||
} from './__generated__/Positions';
|
} from './__generated__/Positions';
|
||||||
import {
|
import {
|
||||||
PositionsDocument,
|
PositionsDocument,
|
||||||
PositionsSubscriptionDocument,
|
PositionsSubscriptionDocument,
|
||||||
} from './__generated__/Positions';
|
} from './__generated__/Positions';
|
||||||
import { marginsDataProvider } from './margin-data-provider';
|
import { marginsDataProvider } from './margin-data-provider';
|
||||||
|
import { calculateMargins } from './margin-calculator';
|
||||||
|
import type { Edge } from '@vegaprotocol/utils';
|
||||||
|
import { OrderStatus, Side } from '@vegaprotocol/types';
|
||||||
|
import { marketInfoProvider } from '@vegaprotocol/market-info';
|
||||||
|
import type { MarketInfoQuery } from '@vegaprotocol/market-info';
|
||||||
|
import { marketDataProvider } from '@vegaprotocol/market-list';
|
||||||
|
import type { MarketData } from '@vegaprotocol/market-list';
|
||||||
|
import { ordersProvider } from '@vegaprotocol/orders';
|
||||||
|
import type { OrderFieldsFragment } from '@vegaprotocol/orders';
|
||||||
import type { PositionStatus } from '@vegaprotocol/types';
|
import type { PositionStatus } from '@vegaprotocol/types';
|
||||||
|
|
||||||
type PositionMarginLevel = Pick<
|
type PositionMarginLevel = Pick<
|
||||||
@ -229,7 +242,8 @@ export const positionsDataProvider = makeDataProvider<
|
|||||||
PositionsQuery,
|
PositionsQuery,
|
||||||
PositionFieldsFragment[],
|
PositionFieldsFragment[],
|
||||||
PositionsSubscriptionSubscription,
|
PositionsSubscriptionSubscription,
|
||||||
PositionsSubscriptionSubscription['positions']
|
PositionsSubscriptionSubscription['positions'],
|
||||||
|
PositionsQueryVariables
|
||||||
>({
|
>({
|
||||||
query: PositionsDocument,
|
query: PositionsDocument,
|
||||||
subscriptionQuery: PositionsSubscriptionDocument,
|
subscriptionQuery: PositionsSubscriptionDocument,
|
||||||
@ -260,6 +274,32 @@ const upgradeMarginsConnection = (
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const positionDataProvider = makeDerivedDataProvider<
|
||||||
|
PositionFieldsFragment,
|
||||||
|
never,
|
||||||
|
PositionsQueryVariables & MarketDataQueryVariables
|
||||||
|
>(
|
||||||
|
[
|
||||||
|
(callback, client, variables) =>
|
||||||
|
positionsDataProvider(callback, client, {
|
||||||
|
partyId: variables?.partyId || '',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
(data, variables) =>
|
||||||
|
(data[0] as PositionFieldsFragment[] | null)?.find(
|
||||||
|
(p) => p.market.id === variables?.marketId
|
||||||
|
) || null
|
||||||
|
);
|
||||||
|
|
||||||
|
export const openVolumeDataProvider = makeDerivedDataProvider<
|
||||||
|
string,
|
||||||
|
never,
|
||||||
|
PositionsQueryVariables & MarketDataQueryVariables
|
||||||
|
>(
|
||||||
|
[positionDataProvider],
|
||||||
|
(data) => (data[0] as PositionFieldsFragment | null)?.openVolume || null
|
||||||
|
);
|
||||||
|
|
||||||
export const rejoinPositionData = (
|
export const rejoinPositionData = (
|
||||||
positions: PositionFieldsFragment[] | null,
|
positions: PositionFieldsFragment[] | null,
|
||||||
marketsData: MarketMaybeWithData[] | null,
|
marketsData: MarketMaybeWithData[] | null,
|
||||||
@ -284,19 +324,15 @@ export const rejoinPositionData = (
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface PositionsMetricsProviderVariables {
|
|
||||||
partyId: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const positionsMetricsProvider = makeDerivedDataProvider<
|
export const positionsMetricsProvider = makeDerivedDataProvider<
|
||||||
Position[],
|
Position[],
|
||||||
Position[],
|
Position[],
|
||||||
PositionsMetricsProviderVariables
|
PositionsQueryVariables
|
||||||
>(
|
>(
|
||||||
[
|
[
|
||||||
positionsDataProvider,
|
positionsDataProvider,
|
||||||
accountsDataProvider,
|
accountsDataProvider,
|
||||||
marketsWithDataProvider,
|
(callback, client) => marketsWithDataProvider(callback, client, undefined),
|
||||||
marginsDataProvider,
|
marginsDataProvider,
|
||||||
],
|
],
|
||||||
([positions, accounts, marketsData, margins], variables) => {
|
([positions, accounts, marketsData, margins], variables) => {
|
||||||
@ -317,3 +353,103 @@ export const positionsMetricsProvider = makeDerivedDataProvider<
|
|||||||
return !(previousRow && isEqual(previousRow, row));
|
return !(previousRow && isEqual(previousRow, row));
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export const volumeAndMarginProvider = makeDerivedDataProvider<
|
||||||
|
{
|
||||||
|
buyVolume: string;
|
||||||
|
sellVolume: string;
|
||||||
|
buyInitialMargin: string;
|
||||||
|
sellInitialMargin: string;
|
||||||
|
},
|
||||||
|
never,
|
||||||
|
PositionsQueryVariables & MarketDataQueryVariables
|
||||||
|
>(
|
||||||
|
[
|
||||||
|
(callback, client, variables) =>
|
||||||
|
ordersProvider(callback, client, {
|
||||||
|
...variables,
|
||||||
|
filter: {
|
||||||
|
status: [
|
||||||
|
OrderStatus.STATUS_ACTIVE,
|
||||||
|
OrderStatus.STATUS_PARTIALLY_FILLED,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
(callback, client, variables) =>
|
||||||
|
marketDataProvider(callback, client, { marketId: variables.marketId }),
|
||||||
|
(callback, client, variables) =>
|
||||||
|
marketInfoProvider(callback, client, { marketId: variables.marketId }),
|
||||||
|
openVolumeDataProvider,
|
||||||
|
],
|
||||||
|
(data) => {
|
||||||
|
const orders = data[0] as (Edge<OrderFieldsFragment> | null)[] | null;
|
||||||
|
const marketData = data[1] as MarketData | null;
|
||||||
|
const marketInfo = data[2] as MarketInfoQuery['market'];
|
||||||
|
let openVolume = (data[3] as string | null) || '0';
|
||||||
|
const shortPosition = openVolume?.startsWith('-');
|
||||||
|
if (shortPosition) {
|
||||||
|
openVolume = openVolume.substring(1);
|
||||||
|
}
|
||||||
|
let buyVolume = BigInt(shortPosition ? 0 : openVolume);
|
||||||
|
let sellVolume = BigInt(shortPosition ? openVolume : 0);
|
||||||
|
let buyInitialMargin = BigInt(0);
|
||||||
|
let sellInitialMargin = BigInt(0);
|
||||||
|
if (marketInfo?.riskFactors && marketData) {
|
||||||
|
const {
|
||||||
|
positionDecimalPlaces,
|
||||||
|
decimalPlaces,
|
||||||
|
tradableInstrument,
|
||||||
|
riskFactors,
|
||||||
|
} = marketInfo;
|
||||||
|
const { marginCalculator, instrument } = tradableInstrument;
|
||||||
|
const { decimals } = instrument.product.settlementAsset;
|
||||||
|
const calculatorParams = {
|
||||||
|
positionDecimalPlaces,
|
||||||
|
decimalPlaces,
|
||||||
|
decimals,
|
||||||
|
scalingFactors: marginCalculator?.scalingFactors,
|
||||||
|
riskFactors,
|
||||||
|
};
|
||||||
|
if (openVolume !== '0') {
|
||||||
|
const { initialMargin } = calculateMargins({
|
||||||
|
side: shortPosition ? Side.SIDE_SELL : Side.SIDE_BUY,
|
||||||
|
size: openVolume,
|
||||||
|
price: marketData.markPrice,
|
||||||
|
...calculatorParams,
|
||||||
|
});
|
||||||
|
if (shortPosition) {
|
||||||
|
sellInitialMargin += BigInt(initialMargin);
|
||||||
|
} else {
|
||||||
|
buyInitialMargin += BigInt(initialMargin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
orders?.forEach((order) => {
|
||||||
|
if (!order) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const { side, remaining: size } = order.node;
|
||||||
|
const initialMargin = BigInt(
|
||||||
|
calculateMargins({
|
||||||
|
side,
|
||||||
|
size,
|
||||||
|
price: marketData.markPrice, //getDerivedPrice(order.node, marketData), same use-initial-margin
|
||||||
|
...calculatorParams,
|
||||||
|
}).initialMargin
|
||||||
|
);
|
||||||
|
if (order.node.side === Side.SIDE_BUY) {
|
||||||
|
buyVolume += BigInt(size);
|
||||||
|
buyInitialMargin += initialMargin;
|
||||||
|
} else {
|
||||||
|
sellVolume += BigInt(size);
|
||||||
|
sellInitialMargin += initialMargin;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
buyVolume: buyVolume.toString(),
|
||||||
|
sellVolume: sellVolume.toString(),
|
||||||
|
buyInitialMargin: buyInitialMargin.toString(),
|
||||||
|
sellInitialMargin: sellInitialMargin.toString(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
21
libs/positions/src/lib/use-open-volume.ts
Normal file
21
libs/positions/src/lib/use-open-volume.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import { useState, useCallback } from 'react';
|
||||||
|
import { openVolumeDataProvider } from './positions-data-providers';
|
||||||
|
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
|
export const useOpenVolume = (
|
||||||
|
partyId: string | null | undefined,
|
||||||
|
marketId: string
|
||||||
|
) => {
|
||||||
|
const [openVolume, setOpenVolume] = useState<string | undefined>(undefined);
|
||||||
|
const update = useCallback(({ data }: { data: string | null }) => {
|
||||||
|
setOpenVolume(data ?? undefined);
|
||||||
|
return true;
|
||||||
|
}, []);
|
||||||
|
useDataProvider({
|
||||||
|
dataProvider: openVolumeDataProvider,
|
||||||
|
update,
|
||||||
|
variables: { partyId: partyId || '', marketId },
|
||||||
|
skip: !partyId,
|
||||||
|
});
|
||||||
|
return openVolume;
|
||||||
|
};
|
@ -3,7 +3,7 @@ import type { RefObject } from 'react';
|
|||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import type { Position } from './positions-data-providers';
|
import type { Position } from './positions-data-providers';
|
||||||
import { positionsMetricsProvider } from './positions-data-providers';
|
import { positionsMetricsProvider } from './positions-data-providers';
|
||||||
import type { PositionsMetricsProviderVariables } from './positions-data-providers';
|
import type { PositionsQueryVariables } from './__generated__/Positions';
|
||||||
import { useDataProvider, updateGridData } from '@vegaprotocol/react-helpers';
|
import { useDataProvider, updateGridData } from '@vegaprotocol/react-helpers';
|
||||||
import type { GetRowsParams } from '@vegaprotocol/datagrid';
|
import type { GetRowsParams } from '@vegaprotocol/datagrid';
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ export const usePositionsData = (
|
|||||||
gridRef: RefObject<AgGridReact>,
|
gridRef: RefObject<AgGridReact>,
|
||||||
clientSideModel?: boolean
|
clientSideModel?: boolean
|
||||||
) => {
|
) => {
|
||||||
const variables = useMemo<PositionsMetricsProviderVariables>(
|
const variables = useMemo<PositionsQueryVariables>(
|
||||||
() => ({ partyId }),
|
() => ({ partyId }),
|
||||||
[partyId]
|
[partyId]
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { makeDataProvider } from '@vegaprotocol/utils';
|
import { makeDataProvider } from '@vegaprotocol/utils';
|
||||||
import type {
|
import type {
|
||||||
ProposalsListQuery,
|
ProposalsListQuery,
|
||||||
|
ProposalsListQueryVariables,
|
||||||
ProposalListFieldsFragment,
|
ProposalListFieldsFragment,
|
||||||
} from './__generated__/Proposals';
|
} from './__generated__/Proposals';
|
||||||
import { ProposalsListDocument } from './__generated__/Proposals';
|
import { ProposalsListDocument } from './__generated__/Proposals';
|
||||||
@ -14,5 +15,6 @@ export const proposalsDataProvider = makeDataProvider<
|
|||||||
ProposalsListQuery,
|
ProposalsListQuery,
|
||||||
ProposalListFieldsFragment[],
|
ProposalListFieldsFragment[],
|
||||||
never,
|
never,
|
||||||
never
|
never,
|
||||||
|
ProposalsListQueryVariables
|
||||||
>({ query: ProposalsListDocument, getData });
|
>({ query: ProposalsListDocument, getData });
|
||||||
|
@ -3,7 +3,7 @@ import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
|
|||||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
import * as Types from '@vegaprotocol/types';
|
import * as Types from '@vegaprotocol/types';
|
||||||
import { proposalsDataProvider } from '../proposals-data-provider';
|
import { proposalsDataProvider } from '../proposals-data-provider';
|
||||||
import { useCallback, useMemo, useRef } from 'react';
|
import { useCallback, useRef } from 'react';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { useColumnDefs } from './use-column-defs';
|
import { useColumnDefs } from './use-column-defs';
|
||||||
import type { ProposalListFieldsFragment } from '../proposals-data-provider/__generated__/Proposals';
|
import type { ProposalListFieldsFragment } from '../proposals-data-provider/__generated__/Proposals';
|
||||||
@ -22,14 +22,11 @@ export const ProposalsList = () => {
|
|||||||
const handleOnGridReady = useCallback(() => {
|
const handleOnGridReady = useCallback(() => {
|
||||||
gridRef.current?.api?.sizeColumnsToFit();
|
gridRef.current?.api?.sizeColumnsToFit();
|
||||||
}, [gridRef]);
|
}, [gridRef]);
|
||||||
const variables = useMemo(() => {
|
|
||||||
return {
|
|
||||||
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
const { data, loading, error, reload } = useDataProvider({
|
const { data, loading, error, reload } = useDataProvider({
|
||||||
dataProvider: proposalsDataProvider,
|
dataProvider: proposalsDataProvider,
|
||||||
variables,
|
variables: {
|
||||||
|
proposalType: Types.ProposalType.TYPE_NEW_MARKET,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const filteredData = getNewMarketProposals(data || []);
|
const filteredData = getNewMarketProposals(data || []);
|
||||||
const { columnDefs, defaultColDef } = useColumnDefs();
|
const { columnDefs, defaultColDef } = useColumnDefs();
|
||||||
|
@ -6,6 +6,7 @@ import { MockedProvider } from '@apollo/client/testing';
|
|||||||
|
|
||||||
type Data = number;
|
type Data = number;
|
||||||
type Delta = number;
|
type Delta = number;
|
||||||
|
type Variables = { partyId: string };
|
||||||
|
|
||||||
const unsubscribe = jest.fn();
|
const unsubscribe = jest.fn();
|
||||||
const reload = jest.fn();
|
const reload = jest.fn();
|
||||||
@ -23,8 +24,8 @@ const updateCallbackPayload: Parameters<UpdateCallback<Data, Delta>>['0'] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const dataProvider = jest.fn<
|
const dataProvider = jest.fn<
|
||||||
ReturnType<Subscribe<Data, Delta>>,
|
ReturnType<Subscribe<Data, Delta, Variables>>,
|
||||||
Parameters<Subscribe<Data, Delta>>
|
Parameters<Subscribe<Data, Delta, Variables>>
|
||||||
>();
|
>();
|
||||||
|
|
||||||
dataProvider.mockReturnValue({
|
dataProvider.mockReturnValue({
|
||||||
@ -37,10 +38,12 @@ dataProvider.mockReturnValue({
|
|||||||
jest.useFakeTimers();
|
jest.useFakeTimers();
|
||||||
|
|
||||||
describe('useDataProvider hook', () => {
|
describe('useDataProvider hook', () => {
|
||||||
const render = (initialProps?: useDataProviderParams<Data, Delta>) =>
|
const render = (
|
||||||
|
initialProps?: useDataProviderParams<Data, Delta, Variables>
|
||||||
|
) =>
|
||||||
renderHook<
|
renderHook<
|
||||||
ReturnType<typeof useDataProvider>,
|
ReturnType<typeof useDataProvider>,
|
||||||
useDataProviderParams<Data, Delta>
|
useDataProviderParams<Data, Delta, Variables>
|
||||||
>((props) => useDataProvider(props), {
|
>((props) => useDataProvider(props), {
|
||||||
wrapper: MockedProvider,
|
wrapper: MockedProvider,
|
||||||
initialProps,
|
initialProps,
|
||||||
@ -224,6 +227,7 @@ describe('useThrottledDataProvider hook', () => {
|
|||||||
useThrottledDataProvider(
|
useThrottledDataProvider(
|
||||||
{
|
{
|
||||||
dataProvider,
|
dataProvider,
|
||||||
|
variables,
|
||||||
},
|
},
|
||||||
wait
|
wait
|
||||||
),
|
),
|
||||||
|
@ -9,7 +9,7 @@ import type { Subscribe, Load, UpdateCallback } from '@vegaprotocol/utils';
|
|||||||
export interface useDataProviderParams<
|
export interface useDataProviderParams<
|
||||||
Data,
|
Data,
|
||||||
Delta,
|
Delta,
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
> {
|
> {
|
||||||
dataProvider: Subscribe<Data, Delta, Variables>;
|
dataProvider: Subscribe<Data, Delta, Variables>;
|
||||||
update?: ({
|
update?: ({
|
||||||
@ -30,7 +30,7 @@ export interface useDataProviderParams<
|
|||||||
data: Data | null;
|
data: Data | null;
|
||||||
totalCount?: number;
|
totalCount?: number;
|
||||||
}) => boolean;
|
}) => boolean;
|
||||||
variables?: Variables;
|
variables: Variables;
|
||||||
skipUpdates?: boolean;
|
skipUpdates?: boolean;
|
||||||
skip?: boolean;
|
skip?: boolean;
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ export interface useDataProviderParams<
|
|||||||
export const useDataProvider = <
|
export const useDataProvider = <
|
||||||
Data,
|
Data,
|
||||||
Delta,
|
Delta,
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
>({
|
>({
|
||||||
dataProvider,
|
dataProvider,
|
||||||
update,
|
update,
|
||||||
@ -163,8 +163,12 @@ export const useDataProvider = <
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useThrottledDataProvider = <Data, Delta>(
|
export const useThrottledDataProvider = <
|
||||||
params: Omit<useDataProviderParams<Data, Delta>, 'update'>,
|
Data,
|
||||||
|
Delta,
|
||||||
|
Variables extends OperationVariables = OperationVariables
|
||||||
|
>(
|
||||||
|
params: Omit<useDataProviderParams<Data, Delta, Variables>, 'update'>,
|
||||||
wait?: number
|
wait?: number
|
||||||
) => {
|
) => {
|
||||||
const [data, setData] = useState<Data | null>(null);
|
const [data, setData] = useState<Data | null>(null);
|
||||||
|
@ -2,12 +2,11 @@ import { makeInfiniteScrollGetRows } from '@vegaprotocol/utils';
|
|||||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { useCallback, useMemo, useRef } from 'react';
|
import { useCallback, useRef } from 'react';
|
||||||
import type { BodyScrollEvent, BodyScrollEndEvent } from 'ag-grid-community';
|
import type { BodyScrollEvent, BodyScrollEndEvent } from 'ag-grid-community';
|
||||||
import { MAX_TRADES, tradesWithMarketProvider } from './trades-data-provider';
|
import { tradesWithMarketProvider } from './trades-data-provider';
|
||||||
import { TradesTable } from './trades-table';
|
import { TradesTable } from './trades-table';
|
||||||
import type { Trade, TradeEdge } from './trades-data-provider';
|
import type { Trade, TradeEdge } from './trades-data-provider';
|
||||||
import type { TradesQueryVariables } from './__generated__/Trades';
|
|
||||||
import { useOrderStore } from '@vegaprotocol/orders';
|
import { useOrderStore } from '@vegaprotocol/orders';
|
||||||
|
|
||||||
interface TradesContainerProps {
|
interface TradesContainerProps {
|
||||||
@ -22,11 +21,6 @@ export const TradesContainer = ({ marketId }: TradesContainerProps) => {
|
|||||||
const scrolledToTop = useRef(true);
|
const scrolledToTop = useRef(true);
|
||||||
const updateOrder = useOrderStore((store) => store.update);
|
const updateOrder = useOrderStore((store) => store.update);
|
||||||
|
|
||||||
const variables = useMemo<TradesQueryVariables>(
|
|
||||||
() => ({ marketId, maxTrades: MAX_TRADES }),
|
|
||||||
[marketId]
|
|
||||||
);
|
|
||||||
|
|
||||||
const addNewRows = useCallback(() => {
|
const addNewRows = useCallback(() => {
|
||||||
if (newRows.current === 0) {
|
if (newRows.current === 0) {
|
||||||
return;
|
return;
|
||||||
@ -84,7 +78,7 @@ export const TradesContainer = ({ marketId }: TradesContainerProps) => {
|
|||||||
dataProvider: tradesWithMarketProvider,
|
dataProvider: tradesWithMarketProvider,
|
||||||
update,
|
update,
|
||||||
insert,
|
insert,
|
||||||
variables,
|
variables: { marketId },
|
||||||
});
|
});
|
||||||
totalCountRef.current = totalCount;
|
totalCountRef.current = totalCount;
|
||||||
const getRows = makeInfiniteScrollGetRows<TradeEdge>(
|
const getRows = makeInfiniteScrollGetRows<TradeEdge>(
|
||||||
|
@ -10,6 +10,7 @@ import type { Market } from '@vegaprotocol/market-list';
|
|||||||
import { marketsProvider } from '@vegaprotocol/market-list';
|
import { marketsProvider } from '@vegaprotocol/market-list';
|
||||||
import type {
|
import type {
|
||||||
TradesQuery,
|
TradesQuery,
|
||||||
|
TradesQueryVariables,
|
||||||
TradeFieldsFragment,
|
TradeFieldsFragment,
|
||||||
TradesUpdateSubscription,
|
TradesUpdateSubscription,
|
||||||
} from './__generated__/Trades';
|
} from './__generated__/Trades';
|
||||||
@ -67,10 +68,16 @@ const update = (
|
|||||||
export type Trade = Omit<TradeFieldsFragment, 'market'> & { market?: Market };
|
export type Trade = Omit<TradeFieldsFragment, 'market'> & { market?: Market };
|
||||||
export type TradeEdge = Edge<Trade>;
|
export type TradeEdge = Edge<Trade>;
|
||||||
|
|
||||||
const getPageInfo = (responseData: TradesQuery): PageInfo | null =>
|
const getPageInfo = (responseData: TradesQuery | null): PageInfo | null =>
|
||||||
responseData.market?.tradesConnection?.pageInfo || null;
|
responseData?.market?.tradesConnection?.pageInfo || null;
|
||||||
|
|
||||||
export const tradesProvider = makeDataProvider({
|
export const tradesProvider = makeDataProvider<
|
||||||
|
Parameters<typeof getData>['0'],
|
||||||
|
ReturnType<typeof getData>,
|
||||||
|
Parameters<typeof getDelta>['0'],
|
||||||
|
ReturnType<typeof getDelta>,
|
||||||
|
TradesQueryVariables
|
||||||
|
>({
|
||||||
query: TradesDocument,
|
query: TradesDocument,
|
||||||
subscriptionQuery: TradesUpdateDocument,
|
subscriptionQuery: TradesUpdateDocument,
|
||||||
update,
|
update,
|
||||||
@ -85,9 +92,13 @@ export const tradesProvider = makeDataProvider({
|
|||||||
|
|
||||||
export const tradesWithMarketProvider = makeDerivedDataProvider<
|
export const tradesWithMarketProvider = makeDerivedDataProvider<
|
||||||
(TradeEdge | null)[],
|
(TradeEdge | null)[],
|
||||||
Trade[]
|
Trade[],
|
||||||
|
TradesQueryVariables
|
||||||
>(
|
>(
|
||||||
[tradesProvider, marketsProvider],
|
[
|
||||||
|
tradesProvider,
|
||||||
|
(callback, client) => marketsProvider(callback, client, undefined),
|
||||||
|
],
|
||||||
(partsData): (TradeEdge | null)[] | null => {
|
(partsData): (TradeEdge | null)[] | null => {
|
||||||
const edges = partsData[0] as ReturnType<typeof getData>;
|
const edges = partsData[0] as ReturnType<typeof getData>;
|
||||||
return edges.map((edge) => {
|
return edges.map((edge) => {
|
||||||
|
@ -45,10 +45,11 @@ type CombinedData = {
|
|||||||
|
|
||||||
type SubscriptionData = QueryData;
|
type SubscriptionData = QueryData;
|
||||||
type Delta = Data;
|
type Delta = Data;
|
||||||
|
type Variables = { var: string };
|
||||||
|
|
||||||
const update = jest.fn<
|
const update = jest.fn<
|
||||||
ReturnType<Update<Data, Delta>>,
|
ReturnType<Update<Data, Delta, Variables>>,
|
||||||
Parameters<Update<Data, Delta>>
|
Parameters<Update<Data, Delta, Variables>>
|
||||||
>();
|
>();
|
||||||
|
|
||||||
const callback = jest.fn<
|
const callback = jest.fn<
|
||||||
@ -66,7 +67,13 @@ const getData = jest.fn((r: QueryData | null) => r?.data || null);
|
|||||||
|
|
||||||
const getDelta = jest.fn((r: SubscriptionData) => r.data);
|
const getDelta = jest.fn((r: SubscriptionData) => r.data);
|
||||||
|
|
||||||
const subscribe = makeDataProvider<QueryData, Data, SubscriptionData, Delta>({
|
const subscribe = makeDataProvider<
|
||||||
|
QueryData,
|
||||||
|
Data,
|
||||||
|
SubscriptionData,
|
||||||
|
Delta,
|
||||||
|
Variables
|
||||||
|
>({
|
||||||
query,
|
query,
|
||||||
subscriptionQuery,
|
subscriptionQuery,
|
||||||
update,
|
update,
|
||||||
@ -75,18 +82,18 @@ const subscribe = makeDataProvider<QueryData, Data, SubscriptionData, Delta>({
|
|||||||
});
|
});
|
||||||
|
|
||||||
const combineData = jest.fn<
|
const combineData = jest.fn<
|
||||||
ReturnType<CombineDerivedData<CombinedData>>,
|
ReturnType<CombineDerivedData<CombinedData, Variables>>,
|
||||||
Parameters<CombineDerivedData<CombinedData>>
|
Parameters<CombineDerivedData<CombinedData, Variables>>
|
||||||
>();
|
>();
|
||||||
|
|
||||||
const combineDelta = jest.fn<
|
const combineDelta = jest.fn<
|
||||||
ReturnType<CombineDerivedDelta<CombinedData, CombinedData>>,
|
ReturnType<CombineDerivedDelta<CombinedData, CombinedData, Variables>>,
|
||||||
Parameters<CombineDerivedDelta<CombinedData, CombinedData>>
|
Parameters<CombineDerivedDelta<CombinedData, CombinedData, Variables>>
|
||||||
>();
|
>();
|
||||||
|
|
||||||
const combineInsertionData = jest.fn<
|
const combineInsertionData = jest.fn<
|
||||||
ReturnType<CombineInsertionData<CombinedData>>,
|
ReturnType<CombineInsertionData<CombinedData, Variables>>,
|
||||||
Parameters<CombineInsertionData<CombinedData>>
|
Parameters<CombineInsertionData<CombinedData, Variables>>
|
||||||
>();
|
>();
|
||||||
|
|
||||||
const first = 100;
|
const first = 100;
|
||||||
@ -94,7 +101,8 @@ const paginatedSubscribe = makeDataProvider<
|
|||||||
QueryData,
|
QueryData,
|
||||||
Data,
|
Data,
|
||||||
SubscriptionData,
|
SubscriptionData,
|
||||||
Delta
|
Delta,
|
||||||
|
Variables
|
||||||
>({
|
>({
|
||||||
query,
|
query,
|
||||||
subscriptionQuery,
|
subscriptionQuery,
|
||||||
@ -116,7 +124,8 @@ const errorGuardedSubscribe = makeDataProvider<
|
|||||||
QueryData,
|
QueryData,
|
||||||
Data,
|
Data,
|
||||||
SubscriptionData,
|
SubscriptionData,
|
||||||
Delta
|
Delta,
|
||||||
|
Variables
|
||||||
>({
|
>({
|
||||||
query,
|
query,
|
||||||
subscriptionQuery,
|
subscriptionQuery,
|
||||||
@ -210,6 +219,8 @@ const clearPendingQueries = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const variables = { var: 'val' };
|
||||||
|
|
||||||
describe('data provider', () => {
|
describe('data provider', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
clearPendingQueries();
|
clearPendingQueries();
|
||||||
@ -220,7 +231,6 @@ describe('data provider', () => {
|
|||||||
clientSubscribeSubscribe.mockClear();
|
clientSubscribeSubscribe.mockClear();
|
||||||
});
|
});
|
||||||
it('memoize instance and unsubscribe if no subscribers', () => {
|
it('memoize instance and unsubscribe if no subscribers', () => {
|
||||||
const variables = { var: 'val' };
|
|
||||||
const subscription1 = subscribe(jest.fn(), client, variables);
|
const subscription1 = subscribe(jest.fn(), client, variables);
|
||||||
const subscription2 = subscribe(jest.fn(), client, { ...variables });
|
const subscription2 = subscribe(jest.fn(), client, { ...variables });
|
||||||
// const subscription1 = subscribe(jest.fn(), client);
|
// const subscription1 = subscribe(jest.fn(), client);
|
||||||
@ -234,7 +244,7 @@ describe('data provider', () => {
|
|||||||
|
|
||||||
it('calls callback before and after initial fetch', async () => {
|
it('calls callback before and after initial fetch', async () => {
|
||||||
const data: Item[] = [];
|
const data: Item[] = [];
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client, variables);
|
||||||
expect(callback.mock.calls.length).toBe(1);
|
expect(callback.mock.calls.length).toBe(1);
|
||||||
expect(callback.mock.calls[0][0].data).toBe(null);
|
expect(callback.mock.calls[0][0].data).toBe(null);
|
||||||
expect(callback.mock.calls[0][0].loading).toBe(true);
|
expect(callback.mock.calls[0][0].loading).toBe(true);
|
||||||
@ -246,7 +256,7 @@ describe('data provider', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('calls callback on error', async () => {
|
it('calls callback on error', async () => {
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client, variables);
|
||||||
expect(callback.mock.calls.length).toBe(1);
|
expect(callback.mock.calls.length).toBe(1);
|
||||||
expect(callback.mock.calls[0][0].data).toBe(null);
|
expect(callback.mock.calls[0][0].data).toBe(null);
|
||||||
expect(callback.mock.calls[0][0].loading).toBe(true);
|
expect(callback.mock.calls[0][0].loading).toBe(true);
|
||||||
@ -260,7 +270,7 @@ describe('data provider', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('calls successful callback on NotFound error on party path', async () => {
|
it('calls successful callback on NotFound error on party path', async () => {
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client, variables);
|
||||||
expect(callback.mock.calls.length).toBe(1);
|
expect(callback.mock.calls.length).toBe(1);
|
||||||
expect(callback.mock.calls[0][0].data).toBe(null);
|
expect(callback.mock.calls[0][0].data).toBe(null);
|
||||||
expect(callback.mock.calls[0][0].loading).toBe(true);
|
expect(callback.mock.calls[0][0].loading).toBe(true);
|
||||||
@ -280,7 +290,7 @@ describe('data provider', () => {
|
|||||||
const data: Data = [];
|
const data: Data = [];
|
||||||
getData.mockReturnValueOnce(data);
|
getData.mockReturnValueOnce(data);
|
||||||
await rejectQuery(error);
|
await rejectQuery(error);
|
||||||
expect(getData).toHaveBeenCalledWith(null, undefined);
|
expect(getData).toHaveBeenCalledWith(null, variables);
|
||||||
expect(callback.mock.calls.length).toBe(2);
|
expect(callback.mock.calls.length).toBe(2);
|
||||||
expect(callback.mock.calls[1][0].data).toEqual(data);
|
expect(callback.mock.calls[1][0].data).toEqual(data);
|
||||||
expect(callback.mock.calls[1][0].error).toEqual(undefined);
|
expect(callback.mock.calls[1][0].error).toEqual(undefined);
|
||||||
@ -290,7 +300,7 @@ describe('data provider', () => {
|
|||||||
|
|
||||||
it('calls update and callback on each update', async () => {
|
it('calls update and callback on each update', async () => {
|
||||||
const data: Item[] = [];
|
const data: Item[] = [];
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client, variables);
|
||||||
await resolveQuery({ data });
|
await resolveQuery({ data });
|
||||||
const delta: Item[] = [];
|
const delta: Item[] = [];
|
||||||
update.mockImplementationOnce((data, delta) => [...(data || []), ...delta]);
|
update.mockImplementationOnce((data, delta) => [...(data || []), ...delta]);
|
||||||
@ -308,7 +318,7 @@ describe('data provider', () => {
|
|||||||
|
|
||||||
it("don't calls callback on update if data doesn't change", async () => {
|
it("don't calls callback on update if data doesn't change", async () => {
|
||||||
const data: Item[] = [];
|
const data: Item[] = [];
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client, variables);
|
||||||
await resolveQuery({ data });
|
await resolveQuery({ data });
|
||||||
const delta: Item[] = [];
|
const delta: Item[] = [];
|
||||||
update.mockImplementationOnce((data) => data || []);
|
update.mockImplementationOnce((data) => data || []);
|
||||||
@ -325,7 +335,7 @@ describe('data provider', () => {
|
|||||||
|
|
||||||
it('refetch data on reload', async () => {
|
it('refetch data on reload', async () => {
|
||||||
const data: Item[] = [];
|
const data: Item[] = [];
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client, variables);
|
||||||
await resolveQuery({ data });
|
await resolveQuery({ data });
|
||||||
subscription.reload();
|
subscription.reload();
|
||||||
await resolveQuery({ data });
|
await resolveQuery({ data });
|
||||||
@ -337,7 +347,7 @@ describe('data provider', () => {
|
|||||||
|
|
||||||
it('refetch data and restart subscription on reload with force', async () => {
|
it('refetch data and restart subscription on reload with force', async () => {
|
||||||
const data: Item[] = [];
|
const data: Item[] = [];
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client, variables);
|
||||||
await resolveQuery({ data });
|
await resolveQuery({ data });
|
||||||
subscription.reload(true);
|
subscription.reload(true);
|
||||||
await resolveQuery({ data });
|
await resolveQuery({ data });
|
||||||
@ -349,7 +359,7 @@ describe('data provider', () => {
|
|||||||
|
|
||||||
it('calls callback on flush', async () => {
|
it('calls callback on flush', async () => {
|
||||||
const data: Item[] = [];
|
const data: Item[] = [];
|
||||||
const subscription = subscribe(callback, client);
|
const subscription = subscribe(callback, client, variables);
|
||||||
await resolveQuery({ data });
|
await resolveQuery({ data });
|
||||||
const callbackCallsLength = callback.mock.calls.length;
|
const callbackCallsLength = callback.mock.calls.length;
|
||||||
subscription.flush();
|
subscription.flush();
|
||||||
@ -365,7 +375,7 @@ describe('data provider', () => {
|
|||||||
id: i.toString(),
|
id: i.toString(),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
const subscription = paginatedSubscribe(callback, client);
|
const subscription = paginatedSubscribe(callback, client, variables);
|
||||||
await resolveQuery({
|
await resolveQuery({
|
||||||
data,
|
data,
|
||||||
totalCount,
|
totalCount,
|
||||||
@ -379,7 +389,7 @@ describe('data provider', () => {
|
|||||||
|
|
||||||
it('loads requested data blocks and inserts data with total count', async () => {
|
it('loads requested data blocks and inserts data with total count', async () => {
|
||||||
const totalCount = 1000;
|
const totalCount = 1000;
|
||||||
const subscription = paginatedSubscribe(callback, client);
|
const subscription = paginatedSubscribe(callback, client, variables);
|
||||||
await resolveQuery({
|
await resolveQuery({
|
||||||
data: generateData(),
|
data: generateData(),
|
||||||
totalCount,
|
totalCount,
|
||||||
@ -503,7 +513,7 @@ describe('data provider', () => {
|
|||||||
|
|
||||||
it('loads requested data blocks and inserts data without totalCount', async () => {
|
it('loads requested data blocks and inserts data without totalCount', async () => {
|
||||||
const totalCount = undefined;
|
const totalCount = undefined;
|
||||||
const subscription = paginatedSubscribe(callback, client);
|
const subscription = paginatedSubscribe(callback, client, variables);
|
||||||
await resolveQuery({
|
await resolveQuery({
|
||||||
data: generateData(),
|
data: generateData(),
|
||||||
totalCount,
|
totalCount,
|
||||||
@ -542,7 +552,7 @@ describe('data provider', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('sets total count when first page has no next page', async () => {
|
it('sets total count when first page has no next page', async () => {
|
||||||
const subscription = paginatedSubscribe(callback, client);
|
const subscription = paginatedSubscribe(callback, client, variables);
|
||||||
await resolveQuery({
|
await resolveQuery({
|
||||||
data: generateData(),
|
data: generateData(),
|
||||||
pageInfo: {
|
pageInfo: {
|
||||||
@ -556,8 +566,8 @@ describe('data provider', () => {
|
|||||||
subscription.unsubscribe();
|
subscription.unsubscribe();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('errorPolicyGuard should work properly', async () => {
|
it('should retry with ignore error policy if errorPolicyGuard returns true', async () => {
|
||||||
const subscription = errorGuardedSubscribe(callback, client);
|
const subscription = errorGuardedSubscribe(callback, client, variables);
|
||||||
const graphQLError = new GraphQLError(
|
const graphQLError = new GraphQLError(
|
||||||
'',
|
'',
|
||||||
undefined,
|
undefined,
|
||||||
@ -579,7 +589,7 @@ describe('data provider', () => {
|
|||||||
});
|
});
|
||||||
expect(mockErrorPolicyGuard).toHaveBeenNthCalledWith(1, graphQLErrors);
|
expect(mockErrorPolicyGuard).toHaveBeenNthCalledWith(1, graphQLErrors);
|
||||||
await waitFor(() =>
|
await waitFor(() =>
|
||||||
expect(getData).toHaveBeenCalledWith({ data }, undefined)
|
expect(getData).toHaveBeenCalledWith({ data }, variables)
|
||||||
);
|
);
|
||||||
subscription.unsubscribe();
|
subscription.unsubscribe();
|
||||||
});
|
});
|
||||||
@ -589,7 +599,6 @@ describe('derived data provider', () => {
|
|||||||
it('memoize instance and unsubscribe if no subscribers', () => {
|
it('memoize instance and unsubscribe if no subscribers', () => {
|
||||||
clientSubscribeSubscribe.mockClear();
|
clientSubscribeSubscribe.mockClear();
|
||||||
clientSubscribeUnsubscribe.mockClear();
|
clientSubscribeUnsubscribe.mockClear();
|
||||||
const variables = {};
|
|
||||||
const subscription1 = derivedSubscribe(jest.fn(), client, variables);
|
const subscription1 = derivedSubscribe(jest.fn(), client, variables);
|
||||||
const subscription2 = derivedSubscribe(jest.fn(), client, variables);
|
const subscription2 = derivedSubscribe(jest.fn(), client, variables);
|
||||||
expect(clientSubscribeSubscribe.mock.calls.length).toEqual(2);
|
expect(clientSubscribeSubscribe.mock.calls.length).toEqual(2);
|
||||||
@ -615,7 +624,7 @@ describe('derived data provider', () => {
|
|||||||
ReturnType<UpdateCallback<CombinedData, CombinedData>>,
|
ReturnType<UpdateCallback<CombinedData, CombinedData>>,
|
||||||
Parameters<UpdateCallback<CombinedData, CombinedData>>
|
Parameters<UpdateCallback<CombinedData, CombinedData>>
|
||||||
>();
|
>();
|
||||||
const subscription = derivedSubscribe(callback, client);
|
const subscription = derivedSubscribe(callback, client, variables);
|
||||||
const data = { totalCount: 0 };
|
const data = { totalCount: 0 };
|
||||||
combineData.mockReturnValueOnce(data);
|
combineData.mockReturnValueOnce(data);
|
||||||
expect(callback.mock.calls.length).toBe(0);
|
expect(callback.mock.calls.length).toBe(0);
|
||||||
@ -642,7 +651,7 @@ describe('derived data provider', () => {
|
|||||||
Parameters<UpdateCallback<CombinedData, CombinedData>>
|
Parameters<UpdateCallback<CombinedData, CombinedData>>
|
||||||
>();
|
>();
|
||||||
expect(callback.mock.calls.length).toBe(0);
|
expect(callback.mock.calls.length).toBe(0);
|
||||||
const subscription = derivedSubscribe(callback, client);
|
const subscription = derivedSubscribe(callback, client, variables);
|
||||||
const data = { totalCount: 0 };
|
const data = { totalCount: 0 };
|
||||||
combineData.mockReturnValueOnce(data);
|
combineData.mockReturnValueOnce(data);
|
||||||
expect(callback.mock.calls.length).toBe(0);
|
expect(callback.mock.calls.length).toBe(0);
|
||||||
@ -677,7 +686,7 @@ describe('derived data provider', () => {
|
|||||||
ReturnType<UpdateCallback<CombinedData, CombinedData>>,
|
ReturnType<UpdateCallback<CombinedData, CombinedData>>,
|
||||||
Parameters<UpdateCallback<CombinedData, CombinedData>>
|
Parameters<UpdateCallback<CombinedData, CombinedData>>
|
||||||
>();
|
>();
|
||||||
const subscription = derivedSubscribe(callback, client);
|
const subscription = derivedSubscribe(callback, client, variables);
|
||||||
const data = { totalCount: 0 };
|
const data = { totalCount: 0 };
|
||||||
combineData.mockReturnValueOnce(data);
|
combineData.mockReturnValueOnce(data);
|
||||||
await resolveQuery({ data: part1 });
|
await resolveQuery({ data: part1 });
|
||||||
@ -709,7 +718,7 @@ describe('derived data provider', () => {
|
|||||||
ReturnType<UpdateCallback<CombinedData, CombinedData>>,
|
ReturnType<UpdateCallback<CombinedData, CombinedData>>,
|
||||||
Parameters<UpdateCallback<CombinedData, CombinedData>>
|
Parameters<UpdateCallback<CombinedData, CombinedData>>
|
||||||
>();
|
>();
|
||||||
const subscription = derivedSubscribe(callback, client);
|
const subscription = derivedSubscribe(callback, client, variables);
|
||||||
const data = { totalCount: 0 };
|
const data = { totalCount: 0 };
|
||||||
combineData.mockReturnValueOnce(data);
|
combineData.mockReturnValueOnce(data);
|
||||||
await resolveQuery({
|
await resolveQuery({
|
||||||
|
@ -53,12 +53,12 @@ export interface PageInfo {
|
|||||||
export interface Subscribe<
|
export interface Subscribe<
|
||||||
Data,
|
Data,
|
||||||
Delta,
|
Delta,
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
> {
|
> {
|
||||||
(
|
(
|
||||||
callback: UpdateCallback<Data, Delta>,
|
callback: UpdateCallback<Data, Delta>,
|
||||||
client: ApolloClient<object>,
|
client: ApolloClient<object>,
|
||||||
variables?: Variables
|
variables: Variables
|
||||||
): {
|
): {
|
||||||
unsubscribe: () => void;
|
unsubscribe: () => void;
|
||||||
reload: Reload;
|
reload: Reload;
|
||||||
@ -73,14 +73,9 @@ export type Query<Result> = DocumentNode | TypedDocumentNode<Result, any>;
|
|||||||
export interface Update<
|
export interface Update<
|
||||||
Data,
|
Data,
|
||||||
Delta,
|
Delta,
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
> {
|
> {
|
||||||
(
|
(data: Data | null, delta: Delta, reload: Reload, variables: Variables): Data;
|
||||||
data: Data | null,
|
|
||||||
delta: Delta,
|
|
||||||
reload: Reload,
|
|
||||||
variables?: Variables
|
|
||||||
): Data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Append<Data> {
|
export interface Append<Data> {
|
||||||
@ -165,7 +160,7 @@ interface DataProviderParams<
|
|||||||
Data,
|
Data,
|
||||||
SubscriptionData,
|
SubscriptionData,
|
||||||
Delta,
|
Delta,
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
> {
|
> {
|
||||||
query: Query<QueryData>;
|
query: Query<QueryData>;
|
||||||
subscriptionQuery?: Query<SubscriptionData>;
|
subscriptionQuery?: Query<SubscriptionData>;
|
||||||
@ -200,7 +195,7 @@ function makeDataProviderInternal<
|
|||||||
Data,
|
Data,
|
||||||
SubscriptionData,
|
SubscriptionData,
|
||||||
Delta,
|
Delta,
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
>({
|
>({
|
||||||
query,
|
query,
|
||||||
subscriptionQuery,
|
subscriptionQuery,
|
||||||
@ -225,7 +220,7 @@ function makeDataProviderInternal<
|
|||||||
const updateQueue: Delta[] = [];
|
const updateQueue: Delta[] = [];
|
||||||
|
|
||||||
let resetTimer: ReturnType<typeof setTimeout>;
|
let resetTimer: ReturnType<typeof setTimeout>;
|
||||||
let variables: Variables | undefined;
|
let variables: Variables;
|
||||||
let data: Data | null = null;
|
let data: Data | null = null;
|
||||||
let error: Error | undefined;
|
let error: Error | undefined;
|
||||||
let loading = true;
|
let loading = true;
|
||||||
@ -492,7 +487,9 @@ function makeDataProviderInternal<
|
|||||||
callbacks.push(callback);
|
callbacks.push(callback);
|
||||||
if (callbacks.length === 1) {
|
if (callbacks.length === 1) {
|
||||||
client = c;
|
client = c;
|
||||||
variables = v;
|
if (v) {
|
||||||
|
variables = v;
|
||||||
|
}
|
||||||
initialize();
|
initialize();
|
||||||
} else {
|
} else {
|
||||||
notify(callback);
|
notify(callback);
|
||||||
@ -515,7 +512,7 @@ function makeDataProviderInternal<
|
|||||||
const memoize = <
|
const memoize = <
|
||||||
Data,
|
Data,
|
||||||
Delta,
|
Delta,
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
>(
|
>(
|
||||||
fn: () => Subscribe<Data, Delta, Variables>
|
fn: () => Subscribe<Data, Delta, Variables>
|
||||||
) => {
|
) => {
|
||||||
@ -563,7 +560,7 @@ export function makeDataProvider<
|
|||||||
Data,
|
Data,
|
||||||
SubscriptionData,
|
SubscriptionData,
|
||||||
Delta,
|
Delta,
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
>(
|
>(
|
||||||
params: DataProviderParams<
|
params: DataProviderParams<
|
||||||
QueryData,
|
QueryData,
|
||||||
@ -585,27 +582,27 @@ export function makeDataProvider<
|
|||||||
* This effects in parts in combine function has any[] type
|
* This effects in parts in combine function has any[] type
|
||||||
*/
|
*/
|
||||||
type DependencySubscribe<
|
type DependencySubscribe<
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
> = Subscribe<any, any, Variables>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
> = Subscribe<any, any, Variables>; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||||
type DependencyUpdateCallback<
|
type DependencyUpdateCallback<
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
> = Parameters<DependencySubscribe<Variables>>['0'];
|
> = Parameters<DependencySubscribe<Variables>>['0'];
|
||||||
export type DerivedPart<
|
export type DerivedPart<
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
> = Parameters<DependencyUpdateCallback<Variables>>['0'];
|
> = Parameters<DependencyUpdateCallback<Variables>>['0'];
|
||||||
export type CombineDerivedData<
|
export type CombineDerivedData<
|
||||||
Data,
|
Data,
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
> = (
|
> = (
|
||||||
data: DerivedPart<Variables>['data'][],
|
data: DerivedPart<Variables>['data'][],
|
||||||
variables: Variables | undefined,
|
variables: Variables,
|
||||||
prevData: Data | null
|
prevData: Data | null
|
||||||
) => Data | null;
|
) => Data | null;
|
||||||
|
|
||||||
export type CombineDerivedDelta<
|
export type CombineDerivedDelta<
|
||||||
Data,
|
Data,
|
||||||
Delta,
|
Delta,
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
> = (
|
> = (
|
||||||
data: Data,
|
data: Data,
|
||||||
parts: DerivedPart<Variables>[],
|
parts: DerivedPart<Variables>[],
|
||||||
@ -615,7 +612,7 @@ export type CombineDerivedDelta<
|
|||||||
|
|
||||||
export type CombineInsertionData<
|
export type CombineInsertionData<
|
||||||
Data,
|
Data,
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
> = (
|
> = (
|
||||||
data: Data,
|
data: Data,
|
||||||
parts: DerivedPart<Variables>[],
|
parts: DerivedPart<Variables>[],
|
||||||
@ -625,7 +622,7 @@ export type CombineInsertionData<
|
|||||||
function makeDerivedDataProviderInternal<
|
function makeDerivedDataProviderInternal<
|
||||||
Data,
|
Data,
|
||||||
Delta,
|
Delta,
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
>(
|
>(
|
||||||
dependencies: DependencySubscribe<Variables>[],
|
dependencies: DependencySubscribe<Variables>[],
|
||||||
combineData: CombineDerivedData<Data, Variables>,
|
combineData: CombineDerivedData<Data, Variables>,
|
||||||
@ -635,7 +632,7 @@ function makeDerivedDataProviderInternal<
|
|||||||
let subscriptions: ReturnType<DependencySubscribe>[] | undefined;
|
let subscriptions: ReturnType<DependencySubscribe>[] | undefined;
|
||||||
let client: ApolloClient<object>;
|
let client: ApolloClient<object>;
|
||||||
const callbacks: UpdateCallback<Data, Delta>[] = [];
|
const callbacks: UpdateCallback<Data, Delta>[] = [];
|
||||||
let variables: Variables | undefined;
|
let variables: Variables;
|
||||||
const parts: DerivedPart<Variables>[] = [];
|
const parts: DerivedPart<Variables>[] = [];
|
||||||
let data: Data | null = null;
|
let data: Data | null = null;
|
||||||
let error: Error | undefined;
|
let error: Error | undefined;
|
||||||
@ -756,7 +753,9 @@ function makeDerivedDataProviderInternal<
|
|||||||
callbacks.push(callback);
|
callbacks.push(callback);
|
||||||
if (callbacks.length === 1) {
|
if (callbacks.length === 1) {
|
||||||
client = c;
|
client = c;
|
||||||
variables = v;
|
if (v) {
|
||||||
|
variables = v;
|
||||||
|
}
|
||||||
initialize();
|
initialize();
|
||||||
} else {
|
} else {
|
||||||
notify(callback);
|
notify(callback);
|
||||||
@ -777,7 +776,7 @@ function makeDerivedDataProviderInternal<
|
|||||||
export function makeDerivedDataProvider<
|
export function makeDerivedDataProvider<
|
||||||
Data,
|
Data,
|
||||||
Delta,
|
Delta,
|
||||||
Variables extends OperationVariables = OperationVariables
|
Variables extends OperationVariables | undefined = undefined
|
||||||
>(
|
>(
|
||||||
dependencies: DependencySubscribe<Variables>[],
|
dependencies: DependencySubscribe<Variables>[],
|
||||||
combineData: CombineDerivedData<Data, Variables>,
|
combineData: CombineDerivedData<Data, Variables>,
|
||||||
|
@ -29,12 +29,16 @@ export const encodeTransaction = (tx: Transaction): string => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const normalizeOrderSubmission = <T extends Exact<OrderSubmission, T>>(
|
export const normalizeOrderSubmission = (
|
||||||
order: T,
|
order: OrderSubmission,
|
||||||
decimalPlaces: number,
|
decimalPlaces: number,
|
||||||
positionDecimalPlaces: number
|
positionDecimalPlaces: number
|
||||||
): OrderSubmission => ({
|
): OrderSubmission => ({
|
||||||
...order,
|
marketId: order.marketId,
|
||||||
|
reference: order.reference,
|
||||||
|
type: order.type,
|
||||||
|
side: order.side,
|
||||||
|
timeInForce: order.timeInForce,
|
||||||
price:
|
price:
|
||||||
order.type === OrderType.TYPE_LIMIT && order.price
|
order.type === OrderType.TYPE_LIMIT && order.price
|
||||||
? removeDecimal(order.price, decimalPlaces)
|
? removeDecimal(order.price, decimalPlaces)
|
||||||
|
@ -19,10 +19,9 @@ export const WithdrawFormContainer = ({
|
|||||||
partyId,
|
partyId,
|
||||||
submit,
|
submit,
|
||||||
}: WithdrawFormContainerProps) => {
|
}: WithdrawFormContainerProps) => {
|
||||||
const variables = useMemo(() => ({ partyId }), [partyId]);
|
|
||||||
const { data, loading, error } = useDataProvider({
|
const { data, loading, error } = useDataProvider({
|
||||||
dataProvider: accountsDataProvider,
|
dataProvider: accountsDataProvider,
|
||||||
variables,
|
variables: { partyId: partyId || '' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const filteredAsset = useMemo(
|
const filteredAsset = useMemo(
|
||||||
|
Loading…
Reference in New Issue
Block a user