chore: LP tooltips & move market-info lib (#1267)

* feat(#473): add positions metrics data provider

* feat(#473) add positions stats

* feat(#473) add positions stats

* feat(#473): add positions stats

* feat(#473): add positions stats

* feat(#473): position metrics, test and refactoring

* feat(#473): add unit tests to positions table

* feat(#473): fix spelling, order positions by updated at desc

* feat(#473): protect from division by 0

* feat(#473): fix trading positions e2e tests

* feat(#473): fix e2e data mocks

* feat(#473): post code review clean up

* feat(#993): dependencies handling in data provider

* feat(#993): fix e2e tests data mocks

* feat(#993): remove position metrics mocks, add market data market id

* feat: #994 add price monitoring bounds and candles update interface

* fix: move best bid price to diff section

* feat(#993): add missing mocks, fix combine function

* fix: add insurance pool and calc volume 24h

* feat: display some oracle min info, asset id, insurance pool, move open interest and 24hVol

* fix: add  market-info.cy.ts case

* fix: remove # from numbered price monitoring settings

* fix: add insurance pool test

* fix: format 24hvol

* feat(#993): set loading initially to true, add unit tests

* feat(#993): cleanup, add comments

* feat(#993): remove undefined from client type

* fix: remove indicativeVolume and oracleSpecBinding from market info

* feat(#993): cosmetic changes

* fix: add oracleSpecBinding back

* Update libs/deal-ticket/src/components/info-market.tsx

Co-authored-by: botond <105208209+notbot00@users.noreply.github.com>

* feat: add initial queries

* fix: memo yesterday's timestamp

* fix: add back info

* fix: update query

* fix: add view full oracle details link and update mappings

* fix: regen code, make link reactnode, fix index.ts

* feat: add liquidity lib, refactor info market

* fix: remove liquidity query from deal-ticket

* feat:(#993): pass informaton about update callback cause

* fix: small ui tweaks

* fix: display in grid

* feat: navigate to oracle by termination id

* feat: #491 add use liquidity provision merging

* fix: remove logs, add extra check on my liquidity provision

* fix: type number trivially inferred from a number literal, remove type annotation

* fix: cypress tests and formatting for market info

* Update libs/deal-ticket/src/components/market-info/info-market.tsx

* fix: use position decimal places for stake and market value proxy

* fix: #491 use size/position decimal places for obligation, supplied and commitment amount

* fix: add size component and use decimal places

* fix: update readme liquidity

* fix: #491 add correct asset decimal formatters

* Update libs/deal-ticket/src/components/market-info/tooltip-mapping.tsx

Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>

* fix: make link instead of button to open liquidity

* fix: #491 add liquidity page, link to trading mode tooltip, tabs hidden or choose active

* fix: remove LP dialog, use only link to page

* fix: add market id in LP view

* fix: follow trade grid design

* fix: add one line tabs , remove link styling, remove any, add value formatters

* fix: remove falsy check LP undefined

* fix: keep date formatter in LP table

* fix: add generic type market info, hooks in body function

* fix: revert number formatters

* fix: use one param only in network params query

* fix:  use network param in web3 lib

* fix: move lp container to trading app

* fix: remove resizable panel

* feat: add header component, remove isEstimate

* chore: remove unnecessary type cast

* fix: fix build with children map clone element

* chore: lint

* fix: move use network params to react helpers

* fix: add const for LP tabs

* fix: fix formatting on LP page

* fix: only show tilde for liquidity monitoring auction end date

* fix: market id being rendered twice in market info

* chore: fix lint

* fix: types for generate withdraw form query

* chore: fix intermittent failing withdrawal test

* Update libs/deal-ticket/src/components/market-info/info-market.tsx

* fix: route to LP and update selected market

* fix: add market-info lib

* fix: add tooltips to header stat

* fix: add overflow-y on div within auto sizer

* fix: fix merge conflicts

* fix: size and dialog

* fix: format target stake and supplied stake

* fix: add tooltips ag-grid and fix decimals

* fix: overflow on both axes auto-sizer

* fix: remove symbol, add to commitment

* fix: update tooltips and headers after demo

* fix: network switcher background

* fix: remove any from market info

* fix: integration test

* fix: remove e2e test for risk factors for now until grpc error sorted

* fix: get liquidity panel  by test-id

* fix: fix market-info.cy.ts test

* fix: liquidity test

* f
ix: fix link data test id

Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
Co-authored-by: botond <105208209+notbot00@users.noreply.github.com>
Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
Co-authored-by: Joe <joe@vega.xyz>
This commit is contained in:
m.ray 2022-09-12 10:07:29 +01:00 committed by GitHub
parent 7675fe0ab0
commit d85c5d7c1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 578 additions and 205 deletions

View File

@ -4,6 +4,7 @@ import { mockTradingPage } from '../support/trading';
const marketInfoBtn = 'Info';
const row = 'key-value-table-row';
const marketTitle = 'accordion-title';
const link = 'link';
const externalLink = 'external-link';
describe('market info is displayed', () => {
@ -85,13 +86,6 @@ describe('market info is displayed', () => {
validateMarketDataRow(4, 'Sector', 'crypto');
});
it('risk factors displayed', () => {
cy.getByTestId(marketTitle).contains('Risk factors').click();
validateMarketDataRow(0, 'Short', '0.008571790367285281');
validateMarketDataRow(1, 'Long', '0.008508132993273576');
});
it('risk model displayed', () => {
cy.getByTestId(marketTitle).contains('Risk model').click();
@ -127,17 +121,13 @@ describe('market info is displayed', () => {
});
it('liquidity displayed', () => {
cy.getByTestId('accordion-toggle').eq(14).click();
cy.getByTestId('accordion-toggle').eq(13).click();
validateMarketDataRow(0, 'Target Stake', '0.56789 tBTC');
validateMarketDataRow(1, 'Supplied Stake', '0.56767 tBTC');
validateMarketDataRow(2, 'Market Value Proxy', '6.77678 tBTC');
cy.getByTestId(externalLink).should(
'have.attr',
'href',
'/liquidity/market-0'
);
cy.getByTestId(link).should('have.text', 'View liquidity provision table');
});
it('oracle displayed', () => {
@ -149,16 +139,6 @@ describe('market info is displayed', () => {
'Trading Termination Property',
'termination.BTC.value'
);
validateMarketDataRow(
2,
'Price Oracle',
'f028fe5ea7de3890962a05a7163fdde562629af649ed81b8c8902fafb6eef04f'
);
validateMarketDataRow(
3,
'Termination Oracle',
'f028fe5ea7de3890962a05a7163fdde562629af649ed81b8c8902fafb6eef04f'
);
cy.getByTestId(externalLink)
.should('have.attr', 'href')

View File

@ -1,4 +1,4 @@
import type { MarketInfoQuery } from '@vegaprotocol/deal-ticket';
import type { MarketInfoQuery } from '@vegaprotocol/market-info';
import {
AccountType,
AuctionTrigger,

View File

@ -58,6 +58,7 @@ export const generateMarket = (override?: PartialDeep<Market>): Market => {
},
quoteName: 'BTCUSD Monthly',
settlementAsset: {
decimals: 0,
id: '000',
symbol: 'USD',
name: 'United States Dollar',

View File

@ -1,3 +1,4 @@
import { Tooltip } from '@vegaprotocol/ui-toolkit';
import type { ReactElement, ReactNode } from 'react';
import { Children } from 'react';
import { cloneElement } from 'react';
@ -11,9 +12,7 @@ export const Header = ({ title, children }: TradeMarketHeaderProps) => {
return (
<header className="w-screen xl:px-4 pt-4 border-b border-neutral-300 dark:border-neutral-700">
<div className="xl:flex xl:gap-4 items-start">
<div className="px-4 mb-2 xl:mb-0 sm:text-lg md:text-xl lg:text-2xl">
{title}
</div>
<div className="px-4 mb-2">{title}</div>
<div
data-testid="market-summary"
className="flex flex-nowrap items-start xl:flex-1 w-full overflow-x-auto text-xs "
@ -33,10 +32,12 @@ export const HeaderStat = ({
children,
heading,
id,
description,
}: {
children: ReactNode;
heading: string;
id?: string;
description?: string | ReactNode;
}) => {
const itemClass =
'min-w-min w-[120px] whitespace-nowrap pb-3 px-4 border-l border-neutral-300 dark:border-neutral-700';
@ -44,9 +45,11 @@ export const HeaderStat = ({
return (
<div className={itemClass}>
<div id={id} className={itemHeading}>
{heading}
</div>
<Tooltip description={description}>
<div id={id} className={itemHeading}>
{heading}
</div>
</Tooltip>
<div aria-labelledby={id}>{children}</div>
</div>
);

View File

@ -27,7 +27,7 @@ export const Navbar = ({ theme, toggleTheme }: NavbarProps) => {
<VLogo className="w-6 h-6 fill-white" />
</a>
</Link>
<NetworkSwitcher />
<NetworkSwitcher fixedBg="dark" />
</div>
<nav className="flex items-center">
{[

View File

@ -36,14 +36,17 @@ const MarketDataGrid = ({ grid }: MarketDataGridProps) => {
const formatStake = (value: string, market: Market_market) => {
const formattedValue = addDecimalsFormatNumber(
value,
market.positionDecimalPlaces
market.tradableInstrument.instrument.product.settlementAsset.decimals
);
const asset =
market.tradableInstrument.instrument.product.settlementAsset.symbol;
return `${formattedValue} ${asset}`;
};
const compileGridData = (market: Market_market) => {
const compileGridData = (
market: Market_market,
onSelect?: (id: string) => void
) => {
const grid: MarketDataGridProps['grid'] = [];
const isLiquidityMonitoringAuction =
market.tradingMode === MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
@ -80,7 +83,7 @@ const compileGridData = (market: Market_market) => {
if (isLiquidityMonitoringAuction && market.data?.suppliedStake) {
grid.push({
label: (
<Link href={`/liquidity/${market.id}`} target="_blank">
<Link onClick={() => onSelect && onSelect(market.id)}>
{t('Current liquidity')}
</Link>
),
@ -117,9 +120,13 @@ const compileGridData = (market: Market_market) => {
type TradingModeTooltipProps = {
market: Market_market;
onSelect?: (marketId: string) => void;
};
export const TradingModeTooltip = ({ market }: TradingModeTooltipProps) => {
export const TradingModeTooltip = ({
market,
onSelect,
}: TradingModeTooltipProps) => {
switch (market.tradingMode) {
case MarketTradingMode.TRADING_MODE_CONTINUOUS: {
return (
@ -168,7 +175,7 @@ export const TradingModeTooltip = ({ market }: TradingModeTooltipProps) => {
{t('Find out more')}
</Link>
</p>
<MarketDataGrid grid={compileGridData(market)} />
<MarketDataGrid grid={compileGridData(market, onSelect)} />
</>
);
}

View File

@ -22,6 +22,7 @@ export function Index() {
if (marketId) {
replace(`/markets/${marketId}`);
update({ marketId });
}
// Fallback to the markets list page
else {

View File

@ -1,16 +1,16 @@
import { LiquidityTable, useLiquidityProvision } from '@vegaprotocol/liquidity';
import { t } from '@vegaprotocol/react-helpers';
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
import { LiquidityProvisionStatus } from '@vegaprotocol/types';
import { AsyncRenderer, Tab, Tabs } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import type { AgGridReact } from 'ag-grid-react';
import { Header, HeaderStat } from '../../components/header';
import Link from 'next/link';
import { useRouter } from 'next/router';
import { useRef, useMemo } from 'react';
import { tooltipMapping } from '@vegaprotocol/market-info';
const LiquidityPage = ({ id }: { id?: string }) => {
const { query } = useRouter();
const { query, push } = useRouter();
const { keypair } = useVegaWallet();
const gridRef = useRef<AgGridReact | null>(null);
@ -20,7 +20,14 @@ const LiquidityPage = ({ id }: { id?: string }) => {
id || (Array.isArray(query.marketId) ? query.marketId[0] : query.marketId);
const {
data: { liquidityProviders, suppliedStake, targetStake, code, symbol },
data: {
liquidityProviders,
suppliedStake,
targetStake,
name,
symbol,
assetDecimalPlaces,
},
loading,
error,
} = useLiquidityProvision({ marketId });
@ -62,16 +69,36 @@ const LiquidityPage = ({ id }: { id?: string }) => {
<div className="h-full grid grid-rows-[min-content_1fr]">
<Header
title={
<Link href={`/markets/${marketId}`}>
{`${code} ${t('liquidity provision')}`}
</Link>
<button onClick={() => push(`/markets/${marketId}`)}>{`${name} ${t(
'liquidity provision'
)}`}</button>
}
>
<HeaderStat heading={t('Target stake')}>
<div>{`${targetStake} ${symbol}`}</div>
<HeaderStat
heading={t('Target stake')}
description={tooltipMapping['targetStake']}
>
<div>
{targetStake
? `${addDecimalsFormatNumber(
targetStake,
assetDecimalPlaces ?? 0
)} ${symbol}`
: '-'}
</div>
</HeaderStat>
<HeaderStat heading={t('Supplied stake')}>
<div>{`${suppliedStake} ${symbol}`}</div>
<HeaderStat
heading={t('Supplied stake')}
description={tooltipMapping['suppliedStake']}
>
<div>
{suppliedStake
? `${addDecimalsFormatNumber(
suppliedStake,
assetDecimalPlaces ?? 0
)} ${symbol}`
: '-'}
</div>
</HeaderStat>
<HeaderStat heading={t('Market ID')}>
<div className="break-word">{marketId}</div>
@ -83,13 +110,28 @@ const LiquidityPage = ({ id }: { id?: string }) => {
name={t('My liquidity provision')}
hidden={!partyId}
>
<LiquidityTable ref={gridRef} data={myLpEdges} />
<LiquidityTable
ref={gridRef}
data={myLpEdges}
symbol={symbol}
assetDecimalPlaces={assetDecimalPlaces}
/>
</Tab>
<Tab id={LiquidityTabs.Active} name={t('Active')}>
<LiquidityTable ref={gridRef} data={activeEdges} />
<LiquidityTable
ref={gridRef}
data={activeEdges}
symbol={symbol}
assetDecimalPlaces={assetDecimalPlaces}
/>
</Tab>
<Tab id={LiquidityTabs.Inactive} name={t('Inactive')}>
<LiquidityTable ref={gridRef} data={inactiveEdges} />
<LiquidityTable
ref={gridRef}
data={inactiveEdges}
symbol={symbol}
assetDecimalPlaces={assetDecimalPlaces}
/>
</Tab>
</Tabs>
</div>

View File

@ -41,6 +41,7 @@ query Market($marketId: ID!, $interval: Interval!, $since: String!) {
id
symbol
name
decimals
}
}
}

View File

@ -55,6 +55,7 @@ const MARKET_QUERY = gql`
id
symbol
name
decimals
}
}
}
@ -83,11 +84,20 @@ const MarketPage = ({ id }: { id?: string }) => {
update: store.update,
})
);
const { update: updateStore } = useGlobalStore((store) => ({
update: store.update,
}));
// Default to first marketId query item if found
const marketId =
id || (Array.isArray(query.marketId) ? query.marketId[0] : query.marketId);
const onSelect = (id: string) => {
if (id && id !== marketId) {
updateStore({ marketId: id });
}
};
// Cache timestamp for yesterday to prevent full unmount of market page when
// a rerender occurs
const yTimestamp = useMemo(() => {
@ -128,20 +138,16 @@ const MarketPage = ({ id }: { id?: string }) => {
return (
<>
{w > 960 ? (
<TradeGrid market={market} />
<TradeGrid market={market} onSelect={onSelect} />
) : (
<TradePanels market={market} />
<TradePanels market={market} onSelect={onSelect} />
)}
<SelectMarketDialog
dialogOpen={landingDialog && !riskNoticeDialog}
setDialogOpen={(isOpen: boolean) =>
update({ landingDialog: isOpen })
}
onSelect={(marketId: string) => {
if (marketId && marketId !== marketId) {
update({ marketId });
}
}}
onSelect={onSelect}
/>
</>
);

View File

@ -103,6 +103,10 @@ export interface Market_market_tradableInstrument_instrument_product_settlementA
* The full name of the asset (e.g: Great British Pound)
*/
name: string;
/**
* The precision of the asset. Should match the decimal precision of the asset on its native chain, e.g: for ERC20 assets, it is often 18
*/
decimals: number;
}
export interface Market_market_tradableInstrument_instrument_product {
@ -198,14 +202,14 @@ export interface Market_market {
/**
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
* number denominated in the currency of the market. (uint64)
*
*
* Examples:
* Currency Balance decimalPlaces Real Balance
* GBP 100 0 GBP 100
* GBP 100 2 GBP 1.00
* GBP 100 4 GBP 0.01
* GBP 1 4 GBP 0.0001 ( 0.01p )
*
*
* GBX (pence) 100 0 GBP 1.00 (100p )
* GBX (pence) 100 2 GBP 0.01 ( 1p )
* GBX (pence) 100 4 GBP 0.0001 ( 0.01p )

View File

@ -1,7 +1,5 @@
import {
DealTicketContainer,
MarketInfoContainer,
} from '@vegaprotocol/deal-ticket';
import { DealTicketContainer } from '@vegaprotocol/deal-ticket';
import { MarketInfoContainer } from '@vegaprotocol/market-info';
import { OrderbookContainer } from '@vegaprotocol/market-depth';
import { OrderListContainer } from '@vegaprotocol/orders';
import { FillsContainer } from '@vegaprotocol/fills';
@ -32,7 +30,6 @@ import {
t,
} from '@vegaprotocol/react-helpers';
import { SelectMarketPopover } from '@vegaprotocol/market-list';
import { useGlobalStore } from '../../stores';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import { useEnvironment } from '@vegaprotocol/environment';
import type { CandleClose } from '@vegaprotocol/types';
@ -43,6 +40,7 @@ import {
MarketTradingModeMapping,
} from '@vegaprotocol/types';
import { TradingModeTooltip } from '../../components/trading-mode-tooltip';
import { useRouter } from 'next/router';
const TradingViews = {
Candles: CandlesChartContainer,
@ -110,21 +108,16 @@ const ExpiryTooltipContent = ({
interface TradeMarketHeaderProps {
market: Market_market;
onSelect: (marketId: string) => void;
}
export const TradeMarketHeader = ({ market }: TradeMarketHeaderProps) => {
export const TradeMarketHeader = ({
market,
onSelect,
}: TradeMarketHeaderProps) => {
const { VEGA_EXPLORER_URL } = useEnvironment();
const { setAssetDetailsDialogOpen, setAssetDetailsDialogSymbol } =
useAssetDetailsDialogStore();
const { update } = useGlobalStore((store) => ({
update: store.update,
}));
const onSelect = (marketId: string) => {
if (marketId && marketId !== marketId) {
update({ marketId });
}
};
const candlesClose: string[] = (market?.candles || [])
.map((candle) => candle?.close)
@ -136,6 +129,7 @@ export const TradeMarketHeader = ({ market }: TradeMarketHeaderProps) => {
const itemClass =
'min-w-min w-[120px] whitespace-nowrap pb-3 px-4 border-l border-neutral-300 dark:border-neutral-700';
const itemHeading = 'text-neutral-400';
const { push } = useRouter();
return (
<header className="w-screen xl:px-4 pt-4 border-b border-neutral-300 dark:border-neutral-700">
@ -194,7 +188,15 @@ export const TradeMarketHeader = ({ market }: TradeMarketHeaderProps) => {
<div className={itemHeading}>{t('Trading mode')}</div>
<Tooltip
align="start"
description={<TradingModeTooltip market={market} />}
description={
<TradingModeTooltip
market={market}
onSelect={(marketId: string) => {
onSelect(marketId);
push(`/liquidity/${marketId}`);
}}
/>
}
>
<div data-testid="trading-mode">
{market.tradingMode ===
@ -242,12 +244,14 @@ export const TradeMarketHeader = ({ market }: TradeMarketHeaderProps) => {
interface TradeGridProps {
market: Market_market;
onSelect: (marketId: string) => void;
}
export const TradeGrid = ({ market }: TradeGridProps) => {
export const TradeGrid = ({ market, onSelect }: TradeGridProps) => {
const { push } = useRouter();
return (
<div className="h-full grid grid-rows-[min-content_1fr]">
<TradeMarketHeader market={market} />
<TradeMarketHeader market={market} onSelect={onSelect} />
<ResizableGrid vertical={true}>
<ResizableGridPanel minSize={75} priority={LayoutPriority.High}>
<ResizableGrid proportionalLayout={false} minSize={200}>
@ -278,7 +282,13 @@ export const TradeGrid = ({ market }: TradeGridProps) => {
<TradingViews.Ticket marketId={market.id} />
</Tab>
<Tab id="info" name={t('Info')}>
<TradingViews.Info marketId={market.id} />
<TradingViews.Info
marketId={market.id}
onSelect={(id: string) => {
onSelect(id);
push(`/liquidity/${id}`);
}}
/>
</Tab>
</Tabs>
</TradeGridChild>
@ -348,9 +358,11 @@ const TradeGridChild = ({ children }: TradeGridChildProps) => {
interface TradePanelsProps {
market: Market_market;
onSelect: (marketId: string) => void;
}
export const TradePanels = ({ market }: TradePanelsProps) => {
export const TradePanels = ({ market, onSelect }: TradePanelsProps) => {
const { push } = useRouter();
const [view, setView] = useState<TradingView>('Candles');
const renderView = () => {
@ -360,16 +372,26 @@ export const TradePanels = ({ market }: TradePanelsProps) => {
throw new Error(`No component for view: ${view}`);
}
return <Component marketId={market.id} />;
return (
<Component
marketId={market.id}
onSelect={(id: string) => {
onSelect(id);
push(`/liquidity/${id}`);
}}
/>
);
};
return (
<div className="h-full grid grid-rows-[min-content_1fr_min-content]">
<TradeMarketHeader market={market} />
<TradeMarketHeader market={market} onSelect={onSelect} />
<div className="h-full">
<AutoSizer>
{({ width, height }) => (
<div style={{ width, height }}>{renderView()}</div>
<div style={{ width, height }} className="overflow-auto">
{renderView()}
</div>
)}
</AutoSizer>
</div>

View File

@ -1,2 +1 @@
export * from './deal-ticket';
export * from './market-info';

View File

@ -9,6 +9,7 @@ import {
} from '@vegaprotocol/ui-toolkit';
import { useEnvironment } from '../../hooks/use-environment';
import { Networks } from '../../types';
import classNames from 'classnames';
export const envNameMapping: Record<Networks, string> = {
[Networks.CUSTOM]: t('Custom'),
@ -68,7 +69,11 @@ const NetworkLabel = ({
</span>
);
export const NetworkSwitcher = () => {
export const NetworkSwitcher = ({
fixedBg,
}: {
fixedBg?: 'dark' | 'light';
}) => {
const { VEGA_ENV, VEGA_NETWORKS } = useEnvironment();
const [isOpen, setOpen] = useState(false);
const [isAdvancedView, setAdvancedView] = useState(false);
@ -83,9 +88,15 @@ export const NetworkSwitcher = () => {
[setOpen, setAdvancedView]
);
const dropdownTriggerClasses = classNames({
'dark:text-white dark:bg-black text-black bg-white': !fixedBg,
'text-black bg-white': fixedBg === 'light',
'text-white bg-black': fixedBg === 'dark',
});
return (
<DropdownMenu open={isOpen} onOpenChange={handleOpen}>
<DropdownMenuTrigger className="text-white dark:text-white">
<DropdownMenuTrigger className={dropdownTriggerClasses}>
{envTriggerMapping[VEGA_ENV]}
</DropdownMenuTrigger>
<DropdownMenuContent align="start">

View File

@ -0,0 +1,61 @@
query MarketLiquidity($marketId: ID!, $partyId: String) {
market(id: $marketId) {
id
decimalPlaces
positionDecimalPlaces
liquidityProvisionsConnection(party: $partyId) {
edges {
node {
id
party {
id
accountsConnection(marketId: $marketId, type: ACCOUNT_TYPE_BOND) {
edges {
node {
type
balance
}
}
}
}
createdAt
updatedAt
commitmentAmount
fee
status
}
}
}
tradableInstrument {
instrument {
code
name
product {
... on Future {
settlementAsset {
id
symbol
decimals
}
}
}
}
}
data {
market {
id
}
suppliedStake
openInterest
targetStake
marketValueProxy
liquidityProviderFeeShare {
party {
id
}
equityLikeShare
averageEntryValuation
}
}
}
}

View File

@ -121,6 +121,10 @@ export interface MarketLiquidity_market_tradableInstrument_instrument {
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
*/
code: string;
/**
* Full and fairly descriptive name for the instrument
*/
name: string;
/**
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
*/
@ -204,14 +208,14 @@ export interface MarketLiquidity_market {
/**
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
* number denominated in the currency of the market. (uint64)
*
*
* Examples:
* Currency Balance decimalPlaces Real Balance
* GBP 100 0 GBP 100
* GBP 100 2 GBP 1.00
* GBP 100 4 GBP 0.01
* GBP 1 4 GBP 0.0001 ( 0.01p )
*
*
* GBX (pence) 100 0 GBP 1.00 (100p )
* GBX (pence) 100 2 GBP 0.01 ( 1p )
* GBX (pence) 100 4 GBP 0.0001 ( 0.01p )

View File

@ -42,6 +42,7 @@ const MARKET_LIQUIDITY_QUERY = gql`
tradableInstrument {
instrument {
code
name
product {
... on Future {
settlementAsset {
@ -95,6 +96,7 @@ export interface LiquidityData {
decimalPlaces?: number;
positionDecimalPlaces?: number;
assetDecimalPlaces?: number;
name?: string;
}
export const useLiquidityProvision = ({
@ -161,6 +163,7 @@ export const useLiquidityProvision = ({
decimalPlaces: data?.market?.decimalPlaces,
positionDecimalPlaces: data?.market?.positionDecimalPlaces,
code: data?.market?.tradableInstrument.instrument.code,
name: data?.market?.tradableInstrument.instrument.name,
assetDecimalPlaces:
data?.market?.tradableInstrument.instrument.product.settlementAsset
.decimals,

View File

@ -5,7 +5,10 @@ import {
getDateTimeFormat,
t,
} from '@vegaprotocol/react-helpers';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
import {
AgGridDynamic as AgGrid,
TooltipCellComponent,
} from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridColumn } from 'ag-grid-react';
import type { LiquidityProvision } from './liquidity-data-provider';
@ -14,11 +17,6 @@ import BigNumber from 'bignumber.js';
import type { LiquidityProvisionStatus } from '@vegaprotocol/types';
import { LiquidityProvisionStatusMapping } from '@vegaprotocol/types';
const assetDecimalsFormatter = ({ value, data }: ValueFormatterParams) => {
if (!value) return '-';
return addDecimalsFormatNumber(value, data.assetDecimalPlaces);
};
const percentageFormatter = ({ value }: ValueFormatterParams) => {
if (!value) return '-';
return formatNumberPercentage(new BigNumber(value).times(100), 4) || '-';
@ -33,10 +31,16 @@ const dateValueFormatter = ({ value }: { value?: string | null }) => {
export interface LiquidityTableProps {
data: LiquidityProvision[];
symbol?: string;
assetDecimalPlaces?: number;
}
export const LiquidityTable = forwardRef<AgGridReact, LiquidityTableProps>(
(props, ref) => {
({ data, symbol = '', assetDecimalPlaces }, ref) => {
const assetDecimalsFormatter = ({ value }: ValueFormatterParams) => {
if (!value) return '-';
return `${addDecimalsFormatNumber(value, assetDecimalPlaces ?? 0)}`;
};
return (
<AgGrid
style={{ width: '100%', height: '100%' }}
@ -44,29 +48,45 @@ export const LiquidityTable = forwardRef<AgGridReact, LiquidityTableProps>(
getRowId={({ data }) => data.party}
rowHeight={34}
ref={ref}
tooltipShowDelay={500}
defaultColDef={{
flex: 1,
resizable: true,
minWidth: 100,
tooltipComponent: TooltipCellComponent,
}}
rowData={props.data}
{...props}
rowData={data}
>
<AgGridColumn headerName={t('Party')} field="party" />
<AgGridColumn
headerName={t('Commitment')}
headerName={t('Party')}
field="party"
headerTooltip={t(
'The public key of the party making this commitment.'
)}
/>
<AgGridColumn
headerName={t(`Commitment (${symbol})`)}
field="commitmentAmount"
type="rightAligned"
headerTooltip={t(
'The amount committed to the market by this liquidity provider.'
)}
valueFormatter={assetDecimalsFormatter}
/>
<AgGridColumn
headerName={t('Share')}
field="equityLikeShare"
type="rightAligned"
headerTooltip={t(
'The equity-like share of liquidity of the market, specific to each liquidity provider.'
)}
valueFormatter={percentageFormatter}
/>
<AgGridColumn
headerName={t('Fee')}
headerName={t('Proposed fee')}
headerTooltip={t(
'The fee percentage (per trade) proposed by each liquidity provider.'
)}
field="fee"
type="rightAligned"
valueFormatter={percentageFormatter}
@ -75,22 +95,33 @@ export const LiquidityTable = forwardRef<AgGridReact, LiquidityTableProps>(
headerName={t('Average entry valuation')}
field="averageEntryValuation"
type="rightAligned"
headerTooltip={t(
'The average entry valuation of this liquidity provision for the market.'
)}
minWidth={160}
valueFormatter={assetDecimalsFormatter}
/>
<AgGridColumn
headerName={t('Obligation (siskas)')}
headerName={t('Obligation')}
field="obligation"
type="rightAligned"
headerTooltip={t(
'The liquidity providers obligation to the market, calculated as the liquidity commitment amount multiplied by the value of the stake_to_ccy_siskas network parameter.'
)}
valueFormatter={assetDecimalsFormatter}
/>
<AgGridColumn
headerName={t('Supplied (siskas)')}
headerName={t('Supplied')}
headerTooltip={t(
'The amount of the settlement asset supplied for liquidity by this provider, calculated as the bond account balance multiplied by the value of the stake_to_ccy_siskas network parameter.'
)}
field="supplied"
type="rightAligned"
valueFormatter={assetDecimalsFormatter}
/>
<AgGridColumn
headerName={t('Status')}
headerTooltip={t('The current status of this liquidity provision.')}
field="status"
valueFormatter={({ value }: { value: LiquidityProvisionStatus }) => {
if (!value) return value;
@ -99,12 +130,18 @@ export const LiquidityTable = forwardRef<AgGridReact, LiquidityTableProps>(
/>
<AgGridColumn
headerName={t('Created')}
headerTooltip={t(
'The date and time this liquidity provision was created.'
)}
field="createdAt"
type="rightAligned"
valueFormatter={dateValueFormatter}
/>
<AgGridColumn
headerName={t('Updated')}
headerTooltip={t(
'The last time this liquidity provision was updated.'
)}
field="updatedAt"
type="rightAligned"
valueFormatter={dateValueFormatter}

12
libs/market-info/.babelrc Normal file
View File

@ -0,0 +1,12 @@
{
"presets": [
[
"@nrwl/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}

View File

@ -0,0 +1,18 @@
{
"extends": ["plugin:@nrwl/nx/react", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*", "__generated__", "__generated___"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}

View File

@ -0,0 +1,7 @@
# market-info
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test market-info` to execute the unit tests via [Jest](https://jestjs.io).

View File

@ -0,0 +1,11 @@
/* eslint-disable */
export default {
displayName: 'market-info',
preset: '../../jest.preset.js',
transform: {
'^.+\\.[tj]sx?$': 'babel-jest',
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
coverageDirectory: '../../coverage/libs/market-info',
setupFilesAfterEnv: ['./src/setup-tests.ts'],
};

View File

@ -0,0 +1,4 @@
{
"name": "@vegaprotocol/market-info",
"version": "0.0.1"
}

View File

@ -0,0 +1,43 @@
{
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/market-info/src",
"projectType": "library",
"tags": [],
"targets": {
"build": {
"executor": "@nrwl/web:rollup",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/libs/market-info",
"tsConfig": "libs/market-info/tsconfig.lib.json",
"project": "libs/market-info/package.json",
"entryFile": "libs/market-info/src/index.ts",
"external": ["react/jsx-runtime"],
"rollupConfig": "@nrwl/react/plugins/bundle-rollup",
"compiler": "babel",
"assets": [
{
"glob": "libs/market-info/README.md",
"input": ".",
"output": "."
}
]
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/market-info/**/*.{ts,tsx,js,jsx}"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/libs/market-info"],
"options": {
"jestConfig": "libs/market-info/jest.config.ts",
"passWithNoTests": true
}
}
}
}

View File

@ -0,0 +1,20 @@
query MarketNames {
markets {
id
name
state
tradableInstrument {
instrument {
code
metadata {
tags
}
product {
... on Future {
quoteName
}
}
}
}
}
}

View File

@ -0,0 +1 @@
export * from './market-info';

View File

@ -1,3 +1,5 @@
export * from './__generated__';
export * from './info-key-value-table';
export * from './info-market-query';
export * from './info-market';
export * from './tooltip-mapping';

View File

@ -16,8 +16,7 @@ import { tooltipMapping } from './tooltip-mapping';
interface RowProps {
field: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
value: any;
value: unknown;
decimalPlaces?: number;
asPercentage?: boolean;
unformatted?: boolean;
@ -32,49 +31,48 @@ const Row = ({
unformatted,
assetSymbol = '',
}: RowProps) => {
const isNumber = typeof value === 'number' || !isNaN(Number(value));
const isPrimitive = typeof value === 'string' || isNumber;
const className = 'text-black dark:text-white text-ui !px-0 !font-normal';
let formattedValue = value;
if (isNumber && !unformatted) {
if (decimalPlaces) {
formattedValue = `${addDecimalsFormatNumber(
value,
decimalPlaces
)} ${assetSymbol}`;
} else if (asPercentage && value) {
formattedValue = formatNumberPercentage(new BigNumber(value).times(100));
} else {
formattedValue = `${formatNumber(Number(value))} ${assetSymbol}`;
const getFormattedValue = (value: unknown) => {
if (typeof value !== 'string' && typeof value !== 'number') return null;
if (unformatted || isNaN(Number(value))) {
return value;
}
}
if (isPrimitive) {
return (
<KeyValueTableRow
key={field}
inline={isPrimitive}
noBorder={true}
dtClassName={className}
ddClassName={className}
>
<Tooltip description={tooltipMapping[field]} align="start">
<div tabIndex={-1}>{startCase(t(field))}</div>
</Tooltip>
<span style={{ wordBreak: 'break-word' }}>{formattedValue}</span>
</KeyValueTableRow>
);
}
return null;
if (decimalPlaces) {
return `${addDecimalsFormatNumber(value, decimalPlaces)} ${assetSymbol}`;
}
if (asPercentage) {
return formatNumberPercentage(new BigNumber(value).times(100));
}
return `${formatNumber(Number(value))} ${assetSymbol}`;
};
const formattedValue: string | number | null = getFormattedValue(value);
if (!formattedValue) return null;
return (
<KeyValueTableRow
key={field}
inline={true}
noBorder={true}
dtClassName={className}
ddClassName={className}
>
<Tooltip description={tooltipMapping[field]} align="start">
<div tabIndex={-1}>{startCase(t(field))}</div>
</Tooltip>
<span style={{ wordBreak: 'break-word' }}>{formattedValue}</span>
</KeyValueTableRow>
);
};
export interface MarketInfoTableProps {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: any;
data: unknown;
decimalPlaces?: number;
asPercentage?: boolean;
unformatted?: boolean;
omits?: string[];
link?: ReactNode;
children?: ReactNode;
assetSymbol?: string;
}
@ -84,9 +82,12 @@ export const MarketInfoTable = ({
asPercentage,
unformatted,
omits = ['__typename'],
link,
children,
assetSymbol,
}: MarketInfoTableProps) => {
if (!data || typeof data !== 'object') {
return null;
}
return (
<>
<KeyValueTable>
@ -104,7 +105,7 @@ export const MarketInfoTable = ({
/>
))}
</KeyValueTable>
{link}
<div className="flex flex-col gap-2">{children}</div>
</>
);
};

View File

@ -39,11 +39,6 @@ export const MARKET_INFO_QUERY = gql`
}
}
}
riskFactors {
market
short
long
}
data {
market {
id

View File

@ -1,6 +1,11 @@
import { useMemo } from 'react';
import { formatNumber, t } from '@vegaprotocol/react-helpers';
import { AsyncRenderer, Splash, Accordion } from '@vegaprotocol/ui-toolkit';
import {
AsyncRenderer,
Splash,
Accordion,
Link,
} from '@vegaprotocol/ui-toolkit';
import pick from 'lodash/pick';
import BigNumber from 'bignumber.js';
import { useQuery } from '@apollo/client';
@ -19,7 +24,6 @@ import type {
} from './__generated__/MarketInfoQuery';
import { MarketInfoTable } from './info-key-value-table';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import { generatePath } from 'react-router-dom';
import { useEnvironment } from '@vegaprotocol/environment';
@ -29,6 +33,7 @@ const Links = {
export interface InfoProps {
market: MarketInfoQuery_market;
onSelect: (id: string) => void;
}
export const calcCandleVolume = (
@ -43,8 +48,12 @@ export const calcCandleVolume = (
export interface MarketInfoContainerProps {
marketId: string;
onSelect: (id: string) => void;
}
export const MarketInfoContainer = ({ marketId }: MarketInfoContainerProps) => {
export const MarketInfoContainer = ({
marketId,
onSelect,
}: MarketInfoContainerProps) => {
const yTimestamp = useMemo(() => {
const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
return new Date(yesterday * 1000).toISOString();
@ -63,7 +72,7 @@ export const MarketInfoContainer = ({ marketId }: MarketInfoContainerProps) => {
return (
<AsyncRenderer<MarketInfoQuery> data={data} loading={loading} error={error}>
{data && data.market ? (
<Info market={data.market} />
<Info market={data.market} onSelect={onSelect} />
) : (
<Splash>
<p>{t('Could not load market')}</p>
@ -73,8 +82,8 @@ export const MarketInfoContainer = ({ marketId }: MarketInfoContainerProps) => {
);
};
export const Info = ({ market }: InfoProps) => {
const { VEGA_TOKEN_URL } = useEnvironment();
export const Info = ({ market, onSelect }: InfoProps) => {
const { VEGA_TOKEN_URL, VEGA_EXPLORER_URL } = useEnvironment();
const headerClassName = 'uppercase text-lg';
const dayVolume = calcCandleVolume(market);
const assetSymbol =
@ -153,7 +162,6 @@ export const Info = ({ market }: InfoProps) => {
),
})),
];
const { VEGA_EXPLORER_URL } = useEnvironment();
const keyDetails = {
...pick(market, 'decimalPlaces', 'positionDecimalPlaces', 'tradingMode'),
state: MarketStateMapping[market.state],
@ -218,16 +226,6 @@ export const Info = ({ market }: InfoProps) => {
/>
),
},
{
title: t('Risk factors'),
content: (
<MarketInfoTable
data={market.riskFactors}
unformatted={true}
omits={['market', '__typename']}
/>
),
},
{
title: t('Risk model'),
content: (
@ -282,35 +280,30 @@ export const Info = ({ market }: InfoProps) => {
.decimals
}
assetSymbol={assetSymbol}
link={
<ExternalLink href={`/liquidity/${market.id}`}>
{t('View liquidity provision table')}
</ExternalLink>
}
/>
>
<Link onClick={() => onSelect(market.id)}>
{t('View liquidity provision table')}
</Link>
</MarketInfoTable>
),
},
{
title: t('Oracle'),
content: (
<MarketInfoTable
data={{
...market.tradableInstrument.instrument.product.oracleSpecBinding,
priceOracle:
market.tradableInstrument.instrument.product
.oracleSpecForSettlementPrice.id,
terminationOracle:
market.tradableInstrument.instrument.product
.oracleSpecForTradingTermination.id,
}}
link={
<ExternalLink
href={`${VEGA_EXPLORER_URL}/oracles#${market.tradableInstrument.instrument.product.oracleSpecForTradingTermination.id}`}
>
{t('View full oracle details')}
</ExternalLink>
}
/>
data={market.tradableInstrument.instrument.product.oracleSpecBinding}
>
<ExternalLink
href={`${VEGA_EXPLORER_URL}/oracles#${market.tradableInstrument.instrument.product.oracleSpecForSettlementPrice.id}`}
>
{t('View price oracle specification')}
</ExternalLink>
<ExternalLink
href={`${VEGA_EXPLORER_URL}/oracles#${market.tradableInstrument.instrument.product.oracleSpecForTradingTermination.id}`}
>
{t('View termination oracle specification')}
</ExternalLink>
</MarketInfoTable>
),
},
];
@ -319,21 +312,19 @@ export const Info = ({ market }: InfoProps) => {
{
title: t('Proposal'),
content: (
<p>
<ExternalLink
href={generatePath(Links.PROPOSAL_PAGE, {
tokenUrl: VEGA_TOKEN_URL,
proposalId: market.proposal?.id || '',
})}
title={
market.proposal?.rationale.title ||
market.proposal?.rationale.description ||
''
}
>
{t('View governance proposal')}
</ExternalLink>
</p>
<ExternalLink
href={generatePath(Links.PROPOSAL_PAGE, {
tokenUrl: VEGA_TOKEN_URL,
proposalId: market.proposal?.id || '',
})}
title={
market.proposal?.rationale.title ||
market.proposal?.rationale.description ||
''
}
>
{t('View governance proposal')}
</ExternalLink>
),
},
];

View File

@ -7,7 +7,7 @@ export const tooltipMapping: Record<string, ReactNode> = {
'Maker portion of the fee is transferred to the non-aggressive, or passive party in the trade (the maker, as opposed to the taker).'
),
liquidityFee: t(
'Liquidity portion of the fee is paid to market makers for providing liquidity, and is transferred to the liquidity fee pool for the market.'
'Liquidity portion of the fee is paid to liquidity providers, and is transferred to the liquidity fee pool for the market.'
),
infrastructureFee: t(
'Fees paid to validators as a reward for running the infrastructure of the network.'
@ -100,4 +100,8 @@ export const tooltipMapping: Record<string, ReactNode> = {
scalingFactor: t(
'The scaling between the liquidity demand estimate, based on open interest and target stake.'
),
targetStake: t(
`The market's liquidity requirement which is derived from the maximum open interest observed over a rolling time window.`
),
suppliedStake: t('The current amount of liquidity supplied for this market.'),
};

View File

@ -0,0 +1 @@
export * from './components';

View File

@ -0,0 +1 @@
import '@testing-library/jest-dom';

View File

@ -0,0 +1,25 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": false,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"files": [],
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
}
]
}

View File

@ -0,0 +1,23 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../node_modules/@nrwl/react/typings/cssmodule.d.ts",
"../../node_modules/@nrwl/react/typings/image.d.ts"
],
"exclude": [
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"jest.config.ts"
],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

View File

@ -0,0 +1,20 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"module": "commonjs",
"types": ["jest", "node", "@testing-library/jest-dom"]
},
"include": [
"**/*.test.ts",
"**/*.spec.ts",
"**/*.test.tsx",
"**/*.spec.tsx",
"**/*.test.js",
"**/*.spec.js",
"**/*.test.jsx",
"**/*.spec.jsx",
"**/*.d.ts",
"jest.config.ts"
]
}

View File

@ -23,7 +23,7 @@ import type { AgGridReact, AgGridReactProps } from 'ag-grid-react';
import type { IDatasource, IGetRowsParams } from 'ag-grid-community';
import type { Position } from './positions-data-providers';
import { MarketTradingMode } from '@vegaprotocol/types';
import { Intent, Button } from '@vegaprotocol/ui-toolkit';
import { Intent, Button, TooltipCellComponent } from '@vegaprotocol/ui-toolkit';
export const getRowId = ({ data }: { data: Position }) => data.marketId;
@ -151,9 +151,11 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
getRowId={getRowId}
rowHeight={34}
ref={ref}
tooltipShowDelay={500}
defaultColDef={{
flex: 1,
resizable: true,
tooltipComponent: TooltipCellComponent,
}}
components={{ PriceFlashCell, ProgressBarCell }}
{...props}

View File

@ -2,7 +2,6 @@ import { Side } from '@vegaprotocol/types';
import type { ICellRendererParams } from 'ag-grid-community';
import classNames from 'classnames';
import { addDecimalsFormatNumber } from '../format';
import { negativeClassNames, positiveClassNames } from './cell-class-rules';
export const Size = ({
value,
@ -17,8 +16,8 @@ export const Size = ({
<span
data-testid="size"
className={classNames('text-right', {
[positiveClassNames]: side === Side.SIDE_BUY,
[negativeClassNames]: side === Side.SIDE_SELL,
'text-vega-green-dark dark:text-vega-green': side === Side.SIDE_BUY,
'text-vega-red-dark dark:text-vega-red': side === Side.SIDE_SELL,
})}
>
{side === Side.SIDE_BUY ? '+' : side === Side.SIDE_SELL ? '-' : ''}

View File

@ -1 +1 @@
export { Tooltip } from './tooltip';
export * from './tooltip';

View File

@ -8,6 +8,7 @@ import {
Arrow,
Portal,
} from '@radix-ui/react-tooltip';
import type { ITooltipParams } from 'ag-grid-community';
export interface TooltipProps {
children: React.ReactElement;
@ -56,3 +57,11 @@ export const Tooltip = ({
) : (
children
);
export const TooltipCellComponent = (props: ITooltipParams) => {
return (
<p className="max-w-sm bg-neutral-200 px-4 py-2 z-20 rounded text-sm break-word text-black">
{props.value}
</p>
);
};

View File

@ -27,6 +27,7 @@
"@vegaprotocol/governance": ["libs/governance/src/index.ts"],
"@vegaprotocol/liquidity": ["libs/liquidity/src/index.ts"],
"@vegaprotocol/market-depth": ["libs/market-depth/src/index.ts"],
"@vegaprotocol/market-info": ["libs/market-info/src/index.ts"],
"@vegaprotocol/market-list": ["libs/market-list/src/index.ts"],
"@vegaprotocol/network-info": ["libs/network-info/src/index.ts"],
"@vegaprotocol/network-stats": ["libs/network-stats/src/index.ts"],

View File

@ -16,6 +16,7 @@
"governance": "libs/governance",
"liquidity": "libs/liquidity",
"market-depth": "libs/market-depth",
"market-info": "libs/market-info",
"market-list": "libs/market-list",
"network-info": "libs/network-info",
"network-stats": "libs/network-stats",