Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
946e1b5226 | ||
|
|
13ae166235 | ||
|
|
bee7b9faad | ||
|
|
097bf7c08c | ||
|
|
236e35a92b | ||
|
|
6fe8fbc681 | ||
|
|
a22e2f0921 | ||
|
|
02fc056def | ||
|
|
abf84b9d45 | ||
|
|
6d2a2ea0a0 | ||
|
|
6ac79e9f6d | ||
|
|
835ee64243 | ||
|
|
e7c3b5054c | ||
|
|
209a430707 | ||
|
|
6cc32eb03e | ||
|
|
7897f08a88 | ||
|
|
2ea15c4dab | ||
|
|
87cffd646b | ||
|
|
77ae530564 | ||
|
|
45fd9563c6 | ||
|
|
ae8a721d94 | ||
|
|
17c49454bd | ||
|
|
cab087449b | ||
|
|
01842a78b0 | ||
|
|
c27f08c672 | ||
|
|
8263712111 | ||
|
|
c5105d49cb | ||
|
|
6d864c0c3c | ||
|
|
8f95e8a376 | ||
|
|
47edb908d0 | ||
|
|
45ab8e51b5 | ||
|
|
3f14580bbd | ||
|
|
daa737c0e4 |
+1
-1
@@ -1,2 +1,2 @@
|
||||
* @vegaprotocol/frontend @vegaprotocol/frontend-qa
|
||||
* @vegaprotocol/frontend
|
||||
*.graphql @vegaprotocol/core
|
||||
|
||||
+1
-3
@@ -128,9 +128,7 @@ describe('<ProposalReferralProgramDetails />', () => {
|
||||
it('should not render if there are no relevant fields', () => {
|
||||
const incompleteProposal = generateProposal({
|
||||
terms: {
|
||||
change: {
|
||||
__typename: 'UpdateReferralProgram',
|
||||
},
|
||||
change: {},
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ import {
|
||||
blockStatisticsQuery,
|
||||
networkParamQuery,
|
||||
liquidityProvisionsQuery,
|
||||
liquidityProviderFeeShareQuery,
|
||||
successorMarketQuery,
|
||||
parentMarketIdQuery,
|
||||
successorMarketIdsQuery,
|
||||
@@ -162,11 +161,7 @@ const mockTradingPage = (
|
||||
aliasGQLQuery(req, 'Trades', tradesQuery());
|
||||
aliasGQLQuery(req, 'Chart', chartQuery());
|
||||
aliasGQLQuery(req, 'LiquidityProvisions', liquidityProvisionsQuery());
|
||||
aliasGQLQuery(
|
||||
req,
|
||||
'LiquidityProviderFeeShare',
|
||||
liquidityProviderFeeShareQuery
|
||||
);
|
||||
aliasGQLQuery(req, 'LiquidityProviderFeeShare');
|
||||
aliasGQLQuery(req, 'Candles', candlesQuery());
|
||||
aliasGQLQuery(req, 'Withdrawals', withdrawalsQuery());
|
||||
aliasGQLQuery(req, 'NetworkParams', networkParamsQuery());
|
||||
|
||||
@@ -21,6 +21,7 @@ const market = {
|
||||
} as unknown as Market;
|
||||
|
||||
let mockDataSuccessorMarket: PartialDeep<Market> | null = null;
|
||||
let mockDataMarketState: Market['state'] | null = null;
|
||||
jest.mock('@vegaprotocol/data-provider', () => ({
|
||||
...jest.requireActual('@vegaprotocol/data-provider'),
|
||||
useDataProvider: jest.fn().mockImplementation((args) => {
|
||||
@@ -43,6 +44,12 @@ jest.mock('@vegaprotocol/utils', () => ({
|
||||
let mockCandles = {};
|
||||
jest.mock('@vegaprotocol/markets', () => ({
|
||||
...jest.requireActual('@vegaprotocol/markets'),
|
||||
useMarketState: (marketId: string) =>
|
||||
marketId
|
||||
? {
|
||||
data: mockDataMarketState,
|
||||
}
|
||||
: { data: undefined },
|
||||
useSuccessorMarket: (marketId: string) =>
|
||||
marketId
|
||||
? {
|
||||
@@ -81,30 +88,6 @@ describe('MarketSuccessorBanner', () => {
|
||||
});
|
||||
expect(container).toBeEmptyDOMElement();
|
||||
});
|
||||
|
||||
it('successor market not in continuous mode', () => {
|
||||
mockDataSuccessorMarket = {
|
||||
...mockDataSuccessorMarket,
|
||||
tradingMode: Types.MarketTradingMode.TRADING_MODE_NO_TRADING,
|
||||
};
|
||||
const { container } = render(<MarketSuccessorBanner market={market} />, {
|
||||
wrapper: MockedProvider,
|
||||
});
|
||||
expect(container).toBeEmptyDOMElement();
|
||||
expect(allUtils.getMarketExpiryDate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('successor market is not active', () => {
|
||||
mockDataSuccessorMarket = {
|
||||
...mockDataSuccessorMarket,
|
||||
state: Types.MarketState.STATE_PENDING,
|
||||
};
|
||||
const { container } = render(<MarketSuccessorBanner market={market} />, {
|
||||
wrapper: MockedProvider,
|
||||
});
|
||||
expect(container).toBeEmptyDOMElement();
|
||||
expect(allUtils.getMarketExpiryDate).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('should be displayed', () => {
|
||||
@@ -120,6 +103,17 @@ describe('MarketSuccessorBanner', () => {
|
||||
).toHaveAttribute('href', '/#/markets/successorMarketID');
|
||||
});
|
||||
|
||||
it('no successor market data, market settled', () => {
|
||||
mockDataSuccessorMarket = null;
|
||||
mockDataMarketState = Types.MarketState.STATE_SETTLED;
|
||||
render(<MarketSuccessorBanner market={market} />, {
|
||||
wrapper: MockedProvider,
|
||||
});
|
||||
expect(
|
||||
screen.getByText('This market has been settled')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display optionally successor volume', () => {
|
||||
mockDataSuccessorMarket = {
|
||||
...mockDataSuccessorMarket,
|
||||
@@ -137,7 +131,9 @@ describe('MarketSuccessorBanner', () => {
|
||||
render(<MarketSuccessorBanner market={market} />, {
|
||||
wrapper: MockedProvider,
|
||||
});
|
||||
expect(screen.getByText('has 101.367 24h vol.')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('has a 24h trading volume of 101.367')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display optionally duration', () => {
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { Market } from '@vegaprotocol/markets';
|
||||
import {
|
||||
calcCandleVolume,
|
||||
useCandles,
|
||||
useMarketState,
|
||||
useSuccessorMarket,
|
||||
} from '@vegaprotocol/markets';
|
||||
import {
|
||||
@@ -29,7 +30,9 @@ export const MarketSuccessorBanner = ({
|
||||
}: {
|
||||
market: Market | null;
|
||||
}) => {
|
||||
const { data: successorData } = useSuccessorMarket(market?.id);
|
||||
const { data: marketState } = useMarketState(market?.id);
|
||||
const isSettled = marketState === Types.MarketState.STATE_SETTLED;
|
||||
const { data: successorData, loading } = useSuccessorMarket(market?.id);
|
||||
|
||||
const [visible, setVisible] = useState(true);
|
||||
|
||||
@@ -45,11 +48,6 @@ export const MarketSuccessorBanner = ({
|
||||
? intervalToDuration({ start: new Date(), end: expiry })
|
||||
: null;
|
||||
|
||||
const isInContinuesMode =
|
||||
successorData?.state === Types.MarketState.STATE_ACTIVE &&
|
||||
successorData?.tradingMode ===
|
||||
Types.MarketTradingMode.TRADING_MODE_CONTINUOUS;
|
||||
|
||||
const { oneDayCandles } = useCandles({
|
||||
marketId: successorData?.id,
|
||||
});
|
||||
@@ -66,7 +64,7 @@ export const MarketSuccessorBanner = ({
|
||||
)
|
||||
: null;
|
||||
|
||||
if (isInContinuesMode && visible) {
|
||||
if (!loading && (isSettled || successorData) && visible) {
|
||||
return (
|
||||
<NotificationBanner
|
||||
intent={Intent.Primary}
|
||||
@@ -74,34 +72,47 @@ export const MarketSuccessorBanner = ({
|
||||
setVisible(false);
|
||||
}}
|
||||
>
|
||||
<div className="uppercase mb-1">
|
||||
{t('This market has been succeeded')}
|
||||
</div>
|
||||
<div>
|
||||
{duration && (
|
||||
<span>
|
||||
{t('This market expires in %s.', [
|
||||
formatDuration(duration, {
|
||||
format: [
|
||||
'years',
|
||||
'months',
|
||||
'weeks',
|
||||
'days',
|
||||
'hours',
|
||||
'minutes',
|
||||
],
|
||||
}),
|
||||
])}
|
||||
</span>
|
||||
)}{' '}
|
||||
{t('The successor market')}{' '}
|
||||
<ExternalLink href={`/#/markets/${successorData?.id}`}>
|
||||
{successorData?.tradableInstrument.instrument.name}
|
||||
</ExternalLink>
|
||||
{successorVolume && (
|
||||
<span> {t('has %s 24h vol.', [successorVolume])}</span>
|
||||
)}
|
||||
<div className="uppercase">
|
||||
{successorData
|
||||
? t('This market has been succeeded')
|
||||
: t('This market has been settled')}
|
||||
</div>
|
||||
{(duration || successorData) && (
|
||||
<div className="mt-1">
|
||||
{duration && (
|
||||
<span>
|
||||
{t('This market expires in %s.', [
|
||||
formatDuration(duration, {
|
||||
format: [
|
||||
'years',
|
||||
'months',
|
||||
'weeks',
|
||||
'days',
|
||||
'hours',
|
||||
'minutes',
|
||||
],
|
||||
}),
|
||||
])}
|
||||
</span>
|
||||
)}
|
||||
{successorData && (
|
||||
<>
|
||||
{' '}
|
||||
{t('The successor market')}
|
||||
{!successorVolume ? ' is ' : ' '}
|
||||
<ExternalLink href={`/#/markets/${successorData?.id}`}>
|
||||
{successorData?.tradableInstrument.instrument.name}
|
||||
</ExternalLink>
|
||||
{successorVolume && (
|
||||
<span>
|
||||
{' '}
|
||||
{t('has a 24h trading volume of %s', [successorVolume])}
|
||||
</span>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</NotificationBanner>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ const MarketData = ({
|
||||
variables: {
|
||||
marketId: market.id,
|
||||
},
|
||||
fetchPolicy: 'no-cache',
|
||||
});
|
||||
|
||||
const marketData = data?.marketsData[0];
|
||||
@@ -70,6 +71,8 @@ const MarketData = ({
|
||||
|
||||
const marketTradingMode = marketData
|
||||
? marketData.marketTradingMode
|
||||
: market.data
|
||||
? market.data.marketTradingMode
|
||||
: market.tradingMode;
|
||||
|
||||
const mode = [
|
||||
@@ -95,7 +98,7 @@ const MarketData = ({
|
||||
<>
|
||||
<div className="w-2/5" role="gridcell">
|
||||
<h3 className="flex items-baseline">
|
||||
<span className="text-sm lg:text-base text-ellipsis whitespace-nowrap overflow-hidden">
|
||||
<span className="overflow-hidden text-sm lg:text-base text-ellipsis whitespace-nowrap">
|
||||
{market.tradableInstrument.instrument.code}
|
||||
</span>
|
||||
{allProducts && productType && (
|
||||
|
||||
@@ -2,7 +2,10 @@ import { render, screen } from '@testing-library/react';
|
||||
import userEvent from '@testing-library/user-event';
|
||||
import { MarketSelector } from './market-selector';
|
||||
import { useMarketList } from '@vegaprotocol/markets';
|
||||
import { createMarketFragment } from '@vegaprotocol/mock';
|
||||
import {
|
||||
createMarketFragment,
|
||||
createMarketsDataFragment,
|
||||
} from '@vegaprotocol/mock';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import type { ReactNode } from 'react';
|
||||
@@ -36,6 +39,10 @@ describe('MarketSelector', () => {
|
||||
const markets = [
|
||||
createMarketFragment({
|
||||
id: 'market-0',
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'a',
|
||||
@@ -56,7 +63,10 @@ describe('MarketSelector', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-1',
|
||||
state: MarketState.STATE_SUSPENDED,
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_SUSPENDED,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'b',
|
||||
@@ -77,7 +87,10 @@ describe('MarketSelector', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-2',
|
||||
state: MarketState.STATE_CLOSED,
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_CLOSED,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
@@ -91,7 +104,10 @@ describe('MarketSelector', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-3',
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'c',
|
||||
@@ -112,6 +128,10 @@ describe('MarketSelector', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-4',
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'cd',
|
||||
@@ -132,7 +152,10 @@ describe('MarketSelector', () => {
|
||||
}),
|
||||
];
|
||||
|
||||
const activeMarkets = markets.filter((m) => isMarketActive(m.state));
|
||||
const activeMarkets = markets.filter((m) =>
|
||||
// @ts-ignore candles get joined outside this type
|
||||
isMarketActive(m.data.marketState)
|
||||
);
|
||||
mockUseMarketList.mockReturnValue({
|
||||
data: markets,
|
||||
loading: false,
|
||||
|
||||
@@ -4,7 +4,10 @@ import { useMarketSelectorList } from './use-market-selector-list';
|
||||
import { isMarketActive } from '../../lib/utils';
|
||||
import { Product } from './product-selector';
|
||||
import { Sort } from './sort-dropdown';
|
||||
import { createMarketFragment } from '@vegaprotocol/mock';
|
||||
import {
|
||||
createMarketFragment,
|
||||
createMarketsDataFragment,
|
||||
} from '@vegaprotocol/mock';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import { useMarketList } from '@vegaprotocol/markets';
|
||||
import type { Filter } from './market-selector';
|
||||
@@ -31,22 +34,40 @@ describe('useMarketSelectorList', () => {
|
||||
|
||||
it('returns all markets active and suspended markets', () => {
|
||||
const markets = [
|
||||
createMarketFragment({ id: 'market-0' }),
|
||||
createMarketFragment({
|
||||
id: 'market-0',
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-1',
|
||||
state: MarketState.STATE_SUSPENDED,
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_SUSPENDED,
|
||||
}),
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-2',
|
||||
state: MarketState.STATE_CLOSED,
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_CLOSED,
|
||||
}),
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-3',
|
||||
state: MarketState.STATE_CLOSED,
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_CLOSED,
|
||||
}),
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-4',
|
||||
state: MarketState.STATE_PENDING,
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_PENDING,
|
||||
}),
|
||||
}),
|
||||
];
|
||||
mockUseMarketList.mockReturnValue({
|
||||
@@ -56,7 +77,8 @@ describe('useMarketSelectorList', () => {
|
||||
});
|
||||
const { result } = setup();
|
||||
const expectedFilteredMarkets = markets.filter((m) =>
|
||||
isMarketActive(m.state)
|
||||
// @ts-ignore candles get joined outside this type
|
||||
isMarketActive(m.data.marketState)
|
||||
);
|
||||
expect(result.current).toEqual({
|
||||
data: markets,
|
||||
@@ -70,6 +92,10 @@ describe('useMarketSelectorList', () => {
|
||||
const markets = [
|
||||
createMarketFragment({
|
||||
id: 'market-0',
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
@@ -90,6 +116,10 @@ describe('useMarketSelectorList', () => {
|
||||
// }),
|
||||
createMarketFragment({
|
||||
id: 'market-2',
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
@@ -135,6 +165,10 @@ describe('useMarketSelectorList', () => {
|
||||
const markets = [
|
||||
createMarketFragment({
|
||||
id: 'market-0',
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
@@ -148,6 +182,10 @@ describe('useMarketSelectorList', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-1',
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
@@ -161,6 +199,10 @@ describe('useMarketSelectorList', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-2',
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
@@ -174,6 +216,10 @@ describe('useMarketSelectorList', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-3',
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
@@ -238,6 +284,10 @@ describe('useMarketSelectorList', () => {
|
||||
const markets = [
|
||||
createMarketFragment({
|
||||
id: 'market-0',
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'abc',
|
||||
@@ -247,6 +297,10 @@ describe('useMarketSelectorList', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-1',
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'def',
|
||||
@@ -256,6 +310,10 @@ describe('useMarketSelectorList', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-2',
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'defg',
|
||||
@@ -265,6 +323,10 @@ describe('useMarketSelectorList', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-3',
|
||||
// @ts-ignore candles get joined outside this type
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
code: 'ggg',
|
||||
@@ -333,11 +395,11 @@ describe('useMarketSelectorList', () => {
|
||||
const markets = [
|
||||
createMarketFragment({
|
||||
id: 'market-0',
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
// @ts-ignore data not on fragment
|
||||
data: {
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
markPrice: '1',
|
||||
},
|
||||
}),
|
||||
// @ts-ignore candles not on fragment
|
||||
candles: [
|
||||
{
|
||||
@@ -349,9 +411,10 @@ describe('useMarketSelectorList', () => {
|
||||
id: 'market-1',
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
// @ts-ignore data not on fragment
|
||||
data: {
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
markPrice: '1',
|
||||
},
|
||||
}),
|
||||
// @ts-ignore candles not on fragment
|
||||
candles: [
|
||||
{
|
||||
@@ -363,9 +426,10 @@ describe('useMarketSelectorList', () => {
|
||||
id: 'market-2',
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
// @ts-ignore data not on fragment
|
||||
data: {
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
markPrice: '1',
|
||||
},
|
||||
}),
|
||||
// @ts-ignore candles not on fragment
|
||||
candles: [
|
||||
{
|
||||
@@ -377,9 +441,10 @@ describe('useMarketSelectorList', () => {
|
||||
id: 'market-3',
|
||||
state: MarketState.STATE_ACTIVE,
|
||||
// @ts-ignore data not on fragment
|
||||
data: {
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
markPrice: '1',
|
||||
},
|
||||
}),
|
||||
// @ts-ignore candles not on fragment
|
||||
candles: [
|
||||
{
|
||||
@@ -414,6 +479,10 @@ describe('useMarketSelectorList', () => {
|
||||
const markets = [
|
||||
createMarketFragment({
|
||||
id: 'market-0',
|
||||
// @ts-ignore data not on fragment
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
// @ts-ignore actual fragment doesn't contain candles and is joined later
|
||||
candles: [
|
||||
{
|
||||
@@ -426,6 +495,10 @@ describe('useMarketSelectorList', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-1',
|
||||
// @ts-ignore data not on fragment
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
// @ts-ignore actual fragment doesn't contain candles and is joined later
|
||||
candles: [
|
||||
{
|
||||
@@ -438,6 +511,10 @@ describe('useMarketSelectorList', () => {
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-2',
|
||||
// @ts-ignore data not on fragment
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
// @ts-ignore actual fragment doesn't contain candles and is joined later
|
||||
candles: [
|
||||
{
|
||||
@@ -482,18 +559,30 @@ describe('useMarketSelectorList', () => {
|
||||
const markets = [
|
||||
createMarketFragment({
|
||||
id: 'market-0',
|
||||
// @ts-ignore data not on fragment
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
marketTimestamps: {
|
||||
open: subDays(new Date(), 3).toISOString(),
|
||||
},
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-1',
|
||||
// @ts-ignore data not on fragment
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
marketTimestamps: {
|
||||
open: subDays(new Date(), 1).toISOString(),
|
||||
},
|
||||
}),
|
||||
createMarketFragment({
|
||||
id: 'market-2',
|
||||
// @ts-ignore data not on fragment
|
||||
data: createMarketsDataFragment({
|
||||
marketState: MarketState.STATE_ACTIVE,
|
||||
}),
|
||||
marketTimestamps: {
|
||||
open: subDays(new Date(), 2).toISOString(),
|
||||
},
|
||||
|
||||
@@ -22,8 +22,12 @@ export const useMarketSelectorList = ({
|
||||
const markets = useMemo(() => {
|
||||
if (!data?.length) return [];
|
||||
const markets = data
|
||||
// only active
|
||||
.filter((m) => isMarketActive(m.state))
|
||||
// show only active markets, using m.data.marketState as this will be
|
||||
// data that will get refreshed when calling reload
|
||||
.filter((m) => {
|
||||
if (!m.data) return false;
|
||||
return isMarketActive(m.data.marketState);
|
||||
})
|
||||
// only selected product type
|
||||
.filter((m) => {
|
||||
if (
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export const SSRLoader = () => {
|
||||
const randomDelay = () => {
|
||||
return parseFloat((Math.random() * (4 - 1) + 1).toFixed(2));
|
||||
};
|
||||
import { pseudoRandom } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
const generate = pseudoRandom(1);
|
||||
|
||||
export const SSRLoader = () => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
@@ -38,10 +38,9 @@ export const SSRLoader = () => {
|
||||
width: 10,
|
||||
height: 10,
|
||||
animation: 'flickering 0.4s linear alternate infinite',
|
||||
animationDelay: `-${randomDelay()}s`,
|
||||
animationDelay: `-${generate()}s`,
|
||||
animationDirection: i % 2 === 0 ? 'reverse' : 'alternate',
|
||||
background: 'black',
|
||||
opacity: Math.random() > 0.5 ? 1 : 0,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -57,7 +57,16 @@ export const rows: Rows = [
|
||||
key: AssetDetail.ID,
|
||||
label: t('ID'),
|
||||
tooltip: '',
|
||||
value: (asset) => truncateMiddle(asset.id),
|
||||
value: (asset) => (
|
||||
<>
|
||||
{truncateMiddle(asset.id)}{' '}
|
||||
<CopyWithTooltip text={asset.id}>
|
||||
<button title={t('Copy id to clipboard')}>
|
||||
<VegaIcon size={14} name={VegaIconNames.COPY} />
|
||||
</button>
|
||||
</CopyWithTooltip>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
key: AssetDetail.TYPE,
|
||||
|
||||
@@ -14,16 +14,17 @@ export const MarketProductPill = ({
|
||||
}: {
|
||||
productType?: ProductType;
|
||||
}) => {
|
||||
if (!productType) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
productType && (
|
||||
<Pill
|
||||
size="xxs"
|
||||
className="uppercase ml-0.5"
|
||||
title={ProductTypeMapping[productType]}
|
||||
>
|
||||
{ProductTypeShortName[productType]}
|
||||
</Pill>
|
||||
)
|
||||
<Pill
|
||||
size="xxs"
|
||||
className="uppercase ml-0.5"
|
||||
title={ProductTypeMapping[productType]}
|
||||
>
|
||||
{ProductTypeShortName[productType]}
|
||||
</Pill>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -32,39 +32,43 @@ query LiquidityProvisions($marketId: ID!) {
|
||||
}
|
||||
}
|
||||
|
||||
subscription LiquidityProvisionsUpdate($partyId: ID, $marketId: ID) {
|
||||
liquidityProvisions(partyId: $partyId, marketId: $marketId) {
|
||||
id
|
||||
partyID
|
||||
createdAt
|
||||
updatedAt
|
||||
marketID
|
||||
commitmentAmount
|
||||
fee
|
||||
status
|
||||
}
|
||||
}
|
||||
|
||||
# Liquidity Provider Share Fee
|
||||
|
||||
fragment LiquidityProviderFeeShareFields on LiquidityProviderFeeShare {
|
||||
party {
|
||||
id
|
||||
}
|
||||
equityLikeShare
|
||||
averageEntryValuation
|
||||
averageScore
|
||||
virtualStake
|
||||
}
|
||||
|
||||
query LiquidityProviderFeeShare($marketId: ID!) {
|
||||
market(id: $marketId) {
|
||||
id
|
||||
data {
|
||||
market {
|
||||
id
|
||||
}
|
||||
liquidityProviderFeeShare {
|
||||
...LiquidityProviderFeeShareFields
|
||||
fragment LiquidityProviderSLAFields on LiquidityProviderSLA {
|
||||
currentEpochFractionOfTimeOnBook
|
||||
lastEpochFractionOfTimeOnBook
|
||||
lastEpochFeePenalty
|
||||
lastEpochBondPenalty
|
||||
hysteresisPeriodFeePenalties
|
||||
requiredLiquidity
|
||||
notionalVolumeBuys
|
||||
notionalVolumeSells
|
||||
}
|
||||
|
||||
query LiquidityProviders($marketId: ID!) {
|
||||
liquidityProviders(marketId: $marketId) {
|
||||
edges {
|
||||
node {
|
||||
...LiquidityProviderFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fragment LiquidityProviderFields on LiquidityProvider {
|
||||
partyId
|
||||
marketId
|
||||
feeShare {
|
||||
...LiquidityProviderFeeShareFields
|
||||
}
|
||||
sla {
|
||||
...LiquidityProviderSLAFields
|
||||
}
|
||||
}
|
||||
|
||||
+51
-73
@@ -12,22 +12,18 @@ export type LiquidityProvisionsQueryVariables = Types.Exact<{
|
||||
|
||||
export type LiquidityProvisionsQuery = { __typename?: 'Query', market?: { __typename?: 'Market', liquidityProvisionsConnection?: { __typename?: 'LiquidityProvisionsConnection', edges?: Array<{ __typename?: 'LiquidityProvisionsEdge', node: { __typename?: 'LiquidityProvision', id: string, createdAt: any, updatedAt?: any | null, commitmentAmount: string, fee: string, status: Types.LiquidityProvisionStatus, party: { __typename?: 'Party', id: string, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string } } | null> | null } | null } } } | null> | null } | null } | null };
|
||||
|
||||
export type LiquidityProvisionsUpdateSubscriptionVariables = Types.Exact<{
|
||||
partyId?: Types.InputMaybe<Types.Scalars['ID']>;
|
||||
marketId?: Types.InputMaybe<Types.Scalars['ID']>;
|
||||
}>;
|
||||
export type LiquidityProviderFeeShareFieldsFragment = { __typename?: 'LiquidityProviderFeeShare', equityLikeShare: string, averageEntryValuation: string, averageScore: string, virtualStake: string };
|
||||
|
||||
export type LiquidityProviderSLAFieldsFragment = { __typename?: 'LiquidityProviderSLA', currentEpochFractionOfTimeOnBook: string, lastEpochFractionOfTimeOnBook: string, lastEpochFeePenalty: string, lastEpochBondPenalty: string, hysteresisPeriodFeePenalties?: Array<string> | null, requiredLiquidity: string, notionalVolumeBuys: string, notionalVolumeSells: string };
|
||||
|
||||
export type LiquidityProvisionsUpdateSubscription = { __typename?: 'Subscription', liquidityProvisions?: Array<{ __typename?: 'LiquidityProvisionUpdate', id: string, partyID: string, createdAt: any, updatedAt?: any | null, marketID: string, commitmentAmount: string, fee: string, status: Types.LiquidityProvisionStatus }> | null };
|
||||
|
||||
export type LiquidityProviderFeeShareFieldsFragment = { __typename?: 'LiquidityProviderFeeShare', equityLikeShare: string, averageEntryValuation: string, party: { __typename?: 'Party', id: string } };
|
||||
|
||||
export type LiquidityProviderFeeShareQueryVariables = Types.Exact<{
|
||||
export type LiquidityProvidersQueryVariables = Types.Exact<{
|
||||
marketId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type LiquidityProviderFeeShareQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, data?: { __typename?: 'MarketData', market: { __typename?: 'Market', id: string }, liquidityProviderFeeShare?: Array<{ __typename?: 'LiquidityProviderFeeShare', equityLikeShare: string, averageEntryValuation: string, party: { __typename?: 'Party', id: string } }> | null } | null } | null };
|
||||
export type LiquidityProvidersQuery = { __typename?: 'Query', liquidityProviders?: { __typename?: 'LiquidityProviderConnection', edges: Array<{ __typename?: 'LiquidityProviderEdge', node: { __typename?: 'LiquidityProvider', partyId: string, marketId: string, feeShare?: { __typename?: 'LiquidityProviderFeeShare', equityLikeShare: string, averageEntryValuation: string, averageScore: string, virtualStake: string } | null, sla?: { __typename?: 'LiquidityProviderSLA', currentEpochFractionOfTimeOnBook: string, lastEpochFractionOfTimeOnBook: string, lastEpochFeePenalty: string, lastEpochBondPenalty: string, hysteresisPeriodFeePenalties?: Array<string> | null, requiredLiquidity: string, notionalVolumeBuys: string, notionalVolumeSells: string } | null } }> } | null };
|
||||
|
||||
export type LiquidityProviderFieldsFragment = { __typename?: 'LiquidityProvider', partyId: string, marketId: string, feeShare?: { __typename?: 'LiquidityProviderFeeShare', equityLikeShare: string, averageEntryValuation: string, averageScore: string, virtualStake: string } | null, sla?: { __typename?: 'LiquidityProviderSLA', currentEpochFractionOfTimeOnBook: string, lastEpochFractionOfTimeOnBook: string, lastEpochFeePenalty: string, lastEpochBondPenalty: string, hysteresisPeriodFeePenalties?: Array<string> | null, requiredLiquidity: string, notionalVolumeBuys: string, notionalVolumeSells: string } | null };
|
||||
|
||||
export const LiquidityProvisionFieldsFragmentDoc = gql`
|
||||
fragment LiquidityProvisionFields on LiquidityProvision {
|
||||
@@ -52,13 +48,37 @@ export const LiquidityProvisionFieldsFragmentDoc = gql`
|
||||
`;
|
||||
export const LiquidityProviderFeeShareFieldsFragmentDoc = gql`
|
||||
fragment LiquidityProviderFeeShareFields on LiquidityProviderFeeShare {
|
||||
party {
|
||||
id
|
||||
}
|
||||
equityLikeShare
|
||||
averageEntryValuation
|
||||
averageScore
|
||||
virtualStake
|
||||
}
|
||||
`;
|
||||
export const LiquidityProviderSLAFieldsFragmentDoc = gql`
|
||||
fragment LiquidityProviderSLAFields on LiquidityProviderSLA {
|
||||
currentEpochFractionOfTimeOnBook
|
||||
lastEpochFractionOfTimeOnBook
|
||||
lastEpochFeePenalty
|
||||
lastEpochBondPenalty
|
||||
hysteresisPeriodFeePenalties
|
||||
requiredLiquidity
|
||||
notionalVolumeBuys
|
||||
notionalVolumeSells
|
||||
}
|
||||
`;
|
||||
export const LiquidityProviderFieldsFragmentDoc = gql`
|
||||
fragment LiquidityProviderFields on LiquidityProvider {
|
||||
partyId
|
||||
marketId
|
||||
feeShare {
|
||||
...LiquidityProviderFeeShareFields
|
||||
}
|
||||
sla {
|
||||
...LiquidityProviderSLAFields
|
||||
}
|
||||
}
|
||||
${LiquidityProviderFeeShareFieldsFragmentDoc}
|
||||
${LiquidityProviderSLAFieldsFragmentDoc}`;
|
||||
export const LiquidityProvisionsDocument = gql`
|
||||
query LiquidityProvisions($marketId: ID!) {
|
||||
market(id: $marketId) {
|
||||
@@ -100,84 +120,42 @@ export function useLiquidityProvisionsLazyQuery(baseOptions?: Apollo.LazyQueryHo
|
||||
export type LiquidityProvisionsQueryHookResult = ReturnType<typeof useLiquidityProvisionsQuery>;
|
||||
export type LiquidityProvisionsLazyQueryHookResult = ReturnType<typeof useLiquidityProvisionsLazyQuery>;
|
||||
export type LiquidityProvisionsQueryResult = Apollo.QueryResult<LiquidityProvisionsQuery, LiquidityProvisionsQueryVariables>;
|
||||
export const LiquidityProvisionsUpdateDocument = gql`
|
||||
subscription LiquidityProvisionsUpdate($partyId: ID, $marketId: ID) {
|
||||
liquidityProvisions(partyId: $partyId, marketId: $marketId) {
|
||||
id
|
||||
partyID
|
||||
createdAt
|
||||
updatedAt
|
||||
marketID
|
||||
commitmentAmount
|
||||
fee
|
||||
status
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useLiquidityProvisionsUpdateSubscription__
|
||||
*
|
||||
* To run a query within a React component, call `useLiquidityProvisionsUpdateSubscription` and pass it any options that fit your needs.
|
||||
* When your component renders, `useLiquidityProvisionsUpdateSubscription` 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 subscription, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useLiquidityProvisionsUpdateSubscription({
|
||||
* variables: {
|
||||
* partyId: // value for 'partyId'
|
||||
* marketId: // value for 'marketId'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useLiquidityProvisionsUpdateSubscription(baseOptions?: Apollo.SubscriptionHookOptions<LiquidityProvisionsUpdateSubscription, LiquidityProvisionsUpdateSubscriptionVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useSubscription<LiquidityProvisionsUpdateSubscription, LiquidityProvisionsUpdateSubscriptionVariables>(LiquidityProvisionsUpdateDocument, options);
|
||||
}
|
||||
export type LiquidityProvisionsUpdateSubscriptionHookResult = ReturnType<typeof useLiquidityProvisionsUpdateSubscription>;
|
||||
export type LiquidityProvisionsUpdateSubscriptionResult = Apollo.SubscriptionResult<LiquidityProvisionsUpdateSubscription>;
|
||||
export const LiquidityProviderFeeShareDocument = gql`
|
||||
query LiquidityProviderFeeShare($marketId: ID!) {
|
||||
market(id: $marketId) {
|
||||
id
|
||||
data {
|
||||
market {
|
||||
id
|
||||
}
|
||||
liquidityProviderFeeShare {
|
||||
...LiquidityProviderFeeShareFields
|
||||
export const LiquidityProvidersDocument = gql`
|
||||
query LiquidityProviders($marketId: ID!) {
|
||||
liquidityProviders(marketId: $marketId) {
|
||||
edges {
|
||||
node {
|
||||
...LiquidityProviderFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${LiquidityProviderFeeShareFieldsFragmentDoc}`;
|
||||
${LiquidityProviderFieldsFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __useLiquidityProviderFeeShareQuery__
|
||||
* __useLiquidityProvidersQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useLiquidityProviderFeeShareQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useLiquidityProviderFeeShareQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* To run a query within a React component, call `useLiquidityProvidersQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useLiquidityProvidersQuery` 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 } = useLiquidityProviderFeeShareQuery({
|
||||
* const { data, loading, error } = useLiquidityProvidersQuery({
|
||||
* variables: {
|
||||
* marketId: // value for 'marketId'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useLiquidityProviderFeeShareQuery(baseOptions: Apollo.QueryHookOptions<LiquidityProviderFeeShareQuery, LiquidityProviderFeeShareQueryVariables>) {
|
||||
export function useLiquidityProvidersQuery(baseOptions: Apollo.QueryHookOptions<LiquidityProvidersQuery, LiquidityProvidersQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<LiquidityProviderFeeShareQuery, LiquidityProviderFeeShareQueryVariables>(LiquidityProviderFeeShareDocument, options);
|
||||
return Apollo.useQuery<LiquidityProvidersQuery, LiquidityProvidersQueryVariables>(LiquidityProvidersDocument, options);
|
||||
}
|
||||
export function useLiquidityProviderFeeShareLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<LiquidityProviderFeeShareQuery, LiquidityProviderFeeShareQueryVariables>) {
|
||||
export function useLiquidityProvidersLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<LiquidityProvidersQuery, LiquidityProvidersQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<LiquidityProviderFeeShareQuery, LiquidityProviderFeeShareQueryVariables>(LiquidityProviderFeeShareDocument, options);
|
||||
return Apollo.useLazyQuery<LiquidityProvidersQuery, LiquidityProvidersQueryVariables>(LiquidityProvidersDocument, options);
|
||||
}
|
||||
export type LiquidityProviderFeeShareQueryHookResult = ReturnType<typeof useLiquidityProviderFeeShareQuery>;
|
||||
export type LiquidityProviderFeeShareLazyQueryHookResult = ReturnType<typeof useLiquidityProviderFeeShareLazyQuery>;
|
||||
export type LiquidityProviderFeeShareQueryResult = Apollo.QueryResult<LiquidityProviderFeeShareQuery, LiquidityProviderFeeShareQueryVariables>;
|
||||
export type LiquidityProvidersQueryHookResult = ReturnType<typeof useLiquidityProvidersQuery>;
|
||||
export type LiquidityProvidersLazyQueryHookResult = ReturnType<typeof useLiquidityProvidersLazyQuery>;
|
||||
export type LiquidityProvidersQueryResult = Apollo.QueryResult<LiquidityProvidersQuery, LiquidityProvidersQueryVariables>;
|
||||
@@ -1,7 +1,9 @@
|
||||
import type { LiquidityProviderFeeShare } from '@vegaprotocol/types';
|
||||
import { AccountType } from '@vegaprotocol/types';
|
||||
import { getLiquidityProvision } from './liquidity-data-provider';
|
||||
import type { LiquidityProvisionFieldsFragment } from './__generated__/MarketLiquidity';
|
||||
import type {
|
||||
LiquidityProviderFieldsFragment,
|
||||
LiquidityProvisionFieldsFragment,
|
||||
} from './__generated__/MarketLiquidity';
|
||||
|
||||
const input = {
|
||||
liquidityProvisions: [
|
||||
@@ -31,28 +33,32 @@ const input = {
|
||||
__typename: 'LiquidityProvision',
|
||||
} as LiquidityProvisionFieldsFragment,
|
||||
],
|
||||
liquidityFeeShare: [
|
||||
liquidityProviders: [
|
||||
{
|
||||
party: {
|
||||
id: 'dde288688af2aeb5feb349dd72d3679a7a9be34c7375f6a4a48ef2f6140e7e59',
|
||||
__typename: 'Party',
|
||||
partyId:
|
||||
'dde288688af2aeb5feb349dd72d3679a7a9be34c7375f6a4a48ef2f6140e7e59',
|
||||
feeShare: {
|
||||
equityLikeShare: '1',
|
||||
averageEntryValuation: '12064118310408958216220.7224556301338111',
|
||||
__typename: 'LiquidityProviderFeeShare',
|
||||
},
|
||||
equityLikeShare: '1',
|
||||
averageEntryValuation: '12064118310408958216220.7224556301338111',
|
||||
__typename: 'LiquidityProviderFeeShare',
|
||||
} as LiquidityProviderFeeShare,
|
||||
} as LiquidityProviderFieldsFragment,
|
||||
],
|
||||
};
|
||||
|
||||
const result = [
|
||||
{
|
||||
__typename: 'LiquidityProvision',
|
||||
averageEntryValuation: '12064118310408958216220.7224556301338111',
|
||||
__typename: undefined,
|
||||
balance: '1.8003328918633596575e+22',
|
||||
commitmentAmount: '18003328918633596575000',
|
||||
createdAt: '2022-12-16T09:28:29.071781Z',
|
||||
equityLikeShare: '1',
|
||||
feeShare: {
|
||||
equityLikeShare: '1',
|
||||
__typename: 'LiquidityProviderFeeShare',
|
||||
averageEntryValuation: '12064118310408958216220.7224556301338111',
|
||||
},
|
||||
fee: '0.001',
|
||||
partyId: 'dde288688af2aeb5feb349dd72d3679a7a9be34c7375f6a4a48ef2f6140e7e59',
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
accountsConnection: {
|
||||
@@ -84,13 +90,13 @@ describe('getLiquidityProvision', () => {
|
||||
it('should return correct array when correct liquidity provision parameters are provided', () => {
|
||||
const data = getLiquidityProvision(
|
||||
input.liquidityProvisions,
|
||||
input.liquidityFeeShare
|
||||
input.liquidityProviders
|
||||
);
|
||||
expect(data).toStrictEqual(result);
|
||||
});
|
||||
|
||||
it('should return empty array when no liquidity provision parameters are provided', () => {
|
||||
const data = getLiquidityProvision([], input.liquidityFeeShare);
|
||||
const data = getLiquidityProvision([], input.liquidityProviders);
|
||||
expect(data).toStrictEqual([]);
|
||||
});
|
||||
|
||||
|
||||
@@ -5,86 +5,50 @@ import {
|
||||
} from '@vegaprotocol/data-provider';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import produce from 'immer';
|
||||
|
||||
import {
|
||||
LiquidityProviderFeeShareDocument,
|
||||
LiquidityProvidersDocument,
|
||||
LiquidityProvisionsDocument,
|
||||
LiquidityProvisionsUpdateDocument,
|
||||
} from './__generated__/MarketLiquidity';
|
||||
|
||||
import type {
|
||||
LiquidityProviderFeeShareFieldsFragment,
|
||||
LiquidityProviderFeeShareQuery,
|
||||
LiquidityProviderFeeShareQueryVariables,
|
||||
LiquidityProviderFieldsFragment,
|
||||
LiquidityProvidersQuery,
|
||||
LiquidityProvidersQueryVariables,
|
||||
LiquidityProvisionFieldsFragment,
|
||||
LiquidityProvisionsQuery,
|
||||
LiquidityProvisionsQueryVariables,
|
||||
LiquidityProvisionsUpdateSubscription,
|
||||
} from './__generated__/MarketLiquidity';
|
||||
|
||||
export const liquidityProvisionsDataProvider = makeDataProvider<
|
||||
LiquidityProvisionsQuery,
|
||||
LiquidityProvisionFieldsFragment[],
|
||||
LiquidityProvisionsUpdateSubscription,
|
||||
LiquidityProvisionsUpdateSubscription['liquidityProvisions'],
|
||||
never,
|
||||
never,
|
||||
LiquidityProvisionsQueryVariables
|
||||
>({
|
||||
query: LiquidityProvisionsDocument,
|
||||
subscriptionQuery: LiquidityProvisionsUpdateDocument,
|
||||
update: (
|
||||
data: LiquidityProvisionFieldsFragment[] | null,
|
||||
deltas: LiquidityProvisionsUpdateSubscription['liquidityProvisions']
|
||||
) => {
|
||||
return produce(data || [], (draft) => {
|
||||
deltas?.forEach((delta) => {
|
||||
const index = draft.findIndex((a) => delta.id === a.id);
|
||||
if (index !== -1) {
|
||||
draft[index].commitmentAmount = delta.commitmentAmount;
|
||||
draft[index].fee = delta.fee;
|
||||
draft[index].updatedAt = delta.updatedAt;
|
||||
draft[index].status = delta.status;
|
||||
} else {
|
||||
draft.unshift({
|
||||
id: delta.id,
|
||||
commitmentAmount: delta.commitmentAmount,
|
||||
fee: delta.fee,
|
||||
status: delta.status,
|
||||
updatedAt: delta.updatedAt,
|
||||
createdAt: delta.createdAt,
|
||||
party: {
|
||||
id: delta.partyID,
|
||||
},
|
||||
// TODO add accounts connection to the subscription
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
getData: (responseData: LiquidityProvisionsQuery | null) => {
|
||||
return (
|
||||
responseData?.market?.liquidityProvisionsConnection?.edges?.map(
|
||||
(e) => e?.node
|
||||
) ?? []
|
||||
).filter((e) => !!e) as LiquidityProvisionFieldsFragment[];
|
||||
},
|
||||
getDelta: (
|
||||
subscriptionData: LiquidityProvisionsUpdateSubscription
|
||||
): LiquidityProvisionsUpdateSubscription['liquidityProvisions'] => {
|
||||
return subscriptionData.liquidityProvisions;
|
||||
).filter((n) => !!n) as LiquidityProvisionFieldsFragment[];
|
||||
},
|
||||
});
|
||||
|
||||
export const liquidityFeeShareDataProvider = makeDataProvider<
|
||||
LiquidityProviderFeeShareQuery,
|
||||
LiquidityProviderFeeShareFieldsFragment[],
|
||||
export const lpDataProvider = makeDataProvider<
|
||||
LiquidityProvidersQuery,
|
||||
LiquidityProviderFieldsFragment[],
|
||||
never,
|
||||
never,
|
||||
LiquidityProviderFeeShareQueryVariables
|
||||
LiquidityProvidersQueryVariables
|
||||
>({
|
||||
query: LiquidityProviderFeeShareDocument,
|
||||
query: LiquidityProvidersDocument,
|
||||
getData: (data) => {
|
||||
return data?.market?.data?.liquidityProviderFeeShare || [];
|
||||
return (
|
||||
data?.liquidityProviders?.edges.filter(Boolean).map((e) => e.node) ?? []
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -101,17 +65,17 @@ export const lpAggregatedDataProvider = makeDerivedDataProvider<
|
||||
marketId: variables.marketId,
|
||||
}),
|
||||
(callback, client, variables) =>
|
||||
liquidityFeeShareDataProvider(callback, client, {
|
||||
lpDataProvider(callback, client, {
|
||||
marketId: variables.marketId,
|
||||
}),
|
||||
],
|
||||
(
|
||||
[liquidityProvisions, liquidityFeeShare],
|
||||
[liquidityProvisions, liquidityProvider],
|
||||
{ filter }
|
||||
): LiquidityProvisionData[] => {
|
||||
return getLiquidityProvision(
|
||||
liquidityProvisions,
|
||||
liquidityFeeShare,
|
||||
liquidityProvider,
|
||||
filter
|
||||
);
|
||||
}
|
||||
@@ -139,9 +103,17 @@ export const matchFilter = (
|
||||
return true;
|
||||
};
|
||||
|
||||
export interface LiquidityProvisionData
|
||||
extends Omit<LiquidityProvisionFieldsFragment, '__typename'> {
|
||||
assetDecimalPlaces?: number;
|
||||
balance?: string;
|
||||
averageEntryValuation?: string;
|
||||
equityLikeShare?: string;
|
||||
}
|
||||
|
||||
export const getLiquidityProvision = (
|
||||
liquidityProvisions: LiquidityProvisionFieldsFragment[],
|
||||
liquidityFeeShare: LiquidityProviderFeeShareFieldsFragment[],
|
||||
liquidityProvider: LiquidityProviderFieldsFragment[],
|
||||
filter?: Filter
|
||||
): LiquidityProvisionData[] => {
|
||||
return liquidityProvisions
|
||||
@@ -161,10 +133,8 @@ export const getLiquidityProvision = (
|
||||
return true;
|
||||
})
|
||||
.map((lp) => {
|
||||
const feeShare = liquidityFeeShare.find(
|
||||
(f) => f.party.id === lp.party.id
|
||||
);
|
||||
if (!feeShare) return lp;
|
||||
const lpObj = liquidityProvider.find((f) => lp.party.id === f.partyId);
|
||||
if (!lpObj) return lp;
|
||||
const accounts = compact(lp.party.accountsConnection?.edges).map(
|
||||
(e) => e.node
|
||||
);
|
||||
@@ -180,17 +150,9 @@ export const getLiquidityProvision = (
|
||||
.toString() || '0';
|
||||
return {
|
||||
...lp,
|
||||
averageEntryValuation: feeShare?.averageEntryValuation,
|
||||
equityLikeShare: feeShare?.equityLikeShare,
|
||||
...lpObj,
|
||||
balance,
|
||||
__typename: undefined,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
export interface LiquidityProvisionData
|
||||
extends LiquidityProvisionFieldsFragment {
|
||||
assetDecimalPlaces?: number;
|
||||
balance?: string;
|
||||
averageEntryValuation?: string;
|
||||
equityLikeShare?: string;
|
||||
}
|
||||
|
||||
@@ -10,8 +10,10 @@ const singleRow = {
|
||||
commitmentAmount: '56298653179',
|
||||
fee: '0.001',
|
||||
status: Schema.LiquidityProvisionStatus.STATUS_ACTIVE,
|
||||
equityLikeShare: '0.5',
|
||||
averageEntryValuation: '0.5',
|
||||
feeShare: {
|
||||
equityLikeShare: '0.5',
|
||||
averageEntryValuation: '0.5',
|
||||
},
|
||||
supplied: '67895',
|
||||
obligation: '56785',
|
||||
} as unknown as LiquidityProvisionData;
|
||||
@@ -41,16 +43,16 @@ describe('LiquidityTable', () => {
|
||||
h.querySelector('[ref="eText"]')?.textContent?.trim()
|
||||
);
|
||||
const expectedHeaders = [
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
'Party',
|
||||
'Commitment ()',
|
||||
'Share',
|
||||
'Proposed fee',
|
||||
'Market valuation at entry',
|
||||
'Obligation',
|
||||
'Supplied',
|
||||
'Live time fraction on book',
|
||||
'Last time fraction on the book',
|
||||
'Status',
|
||||
'Created',
|
||||
'Updated',
|
||||
];
|
||||
expect(headers).toHaveLength(expectedHeaders.length);
|
||||
expect(headerTexts).toEqual(expectedHeaders);
|
||||
|
||||
@@ -8,9 +8,16 @@ import {
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type { TypedDataAgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { TooltipCellComponent } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
CopyWithTooltip,
|
||||
Tooltip,
|
||||
TooltipCellComponent,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
truncateMiddle,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import type {
|
||||
ColDef,
|
||||
ColGroupDef,
|
||||
ITooltipParams,
|
||||
ValueFormatterParams,
|
||||
} from 'ag-grid-community';
|
||||
@@ -24,6 +31,20 @@ const percentageFormatter = ({ value }: ValueFormatterParams) => {
|
||||
return formatNumberPercentage(new BigNumber(value).times(100), 2) || '-';
|
||||
};
|
||||
|
||||
const copyCellRenderer = ({ value }: { value?: string | null }) => {
|
||||
if (!value) return '-';
|
||||
return (
|
||||
<CopyWithTooltip data-testid="copy-to-clipboard" text={value}>
|
||||
<button className="flex gap-1">
|
||||
<Tooltip description={value}>
|
||||
<span className="break-words">{truncateMiddle(value)}</span>
|
||||
</Tooltip>
|
||||
<VegaIcon name={VegaIconNames.COPY} size={12} />
|
||||
</button>
|
||||
</CopyWithTooltip>
|
||||
);
|
||||
};
|
||||
|
||||
const dateValueFormatter = ({ value }: { value?: string | null }) => {
|
||||
if (!value) {
|
||||
return '-';
|
||||
@@ -89,103 +110,176 @@ export const LiquidityTable = ({
|
||||
)}`;
|
||||
};
|
||||
|
||||
const defs: ColDef[] = [
|
||||
const defs: ColGroupDef[] = [
|
||||
{
|
||||
headerName: t('Party'),
|
||||
field: 'party.id',
|
||||
headerTooltip: t('The public key of the party making this commitment.'),
|
||||
headerName: '',
|
||||
children: [
|
||||
{
|
||||
headerName: t('Party'),
|
||||
field: 'partyId',
|
||||
headerTooltip: t(
|
||||
'The public key of the party making this commitment.'
|
||||
),
|
||||
cellRenderer: copyCellRenderer,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headerName: t(`Commitment (${symbol})`),
|
||||
field: 'commitmentAmount',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'The amount committed to the market by this liquidity provider.'
|
||||
),
|
||||
valueFormatter: assetDecimalsQuantumFormatter,
|
||||
tooltipValueGetter: assetDecimalsFormatter,
|
||||
headerName: t('Commitment details'),
|
||||
marryChildren: true,
|
||||
children: [
|
||||
{
|
||||
headerName: t(`Commitment (${symbol})`),
|
||||
field: 'commitmentAmount',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'The amount committed to the market by this liquidity provider.'
|
||||
),
|
||||
valueFormatter: assetDecimalsQuantumFormatter,
|
||||
tooltipValueGetter: assetDecimalsFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Obligation'),
|
||||
field: 'commitmentAmount',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
`The liquidity provider's obligation to the market, calculated as the liquidity commitment amount multiplied by the value of the stake_to_ccy_volume network parameter to convert into units of liquidity volume. The obligation can be met by a combination of LP orders and limit orders on the order book.`
|
||||
),
|
||||
valueFormatter: stakeToCcyVolumeQuantumFormatter,
|
||||
tooltipValueGetter: stakeToCcyVolumeFormatter,
|
||||
columnGroupShow: 'open',
|
||||
},
|
||||
{
|
||||
headerName: t('Fee'),
|
||||
headerTooltip: t(
|
||||
'The fee percentage (per trade) proposed by each liquidity provider.'
|
||||
),
|
||||
field: 'fee',
|
||||
type: 'rightAligned',
|
||||
valueFormatter: percentageFormatter,
|
||||
columnGroupShow: 'open',
|
||||
},
|
||||
{
|
||||
headerName: t('Adjusted stake share'),
|
||||
field: 'feeShare.virtualStake',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t('The virtual stake of the liquidity provider.'),
|
||||
|
||||
valueFormatter: assetDecimalsQuantumFormatter,
|
||||
tooltipValueGetter: assetDecimalsFormatter,
|
||||
columnGroupShow: 'open',
|
||||
},
|
||||
{
|
||||
headerName: t(`Share`),
|
||||
field: 'feeShare.equityLikeShare',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'The equity-like share of liquidity of the market used to determine allocation of LP fees. Calculated based on share of total liquidity, with a premium added for length of commitment.'
|
||||
),
|
||||
valueFormatter: percentageFormatter,
|
||||
columnGroupShow: 'open',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headerName: t(`Share`),
|
||||
field: 'equityLikeShare',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'The equity-like share of liquidity of the market used to determine allocation of LP fees. Calculated based on share of total liquidity, with a premium added for length of commitment.'
|
||||
),
|
||||
valueFormatter: percentageFormatter,
|
||||
headerName: t('Live liquidity details'),
|
||||
marryChildren: true,
|
||||
children: [
|
||||
{
|
||||
headerName: t('Live supplied liquidity'),
|
||||
field: 'balance',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
`The amount of liquidity volume supplied by the LP order in order to meet the obligation. If the obligation is already met in full by other limit orders from the same Vega key the LP order is not required and this value will be zero. Also note if the target stake for the market is less than the obligation the full value of the obligation may not be required.`
|
||||
),
|
||||
valueFormatter: stakeToCcyVolumeQuantumFormatter,
|
||||
tooltipValueGetter: stakeToCcyVolumeFormatter,
|
||||
columnGroupShow: 'open',
|
||||
},
|
||||
{
|
||||
headerName: t(`Live time fraction on book`),
|
||||
field: 'sla.currentEpochFractionOfTimeOnBook',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t('Current epoch fraction of time on the book.'),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Live liquidity quality score (%)'),
|
||||
field: 'feeShare.averageScore',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t('The average score of the liquidity provider.'),
|
||||
valueFormatter: percentageFormatter,
|
||||
columnGroupShow: 'open',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headerName: t('Proposed fee'),
|
||||
headerTooltip: t(
|
||||
'The fee percentage (per trade) proposed by each liquidity provider.'
|
||||
),
|
||||
field: 'fee',
|
||||
type: 'rightAligned',
|
||||
valueFormatter: percentageFormatter,
|
||||
headerName: t('Last epoch SLA details'),
|
||||
marryChildren: true,
|
||||
children: [
|
||||
{
|
||||
headerName: t(`Last time fraction on the book`),
|
||||
field: 'sla.lastEpochFractionOfTimeOnBook',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t('Last epoch fraction of time on the book.'),
|
||||
valueFormatter: percentageFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t(`Last fee penalty`),
|
||||
field: 'sla.lastEpochFeePenalty',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t('Last epoch fee penalty.'),
|
||||
valueFormatter: percentageFormatter,
|
||||
columnGroupShow: 'open',
|
||||
},
|
||||
{
|
||||
headerName: t(`Last bond penalty`),
|
||||
field: 'sla.lastEpochBondPenalty',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t('Last epoch bond penalty.'),
|
||||
valueFormatter: percentageFormatter,
|
||||
columnGroupShow: 'open',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
headerName: t('Market valuation at entry'),
|
||||
field: 'averageEntryValuation',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
'The valuation of the market at the time the liquidity commitment was made. Commitments made at a lower valuation earlier in the lifetime of the market would be expected to have a higher equity-like share if the market has grown. If a commitment is amended, value will reflect the average of the market valuations across the lifetime of the commitment.'
|
||||
),
|
||||
valueFormatter: assetDecimalsQuantumFormatter,
|
||||
tooltipValueGetter: assetDecimalsFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Obligation'),
|
||||
field: 'commitmentAmount',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
`The liquidity provider's obligation to the market, calculated as the liquidity commitment amount multiplied by the value of the stake_to_ccy_volume network parameter to convert into units of liquidity volume. The obligation can be met by a combination of LP orders and limit orders on the order book.`
|
||||
),
|
||||
valueFormatter: stakeToCcyVolumeQuantumFormatter,
|
||||
tooltipValueGetter: stakeToCcyVolumeFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Supplied'),
|
||||
field: 'balance',
|
||||
type: 'rightAligned',
|
||||
headerTooltip: t(
|
||||
`The amount of liquidity volume supplied by the LP order in order to meet the obligation. If the obligation is already met in full by other limit orders from the same Vega key the LP order is not required and this value will be zero. Also note if the target stake for the market is less than the obligation the full value of the obligation may not be required.`
|
||||
),
|
||||
valueFormatter: stakeToCcyVolumeQuantumFormatter,
|
||||
tooltipValueGetter: stakeToCcyVolumeFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Status'),
|
||||
headerTooltip: t('The current status of this liquidity provision.'),
|
||||
field: 'status',
|
||||
valueFormatter: ({ value }) => {
|
||||
if (!value) return value;
|
||||
return LiquidityProvisionStatusMapping[
|
||||
value as LiquidityProvisionStatus
|
||||
];
|
||||
},
|
||||
},
|
||||
{
|
||||
headerName: t('Created'),
|
||||
headerTooltip: t(
|
||||
'The date and time this liquidity provision was created.'
|
||||
),
|
||||
field: 'createdAt',
|
||||
type: 'rightAligned',
|
||||
valueFormatter: dateValueFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Updated'),
|
||||
headerTooltip: t(
|
||||
'The date and time this liquidity provision was last updated.'
|
||||
),
|
||||
field: 'updatedAt',
|
||||
type: 'rightAligned',
|
||||
valueFormatter: dateValueFormatter,
|
||||
headerName: '',
|
||||
marryChildren: true,
|
||||
children: [
|
||||
{
|
||||
headerName: t('Status'),
|
||||
headerTooltip: t('The current status of this liquidity provision.'),
|
||||
field: 'status',
|
||||
valueFormatter: ({ value }) => {
|
||||
if (!value) return value;
|
||||
return LiquidityProvisionStatusMapping[
|
||||
value as LiquidityProvisionStatus
|
||||
];
|
||||
},
|
||||
},
|
||||
{
|
||||
headerName: t('Created'),
|
||||
headerTooltip: t(
|
||||
'The date and time this liquidity provision was created.'
|
||||
),
|
||||
field: 'createdAt',
|
||||
type: 'rightAligned',
|
||||
valueFormatter: dateValueFormatter,
|
||||
},
|
||||
{
|
||||
headerName: t('Updated'),
|
||||
headerTooltip: t(
|
||||
'The date and time this liquidity provision was last updated.'
|
||||
),
|
||||
field: 'updatedAt',
|
||||
type: 'rightAligned',
|
||||
valueFormatter: dateValueFormatter,
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
return defs;
|
||||
}, [assetDecimalPlaces, quantum, stakeToCcyVolume, symbol]);
|
||||
|
||||
return (
|
||||
<AgGrid
|
||||
overlayNoRowsTemplate={t('No liquidity provisions')}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
import merge from 'lodash/merge';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type {
|
||||
LiquidityProviderFeeShareQuery,
|
||||
LiquidityProvisionsQuery,
|
||||
} from './__generated__/MarketLiquidity';
|
||||
import type { LiquidityProvisionsQuery } from './__generated__/MarketLiquidity';
|
||||
import type { LiquidityProvisionFieldsFragment } from './__generated__/MarketLiquidity';
|
||||
|
||||
export const liquidityProvisionsQuery = (
|
||||
@@ -26,45 +23,6 @@ export const liquidityProvisionsQuery = (
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
|
||||
export const liquidityProviderFeeShareQuery = (
|
||||
override?: PartialDeep<LiquidityProviderFeeShareQuery>
|
||||
): LiquidityProviderFeeShareQuery => {
|
||||
const defaultResult: LiquidityProviderFeeShareQuery = {
|
||||
market: {
|
||||
id: 'market-0',
|
||||
data: {
|
||||
market: {
|
||||
id: 'market-0',
|
||||
__typename: 'Market',
|
||||
},
|
||||
liquidityProviderFeeShare: [
|
||||
{
|
||||
party: {
|
||||
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
|
||||
__typename: 'Party',
|
||||
},
|
||||
equityLikeShare: '1',
|
||||
averageEntryValuation: '68585293691.5598054356207737',
|
||||
__typename: 'LiquidityProviderFeeShare',
|
||||
},
|
||||
{
|
||||
party: {
|
||||
id: 'cc464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
|
||||
__typename: 'Party',
|
||||
},
|
||||
equityLikeShare: '1',
|
||||
averageEntryValuation: '68585293691.5598054356207737',
|
||||
__typename: 'LiquidityProviderFeeShare',
|
||||
},
|
||||
],
|
||||
__typename: 'MarketData',
|
||||
},
|
||||
__typename: 'Market',
|
||||
},
|
||||
};
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
|
||||
export const liquidityFields: LiquidityProvisionFieldsFragment[] = [
|
||||
{
|
||||
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
|
||||
|
||||
+3
-2
@@ -3,12 +3,12 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type MarketsDataFieldsFragment = { __typename?: 'MarketData', bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketTradingMode: Types.MarketTradingMode, 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 MarketsDataFieldsFragment = { __typename?: 'MarketData', bestBidPrice: string, bestOfferPrice: string, markPrice: string, trigger: Types.AuctionTrigger, staticMidPrice: string, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, 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 MarketsDataQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type MarketsDataQuery = { __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, 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 MarketsDataQuery = { __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, marketState: Types.MarketState, marketTradingMode: Types.MarketTradingMode, 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 const MarketsDataFieldsFragmentDoc = gql`
|
||||
fragment MarketsDataFields on MarketData {
|
||||
@@ -20,6 +20,7 @@ export const MarketsDataFieldsFragmentDoc = gql`
|
||||
markPrice
|
||||
trigger
|
||||
staticMidPrice
|
||||
marketState
|
||||
marketTradingMode
|
||||
indicativeVolume
|
||||
indicativePrice
|
||||
|
||||
@@ -126,6 +126,16 @@ export const marketTradingModeProvider = makeDerivedDataProvider<
|
||||
(parts[0] as ReturnType<typeof getData>)?.marketTradingMode
|
||||
);
|
||||
|
||||
export const marketStateProvider = makeDerivedDataProvider<
|
||||
MarketDataFieldsFragment['marketState'] | undefined,
|
||||
never,
|
||||
MarketDataQueryVariables
|
||||
>(
|
||||
[marketDataProvider],
|
||||
(parts, variables, prevData) =>
|
||||
(parts[0] as ReturnType<typeof getData>)?.marketState
|
||||
);
|
||||
|
||||
export const fundingRateProvider = makeDerivedDataProvider<
|
||||
string,
|
||||
never,
|
||||
@@ -176,3 +186,11 @@ export const useMarketTradingMode = (marketId?: string, skip?: boolean) => {
|
||||
skip: skip || !marketId,
|
||||
});
|
||||
};
|
||||
|
||||
export const useMarketState = (marketId?: string, skip?: boolean) => {
|
||||
return useDataProvider({
|
||||
dataProvider: marketStateProvider,
|
||||
variables: { marketId: marketId || '' },
|
||||
skip: skip || !marketId,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ fragment MarketsDataFields on MarketData {
|
||||
markPrice
|
||||
trigger
|
||||
staticMidPrice
|
||||
marketState
|
||||
marketTradingMode
|
||||
indicativeVolume
|
||||
indicativePrice
|
||||
|
||||
@@ -34,6 +34,7 @@ export const createMarketsDataFragment = (
|
||||
__typename: 'Market',
|
||||
},
|
||||
marketTradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
|
||||
marketState: Schema.MarketState.STATE_ACTIVE,
|
||||
staticMidPrice: '0',
|
||||
indicativePrice: '0',
|
||||
bestStaticBidPrice: '0',
|
||||
|
||||
@@ -2,8 +2,8 @@ import { render, act, screen } from '@testing-library/react';
|
||||
import { AsyncRenderer } from './async-renderer';
|
||||
|
||||
describe('AsyncRenderer', () => {
|
||||
const reload = jest.fn();
|
||||
it('timeout error should render button', async () => {
|
||||
const reload = jest.fn();
|
||||
await act(() => {
|
||||
render(
|
||||
<AsyncRenderer
|
||||
@@ -20,4 +20,22 @@ describe('AsyncRenderer', () => {
|
||||
});
|
||||
expect(reload).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('errors should be handled properly', async () => {
|
||||
const message = 'Node has been collapsed';
|
||||
await act(() => {
|
||||
render(
|
||||
<AsyncRenderer
|
||||
reload={reload}
|
||||
error={new Error(message)}
|
||||
loading={false}
|
||||
data={[]}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
expect(
|
||||
screen.getByText(`Something went wrong: ${message}`)
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,7 +29,7 @@ export function AsyncRenderer<T = object>({
|
||||
reload,
|
||||
}: AsyncRendererProps<T>) {
|
||||
if (error) {
|
||||
if (!data) {
|
||||
if (!data || (Array.isArray(data) && !data.length)) {
|
||||
return (
|
||||
<div className="h-full flex items-center justify-center">
|
||||
<div className="h-12 flex flex-col items-center">
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import classNames from 'classnames';
|
||||
import { useMemo } from 'react';
|
||||
import styles from './loader.module.scss';
|
||||
|
||||
const pseudoRandom = (seed: number) => {
|
||||
export const pseudoRandom = (seed: number) => {
|
||||
let value = seed;
|
||||
return () => {
|
||||
value = (value * 16807) % 2147483647;
|
||||
@@ -10,6 +9,8 @@ const pseudoRandom = (seed: number) => {
|
||||
};
|
||||
};
|
||||
|
||||
const generate = pseudoRandom(1);
|
||||
|
||||
export interface LoaderProps {
|
||||
size?: 'small' | 'large';
|
||||
forceTheme?: 'dark' | 'light';
|
||||
@@ -27,8 +28,6 @@ export const Loader = ({ size = 'large', forceTheme }: LoaderProps) => {
|
||||
size === 'small' ? 'w-[15px] h-[15px]' : 'w-[50px] h-[50px]';
|
||||
const items = size === 'small' ? 9 : 25;
|
||||
|
||||
const generate = useMemo(() => pseudoRandom(1), []);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center" data-testid="loader">
|
||||
<div className={`${wrapperClasses} flex flex-wrap`}>
|
||||
|
||||
@@ -53,7 +53,10 @@ export const Tooltip = ({
|
||||
className={tooltipContentClasses}
|
||||
sideOffset={sideOffset}
|
||||
>
|
||||
<div className="relative z-0" data-testid="tooltip-content">
|
||||
<div
|
||||
className="relative z-0 break-words"
|
||||
data-testid="tooltip-content"
|
||||
>
|
||||
{description}
|
||||
</div>
|
||||
</Content>
|
||||
|
||||
@@ -41,7 +41,7 @@ const ethereumRequest = <T>(args: RequestArguments): Promise<T> => {
|
||||
|
||||
export const LOCAL_SNAP_ID = 'local:http://localhost:8080';
|
||||
export const DEFAULT_SNAP_ID = 'npm:@vegaprotocol/snap';
|
||||
export const DEFAULT_SNAP_VERSION = '0.2.0';
|
||||
export const DEFAULT_SNAP_VERSION = '0.3.1';
|
||||
|
||||
type GetSnapsResponse = Record<string, Snap>;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user