From 9e5bc9c8d1cc335e795987579182be524085aae0 Mon Sep 17 00:00:00 2001 From: Maciek Date: Mon, 4 Sep 2023 09:46:02 +0200 Subject: [PATCH 01/14] chore(trading): handle negative decimals (#4659) --- .../deal-ticket/deal-ticket.spec.tsx | 33 +++++++++++++++++-- libs/fills/src/lib/fills-table.spec.tsx | 22 ++++++++++++- .../components/order-list/order-list.spec.tsx | 20 ++++++++++- .../src/lib/positions-table.spec.tsx | 13 ++++++++ libs/utils/src/lib/format/number.spec.ts | 28 ++++++++++++++++ libs/utils/src/lib/format/number.ts | 8 +++-- .../utils/src/lib/validate/validate-amount.ts | 6 ++++ 7 files changed, 122 insertions(+), 8 deletions(-) diff --git a/libs/deal-ticket/src/components/deal-ticket/deal-ticket.spec.tsx b/libs/deal-ticket/src/components/deal-ticket/deal-ticket.spec.tsx index 5008c2b59..c672e93bc 100644 --- a/libs/deal-ticket/src/components/deal-ticket/deal-ticket.spec.tsx +++ b/libs/deal-ticket/src/components/deal-ticket/deal-ticket.spec.tsx @@ -21,6 +21,8 @@ import { import * as positionsTools from '@vegaprotocol/positions'; import { OrdersDocument } from '@vegaprotocol/orders'; import { formatForInput } from '@vegaprotocol/utils'; +import type { PartialDeep } from 'type-fest'; +import type { Market } from '@vegaprotocol/markets'; jest.mock('zustand'); jest.mock('./deal-ticket-fee-details', () => ({ @@ -36,12 +38,19 @@ const market = generateMarket(); const marketData = generateMarketData(); const submit = jest.fn(); -function generateJsx(mocks: MockedResponse[] = []) { +function generateJsx( + mocks: MockedResponse[] = [], + marketOverrides: PartialDeep = {} +) { + const joinedMarket: Market = { + ...market, + ...marketOverrides, + } as Market; return ( { expect(screen.getByTestId('iceberg')).toBeDisabled(); }); - // eslint-disable-next-line jest/no-disabled-tests it('handles TIF select box dependent on order type', async () => { render(generateJsx()); @@ -533,6 +541,25 @@ describe('DealTicket', () => { expect(screen.queryByTestId(priceErrorMessage)).toBeNull(); }); + it('validates size when positionDecimalPlaces is negative', async () => { + render(generateJsx([], { positionDecimalPlaces: -4 })); + const sizeErrorMessage = 'deal-ticket-error-message-size'; + const sizeInput = 'order-size'; + await userEvent.click(screen.getByTestId('place-order')); + // default value should be invalid + expect(screen.getByTestId(sizeErrorMessage)).toBeInTheDocument(); + expect(screen.getByTestId(sizeErrorMessage)).toHaveTextContent( + 'Size cannot be lower than 10000' + ); + await userEvent.type(screen.getByTestId(sizeInput), '10001'); + expect(screen.getByTestId(sizeErrorMessage)).toHaveTextContent( + 'Size must be a multiple of 10000 for this market' + ); + await userEvent.clear(screen.getByTestId(sizeInput)); + await userEvent.type(screen.getByTestId(sizeInput), '10000'); + expect(screen.queryByTestId(sizeErrorMessage)).toBeNull(); + }); + it('validates iceberg field', async () => { const peakSizeErrorMessage = 'deal-ticket-peak-error-message'; const minimumSizeErrorMessage = 'deal-ticket-minimum-error-message'; diff --git a/libs/fills/src/lib/fills-table.spec.tsx b/libs/fills/src/lib/fills-table.spec.tsx index b65fe4dea..f68e124ff 100644 --- a/libs/fills/src/lib/fills-table.spec.tsx +++ b/libs/fills/src/lib/fills-table.spec.tsx @@ -4,7 +4,6 @@ import { getDateTimeFormat } from '@vegaprotocol/utils'; import * as Schema from '@vegaprotocol/types'; import type { PartialDeep } from 'type-fest'; import type { Trade } from './fills-data-provider'; - import { FillsTable, getFeesBreakdown } from './fills-table'; import { generateFill } from './test-helpers'; @@ -215,6 +214,27 @@ describe('FillsTable', () => { ).toBeInTheDocument(); }); + it('negative positionDecimalPoints should be properly rendered in size column', async () => { + const partyId = 'party-id'; + const negativeDecimalPositionFill = generateFill({ + ...defaultFill, + market: { + ...defaultFill.market, + positionDecimalPlaces: -4, + }, + }); + await act(async () => { + render( + + ); + }); + + const sizeCell = screen + .getAllByRole('gridcell') + .find((c) => c.getAttribute('col-id') === 'size'); + expect(sizeCell).toHaveTextContent('3,000,000,000'); + }); + describe('getFeesBreakdown', () => { it('should return correct fees breakdown for a taker', () => { const fees = { diff --git a/libs/orders/src/lib/components/order-list/order-list.spec.tsx b/libs/orders/src/lib/components/order-list/order-list.spec.tsx index 8dde7f8a9..5cfa49863 100644 --- a/libs/orders/src/lib/components/order-list/order-list.spec.tsx +++ b/libs/orders/src/lib/components/order-list/order-list.spec.tsx @@ -6,7 +6,7 @@ import type { PartialDeep } from 'type-fest'; import type { VegaWalletContextShape } from '@vegaprotocol/wallet'; import { VegaWalletContext } from '@vegaprotocol/wallet'; import { MockedProvider } from '@apollo/client/testing'; -import type { OrderFieldsFragment, OrderListTableProps } from '../'; +import type { Order, OrderFieldsFragment, OrderListTableProps } from '../'; import { OrderListTable } from '../'; import { generateOrder, @@ -164,6 +164,24 @@ describe('OrderListTable', () => { ); }); + it('negative positionDecimalPoints should be properly rendered in size column', async () => { + const localMarketOrder = { + ...marketOrder, + size: '3000', + market: { + ...marketOrder.market, + positionDecimalPlaces: -4, + }, + } as Order; + + await act(async () => { + render(generateJsx({ rowData: [localMarketOrder] })); + }); + + const cells = screen.getAllByRole('gridcell'); + expect(cells[2]).toHaveTextContent('+30,000,000'); + }); + describe('amend cell', () => { it('allows cancelling and editing for permitted orders', async () => { const mockEdit = jest.fn(); diff --git a/libs/positions/src/lib/positions-table.spec.tsx b/libs/positions/src/lib/positions-table.spec.tsx index 79fc39b6d..7dc85c5d1 100644 --- a/libs/positions/src/lib/positions-table.spec.tsx +++ b/libs/positions/src/lib/positions-table.spec.tsx @@ -201,6 +201,19 @@ describe('Positions', () => { ).not.toBeInTheDocument(); }); + it('handle negative positionDecimalPlaces', async () => { + await renderComponent({ + ...singleRow, + openVolume: '-2000', + positionDecimalPlaces: -4, + }); + const cells = screen.getAllByRole('gridcell'); + const cell = cells[1]; + expect(within(cell).getByTestId('stack-cell-primary')).toHaveTextContent( + '-20,000,000' + ); + }); + describe('PNLCell', () => { const props = { data: undefined, diff --git a/libs/utils/src/lib/format/number.spec.ts b/libs/utils/src/lib/format/number.spec.ts index d36dfb719..119087fca 100644 --- a/libs/utils/src/lib/format/number.spec.ts +++ b/libs/utils/src/lib/format/number.spec.ts @@ -7,6 +7,8 @@ import { formatNumberPercentage, getUnlimitedThreshold, isNumeric, + removeDecimal, + toBigNum, quantumDecimalPlaces, toDecimal, toNumberParts, @@ -153,10 +155,36 @@ describe('number utils', () => { { v: 7, o: '0.0000001' }, { v: 8, o: '0.00000001' }, { v: 9, o: '0.000000001' }, + { v: -1, o: '10' }, + { v: -2, o: '100' }, + { v: -3, o: '1000' }, ])('formats with toNumber given number correctly', ({ v, o }) => { expect(toDecimal(v)).toStrictEqual(o); }); }); + + describe('positive and negative decimals should be handled correctly', () => { + const baseNum = '2000'; + const methods = [removeDecimal, toBigNum]; + it.each([ + { decimals: 0, result: ['2000', '2000'] }, + { decimals: 1, result: ['20000', '200'] }, + { decimals: -1, result: ['200', '20000'] }, + { decimals: 2, result: ['200000', '20'] }, + { decimals: -2, result: ['20', '200000'] }, + { decimals: 3, result: ['2000000', '2'] }, + { decimals: -3, result: ['2', '2000000'] }, + { decimals: 4, result: ['20000000', '0.2'] }, + { decimals: -4, result: ['0', '20000000'] }, // removeDecimal has toFixed(0) at the end + ])( + 'number methods should handle negative decimals', + ({ decimals, result }) => { + methods.forEach((method, i) => { + expect(method(baseNum, decimals).toString()).toEqual(result[i]); + }); + } + ); + }); }); describe('quantumDecimalPlaces', () => { diff --git a/libs/utils/src/lib/format/number.ts b/libs/utils/src/lib/format/number.ts index e0d035a50..bf5a93ff4 100644 --- a/libs/utils/src/lib/format/number.ts +++ b/libs/utils/src/lib/format/number.ts @@ -21,7 +21,7 @@ const MAX_FRACTION_DIGITS = 20; export function toDecimal(numberOfDecimals: number) { return new BigNumber(1) - .dividedBy(Math.pow(10, numberOfDecimals)) + .dividedBy(new BigNumber(10).exponentiatedBy(numberOfDecimals)) .toString(10); } @@ -29,7 +29,8 @@ export function toBigNum( rawValue: string | number, decimals: number ): BigNumber { - return new BigNumber(rawValue || 0).dividedBy(Math.pow(10, decimals)); + const divides = new BigNumber(10).exponentiatedBy(decimals); + return new BigNumber(rawValue || 0).dividedBy(divides); } export function addDecimal( @@ -48,7 +49,8 @@ export function removeDecimal( value: string | BigNumber, decimals: number ): string { - return new BigNumber(value || 0).times(Math.pow(10, decimals)).toFixed(0); + const times = new BigNumber(10).exponentiatedBy(decimals); + return new BigNumber(value || 0).times(times).toFixed(0); } // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat diff --git a/libs/utils/src/lib/validate/validate-amount.ts b/libs/utils/src/lib/validate/validate-amount.ts index ef45d3bba..95549ab1f 100644 --- a/libs/utils/src/lib/validate/validate-amount.ts +++ b/libs/utils/src/lib/validate/validate-amount.ts @@ -4,6 +4,12 @@ export const validateAmount = (step: number | string, field: string) => { const [, stepDecimals = ''] = String(step).split('.'); return (value?: string) => { + if (Number(step) > 1) { + if (Number(value) % Number(step) > 0) { + return t(`${field} must be a multiple of ${step} for this market`); + } + return true; + } const [, valueDecimals = ''] = (value || '').split('.'); if (stepDecimals.length < valueDecimals.length) { if (stepDecimals === '') { From 4afd4694049c2710b3c882b631b6862870d91243 Mon Sep 17 00:00:00 2001 From: Edd Date: Mon, 4 Sep 2023 10:36:13 +0100 Subject: [PATCH 02/14] chore(explorer,trading,governance): reconfigure hooks (#4655) --- .husky/commit-msg | 3 --- .husky/pre-commit | 5 +++++ .husky/pre-push | 8 ++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) create mode 100755 .husky/pre-commit create mode 100755 .husky/pre-push diff --git a/.husky/commit-msg b/.husky/commit-msg index b0dca9dee..047fa8eb6 100755 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -3,6 +3,3 @@ # Lint commit messages to ensure they follow conventional commit standards yarn commitlint --edit "${1}" - -# Lint all staged files -yarn lint-staged diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100755 index 000000000..c18cf4092 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1,5 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +# Lint all staged files +yarn lint-staged diff --git a/.husky/pre-push b/.husky/pre-push new file mode 100755 index 000000000..30b469329 --- /dev/null +++ b/.husky/pre-push @@ -0,0 +1,8 @@ +#!/bin/sh +. "$(dirname "$0")/_/husky.sh" + +# Lint all staged files +yarn nx format:check + +# Test all projects with changes +yarn nx affected -t test --exclude trading From 66f25603d3107211d5cde6a49bff59d7225c71e2 Mon Sep 17 00:00:00 2001 From: Joe Tsang <30622993+jtsang586@users.noreply.github.com> Date: Mon, 4 Sep 2023 10:41:04 +0100 Subject: [PATCH 03/14] test(explorer): add e2e test for explorer oracles (#4657) --- .../src/integration/oracles.cy.js | 68 +++++++++++++++++++ .../src/app/routes/oracles/home/index.tsx | 7 +- 2 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 apps/explorer-e2e/src/integration/oracles.cy.js diff --git a/apps/explorer-e2e/src/integration/oracles.cy.js b/apps/explorer-e2e/src/integration/oracles.cy.js new file mode 100644 index 000000000..06c4466af --- /dev/null +++ b/apps/explorer-e2e/src/integration/oracles.cy.js @@ -0,0 +1,68 @@ +context('Oracle page', { tags: '@smoke' }, () => { + describe('Verify elements on page', () => { + before('create market and navigate to oracle page', () => { + cy.createMarket(); + cy.visit('/oracles'); + }); + it('should see oracle data', () => { + cy.getByTestId('oracle-details').should('have.length.at.least', 2); + cy.getByTestId('oracle-details') + .should('exist') + .eq(0) + .within(() => { + cy.get('tr') + .eq(0) + .within(() => { + cy.get('th').should('have.text', 'ID'); + cy.get('a').invoke('text').should('have.length', 64); + cy.get('a') + .should('have.attr', 'href') + .and('contain', '/oracles/'); + }); + cy.get('tr') + .eq(1) + .within(() => { + cy.get('th').should('have.text', 'Type'); + cy.get('td').should('have.text', 'External data'); + }); + cy.get('tr') + .eq(2) + .within(() => { + cy.get('th').should('have.text', 'Signer'); + cy.getByTestId('keytype').should('have.text', 'Vega'); + cy.get('a').invoke('text').should('have.length', 64); + cy.get('a') + .should('have.attr', 'href') + .and('contain', '/parties/'); + }); + cy.get('tr') + .eq(3) + .within(() => { + cy.get('th').should('have.text', 'Settlement for'); + cy.get('a').invoke('text').should('have.length', 64); + cy.get('a') + .should('have.attr', 'href') + .and('contain', '/markets/'); + }); + cy.get('tr') + .eq(4) + .within(() => { + cy.get('th').should('have.text', 'Matched data'); + cy.get('td').should('have.text', '❌'); + }); + cy.get('details') + .eq(0) + .within(() => { + cy.contains('Filter').click(); + cy.get('.language-json').should('exist'); + }); + cy.get('details') + .eq(1) + .within(() => { + cy.contains('JSON').click(); + cy.get('.language-json').should('exist'); + }); + }); + }); + }); +}); diff --git a/apps/explorer/src/app/routes/oracles/home/index.tsx b/apps/explorer/src/app/routes/oracles/home/index.tsx index 0ee9abc0b..d088a0a47 100644 --- a/apps/explorer/src/app/routes/oracles/home/index.tsx +++ b/apps/explorer/src/app/routes/oracles/home/index.tsx @@ -38,7 +38,12 @@ const Oracles = () => { const dataConnection = o?.node.dataConnection; return ( -
+
Date: Mon, 4 Sep 2023 12:09:38 +0100 Subject: [PATCH 04/14] fix(governance,utils,react-helpers): token locale formatting issue (#4678) --- .../src/components/wallet-card/wallet-card.tsx | 17 +++++++++++++---- .../react-helpers/src/hooks/use-number-parts.ts | 2 +- libs/utils/src/lib/format/number.spec.ts | 16 ++++++++-------- libs/utils/src/lib/format/number.ts | 6 +++--- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/apps/governance/src/components/wallet-card/wallet-card.tsx b/apps/governance/src/components/wallet-card/wallet-card.tsx index aa8b06e5f..6a1b1e5fa 100644 --- a/apps/governance/src/components/wallet-card/wallet-card.tsx +++ b/apps/governance/src/components/wallet-card/wallet-card.tsx @@ -54,7 +54,7 @@ export const WalletCardRow = ({ }) => { const ref = React.useRef(null); useAnimateValue(ref, value); - const [integers, decimalsPlaces] = useNumberParts(value, decimals); + const [integers, decimalsPlaces, separator] = useNumberParts(value, decimals); return (
- {integers}. + + {integers} + {separator} + {decimalsPlaces} )} @@ -110,7 +113,10 @@ export const WalletCardAsset = ({ border, subheading, }: WalletCardAssetProps) => { - const [integers, decimalsPlaces] = useNumberParts(balance, decimals); + const [integers, decimalsPlaces, separator] = useNumberParts( + balance, + decimals + ); return (
@@ -132,7 +138,10 @@ export const WalletCardAsset = ({
- {integers}. + + {integers} + {separator} + {decimalsPlaces}
diff --git a/libs/react-helpers/src/hooks/use-number-parts.ts b/libs/react-helpers/src/hooks/use-number-parts.ts index 606e854a8..2c3ba399d 100644 --- a/libs/react-helpers/src/hooks/use-number-parts.ts +++ b/libs/react-helpers/src/hooks/use-number-parts.ts @@ -5,6 +5,6 @@ import { toNumberParts } from '@vegaprotocol/utils'; export const useNumberParts = ( value: BigNumber | null | undefined, decimals: number -): [integers: string, decimalPlaces: string] => { +): [integers: string, decimalPlaces: string, separator: string | undefined] => { return useMemo(() => toNumberParts(value, decimals), [decimals, value]); }; diff --git a/libs/utils/src/lib/format/number.spec.ts b/libs/utils/src/lib/format/number.spec.ts index 119087fca..d30e14ab7 100644 --- a/libs/utils/src/lib/format/number.spec.ts +++ b/libs/utils/src/lib/format/number.spec.ts @@ -86,17 +86,17 @@ describe('number utils', () => { describe('toNumberParts', () => { it.each([ - { v: null, d: 3, o: ['0', '000'] }, - { v: undefined, d: 3, o: ['0', '000'] }, - { v: new BigNumber(123), d: 3, o: ['123', '00'] }, - { v: new BigNumber(123.123), d: 3, o: ['123', '123'] }, - { v: new BigNumber(123.123), d: 6, o: ['123', '123'] }, - { v: new BigNumber(123.123), d: 0, o: ['123', ''] }, - { v: new BigNumber(123), d: undefined, o: ['123', '00'] }, + { v: null, d: 3, o: ['0', '000', '.'] }, + { v: undefined, d: 3, o: ['0', '000', '.'] }, + { v: new BigNumber(123), d: 3, o: ['123', '00', '.'] }, + { v: new BigNumber(123.123), d: 3, o: ['123', '123', '.'] }, + { v: new BigNumber(123.123), d: 6, o: ['123', '123', '.'] }, + { v: new BigNumber(123.123), d: 0, o: ['123', '', '.'] }, + { v: new BigNumber(123), d: undefined, o: ['123', '00', '.'] }, { v: new BigNumber(30000), d: undefined, - o: ['30,000', '00'], + o: ['30,000', '00', '.'], }, ])('returns correct tuple given the different arguments', ({ v, d, o }) => { expect(toNumberParts(v, d)).toStrictEqual(o); diff --git a/libs/utils/src/lib/format/number.ts b/libs/utils/src/lib/format/number.ts index bf5a93ff4..261502a38 100644 --- a/libs/utils/src/lib/format/number.ts +++ b/libs/utils/src/lib/format/number.ts @@ -165,15 +165,15 @@ export const formatNumberPercentage = (value: BigNumber, decimals?: number) => { export const toNumberParts = ( value: BigNumber | null | undefined, decimals = 18 -): [integers: string, decimalPlaces: string] => { +): [integers: string, decimalPlaces: string, separator: string] => { if (!value) { - return ['0', '0'.repeat(decimals)]; + return ['0', '0'.repeat(decimals), '.']; } const separator = getDecimalSeparator() || '.'; const [integers, decimalsPlaces] = formatNumber(value, decimals) .toString() .split(separator); - return [integers, decimalsPlaces || '']; + return [integers, decimalsPlaces || '', separator]; }; export const isNumeric = ( From 1208d3f2a80357d66f51949926b279634586310a Mon Sep 17 00:00:00 2001 From: Matthew Russell Date: Mon, 4 Sep 2023 07:47:27 -0700 Subject: [PATCH 05/14] feat(market-depth): additional orderbook grouping levels (#4658) --- .../src/integration/order-book.cy.ts | 117 ------------------ .../src/lib/orderbook-controls.tsx | 85 +++++++++---- libs/market-depth/src/lib/orderbook-data.ts | 4 +- libs/market-depth/src/lib/orderbook-row.tsx | 6 +- libs/market-depth/src/lib/orderbook.spec.tsx | 95 +++++++++++--- libs/market-depth/src/lib/orderbook.tsx | 15 ++- 6 files changed, 161 insertions(+), 161 deletions(-) delete mode 100644 apps/trading-e2e/src/integration/order-book.cy.ts diff --git a/apps/trading-e2e/src/integration/order-book.cy.ts b/apps/trading-e2e/src/integration/order-book.cy.ts deleted file mode 100644 index 34cb68fce..000000000 --- a/apps/trading-e2e/src/integration/order-book.cy.ts +++ /dev/null @@ -1,117 +0,0 @@ -const orderbookTab = 'Orderbook'; -const orderbookTable = 'tab-orderbook'; -const askPrice = 'price-9894185'; -const bidPrice = 'price-9889001'; -const askVolume = 'ask-vol-9894185'; -const bidVolume = 'bid-vol-9889001'; -const askCumulative = 'cumulative-vol-9894185'; -const bidCumulative = 'cumulative-vol-9889001'; -const midPrice = 'last-traded-4612690000'; -const priceResolution = 'resolution'; -const dealTicketPrice = 'order-price'; -const dealTicketSize = 'order-size'; -const resPrice = 'price-990'; - -describe('order book', { tags: '@smoke' }, () => { - before(() => { - cy.setOnBoardingViewed(); - cy.mockTradingPage(); - cy.mockSubscription(); - cy.visit('/#/markets/market-0'); - cy.wait('@Markets'); - }); - - beforeEach(() => { - cy.mockTradingPage(); - }); - - it('show order book', () => { - // 6003-ORDB-001 - // 6003-ORDB-002 - cy.getByTestId(orderbookTab).click(); - cy.getByTestId(orderbookTable).should('be.visible'); - cy.getByTestId(orderbookTable).should('not.be.empty'); - }); - - it('show orders prices', () => { - // 6003-ORDB-003 - cy.getByTestId(askPrice).should('have.text', '98.94185'); - cy.getByTestId(bidPrice).should('have.text', '98.89001'); - }); - - it('show prices volumes', () => { - // 6003-ORDB-004 - cy.getByTestId(askVolume).should('have.text', '1'); - cy.getByTestId(bidVolume).should('have.text', '1'); - }); - - it('show prices cumulative volumes', () => { - // 6003-ORDB-005 - cy.getByTestId(askCumulative).should('have.text', '38'); - cy.getByTestId(bidCumulative).should('have.text', '7'); - }); - - it('show mid price', () => { - // 6003-ORDB-006 - cy.getByTestId(midPrice).should('have.text', '46,126.90'); - }); - - it('sort prices descending', () => { - // 6003-ORDB-007 - const prices: number[] = []; - cy.getByTestId(orderbookTable).within(() => { - cy.get('[data-testid*=price]') - .each(($el) => { - prices.push(Number($el.text())); - }) - .then(() => { - expect(prices).to.deep.equal(prices.sort((a, b) => b - a)); - }); - }); - }); - - it('copy price to deal ticket form', () => { - // 6003-ORDB-009 - cy.getByTestId(askPrice).click(); - cy.getByTestId(dealTicketPrice).should('have.value', '98.94185'); - }); - - it('copy size to deal ticket form', () => { - // 6003-ORDB-009 - cy.getByTestId(bidCumulative).click(); - cy.getByTestId(dealTicketSize).should('have.value', '7'); - }); - - it('copy size to deal ticket form', () => { - // 6003-ORDB-009 - cy.getByTestId(bidVolume).click(); - cy.getByTestId(dealTicketSize).should('have.value', '1'); - }); - - it('change price resolution', () => { - // 6003-ORDB-008 - const resolutions = [ - '0.00000', - '0.0000', - '0.000', - '0.00', - '0.0', - '0', - '10', - '100', - '1,000', - '10,000', - ]; - cy.getByTestId(priceResolution).click(); - cy.get('[role="menu"]') - .find('[role="menuitem"]') - .each(($el, index) => { - expect($el.text()).to.equal(resolutions[index]); - }); - - cy.get('[role="menuitem"]').eq(4).click(); - cy.getByTestId(resPrice).should('have.text', '99.0'); - cy.getByTestId(askPrice).should('not.exist'); - cy.getByTestId(bidPrice).should('not.exist'); - }); -}); diff --git a/libs/market-depth/src/lib/orderbook-controls.tsx b/libs/market-depth/src/lib/orderbook-controls.tsx index 62c3f6b0a..b41e146e2 100644 --- a/libs/market-depth/src/lib/orderbook-controls.tsx +++ b/libs/market-depth/src/lib/orderbook-controls.tsx @@ -7,7 +7,7 @@ import { TradingDropdownContent, TradingDropdownItem, } from '@vegaprotocol/ui-toolkit'; -import { formatNumberFixed } from '@vegaprotocol/utils'; +import { addDecimalsFormatNumber } from '@vegaprotocol/utils'; export const OrderbookControls = ({ lastTradedPrice, @@ -15,27 +15,14 @@ export const OrderbookControls = ({ decimalPlaces, setResolution, }: { - lastTradedPrice: string | undefined; + lastTradedPrice: string; resolution: number; decimalPlaces: number; setResolution: (resolution: number) => void; }) => { const [isOpen, setOpen] = useState(false); - const resolutions = new Array( - Math.max(lastTradedPrice?.toString().length ?? 0, decimalPlaces + 1) - ) - .fill(null) - .map((v, i) => Math.pow(10, i)); - - const formatResolution = (r: number) => { - return formatNumberFixed( - Math.log10(r) - decimalPlaces > 0 - ? Math.pow(10, Math.log10(r) - decimalPlaces) - : 0, - decimalPlaces - Math.log10(r) - ); - }; + const resolutions = createResolutions(lastTradedPrice, decimalPlaces); const increaseResolution = () => { const index = resolutions.indexOf(resolution); @@ -56,7 +43,7 @@ export const OrderbookControls = ({ } > {resolutions.map((r) => ( - setResolution(r)}> - {formatResolution(r)} + setResolution(r)} + className="justify-end" + > + {formatResolution(r, decimalPlaces)} ))} @@ -99,7 +92,7 @@ export const OrderbookControls = ({
); }; + +export const formatResolution = (r: number, decimalPlaces: number) => { + let num = addDecimalsFormatNumber(r, decimalPlaces); + + // Remove trailing zeroes + num = num.replace(/\.?0+$/, ''); + + return num; +}; + +/** + * Create a list of resolutions based on the largest and smallest + * possible values using the last traded price and the market + * decimal places + */ +export const createResolutions = ( + lastTradedPrice: string, + decimalPlaces: number +) => { + // number of levels determined by either the number + // of digits in the last traded price OR the number of decimal + // places. For example: + // + // last traded = 1 (0.001) + // dps = 3 + // result = 3 + // + // last traded = 100001 (1000.01 + // dps = 2 + // result = 6 + const levelCount = Math.max(lastTradedPrice.length ?? 0, decimalPlaces + 1); + const generatedResolutions = new Array(levelCount) + .fill(null) + .map((_, i) => Math.pow(10, i)); + const customResolutions = [2, 5, 20, 50, 200, 500]; + const combined = customResolutions.concat(generatedResolutions); + combined.sort((a, b) => a - b); + + // Remove any resolutions higher than the generated ones as + // we dont want a custom resolution higher than necessary + const resolutions = combined.filter((r) => { + return r <= generatedResolutions[generatedResolutions.length - 1]; + }); + + return resolutions; +}; diff --git a/libs/market-depth/src/lib/orderbook-data.ts b/libs/market-depth/src/lib/orderbook-data.ts index 31be1491a..2b81eb6e5 100644 --- a/libs/market-depth/src/lib/orderbook-data.ts +++ b/libs/market-depth/src/lib/orderbook-data.ts @@ -12,7 +12,7 @@ export interface OrderbookRowData { cumulativeVol: number; } -export const getPriceLevel = (price: string | bigint, resolution: number) => { +export const getPriceLevel = (price: string, resolution: number) => { const p = BigInt(price); const r = BigInt(resolution); let priceLevel = (p / r) * r; @@ -43,7 +43,7 @@ const updateCumulativeVolumeByType = ( }; export const compactRows = ( - data: PriceLevelFieldsFragment[] | null | undefined, + data: PriceLevelFieldsFragment[], dataType: VolumeType, resolution: number ) => { diff --git a/libs/market-depth/src/lib/orderbook-row.tsx b/libs/market-depth/src/lib/orderbook-row.tsx index 82cc238c1..e6e2ffcb2 100644 --- a/libs/market-depth/src/lib/orderbook-row.tsx +++ b/libs/market-depth/src/lib/orderbook-row.tsx @@ -13,6 +13,7 @@ interface OrderbookRowProps { cumulativeVolume: number; decimalPlaces: number; positionDecimalPlaces: number; + priceFormatDecimalPlaces: number; price: string; onClick: (args: { price?: string; size?: string }) => void; type: VolumeType; @@ -26,6 +27,7 @@ export const OrderbookRow = memo( cumulativeVolume, decimalPlaces, positionDecimalPlaces, + priceFormatDecimalPlaces, price, onClick, type, @@ -35,6 +37,7 @@ export const OrderbookRow = memo( const txtId = type === VolumeType.bid ? 'bid' : 'ask'; const cols = width >= HIDE_CUMULATIVE_VOL_WIDTH ? 3 : width >= HIDE_VOL_WIDTH ? 2 : 1; + return (
{ jest.clearAllMocks(); mockOffsetSize(800, 768); }); - it('markPrice should be in the middle', async () => { + + it('lastTradedPrice should be in the middle', async () => { render( { expect( await screen.findByTestId(`last-traded-${params.lastTradedPrice}`) ).toBeInTheDocument(); + // Before resolution change the price is 122.934 await userEvent.click(screen.getByTestId('price-122901')); expect(onClickSpy).toBeCalledWith({ price: '122.901' }); @@ -86,15 +89,16 @@ describe('Orderbook', () => { expect(orderbookData.compactRows).toHaveBeenCalledWith( mockedData.bids, VolumeType.bid, - 10 + 2 ); expect(orderbookData.compactRows).toHaveBeenCalledWith( mockedData.asks, VolumeType.ask, - 10 + 2 ); - await userEvent.click(screen.getByTestId('price-12294')); - expect(onClickSpy).toBeCalledWith({ price: '122.94' }); + + await userEvent.click(screen.getByTestId('price-122938')); + expect(onClickSpy).toBeCalledWith({ price: '122.938' }); }); it('plus - minus buttons should change resolution', async () => { @@ -114,26 +118,30 @@ describe('Orderbook', () => { 1 ); expect(screen.getByTestId('minus-button')).toBeDisabled(); - userEvent.click(screen.getByTestId('plus-button')); + await userEvent.click(screen.getByTestId('plus-button')); + expect((orderbookData.compactRows as jest.Mock).mock.lastCall[2]).toEqual( + 2 + ); + + await userEvent.click(screen.getByTestId('plus-button')); + expect((orderbookData.compactRows as jest.Mock).mock.lastCall[2]).toEqual( + 5 + ); + + expect(screen.getByTestId('minus-button')).not.toBeDisabled(); + await userEvent.click(screen.getByTestId('minus-button')); await waitFor(() => { expect((orderbookData.compactRows as jest.Mock).mock.lastCall[2]).toEqual( - 10 + 2 ); }); expect(screen.getByTestId('minus-button')).not.toBeDisabled(); - userEvent.click(screen.getByTestId('minus-button')); - await waitFor(() => { - expect((orderbookData.compactRows as jest.Mock).mock.lastCall[2]).toEqual( - 1 - ); - }); - expect(screen.getByTestId('minus-button')).toBeDisabled(); - await userEvent.click(screen.getByTestId('resolution')); + await userEvent.click(screen.getByTestId('resolution')); await waitFor(() => { expect(screen.getByRole('menu')).toBeInTheDocument(); }); - await userEvent.click(screen.getAllByRole('menuitem')[5]); + await userEvent.click(screen.getAllByRole('menuitem')[11]); await waitFor(() => { expect((orderbookData.compactRows as jest.Mock).mock.lastCall[2]).toEqual( 100000 @@ -223,3 +231,58 @@ describe('OrderbookMid', () => { expect(screen.getByTestId('icon-arrow-down')).toBeInTheDocument(); }); }); + +describe('createResolutions', () => { + it('create resolutions relative to the market', () => { + expect( + createResolutions( + '1', // 0.001 + 3 + ) + ).toEqual([1, 2, 5, 10, 20, 50, 100, 200, 500, 1000]); + + expect( + createResolutions( + '190017', // 1900.17 + 2 + ) + ).toEqual([1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 10000, 100000]); + + expect( + createResolutions( + '123456789', // 1234.56789 + 5 + ) + ).toEqual([ + 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 10000, 100000, 1000000, + 10000000, 100000000, + ]); + }); + + it('removes resolutions that arent precise enough for the market', () => { + expect( + createResolutions( + '1', // 0.01 + 2 + ) + ).toEqual([1, 2, 5, 10, 20, 50, 100]); + }); +}); + +describe('formatResolution', () => { + it('formats less than 1', () => { + expect(formatResolution(1, 2)).toEqual('0.01'); + expect(formatResolution(1, 3)).toEqual('0.001'); + expect(formatResolution(2, 4)).toEqual('0.0002'); + expect(formatResolution(5, 8)).toEqual('0.00000005'); + expect(formatResolution(10000, 5)).toEqual('0.1'); + }); + + it('formats greater than 1', () => { + expect(formatResolution(1000, 2)).toEqual('10'); + expect(formatResolution(100000, 4)).toEqual('10'); + expect(formatResolution(10000000, 2)).toEqual('100,000'); + expect(formatResolution(500, 2)).toEqual('5'); + expect(formatResolution(500, 1)).toEqual('50'); + }); +}); diff --git a/libs/market-depth/src/lib/orderbook.tsx b/libs/market-depth/src/lib/orderbook.tsx index 145ddbb30..8d4878817 100644 --- a/libs/market-depth/src/lib/orderbook.tsx +++ b/libs/market-depth/src/lib/orderbook.tsx @@ -23,6 +23,7 @@ const OrderbookSide = ({ type, decimalPlaces, positionDecimalPlaces, + priceFormatDecimalPlaces, onClick, width, maxVol, @@ -31,6 +32,7 @@ const OrderbookSide = ({ resolution: number; decimalPlaces: number; positionDecimalPlaces: number; + priceFormatDecimalPlaces: number; type: VolumeType; onClick: (args: { price?: string; size?: string }) => void; width: number; @@ -53,10 +55,11 @@ const OrderbookSide = ({ {rows.map((data) => (
@@ -203,6 +212,7 @@ export const Orderbook = ({ resolution={resolution} decimalPlaces={decimalPlaces} positionDecimalPlaces={positionDecimalPlaces} + priceFormatDecimalPlaces={priceFormatDecimalPlaces} onClick={onClick} width={width} maxVol={maxVol} @@ -220,6 +230,7 @@ export const Orderbook = ({ resolution={resolution} decimalPlaces={decimalPlaces} positionDecimalPlaces={positionDecimalPlaces} + priceFormatDecimalPlaces={priceFormatDecimalPlaces} onClick={onClick} width={width} maxVol={maxVol} From d268088e6014d6b2dc74ee2a8918fbdd640f998d Mon Sep 17 00:00:00 2001 From: "m.ray" <16125548+MadalinaRaicu@users.noreply.github.com> Date: Mon, 4 Sep 2023 23:25:24 +0300 Subject: [PATCH 06/14] chore(trading): update dropdowns (#4694) Co-authored-by: Matthew Russell --- .../market-selector/asset-dropdown.tsx | 43 +++++++++---------- .../components/market-selector/index.ts | 1 + .../market-selector-button.tsx | 23 ++++++++++ .../market-selector/market-selector-item.tsx | 10 ++--- .../market-selector/market-selector.tsx | 2 +- .../market-selector/product-selector.tsx | 15 ++++--- .../market-selector/sort-dropdown.tsx | 40 ++++++++--------- libs/markets/src/lib/markets-provider.ts | 2 +- .../src/components/trading-input/input.tsx | 6 +-- 9 files changed, 82 insertions(+), 60 deletions(-) create mode 100644 apps/trading/components/market-selector/market-selector-button.tsx diff --git a/apps/trading/components/market-selector/asset-dropdown.tsx b/apps/trading/components/market-selector/asset-dropdown.tsx index 308bba84e..d0bcefb0c 100644 --- a/apps/trading/components/market-selector/asset-dropdown.tsx +++ b/apps/trading/components/market-selector/asset-dropdown.tsx @@ -1,13 +1,12 @@ import { t } from '@vegaprotocol/i18n'; import { - DropdownMenu, - DropdownMenuCheckboxItem, - DropdownMenuContent, - DropdownMenuItemIndicator, - DropdownMenuTrigger, - VegaIcon, - VegaIconNames, + TradingDropdown, + TradingDropdownCheckboxItem, + TradingDropdownContent, + TradingDropdownItemIndicator, + TradingDropdownTrigger, } from '@vegaprotocol/ui-toolkit'; +import { MarketSelectorButton } from './market-selector-button'; type Assets = Array<{ id: string; symbol: string }>; @@ -25,17 +24,19 @@ export const AssetDropdown = ({ } return ( - - - + + + {triggerText({ assets, checkedAssets })} + + } > - + {assets?.map((a) => { return ( - { @@ -46,16 +47,16 @@ export const AssetDropdown = ({ data-testid={`asset-id-${a.id}`} > {a.symbol} - - + + ); })} - - + + ); }; -const TriggerText = ({ +const triggerText = ({ assets, checkedAssets, }: { @@ -72,9 +73,5 @@ const TriggerText = ({ text = t(`${checkedAssets.length} Assets`); } - return ( - - {text} - - ); + return text; }; diff --git a/apps/trading/components/market-selector/index.ts b/apps/trading/components/market-selector/index.ts index ddd159890..6a16773bb 100644 --- a/apps/trading/components/market-selector/index.ts +++ b/apps/trading/components/market-selector/index.ts @@ -1,2 +1,3 @@ export * from './market-selector'; export * from './market-selector-item'; +export * from './market-selector-button'; diff --git a/apps/trading/components/market-selector/market-selector-button.tsx b/apps/trading/components/market-selector/market-selector-button.tsx new file mode 100644 index 000000000..90ae6cacf --- /dev/null +++ b/apps/trading/components/market-selector/market-selector-button.tsx @@ -0,0 +1,23 @@ +import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit'; +import classNames from 'classnames'; +import type { ButtonHTMLAttributes } from 'react'; +import { forwardRef } from 'react'; + +export const MarketSelectorButton = forwardRef< + HTMLButtonElement, + ButtonHTMLAttributes +>((props, ref) => ( + +)); +MarketSelectorButton.displayName = 'MarketSelectorButton'; diff --git a/apps/trading/components/market-selector/market-selector-item.tsx b/apps/trading/components/market-selector/market-selector-item.tsx index b60ef54af..af54ecd66 100644 --- a/apps/trading/components/market-selector/market-selector-item.tsx +++ b/apps/trading/components/market-selector/market-selector-item.tsx @@ -31,7 +31,7 @@ export const MarketSelectorItem = ({
-

+

{market.tradableInstrument.instrument.code}{' '} {allProducts && productType && ( @@ -107,7 +107,7 @@ const MarketData = ({ )}

{volume}
-
+
{oneDayCandles && ( +
{Object.keys(Product).map((t) => { - const classes = classNames('px-3 py-1.5 rounded', { - 'bg-vega-clight-500 dark:bg-vega-cdark-500 text-default': - t === product, - 'text-secondary': t !== product, - }); + const classes = classNames( + 'text-sm px-3 py-1.5 rounded hover:text-vega-clight-50 dark:hover:text-vega-cdark-50', + { + 'bg-vega-clight-500 dark:bg-vega-cdark-500 text-default': + t === product, + 'text-secondary': t !== product, + } + ); return ( -
- - ); - } - - return <>{children}; -}; diff --git a/apps/trading/components/welcome-dialog/telemetry-approval.tsx b/apps/trading/components/welcome-dialog/telemetry-approval.tsx index 5b38c2963..0c21a4cd3 100644 --- a/apps/trading/components/welcome-dialog/telemetry-approval.tsx +++ b/apps/trading/components/welcome-dialog/telemetry-approval.tsx @@ -16,29 +16,32 @@ export const TelemetryApproval = ({ setTelemetryValue, }: Props) => { return ( -
+
-
+

{t( 'Help us identify bugs and improve Vega Governance by sharing anonymous usage data.' )} -

-
- -
-
{t('Anonymous')}
-
{t('Your identity is always anonymous on Vega')}
+

+
+ +
+
{t('Anonymous')}
+

+ {t('Your identity is always anonymous on Vega')} +

- -
- -
-
{t('Optional')}
-
{t('You can opt out any time via settings')}
+
+ +
+
{t('Optional')}
+

+ {t('You can opt out any time via settings')} +

-
+
setTelemetryValue('false')} size="small" diff --git a/apps/trading/components/welcome-dialog/welcome-dialog.tsx b/apps/trading/components/welcome-dialog/welcome-dialog.tsx index a3c42cdf1..7f7cbb06e 100644 --- a/apps/trading/components/welcome-dialog/welcome-dialog.tsx +++ b/apps/trading/components/welcome-dialog/welcome-dialog.tsx @@ -92,7 +92,7 @@ export const WelcomeDialog = () => { intent: Intent.Primary, content: ( <> -

+

{t('Improve vega console')}

- {t('Deposit')} - - + {t('Withdraw')} - - + {t('Transfer')} - - + {t('View usage breakdown')} - - + { openAssetDialog(assetId, e.target as HTMLElement); }} > {t('View asset details')} - - + + {assetContractAddress && ( - + - + )} ); diff --git a/libs/accounts/src/lib/accounts-table.tsx b/libs/accounts/src/lib/accounts-table.tsx index 847868230..413eb9338 100644 --- a/libs/accounts/src/lib/accounts-table.tsx +++ b/libs/accounts/src/lib/accounts-table.tsx @@ -11,9 +11,13 @@ import type { VegaValueFormatterParams, } from '@vegaprotocol/datagrid'; import { COL_DEFS } from '@vegaprotocol/datagrid'; -import { Button, VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit'; - -import { TooltipCellComponent } from '@vegaprotocol/ui-toolkit'; +import { + Intent, + TradingButton, + VegaIcon, + VegaIconNames, + TooltipCellComponent, +} from '@vegaprotocol/ui-toolkit'; import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid'; import type { IGetRowsParams, @@ -186,7 +190,7 @@ export const AccountTable = ({ ) : ( <> {valueFormatted} - + {t('0.00%')} @@ -248,26 +252,26 @@ export const AccountTable = ({ colId: 'accounts-actions', field: 'asset.id', ...COL_DEFS.actions, - minWidth: showDepositButton ? 130 : COL_DEFS.actions.minWidth, - maxWidth: showDepositButton ? 130 : COL_DEFS.actions.maxWidth, + minWidth: showDepositButton ? 105 : COL_DEFS.actions.minWidth, + maxWidth: showDepositButton ? 105 : COL_DEFS.actions.maxWidth, cellRenderer: ({ value: assetId, node, }: VegaICellRendererParams) => { if (!assetId) return null; - if (node.rowPinned && node.data?.total === '0') { + if (node.rowPinned && node.data?.balance === '0') { return ( - +
); } diff --git a/libs/accounts/src/lib/transfer-form.tsx b/libs/accounts/src/lib/transfer-form.tsx index a3e81c4c7..f0adcba94 100644 --- a/libs/accounts/src/lib/transfer-form.tsx +++ b/libs/accounts/src/lib/transfer-form.tsx @@ -8,7 +8,6 @@ import { } from '@vegaprotocol/utils'; import { t } from '@vegaprotocol/i18n'; import { - Button, TradingFormGroup, TradingInput, TradingInputError, @@ -16,6 +15,7 @@ import { TradingSelect, Tooltip, TradingCheckbox, + TradingButton, } from '@vegaprotocol/ui-toolkit'; import type { Transfer } from '@vegaprotocol/wallet'; import { normalizeTransfer } from '@vegaprotocol/wallet'; @@ -276,9 +276,9 @@ export const TransferForm = ({ decimals={asset?.decimals} /> )} - + ); }; @@ -309,8 +309,8 @@ export const TransferFee = ({ const totalValue = new BigNumber(transferAmount).plus(fee).toString(); return ( -
-
+
+
-
+
-
+
!curr); onChange(); }} - className="ml-auto text-sm absolute top-0 right-0 underline" + className="absolute top-0 right-0 ml-auto text-sm underline" > {isInput ? t('Select from wallet') : t('Enter manually')} diff --git a/libs/assets/src/lib/asset-details-dialog.tsx b/libs/assets/src/lib/asset-details-dialog.tsx index 1fb26fe48..9f2fa7503 100644 --- a/libs/assets/src/lib/asset-details-dialog.tsx +++ b/libs/assets/src/lib/asset-details-dialog.tsx @@ -2,9 +2,10 @@ import { t } from '@vegaprotocol/i18n'; import { Button, Dialog, - Icon, Splash, SyntaxHighlighter, + VegaIcon, + VegaIconNames, } from '@vegaprotocol/ui-toolkit'; import { create } from 'zustand'; import { AssetDetailsTable } from './asset-details-table'; @@ -82,7 +83,7 @@ export const AssetDetailsDialog = ({ return ( } + icon={} open={open} onChange={(isOpen) => onChange(isOpen)} onCloseAutoFocus={(e) => { @@ -97,7 +98,7 @@ export const AssetDetailsDialog = ({ }} > {content} -

+

{t( 'There is 1 unit of the settlement asset (%s) to every 1 quote unit.', [assetSymbol] diff --git a/libs/assets/src/lib/asset-details-table.tsx b/libs/assets/src/lib/asset-details-table.tsx index eca9a30a3..f6ef156a9 100644 --- a/libs/assets/src/lib/asset-details-table.tsx +++ b/libs/assets/src/lib/asset-details-table.tsx @@ -3,11 +3,8 @@ import { addDecimalsFormatNumber } from '@vegaprotocol/utils'; import { t } from '@vegaprotocol/i18n'; import type * as Schema from '@vegaprotocol/types'; import type { KeyValueTableRowProps } from '@vegaprotocol/ui-toolkit'; -import { - CopyWithTooltip, - Icon, - truncateMiddle, -} from '@vegaprotocol/ui-toolkit'; +import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit'; +import { CopyWithTooltip, truncateMiddle } from '@vegaprotocol/ui-toolkit'; import { KeyValueTable, KeyValueTableRow, @@ -118,7 +115,7 @@ export const rows: Rows = [ {' '} diff --git a/libs/candles-chart/src/lib/candles-menu.spec.tsx b/libs/candles-chart/src/lib/candles-menu.spec.tsx index 85f8b5b24..9289581bd 100644 --- a/libs/candles-chart/src/lib/candles-menu.spec.tsx +++ b/libs/candles-chart/src/lib/candles-menu.spec.tsx @@ -3,7 +3,7 @@ import userEvent from '@testing-library/user-event'; import { CandlesMenu } from './candles-menu'; describe('CandlesMenu', () => { - it('should render with volume study showing by default', async () => { + it('should render with the correct default studies', async () => { render(); await userEvent.click( @@ -13,5 +13,21 @@ describe('CandlesMenu', () => { ); expect(await screen.findByRole('menu')).toBeInTheDocument(); expect(screen.getByText('Volume')).toHaveAttribute('data-state', 'checked'); + expect(screen.getByText('MACD')).toHaveAttribute('data-state', 'checked'); + }); + + it('should render with the correct default overlays', async () => { + render(); + + await userEvent.click( + screen.getByRole('button', { + name: 'Overlays', + }) + ); + expect(await screen.findByRole('menu')).toBeInTheDocument(); + expect(screen.getByText('Moving average')).toHaveAttribute( + 'data-state', + 'checked' + ); }); }); diff --git a/libs/candles-chart/src/lib/use-candles-chart-settings.ts b/libs/candles-chart/src/lib/use-candles-chart-settings.ts index 78e5f81f9..cce6fb5b5 100644 --- a/libs/candles-chart/src/lib/use-candles-chart-settings.ts +++ b/libs/candles-chart/src/lib/use-candles-chart-settings.ts @@ -15,8 +15,8 @@ interface StoredSettings { const DEFAULT_CHART_SETTINGS = { interval: Interval.I15M, type: ChartType.CANDLE, - overlays: [], - studies: [Study.VOLUME], + overlays: [Overlay.MOVING_AVERAGE], + studies: [Study.MACD, Study.VOLUME], }; export const useCandlesChartSettingsStore = create< diff --git a/libs/deposits/src/lib/deposit-form.spec.tsx b/libs/deposits/src/lib/deposit-form.spec.tsx index b6f226cc3..7a6af6fb3 100644 --- a/libs/deposits/src/lib/deposit-form.spec.tsx +++ b/libs/deposits/src/lib/deposit-form.spec.tsx @@ -305,9 +305,7 @@ describe('Deposit form', () => { target: { value: '8' }, }); - fireEvent.click( - screen.getByText('Deposit', { selector: '[type="submit"]' }) - ); + fireEvent.click(screen.getByRole('button', { name: 'Deposit' })); await waitFor(() => { expect(props.submitDeposit).toHaveBeenCalledWith({ diff --git a/libs/deposits/src/lib/deposit-form.tsx b/libs/deposits/src/lib/deposit-form.tsx index 0044592c2..0bee8999f 100644 --- a/libs/deposits/src/lib/deposit-form.tsx +++ b/libs/deposits/src/lib/deposit-form.tsx @@ -13,7 +13,6 @@ import { import { t } from '@vegaprotocol/i18n'; import { useLocalStorage } from '@vegaprotocol/react-helpers'; import { - Button, TradingFormGroup, TradingInput, TradingInputError, @@ -23,6 +22,7 @@ import { ButtonLink, TradingSelect, truncateMiddle, + TradingButton, } from '@vegaprotocol/ui-toolkit'; import { useVegaWallet } from '@vegaprotocol/wallet'; import { useWeb3React } from '@web3-react/core'; @@ -186,14 +186,14 @@ export const DepositForm = ({ ); } return ( - + ); }} /> @@ -435,15 +435,14 @@ const FormButton = ({ approved, selectedAsset }: FormButtonProps) => { />

)} - + ); }; @@ -455,7 +454,7 @@ const UseButton = (props: UseButtonProps) => {
)} - +
); diff --git a/libs/orders/src/lib/components/order-list/order-list.tsx b/libs/orders/src/lib/components/order-list/order-list.tsx index aca064bd0..8c7218d7d 100644 --- a/libs/orders/src/lib/components/order-list/order-list.tsx +++ b/libs/orders/src/lib/components/order-list/order-list.tsx @@ -10,7 +10,7 @@ import { ActionsDropdown, ButtonLink, TradingDropdownCopyItem, - DropdownMenuItem, + TradingDropdownItem, VegaIcon, VegaIconNames, } from '@vegaprotocol/ui-toolkit'; @@ -277,7 +277,7 @@ export const OrderListTable = memo< if (!data) return null; return ( -
+
{isOrderAmendable(data) && !props.isReadOnly && ( <> {!data.icebergOrder && ( @@ -301,14 +301,14 @@ export const OrderListTable = memo< value={data.id} text={t('Copy order ID')} /> - onView(data)} > {t('View order details')} - +
); diff --git a/libs/orders/src/lib/components/stop-orders-table/stop-orders-table.tsx b/libs/orders/src/lib/components/stop-orders-table/stop-orders-table.tsx index 9af429a0e..5c8a9e049 100644 --- a/libs/orders/src/lib/components/stop-orders-table/stop-orders-table.tsx +++ b/libs/orders/src/lib/components/stop-orders-table/stop-orders-table.tsx @@ -12,7 +12,7 @@ import { ButtonLink, VegaIcon, VegaIconNames, - DropdownMenuItem, + TradingDropdownItem, TradingDropdownCopyItem, Pill, } from '@vegaprotocol/ui-toolkit'; @@ -246,7 +246,7 @@ export const StopOrdersTable = memo( if (!data) return null; return ( -
+
{data.status === Schema.StopOrderStatus.STATUS_PENDING && !props.isReadOnly && ( - @@ -273,7 +273,7 @@ export const StopOrdersTable = memo( > {t('View order details')} - + )}
diff --git a/libs/positions/src/lib/positions-table.spec.tsx b/libs/positions/src/lib/positions-table.spec.tsx index 7dc85c5d1..ed2aebf4c 100644 --- a/libs/positions/src/lib/positions-table.spec.tsx +++ b/libs/positions/src/lib/positions-table.spec.tsx @@ -61,7 +61,7 @@ describe('Positions', () => { 'Market', 'Size / Notional', 'Entry / Mark', - 'Margin', + 'Margin / Leverage', 'Liquidation', 'Realised PNL', 'Unrealised PNL', diff --git a/libs/positions/src/lib/positions-table.tsx b/libs/positions/src/lib/positions-table.tsx index 11d7ce1c1..b3af73bd3 100644 --- a/libs/positions/src/lib/positions-table.tsx +++ b/libs/positions/src/lib/positions-table.tsx @@ -292,7 +292,7 @@ export const PositionsTable = ({ }, }, { - headerName: t('Margin'), + headerName: t('Margin / Leverage'), colId: 'margin', type: 'rightAligned', cellClass: 'font-mono text-right', @@ -456,7 +456,7 @@ export const PositionsTable = ({ ...COL_DEFS.actions, cellRenderer: ({ data }: VegaICellRendererParams) => { return ( -
+
{data?.openVolume && data?.openVolume !== '0' && data.partyId === pubKey ? ( @@ -548,9 +548,9 @@ const WarningCell = ({ showIcon?: boolean; }) => { return ( -
+
{showIcon && ( - + )} diff --git a/libs/proposals/src/components/proposals-list/proposals-list.tsx b/libs/proposals/src/components/proposals-list/proposals-list.tsx index 38ab2b753..9cdb01aef 100644 --- a/libs/proposals/src/components/proposals-list/proposals-list.tsx +++ b/libs/proposals/src/components/proposals-list/proposals-list.tsx @@ -35,16 +35,13 @@ export const ProposalsList = ({ const { columnDefs, defaultColDef } = useColumnDefs(); return ( -
- data.id} - overlayNoRowsTemplate={t('No markets')} - components={{ SuccessorMarketRenderer, MarketNameProposalCell }} - /> -
+ data.id} + overlayNoRowsTemplate={t('No markets')} + components={{ SuccessorMarketRenderer, MarketNameProposalCell }} + /> ); }; diff --git a/libs/ui-toolkit/src/components/icon/vega-icons/svg-icons/icon-info.tsx b/libs/ui-toolkit/src/components/icon/vega-icons/svg-icons/icon-info.tsx index 84467122f..4005187f7 100644 --- a/libs/ui-toolkit/src/components/icon/vega-icons/svg-icons/icon-info.tsx +++ b/libs/ui-toolkit/src/components/icon/vega-icons/svg-icons/icon-info.tsx @@ -1,11 +1,6 @@ export const IconInfo = ({ size = 14 }: { size: number }) => { return ( - + ); diff --git a/libs/ui-toolkit/src/components/toast/toast.tsx b/libs/ui-toolkit/src/components/toast/toast.tsx index 89d7155cf..5c4b1c5c9 100644 --- a/libs/ui-toolkit/src/components/toast/toast.tsx +++ b/libs/ui-toolkit/src/components/toast/toast.tsx @@ -10,7 +10,7 @@ import { useCallback } from 'react'; import { useLayoutEffect } from 'react'; import { useRef } from 'react'; import { Intent } from '../../utils/intent'; -import { Icon } from '../icon'; +import { Icon, VegaIcon, VegaIconNames } from '../icon'; import { Loader } from '../loader'; import { t } from '@vegaprotocol/i18n'; @@ -317,18 +317,14 @@ export const Toast = ({ } )} > -
+
diff --git a/libs/ui-toolkit/src/components/toast/toasts-container.tsx b/libs/ui-toolkit/src/components/toast/toasts-container.tsx index 00fc88e4e..ae380b16d 100644 --- a/libs/ui-toolkit/src/components/toast/toasts-container.tsx +++ b/libs/ui-toolkit/src/components/toast/toasts-container.tsx @@ -3,7 +3,7 @@ import { usePrevious } from '@vegaprotocol/react-helpers'; import classNames from 'classnames'; import type { Ref } from 'react'; import { useLayoutEffect, useRef } from 'react'; -import { Button } from '../button'; +import { TradingButton } from '../trading-button'; import { Toast } from './toast'; import type { Toasts } from './use-toasts'; import { ToastPosition, useToasts, useToastsConfiguration } from './use-toasts'; @@ -87,26 +87,27 @@ export const ToastsContainer = ({ ); })} - + { + closeAll(); + }} + > + {t('Dismiss all')} + +
); diff --git a/libs/ui-toolkit/src/components/trading-dropdown/trading-dropdown.tsx b/libs/ui-toolkit/src/components/trading-dropdown/trading-dropdown.tsx index 7d3db2ad3..fba456688 100644 --- a/libs/ui-toolkit/src/components/trading-dropdown/trading-dropdown.tsx +++ b/libs/ui-toolkit/src/components/trading-dropdown/trading-dropdown.tsx @@ -146,7 +146,7 @@ export const TradingDropdownItemIndicator = forwardRef< diff --git a/libs/ui-toolkit/src/components/trading-select/select.tsx b/libs/ui-toolkit/src/components/trading-select/select.tsx index a8869a661..5be5c0df3 100644 --- a/libs/ui-toolkit/src/components/trading-select/select.tsx +++ b/libs/ui-toolkit/src/components/trading-select/select.tsx @@ -2,7 +2,7 @@ import type { Ref, SelectHTMLAttributes } from 'react'; import { useRef } from 'react'; import { forwardRef } from 'react'; import classNames from 'classnames'; -import { Icon } from '..'; +import { Icon, VegaIcon, VegaIconNames } from '..'; import { defaultSelectElement } from '../../utils/shared'; import * as SelectPrimitive from '@radix-ui/react-select'; @@ -16,7 +16,7 @@ export interface TradingSelectProps export const TradingSelect = forwardRef( ({ className, hasError, ...props }, ref) => ( -
+