Compare commits
31
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45c3453af6 | ||
|
|
01fa0657e6 | ||
|
|
60ca6c2eb6 | ||
|
|
eeff4ffcd4 | ||
|
|
73ae00f12c | ||
|
|
8b249e1917 | ||
|
|
abb771e2f9 | ||
|
|
acf1d50d0f | ||
|
|
30da1663eb | ||
|
|
79cbe62774 | ||
|
|
2f0be0bf34 | ||
|
|
5b5802104e | ||
|
|
ff2e2574f6 | ||
|
|
478cc9e753 | ||
|
|
e2a72cb395 | ||
|
|
7fe269fad6 | ||
|
|
b761023069 | ||
|
|
7ac3a68ac9 | ||
|
|
2640ccb20a | ||
|
|
d78de10855 | ||
|
|
bb402c02f6 | ||
|
|
8a9b1c7874 | ||
|
|
a7e8b0eb01 | ||
|
|
89b3c06107 | ||
|
|
cd5c73d3fd | ||
|
|
b3a5ab022d | ||
|
|
496d1f5c68 | ||
|
|
e914e7bb70 | ||
|
|
71a36c2382 | ||
|
|
1c6a307bcd | ||
|
|
ef4a740b91 |
@@ -5,12 +5,12 @@ on:
|
||||
branches:
|
||||
- release/*
|
||||
- develop
|
||||
- main
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- ready_for_review
|
||||
- reopened
|
||||
- edited
|
||||
- synchronize
|
||||
jobs:
|
||||
node-modules:
|
||||
@@ -42,13 +42,6 @@ jobs:
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: yarn install --pure-lockfile
|
||||
|
||||
lint-pr-title:
|
||||
needs: node-modules
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
name: Verify PR title
|
||||
uses: ./.github/workflows/lint-pr.yml
|
||||
secrets: inherit
|
||||
|
||||
lint-format:
|
||||
timeout-minutes: 20
|
||||
needs: node-modules
|
||||
@@ -175,19 +168,42 @@ jobs:
|
||||
preview_explorer: ${{ env.PREVIEW_EXPLORER }}
|
||||
preview_tools: ${{ env.PREVIEW_TOOLS }}
|
||||
|
||||
console-e2e:
|
||||
# console-e2e:
|
||||
# needs: build-sources
|
||||
# name: '(CI) console python'
|
||||
# uses: ./.github/workflows/console-test-run.yml
|
||||
# secrets: inherit
|
||||
# if: ${{ contains(fromJSON(needs.build-sources.outputs.projects), 'trading') && github.event_name == 'pull_request' }}
|
||||
# with:
|
||||
# github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
check-e2e-needed:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build-sources
|
||||
name: '(CI) console python'
|
||||
uses: ./.github/workflows/console-test-run.yml
|
||||
secrets: inherit
|
||||
if: ${{ contains(fromJSON(needs.build-sources.outputs.projects), 'trading') && github.event_name == 'pull_request' }}
|
||||
with:
|
||||
github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
name: '(CI) check if e2e needed'
|
||||
outputs:
|
||||
run-tests: ${{ steps.check-test.outputs.e2e-needed }}
|
||||
steps:
|
||||
- name: Check branch
|
||||
id: check-test
|
||||
run: |
|
||||
if [ '${{ github.base_ref }}' == 'develop' ]; then
|
||||
echo "e2e-needed=true" >> $GITHUB_OUTPUT
|
||||
elif [ '${{ github.base_ref }}' == 'main' ]; then
|
||||
echo "e2e-needed=true" >> $GITHUB_OUTPUT
|
||||
elif [[ '${{ github.event_name }}' == 'push' && ${{ contains(github.ref_name, 'release/') }} ]]; then
|
||||
echo "e2e-needed=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "e2e-needed=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
- name: Print result
|
||||
run: |
|
||||
echo "e2e-needed: ${{ steps.check-test.outputs.e2e-needed }}"
|
||||
|
||||
cypress:
|
||||
needs: build-sources
|
||||
needs: [build-sources, check-e2e-needed]
|
||||
name: '(CI) cypress'
|
||||
# if: ${{ needs.build-sources.outputs.projects-e2e != '[]' }}
|
||||
if: ${{ needs.check-e2e-needed.outputs.run-tests == 'true' }}
|
||||
uses: ./.github/workflows/cypress-run.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
|
||||
@@ -6,23 +6,37 @@ on:
|
||||
github-sha:
|
||||
required: true
|
||||
type: string
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
console-test-branch:
|
||||
type: choice
|
||||
description: 'main: v0.72.14, develop: v0.73.0-preview7'
|
||||
options:
|
||||
- main
|
||||
- develop
|
||||
|
||||
jobs:
|
||||
run-tests:
|
||||
name: run-tests
|
||||
runs-on: console-test
|
||||
runs-on: 8-cores
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
#----------------------------------------------
|
||||
# check-out frontend-monorepo
|
||||
#----------------------------------------------
|
||||
- name: Checkout console test repo
|
||||
- name: Checkout frontend-monorepo
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ inputs.github-sha }}
|
||||
ref: ${{ inputs.github-sha || github.sha }}
|
||||
#----------------------------------------------
|
||||
# cache node modules
|
||||
#----------------------------------------------
|
||||
- name: setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: '16'
|
||||
cache: yarn
|
||||
|
||||
- name: Cache node modules
|
||||
id: cache
|
||||
uses: actions/cache@v3
|
||||
@@ -65,32 +79,42 @@ jobs:
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: vegaprotocol/console-test
|
||||
ref: ${{ inputs.console-test-branch }}
|
||||
path: './console-test'
|
||||
|
||||
- name: Load console test envs
|
||||
id: console-test-env
|
||||
uses: falti/dotenv-action@v1.0.4
|
||||
with:
|
||||
path: './console-test/.env.${{ inputs.console-test-branch }}'
|
||||
export-variables: true
|
||||
keys-case: upper
|
||||
log-variables: true
|
||||
|
||||
#----------------------------------------------
|
||||
# install dependencies if cache does not exist
|
||||
#----------------------------------------------
|
||||
- name: Install dependencies
|
||||
working-directory: ./console-test
|
||||
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
|
||||
run: poetry install --no-interaction --no-root
|
||||
#----------------------------------------------
|
||||
# install vega binaries
|
||||
#----------------------------------------------
|
||||
- name: Install vega binaries
|
||||
working-directory: ./console-test
|
||||
run: poetry run python -m vega_sim.tools.load_binaries --force
|
||||
run: poetry run python -m vega_sim.tools.load_binaries --force --version ${{ env.VEGA_VERSION }}
|
||||
#----------------------------------------------
|
||||
# install playwright
|
||||
#----------------------------------------------
|
||||
- name: install playwright
|
||||
run: poetry run playwright install
|
||||
run: poetry run playwright install --with-deps chromium
|
||||
working-directory: ./console-test
|
||||
#----------------------------------------------
|
||||
# run tests
|
||||
#----------------------------------------------
|
||||
- name: Run tests
|
||||
working-directory: ./console-test
|
||||
run: poetry run pytest -v -s --numprocesses 2 --dist loadfile --durations=20
|
||||
run: poetry run pytest -v -s --numprocesses 4 --dist loadfile --durations=15
|
||||
- name: Check files
|
||||
run: |
|
||||
ls -al .
|
||||
@@ -105,3 +129,13 @@ jobs:
|
||||
name: playwright-trace
|
||||
path: ./traces/
|
||||
retention-days: 15
|
||||
#----------------------------------------------
|
||||
# ----- upload logs -----
|
||||
#----------------------------------------------
|
||||
- name: Upload worker logs
|
||||
uses: actions/upload-artifact@v3
|
||||
if: always()
|
||||
with:
|
||||
name: worker-logs
|
||||
path: ./logs/
|
||||
retention-days: 15
|
||||
|
||||
@@ -13,13 +13,35 @@ on:
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
runner-choice:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
runner: ${{ steps.step.outputs.runner }}
|
||||
steps:
|
||||
- name: Check branch
|
||||
id: step
|
||||
run: |
|
||||
if [ '${{ github.base_ref }}' == 'main' ]; then
|
||||
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
|
||||
elif [[ '${{ github.base_ref }}' == 'develop' && '${{ github.ref_name }}' == 'main' ]]; then
|
||||
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
|
||||
elif [[ '${{ github.event_name }}' == 'push' && ${{ contains(github.ref_name, 'release/mainnet') }} ]]; then
|
||||
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "runner=self-hosted-runner" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Print runner
|
||||
run: echo ${{ steps.step.outputs.runner }}
|
||||
|
||||
e2e:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
project: ${{ fromJSON(inputs.projects) }}
|
||||
name: ${{ matrix.project }}
|
||||
runs-on: self-hosted-runner
|
||||
needs: runner-choice
|
||||
runs-on: ${{ needs.runner-choice.outputs.runner }}
|
||||
timeout-minutes: 120
|
||||
steps:
|
||||
# Checks if skip cache was requested
|
||||
@@ -63,6 +85,7 @@ jobs:
|
||||
- name: Run Vegacapsule network and Vega wallet
|
||||
id: setup-vega
|
||||
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
|
||||
timeout-minutes: 10
|
||||
|
||||
######
|
||||
## Run some tests
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
name: Verify PR title
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- reopened
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
lint_pr:
|
||||
@@ -11,21 +16,16 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
cache: yarn
|
||||
node-version: 16
|
||||
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: node_modules
|
||||
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
rm package.json
|
||||
npm install --no-save @commitlint/cli @commitlint/config-conventional @commitlint/config-nx-scopes nx
|
||||
|
||||
- name: Check PR title
|
||||
run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js
|
||||
|
||||
@@ -30,12 +30,18 @@ jobs:
|
||||
echo IS_IPFS_RELEASE=false >> $GITHUB_ENV
|
||||
echo IS_S3_RELEASE=false >> $GITHUB_ENV
|
||||
echo IS_DEV_IMAGE=false >> $GITHUB_ENV
|
||||
echo IS_MAIN_IMAGE=false >> $GITHUB_ENV
|
||||
|
||||
- name: Is dev image
|
||||
if: ${{ contains(github.ref, 'develop') && github.event_name == 'push' && matrix.app == 'trading' }}
|
||||
if: ${{ github.ref_name == 'develop' && github.event_name == 'push' && matrix.app == 'trading' }}
|
||||
run: |
|
||||
echo IS_DEV_IMAGE=true >> $GITHUB_ENV
|
||||
|
||||
- name: Is main image
|
||||
if: ${{ github.ref_name == 'main' && github.event_name == 'push' && matrix.app == 'trading' }}
|
||||
run: |
|
||||
echo IS_MAIN_IMAGE=true >> $GITHUB_ENV
|
||||
|
||||
- name: Is PR
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
run: |
|
||||
@@ -57,7 +63,7 @@ jobs:
|
||||
echo IS_IPFS_RELEASE=true >> $GITHUB_ENV
|
||||
|
||||
- name: Is S3 Release
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'false' && github.event_name == 'push' }}
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'false' && github.event_name == 'push' && github.ref_name != 'main'}}
|
||||
run: |
|
||||
echo IS_S3_RELEASE=true >> $GITHUB_ENV
|
||||
|
||||
@@ -81,7 +87,7 @@ jobs:
|
||||
|
||||
- name: Log in to the Container registry (docker hub)
|
||||
uses: docker/login-action@v2
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' }}
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' || env.IS_MAIN_IMAGE == 'true' }}
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
@@ -155,10 +161,10 @@ jobs:
|
||||
- name: Sanity check docker image
|
||||
run: |
|
||||
echo "Check ipfs-hash"
|
||||
docker run --rm --entrypoint /bin/sh ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local -c 'cat /ipfs-hash'
|
||||
docker run --rm --entrypoint /bin/sh ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local -c 'cat /ipfs-hash' > ${{ matrix.app }}-ipfs-hash
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local /bin/sh -c 'cat /ipfs-hash'
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local /bin/sh -c 'cat /ipfs-hash' > ${{ matrix.app }}-ipfs-hash
|
||||
echo "List html directory"
|
||||
docker run --rm --entrypoint /bin/sh ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local -c 'apk add --update tree; tree /usr/share/nginx/html'
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local /bin/sh -c 'apk add --update tree; tree /usr/share/nginx/html'
|
||||
|
||||
- name: Publish dist as docker image (ghcr)
|
||||
uses: docker/build-push-action@v3
|
||||
@@ -179,7 +185,7 @@ jobs:
|
||||
uses: docker/build-push-action@v3
|
||||
continue-on-error: true
|
||||
id: dockerhub-push
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' }}
|
||||
if: ${{ env.IS_IPFS_RELEASE == 'true' || env.IS_DEV_IMAGE == 'true' || env.IS_MAIN_IMAGE == 'true' }}
|
||||
with:
|
||||
context: .
|
||||
file: docker/node-outside-docker.Dockerfile
|
||||
@@ -189,7 +195,7 @@ jobs:
|
||||
ENV_NAME=${{ env.ENV_NAME }}
|
||||
tags: |
|
||||
vegaprotocol/${{ matrix.app }}:${{ github.sha }}
|
||||
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || '' }}
|
||||
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || env.IS_MAIN_IMAGE == 'true' && 'main' || '' }}
|
||||
|
||||
- name: Publish dist as docker image (ghcr - retry)
|
||||
uses: docker/build-push-action@v3
|
||||
@@ -216,7 +222,7 @@ jobs:
|
||||
ENV_NAME=${{ env.ENV_NAME }}
|
||||
tags: |
|
||||
vegaprotocol/${{ matrix.app }}:${{ github.sha }}
|
||||
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || '' }}
|
||||
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || env.IS_MAIN_IMAGE == 'true' && 'main' || '' }}
|
||||
|
||||
# bucket creation in github.com/vegaprotocol/terraform//frontend
|
||||
- name: Publish dist to s3
|
||||
@@ -329,7 +335,9 @@ jobs:
|
||||
fi
|
||||
|
||||
# create commit
|
||||
commit_msg="Automated hash update from ${{ github.ref }}"
|
||||
git commit -m "$commit_msg"
|
||||
git push -u origin "main"
|
||||
if ! git diff --cached --exit-code; then
|
||||
commit_msg="Automated hash update from ${{ github.ref }}"
|
||||
git commit -m "$commit_msg"
|
||||
git push -u origin "main"
|
||||
fi
|
||||
)
|
||||
|
||||
@@ -118,7 +118,7 @@ On top of that there are two possible scenarios for running docker image - using
|
||||
to run ipfs on port 3000:
|
||||
|
||||
```bash
|
||||
docker run -p 3000:80 [TAG] ipfs
|
||||
docker run -p 3000:80 [TAG] /run-ipfs.sh
|
||||
```
|
||||
|
||||
to run nginx on port 3000:
|
||||
|
||||
@@ -4,7 +4,7 @@ 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 { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import type { VegaICellRendererParams } from '@vegaprotocol/datagrid';
|
||||
import { useRef, useLayoutEffect } from 'react';
|
||||
import { BREAKPOINT_MD } from '../../config/breakpoints';
|
||||
|
||||
@@ -4,7 +4,7 @@ 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 { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueGetterParams,
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { VoteProgress } from '@vegaprotocol/proposals';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
@@ -105,7 +105,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
||||
? new BigNumber(0)
|
||||
: yesTokens.multipliedBy(100).dividedBy(totalTokensVoted);
|
||||
return (
|
||||
<div className="uppercase flex h-full items-center justify-center pt-2">
|
||||
<div className="flex items-center justify-center h-full pt-2 uppercase">
|
||||
<VoteProgress
|
||||
threshold={requiredMajorityPercentage}
|
||||
progress={yesPercentage}
|
||||
|
||||
@@ -8,7 +8,9 @@ import { useScrollToLocation } from '../../../hooks/scroll-to-location';
|
||||
import filter from 'recursive-key-filter';
|
||||
|
||||
const Oracles = () => {
|
||||
const { data, loading, error } = useExplorerOracleSpecsQuery();
|
||||
const { data, loading, error } = useExplorerOracleSpecsQuery({
|
||||
errorPolicy: 'ignore',
|
||||
});
|
||||
|
||||
useDocumentTitle(['Oracles']);
|
||||
useScrollToLocation();
|
||||
|
||||
@@ -8,6 +8,7 @@ NX_FAIRGROUND=false
|
||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","STAGNET1":"https://governance.stagnet1.vega.rocks","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ NX_VEGA_REST_URL=https://api.vega.community/api/v2/
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-mainnet
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
NX_TENDERMINT_URL=https://be.vega.community
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
||||
|
||||
@@ -15,6 +15,7 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
|
||||
NX_VEGA_REST_URL=https://api.n07.testnet.vega.xyz/api/v2/
|
||||
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
||||
|
||||
@@ -6,6 +6,11 @@ import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MemoryRouter, Route, Routes } from 'react-router-dom';
|
||||
import { ProposalDocument } from './__generated__/Proposal';
|
||||
|
||||
jest.mock('@vegaprotocol/data-provider', () => ({
|
||||
...jest.requireActual('@vegaprotocol/data-provider'),
|
||||
useDataProvider: jest.fn(() => ({ data: [], loading: false })),
|
||||
}));
|
||||
|
||||
jest.mock('../components/proposal', () => ({
|
||||
Proposal: () => <div data-testid="proposal" />,
|
||||
}));
|
||||
|
||||
+5
-5
@@ -3,7 +3,7 @@ import { forwardRef, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Button, Icon } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { useAppState } from '../../../../contexts/app-state/app-state-context';
|
||||
import { BigNumber } from '../../../../lib/bignumber';
|
||||
import {
|
||||
@@ -85,17 +85,17 @@ const TopThirdCellRenderer = (
|
||||
}}
|
||||
className="grid grid-cols-[60px_1fr] w-full h-full py-4 px-0 text-sm text-white text-center overflow-scroll"
|
||||
>
|
||||
<div className="text-xs text-left px-3">
|
||||
<div className="px-3 text-xs text-left">
|
||||
{params?.data?.rankingDisplay}
|
||||
</div>
|
||||
<div className="whitespace-normal px-3">
|
||||
<div className="px-3 whitespace-normal">
|
||||
<div className="mb-4">
|
||||
<Button
|
||||
data-testid="show-all-validators"
|
||||
rightIcon={
|
||||
<Icon
|
||||
name="arrow-right"
|
||||
className="fill-current mr-2 align-text-top"
|
||||
className="mr-2 align-text-top fill-current"
|
||||
/>
|
||||
}
|
||||
className="inline-flex items-center"
|
||||
@@ -103,7 +103,7 @@ const TopThirdCellRenderer = (
|
||||
{t('Reveal top validators')}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="font-semibold text-white mb-0">
|
||||
<p className="mb-0 font-semibold text-white">
|
||||
{t(
|
||||
'Validators with too great a stake share will have the staking rewards for their delegators penalised.'
|
||||
)}
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import { forwardRef, useMemo, useRef } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { useAppState } from '../../../../contexts/app-state/app-state-context';
|
||||
import { BigNumber } from '../../../../lib/bignumber';
|
||||
import {
|
||||
|
||||
@@ -24,9 +24,7 @@ describe('deal ticker order validation', { tags: '@smoke' }, () => {
|
||||
|
||||
beforeEach(() => {
|
||||
cy.mockTradingPage();
|
||||
cy.getByTestId('deal-ticket-fee-margin-required').within(() => {
|
||||
cy.get('button').click();
|
||||
});
|
||||
cy.getByTestId('deal-ticket-fee-margin-required').click();
|
||||
});
|
||||
|
||||
describe('limit order', () => {
|
||||
@@ -111,6 +109,7 @@ describe('deal ticker order validation', { tags: '@smoke' }, () => {
|
||||
'Total margin available100.01 tDAI'
|
||||
);
|
||||
});
|
||||
cy.getByTestId('deal-ticket-fee-margin-required').click();
|
||||
});
|
||||
|
||||
it('must have current margin allocation', () => {
|
||||
@@ -120,6 +119,7 @@ describe('deal ticker order validation', { tags: '@smoke' }, () => {
|
||||
'Current margin allocation'
|
||||
);
|
||||
});
|
||||
cy.getByTestId('deal-ticket-fee-margin-required').click();
|
||||
});
|
||||
|
||||
it('should open usage breakdown dialog when clicked on current margin allocation', () => {
|
||||
@@ -128,6 +128,7 @@ describe('deal ticker order validation', { tags: '@smoke' }, () => {
|
||||
});
|
||||
cy.getByTestId('usage-breakdown').should('exist');
|
||||
cy.getByTestId('dialog-close').click();
|
||||
cy.getByTestId('deal-ticket-fee-margin-required').click();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
testOrderAmendment,
|
||||
} from '../support/order-validation';
|
||||
|
||||
const orderSymbol = 'market.tradableInstrument.instrument.code';
|
||||
const orderSymbol = 'instrument-code';
|
||||
const orderSize = 'size';
|
||||
const orderType = 'type';
|
||||
const orderStatus = 'status';
|
||||
@@ -229,10 +229,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
|
||||
status: Schema.OrderStatus.STATUS_FILLED,
|
||||
});
|
||||
cy.getByTestId(`order-status-${orderId}`).should('have.text', 'Filled');
|
||||
cy.get('[col-id="market.tradableInstrument.instrument.code"]').contains(
|
||||
'[title="Future"]',
|
||||
'Futr'
|
||||
);
|
||||
cy.get(`[col-id="${orderSymbol}"]`).contains('[title="Future"]', 'Futr');
|
||||
});
|
||||
|
||||
it('must see a rejected order', () => {
|
||||
|
||||
@@ -86,8 +86,8 @@ describe('trades', { tags: '@smoke' }, () => {
|
||||
});
|
||||
|
||||
it('copy price to deal ticket form', () => {
|
||||
cy.getByTestId('Order').click();
|
||||
// 6005-THIS-007
|
||||
cy.getByTestId('order-type-Limit').click();
|
||||
cy.get(colIdPrice).last().should('be.visible').click();
|
||||
cy.getByTestId('order-price').should('have.value', '171.16898');
|
||||
});
|
||||
|
||||
@@ -12,6 +12,7 @@ NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
|
||||
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
|
||||
@@ -16,6 +16,7 @@ NX_VEGA_CONSOLE_URL=https://console.vega.xyz
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-mainnet/codfcglpplgmmlokgilfkpcjnmkbfiel
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-mainnet
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
|
||||
@@ -16,7 +16,7 @@ NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
|
||||
@@ -17,6 +17,7 @@ NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
|
||||
@@ -128,7 +128,7 @@ const MainGrid = memo(
|
||||
</Tab>
|
||||
) : null}
|
||||
<Tab id="fills" name={t('Fills')}>
|
||||
<TradingViews.fills.component marketId={marketId} />
|
||||
<TradingViews.fills.component />
|
||||
</Tab>
|
||||
<Tab
|
||||
id="accounts"
|
||||
|
||||
@@ -4,7 +4,7 @@ import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { AgGridLazy as AgGrid, COL_DEFS } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid, COL_DEFS } from '@vegaprotocol/datagrid';
|
||||
import { useMemo } from 'react';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type { ProductType } from '@vegaprotocol/types';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { TypedDataAgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGridLazy as AgGrid, PriceFlashCell } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid, PriceFlashCell } from '@vegaprotocol/datagrid';
|
||||
import type { MarketMaybeWithData } from '@vegaprotocol/markets';
|
||||
import { useColumnDefs } from './use-column-defs';
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import type { DataGridSlice } from '../../stores/datagrid-store-slice';
|
||||
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
|
||||
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||
|
||||
export const FillsContainer = ({ marketId }: { marketId?: string }) => {
|
||||
export const FillsContainer = () => {
|
||||
const onMarketClick = useMarketClickHandler(true);
|
||||
const { pubKey } = useVegaWallet();
|
||||
|
||||
@@ -31,7 +31,6 @@ export const FillsContainer = ({ marketId }: { marketId?: string }) => {
|
||||
return (
|
||||
<FillsManager
|
||||
partyId={pubKey}
|
||||
marketId={marketId}
|
||||
onMarketClick={onMarketClick}
|
||||
gridProps={gridStoreCallbacks}
|
||||
/>
|
||||
|
||||
@@ -53,7 +53,7 @@ export const HeaderStat = ({
|
||||
<div data-testid="item-header" id={id}>
|
||||
{heading}
|
||||
</div>
|
||||
<Tooltip description={description}>
|
||||
<Tooltip description={description} underline>
|
||||
<div
|
||||
data-testid="item-value"
|
||||
aria-labelledby={id}
|
||||
|
||||
@@ -28,14 +28,20 @@ export interface OrderContainerProps {
|
||||
filter?: Filter;
|
||||
}
|
||||
|
||||
const AUTO_SIZE_COLUMNS = ['instrument-code'];
|
||||
|
||||
export const OrdersContainer = ({ filter }: OrderContainerProps) => {
|
||||
const { pubKey, isReadOnly } = useVegaWallet();
|
||||
const onMarketClick = useMarketClickHandler(true);
|
||||
const onOrderTypeClick = useMarketLiquidityClickHandler();
|
||||
const { gridState, updateGridState } = useOrderListGridState(filter);
|
||||
const gridStoreCallbacks = useDataGridEvents(gridState, (newState) => {
|
||||
updateGridState(filter, newState);
|
||||
});
|
||||
const gridStoreCallbacks = useDataGridEvents(
|
||||
gridState,
|
||||
(newState) => {
|
||||
updateGridState(filter, newState);
|
||||
},
|
||||
AUTO_SIZE_COLUMNS
|
||||
);
|
||||
|
||||
if (!pubKey) {
|
||||
return <Splash>{t('Please connect Vega wallet')}</Splash>;
|
||||
|
||||
@@ -10,6 +10,8 @@ import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
|
||||
|
||||
const AUTO_SIZE_COLUMNS = ['marketCode'];
|
||||
|
||||
export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => {
|
||||
const onMarketClick = useMarketClickHandler(true);
|
||||
const { pubKey, pubKeys, isReadOnly } = useVegaWallet();
|
||||
@@ -17,7 +19,11 @@ export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => {
|
||||
const showClosed = usePositionsStore((store) => store.showClosedMarkets);
|
||||
const gridStore = usePositionsStore((store) => store.gridStore);
|
||||
const updateGridStore = usePositionsStore((store) => store.updateGridStore);
|
||||
const gridStoreCallbacks = useDataGridEvents(gridStore, updateGridStore);
|
||||
const gridStoreCallbacks = useDataGridEvents(
|
||||
gridStore,
|
||||
updateGridStore,
|
||||
AUTO_SIZE_COLUMNS
|
||||
);
|
||||
|
||||
if (!pubKey) {
|
||||
return (
|
||||
|
||||
@@ -27,8 +27,8 @@ const GetStartedButton = ({ step }: { step: OnboardingStep }) => {
|
||||
const dismiss = useOnboardingStore((store) => store.dismiss);
|
||||
const setDialogOpen = useOnboardingStore((store) => store.setDialogOpen);
|
||||
const marketId = useGlobalStore((store) => store.marketId);
|
||||
const openVegaWalletDialog = useVegaWalletDialogStore(
|
||||
(store) => store.openVegaWalletDialog
|
||||
const setWalletDialogOpen = useOnboardingStore(
|
||||
(store) => store.setWalletDialogOpen
|
||||
);
|
||||
const setViews = useSidebar((store) => store.setViews);
|
||||
|
||||
@@ -40,7 +40,7 @@ const GetStartedButton = ({ step }: { step: OnboardingStep }) => {
|
||||
|
||||
if (step <= OnboardingStep.ONBOARDING_CONNECT_STEP) {
|
||||
return (
|
||||
<TradingButton {...buttonProps} onClick={() => openVegaWalletDialog()}>
|
||||
<TradingButton {...buttonProps} onClick={() => setWalletDialogOpen(true)}>
|
||||
{t('Connect')}
|
||||
</TradingButton>
|
||||
);
|
||||
@@ -70,7 +70,7 @@ const GetStartedButton = ({ step }: { step: OnboardingStep }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<TradingButton {...buttonProps} onClick={() => openVegaWalletDialog()}>
|
||||
<TradingButton {...buttonProps} onClick={() => setWalletDialogOpen(true)}>
|
||||
{t('Get started')}
|
||||
</TradingButton>
|
||||
);
|
||||
|
||||
@@ -12,16 +12,20 @@ import { useGlobalStore } from '../../stores';
|
||||
const ONBOARDING_STORAGE_KEY = 'vega_onboarding';
|
||||
export const useOnboardingStore = create<{
|
||||
dialogOpen: boolean;
|
||||
walletDialogOpen: boolean;
|
||||
dismissed: boolean;
|
||||
dismiss: () => void;
|
||||
setDialogOpen: (isOpen: boolean) => void;
|
||||
setWalletDialogOpen: (isOpen: boolean) => void;
|
||||
}>()(
|
||||
persist(
|
||||
(set) => ({
|
||||
dialogOpen: true,
|
||||
walletDialogOpen: false,
|
||||
dismissed: false,
|
||||
dismiss: () => set({ dismissed: true }),
|
||||
setDialogOpen: (isOpen) => set({ dialogOpen: isOpen }),
|
||||
setWalletDialogOpen: (isOpen) => set({ walletDialogOpen: isOpen }),
|
||||
}),
|
||||
{
|
||||
name: ONBOARDING_STORAGE_KEY,
|
||||
|
||||
@@ -3,30 +3,54 @@ import { t } from '@vegaprotocol/i18n';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { WelcomeDialogContent } from './welcome-dialog-content';
|
||||
import { useOnboardingStore } from './use-get-onboarding-step';
|
||||
import { VegaConnectDialog } from '@vegaprotocol/wallet';
|
||||
import { Connectors } from '../../lib/vega-connectors';
|
||||
import { RiskMessage } from './risk-message';
|
||||
|
||||
export const WelcomeDialog = () => {
|
||||
const { VEGA_ENV } = useEnvironment();
|
||||
const dismissed = useOnboardingStore((store) => store.dismissed);
|
||||
const dialogOpen = useOnboardingStore((store) => store.dialogOpen);
|
||||
const dismiss = useOnboardingStore((store) => store.dismiss);
|
||||
const walletDialogOpen = useOnboardingStore(
|
||||
(store) => store.walletDialogOpen
|
||||
);
|
||||
const setWalletDialogOpen = useOnboardingStore(
|
||||
(store) => store.setWalletDialogOpen
|
||||
);
|
||||
|
||||
const content = walletDialogOpen ? (
|
||||
<VegaConnectDialog
|
||||
connectors={Connectors}
|
||||
riskMessage={<RiskMessage />}
|
||||
onClose={() => setWalletDialogOpen(false)}
|
||||
contentOnly
|
||||
/>
|
||||
) : (
|
||||
<WelcomeDialogContent />
|
||||
);
|
||||
|
||||
const onClose = walletDialogOpen ? () => setWalletDialogOpen(false) : dismiss;
|
||||
|
||||
const title = walletDialogOpen ? null : (
|
||||
<span className="font-alpha calt" data-testid="welcome-title">
|
||||
{t('Console')}{' '}
|
||||
<span className="text-vega-clight-100 dark:text-vega-cdark-100">
|
||||
{VEGA_ENV}
|
||||
</span>
|
||||
</span>
|
||||
);
|
||||
|
||||
return (
|
||||
<Dialog
|
||||
open={dismissed ? false : dialogOpen}
|
||||
title={
|
||||
<span className="font-alpha calt" data-testid="welcome-title">
|
||||
{t('Console')}{' '}
|
||||
<span className="text-vega-clight-100 dark:text-vega-cdark-100">
|
||||
{VEGA_ENV}
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
title={title}
|
||||
size="medium"
|
||||
onChange={() => dismiss()}
|
||||
onChange={onClose}
|
||||
intent={Intent.None}
|
||||
dataTestId="welcome-dialog"
|
||||
>
|
||||
<WelcomeDialogContent />
|
||||
{content}
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -110,8 +110,8 @@ html [data-theme='light'] {
|
||||
--pennant-color-depth-sell-fill: theme(colors.market.red.DEFAULT);
|
||||
--pennant-color-depth-sell-stroke: theme(colors.market.red.650);
|
||||
|
||||
--pennant-color-volume-buy: theme(colors.market.green.300);
|
||||
--pennant-color-volume-sell: theme(colors.market.red.300);
|
||||
--pennant-color-volume-buy: theme(colors.market.green.DEFAULT);
|
||||
--pennant-color-volume-sell: theme(colors.market.red.DEFAULT);
|
||||
}
|
||||
|
||||
html [data-theme='dark'] {
|
||||
@@ -132,7 +132,7 @@ html [data-theme='dark'] {
|
||||
--pennant-color-depth-sell-stroke: theme(colors.market.red.DEFAULT);
|
||||
|
||||
--pennant-color-volume-buy: theme(colors.market.green.600);
|
||||
--pennant-color-volume-sell: theme(colors.market.red.650);
|
||||
--pennant-color-volume-sell: theme(colors.market.red.DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
daemon="${1:-nginx}"
|
||||
|
||||
if [[ "$daemon" = "nginx" ]]; then
|
||||
nginx -g 'daemon off;'
|
||||
elif [[ "$daemon" = "ipfs" ]]; then
|
||||
ipfs config profile apply server
|
||||
ipfs config --json Addresses.Gateway '"/ip4/127.0.0.1/tcp/80"'
|
||||
ipfs daemon
|
||||
fi
|
||||
@@ -20,8 +20,7 @@ RUN sh docker/docker-build.sh
|
||||
FROM --platform=amd64 nginx:1.23-alpine@sha256:6318314189b40e73145a48060bff4783a116c34cc7241532d0d94198fb2c9629
|
||||
# configuration of system
|
||||
EXPOSE 80
|
||||
COPY docker/entrypoint.sh /entrypoint.sh
|
||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
||||
COPY docker/run-ipfs.sh /run-ipfs.sh
|
||||
# Copy dist
|
||||
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
RUN rm -rf /usr/share/nginx/html/*
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
FROM --platform=amd64 nginx:1.23-alpine@sha256:6318314189b40e73145a48060bff4783a116c34cc7241532d0d94198fb2c9629
|
||||
EXPOSE 80
|
||||
COPY docker/entrypoint.sh /entrypoint.sh
|
||||
ENTRYPOINT [ "/entrypoint.sh" ]
|
||||
COPY docker/run-ipfs.sh /run-ipfs.sh
|
||||
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
RUN rm -rf /usr/share/nginx/html/*
|
||||
COPY ./dist-result/ /usr/share/nginx/html/
|
||||
|
||||
Executable
+4
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
ipfs config profile apply server
|
||||
ipfs config --json Addresses.Gateway '"/ip4/127.0.0.1/tcp/80"'
|
||||
ipfs daemon
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
VegaIconNames,
|
||||
TooltipCellComponent,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import type {
|
||||
IGetRowsParams,
|
||||
IRowNode,
|
||||
|
||||
@@ -13,7 +13,7 @@ import type {
|
||||
VegaICellRendererParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { ProgressBarCell } from '@vegaprotocol/datagrid';
|
||||
import { AgGridLazy as AgGrid, PriceCell } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid, PriceCell } from '@vegaprotocol/datagrid';
|
||||
import type { ColDef } from 'ag-grid-community';
|
||||
import { accountValuesComparator } from './accounts-table';
|
||||
import { MarginHealthChart } from './margin-health-chart';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export * from './lib/ag-grid/ag-grid-lazy';
|
||||
export * from './lib/ag-grid/ag-grid';
|
||||
|
||||
export * from './lib/column-definitions';
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
import { forwardRef, lazy } from 'react';
|
||||
import type { AgGridReactProps, AgGridReact } from 'ag-grid-react';
|
||||
|
||||
type Props = AgGridReactProps & {
|
||||
style?: React.CSSProperties;
|
||||
gridRef?: React.Ref<AgGridReact>;
|
||||
};
|
||||
|
||||
export const AgGridLazyInternal = lazy(() =>
|
||||
import('./ag-grid-lazy-themed').then((module) => ({
|
||||
default: module.AgGridThemed,
|
||||
}))
|
||||
);
|
||||
|
||||
export const AgGridLazy = forwardRef<AgGridReact, Props>((props, ref) => (
|
||||
<AgGridLazyInternal {...props} gridRef={ref} />
|
||||
));
|
||||
@@ -0,0 +1,12 @@
|
||||
import { forwardRef } from 'react';
|
||||
import type { AgGridReactProps, AgGridReact } from 'ag-grid-react';
|
||||
import { AgGridThemed } from './ag-grid-themed';
|
||||
|
||||
type Props = AgGridReactProps & {
|
||||
style?: React.CSSProperties;
|
||||
gridRef?: React.Ref<AgGridReact>;
|
||||
};
|
||||
|
||||
export const AgGrid = forwardRef<AgGridReact, Props>((props, ref) => (
|
||||
<AgGridThemed {...props} gridRef={ref} />
|
||||
));
|
||||
@@ -1,9 +1,6 @@
|
||||
import { act, render, waitFor } from '@testing-library/react';
|
||||
import {
|
||||
useDataGridEvents,
|
||||
GRID_EVENT_DEBOUNCE_TIME,
|
||||
} from './use-datagrid-events';
|
||||
import { AgGridThemed } from './ag-grid/ag-grid-lazy-themed';
|
||||
import { useDataGridEvents } from './use-datagrid-events';
|
||||
import { AgGridThemed } from './ag-grid/ag-grid-themed';
|
||||
import type { MutableRefObject } from 'react';
|
||||
import { useRef } from 'react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
@@ -19,25 +16,29 @@ const gridProps = {
|
||||
],
|
||||
style: { width: 500, height: 300 },
|
||||
};
|
||||
const GRID_EVENT_DEBOUNCE_TIME = 300;
|
||||
let gridRef: MutableRefObject<AgGridReact | null>;
|
||||
function TestComponent({
|
||||
hookParams,
|
||||
}: {
|
||||
hookParams: Parameters<typeof useDataGridEvents>;
|
||||
}) {
|
||||
const hookCallbacks = useDataGridEvents(...hookParams);
|
||||
gridRef = useRef<AgGridReact | null>(null);
|
||||
return <AgGridThemed gridRef={gridRef} {...gridProps} {...hookCallbacks} />;
|
||||
}
|
||||
|
||||
// Not using render hook so I can pass event callbacks
|
||||
// to a rendered grid
|
||||
function setup(...args: Parameters<typeof useDataGridEvents>) {
|
||||
let gridRef;
|
||||
|
||||
function TestComponent() {
|
||||
const hookCallbacks = useDataGridEvents(...args);
|
||||
gridRef = useRef<AgGridReact | null>(null);
|
||||
return <AgGridThemed gridRef={gridRef} {...gridProps} {...hookCallbacks} />;
|
||||
}
|
||||
render(<TestComponent />);
|
||||
return gridRef as unknown as MutableRefObject<AgGridReact>;
|
||||
return render(<TestComponent hookParams={args} />);
|
||||
}
|
||||
|
||||
describe('useDataGridEvents', () => {
|
||||
const originalWarn = console.warn;
|
||||
|
||||
beforeAll(() => {
|
||||
gridRef = undefined;
|
||||
jest.useFakeTimers();
|
||||
|
||||
// disabling some ag grid warnings that are caused by test setup only
|
||||
@@ -56,15 +57,15 @@ describe('useDataGridEvents', () => {
|
||||
columnState: undefined,
|
||||
};
|
||||
|
||||
const result = setup(initialState, callback);
|
||||
setup(initialState, callback);
|
||||
|
||||
// column state was not updated, so the default width provided by the
|
||||
// col def should be set
|
||||
expect(result.current.columnApi.getColumnState()[0].width).toEqual(
|
||||
expect(gridRef.current?.columnApi.getColumnState()[0].width).toEqual(
|
||||
gridProps.columnDefs[0].width
|
||||
);
|
||||
// no filters set
|
||||
expect(result.current.api.getFilterModel()).toEqual({});
|
||||
expect(gridRef.current?.api.getFilterModel()).toEqual({});
|
||||
|
||||
// Set filter
|
||||
const idFilter = {
|
||||
@@ -73,7 +74,7 @@ describe('useDataGridEvents', () => {
|
||||
type: 'equals',
|
||||
};
|
||||
await act(async () => {
|
||||
result.current.api.setFilterModel({
|
||||
gridRef.current?.api.setFilterModel({
|
||||
id: idFilter,
|
||||
});
|
||||
});
|
||||
@@ -89,7 +90,7 @@ describe('useDataGridEvents', () => {
|
||||
},
|
||||
});
|
||||
callback.mockClear();
|
||||
expect(result.current.api.getFilterModel()['id']).toEqual(idFilter);
|
||||
expect(gridRef.current?.api.getFilterModel()['id']).toEqual(idFilter);
|
||||
});
|
||||
|
||||
it('applies grid state on ready', async () => {
|
||||
@@ -106,11 +107,11 @@ describe('useDataGridEvents', () => {
|
||||
columnState: [colState],
|
||||
};
|
||||
|
||||
const result = setup(initialState, jest.fn());
|
||||
setup(initialState, jest.fn());
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.api.getFilterModel()['id']).toEqual(idFilter);
|
||||
expect(result.current.columnApi.getColumnState()[0]).toEqual(
|
||||
expect(gridRef.current?.api.getFilterModel()['id']).toEqual(idFilter);
|
||||
expect(gridRef.current?.columnApi.getColumnState()[0]).toEqual(
|
||||
expect.objectContaining(colState)
|
||||
);
|
||||
});
|
||||
@@ -123,13 +124,13 @@ describe('useDataGridEvents', () => {
|
||||
columnState: undefined,
|
||||
};
|
||||
|
||||
const result = setup(initialState, callback);
|
||||
setup(initialState, callback);
|
||||
|
||||
const newWidth = 400;
|
||||
|
||||
// Set col width multiple times
|
||||
await act(async () => {
|
||||
result.current.columnApi.setColumnWidth('id', newWidth);
|
||||
gridRef.current?.columnApi.setColumnWidth('id', newWidth);
|
||||
});
|
||||
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
@@ -140,4 +141,23 @@ describe('useDataGridEvents', () => {
|
||||
|
||||
expect(callback).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it('columns for autosizing should be handle', () => {
|
||||
const callback = jest.fn();
|
||||
const initialState = {
|
||||
filterModel: undefined,
|
||||
columnState: undefined,
|
||||
};
|
||||
|
||||
const { rerender } = setup(initialState, callback, ['id']);
|
||||
jest.spyOn(gridRef.current?.columnApi, 'autoSizeColumns');
|
||||
rerender(<TestComponent hookParams={[initialState, callback, ['id']]} />);
|
||||
act(() => {
|
||||
gridRef.current?.api.setRowData([{ id: 'test-id' }]);
|
||||
jest.advanceTimersByTime(GRID_EVENT_DEBOUNCE_TIME);
|
||||
});
|
||||
expect(gridRef.current?.columnApi.autoSizeColumns).toHaveBeenCalledWith([
|
||||
'id',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ import type {
|
||||
FilterChangedEvent,
|
||||
FirstDataRenderedEvent,
|
||||
SortChangedEvent,
|
||||
GridReadyEvent,
|
||||
} from 'ag-grid-community';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
@@ -17,7 +18,8 @@ type State = {
|
||||
|
||||
export const useDataGridEvents = (
|
||||
state: State,
|
||||
callback: (data: State) => void
|
||||
callback: (data: State) => void,
|
||||
autoSizeColumns?: string[]
|
||||
) => {
|
||||
/**
|
||||
* Callback for filter events
|
||||
@@ -78,7 +80,7 @@ export const useDataGridEvents = (
|
||||
* State only applied if found, otherwise columns sized to fit available space
|
||||
*/
|
||||
const onGridReady = useCallback(
|
||||
({ api, columnApi }: FirstDataRenderedEvent) => {
|
||||
({ api, columnApi }: GridReadyEvent) => {
|
||||
if (!api || !columnApi) return;
|
||||
|
||||
if (state.columnState) {
|
||||
@@ -97,6 +99,16 @@ export const useDataGridEvents = (
|
||||
[state]
|
||||
);
|
||||
|
||||
const onFirstDataRendered = useCallback(
|
||||
({ columnApi }: FirstDataRenderedEvent) => {
|
||||
if (!columnApi) return;
|
||||
if (!state?.columnState && autoSizeColumns?.length) {
|
||||
columnApi.autoSizeColumns(autoSizeColumns);
|
||||
}
|
||||
},
|
||||
[state, autoSizeColumns]
|
||||
);
|
||||
|
||||
return {
|
||||
onGridReady,
|
||||
// these events don't use the 'finished' flag
|
||||
@@ -106,5 +118,6 @@ export const useDataGridEvents = (
|
||||
// these trigger a lot so this callback uses the 'finished' flag
|
||||
onColumnMoved: onDebouncedColumnChange,
|
||||
onColumnResized: onDebouncedColumnChange,
|
||||
onFirstDataRendered,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -12,6 +12,7 @@ import { formatRange, formatValue } from '@vegaprotocol/utils';
|
||||
import { marketMarginDataProvider } from '@vegaprotocol/accounts';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
|
||||
import {
|
||||
MARGIN_DIFF_TOOLTIP_TEXT,
|
||||
@@ -37,14 +38,16 @@ export interface DealTicketFeeDetailsProps {
|
||||
assetSymbol: string;
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
market: Market;
|
||||
isMarketInAuction?: boolean;
|
||||
}
|
||||
|
||||
export const DealTicketFeeDetails = ({
|
||||
assetSymbol,
|
||||
order,
|
||||
market,
|
||||
isMarketInAuction,
|
||||
}: DealTicketFeeDetailsProps) => {
|
||||
const feeEstimate = useEstimateFees(order);
|
||||
const feeEstimate = useEstimateFees(order, isMarketInAuction);
|
||||
const { settlementAsset: asset } =
|
||||
market.tradableInstrument.instrument.product;
|
||||
const { decimals: assetDecimals, quantum } = asset;
|
||||
@@ -64,7 +67,7 @@ export const DealTicketFeeDetails = ({
|
||||
<>
|
||||
<span>
|
||||
{t(
|
||||
`An estimate of the most you would be expected to pay in fees, in the market's settlement asset ${assetSymbol}.`
|
||||
`An estimate of the most you would be expected to pay in fees, in the market's settlement asset ${assetSymbol}. Fees estimated are "taker" fees and will only be payable if the order trades aggressively. Rebate equal to the maker portion will be paid to the trader if the order trades passively.`
|
||||
)}
|
||||
</span>
|
||||
<FeesBreakdown
|
||||
@@ -87,6 +90,7 @@ export interface DealTicketMarginDetailsProps {
|
||||
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||
assetSymbol: string;
|
||||
positionEstimate: EstimatePositionQuery['estimatePosition'];
|
||||
side: Schema.Side;
|
||||
}
|
||||
|
||||
export const DealTicketMarginDetails = ({
|
||||
@@ -96,6 +100,7 @@ export const DealTicketMarginDetails = ({
|
||||
market,
|
||||
onMarketClick,
|
||||
positionEstimate,
|
||||
side,
|
||||
}: DealTicketMarginDetailsProps) => {
|
||||
const [breakdownDialog, setBreakdownDialog] = useState(false);
|
||||
const { pubKey: partyId } = useVegaWallet();
|
||||
@@ -165,10 +170,7 @@ export const DealTicketMarginDetails = ({
|
||||
: '0',
|
||||
assetDecimals
|
||||
)}
|
||||
formattedValue={formatRange(
|
||||
deductionFromCollateralBestCase > 0
|
||||
? deductionFromCollateralBestCase.toString()
|
||||
: '0',
|
||||
formattedValue={formatValue(
|
||||
deductionFromCollateralWorstCase > 0
|
||||
? deductionFromCollateralWorstCase.toString()
|
||||
: '0',
|
||||
@@ -187,8 +189,7 @@ export const DealTicketMarginDetails = ({
|
||||
marginEstimate?.worstCase.initialLevel,
|
||||
assetDecimals
|
||||
)}
|
||||
formattedValue={formatRange(
|
||||
marginEstimate?.bestCase.initialLevel,
|
||||
formattedValue={formatValue(
|
||||
marginEstimate?.worstCase.initialLevel,
|
||||
assetDecimals,
|
||||
quantum
|
||||
@@ -200,6 +201,7 @@ export const DealTicketMarginDetails = ({
|
||||
}
|
||||
|
||||
let liquidationPriceEstimate = emptyValue;
|
||||
let liquidationPriceEstimateRange = emptyValue;
|
||||
|
||||
if (liquidationEstimate) {
|
||||
const liquidationEstimateBestCaseIncludingBuyOrders = BigInt(
|
||||
@@ -209,8 +211,7 @@ export const DealTicketMarginDetails = ({
|
||||
liquidationEstimate.bestCase.including_sell_orders.replace(/\..*/, '')
|
||||
);
|
||||
const liquidationEstimateBestCase =
|
||||
liquidationEstimateBestCaseIncludingBuyOrders >
|
||||
liquidationEstimateBestCaseIncludingSellOrders
|
||||
side === Schema.Side.SIDE_BUY
|
||||
? liquidationEstimateBestCaseIncludingBuyOrders
|
||||
: liquidationEstimateBestCaseIncludingSellOrders;
|
||||
|
||||
@@ -221,14 +222,19 @@ export const DealTicketMarginDetails = ({
|
||||
liquidationEstimate.worstCase.including_sell_orders.replace(/\..*/, '')
|
||||
);
|
||||
const liquidationEstimateWorstCase =
|
||||
liquidationEstimateWorstCaseIncludingBuyOrders >
|
||||
liquidationEstimateWorstCaseIncludingSellOrders
|
||||
side === Schema.Side.SIDE_BUY
|
||||
? liquidationEstimateWorstCaseIncludingBuyOrders
|
||||
: liquidationEstimateWorstCaseIncludingSellOrders;
|
||||
|
||||
// The estimate order query API gives us the liquidation price in formatted by asset decimals.
|
||||
// We need to calculate it with asset decimals, but display it with market decimals precision until the API changes.
|
||||
liquidationPriceEstimate = formatRange(
|
||||
liquidationPriceEstimate = formatValue(
|
||||
liquidationEstimateWorstCase.toString(),
|
||||
assetDecimals,
|
||||
undefined,
|
||||
market.decimalPlaces
|
||||
);
|
||||
liquidationPriceEstimateRange = formatRange(
|
||||
(liquidationEstimateBestCase < liquidationEstimateWorstCase
|
||||
? liquidationEstimateBestCase
|
||||
: liquidationEstimateWorstCase
|
||||
@@ -284,11 +290,9 @@ export const DealTicketMarginDetails = ({
|
||||
assetDecimals
|
||||
) ?? '-'
|
||||
}
|
||||
noUnderline
|
||||
>
|
||||
<div className="font-mono text-right">
|
||||
{formatRange(
|
||||
marginRequiredBestCase,
|
||||
{formatValue(
|
||||
marginRequiredWorstCase,
|
||||
assetDecimals,
|
||||
quantum
|
||||
@@ -346,7 +350,7 @@ export const DealTicketMarginDetails = ({
|
||||
{projectedMargin}
|
||||
<KeyValue
|
||||
label={t('Liquidation')}
|
||||
value={liquidationPriceEstimate}
|
||||
value={liquidationPriceEstimateRange}
|
||||
formattedValue={liquidationPriceEstimate}
|
||||
symbol={quoteName}
|
||||
labelDescription={LIQUIDATION_PRICE_ESTIMATE_TOOLTIP_TEXT}
|
||||
|
||||
@@ -36,7 +36,7 @@ import {
|
||||
formatValue,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { activeOrdersProvider } from '@vegaprotocol/orders';
|
||||
import { getDerivedPrice } from '@vegaprotocol/markets';
|
||||
import { getDerivedPrice, isMarketInAuction } from '@vegaprotocol/markets';
|
||||
import {
|
||||
validateExpiration,
|
||||
validateMarketState,
|
||||
@@ -182,6 +182,7 @@ export const DealTicket = ({
|
||||
const iceberg = watch('iceberg');
|
||||
const peakSize = watch('peakSize');
|
||||
const expiresAt = watch('expiresAt');
|
||||
const postOnly = watch('postOnly');
|
||||
|
||||
useEffect(() => {
|
||||
const size = storedFormValues?.[dealTicketType]?.size;
|
||||
@@ -211,6 +212,7 @@ export const DealTicket = ({
|
||||
size: rawSize,
|
||||
timeInForce,
|
||||
type,
|
||||
postOnly,
|
||||
},
|
||||
market.id,
|
||||
market.decimalPlaces,
|
||||
@@ -219,8 +221,7 @@ export const DealTicket = ({
|
||||
|
||||
const price =
|
||||
normalizedOrder &&
|
||||
marketPrice &&
|
||||
getDerivedPrice(normalizedOrder, marketPrice);
|
||||
getDerivedPrice(normalizedOrder, marketPrice ?? undefined);
|
||||
|
||||
const notionalSize = getNotionalSize(
|
||||
price,
|
||||
@@ -474,6 +475,7 @@ export const DealTicket = ({
|
||||
}
|
||||
assetSymbol={assetSymbol}
|
||||
market={market}
|
||||
isMarketInAuction={isMarketInAuction(marketData.marketTradingMode)}
|
||||
/>
|
||||
</div>
|
||||
<Controller
|
||||
@@ -676,6 +678,7 @@ export const DealTicket = ({
|
||||
)}
|
||||
</Button>
|
||||
<DealTicketMarginDetails
|
||||
side={normalizedOrder.side}
|
||||
onMarketClick={onMarketClick}
|
||||
assetSymbol={assetSymbol}
|
||||
marginAccountBalance={marginAccountBalance}
|
||||
|
||||
@@ -47,7 +47,7 @@ export const KeyValue = ({
|
||||
<Tooltip description={labelDescription}>
|
||||
<div className="text-muted">{label}</div>
|
||||
</Tooltip>
|
||||
<Tooltip description={`${value ?? '-'} ${symbol || ''}`} noUnderline>
|
||||
<Tooltip description={`${value ?? '-'} ${symbol || ''}`}>
|
||||
{valueElement}
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import { renderHook } from '@testing-library/react';
|
||||
import { useEstimateFees } from './use-estimate-fees';
|
||||
import { Side, OrderTimeInForce, OrderType } from '@vegaprotocol/types';
|
||||
|
||||
import type { EstimateFeesQuery } from './__generated__/EstimateOrder';
|
||||
|
||||
const data: EstimateFeesQuery = {
|
||||
estimateFees: {
|
||||
totalFeeAmount: '12',
|
||||
fees: {
|
||||
infrastructureFee: '2',
|
||||
liquidityFee: '4',
|
||||
makerFee: '6',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const mockUseEstimateFeesQuery = jest.fn((...args) => ({
|
||||
data,
|
||||
}));
|
||||
|
||||
jest.mock('./__generated__/EstimateOrder', () => ({
|
||||
...jest.requireActual('@vegaprotocol/data-provider'),
|
||||
useEstimateFeesQuery: jest.fn((...args) => mockUseEstimateFeesQuery(...args)),
|
||||
}));
|
||||
|
||||
jest.mock('@vegaprotocol/wallet', () => ({
|
||||
useVegaWallet: () => ({ pubKey: 'pubKey' }),
|
||||
}));
|
||||
|
||||
describe('useEstimateFees', () => {
|
||||
it('returns 0 as estimated values if order is postOnly', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useEstimateFees({
|
||||
marketId: 'marketId',
|
||||
side: Side.SIDE_BUY,
|
||||
size: '1',
|
||||
price: '1',
|
||||
timeInForce: OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
type: OrderType.TYPE_LIMIT,
|
||||
postOnly: true,
|
||||
})
|
||||
);
|
||||
expect(result.current).toEqual({
|
||||
totalFeeAmount: '0',
|
||||
fees: {
|
||||
infrastructureFee: '0',
|
||||
liquidityFee: '0',
|
||||
makerFee: '0',
|
||||
},
|
||||
});
|
||||
expect(mockUseEstimateFeesQuery.mock.lastCall?.[0].skip).toBeTruthy();
|
||||
});
|
||||
|
||||
it('divide values by 2 if market is in auction', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useEstimateFees(
|
||||
{
|
||||
marketId: 'marketId',
|
||||
side: Side.SIDE_BUY,
|
||||
size: '1',
|
||||
price: '1',
|
||||
timeInForce: OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
type: OrderType.TYPE_LIMIT,
|
||||
},
|
||||
true
|
||||
)
|
||||
);
|
||||
expect(result.current).toEqual({
|
||||
totalFeeAmount: '6',
|
||||
fees: {
|
||||
infrastructureFee: '1',
|
||||
liquidityFee: '2',
|
||||
makerFee: '3',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,13 +1,16 @@
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
|
||||
import type { EstimateFeesQuery } from './__generated__/EstimateOrder';
|
||||
import { useEstimateFeesQuery } from './__generated__/EstimateOrder';
|
||||
|
||||
export const useEstimateFees = (
|
||||
order?: OrderSubmissionBody['orderSubmission']
|
||||
) => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const divideByTwo = (n: string) => (BigInt(n) / BigInt(2)).toString();
|
||||
|
||||
export const useEstimateFees = (
|
||||
order?: OrderSubmissionBody['orderSubmission'],
|
||||
isMarketInAuction?: boolean
|
||||
): EstimateFeesQuery['estimateFees'] | undefined => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { data } = useEstimateFeesQuery({
|
||||
variables: order && {
|
||||
marketId: order.marketId,
|
||||
@@ -19,7 +22,28 @@ export const useEstimateFees = (
|
||||
type: order.type,
|
||||
},
|
||||
fetchPolicy: 'no-cache',
|
||||
skip: !pubKey || !order?.size || !order?.price,
|
||||
skip: !pubKey || !order?.size || !order?.price || order.postOnly,
|
||||
});
|
||||
return data?.estimateFees;
|
||||
if (order?.postOnly) {
|
||||
return {
|
||||
totalFeeAmount: '0',
|
||||
fees: {
|
||||
infrastructureFee: '0',
|
||||
liquidityFee: '0',
|
||||
makerFee: '0',
|
||||
},
|
||||
};
|
||||
}
|
||||
return isMarketInAuction && data?.estimateFees
|
||||
? {
|
||||
totalFeeAmount: divideByTwo(data.estimateFees.totalFeeAmount),
|
||||
fees: {
|
||||
infrastructureFee: divideByTwo(
|
||||
data.estimateFees.fees.infrastructureFee
|
||||
),
|
||||
liquidityFee: divideByTwo(data.estimateFees.fees.liquidityFee),
|
||||
makerFee: divideByTwo(data.estimateFees.fees.makerFee),
|
||||
},
|
||||
}
|
||||
: data?.estimateFees;
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
isNumeric,
|
||||
} from '@vegaprotocol/utils';
|
||||
import type { ColDef } from 'ag-grid-community';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
|
||||
@@ -9,14 +9,12 @@ import { fillsWithMarketProvider } from './fills-data-provider';
|
||||
|
||||
interface FillsManagerProps {
|
||||
partyId: string;
|
||||
marketId?: string;
|
||||
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
|
||||
gridProps: ReturnType<typeof useDataGridEvents>;
|
||||
}
|
||||
|
||||
export const FillsManager = ({
|
||||
partyId,
|
||||
marketId,
|
||||
onMarketClick,
|
||||
gridProps,
|
||||
}: FillsManagerProps) => {
|
||||
@@ -24,9 +22,6 @@ export const FillsManager = ({
|
||||
const filter: Schema.TradesFilter | Schema.TradesSubscriptionFilter = {
|
||||
partyIds: [partyId],
|
||||
};
|
||||
if (marketId) {
|
||||
filter.marketIds = [marketId];
|
||||
}
|
||||
const { data, error } = useDataProvider({
|
||||
dataProvider: fillsWithMarketProvider,
|
||||
update: ({ data }) => {
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import {
|
||||
AgGridLazy as AgGrid,
|
||||
AgGrid,
|
||||
positiveClassNames,
|
||||
negativeClassNames,
|
||||
MarketNameCell,
|
||||
@@ -300,7 +300,7 @@ const FeesBreakdownTooltip = ({
|
||||
return (
|
||||
<div
|
||||
data-testid="fee-breakdown-tooltip"
|
||||
className="max-w-sm bg-vega-light-100 dark:bg-vega-dark-100 border border-vega-light-200 dark:border-vega-dark-200 px-4 py-2 z-20 rounded text-sm break-word text-black dark:text-white"
|
||||
className="z-20 max-w-sm px-4 py-2 text-sm text-black border rounded bg-vega-light-100 dark:bg-vega-dark-100 border-vega-light-200 dark:border-vega-dark-200 break-word dark:text-white"
|
||||
>
|
||||
{role === MAKER && (
|
||||
<>
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
} from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type { TypedDataAgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { TooltipCellComponent } from '@vegaprotocol/ui-toolkit';
|
||||
import type {
|
||||
ColDef,
|
||||
|
||||
@@ -175,7 +175,7 @@ export const Orderbook = ({
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="h-full text-xs grid grid-rows-[1fr_min-content]">
|
||||
<div className="h-full text-xs grid grid-rows-[1fr_min-content] overflow-hidden">
|
||||
<div>
|
||||
<ReactVirtualizedAutoSizer>
|
||||
{({ width, height }) => {
|
||||
|
||||
@@ -60,6 +60,7 @@ export const FeesBreakdown = ({
|
||||
.plus(fees.infrastructureFee)
|
||||
.plus(fees.liquidityFee)
|
||||
.toString();
|
||||
if (totalFees === '0') return null;
|
||||
const formatValue = (value: string | number | null | undefined): string => {
|
||||
return value && !isNaN(Number(value))
|
||||
? addDecimalsFormatNumber(value, decimals)
|
||||
|
||||
@@ -33,7 +33,7 @@ export const getDerivedPrice = (
|
||||
type: Schema.OrderType;
|
||||
price?: string | undefined;
|
||||
},
|
||||
marketPrice: string
|
||||
marketPrice?: string
|
||||
) => {
|
||||
// If order type is market we should use either the mark price
|
||||
// or the uncrossing price. If order type is limit use the price
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
import type { ForwardedRef } from 'react';
|
||||
import { memo, forwardRef, useMemo } from 'react';
|
||||
import {
|
||||
AgGridLazy as AgGrid,
|
||||
AgGrid,
|
||||
SetFilter,
|
||||
DateRangeFilter,
|
||||
negativeClassNames,
|
||||
@@ -79,6 +79,7 @@ export const OrderListTable = memo<
|
||||
() => [
|
||||
{
|
||||
headerName: t('Market'),
|
||||
colId: 'instrument-code',
|
||||
field: 'market.tradableInstrument.instrument.code',
|
||||
cellRenderer: 'MarketNameCell',
|
||||
cellRendererParams: { idPath: 'market.id', onMarketClick },
|
||||
|
||||
@@ -18,7 +18,7 @@ import {
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { memo, useMemo } from 'react';
|
||||
import {
|
||||
AgGridLazy as AgGrid,
|
||||
AgGrid,
|
||||
SetFilter,
|
||||
DateRangeFilter,
|
||||
negativeClassNames,
|
||||
|
||||
@@ -8,7 +8,7 @@ import type {
|
||||
VegaICellRendererParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import {
|
||||
AgGridLazy as AgGrid,
|
||||
AgGrid,
|
||||
COL_DEFS,
|
||||
PriceFlashCell,
|
||||
signedNumberCssClassRules,
|
||||
|
||||
@@ -100,7 +100,8 @@ describe('ProposalsList', () => {
|
||||
const container = within(
|
||||
document.querySelector(rowContainerSelector) as HTMLElement
|
||||
);
|
||||
expect(container.getAllByRole('row')).toHaveLength(
|
||||
|
||||
expect(await container.findAllByRole('row')).toHaveLength(
|
||||
// @ts-ignore data is mocked
|
||||
mock?.result?.data.proposalsConnection.edges.length
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { FC } from 'react';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
|
||||
@@ -4,7 +4,7 @@ import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { AgGridLazy as AgGrid, NumericCell } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid, NumericCell } from '@vegaprotocol/datagrid';
|
||||
import {
|
||||
addDecimal,
|
||||
addDecimalsFormatNumber,
|
||||
|
||||
@@ -19,14 +19,14 @@ export interface TooltipProps {
|
||||
align?: 'start' | 'center' | 'end';
|
||||
side?: 'top' | 'right' | 'bottom' | 'left';
|
||||
sideOffset?: number;
|
||||
noUnderline?: boolean;
|
||||
underline?: boolean;
|
||||
}
|
||||
|
||||
export const TOOLTIP_TRIGGER_CLASS_NAME = (noUnderline?: boolean) =>
|
||||
classNames(
|
||||
{ 'underline underline-offset-2': !noUnderline },
|
||||
'decoration-neutral-400 dark:decoration-neutral-400 decoration-dashed'
|
||||
);
|
||||
export const TOOLTIP_TRIGGER_CLASS_NAME = (underline?: boolean) =>
|
||||
classNames({
|
||||
'underline underline-offset-2 decoration-neutral-400 dark:decoration-neutral-400 decoration-dashed':
|
||||
underline,
|
||||
});
|
||||
|
||||
// Conditionally rendered tooltip if description content is provided.
|
||||
export const Tooltip = ({
|
||||
@@ -36,12 +36,12 @@ export const Tooltip = ({
|
||||
sideOffset,
|
||||
align = 'start',
|
||||
side = 'bottom',
|
||||
noUnderline,
|
||||
underline,
|
||||
}: TooltipProps) =>
|
||||
description ? (
|
||||
<Provider delayDuration={200} skipDelayDuration={100}>
|
||||
<Root open={open}>
|
||||
<Trigger asChild className={TOOLTIP_TRIGGER_CLASS_NAME(noUnderline)}>
|
||||
<Trigger asChild className={TOOLTIP_TRIGGER_CLASS_NAME(underline)}>
|
||||
{children}
|
||||
</Trigger>
|
||||
{description && (
|
||||
|
||||
@@ -50,11 +50,15 @@ export type WalletType = 'injected' | 'jsonRpc' | 'view' | 'snap';
|
||||
export interface VegaConnectDialogProps {
|
||||
connectors: Connectors;
|
||||
riskMessage?: ReactNode;
|
||||
contentOnly?: boolean;
|
||||
onClose?: () => void;
|
||||
}
|
||||
|
||||
export const VegaConnectDialog = ({
|
||||
connectors,
|
||||
riskMessage,
|
||||
contentOnly,
|
||||
onClose,
|
||||
}: VegaConnectDialogProps) => {
|
||||
const { disconnect, acknowledgeNeeded } = useVegaWallet();
|
||||
const vegaWalletDialogOpen = useVegaWalletDialogStore(
|
||||
@@ -80,19 +84,24 @@ export const VegaConnectDialog = ({
|
||||
// This value will already be in the cache, if it failed the app wont render
|
||||
const { data } = useChainIdQuery();
|
||||
|
||||
const content = data && (
|
||||
<ConnectDialogContainer
|
||||
connectors={connectors}
|
||||
appChainId={data.statistics.chainId}
|
||||
riskMessage={riskMessage}
|
||||
onClose={onClose}
|
||||
/>
|
||||
);
|
||||
if (contentOnly) {
|
||||
return content;
|
||||
}
|
||||
return (
|
||||
<Dialog
|
||||
open={vegaWalletDialogOpen}
|
||||
size="small"
|
||||
onChange={onVegaWalletDialogChange}
|
||||
>
|
||||
{data && (
|
||||
<ConnectDialogContainer
|
||||
connectors={connectors}
|
||||
appChainId={data.statistics.chainId}
|
||||
riskMessage={riskMessage}
|
||||
/>
|
||||
)}
|
||||
{content}
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -101,15 +110,20 @@ const ConnectDialogContainer = ({
|
||||
connectors,
|
||||
appChainId,
|
||||
riskMessage,
|
||||
onClose,
|
||||
}: {
|
||||
connectors: Connectors;
|
||||
appChainId: string;
|
||||
riskMessage?: ReactNode;
|
||||
onClose?: () => void;
|
||||
}) => {
|
||||
const { vegaUrl, vegaWalletServiceUrl } = useVegaWallet();
|
||||
const closeDialog = useVegaWalletDialogStore(
|
||||
const closeVegaWalletDialog = useVegaWalletDialogStore(
|
||||
(store) => store.closeVegaWalletDialog
|
||||
);
|
||||
const closeDialog = useCallback(() => {
|
||||
onClose ? onClose() : closeVegaWalletDialog();
|
||||
}, [closeVegaWalletDialog, onClose]);
|
||||
const [selectedConnector, setSelectedConnector] = useState<VegaConnector>();
|
||||
const [walletUrl, setWalletUrl] = useState(vegaWalletServiceUrl);
|
||||
|
||||
@@ -155,8 +169,7 @@ const ConnectDialogContainer = ({
|
||||
|
||||
const isDesktopWalletRunning = useIsWalletServiceRunning(
|
||||
walletUrl,
|
||||
connectors['jsonRpc'],
|
||||
appChainId
|
||||
connectors['jsonRpc']
|
||||
);
|
||||
|
||||
const snapStatus = useSnapStatus(
|
||||
@@ -255,7 +268,7 @@ const ConnectorList = ({
|
||||
</>
|
||||
}
|
||||
description={t(
|
||||
`Connect Vega Wallet extension
|
||||
`Connect with Vega Wallet extension
|
||||
for %s to access all features including key
|
||||
management and detailed transaction views from your
|
||||
browser.`,
|
||||
@@ -287,8 +300,18 @@ const ConnectorList = ({
|
||||
{connectors['snap'] !== undefined ? (
|
||||
<div>
|
||||
{snapStatus === SnapStatus.INSTALLED ? (
|
||||
<ConnectionOption
|
||||
<ConnectionOptionWithDescription
|
||||
type="snap"
|
||||
title={
|
||||
<>
|
||||
<span>{t('Metamask Snap')}</span>
|
||||
{' '}
|
||||
<span className="text-xs"> {t('quick start')}</span>
|
||||
</>
|
||||
}
|
||||
description={t(
|
||||
`Connect directly via Metamask with the Vega Snap for single key support without advanced features.`
|
||||
)}
|
||||
text={
|
||||
<>
|
||||
<div className="flex items-center justify-center w-full h-full text-base gap-1">
|
||||
@@ -316,7 +339,7 @@ const ConnectorList = ({
|
||||
</>
|
||||
}
|
||||
description={t(
|
||||
`Connect directly via Metamask with the Vega Snap for single key support without advanced features.`
|
||||
`Install Metamask with the Vega Snap for single key support without advanced features.`
|
||||
)}
|
||||
text={
|
||||
<>
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { JsonRpcConnector } from './connectors';
|
||||
import { useIsWalletServiceRunning } from './use-is-wallet-service-running';
|
||||
|
||||
describe('useIsWalletServiceRunning', () => {
|
||||
it('returns true if wallet is running', async () => {
|
||||
const url = 'https://foo.bar.com';
|
||||
const connector = new JsonRpcConnector();
|
||||
const spyOnCheckCompat = jest
|
||||
.spyOn(connector, 'checkCompat')
|
||||
.mockResolvedValue(true);
|
||||
const { result } = renderHook(() =>
|
||||
useIsWalletServiceRunning(url, connector)
|
||||
);
|
||||
|
||||
expect(result.current).toBe(null);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(spyOnCheckCompat).toHaveBeenCalled();
|
||||
expect(result.current).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('returns false if wallet is not running', async () => {
|
||||
const url = 'https://foo.bar.com';
|
||||
const connector = new JsonRpcConnector();
|
||||
const spyOnCheckCompat = jest
|
||||
.spyOn(connector, 'checkCompat')
|
||||
.mockRejectedValue(false);
|
||||
const { result } = renderHook(() =>
|
||||
useIsWalletServiceRunning(url, connector)
|
||||
);
|
||||
|
||||
expect(result.current).toBe(null);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(spyOnCheckCompat).toHaveBeenCalled();
|
||||
expect(result.current).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,39 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import type { JsonRpcConnector } from './connectors';
|
||||
|
||||
export const useIsWalletServiceRunning = (
|
||||
url: string,
|
||||
connector: JsonRpcConnector | undefined
|
||||
) => {
|
||||
const [isRunning, setIsRunning] = useState<boolean | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!connector) return;
|
||||
|
||||
if (url && url !== connector.url) {
|
||||
connector.url = url;
|
||||
}
|
||||
|
||||
const check = async () => {
|
||||
try {
|
||||
// we are not checking wallet compatibility here, only that the wallet is running
|
||||
await connector.checkCompat();
|
||||
setIsRunning(true);
|
||||
} catch {
|
||||
setIsRunning(false);
|
||||
}
|
||||
};
|
||||
|
||||
// check immediately
|
||||
check();
|
||||
|
||||
// check every second for quick feedback to the user
|
||||
const interval = setInterval(check, 1000);
|
||||
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, [connector, url]);
|
||||
|
||||
return isRunning;
|
||||
};
|
||||
@@ -1,47 +0,0 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import type { JsonRpcConnector } from './connectors';
|
||||
import { ClientErrors } from './connectors';
|
||||
|
||||
export const useIsWalletServiceRunning = (
|
||||
url: string,
|
||||
connector: JsonRpcConnector | undefined,
|
||||
appChainId: string
|
||||
) => {
|
||||
const [run, setRun] = useState<boolean | null>(null);
|
||||
|
||||
const checkState = useCallback(async () => {
|
||||
if (!connector) return false;
|
||||
|
||||
if (url && url !== connector.url) {
|
||||
connector.url = url;
|
||||
}
|
||||
|
||||
try {
|
||||
await connector.checkCompat();
|
||||
const chainIdResult = await connector.getChainId();
|
||||
if (chainIdResult.chainID !== appChainId) {
|
||||
throw ClientErrors.WRONG_NETWORK;
|
||||
}
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}, [connector, url, appChainId]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!connector) return;
|
||||
|
||||
let interval: NodeJS.Timeout;
|
||||
checkState().then((value) => {
|
||||
setRun(value);
|
||||
interval = setInterval(async () => {
|
||||
setRun(await checkState());
|
||||
}, 1000 * 10);
|
||||
});
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, [checkState, connector]);
|
||||
|
||||
return run;
|
||||
};
|
||||
@@ -20,7 +20,7 @@ import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { EtherscanLink } from '@vegaprotocol/environment';
|
||||
import type { WithdrawalFieldsFragment } from './__generated__/Withdrawal';
|
||||
import {
|
||||
|
||||
Reference in New Issue
Block a user