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:
parent
7675fe0ab0
commit
d85c5d7c1f
@ -4,6 +4,7 @@ import { mockTradingPage } from '../support/trading';
|
|||||||
const marketInfoBtn = 'Info';
|
const marketInfoBtn = 'Info';
|
||||||
const row = 'key-value-table-row';
|
const row = 'key-value-table-row';
|
||||||
const marketTitle = 'accordion-title';
|
const marketTitle = 'accordion-title';
|
||||||
|
const link = 'link';
|
||||||
const externalLink = 'external-link';
|
const externalLink = 'external-link';
|
||||||
|
|
||||||
describe('market info is displayed', () => {
|
describe('market info is displayed', () => {
|
||||||
@ -85,13 +86,6 @@ describe('market info is displayed', () => {
|
|||||||
validateMarketDataRow(4, 'Sector', 'crypto');
|
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', () => {
|
it('risk model displayed', () => {
|
||||||
cy.getByTestId(marketTitle).contains('Risk model').click();
|
cy.getByTestId(marketTitle).contains('Risk model').click();
|
||||||
|
|
||||||
@ -127,17 +121,13 @@ describe('market info is displayed', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('liquidity 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(0, 'Target Stake', '0.56789 tBTC');
|
||||||
validateMarketDataRow(1, 'Supplied Stake', '0.56767 tBTC');
|
validateMarketDataRow(1, 'Supplied Stake', '0.56767 tBTC');
|
||||||
validateMarketDataRow(2, 'Market Value Proxy', '6.77678 tBTC');
|
validateMarketDataRow(2, 'Market Value Proxy', '6.77678 tBTC');
|
||||||
|
|
||||||
cy.getByTestId(externalLink).should(
|
cy.getByTestId(link).should('have.text', 'View liquidity provision table');
|
||||||
'have.attr',
|
|
||||||
'href',
|
|
||||||
'/liquidity/market-0'
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('oracle displayed', () => {
|
it('oracle displayed', () => {
|
||||||
@ -149,16 +139,6 @@ describe('market info is displayed', () => {
|
|||||||
'Trading Termination Property',
|
'Trading Termination Property',
|
||||||
'termination.BTC.value'
|
'termination.BTC.value'
|
||||||
);
|
);
|
||||||
validateMarketDataRow(
|
|
||||||
2,
|
|
||||||
'Price Oracle',
|
|
||||||
'f028fe5ea7de3890962a05a7163fdde562629af649ed81b8c8902fafb6eef04f'
|
|
||||||
);
|
|
||||||
validateMarketDataRow(
|
|
||||||
3,
|
|
||||||
'Termination Oracle',
|
|
||||||
'f028fe5ea7de3890962a05a7163fdde562629af649ed81b8c8902fafb6eef04f'
|
|
||||||
);
|
|
||||||
|
|
||||||
cy.getByTestId(externalLink)
|
cy.getByTestId(externalLink)
|
||||||
.should('have.attr', 'href')
|
.should('have.attr', 'href')
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import type { MarketInfoQuery } from '@vegaprotocol/deal-ticket';
|
import type { MarketInfoQuery } from '@vegaprotocol/market-info';
|
||||||
import {
|
import {
|
||||||
AccountType,
|
AccountType,
|
||||||
AuctionTrigger,
|
AuctionTrigger,
|
||||||
|
@ -58,6 +58,7 @@ export const generateMarket = (override?: PartialDeep<Market>): Market => {
|
|||||||
},
|
},
|
||||||
quoteName: 'BTCUSD Monthly',
|
quoteName: 'BTCUSD Monthly',
|
||||||
settlementAsset: {
|
settlementAsset: {
|
||||||
|
decimals: 0,
|
||||||
id: '000',
|
id: '000',
|
||||||
symbol: 'USD',
|
symbol: 'USD',
|
||||||
name: 'United States Dollar',
|
name: 'United States Dollar',
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { ReactElement, ReactNode } from 'react';
|
import type { ReactElement, ReactNode } from 'react';
|
||||||
import { Children } from 'react';
|
import { Children } from 'react';
|
||||||
import { cloneElement } from 'react';
|
import { cloneElement } from 'react';
|
||||||
@ -11,9 +12,7 @@ export const Header = ({ title, children }: TradeMarketHeaderProps) => {
|
|||||||
return (
|
return (
|
||||||
<header className="w-screen xl:px-4 pt-4 border-b border-neutral-300 dark:border-neutral-700">
|
<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="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">
|
<div className="px-4 mb-2">{title}</div>
|
||||||
{title}
|
|
||||||
</div>
|
|
||||||
<div
|
<div
|
||||||
data-testid="market-summary"
|
data-testid="market-summary"
|
||||||
className="flex flex-nowrap items-start xl:flex-1 w-full overflow-x-auto text-xs "
|
className="flex flex-nowrap items-start xl:flex-1 w-full overflow-x-auto text-xs "
|
||||||
@ -33,10 +32,12 @@ export const HeaderStat = ({
|
|||||||
children,
|
children,
|
||||||
heading,
|
heading,
|
||||||
id,
|
id,
|
||||||
|
description,
|
||||||
}: {
|
}: {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
heading: string;
|
heading: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
|
description?: string | ReactNode;
|
||||||
}) => {
|
}) => {
|
||||||
const itemClass =
|
const itemClass =
|
||||||
'min-w-min w-[120px] whitespace-nowrap pb-3 px-4 border-l border-neutral-300 dark:border-neutral-700';
|
'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 (
|
return (
|
||||||
<div className={itemClass}>
|
<div className={itemClass}>
|
||||||
|
<Tooltip description={description}>
|
||||||
<div id={id} className={itemHeading}>
|
<div id={id} className={itemHeading}>
|
||||||
{heading}
|
{heading}
|
||||||
</div>
|
</div>
|
||||||
|
</Tooltip>
|
||||||
<div aria-labelledby={id}>{children}</div>
|
<div aria-labelledby={id}>{children}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -27,7 +27,7 @@ export const Navbar = ({ theme, toggleTheme }: NavbarProps) => {
|
|||||||
<VLogo className="w-6 h-6 fill-white" />
|
<VLogo className="w-6 h-6 fill-white" />
|
||||||
</a>
|
</a>
|
||||||
</Link>
|
</Link>
|
||||||
<NetworkSwitcher />
|
<NetworkSwitcher fixedBg="dark" />
|
||||||
</div>
|
</div>
|
||||||
<nav className="flex items-center">
|
<nav className="flex items-center">
|
||||||
{[
|
{[
|
||||||
|
@ -36,14 +36,17 @@ const MarketDataGrid = ({ grid }: MarketDataGridProps) => {
|
|||||||
const formatStake = (value: string, market: Market_market) => {
|
const formatStake = (value: string, market: Market_market) => {
|
||||||
const formattedValue = addDecimalsFormatNumber(
|
const formattedValue = addDecimalsFormatNumber(
|
||||||
value,
|
value,
|
||||||
market.positionDecimalPlaces
|
market.tradableInstrument.instrument.product.settlementAsset.decimals
|
||||||
);
|
);
|
||||||
const asset =
|
const asset =
|
||||||
market.tradableInstrument.instrument.product.settlementAsset.symbol;
|
market.tradableInstrument.instrument.product.settlementAsset.symbol;
|
||||||
return `${formattedValue} ${asset}`;
|
return `${formattedValue} ${asset}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const compileGridData = (market: Market_market) => {
|
const compileGridData = (
|
||||||
|
market: Market_market,
|
||||||
|
onSelect?: (id: string) => void
|
||||||
|
) => {
|
||||||
const grid: MarketDataGridProps['grid'] = [];
|
const grid: MarketDataGridProps['grid'] = [];
|
||||||
const isLiquidityMonitoringAuction =
|
const isLiquidityMonitoringAuction =
|
||||||
market.tradingMode === MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
|
market.tradingMode === MarketTradingMode.TRADING_MODE_MONITORING_AUCTION &&
|
||||||
@ -80,7 +83,7 @@ const compileGridData = (market: Market_market) => {
|
|||||||
if (isLiquidityMonitoringAuction && market.data?.suppliedStake) {
|
if (isLiquidityMonitoringAuction && market.data?.suppliedStake) {
|
||||||
grid.push({
|
grid.push({
|
||||||
label: (
|
label: (
|
||||||
<Link href={`/liquidity/${market.id}`} target="_blank">
|
<Link onClick={() => onSelect && onSelect(market.id)}>
|
||||||
{t('Current liquidity')}
|
{t('Current liquidity')}
|
||||||
</Link>
|
</Link>
|
||||||
),
|
),
|
||||||
@ -117,9 +120,13 @@ const compileGridData = (market: Market_market) => {
|
|||||||
|
|
||||||
type TradingModeTooltipProps = {
|
type TradingModeTooltipProps = {
|
||||||
market: Market_market;
|
market: Market_market;
|
||||||
|
onSelect?: (marketId: string) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TradingModeTooltip = ({ market }: TradingModeTooltipProps) => {
|
export const TradingModeTooltip = ({
|
||||||
|
market,
|
||||||
|
onSelect,
|
||||||
|
}: TradingModeTooltipProps) => {
|
||||||
switch (market.tradingMode) {
|
switch (market.tradingMode) {
|
||||||
case MarketTradingMode.TRADING_MODE_CONTINUOUS: {
|
case MarketTradingMode.TRADING_MODE_CONTINUOUS: {
|
||||||
return (
|
return (
|
||||||
@ -168,7 +175,7 @@ export const TradingModeTooltip = ({ market }: TradingModeTooltipProps) => {
|
|||||||
{t('Find out more')}
|
{t('Find out more')}
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
</p>
|
||||||
<MarketDataGrid grid={compileGridData(market)} />
|
<MarketDataGrid grid={compileGridData(market, onSelect)} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,7 @@ export function Index() {
|
|||||||
|
|
||||||
if (marketId) {
|
if (marketId) {
|
||||||
replace(`/markets/${marketId}`);
|
replace(`/markets/${marketId}`);
|
||||||
|
update({ marketId });
|
||||||
}
|
}
|
||||||
// Fallback to the markets list page
|
// Fallback to the markets list page
|
||||||
else {
|
else {
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
import { LiquidityTable, useLiquidityProvision } from '@vegaprotocol/liquidity';
|
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 { LiquidityProvisionStatus } from '@vegaprotocol/types';
|
||||||
import { AsyncRenderer, Tab, Tabs } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer, Tab, Tabs } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
import type { AgGridReact } from 'ag-grid-react';
|
import type { AgGridReact } from 'ag-grid-react';
|
||||||
import { Header, HeaderStat } from '../../components/header';
|
import { Header, HeaderStat } from '../../components/header';
|
||||||
import Link from 'next/link';
|
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useRef, useMemo } from 'react';
|
import { useRef, useMemo } from 'react';
|
||||||
|
import { tooltipMapping } from '@vegaprotocol/market-info';
|
||||||
|
|
||||||
const LiquidityPage = ({ id }: { id?: string }) => {
|
const LiquidityPage = ({ id }: { id?: string }) => {
|
||||||
const { query } = useRouter();
|
const { query, push } = useRouter();
|
||||||
const { keypair } = useVegaWallet();
|
const { keypair } = useVegaWallet();
|
||||||
const gridRef = useRef<AgGridReact | null>(null);
|
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);
|
id || (Array.isArray(query.marketId) ? query.marketId[0] : query.marketId);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: { liquidityProviders, suppliedStake, targetStake, code, symbol },
|
data: {
|
||||||
|
liquidityProviders,
|
||||||
|
suppliedStake,
|
||||||
|
targetStake,
|
||||||
|
name,
|
||||||
|
symbol,
|
||||||
|
assetDecimalPlaces,
|
||||||
|
},
|
||||||
loading,
|
loading,
|
||||||
error,
|
error,
|
||||||
} = useLiquidityProvision({ marketId });
|
} = useLiquidityProvision({ marketId });
|
||||||
@ -62,16 +69,36 @@ const LiquidityPage = ({ id }: { id?: string }) => {
|
|||||||
<div className="h-full grid grid-rows-[min-content_1fr]">
|
<div className="h-full grid grid-rows-[min-content_1fr]">
|
||||||
<Header
|
<Header
|
||||||
title={
|
title={
|
||||||
<Link href={`/markets/${marketId}`}>
|
<button onClick={() => push(`/markets/${marketId}`)}>{`${name} ${t(
|
||||||
{`${code} ${t('liquidity provision')}`}
|
'liquidity provision'
|
||||||
</Link>
|
)}`}</button>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<HeaderStat heading={t('Target stake')}>
|
<HeaderStat
|
||||||
<div>{`${targetStake} ${symbol}`}</div>
|
heading={t('Target stake')}
|
||||||
|
description={tooltipMapping['targetStake']}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
{targetStake
|
||||||
|
? `${addDecimalsFormatNumber(
|
||||||
|
targetStake,
|
||||||
|
assetDecimalPlaces ?? 0
|
||||||
|
)} ${symbol}`
|
||||||
|
: '-'}
|
||||||
|
</div>
|
||||||
</HeaderStat>
|
</HeaderStat>
|
||||||
<HeaderStat heading={t('Supplied stake')}>
|
<HeaderStat
|
||||||
<div>{`${suppliedStake} ${symbol}`}</div>
|
heading={t('Supplied stake')}
|
||||||
|
description={tooltipMapping['suppliedStake']}
|
||||||
|
>
|
||||||
|
<div>
|
||||||
|
{suppliedStake
|
||||||
|
? `${addDecimalsFormatNumber(
|
||||||
|
suppliedStake,
|
||||||
|
assetDecimalPlaces ?? 0
|
||||||
|
)} ${symbol}`
|
||||||
|
: '-'}
|
||||||
|
</div>
|
||||||
</HeaderStat>
|
</HeaderStat>
|
||||||
<HeaderStat heading={t('Market ID')}>
|
<HeaderStat heading={t('Market ID')}>
|
||||||
<div className="break-word">{marketId}</div>
|
<div className="break-word">{marketId}</div>
|
||||||
@ -83,13 +110,28 @@ const LiquidityPage = ({ id }: { id?: string }) => {
|
|||||||
name={t('My liquidity provision')}
|
name={t('My liquidity provision')}
|
||||||
hidden={!partyId}
|
hidden={!partyId}
|
||||||
>
|
>
|
||||||
<LiquidityTable ref={gridRef} data={myLpEdges} />
|
<LiquidityTable
|
||||||
|
ref={gridRef}
|
||||||
|
data={myLpEdges}
|
||||||
|
symbol={symbol}
|
||||||
|
assetDecimalPlaces={assetDecimalPlaces}
|
||||||
|
/>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id={LiquidityTabs.Active} name={t('Active')}>
|
<Tab id={LiquidityTabs.Active} name={t('Active')}>
|
||||||
<LiquidityTable ref={gridRef} data={activeEdges} />
|
<LiquidityTable
|
||||||
|
ref={gridRef}
|
||||||
|
data={activeEdges}
|
||||||
|
symbol={symbol}
|
||||||
|
assetDecimalPlaces={assetDecimalPlaces}
|
||||||
|
/>
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id={LiquidityTabs.Inactive} name={t('Inactive')}>
|
<Tab id={LiquidityTabs.Inactive} name={t('Inactive')}>
|
||||||
<LiquidityTable ref={gridRef} data={inactiveEdges} />
|
<LiquidityTable
|
||||||
|
ref={gridRef}
|
||||||
|
data={inactiveEdges}
|
||||||
|
symbol={symbol}
|
||||||
|
assetDecimalPlaces={assetDecimalPlaces}
|
||||||
|
/>
|
||||||
</Tab>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
|
@ -41,6 +41,7 @@ query Market($marketId: ID!, $interval: Interval!, $since: String!) {
|
|||||||
id
|
id
|
||||||
symbol
|
symbol
|
||||||
name
|
name
|
||||||
|
decimals
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ const MARKET_QUERY = gql`
|
|||||||
id
|
id
|
||||||
symbol
|
symbol
|
||||||
name
|
name
|
||||||
|
decimals
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -83,11 +84,20 @@ const MarketPage = ({ id }: { id?: string }) => {
|
|||||||
update: store.update,
|
update: store.update,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
const { update: updateStore } = useGlobalStore((store) => ({
|
||||||
|
update: store.update,
|
||||||
|
}));
|
||||||
|
|
||||||
// Default to first marketId query item if found
|
// Default to first marketId query item if found
|
||||||
const marketId =
|
const marketId =
|
||||||
id || (Array.isArray(query.marketId) ? query.marketId[0] : query.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
|
// Cache timestamp for yesterday to prevent full unmount of market page when
|
||||||
// a rerender occurs
|
// a rerender occurs
|
||||||
const yTimestamp = useMemo(() => {
|
const yTimestamp = useMemo(() => {
|
||||||
@ -128,20 +138,16 @@ const MarketPage = ({ id }: { id?: string }) => {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{w > 960 ? (
|
{w > 960 ? (
|
||||||
<TradeGrid market={market} />
|
<TradeGrid market={market} onSelect={onSelect} />
|
||||||
) : (
|
) : (
|
||||||
<TradePanels market={market} />
|
<TradePanels market={market} onSelect={onSelect} />
|
||||||
)}
|
)}
|
||||||
<SelectMarketDialog
|
<SelectMarketDialog
|
||||||
dialogOpen={landingDialog && !riskNoticeDialog}
|
dialogOpen={landingDialog && !riskNoticeDialog}
|
||||||
setDialogOpen={(isOpen: boolean) =>
|
setDialogOpen={(isOpen: boolean) =>
|
||||||
update({ landingDialog: isOpen })
|
update({ landingDialog: isOpen })
|
||||||
}
|
}
|
||||||
onSelect={(marketId: string) => {
|
onSelect={onSelect}
|
||||||
if (marketId && marketId !== marketId) {
|
|
||||||
update({ marketId });
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
@ -103,6 +103,10 @@ export interface Market_market_tradableInstrument_instrument_product_settlementA
|
|||||||
* The full name of the asset (e.g: Great British Pound)
|
* The full name of the asset (e.g: Great British Pound)
|
||||||
*/
|
*/
|
||||||
name: string;
|
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 {
|
export interface Market_market_tradableInstrument_instrument_product {
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import {
|
import { DealTicketContainer } from '@vegaprotocol/deal-ticket';
|
||||||
DealTicketContainer,
|
import { MarketInfoContainer } from '@vegaprotocol/market-info';
|
||||||
MarketInfoContainer,
|
|
||||||
} from '@vegaprotocol/deal-ticket';
|
|
||||||
import { OrderbookContainer } from '@vegaprotocol/market-depth';
|
import { OrderbookContainer } from '@vegaprotocol/market-depth';
|
||||||
import { OrderListContainer } from '@vegaprotocol/orders';
|
import { OrderListContainer } from '@vegaprotocol/orders';
|
||||||
import { FillsContainer } from '@vegaprotocol/fills';
|
import { FillsContainer } from '@vegaprotocol/fills';
|
||||||
@ -32,7 +30,6 @@ import {
|
|||||||
t,
|
t,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} from '@vegaprotocol/react-helpers';
|
||||||
import { SelectMarketPopover } from '@vegaprotocol/market-list';
|
import { SelectMarketPopover } from '@vegaprotocol/market-list';
|
||||||
import { useGlobalStore } from '../../stores';
|
|
||||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||||
import { useEnvironment } from '@vegaprotocol/environment';
|
import { useEnvironment } from '@vegaprotocol/environment';
|
||||||
import type { CandleClose } from '@vegaprotocol/types';
|
import type { CandleClose } from '@vegaprotocol/types';
|
||||||
@ -43,6 +40,7 @@ import {
|
|||||||
MarketTradingModeMapping,
|
MarketTradingModeMapping,
|
||||||
} from '@vegaprotocol/types';
|
} from '@vegaprotocol/types';
|
||||||
import { TradingModeTooltip } from '../../components/trading-mode-tooltip';
|
import { TradingModeTooltip } from '../../components/trading-mode-tooltip';
|
||||||
|
import { useRouter } from 'next/router';
|
||||||
|
|
||||||
const TradingViews = {
|
const TradingViews = {
|
||||||
Candles: CandlesChartContainer,
|
Candles: CandlesChartContainer,
|
||||||
@ -110,21 +108,16 @@ const ExpiryTooltipContent = ({
|
|||||||
|
|
||||||
interface TradeMarketHeaderProps {
|
interface TradeMarketHeaderProps {
|
||||||
market: Market_market;
|
market: Market_market;
|
||||||
|
onSelect: (marketId: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TradeMarketHeader = ({ market }: TradeMarketHeaderProps) => {
|
export const TradeMarketHeader = ({
|
||||||
|
market,
|
||||||
|
onSelect,
|
||||||
|
}: TradeMarketHeaderProps) => {
|
||||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||||
const { setAssetDetailsDialogOpen, setAssetDetailsDialogSymbol } =
|
const { setAssetDetailsDialogOpen, setAssetDetailsDialogSymbol } =
|
||||||
useAssetDetailsDialogStore();
|
useAssetDetailsDialogStore();
|
||||||
const { update } = useGlobalStore((store) => ({
|
|
||||||
update: store.update,
|
|
||||||
}));
|
|
||||||
|
|
||||||
const onSelect = (marketId: string) => {
|
|
||||||
if (marketId && marketId !== marketId) {
|
|
||||||
update({ marketId });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const candlesClose: string[] = (market?.candles || [])
|
const candlesClose: string[] = (market?.candles || [])
|
||||||
.map((candle) => candle?.close)
|
.map((candle) => candle?.close)
|
||||||
@ -136,6 +129,7 @@ export const TradeMarketHeader = ({ market }: TradeMarketHeaderProps) => {
|
|||||||
const itemClass =
|
const itemClass =
|
||||||
'min-w-min w-[120px] whitespace-nowrap pb-3 px-4 border-l border-neutral-300 dark:border-neutral-700';
|
'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 itemHeading = 'text-neutral-400';
|
||||||
|
const { push } = useRouter();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<header className="w-screen xl:px-4 pt-4 border-b border-neutral-300 dark:border-neutral-700">
|
<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>
|
<div className={itemHeading}>{t('Trading mode')}</div>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
align="start"
|
align="start"
|
||||||
description={<TradingModeTooltip market={market} />}
|
description={
|
||||||
|
<TradingModeTooltip
|
||||||
|
market={market}
|
||||||
|
onSelect={(marketId: string) => {
|
||||||
|
onSelect(marketId);
|
||||||
|
push(`/liquidity/${marketId}`);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<div data-testid="trading-mode">
|
<div data-testid="trading-mode">
|
||||||
{market.tradingMode ===
|
{market.tradingMode ===
|
||||||
@ -242,12 +244,14 @@ export const TradeMarketHeader = ({ market }: TradeMarketHeaderProps) => {
|
|||||||
|
|
||||||
interface TradeGridProps {
|
interface TradeGridProps {
|
||||||
market: Market_market;
|
market: Market_market;
|
||||||
|
onSelect: (marketId: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TradeGrid = ({ market }: TradeGridProps) => {
|
export const TradeGrid = ({ market, onSelect }: TradeGridProps) => {
|
||||||
|
const { push } = useRouter();
|
||||||
return (
|
return (
|
||||||
<div className="h-full grid grid-rows-[min-content_1fr]">
|
<div className="h-full grid grid-rows-[min-content_1fr]">
|
||||||
<TradeMarketHeader market={market} />
|
<TradeMarketHeader market={market} onSelect={onSelect} />
|
||||||
<ResizableGrid vertical={true}>
|
<ResizableGrid vertical={true}>
|
||||||
<ResizableGridPanel minSize={75} priority={LayoutPriority.High}>
|
<ResizableGridPanel minSize={75} priority={LayoutPriority.High}>
|
||||||
<ResizableGrid proportionalLayout={false} minSize={200}>
|
<ResizableGrid proportionalLayout={false} minSize={200}>
|
||||||
@ -278,7 +282,13 @@ export const TradeGrid = ({ market }: TradeGridProps) => {
|
|||||||
<TradingViews.Ticket marketId={market.id} />
|
<TradingViews.Ticket marketId={market.id} />
|
||||||
</Tab>
|
</Tab>
|
||||||
<Tab id="info" name={t('Info')}>
|
<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>
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</TradeGridChild>
|
</TradeGridChild>
|
||||||
@ -348,9 +358,11 @@ const TradeGridChild = ({ children }: TradeGridChildProps) => {
|
|||||||
|
|
||||||
interface TradePanelsProps {
|
interface TradePanelsProps {
|
||||||
market: Market_market;
|
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 [view, setView] = useState<TradingView>('Candles');
|
||||||
|
|
||||||
const renderView = () => {
|
const renderView = () => {
|
||||||
@ -360,16 +372,26 @@ export const TradePanels = ({ market }: TradePanelsProps) => {
|
|||||||
throw new Error(`No component for view: ${view}`);
|
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 (
|
return (
|
||||||
<div className="h-full grid grid-rows-[min-content_1fr_min-content]">
|
<div className="h-full grid grid-rows-[min-content_1fr_min-content]">
|
||||||
<TradeMarketHeader market={market} />
|
<TradeMarketHeader market={market} onSelect={onSelect} />
|
||||||
<div className="h-full">
|
<div className="h-full">
|
||||||
<AutoSizer>
|
<AutoSizer>
|
||||||
{({ width, height }) => (
|
{({ width, height }) => (
|
||||||
<div style={{ width, height }}>{renderView()}</div>
|
<div style={{ width, height }} className="overflow-auto">
|
||||||
|
{renderView()}
|
||||||
|
</div>
|
||||||
)}
|
)}
|
||||||
</AutoSizer>
|
</AutoSizer>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,2 +1 @@
|
|||||||
export * from './deal-ticket';
|
export * from './deal-ticket';
|
||||||
export * from './market-info';
|
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
} from '@vegaprotocol/ui-toolkit';
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
import { useEnvironment } from '../../hooks/use-environment';
|
import { useEnvironment } from '../../hooks/use-environment';
|
||||||
import { Networks } from '../../types';
|
import { Networks } from '../../types';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
export const envNameMapping: Record<Networks, string> = {
|
export const envNameMapping: Record<Networks, string> = {
|
||||||
[Networks.CUSTOM]: t('Custom'),
|
[Networks.CUSTOM]: t('Custom'),
|
||||||
@ -68,7 +69,11 @@ const NetworkLabel = ({
|
|||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const NetworkSwitcher = () => {
|
export const NetworkSwitcher = ({
|
||||||
|
fixedBg,
|
||||||
|
}: {
|
||||||
|
fixedBg?: 'dark' | 'light';
|
||||||
|
}) => {
|
||||||
const { VEGA_ENV, VEGA_NETWORKS } = useEnvironment();
|
const { VEGA_ENV, VEGA_NETWORKS } = useEnvironment();
|
||||||
const [isOpen, setOpen] = useState(false);
|
const [isOpen, setOpen] = useState(false);
|
||||||
const [isAdvancedView, setAdvancedView] = useState(false);
|
const [isAdvancedView, setAdvancedView] = useState(false);
|
||||||
@ -83,9 +88,15 @@ export const NetworkSwitcher = () => {
|
|||||||
[setOpen, setAdvancedView]
|
[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 (
|
return (
|
||||||
<DropdownMenu open={isOpen} onOpenChange={handleOpen}>
|
<DropdownMenu open={isOpen} onOpenChange={handleOpen}>
|
||||||
<DropdownMenuTrigger className="text-white dark:text-white">
|
<DropdownMenuTrigger className={dropdownTriggerClasses}>
|
||||||
{envTriggerMapping[VEGA_ENV]}
|
{envTriggerMapping[VEGA_ENV]}
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent align="start">
|
<DropdownMenuContent align="start">
|
||||||
|
61
libs/liquidity/src/lib/MarketLiquidity.graphql
Normal file
61
libs/liquidity/src/lib/MarketLiquidity.graphql
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
|
||||||
*/
|
*/
|
||||||
code: 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)
|
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
|
||||||
*/
|
*/
|
||||||
|
@ -42,6 +42,7 @@ const MARKET_LIQUIDITY_QUERY = gql`
|
|||||||
tradableInstrument {
|
tradableInstrument {
|
||||||
instrument {
|
instrument {
|
||||||
code
|
code
|
||||||
|
name
|
||||||
product {
|
product {
|
||||||
... on Future {
|
... on Future {
|
||||||
settlementAsset {
|
settlementAsset {
|
||||||
@ -95,6 +96,7 @@ export interface LiquidityData {
|
|||||||
decimalPlaces?: number;
|
decimalPlaces?: number;
|
||||||
positionDecimalPlaces?: number;
|
positionDecimalPlaces?: number;
|
||||||
assetDecimalPlaces?: number;
|
assetDecimalPlaces?: number;
|
||||||
|
name?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useLiquidityProvision = ({
|
export const useLiquidityProvision = ({
|
||||||
@ -161,6 +163,7 @@ export const useLiquidityProvision = ({
|
|||||||
decimalPlaces: data?.market?.decimalPlaces,
|
decimalPlaces: data?.market?.decimalPlaces,
|
||||||
positionDecimalPlaces: data?.market?.positionDecimalPlaces,
|
positionDecimalPlaces: data?.market?.positionDecimalPlaces,
|
||||||
code: data?.market?.tradableInstrument.instrument.code,
|
code: data?.market?.tradableInstrument.instrument.code,
|
||||||
|
name: data?.market?.tradableInstrument.instrument.name,
|
||||||
assetDecimalPlaces:
|
assetDecimalPlaces:
|
||||||
data?.market?.tradableInstrument.instrument.product.settlementAsset
|
data?.market?.tradableInstrument.instrument.product.settlementAsset
|
||||||
.decimals,
|
.decimals,
|
||||||
|
@ -5,7 +5,10 @@ import {
|
|||||||
getDateTimeFormat,
|
getDateTimeFormat,
|
||||||
t,
|
t,
|
||||||
} from '@vegaprotocol/react-helpers';
|
} 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 type { AgGridReact } from 'ag-grid-react';
|
||||||
import { AgGridColumn } from 'ag-grid-react';
|
import { AgGridColumn } from 'ag-grid-react';
|
||||||
import type { LiquidityProvision } from './liquidity-data-provider';
|
import type { LiquidityProvision } from './liquidity-data-provider';
|
||||||
@ -14,11 +17,6 @@ import BigNumber from 'bignumber.js';
|
|||||||
import type { LiquidityProvisionStatus } from '@vegaprotocol/types';
|
import type { LiquidityProvisionStatus } from '@vegaprotocol/types';
|
||||||
import { LiquidityProvisionStatusMapping } 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) => {
|
const percentageFormatter = ({ value }: ValueFormatterParams) => {
|
||||||
if (!value) return '-';
|
if (!value) return '-';
|
||||||
return formatNumberPercentage(new BigNumber(value).times(100), 4) || '-';
|
return formatNumberPercentage(new BigNumber(value).times(100), 4) || '-';
|
||||||
@ -33,10 +31,16 @@ const dateValueFormatter = ({ value }: { value?: string | null }) => {
|
|||||||
|
|
||||||
export interface LiquidityTableProps {
|
export interface LiquidityTableProps {
|
||||||
data: LiquidityProvision[];
|
data: LiquidityProvision[];
|
||||||
|
symbol?: string;
|
||||||
|
assetDecimalPlaces?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const LiquidityTable = forwardRef<AgGridReact, LiquidityTableProps>(
|
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 (
|
return (
|
||||||
<AgGrid
|
<AgGrid
|
||||||
style={{ width: '100%', height: '100%' }}
|
style={{ width: '100%', height: '100%' }}
|
||||||
@ -44,29 +48,45 @@ export const LiquidityTable = forwardRef<AgGridReact, LiquidityTableProps>(
|
|||||||
getRowId={({ data }) => data.party}
|
getRowId={({ data }) => data.party}
|
||||||
rowHeight={34}
|
rowHeight={34}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
tooltipShowDelay={500}
|
||||||
defaultColDef={{
|
defaultColDef={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
|
tooltipComponent: TooltipCellComponent,
|
||||||
}}
|
}}
|
||||||
rowData={props.data}
|
rowData={data}
|
||||||
{...props}
|
|
||||||
>
|
>
|
||||||
<AgGridColumn headerName={t('Party')} field="party" />
|
|
||||||
<AgGridColumn
|
<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"
|
field="commitmentAmount"
|
||||||
type="rightAligned"
|
type="rightAligned"
|
||||||
|
headerTooltip={t(
|
||||||
|
'The amount committed to the market by this liquidity provider.'
|
||||||
|
)}
|
||||||
valueFormatter={assetDecimalsFormatter}
|
valueFormatter={assetDecimalsFormatter}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Share')}
|
headerName={t('Share')}
|
||||||
field="equityLikeShare"
|
field="equityLikeShare"
|
||||||
type="rightAligned"
|
type="rightAligned"
|
||||||
|
headerTooltip={t(
|
||||||
|
'The equity-like share of liquidity of the market, specific to each liquidity provider.'
|
||||||
|
)}
|
||||||
valueFormatter={percentageFormatter}
|
valueFormatter={percentageFormatter}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Fee')}
|
headerName={t('Proposed fee')}
|
||||||
|
headerTooltip={t(
|
||||||
|
'The fee percentage (per trade) proposed by each liquidity provider.'
|
||||||
|
)}
|
||||||
field="fee"
|
field="fee"
|
||||||
type="rightAligned"
|
type="rightAligned"
|
||||||
valueFormatter={percentageFormatter}
|
valueFormatter={percentageFormatter}
|
||||||
@ -75,22 +95,33 @@ export const LiquidityTable = forwardRef<AgGridReact, LiquidityTableProps>(
|
|||||||
headerName={t('Average entry valuation')}
|
headerName={t('Average entry valuation')}
|
||||||
field="averageEntryValuation"
|
field="averageEntryValuation"
|
||||||
type="rightAligned"
|
type="rightAligned"
|
||||||
|
headerTooltip={t(
|
||||||
|
'The average entry valuation of this liquidity provision for the market.'
|
||||||
|
)}
|
||||||
|
minWidth={160}
|
||||||
valueFormatter={assetDecimalsFormatter}
|
valueFormatter={assetDecimalsFormatter}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Obligation (siskas)')}
|
headerName={t('Obligation')}
|
||||||
field="obligation"
|
field="obligation"
|
||||||
type="rightAligned"
|
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_siskas network parameter.'
|
||||||
|
)}
|
||||||
valueFormatter={assetDecimalsFormatter}
|
valueFormatter={assetDecimalsFormatter}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<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"
|
field="supplied"
|
||||||
type="rightAligned"
|
type="rightAligned"
|
||||||
valueFormatter={assetDecimalsFormatter}
|
valueFormatter={assetDecimalsFormatter}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Status')}
|
headerName={t('Status')}
|
||||||
|
headerTooltip={t('The current status of this liquidity provision.')}
|
||||||
field="status"
|
field="status"
|
||||||
valueFormatter={({ value }: { value: LiquidityProvisionStatus }) => {
|
valueFormatter={({ value }: { value: LiquidityProvisionStatus }) => {
|
||||||
if (!value) return value;
|
if (!value) return value;
|
||||||
@ -99,12 +130,18 @@ export const LiquidityTable = forwardRef<AgGridReact, LiquidityTableProps>(
|
|||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Created')}
|
headerName={t('Created')}
|
||||||
|
headerTooltip={t(
|
||||||
|
'The date and time this liquidity provision was created.'
|
||||||
|
)}
|
||||||
field="createdAt"
|
field="createdAt"
|
||||||
type="rightAligned"
|
type="rightAligned"
|
||||||
valueFormatter={dateValueFormatter}
|
valueFormatter={dateValueFormatter}
|
||||||
/>
|
/>
|
||||||
<AgGridColumn
|
<AgGridColumn
|
||||||
headerName={t('Updated')}
|
headerName={t('Updated')}
|
||||||
|
headerTooltip={t(
|
||||||
|
'The last time this liquidity provision was updated.'
|
||||||
|
)}
|
||||||
field="updatedAt"
|
field="updatedAt"
|
||||||
type="rightAligned"
|
type="rightAligned"
|
||||||
valueFormatter={dateValueFormatter}
|
valueFormatter={dateValueFormatter}
|
||||||
|
12
libs/market-info/.babelrc
Normal file
12
libs/market-info/.babelrc
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"presets": [
|
||||||
|
[
|
||||||
|
"@nrwl/react/babel",
|
||||||
|
{
|
||||||
|
"runtime": "automatic",
|
||||||
|
"useBuiltIns": "usage"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"plugins": []
|
||||||
|
}
|
18
libs/market-info/.eslintrc.json
Normal file
18
libs/market-info/.eslintrc.json
Normal 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": {}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
7
libs/market-info/README.md
Normal file
7
libs/market-info/README.md
Normal 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).
|
11
libs/market-info/jest.config.ts
Normal file
11
libs/market-info/jest.config.ts
Normal 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'],
|
||||||
|
};
|
4
libs/market-info/package.json
Normal file
4
libs/market-info/package.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"name": "@vegaprotocol/market-info",
|
||||||
|
"version": "0.0.1"
|
||||||
|
}
|
43
libs/market-info/project.json
Normal file
43
libs/market-info/project.json
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
libs/market-info/src/components/MarketNames.graphql
Normal file
20
libs/market-info/src/components/MarketNames.graphql
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
query MarketNames {
|
||||||
|
markets {
|
||||||
|
id
|
||||||
|
name
|
||||||
|
state
|
||||||
|
tradableInstrument {
|
||||||
|
instrument {
|
||||||
|
code
|
||||||
|
metadata {
|
||||||
|
tags
|
||||||
|
}
|
||||||
|
product {
|
||||||
|
... on Future {
|
||||||
|
quoteName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
libs/market-info/src/components/index.ts
Normal file
1
libs/market-info/src/components/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './market-info';
|
@ -1,3 +1,5 @@
|
|||||||
export * from './__generated__';
|
export * from './__generated__';
|
||||||
|
export * from './info-key-value-table';
|
||||||
export * from './info-market-query';
|
export * from './info-market-query';
|
||||||
export * from './info-market';
|
export * from './info-market';
|
||||||
|
export * from './tooltip-mapping';
|
@ -16,8 +16,7 @@ import { tooltipMapping } from './tooltip-mapping';
|
|||||||
|
|
||||||
interface RowProps {
|
interface RowProps {
|
||||||
field: string;
|
field: string;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
value: unknown;
|
||||||
value: any;
|
|
||||||
decimalPlaces?: number;
|
decimalPlaces?: number;
|
||||||
asPercentage?: boolean;
|
asPercentage?: boolean;
|
||||||
unformatted?: boolean;
|
unformatted?: boolean;
|
||||||
@ -32,27 +31,29 @@ const Row = ({
|
|||||||
unformatted,
|
unformatted,
|
||||||
assetSymbol = '',
|
assetSymbol = '',
|
||||||
}: RowProps) => {
|
}: 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';
|
const className = 'text-black dark:text-white text-ui !px-0 !font-normal';
|
||||||
let formattedValue = value;
|
|
||||||
if (isNumber && !unformatted) {
|
const getFormattedValue = (value: unknown) => {
|
||||||
|
if (typeof value !== 'string' && typeof value !== 'number') return null;
|
||||||
|
if (unformatted || isNaN(Number(value))) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
if (decimalPlaces) {
|
if (decimalPlaces) {
|
||||||
formattedValue = `${addDecimalsFormatNumber(
|
return `${addDecimalsFormatNumber(value, decimalPlaces)} ${assetSymbol}`;
|
||||||
value,
|
|
||||||
decimalPlaces
|
|
||||||
)} ${assetSymbol}`;
|
|
||||||
} else if (asPercentage && value) {
|
|
||||||
formattedValue = formatNumberPercentage(new BigNumber(value).times(100));
|
|
||||||
} else {
|
|
||||||
formattedValue = `${formatNumber(Number(value))} ${assetSymbol}`;
|
|
||||||
}
|
}
|
||||||
|
if (asPercentage) {
|
||||||
|
return formatNumberPercentage(new BigNumber(value).times(100));
|
||||||
}
|
}
|
||||||
if (isPrimitive) {
|
return `${formatNumber(Number(value))} ${assetSymbol}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const formattedValue: string | number | null = getFormattedValue(value);
|
||||||
|
|
||||||
|
if (!formattedValue) return null;
|
||||||
return (
|
return (
|
||||||
<KeyValueTableRow
|
<KeyValueTableRow
|
||||||
key={field}
|
key={field}
|
||||||
inline={isPrimitive}
|
inline={true}
|
||||||
noBorder={true}
|
noBorder={true}
|
||||||
dtClassName={className}
|
dtClassName={className}
|
||||||
ddClassName={className}
|
ddClassName={className}
|
||||||
@ -63,18 +64,15 @@ const Row = ({
|
|||||||
<span style={{ wordBreak: 'break-word' }}>{formattedValue}</span>
|
<span style={{ wordBreak: 'break-word' }}>{formattedValue}</span>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
return null;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface MarketInfoTableProps {
|
export interface MarketInfoTableProps {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
data: unknown;
|
||||||
data: any;
|
|
||||||
decimalPlaces?: number;
|
decimalPlaces?: number;
|
||||||
asPercentage?: boolean;
|
asPercentage?: boolean;
|
||||||
unformatted?: boolean;
|
unformatted?: boolean;
|
||||||
omits?: string[];
|
omits?: string[];
|
||||||
link?: ReactNode;
|
children?: ReactNode;
|
||||||
assetSymbol?: string;
|
assetSymbol?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,9 +82,12 @@ export const MarketInfoTable = ({
|
|||||||
asPercentage,
|
asPercentage,
|
||||||
unformatted,
|
unformatted,
|
||||||
omits = ['__typename'],
|
omits = ['__typename'],
|
||||||
link,
|
children,
|
||||||
assetSymbol,
|
assetSymbol,
|
||||||
}: MarketInfoTableProps) => {
|
}: MarketInfoTableProps) => {
|
||||||
|
if (!data || typeof data !== 'object') {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<KeyValueTable>
|
<KeyValueTable>
|
||||||
@ -104,7 +105,7 @@ export const MarketInfoTable = ({
|
|||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</KeyValueTable>
|
</KeyValueTable>
|
||||||
{link}
|
<div className="flex flex-col gap-2">{children}</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
@ -39,11 +39,6 @@ export const MARKET_INFO_QUERY = gql`
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
riskFactors {
|
|
||||||
market
|
|
||||||
short
|
|
||||||
long
|
|
||||||
}
|
|
||||||
data {
|
data {
|
||||||
market {
|
market {
|
||||||
id
|
id
|
@ -1,6 +1,11 @@
|
|||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { formatNumber, t } from '@vegaprotocol/react-helpers';
|
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 pick from 'lodash/pick';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import { useQuery } from '@apollo/client';
|
import { useQuery } from '@apollo/client';
|
||||||
@ -19,7 +24,6 @@ import type {
|
|||||||
} from './__generated__/MarketInfoQuery';
|
} from './__generated__/MarketInfoQuery';
|
||||||
import { MarketInfoTable } from './info-key-value-table';
|
import { MarketInfoTable } from './info-key-value-table';
|
||||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
import { generatePath } from 'react-router-dom';
|
import { generatePath } from 'react-router-dom';
|
||||||
import { useEnvironment } from '@vegaprotocol/environment';
|
import { useEnvironment } from '@vegaprotocol/environment';
|
||||||
|
|
||||||
@ -29,6 +33,7 @@ const Links = {
|
|||||||
|
|
||||||
export interface InfoProps {
|
export interface InfoProps {
|
||||||
market: MarketInfoQuery_market;
|
market: MarketInfoQuery_market;
|
||||||
|
onSelect: (id: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const calcCandleVolume = (
|
export const calcCandleVolume = (
|
||||||
@ -43,8 +48,12 @@ export const calcCandleVolume = (
|
|||||||
|
|
||||||
export interface MarketInfoContainerProps {
|
export interface MarketInfoContainerProps {
|
||||||
marketId: string;
|
marketId: string;
|
||||||
|
onSelect: (id: string) => void;
|
||||||
}
|
}
|
||||||
export const MarketInfoContainer = ({ marketId }: MarketInfoContainerProps) => {
|
export const MarketInfoContainer = ({
|
||||||
|
marketId,
|
||||||
|
onSelect,
|
||||||
|
}: MarketInfoContainerProps) => {
|
||||||
const yTimestamp = useMemo(() => {
|
const yTimestamp = useMemo(() => {
|
||||||
const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
|
const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
|
||||||
return new Date(yesterday * 1000).toISOString();
|
return new Date(yesterday * 1000).toISOString();
|
||||||
@ -63,7 +72,7 @@ export const MarketInfoContainer = ({ marketId }: MarketInfoContainerProps) => {
|
|||||||
return (
|
return (
|
||||||
<AsyncRenderer<MarketInfoQuery> data={data} loading={loading} error={error}>
|
<AsyncRenderer<MarketInfoQuery> data={data} loading={loading} error={error}>
|
||||||
{data && data.market ? (
|
{data && data.market ? (
|
||||||
<Info market={data.market} />
|
<Info market={data.market} onSelect={onSelect} />
|
||||||
) : (
|
) : (
|
||||||
<Splash>
|
<Splash>
|
||||||
<p>{t('Could not load market')}</p>
|
<p>{t('Could not load market')}</p>
|
||||||
@ -73,8 +82,8 @@ export const MarketInfoContainer = ({ marketId }: MarketInfoContainerProps) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Info = ({ market }: InfoProps) => {
|
export const Info = ({ market, onSelect }: InfoProps) => {
|
||||||
const { VEGA_TOKEN_URL } = useEnvironment();
|
const { VEGA_TOKEN_URL, VEGA_EXPLORER_URL } = useEnvironment();
|
||||||
const headerClassName = 'uppercase text-lg';
|
const headerClassName = 'uppercase text-lg';
|
||||||
const dayVolume = calcCandleVolume(market);
|
const dayVolume = calcCandleVolume(market);
|
||||||
const assetSymbol =
|
const assetSymbol =
|
||||||
@ -153,7 +162,6 @@ export const Info = ({ market }: InfoProps) => {
|
|||||||
),
|
),
|
||||||
})),
|
})),
|
||||||
];
|
];
|
||||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
|
||||||
const keyDetails = {
|
const keyDetails = {
|
||||||
...pick(market, 'decimalPlaces', 'positionDecimalPlaces', 'tradingMode'),
|
...pick(market, 'decimalPlaces', 'positionDecimalPlaces', 'tradingMode'),
|
||||||
state: MarketStateMapping[market.state],
|
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'),
|
title: t('Risk model'),
|
||||||
content: (
|
content: (
|
||||||
@ -282,35 +280,30 @@ export const Info = ({ market }: InfoProps) => {
|
|||||||
.decimals
|
.decimals
|
||||||
}
|
}
|
||||||
assetSymbol={assetSymbol}
|
assetSymbol={assetSymbol}
|
||||||
link={
|
>
|
||||||
<ExternalLink href={`/liquidity/${market.id}`}>
|
<Link onClick={() => onSelect(market.id)}>
|
||||||
{t('View liquidity provision table')}
|
{t('View liquidity provision table')}
|
||||||
</ExternalLink>
|
</Link>
|
||||||
}
|
</MarketInfoTable>
|
||||||
/>
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: t('Oracle'),
|
title: t('Oracle'),
|
||||||
content: (
|
content: (
|
||||||
<MarketInfoTable
|
<MarketInfoTable
|
||||||
data={{
|
data={market.tradableInstrument.instrument.product.oracleSpecBinding}
|
||||||
...market.tradableInstrument.instrument.product.oracleSpecBinding,
|
>
|
||||||
priceOracle:
|
<ExternalLink
|
||||||
market.tradableInstrument.instrument.product
|
href={`${VEGA_EXPLORER_URL}/oracles#${market.tradableInstrument.instrument.product.oracleSpecForSettlementPrice.id}`}
|
||||||
.oracleSpecForSettlementPrice.id,
|
>
|
||||||
terminationOracle:
|
{t('View price oracle specification')}
|
||||||
market.tradableInstrument.instrument.product
|
</ExternalLink>
|
||||||
.oracleSpecForTradingTermination.id,
|
|
||||||
}}
|
|
||||||
link={
|
|
||||||
<ExternalLink
|
<ExternalLink
|
||||||
href={`${VEGA_EXPLORER_URL}/oracles#${market.tradableInstrument.instrument.product.oracleSpecForTradingTermination.id}`}
|
href={`${VEGA_EXPLORER_URL}/oracles#${market.tradableInstrument.instrument.product.oracleSpecForTradingTermination.id}`}
|
||||||
>
|
>
|
||||||
{t('View full oracle details')}
|
{t('View termination oracle specification')}
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
}
|
</MarketInfoTable>
|
||||||
/>
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@ -319,7 +312,6 @@ export const Info = ({ market }: InfoProps) => {
|
|||||||
{
|
{
|
||||||
title: t('Proposal'),
|
title: t('Proposal'),
|
||||||
content: (
|
content: (
|
||||||
<p>
|
|
||||||
<ExternalLink
|
<ExternalLink
|
||||||
href={generatePath(Links.PROPOSAL_PAGE, {
|
href={generatePath(Links.PROPOSAL_PAGE, {
|
||||||
tokenUrl: VEGA_TOKEN_URL,
|
tokenUrl: VEGA_TOKEN_URL,
|
||||||
@ -333,7 +325,6 @@ export const Info = ({ market }: InfoProps) => {
|
|||||||
>
|
>
|
||||||
{t('View governance proposal')}
|
{t('View governance proposal')}
|
||||||
</ExternalLink>
|
</ExternalLink>
|
||||||
</p>
|
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
];
|
];
|
@ -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).'
|
'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(
|
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(
|
infrastructureFee: t(
|
||||||
'Fees paid to validators as a reward for running the infrastructure of the network.'
|
'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(
|
scalingFactor: t(
|
||||||
'The scaling between the liquidity demand estimate, based on open interest and target stake.'
|
'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.'),
|
||||||
};
|
};
|
1
libs/market-info/src/index.ts
Normal file
1
libs/market-info/src/index.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export * from './components';
|
1
libs/market-info/src/setup-tests.ts
Normal file
1
libs/market-info/src/setup-tests.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
import '@testing-library/jest-dom';
|
25
libs/market-info/tsconfig.json
Normal file
25
libs/market-info/tsconfig.json
Normal 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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
23
libs/market-info/tsconfig.lib.json
Normal file
23
libs/market-info/tsconfig.lib.json
Normal 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"]
|
||||||
|
}
|
20
libs/market-info/tsconfig.spec.json
Normal file
20
libs/market-info/tsconfig.spec.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
@ -23,7 +23,7 @@ import type { AgGridReact, AgGridReactProps } from 'ag-grid-react';
|
|||||||
import type { IDatasource, IGetRowsParams } from 'ag-grid-community';
|
import type { IDatasource, IGetRowsParams } from 'ag-grid-community';
|
||||||
import type { Position } from './positions-data-providers';
|
import type { Position } from './positions-data-providers';
|
||||||
import { MarketTradingMode } from '@vegaprotocol/types';
|
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;
|
export const getRowId = ({ data }: { data: Position }) => data.marketId;
|
||||||
|
|
||||||
@ -151,9 +151,11 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
|
|||||||
getRowId={getRowId}
|
getRowId={getRowId}
|
||||||
rowHeight={34}
|
rowHeight={34}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
|
tooltipShowDelay={500}
|
||||||
defaultColDef={{
|
defaultColDef={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
resizable: true,
|
resizable: true,
|
||||||
|
tooltipComponent: TooltipCellComponent,
|
||||||
}}
|
}}
|
||||||
components={{ PriceFlashCell, ProgressBarCell }}
|
components={{ PriceFlashCell, ProgressBarCell }}
|
||||||
{...props}
|
{...props}
|
||||||
|
@ -2,7 +2,6 @@ import { Side } from '@vegaprotocol/types';
|
|||||||
import type { ICellRendererParams } from 'ag-grid-community';
|
import type { ICellRendererParams } from 'ag-grid-community';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { addDecimalsFormatNumber } from '../format';
|
import { addDecimalsFormatNumber } from '../format';
|
||||||
import { negativeClassNames, positiveClassNames } from './cell-class-rules';
|
|
||||||
|
|
||||||
export const Size = ({
|
export const Size = ({
|
||||||
value,
|
value,
|
||||||
@ -17,8 +16,8 @@ export const Size = ({
|
|||||||
<span
|
<span
|
||||||
data-testid="size"
|
data-testid="size"
|
||||||
className={classNames('text-right', {
|
className={classNames('text-right', {
|
||||||
[positiveClassNames]: side === Side.SIDE_BUY,
|
'text-vega-green-dark dark:text-vega-green': side === Side.SIDE_BUY,
|
||||||
[negativeClassNames]: side === Side.SIDE_SELL,
|
'text-vega-red-dark dark:text-vega-red': side === Side.SIDE_SELL,
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{side === Side.SIDE_BUY ? '+' : side === Side.SIDE_SELL ? '-' : ''}
|
{side === Side.SIDE_BUY ? '+' : side === Side.SIDE_SELL ? '-' : ''}
|
||||||
|
@ -1 +1 @@
|
|||||||
export { Tooltip } from './tooltip';
|
export * from './tooltip';
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
Arrow,
|
Arrow,
|
||||||
Portal,
|
Portal,
|
||||||
} from '@radix-ui/react-tooltip';
|
} from '@radix-ui/react-tooltip';
|
||||||
|
import type { ITooltipParams } from 'ag-grid-community';
|
||||||
|
|
||||||
export interface TooltipProps {
|
export interface TooltipProps {
|
||||||
children: React.ReactElement;
|
children: React.ReactElement;
|
||||||
@ -56,3 +57,11 @@ export const Tooltip = ({
|
|||||||
) : (
|
) : (
|
||||||
children
|
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>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
"@vegaprotocol/governance": ["libs/governance/src/index.ts"],
|
"@vegaprotocol/governance": ["libs/governance/src/index.ts"],
|
||||||
"@vegaprotocol/liquidity": ["libs/liquidity/src/index.ts"],
|
"@vegaprotocol/liquidity": ["libs/liquidity/src/index.ts"],
|
||||||
"@vegaprotocol/market-depth": ["libs/market-depth/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/market-list": ["libs/market-list/src/index.ts"],
|
||||||
"@vegaprotocol/network-info": ["libs/network-info/src/index.ts"],
|
"@vegaprotocol/network-info": ["libs/network-info/src/index.ts"],
|
||||||
"@vegaprotocol/network-stats": ["libs/network-stats/src/index.ts"],
|
"@vegaprotocol/network-stats": ["libs/network-stats/src/index.ts"],
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
"governance": "libs/governance",
|
"governance": "libs/governance",
|
||||||
"liquidity": "libs/liquidity",
|
"liquidity": "libs/liquidity",
|
||||||
"market-depth": "libs/market-depth",
|
"market-depth": "libs/market-depth",
|
||||||
|
"market-info": "libs/market-info",
|
||||||
"market-list": "libs/market-list",
|
"market-list": "libs/market-list",
|
||||||
"network-info": "libs/network-info",
|
"network-info": "libs/network-info",
|
||||||
"network-stats": "libs/network-stats",
|
"network-stats": "libs/network-stats",
|
||||||
|
Loading…
Reference in New Issue
Block a user