Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop

This commit is contained in:
Madalina Raicu 2022-09-12 14:08:42 +01:00
commit 92077f4a5a
No known key found for this signature in database
GPG Key ID: 688B7B31149C1DCD
74 changed files with 755 additions and 337 deletions

View File

@ -8,7 +8,7 @@ interface TabBarProps {
export const TabBar = ({ className }: TabBarProps) => (
<div role="group" aria-label="Tab Bar Navigation Menu" className={className}>
<div role="presentation" className="py-[42px]" />
<div className="md:hidden fixed bottom-0 left-0 right-0 bg-black py-4 border-t border-neutral-300 dark:border-neutral-700">
<div className="md:hidden fixed bottom-0 left-0 right-0 bg-black py-4 border-t border-neutral-300 dark:border-neutral-600">
<Nav tabs className="flex justify-evenly items-center" />
</div>
</div>

View File

@ -232,7 +232,7 @@
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "129999.45",
"total_removed": "0",
"locked_amount": "106450.110805869197496885",
"locked_amount": "106394.66488946230805625",
"deposits": [
{
"amount": "129999.45",
@ -298,7 +298,7 @@
"tranche_end": "2023-09-03T00:00:00.000Z",
"total_added": "52600",
"total_removed": "0",
"locked_amount": "51264.11244926433724",
"locked_amount": "51230.43016869609472",
"deposits": [
{
"amount": "2600",
@ -682,7 +682,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "97499.58",
"total_removed": "0",
"locked_amount": "47639.844047104553224188",
"locked_amount": "47585.4567681301376248752",
"deposits": [
{
"amount": "97499.58",
@ -715,7 +715,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "135173.4239508",
"total_removed": "0",
"locked_amount": "65115.442136431506956635638672",
"locked_amount": "65041.104115645490107967157408",
"deposits": [
{
"amount": "135173.4239508",
@ -748,7 +748,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "32499.86",
"total_removed": "0",
"locked_amount": "20041.259694514865488396",
"locked_amount": "20018.379905468400079546",
"deposits": [
{
"amount": "32499.86",
@ -781,7 +781,7 @@
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "10833.29",
"total_removed": "0",
"locked_amount": "6523.235554783837261619",
"locked_amount": "6515.788405469431257442",
"deposits": [
{
"amount": "10833.29",
@ -889,7 +889,7 @@
"tranche_end": "2022-11-01T00:00:00.000Z",
"total_added": "30000",
"total_removed": "0",
"locked_amount": "8108.161609299516",
"locked_amount": "8070.053970410628",
"deposits": [
{
"amount": "7500",
@ -1006,7 +1006,7 @@
"tranche_end": "2023-06-02T00:00:00.000Z",
"total_added": "1939928.38",
"total_removed": "479504.6187210477481",
"locked_amount": "1396376.700114448863244798",
"locked_amount": "1395134.471749858441357522",
"deposits": [
{
"amount": "1852091.69",
@ -1292,7 +1292,7 @@
"tranche_end": "2023-02-01T00:00:00.000Z",
"total_added": "42500",
"total_removed": "0",
"locked_amount": "32736.562279840981",
"locked_amount": "32682.576458081723",
"deposits": [
{
"amount": "12500",
@ -2159,7 +2159,7 @@
"tranche_end": "2022-09-30T00:00:00.000Z",
"total_added": "60916.66666633337",
"total_removed": "20696.25757434884556896",
"locked_amount": "2769.374423754235979646149893795",
"locked_amount": "2732.8670885613374625452081355872",
"deposits": [
{
"amount": "2833.333333",
@ -5893,7 +5893,7 @@
"tranche_start": "2021-09-03T00:00:00.000Z",
"tranche_end": "2022-09-03T00:00:00.000Z",
"total_added": "35958.000000000000000003",
"total_removed": "16846.07240291284",
"total_removed": "17098.49537348884",
"locked_amount": "0",
"deposits": [
{
@ -11868,6 +11868,11 @@
"user": "0x9a563fbC59C9058414f89172DA667B2b337215B1",
"tx": "0xb25834209752fdf0186cc3d71002fb315cf8dc16f70aad0efe6185d5d6f400b7"
},
{
"amount": "252.422970576",
"user": "0x95175E9AEF72e1c5cEbE2766216FD6dAd2B9cDE6",
"tx": "0x427c4a75b78bd0988ab9f5f0d65ce4af60f2b1f67a38f7f01ae6306f64ae7498"
},
{
"amount": "13.82033422112",
"user": "0xb1169C6daAc76bAcaf0D8f87641Fc38fbabe569F",
@ -22273,6 +22278,12 @@
}
],
"withdrawals": [
{
"amount": "252.422970576",
"user": "0x95175E9AEF72e1c5cEbE2766216FD6dAd2B9cDE6",
"tranche_id": 11,
"tx": "0x427c4a75b78bd0988ab9f5f0d65ce4af60f2b1f67a38f7f01ae6306f64ae7498"
},
{
"amount": "100.94326484",
"user": "0x95175E9AEF72e1c5cEbE2766216FD6dAd2B9cDE6",
@ -22287,8 +22298,8 @@
}
],
"total_tokens": "400",
"withdrawn_tokens": "147.577029424",
"remaining_tokens": "252.422970576"
"withdrawn_tokens": "400",
"remaining_tokens": "0"
},
{
"address": "0xc5467213593778E528f0eB8117cc7AFBC5b7491b",
@ -22444,7 +22455,7 @@
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "3732368.4671",
"total_removed": "204390.7646836173642",
"locked_amount": "2170246.1460744605062244632",
"locked_amount": "2168337.2735760661538675426",
"deposits": [
{
"amount": "1998.95815",
@ -23311,8 +23322,8 @@
"tranche_start": "2022-06-05T00:00:00.000Z",
"tranche_end": "2023-12-05T00:00:00.000Z",
"total_added": "15870102.715470999700000001",
"total_removed": "202823.4656688805072444",
"locked_amount": "12995241.0765000433416042690892396805663693",
"total_removed": "203050.3452740934272444",
"locked_amount": "12988472.337182063502716333679636461712625",
"deposits": [
{
"amount": "16249.93",
@ -23836,6 +23847,11 @@
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0xb4d350dd5fcd3f1617fb1eaac7f77fd973f0275bcc35003934ccc9a4e6140cdb"
},
{
"amount": "226.87960521292",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tx": "0xe0040011ab92c3d951d3449fa6159e095b1893639c47fdb1a72aa87c741bdf56"
},
{
"amount": "305.8599694076328",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@ -24413,6 +24429,12 @@
"tranche_id": 2,
"tx": "0xb4d350dd5fcd3f1617fb1eaac7f77fd973f0275bcc35003934ccc9a4e6140cdb"
},
{
"amount": "226.87960521292",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
"tranche_id": 2,
"tx": "0xe0040011ab92c3d951d3449fa6159e095b1893639c47fdb1a72aa87c741bdf56"
},
{
"amount": "305.8599694076328",
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
@ -24871,8 +24893,8 @@
}
],
"total_tokens": "259998.8875",
"withdrawn_tokens": "46908.720189544202",
"remaining_tokens": "213090.167310455798"
"withdrawn_tokens": "47135.599794757122",
"remaining_tokens": "212863.287705242878"
},
{
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
@ -26417,8 +26439,8 @@
"tranche_start": "2021-11-05T00:00:00.000Z",
"tranche_end": "2023-05-05T00:00:00.000Z",
"total_added": "14597706.0446472999",
"total_removed": "2764369.825392547157261647",
"locked_amount": "6275678.36013684215460172103184858",
"total_removed": "2764683.361107610704396897",
"locked_amount": "6269429.503217293486664487151997355",
"deposits": [
{
"amount": "129284.449",
@ -26647,6 +26669,11 @@
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0x3f54acc3bba8d596eea3553509f34983148ff873565c53d993b2248a89d8c057"
},
{
"amount": "313.53571506354713525",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tx": "0x5940c1d1266c4aee837eb2a10ea1a42f52182c5fb2d9f4ca10752ec099ddc239"
},
{
"amount": "551.363354573845008",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
@ -28742,6 +28769,12 @@
"tranche_id": 3,
"tx": "0x3f54acc3bba8d596eea3553509f34983148ff873565c53d993b2248a89d8c057"
},
{
"amount": "313.53571506354713525",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
"tranche_id": 3,
"tx": "0x5940c1d1266c4aee837eb2a10ea1a42f52182c5fb2d9f4ca10752ec099ddc239"
},
{
"amount": "551.363354573845008",
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
@ -30478,8 +30511,8 @@
}
],
"total_tokens": "359123.469575",
"withdrawn_tokens": "204470.17791565298539125",
"remaining_tokens": "154653.29165934701460875"
"withdrawn_tokens": "204783.7136307165325265",
"remaining_tokens": "154339.7559442834674735"
},
{
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
@ -31566,8 +31599,8 @@
"tranche_start": "2021-10-05T00:00:00.000Z",
"tranche_end": "2023-04-05T00:00:00.000Z",
"total_added": "5778205.3912159303",
"total_removed": "1751129.686339809105860354",
"locked_amount": "2162655.071536606212862810394531095",
"total_removed": "1769795.462408277490426354",
"locked_amount": "2160186.110374920105452205502061688",
"deposits": [
{
"amount": "552496.6455",
@ -31721,6 +31754,11 @@
"user": "0x6ae83EAB68b7112BaD5AfD72d6B24546AbFF137D",
"tx": "0xb2b7e68756635897d3d0cc97221a6c9abedce9da7a431baeee6620f15125a7ae"
},
{
"amount": "18665.776068468384566",
"user": "0x5565d64f29Ea17355106DF3bA5903Eb793B3e139",
"tx": "0x0954f744fc48cdb36187ba72505a5ca1c053d05da816b41230b35d86069fdcb0"
},
{
"amount": "8456.402651116281081",
"user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90",
@ -32716,6 +32754,12 @@
}
],
"withdrawals": [
{
"amount": "18665.776068468384566",
"user": "0x5565d64f29Ea17355106DF3bA5903Eb793B3e139",
"tranche_id": 4,
"tx": "0x0954f744fc48cdb36187ba72505a5ca1c053d05da816b41230b35d86069fdcb0"
},
{
"amount": "8992.6333376158479344",
"user": "0x5565d64f29Ea17355106DF3bA5903Eb793B3e139",
@ -32724,8 +32768,8 @@
}
],
"total_tokens": "44199.81164",
"withdrawn_tokens": "8992.6333376158479344",
"remaining_tokens": "35207.1783023841520656"
"withdrawn_tokens": "27658.4094060842325004",
"remaining_tokens": "16541.4022339157674996"
},
{
"address": "0xF5Fb27b912D987B5b6e02A1B1BE0C1F0740E2c6f",
@ -32998,7 +33042,7 @@
"tranche_end": "2023-06-05T00:00:00.000Z",
"total_added": "472355.6199999996",
"total_removed": "3216.01601557326",
"locked_amount": "343887.9075013550365840576763064",
"locked_amount": "343585.43574240396939067269203448",
"deposits": [
{
"amount": "3000",

View File

@ -89,7 +89,7 @@
"tranche_end": "2022-10-12T00:53:20.000Z",
"total_added": "1010.000000000000000001",
"total_removed": "668.4622323651",
"locked_amount": "82.36947773972606420008155393835616442",
"locked_amount": "81.72253456367329370008091340055809237",
"deposits": [
{
"amount": "1000",

View File

@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_ENV=TESTNET
NX_VEGA_ENV=CUSTOM
NX_ETHEREUM_PROVIDER_URL=http://localhost:8545
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
NX_FAIRGROUND=false

View File

@ -4,17 +4,15 @@ import { mockTradingPage } from '../support/trading';
describe('home', () => {
const selectMarketOverlay = 'select-market-list';
beforeEach('load homepage', () => {
beforeEach(() => {
cy.mockGQL((req) => {
mockTradingPage(req, MarketState.STATE_ACTIVE);
});
cy.visit('/');
});
describe('default market found', () => {
it('redirects to a default market with the landing dialog open', () => {
cy.mockGQL((req) => {
// Mock all market page queries
mockTradingPage(req, MarketState.STATE_ACTIVE);
});
cy.visit('/');
cy.wait('@Market');

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,11 +1,8 @@
import { Vega } from '../icons/vega';
export const Footer = () => {
return (
<footer className="px-4 py-2 text-xs border-t border-neutral-300 dark:border-neutral-700">
<footer className="px-4 py-2 text-xs border-t border-neutral-300 dark:border-neutral-600 bg-neutral-100 dark:bg-neutral-800">
<div className="flex justify-between">
<div>Status</div>
<Vega className="w-13" />
</div>
</footer>
);

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';
@ -9,11 +10,9 @@ interface TradeMarketHeaderProps {
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">
<header className="w-screen xl:px-4 pt-4 border-b border-neutral-300 dark:border-neutral-600">
<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,20 +32,24 @@ 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';
'min-w-min w-[120px] whitespace-nowrap pb-3 px-4 border-l border-neutral-300 dark:border-neutral-600';
const itemHeading = 'text-neutral-400';
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

@ -1,7 +1,7 @@
import classNames from 'classnames';
export function Vega({ className }: { className?: string }) {
const svgClasses = classNames(className, 'fill-current');
const svgClasses = classNames(className, 'fill-white');
return (
<svg
width="86"

View File

@ -5,7 +5,8 @@ import { NetworkSwitcher } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/react-helpers';
import { useGlobalStore } from '../../stores/global';
import { VegaWalletConnectButton } from '../vega-wallet-connect-button';
import { ThemeSwitcher, VLogo } from '@vegaprotocol/ui-toolkit';
import { ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
import { Vega } from '../icons/vega';
interface NavbarProps {
theme: 'light' | 'dark';
@ -19,15 +20,15 @@ export const Navbar = ({ theme, toggleTheme }: NavbarProps) => {
}));
const tradingPath = marketId ? `/markets/${marketId}` : '/markets';
return (
<div className="px-4 flex items-stretch border-b border-neutral-300 dark:border-neutral-700 bg-black">
<div className="px-4 flex items-stretch border-b border-neutral-300 dark:border-neutral-400 bg-black">
<div className="flex gap-4 mr-4 items-center h-full">
<Link href="/" passHref={true}>
{/* eslint-disable-next-line jsx-a11y/anchor-is-valid */}
<a>
<VLogo className="w-6 h-6 fill-white" />
<Vega className="w-13" />
</a>
</Link>
<NetworkSwitcher />
<NetworkSwitcher fixedBg="dark" />
</div>
<nav className="flex items-center">
{[
@ -69,7 +70,7 @@ const NavLink = ({ name, path, exact, testId = name }: NavLinkProps) => {
router.asPath === path || (!exact && router.asPath.startsWith(path));
const linkClasses = classNames('mx-2 py-2 self-end border-b-4', {
'border-vega-yellow text-white cursor-default': isActive,
'border-transparent text-neutral-400': !isActive,
'border-transparent text-neutral-400 hover:text-neutral-300': !isActive,
});
return (
<Link data-testid={testId} href={path} passHref={true}>

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

@ -30,7 +30,7 @@ export const VegaWalletConnectButton = ({
return (
<DropdownMenu open={dropdownOpen}>
<DropdownMenuTrigger
className="text-white"
className="text-white hover:!bg-neutral-700"
data-testid="manage-vega-wallet"
onClick={() => setDropdownOpen((curr) => !curr)}
>

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)
@ -134,13 +127,14 @@ export const TradeMarketHeader = ({ market }: TradeMarketHeaderProps) => {
market.tradableInstrument.instrument.product?.settlementAsset?.symbol;
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';
'min-w-min w-[120px] whitespace-nowrap pb-3 px-4 border-l border-neutral-300 dark:border-neutral-600';
const itemHeading = 'text-neutral-500 dark: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">
<header className="w-screen px-4 border-b border-neutral-300 dark:border-neutral-600">
<div className="xl:flex xl:gap-4 items-start">
<div className="px-4 mb-2 xl:mb-0">
<div>
<SelectMarketPopover
marketName={market.tradableInstrument.instrument.name}
onSelect={onSelect}
@ -148,7 +142,7 @@ export const TradeMarketHeader = ({ market }: TradeMarketHeaderProps) => {
</div>
<div
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 mt-3 xl:flex-1 w-full overflow-x-auto text-xs "
>
<div className={itemClass}>
<div className={itemHeading}>{t('Expiry')}</div>
@ -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}>
@ -269,7 +273,7 @@ export const TradeGrid = ({ market }: TradeGridProps) => {
</ResizableGridPanel>
<ResizableGridPanel
priority={LayoutPriority.Low}
preferredSize="25%"
preferredSize={330}
minSize={300}
>
<TradeGridChild>
@ -278,14 +282,20 @@ 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>
</ResizableGridPanel>
<ResizableGridPanel
priority={LayoutPriority.Low}
preferredSize="25%"
preferredSize={430}
minSize={200}
>
<TradeGridChild>
@ -303,7 +313,7 @@ export const TradeGrid = ({ market }: TradeGridProps) => {
</ResizableGridPanel>
<ResizableGridPanel
priority={LayoutPriority.Low}
preferredSize="33%"
preferredSize="25%"
minSize={50}
>
<TradeGridChild>
@ -337,7 +347,10 @@ const TradeGridChild = ({ children }: TradeGridChildProps) => {
<section className="h-full">
<AutoSizer>
{({ width, height }) => (
<div style={{ width, height }} className="overflow-auto">
<div
style={{ width, height }}
className="overflow-auto border-[1px] dark:border-neutral-600"
>
{children}
</div>
)}
@ -348,9 +361,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,20 +375,30 @@ 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>
<div className="flex flex-nowrap overflow-x-auto max-w-full border-t border-neutral-300 dark:border-neutral-700">
<div className="flex flex-nowrap overflow-x-auto max-w-full border-t border-neutral-300 dark:border-neutral-600">
{Object.keys(TradingViews).map((key) => {
const isActive = view === key;
const className = classNames('p-4 min-w-[100px] capitalize', {

View File

@ -16,5 +16,5 @@ html {
html.dark {
--focus-border: theme('colors.vega.yellow');
--separator-border: theme('colors.neutral.700');
--separator-border: theme('colors.neutral.600');
}

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('hover:!bg-neutral-700', {
'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}

View File

@ -27,7 +27,7 @@ interface OrderbookProps extends OrderbookData {
const HorizontalLine = ({ top, testId }: { top: string; testId: string }) => (
<div
className="absolute border-b border-neutral-300 dark:border-neutral-700 inset-x-0"
className="absolute border-b border-neutral-300 dark:border-neutral-600 inset-x-0"
style={{ top }}
data-testid={testId}
/>
@ -309,7 +309,7 @@ export const Orderbook = ({
</div>
) : null;
const c = theme === 'dark' ? colors.neutral[700] : colors.neutral[300];
const c = theme === 'dark' ? colors.neutral[600] : colors.neutral[300];
const gradientStyles = `linear-gradient(${c},${c}) 24.6% 0/1px 100% no-repeat, linear-gradient(${c},${c}) 50% 0/1px 100% no-repeat, linear-gradient(${c},${c}) 75.2% 0/1px 100% no-repeat`;
return (
@ -320,7 +320,7 @@ export const Orderbook = ({
data-testid="scroll"
>
<div
className="sticky top-0 grid grid-cols-4 gap-2 text-right border-b pt-2 bg-white dark:bg-black z-10 border-neutral-300 dark:border-neutral-700"
className="sticky top-0 grid grid-cols-4 gap-2 text-right border-b pt-2 bg-white dark:bg-black z-10 border-neutral-300 dark:border-neutral-600"
style={{ gridAutoRows: '17px' }}
>
<div>{t('Bid vol')}</div>
@ -344,7 +344,7 @@ export const Orderbook = ({
)}
</div>
<div
className="sticky bottom-0 grid grid-cols-4 gap-2 border-t-[1px] border-neutral-300 dark:border-neutral-700 mt-2 z-10 bg-white dark:bg-black"
className="sticky bottom-0 grid grid-cols-4 gap-2 border-t-[1px] border-neutral-300 dark:border-neutral-600 mt-2 z-10 bg-white dark:bg-black"
style={{ gridAutoRows: '17px' }}
>
<div className="col-start-2">

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,28 +312,26 @@ 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>
),
},
];
return (
<div className="p-4">
<div className="mb-4">
<div className="mb-8">
<p className={headerClassName}>{t('Market data')}</p>
<Accordion panels={marketDataPanels} />
</div>

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

@ -24,7 +24,7 @@ import type {
} from '../__generated__/MarketList';
import isNil from 'lodash/isNil';
export const cellClassNames = 'px-2 py-1 first:text-left text-right capitalize';
export const cellClassNames = 'px-0 py-1 first:text-left text-right';
const FeesInfo = () => {
return (
@ -81,12 +81,12 @@ export const columnHeadersPositionMarkets: Column[] = [
onlyOnDetailed: false,
},
{
value: t('24h High'),
value: t('24h high'),
className: `${cellClassNames} hidden xl:table-cell`,
onlyOnDetailed: true,
},
{
value: t('24h Low'),
value: t('24h low'),
className: `${cellClassNames} hidden xl:table-cell`,
onlyOnDetailed: true,
},
@ -139,12 +139,12 @@ export const columnHeaders: Column[] = [
onlyOnDetailed: false,
},
{
value: t('24h High'),
value: t('24h high'),
className: `${cellClassNames} hidden xl:table-cell`,
onlyOnDetailed: true,
},
{
value: t('24h Low'),
value: t('24h low'),
className: `${cellClassNames} hidden xl:table-cell`,
onlyOnDetailed: true,
},
@ -264,7 +264,7 @@ export const columns = (
) : (
'-'
),
className: `${cellClassNames} hidden xl:table-cell`,
className: `${cellClassNames} hidden xl:table-cell font-mono`,
onlyOnDetailed: true,
},
{
@ -280,7 +280,7 @@ export const columns = (
) : (
'-'
),
className: `${cellClassNames} hidden xl:table-cell`,
className: `${cellClassNames} hidden xl:table-cell font-mono`,
onlyOnDetailed: true,
},
{
@ -304,13 +304,13 @@ export const columns = (
market.positionDecimalPlaces
)
: '-',
className: `${cellClassNames} hidden lg:table-cell`,
className: `${cellClassNames} hidden lg:table-cell font-mono`,
onlyOnDetailed: true,
dataTestId: 'market-volume',
},
{
value: <FeesCell feeFactors={market.fees.factors} />,
className: `${cellClassNames} hidden xl:table-cell`,
className: `${cellClassNames} hidden xl:table-cell font-mono`,
onlyOnDetailed: true,
dataTestId: 'taker-fee',
},
@ -417,7 +417,7 @@ export const columnsPositionMarkets = (
) : (
'-'
),
className: `${cellClassNames} hidden xl:table-cell`,
className: `${cellClassNames} hidden xl:table-cell font-mono`,
onlyOnDetailed: true,
},
{
@ -433,7 +433,7 @@ export const columnsPositionMarkets = (
) : (
'-'
),
className: `${cellClassNames} hidden xl:table-cell`,
className: `${cellClassNames} hidden xl:table-cell font-mono`,
onlyOnDetailed: true,
},
{
@ -457,12 +457,12 @@ export const columnsPositionMarkets = (
market.positionDecimalPlaces
)
: '-',
className: `${cellClassNames} hidden lg:table-cell`,
className: `${cellClassNames} hidden lg:table-cell font-mono`,
onlyOnDetailed: true,
},
{
value: <FeesCell feeFactors={market.fees.factors} />,
className: `${cellClassNames} hidden xl:table-cell`,
className: `${cellClassNames} hidden xl:table-cell font-mono`,
onlyOnDetailed: true,
},
{
@ -470,16 +470,16 @@ export const columnsPositionMarkets = (
<p
className={
market.openVolume.includes('+')
? 'text-vega-green'
? 'text-vega-green-dark dark:text-vega-green'
: market.openVolume.includes('-')
? 'text-vega-red'
? 'text-vega-red-dark dark:text-vega-red'
: ''
}
>
{market.openVolume}
</p>
),
className: `${cellClassNames} hidden xxl:table-cell`,
className: `${cellClassNames} hidden xxl:table-cell font-mono`,
onlyOnDetailed: true,
},
];
@ -504,23 +504,23 @@ export const FeesBreakdown = ({
if (!feeFactors) return null;
return (
<dl className="grid grid-cols-2 gap-x-2">
<dt>{t('Infrastructure Fee')}</dt>
<dt>{t('Infrastructure fee')}</dt>
<dd className="text-right">
{formatNumberPercentage(
new BigNumber(feeFactors.infrastructureFee).times(100)
)}
</dd>
<dt>{t('Liquidity Fee')}</dt>
<dt>{t('Liquidity fee')}</dt>
<dd className="text-right">
{formatNumberPercentage(
new BigNumber(feeFactors.liquidityFee).times(100)
)}
</dd>
<dt>{t('Maker Fee')}</dt>
<dt>{t('Maker fee')}</dt>
<dd className="text-right">
{formatNumberPercentage(new BigNumber(feeFactors.makerFee).times(100))}
</dd>
<dt>{t('Total Fees')}</dt>
<dt>{t('Total fees')}</dt>
<dd className="text-right">{totalFees(feeFactors)}</dd>
</dl>
);

View File

@ -7,7 +7,7 @@ export const SelectMarketTableHeader = ({
headers = columnHeaders,
}) => {
return (
<tr className="sticky top-0 z-10 border-b border-neutral-300 dark:border-neutral-700 bg-inherit">
<tr className="sticky top-0 z-10 border-b border-neutral-300 dark:border-neutral-600 bg-inherit">
{headers.map(({ value, className, onlyOnDetailed }, i) => {
const thClass = classNames(
'font-normal text-neutral-500 dark:text-neutral-400',
@ -37,7 +37,7 @@ export const SelectMarketTableRow = ({
}) => {
return (
<tr
className={`hover:bg-black/10 dark:hover:bg-white/20 cursor-pointer relative h-[34px]`}
className={`hover:bg-neutral-200 dark:hover:bg-neutral-700 cursor-pointer relative h-[34px]`}
>
{columns.map(({ value, className, dataTestId, onlyOnDetailed }, i) => {
if (!onlyOnDetailed || detailed === onlyOnDetailed) {

View File

@ -76,7 +76,7 @@ export const SelectAllMarketsTableBody = ({
if (!data) return null;
return (
<>
<thead className="bg-neutral-200 dark:bg-neutral-800">
<thead className="bg-neutral-50 dark:bg-neutral-800">
<SelectMarketTableHeader detailed={true} headers={headers} />
</thead>
{/* Border styles required to create space between tbody elements margin/padding dont work */}
@ -100,7 +100,8 @@ export const SelectMarketPopover = ({
marketName: string;
onSelect: (id: string) => void;
}) => {
const triggerClasses = 'flex items-center gap-4 whitespace-nowrap';
const triggerClasses =
'sm:text-lg md:text-xl lg:text-2xl font-medium flex items-center gap-4 whitespace-nowrap my-3 hover:text-neutral-500 dark:hover:text-neutral-300';
const { keypair } = useVegaWallet();
const [open, setOpen] = useState(false);
const { data, loading: marketsLoading } = useMarketList();
@ -149,7 +150,7 @@ export const SelectMarketPopover = ({
trigger={
<span className={triggerClasses}>
{marketName}
<Icon name="chevron-down" className={iconClass} />
<Icon name="chevron-down" className={iconClass} size={6} />
</span>
}
>
@ -167,7 +168,7 @@ export const SelectMarketPopover = ({
{keypair &&
positionMarkets?.markets &&
positionMarkets.markets.length > 0 && (
<table className="relative text-sm w-full whitespace-nowrap -mx-2">
<table className="relative text-sm w-full whitespace-nowrap">
<TableTitle>{t('My markets')}</TableTitle>
<SelectAllMarketsTableBody
data={positionMarkets.markets}
@ -179,7 +180,7 @@ export const SelectMarketPopover = ({
/>
</table>
)}
<table className="relative text-sm w-full whitespace-nowrap -mx-2">
<table className="relative text-sm w-full whitespace-nowrap">
<TableTitle>{t('All markets')}</TableTitle>
<SelectAllMarketsTableBody
data={data}
@ -197,7 +198,7 @@ const TableTitle = ({ children }: { children: ReactNode }) => {
return (
<thead>
<tr>
<th className="font-normal px-2 text-left">
<th className="font-normal text-left">
<h3 className="text-lg">{children}</h3>
</th>
</tr>

View File

@ -78,7 +78,7 @@ export const OrderEditDialog = ({
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 py-12">
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 py-4">
<form onSubmit={handleSubmit(onSubmit)} data-testid="edit-order">
<FormGroup label={t('Entry price')} labelFor="entryPrice">
<Input

View File

@ -289,7 +289,7 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
onClick={() => {
setEditOrder(data);
}}
size="sm"
size="xs"
>
{t('Edit')}
</Button>
@ -306,7 +306,7 @@ export const OrderListTable = forwardRef<AgGridReact, OrderListTableProps>(
if (isOrderActive(data.status)) {
return (
<Button
size="sm"
size="xs"
data-testid="cancel"
onClick={() => cancel(data)}
>

View File

@ -47,7 +47,7 @@ it('Render correct columns', async () => {
headers.map((h) => h.querySelector('[ref="eText"]')?.textContent?.trim())
).toEqual([
'Market',
'Amount',
'Size',
'Mark price',
'Entry price',
'Leverage',

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;
@ -133,7 +133,7 @@ const ButtonCell = ({
<Button
data-testid="close-position"
onClick={() => onClick(data)}
size="sm"
size="xs"
>
{t('Close')}
</Button>
@ -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}
@ -179,7 +181,7 @@ export const PositionsTable = forwardRef<AgGridReact, Props>(
}}
/>
<AgGridColumn
headerName={t('Amount')}
headerName={t('Size')}
field="openVolume"
valueGetter={({ node, data }: ValueGetterParams) => {
return node?.rowPinned ? data?.notional : data?.openVolume;

View File

@ -82,16 +82,16 @@ export const Positions = memo(
};
return (
<AsyncRenderer loading={loading} error={error} data={data}>
<div className="p-2">
<h4 className="text-lg">
<div className="flex justify-between items-center p-3 pb-1">
<h4 className="text-m">
{assetSymbol} {t('markets')}
</h4>
<p>
<div className="text-sm text-neutral-500 dark:text-neutral-300">
{assetSymbol} {t('balance')}:
<span data-testid="balance" className="pl-1 font-mono">
<AssetBalance partyId={partyId} assetSymbol={assetSymbol} />
</span>
</p>
</div>
</div>
<PositionsTable
domLayout="autoHeight"

View File

@ -26,7 +26,7 @@ export const PriceCell = React.memo(
{valueSplit[0]}
{valueSplit[1] ? decimalSeparator : null}
{valueSplit[1] ? (
<span className="opacity-50">{valueSplit[1]}</span>
<span className="opacity-60">{valueSplit[1]}</span>
) : null}
</span>
);

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

@ -13,8 +13,8 @@ import type { AgGridReactProps, AgReactUiProps } from 'ag-grid-react';
import type { Trades_market_tradesConnection_edges_node } from './__generated__/Trades';
import BigNumber from 'bignumber.js';
export const UP_CLASS = 'text-vega-green';
export const DOWN_CLASS = 'text-vega-red';
export const UP_CLASS = 'text-vega-green-dark dark:text-vega-green';
export const DOWN_CLASS = 'text-vega-red-dark dark:text-vega-red';
const changeCellClass =
(dataKey: string) =>

View File

@ -8,8 +8,9 @@ const agGridDarkVariables = `
--ag-border-color: ${colors.neutral[700]};
--ag-header-background-color: ${colors.black};
--ag-odd-row-background-color: ${colors.black};
--ag-header-column-separator-color: ${colors.neutral[600]};
--ag-row-border-color:${colors.black};
--ag-row-hover-color: ${colors.neutral[700]};
--ag-row-hover-color: ${colors.neutral[800]};
--ag-font-size: 12px;
}
@ -21,10 +22,6 @@ const agGridDarkVariables = `
overflow: hidden;
text-overflow: ellipsis;
}
.ag-theme-balham-dark .ag-header-row {
font-weight: 400;
}
`;
export const AgGrid = ({

View File

@ -8,8 +8,9 @@ const agGridLightVariables = `
--ag-border-color: ${colors.neutral[300]};
--ag-header-background-color: ${colors.white};
--ag-odd-row-background-color: ${colors.white};
--ag-header-column-separator-color: ${colors.neutral[300]};
--ag-row-border-color: ${colors.white};
--ag-row-hover-color: ${colors.neutral[300]};
--ag-row-hover-color: ${colors.neutral[100]};
--ag-font-size: 12px;
}
@ -21,10 +22,6 @@ const agGridLightVariables = `
overflow: hidden;
text-overflow: ellipsis;
}
.ag-theme-balham-dark .ag-header-row {
font-weight: 400;
}
`;
export const AgGrid = ({

View File

@ -9,10 +9,10 @@ import { Icon } from '../icon';
import classnames from 'classnames';
type ButtonVariant = 'default' | 'primary' | 'secondary';
type ButtonSize = 'lg' | 'md' | 'sm';
type ButtonSize = 'lg' | 'md' | 'sm' | 'xs';
const base =
'inline-block uppercase border rounded-md disabled:opacity-40 transition-colors';
const base = 'inline-block uppercase border rounded-md disabled:opacity-60';
const xs = 'px-2 py-0 text-sm';
const sm = 'px-2 py-1 text-sm';
const md = 'px-10 py-2 text-base';
const lg = 'px-14 py-4';
@ -21,8 +21,8 @@ const defaultClasses = [
'text-black dark:text-white',
'border-black dark:border-white',
'bg-white dark:bg-black',
'enabled:hover:bg-neutral-200 dark:enabled:hover:bg-neutral-800',
'enabled:active:bg-neutral-200 dark:enabled:active:bg-neutral-500',
'enabled:hover:bg-neutral-200 dark:enabled:hover:bg-neutral-700',
'enabled:active:bg-neutral-200 dark:enabled:active:bg-neutral-700 enabled:active:border-neutral-400 dark:enabled:active:border-neutral-400',
];
const primary = [
'text-black',
@ -54,9 +54,11 @@ const getClassname = ({
[defaultClasses.join(' ')]: variant === 'default',
[primary.join(' ')]: variant === 'primary',
[secondary.join(' ')]: variant === 'secondary',
[lg]: size === 'lg',
[md]: size === 'md',
[sm]: size === 'sm',
[xs]: size === 'xs',
[fillClasses]: fill,
});
};

View File

@ -70,7 +70,7 @@ export function Dialog({
</DialogPrimitives.Close>
)}
<div className="flex gap-4 max-w-full">
{icon && <div className="pt-2 fill-current">{icon}</div>}
{icon && <div className="fill-current">{icon}</div>}
<div data-testid="dialog-content" className="flex-1">
{title && (
<h1

View File

@ -26,9 +26,10 @@ export const DropdownMenuTrigger = forwardRef<
React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>
>(({ className, children, ...props }, forwardedRef) => {
const triggerClasses = classNames(
className,
'text-sm py-1 px-2 rounded bg-transparent border border-neutral-500',
'focus:border-black dark:focus:border-white whitespace-nowrap',
className
'hover:bg-neutral-100 dark:hover:bg-neutral-700'
);
return (
<DropdownMenuPrimitive.Trigger

View File

@ -14,7 +14,7 @@ export const InputError = ({
...props
}: InputErrorProps) => {
const effectiveClassName = classNames(
'text-sm text-vega-pink flex items-center',
'text-sm text-vega-red flex items-center',
'mt-2',
{
'border-danger': intent === 'danger',

View File

@ -72,9 +72,9 @@ export const KeyValueTableRow = ({
{ 'flex-row items-center': inline },
className
);
const dtClassNames = `break-words capitalize ${dtClassName}`;
const dtClassNames = `break-words ${dtClassName}`;
const ddClassNames = classNames(
'break-words text-neutral-500',
'break-words text-neutral-500 dark:text-neutral-300',
{
'font-mono': numerical,
},

View File

@ -23,11 +23,11 @@ export const Popover = ({
<PopoverPrimitive.Content
data-testid="popover-content"
align="start"
className="p-4 rounded bg-neutral-200 dark:bg-neutral-800 dark:text-neutral-200"
className="p-4 rounded bg-neutral-50 dark:bg-neutral-800 dark:text-neutral-200 border border-neutral-400"
sideOffset={10}
>
<PopoverPrimitive.Close
className="px-4 py-2 absolute top-0 right-0"
className="px-4 py-2 absolute top-0 right-0 z-20"
data-testid="dialog-close"
>
<Icon name="cross" />

View File

@ -19,7 +19,7 @@ export const Tabs = ({ children, active: activeDefaultId }: TabsProps) => {
className="h-full grid grid-rows-[min-content_1fr]"
onValueChange={(value) => setActiveTab(value)}
>
<div className="border-b border-neutral-300 dark:border-neutral-700">
<div className="border-b border-neutral-300 dark:border-neutral-600">
<TabsPrimitive.List
className="flex flex-nowrap overflow-visible"
role="tablist"
@ -28,9 +28,13 @@ export const Tabs = ({ children, active: activeDefaultId }: TabsProps) => {
if (!isValidElement(child) || child.props.hidden) return null;
const isActive = child.props.id === activeTab;
const triggerClass = classNames(
'relative px-4 py-2 border-r border-neutral-300 dark:border-neutral-700',
'text-black dark:text-white',
'uppercase'
'relative px-4 py-2 border-r border-neutral-300 dark:border-neutral-600',
'uppercase',
'inline-block after:content-[attr(data-testid)] after:block after:invisible after:overflow-hidden after:h-0 after:tracking-wider',
{
'text-neutral-400 dark:text-neutral-400 hover:text-neutral-500 dark:hover:text-neutral-300':
!isActive,
}
);
const borderClass = classNames(
'absolute bottom-[-1px] left-0 w-full h-0 border-b',

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

@ -9,7 +9,7 @@ export const defaultFormElement = (hasError?: boolean) =>
'p-2 border-2 rounded-none',
'bg-transparent',
'border border-neutral-500 focus:border-black dark:focus:border-white',
'disabled:opacity-40',
'disabled:opacity-60',
{
'border-vega-pink': hasError,
}

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",