Compare commits
20
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bde7a9fbf9 | ||
|
|
5fd93ee9c8 | ||
|
|
9ac07fd98a | ||
|
|
9c975ed822 | ||
|
|
138bf7da00 | ||
|
|
3e7fe517f3 | ||
|
|
4f960d09b3 | ||
|
|
351a5aaf96 | ||
|
|
381d9011a0 | ||
|
|
861760b4f9 | ||
|
|
18f1c0014c | ||
|
|
474543d91b | ||
|
|
662753c74b | ||
|
|
71aa8882bc | ||
|
|
ecfbccf8ed | ||
|
|
2aad6b1a14 | ||
|
|
8463d371ad | ||
|
|
0914e7ce4b | ||
|
|
7c82144f37 | ||
|
|
17ad0cc975 |
@@ -13,7 +13,7 @@ env:
|
||||
|
||||
jobs:
|
||||
add_issue:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: 'Add issue to project board'
|
||||
run: |
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
name: PR Validations
|
||||
name: CI/CD
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
- main
|
||||
- release/*
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
@@ -12,42 +11,55 @@ on:
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
jobs:
|
||||
pr:
|
||||
runs-on: ubuntu-latest
|
||||
lint-test-build:
|
||||
runs-on: ubuntu-22.04
|
||||
name: '(CI) lint + unit test + build'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Check node version
|
||||
id: node-version
|
||||
run: |
|
||||
npmVersion=$(cat .nvmrc | head -n 1)
|
||||
echo ::set-output name=npmVersion::${npmVersion}
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: ${{ steps.node-version.outputs.npmVersion }}
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
cache: yarn
|
||||
|
||||
- name: Install root dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Derive appropriate SHAs for base and head for `nx affected` commands
|
||||
uses: nrwl/nx-set-shas@v3
|
||||
with:
|
||||
main-branch-name: develop
|
||||
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node_modules-${{ hashFiles('**/yarn.lock') }}
|
||||
- name: Check formatting
|
||||
run: yarn nx format:check
|
||||
|
||||
- name: Install root dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Lint affected
|
||||
run: yarn nx affected:lint --max-warnings=0
|
||||
|
||||
- name: Build affected spec
|
||||
run: yarn nx affected --target=build-spec
|
||||
|
||||
- name: Test affected
|
||||
run: yarn nx affected:test
|
||||
|
||||
- name: Build affected
|
||||
run: yarn nx affected:build
|
||||
|
||||
# See affected apps
|
||||
- name: See affected apps
|
||||
run: |
|
||||
affected="$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=HEAD --select=projects)"
|
||||
echo ">>>> debug"
|
||||
echo "NX Version: $nx_version"
|
||||
echo "NX_BASE: ${{ env.NX_BASE }}"
|
||||
echo "NX_HEAD: ${{ env.NX_HEAD }}"
|
||||
echo ">>>> eof debug"
|
||||
|
||||
affected="$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)"
|
||||
echo -n "Affected projects: $affected"
|
||||
|
||||
projects_e2e=""
|
||||
@@ -64,32 +76,33 @@ jobs:
|
||||
projects: ${{ env.PROJECTS }}
|
||||
projects-e2e: ${{ env.PROJECTS_E2E }}
|
||||
|
||||
run-cypress:
|
||||
needs: pr
|
||||
if: ${{ needs.pr.outputs.projects != '[]' }}
|
||||
cypress:
|
||||
needs: lint-test-build
|
||||
name: '(CI) cypress'
|
||||
if: ${{ needs.lint-test-build.outputs.projects != '[]' }}
|
||||
uses: ./.github/workflows/cypress-run.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
projects: ${{ needs.pr.outputs.projects-e2e }}
|
||||
projects: ${{ needs.lint-test-build.outputs.projects-e2e }}
|
||||
tags: '@smoke @regression'
|
||||
|
||||
run-docker-build:
|
||||
needs: pr
|
||||
if: ${{ needs.pr.outputs.projects != '[]' }}
|
||||
uses: ./.github/workflows/publish-docker-containers.yml
|
||||
publish-dist:
|
||||
needs: lint-test-build
|
||||
name: '(CD) publish dist'
|
||||
if: ${{ needs.lint-test-build.outputs.projects != '[]' }}
|
||||
uses: ./.github/workflows/publish-dist.yml
|
||||
secrets: inherit
|
||||
with:
|
||||
projects: ${{ needs.pr.outputs.projects }}
|
||||
projects: ${{ needs.lint-test-build.outputs.projects }}
|
||||
|
||||
# Report single result at the end, to avoid mess with required checks in PR
|
||||
result:
|
||||
cypress-result:
|
||||
if: ${{ always() }}
|
||||
needs: run-cypress
|
||||
runs-on: ubuntu-latest
|
||||
name: Cypress result
|
||||
needs: cypress
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- run: |
|
||||
result="${{ needs.run-cypress.result }}"
|
||||
result="${{ needs.cypress.result }}"
|
||||
if [[ $result == "success" || $result == "skipped" ]]; then
|
||||
exit 0
|
||||
else
|
||||
@@ -13,7 +13,7 @@ on:
|
||||
jobs:
|
||||
cypress-run:
|
||||
name: Run Cypress Trading tests -- live environment
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Cypress Run
|
||||
name: (CI) Cypress Run
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
|
||||
@@ -8,22 +8,25 @@ on:
|
||||
jobs:
|
||||
master:
|
||||
name: Generate Queries
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Use Node.js 16
|
||||
id: Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16.15.1
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
cache: yarn
|
||||
|
||||
- name: Install root dependencies
|
||||
run: yarn install
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Generate queries
|
||||
run: node ./scripts/get-queries.js
|
||||
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: queries
|
||||
|
||||
@@ -3,21 +3,28 @@ name: Verify PR title
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, ready_for_review, reopened, edited, synchronize]
|
||||
types:
|
||||
- opened
|
||||
- ready_for_review
|
||||
- reopened
|
||||
- edited
|
||||
- synchronize
|
||||
jobs:
|
||||
lint_pr:
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Use Node.js 16
|
||||
id: Node
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: 16.15.1
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
cache: yarn
|
||||
|
||||
- name: Install root dependencies
|
||||
run: yarn install
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Check PR title
|
||||
run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js
|
||||
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
jobs:
|
||||
master:
|
||||
name: Generate Queries
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
||||
+56
-42
@@ -1,4 +1,4 @@
|
||||
name: Docker build
|
||||
name: (CD) Publish docker + s3
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
@@ -8,13 +8,13 @@ on:
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
master:
|
||||
publish-dist:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
app: ${{ fromJSON(inputs.projects) }}
|
||||
name: ${{ matrix.app }}
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- name: Check out code
|
||||
uses: actions/checkout@v3
|
||||
@@ -29,41 +29,6 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
|
||||
# https://docs.github.com/en/actions/learn-github-actions/contexts
|
||||
# https://github.com/actions/checkout#Checkout-pull-request-HEAD-commit-instead-of-merge-commit
|
||||
- name: Determine Docker Image tag
|
||||
id: tags
|
||||
run: |
|
||||
npmVersion=$(cat .nvmrc | head -n 1)
|
||||
versionTag=${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || github.event.pull_request.head.sha }}
|
||||
echo ::set-output name=npmVersion::${npmVersion}
|
||||
echo ::set-output name=version::${versionTag}
|
||||
|
||||
- name: Print config
|
||||
run: |
|
||||
git rev-parse --verify HEAD
|
||||
git status
|
||||
echo "steps.tags.outputs.version=${{ steps.tags.outputs.version }}"
|
||||
|
||||
- name: Build and export to local Docker
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
load: true
|
||||
build-args: |
|
||||
APP=${{ matrix.app }}
|
||||
NODE_VERSION=${{ steps.tags.outputs.npmVersion }}
|
||||
tags: |
|
||||
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
|
||||
|
||||
- name: Sanity check docker image
|
||||
run: |
|
||||
echo "Check .env file"
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat .env
|
||||
echo "Check ipfs-hash"
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat ipfs-hash
|
||||
echo "List html directory"
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local ls -lah
|
||||
|
||||
- name: Log in to the Container registry
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
@@ -71,17 +36,66 @@ jobs:
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
# https://docs.github.com/en/actions/learn-github-actions/contexts
|
||||
- name: Check node version
|
||||
id: tags
|
||||
run: |
|
||||
nodeVersion=$(cat .nvmrc | head -n 1)
|
||||
echo ::set-output name=nodeVersion::${nodeVersion}
|
||||
|
||||
if [[ "${{ github.event_name }}" = "push" ]]; then
|
||||
envName="$(echo ${{ github.ref }} | rev | cut -d '/' -f 1 | rev)"
|
||||
bucketName="${{ github.event.repository.name }}-$envName"
|
||||
echo ::set-output name=bucketName::${bucketName}
|
||||
echo ::set-output name=envName::${envName}
|
||||
fi
|
||||
|
||||
- name: Build and export to local Docker
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
load: true
|
||||
build-args: |
|
||||
APP=${{ matrix.app }}
|
||||
NODE_VERSION=${{ steps.tags.outputs.nodeVersion }}
|
||||
ENV_NAME=${{ steps.tags.outputs.envName || '' }}
|
||||
tags: |
|
||||
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
|
||||
|
||||
- name: Sanity check docker image
|
||||
run: |
|
||||
echo "Check ipfs-hash"
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat ipfs-hash
|
||||
|
||||
echo "List html directory"
|
||||
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local ls -lah
|
||||
|
||||
echo "Copy dist to local filesystem"
|
||||
docker create --name=dist ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
|
||||
docker cp dist:/usr/share/nginx/html dist
|
||||
|
||||
echo "Check local dist"
|
||||
ls -al dist
|
||||
|
||||
- name: Publish dist as docker image
|
||||
uses: docker/build-push-action@v3
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
with:
|
||||
push: true
|
||||
build-args: |
|
||||
APP=${{ matrix.app }}
|
||||
NODE_VERSION=${{ steps.tags.outputs.npmVersion }}
|
||||
NODE_VERSION=${{ steps.tags.outputs.nodeVersion }}
|
||||
tags: |
|
||||
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:latest
|
||||
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:${{ steps.tags.outputs.version }}
|
||||
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:${{ github.event.pull_request.head.sha || github.sha }}
|
||||
|
||||
# - uses: shallwefootball/s3-upload-action@master
|
||||
# if: ${{ github.event_name == 'push' }}
|
||||
# name: Upload dist S3
|
||||
# with:
|
||||
# aws_key_id: ${{ secrets.AWS_KEY_ID }}
|
||||
# aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY}}
|
||||
# aws_bucket: ${{ steps.tags.outputs.bucketName }}
|
||||
# source_dir: 'dist'
|
||||
|
||||
- name: Add preview label
|
||||
uses: actions-ecosystem/action-add-labels@v1
|
||||
@@ -19,29 +19,27 @@ on:
|
||||
jobs:
|
||||
publish:
|
||||
name: Build & Publish - Tag
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu-22.04
|
||||
permissions:
|
||||
contents: 'read'
|
||||
actions: 'read'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: User Node.js 16
|
||||
id: Node
|
||||
|
||||
- name: Setup node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.15.1
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node_modules-${{ hashFiles('**/yarn.lock') }}
|
||||
node-version-file: '.nvmrc'
|
||||
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
|
||||
cache: yarn
|
||||
|
||||
- name: Install root dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
|
||||
- name: Build project
|
||||
run: yarn nx build ${{inputs.project}}
|
||||
|
||||
- name: Publish project to @vegaprotocol
|
||||
uses: JS-DevTools/npm-publish@v1
|
||||
with:
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
name: Unit tests & build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
- main
|
||||
pull_request:
|
||||
jobs:
|
||||
pr:
|
||||
name: Test and lint - PR
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: 'read'
|
||||
actions: 'read'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Derive appropriate SHAs for base and head for `nx affected` commands
|
||||
uses: nrwl/nx-set-shas@v2
|
||||
with:
|
||||
main-branch-name: ${{ github.base_ref }}
|
||||
- name: Use Node.js 16
|
||||
id: Node
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16.15.1
|
||||
- name: Restore node_modules from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: '**/node_modules'
|
||||
key: node_modules-${{ hashFiles('**/yarn.lock') }}
|
||||
- name: Install root dependencies
|
||||
run: yarn install --frozen-lockfile
|
||||
- name: Check formatting
|
||||
run: yarn nx format:check
|
||||
- name: Lint affected
|
||||
run: yarn nx affected:lint --max-warnings=0
|
||||
- name: Test affected
|
||||
run: yarn nx affected:test
|
||||
- name: Build affected
|
||||
run: yarn nx affected:build
|
||||
- name: Build affected spec
|
||||
run: yarn nx affected --target=build-spec
|
||||
+2
-7
@@ -4,6 +4,7 @@ FROM --platform=amd64 node:${NODE_VERSION}-alpine3.16 as build
|
||||
WORKDIR /app
|
||||
# Argument to allow building of different apps
|
||||
ARG APP
|
||||
ARG ENV_NAME=""
|
||||
RUN apk add --update --no-cache \
|
||||
python3 \
|
||||
make \
|
||||
@@ -18,16 +19,10 @@ RUN sh ./docker-build.sh
|
||||
# if this fails you need to docker pull nginx:1.23-alpine and pin new SHA
|
||||
# this is to ensure that we run always same version of alpine to make sure ipfs is indempotent
|
||||
FROM --platform=amd64 nginx:1.23-alpine@sha256:6318314189b40e73145a48060bff4783a116c34cc7241532d0d94198fb2c9629
|
||||
ARG APP
|
||||
# configuration of system
|
||||
RUN apk add --no-cache bash go-ipfs
|
||||
EXPOSE 80
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
CMD ["/entrypoint.sh"]
|
||||
|
||||
# Copy dist
|
||||
WORKDIR /usr/share/nginx/html
|
||||
COPY nginx/nginx.conf /etc/nginx/conf.d/default.conf
|
||||
COPY --from=build /app/dist/apps/${APP} /usr/share/nginx/html
|
||||
COPY ./apps/${APP}/.env .env
|
||||
RUN ipfs init && echo "$(ipfs add -rQ .)" > ipfs-hash
|
||||
RUN apk add --no-cache go-ipfs; ipfs init && echo "$(ipfs add -rQ .)" > ipfs-hash; apk del go-ipfs
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n00.stagnet3.vega.xyz/websocket
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
|
||||
NX_VEGA_NETWORKS='{"SANDBOX":"https://sandbox.explorer.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz", "STAGNET3":"https://stagnet3.explorer.vega.xyz","VALIDATOR_TESTNET":"https://validator-testnet.fairground.wtf","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
||||
NX_VEGA_NETWORKS='{"STAGNET1":"https://stagnet1.token.vega.xyz", "STAGNET3":"https://stagnet3.explorer.vega.xyz","VALIDATOR_TESTNET":"https://validator-testnet.fairground.wtf","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
# App configuration variables
|
||||
NX_TENDERMINT_URL=https://tm.be.mainnet-mirror.vega.xyz
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.xyz/websocket
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
|
||||
NX_VEGA_ENV=MIRROR
|
||||
NX_BLOCK_EXPLORER=https://be.mainnet-mirror.vega.xyz/rest/
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://mainnet-mirror.token.vega.xyz
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
NX_EXPLORER_GENESIS=1
|
||||
NX_EXPLORER_GOVERNANCE=1
|
||||
NX_EXPLORER_NETWORK_PARAMETERS=1
|
||||
NX_EXPLORER_PARTIES=1
|
||||
NX_EXPLORER_VALIDATORS=1
|
||||
NX_EXPLORER_MARKETS=0
|
||||
NX_EXPLORER_ORACLES=0
|
||||
NX_EXPLORER_TXS_LIST=1
|
||||
@@ -1,12 +0,0 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_ENV=SANDBOX
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
|
||||
NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_TENDERMINT_URL=https://tm.sandbox.vega.xyz
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.sandbox.vega.xyz/websocket
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_VEGA_GOVERNANCE_URL=https://sandbox.token.vega.xyz
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
@@ -9,5 +9,5 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
|
||||
|
||||
NX_VEGA_GOVERNANCE_URL=https://validator-testnet.governance.vega.xyz
|
||||
NX_TENDERMINT_URL=https://tm-be.validators-testnet.vega.rocks
|
||||
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/
|
||||
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/rest
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
|
||||
|
||||
@@ -13,6 +13,8 @@ NX_LOCAL_PROVIDER_URL=http://localhost:8545/
|
||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
||||
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
|
||||
#Test configuration variables
|
||||
CYPRESS_FAIRGROUND=false
|
||||
|
||||
@@ -6,159 +6,203 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
||||
cy.get('nav', { timeout: 10000 }).should('be.visible');
|
||||
});
|
||||
|
||||
describe('with wallets disconnected', function () {
|
||||
describe('Links and buttons', function () {
|
||||
it('should have link for proposal page', function () {
|
||||
cy.getByTestId('home-proposals').within(() => {
|
||||
cy.get('[href="/proposals"]')
|
||||
.should('exist')
|
||||
.and('have.text', 'Browse, vote, and propose');
|
||||
});
|
||||
});
|
||||
it('should show open or enacted proposals with proposal summary', function () {
|
||||
cy.get('body').then(($body) => {
|
||||
if (!$body.find('[data-testid="proposals-list-item"]').length) {
|
||||
cy.createMarket();
|
||||
cy.reload();
|
||||
waitForSpinner();
|
||||
}
|
||||
});
|
||||
cy.getByTestId('proposals-list-item')
|
||||
.should('have.length.at.least', 1)
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.getByTestId('proposal-title')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('proposal-type')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('proposal-description')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('proposal-details')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('proposal-status')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('vote-details')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('view-proposal-btn').should('be.visible');
|
||||
});
|
||||
});
|
||||
it('should have external link for governance', function () {
|
||||
cy.getByTestId('home-proposals').within(() => {
|
||||
cy.getByTestId('external-link')
|
||||
.should('have.attr', 'href')
|
||||
.and('contain', 'https://vega.xyz/governance');
|
||||
});
|
||||
});
|
||||
it('should have link for validator page', function () {
|
||||
cy.getByTestId('home-validators').within(() => {
|
||||
cy.get('[href="/validators"]')
|
||||
.first()
|
||||
.should('exist')
|
||||
.and('have.text', 'Browse, and stake');
|
||||
});
|
||||
});
|
||||
it('should have external link for validators', function () {
|
||||
cy.getByTestId('home-validators').within(() => {
|
||||
cy.getByTestId('external-link')
|
||||
.should('have.attr', 'href')
|
||||
.and(
|
||||
'contain',
|
||||
'https://community.vega.xyz/c/mainnet-validator-candidates'
|
||||
);
|
||||
});
|
||||
});
|
||||
it('should have information on active nodes', function () {
|
||||
cy.getByTestId('node-information')
|
||||
.first()
|
||||
.should('contain.text', '2')
|
||||
.and('contain.text', 'active nodes');
|
||||
});
|
||||
it('should have information on consensus nodes', function () {
|
||||
cy.getByTestId('node-information')
|
||||
.last()
|
||||
.should('contain.text', '2')
|
||||
.and('contain.text', 'consensus nodes');
|
||||
});
|
||||
it('should contain link to specific validators', function () {
|
||||
cy.getByTestId('validators')
|
||||
.should('have.length', '2')
|
||||
.each(($validator) => {
|
||||
cy.wrap($validator).find('a').should('have.attr', 'href');
|
||||
});
|
||||
});
|
||||
it('should have link for rewards page', function () {
|
||||
cy.getByTestId('home-rewards').within(() => {
|
||||
cy.get('[href="/rewards"]')
|
||||
.first()
|
||||
.should('exist')
|
||||
.and('have.text', 'See rewards');
|
||||
});
|
||||
});
|
||||
it('should have link for withdrawal page', function () {
|
||||
cy.getByTestId('home-vega-token').within(() => {
|
||||
cy.get('[href="/token/withdraw"]')
|
||||
.first()
|
||||
.should('exist')
|
||||
.and('have.text', 'Manage tokens');
|
||||
});
|
||||
describe('Links and buttons', function () {
|
||||
it('should have link for proposal page', function () {
|
||||
cy.getByTestId('home-proposals').within(() => {
|
||||
cy.get('[href="/proposals"]')
|
||||
.should('exist')
|
||||
.and('have.text', 'Browse, vote, and propose');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Mobile view - navigation bar', function () {
|
||||
before('Change to mobile resolution', function () {
|
||||
cy.viewport('iphone-xr');
|
||||
});
|
||||
|
||||
it('should have burger button', () => {
|
||||
cy.getByTestId('button-menu-drawer').should('be.visible').click();
|
||||
cy.getByTestId('menu-drawer').should('be.visible');
|
||||
});
|
||||
|
||||
it('should have link for proposal page', function () {
|
||||
cy.getByTestId('menu-drawer').within(() => {
|
||||
cy.get('[href="/proposals"]')
|
||||
.should('exist')
|
||||
.and('have.text', 'Proposals');
|
||||
it('should display announcement banner', function () {
|
||||
cy.getByTestId('app-announcement')
|
||||
.should('be.visible')
|
||||
.within(() => {
|
||||
cy.getByTestId('external-link').should('exist');
|
||||
});
|
||||
cy.getByTestId('app-announcement-close').should('be.visible').click();
|
||||
cy.getByTestId('app-announcement').should('not.exist');
|
||||
});
|
||||
|
||||
it('should show open or enacted proposals with proposal summary', function () {
|
||||
cy.get('body').then(($body) => {
|
||||
if (!$body.find('[data-testid="proposals-list-item"]').length) {
|
||||
cy.createMarket();
|
||||
cy.reload();
|
||||
waitForSpinner();
|
||||
}
|
||||
});
|
||||
it('should have link for validator page', function () {
|
||||
cy.getByTestId('menu-drawer').within(() => {
|
||||
cy.get('[href="/validators"]')
|
||||
cy.getByTestId('proposals-list-item')
|
||||
.should('have.length.at.least', 1)
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.getByTestId('proposal-title')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('proposal-type').invoke('text').should('not.be.empty');
|
||||
cy.getByTestId('proposal-description')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('proposal-details')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('proposal-status')
|
||||
.invoke('text')
|
||||
.should('not.be.empty');
|
||||
cy.getByTestId('vote-details').invoke('text').should('not.be.empty');
|
||||
cy.getByTestId('view-proposal-btn').should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have external link for governance', function () {
|
||||
cy.getByTestId('home-proposals').within(() => {
|
||||
cy.getByTestId('external-link')
|
||||
.should('have.attr', 'href')
|
||||
.and('contain', 'https://vega.xyz/governance');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have link for validator page', function () {
|
||||
cy.getByTestId('home-validators').within(() => {
|
||||
cy.get('[href="/validators"]')
|
||||
.first()
|
||||
.should('exist')
|
||||
.and('have.text', 'Browse, and stake');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have external link for validators', function () {
|
||||
cy.getByTestId('home-validators').within(() => {
|
||||
cy.getByTestId('external-link')
|
||||
.should('have.attr', 'href')
|
||||
.and(
|
||||
'contain',
|
||||
'https://community.vega.xyz/c/mainnet-validator-candidates'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should have information on active nodes', function () {
|
||||
cy.getByTestId('node-information')
|
||||
.first()
|
||||
.should('contain.text', '2')
|
||||
.and('contain.text', 'active nodes');
|
||||
});
|
||||
|
||||
it('should have information on consensus nodes', function () {
|
||||
cy.getByTestId('node-information')
|
||||
.last()
|
||||
.should('contain.text', '2')
|
||||
.and('contain.text', 'consensus nodes');
|
||||
});
|
||||
|
||||
it('should contain link to specific validators', function () {
|
||||
cy.getByTestId('validators')
|
||||
.should('have.length', '2')
|
||||
.each(($validator) => {
|
||||
cy.wrap($validator).find('a').should('have.attr', 'href');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have link for rewards page', function () {
|
||||
cy.getByTestId('home-rewards').within(() => {
|
||||
cy.get('[href="/rewards"]')
|
||||
.first()
|
||||
.should('exist')
|
||||
.and('have.text', 'See rewards');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have link for withdrawal page', function () {
|
||||
cy.getByTestId('home-vega-token').within(() => {
|
||||
cy.get('[href="/token/withdraw"]')
|
||||
.first()
|
||||
.should('exist')
|
||||
.and('have.text', 'Manage tokens');
|
||||
});
|
||||
});
|
||||
|
||||
it('should display network data', function () {
|
||||
cy.getByTestId('git-network-data')
|
||||
.should('contain.text', 'Reading network data from')
|
||||
.within(() => {
|
||||
cy.get('span')
|
||||
.first()
|
||||
.should('exist')
|
||||
.and('have.text', 'Validators');
|
||||
.should('have.text', 'http://localhost:3028/query');
|
||||
cy.getByTestId('link').should('exist');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should have link for rewards page', function () {
|
||||
cy.getByTestId('menu-drawer').within(() => {
|
||||
cy.get('[href="/rewards"]')
|
||||
.first()
|
||||
.should('exist')
|
||||
.and('have.text', 'Rewards');
|
||||
it('should display eth data', function () {
|
||||
cy.getByTestId('git-eth-data')
|
||||
.should('contain.text', 'Reading Ethereum data from')
|
||||
.within(() => {
|
||||
cy.get('span').should('have.text', 'http://localhost:8545');
|
||||
});
|
||||
});
|
||||
it('should have link for withdrawal page', function () {
|
||||
cy.getByTestId('menu-drawer').within(() => {
|
||||
cy.get('[href="/token/withdraw"]')
|
||||
.first()
|
||||
.should('exist')
|
||||
.and('have.text', 'Withdraw');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
cy.viewport(
|
||||
Cypress.config('viewportWidth'),
|
||||
Cypress.config('viewportHeight')
|
||||
);
|
||||
it('should contain link for known issues on Github', function () {
|
||||
cy.getByTestId('git-info').within(() => {
|
||||
cy.contains('Known issues and feedback on')
|
||||
.find('[data-testid="link"]')
|
||||
.should(
|
||||
'have.attr',
|
||||
'href',
|
||||
'https://github.com/vegaprotocol/feedback/discussions'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Mobile view - navigation bar', function () {
|
||||
before('Change to mobile resolution', function () {
|
||||
cy.viewport('iphone-xr');
|
||||
});
|
||||
|
||||
it('should have burger button', () => {
|
||||
cy.getByTestId('button-menu-drawer').should('be.visible').click();
|
||||
cy.getByTestId('menu-drawer').should('be.visible');
|
||||
});
|
||||
|
||||
it('should have link for proposal page', function () {
|
||||
cy.getByTestId('menu-drawer').within(() => {
|
||||
cy.get('[href="/proposals"]')
|
||||
.should('exist')
|
||||
.and('have.text', 'Proposals');
|
||||
});
|
||||
});
|
||||
it('should have link for validator page', function () {
|
||||
cy.getByTestId('menu-drawer').within(() => {
|
||||
cy.get('[href="/validators"]')
|
||||
.first()
|
||||
.should('exist')
|
||||
.and('have.text', 'Validators');
|
||||
});
|
||||
});
|
||||
|
||||
it('should have link for rewards page', function () {
|
||||
cy.getByTestId('menu-drawer').within(() => {
|
||||
cy.get('[href="/rewards"]')
|
||||
.first()
|
||||
.should('exist')
|
||||
.and('have.text', 'Rewards');
|
||||
});
|
||||
});
|
||||
it('should have link for withdrawal page', function () {
|
||||
cy.getByTestId('menu-drawer').within(() => {
|
||||
cy.get('[href="/token/withdraw"]')
|
||||
.first()
|
||||
.should('exist')
|
||||
.and('have.text', 'Withdraw');
|
||||
});
|
||||
});
|
||||
|
||||
after(function () {
|
||||
cy.viewport(
|
||||
Cypress.config('viewportWidth'),
|
||||
Cypress.config('viewportHeight')
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,6 +5,7 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_FAIRGROUND=false
|
||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
NX_VEGA_CONFIG_URL=''
|
||||
|
||||
NX_VEGA_URL=http://localhost:3028/query
|
||||
@@ -16,7 +17,6 @@ NX_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
|
||||
|
||||
#Test configuration variables
|
||||
CYPRESS_FAIRGROUND=false
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_ENV=MIRROR
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
|
||||
NX_VEGA_URL=https://api.n00.mainnet-mirror.vega.xyz/graphql
|
||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_VEGA_EXPLORER_URL=https://mirror.explorer.vega.xyz
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||
@@ -1,9 +0,0 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_URL=https://api.sandbox.vega.xyz/graphql
|
||||
NX_VEGA_ENV=SANDBOX
|
||||
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
|
||||
NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
@@ -8,3 +8,4 @@ NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
|
||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
|
||||
@@ -12,6 +12,7 @@ const TRUTHY = ['1', 'true'];
|
||||
interface VegaContracts {
|
||||
claimAddress: string;
|
||||
lockedAddress: string;
|
||||
tokenVestingAddress?: string;
|
||||
}
|
||||
|
||||
const customClaimAddress = process.env['NX_CUSTOM_CLAIM_ADDRESS'] as string;
|
||||
@@ -36,21 +37,16 @@ export const ContractAddresses: {
|
||||
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
|
||||
lockedAddress: '0x0', // TODO not deployed to this env
|
||||
},
|
||||
SANDBOX: {
|
||||
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
|
||||
lockedAddress: '0x0', // TODO not deployed to this env
|
||||
},
|
||||
TESTNET: {
|
||||
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
|
||||
lockedAddress: '0x0', // TODO not deployed to this env
|
||||
},
|
||||
MIRROR: {
|
||||
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
|
||||
lockedAddress: '0x0', // TODO not deployed to this env
|
||||
},
|
||||
VALIDATOR_TESTNET: {
|
||||
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
|
||||
lockedAddress: '0x0', // TODO not deployed to this env
|
||||
// This is a fallback contract address for the validator testnet network which does not
|
||||
// have a vesting contract address set and is therefore not in the ethereum config
|
||||
tokenVestingAddress: '0xadFcb7f93a24F8743a8e548d74d2ecB373c92866',
|
||||
},
|
||||
MAINNET: {
|
||||
claimAddress: '0x0ee1fb382caf98e86e97e51f9f42f8b4654020f3',
|
||||
|
||||
@@ -49,6 +49,13 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
|
||||
signer = provider.getSigner();
|
||||
}
|
||||
|
||||
const tokenVestingAddress =
|
||||
config.token_vesting_contract?.address ||
|
||||
ENV.addresses.tokenVestingAddress;
|
||||
if (!tokenVestingAddress) {
|
||||
throw new Error('No token vesting address found');
|
||||
}
|
||||
|
||||
if (provider && config) {
|
||||
const staking = new StakingBridge(
|
||||
config.staking_bridge_contract.address,
|
||||
@@ -63,7 +70,7 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
|
||||
signer || provider
|
||||
),
|
||||
vesting: new TokenVesting(
|
||||
config.token_vesting_contract.address,
|
||||
tokenVestingAddress,
|
||||
signer || provider
|
||||
),
|
||||
claim: new Claim(ENV.addresses.claimAddress, signer || provider),
|
||||
|
||||
@@ -14,6 +14,7 @@ import { TokenDetailsCirculating } from './token-details-circulating';
|
||||
import { SplashLoader } from '../../../components/splash-loader';
|
||||
import { useEthereumConfig } from '@vegaprotocol/web3';
|
||||
import { useContracts } from '../../../contexts/contracts/contracts-context';
|
||||
import { ENV } from '../../../config';
|
||||
|
||||
export const TokenDetails = ({
|
||||
totalSupply,
|
||||
@@ -49,6 +50,9 @@ export const TokenDetails = ({
|
||||
);
|
||||
}
|
||||
|
||||
const tokenVestingContractAddress =
|
||||
config.token_vesting_contract?.address || ENV.addresses.tokenVestingAddress;
|
||||
|
||||
return (
|
||||
<div className="token-details">
|
||||
<RoundedWrapper>
|
||||
@@ -65,18 +69,20 @@ export const TokenDetails = ({
|
||||
{token.address}
|
||||
</Link>
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow>
|
||||
{t('Vesting contract').toUpperCase()}
|
||||
<Link
|
||||
data-testid="token-contract"
|
||||
title={t('View on Etherscan (opens in a new tab)')}
|
||||
className="font-mono text-white text-right"
|
||||
href={`${ETHERSCAN_URL}/address/${config.token_vesting_contract.address}`}
|
||||
target="_blank"
|
||||
>
|
||||
{config.token_vesting_contract.address}
|
||||
</Link>
|
||||
</KeyValueTableRow>
|
||||
{tokenVestingContractAddress && (
|
||||
<KeyValueTableRow>
|
||||
{t('Vesting contract').toUpperCase()}
|
||||
<Link
|
||||
data-testid="token-contract"
|
||||
title={t('View on Etherscan (opens in a new tab)')}
|
||||
className="font-mono text-white text-right"
|
||||
href={`${ETHERSCAN_URL}/address/${tokenVestingContractAddress}`}
|
||||
target="_blank"
|
||||
>
|
||||
{tokenVestingContractAddress}
|
||||
</Link>
|
||||
</KeyValueTableRow>
|
||||
)}
|
||||
<KeyValueTableRow>
|
||||
{t('Total supply').toUpperCase()}
|
||||
<span className="font-mono" data-testid="total-supply">
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
|
||||
NX_VEGA_URL=https://api.sandbox.vega.xyz/graphql
|
||||
NX_VEGA_ENV=SANDBOX
|
||||
NX_VEGA_NETWORKS={\"DEVNET\":\"https://dev.token.vega.xyz\",\"STAGNET3\":\"https://stagnet3.token.vega.xyz\",\"STAGNET1\":\"https://stagnet1.token.vega.xyz\",\"TESTNET\":\"https://token.fairground.wtf\",\"MAINNET\":\"https://token.vega.xyz\"}
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
|
||||
@@ -3,12 +3,134 @@
|
||||
"tranche_id": 56,
|
||||
"tranche_start": "2023-04-20T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-20T00:00:00.000Z",
|
||||
"total_added": "0",
|
||||
"total_added": "10724.25",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "0",
|
||||
"deposits": [],
|
||||
"locked_amount": "10724.25",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "50",
|
||||
"user": "0x15024E62134A8BFFCce11f5ce58CeCDe853038D7",
|
||||
"tx": "0xc38d2e52912f15452c76b863dbfad88927b49435c284eaf6997be4cf13782fc0"
|
||||
},
|
||||
{
|
||||
"amount": "6001.25",
|
||||
"user": "0x94097462EF7c43D0aC732E7B18f830096D95207C",
|
||||
"tx": "0xde2c8eedaba7ef1c953a7ca5439a8d7900ff01d92bd49d9dff1c9cdeaaa38d6f"
|
||||
},
|
||||
{
|
||||
"amount": "2378.75",
|
||||
"user": "0xd5EAB7ecE436D997139dbCd2c38bCE932B65a8ea",
|
||||
"tx": "0x79d5279a108f5621488b5fba2e0b4c1508fff80bd3cf7bd36f8d79f5a87f9fea"
|
||||
},
|
||||
{
|
||||
"amount": "1121.25",
|
||||
"user": "0xf96afaB11e5617560b9183766470B23F45c38C56",
|
||||
"tx": "0xd75c7996c5a9484ad3432eab458341b21eb76e117d68fb2885170bfb7b017da1"
|
||||
},
|
||||
{
|
||||
"amount": "1121.25",
|
||||
"user": "0xf915Da10e5136352Ba049acB0545Deb119054256",
|
||||
"tx": "0x6840e2b579765303fc31a04f43fcea1d5ccf157b46bbd1e3f3e7f6a2e6cea039"
|
||||
},
|
||||
{
|
||||
"amount": "51.75",
|
||||
"user": "0x237D23FcA6d7B2530C7614a9cB921CF27924911E",
|
||||
"tx": "0x3e9c304b5ca74d1238cc4ee2f1396812aac6e62eb8674e8be3e01c9ad3e5bcb0"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"users": []
|
||||
"users": [
|
||||
{
|
||||
"address": "0x15024E62134A8BFFCce11f5ce58CeCDe853038D7",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "50",
|
||||
"user": "0x15024E62134A8BFFCce11f5ce58CeCDe853038D7",
|
||||
"tranche_id": 56,
|
||||
"tx": "0xc38d2e52912f15452c76b863dbfad88927b49435c284eaf6997be4cf13782fc0"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "50",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "50"
|
||||
},
|
||||
{
|
||||
"address": "0x94097462EF7c43D0aC732E7B18f830096D95207C",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "6001.25",
|
||||
"user": "0x94097462EF7c43D0aC732E7B18f830096D95207C",
|
||||
"tranche_id": 56,
|
||||
"tx": "0xde2c8eedaba7ef1c953a7ca5439a8d7900ff01d92bd49d9dff1c9cdeaaa38d6f"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "6001.25",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "6001.25"
|
||||
},
|
||||
{
|
||||
"address": "0xd5EAB7ecE436D997139dbCd2c38bCE932B65a8ea",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2378.75",
|
||||
"user": "0xd5EAB7ecE436D997139dbCd2c38bCE932B65a8ea",
|
||||
"tranche_id": 56,
|
||||
"tx": "0x79d5279a108f5621488b5fba2e0b4c1508fff80bd3cf7bd36f8d79f5a87f9fea"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "2378.75",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "2378.75"
|
||||
},
|
||||
{
|
||||
"address": "0xf96afaB11e5617560b9183766470B23F45c38C56",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1121.25",
|
||||
"user": "0xf96afaB11e5617560b9183766470B23F45c38C56",
|
||||
"tranche_id": 56,
|
||||
"tx": "0xd75c7996c5a9484ad3432eab458341b21eb76e117d68fb2885170bfb7b017da1"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "1121.25",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "1121.25"
|
||||
},
|
||||
{
|
||||
"address": "0xf915Da10e5136352Ba049acB0545Deb119054256",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1121.25",
|
||||
"user": "0xf915Da10e5136352Ba049acB0545Deb119054256",
|
||||
"tranche_id": 56,
|
||||
"tx": "0x6840e2b579765303fc31a04f43fcea1d5ccf157b46bbd1e3f3e7f6a2e6cea039"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "1121.25",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "1121.25"
|
||||
},
|
||||
{
|
||||
"address": "0x237D23FcA6d7B2530C7614a9cB921CF27924911E",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "51.75",
|
||||
"user": "0x237D23FcA6d7B2530C7614a9cB921CF27924911E",
|
||||
"tranche_id": 56,
|
||||
"tx": "0x3e9c304b5ca74d1238cc4ee2f1396812aac6e62eb8674e8be3e01c9ad3e5bcb0"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "51.75",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "51.75"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tranche_id": 55,
|
||||
@@ -67,9 +189,9 @@
|
||||
"tranche_id": 54,
|
||||
"tranche_start": "2023-04-06T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-06T00:00:00.000Z",
|
||||
"total_added": "2970",
|
||||
"total_added": "8565",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "2970",
|
||||
"locked_amount": "8565",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "33",
|
||||
@@ -86,6 +208,21 @@
|
||||
"user": "0xE9F41a0090fcc7eaf626037003AAD44B17098E7C",
|
||||
"tx": "0x09d3e968eb8dbd6851f47b36f7bb9e7d25a078c5c1b23ce5341a66ce19578e65"
|
||||
},
|
||||
{
|
||||
"amount": "678",
|
||||
"user": "0x94097462EF7c43D0aC732E7B18f830096D95207C",
|
||||
"tx": "0x157b13e78d027a5b6cf35fdae80a8cec7797149f35c23eb43faa07d74a03d70d"
|
||||
},
|
||||
{
|
||||
"amount": "2394",
|
||||
"user": "0xd5EAB7ecE436D997139dbCd2c38bCE932B65a8ea",
|
||||
"tx": "0xbe03bd7e16faa3586fe66ddaac2bcacba4604b175721eb10aee29b40248759ea"
|
||||
},
|
||||
{
|
||||
"amount": "2523",
|
||||
"user": "0xf96afaB11e5617560b9183766470B23F45c38C56",
|
||||
"tx": "0x49ab3f37bda02347cb1966e8fa21885a463f09d0593a890e96b2e36dfb8dec49"
|
||||
},
|
||||
{
|
||||
"amount": "111",
|
||||
"user": "0x268070d5EEd5b24E34a5F4C17B5482178b18089D",
|
||||
@@ -214,6 +351,51 @@
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "288"
|
||||
},
|
||||
{
|
||||
"address": "0x94097462EF7c43D0aC732E7B18f830096D95207C",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "678",
|
||||
"user": "0x94097462EF7c43D0aC732E7B18f830096D95207C",
|
||||
"tranche_id": 54,
|
||||
"tx": "0x157b13e78d027a5b6cf35fdae80a8cec7797149f35c23eb43faa07d74a03d70d"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "678",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "678"
|
||||
},
|
||||
{
|
||||
"address": "0xd5EAB7ecE436D997139dbCd2c38bCE932B65a8ea",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2394",
|
||||
"user": "0xd5EAB7ecE436D997139dbCd2c38bCE932B65a8ea",
|
||||
"tranche_id": 54,
|
||||
"tx": "0xbe03bd7e16faa3586fe66ddaac2bcacba4604b175721eb10aee29b40248759ea"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "2394",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "2394"
|
||||
},
|
||||
{
|
||||
"address": "0xf96afaB11e5617560b9183766470B23F45c38C56",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2523",
|
||||
"user": "0xf96afaB11e5617560b9183766470B23F45c38C56",
|
||||
"tranche_id": 54,
|
||||
"tx": "0x49ab3f37bda02347cb1966e8fa21885a463f09d0593a890e96b2e36dfb8dec49"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "2523",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "2523"
|
||||
},
|
||||
{
|
||||
"address": "0x268070d5EEd5b24E34a5F4C17B5482178b18089D",
|
||||
"deposits": [
|
||||
@@ -561,7 +743,7 @@
|
||||
"tranche_end": "2023-04-06T00:00:00.000Z",
|
||||
"total_added": "14099",
|
||||
"total_removed": "165.10784124668",
|
||||
"locked_amount": "1247.56462776284332054",
|
||||
"locked_amount": "565.470757541816007166",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "30",
|
||||
@@ -3349,7 +3531,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "86666.297",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "58349.7031275271807221145",
|
||||
"locked_amount": "57993.6007228891030790117",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "86666.297",
|
||||
@@ -3415,7 +3597,7 @@
|
||||
"tranche_end": "2023-06-01T00:00:00.000Z",
|
||||
"total_added": "2500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "806.91026276963785",
|
||||
"locked_amount": "786.30936482498975",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2500",
|
||||
@@ -3536,7 +3718,7 @@
|
||||
"tranche_end": "2023-09-01T00:00:00.000Z",
|
||||
"total_added": "17500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "14336.97649330716525",
|
||||
"locked_amount": "14194.337667320853",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "12500",
|
||||
@@ -3802,8 +3984,8 @@
|
||||
"tranche_start": "2023-02-01T00:00:00.000Z",
|
||||
"tranche_end": "2023-08-01T00:00:00.000Z",
|
||||
"total_added": "37500",
|
||||
"total_removed": "11668.32172695",
|
||||
"locked_amount": "24808.64650475752125",
|
||||
"total_removed": "11781.2245815",
|
||||
"locked_amount": "24497.9257788520575",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -3837,6 +4019,11 @@
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xf440dd4b160a155a08a3cc6e16706d5e4f9609bddd46c495217c377ef538c76f"
|
||||
},
|
||||
{
|
||||
"amount": "112.90285455",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x69a4b32bad0a702a9e19ec1a77e4bc75d936f323720ca4c6213f2e4f41a750ed"
|
||||
},
|
||||
{
|
||||
"amount": "92.587476975",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -3963,6 +4150,12 @@
|
||||
"tranche_id": 34,
|
||||
"tx": "0xf440dd4b160a155a08a3cc6e16706d5e4f9609bddd46c495217c377ef538c76f"
|
||||
},
|
||||
{
|
||||
"amount": "112.90285455",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 34,
|
||||
"tx": "0x69a4b32bad0a702a9e19ec1a77e4bc75d936f323720ca4c6213f2e4f41a750ed"
|
||||
},
|
||||
{
|
||||
"amount": "92.587476975",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -4073,8 +4266,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "7500",
|
||||
"withdrawn_tokens": "2432.87244855",
|
||||
"remaining_tokens": "5067.12755145"
|
||||
"withdrawn_tokens": "2545.7753031",
|
||||
"remaining_tokens": "4954.2246969"
|
||||
},
|
||||
{
|
||||
"address": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600",
|
||||
@@ -4112,7 +4305,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "129999.45",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "58296.4663652644736979915",
|
||||
"locked_amount": "57940.6888592641162179",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129999.45",
|
||||
@@ -4145,7 +4338,7 @@
|
||||
"tranche_end": "2024-04-01T00:00:00.000Z",
|
||||
"total_added": "54144.7663",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "53810.8835054071292707386",
|
||||
"locked_amount": "53589.01639451037519275324",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "54144.7663",
|
||||
@@ -4178,7 +4371,7 @@
|
||||
"tranche_end": "2023-09-03T00:00:00.000Z",
|
||||
"total_added": "62600",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "26196.482198122780824",
|
||||
"locked_amount": "25939.265594875696096",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10000",
|
||||
@@ -4371,7 +4564,7 @@
|
||||
"tranche_end": "2023-09-17T00:00:00.000Z",
|
||||
"total_added": "5000",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "2284.15160451547415",
|
||||
"locked_amount": "2263.60714738711335",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "5000",
|
||||
@@ -4582,7 +4775,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "97499.58",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "405.60456575344483061187",
|
||||
"locked_amount": "56.619974540901995087628",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "97499.58",
|
||||
@@ -4615,7 +4808,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "135173.4239508",
|
||||
"total_removed": "133818.54965292963650862",
|
||||
"locked_amount": "554.3914166779487086967342868",
|
||||
"locked_amount": "77.38973016660167928688450596",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "135173.4239508",
|
||||
@@ -4672,7 +4865,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "32499.86",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "170.63083639627856110929",
|
||||
"locked_amount": "23.819045514696515832434",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "32499.86",
|
||||
@@ -4705,7 +4898,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "10833.29",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "55.53868148454478352929",
|
||||
"locked_amount": "7.752868180487023081501",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10833.29",
|
||||
@@ -4738,7 +4931,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "22749.93",
|
||||
"total_removed": "4720.860935375",
|
||||
"locked_amount": "207.61599572971184611278",
|
||||
"locked_amount": "28.98195283049736585006",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "6500",
|
||||
@@ -4889,8 +5082,8 @@
|
||||
"tranche_start": "2022-11-01T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-01T00:00:00.000Z",
|
||||
"total_added": "22500",
|
||||
"total_removed": "6244.98110415",
|
||||
"locked_amount": "3448.723814456722875",
|
||||
"total_removed": "6357.929999175",
|
||||
"locked_amount": "3262.2913789134444",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -4919,6 +5112,16 @@
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x0e47007cb85268a4e0c3c1143b96e4c98c9880060c4218babcadd0c82f8247a9"
|
||||
},
|
||||
{
|
||||
"amount": "112.943139975",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xde2d6d5df9d5097adf8a894beb8a02f0bd1cc4da1eccc221f8bfa08403dfed87"
|
||||
},
|
||||
{
|
||||
"amount": "0.00575505",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xa7a9a0e91b78fd7d8ba4c16bf5b58fb1a3cb19ec1302788e894f5e24ccb07904"
|
||||
},
|
||||
{
|
||||
"amount": "92.593232025",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -5100,6 +5303,18 @@
|
||||
"tranche_id": 33,
|
||||
"tx": "0x0e47007cb85268a4e0c3c1143b96e4c98c9880060c4218babcadd0c82f8247a9"
|
||||
},
|
||||
{
|
||||
"amount": "112.943139975",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 33,
|
||||
"tx": "0xde2d6d5df9d5097adf8a894beb8a02f0bd1cc4da1eccc221f8bfa08403dfed87"
|
||||
},
|
||||
{
|
||||
"amount": "0.00575505",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 33,
|
||||
"tx": "0xa7a9a0e91b78fd7d8ba4c16bf5b58fb1a3cb19ec1302788e894f5e24ccb07904"
|
||||
},
|
||||
{
|
||||
"amount": "92.593232025",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -5282,8 +5497,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "7500",
|
||||
"withdrawn_tokens": "6244.98110415",
|
||||
"remaining_tokens": "1255.01889585"
|
||||
"withdrawn_tokens": "6357.929999175",
|
||||
"remaining_tokens": "1142.070000825"
|
||||
},
|
||||
{
|
||||
"address": "0x2539b51EbDE65a75672aBcfE9439a706a99D18D1",
|
||||
@@ -5308,7 +5523,7 @@
|
||||
"tranche_end": "2023-06-02T00:00:00.000Z",
|
||||
"total_added": "1939928.38",
|
||||
"total_removed": "928642.9598472029154",
|
||||
"locked_amount": "317526.7710493525900617104",
|
||||
"locked_amount": "309555.815962352273510404",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1852091.69",
|
||||
@@ -39041,7 +39256,7 @@
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "3732368.4671",
|
||||
"total_removed": "700133.348465855088393",
|
||||
"locked_amount": "512429.420752227829460135708",
|
||||
"locked_amount": "500180.743448598467211370596",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1998.95815",
|
||||
@@ -40422,8 +40637,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "15870102.715470999700000001",
|
||||
"total_removed": "814470.78267520605435452",
|
||||
"locked_amount": "7116729.41051479466949006868895061288618547",
|
||||
"total_removed": "815414.41205294384422952",
|
||||
"locked_amount": "7073296.38723637379898712666179481614084885",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "16249.93",
|
||||
@@ -40957,6 +41172,16 @@
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x58bac20de3636c17156dcb64322cc7612c48f553d941bc039c796ef4167eeeb5"
|
||||
},
|
||||
{
|
||||
"amount": "481.17190713062625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x625ce40117b67b756a12ad676cfbfd2c59e264b3c86adbc624bf7107c4dbc5d5"
|
||||
},
|
||||
{
|
||||
"amount": "462.457470607163625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xa65322922116e2e0949be9d83e65ef0b1f2d8fe3eb399616a5cbbb7c95593717"
|
||||
},
|
||||
{
|
||||
"amount": "545.4204142199725",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -42981,6 +43206,18 @@
|
||||
"tranche_id": 2,
|
||||
"tx": "0x58bac20de3636c17156dcb64322cc7612c48f553d941bc039c796ef4167eeeb5"
|
||||
},
|
||||
{
|
||||
"amount": "481.17190713062625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x625ce40117b67b756a12ad676cfbfd2c59e264b3c86adbc624bf7107c4dbc5d5"
|
||||
},
|
||||
{
|
||||
"amount": "462.457470607163625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0xa65322922116e2e0949be9d83e65ef0b1f2d8fe3eb399616a5cbbb7c95593717"
|
||||
},
|
||||
{
|
||||
"amount": "545.4204142199725",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -44357,8 +44594,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "259998.8875",
|
||||
"withdrawn_tokens": "143014.802273444948",
|
||||
"remaining_tokens": "116984.085226555052"
|
||||
"withdrawn_tokens": "143958.431651182737875",
|
||||
"remaining_tokens": "116040.455848817262125"
|
||||
},
|
||||
{
|
||||
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
|
||||
@@ -46703,8 +46940,8 @@
|
||||
"tranche_start": "2021-11-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-05T00:00:00.000Z",
|
||||
"total_added": "14597706.0446472999",
|
||||
"total_removed": "5802489.518043560526965506",
|
||||
"locked_amount": "848673.9247506211806821697552292785",
|
||||
"total_removed": "5807463.612246947184450156",
|
||||
"locked_amount": "808576.834982455928473059742460535",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129284.449",
|
||||
@@ -46968,6 +47205,21 @@
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0xae9047ab72d73da1001c570a12dddc5e82fd523454c1b377928e008da9bdfa85"
|
||||
},
|
||||
{
|
||||
"amount": "3666.3885480971028369",
|
||||
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
||||
"tx": "0x54687b81b06562122894e34822a416021671c28f99066a23c5a69399b614409d"
|
||||
},
|
||||
{
|
||||
"amount": "661.66343451005891275",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x523cbf99fb25ac9633e40a26cf1aa66ac5442392e577299159bf50e844a860e1"
|
||||
},
|
||||
{
|
||||
"amount": "646.042220779495735",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0xcd3480c11e987e702a52413185dcc232b399747ef2fd7529aa46bea02c6f4be5"
|
||||
},
|
||||
{
|
||||
"amount": "755.482067130393772",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@@ -50134,6 +50386,18 @@
|
||||
"tranche_id": 3,
|
||||
"tx": "0xae9047ab72d73da1001c570a12dddc5e82fd523454c1b377928e008da9bdfa85"
|
||||
},
|
||||
{
|
||||
"amount": "661.66343451005891275",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x523cbf99fb25ac9633e40a26cf1aa66ac5442392e577299159bf50e844a860e1"
|
||||
},
|
||||
{
|
||||
"amount": "646.042220779495735",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0xcd3480c11e987e702a52413185dcc232b399747ef2fd7529aa46bea02c6f4be5"
|
||||
},
|
||||
{
|
||||
"amount": "755.482067130393772",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@@ -52812,8 +53076,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "359123.469575",
|
||||
"withdrawn_tokens": "337702.576476093841779",
|
||||
"remaining_tokens": "21420.893098906158221"
|
||||
"withdrawn_tokens": "339010.28213138339642675",
|
||||
"remaining_tokens": "20113.18744361660357325"
|
||||
},
|
||||
{
|
||||
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
|
||||
@@ -53073,6 +53337,12 @@
|
||||
"tranche_id": 3,
|
||||
"tx": "0x14811c8d77a39b0331cb2fdc96049b462916877050cc73143c494277304c2496"
|
||||
},
|
||||
{
|
||||
"amount": "3666.3885480971028369",
|
||||
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x54687b81b06562122894e34822a416021671c28f99066a23c5a69399b614409d"
|
||||
},
|
||||
{
|
||||
"amount": "80421.5336580481619385",
|
||||
"user": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
||||
@@ -53405,8 +53675,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "1266324.603486",
|
||||
"withdrawn_tokens": "1189269.53625719263269252",
|
||||
"remaining_tokens": "77055.06722880736730748"
|
||||
"withdrawn_tokens": "1192935.92480528973552942",
|
||||
"remaining_tokens": "73388.67868071026447058"
|
||||
},
|
||||
{
|
||||
"address": "0xC5d9221EB9c28A69859264c0A2Fe0d3272228296",
|
||||
@@ -54234,8 +54504,8 @@
|
||||
"tranche_start": "2021-10-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "5778205.3912159303",
|
||||
"total_removed": "3381706.364737906998719578",
|
||||
"locked_amount": "18412.7968659549219832486449580318",
|
||||
"total_removed": "3405527.985875969683269578",
|
||||
"locked_amount": "2570.194193372696618931420745650855",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "552496.6455",
|
||||
@@ -54379,6 +54649,16 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "10509.407528939748325",
|
||||
"user": "0xBc934494675a6ceB639B9EfEe5b9C0f017D35a75",
|
||||
"tx": "0x621a569bfd19dbc0a6ba78addf836a9f2f1897258a88198d994e5b18c9f4901e"
|
||||
},
|
||||
{
|
||||
"amount": "13312.213609122936225",
|
||||
"user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90",
|
||||
"tx": "0x8a1d50991be09f4adc9eba704fbbcd271e8022db56498b300f39d3111bf187ea"
|
||||
},
|
||||
{
|
||||
"amount": "8511.948415174862415",
|
||||
"user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90",
|
||||
@@ -55376,6 +55656,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "10509.407528939748325",
|
||||
"user": "0xBc934494675a6ceB639B9EfEe5b9C0f017D35a75",
|
||||
"tranche_id": 4,
|
||||
"tx": "0x621a569bfd19dbc0a6ba78addf836a9f2f1897258a88198d994e5b18c9f4901e"
|
||||
},
|
||||
{
|
||||
"amount": "990.74735267405816",
|
||||
"user": "0xBc934494675a6ceB639B9EfEe5b9C0f017D35a75",
|
||||
@@ -55480,8 +55766,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "110499.5291",
|
||||
"withdrawn_tokens": "99798.20962987885552",
|
||||
"remaining_tokens": "10701.31947012114448"
|
||||
"withdrawn_tokens": "110307.617158818603845",
|
||||
"remaining_tokens": "191.911941181396155"
|
||||
},
|
||||
{
|
||||
"address": "0xdbC5d439F373EB646345e1c67D1d46231ACE7dD3",
|
||||
@@ -55999,6 +56285,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "13312.213609122936225",
|
||||
"user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90",
|
||||
"tranche_id": 4,
|
||||
"tx": "0x8a1d50991be09f4adc9eba704fbbcd271e8022db56498b300f39d3111bf187ea"
|
||||
},
|
||||
{
|
||||
"amount": "8511.948415174862415",
|
||||
"user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90",
|
||||
@@ -56259,8 +56551,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "331498.5873",
|
||||
"withdrawn_tokens": "317966.428170547352487",
|
||||
"remaining_tokens": "13532.159129452647513"
|
||||
"withdrawn_tokens": "331278.641779670288712",
|
||||
"remaining_tokens": "219.945520329711288"
|
||||
},
|
||||
{
|
||||
"address": "0x16da609341ed67750A8BCC5AAa2005471006Cd77",
|
||||
@@ -56362,8 +56654,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "472355.6199999996",
|
||||
"total_removed": "40152.1324861581949",
|
||||
"locked_amount": "81197.370889637811460062778488072",
|
||||
"total_removed": "41316.3370079701949",
|
||||
"locked_amount": "79256.497954453234412822232673788",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "3000",
|
||||
@@ -63042,6 +63334,16 @@
|
||||
"user": "0x28FC83947F02f59Cb36b40f97f2D32BBC5D00585",
|
||||
"tx": "0x14da65fbf5ae2f3a593036daa58b3353ab88fc22666e5514f9160e252ad2fdf9"
|
||||
},
|
||||
{
|
||||
"amount": "332.441235412",
|
||||
"user": "0x5c8fadaf56946d60823Dae0526A540EEfE791c99",
|
||||
"tx": "0x67af8d72b36a27796fbe8f52ac55951d54102ac58582f848f0d21cf8ca427e77"
|
||||
},
|
||||
{
|
||||
"amount": "831.7632864",
|
||||
"user": "0x9405F540EcC1204801De5C4444D06386BD6693F0",
|
||||
"tx": "0x0df6ec04cbdda41c8649a5e360ec541d14371e3877d82e1404308180024ede02"
|
||||
},
|
||||
{
|
||||
"amount": "154.812094114",
|
||||
"user": "0x27e2254A2A8c9c9D1321E5Fe64cAD88e7A4f0ba7",
|
||||
@@ -68209,10 +68511,17 @@
|
||||
"tx": "0x1c2c084e3efafb2ffa09c0b259bd229cce0d6da04dd092d911c7e6136a7ac8a9"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "831.7632864",
|
||||
"user": "0x9405F540EcC1204801De5C4444D06386BD6693F0",
|
||||
"tranche_id": 5,
|
||||
"tx": "0x0df6ec04cbdda41c8649a5e360ec541d14371e3877d82e1404308180024ede02"
|
||||
}
|
||||
],
|
||||
"total_tokens": "1000",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "1000"
|
||||
"withdrawn_tokens": "831.7632864",
|
||||
"remaining_tokens": "168.2367136"
|
||||
},
|
||||
{
|
||||
"address": "0x99b4635De6c5c8cdbBf728d7AA0d1b9DD8Ee381F",
|
||||
@@ -84049,10 +84358,17 @@
|
||||
"tx": "0xb59405747c8088945a412703637a7b422f3639439ec2ee15e180c0a2a0d71ee4"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "332.441235412",
|
||||
"user": "0x5c8fadaf56946d60823Dae0526A540EEfE791c99",
|
||||
"tranche_id": 5,
|
||||
"tx": "0x67af8d72b36a27796fbe8f52ac55951d54102ac58582f848f0d21cf8ca427e77"
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "400"
|
||||
"withdrawn_tokens": "332.441235412",
|
||||
"remaining_tokens": "67.558764588"
|
||||
},
|
||||
{
|
||||
"address": "0x96715eF2F036069202B1C8065Db14601F40C9554",
|
||||
@@ -85900,7 +86216,7 @@
|
||||
"tranche_start": "2021-12-05T00:00:00.000Z",
|
||||
"tranche_end": "2022-06-05T00:00:00.000Z",
|
||||
"total_added": "171288.42",
|
||||
"total_removed": "67553.5995794947989",
|
||||
"total_removed": "68803.5995794947989",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
@@ -90125,6 +90441,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "1250",
|
||||
"user": "0x9405F540EcC1204801De5C4444D06386BD6693F0",
|
||||
"tx": "0x7dbc1e3f31a7aeea4e74f2bf14137bb99045b84afe7582a9ed2bc9d63b5458a4"
|
||||
},
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x2dd204e9cC4D41C68f2bb7Aa3b8Ce49884e482f5",
|
||||
@@ -95549,10 +95870,17 @@
|
||||
"tx": "0x1c2c084e3efafb2ffa09c0b259bd229cce0d6da04dd092d911c7e6136a7ac8a9"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "1250",
|
||||
"user": "0x9405F540EcC1204801De5C4444D06386BD6693F0",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x7dbc1e3f31a7aeea4e74f2bf14137bb99045b84afe7582a9ed2bc9d63b5458a4"
|
||||
}
|
||||
],
|
||||
"total_tokens": "1250",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "1250"
|
||||
"withdrawn_tokens": "1250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xf36f5369adBE86DF71f5bFfB0264fc1D99fA2935",
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"hosts": ["https://api-n00.mainnet-mirror.vega.rocks/graphql"]
|
||||
}
|
||||
@@ -1,3 +0,0 @@
|
||||
{
|
||||
"hosts": ["https://api-n01.sandbox.vega.rocks/graphql"]
|
||||
}
|
||||
@@ -95,6 +95,16 @@ describe('Console - market info - live env', { tags: '@live' }, () => {
|
||||
cy.wrap(element).should('have.text', subtitles[index]);
|
||||
});
|
||||
});
|
||||
|
||||
it('renders correctly liquidity in trading tab', () => {
|
||||
cy.getByTestId('Liquidity').click();
|
||||
cy.contains('Loading').should('not.exist');
|
||||
cy.contains('Something went wrong').should('not.exist');
|
||||
cy.contains('Application error').should('not.exist');
|
||||
cy.getByTestId('tab-liquidity').within(() => {
|
||||
cy.get('[col-id="party.id"]').eq(1).should('not.be.empty');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Console - market summary - live env', { tags: '@live' }, () => {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {
|
||||
getId,
|
||||
matchFilter,
|
||||
liquidityProvisionsDataProvider,
|
||||
LiquidityTable,
|
||||
lpAggregatedDataProvider,
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
useNetworkParams,
|
||||
updateGridData,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import {
|
||||
AsyncRenderer,
|
||||
Tab,
|
||||
@@ -26,19 +25,18 @@ import {
|
||||
Indicator,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { memo, useCallback, useEffect, useRef, useState } from 'react';
|
||||
|
||||
import { Header, HeaderStat, HeaderTitle } from '../../components/header';
|
||||
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import type { IGetRowsParams } from 'ag-grid-community';
|
||||
|
||||
import type { LiquidityProvisionData } from '@vegaprotocol/liquidity';
|
||||
import type { LiquidityProvisionData, Filter } from '@vegaprotocol/liquidity';
|
||||
import { Link, useParams } from 'react-router-dom';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
|
||||
import { useMarket, useStaticMarketData } from '@vegaprotocol/market-list';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
|
||||
const enum LiquidityTabs {
|
||||
Active = 'active',
|
||||
@@ -67,8 +65,10 @@ const useReloadLiquidityData = (marketId: string | undefined) => {
|
||||
|
||||
export const LiquidityContainer = ({
|
||||
marketId,
|
||||
filter,
|
||||
}: {
|
||||
marketId: string | undefined;
|
||||
filter?: Filter;
|
||||
}) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const { data: market } = useMarket(marketId);
|
||||
@@ -87,7 +87,7 @@ export const LiquidityContainer = ({
|
||||
const { data, loading, error } = useDataProvider({
|
||||
dataProvider: lpAggregatedDataProvider,
|
||||
update,
|
||||
variables: { marketId: marketId || '' },
|
||||
variables: { marketId: marketId || '', filter },
|
||||
skip: !marketId,
|
||||
});
|
||||
|
||||
@@ -216,178 +216,56 @@ const LiquidityViewHeader = memo(({ marketId }: { marketId?: string }) => {
|
||||
});
|
||||
LiquidityViewHeader.displayName = 'LiquidityViewHeader';
|
||||
|
||||
const filterLiquidities = (
|
||||
tab: string,
|
||||
liquidities?: LiquidityProvisionData[] | null,
|
||||
pubKey?: string | null
|
||||
) => {
|
||||
switch (tab) {
|
||||
case LiquidityTabs.MyLiquidityProvision:
|
||||
return pubKey
|
||||
? (liquidities || []).filter((e) => e.party.id === pubKey)
|
||||
: [];
|
||||
break;
|
||||
case LiquidityTabs.Active:
|
||||
return (liquidities || []).filter(
|
||||
(e) => e.status === Schema.LiquidityProvisionStatus.STATUS_ACTIVE
|
||||
);
|
||||
case LiquidityTabs.Inactive:
|
||||
return (liquidities || []).filter(
|
||||
(e) => e.status !== Schema.LiquidityProvisionStatus.STATUS_ACTIVE
|
||||
);
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
||||
export const LiquidityViewContainer = ({
|
||||
marketId,
|
||||
}: {
|
||||
marketId: string | undefined;
|
||||
}) => {
|
||||
const [tab, setTab] = useState('');
|
||||
const [tab, setTab] = useState<string | undefined>(undefined);
|
||||
const { pubKey } = useVegaWallet();
|
||||
const [liquidityProviders, setLiquidityProviders] = useState<
|
||||
LiquidityProvisionData[] | null
|
||||
>();
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const { data: market } = useMarket(marketId);
|
||||
const dataRef = useRef<LiquidityProvisionData[] | null>(null);
|
||||
|
||||
// To be removed when liquidityProvision subscriptions are working
|
||||
useReloadLiquidityData(marketId);
|
||||
|
||||
const update = useCallback(
|
||||
({ data }: { data: LiquidityProvisionData[] | null }) => {
|
||||
if (!dataRef.current) {
|
||||
setLiquidityProviders(data);
|
||||
dataRef.current = data;
|
||||
}
|
||||
if (!gridRef.current?.api) {
|
||||
return false;
|
||||
}
|
||||
const updateRows: LiquidityProvisionData[] = [];
|
||||
const addRows: LiquidityProvisionData[] = [];
|
||||
if (gridRef.current?.api?.getModel().getType() === 'infinite') {
|
||||
dataRef.current = data;
|
||||
gridRef.current.api.refreshInfiniteCache();
|
||||
} else {
|
||||
const filteredData = filterLiquidities(tab, data, pubKey as string);
|
||||
filteredData?.forEach((d) => {
|
||||
const rowNode = gridRef.current?.api?.getRowNode(getId(d));
|
||||
if (rowNode) {
|
||||
if (!isEqual(rowNode.data, d)) {
|
||||
updateRows.push(d);
|
||||
}
|
||||
} else {
|
||||
addRows.push(d);
|
||||
}
|
||||
});
|
||||
gridRef.current?.api?.applyTransaction({
|
||||
update: updateRows,
|
||||
add: addRows,
|
||||
addIndex: 0,
|
||||
});
|
||||
}
|
||||
return true;
|
||||
},
|
||||
[gridRef, tab, pubKey]
|
||||
);
|
||||
|
||||
const { loading, error } = useDataProvider({
|
||||
const { data } = useDataProvider({
|
||||
dataProvider: lpAggregatedDataProvider,
|
||||
update,
|
||||
skipUpdates: true,
|
||||
variables: { marketId: marketId || '' },
|
||||
skip: !marketId,
|
||||
});
|
||||
const assetDecimalPlaces =
|
||||
market?.tradableInstrument.instrument.product.settlementAsset.decimals || 0;
|
||||
const symbol =
|
||||
market?.tradableInstrument.instrument.product.settlementAsset.symbol;
|
||||
|
||||
const { params } = useNetworkParams([
|
||||
NetworkParams.market_liquidity_stakeToCcyVolume,
|
||||
NetworkParams.market_liquidity_targetstake_triggering_ratio,
|
||||
]);
|
||||
const stakeToCcyVolume = params.market_liquidity_stakeToCcyVolume;
|
||||
const myLpEdges = useMemo(
|
||||
() =>
|
||||
filterLiquidities(
|
||||
LiquidityTabs.MyLiquidityProvision,
|
||||
liquidityProviders,
|
||||
pubKey
|
||||
),
|
||||
[liquidityProviders, pubKey]
|
||||
);
|
||||
const activeEdges = useMemo(
|
||||
() => filterLiquidities(LiquidityTabs.Active, liquidityProviders),
|
||||
[liquidityProviders]
|
||||
);
|
||||
const inactiveEdges = useMemo(
|
||||
() => filterLiquidities(LiquidityTabs.Inactive, liquidityProviders),
|
||||
[liquidityProviders]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (tab) {
|
||||
return;
|
||||
if (data) {
|
||||
if (pubKey && data.some((lp) => matchFilter({ partyId: pubKey }, lp))) {
|
||||
setTab(LiquidityTabs.MyLiquidityProvision);
|
||||
return;
|
||||
}
|
||||
if (data.some((lp) => matchFilter({ active: true }, lp))) {
|
||||
setTab(LiquidityTabs.Active);
|
||||
return;
|
||||
}
|
||||
setTab(LiquidityTabs.Inactive);
|
||||
}
|
||||
let initialTab = LiquidityTabs.Active;
|
||||
if (myLpEdges.length > 0) {
|
||||
initialTab = LiquidityTabs.MyLiquidityProvision;
|
||||
}
|
||||
if (activeEdges?.length) {
|
||||
initialTab = LiquidityTabs.Active;
|
||||
} else if (inactiveEdges.length > 0) {
|
||||
initialTab = LiquidityTabs.Inactive;
|
||||
}
|
||||
setTab(initialTab);
|
||||
}, [tab, myLpEdges?.length, activeEdges?.length, inactiveEdges?.length]);
|
||||
}, [data, pubKey]);
|
||||
|
||||
return (
|
||||
<AsyncRenderer loading={loading} error={error} data={liquidityProviders}>
|
||||
<div className="h-full grid grid-rows-[min-content_1fr]">
|
||||
<LiquidityViewHeader marketId={marketId} />
|
||||
<Tabs value={tab} onValueChange={setTab}>
|
||||
<Tab
|
||||
id={LiquidityTabs.MyLiquidityProvision}
|
||||
name={t('My liquidity provision')}
|
||||
hidden={!pubKey}
|
||||
>
|
||||
{myLpEdges && (
|
||||
<LiquidityTable
|
||||
ref={gridRef}
|
||||
rowData={myLpEdges}
|
||||
symbol={symbol}
|
||||
stakeToCcyVolume={stakeToCcyVolume}
|
||||
assetDecimalPlaces={assetDecimalPlaces}
|
||||
/>
|
||||
)}
|
||||
</Tab>
|
||||
<Tab id={LiquidityTabs.Active} name={t('Active')}>
|
||||
{activeEdges && (
|
||||
<LiquidityTable
|
||||
ref={gridRef}
|
||||
rowData={activeEdges}
|
||||
symbol={symbol}
|
||||
assetDecimalPlaces={assetDecimalPlaces}
|
||||
stakeToCcyVolume={stakeToCcyVolume}
|
||||
/>
|
||||
)}
|
||||
</Tab>
|
||||
<Tab id={LiquidityTabs.Inactive} name={t('Inactive')}>
|
||||
{inactiveEdges && (
|
||||
<LiquidityTable
|
||||
ref={gridRef}
|
||||
rowData={inactiveEdges}
|
||||
symbol={symbol}
|
||||
assetDecimalPlaces={assetDecimalPlaces}
|
||||
stakeToCcyVolume={stakeToCcyVolume}
|
||||
/>
|
||||
)}
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
</AsyncRenderer>
|
||||
<div className="h-full grid grid-rows-[min-content_1fr]">
|
||||
<LiquidityViewHeader marketId={marketId} />
|
||||
<Tabs value={tab || LiquidityTabs.Active} onValueChange={setTab}>
|
||||
<Tab
|
||||
id={LiquidityTabs.MyLiquidityProvision}
|
||||
name={t('My liquidity provision')}
|
||||
hidden={!pubKey}
|
||||
>
|
||||
<LiquidityContainer
|
||||
marketId={marketId}
|
||||
filter={{ partyId: pubKey || undefined }}
|
||||
/>
|
||||
</Tab>
|
||||
<Tab id={LiquidityTabs.Active} name={t('Active')}>
|
||||
<LiquidityContainer marketId={marketId} filter={{ active: true }} />
|
||||
</Tab>
|
||||
<Tab id={LiquidityTabs.Inactive} name={t('Inactive')}>
|
||||
<LiquidityContainer marketId={marketId} filter={{ active: false }} />
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -474,13 +474,16 @@ const VegaTxCompleteToastsContent = ({ tx }: VegaTxToastContentProps) => {
|
||||
}
|
||||
|
||||
if (tx.order && tx.order.rejectionReason) {
|
||||
const rejectionReason = getRejectionReason(tx.order) || ' ';
|
||||
const rejectionReason =
|
||||
getRejectionReason(tx.order) || tx.order.rejectionReason || '';
|
||||
return (
|
||||
<>
|
||||
<ToastHeading>{t('Order rejected')}</ToastHeading>
|
||||
{rejectionReason ? (
|
||||
{rejectionReason || tx.order.rejectionReason ? (
|
||||
<p>
|
||||
{t('Your order has been rejected because: %s', [rejectionReason])}
|
||||
{t('Your order has been rejected because: %s', [
|
||||
rejectionReason || tx.order.rejectionReason,
|
||||
])}
|
||||
</p>
|
||||
) : (
|
||||
<p>{t('Your order has been rejected.')}</p>
|
||||
@@ -579,7 +582,7 @@ const VegaTxErrorToastContent = ({ tx }: VegaTxToastContentProps) => {
|
||||
if (orderRejection) {
|
||||
label = t('Order rejected');
|
||||
errorMessage = t('Your order has been rejected because: %s', [
|
||||
orderRejection,
|
||||
orderRejection || tx.order?.rejectionReason || ' ',
|
||||
]);
|
||||
}
|
||||
if (walletError) {
|
||||
@@ -646,7 +649,11 @@ export const useVegaTransactionToasts = () => {
|
||||
|
||||
// Transaction can be successful but the order can be rejected by the network
|
||||
const intent =
|
||||
tx.order && [OrderStatus.STATUS_REJECTED].includes(tx.order.status)
|
||||
(tx.order &&
|
||||
[OrderStatus.STATUS_REJECTED, OrderStatus.STATUS_STOPPED].includes(
|
||||
tx.order.status
|
||||
)) ||
|
||||
tx.order?.rejectionReason
|
||||
? Intent.Danger
|
||||
: intentMap[tx.status];
|
||||
|
||||
|
||||
+15
-3
@@ -1,10 +1,22 @@
|
||||
#!/bin/sh -eux
|
||||
#!/bin/bash -ex
|
||||
|
||||
export PATH="/app/node_modules/.bin:$PATH"
|
||||
|
||||
flags="--network-timeout 100000 --pure-lockfile"
|
||||
|
||||
if [[ ! -z "${ENV_NAME}" ]]; then
|
||||
flags="--env=${ENV_NAME} $flags"
|
||||
fi
|
||||
|
||||
if [ "${APP}" = "trading" ]; then
|
||||
yarn nx export ${APP} --network-timeout 100000 --pure-lockfile
|
||||
yarn nx export ${APP} $flags
|
||||
mv /app/dist/apps/trading/exported/ /app/tmp
|
||||
rm -rf /app/dist/apps/trading
|
||||
mv /app/tmp /app/dist/apps/trading
|
||||
else
|
||||
yarn nx build ${APP} --network-timeout 100000 --pure-lockfile
|
||||
yarn nx build ${APP} $flags
|
||||
fi
|
||||
|
||||
env_vars_file="/app/dist/apps/${APP}/.env"
|
||||
# make sure there are no exposed .env files
|
||||
rm $env_vars_file || echo "No env vars file"
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# Recreate config file
|
||||
env_file=/usr/share/nginx/html/assets/env-config.js
|
||||
mkdir -p $(dirname $env_file)
|
||||
rm -rf $env_file || echo "no file to delete"
|
||||
touch $env_file
|
||||
|
||||
env_vars_file=/usr/share/nginx/html/.env
|
||||
sed -i '/^#/d' $env_vars_file # remove comment lines
|
||||
sed -i '/^$/d' $env_vars_file # remove empty lines
|
||||
|
||||
# Add assignment
|
||||
echo "window._env_ = {" >> $env_file
|
||||
|
||||
# Read each line in .env file
|
||||
# Each line represents key=value pairs
|
||||
while read -r line || [[ -n "$line" ]];
|
||||
do
|
||||
# Split env variables by character `=`
|
||||
if printf '%s\n' "$line" | grep -q -e '='; then
|
||||
varname=$(printf '%s\n' "$line" | sed -e 's/=.*//')
|
||||
varvalue=$(printf '%s\n' "$line" | sed -e 's/^[^=]*=//')
|
||||
fi
|
||||
|
||||
# Read value of current variable if exists as Environment variable
|
||||
value=$(printf '%s\n' "${!varname}")
|
||||
# Otherwise use value from .env file
|
||||
[[ -z $value ]] && value=${varvalue}
|
||||
|
||||
# Append configuration property to JS file if non-empty
|
||||
if [ ! -z "$varname" ]; then
|
||||
echo " $varname: \"$value\"," >> $env_file
|
||||
fi
|
||||
done < $env_vars_file
|
||||
|
||||
rm $env_vars_file
|
||||
|
||||
echo "}" >> $env_file
|
||||
|
||||
# start serving
|
||||
nginx -g 'daemon off;'
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||
import classnames from 'classnames';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { OrderSubmissionBody } from '@vegaprotocol/wallet';
|
||||
import type { Market, MarketData } from '@vegaprotocol/market-list';
|
||||
@@ -11,9 +12,12 @@ interface DealTicketFeeDetailsProps {
|
||||
order: OrderSubmissionBody['orderSubmission'];
|
||||
market: Market;
|
||||
marketData: MarketData;
|
||||
margin: string;
|
||||
totalMargin: string;
|
||||
balance: string;
|
||||
currentInitialMargin?: string;
|
||||
currentMaintenanceMargin?: string;
|
||||
estimatedInitialMargin: string;
|
||||
estimatedTotalInitialMargin: string;
|
||||
marginAccountBalance: string;
|
||||
generalAccountBalance: string;
|
||||
}
|
||||
|
||||
export interface DealTicketFeeDetailProps {
|
||||
@@ -45,23 +49,22 @@ export const DealTicketFeeDetails = ({
|
||||
order,
|
||||
market,
|
||||
marketData,
|
||||
margin,
|
||||
totalMargin,
|
||||
balance,
|
||||
...args
|
||||
}: DealTicketFeeDetailsProps) => {
|
||||
const feeDetails = useFeeDealTicketDetails(order, market, marketData);
|
||||
const details = getFeeDetailsValues({
|
||||
...feeDetails,
|
||||
margin,
|
||||
totalMargin,
|
||||
balance,
|
||||
...args,
|
||||
});
|
||||
return (
|
||||
<div>
|
||||
{details.map(({ label, value, labelDescription, symbol }) => (
|
||||
{details.map(({ label, value, labelDescription, symbol, indent }) => (
|
||||
<div
|
||||
key={typeof label === 'string' ? label : 'value-dropdown'}
|
||||
className="text-xs mt-2 flex justify-between items-center gap-4 flex-wrap"
|
||||
className={classnames(
|
||||
'text-xs mt-2 flex justify-between items-center gap-4 flex-wrap',
|
||||
{ 'ml-2': indent }
|
||||
)}
|
||||
>
|
||||
<div>
|
||||
<Tooltip description={labelDescription}>
|
||||
|
||||
@@ -107,7 +107,7 @@ describe('DealTicket', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should use local storage state for initial values reduceOnly and postOnly', () => {
|
||||
it('should set values for a non-persistent reduce only order and disable post only checkbox', () => {
|
||||
const expectedOrder = {
|
||||
marketId: market.id,
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
@@ -115,7 +115,7 @@ describe('DealTicket', () => {
|
||||
size: '0.1',
|
||||
price: '300.22',
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_IOC,
|
||||
persist: true,
|
||||
persist: false,
|
||||
reduceOnly: true,
|
||||
postOnly: false,
|
||||
};
|
||||
@@ -149,6 +149,58 @@ describe('DealTicket', () => {
|
||||
expect(screen.getByTestId('order-price')).toHaveDisplayValue(
|
||||
expectedOrder.price
|
||||
);
|
||||
expect(screen.getByTestId('post-only')).toBeDisabled();
|
||||
expect(screen.getByTestId('reduce-only')).toBeEnabled();
|
||||
expect(screen.getByTestId('reduce-only')).toBeChecked();
|
||||
expect(screen.getByTestId('post-only')).not.toBeChecked();
|
||||
});
|
||||
|
||||
it('should set values for a persistent post only order and disable reduce only checkbox', () => {
|
||||
const expectedOrder = {
|
||||
marketId: market.id,
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
side: Schema.Side.SIDE_SELL,
|
||||
size: '0.1',
|
||||
price: '300.22',
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
|
||||
persist: true,
|
||||
reduceOnly: false,
|
||||
postOnly: true,
|
||||
};
|
||||
|
||||
useOrderStore.setState({
|
||||
orders: {
|
||||
[expectedOrder.marketId]: expectedOrder,
|
||||
},
|
||||
});
|
||||
|
||||
render(generateJsx());
|
||||
|
||||
// Assert correct defaults are used from store
|
||||
expect(
|
||||
screen
|
||||
.getByTestId(`order-type-${Schema.OrderType.TYPE_LIMIT}`)
|
||||
.querySelector('input')
|
||||
).toBeChecked();
|
||||
expect(
|
||||
screen.queryByTestId('order-side-SIDE_SELL')?.querySelector('input')
|
||||
).toBeChecked();
|
||||
expect(
|
||||
screen.queryByTestId('order-side-SIDE_BUY')?.querySelector('input')
|
||||
).not.toBeChecked();
|
||||
expect(screen.getByTestId('order-size')).toHaveDisplayValue(
|
||||
expectedOrder.size
|
||||
);
|
||||
expect(screen.getByTestId('order-tif')).toHaveValue(
|
||||
expectedOrder.timeInForce
|
||||
);
|
||||
expect(screen.getByTestId('order-price')).toHaveDisplayValue(
|
||||
expectedOrder.price
|
||||
);
|
||||
expect(screen.getByTestId('post-only')).toBeEnabled();
|
||||
expect(screen.getByTestId('reduce-only')).toBeDisabled();
|
||||
expect(screen.getByTestId('post-only')).toBeChecked();
|
||||
expect(screen.getByTestId('reduce-only')).not.toBeChecked();
|
||||
});
|
||||
|
||||
it('handles TIF select box dependent on order type', async () => {
|
||||
|
||||
@@ -44,6 +44,9 @@ import {
|
||||
|
||||
import { OrderTimeInForce, OrderType } from '@vegaprotocol/types';
|
||||
import { useOrderForm } from '../../hooks/use-order-form';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
|
||||
import { marketMarginDataProvider } from '@vegaprotocol/positions';
|
||||
|
||||
export interface DealTicketProps {
|
||||
market: Market;
|
||||
@@ -103,6 +106,12 @@ export const DealTicket = ({
|
||||
|
||||
const { margin, totalMargin } = useInitialMargin(market.id, normalizedOrder);
|
||||
|
||||
const { data: currentMargins } = useDataProvider({
|
||||
dataProvider: marketMarginDataProvider,
|
||||
variables: { marketId: market.id, partyId: pubKey || '' },
|
||||
skip: !pubKey,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (!pubKey) {
|
||||
setError('summary', {
|
||||
@@ -158,6 +167,16 @@ export const DealTicket = ({
|
||||
return disabled;
|
||||
}, [order]);
|
||||
|
||||
const disableReduceOnlyCheckbox = useMemo(() => {
|
||||
const disabled = order
|
||||
? ![
|
||||
Schema.OrderTimeInForce.TIME_IN_FORCE_IOC,
|
||||
Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
].includes(order.timeInForce)
|
||||
: true;
|
||||
return disabled;
|
||||
}, [order]);
|
||||
|
||||
const onSubmit = useCallback(
|
||||
(order: OrderSubmission) => {
|
||||
const now = new Date().getTime();
|
||||
@@ -202,8 +221,18 @@ export const DealTicket = ({
|
||||
if (type === OrderType.TYPE_NETWORK) return;
|
||||
update({
|
||||
type,
|
||||
// when changing type also update the tif to what was last used of new type
|
||||
// when changing type also update the TIF to what was last used of new type
|
||||
timeInForce: lastTIF[type] || order.timeInForce,
|
||||
postOnly:
|
||||
type === OrderType.TYPE_MARKET ? false : order.postOnly,
|
||||
reduceOnly:
|
||||
type === OrderType.TYPE_LIMIT &&
|
||||
![
|
||||
OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
OrderTimeInForce.TIME_IN_FORCE_IOC,
|
||||
].includes(lastTIF[type] || order.timeInForce)
|
||||
? false
|
||||
: order.postOnly,
|
||||
expiresAt: undefined,
|
||||
});
|
||||
clearErrors('expiresAt');
|
||||
@@ -251,8 +280,23 @@ export const DealTicket = ({
|
||||
value={order.timeInForce}
|
||||
orderType={order.type}
|
||||
onSelect={(timeInForce) => {
|
||||
update({ timeInForce, postOnly: false, reduceOnly: false });
|
||||
// Set tif value for the given order type, so that when switching
|
||||
// Reset post only and reduce only when changing TIF
|
||||
update({
|
||||
timeInForce,
|
||||
postOnly: [
|
||||
OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
OrderTimeInForce.TIME_IN_FORCE_IOC,
|
||||
].includes(timeInForce)
|
||||
? false
|
||||
: order.postOnly,
|
||||
reduceOnly: ![
|
||||
OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
OrderTimeInForce.TIME_IN_FORCE_IOC,
|
||||
].includes(timeInForce)
|
||||
? false
|
||||
: order.reduceOnly,
|
||||
});
|
||||
// Set TIF value for the given order type, so that when switching
|
||||
// types we know the last used TIF for the given order type
|
||||
setLastTIF((curr) => ({
|
||||
...curr,
|
||||
@@ -327,6 +371,7 @@ export const DealTicket = ({
|
||||
<Checkbox
|
||||
name="reduce-only"
|
||||
checked={order.reduceOnly}
|
||||
disabled={disableReduceOnlyCheckbox}
|
||||
onCheckedChange={() => {
|
||||
update({ postOnly: false, reduceOnly: !order.reduceOnly });
|
||||
}}
|
||||
@@ -334,9 +379,13 @@ export const DealTicket = ({
|
||||
<Tooltip
|
||||
description={
|
||||
<span>
|
||||
{t(
|
||||
'"Reduce only" will ensure that this order will not increase the size of an open position. When the order is matched, it will only trade enough volume to bring your open volume towards 0 but never change the direction of your position. If applied to a limit order that is not instantly filled, the order will be stopped.'
|
||||
)}
|
||||
{disableReduceOnlyCheckbox
|
||||
? t(
|
||||
'"Reduce only" can be used only with non-persistent orders, such as "Fill or Kill" or "Immediate or Cancel".'
|
||||
)
|
||||
: t(
|
||||
'"Reduce only" will ensure that this order will not increase the size of an open position. When the order is matched, it will only trade enough volume to bring your open volume towards 0 but never change the direction of your position. If applied to a limit order that is not instantly filled, the order will be stopped.'
|
||||
)}
|
||||
</span>
|
||||
}
|
||||
>
|
||||
@@ -367,9 +416,12 @@ export const DealTicket = ({
|
||||
order={normalizedOrder}
|
||||
market={market}
|
||||
marketData={marketData}
|
||||
margin={margin}
|
||||
totalMargin={totalMargin}
|
||||
balance={marginAccountBalance}
|
||||
estimatedInitialMargin={margin}
|
||||
estimatedTotalInitialMargin={totalMargin}
|
||||
currentInitialMargin={currentMargins?.initialLevel}
|
||||
currentMaintenanceMargin={currentMargins?.maintenanceLevel}
|
||||
marginAccountBalance={marginAccountBalance}
|
||||
generalAccountBalance={generalAccountBalance}
|
||||
/>
|
||||
</form>
|
||||
</TinyScroll>
|
||||
|
||||
@@ -10,12 +10,36 @@ export const EST_MARGIN_TOOLTIP_TEXT = (settlementAsset: string) =>
|
||||
export const EST_TOTAL_MARGIN_TOOLTIP_TEXT = t(
|
||||
'Estimated total margin that will cover open position, active orders and this order.'
|
||||
);
|
||||
export const MARGIN_ACCOUNT_TOOLTIP_TEXT = t('Margin account balance');
|
||||
export const MARGIN_ACCOUNT_TOOLTIP_TEXT = t('Margin account balance.');
|
||||
export const MARGIN_DIFF_TOOLTIP_TEXT = (settlementAsset: string) =>
|
||||
t(
|
||||
"The additional margin required for your new position (taking into account volume and open orders), compared to your current margin. Measured in the market's settlement asset (%s).",
|
||||
[settlementAsset]
|
||||
);
|
||||
export const DEDUCTION_FROM_COLLATERAL_TOOLTIP_TEXT = (
|
||||
settlementAsset: string
|
||||
) =>
|
||||
t(
|
||||
'To cover the required margin, this amount will be drawn from your general (%s) account.',
|
||||
[settlementAsset]
|
||||
);
|
||||
|
||||
export const TOTAL_MARGIN_AVAILABLE = (
|
||||
generalAccountBalance: string,
|
||||
marginAccountBalance: string,
|
||||
marginMaintenance: string,
|
||||
settlementAsset: string
|
||||
) =>
|
||||
t(
|
||||
'Total margin available = general %s balance (%s) + margin balance (%s) - maintenance level (%s).',
|
||||
[
|
||||
settlementAsset,
|
||||
`${generalAccountBalance} ${settlementAsset}`,
|
||||
`${marginAccountBalance} ${settlementAsset}`,
|
||||
`${marginMaintenance} ${settlementAsset}`,
|
||||
]
|
||||
);
|
||||
|
||||
export const CONTRACTS_MARGIN_TOOLTIP_TEXT = t(
|
||||
'The number of contracts determines how many units of the futures contract to buy or sell. For example, this is similar to buying one share of a listed company. The value of 1 contract is equivalent to the price of the contract. For example, if the current price is $50, then one contract is worth $50.'
|
||||
);
|
||||
@@ -40,7 +64,7 @@ export const EST_SLIPPAGE = t(
|
||||
);
|
||||
|
||||
export const ERROR_SIZE_DECIMAL = t(
|
||||
'The size field accepts up to X decimal places'
|
||||
'The size field accepts up to X decimal places.'
|
||||
);
|
||||
|
||||
export enum MarketModeValidationType {
|
||||
|
||||
@@ -15,6 +15,8 @@ import {
|
||||
NOTIONAL_SIZE_TOOLTIP_TEXT,
|
||||
MARGIN_ACCOUNT_TOOLTIP_TEXT,
|
||||
MARGIN_DIFF_TOOLTIP_TEXT,
|
||||
DEDUCTION_FROM_COLLATERAL_TOOLTIP_TEXT,
|
||||
TOTAL_MARGIN_AVAILABLE,
|
||||
} from '../constants';
|
||||
import { useOrderCloseOut } from './use-order-closeout';
|
||||
import { useMarketAccountBalance } from '@vegaprotocol/accounts';
|
||||
@@ -85,24 +87,32 @@ export const useFeeDealTicketDetails = (
|
||||
};
|
||||
|
||||
export interface FeeDetails {
|
||||
balance: string;
|
||||
generalAccountBalance?: string;
|
||||
marginAccountBalance?: string;
|
||||
market: Market;
|
||||
assetSymbol: string;
|
||||
notionalSize: string | null;
|
||||
estCloseOut: string | null;
|
||||
estimateOrder: EstimateOrderQuery['estimateOrder'] | undefined;
|
||||
margin: string;
|
||||
totalMargin: string;
|
||||
estimatedInitialMargin: string;
|
||||
estimatedTotalInitialMargin: string;
|
||||
currentInitialMargin?: string;
|
||||
currentMaintenanceMargin?: string;
|
||||
}
|
||||
|
||||
export const getFeeDetailsValues = ({
|
||||
balance,
|
||||
marginAccountBalance,
|
||||
generalAccountBalance,
|
||||
assetSymbol,
|
||||
estimateOrder,
|
||||
market,
|
||||
notionalSize,
|
||||
totalMargin,
|
||||
estimatedTotalInitialMargin,
|
||||
currentInitialMargin,
|
||||
currentMaintenanceMargin,
|
||||
}: FeeDetails) => {
|
||||
const totalBalance =
|
||||
BigInt(generalAccountBalance || '0') + BigInt(marginAccountBalance || '0');
|
||||
const assetDecimals =
|
||||
market.tradableInstrument.instrument.product.settlementAsset.decimals;
|
||||
const formatValueWithMarketDp = (
|
||||
@@ -123,7 +133,8 @@ export const getFeeDetailsValues = ({
|
||||
label: string;
|
||||
value?: string | null;
|
||||
symbol: string;
|
||||
labelDescription: React.ReactNode;
|
||||
indent?: boolean;
|
||||
labelDescription?: React.ReactNode;
|
||||
}[] = [
|
||||
{
|
||||
label: t('Notional'),
|
||||
@@ -153,38 +164,64 @@ export const getFeeDetailsValues = ({
|
||||
),
|
||||
symbol: assetSymbol,
|
||||
},
|
||||
/*
|
||||
{
|
||||
label: t('Initial margin'),
|
||||
value: margin && `~${formatValueWithAssetDp(margin)}`,
|
||||
symbol: assetSymbol,
|
||||
labelDescription: EST_MARGIN_TOOLTIP_TEXT(assetSymbol),
|
||||
},
|
||||
*/
|
||||
{
|
||||
label: t('Margin required'),
|
||||
value: `~${formatValueWithAssetDp(
|
||||
balance
|
||||
? (BigInt(totalMargin) - BigInt(balance)).toString()
|
||||
: totalMargin
|
||||
currentInitialMargin
|
||||
? (
|
||||
BigInt(estimatedTotalInitialMargin) - BigInt(currentInitialMargin)
|
||||
).toString()
|
||||
: estimatedTotalInitialMargin
|
||||
)}`,
|
||||
symbol: assetSymbol,
|
||||
labelDescription: MARGIN_DIFF_TOOLTIP_TEXT(assetSymbol),
|
||||
},
|
||||
];
|
||||
if (balance) {
|
||||
if (totalBalance) {
|
||||
const totalMarginAvailable = (
|
||||
currentMaintenanceMargin
|
||||
? totalBalance - BigInt(currentMaintenanceMargin)
|
||||
: totalBalance
|
||||
).toString();
|
||||
|
||||
details.push({
|
||||
indent: true,
|
||||
label: t('Total margin available'),
|
||||
value: `~${formatValueWithAssetDp(totalMarginAvailable)}`,
|
||||
symbol: assetSymbol,
|
||||
labelDescription: TOTAL_MARGIN_AVAILABLE(
|
||||
formatValueWithAssetDp(generalAccountBalance),
|
||||
formatValueWithAssetDp(marginAccountBalance),
|
||||
formatValueWithAssetDp(currentMaintenanceMargin),
|
||||
assetSymbol
|
||||
),
|
||||
});
|
||||
|
||||
if (marginAccountBalance) {
|
||||
const deductionFromCollateral =
|
||||
BigInt(estimatedTotalInitialMargin) - BigInt(marginAccountBalance);
|
||||
|
||||
details.push({
|
||||
indent: true,
|
||||
label: t('Deduction from collateral'),
|
||||
value: `~${formatValueWithAssetDp(
|
||||
deductionFromCollateral > 0 ? deductionFromCollateral.toString() : '0'
|
||||
)}`,
|
||||
symbol: assetSymbol,
|
||||
labelDescription: DEDUCTION_FROM_COLLATERAL_TOOLTIP_TEXT(assetSymbol),
|
||||
});
|
||||
}
|
||||
|
||||
details.push({
|
||||
label: t('Projected margin'),
|
||||
value: `~${formatValueWithAssetDp(totalMargin)}`,
|
||||
value: `~${formatValueWithAssetDp(estimatedTotalInitialMargin)}`,
|
||||
symbol: assetSymbol,
|
||||
labelDescription: EST_TOTAL_MARGIN_TOOLTIP_TEXT,
|
||||
});
|
||||
}
|
||||
details.push({
|
||||
label: t('Current margin allocation'),
|
||||
value: balance
|
||||
? `~${formatValueWithAssetDp(balance)}`
|
||||
: `${formatValueWithAssetDp(balance)}`,
|
||||
value: `${formatValueWithAssetDp(marginAccountBalance)}`,
|
||||
symbol: assetSymbol,
|
||||
labelDescription: MARGIN_ACCOUNT_TOOLTIP_TEXT,
|
||||
});
|
||||
|
||||
@@ -65,5 +65,11 @@ export const useInitialMargin = (
|
||||
sellMargin > buyMargin ? sellMargin.toString() : buyMargin.toString();
|
||||
}
|
||||
|
||||
return useMemo(() => ({ totalMargin, margin }), [totalMargin, margin]);
|
||||
return useMemo(
|
||||
() => ({
|
||||
totalMargin,
|
||||
margin,
|
||||
}),
|
||||
[totalMargin, margin]
|
||||
);
|
||||
};
|
||||
|
||||
@@ -140,8 +140,6 @@ describe('Network switcher', () => {
|
||||
[Networks.STAGNET3]: 'https://stag3.net',
|
||||
[Networks.DEVNET]: 'https://dev.net',
|
||||
[Networks.STAGNET1]: 'https://stag1.net',
|
||||
[Networks.SANDBOX]: 'https://sandbox.net',
|
||||
[Networks.MIRROR]: 'https://mirror.net',
|
||||
};
|
||||
// @ts-ignore Typescript doesn't know about this module being mocked
|
||||
useEnvironment.mockImplementation(() => ({
|
||||
@@ -181,8 +179,6 @@ describe('Network switcher', () => {
|
||||
[Networks.STAGNET3]: 'https://stag3.net',
|
||||
[Networks.DEVNET]: 'https://dev.net',
|
||||
[Networks.STAGNET1]: 'https://stag1.net',
|
||||
[Networks.SANDBOX]: 'https://sandbox.net',
|
||||
[Networks.MIRROR]: 'https://mirror.net',
|
||||
};
|
||||
// @ts-ignore Typescript doesn't know about this module being mocked
|
||||
useEnvironment.mockImplementation(() => ({
|
||||
@@ -215,8 +211,6 @@ describe('Network switcher', () => {
|
||||
[Networks.STAGNET3]: 'https://stag3.net',
|
||||
[Networks.DEVNET]: 'https://dev.net',
|
||||
[Networks.STAGNET1]: 'https://stag1.net',
|
||||
[Networks.SANDBOX]: 'https://sandbox.net',
|
||||
[Networks.MIRROR]: 'https://mirror.net',
|
||||
};
|
||||
// @ts-ignore Typescript doesn't know about this module being mocked
|
||||
useEnvironment.mockImplementation(() => ({
|
||||
|
||||
@@ -17,12 +17,10 @@ export const envNameMapping: Record<Networks, string> = {
|
||||
[Networks.VALIDATOR_TESTNET]: t('VALIDATOR_TESTNET'),
|
||||
[Networks.CUSTOM]: t('Custom'),
|
||||
[Networks.DEVNET]: t('Devnet'),
|
||||
[Networks.SANDBOX]: t('Sandbox'),
|
||||
[Networks.STAGNET1]: t('Stagnet'),
|
||||
[Networks.STAGNET3]: t('Stagnet3'),
|
||||
[Networks.TESTNET]: t('Fairground testnet'),
|
||||
[Networks.MAINNET]: t('Mainnet'),
|
||||
[Networks.MIRROR]: t('Mainnet mirror'),
|
||||
};
|
||||
|
||||
export const envTriggerMapping: Record<Networks, string> = {
|
||||
@@ -32,7 +30,6 @@ export const envTriggerMapping: Record<Networks, string> = {
|
||||
|
||||
export const envDescriptionMapping: Record<Networks, string> = {
|
||||
[Networks.CUSTOM]: '',
|
||||
[Networks.SANDBOX]: t('A playground test environment'),
|
||||
[Networks.VALIDATOR_TESTNET]: t('The validator deployed testnet'),
|
||||
[Networks.DEVNET]: t('The latest Vega code auto-deployed'),
|
||||
[Networks.STAGNET1]: t('A release candidate for the staging environment'),
|
||||
@@ -41,9 +38,6 @@ export const envDescriptionMapping: Record<Networks, string> = {
|
||||
'Public testnet run by the Vega team, often used for incentives'
|
||||
),
|
||||
[Networks.MAINNET]: t('The vega mainnet'),
|
||||
[Networks.MIRROR]: t(
|
||||
'A mirror of the mainnet environment running on an Ethereum test network'
|
||||
),
|
||||
};
|
||||
|
||||
const standardNetworkKeys = [Networks.MAINNET, Networks.TESTNET];
|
||||
|
||||
@@ -3,7 +3,7 @@ import { useCallback } from 'react';
|
||||
import { Networks } from '../types';
|
||||
import { useEnvironment } from './use-environment';
|
||||
|
||||
type Net = Exclude<Networks, 'CUSTOM' | 'SANDBOX'>;
|
||||
type Net = Exclude<Networks, 'CUSTOM'>;
|
||||
export enum DApp {
|
||||
Explorer = 'Explorer',
|
||||
Console = 'Console',
|
||||
@@ -21,7 +21,6 @@ const EmptyLinks: DAppLinks = {
|
||||
[Networks.STAGNET3]: '',
|
||||
[Networks.TESTNET]: '',
|
||||
[Networks.MAINNET]: '',
|
||||
[Networks.MIRROR]: '',
|
||||
};
|
||||
|
||||
const ExplorerLinks = {
|
||||
@@ -61,7 +60,7 @@ export const useLinks = (dapp: DApp, network?: Net) => {
|
||||
};
|
||||
|
||||
let net = network || VEGA_ENV;
|
||||
if (net === Networks.CUSTOM || net === Networks.SANDBOX) {
|
||||
if (net === Networks.CUSTOM) {
|
||||
net = Networks.TESTNET;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,13 +5,11 @@ import type { envSchema } from './utils/validate-environment';
|
||||
export enum Networks {
|
||||
VALIDATOR_TESTNET = 'VALIDATOR_TESTNET',
|
||||
CUSTOM = 'CUSTOM',
|
||||
SANDBOX = 'SANDBOX',
|
||||
TESTNET = 'TESTNET',
|
||||
STAGNET1 = 'STAGNET1',
|
||||
STAGNET3 = 'STAGNET3',
|
||||
DEVNET = 'DEVNET',
|
||||
MAINNET = 'MAINNET',
|
||||
MIRROR = 'MIRROR',
|
||||
}
|
||||
export type Environment = z.infer<typeof envSchema>;
|
||||
export type Configuration = z.infer<typeof tomlConfigSchema>;
|
||||
|
||||
@@ -3,13 +3,11 @@ import z from 'zod';
|
||||
export enum Networks {
|
||||
VALIDATOR_TESTNET = 'VALIDATOR_TESTNET',
|
||||
CUSTOM = 'CUSTOM',
|
||||
SANDBOX = 'SANDBOX',
|
||||
TESTNET = 'TESTNET',
|
||||
STAGNET1 = 'STAGNET1',
|
||||
STAGNET3 = 'STAGNET3',
|
||||
DEVNET = 'DEVNET',
|
||||
MAINNET = 'MAINNET',
|
||||
MIRROR = 'MIRROR',
|
||||
}
|
||||
|
||||
const schemaObject = {
|
||||
|
||||
@@ -7,7 +7,6 @@ import type { Trade } from './fills-data-provider';
|
||||
|
||||
import { FillsTable, getFeesBreakdown } from './fills-table';
|
||||
import { generateFill } from './test-helpers';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
describe('FillsTable', () => {
|
||||
let defaultFill: PartialDeep<Trade>;
|
||||
@@ -37,11 +36,7 @@ describe('FillsTable', () => {
|
||||
|
||||
it('correct columns are rendered', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<FillsTable partyId="party-id" rowData={[generateFill()]} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
render(<FillsTable partyId="party-id" rowData={[generateFill()]} />);
|
||||
});
|
||||
|
||||
const headers = screen.getAllByRole('columnheader');
|
||||
@@ -72,11 +67,7 @@ describe('FillsTable', () => {
|
||||
liquidityFee: '2',
|
||||
},
|
||||
});
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<FillsTable partyId={partyId} rowData={[{ ...buyerFill }]} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
render(<FillsTable partyId={partyId} rowData={[{ ...buyerFill }]} />);
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
const expectedValues = [
|
||||
buyerFill.market?.tradableInstrument.instrument.name || '',
|
||||
@@ -109,11 +100,7 @@ describe('FillsTable', () => {
|
||||
liquidityFee: '1',
|
||||
},
|
||||
});
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<FillsTable partyId={partyId} rowData={[buyerFill]} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
render(<FillsTable partyId={partyId} rowData={[buyerFill]} />);
|
||||
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
const expectedValues = [
|
||||
@@ -142,9 +129,7 @@ describe('FillsTable', () => {
|
||||
aggressor: Schema.Side.SIDE_SELL,
|
||||
});
|
||||
const { rerender } = render(
|
||||
<MemoryRouter>
|
||||
<FillsTable partyId={partyId} rowData={[takerFill]} />
|
||||
</MemoryRouter>
|
||||
<FillsTable partyId={partyId} rowData={[takerFill]} />
|
||||
);
|
||||
expect(
|
||||
screen
|
||||
@@ -158,11 +143,7 @@ describe('FillsTable', () => {
|
||||
},
|
||||
aggressor: Schema.Side.SIDE_BUY,
|
||||
});
|
||||
rerender(
|
||||
<MemoryRouter>
|
||||
<FillsTable partyId={partyId} rowData={[makerFill]} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
rerender(<FillsTable partyId={partyId} rowData={[makerFill]} />);
|
||||
|
||||
expect(
|
||||
screen
|
||||
@@ -179,11 +160,7 @@ describe('FillsTable', () => {
|
||||
},
|
||||
aggressor: Schema.Side.SIDE_SELL,
|
||||
});
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<FillsTable partyId={partyId} rowData={[takerFill]} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
render(<FillsTable partyId={partyId} rowData={[takerFill]} />);
|
||||
|
||||
const feeCell = screen
|
||||
.getAllByRole('gridcell')
|
||||
|
||||
@@ -103,13 +103,3 @@ query LiquidityProviderFeeShare($marketId: ID!) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
subscription LiquidityProviderFeeShareUpdate($marketId: ID!) {
|
||||
marketsData(marketIds: [$marketId]) {
|
||||
liquidityProviderFeeShare {
|
||||
partyId
|
||||
equityLikeShare
|
||||
averageEntryValuation
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-42
@@ -36,13 +36,6 @@ export type LiquidityProviderFeeShareQueryVariables = Types.Exact<{
|
||||
|
||||
export type LiquidityProviderFeeShareQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, data?: { __typename?: 'MarketData', market: { __typename?: 'Market', id: string }, liquidityProviderFeeShare?: Array<{ __typename?: 'LiquidityProviderFeeShare', equityLikeShare: string, averageEntryValuation: string, party: { __typename?: 'Party', id: string } }> | null } | null } | null };
|
||||
|
||||
export type LiquidityProviderFeeShareUpdateSubscriptionVariables = Types.Exact<{
|
||||
marketId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type LiquidityProviderFeeShareUpdateSubscription = { __typename?: 'Subscription', marketsData: Array<{ __typename?: 'ObservableMarketData', liquidityProviderFeeShare?: Array<{ __typename?: 'ObservableLiquidityProviderFeeShare', partyId: string, equityLikeShare: string, averageEntryValuation: string }> | null }> };
|
||||
|
||||
export const LiquidityProvisionFieldsFragmentDoc = gql`
|
||||
fragment LiquidityProvisionFields on LiquidityProvision {
|
||||
party {
|
||||
@@ -256,38 +249,4 @@ export function useLiquidityProviderFeeShareLazyQuery(baseOptions?: Apollo.LazyQ
|
||||
}
|
||||
export type LiquidityProviderFeeShareQueryHookResult = ReturnType<typeof useLiquidityProviderFeeShareQuery>;
|
||||
export type LiquidityProviderFeeShareLazyQueryHookResult = ReturnType<typeof useLiquidityProviderFeeShareLazyQuery>;
|
||||
export type LiquidityProviderFeeShareQueryResult = Apollo.QueryResult<LiquidityProviderFeeShareQuery, LiquidityProviderFeeShareQueryVariables>;
|
||||
export const LiquidityProviderFeeShareUpdateDocument = gql`
|
||||
subscription LiquidityProviderFeeShareUpdate($marketId: ID!) {
|
||||
marketsData(marketIds: [$marketId]) {
|
||||
liquidityProviderFeeShare {
|
||||
partyId
|
||||
equityLikeShare
|
||||
averageEntryValuation
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useLiquidityProviderFeeShareUpdateSubscription__
|
||||
*
|
||||
* To run a query within a React component, call `useLiquidityProviderFeeShareUpdateSubscription` and pass it any options that fit your needs.
|
||||
* When your component renders, `useLiquidityProviderFeeShareUpdateSubscription` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the subscription, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useLiquidityProviderFeeShareUpdateSubscription({
|
||||
* variables: {
|
||||
* marketId: // value for 'marketId'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useLiquidityProviderFeeShareUpdateSubscription(baseOptions: Apollo.SubscriptionHookOptions<LiquidityProviderFeeShareUpdateSubscription, LiquidityProviderFeeShareUpdateSubscriptionVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useSubscription<LiquidityProviderFeeShareUpdateSubscription, LiquidityProviderFeeShareUpdateSubscriptionVariables>(LiquidityProviderFeeShareUpdateDocument, options);
|
||||
}
|
||||
export type LiquidityProviderFeeShareUpdateSubscriptionHookResult = ReturnType<typeof useLiquidityProviderFeeShareUpdateSubscription>;
|
||||
export type LiquidityProviderFeeShareUpdateSubscriptionResult = Apollo.SubscriptionResult<LiquidityProviderFeeShareUpdateSubscription>;
|
||||
export type LiquidityProviderFeeShareQueryResult = Apollo.QueryResult<LiquidityProviderFeeShareQuery, LiquidityProviderFeeShareQueryVariables>;
|
||||
@@ -6,7 +6,6 @@ import produce from 'immer';
|
||||
|
||||
import {
|
||||
LiquidityProviderFeeShareDocument,
|
||||
LiquidityProviderFeeShareUpdateDocument,
|
||||
LiquidityProvisionsDocument,
|
||||
LiquidityProvisionsUpdateDocument,
|
||||
MarketLpDocument,
|
||||
@@ -18,7 +17,6 @@ import type {
|
||||
LiquidityProviderFeeShareFieldsFragment,
|
||||
LiquidityProviderFeeShareQuery,
|
||||
LiquidityProviderFeeShareQueryVariables,
|
||||
LiquidityProviderFeeShareUpdateSubscription,
|
||||
LiquidityProvisionFieldsFragment,
|
||||
LiquidityProvisionsQuery,
|
||||
LiquidityProvisionsQueryVariables,
|
||||
@@ -115,73 +113,94 @@ export const marketLiquidityDataProvider = makeDataProvider<
|
||||
export const liquidityFeeShareDataProvider = makeDataProvider<
|
||||
LiquidityProviderFeeShareQuery,
|
||||
LiquidityProviderFeeShareFieldsFragment[],
|
||||
LiquidityProviderFeeShareUpdateSubscription,
|
||||
LiquidityProviderFeeShareUpdateSubscription['marketsData'][0]['liquidityProviderFeeShare'],
|
||||
never,
|
||||
never,
|
||||
LiquidityProviderFeeShareQueryVariables
|
||||
>({
|
||||
query: LiquidityProviderFeeShareDocument,
|
||||
subscriptionQuery: LiquidityProviderFeeShareUpdateDocument,
|
||||
update: (
|
||||
data: LiquidityProviderFeeShareFieldsFragment[] | null,
|
||||
deltas: LiquidityProviderFeeShareUpdateSubscription['marketsData'][0]['liquidityProviderFeeShare']
|
||||
) => {
|
||||
return produce(data || [], (draft) => {
|
||||
deltas?.forEach((delta) => {
|
||||
const id = delta.partyId;
|
||||
const index = draft.findIndex((a) => a.party.id === id);
|
||||
if (index !== -1) {
|
||||
draft[index].equityLikeShare = delta.equityLikeShare;
|
||||
draft[index].averageEntryValuation = delta.averageEntryValuation;
|
||||
} else {
|
||||
draft.unshift({
|
||||
equityLikeShare: delta.equityLikeShare,
|
||||
averageEntryValuation: delta.averageEntryValuation,
|
||||
party: {
|
||||
id: delta.partyId,
|
||||
},
|
||||
// TODO add accounts connection to the subscription
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
getData: (data) => {
|
||||
return data?.market?.data?.liquidityProviderFeeShare || [];
|
||||
},
|
||||
getDelta: (subscriptionData: LiquidityProviderFeeShareUpdateSubscription) => {
|
||||
return subscriptionData.marketsData[0].liquidityProviderFeeShare;
|
||||
},
|
||||
});
|
||||
|
||||
export type Filter = { partyId?: string; active?: boolean };
|
||||
|
||||
export const lpAggregatedDataProvider = makeDerivedDataProvider<
|
||||
ReturnType<typeof getLiquidityProvision>,
|
||||
LiquidityProvisionData[],
|
||||
never,
|
||||
MarketLpQueryVariables
|
||||
MarketLpQueryVariables & { filter?: Filter }
|
||||
>(
|
||||
[
|
||||
liquidityProvisionsDataProvider,
|
||||
marketLiquidityDataProvider,
|
||||
liquidityFeeShareDataProvider,
|
||||
(callback, client, variables) =>
|
||||
liquidityProvisionsDataProvider(callback, client, {
|
||||
marketId: variables.marketId,
|
||||
}),
|
||||
(callback, client, variables) =>
|
||||
marketLiquidityDataProvider(callback, client, {
|
||||
marketId: variables.marketId,
|
||||
}),
|
||||
(callback, client, variables) =>
|
||||
liquidityFeeShareDataProvider(callback, client, {
|
||||
marketId: variables.marketId,
|
||||
}),
|
||||
],
|
||||
([
|
||||
liquidityProvisions,
|
||||
marketLiquidity,
|
||||
liquidityFeeShare,
|
||||
]): LiquidityProvisionData[] => {
|
||||
(
|
||||
[liquidityProvisions, marketLiquidity, liquidityFeeShare],
|
||||
{ filter }
|
||||
): LiquidityProvisionData[] => {
|
||||
return getLiquidityProvision(
|
||||
liquidityProvisions,
|
||||
marketLiquidity,
|
||||
liquidityFeeShare
|
||||
liquidityFeeShare,
|
||||
filter
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export const matchFilter = (
|
||||
filter: Filter,
|
||||
lp: LiquidityProvisionFieldsFragment
|
||||
) => {
|
||||
if (filter.partyId && lp.party.id !== filter.partyId) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
filter.active === true &&
|
||||
lp.status !== Schema.LiquidityProvisionStatus.STATUS_ACTIVE
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
filter.active === false &&
|
||||
lp.status === Schema.LiquidityProvisionStatus.STATUS_ACTIVE
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
export const getLiquidityProvision = (
|
||||
liquidityProvisions: LiquidityProvisionFieldsFragment[],
|
||||
marketLiquidity: MarketLpQuery,
|
||||
liquidityFeeShare: LiquidityProviderFeeShareFieldsFragment[]
|
||||
liquidityFeeShare: LiquidityProviderFeeShareFieldsFragment[],
|
||||
filter?: Filter
|
||||
): LiquidityProvisionData[] => {
|
||||
return liquidityProvisions
|
||||
.filter((lp) => {
|
||||
if (
|
||||
![
|
||||
Schema.LiquidityProvisionStatus.STATUS_ACTIVE,
|
||||
Schema.LiquidityProvisionStatus.STATUS_UNDEPLOYED,
|
||||
Schema.LiquidityProvisionStatus.STATUS_PENDING,
|
||||
].includes(lp.status)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (filter && !matchFilter(filter, lp)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.map((lp) => {
|
||||
const market = marketLiquidity?.market;
|
||||
const feeShare = liquidityFeeShare.find(
|
||||
@@ -210,14 +229,7 @@ export const getLiquidityProvision = (
|
||||
.decimals,
|
||||
balance,
|
||||
};
|
||||
})
|
||||
.filter((e) =>
|
||||
[
|
||||
Schema.LiquidityProvisionStatus.STATUS_ACTIVE,
|
||||
Schema.LiquidityProvisionStatus.STATUS_UNDEPLOYED,
|
||||
Schema.LiquidityProvisionStatus.STATUS_PENDING,
|
||||
].includes(e.status)
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
export interface LiquidityProvisionData
|
||||
|
||||
@@ -14,6 +14,8 @@ fragment OrderFields on Order {
|
||||
expiresAt
|
||||
createdAt
|
||||
updatedAt
|
||||
postOnly
|
||||
reduceOnly
|
||||
liquidityProvision {
|
||||
__typename
|
||||
}
|
||||
@@ -30,12 +32,16 @@ query OrderById($orderId: ID!) {
|
||||
|
||||
query Orders(
|
||||
$partyId: ID!
|
||||
$marketIds: [ID!]
|
||||
$pagination: Pagination
|
||||
$filter: OrderByMarketIdsFilter
|
||||
$filter: OrderFilter
|
||||
) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
ordersConnection(pagination: $pagination, filter: $filter) {
|
||||
ordersConnection(
|
||||
pagination: $pagination
|
||||
filter: { order: $filter, marketIds: $marketIds }
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
...OrderFields
|
||||
@@ -72,8 +78,8 @@ fragment OrderUpdateFields on OrderUpdate {
|
||||
}
|
||||
}
|
||||
|
||||
subscription OrdersUpdate($partyId: ID!) {
|
||||
orders(filter: { partyIds: [$partyId] }) {
|
||||
subscription OrdersUpdate($partyId: ID!, $marketIds: [ID!]) {
|
||||
orders(filter: { partyIds: [$partyId], marketIds: $marketIds }) {
|
||||
...OrderUpdateFields
|
||||
}
|
||||
}
|
||||
|
||||
+17
-8
@@ -3,28 +3,30 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type OrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder' } | null };
|
||||
export type OrderFieldsFragment = { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, postOnly?: boolean | null, reduceOnly?: boolean | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder' } | null };
|
||||
|
||||
export type OrderByIdQueryVariables = Types.Exact<{
|
||||
orderId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type OrderByIdQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder' } | null } };
|
||||
export type OrderByIdQuery = { __typename?: 'Query', orderByID: { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, postOnly?: boolean | null, reduceOnly?: boolean | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder' } | null } };
|
||||
|
||||
export type OrdersQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
marketIds?: Types.InputMaybe<Array<Types.Scalars['ID']> | Types.Scalars['ID']>;
|
||||
pagination?: Types.InputMaybe<Types.Pagination>;
|
||||
filter?: Types.InputMaybe<Types.OrderByMarketIdsFilter>;
|
||||
filter?: Types.InputMaybe<Types.OrderFilter>;
|
||||
}>;
|
||||
|
||||
|
||||
export type OrdersQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, ordersConnection?: { __typename?: 'OrderConnection', edges?: Array<{ __typename?: 'OrderEdge', cursor?: string | null, node: { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder' } | null } }> | null, pageInfo?: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } | null } | null } | null };
|
||||
export type OrdersQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, ordersConnection?: { __typename?: 'OrderConnection', edges?: Array<{ __typename?: 'OrderEdge', cursor?: string | null, node: { __typename?: 'Order', id: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, postOnly?: boolean | null, reduceOnly?: boolean | null, market: { __typename?: 'Market', id: string }, liquidityProvision?: { __typename: 'LiquidityProvision' } | null, peggedOrder?: { __typename: 'PeggedOrder' } | null } }> | null, pageInfo?: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } | null } | null } | null };
|
||||
|
||||
export type OrderUpdateFieldsFragment = { __typename?: 'OrderUpdate', id: string, marketId: string, type?: Types.OrderType | null, side: Types.Side, size: string, status: Types.OrderStatus, rejectionReason?: Types.OrderRejectionReason | null, price: string, timeInForce: Types.OrderTimeInForce, remaining: string, expiresAt?: any | null, createdAt: any, updatedAt?: any | null, liquidityProvisionId?: string | null, peggedOrder?: { __typename: 'PeggedOrder' } | null };
|
||||
|
||||
export type OrdersUpdateSubscriptionVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
marketIds?: Types.InputMaybe<Array<Types.Scalars['ID']> | Types.Scalars['ID']>;
|
||||
}>;
|
||||
|
||||
|
||||
@@ -47,6 +49,8 @@ export const OrderFieldsFragmentDoc = gql`
|
||||
expiresAt
|
||||
createdAt
|
||||
updatedAt
|
||||
postOnly
|
||||
reduceOnly
|
||||
liquidityProvision {
|
||||
__typename
|
||||
}
|
||||
@@ -112,10 +116,13 @@ export type OrderByIdQueryHookResult = ReturnType<typeof useOrderByIdQuery>;
|
||||
export type OrderByIdLazyQueryHookResult = ReturnType<typeof useOrderByIdLazyQuery>;
|
||||
export type OrderByIdQueryResult = Apollo.QueryResult<OrderByIdQuery, OrderByIdQueryVariables>;
|
||||
export const OrdersDocument = gql`
|
||||
query Orders($partyId: ID!, $pagination: Pagination, $filter: OrderByMarketIdsFilter) {
|
||||
query Orders($partyId: ID!, $marketIds: [ID!], $pagination: Pagination, $filter: OrderFilter) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
ordersConnection(pagination: $pagination, filter: $filter) {
|
||||
ordersConnection(
|
||||
pagination: $pagination
|
||||
filter: {order: $filter, marketIds: $marketIds}
|
||||
) {
|
||||
edges {
|
||||
node {
|
||||
...OrderFields
|
||||
@@ -146,6 +153,7 @@ export const OrdersDocument = gql`
|
||||
* const { data, loading, error } = useOrdersQuery({
|
||||
* variables: {
|
||||
* partyId: // value for 'partyId'
|
||||
* marketIds: // value for 'marketIds'
|
||||
* pagination: // value for 'pagination'
|
||||
* filter: // value for 'filter'
|
||||
* },
|
||||
@@ -163,8 +171,8 @@ export type OrdersQueryHookResult = ReturnType<typeof useOrdersQuery>;
|
||||
export type OrdersLazyQueryHookResult = ReturnType<typeof useOrdersLazyQuery>;
|
||||
export type OrdersQueryResult = Apollo.QueryResult<OrdersQuery, OrdersQueryVariables>;
|
||||
export const OrdersUpdateDocument = gql`
|
||||
subscription OrdersUpdate($partyId: ID!) {
|
||||
orders(filter: {partyIds: [$partyId]}) {
|
||||
subscription OrdersUpdate($partyId: ID!, $marketIds: [ID!]) {
|
||||
orders(filter: {partyIds: [$partyId], marketIds: $marketIds}) {
|
||||
...OrderUpdateFields
|
||||
}
|
||||
}
|
||||
@@ -183,6 +191,7 @@ export const OrdersUpdateDocument = gql`
|
||||
* const { data, loading, error } = useOrdersUpdateSubscription({
|
||||
* variables: {
|
||||
* partyId: // value for 'partyId'
|
||||
* marketIds: // value for 'marketIds'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
|
||||
@@ -112,9 +112,7 @@ describe('order data provider', () => {
|
||||
const updatedData = update(data, delta, () => null, {
|
||||
partyId: '0x123',
|
||||
filter: {
|
||||
order: {
|
||||
dateRange: { end: new Date('2022-02-01').toISOString() },
|
||||
},
|
||||
dateRange: { end: new Date('2022-02-01').toISOString() },
|
||||
},
|
||||
});
|
||||
expect(
|
||||
|
||||
@@ -35,45 +35,40 @@ const orderMatchFilters = (
|
||||
return true;
|
||||
}
|
||||
if (
|
||||
variables?.filter?.order?.status &&
|
||||
!(order.status && variables.filter.order.status.includes(order.status))
|
||||
variables?.filter?.status &&
|
||||
!(order.status && variables.filter.status.includes(order.status))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
variables?.filter?.order?.types &&
|
||||
!(order.type && variables.filter.order.types.includes(order.type))
|
||||
variables?.filter?.types &&
|
||||
!(order.type && variables.filter.types.includes(order.type))
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
variables?.filter?.order?.timeInForce &&
|
||||
!variables.filter.order.timeInForce.includes(order.timeInForce)
|
||||
variables?.filter?.timeInForce &&
|
||||
!variables.filter.timeInForce.includes(order.timeInForce)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
variables?.filter?.order?.excludeLiquidity &&
|
||||
order.liquidityProvisionId
|
||||
) {
|
||||
if (variables?.filter?.excludeLiquidity && order.liquidityProvisionId) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
variables?.filter?.order?.dateRange?.start &&
|
||||
variables?.filter?.dateRange?.start &&
|
||||
!(
|
||||
(order.updatedAt || order.createdAt) &&
|
||||
variables.filter.order.dateRange.start <
|
||||
(order.updatedAt || order.createdAt)
|
||||
variables.filter.dateRange.start < (order.updatedAt || order.createdAt)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
variables?.filter?.order?.dateRange?.end &&
|
||||
variables?.filter?.dateRange?.end &&
|
||||
!(
|
||||
(order.updatedAt || order.createdAt) &&
|
||||
variables.filter.order.dateRange.end >
|
||||
(order.updatedAt || order.createdAt)
|
||||
variables.filter.dateRange.end > (order.updatedAt || order.createdAt)
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
@@ -243,18 +238,17 @@ export const hasActiveOrderProvider = makeDerivedDataProvider<
|
||||
{ partyId: string; marketId?: string }
|
||||
>(
|
||||
[
|
||||
(callback, client, variables) =>
|
||||
(callback, client, { partyId, marketId }) =>
|
||||
hasActiveOrderProviderInternal(callback, client, {
|
||||
marketIds: marketId ? [marketId] : undefined,
|
||||
filter: {
|
||||
order: {
|
||||
status: [OrderStatus.STATUS_ACTIVE],
|
||||
excludeLiquidity: true,
|
||||
},
|
||||
status: [OrderStatus.STATUS_ACTIVE],
|
||||
excludeLiquidity: true,
|
||||
},
|
||||
pagination: {
|
||||
first: 1,
|
||||
},
|
||||
...variables,
|
||||
partyId,
|
||||
} as OrdersQueryVariables),
|
||||
],
|
||||
(parts) => parts[0]
|
||||
|
||||
@@ -72,12 +72,10 @@ export const useOrderListData = ({
|
||||
const allVars: OrdersQueryVariables & OrdersUpdateSubscriptionVariables = {
|
||||
partyId,
|
||||
filter: {
|
||||
order: {
|
||||
dateRange: filter?.updatedAt?.value,
|
||||
status: filter?.status?.value,
|
||||
timeInForce: filter?.timeInForce?.value,
|
||||
types: filter?.type?.value,
|
||||
},
|
||||
dateRange: filter?.updatedAt?.value,
|
||||
status: filter?.status?.value,
|
||||
timeInForce: filter?.timeInForce?.value,
|
||||
types: filter?.type?.value,
|
||||
},
|
||||
pagination: {
|
||||
first: 1000,
|
||||
|
||||
@@ -13,7 +13,6 @@ import {
|
||||
limitOrder,
|
||||
marketOrder,
|
||||
} from '../mocks/generate-orders';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
// Mock theme switcher to get around inconsistent mocking of zustand
|
||||
// stores
|
||||
@@ -37,11 +36,9 @@ const generateJsx = (
|
||||
) => {
|
||||
return (
|
||||
<MockedProvider>
|
||||
<MemoryRouter>
|
||||
<VegaWalletContext.Provider value={context as VegaWalletContextShape}>
|
||||
<OrderListTable {...defaultProps} {...props} />
|
||||
</VegaWalletContext.Provider>
|
||||
</MemoryRouter>
|
||||
<VegaWalletContext.Provider value={context as VegaWalletContextShape}>
|
||||
<OrderListTable {...defaultProps} {...props} />
|
||||
</VegaWalletContext.Provider>
|
||||
</MockedProvider>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -129,8 +129,9 @@ export const OrderListTable = memo(
|
||||
}: VegaValueFormatterParams<Order, 'status'>) => {
|
||||
if (data?.rejectionReason && value) {
|
||||
return `${Schema.OrderStatusMapping[value]}: ${
|
||||
data?.rejectionReason &&
|
||||
Schema.OrderRejectionReasonMapping[data.rejectionReason]
|
||||
(data?.rejectionReason &&
|
||||
Schema.OrderRejectionReasonMapping[data.rejectionReason]) ||
|
||||
data?.rejectionReason
|
||||
}`;
|
||||
}
|
||||
return value ? Schema.OrderStatusMapping[value] : '';
|
||||
@@ -218,7 +219,14 @@ export const OrderListTable = memo(
|
||||
return `${Schema.OrderTimeInForceMapping[value]}: ${expiry}`;
|
||||
}
|
||||
|
||||
return value ? Schema.OrderTimeInForceMapping[value] : '';
|
||||
const tifLabel = value
|
||||
? Schema.OrderTimeInForceMapping[value]
|
||||
: '';
|
||||
const label = `${tifLabel}${
|
||||
data?.postOnly ? t('. Post Only') : ''
|
||||
}${data?.reduceOnly ? t('. Reduce only') : ''}`;
|
||||
|
||||
return label;
|
||||
}}
|
||||
minWidth={150}
|
||||
/>
|
||||
|
||||
@@ -53,14 +53,12 @@ export const useActiveOrdersVolumeAndMargin = (
|
||||
update,
|
||||
variables: {
|
||||
partyId: partyId || '',
|
||||
marketIds: [marketId],
|
||||
filter: {
|
||||
marketIds: [marketId],
|
||||
order: {
|
||||
status: [
|
||||
OrderStatus.STATUS_ACTIVE,
|
||||
OrderStatus.STATUS_PARTIALLY_FILLED,
|
||||
],
|
||||
},
|
||||
status: [
|
||||
OrderStatus.STATUS_ACTIVE,
|
||||
OrderStatus.STATUS_PARTIALLY_FILLED,
|
||||
],
|
||||
},
|
||||
},
|
||||
skip: !partyId,
|
||||
|
||||
@@ -4,7 +4,6 @@ export * from './lib/positions-data-providers';
|
||||
export * from './lib/margin-data-provider';
|
||||
export * from './lib/margin-calculator';
|
||||
export * from './lib/positions-table';
|
||||
export * from './lib/use-close-position';
|
||||
export * from './lib/use-market-margin';
|
||||
export * from './lib/use-market-position-open-volume';
|
||||
export * from './lib/use-open-volume';
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import type { OrderFieldsFragment } from '@vegaprotocol/orders';
|
||||
import { truncateByChars } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||
import type { TransactionResult, VegaTxState } from '@vegaprotocol/wallet';
|
||||
import type { ClosingOrder as IClosingOrder } from '../use-close-position';
|
||||
import { useRequestClosePositionData } from '../use-request-close-position-data';
|
||||
import { ClosingOrder } from './shared';
|
||||
|
||||
interface CompleteProps {
|
||||
partyId: string;
|
||||
transaction: VegaTxState;
|
||||
transactionResult?: TransactionResult;
|
||||
closingOrder?: IClosingOrder;
|
||||
closingOrderResult?: OrderFieldsFragment;
|
||||
}
|
||||
|
||||
export const Complete = ({
|
||||
partyId,
|
||||
transaction,
|
||||
transactionResult,
|
||||
closingOrder,
|
||||
closingOrderResult,
|
||||
}: CompleteProps) => {
|
||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||
|
||||
if (!transactionResult || !closingOrderResult) return null;
|
||||
|
||||
return (
|
||||
<>
|
||||
{closingOrderResult.status === Schema.OrderStatus.STATUS_FILLED &&
|
||||
transactionResult.status ? (
|
||||
<Success partyId={partyId} order={closingOrder} />
|
||||
) : (
|
||||
<Error
|
||||
transactionResult={transactionResult}
|
||||
closingOrderResult={closingOrderResult}
|
||||
/>
|
||||
)}
|
||||
{transaction.txHash && (
|
||||
<>
|
||||
<p className="font-semibold mt-4">{t('Transaction')}</p>
|
||||
<p>
|
||||
<Link
|
||||
href={`${VEGA_EXPLORER_URL}/txs/${transaction.txHash}`}
|
||||
target="_blank"
|
||||
>
|
||||
{truncateByChars(transaction.txHash)}
|
||||
</Link>
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const Success = ({
|
||||
partyId,
|
||||
order,
|
||||
}: {
|
||||
partyId: string;
|
||||
order?: IClosingOrder;
|
||||
}) => {
|
||||
const { market, marketData, orders } = useRequestClosePositionData(
|
||||
order?.marketId,
|
||||
partyId
|
||||
);
|
||||
|
||||
if (!market || !marketData || !orders) {
|
||||
return <div>{t('Loading...')}</div>;
|
||||
}
|
||||
|
||||
if (!order) {
|
||||
return (
|
||||
<div className="text-vega-pink">{t('Could retrieve closing order')}</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<h2 className="font-bold">{t('Position closed')}</h2>
|
||||
<ClosingOrder order={order} market={market} marketData={marketData} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const Error = ({
|
||||
transactionResult,
|
||||
closingOrderResult,
|
||||
}: {
|
||||
transactionResult: TransactionResult;
|
||||
closingOrderResult: OrderFieldsFragment;
|
||||
}) => {
|
||||
const reason =
|
||||
closingOrderResult.rejectionReason &&
|
||||
Schema.OrderRejectionReasonMapping[closingOrderResult.rejectionReason];
|
||||
return (
|
||||
<div className="text-vega-pink">
|
||||
{reason ? (
|
||||
<p>{reason}</p>
|
||||
) : (
|
||||
<p>
|
||||
{t('Transaction failed')}: {transactionResult.error}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -1,102 +0,0 @@
|
||||
import { render, screen, within } from '@testing-library/react';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import * as dataHook from '../use-request-close-position-data';
|
||||
import { Requested } from './requested';
|
||||
|
||||
jest.mock('./use-request-close-position-data');
|
||||
|
||||
describe('Close position dialog - Request', () => {
|
||||
const props = {
|
||||
partyId: 'party-id',
|
||||
order: {
|
||||
marketId: 'market-id',
|
||||
type: Schema.OrderType.TYPE_MARKET as const,
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK as const,
|
||||
side: Schema.Side.SIDE_BUY,
|
||||
size: '10',
|
||||
},
|
||||
};
|
||||
|
||||
it('loading state', async () => {
|
||||
jest.spyOn(dataHook, 'useRequestClosePositionData').mockReturnValue({
|
||||
loading: false,
|
||||
market: null,
|
||||
marketData: null,
|
||||
orders: [],
|
||||
});
|
||||
render(<Requested {...props} />);
|
||||
expect(screen.getByText('Loading...')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders message if no closing order found', async () => {
|
||||
const orders = [
|
||||
{
|
||||
size: '200',
|
||||
price: '999',
|
||||
side: Schema.Side.SIDE_BUY,
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
|
||||
},
|
||||
{
|
||||
size: '300',
|
||||
price: '888',
|
||||
side: Schema.Side.SIDE_SELL,
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
|
||||
},
|
||||
];
|
||||
jest.spyOn(dataHook, 'useRequestClosePositionData').mockReturnValue({
|
||||
market: {
|
||||
decimalPlaces: 2,
|
||||
positionDecimalPlaces: 2,
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
name: 'test market',
|
||||
product: {
|
||||
// @ts-ignore avoiding having to add every property on the type
|
||||
settlementAsset: {
|
||||
symbol: 'SYM',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
// @ts-ignore avoid all fields
|
||||
marketData: {
|
||||
markPrice: '100',
|
||||
},
|
||||
// @ts-ignore avoid all fields
|
||||
orders,
|
||||
});
|
||||
render(<Requested {...props} />);
|
||||
|
||||
// closing order
|
||||
const closingOrderHeader = screen.getByText('Position to be closed');
|
||||
const closingOrderTable = within(
|
||||
closingOrderHeader.nextElementSibling?.querySelector(
|
||||
'tbody'
|
||||
) as HTMLElement
|
||||
);
|
||||
const closingOrderRow = closingOrderTable.getAllByRole('row');
|
||||
expect(closingOrderRow[0].children[0]).toHaveTextContent('test market');
|
||||
expect(closingOrderRow[0].children[1]).toHaveTextContent('+0.1');
|
||||
expect(closingOrderRow[0].children[2]).toHaveTextContent('~1.00 SYM');
|
||||
|
||||
// orders
|
||||
const ordersHeading = screen.getByText('Orders to be closed');
|
||||
const ordersTable = within(
|
||||
ordersHeading.nextElementSibling?.querySelector('tbody') as HTMLElement
|
||||
);
|
||||
const orderRows = ordersTable.getAllByRole('row');
|
||||
expect(orderRows).toHaveLength(orders.length);
|
||||
expect(orderRows[0].children[0]).toHaveTextContent('+2');
|
||||
expect(orderRows[0].children[1]).toHaveTextContent('9.99 SYM');
|
||||
expect(orderRows[0].children[2]).toHaveTextContent(
|
||||
"Good 'til Cancelled (GTC)"
|
||||
);
|
||||
|
||||
expect(orderRows[1].children[0]).toHaveTextContent('-3');
|
||||
expect(orderRows[1].children[1]).toHaveTextContent('8.88 SYM');
|
||||
expect(orderRows[1].children[2]).toHaveTextContent(
|
||||
"Good 'til Cancelled (GTC)"
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,37 +0,0 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type { ClosingOrder as IClosingOrder } from '../use-close-position';
|
||||
import { useRequestClosePositionData } from '../use-request-close-position-data';
|
||||
import { ActiveOrders, ClosingOrder } from './shared';
|
||||
|
||||
export const Requested = ({
|
||||
order,
|
||||
partyId,
|
||||
}: {
|
||||
order?: IClosingOrder;
|
||||
partyId: string;
|
||||
}) => {
|
||||
const { market, marketData, orders, loading } = useRequestClosePositionData(
|
||||
order?.marketId,
|
||||
partyId
|
||||
);
|
||||
|
||||
if (loading || !market || !marketData || !orders) {
|
||||
return <div>{t('Loading...')}</div>;
|
||||
}
|
||||
|
||||
if (!order) {
|
||||
return (
|
||||
<div className="text-vega-pink">
|
||||
{t('Could not create closing order')}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2 className="font-bold">{t('Position to be closed')}</h2>
|
||||
<ClosingOrder order={order} market={market} marketData={marketData} />
|
||||
<ActiveOrders market={market} orders={orders} />
|
||||
</>
|
||||
);
|
||||
};
|
||||
@@ -1,114 +0,0 @@
|
||||
import type { MarketData, Market } from '@vegaprotocol/market-list';
|
||||
import type { Order } from '@vegaprotocol/orders';
|
||||
import { timeInForceLabel } from '@vegaprotocol/orders';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { Size } from '@vegaprotocol/react-helpers';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { ClosingOrder as IClosingOrder } from '../use-close-position';
|
||||
|
||||
export const ClosingOrder = ({
|
||||
order,
|
||||
market,
|
||||
marketData,
|
||||
}: {
|
||||
order: IClosingOrder;
|
||||
market: Market;
|
||||
marketData: MarketData;
|
||||
}) => {
|
||||
const asset = market.tradableInstrument.instrument.product.settlementAsset;
|
||||
const estimatedPrice =
|
||||
marketData && market
|
||||
? addDecimalsFormatNumber(marketData.markPrice, market.decimalPlaces)
|
||||
: '-';
|
||||
const size = market ? (
|
||||
<Size
|
||||
value={order.size}
|
||||
side={order.side}
|
||||
positionDecimalPlaces={market.positionDecimalPlaces}
|
||||
/>
|
||||
) : (
|
||||
'-'
|
||||
);
|
||||
|
||||
return (
|
||||
<BasicTable
|
||||
headers={[t('Market'), t('Amount'), t('Est price')]}
|
||||
rows={[
|
||||
[
|
||||
market.tradableInstrument.instrument.name,
|
||||
size,
|
||||
`~${estimatedPrice} ${asset?.symbol}`,
|
||||
],
|
||||
]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const ActiveOrders = ({
|
||||
market,
|
||||
orders,
|
||||
}: {
|
||||
market: Market;
|
||||
orders: Order[];
|
||||
}) => {
|
||||
const asset = market.tradableInstrument.instrument.product.settlementAsset;
|
||||
|
||||
if (!orders.length) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mt-4">
|
||||
<h2 className="font-bold">{t('Orders to be closed')}</h2>
|
||||
<BasicTable
|
||||
headers={[t('Amount'), t('Target price'), t('Time in force')]}
|
||||
rows={orders.map((o) => {
|
||||
return [
|
||||
<Size
|
||||
value={o.size}
|
||||
side={o.side}
|
||||
positionDecimalPlaces={market.positionDecimalPlaces}
|
||||
/>,
|
||||
`${addDecimalsFormatNumber(o.price, market.decimalPlaces)} ${
|
||||
asset.symbol
|
||||
}`,
|
||||
timeInForceLabel(o.timeInForce),
|
||||
];
|
||||
})}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
interface BasicTableProps {
|
||||
headers: ReactNode[];
|
||||
rows: ReactNode[][];
|
||||
}
|
||||
|
||||
const BasicTable = ({ headers, rows }: BasicTableProps) => {
|
||||
return (
|
||||
<table className="w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
{headers.map((h, i) => (
|
||||
<th key={i} className="text-left font-medium">
|
||||
{h}
|
||||
</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows.map((cells, i) => (
|
||||
<tr key={i}>
|
||||
{cells.map((c, i) => (
|
||||
<td key={i} className="align-top">
|
||||
{c}
|
||||
</td>
|
||||
))}
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
};
|
||||
@@ -349,16 +349,15 @@ export const volumeAndMarginProvider = makeDerivedDataProvider<
|
||||
PositionsQueryVariables & MarketDataQueryVariables
|
||||
>(
|
||||
[
|
||||
(callback, client, variables) =>
|
||||
(callback, client, { partyId, marketId }) =>
|
||||
ordersProvider(callback, client, {
|
||||
...variables,
|
||||
partyId,
|
||||
marketIds: [marketId],
|
||||
filter: {
|
||||
order: {
|
||||
status: [
|
||||
OrderStatus.STATUS_ACTIVE,
|
||||
OrderStatus.STATUS_PARTIALLY_FILLED,
|
||||
],
|
||||
},
|
||||
status: [
|
||||
OrderStatus.STATUS_ACTIVE,
|
||||
OrderStatus.STATUS_PARTIALLY_FILLED,
|
||||
],
|
||||
},
|
||||
}),
|
||||
(callback, client, variables) =>
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { useCallback, useEffect, useRef, useState } from 'react';
|
||||
import { useCallback, useRef, useState } from 'react';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import type { Position } from '../';
|
||||
import { usePositionsData, PositionsTable } from '../';
|
||||
import type { FilterChangedEvent } from 'ag-grid-community';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { useVegaTransactionStore } from '@vegaprotocol/wallet';
|
||||
@@ -23,8 +22,8 @@ export const PositionsManager = ({
|
||||
noBottomPlaceholder,
|
||||
}: PositionsManagerProps) => {
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
const [dataCount, setDataCount] = useState(0);
|
||||
const { data, error, loading, reload } = usePositionsData(partyId, gridRef);
|
||||
const [dataCount, setDataCount] = useState(data?.length ?? 0);
|
||||
const create = useVegaTransactionStore((store) => store.create);
|
||||
const onClose = ({
|
||||
marketId,
|
||||
@@ -67,10 +66,7 @@ export const PositionsManager = ({
|
||||
setId,
|
||||
disabled: noBottomPlaceholder,
|
||||
});
|
||||
useEffect(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, [data]);
|
||||
const onFilterChanged = useCallback((event: FilterChangedEvent) => {
|
||||
const updateRowCount = useCallback(() => {
|
||||
setDataCount(gridRef.current?.api?.getModel().getRowCount() ?? 0);
|
||||
}, []);
|
||||
return (
|
||||
@@ -83,7 +79,8 @@ export const PositionsManager = ({
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
isReadOnly={isReadOnly}
|
||||
onFilterChanged={onFilterChanged}
|
||||
onFilterChanged={updateRowCount}
|
||||
onRowDataUpdated={updateRowCount}
|
||||
{...bottomPlaceholderProps}
|
||||
/>
|
||||
<div className="pointer-events-none absolute inset-0">
|
||||
|
||||
@@ -6,7 +6,6 @@ import type { Position } from './positions-data-providers';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { PositionStatus, PositionStatusMapping } from '@vegaprotocol/types';
|
||||
import type { ICellRendererParams } from 'ag-grid-community';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
const singleRow: Position = {
|
||||
marketName: 'ETH/BTC (31 july 2022)',
|
||||
@@ -38,9 +37,7 @@ const singleRowData = [singleRow];
|
||||
it('should render successfully', async () => {
|
||||
await act(async () => {
|
||||
const { baseElement } = render(
|
||||
<MemoryRouter>
|
||||
<PositionsTable rowData={[]} isReadOnly={false} />
|
||||
</MemoryRouter>
|
||||
<PositionsTable rowData={[]} isReadOnly={false} />
|
||||
);
|
||||
expect(baseElement).toBeTruthy();
|
||||
});
|
||||
@@ -48,11 +45,7 @@ it('should render successfully', async () => {
|
||||
|
||||
it('render correct columns', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<PositionsTable rowData={singleRowData} isReadOnly={true} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
render(<PositionsTable rowData={singleRowData} isReadOnly={true} />);
|
||||
});
|
||||
|
||||
const headers = screen.getAllByRole('columnheader');
|
||||
@@ -76,11 +69,7 @@ it('render correct columns', async () => {
|
||||
|
||||
it('renders market name', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
render(<PositionsTable rowData={singleRowData} isReadOnly={false} />);
|
||||
});
|
||||
expect(screen.getByText('ETH/BTC (31 july 2022)')).toBeTruthy();
|
||||
});
|
||||
@@ -91,11 +80,7 @@ it('Does not fail if the market name does not match the split pattern', async ()
|
||||
Object.assign({}, singleRow, { marketName: breakingMarketName }),
|
||||
];
|
||||
await act(async () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<PositionsTable rowData={row} isReadOnly={false} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
render(<PositionsTable rowData={row} isReadOnly={false} />);
|
||||
});
|
||||
|
||||
expect(screen.getByText(breakingMarketName)).toBeTruthy();
|
||||
@@ -105,9 +90,7 @@ it('add color and sign to amount, displays positive notional value', async () =>
|
||||
let result: RenderResult;
|
||||
await act(async () => {
|
||||
result = render(
|
||||
<MemoryRouter>
|
||||
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||
</MemoryRouter>
|
||||
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||
);
|
||||
});
|
||||
let cells = screen.getAllByRole('gridcell');
|
||||
@@ -118,12 +101,10 @@ it('add color and sign to amount, displays positive notional value', async () =>
|
||||
expect(cells[1].textContent).toEqual('1,230.0');
|
||||
await act(async () => {
|
||||
result.rerender(
|
||||
<MemoryRouter>
|
||||
<PositionsTable
|
||||
rowData={[{ ...singleRow, openVolume: '-100' }]}
|
||||
isReadOnly={false}
|
||||
/>
|
||||
</MemoryRouter>
|
||||
<PositionsTable
|
||||
rowData={[{ ...singleRow, openVolume: '-100' }]}
|
||||
isReadOnly={false}
|
||||
/>
|
||||
);
|
||||
});
|
||||
cells = screen.getAllByRole('gridcell');
|
||||
@@ -137,9 +118,7 @@ it('displays mark price', async () => {
|
||||
let result: RenderResult;
|
||||
await act(async () => {
|
||||
result = render(
|
||||
<MemoryRouter>
|
||||
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||
</MemoryRouter>
|
||||
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||
);
|
||||
});
|
||||
|
||||
@@ -148,18 +127,16 @@ it('displays mark price', async () => {
|
||||
|
||||
await act(async () => {
|
||||
result.rerender(
|
||||
<MemoryRouter>
|
||||
<PositionsTable
|
||||
rowData={[
|
||||
{
|
||||
...singleRow,
|
||||
marketTradingMode:
|
||||
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
|
||||
},
|
||||
]}
|
||||
isReadOnly={false}
|
||||
/>
|
||||
</MemoryRouter>
|
||||
<PositionsTable
|
||||
rowData={[
|
||||
{
|
||||
...singleRow,
|
||||
marketTradingMode:
|
||||
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
|
||||
},
|
||||
]}
|
||||
isReadOnly={false}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -169,11 +146,7 @@ it('displays mark price', async () => {
|
||||
|
||||
it('displays leverage', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
render(<PositionsTable rowData={singleRowData} isReadOnly={false} />);
|
||||
});
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
expect(cells[6].textContent).toEqual('1.1');
|
||||
@@ -181,11 +154,7 @@ it('displays leverage', async () => {
|
||||
|
||||
it('displays allocated margin', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
render(<PositionsTable rowData={singleRowData} isReadOnly={false} />);
|
||||
});
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
const cell = cells[7];
|
||||
@@ -194,11 +163,7 @@ it('displays allocated margin', async () => {
|
||||
|
||||
it('displays realised and unrealised PNL', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<PositionsTable rowData={singleRowData} isReadOnly={false} />
|
||||
</MemoryRouter>
|
||||
);
|
||||
render(<PositionsTable rowData={singleRowData} isReadOnly={false} />);
|
||||
});
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
expect(cells[9].textContent).toEqual('4.56');
|
||||
@@ -207,15 +172,13 @@ it('displays realised and unrealised PNL', async () => {
|
||||
it('displays close button', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<PositionsTable
|
||||
rowData={singleRowData}
|
||||
onClose={() => {
|
||||
return;
|
||||
}}
|
||||
isReadOnly={false}
|
||||
/>
|
||||
</MemoryRouter>
|
||||
<PositionsTable
|
||||
rowData={singleRowData}
|
||||
onClose={() => {
|
||||
return;
|
||||
}}
|
||||
isReadOnly={false}
|
||||
/>
|
||||
);
|
||||
});
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
@@ -225,15 +188,13 @@ it('displays close button', async () => {
|
||||
it('do not display close button if openVolume is zero', async () => {
|
||||
await act(async () => {
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<PositionsTable
|
||||
rowData={[{ ...singleRow, openVolume: '0' }]}
|
||||
onClose={() => {
|
||||
return;
|
||||
}}
|
||||
isReadOnly={false}
|
||||
/>
|
||||
</MemoryRouter>
|
||||
<PositionsTable
|
||||
rowData={[{ ...singleRow, openVolume: '0' }]}
|
||||
onClose={() => {
|
||||
return;
|
||||
}}
|
||||
isReadOnly={false}
|
||||
/>
|
||||
);
|
||||
});
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
|
||||
@@ -1,211 +0,0 @@
|
||||
import type { ReactNode } from 'react';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { renderHook, waitFor } from '@testing-library/react';
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
import { useClosePosition } from './use-close-position';
|
||||
import { VegaTxStatus, VegaWalletContext } from '@vegaprotocol/wallet';
|
||||
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
|
||||
import { initialState } from '@vegaprotocol/wallet';
|
||||
import type { TransactionEventSubscription } from '@vegaprotocol/wallet';
|
||||
import { TransactionEventDocument } from '@vegaprotocol/wallet';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import type { OrderSubSubscription } from '@vegaprotocol/orders';
|
||||
import { OrderSubDocument } from '@vegaprotocol/orders';
|
||||
|
||||
const pubKey = 'test-pubkey';
|
||||
const defaultWalletContext = {
|
||||
pubKey,
|
||||
pubKeys: [{ publicKey: pubKey, name: 'test pubkey' }],
|
||||
isReadOnly: false,
|
||||
sendTx: jest.fn().mockReturnValue(Promise.resolve(null)),
|
||||
connect: jest.fn(),
|
||||
disconnect: jest.fn(),
|
||||
selectPubKey: jest.fn(),
|
||||
connector: null,
|
||||
};
|
||||
const txResult = {
|
||||
__typename: 'TransactionResult',
|
||||
partyId: pubKey,
|
||||
hash: '0x123',
|
||||
status: true,
|
||||
error: null,
|
||||
};
|
||||
|
||||
function setup(context?: Partial<VegaWalletContextShape>) {
|
||||
const mockTransactionResult: MockedResponse<TransactionEventSubscription> = {
|
||||
request: {
|
||||
query: TransactionEventDocument,
|
||||
variables: {
|
||||
partyId: context?.pubKey || '',
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
busEvents: [
|
||||
{
|
||||
type: Types.BusEventType.TransactionResult,
|
||||
event: txResult,
|
||||
__typename: 'BusEvent',
|
||||
},
|
||||
] as TransactionEventSubscription['busEvents'],
|
||||
},
|
||||
},
|
||||
};
|
||||
const mockOrderResult: MockedResponse<OrderSubSubscription> = {
|
||||
request: {
|
||||
query: OrderSubDocument,
|
||||
variables: {
|
||||
partyId: context?.pubKey || '',
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
orders: [
|
||||
{
|
||||
type: Types.OrderType.TYPE_LIMIT,
|
||||
id: '2fca514cebf9f465ae31ecb4c5721e3a6f5f260425ded887ca50ba15b81a5d50',
|
||||
status: Types.OrderStatus.STATUS_ACTIVE,
|
||||
rejectionReason: null,
|
||||
createdAt: '2022-07-05T14:25:47.815283706Z',
|
||||
expiresAt: '2022-07-05T14:25:47.815283706Z',
|
||||
size: '10',
|
||||
price: '300000',
|
||||
timeInForce: Types.OrderTimeInForce.TIME_IN_FORCE_GTC,
|
||||
side: Types.Side.SIDE_BUY,
|
||||
marketId: 'market-id',
|
||||
__typename: 'OrderUpdate',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const wrapper = ({ children }: { children: ReactNode }) => (
|
||||
<MockedProvider mocks={[mockTransactionResult, mockOrderResult]}>
|
||||
<VegaWalletContext.Provider
|
||||
value={{ ...defaultWalletContext, ...context }}
|
||||
>
|
||||
{children}
|
||||
</VegaWalletContext.Provider>
|
||||
</MockedProvider>
|
||||
);
|
||||
return renderHook(() => useClosePosition(), { wrapper });
|
||||
}
|
||||
|
||||
describe('useClosePosition', () => {
|
||||
const txResponse = {
|
||||
signature:
|
||||
'cfe592d169f87d0671dd447751036d0dddc165b9c4b65e5a5060e2bbadd1aa726d4cbe9d3c3b327bcb0bff4f83999592619a2493f9bbd251fae99ce7ce766909',
|
||||
transactionHash: '0x123',
|
||||
};
|
||||
|
||||
it('doesnt send the tx if there is no open volume', () => {
|
||||
const mockSend = jest.fn();
|
||||
const { result } = setup({ sendTx: mockSend });
|
||||
expect(result.current).toEqual({
|
||||
submit: expect.any(Function),
|
||||
transaction: initialState,
|
||||
Dialog: expect.any(Function),
|
||||
});
|
||||
result.current.submit({ marketId: 'test-market', openVolume: '0' });
|
||||
expect(mockSend).not.toBeCalled();
|
||||
expect(result.current.transaction.status).toEqual(VegaTxStatus.Default);
|
||||
});
|
||||
|
||||
it('doesnt send the tx if there is no pubkey', () => {
|
||||
const mockSend = jest.fn();
|
||||
const { result } = setup({ sendTx: mockSend, pubKey: null });
|
||||
result.current.submit({ marketId: 'test-market', openVolume: '1000' });
|
||||
expect(mockSend).not.toBeCalled();
|
||||
expect(result.current.transaction.status).toEqual(VegaTxStatus.Default);
|
||||
});
|
||||
|
||||
it('closes long positions', async () => {
|
||||
const marketId = 'test-market';
|
||||
const openVolume = '1000';
|
||||
const mockSend = jest.fn().mockResolvedValue(txResponse);
|
||||
const { result } = setup({ sendTx: mockSend, pubKey });
|
||||
|
||||
act(() => {
|
||||
result.current.submit({ marketId, openVolume });
|
||||
});
|
||||
|
||||
expect(mockSend).toBeCalledWith(defaultWalletContext.pubKey, {
|
||||
batchMarketInstructions: {
|
||||
cancellations: [
|
||||
{
|
||||
marketId,
|
||||
orderId: '',
|
||||
},
|
||||
],
|
||||
submissions: [
|
||||
{
|
||||
marketId,
|
||||
type: Types.OrderType.TYPE_MARKET,
|
||||
timeInForce: Types.OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
side: Types.Side.SIDE_SELL,
|
||||
size: openVolume,
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.current.transaction.status).toEqual(VegaTxStatus.Requested);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.transaction).toEqual({
|
||||
status: VegaTxStatus.Complete,
|
||||
signature: txResponse.signature,
|
||||
txHash: txResponse.transactionHash,
|
||||
dialogOpen: true,
|
||||
error: null,
|
||||
});
|
||||
expect(result.current.transactionResult).toEqual(txResult);
|
||||
});
|
||||
});
|
||||
|
||||
it('closes short positions', async () => {
|
||||
const marketId = 'test-market';
|
||||
const openVolume = '-1000';
|
||||
const mockSend = jest.fn().mockResolvedValue(txResponse);
|
||||
const { result } = setup({ sendTx: mockSend, pubKey });
|
||||
|
||||
act(() => {
|
||||
result.current.submit({ marketId, openVolume });
|
||||
});
|
||||
|
||||
expect(mockSend).toBeCalledWith(defaultWalletContext.pubKey, {
|
||||
batchMarketInstructions: {
|
||||
cancellations: [
|
||||
{
|
||||
marketId,
|
||||
orderId: '',
|
||||
},
|
||||
],
|
||||
submissions: [
|
||||
{
|
||||
marketId,
|
||||
type: Types.OrderType.TYPE_MARKET,
|
||||
timeInForce: Types.OrderTimeInForce.TIME_IN_FORCE_FOK,
|
||||
side: Types.Side.SIDE_BUY,
|
||||
size: openVolume.replace('-', ''),
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.current.transaction.status).toEqual(VegaTxStatus.Requested);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(result.current.transaction).toEqual({
|
||||
status: VegaTxStatus.Complete,
|
||||
signature: txResponse.signature,
|
||||
txHash: txResponse.transactionHash,
|
||||
dialogOpen: true,
|
||||
error: null,
|
||||
});
|
||||
expect(result.current.transactionResult).toEqual(txResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,105 +0,0 @@
|
||||
import { useCallback, useState } from 'react';
|
||||
import type { TransactionResult } from '@vegaprotocol/wallet';
|
||||
import { determineId } from '@vegaprotocol/wallet';
|
||||
import { useVegaWallet, useTransactionResult } from '@vegaprotocol/wallet';
|
||||
import { useVegaTransaction } from '@vegaprotocol/wallet';
|
||||
import * as Sentry from '@sentry/react';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { useOrderUpdate } from '@vegaprotocol/orders';
|
||||
import type { OrderSubFieldsFragment } from '@vegaprotocol/orders';
|
||||
|
||||
export interface ClosingOrder {
|
||||
marketId: string;
|
||||
type: Schema.OrderType.TYPE_MARKET;
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK;
|
||||
side: Schema.Side;
|
||||
size: string;
|
||||
}
|
||||
|
||||
export const useClosePosition = () => {
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { send, transaction, setComplete, Dialog } = useVegaTransaction();
|
||||
const [closingOrder, setClosingOrder] = useState<ClosingOrder>();
|
||||
const [closingOrderResult, setClosingOrderResult] =
|
||||
useState<OrderSubFieldsFragment>();
|
||||
const [transactionResult, setTransactionResult] =
|
||||
useState<TransactionResult>();
|
||||
const waitForTransactionResult = useTransactionResult();
|
||||
const waitForOrder = useOrderUpdate(transaction);
|
||||
|
||||
const submit = useCallback(
|
||||
async ({
|
||||
marketId,
|
||||
openVolume,
|
||||
}: {
|
||||
marketId: string;
|
||||
openVolume: string;
|
||||
}) => {
|
||||
if (!pubKey || openVolume === '0') {
|
||||
return;
|
||||
}
|
||||
|
||||
setTransactionResult(undefined);
|
||||
setClosingOrder(undefined);
|
||||
|
||||
try {
|
||||
// figure out if position is long or short and make side the opposite
|
||||
const side = openVolume.startsWith('-')
|
||||
? Schema.Side.SIDE_BUY
|
||||
: Schema.Side.SIDE_SELL;
|
||||
|
||||
// volume could be prefixed with '-' if position is short, remove it
|
||||
const size = openVolume.replace('-', '');
|
||||
const closingOrder = {
|
||||
marketId: marketId,
|
||||
type: Schema.OrderType.TYPE_MARKET as const,
|
||||
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK as const,
|
||||
side,
|
||||
size,
|
||||
};
|
||||
|
||||
setClosingOrder(closingOrder);
|
||||
|
||||
const command = {
|
||||
batchMarketInstructions: {
|
||||
cancellations: [
|
||||
{
|
||||
marketId,
|
||||
orderId: '', // omit order id to cancel all active orders
|
||||
},
|
||||
],
|
||||
submissions: [closingOrder],
|
||||
},
|
||||
};
|
||||
|
||||
const res = await send(pubKey, command);
|
||||
|
||||
if (res) {
|
||||
const orderId = determineId(res.signature);
|
||||
const [txResult, orderResult] = await Promise.all([
|
||||
waitForTransactionResult(res.transactionHash, pubKey),
|
||||
waitForOrder(orderId, pubKey),
|
||||
]);
|
||||
setTransactionResult(txResult);
|
||||
setClosingOrderResult(orderResult);
|
||||
setComplete();
|
||||
}
|
||||
|
||||
return res;
|
||||
} catch (e) {
|
||||
Sentry.captureException(e);
|
||||
return;
|
||||
}
|
||||
},
|
||||
[pubKey, send, setComplete, waitForTransactionResult, waitForOrder]
|
||||
);
|
||||
|
||||
return {
|
||||
transaction,
|
||||
transactionResult,
|
||||
submit,
|
||||
closingOrder,
|
||||
closingOrderResult,
|
||||
Dialog,
|
||||
};
|
||||
};
|
||||
@@ -1,66 +0,0 @@
|
||||
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
|
||||
import { isOrderActive, ordersWithMarketProvider } from '@vegaprotocol/orders';
|
||||
import type { OrdersQueryVariables } from '@vegaprotocol/orders';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const useRequestClosePositionData = (
|
||||
marketId?: string,
|
||||
partyId?: string
|
||||
) => {
|
||||
const marketVariables = useMemo(
|
||||
() => ({ marketId: marketId || '' }),
|
||||
[marketId]
|
||||
);
|
||||
const orderVariables = useMemo<OrdersQueryVariables>(
|
||||
() => ({ partyId: partyId || '' }),
|
||||
[partyId]
|
||||
);
|
||||
const { data: market, loading: marketLoading } = useDataProvider({
|
||||
dataProvider: marketProvider,
|
||||
variables: marketVariables,
|
||||
skip: !marketId,
|
||||
});
|
||||
const { data: marketData, loading: marketDataLoading } = useDataProvider({
|
||||
dataProvider: marketDataProvider,
|
||||
variables: marketVariables,
|
||||
});
|
||||
const { data: orderData, loading: orderDataLoading } = useDataProvider({
|
||||
dataProvider: ordersWithMarketProvider,
|
||||
variables: orderVariables,
|
||||
skip: !partyId,
|
||||
});
|
||||
|
||||
const orders = useMemo(() => {
|
||||
if (!orderData || !market) return [];
|
||||
return (
|
||||
orderData
|
||||
.filter((o) => {
|
||||
// Filter out orders not on market for position
|
||||
if (
|
||||
!o ||
|
||||
!o.node ||
|
||||
!o.node.market ||
|
||||
o.node.market.id !== market.id
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!isOrderActive(o.node.status)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
// @ts-ignore o is never null as its been filtered out above
|
||||
.map((o) => o.node)
|
||||
);
|
||||
}, [orderData, market]);
|
||||
|
||||
return {
|
||||
market,
|
||||
marketData,
|
||||
orders,
|
||||
loading: marketLoading || marketDataLoading || orderDataLoading,
|
||||
};
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ethers } from 'ethers';
|
||||
import { hexlify } from 'ethers/lib/utils';
|
||||
import abi from '../abis/claim_abi.json';
|
||||
import { calcGasBuffer } from '../utils';
|
||||
|
||||
export const UNSPENT_CODE = '0x0000000000000000000000000000000000000000';
|
||||
export const SPENT_CODE = '0x0000000000000000000000000000000000000001';
|
||||
@@ -42,7 +43,7 @@ export class Claim {
|
||||
* was performed and mined beforehand
|
||||
* @return {Promise<boolean>}
|
||||
*/
|
||||
public claim({
|
||||
public async claim({
|
||||
amount,
|
||||
tranche,
|
||||
expiry,
|
||||
@@ -61,20 +62,20 @@ export class Claim {
|
||||
r: string;
|
||||
s: string;
|
||||
}): Promise<ethers.ContractTransaction> {
|
||||
return this.contract[
|
||||
target != null ? 'claim_targeted' : 'claim_untargeted'
|
||||
](
|
||||
...[
|
||||
{ r, s, v },
|
||||
{
|
||||
amount,
|
||||
tranche,
|
||||
expiry,
|
||||
},
|
||||
hexlify(country),
|
||||
target,
|
||||
].filter(Boolean)
|
||||
);
|
||||
const method = target != null ? 'claim_targeted' : 'claim_untargeted';
|
||||
const args = [
|
||||
{ r, s, v },
|
||||
{
|
||||
amount,
|
||||
tranche,
|
||||
expiry,
|
||||
},
|
||||
hexlify(country),
|
||||
target,
|
||||
].filter(Boolean);
|
||||
const res = await this.contract.estimateGas[method](...args);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract[method](...args, { gasLimit });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { BigNumber } from 'ethers';
|
||||
import { ethers } from 'ethers';
|
||||
import abi from '../abis/erc20_bridge_abi.json';
|
||||
import { calcGasBuffer } from '../utils';
|
||||
|
||||
export class CollateralBridge {
|
||||
public contract: ethers.Contract;
|
||||
@@ -13,8 +14,20 @@ export class CollateralBridge {
|
||||
this.contract = new ethers.Contract(address, abi, signerOrProvider);
|
||||
}
|
||||
|
||||
deposit_asset(assetSource: string, amount: string, vegaPublicKey: string) {
|
||||
return this.contract.deposit_asset(assetSource, amount, vegaPublicKey);
|
||||
async deposit_asset(
|
||||
assetSource: string,
|
||||
amount: string,
|
||||
vegaPublicKey: string
|
||||
) {
|
||||
const res = await this.contract.estimateGas.deposit_asset(
|
||||
assetSource,
|
||||
amount,
|
||||
vegaPublicKey
|
||||
);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.deposit_asset(assetSource, amount, vegaPublicKey, {
|
||||
gasLimit,
|
||||
});
|
||||
}
|
||||
get_asset_source(vegaAssetId: string) {
|
||||
return this.contract.get_asset_source(vegaAssetId);
|
||||
@@ -37,7 +50,7 @@ export class CollateralBridge {
|
||||
default_withdraw_delay() {
|
||||
return this.contract.default_withdraw_delay();
|
||||
}
|
||||
list_asset(
|
||||
async list_asset(
|
||||
address: string,
|
||||
vegaAssetId: string,
|
||||
lifetimeLimit: string,
|
||||
@@ -45,7 +58,7 @@ export class CollateralBridge {
|
||||
nonce: string,
|
||||
signatures: string
|
||||
) {
|
||||
return this.contract.list_asset(
|
||||
const res = await this.contract.estimateGas.list_asset(
|
||||
address,
|
||||
vegaAssetId,
|
||||
lifetimeLimit,
|
||||
@@ -53,8 +66,20 @@ export class CollateralBridge {
|
||||
nonce,
|
||||
signatures
|
||||
);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.list_asset(
|
||||
address,
|
||||
vegaAssetId,
|
||||
lifetimeLimit,
|
||||
withdraw_threshold,
|
||||
nonce,
|
||||
signatures,
|
||||
{
|
||||
gasLimit,
|
||||
}
|
||||
);
|
||||
}
|
||||
withdraw_asset(
|
||||
async withdraw_asset(
|
||||
assetSource: string,
|
||||
amount: string,
|
||||
target: string,
|
||||
@@ -62,7 +87,7 @@ export class CollateralBridge {
|
||||
nonce: string,
|
||||
signatures: string
|
||||
) {
|
||||
return this.contract.withdraw_asset(
|
||||
const res = await this.contract.estimateGas.withdraw_asset(
|
||||
assetSource,
|
||||
amount,
|
||||
target,
|
||||
@@ -70,6 +95,18 @@ export class CollateralBridge {
|
||||
nonce,
|
||||
signatures
|
||||
);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.withdraw_asset(
|
||||
assetSource,
|
||||
amount,
|
||||
target,
|
||||
creation,
|
||||
nonce,
|
||||
signatures,
|
||||
{
|
||||
gasLimit,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
is_stopped() {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { ethers } from 'ethers';
|
||||
import abi from '../abis/multisig_abi.json';
|
||||
import { calcGasBuffer } from '../utils';
|
||||
|
||||
export class MultisigControl {
|
||||
public contract: ethers.Contract;
|
||||
@@ -13,12 +14,20 @@ export class MultisigControl {
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
add_signer(newSigner: string, nonce: string, signatures: string) {
|
||||
return this.contract.add_signer(newSigner, nonce, signatures);
|
||||
async add_signer(newSigner: string, nonce: string, signatures: string) {
|
||||
const res = await this.contract.estimateGas.add_signer(
|
||||
newSigner,
|
||||
nonce,
|
||||
signatures
|
||||
);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.add_signer(newSigner, nonce, signatures, { gasLimit });
|
||||
}
|
||||
|
||||
burn_nonce(nonce: string, signatures: string) {
|
||||
return this.contract.burn_nonce(nonce, signatures);
|
||||
async burn_nonce(nonce: string, signatures: string) {
|
||||
const res = await this.contract.estimateGas.burn_nonce(nonce, signatures);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.burn_nonce(nonce, signatures, { gasLimit });
|
||||
}
|
||||
|
||||
get_current_threshold() {
|
||||
@@ -37,19 +46,43 @@ export class MultisigControl {
|
||||
return this.contract.is_valid_signer(signerAddress);
|
||||
}
|
||||
|
||||
remove_signer(oldSigner: string, nonce: string, signatures: string) {
|
||||
return this.contract.remove_signer(oldSigner, nonce, signatures);
|
||||
async remove_signer(oldSigner: string, nonce: string, signatures: string) {
|
||||
const res = await this.contract.estimateGas.remove_signer(
|
||||
oldSigner,
|
||||
nonce,
|
||||
signatures
|
||||
);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.remove_signer(oldSigner, nonce, signatures, {
|
||||
gasLimit,
|
||||
});
|
||||
}
|
||||
|
||||
set_threshold(newThreshold: string, nonce: string, signatures: string) {
|
||||
return this.contract.set_threshold(newThreshold, nonce, signatures);
|
||||
async set_threshold(newThreshold: string, nonce: string, signatures: string) {
|
||||
const res = await this.contract.estimateGas.set_threshold(
|
||||
newThreshold,
|
||||
nonce,
|
||||
signatures
|
||||
);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.set_threshold(newThreshold, nonce, signatures, {
|
||||
gasLimit,
|
||||
});
|
||||
}
|
||||
|
||||
signers(address: string) {
|
||||
return this.contract.signers(address);
|
||||
}
|
||||
|
||||
verify_signatures(nonce: string, message: string, signatures: string) {
|
||||
return this.contract.verify_signatures(nonce, message, signatures);
|
||||
async verify_signatures(nonce: string, message: string, signatures: string) {
|
||||
const res = await this.contract.estimateGas.verify_signatures(
|
||||
nonce,
|
||||
message,
|
||||
signatures
|
||||
);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.verify_signatures(nonce, message, signatures, {
|
||||
gasLimit,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ethers } from 'ethers';
|
||||
import abi from '../abis/staking_abi.json';
|
||||
import { prepend0x } from '../utils';
|
||||
import { calcGasBuffer, prepend0x } from '../utils';
|
||||
|
||||
export class StakingBridge {
|
||||
public contract: ethers.Contract;
|
||||
@@ -13,20 +13,41 @@ export class StakingBridge {
|
||||
this.contract = new ethers.Contract(address, abi, signerOrProvider);
|
||||
this.address = address;
|
||||
}
|
||||
async stake(amount: string, vegaPublicKey: string) {
|
||||
const key = prepend0x(vegaPublicKey);
|
||||
const res = await this.contract.estimateGas.stake(amount, key);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.stake(amount, key, {
|
||||
gasLimit,
|
||||
});
|
||||
}
|
||||
|
||||
stake(amount: string, vegaPublicKey: string) {
|
||||
return this.contract.stake(amount, prepend0x(vegaPublicKey));
|
||||
async remove_stake(amount: string, vegaPublicKey: string) {
|
||||
const key = prepend0x(vegaPublicKey);
|
||||
const res = await this.contract.estimateGas.remove_stake(amount, key);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.remove_stake(amount, key, {
|
||||
gasLimit,
|
||||
});
|
||||
}
|
||||
remove_stake(amount: string, vegaPublicKey: string) {
|
||||
return this.contract.remove_stake(amount, prepend0x(vegaPublicKey));
|
||||
}
|
||||
transfer_stake(amount: string, newAddress: string, vegaPublicKey: string) {
|
||||
return this.contract.transfer_stake(
|
||||
|
||||
async transfer_stake(
|
||||
amount: string,
|
||||
newAddress: string,
|
||||
vegaPublicKey: string
|
||||
) {
|
||||
const key = prepend0x(vegaPublicKey);
|
||||
const res = await this.contract.estimateGas.transfer_stake(
|
||||
amount,
|
||||
newAddress,
|
||||
prepend0x(vegaPublicKey)
|
||||
key
|
||||
);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.transfer_stake(amount, newAddress, key, {
|
||||
gasLimit,
|
||||
});
|
||||
}
|
||||
|
||||
staking_token() {
|
||||
return this.contract.staking_token();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { BigNumber } from 'ethers';
|
||||
import { ethers } from 'ethers';
|
||||
import erc20AbiFaucetable from '../abis/erc20_abi_faucet.json';
|
||||
import { calcGasBuffer } from '../utils';
|
||||
|
||||
export class TokenFaucetable {
|
||||
public contract: ethers.Contract;
|
||||
@@ -27,13 +28,17 @@ export class TokenFaucetable {
|
||||
allowance(owner: string, spender: string): Promise<BigNumber> {
|
||||
return this.contract.allowance(owner, spender);
|
||||
}
|
||||
approve(spender: string, amount: string) {
|
||||
return this.contract.approve(spender, amount);
|
||||
async approve(spender: string, amount: string) {
|
||||
const res = await this.contract.estimateGas.approve(spender, amount);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.approve(spender, amount, { gasLimit });
|
||||
}
|
||||
decimals(): Promise<number> {
|
||||
return this.contract.decimals();
|
||||
}
|
||||
faucet() {
|
||||
return this.contract.faucet();
|
||||
async faucet() {
|
||||
const res = await this.contract.estimateGas.faucet();
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.faucet({ gasLimit });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { ethers } from 'ethers';
|
||||
import abi from '../abis/vesting_abi.json';
|
||||
import { prepend0x } from '../utils';
|
||||
import { calcGasBuffer, prepend0x } from '../utils';
|
||||
|
||||
export class TokenVesting {
|
||||
public contract: ethers.Contract;
|
||||
@@ -13,12 +13,21 @@ export class TokenVesting {
|
||||
this.contract = new ethers.Contract(address, abi, signerOrProvider);
|
||||
this.address = address;
|
||||
}
|
||||
|
||||
stake_tokens(amount: string, vegaPublicKey: string) {
|
||||
return this.contract.stake_tokens(amount, prepend0x(vegaPublicKey));
|
||||
async stake_tokens(amount: string, vegaPublicKey: string) {
|
||||
const key = prepend0x(vegaPublicKey);
|
||||
const res = await this.contract.estimateGas.stake_tokens(amount, key);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.stake_tokens(amount, key, {
|
||||
gasLimit,
|
||||
});
|
||||
}
|
||||
remove_stake(amount: string, vegaPublicKey: string) {
|
||||
return this.contract.remove_stake(amount, prepend0x(vegaPublicKey));
|
||||
async remove_stake(amount: string, vegaPublicKey: string) {
|
||||
const key = prepend0x(vegaPublicKey);
|
||||
const res = await this.contract.estimateGas.remove_stake(amount, key);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.remove_stake(amount, key, {
|
||||
gasLimit,
|
||||
});
|
||||
}
|
||||
stake_balance(address: string, vegaPublicKey: string) {
|
||||
return this.contract.stake_balance(address, prepend0x(vegaPublicKey));
|
||||
@@ -38,7 +47,13 @@ export class TokenVesting {
|
||||
user_total_all_tranches(address: string) {
|
||||
return this.contract.user_total_all_tranches(address);
|
||||
}
|
||||
withdraw_from_tranche(trancheId: number) {
|
||||
return this.contract.withdraw_from_tranche(trancheId);
|
||||
async withdraw_from_tranche(trancheId: number) {
|
||||
const res = await this.contract.estimateGas.withdraw_from_tranche(
|
||||
trancheId
|
||||
);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.withdraw_from_tranche(trancheId, {
|
||||
gasLimit,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import type { BigNumber } from 'ethers';
|
||||
import { ethers } from 'ethers';
|
||||
import erc20Abi from '../abis/erc20_abi.json';
|
||||
import { calcGasBuffer } from '../utils';
|
||||
|
||||
export class Token {
|
||||
public contract: ethers.Contract;
|
||||
@@ -23,13 +24,15 @@ export class Token {
|
||||
allowance(owner: string, spender: string): Promise<BigNumber> {
|
||||
return this.contract.allowance(owner, spender);
|
||||
}
|
||||
approve(spender: string, amount: string) {
|
||||
return this.contract.approve(spender, amount);
|
||||
async approve(spender: string, amount: string) {
|
||||
const res = await this.contract.estimateGas.approve(spender, amount);
|
||||
const gasLimit = calcGasBuffer(res);
|
||||
return this.contract.approve(spender, amount, { gasLimit });
|
||||
}
|
||||
decimals(): Promise<number> {
|
||||
return this.contract.decimals();
|
||||
}
|
||||
faucet() {
|
||||
async faucet() {
|
||||
/* No op */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import type { BigNumber as EthersBigNumber } from 'ethers';
|
||||
|
||||
export function calcGasBuffer(value: EthersBigNumber): EthersBigNumber {
|
||||
return value.mul(120).div(100);
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
export * from './calc-gas-buffer';
|
||||
export * from './prepend-0x';
|
||||
|
||||
@@ -38,6 +38,7 @@ export const Checkbox = ({
|
||||
checked={checked}
|
||||
onCheckedChange={onCheckedChange}
|
||||
disabled={disabled}
|
||||
data-testid={name}
|
||||
>
|
||||
<CheckboxPrimitive.CheckboxIndicator className="flex justify-center items-center w-[15px] h-[15px] bg-black dark:bg-white">
|
||||
{checked === 'indeterminate' ? (
|
||||
|
||||
Reference in New Issue
Block a user