diff --git a/.eslintrc.json b/.eslintrc.json index 88d9bd572..e58c2f737 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -73,7 +73,8 @@ "error", { "prefer": "type-imports", - "disallowTypeAnnotations": true + "disallowTypeAnnotations": true, + "fixStyle": "inline-type-imports" } ], "curly": ["error", "multi-line"] diff --git a/.github/workflows/ci-cd-trigger.yml b/.github/workflows/ci-cd-trigger.yml index ec26eeb56..bdb570d9b 100644 --- a/.github/workflows/ci-cd-trigger.yml +++ b/.github/workflows/ci-cd-trigger.yml @@ -34,7 +34,7 @@ jobs: ${{ runner.os }}-cache-node-modules- - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 if: steps.cache.outputs.cache-hit != 'true' with: node-version-file: '.nvmrc' @@ -57,7 +57,7 @@ jobs: ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' # https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions @@ -96,7 +96,7 @@ jobs: ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn @@ -128,7 +128,7 @@ jobs: ref: ${{ github.event.pull_request.head.sha || github.sha }} - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' cache: yarn @@ -182,7 +182,7 @@ jobs: run: | if [[ "${{ github.base_ref }}" == "develop" ]]; then echo "e2e-needed=true" >> $GITHUB_OUTPUT - elif [[ "${{ github.base_ref }}" == "main" ]]; then + elif [[ "${{ github.base_ref }}" == "main" ]]; then echo "e2e-needed=true" >> $GITHUB_OUTPUT elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref_name }}" == *"release/"* ]]; then echo "e2e-needed=true" >> $GITHUB_OUTPUT @@ -205,7 +205,7 @@ jobs: console-e2e: needs: [build-sources, check-e2e-needed] - name: '(CI) console python' + name: '(CI) trading e2e python' uses: ./.github/workflows/console-test-run.yml secrets: inherit if: needs.check-e2e-needed.outputs.run-tests == 'true' && contains(needs.build-sources.outputs.projects, 'trading') diff --git a/.github/workflows/console-test-run.yml b/.github/workflows/console-test-run.yml index 661ba9472..f78a086ee 100644 --- a/.github/workflows/console-test-run.yml +++ b/.github/workflows/console-test-run.yml @@ -10,7 +10,7 @@ on: inputs: console-test-branch: type: choice - description: 'main: v0.72.14, develop: v0.73.0-preview7' + description: 'main: v0.72.14, develop: v0.73.4' options: - main - develop @@ -32,9 +32,9 @@ jobs: # cache node modules #---------------------------------------------- - name: setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: '16' + node-version-file: '.nvmrc' cache: yarn - name: Cache node modules @@ -153,25 +153,19 @@ jobs: run: | docker load --input /tmp/console-image.tar docker image ls -a - #---------------------------------------------- - # check-out tests repo + # check-out frontend-monorepo #---------------------------------------------- - - name: Checkout console test repo + - name: Checkout frontend-monorepo uses: actions/checkout@v3 with: - repository: vegaprotocol/console-test - ref: ${{ needs.console-test-branch.outputs.console-branch }} - - - name: Load console test envs - id: console-test-env - uses: falti/dotenv-action@v1.0.4 - with: - path: '.env.${{ needs.console-test-branch.outputs.console-branch }}' - export-variables: true - keys-case: upper - log-variables: true - + ref: ${{ inputs.github-sha || github.sha }} + #---------------------------------------------- + # get vega version + #---------------------------------------------- + - name: Set VEGA_VERSION from .env + id: set_vega_version + run: echo "VEGA_VERSION=$(grep VEGA_VERSION apps/trading/e2e/.env | cut -d '=' -f2)" >> $GITHUB_ENV #---------------------------------------------- # ----- Setup python ----- #---------------------------------------------- @@ -194,22 +188,25 @@ jobs: #---------------------------------------------- - name: Install dependencies run: poetry install --no-interaction --no-root + working-directory: apps/trading/e2e #---------------------------------------------- # install vega binaries #---------------------------------------------- - name: Install vega binaries run: poetry run python -m vega_sim.tools.load_binaries --force --version ${{ env.VEGA_VERSION }} + working-directory: apps/trading/e2e #---------------------------------------------- - # install playwright + # install playwrightworking-directory: apps/trading/e2e #---------------------------------------------- - name: install playwright run: poetry run playwright install --with-deps chromium + working-directory: apps/trading/e2e #---------------------------------------------- # run tests #---------------------------------------------- - name: Run tests run: CONSOLE_IMAGE_NAME=ci/trading:local poetry run pytest -v -s --numprocesses 4 --dist loadfile --durations=15 - + working-directory: apps/trading/e2e #---------------------------------------------- # upload traces #---------------------------------------------- diff --git a/.github/workflows/cypress-live-test.yml b/.github/workflows/cypress-live-test.yml index dcd813036..4c39a6e28 100644 --- a/.github/workflows/cypress-live-test.yml +++ b/.github/workflows/cypress-live-test.yml @@ -18,11 +18,11 @@ jobs: - name: Checkout uses: actions/checkout@v2 - - name: Use Node.js 16 + - name: Use Node.js 20 id: Node - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: - node-version: 16.15.1 + node-version-file: '.nvmrc' - name: Run Cypress tests uses: cypress-io/github-action@v4 diff --git a/.github/workflows/cypress-run.yml b/.github/workflows/cypress-run.yml index fe41f1c89..4411bd54b 100644 --- a/.github/workflows/cypress-run.yml +++ b/.github/workflows/cypress-run.yml @@ -57,6 +57,14 @@ jobs: path: './frontend-monorepo' ref: ${{ github.event.pull_request.head.sha || github.sha }} + - name: Setup node + uses: actions/setup-node@v4 + with: + node-version-file: './frontend-monorepo/.nvmrc' + # https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions + cache: yarn + cache-dependency-path: './frontend-monorepo/yarn.lock' + # Restore node_modules from cache if possible - name: Restore node_modules from cache id: cache-node-modules diff --git a/.github/workflows/generate-queries.yml b/.github/workflows/generate-queries.yml index 43db3338c..c4d628947 100644 --- a/.github/workflows/generate-queries.yml +++ b/.github/workflows/generate-queries.yml @@ -15,7 +15,7 @@ jobs: uses: actions/checkout@v3 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' # https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions diff --git a/.github/workflows/lint-pr.yml b/.github/workflows/lint-pr.yml index 8763b67cd..325641ca6 100644 --- a/.github/workflows/lint-pr.yml +++ b/.github/workflows/lint-pr.yml @@ -18,13 +18,13 @@ jobs: uses: actions/checkout@v3 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 16 + node-version-file: '.nvmrc' - name: Install dependencies run: | - rm package.json + rm package.json npm install --no-save @commitlint/cli @commitlint/config-conventional @commitlint/config-nx-scopes nx - name: Check PR title diff --git a/.github/workflows/publish-dist.yml b/.github/workflows/publish-dist.yml index 622d25b71..309264f90 100644 --- a/.github/workflows/publish-dist.yml +++ b/.github/workflows/publish-dist.yml @@ -93,7 +93,7 @@ jobs: password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' # https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml index 672bb7da0..a40cb66e9 100644 --- a/.github/workflows/publish-npm.yml +++ b/.github/workflows/publish-npm.yml @@ -29,7 +29,7 @@ jobs: uses: actions/checkout@v3 - name: Setup node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: node-version-file: '.nvmrc' # https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions diff --git a/.gitignore b/.gitignore index 0a587cc44..6b34d3516 100644 --- a/.gitignore +++ b/.gitignore @@ -52,3 +52,12 @@ cypress.env.json /apps/**/cypress/reports/ /apps/**/cypress/downloads/ /apps/**/fixtures/wallet/node** + +#console-test +__pycache__/ +apps/trading/e2e/logs/ +apps/trading/e2e/.pytest_cache/ +apps/trading/e2e/traces/ + +.nx/cache + diff --git a/.nvmrc b/.nvmrc index cb406c60c..f3f52b42d 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -16.20.2 +20.9.0 diff --git a/.prettierignore b/.prettierignore index 365c3d4f7..2b04963a2 100644 --- a/.prettierignore +++ b/.prettierignore @@ -8,3 +8,8 @@ __generated___ apps/static/src/assets/devnet-tranches.json apps/static/src/assets/mainnet-tranches.json apps/static/src/assets/testnet-tranches.json + +/apps/**/cypress/reports/ +/apps/**/cypress/downloads/ + +/.nx/cache diff --git a/CODEOWNERS b/CODEOWNERS index 8117415dd..a63dde642 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,2 +1,4 @@ * @vegaprotocol/frontend +apps/ @vegaprotocol/frontend-qa +libs/ @vegaprotocol/frontend-qa *.graphql @vegaprotocol/core diff --git a/README.md b/README.md index 57c165cd6..9e657a93a 100644 --- a/README.md +++ b/README.md @@ -136,7 +136,7 @@ The [`docker`](./docker) subfolder has some docker configurations for easily set Using multistage dockerfile dist is compiled using [node](https://hub.docker.com/_/node) image and later packed to nginx as in [dist build](#dist-build). The multistage builds ensures consistent CPU architecture and build toolchains are used so that the result will be identical. ```bash -docker build --build-arg APP=[YOUR APP] --build-arg NODE_VERSION=16.5.1 --build-arg ENV_NAME=mainnet -t [TAG] -f docker/node-inside-docker.Dockerfile . +docker build --build-arg APP=[YOUR APP] --build-arg NODE_VERSION=20.9.1 --build-arg ENV_NAME=mainnet -t [TAG] -f docker/node-inside-docker.Dockerfile . ``` ### Computing ipfs-hash of the build diff --git a/apps/explorer-e2e/.eslintrc.json b/apps/explorer-e2e/.eslintrc.json index 696cb8b12..70128adc7 100644 --- a/apps/explorer-e2e/.eslintrc.json +++ b/apps/explorer-e2e/.eslintrc.json @@ -4,7 +4,9 @@ "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": {} + "rules": { + "cypress/unsafe-to-chain-command": 0 + } } ] } diff --git a/apps/explorer-e2e/project.json b/apps/explorer-e2e/project.json index f553e9f1b..3e40a7e58 100644 --- a/apps/explorer-e2e/project.json +++ b/apps/explorer-e2e/project.json @@ -17,7 +17,7 @@ } }, "lint": { - "executor": "@nx/linter:eslint", + "executor": "@nx/eslint:lint", "outputs": ["{options.outputFile}"], "options": { "lintFilePatterns": ["apps/explorer-e2e/**/*.{js,ts}"] diff --git a/apps/explorer/project.json b/apps/explorer/project.json index c2aec3281..917e2560e 100644 --- a/apps/explorer/project.json +++ b/apps/explorer/project.json @@ -53,7 +53,7 @@ } }, "lint": { - "executor": "@nx/linter:eslint", + "executor": "@nx/eslint:lint", "outputs": ["{options.outputFile}"], "options": { "lintFilePatterns": ["apps/explorer/**/*.{ts,tsx,js,jsx}"] @@ -63,14 +63,7 @@ "executor": "@nx/jest:jest", "outputs": ["{workspaceRoot}/coverage/apps/explorer"], "options": { - "jestConfig": "apps/explorer/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } + "jestConfig": "apps/explorer/jest.config.ts" } }, "generate-types": { diff --git a/apps/explorer/src/app/components/asset-balance/asset-balance.tsx b/apps/explorer/src/app/components/asset-balance/asset-balance.tsx index a64a43623..758fed005 100644 --- a/apps/explorer/src/app/components/asset-balance/asset-balance.tsx +++ b/apps/explorer/src/app/components/asset-balance/asset-balance.tsx @@ -1,5 +1,5 @@ import { useAssetDataProvider } from '@vegaprotocol/assets'; -import { addDecimalsFormatNumber } from '@vegaprotocol/utils'; +import { addDecimalsFixedFormatNumber } from '@vegaprotocol/utils'; import { AssetLink } from '../links'; export type AssetBalanceProps = { @@ -23,12 +23,12 @@ const AssetBalance = ({ const label = !loading && asset && asset.decimals - ? addDecimalsFormatNumber(price, asset.decimals) + ? addDecimalsFixedFormatNumber(price, asset.decimals) : price; return (
- {label}{' '} + {label}{' '} {showAssetLink && asset?.id ? ( ) : null} diff --git a/apps/explorer/src/app/components/assets/assets-table.tsx b/apps/explorer/src/app/components/assets/assets-table.tsx index af3959d7a..b5ce2377d 100644 --- a/apps/explorer/src/app/components/assets/assets-table.tsx +++ b/apps/explorer/src/app/components/assets/assets-table.tsx @@ -1,20 +1,25 @@ import { useMemo } from 'react'; -import type { AssetFieldsFragment } from '@vegaprotocol/assets'; -import { AssetTypeMapping, AssetStatusMapping } from '@vegaprotocol/assets'; +import { + useAssetTypeMapping, + useAssetStatusMapping, + type AssetFieldsFragment, +} from '@vegaprotocol/assets'; import { t } from '@vegaprotocol/i18n'; import { ButtonLink } from '@vegaprotocol/ui-toolkit'; -import type { AgGridReact } from 'ag-grid-react'; +import { type AgGridReact } from 'ag-grid-react'; import { AgGrid } from '@vegaprotocol/datagrid'; -import type { VegaICellRendererParams } from '@vegaprotocol/datagrid'; +import { type VegaICellRendererParams } from '@vegaprotocol/datagrid'; import { useRef, useLayoutEffect } from 'react'; import { BREAKPOINT_MD } from '../../config/breakpoints'; import { useNavigate } from 'react-router-dom'; -import type { RowClickedEvent, ColDef } from 'ag-grid-community'; +import { type RowClickedEvent, ColDef } from 'ag-grid-community'; type AssetsTableProps = { data: AssetFieldsFragment[] | null; }; export const AssetsTable = ({ data }: AssetsTableProps) => { + const assetTypeMapping = useAssetTypeMapping(); + const assetStatusMapping = useAssetStatusMapping(); const navigate = useNavigate(); const ref = useRef(null); const showColumnsOnDesktop = () => { @@ -47,14 +52,14 @@ export const AssetsTable = ({ data }: AssetsTableProps) => { field: 'source.__typename', hide: window.innerWidth < BREAKPOINT_MD, valueFormatter: ({ value }: { value?: string }) => - value ? AssetTypeMapping[value].value : '', + value ? assetTypeMapping[value].value : '', }, { headerName: t('Status'), field: 'status', hide: window.innerWidth < BREAKPOINT_MD, valueFormatter: ({ value }: { value?: string }) => - value ? AssetStatusMapping[value].value : '', + value ? assetStatusMapping[value].value : '', }, { colId: 'actions', @@ -69,7 +74,7 @@ export const AssetsTable = ({ data }: AssetsTableProps) => { }: VegaICellRendererParams) => value ? ( { + onClick={() => { navigate(value); }} > @@ -80,7 +85,7 @@ export const AssetsTable = ({ data }: AssetsTableProps) => { ), }, ], - [navigate] + [navigate, assetStatusMapping, assetTypeMapping] ); return ( diff --git a/apps/explorer/src/app/components/links/market-link/market-link.spec.tsx b/apps/explorer/src/app/components/links/market-link/market-link.spec.tsx index 9f67adf64..78240bdcb 100644 --- a/apps/explorer/src/app/components/links/market-link/market-link.spec.tsx +++ b/apps/explorer/src/app/components/links/market-link/market-link.spec.tsx @@ -91,6 +91,6 @@ describe('Market link component', () => { }; const res = render(renderComponent('123', [mock])); - expect(await res.findByText('123')).toBeInTheDocument(); + expect(await res.findByTitle('123')).toBeInTheDocument(); }); }); diff --git a/apps/explorer/src/app/components/markets/markets-table.tsx b/apps/explorer/src/app/components/markets/markets-table.tsx index fd02c4d59..0ecbe5769 100644 --- a/apps/explorer/src/app/components/markets/markets-table.tsx +++ b/apps/explorer/src/app/components/markets/markets-table.tsx @@ -2,18 +2,18 @@ import { useMemo } from 'react'; import { getAsset, type MarketFieldsFragment } from '@vegaprotocol/markets'; import { t } from '@vegaprotocol/i18n'; import { ButtonLink } from '@vegaprotocol/ui-toolkit'; -import type { AgGridReact } from 'ag-grid-react'; -import type { ColDef } from 'ag-grid-community'; +import { type AgGridReact } from 'ag-grid-react'; +import { type ColDef } from 'ag-grid-community'; import { AgGrid } from '@vegaprotocol/datagrid'; -import type { - VegaICellRendererParams, - VegaValueGetterParams, +import { + type VegaICellRendererParams, + type VegaValueGetterParams, } from '@vegaprotocol/datagrid'; import { useRef, useLayoutEffect } from 'react'; import { BREAKPOINT_MD } from '../../config/breakpoints'; import { MarketStateMapping } from '@vegaprotocol/types'; import { useAssetDetailsDialogStore } from '@vegaprotocol/assets'; -import type { RowClickedEvent } from 'ag-grid-community'; +import { type RowClickedEvent } from 'ag-grid-community'; import { Link, useNavigate } from 'react-router-dom'; type MarketsTableProps = { diff --git a/apps/explorer/src/app/components/order-details/amend-order-details.spec.tsx b/apps/explorer/src/app/components/order-details/amend-order-details.spec.tsx index 3314fdf3e..94696d296 100644 --- a/apps/explorer/src/app/components/order-details/amend-order-details.spec.tsx +++ b/apps/explorer/src/app/components/order-details/amend-order-details.spec.tsx @@ -17,7 +17,7 @@ function renderAmendOrderDetails( mocks: MockedResponse[] ) { return render( - + @@ -44,18 +44,18 @@ function renderExistingAmend( orderByID: { __typename: 'Order', id: '123', - type: 'GTT', + type: Schema.OrderType.TYPE_LIMIT, status: Schema.OrderStatus.STATUS_ACTIVE, - version: version, + version: version ? version.toString() : '', createdAt: '123', updatedAt: '456', expiresAt: '789', timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC, price: '200', - side: 'BUY', + side: Schema.Side.SIDE_BUY, peggedOrder: null, remaining: '99', - rejectionReason: 'rejection', + rejectionReason: Schema.OrderRejectionReason.ORDER_ERROR_NOT_FOUND, reference: '123', size: '100', party: { @@ -65,18 +65,15 @@ function renderExistingAmend( market: { __typename: 'Market', id: '789', - state: 'STATUS_ACTIVE', + state: Schema.MarketState.STATE_ACTIVE, positionDecimalPlaces: 2, - decimalPlaces: '5', + decimalPlaces: 0, tradableInstrument: { instrument: { name: 'test', product: { __typename: 'Future', quoteName: '123', - settlementAsset: { - decimals: 8, - }, }, }, }, @@ -97,18 +94,18 @@ function renderExistingAmend( orderByID: { __typename: 'Order', id: '123', - type: 'GTT', + type: Schema.OrderType.TYPE_LIMIT, status: Schema.OrderStatus.STATUS_ACTIVE, - version: 100, + version: '100', createdAt: '123', updatedAt: '456', expiresAt: '789', timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC, peggedOrder: null, price: '200', - side: 'BUY', + side: Schema.Side.SIDE_BUY, remaining: '99', - rejectionReason: 'rejection', + rejectionReason: Schema.OrderRejectionReason.ORDER_ERROR_NOT_FOUND, reference: '123', size: '200', party: { @@ -117,19 +114,16 @@ function renderExistingAmend( }, market: { __typename: 'Market', - id: 'amend-to-order-latest-version', - state: 'STATUS_ACTIVE', + id: '8888', + state: Schema.MarketState.STATE_ACTIVE, positionDecimalPlaces: 2, - decimalPlaces: '5', + decimalPlaces: 0, tradableInstrument: { instrument: { name: 'amend-to-order-latest-version-test', product: { __typename: 'Future', quoteName: '123', - settlementAsset: { - decimals: 8, - }, }, }, }, @@ -142,13 +136,13 @@ function renderExistingAmend( request: { query: ExplorerMarketDocument, variables: { - id: '789', + id: '8888', }, }, result: { data: { market: { - id: '789', + id: '8888', decimalPlaces: 5, positionDecimalPlaces: 2, state: 'irrelevant-test-data', @@ -225,12 +219,10 @@ describe('Amend order details', () => { it('Fetches latest version when version is not specified', async () => { const amend: Amend = { - price: '-7879', + price: '123', }; const res = renderExistingAmend('123', undefined, amend); - expect( - await res.findByText('amend-to-order-latest-version') - ).toBeInTheDocument(); + expect(await res.findByText('test-label')).toBeInTheDocument(); }); }); diff --git a/apps/explorer/src/app/components/order-details/amend-order-details.tsx b/apps/explorer/src/app/components/order-details/amend-order-details.tsx index 8a762c9da..7c603b0ad 100644 --- a/apps/explorer/src/app/components/order-details/amend-order-details.tsx +++ b/apps/explorer/src/app/components/order-details/amend-order-details.tsx @@ -46,10 +46,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
-

+

{t('Order not found')}

-

+

{t('No order created from this transaction')}

@@ -68,24 +68,24 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
-

+

{t('Edits to ')} {sideText[o.side]} {t(' order')}

-

+

In , updated at{' '}
-
+
{amend.sizeDelta && amend.sizeDelta !== '0' ? (
-

+

{t('New size')}

@@ -96,10 +96,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => { {amend.price && amend.price !== '0' ? (
-

+

{t('New price')}

-
+
@@ -108,10 +108,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => { {amend.peggedReference && amend.peggedReference !== 'PEGGED_REFERENCE_UNSPECIFIED' ? (
-

+

{t('New reference')}

-
+
{peggedReference[amend.peggedReference]}
@@ -119,10 +119,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => { {amend.peggedOffset ? (
-

+

{t('New offset')}

-
+
{amend.peggedOffset}
diff --git a/apps/explorer/src/app/components/proposals/proposals-table.tsx b/apps/explorer/src/app/components/proposals/proposals-table.tsx index 2bfb32992..dcf25e05c 100644 --- a/apps/explorer/src/app/components/proposals/proposals-table.tsx +++ b/apps/explorer/src/app/components/proposals/proposals-table.tsx @@ -1,14 +1,14 @@ -import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals'; +import { type ProposalListFieldsFragment } from '@vegaprotocol/proposals'; import { VoteProgress } from '@vegaprotocol/proposals'; -import type { AgGridReact } from 'ag-grid-react'; +import { type AgGridReact } from 'ag-grid-react'; import { ExternalLink } from '@vegaprotocol/ui-toolkit'; import { AgGrid } from '@vegaprotocol/datagrid'; -import type { - VegaICellRendererParams, - VegaValueFormatterParams, +import { + type VegaICellRendererParams, + type VegaValueFormatterParams, } from '@vegaprotocol/datagrid'; import { useLayoutEffect, useMemo, useRef, useState } from 'react'; -import type { RowClickedEvent, ColDef } from 'ag-grid-community'; +import { type RowClickedEvent, ColDef } from 'ag-grid-community'; import { getDateTimeFormat } from '@vegaprotocol/utils'; import { t } from '@vegaprotocol/i18n'; import { @@ -105,7 +105,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => { ? new BigNumber(0) : yesTokens.multipliedBy(100).dividedBy(totalTokensVoted); return ( -
+
{ return null; } - const { builtin, erc20, erc20Multisig, stakingEvent } = + const { builtin, erc20, erc20Multisig, stakingEvent, contractCall } = txData.command.chainEvent; // Builtin Asset events @@ -140,6 +141,10 @@ export const ChainEvent = ({ txData }: ChainEventProps) => { } } + if (contractCall) { + return ; + } + // If we hit this return, tx-shared-details should give a basic overview return null; }; diff --git a/apps/explorer/src/app/components/txs/details/chain-events/tx-contract-call.spec.tsx b/apps/explorer/src/app/components/txs/details/chain-events/tx-contract-call.spec.tsx new file mode 100644 index 000000000..5dde3e863 --- /dev/null +++ b/apps/explorer/src/app/components/txs/details/chain-events/tx-contract-call.spec.tsx @@ -0,0 +1,26 @@ +import { decodeEthCallResult } from './tx-contract-call'; +import { base64 } from 'ethers/lib/utils'; +import { defaultAbiCoder } from '@ethersproject/abi'; +import { BigNumber } from '@ethersproject/bignumber'; + +describe('decodeEthCallResult', () => { + it('should decode contractData correctly (mocked)', () => { + const mockContractData = base64.encode( + defaultAbiCoder.encode(['int256'], [BigNumber.from(123)]) + ); + const result = decodeEthCallResult(mockContractData); + expect(result).toBe('123'); + }); + + it('should decode contractData correctly (known data)', () => { + const mockContractData = 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADH8cueyY='; + const result = decodeEthCallResult(mockContractData); + expect(result).toBe('3435020581670'); + }); + + it('should return "-" when an error occurs', () => { + const mockContractData = 'invalid_data'; + const result = decodeEthCallResult(mockContractData); + expect(result).toBe('-'); + }); +}); diff --git a/apps/explorer/src/app/components/txs/details/chain-events/tx-contract-call.tsx b/apps/explorer/src/app/components/txs/details/chain-events/tx-contract-call.tsx new file mode 100644 index 000000000..f7c367eaf --- /dev/null +++ b/apps/explorer/src/app/components/txs/details/chain-events/tx-contract-call.tsx @@ -0,0 +1,88 @@ +import { TableCell, TableRow } from '../../../table'; +import { t } from '@vegaprotocol/i18n'; +import { + EthExplorerLink, + EthExplorerLinkTypes, +} from '../../../links/eth-explorer-link/eth-explorer-link'; +import type { components } from '../../../../../types/explorer'; +import { defaultAbiCoder, base64 } from 'ethers/lib/utils'; +import { BigNumber } from 'ethers'; +import OracleLink from '../../../links/oracle-link/oracle-link'; +import { useExplorerOracleSpecByIdQuery } from '../../../../routes/oracles/__generated__/Oracles'; +import { OracleEthSource } from '../../../../routes/oracles/components/oracle-eth-source'; + +/** + * Decodes the b64/ABIcoded result from an eth cal + * @param data + * @returns + */ +export function decodeEthCallResult(contractData: string): string { + try { + const rawResult = defaultAbiCoder.decode( + ['int256'], + base64.decode(contractData) + ); + + // Finally, convert the resulting BigNumber in to a string + const res = BigNumber.from(rawResult[0]).toString(); + return res; + } catch (e) { + return '-'; + } +} + +interface TxDetailsContractCallProps { + contractCall: components['schemas']['vegaEthContractCallEvent']; +} + +export const TxDetailsContractCall = ({ + contractCall, +}: TxDetailsContractCallProps) => { + const { data } = useExplorerOracleSpecByIdQuery({ + variables: { + id: contractCall.specId || '1', + }, + }); + + if (!contractCall || !contractCall.result) { + return null; + } + + return ( + <> + {contractCall.specId && ( + + {t('Oracle')} + + + + + )} + {contractCall.blockHeight && ( + + {t('ETH block')} + + + + + )} + {data?.oracleSpec?.dataSourceSpec && ( + + )} + + + {t('Result')} + {decodeEthCallResult(contractCall.result)} + + + ); +}; diff --git a/apps/explorer/src/app/components/txs/details/tx-chain-event.tsx b/apps/explorer/src/app/components/txs/details/tx-chain-event.tsx index 2b87a74aa..45ebc2448 100644 --- a/apps/explorer/src/app/components/txs/details/tx-chain-event.tsx +++ b/apps/explorer/src/app/components/txs/details/tx-chain-event.tsx @@ -1,51 +1,11 @@ import { t } from '@vegaprotocol/i18n'; import { TxDetailsShared } from './shared/tx-details-shared'; import { TableWithTbody } from '../../table'; -import { defaultAbiCoder, base64 } from 'ethers/lib/utils'; import { ChainEvent } from './chain-events'; -import { BigNumber } from 'ethers'; -import type { AbiType } from '../../../lib/encoders/abis/abi-types'; import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response'; import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response'; -interface AbiOutput { - type: AbiType; - internalType: AbiType; - name: string; -} - -/** - * Decodes the b64/ABIcoded result from an eth cal - * @param data - * @returns - */ -export function decodeEthCallResult( - data: BlockExplorerTransactionResult -): string { - const ethResult = data.command.chainEvent?.contractCall.result; - - try { - // Decode the result string: base64 => uint8array - const data = base64.decode(ethResult); - - // Parse the escaped ABI in to an object - const abi = JSON.parse( - '[{"inputs":[],"name":"latestAnswer","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"}]' - ); - // Pull the expected types out of the Oracles ABI - const types: AbiType[] = abi[0].outputs.map((o: AbiOutput) => o.type); - - const rawResult = defaultAbiCoder.decode(types, data); - - // Finally, convert the resulting BigNumber in to a string - const res = BigNumber.from(rawResult[0]).toString(); - return res; - } catch (e) { - return '-'; - } -} - interface TxDetailsChainEventProps { txData: BlockExplorerTransactionResult | undefined; pubKey: string | undefined; diff --git a/apps/explorer/src/app/components/txs/details/tx-details-wrapper.tsx b/apps/explorer/src/app/components/txs/details/tx-details-wrapper.tsx index f8292e9fd..6c6478d76 100644 --- a/apps/explorer/src/app/components/txs/details/tx-details-wrapper.tsx +++ b/apps/explorer/src/app/components/txs/details/tx-details-wrapper.tsx @@ -3,8 +3,8 @@ import { DATA_SOURCES } from '../../../config'; import { t } from '@vegaprotocol/i18n'; import { useFetch } from '@vegaprotocol/react-helpers'; import { TxDetailsOrder } from './tx-order'; -import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response'; -import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response'; +import { type BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response'; +import { type TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response'; import { TxDetailsHeartbeat } from './tx-hearbeat'; import { TxDetailsGeneric } from './tx-generic'; import { TxDetailsBatch } from './tx-batch'; diff --git a/apps/explorer/src/app/components/txs/txs-per-block.tsx b/apps/explorer/src/app/components/txs/txs-per-block.tsx index 63b9a76ef..b15a1fe0d 100644 --- a/apps/explorer/src/app/components/txs/txs-per-block.tsx +++ b/apps/explorer/src/app/components/txs/txs-per-block.tsx @@ -1,7 +1,7 @@ import { Table, TableRow } from '../table'; import { t } from '@vegaprotocol/i18n'; import { useFetch } from '@vegaprotocol/react-helpers'; -import type { BlockExplorerTransactions } from '../../routes/types/block-explorer-response'; +import { type BlockExplorerTransactions } from '../../routes/types/block-explorer-response'; import { getTxsDataUrl } from '../../hooks/get-txs-data-url'; import { AsyncRenderer, Loader } from '@vegaprotocol/ui-toolkit'; import EmptyList from '../empty-list/empty-list'; @@ -22,7 +22,7 @@ export const TxsPerBlock = ({ blockHeight, txCount }: TxsPerBlockProps) => { return ( {data && data.transactions.length > 0 ? ( -
+
diff --git a/apps/explorer/src/app/hooks/use-txs-data.ts b/apps/explorer/src/app/hooks/use-txs-data.ts index 13ab7fd98..7d8f638a8 100644 --- a/apps/explorer/src/app/hooks/use-txs-data.ts +++ b/apps/explorer/src/app/hooks/use-txs-data.ts @@ -1,14 +1,14 @@ import { useSearchParams } from 'react-router-dom'; -import type { URLSearchParamsInit } from 'react-router-dom'; +import { type URLSearchParamsInit } from 'react-router-dom'; import { useCallback } from 'react'; import { useFetch } from '@vegaprotocol/react-helpers'; -import type { - BlockExplorerTransactionResult, - BlockExplorerTransactions, +import { + type BlockExplorerTransactionResult, + type BlockExplorerTransactions, } from '../routes/types/block-explorer-response'; import isNumber from 'lodash/isNumber'; import { AllFilterOptions } from '../components/txs/tx-filter'; -import type { FilterOption } from '../components/txs/tx-filter'; +import { type FilterOption } from '../components/txs/tx-filter'; import { BE_TXS_PER_REQUEST, getTxsDataUrl } from './get-txs-data-url'; export function getTypeFilters(filters?: Set) { diff --git a/apps/explorer/src/app/routes/assets/asset-page.tsx b/apps/explorer/src/app/routes/assets/asset-page.tsx index 9288bafab..ccf949100 100644 --- a/apps/explorer/src/app/routes/assets/asset-page.tsx +++ b/apps/explorer/src/app/routes/assets/asset-page.tsx @@ -9,11 +9,13 @@ import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog'; import { useState } from 'react'; import { PageTitle } from '../../components/page-helpers/page-title'; +type Params = { assetId: string }; + export const AssetPage = () => { useDocumentTitle(['Assets']); useScrollToLocation(); - const { assetId } = useParams<{ assetId: string }>(); + const { assetId } = useParams(); const { data, loading, error } = useAssetDataProvider(assetId || ''); const title = data ? data.name : error ? t('Asset not found') : ''; @@ -41,7 +43,7 @@ export const AssetPage = () => { loading={loading} error={error} > -
+
diff --git a/apps/explorer/src/app/routes/blocks/home/index.tsx b/apps/explorer/src/app/routes/blocks/home/index.tsx index a92050a7d..abfa8f820 100644 --- a/apps/explorer/src/app/routes/blocks/home/index.tsx +++ b/apps/explorer/src/app/routes/blocks/home/index.tsx @@ -1,8 +1,8 @@ import { useCallback, useState } from 'react'; import { DATA_SOURCES } from '../../../config'; -import type { - BlockMeta, - TendermintBlockchainResponse, +import { + type BlockMeta, + type TendermintBlockchainResponse, } from '../tendermint-blockchain-response'; import { RouteTitle } from '../../../components/route-title'; import { BlocksRefetch } from '../../../components/blocks'; diff --git a/apps/explorer/src/app/routes/blocks/id/block.tsx b/apps/explorer/src/app/routes/blocks/id/block.tsx index 888988b0a..7d54a7461 100644 --- a/apps/explorer/src/app/routes/blocks/id/block.tsx +++ b/apps/explorer/src/app/routes/blocks/id/block.tsx @@ -17,8 +17,10 @@ import { NodeLink } from '../../../components/links'; import { useDocumentTitle } from '../../../hooks/use-document-title'; import EmptyList from '../../../components/empty-list/empty-list'; +type Params = { block: string }; + const Block = () => { - const { block } = useParams<{ block: string }>(); + const { block } = useParams(); useDocumentTitle(['Blocks', `Block #${block}`]); const { state: { data: blockData, loading, error }, @@ -29,7 +31,7 @@ const Block = () => { {t(`BLOCK ${block}`)} <> -
+
{ diff --git a/apps/explorer/src/app/routes/markets/market-page.tsx b/apps/explorer/src/app/routes/markets/market-page.tsx index dae69f227..4a1b21db3 100644 --- a/apps/explorer/src/app/routes/markets/market-page.tsx +++ b/apps/explorer/src/app/routes/markets/market-page.tsx @@ -11,10 +11,12 @@ import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog'; import { marketInfoWithDataProvider } from '@vegaprotocol/markets'; import { PageTitle } from '../../components/page-helpers/page-title'; +type Params = { marketId: string }; + export const MarketPage = () => { useScrollToLocation(); - const { marketId } = useParams<{ marketId: string }>(); + const { marketId } = useParams(); const { data, loading, error } = useDataProvider({ dataProvider: marketInfoWithDataProvider, diff --git a/apps/explorer/src/app/routes/oracles/components/oracle-markets.tsx b/apps/explorer/src/app/routes/oracles/components/oracle-markets.tsx index fa1bbd45e..0bb02e8b0 100644 --- a/apps/explorer/src/app/routes/oracles/components/oracle-markets.tsx +++ b/apps/explorer/src/app/routes/oracles/components/oracle-markets.tsx @@ -1,8 +1,10 @@ import { getNodes } from '@vegaprotocol/utils'; import { MarketLink } from '../../../components/links'; import { TableRow, TableCell, TableHeader } from '../../../components/table'; -import type { ExplorerOracleForMarketsMarketFragment } from '../__generated__/OraclesForMarkets'; -import { useExplorerOracleFormMarketsQuery } from '../__generated__/OraclesForMarkets'; +import { + useExplorerOracleFormMarketsQuery, + type ExplorerOracleForMarketsMarketFragment, +} from '../__generated__/OraclesForMarkets'; interface OracleMarketsProps { id: string; diff --git a/apps/explorer/src/app/routes/oracles/id/index.tsx b/apps/explorer/src/app/routes/oracles/id/index.tsx index de979d949..52ccdf4d4 100644 --- a/apps/explorer/src/app/routes/oracles/id/index.tsx +++ b/apps/explorer/src/app/routes/oracles/id/index.tsx @@ -9,8 +9,10 @@ import { AsyncRenderer, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit'; import filter from 'recursive-key-filter'; import { TruncateInline } from '../../../components/truncate/truncate'; +type Params = { id: string }; + export const Oracle = () => { - const { id } = useParams<{ id: string }>(); + const { id } = useParams(); useDocumentTitle(['Oracle', `Oracle #${truncateByChars(id || '1', 5, 5)}`]); diff --git a/apps/explorer/src/app/routes/parties/id/accounts/index.tsx b/apps/explorer/src/app/routes/parties/id/accounts/index.tsx index 1a7ba9aa7..40c37acd5 100644 --- a/apps/explorer/src/app/routes/parties/id/accounts/index.tsx +++ b/apps/explorer/src/app/routes/parties/id/accounts/index.tsx @@ -6,8 +6,10 @@ import { useDocumentTitle } from '../../../../hooks/use-document-title'; import { PartyAccounts } from '../components/party-accounts'; +type Params = { party: string }; + const PartyAccountsByAsset = () => { - const { party } = useParams<{ party: string }>(); + const { party } = useParams(); useDocumentTitle(['Public keys', party || '-']); const partyId = toNonHex(party ? party : ''); diff --git a/apps/explorer/src/app/routes/parties/id/components/party-accounts.tsx b/apps/explorer/src/app/routes/parties/id/components/party-accounts.tsx index 4edd52548..016fe6ae4 100644 --- a/apps/explorer/src/app/routes/parties/id/components/party-accounts.tsx +++ b/apps/explorer/src/app/routes/parties/id/components/party-accounts.tsx @@ -1,6 +1,7 @@ -import { AccountManager } from '@vegaprotocol/accounts'; -import { useCallback } from 'react'; -import { useAssetDetailsDialogStore } from '@vegaprotocol/assets'; +import { useExplorerPartyAssetsQuery } from '../__generated__/Party-assets'; +import { AssetLink, MarketLink } from '../../../../components/links'; +import AssetBalance from '../../../../components/asset-balance/asset-balance'; +import { AccountTypeMapping } from '@vegaprotocol/types'; interface PartyAccountsProps { partyId: string; @@ -12,21 +13,71 @@ interface PartyAccountsProps { * appearing first and... tbd */ export const PartyAccounts = ({ partyId }: PartyAccountsProps) => { - const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore(); - const onClickAsset = useCallback( - (assetId?: string) => { - assetId && openAssetDetailsDialog(assetId); - }, - [openAssetDetailsDialog] - ); + const { data } = useExplorerPartyAssetsQuery({ + variables: { partyId }, + }); + + const party = data?.partiesConnection?.edges[0]?.node; + const accounts = + party?.accountsConnection?.edges?.filter((edge) => edge?.node) || []; return (
- +
+ + + + + + + + + + {accounts + .sort((a, b) => { + // Sort by asset id, then market id, with general accounts first + if (!a) { + return 1; + } + if (!b) { + return -1; + } + if (a.node.asset.id !== b.node.asset.id) { + return a.node.asset.id.localeCompare(b.node.asset.id); + } + if (a.node.type === 'ACCOUNT_TYPE_GENERAL') return -1; + if (b.node.type === 'ACCOUNT_TYPE_GENERAL') return 1; + if (a.node.market && b.node.market) { + return a.node.market.id.localeCompare(b.node.market.id); + } else { + return a.node.type.localeCompare(b.node.type); + } + }) + .map((e) => { + if (!e) return null; + const { type, asset, balance, market } = e.node; + + return ( + + + + + + + ); + })} + +
BalanceTypeMarketAsset
+ + {AccountTypeMapping[type]} + {market?.id ? : '-'} + + +
); }; diff --git a/apps/explorer/src/app/routes/parties/id/index.tsx b/apps/explorer/src/app/routes/parties/id/index.tsx index 196616fed..319d69101 100644 --- a/apps/explorer/src/app/routes/parties/id/index.tsx +++ b/apps/explorer/src/app/routes/parties/id/index.tsx @@ -19,11 +19,13 @@ import type { FilterOption } from '../../../components/txs/tx-filter'; import { AllFilterOptions, TxsFilter } from '../../../components/txs/tx-filter'; import { useSearchParams } from 'react-router-dom'; +type Params = { party: string }; + const Party = () => { const [params] = useSearchParams(); const [filters, setFilters] = useState(new Set(AllFilterOptions)); - const { party } = useParams<{ party: string }>(); + const { party } = useParams(); useDocumentTitle(['Public keys', party || '-']); const navigate = useNavigate(); @@ -60,7 +62,7 @@ const Party = () => { if (!isValidPartyId(partyId)) { return ( -
+
{ truncateEnd={visibleChars} /> -
+
{ - const { txHash } = useParams<{ txHash: string }>(); + const { txHash } = useParams(); const hash = txHash ? toNonHex(txHash) : ''; let errorMessage: string | undefined = undefined; diff --git a/apps/explorer/tsconfig.app.json b/apps/explorer/tsconfig.app.json index 621db72d7..fcf58fcd6 100644 --- a/apps/explorer/tsconfig.app.json +++ b/apps/explorer/tsconfig.app.json @@ -2,7 +2,11 @@ "extends": "./tsconfig.json", "compilerOptions": { "outDir": "../../dist/out-tsc", - "types": ["node"] + "types": [ + "node", + "@nx/react/typings/cssmodule.d.ts", + "@nx/react/typings/image.d.ts" + ] }, "files": [ "../../node_modules/@nx/react/typings/cssmodule.d.ts", diff --git a/apps/explorer/tsconfig.spec.json b/apps/explorer/tsconfig.spec.json index f0cb466b1..a789290d7 100644 --- a/apps/explorer/tsconfig.spec.json +++ b/apps/explorer/tsconfig.spec.json @@ -3,7 +3,13 @@ "compilerOptions": { "outDir": "../../dist/out-tsc", "module": "commonjs", - "types": ["jest", "node", "@testing-library/jest-dom"] + "types": [ + "jest", + "node", + "@testing-library/jest-dom", + "@nx/react/typings/cssmodule.d.ts", + "@nx/react/typings/image.d.ts" + ] }, "include": [ "**/*.test.ts", diff --git a/apps/governance-e2e/.eslintrc.json b/apps/governance-e2e/.eslintrc.json index 696cb8b12..225e97426 100644 --- a/apps/governance-e2e/.eslintrc.json +++ b/apps/governance-e2e/.eslintrc.json @@ -1,10 +1,12 @@ { "extends": ["plugin:cypress/recommended", "../../.eslintrc.json"], - "ignorePatterns": ["!**/*"], + "ignorePatterns": ["!**/*", "cypress"], "overrides": [ { "files": ["*.ts", "*.tsx", "*.js", "*.jsx"], - "rules": {} + "rules": { + "cypress/unsafe-to-chain-command": 0 + } } ] } diff --git a/apps/governance-e2e/project.json b/apps/governance-e2e/project.json index 1b46e211e..b9cd50d0e 100644 --- a/apps/governance-e2e/project.json +++ b/apps/governance-e2e/project.json @@ -17,7 +17,7 @@ } }, "lint": { - "executor": "@nx/linter:eslint", + "executor": "@nx/eslint:lint", "outputs": ["{options.outputFile}"], "options": { "lintFilePatterns": ["apps/governance-e2e/**/*.{js,ts}"] diff --git a/apps/governance-e2e/src/integration/flow/proposal-details.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-details.cy.ts index c3a1a01ce..c57424cb7 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-details.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-details.cy.ts @@ -31,7 +31,7 @@ import { switchVegaWalletPubKey, vegaWalletSetSpecifiedApprovalAmount, } from '../../support/wallet-functions'; -import type { testFreeformProposal } from '../../support/common-interfaces'; +import { type testFreeformProposal } from '../../support/common-interfaces'; import { formatDateWithLocalTimezone } from '@vegaprotocol/utils'; import { createGovernanceTransferProposalTxBody, @@ -61,6 +61,7 @@ const marketProposalType = 'proposal-type'; describe( 'Governance flow for proposal details', { tags: '@slow' }, + // @ts-ignore clash between jest and cypress function () { before('connect wallets and set approval limit', function () { cy.visit('/'); @@ -78,6 +79,7 @@ describe( getProposalInformationFromTable('ID').invoke('text').as('parentMarketId'); }); + // @ts-ignore clash between jest and cypress beforeEach('visit proposals tab', function () { cy.clearLocalStorage(); turnTelemetryOff(); @@ -323,6 +325,7 @@ describe( }); }); cy.VegaWalletSubmitProposal( + // @ts-ignore this is any createSuccessorMarketProposalTxBody(this.parentMarketId) ); navigateTo(navigation.proposals); @@ -334,6 +337,7 @@ describe( cy.getByTestId(proposalTermsToggle).click(); cy.get('.language-json').within(() => { cy.get('.hljs-attr').should('contain.text', 'parentMarketId'); + // @ts-ignore this is any cy.get('.hljs-string').should('contain.text', this.parentMarketId); cy.get('.hljs-attr').should('contain.text', 'insurancePoolFraction'); cy.get('.hljs-string').should('contain.text', '0.75'); @@ -352,6 +356,7 @@ describe( validateProposalDetailsDiff( 'Parent Market ID', proposalChangeType.ADDED, + // @ts-ignore this is any this.parentMarketId ); validateProposalDetailsDiff( @@ -450,6 +455,7 @@ describe( const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2); submitUniqueRawProposal({ proposalBody: proposalPath, + // @ts-ignore this is any updateMarketId: this.parentMarketId, enactmentTimestamp: enactmentTimestamp, closingTimestamp: closingTimestamp, @@ -466,6 +472,7 @@ describe( cy.getByTestId('proposal-update-market-state').within(() => { getProposalInformationFromTable('Market ID') .invoke('text') + // @ts-ignore this is any .and('eq', this.parentMarketId); }); }); @@ -476,6 +483,7 @@ describe( const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2); submitUniqueRawProposal({ proposalBody: proposalPath, + // @ts-ignore this is any updateMarketId: this.parentMarketId, enactmentTimestamp: enactmentTimestamp, closingTimestamp: closingTimestamp, @@ -489,6 +497,7 @@ describe( cy.getByTestId('proposal-update-market-state').within(() => { getProposalInformationFromTable('Market ID') .invoke('text') + // @ts-ignore this is any .and('eq', this.parentMarketId); }); }); @@ -499,6 +508,7 @@ describe( const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2); submitUniqueRawProposal({ proposalBody: proposalPath, + // @ts-ignore this is any updateMarketId: this.parentMarketId, enactmentTimestamp: enactmentTimestamp, closingTimestamp: closingTimestamp, @@ -518,6 +528,7 @@ describe( cy.getByTestId('proposal-update-market-state').within(() => { getProposalInformationFromTable('Market ID') .invoke('text') + // @ts-ignore this is any .and('eq', this.parentMarketId); getProposalDetailsValue('Termination Price').should( 'contain.text', diff --git a/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts index e805f3b75..d10b13dad 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-enacted.cy.ts @@ -37,6 +37,7 @@ context( vegaWalletSetSpecifiedApprovalAmount('1000'); }); + // @ts-ignore clash between jest and cypress beforeEach('visit proposals', function () { cy.clearLocalStorage(); turnTelemetryOff(); diff --git a/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts index 4b16a2793..fbb115d34 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-flow.cy.ts @@ -34,7 +34,7 @@ import { vegaWalletTeardown, } from '../../support/wallet-functions'; import { ethereumWalletConnect } from '../../support/wallet-eth.functions'; -import type { testFreeformProposal } from '../../support/common-interfaces'; +import { type testFreeformProposal } from '../../support/common-interfaces'; const vegaWalletStakedBalances = 'vega-wallet-balance-staked-validators'; const vegaWalletAssociatedBalance = 'associated-amount'; @@ -78,6 +78,7 @@ context( vegaWalletSetSpecifiedApprovalAmount('1000'); }); + // @ts-ignore clash between jest and cypress beforeEach('visit governance tab', function () { cy.clearLocalStorage(); turnTelemetryOff(); @@ -301,6 +302,7 @@ context( cy.getByTestId(voteButtons).should('not.exist'); cy.getByTestId('min-proposal-requirements').should( 'have.text', + // @ts-ignore this is any `You must have at least ${this.minVoterBalance} VEGA associated to vote on this proposal` ); }); diff --git a/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts index fafc7f5a1..95fdb8611 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-forms.cy.ts @@ -70,6 +70,7 @@ context( vegaWalletSetSpecifiedApprovalAmount('1000'); }); + // @ts-ignore clash between jest and cypress beforeEach('visit governance tab', function () { cy.clearLocalStorage(); turnTelemetryOff(); @@ -216,6 +217,7 @@ context( // 3003-PMAN-001 it( 'Able to submit valid new market proposal', + // @ts-ignore clash between jest and cypress { tags: '@smoke' }, function () { const proposalTitle = 'Test new market proposal'; @@ -631,6 +633,7 @@ context( ); cy.fixture('/proposals/successor-market').then((newMarketProposal) => { newMarketProposal.changes.successor.parentMarketId = + // @ts-ignore clash between jest and cypress this.parentMarketId; const newMarketPayload = JSON.stringify(newMarketProposal); cy.getByTestId(newProposalTerms).type(newMarketPayload, { @@ -658,6 +661,7 @@ context( .should('have.text', 'Successor market to: TEST.24h') .find('a') .should('have.attr', 'href') + // @ts-ignore clash between jest and cypress .and('contain', this.parentMarketId); }); }); diff --git a/apps/governance-e2e/src/integration/flow/proposal-list.cy.ts b/apps/governance-e2e/src/integration/flow/proposal-list.cy.ts index 59d1b88da..e94c8200e 100644 --- a/apps/governance-e2e/src/integration/flow/proposal-list.cy.ts +++ b/apps/governance-e2e/src/integration/flow/proposal-list.cy.ts @@ -1,4 +1,4 @@ -import type { testFreeformProposal } from '../../support/common-interfaces'; +import { type testFreeformProposal } from '../../support/common-interfaces'; import { navigateTo, navigation, @@ -33,12 +33,14 @@ const voteMajorityNotMet = 'token-majority-not-met'; const voteMajorityMet = 'token-majority-met'; const votesForPercentage = 'votes-for-percentage'; +// @ts-ignore clash between jest and cypress describe('Governance flow for proposal list', { tags: '@slow' }, function () { before('connect wallets and set approval limit', function () { vegaWalletSetSpecifiedApprovalAmount('1000'); cy.visit('/'); }); + // @ts-ignore clash between jest and cypress beforeEach('visit proposals tab', function () { cy.clearLocalStorage(); turnTelemetryOff(); @@ -106,6 +108,7 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () { it('Newly created proposals list - shows open proposals in an open state', function () { // 3001-VOTE-004 // 3001-VOTE-035 + // @ts-ignore clash between jest and cypress createRawProposal(this.minProposerBalance); cy.get('@rawProposal').then((rawProposal) => { getProposalFromTitle(rawProposal.rationale.title).within(() => { diff --git a/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts b/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts index f41bab520..6c5c1f298 100644 --- a/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/staking-flow.cy.ts @@ -64,6 +64,7 @@ context( describe('Eth wallet - contains VEGA tokens', function () { beforeEach( + // @ts-ignore clash between jest and cypress 'teardown wallet & drill into a specific validator', function () { cy.clearLocalStorage(); @@ -237,6 +238,7 @@ context( // 1002-STKE-041 1002-STKE-053 it( 'Able to remove part of a stake against a validator', + // @ts-ignore clash between jest and cypress { tags: '@smoke' }, function () { ensureSpecifiedUnstakedTokensAreAssociated('4'); diff --git a/apps/governance-e2e/src/integration/flow/token-association-flow.cy.ts b/apps/governance-e2e/src/integration/flow/token-association-flow.cy.ts index 540dc87fb..af57804e5 100644 --- a/apps/governance-e2e/src/integration/flow/token-association-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/token-association-flow.cy.ts @@ -52,6 +52,7 @@ context( describe('Eth wallet - contains VEGA tokens', function () { beforeEach( + // @ts-ignore clash between jest and cypress 'teardown wallet & drill into a specific validator', function () { cy.clearLocalStorage(); @@ -67,6 +68,7 @@ context( it( 'Able to associate tokens - from wallet', + // @ts-ignore clash between jest and cypress { tags: '@smoke' }, function () { //1004-ASSO-003 diff --git a/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts b/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts index 61a469e87..9013ffef6 100644 --- a/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts +++ b/apps/governance-e2e/src/integration/flow/withdrawal-flow.cy.ts @@ -48,6 +48,7 @@ context( depositAsset(usdcEthAddress, '1000', 5); }); + // @ts-ignore clash between jest and cypress beforeEach('Navigate to withdrawal page', function () { cy.clearLocalStorage(); turnTelemetryOff(); @@ -101,6 +102,7 @@ context( // eslint-disable-next-line it.skip( 'Able to withdraw asset: -eth wallet connected -withdraw funds button', + // @ts-ignore clash between jest and cypress { tags: '@smoke' }, function () { // fill in withdrawal form diff --git a/apps/governance-e2e/src/integration/view/pubkey-view.cy.ts b/apps/governance-e2e/src/integration/view/pubkey-view.cy.ts index edd20d669..fe3a5fbe6 100644 --- a/apps/governance-e2e/src/integration/view/pubkey-view.cy.ts +++ b/apps/governance-e2e/src/integration/view/pubkey-view.cy.ts @@ -25,6 +25,7 @@ context('View functionality with public key', { tags: '@smoke' }, function () { ); }); + // @ts-ignore clash between jest and cypress beforeEach('visit home page', function () { cy.clearLocalStorage(); turnTelemetryOff(); diff --git a/apps/governance-e2e/src/integration/view/rewards.cy.ts b/apps/governance-e2e/src/integration/view/rewards.cy.ts index 6100f9838..3db50cfb9 100644 --- a/apps/governance-e2e/src/integration/view/rewards.cy.ts +++ b/apps/governance-e2e/src/integration/view/rewards.cy.ts @@ -52,6 +52,7 @@ context( .invoke('text') .then(($newPageNumber) => { const newPageNumber = Number($newPageNumber.slice(5)); + // @ts-ignore clash between jest and cypress expect(newPageNumber).to.be.greaterThan(currentPageNumber); cy.getByTestId('goto-previous-page').click(); cy.getByTestId('page-info').should( diff --git a/apps/governance-e2e/src/integration/view/validators.cy.ts b/apps/governance-e2e/src/integration/view/validators.cy.ts index 496a29069..791bf01d4 100644 --- a/apps/governance-e2e/src/integration/view/validators.cy.ts +++ b/apps/governance-e2e/src/integration/view/validators.cy.ts @@ -44,6 +44,7 @@ context('Validators Page - verify elements on page', function () { cy.mockChainId(); }); + // @ts-ignore clash between jest and cypress describe('with wallets disconnected', { tags: '@smoke' }, function () { it('Should have validators tab highlighted', function () { verifyTabHighlighted(navigation.validators); @@ -76,6 +77,7 @@ context('Validators Page - verify elements on page', function () { describe( 'Should be able to see validator list from the staking page', { tags: '@regression' }, + // @ts-ignore clash between jest and cypress function () { // 1002-STKE-050 it('Should be able to see validator names', function () { @@ -180,6 +182,7 @@ context('Validators Page - verify elements on page', function () { describe( 'Should be able to see static information about a validator', { tags: '@smoke' }, + // @ts-ignore clash between jest and cypress function () { before('connect wallets and click on validator', function () { cy.mockChainId(); diff --git a/apps/governance-e2e/src/integration/view/wallet-eth.cy.ts b/apps/governance-e2e/src/integration/view/wallet-eth.cy.ts index 503ee7e1b..5e1f3276d 100644 --- a/apps/governance-e2e/src/integration/view/wallet-eth.cy.ts +++ b/apps/governance-e2e/src/integration/view/wallet-eth.cy.ts @@ -198,6 +198,7 @@ context( }); }) .then(function () { + // @ts-ignore clash between jest and cypress expect(parseFloat(this.value).toFixed(1)).to.equal( (Math.round((this.locked + this.unlocked) * 100) / 100).toFixed( 1 @@ -270,6 +271,7 @@ context( }); }) .then(function () { + // @ts-ignore clash between jest and cypress expect(this.value).to.equal(this.locked + this.unlocked); }); }); diff --git a/apps/governance-e2e/src/integration/view/wallet-vega.cy.ts b/apps/governance-e2e/src/integration/view/wallet-vega.cy.ts index eec6a3c77..58011cc60 100644 --- a/apps/governance-e2e/src/integration/view/wallet-vega.cy.ts +++ b/apps/governance-e2e/src/integration/view/wallet-vega.cy.ts @@ -105,6 +105,7 @@ context( // 0002-WCON-008 it( 'should have truncated account number visible', + // @ts-ignore clash between jest and cypress { tags: '@smoke' }, function () { cy.get(walletContainer).within(() => { @@ -125,6 +126,7 @@ context( it( 'should have Vega Associated currency value visible', + // @ts-ignore clash between jest and cypress { tags: '@smoke' }, function () { cy.get(walletContainer).within(() => { @@ -135,14 +137,19 @@ context( } ); - it('should have Unstaked value visible', { tags: '@smoke' }, function () { - cy.get(walletContainer).within(() => { - cy.get(vegaUnstaked) - .should('be.visible') - .invoke('text') - .and('not.be.empty'); - }); - }); + it( + 'should have Unstaked value visible', + // @ts-ignore clash between jest and cypress + { tags: '@smoke' }, + function () { + cy.get(walletContainer).within(() => { + cy.get(vegaUnstaked) + .should('be.visible') + .invoke('text') + .and('not.be.empty'); + }); + } + ); it('should have Governance button visible', function () { cy.get(walletContainer).within(() => { @@ -302,10 +309,10 @@ context( '[data-account-type="account_type_general"] [data-value]' ).should((elementAmount) => { const displayedAmount = parseFloat(elementAmount.text()); + // @ts-ignore clash between jest and cypress expect(displayedAmount).be.gte(expectedAmount); }); }); - cy.getByTestId(vegaWalletCurrencyTitle) .contains(name) .parent() diff --git a/apps/governance/project.json b/apps/governance/project.json index 82b9cd991..8661b816c 100644 --- a/apps/governance/project.json +++ b/apps/governance/project.json @@ -56,7 +56,7 @@ } }, "lint": { - "executor": "@nx/linter:eslint", + "executor": "@nx/eslint:lint", "outputs": ["{options.outputFile}"], "options": { "lintFilePatterns": ["apps/governance/**/*.{ts,tsx,js,jsx}"] @@ -66,14 +66,7 @@ "executor": "@nx/jest:jest", "outputs": ["{workspaceRoot}/coverage/apps/governance"], "options": { - "jestConfig": "apps/governance/jest.config.ts", - "passWithNoTests": true - }, - "configurations": { - "ci": { - "ci": true, - "codeCoverage": true - } + "jestConfig": "apps/governance/jest.config.ts" } }, "build-netlify": { diff --git a/apps/governance/src/app-loader.tsx b/apps/governance/src/app-loader.tsx index 150ecac4b..7536cc519 100644 --- a/apps/governance/src/app-loader.tsx +++ b/apps/governance/src/app-loader.tsx @@ -4,7 +4,7 @@ import { Splash } from '@vegaprotocol/ui-toolkit'; import { useVegaWallet, useEagerConnect } from '@vegaprotocol/wallet'; import { FLAGS, useEnvironment } from '@vegaprotocol/environment'; import { useWeb3React } from '@web3-react/core'; -import React from 'react'; +import React, { Suspense } from 'react'; import { useTranslation } from 'react-i18next'; import { SplashError } from './components/splash-error'; @@ -164,13 +164,14 @@ export const AppLoader = ({ children }: { children: React.ReactElement }) => { ); } - if (!loaded) { - return ( - - - - ); - } + const loading = ( + + + + ); - return children; + if (!loaded) { + return loading; + } + return {children}; }; diff --git a/apps/governance/src/app.tsx b/apps/governance/src/app.tsx index 39f77bd65..56b35ccee 100644 --- a/apps/governance/src/app.tsx +++ b/apps/governance/src/app.tsx @@ -42,6 +42,7 @@ import { useNodeSwitcherStore, DocsLinks, NodeFailure, + AppLoader as Loader, } from '@vegaprotocol/environment'; import { ENV } from './config'; import type { InMemoryCacheConfig } from '@apollo/client'; @@ -352,9 +353,11 @@ function App() { useInitializeEnv(); return ( - - - + }> + + + + ); } diff --git a/apps/governance/src/assets/locales b/apps/governance/src/assets/locales new file mode 120000 index 000000000..5f39c8875 --- /dev/null +++ b/apps/governance/src/assets/locales @@ -0,0 +1 @@ +../../../../libs/i18n/src/locales \ No newline at end of file diff --git a/apps/governance/src/components/vega-wallet/hooks.ts b/apps/governance/src/components/vega-wallet/hooks.ts index ebc8468be..38f9f9d10 100644 --- a/apps/governance/src/components/vega-wallet/hooks.ts +++ b/apps/governance/src/components/vega-wallet/hooks.ts @@ -10,7 +10,7 @@ import noIcon from '../../images/token-no-icon.png'; import vegaBlack from '../../images/vega_black.png'; import vegaVesting from '../../images/vega_vesting.png'; import { BigNumber } from '../../lib/bignumber'; -import type { WalletCardAssetProps } from '../wallet-card'; +import { type WalletCardAssetProps } from '../wallet-card'; import { useVegaWallet } from '@vegaprotocol/wallet'; import { useContracts } from '../../contexts/contracts/contracts-context'; import * as Schema from '@vegaprotocol/types'; @@ -21,12 +21,12 @@ import { toBigNum, } from '@vegaprotocol/utils'; import { useAppState } from '../../contexts/app-state/app-state-context'; -import type { - DelegationsQuery, - DelegationsQueryVariables, - WalletDelegationFieldsFragment, +import { + DelegationsDocument, + type DelegationsQuery, + type DelegationsQueryVariables, + type WalletDelegationFieldsFragment, } from './__generated__/Delegations'; -import { DelegationsDocument } from './__generated__/Delegations'; import { isPartyNotFoundError } from '../../lib/party'; export const usePollForDelegations = () => { @@ -44,6 +44,7 @@ export const usePollForDelegations = () => { const [delegatedNodes, setDelegatedNodes] = React.useState< { nodeId: string; + // eslint-disable-next-line name: string; hasStakePending: boolean; currentEpochStake?: BigNumber; diff --git a/apps/governance/src/contexts/contracts/contracts-provider.tsx b/apps/governance/src/contexts/contracts/contracts-provider.tsx index f4a4c470f..d416a674b 100644 --- a/apps/governance/src/contexts/contracts/contracts-provider.tsx +++ b/apps/governance/src/contexts/contracts/contracts-provider.tsx @@ -9,7 +9,7 @@ import { useWeb3React } from '@web3-react/core'; import React from 'react'; import { SplashLoader } from '../../components/splash-loader'; -import type { ContractsContextShape } from './contracts-context'; +import { type ContractsContextShape } from './contracts-context'; import { ContractsContext } from './contracts-context'; import { createDefaultProvider } from '../../lib/web3-connectors'; import { useEthereumConfig } from '@vegaprotocol/web3'; diff --git a/apps/governance/src/i18n/index.ts b/apps/governance/src/i18n/index.ts index ce094b69e..0f2c9b12e 100644 --- a/apps/governance/src/i18n/index.ts +++ b/apps/governance/src/i18n/index.ts @@ -1,29 +1,41 @@ +import type { Module } from 'i18next'; import i18n from 'i18next'; +import HttpBackend from 'i18next-http-backend'; +import LocizeBackend from 'i18next-locize-backend'; import LanguageDetector from 'i18next-browser-languagedetector'; import { initReactI18next } from 'react-i18next'; -import dev from './translations/dev.json'; +const isInDev = process.env.NODE_ENV === 'development'; +const useLocize = isInDev && !!process.env.NX_USE_LOCIZE; + +const backend = useLocize + ? { + projectId: '96ac1231-4bdd-455a-b9d7-f5322a2e7430', + apiKey: process.env.NX_LOCIZE_API_KEY, + referenceLng: 'en', + } + : { + loadPath: '/assets/locales/{{lng}}/{{ns}}.json', + }; + +const Backend: Module = useLocize ? LocizeBackend : HttpBackend; i18n + .use(Backend) .use(LanguageDetector) .use(initReactI18next) .init({ - // we init with resources - resources: { - en: { - translations: { - ...dev, - }, - }, - }, - lng: undefined, + lng: 'en', fallbackLng: 'en', - debug: true, + supportedLngs: ['en'], + load: 'languageOnly', + debug: isInDev, // have a common namespace used around the full app - ns: ['translations'], - defaultNS: 'translations', + ns: ['governance'], + defaultNS: 'governance', keySeparator: false, // we use content as keys - + backend, + saveMissing: useLocize && !!process.env.NX_LOCIZE_API_KEY, interpolation: { escapeValue: false, }, diff --git a/apps/governance/src/routes/proposals/components/list-asset/list-asset.tsx b/apps/governance/src/routes/proposals/components/list-asset/list-asset.tsx index c4dc20d62..41b49a713 100644 --- a/apps/governance/src/routes/proposals/components/list-asset/list-asset.tsx +++ b/apps/governance/src/routes/proposals/components/list-asset/list-asset.tsx @@ -1,4 +1,4 @@ -import type { CollateralBridge } from '@vegaprotocol/smart-contracts'; +import { type CollateralBridge } from '@vegaprotocol/smart-contracts'; import * as Schema from '@vegaprotocol/types'; import { Button } from '@vegaprotocol/ui-toolkit'; import { useBridgeContract, useEthereumTransaction } from '@vegaprotocol/web3'; @@ -88,7 +88,7 @@ export const ListAsset = ({ assetData.erc20ListAssetBundle; return (
-

{t('ListAsset')}

+

{t('ListAsset')}

{t('ListAssetDescription')}

)} -

{t('OR')}

+

{t('OR')}

{ const { account: address } = useWeb3React(); const { vesting } = useContracts(); @@ -34,7 +36,7 @@ export const RedeemFromTranche = () => { tranches: state.tranches, getTranches: state.getTranches, })); - const { id } = useParams<{ id: string }>(); + const { id } = useParams(); const numberId = Number(id); const tranche = React.useMemo( () => tranches?.find(({ tranche_id }) => tranche_id === numberId) || null, @@ -86,7 +88,7 @@ export const RedeemFromTranche = () => { i18nKey="noVestingTokens" components={{ tranchesLink: ( - + ), }} /> @@ -128,13 +130,13 @@ export const RedeemFromTranche = () => { components={{ stakingLink: ( ), governanceLink: ( ), diff --git a/apps/governance/src/routes/staking/associate/hooks.ts b/apps/governance/src/routes/staking/associate/hooks.ts index 394fb7918..d42fe8b09 100644 --- a/apps/governance/src/routes/staking/associate/hooks.ts +++ b/apps/governance/src/routes/staking/associate/hooks.ts @@ -11,12 +11,12 @@ import { useTransaction } from '../../../hooks/use-transaction'; import { useAppState } from '../../../contexts/app-state/app-state-context'; import { removeDecimal, removePaginationWrapper } from '@vegaprotocol/utils'; import * as Schema from '@vegaprotocol/types'; -import type { - LinkingsFieldsFragment, - PartyStakeLinkingsQuery, - PartyStakeLinkingsQueryVariables, +import { + PartyStakeLinkingsDocument, + type LinkingsFieldsFragment, + type PartyStakeLinkingsQuery, + type PartyStakeLinkingsQueryVariables, } from './__generated__/PartyStakeLinkings'; -import { PartyStakeLinkingsDocument } from './__generated__/PartyStakeLinkings'; export const useAddStake = ( address: string, diff --git a/apps/governance/src/routes/staking/home/validator-tables/consensus-validators-table.tsx b/apps/governance/src/routes/staking/home/validator-tables/consensus-validators-table.tsx index 2a07ddc76..6fb29be83 100644 --- a/apps/governance/src/routes/staking/home/validator-tables/consensus-validators-table.tsx +++ b/apps/governance/src/routes/staking/home/validator-tables/consensus-validators-table.tsx @@ -26,9 +26,9 @@ import { ValidatorRenderer, VotingPowerRenderer, } from './shared'; -import type { AgGridReact } from 'ag-grid-react'; -import type { ColDef, RowHeightParams } from 'ag-grid-community'; -import type { ValidatorsTableProps } from './shared'; +import { type AgGridReact } from 'ag-grid-react'; +import { type ColDef, type RowHeightParams } from 'ag-grid-community'; +import { type ValidatorsTableProps } from './shared'; import { formatNumber, formatNumberPercentage, @@ -83,19 +83,19 @@ const TopThirdCellRenderer = ( e.preventDefault(); setHideTopThird(false); }} - className="grid grid-cols-[60px_1fr] w-full h-full py-4 px-0 text-sm text-white text-center overflow-scroll" + className="grid h-full w-full grid-cols-[60px_1fr] overflow-scroll px-0 py-4 text-center text-sm text-white" > -
+
{params?.data?.rankingDisplay}
-
+