Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into develop
This commit is contained in:
commit
92077f4a5a
@ -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>
|
||||
|
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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');
|
||||
|
||||
|
@ -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')
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { MarketInfoQuery } from '@vegaprotocol/deal-ticket';
|
||||
import type { MarketInfoQuery } from '@vegaprotocol/market-info';
|
||||
import {
|
||||
AccountType,
|
||||
AuctionTrigger,
|
||||
|
@ -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',
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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"
|
||||
|
@ -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}>
|
||||
|
@ -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)} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -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)}
|
||||
>
|
||||
|
@ -22,6 +22,7 @@ export function Index() {
|
||||
|
||||
if (marketId) {
|
||||
replace(`/markets/${marketId}`);
|
||||
update({ marketId });
|
||||
}
|
||||
// Fallback to the markets list page
|
||||
else {
|
||||
|
@ -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>
|
||||
|
@ -41,6 +41,7 @@ query Market($marketId: ID!, $interval: Interval!, $since: String!) {
|
||||
id
|
||||
symbol
|
||||
name
|
||||
decimals
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
@ -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 )
|
||||
|
@ -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', {
|
||||
|
@ -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');
|
||||
}
|
||||
|
@ -1,2 +1 @@
|
||||
export * from './deal-ticket';
|
||||
export * from './market-info';
|
||||
|
@ -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">
|
||||
|
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)
|
||||
*/
|
||||
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 )
|
||||
|
@ -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,
|
||||
|
@ -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 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}
|
||||
/>
|
||||
<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}
|
||||
|
@ -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
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 './info-key-value-table';
|
||||
export * from './info-market-query';
|
||||
export * from './info-market';
|
||||
export * from './tooltip-mapping';
|
@ -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>
|
||||
</>
|
||||
);
|
||||
};
|
@ -39,11 +39,6 @@ export const MARKET_INFO_QUERY = gql`
|
||||
}
|
||||
}
|
||||
}
|
||||
riskFactors {
|
||||
market
|
||||
short
|
||||
long
|
||||
}
|
||||
data {
|
||||
market {
|
||||
id
|
@ -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>
|
@ -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.'),
|
||||
};
|
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"
|
||||
]
|
||||
}
|
@ -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>
|
||||
);
|
||||
|
@ -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) {
|
||||
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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)}
|
||||
>
|
||||
|
@ -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',
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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 ? '-' : ''}
|
||||
|
@ -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) =>
|
||||
|
@ -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 = ({
|
||||
|
@ -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 = ({
|
||||
|
@ -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,
|
||||
});
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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',
|
||||
|
@ -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,
|
||||
},
|
||||
|
@ -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" />
|
||||
|
@ -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',
|
||||
|
@ -1 +1 @@
|
||||
export { Tooltip } from './tooltip';
|
||||
export * from './tooltip';
|
||||
|
@ -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>
|
||||
);
|
||||
};
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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"],
|
||||
|
@ -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",
|
||||
|
Loading…
Reference in New Issue
Block a user