Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f84fad1ccd | ||
|
|
b1549c8a81 |
+1
-3
@@ -73,11 +73,9 @@
|
||||
"error",
|
||||
{
|
||||
"prefer": "type-imports",
|
||||
"disallowTypeAnnotations": true,
|
||||
"fixStyle": "inline-type-imports"
|
||||
"disallowTypeAnnotations": true
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-useless-constructor": 0,
|
||||
"curly": ["error", "multi-line"]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
* text eol=lf
|
||||
*.png binary
|
||||
*.ico binary
|
||||
*.woff2 binary
|
||||
|
||||
@@ -34,7 +34,7 @@ jobs:
|
||||
${{ runner.os }}-cache-node-modules-
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v3
|
||||
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@v4
|
||||
uses: actions/setup-node@v3
|
||||
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@v4
|
||||
uses: actions/setup-node@v3
|
||||
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@v4
|
||||
uses: actions/setup-node@v3
|
||||
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) trading e2e python'
|
||||
name: '(CI) console 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')
|
||||
|
||||
@@ -10,7 +10,7 @@ on:
|
||||
inputs:
|
||||
console-test-branch:
|
||||
type: choice
|
||||
description: 'main: v0.73.5, develop: v0.73.5'
|
||||
description: 'main: v0.72.14, develop: v0.73.0-preview7'
|
||||
options:
|
||||
- main
|
||||
- develop
|
||||
@@ -32,9 +32,9 @@ jobs:
|
||||
# cache node modules
|
||||
#----------------------------------------------
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
node-version: '16'
|
||||
cache: yarn
|
||||
|
||||
- name: Cache node modules
|
||||
@@ -153,19 +153,25 @@ jobs:
|
||||
run: |
|
||||
docker load --input /tmp/console-image.tar
|
||||
docker image ls -a
|
||||
|
||||
#----------------------------------------------
|
||||
# check-out frontend-monorepo
|
||||
# check-out tests repo
|
||||
#----------------------------------------------
|
||||
- name: Checkout frontend-monorepo
|
||||
- name: Checkout console test repo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
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
|
||||
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
|
||||
|
||||
#----------------------------------------------
|
||||
# ----- Setup python -----
|
||||
#----------------------------------------------
|
||||
@@ -188,25 +194,22 @@ 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 playwrightworking-directory: apps/trading/e2e
|
||||
# install playwright
|
||||
#----------------------------------------------
|
||||
- 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
|
||||
#----------------------------------------------
|
||||
@@ -215,7 +218,7 @@ jobs:
|
||||
if: always()
|
||||
with:
|
||||
name: playwright-trace
|
||||
path: apps/trading/e2e/traces/
|
||||
path: ./traces/
|
||||
retention-days: 15
|
||||
#----------------------------------------------
|
||||
# ----- upload logs -----
|
||||
|
||||
@@ -18,11 +18,11 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Use Node.js 20
|
||||
- name: Use Node.js 16
|
||||
id: Node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
node-version: 16.15.1
|
||||
|
||||
- name: Run Cypress tests
|
||||
uses: cypress-io/github-action@v4
|
||||
|
||||
@@ -57,14 +57,6 @@ 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
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
|
||||
@@ -18,13 +18,13 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
node-version: 16
|
||||
|
||||
- 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
|
||||
|
||||
@@ -93,7 +93,7 @@ jobs:
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v4
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
|
||||
+1
-8
@@ -48,15 +48,8 @@ cypress.env.json
|
||||
# Next.js
|
||||
.next
|
||||
|
||||
# cypress
|
||||
#cypress
|
||||
/apps/**/cypress/reports/
|
||||
/apps/**/cypress/downloads/
|
||||
/apps/**/fixtures/wallet/node**
|
||||
|
||||
# apps/trading/e2e
|
||||
__pycache__/
|
||||
apps/trading/e2e/logs/
|
||||
apps/trading/e2e/.pytest_cache/
|
||||
apps/trading/e2e/traces/
|
||||
|
||||
.nx/
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
# Auto-format all files
|
||||
yarn nx format:write
|
||||
|
||||
# Lint all staged files
|
||||
yarn lint-staged
|
||||
|
||||
+3
-3
@@ -1,8 +1,8 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
# Lint all staged files - this brings more value as pre-commit
|
||||
# yarn nx format:check
|
||||
# Lint all staged files
|
||||
yarn nx format:check
|
||||
|
||||
# Test all projects with changes
|
||||
# yarn nx affected -t test --exclude trading
|
||||
yarn nx affected -t test --exclude trading
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
# Add files here to ignore them from prettier formatting
|
||||
|
||||
/dist
|
||||
/dist-result
|
||||
/coverage
|
||||
__generated__
|
||||
__generated___
|
||||
@@ -9,15 +8,3 @@ __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
|
||||
|
||||
# apps/trading/e2e
|
||||
__pycache__/
|
||||
apps/trading/e2e/logs/
|
||||
apps/trading/e2e/.pytest_cache/
|
||||
apps/trading/e2e/traces/
|
||||
.pytest_cache/
|
||||
|
||||
@@ -1,4 +1,2 @@
|
||||
* @vegaprotocol/frontend
|
||||
apps/ @vegaprotocol/frontend-qa
|
||||
libs/ @vegaprotocol/frontend-qa
|
||||
*.graphql @vegaprotocol/core
|
||||
|
||||
@@ -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=20.9.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=16.5.1 --build-arg ENV_NAME=mainnet -t [TAG] -f docker/node-inside-docker.Dockerfile .
|
||||
```
|
||||
|
||||
### Computing ipfs-hash of the build
|
||||
|
||||
@@ -4,9 +4,7 @@
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {
|
||||
"cypress/unsafe-to-chain-command": 0
|
||||
}
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/eslint:lint",
|
||||
"executor": "@nx/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/explorer-e2e/**/*.{js,ts}"]
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[[redirects]]
|
||||
from = "/*"
|
||||
to = "/index.html"
|
||||
status = 200
|
||||
@@ -53,7 +53,7 @@
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/eslint:lint",
|
||||
"executor": "@nx/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/explorer/**/*.{ts,tsx,js,jsx}"]
|
||||
@@ -63,7 +63,14 @@
|
||||
"executor": "@nx/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/apps/explorer"],
|
||||
"options": {
|
||||
"jestConfig": "apps/explorer/jest.config.ts"
|
||||
"jestConfig": "apps/explorer/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"ci": true,
|
||||
"codeCoverage": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"generate-types": {
|
||||
@@ -74,6 +81,15 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"build-netlify": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
"cp apps/explorer/netlify.toml netlify.toml",
|
||||
"nx build explorer"
|
||||
]
|
||||
}
|
||||
},
|
||||
"build-spec": {
|
||||
"executor": "nx:run-commands",
|
||||
"outputs": [],
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import '../i18n';
|
||||
import {
|
||||
NetworkLoader,
|
||||
NodeFailure,
|
||||
@@ -12,8 +11,7 @@ import { TendermintWebsocketProvider } from './contexts/websocket/tendermint-web
|
||||
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { DEFAULT_CACHE_CONFIG } from '@vegaprotocol/apollo-client';
|
||||
import { RouterProvider } from 'react-router-dom';
|
||||
import { useRouterConfig } from './routes/router-config';
|
||||
import { createBrowserRouter } from 'react-router-dom';
|
||||
import { router } from './routes/router-config';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { Suspense } from 'react';
|
||||
|
||||
@@ -30,27 +28,20 @@ function App() {
|
||||
);
|
||||
return (
|
||||
<TendermintWebsocketProvider>
|
||||
<Suspense fallback={splashLoading}>
|
||||
<NetworkLoader cache={DEFAULT_CACHE_CONFIG}>
|
||||
<NodeGuard
|
||||
skeleton={<div>{t('Loading')}</div>}
|
||||
failure={
|
||||
<NodeFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />
|
||||
}
|
||||
>
|
||||
<Suspense fallback={splashLoading}>
|
||||
<RouterProvider
|
||||
router={createBrowserRouter(useRouterConfig())}
|
||||
fallbackElement={splashLoading}
|
||||
/>
|
||||
</Suspense>
|
||||
</NodeGuard>
|
||||
<NodeSwitcherDialog
|
||||
open={nodeSwitcherOpen}
|
||||
setOpen={setNodeSwitcherOpen}
|
||||
/>
|
||||
</NetworkLoader>
|
||||
</Suspense>
|
||||
<NetworkLoader cache={DEFAULT_CACHE_CONFIG}>
|
||||
<NodeGuard
|
||||
skeleton={<div>{t('Loading')}</div>}
|
||||
failure={<NodeFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />}
|
||||
>
|
||||
<Suspense fallback={splashLoading}>
|
||||
<RouterProvider router={router} fallbackElement={splashLoading} />
|
||||
</Suspense>
|
||||
</NodeGuard>
|
||||
<NodeSwitcherDialog
|
||||
open={nodeSwitcherOpen}
|
||||
setOpen={setNodeSwitcherOpen}
|
||||
/>
|
||||
</NetworkLoader>
|
||||
</TendermintWebsocketProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useAssetDataProvider } from '@vegaprotocol/assets';
|
||||
import { addDecimalsFixedFormatNumber } from '@vegaprotocol/utils';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
import { AssetLink } from '../links';
|
||||
|
||||
export type AssetBalanceProps = {
|
||||
@@ -23,12 +23,12 @@ const AssetBalance = ({
|
||||
|
||||
const label =
|
||||
!loading && asset && asset.decimals
|
||||
? addDecimalsFixedFormatNumber(price, asset.decimals)
|
||||
? addDecimalsFormatNumber(price, asset.decimals)
|
||||
: price;
|
||||
|
||||
return (
|
||||
<div className="inline-block">
|
||||
<span className="font-mono">{label}</span>{' '}
|
||||
<span>{label}</span>{' '}
|
||||
{showAssetLink && asset?.id ? (
|
||||
<AssetLink showAssetSymbol={showAssetSymbol} assetId={assetId} />
|
||||
) : null}
|
||||
|
||||
@@ -1,26 +1,20 @@
|
||||
import { useMemo } from 'react';
|
||||
import {
|
||||
useAssetTypeMapping,
|
||||
useAssetStatusMapping,
|
||||
type AssetFieldsFragment,
|
||||
} from '@vegaprotocol/assets';
|
||||
import type { AssetFieldsFragment } from '@vegaprotocol/assets';
|
||||
import { AssetTypeMapping, AssetStatusMapping } 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 ColDef } from 'ag-grid-community';
|
||||
import type { RowClickedEvent } 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<AgGridReact>(null);
|
||||
const showColumnsOnDesktop = () => {
|
||||
@@ -53,14 +47,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',
|
||||
@@ -75,7 +69,7 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
|
||||
}: VegaICellRendererParams<AssetFieldsFragment, 'id'>) =>
|
||||
value ? (
|
||||
<ButtonLink
|
||||
onClick={() => {
|
||||
onClick={(e) => {
|
||||
navigate(value);
|
||||
}}
|
||||
>
|
||||
@@ -86,7 +80,7 @@ export const AssetsTable = ({ data }: AssetsTableProps) => {
|
||||
),
|
||||
},
|
||||
],
|
||||
[navigate, assetStatusMapping, assetTypeMapping]
|
||||
[navigate]
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -14,7 +14,7 @@ import { Routes } from '../../routes/route-names';
|
||||
import { NetworkSwitcher } from '@vegaprotocol/environment';
|
||||
import type { Navigable } from '../../routes/router-config';
|
||||
import { isNavigable } from '../../routes/router-config';
|
||||
import { useRouterConfig } from '../../routes/router-config';
|
||||
import { routerConfig } from '../../routes/router-config';
|
||||
import { useMemo } from 'react';
|
||||
import compact from 'lodash/compact';
|
||||
import { Search } from '../search';
|
||||
@@ -26,7 +26,6 @@ const routeToNavigationItem = (r: Navigable) => (
|
||||
);
|
||||
|
||||
export const Header = () => {
|
||||
const routerConfig = useRouterConfig();
|
||||
const isHome = Boolean(useMatch(Routes.HOME));
|
||||
const pages = routerConfig[0].children || [];
|
||||
const mainItems = compact(
|
||||
|
||||
@@ -91,6 +91,6 @@ describe('Market link component', () => {
|
||||
};
|
||||
|
||||
const res = render(renderComponent('123', [mock]));
|
||||
expect(await res.findByTitle('123')).toBeInTheDocument();
|
||||
expect(await res.findByText('123')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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,
|
||||
type VegaValueGetterParams,
|
||||
import type {
|
||||
VegaICellRendererParams,
|
||||
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 = {
|
||||
|
||||
@@ -17,7 +17,7 @@ function renderAmendOrderDetails(
|
||||
mocks: MockedResponse[]
|
||||
) {
|
||||
return render(
|
||||
<MockedProvider mocks={mocks}>
|
||||
<MockedProvider mocks={mocks} addTypename={false}>
|
||||
<MemoryRouter>
|
||||
<AmendOrderDetails version={version} id={id} amend={amend} />
|
||||
</MemoryRouter>
|
||||
@@ -44,18 +44,18 @@ function renderExistingAmend(
|
||||
orderByID: {
|
||||
__typename: 'Order',
|
||||
id: '123',
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
type: 'GTT',
|
||||
status: Schema.OrderStatus.STATUS_ACTIVE,
|
||||
version: version ? version.toString() : '',
|
||||
version: version,
|
||||
createdAt: '123',
|
||||
updatedAt: '456',
|
||||
expiresAt: '789',
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
|
||||
price: '200',
|
||||
side: Schema.Side.SIDE_BUY,
|
||||
side: 'BUY',
|
||||
peggedOrder: null,
|
||||
remaining: '99',
|
||||
rejectionReason: Schema.OrderRejectionReason.ORDER_ERROR_NOT_FOUND,
|
||||
rejectionReason: 'rejection',
|
||||
reference: '123',
|
||||
size: '100',
|
||||
party: {
|
||||
@@ -65,15 +65,18 @@ function renderExistingAmend(
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '789',
|
||||
state: Schema.MarketState.STATE_ACTIVE,
|
||||
state: 'STATUS_ACTIVE',
|
||||
positionDecimalPlaces: 2,
|
||||
decimalPlaces: 0,
|
||||
decimalPlaces: '5',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'test',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: '123',
|
||||
settlementAsset: {
|
||||
decimals: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -94,18 +97,18 @@ function renderExistingAmend(
|
||||
orderByID: {
|
||||
__typename: 'Order',
|
||||
id: '123',
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
type: 'GTT',
|
||||
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: Schema.Side.SIDE_BUY,
|
||||
side: 'BUY',
|
||||
remaining: '99',
|
||||
rejectionReason: Schema.OrderRejectionReason.ORDER_ERROR_NOT_FOUND,
|
||||
rejectionReason: 'rejection',
|
||||
reference: '123',
|
||||
size: '200',
|
||||
party: {
|
||||
@@ -114,16 +117,19 @@ function renderExistingAmend(
|
||||
},
|
||||
market: {
|
||||
__typename: 'Market',
|
||||
id: '8888',
|
||||
state: Schema.MarketState.STATE_ACTIVE,
|
||||
id: 'amend-to-order-latest-version',
|
||||
state: 'STATUS_ACTIVE',
|
||||
positionDecimalPlaces: 2,
|
||||
decimalPlaces: 0,
|
||||
decimalPlaces: '5',
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'amend-to-order-latest-version-test',
|
||||
product: {
|
||||
__typename: 'Future',
|
||||
quoteName: '123',
|
||||
settlementAsset: {
|
||||
decimals: 8,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -136,13 +142,13 @@ function renderExistingAmend(
|
||||
request: {
|
||||
query: ExplorerMarketDocument,
|
||||
variables: {
|
||||
id: '8888',
|
||||
id: '789',
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
market: {
|
||||
id: '8888',
|
||||
id: '789',
|
||||
decimalPlaces: 5,
|
||||
positionDecimalPlaces: 2,
|
||||
state: 'irrelevant-test-data',
|
||||
@@ -219,10 +225,12 @@ describe('Amend order details', () => {
|
||||
|
||||
it('Fetches latest version when version is not specified', async () => {
|
||||
const amend: Amend = {
|
||||
price: '123',
|
||||
price: '-7879',
|
||||
};
|
||||
|
||||
const res = renderExistingAmend('123', undefined, amend);
|
||||
expect(await res.findByText('test-label')).toBeInTheDocument();
|
||||
expect(
|
||||
await res.findByText('amend-to-order-latest-version')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -46,10 +46,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
|
||||
<div className={wrapperClasses}>
|
||||
<div className="mb-12 lg:mb-0">
|
||||
<div className="relative block rounded-lg px-3 py-6 md:px-6 lg:-mr-7">
|
||||
<h2 className="display-5 mb-4 text-3xl font-bold">
|
||||
<h2 className="text-3xl font-bold mb-4 display-5">
|
||||
{t('Order not found')}
|
||||
</h2>
|
||||
<p className="mb-12 text-gray-500">
|
||||
<p className="text-gray-500 mb-12">
|
||||
{t('No order created from this transaction')}
|
||||
</p>
|
||||
</div>
|
||||
@@ -68,24 +68,24 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
|
||||
<div className={wrapperClasses}>
|
||||
<div className="mb-12 lg:mb-0">
|
||||
<div className="relative block px-3 py-6 md:px-6 lg:-mr-7">
|
||||
<h2 className="display-5 mb-4 text-3xl font-bold">
|
||||
<h2 className="text-3xl font-bold mb-4 display-5">
|
||||
{t('Edits to ')}
|
||||
{sideText[o.side]}
|
||||
{t(' order')}
|
||||
</h2>
|
||||
<div className="mb-4 text-gray-500">
|
||||
<p className="text-gray-500 mb-4">
|
||||
In <MarketLink id={o.market.id} />, updated at{' '}
|
||||
<Time date={o.updatedAt} />.
|
||||
</div>
|
||||
</p>
|
||||
|
||||
<div className="grid gap-x-6 md:grid-cols-4">
|
||||
<div className="grid md:grid-cols-4 gap-x-6">
|
||||
{amend.sizeDelta && amend.sizeDelta !== '0' ? (
|
||||
<div className="mb-12 md:mb-0">
|
||||
<h2 className="text-dark mb-4 text-2xl font-bold">
|
||||
<h2 className="text-2xl font-bold text-dark mb-4">
|
||||
{t('New size')}
|
||||
</h2>
|
||||
<h5
|
||||
className={`mb-0 text-lg font-medium capitalize text-gray-500 ${getSideDeltaColour(
|
||||
className={`text-lg font-medium text-gray-500 mb-0 capitalize ${getSideDeltaColour(
|
||||
amend.sizeDelta
|
||||
)}`}
|
||||
>
|
||||
@@ -96,10 +96,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
|
||||
|
||||
{amend.price && amend.price !== '0' ? (
|
||||
<div className="">
|
||||
<h2 className="text-dark mb-4 text-2xl font-bold">
|
||||
<h2 className="text-2xl font-bold text-dark mb-4">
|
||||
{t('New price')}
|
||||
</h2>
|
||||
<h5 className="mb-0 text-lg font-medium text-gray-500">
|
||||
<h5 className="text-lg font-medium text-gray-500 mb-0">
|
||||
<PriceInMarket price={amend.price} marketId={o.market.id} />
|
||||
</h5>
|
||||
</div>
|
||||
@@ -108,10 +108,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
|
||||
{amend.peggedReference &&
|
||||
amend.peggedReference !== 'PEGGED_REFERENCE_UNSPECIFIED' ? (
|
||||
<div className="">
|
||||
<h2 className="text-dark mb-4 text-2xl font-bold">
|
||||
<h2 className="text-2xl font-bold text-dark mb-4">
|
||||
{t('New reference')}
|
||||
</h2>
|
||||
<h5 className="mb-0 text-lg font-medium text-gray-500">
|
||||
<h5 className="text-lg font-medium text-gray-500 mb-0">
|
||||
{peggedReference[amend.peggedReference]}
|
||||
</h5>
|
||||
</div>
|
||||
@@ -119,10 +119,10 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
|
||||
|
||||
{amend.peggedOffset ? (
|
||||
<div className="">
|
||||
<h2 className="text-dark mb-4 text-2xl font-bold">
|
||||
<h2 className="text-2xl font-bold text-dark mb-4">
|
||||
{t('New offset')}
|
||||
</h2>
|
||||
<h5 className="mb-0 text-lg font-medium text-gray-500">
|
||||
<h5 className="text-lg font-medium text-gray-500 mb-0">
|
||||
{amend.peggedOffset}
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,6 @@ import { Time } from '../time';
|
||||
import { sideText, statusText, tifFull, tifShort } from './lib/order-labels';
|
||||
import SizeInMarket from '../size-in-market/size-in-market';
|
||||
import { TxOrderPeggedReference } from '../txs/details/order/tx-order-peg';
|
||||
import { OrderTypeMapping } from '@vegaprotocol/types';
|
||||
|
||||
export interface DeterministicOrderDetailsProps {
|
||||
id: string;
|
||||
@@ -70,7 +69,7 @@ const DeterministicOrderDetails = ({
|
||||
<span className="mx-5 text-base">@</span>
|
||||
<PriceInMarket price={o.price} marketId={o.market.id} />
|
||||
</h2>
|
||||
<p className="text-gray-400 dark:text-gray-600">
|
||||
<p className="text-gray-200">
|
||||
In <MarketLink id={o.market.id} /> at <Time date={o.createdAt} />.
|
||||
</p>
|
||||
{o.peggedOrder ? (
|
||||
@@ -84,12 +83,13 @@ const DeterministicOrderDetails = ({
|
||||
/>
|
||||
</p>
|
||||
) : null}
|
||||
|
||||
{o.reference ? (
|
||||
<p className="text-gray-500 mt-4">
|
||||
<span>{t('Reference')}</span>: {o.reference}
|
||||
</p>
|
||||
) : null}
|
||||
<div className="grid md:grid-cols-5 gap-x-6 mt-4">
|
||||
<div className="grid md:grid-cols-4 gap-x-6 mt-4">
|
||||
<div className="mb-12 md:mb-0">
|
||||
<h2 className="text-2xl font-bold text-dark mb-4">
|
||||
{t('Status')}
|
||||
@@ -114,16 +114,6 @@ const DeterministicOrderDetails = ({
|
||||
{o.version}
|
||||
</h5>
|
||||
</div>
|
||||
{o.type ? (
|
||||
<div className="">
|
||||
<h2 className="text-2xl font-bold text-dark mb-4">
|
||||
{t('Type')}
|
||||
</h2>
|
||||
<h5 className="text-lg font-medium text-gray-500 mb-0">
|
||||
{OrderTypeMapping[o.type]}
|
||||
</h5>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,15 +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,
|
||||
type VegaValueFormatterParams,
|
||||
import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { useLayoutEffect, useMemo, useRef, useState } from 'react';
|
||||
import { type ColDef } from 'ag-grid-community';
|
||||
import type { RowClickedEvent } from 'ag-grid-community';
|
||||
import type { RowClickedEvent, ColDef } from 'ag-grid-community';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
@@ -106,7 +105,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
||||
? new BigNumber(0)
|
||||
: yesTokens.multipliedBy(100).dividedBy(totalTokensVoted);
|
||||
return (
|
||||
<div className="flex h-full items-center justify-center pt-2 uppercase">
|
||||
<div className="flex items-center justify-center h-full pt-2 uppercase">
|
||||
<VoteProgress
|
||||
threshold={requiredMajorityPercentage}
|
||||
progress={yesPercentage}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
import { useState } from 'react';
|
||||
import type { BlockExplorerTransactionResult } from '../../routes/types/block-explorer-response';
|
||||
import {
|
||||
CopyWithTooltip,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
interface SignatureProps {
|
||||
signature: BlockExplorerTransactionResult['signature'];
|
||||
}
|
||||
|
||||
const valueClass =
|
||||
'font-mono px-2.5 py-0.5 text-xs max-w-[200px] cursor-pointer';
|
||||
const valueClassClosed = 'text-ellipsis overflow-hidden';
|
||||
const valueClassOpen = 'break-words text-left';
|
||||
|
||||
/**
|
||||
* Viewer component for a vega signature. Featuers copy and pasting, truncation
|
||||
*
|
||||
* @param signature
|
||||
*/
|
||||
export const Signature = ({ signature }: SignatureProps) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
|
||||
if (!signature || !signature.value || !signature.version || !signature.algo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="inline-flex border rounded signature-component relative pr-[20px]">
|
||||
<span
|
||||
className="bg-gray-100 px-2.5 py-0.5 text-xs text-gray-500 select-none cursor-default"
|
||||
title={`Version ${signature.version}`}
|
||||
>
|
||||
{signature.algo}
|
||||
</span>
|
||||
<div
|
||||
className={
|
||||
isOpen
|
||||
? `${valueClass} ${valueClassOpen}`
|
||||
: `${valueClass} ${valueClassClosed}`
|
||||
}
|
||||
>
|
||||
<CopyWithTooltip text={signature.value}>
|
||||
<span title={signature.value}>{signature.value}</span>
|
||||
</CopyWithTooltip>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className="absolute top-[-3px] right-0 pr-2"
|
||||
title={t('Show full signature')}
|
||||
>
|
||||
<VegaIcon name={isOpen ? VegaIconNames.EYE_OFF : VegaIconNames.EYE} />
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -15,7 +15,6 @@ import isUndefined from 'lodash/isUndefined';
|
||||
import type { BlockExplorerTransactionResult } from '../../../../routes/types/block-explorer-response';
|
||||
import { TxDetailsChainEventWithdrawal } from './tx-erc20-withdrawal';
|
||||
import { TxDetailsChainEventErc20AssetDelist } from './tx-erc20-asset-delist';
|
||||
import { TxDetailsContractCall } from './tx-contract-call';
|
||||
|
||||
interface ChainEventProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
@@ -39,7 +38,7 @@ export const ChainEvent = ({ txData }: ChainEventProps) => {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { builtin, erc20, erc20Multisig, stakingEvent, contractCall } =
|
||||
const { builtin, erc20, erc20Multisig, stakingEvent } =
|
||||
txData.command.chainEvent;
|
||||
|
||||
// Builtin Asset events
|
||||
@@ -141,10 +140,6 @@ export const ChainEvent = ({ txData }: ChainEventProps) => {
|
||||
}
|
||||
}
|
||||
|
||||
if (contractCall) {
|
||||
return <TxDetailsContractCall contractCall={contractCall} />;
|
||||
}
|
||||
|
||||
// If we hit this return, tx-shared-details should give a basic overview
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
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('-');
|
||||
});
|
||||
});
|
||||
@@ -1,88 +0,0 @@
|
||||
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 && (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Oracle')}</TableCell>
|
||||
<TableCell>
|
||||
<OracleLink
|
||||
id={contractCall.specId}
|
||||
hasSeenOracleReports={true}
|
||||
status={data?.oracleSpec?.dataSourceSpec.spec.status || '-'}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
{contractCall.blockHeight && (
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('ETH block')}</TableCell>
|
||||
<TableCell>
|
||||
<EthExplorerLink
|
||||
id={contractCall.blockHeight}
|
||||
type={EthExplorerLinkTypes.block}
|
||||
/>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
{data?.oracleSpec?.dataSourceSpec && (
|
||||
<OracleEthSource
|
||||
sourceType={data.oracleSpec.dataSourceSpec.spec.data.sourceType}
|
||||
/>
|
||||
)}
|
||||
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell>{t('Result')}</TableCell>
|
||||
<TableCell>{decodeEthCallResult(contractCall.result)}</TableCell>
|
||||
</TableRow>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -9,7 +9,6 @@ import { Time } from '../../../time';
|
||||
import { ChainResponseCode } from '../chain-response-code/chain-reponse.code';
|
||||
import { TxDataView } from '../../tx-data-view';
|
||||
import Hash from '../../../links/hash';
|
||||
import { Signature } from '../../../signature/signature';
|
||||
|
||||
interface TxDetailsSharedProps {
|
||||
txData: BlockExplorerTransactionResult | undefined;
|
||||
@@ -76,12 +75,6 @@ export const TxDetailsShared = ({
|
||||
<BlockLink height={height} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell {...sharedHeaderProps}>{t('Signature')}</TableCell>
|
||||
<TableCell>
|
||||
<Signature signature={txData.signature} />
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
<TableRow modifier="bordered">
|
||||
<TableCell {...sharedHeaderProps}>{t('Time')}</TableCell>
|
||||
<TableCell>
|
||||
|
||||
@@ -1,11 +1,51 @@
|
||||
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;
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -80,12 +80,6 @@ export function getLabelForOrderType(
|
||||
if (command.orderSubmission.icebergOpts) {
|
||||
return 'Iceberg';
|
||||
}
|
||||
if (command.orderSubmission.type === 'TYPE_MARKET') {
|
||||
return 'Market order';
|
||||
}
|
||||
if (command.orderSubmission.type === 'TYPE_LIMIT') {
|
||||
return 'Limit order';
|
||||
}
|
||||
}
|
||||
return 'Order';
|
||||
}
|
||||
|
||||
@@ -98,8 +98,6 @@ describe('TxDetailsTransfer', () => {
|
||||
},
|
||||
},
|
||||
signature: {
|
||||
version: '1',
|
||||
algo: 'vega/ed25519',
|
||||
value:
|
||||
'610c2e196a7d4fed4413b9e82af267b1ff3e30e943df3a3d28096fd60604d430d752fbaf6dd4f84d496be78885bb6118f40560bff7832c06bd7a3d67b718b700',
|
||||
},
|
||||
|
||||
@@ -20,8 +20,6 @@ const generateTxs = (number: number): BlockExplorerTransactionResult[] => {
|
||||
'4b782482f587d291e8614219eb9a5ee9280fa2c58982dee71d976782a9be1964',
|
||||
type: 'Submit Order',
|
||||
signature: {
|
||||
version: '1',
|
||||
algo: 'vega/ed25519',
|
||||
value: '123',
|
||||
},
|
||||
code: 0,
|
||||
|
||||
@@ -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 (
|
||||
<AsyncRenderer data={data} error={error} loading={!!loading}>
|
||||
{data && data.transactions.length > 0 ? (
|
||||
<div className="mb-28 overflow-x-auto whitespace-nowrap">
|
||||
<div className="overflow-x-auto whitespace-nowrap mb-28">
|
||||
<Table>
|
||||
<thead>
|
||||
<TableRow modifier="bordered" className="font-mono">
|
||||
|
||||
@@ -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,
|
||||
type BlockExplorerTransactions,
|
||||
import type {
|
||||
BlockExplorerTransactionResult,
|
||||
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<FilterOption>) {
|
||||
|
||||
@@ -9,13 +9,11 @@ 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<Params>();
|
||||
const { assetId } = useParams<{ assetId: string }>();
|
||||
const { data, loading, error } = useAssetDataProvider(assetId || '');
|
||||
|
||||
const title = data ? data.name : error ? t('Asset not found') : '';
|
||||
@@ -43,7 +41,7 @@ export const AssetPage = () => {
|
||||
loading={loading}
|
||||
error={error}
|
||||
>
|
||||
<div className="relative h-full">
|
||||
<div className="h-full relative">
|
||||
<AssetDetailsTable asset={data as AssetFieldsFragment} />
|
||||
</div>
|
||||
</AsyncRenderer>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import { DATA_SOURCES } from '../../../config';
|
||||
import {
|
||||
type BlockMeta,
|
||||
type TendermintBlockchainResponse,
|
||||
import type {
|
||||
BlockMeta,
|
||||
TendermintBlockchainResponse,
|
||||
} from '../tendermint-blockchain-response';
|
||||
import { RouteTitle } from '../../../components/route-title';
|
||||
import { BlocksRefetch } from '../../../components/blocks';
|
||||
|
||||
@@ -17,10 +17,8 @@ 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<Params>();
|
||||
const { block } = useParams<{ block: string }>();
|
||||
useDocumentTitle(['Blocks', `Block #${block}`]);
|
||||
const {
|
||||
state: { data: blockData, loading, error },
|
||||
@@ -31,7 +29,7 @@ const Block = () => {
|
||||
<RouteTitle data-testid="block-header">{t(`BLOCK ${block}`)}</RouteTitle>
|
||||
<AsyncRenderer data={blockData} error={error} loading={!!loading}>
|
||||
<>
|
||||
<div className="mb-8 grid grid-cols-2 gap-2">
|
||||
<div className="grid grid-cols-2 gap-2 mb-8">
|
||||
<Link
|
||||
data-testid="previous-block"
|
||||
to={`/${Routes.BLOCKS}/${Number(block) - 1}`}
|
||||
@@ -54,7 +52,7 @@ const Block = () => {
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
{blockData && 'result' in blockData && (
|
||||
{blockData && (
|
||||
<>
|
||||
<TableWithTbody className="mb-8">
|
||||
<TableRow modifier="bordered">
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { RouteTitle } from '../../components/route-title';
|
||||
import { AsyncRenderer, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { DATA_SOURCES } from '../../config';
|
||||
import { type TendermintGenesisResponse } from './tendermint-genesis-response';
|
||||
import type { TendermintGenesisResponse } from './tendermint-genesis-response';
|
||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||
|
||||
const Genesis = () => {
|
||||
|
||||
@@ -11,12 +11,10 @@ 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<Params>();
|
||||
const { marketId } = useParams<{ marketId: string }>();
|
||||
|
||||
const { data, loading, error } = useDataProvider({
|
||||
dataProvider: marketInfoWithDataProvider,
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import { getNodes } from '@vegaprotocol/utils';
|
||||
import { MarketLink } from '../../../components/links';
|
||||
import { TableRow, TableCell, TableHeader } from '../../../components/table';
|
||||
import {
|
||||
useExplorerOracleFormMarketsQuery,
|
||||
type ExplorerOracleForMarketsMarketFragment,
|
||||
} from '../__generated__/OraclesForMarkets';
|
||||
import type { ExplorerOracleForMarketsMarketFragment } from '../__generated__/OraclesForMarkets';
|
||||
import { useExplorerOracleFormMarketsQuery } from '../__generated__/OraclesForMarkets';
|
||||
|
||||
interface OracleMarketsProps {
|
||||
id: string;
|
||||
|
||||
@@ -9,10 +9,8 @@ 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<Params>();
|
||||
const { id } = useParams<{ id: string }>();
|
||||
|
||||
useDocumentTitle(['Oracle', `Oracle #${truncateByChars(id || '1', 5, 5)}`]);
|
||||
|
||||
|
||||
@@ -6,10 +6,8 @@ import { useDocumentTitle } from '../../../../hooks/use-document-title';
|
||||
|
||||
import { PartyAccounts } from '../components/party-accounts';
|
||||
|
||||
type Params = { party: string };
|
||||
|
||||
const PartyAccountsByAsset = () => {
|
||||
const { party } = useParams<Params>();
|
||||
const { party } = useParams<{ party: string }>();
|
||||
|
||||
useDocumentTitle(['Public keys', party || '-']);
|
||||
const partyId = toNonHex(party ? party : '');
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
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';
|
||||
import { AccountManager } from '@vegaprotocol/accounts';
|
||||
import { useCallback } from 'react';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
|
||||
interface PartyAccountsProps {
|
||||
partyId: string;
|
||||
@@ -13,71 +12,21 @@ interface PartyAccountsProps {
|
||||
* appearing first and... tbd
|
||||
*/
|
||||
export const PartyAccounts = ({ partyId }: PartyAccountsProps) => {
|
||||
const { data } = useExplorerPartyAssetsQuery({
|
||||
variables: { partyId },
|
||||
});
|
||||
|
||||
const party = data?.partiesConnection?.edges[0]?.node;
|
||||
const accounts =
|
||||
party?.accountsConnection?.edges?.filter((edge) => edge?.node) || [];
|
||||
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
|
||||
const onClickAsset = useCallback(
|
||||
(assetId?: string) => {
|
||||
assetId && openAssetDetailsDialog(assetId);
|
||||
},
|
||||
[openAssetDetailsDialog]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="block min-h-44 h-60 4 w-full border-red-800 relative">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th className="text-right px-4">Balance</th>
|
||||
<th className="text-left px-4">Type</th>
|
||||
<th className="text-left px-4">Market</th>
|
||||
<th className="text-left px-4">Asset</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{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 (
|
||||
<tr className="border-t border-neutral-300 dark:border-neutral-600">
|
||||
<td className="px-4 text-right">
|
||||
<AssetBalance
|
||||
assetId={asset.id}
|
||||
price={balance}
|
||||
showAssetSymbol={true}
|
||||
/>
|
||||
</td>
|
||||
<td className="px-4">{AccountTypeMapping[type]}</td>
|
||||
<td className="px-4">
|
||||
{market?.id ? <MarketLink id={market.id} /> : '-'}
|
||||
</td>
|
||||
<td className="px-4">
|
||||
<AssetLink assetId={asset.id} />
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
<AccountManager
|
||||
partyId={partyId}
|
||||
onClickAsset={onClickAsset}
|
||||
isReadOnly={true}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -19,13 +19,11 @@ 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<Params>();
|
||||
const { party } = useParams<{ party: string }>();
|
||||
|
||||
useDocumentTitle(['Public keys', party || '-']);
|
||||
const navigate = useNavigate();
|
||||
@@ -62,7 +60,7 @@ const Party = () => {
|
||||
|
||||
if (!isValidPartyId(partyId)) {
|
||||
return (
|
||||
<div className="mx-auto max-w-sm">
|
||||
<div className="max-w-sm mx-auto">
|
||||
<Notification
|
||||
message={t('Invalid party ID')}
|
||||
intent={Intent.Danger}
|
||||
@@ -86,7 +84,7 @@ const Party = () => {
|
||||
truncateEnd={visibleChars}
|
||||
/>
|
||||
|
||||
<div className="grid w-full grid-flow-row grid-cols-1 md:grid-flow-col md:grid-cols-2 md:space-x-4">
|
||||
<div className="grid md:grid-flow-col grid-flow-row md:space-x-4 grid-cols-1 md:grid-cols-2 w-full">
|
||||
<PartyBlockAccounts
|
||||
accountError={AccountError}
|
||||
accountLoading={AccountLoading}
|
||||
|
||||
@@ -18,6 +18,7 @@ import { t } from '@vegaprotocol/i18n';
|
||||
import { Routes } from './route-names';
|
||||
import { NetworkParameters } from './network-parameters';
|
||||
import type { Params, RouteObject } from 'react-router-dom';
|
||||
import { createBrowserRouter } from 'react-router-dom';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { MarketPage, MarketsPage } from './markets';
|
||||
import type { ReactNode } from 'react';
|
||||
@@ -28,7 +29,7 @@ import { truncateMiddle } from '@vegaprotocol/ui-toolkit';
|
||||
import { remove0x } from '@vegaprotocol/utils';
|
||||
import { PartyAccountsByAsset } from './parties/id/accounts';
|
||||
import { Disclaimer } from './pages/disclaimer';
|
||||
import { useFeatureFlags } from '@vegaprotocol/environment';
|
||||
import { FLAGS } from '@vegaprotocol/environment';
|
||||
import RestrictedPage from './restricted';
|
||||
|
||||
export type Navigable = {
|
||||
@@ -59,315 +60,311 @@ type Route = RouteItem & {
|
||||
children?: RouteItem[];
|
||||
};
|
||||
|
||||
export const useRouterConfig = () => {
|
||||
const featureFlags = useFeatureFlags((state) => state.flags);
|
||||
|
||||
const partiesRoutes: Route[] = featureFlags.EXPLORER_PARTIES
|
||||
? [
|
||||
{
|
||||
path: Routes.PARTIES,
|
||||
element: <Party />,
|
||||
handle: {
|
||||
name: t('Parties'),
|
||||
text: t('Parties'),
|
||||
breadcrumb: () => <Link to={Routes.PARTIES}>{t('Parties')}</Link>,
|
||||
const partiesRoutes: Route[] = FLAGS.EXPLORER_PARTIES
|
||||
? [
|
||||
{
|
||||
path: Routes.PARTIES,
|
||||
element: <Party />,
|
||||
handle: {
|
||||
name: t('Parties'),
|
||||
text: t('Parties'),
|
||||
breadcrumb: () => <Link to={Routes.PARTIES}>{t('Parties')}</Link>,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <Parties />,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <Parties />,
|
||||
},
|
||||
{
|
||||
path: ':party',
|
||||
element: <Party />,
|
||||
{
|
||||
path: ':party',
|
||||
element: <Party />,
|
||||
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <PartySingle />,
|
||||
handle: {
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<Link to={linkTo(Routes.PARTIES, params.party)}>
|
||||
{truncateMiddle(params.party as string)}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <PartySingle />,
|
||||
handle: {
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<Link to={linkTo(Routes.PARTIES, params.party)}>
|
||||
{truncateMiddle(params.party as string)}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: 'assets',
|
||||
element: <Party />,
|
||||
handle: {
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<Link to={linkTo(Routes.PARTIES, params.party)}>
|
||||
{truncateMiddle(params.party as string)}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <PartyAccountsByAsset />,
|
||||
handle: {
|
||||
breadcrumb: () => {
|
||||
return t('Assets');
|
||||
},
|
||||
},
|
||||
{
|
||||
path: 'assets',
|
||||
element: <Party />,
|
||||
handle: {
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<Link to={linkTo(Routes.PARTIES, params.party)}>
|
||||
{truncateMiddle(params.party as string)}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <PartyAccountsByAsset />,
|
||||
handle: {
|
||||
breadcrumb: () => {
|
||||
return t('Assets');
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const assetsRoutes: Route[] = featureFlags.EXPLORER_ASSETS
|
||||
? [
|
||||
{
|
||||
path: Routes.ASSETS,
|
||||
handle: {
|
||||
name: t('Assets'),
|
||||
text: t('Assets'),
|
||||
breadcrumb: () => <Link to={Routes.ASSETS}>{t('Assets')}</Link>,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <AssetsPage />,
|
||||
},
|
||||
{
|
||||
path: ':assetId',
|
||||
element: <AssetPage />,
|
||||
handle: {
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<AssetLink assetId={params.assetId as string} />
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const genesisRoutes: Route[] = featureFlags.EXPLORER_GENESIS
|
||||
? [
|
||||
{
|
||||
path: Routes.GENESIS,
|
||||
handle: {
|
||||
name: t('Genesis'),
|
||||
text: t('Genesis Parameters'),
|
||||
breadcrumb: () => (
|
||||
<Link to={Routes.GENESIS}>{t('Genesis Parameters')}</Link>
|
||||
),
|
||||
],
|
||||
},
|
||||
element: <Genesis />,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
],
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const governanceRoutes: Route[] = featureFlags.EXPLORER_GOVERNANCE
|
||||
? [
|
||||
{
|
||||
path: Routes.GOVERNANCE,
|
||||
handle: {
|
||||
name: t('Governance proposals'),
|
||||
text: t('Governance Proposals'),
|
||||
breadcrumb: () => (
|
||||
<Link to={Routes.GOVERNANCE}>{t('Governance Proposals')}</Link>
|
||||
),
|
||||
},
|
||||
element: <Proposals />,
|
||||
const assetsRoutes: Route[] = FLAGS.EXPLORER_ASSETS
|
||||
? [
|
||||
{
|
||||
path: Routes.ASSETS,
|
||||
handle: {
|
||||
name: t('Assets'),
|
||||
text: t('Assets'),
|
||||
breadcrumb: () => <Link to={Routes.ASSETS}>{t('Assets')}</Link>,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const marketsRoutes: Route[] = featureFlags.EXPLORER_MARKETS
|
||||
? [
|
||||
{
|
||||
path: Routes.MARKETS,
|
||||
handle: {
|
||||
name: t('Markets'),
|
||||
text: t('Markets'),
|
||||
breadcrumb: () => <Link to={Routes.MARKETS}>{t('Markets')}</Link>,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <MarketsPage />,
|
||||
},
|
||||
{
|
||||
path: ':marketId',
|
||||
element: <MarketPage />,
|
||||
handle: {
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<MarketLink id={params.marketId as string} />
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const networkParametersRoutes: Route[] =
|
||||
featureFlags.EXPLORER_NETWORK_PARAMETERS
|
||||
? [
|
||||
children: [
|
||||
{
|
||||
path: Routes.NETWORK_PARAMETERS,
|
||||
index: true,
|
||||
element: <AssetsPage />,
|
||||
},
|
||||
{
|
||||
path: ':assetId',
|
||||
element: <AssetPage />,
|
||||
handle: {
|
||||
name: t('NetworkParameters'),
|
||||
text: t('Network Parameters'),
|
||||
breadcrumb: () => (
|
||||
<Link to={Routes.NETWORK_PARAMETERS}>
|
||||
{t('Network Parameters')}
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<AssetLink assetId={params.assetId as string} />
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const genesisRoutes: Route[] = FLAGS.EXPLORER_GENESIS
|
||||
? [
|
||||
{
|
||||
path: Routes.GENESIS,
|
||||
handle: {
|
||||
name: t('Genesis'),
|
||||
text: t('Genesis Parameters'),
|
||||
breadcrumb: () => (
|
||||
<Link to={Routes.GENESIS}>{t('Genesis Parameters')}</Link>
|
||||
),
|
||||
},
|
||||
element: <Genesis />,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const governanceRoutes: Route[] = FLAGS.EXPLORER_GOVERNANCE
|
||||
? [
|
||||
{
|
||||
path: Routes.GOVERNANCE,
|
||||
handle: {
|
||||
name: t('Governance proposals'),
|
||||
text: t('Governance Proposals'),
|
||||
breadcrumb: () => (
|
||||
<Link to={Routes.GOVERNANCE}>{t('Governance Proposals')}</Link>
|
||||
),
|
||||
},
|
||||
element: <Proposals />,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const marketsRoutes: Route[] = FLAGS.EXPLORER_MARKETS
|
||||
? [
|
||||
{
|
||||
path: Routes.MARKETS,
|
||||
handle: {
|
||||
name: t('Markets'),
|
||||
text: t('Markets'),
|
||||
breadcrumb: () => <Link to={Routes.MARKETS}>{t('Markets')}</Link>,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <MarketsPage />,
|
||||
},
|
||||
{
|
||||
path: ':marketId',
|
||||
element: <MarketPage />,
|
||||
handle: {
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<MarketLink id={params.marketId as string} />
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const networkParametersRoutes: Route[] = FLAGS.EXPLORER_NETWORK_PARAMETERS
|
||||
? [
|
||||
{
|
||||
path: Routes.NETWORK_PARAMETERS,
|
||||
handle: {
|
||||
name: t('NetworkParameters'),
|
||||
text: t('Network Parameters'),
|
||||
breadcrumb: () => (
|
||||
<Link to={Routes.NETWORK_PARAMETERS}>
|
||||
{t('Network Parameters')}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
element: <NetworkParameters />,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const validators: Route[] = FLAGS.EXPLORER_VALIDATORS
|
||||
? [
|
||||
{
|
||||
path: Routes.VALIDATORS,
|
||||
handle: {
|
||||
name: t('Validators'),
|
||||
text: t('Validators'),
|
||||
breadcrumb: () => (
|
||||
<Link to={Routes.VALIDATORS}>{t('Validators')}</Link>
|
||||
),
|
||||
},
|
||||
element: <ValidatorsPage />,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const linkTo = (...segments: (string | undefined)[]) =>
|
||||
compact(segments).join('/');
|
||||
|
||||
export const routerConfig: Route[] = [
|
||||
{
|
||||
path: Routes.HOME,
|
||||
element: <Layout />,
|
||||
handle: {
|
||||
name: t('Home'),
|
||||
text: t('Home'),
|
||||
breadcrumb: () => <Link to={Routes.HOME}>{t('Home')}</Link>,
|
||||
},
|
||||
errorElement: <ErrorBoundary />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <Home />,
|
||||
},
|
||||
{
|
||||
path: Routes.TX,
|
||||
handle: {
|
||||
name: t('Txs'),
|
||||
text: t('Transactions'),
|
||||
breadcrumb: () => <Link to={Routes.TX}>{t('Transactions')}</Link>,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: ':txHash',
|
||||
element: <Tx />,
|
||||
handle: {
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<Link to={linkTo(Routes.TX, params.txHash)}>
|
||||
{truncateMiddle(remove0x(params.txHash as string))}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
element: <NetworkParameters />,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const validators: Route[] = featureFlags.EXPLORER_VALIDATORS
|
||||
? [
|
||||
{
|
||||
path: Routes.VALIDATORS,
|
||||
handle: {
|
||||
name: t('Validators'),
|
||||
text: t('Validators'),
|
||||
breadcrumb: () => (
|
||||
<Link to={Routes.VALIDATORS}>{t('Validators')}</Link>
|
||||
),
|
||||
{
|
||||
index: true,
|
||||
element: <TxsList />,
|
||||
},
|
||||
element: <ValidatorsPage />,
|
||||
},
|
||||
]
|
||||
: [];
|
||||
|
||||
const linkTo = (...segments: (string | undefined)[]) =>
|
||||
compact(segments).join('/');
|
||||
|
||||
const routerConfig: Route[] = [
|
||||
{
|
||||
path: Routes.HOME,
|
||||
element: <Layout />,
|
||||
handle: {
|
||||
name: t('Home'),
|
||||
text: t('Home'),
|
||||
breadcrumb: () => <Link to={Routes.HOME}>{t('Home')}</Link>,
|
||||
],
|
||||
},
|
||||
errorElement: <ErrorBoundary />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <Home />,
|
||||
{
|
||||
path: Routes.BLOCKS,
|
||||
handle: {
|
||||
name: t('Blocks'),
|
||||
text: t('Blocks'),
|
||||
breadcrumb: () => <Link to={Routes.BLOCKS}>{t('Blocks')}</Link>,
|
||||
},
|
||||
{
|
||||
path: Routes.TX,
|
||||
handle: {
|
||||
name: t('Txs'),
|
||||
text: t('Transactions'),
|
||||
breadcrumb: () => <Link to={Routes.TX}>{t('Transactions')}</Link>,
|
||||
element: <BlockPage />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <Blocks />,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: ':txHash',
|
||||
element: <Tx />,
|
||||
handle: {
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<Link to={linkTo(Routes.TX, params.txHash)}>
|
||||
{truncateMiddle(remove0x(params.txHash as string))}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
path: ':block',
|
||||
element: <Block />,
|
||||
handle: {
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<Link to={linkTo(Routes.BLOCKS, params.block)}>
|
||||
{params.block}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
index: true,
|
||||
element: <TxsList />,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.BLOCKS,
|
||||
handle: {
|
||||
name: t('Blocks'),
|
||||
text: t('Blocks'),
|
||||
breadcrumb: () => <Link to={Routes.BLOCKS}>{t('Blocks')}</Link>,
|
||||
},
|
||||
element: <BlockPage />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <Blocks />,
|
||||
},
|
||||
{
|
||||
path: ':block',
|
||||
element: <Block />,
|
||||
handle: {
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<Link to={linkTo(Routes.BLOCKS, params.block)}>
|
||||
{params.block}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.ORACLES,
|
||||
handle: {
|
||||
name: t('Oracles'),
|
||||
text: t('Oracles'),
|
||||
breadcrumb: () => <Link to={Routes.ORACLES}>{t('Oracles')}</Link>,
|
||||
},
|
||||
element: <OraclePage />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <Oracles />,
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
element: <Oracle />,
|
||||
handle: {
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<Link to={linkTo(Routes.ORACLES, params.id)}>
|
||||
{truncateMiddle(params.id as string)}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.DISCLAIMER,
|
||||
element: <Disclaimer />,
|
||||
handle: {
|
||||
name: t('Disclaimer'),
|
||||
text: t('Disclaimer'),
|
||||
breadcrumb: () => (
|
||||
<Link to={Routes.DISCLAIMER}>{t('Disclaimer')}</Link>
|
||||
),
|
||||
},
|
||||
},
|
||||
...partiesRoutes,
|
||||
...assetsRoutes,
|
||||
...genesisRoutes,
|
||||
...governanceRoutes,
|
||||
...marketsRoutes,
|
||||
...networkParametersRoutes,
|
||||
...validators,
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.RESTRICTED,
|
||||
element: <RestrictedPage />,
|
||||
handle: {
|
||||
name: t('Restricted'),
|
||||
text: t('Restricted'),
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.ORACLES,
|
||||
handle: {
|
||||
name: t('Oracles'),
|
||||
text: t('Oracles'),
|
||||
breadcrumb: () => <Link to={Routes.ORACLES}>{t('Oracles')}</Link>,
|
||||
},
|
||||
element: <OraclePage />,
|
||||
children: [
|
||||
{
|
||||
index: true,
|
||||
element: <Oracles />,
|
||||
},
|
||||
{
|
||||
path: ':id',
|
||||
element: <Oracle />,
|
||||
handle: {
|
||||
breadcrumb: (params: Params<string>) => (
|
||||
<Link to={linkTo(Routes.ORACLES, params.id)}>
|
||||
{truncateMiddle(params.id as string)}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.DISCLAIMER,
|
||||
element: <Disclaimer />,
|
||||
handle: {
|
||||
name: t('Disclaimer'),
|
||||
text: t('Disclaimer'),
|
||||
breadcrumb: () => (
|
||||
<Link to={Routes.DISCLAIMER}>{t('Disclaimer')}</Link>
|
||||
),
|
||||
},
|
||||
},
|
||||
...partiesRoutes,
|
||||
...assetsRoutes,
|
||||
...genesisRoutes,
|
||||
...governanceRoutes,
|
||||
...marketsRoutes,
|
||||
...networkParametersRoutes,
|
||||
...validators,
|
||||
],
|
||||
},
|
||||
{
|
||||
path: Routes.RESTRICTED,
|
||||
element: <RestrictedPage />,
|
||||
handle: {
|
||||
name: t('Restricted'),
|
||||
text: t('Restricted'),
|
||||
},
|
||||
];
|
||||
return routerConfig;
|
||||
};
|
||||
},
|
||||
];
|
||||
|
||||
export const router = createBrowserRouter(routerConfig);
|
||||
|
||||
@@ -4,15 +4,13 @@ import { useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { DATA_SOURCES } from '../../../config';
|
||||
import { RenderFetched } from '../../../components/render-fetched';
|
||||
import { TxDetails } from './tx-details';
|
||||
import { type BlockExplorerTransaction } from '../../../routes/types/block-explorer-response';
|
||||
import type { BlockExplorerTransaction } from '../../../routes/types/block-explorer-response';
|
||||
import { toNonHex } from '../../../components/search/detect-search';
|
||||
import { PageHeader } from '../../../components/page-header';
|
||||
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||
|
||||
type Params = { txHash: string };
|
||||
|
||||
const Tx = () => {
|
||||
const { txHash } = useParams<Params>();
|
||||
const { txHash } = useParams<{ txHash: string }>();
|
||||
const hash = txHash ? toNonHex(txHash) : '';
|
||||
let errorMessage: string | undefined = undefined;
|
||||
|
||||
|
||||
@@ -23,8 +23,6 @@ const txData: BlockExplorerTransactionResult = {
|
||||
type: 'type',
|
||||
command: {} as ValidatorHeartbeat,
|
||||
signature: {
|
||||
version: '1',
|
||||
algo: 'vega/ed25519',
|
||||
value: '123',
|
||||
},
|
||||
};
|
||||
|
||||
@@ -11,8 +11,6 @@ export interface BlockExplorerTransactionResult {
|
||||
cursor: string;
|
||||
command: components['schemas']['blockexplorerv1transaction'];
|
||||
signature: {
|
||||
version: string;
|
||||
algo: string;
|
||||
value: string;
|
||||
};
|
||||
error?: string;
|
||||
|
||||
@@ -3,9 +3,6 @@
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import '@testing-library/jest-dom';
|
||||
import { locales } from '@vegaprotocol/i18n';
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
Object.defineProperty(window, 'ResizeObserver', {
|
||||
writable: false,
|
||||
@@ -16,14 +13,3 @@ Object.defineProperty(window, 'ResizeObserver', {
|
||||
disconnect: jest.fn(),
|
||||
})),
|
||||
});
|
||||
|
||||
// Set up i18n instance so that components have the correct default
|
||||
// en translations
|
||||
i18n.use(initReactI18next).init({
|
||||
// we init with resources
|
||||
resources: locales,
|
||||
fallbackLng: 'en',
|
||||
nsSeparator: false,
|
||||
ns: ['explorer'],
|
||||
defaultNS: 'explorer',
|
||||
});
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../../../libs/i18n/src/locales
|
||||
@@ -1,45 +0,0 @@
|
||||
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';
|
||||
|
||||
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({
|
||||
lng: 'en',
|
||||
fallbackLng: 'en',
|
||||
supportedLngs: ['en'],
|
||||
load: 'languageOnly',
|
||||
debug: isInDev,
|
||||
// have a common namespace used around the full app
|
||||
ns: ['explorer'],
|
||||
defaultNS: 'explorer',
|
||||
keySeparator: false, // we use content as keys
|
||||
nsSeparator: false,
|
||||
backend,
|
||||
saveMissing: useLocize && !!process.env.NX_LOCIZE_API_KEY,
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
},
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
@@ -2,11 +2,7 @@
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": [
|
||||
"node",
|
||||
"@nx/react/typings/cssmodule.d.ts",
|
||||
"@nx/react/typings/image.d.ts"
|
||||
]
|
||||
"types": ["node"]
|
||||
},
|
||||
"files": [
|
||||
"../../node_modules/@nx/react/typings/cssmodule.d.ts",
|
||||
|
||||
@@ -3,13 +3,7 @@
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": [
|
||||
"jest",
|
||||
"node",
|
||||
"@testing-library/jest-dom",
|
||||
"@nx/react/typings/cssmodule.d.ts",
|
||||
"@nx/react/typings/image.d.ts"
|
||||
]
|
||||
"types": ["jest", "node", "@testing-library/jest-dom"]
|
||||
},
|
||||
"include": [
|
||||
"**/*.test.ts",
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
{
|
||||
"extends": ["plugin:cypress/recommended", "../../.eslintrc.json"],
|
||||
"ignorePatterns": ["!**/*", "cypress"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {
|
||||
"cypress/unsafe-to-chain-command": 0
|
||||
}
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/eslint:lint",
|
||||
"executor": "@nx/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/governance-e2e/**/*.{js,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,7 +61,6 @@ 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('/');
|
||||
@@ -79,7 +78,6 @@ describe(
|
||||
getProposalInformationFromTable('ID').invoke('text').as('parentMarketId');
|
||||
});
|
||||
|
||||
// @ts-ignore clash between jest and cypress
|
||||
beforeEach('visit proposals tab', function () {
|
||||
cy.clearLocalStorage();
|
||||
turnTelemetryOff();
|
||||
@@ -325,7 +323,6 @@ describe(
|
||||
});
|
||||
});
|
||||
cy.VegaWalletSubmitProposal(
|
||||
// @ts-ignore this is any
|
||||
createSuccessorMarketProposalTxBody(this.parentMarketId)
|
||||
);
|
||||
navigateTo(navigation.proposals);
|
||||
@@ -337,7 +334,6 @@ 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');
|
||||
@@ -356,7 +352,6 @@ describe(
|
||||
validateProposalDetailsDiff(
|
||||
'Parent Market ID',
|
||||
proposalChangeType.ADDED,
|
||||
// @ts-ignore this is any
|
||||
this.parentMarketId
|
||||
);
|
||||
validateProposalDetailsDiff(
|
||||
@@ -455,7 +450,6 @@ describe(
|
||||
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
|
||||
submitUniqueRawProposal({
|
||||
proposalBody: proposalPath,
|
||||
// @ts-ignore this is any
|
||||
updateMarketId: this.parentMarketId,
|
||||
enactmentTimestamp: enactmentTimestamp,
|
||||
closingTimestamp: closingTimestamp,
|
||||
@@ -472,7 +466,6 @@ describe(
|
||||
cy.getByTestId('proposal-update-market-state').within(() => {
|
||||
getProposalInformationFromTable('Market ID')
|
||||
.invoke('text')
|
||||
// @ts-ignore this is any
|
||||
.and('eq', this.parentMarketId);
|
||||
});
|
||||
});
|
||||
@@ -483,7 +476,6 @@ describe(
|
||||
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
|
||||
submitUniqueRawProposal({
|
||||
proposalBody: proposalPath,
|
||||
// @ts-ignore this is any
|
||||
updateMarketId: this.parentMarketId,
|
||||
enactmentTimestamp: enactmentTimestamp,
|
||||
closingTimestamp: closingTimestamp,
|
||||
@@ -497,7 +489,6 @@ describe(
|
||||
cy.getByTestId('proposal-update-market-state').within(() => {
|
||||
getProposalInformationFromTable('Market ID')
|
||||
.invoke('text')
|
||||
// @ts-ignore this is any
|
||||
.and('eq', this.parentMarketId);
|
||||
});
|
||||
});
|
||||
@@ -508,7 +499,6 @@ describe(
|
||||
const closingTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
|
||||
submitUniqueRawProposal({
|
||||
proposalBody: proposalPath,
|
||||
// @ts-ignore this is any
|
||||
updateMarketId: this.parentMarketId,
|
||||
enactmentTimestamp: enactmentTimestamp,
|
||||
closingTimestamp: closingTimestamp,
|
||||
@@ -528,7 +518,6 @@ 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',
|
||||
|
||||
@@ -37,7 +37,6 @@ context(
|
||||
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||
});
|
||||
|
||||
// @ts-ignore clash between jest and cypress
|
||||
beforeEach('visit proposals', function () {
|
||||
cy.clearLocalStorage();
|
||||
turnTelemetryOff();
|
||||
|
||||
@@ -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,7 +78,6 @@ context(
|
||||
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||
});
|
||||
|
||||
// @ts-ignore clash between jest and cypress
|
||||
beforeEach('visit governance tab', function () {
|
||||
cy.clearLocalStorage();
|
||||
turnTelemetryOff();
|
||||
@@ -302,7 +301,6 @@ 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`
|
||||
);
|
||||
});
|
||||
|
||||
@@ -70,7 +70,6 @@ context(
|
||||
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||
});
|
||||
|
||||
// @ts-ignore clash between jest and cypress
|
||||
beforeEach('visit governance tab', function () {
|
||||
cy.clearLocalStorage();
|
||||
turnTelemetryOff();
|
||||
@@ -217,7 +216,6 @@ 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';
|
||||
@@ -633,7 +631,6 @@ 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, {
|
||||
@@ -661,7 +658,6 @@ 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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { type testFreeformProposal } from '../../support/common-interfaces';
|
||||
import type { testFreeformProposal } from '../../support/common-interfaces';
|
||||
import {
|
||||
navigateTo,
|
||||
navigation,
|
||||
@@ -33,14 +33,12 @@ 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();
|
||||
@@ -108,7 +106,6 @@ 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<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||
|
||||
@@ -64,7 +64,6 @@ 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();
|
||||
@@ -238,7 +237,6 @@ 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');
|
||||
|
||||
@@ -52,7 +52,6 @@ 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();
|
||||
@@ -68,7 +67,6 @@ context(
|
||||
|
||||
it(
|
||||
'Able to associate tokens - from wallet',
|
||||
// @ts-ignore clash between jest and cypress
|
||||
{ tags: '@smoke' },
|
||||
function () {
|
||||
//1004-ASSO-003
|
||||
|
||||
@@ -48,7 +48,6 @@ context(
|
||||
depositAsset(usdcEthAddress, '1000', 5);
|
||||
});
|
||||
|
||||
// @ts-ignore clash between jest and cypress
|
||||
beforeEach('Navigate to withdrawal page', function () {
|
||||
cy.clearLocalStorage();
|
||||
turnTelemetryOff();
|
||||
@@ -102,7 +101,6 @@ 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
|
||||
|
||||
@@ -25,7 +25,6 @@ context('View functionality with public key', { tags: '@smoke' }, function () {
|
||||
);
|
||||
});
|
||||
|
||||
// @ts-ignore clash between jest and cypress
|
||||
beforeEach('visit home page', function () {
|
||||
cy.clearLocalStorage();
|
||||
turnTelemetryOff();
|
||||
|
||||
@@ -52,7 +52,6 @@ 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(
|
||||
|
||||
@@ -44,7 +44,6 @@ 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);
|
||||
@@ -77,7 +76,6 @@ 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 () {
|
||||
@@ -182,7 +180,6 @@ 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();
|
||||
|
||||
@@ -198,7 +198,6 @@ 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
|
||||
@@ -271,7 +270,6 @@ context(
|
||||
});
|
||||
})
|
||||
.then(function () {
|
||||
// @ts-ignore clash between jest and cypress
|
||||
expect(this.value).to.equal(this.locked + this.unlocked);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -105,7 +105,6 @@ 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(() => {
|
||||
@@ -126,7 +125,6 @@ context(
|
||||
|
||||
it(
|
||||
'should have Vega Associated currency value visible',
|
||||
// @ts-ignore clash between jest and cypress
|
||||
{ tags: '@smoke' },
|
||||
function () {
|
||||
cy.get(walletContainer).within(() => {
|
||||
@@ -137,19 +135,14 @@ context(
|
||||
}
|
||||
);
|
||||
|
||||
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 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 Governance button visible', function () {
|
||||
cy.get(walletContainer).within(() => {
|
||||
@@ -302,17 +295,13 @@ context(
|
||||
|
||||
cy.getByTestId(vegaWalletCurrencyTitle)
|
||||
.contains(name)
|
||||
.parent() // back to currency-title
|
||||
.parent() // back to container
|
||||
.within(() => {
|
||||
cy.get(
|
||||
'[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);
|
||||
});
|
||||
.parent()
|
||||
.siblings(txTimeout)
|
||||
.should((elementAmount) => {
|
||||
const displayedAmount = parseFloat(elementAmount.text());
|
||||
expect(displayedAmount).be.gte(expectedAmount);
|
||||
});
|
||||
|
||||
cy.getByTestId(vegaWalletCurrencyTitle)
|
||||
.contains(name)
|
||||
.parent()
|
||||
|
||||
@@ -256,7 +256,10 @@ export function validateWalletCurrency(
|
||||
.parent()
|
||||
.parent()
|
||||
.within(() => {
|
||||
cy.get('[data-value]', txTimeout).should('have.text', expectedAmount);
|
||||
cy.getByTestId('currency-value', txTimeout).should(
|
||||
'have.text',
|
||||
expectedAmount
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ CYPRESS_FAIRGROUND=false
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
NX_REFERRALS=true
|
||||
|
||||
@@ -23,7 +23,7 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
NX_REFERRALS=true
|
||||
|
||||
@@ -22,7 +22,7 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
NX_REFERRALS=true
|
||||
|
||||
@@ -21,7 +21,7 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
NX_REFERRALS=true
|
||||
|
||||
@@ -49,6 +49,10 @@ There are a few different configuration options offered for this app:
|
||||
| `NX_ETH_WALLET_MNEMONIC` (optional) | The mnemonic to be used to sign transactions with in browser |
|
||||
| `NX_LOCAL_PROVIDER_URL` (optional) | The local node to use to send transaction to when signing in browser |
|
||||
|
||||
## Example configs:
|
||||
|
||||
For example configurations, check out our [netlify.toml](./netlify.toml).
|
||||
|
||||
## Testing
|
||||
|
||||
To run the minimal set of unit tests, run the following:
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[[redirects]]
|
||||
from = "/*"
|
||||
to = "/index.html"
|
||||
status = 200
|
||||
@@ -56,7 +56,7 @@
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/eslint:lint",
|
||||
"executor": "@nx/linter:eslint",
|
||||
"outputs": ["{options.outputFile}"],
|
||||
"options": {
|
||||
"lintFilePatterns": ["apps/governance/**/*.{ts,tsx,js,jsx}"]
|
||||
@@ -66,7 +66,23 @@
|
||||
"executor": "@nx/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/apps/governance"],
|
||||
"options": {
|
||||
"jestConfig": "apps/governance/jest.config.ts"
|
||||
"jestConfig": "apps/governance/jest.config.ts",
|
||||
"passWithNoTests": true
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"ci": true,
|
||||
"codeCoverage": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"build-netlify": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"commands": [
|
||||
"cp apps/governance/netlify.toml netlify.toml",
|
||||
"nx build token"
|
||||
]
|
||||
}
|
||||
},
|
||||
"build-spec": {
|
||||
|
||||
@@ -2,9 +2,9 @@ import * as Sentry from '@sentry/react';
|
||||
import { toBigNum } from '@vegaprotocol/utils';
|
||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWallet, useEagerConnect } from '@vegaprotocol/wallet';
|
||||
import { useFeatureFlags, useEnvironment } from '@vegaprotocol/environment';
|
||||
import { FLAGS, useEnvironment } from '@vegaprotocol/environment';
|
||||
import { useWeb3React } from '@web3-react/core';
|
||||
import React, { Suspense } from 'react';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { SplashError } from './components/splash-error';
|
||||
@@ -15,23 +15,21 @@ import {
|
||||
} from './contexts/app-state/app-state-context';
|
||||
import { useContracts } from './contexts/contracts/contracts-context';
|
||||
import { useRefreshAssociatedBalances } from './hooks/use-refresh-associated-balances';
|
||||
import { useConnectors } from './lib/vega-connectors';
|
||||
import { Connectors } from './lib/vega-connectors';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
|
||||
const useVegaWalletEagerConnect = () => {
|
||||
const connectors = useConnectors();
|
||||
const vegaConnecting = useEagerConnect(connectors);
|
||||
const vegaConnecting = useEagerConnect(Connectors);
|
||||
const { pubKey, connect } = useVegaWallet();
|
||||
const [searchParams] = useSearchParams();
|
||||
const [query] = React.useState(searchParams.get('address'));
|
||||
if (query && !pubKey) {
|
||||
connect(connectors.view);
|
||||
connect(Connectors['view']);
|
||||
}
|
||||
return vegaConnecting;
|
||||
};
|
||||
|
||||
export const AppLoader = ({ children }: { children: React.ReactElement }) => {
|
||||
const featureFlags = useFeatureFlags((state) => state.flags);
|
||||
const { t } = useTranslation();
|
||||
const { account } = useWeb3React();
|
||||
const { VEGA_URL } = useEnvironment();
|
||||
@@ -81,16 +79,10 @@ export const AppLoader = ({ children }: { children: React.ReactElement }) => {
|
||||
}
|
||||
};
|
||||
|
||||
if (!featureFlags.GOVERNANCE_NETWORK_DOWN) {
|
||||
if (!FLAGS.GOVERNANCE_NETWORK_DOWN) {
|
||||
run();
|
||||
}
|
||||
}, [
|
||||
token,
|
||||
appDispatch,
|
||||
staking,
|
||||
vesting,
|
||||
featureFlags.GOVERNANCE_NETWORK_DOWN,
|
||||
]);
|
||||
}, [token, appDispatch, staking, vesting]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (account && pubKey) {
|
||||
@@ -155,16 +147,16 @@ export const AppLoader = ({ children }: { children: React.ReactElement }) => {
|
||||
};
|
||||
|
||||
// Only begin polling if network limits flag is set, as this is a new API not yet on mainnet 7/3/22
|
||||
if (featureFlags.GOVERNANCE_NETWORK_LIMITS) {
|
||||
if (FLAGS.GOVERNANCE_NETWORK_LIMITS) {
|
||||
getNetworkLimits();
|
||||
}
|
||||
|
||||
return () => {
|
||||
stopPoll();
|
||||
};
|
||||
}, [appDispatch, VEGA_URL, t, featureFlags.GOVERNANCE_NETWORK_LIMITS]);
|
||||
}, [appDispatch, VEGA_URL, t]);
|
||||
|
||||
if (featureFlags.GOVERNANCE_NETWORK_DOWN) {
|
||||
if (FLAGS.GOVERNANCE_NETWORK_DOWN) {
|
||||
return (
|
||||
<Splash>
|
||||
<SplashError />
|
||||
@@ -172,14 +164,13 @@ export const AppLoader = ({ children }: { children: React.ReactElement }) => {
|
||||
);
|
||||
}
|
||||
|
||||
const loading = (
|
||||
<Splash>
|
||||
<SplashLoader />
|
||||
</Splash>
|
||||
);
|
||||
|
||||
if (!loaded) {
|
||||
return loading;
|
||||
return (
|
||||
<Splash>
|
||||
<SplashLoader />
|
||||
</Splash>
|
||||
);
|
||||
}
|
||||
return <Suspense fallback={loading}>{children}</Suspense>;
|
||||
|
||||
return children;
|
||||
};
|
||||
|
||||
@@ -42,7 +42,6 @@ import {
|
||||
useNodeSwitcherStore,
|
||||
DocsLinks,
|
||||
NodeFailure,
|
||||
AppLoader as Loader,
|
||||
} from '@vegaprotocol/environment';
|
||||
import { ENV } from './config';
|
||||
import type { InMemoryCacheConfig } from '@apollo/client';
|
||||
@@ -353,11 +352,9 @@ function App() {
|
||||
useInitializeEnv();
|
||||
|
||||
return (
|
||||
<React.Suspense fallback={<Loader />}>
|
||||
<NetworkLoader cache={cache}>
|
||||
<AppContainer />
|
||||
</NetworkLoader>
|
||||
</React.Suspense>
|
||||
<NetworkLoader cache={cache}>
|
||||
<AppContainer />
|
||||
</NetworkLoader>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../../../../libs/i18n/src/locales
|
||||
@@ -23,13 +23,10 @@ export const Heading = ({
|
||||
})}
|
||||
>
|
||||
<h1
|
||||
className={classNames(
|
||||
'font-alpha calt text-5xl [word-break:break-word]',
|
||||
{
|
||||
'mt-0': !marginTop,
|
||||
'mb-0': !marginBottom,
|
||||
}
|
||||
)}
|
||||
className={classNames('font-alpha calt text-5xl break-words', {
|
||||
'mt-0': !marginTop,
|
||||
'mb-0': !marginBottom,
|
||||
})}
|
||||
>
|
||||
{title}
|
||||
</h1>
|
||||
|
||||
@@ -7,16 +7,16 @@ import {
|
||||
AppStateActionType,
|
||||
useAppState,
|
||||
} from '../../contexts/app-state/app-state-context';
|
||||
import { useConnectors } from '../../lib/vega-connectors';
|
||||
import { Connectors } from '../../lib/vega-connectors';
|
||||
import { RiskMessage } from './risk-message';
|
||||
|
||||
export const VegaWalletDialogs = () => {
|
||||
const { appState, appDispatch } = useAppState();
|
||||
const connectors = useConnectors();
|
||||
|
||||
return (
|
||||
<>
|
||||
<VegaConnectDialog
|
||||
connectors={connectors}
|
||||
connectors={Connectors}
|
||||
riskMessage={<RiskMessage />}
|
||||
/>
|
||||
|
||||
@@ -30,7 +30,7 @@ export const VegaWalletDialogs = () => {
|
||||
}
|
||||
/>
|
||||
|
||||
<ViewAsDialog connector={connectors.view} />
|
||||
<ViewAsDialog connector={Connectors.view} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -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 {
|
||||
DelegationsDocument,
|
||||
type DelegationsQuery,
|
||||
type DelegationsQueryVariables,
|
||||
type WalletDelegationFieldsFragment,
|
||||
import type {
|
||||
DelegationsQuery,
|
||||
DelegationsQueryVariables,
|
||||
WalletDelegationFieldsFragment,
|
||||
} from './__generated__/Delegations';
|
||||
import { DelegationsDocument } from './__generated__/Delegations';
|
||||
import { isPartyNotFoundError } from '../../lib/party';
|
||||
|
||||
export const usePollForDelegations = () => {
|
||||
@@ -44,7 +44,6 @@ export const usePollForDelegations = () => {
|
||||
const [delegatedNodes, setDelegatedNodes] = React.useState<
|
||||
{
|
||||
nodeId: string;
|
||||
// eslint-disable-next-line
|
||||
name: string;
|
||||
hasStakePending: boolean;
|
||||
currentEpochStake?: BigNumber;
|
||||
@@ -114,16 +113,6 @@ export const usePollForDelegations = () => {
|
||||
isAssetTypeERC20(a.asset) &&
|
||||
a.asset.source.contractAddress === vegaToken.address;
|
||||
|
||||
const isVesting =
|
||||
a.type === Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS ||
|
||||
a.type === Schema.AccountType.ACCOUNT_TYPE_VESTING_REWARDS;
|
||||
|
||||
let icon = noIcon;
|
||||
if (isVega) {
|
||||
if (isVesting) icon = vegaVesting;
|
||||
else icon = vegaBlack;
|
||||
}
|
||||
|
||||
return {
|
||||
isVega,
|
||||
name: a.asset.name,
|
||||
@@ -134,7 +123,14 @@ export const usePollForDelegations = () => {
|
||||
balance: new BigNumber(
|
||||
addDecimal(a.balance, a.asset.decimals)
|
||||
),
|
||||
image: icon,
|
||||
image: isVega
|
||||
? vegaBlack
|
||||
: a.type ===
|
||||
Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS ||
|
||||
a.type ===
|
||||
Schema.AccountType.ACCOUNT_TYPE_VESTING_REWARDS
|
||||
? vegaVesting
|
||||
: noIcon,
|
||||
border: isVega,
|
||||
address: isAssetTypeERC20(a.asset)
|
||||
? a.asset.source.contractAddress
|
||||
|
||||
@@ -11,10 +11,7 @@ import { BigNumber } from '../../lib/bignumber';
|
||||
import { truncateMiddle } from '../../lib/truncate-middle';
|
||||
import Routes from '../../routes/routes';
|
||||
import { BulletHeader } from '../bullet-header';
|
||||
import type {
|
||||
WalletCardAssetProps,
|
||||
WalletCardAssetWithMultipleBalancesProps,
|
||||
} from '../wallet-card';
|
||||
import type { WalletCardAssetProps } from '../wallet-card';
|
||||
import {
|
||||
WalletCard,
|
||||
WalletCardActions,
|
||||
@@ -30,7 +27,6 @@ import { Button, ButtonLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { toBigNum } from '@vegaprotocol/utils';
|
||||
import { usePendingBalancesStore } from '../../hooks/use-pending-balances-manager';
|
||||
import { StakingEventType } from '../../hooks/use-get-association-breakdown';
|
||||
import omit from 'lodash/omit';
|
||||
|
||||
export const VegaWallet = () => {
|
||||
const { t } = useTranslation();
|
||||
@@ -103,29 +99,12 @@ const VegaWalletAssetList = ({ accounts }: VegaWalletAssetsListProps) => {
|
||||
if (!accounts.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const groupedByAsset = accounts.reduce((all, a) => {
|
||||
const foundIndex = all.findIndex((acc) => acc.assetId === a.assetId);
|
||||
if (foundIndex > -1) {
|
||||
const found = all[foundIndex];
|
||||
all[foundIndex] = {
|
||||
...found,
|
||||
balances: [...found.balances, { balance: a.balance, type: a.type }],
|
||||
};
|
||||
return all;
|
||||
}
|
||||
const acc = {
|
||||
...omit(a, 'balance', 'type'),
|
||||
balances: [{ balance: a.balance, type: a.type }],
|
||||
};
|
||||
return [...all, acc];
|
||||
}, [] as WalletCardAssetWithMultipleBalancesProps[]);
|
||||
return (
|
||||
<>
|
||||
<WalletCardHeader>
|
||||
<BulletHeader tag="h2">{t('assets')}</BulletHeader>
|
||||
</WalletCardHeader>
|
||||
{groupedByAsset.map((a, i) => (
|
||||
{accounts.map((a, i) => (
|
||||
<WalletCardAsset key={i} {...a} />
|
||||
))}
|
||||
</>
|
||||
@@ -203,7 +182,6 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
|
||||
subheading={t('Associated')}
|
||||
symbol="VEGA"
|
||||
balance={currentStakeAvailable}
|
||||
allowZeroBalance={true}
|
||||
/>
|
||||
{totalPending.eq(0) ? null : (
|
||||
<>
|
||||
@@ -214,7 +192,6 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
|
||||
subheading={t('Pending association')}
|
||||
symbol="VEGA"
|
||||
balance={totalPending}
|
||||
allowZeroBalance={true}
|
||||
/>
|
||||
<WalletCardAsset
|
||||
image={vegaWhite}
|
||||
@@ -223,7 +200,6 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
|
||||
subheading={t('Total associated after pending')}
|
||||
symbol="VEGA"
|
||||
balance={pendingStakeAmount}
|
||||
allowZeroBalance={true}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -103,7 +103,7 @@ export const WalletCardActions = ({
|
||||
return <div className="flex justify-end gap-2 mb-4">{children}</div>;
|
||||
};
|
||||
|
||||
export type WalletCardAssetProps = {
|
||||
export interface WalletCardAssetProps {
|
||||
image: string;
|
||||
name: string;
|
||||
symbol: string;
|
||||
@@ -113,61 +113,42 @@ export type WalletCardAssetProps = {
|
||||
border?: boolean;
|
||||
subheading?: string;
|
||||
type?: Schema.AccountType;
|
||||
allowZeroBalance?: boolean;
|
||||
};
|
||||
|
||||
export type WalletCardAssetWithMultipleBalancesProps = Omit<
|
||||
WalletCardAssetProps,
|
||||
'balance' | 'type'
|
||||
> & {
|
||||
balances: { balance: BigNumber; type?: Schema.AccountType }[];
|
||||
};
|
||||
}
|
||||
|
||||
export const WalletCardAsset = ({
|
||||
image,
|
||||
name,
|
||||
symbol,
|
||||
balance,
|
||||
decimals,
|
||||
assetId,
|
||||
border,
|
||||
subheading,
|
||||
allowZeroBalance = false,
|
||||
...props
|
||||
}: WalletCardAssetProps | WalletCardAssetWithMultipleBalancesProps) => {
|
||||
const balance = 'balance' in props ? props.balance : undefined;
|
||||
const type = 'type' in props ? props.type : undefined;
|
||||
const balances =
|
||||
'balances' in props
|
||||
? props.balances
|
||||
: balance
|
||||
? [{ balance, type }]
|
||||
: undefined;
|
||||
type,
|
||||
}: WalletCardAssetProps) => {
|
||||
const [integers, decimalsPlaces, separator] = useNumberParts(
|
||||
balance,
|
||||
decimals
|
||||
);
|
||||
const { t } = useTranslation();
|
||||
const consoleLink = useLinks(DApp.Console);
|
||||
const transferAssetLink = (assetId: string) =>
|
||||
consoleLink(CONSOLE_TRANSFER_ASSET.replace(':assetId', assetId));
|
||||
const { param: baseRate } = useNetworkParam('rewards_vesting_baseRate');
|
||||
|
||||
const values =
|
||||
balances &&
|
||||
balances.length > 0 &&
|
||||
balances
|
||||
.filter((b) => allowZeroBalance || !b.balance.isZero())
|
||||
.sort((a, b) => {
|
||||
const order = [
|
||||
Schema.AccountType.ACCOUNT_TYPE_VESTING_REWARDS,
|
||||
Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS,
|
||||
Schema.AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
undefined,
|
||||
];
|
||||
return order.indexOf(a.type) - order.indexOf(b.type);
|
||||
})
|
||||
.map(({ balance, type }, i) => (
|
||||
<CurrencyValue
|
||||
key={i}
|
||||
balance={balance}
|
||||
decimals={decimals}
|
||||
type={type}
|
||||
assetId={assetId}
|
||||
/>
|
||||
));
|
||||
const isRedeemable =
|
||||
type === Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS && assetId;
|
||||
|
||||
if (!values || values.length === 0) return;
|
||||
const accountTypeTooltip = useMemo(() => {
|
||||
if (type === Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS) {
|
||||
return t('VestedRewardsTooltip');
|
||||
}
|
||||
if (type === Schema.AccountType.ACCOUNT_TYPE_VESTING_REWARDS && baseRate) {
|
||||
return t('VestingRewardsTooltip', { baseRate });
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [baseRate, t, type]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-nowrap gap-2 mt-2 mb-4">
|
||||
@@ -188,92 +169,35 @@ export const WalletCardAsset = ({
|
||||
{subheading || symbol}
|
||||
</div>
|
||||
</div>
|
||||
{values}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const useAccountTypeTooltip = (type?: Schema.AccountType) => {
|
||||
const { t } = useTranslation();
|
||||
const { param: baseRate } = useNetworkParam('rewards_vesting_baseRate');
|
||||
const accountTypeTooltip = useMemo(() => {
|
||||
if (type === Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS) {
|
||||
return t('VestedRewardsTooltip');
|
||||
}
|
||||
if (type === Schema.AccountType.ACCOUNT_TYPE_VESTING_REWARDS && baseRate) {
|
||||
return t('VestingRewardsTooltip', { baseRate });
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [baseRate, t, type]);
|
||||
|
||||
return accountTypeTooltip;
|
||||
};
|
||||
|
||||
const CurrencyValue = ({
|
||||
balance,
|
||||
decimals,
|
||||
type,
|
||||
assetId,
|
||||
}: {
|
||||
balance: BigNumber;
|
||||
decimals: number;
|
||||
type?: Schema.AccountType;
|
||||
assetId?: string;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const consoleLink = useLinks(DApp.Console);
|
||||
const transferAssetLink = (assetId: string) =>
|
||||
consoleLink(CONSOLE_TRANSFER_ASSET.replace(':assetId', assetId));
|
||||
|
||||
const [integers, decimalsPlaces, separator] = useNumberParts(
|
||||
balance,
|
||||
decimals
|
||||
);
|
||||
const accountTypeTooltip = useAccountTypeTooltip(type);
|
||||
|
||||
const accountType = type && (
|
||||
<Tooltip description={accountTypeTooltip}>
|
||||
<span className="px-2 py-1 leading-none text-xs bg-vega-cdark-700 rounded">
|
||||
{Schema.AccountTypeMapping[type]}
|
||||
</span>
|
||||
</Tooltip>
|
||||
);
|
||||
const isRedeemable =
|
||||
type === Schema.AccountType.ACCOUNT_TYPE_VESTED_REWARDS && assetId;
|
||||
const redeemBtn = isRedeemable ? (
|
||||
<Tooltip description={t('RedeemRewardsTooltip')}>
|
||||
<AnchorButton
|
||||
variant="primary"
|
||||
size="xs"
|
||||
href={transferAssetLink(assetId)}
|
||||
target="_blank"
|
||||
className="px-2 py-1 leading-none text-xs bg-vega-yellow text-black rounded"
|
||||
>
|
||||
{t('Redeem')}
|
||||
</AnchorButton>
|
||||
</Tooltip>
|
||||
) : null;
|
||||
|
||||
return (
|
||||
<div
|
||||
className="basis-full font-mono mb-1"
|
||||
data-account-type={type?.toLowerCase() || 'unspecified'}
|
||||
data-testid="currency-value"
|
||||
>
|
||||
{type && (
|
||||
<div data-type className="flex gap-1">
|
||||
{accountType}
|
||||
{redeemBtn}
|
||||
{type ? (
|
||||
<div className="mb-[2px] flex gap-2 items-baseline">
|
||||
<Tooltip description={accountTypeTooltip}>
|
||||
<span className="px-2 py-1 leading-none text-xs bg-vega-cdark-700 rounded">
|
||||
{Schema.AccountTypeMapping[type]}
|
||||
</span>
|
||||
</Tooltip>
|
||||
{isRedeemable ? (
|
||||
<Tooltip description={t('RedeemRewardsTooltip')}>
|
||||
<AnchorButton
|
||||
variant="primary"
|
||||
size="xs"
|
||||
href={transferAssetLink(assetId)}
|
||||
target="_blank"
|
||||
className="px-2 py-1 leading-none text-xs bg-vega-yellow text-black rounded"
|
||||
>
|
||||
{t('Redeem')}
|
||||
</AnchorButton>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
<div className="basis-full font-mono" data-testid="currency-value">
|
||||
<span>
|
||||
{integers}
|
||||
{separator}
|
||||
</span>
|
||||
<span className="text-neutral-400">{decimalsPlaces}</span>
|
||||
</div>
|
||||
)}
|
||||
<div data-value>
|
||||
<span>
|
||||
{integers}
|
||||
{separator}
|
||||
</span>
|
||||
<span className="text-neutral-400">{decimalsPlaces}</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -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';
|
||||
@@ -49,8 +49,12 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
|
||||
? activeProvider
|
||||
: defaultProvider;
|
||||
|
||||
if (account && provider && typeof provider.getSigner === 'function') {
|
||||
signer = provider.getSigner(account);
|
||||
if (
|
||||
account &&
|
||||
activeProvider &&
|
||||
typeof activeProvider.getSigner === 'function'
|
||||
) {
|
||||
signer = provider.getSigner();
|
||||
}
|
||||
|
||||
const tokenVestingAddress =
|
||||
|
||||
@@ -1,42 +1,29 @@
|
||||
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';
|
||||
|
||||
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;
|
||||
import dev from './translations/dev.json';
|
||||
|
||||
i18n
|
||||
.use(Backend)
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
lng: 'en',
|
||||
// we init with resources
|
||||
resources: {
|
||||
en: {
|
||||
translations: {
|
||||
...dev,
|
||||
},
|
||||
},
|
||||
},
|
||||
lng: undefined,
|
||||
fallbackLng: 'en',
|
||||
supportedLngs: ['en'],
|
||||
load: 'languageOnly',
|
||||
debug: isInDev,
|
||||
debug: true,
|
||||
// have a common namespace used around the full app
|
||||
ns: ['governance'],
|
||||
defaultNS: 'governance',
|
||||
ns: ['translations'],
|
||||
defaultNS: 'translations',
|
||||
keySeparator: false, // we use content as keys
|
||||
nsSeparator: false,
|
||||
backend,
|
||||
saveMissing: useLocize && !!process.env.NX_LOCIZE_API_KEY,
|
||||
|
||||
interpolation: {
|
||||
escapeValue: false,
|
||||
},
|
||||
|
||||
+924
-924
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,4 @@
|
||||
import { useFeatureFlags } from '@vegaprotocol/environment';
|
||||
import { useMemo } from 'react';
|
||||
import { FLAGS } from '@vegaprotocol/environment';
|
||||
import {
|
||||
JsonRpcConnector,
|
||||
ViewConnector,
|
||||
@@ -14,17 +13,13 @@ export const jsonRpc = new JsonRpcConnector();
|
||||
export const injected = new InjectedConnector();
|
||||
export const view = new ViewConnector(urlParams.get('address'));
|
||||
|
||||
export const snap = new SnapConnector(DEFAULT_SNAP_ID);
|
||||
export const snap = FLAGS.METAMASK_SNAPS
|
||||
? new SnapConnector(DEFAULT_SNAP_ID)
|
||||
: undefined;
|
||||
|
||||
export const useConnectors = () => {
|
||||
const featureFlags = useFeatureFlags((state) => state.flags);
|
||||
return useMemo(
|
||||
() => ({
|
||||
injected,
|
||||
jsonRpc,
|
||||
view,
|
||||
snap: featureFlags.METAMASK_SNAPS ? snap : undefined,
|
||||
}),
|
||||
[featureFlags.METAMASK_SNAPS]
|
||||
);
|
||||
export const Connectors = {
|
||||
injected,
|
||||
jsonRpc,
|
||||
view,
|
||||
snap,
|
||||
};
|
||||
|
||||
@@ -12,7 +12,7 @@ import { useRefreshAfterEpoch } from '../../hooks/use-refresh-after-epoch';
|
||||
import { ProposalsListItem } from '../proposals/components/proposals-list-item';
|
||||
import { ProtocolUpgradeProposalsListItem } from '../proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item';
|
||||
import Routes from '../routes';
|
||||
import { ExternalLinks, useFeatureFlags } from '@vegaprotocol/environment';
|
||||
import { ExternalLinks, FLAGS } from '@vegaprotocol/environment';
|
||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import { useNodesQuery } from '../staking/home/__generated__/Nodes';
|
||||
import { useProposalsQuery } from '../proposals/proposals/__generated__/Proposals';
|
||||
@@ -175,7 +175,6 @@ export const ValidatorDetailsLink = ({
|
||||
};
|
||||
|
||||
const GovernanceHome = ({ name }: RouteChildProps) => {
|
||||
const featureFlags = useFeatureFlags((state) => state.flags);
|
||||
useDocumentTitle(name);
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
@@ -187,9 +186,9 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
|
||||
fetchPolicy: 'network-only',
|
||||
errorPolicy: 'ignore',
|
||||
variables: {
|
||||
includeNewMarketProductFields: !!featureFlags.PRODUCT_PERPETUALS,
|
||||
includeUpdateMarketStates: !!featureFlags.UPDATE_MARKET_STATE,
|
||||
includeUpdateReferralPrograms: !!featureFlags.REFERRALS,
|
||||
includeNewMarketProductFields: !!FLAGS.PRODUCT_PERPETUALS,
|
||||
includeUpdateMarketStates: !!FLAGS.UPDATE_MARKET_STATE,
|
||||
includeUpdateReferralPrograms: !!FLAGS.REFERRALS,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -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 (
|
||||
<div className="mb-8">
|
||||
<h3 className="mb-2 text-xl">{t('ListAsset')}</h3>
|
||||
<h3 className="text-xl mb-2">{t('ListAsset')}</h3>
|
||||
<p className="pr-8">{t('ListAssetDescription')}</p>
|
||||
<EthWalletContainer>
|
||||
<Button
|
||||
|
||||
-3
@@ -7,10 +7,8 @@ import type { AssetFieldsFragment } from '@vegaprotocol/assets';
|
||||
|
||||
export const ProposalAssetDetails = ({
|
||||
asset,
|
||||
originalAsset,
|
||||
}: {
|
||||
asset: AssetFieldsFragment;
|
||||
originalAsset?: AssetFieldsFragment;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [showAssetDetails, setShowAssetDetails] = useState(false);
|
||||
@@ -29,7 +27,6 @@ export const ProposalAssetDetails = ({
|
||||
<div className="mb-10 pb-4">
|
||||
<AssetDetailsTable
|
||||
asset={asset}
|
||||
originalAsset={originalAsset}
|
||||
omitRows={[
|
||||
AssetDetail.STATUS,
|
||||
AssetDetail.INFRASTRUCTURE_FEE_ACCOUNT_BALANCE,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user