Compare commits

..
Author SHA1 Message Date
asiaznik c183fa39f8 fix(trading): missing wallet connect button 2023-10-03 10:38:44 +02:00
192 changed files with 1499 additions and 2929 deletions
@@ -82,38 +82,3 @@ jobs:
https://${{ env.IPFS_V1 }}.ipfs.dweb.link/
https://${{ env.IPFS_V1 }}.ipfs.cf-ipfs.com/
ipfs://${{ env.IPFS_V0 }}/
- name: Ensure 'Released' label exists
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
REPO="${{ github.repository }}"
LABEL_EXIST=$(curl -s -H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
"https://api.github.com/repos/$REPO/labels/Released")
if [[ "$LABEL_EXIST" == *"Not Found"* ]]; then
curl -s -H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-X POST "https://api.github.com/repos/$REPO/labels" \
-d '{"name": "Released", "color": "FFFFFF"}'
fi
- name: Extract issues from release notes
id: extract-issues
run: |
ISSUES=$(echo "${{ github.event.release.body }}" | grep -o -E '#[0-9]+' | tr -d '#' | jq -R . | jq -cs .)
echo "Issues to label: $ISSUES"
echo "::set-output name=issue_numbers::$ISSUES"
- name: Add 'Released' label to issues
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
ISSUE_NUMBERS="${{ steps.extract-issues.outputs.issue_numbers }}"
REPO="${{ github.repository }}"
for ISSUE in $(echo "$ISSUE_NUMBERS" | jq -r '.[]'); do
curl -s -H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github.v3+json" \
-X POST "https://api.github.com/repos/$REPO/issues/$ISSUE/labels" \
-d '{"labels": ["Released"]}'
done
+10 -34
View File
@@ -5,7 +5,6 @@ on:
branches:
- release/*
- develop
- main
pull_request:
types:
- opened
@@ -170,48 +169,25 @@ jobs:
preview_explorer: ${{ env.PREVIEW_EXPLORER }}
preview_tools: ${{ env.PREVIEW_TOOLS }}
check-e2e-needed:
runs-on: ubuntu-latest
needs: build-sources
name: '(CI) check if e2e needed'
outputs:
run-tests: ${{ steps.check-test.outputs.e2e-needed }}
steps:
- name: Check branch
id: check-test
run: |
if [[ "${{ github.base_ref }}" == "develop" ]]; then
echo "e2e-needed=true" >> $GITHUB_OUTPUT
elif [[ "${{ github.base_ref }}" == "main" ]]; then
echo "e2e-needed=true" >> $GITHUB_OUTPUT
elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref_name }}" == *"release/"* ]]; then
echo "e2e-needed=true" >> $GITHUB_OUTPUT
else
echo "e2e-needed=false" >> $GITHUB_OUTPUT
fi
- name: Print result
run: |
echo "e2e-needed: ${{ steps.check-test.outputs.e2e-needed }}"
# console-e2e:
# needs: build-sources
# name: '(CI) console python'
# uses: ./.github/workflows/console-test-run.yml
# secrets: inherit
# if: ${{ contains(fromJSON(needs.build-sources.outputs.projects), 'trading') && github.event_name == 'pull_request' }}
# with:
# github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
cypress:
needs: [build-sources, check-e2e-needed]
needs: build-sources
name: '(CI) cypress'
if: ${{ needs.check-e2e-needed.outputs.run-tests == 'true' }}
# if: ${{ needs.build-sources.outputs.projects-e2e != '[]' }}
uses: ./.github/workflows/cypress-run.yml
secrets: inherit
with:
projects: ${{ needs.build-sources.outputs.projects-e2e }}
tags: '@smoke'
console-e2e:
needs: [build-sources, check-e2e-needed]
name: '(CI) console python'
uses: ./.github/workflows/console-test-run.yml
secrets: inherit
if: ${{ needs.check-e2e-needed.outputs.run-tests == 'true' }} && ${{ contains(fromJSON(needs.build-sources.outputs.projects), 'trading') }}
with:
github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
publish-dist:
needs: build-sources
name: '(CD) publish dist'
-29
View File
@@ -1,29 +0,0 @@
# https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#managing-caches
name: cleanup caches by a branch
on:
pull_request:
types:
- closed
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Cleanup
run: |
gh extension install actions/gh-actions-cache
echo "Fetching list of cache key"
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH -L 100 | cut -f 1 )
## Setting this to not fail the workflow while deleting cache keys.
set +e
echo "Deleting caches..."
for cacheKey in $cacheKeysForPR
do
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
done
echo "Done"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
REPO: ${{ github.repository }}
BRANCH: refs/pull/${{ github.event.pull_request.number }}/merge
+45 -117
View File
@@ -1,5 +1,8 @@
name: (CI) Console tests
env:
VEGA_VERSION: v0.72.14
on:
workflow_call:
inputs:
@@ -16,9 +19,9 @@ on:
- develop
jobs:
create-docker-image:
name: Create docker image for console-test
runs-on: ubuntu-22.04
run-tests:
name: run-tests
runs-on: 8-cores
timeout-minutes: 20
steps:
#----------------------------------------------
@@ -55,105 +58,23 @@ jobs:
#----------------------------------------------
# build trading
#----------------------------------------------
- name: Build trading app
- name: Build affected spec
run: |
yarn env-cmd -f ./apps/trading/.env.stagnet1 yarn nx export trading
DIST_LOCATION=dist/apps/trading/exported
mv $DIST_LOCATION dist-result
tree dist-result
#----------------------------------------------
# export trading app docker image
# run trading server
#----------------------------------------------
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and export to local Docker
id: docker_build
uses: docker/build-push-action@v5
with:
context: .
file: docker/node-outside-docker.Dockerfile
load: true
build-args: |
APP=trading
ENV_NAME=stagnet1
tags: ci/trading:local
outputs: type=docker,dest=/tmp/console-image.tar
- name: Verify docker image created
- name: Run trading server
run: |
echo ${{ steps.docker_build.outputs.digest }}
echo ${{ steps.docker_build.outputs.imageid }}
- name: Upload docker image for console-test usage
uses: actions/upload-artifact@v3
with:
name: console-image
path: /tmp/console-image.tar
console-test-branch:
name: Choose console-test branch to run on
runs-on: ubuntu-22.04
timeout-minutes: 5
outputs:
console-branch: ${{ steps.output-step.outputs.branch }}
steps:
- name: Workflow dispatch input
id: dispatch-step
if: github.event_name == 'workflow_dispatch'
run: echo "branch=${{ inputs.console-test-branch }}" >> $GITHUB_OUTPUT
- name: Print Workflow dispatch input
if: github.event_name == 'workflow_dispatch'
run: echo ${{ steps.dispatch-step.outputs.branch }}
- name: Workflow_call input
id: workflow_call-step
if: github.event_name != 'workflow_dispatch'
run: |
if [[ "${{ github.base_ref }}" == "main" ]]; then
echo "branch=main" >> $GITHUB_OUTPUT
elif [[ "${{ github.base_ref }}" == "develop" && "${{ github.ref_name }}" == "main" ]]; then
echo "branch=main" >> $GITHUB_OUTPUT
elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref_name }}" == *"release/mainnet"* ]]; then
echo "branch=main" >> $GITHUB_OUTPUT
else
echo "branch=develop" >> $GITHUB_OUTPUT
fi
- name: Print Workflow_call input
if: github.event_name != 'workflow_dispatch'
run: echo ${{ steps.workflow_call-step.outputs.branch }}
- name: Set output
id: output-step
run: echo "branch=${{ steps.dispatch-step.outputs.branch || steps.workflow_call-step.outputs.branch }}" >> $GITHUB_OUTPUT
- name: Print final output
run: echo ${{ steps.output-step.outputs.branch }}
run-tests:
name: run-tests
runs-on: 8-cores
needs: [create-docker-image, console-test-branch]
timeout-minutes: 20
steps:
docker run -d -p 80:4200 -v $PWD/docker/nginx.conf:/etc/nginx/conf.d/default.conf -v $PWD/dist/apps/trading/exported:/usr/share/nginx/html nginx:1.23-alpine@sha256:6318314189b40e73145a48060bff4783a116c34cc7241532d0d94198fb2c9629
sleep 5
docker ps
#----------------------------------------------
# load docker image
# check if container persists between runs
#----------------------------------------------
- name: Download docker image from previous job
uses: actions/download-artifact@v3
with:
name: console-image
path: /tmp
- name: Load Docker image
- name: Check server
run: |
docker load --input /tmp/console-image.tar
docker image ls -a
docker ps
#----------------------------------------------
# check-out tests repo
#----------------------------------------------
@@ -161,55 +82,62 @@ jobs:
uses: actions/checkout@v3
with:
repository: vegaprotocol/console-test
ref: ${{ needs.console-test-branch.outputs.console-branch }}
ref: ${{ inputs.console-test-branch }}
path: './console-test'
- name: Load console test envs
id: console-test-env
uses: falti/dotenv-action@v1.0.4
with:
path: '.env.${{ needs.console-test-branch.outputs.console-branch }}'
path: './console-test/.env.${{ inputs.console-test-branch }}'
export-variables: true
keys-case: upper
log-variables: true
#----------------------------------------------
# ----- Setup python -----
#----------------------------------------------
- name: Setup Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
#----------------------------------------------
# ----- install & configure poetry -----
#----------------------------------------------
- name: Install Poetry
uses: snok/install-poetry@v1
with:
virtualenvs-create: true
virtualenvs-in-project: true
virtualenvs-path: .venv
#----------------------------------------------
# install python dependencies
# install dependencies
#----------------------------------------------
- name: Install dependencies
working-directory: ./console-test
run: poetry install --no-interaction --no-root
#----------------------------------------------
# install vega binaries
# find vega binaries path
#----------------------------------------------
- name: Find vega binaries path
id: vega_bin_path
working-directory: ./console-test
run: echo path=$(poetry run python -c "import vega_sim; print(vega_sim.vega_bin_path)") >> $GITHUB_OUTPUT
#----------------------------------------------
# vega binaries cache
#----------------------------------------------
- name: Vega binaries cache
uses: actions/cache@v3
id: vega_binaries_cache
with:
path: ${{ steps.vega_bin_path.outputs.path }}
key: ${{ runner.os }}-vega-binaries-${{ env.VEGA_VERSION }}
#----------------------------------------------
# install vega binaries
#----------------------------------------------
- name: Install vega binaries
working-directory: ./console-test
run: poetry run python -m vega_sim.tools.load_binaries --force --version ${{ env.VEGA_VERSION }}
#----------------------------------------------
# install playwright
#----------------------------------------------
- name: install playwright
run: poetry run playwright install --with-deps chromium
working-directory: ./console-test
#----------------------------------------------
# run tests
#----------------------------------------------
- name: Run tests
run: CONSOLE_IMAGE_NAME=ci/trading:local poetry run pytest -v -s --numprocesses 4 --dist loadfile --durations=15
working-directory: ./console-test
run: poetry run pytest -v -s --numprocesses 4 --dist loadfile --durations=15
- name: Check files
run: |
ls -al .
ls -al console-test
#----------------------------------------------
# upload traces
#----------------------------------------------
+3 -4
View File
@@ -21,11 +21,11 @@ jobs:
- name: Check branch
id: step
run: |
if [[ "${{ github.base_ref }}" == "main" ]]; then
if [ ${{ github.base_ref }} == 'main' ]; then
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
elif [[ "${{ github.base_ref }}" == "develop" && "${{ github.ref_name }}" == "main" ]]; then
elif [ ${{ github.base_ref }} == 'develop' ] && [ ${{ github.ref_name }} == 'main' ]; then
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
elif [[ "${{ github.event_name }}" == "push" && "${{ github.ref_name }}" == *"release/mainnet"* ]]; then
elif [ ${{ github.event_name }} == 'push' ] && [ ${{ contains(github.ref_name, 'release/mainnet') }} ]; then
echo "runner=mainnet-compatible-runner" >> $GITHUB_OUTPUT
else
echo "runner=self-hosted-runner" >> $GITHUB_OUTPUT
@@ -85,7 +85,6 @@ jobs:
- name: Run Vegacapsule network and Vega wallet
id: setup-vega
uses: ./frontend-monorepo/.github/actions/run-vegacapsule
timeout-minutes: 10
######
## Run some tests
+3 -3
View File
@@ -63,7 +63,7 @@ jobs:
echo IS_IPFS_RELEASE=true >> $GITHUB_ENV
- name: Is S3 Release
if: ${{ env.IS_IPFS_RELEASE == 'false' && github.event_name == 'push' && github.ref_name != 'main'}}
if: ${{ env.IS_IPFS_RELEASE == 'false' && github.event_name == 'push' }}
run: |
echo IS_S3_RELEASE=true >> $GITHUB_ENV
@@ -195,7 +195,7 @@ jobs:
ENV_NAME=${{ env.ENV_NAME }}
tags: |
vegaprotocol/${{ matrix.app }}:${{ github.sha }}
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || env.IS_MAIN_IMAGE == 'true' && 'main' || '' }}
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || env.IS_MAIN_IMAGE == 'true && main' || '' }}
- name: Publish dist as docker image (ghcr - retry)
uses: docker/build-push-action@v3
@@ -222,7 +222,7 @@ jobs:
ENV_NAME=${{ env.ENV_NAME }}
tags: |
vegaprotocol/${{ matrix.app }}:${{ github.sha }}
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || env.IS_MAIN_IMAGE == 'true' && 'main' || '' }}
vegaprotocol/${{ matrix.app }}:${{ env.IS_MAINNET_RELEASE == 'true' && 'mainnet' || env.IS_TESTNET_RELEASE == 'true' && 'testnet' || env.IS_DEV_IMAGE == 'true' && 'develop' || env.IS_MAIN_IMAGE == 'true && main' || '' }}
# bucket creation in github.com/vegaprotocol/terraform//frontend
- name: Publish dist to s3
@@ -36,7 +36,7 @@ context('Market page', { tags: '@regression' }, function () {
it('Able to go to market details page', function () {
cy.navigate_to('markets');
cy.contains('Test market 1').click();
cy.get_element_by_col_id('actions').eq(1).click();
cy.getByTestId(marketHeaders).should('have.text', 'Test market 1');
cy.validate_element_from_table('Name', 'Test market 1');
cy.validate_element_from_table('Market ID', this.createdMarketId);
@@ -90,7 +90,7 @@ context('Market page', { tags: '@regression' }, function () {
// Liquidity price range
cy.validate_element_from_table(
'Liquidity Price Range',
'95.00% of mid price'
'1,000.00% of mid price'
);
cy.validate_element_from_table('Lowest Price', '0.00 fUSDC');
cy.validate_element_from_table('Highest Price', '0.00 fUSDC');
@@ -40,7 +40,7 @@ context.skip('Node switcher', { tags: '@regression' }, function () {
const errorTypeTxt = 'Error: invalid url';
const nodeErrorTxt = 'fakeUrl is not a valid url.';
cy.getByTestId('node-url-custom').click({ force: true });
cy.getByTestId('node-url-custom').click();
cy.getByTestId(customNodeBtn).within(() => {
cy.get('input').clear().type('fakeUrl');
@@ -8,9 +8,7 @@ import { useScrollToLocation } from '../../../hooks/scroll-to-location';
import filter from 'recursive-key-filter';
const Oracles = () => {
const { data, loading, error } = useExplorerOracleSpecsQuery({
errorPolicy: 'ignore',
});
const { data, loading, error } = useExplorerOracleSpecsQuery();
useDocumentTitle(['Oracles']);
useScrollToLocation();
@@ -433,10 +433,9 @@ describe(
'contain.text',
'0.3'
);
getProposalDetailsValue('Min Probability Of Trading LP Orders').should(
'contain.text',
'1e-8'
);
getProposalDetailsValue(
'Minimum Probability Of Trading LP Orders'
).should('contain.text', '1e-8');
});
it('Able to see suspended market proposal', function () {
@@ -310,9 +310,7 @@ context(
closeStakingDialog();
navigateTo(navigation.validators);
clickOnValidatorFromList(0);
cy.getByTestId(stakeRemoveStakeRadioButton, txTimeout).click({
force: true,
});
cy.getByTestId(stakeRemoveStakeRadioButton, txTimeout).click();
cy.getByTestId(stakeTokenAmountInputBox).type('-0.1');
cy.contains('Waiting for next epoch to start', epochTimeout);
cy.getByTestId(stakeTokenSubmitButton)
@@ -333,7 +331,7 @@ context(
closeStakingDialog();
navigateTo(navigation.validators);
clickOnValidatorFromList(0);
cy.getByTestId(stakeRemoveStakeRadioButton).click({ force: true });
cy.getByTestId(stakeRemoveStakeRadioButton).click();
cy.getByTestId(stakeTokenAmountInputBox).type('4');
cy.contains('Waiting for next epoch to start', epochTimeout);
cy.getByTestId(stakeTokenSubmitButton)
@@ -424,7 +422,7 @@ context(
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
});
it.skip('Associating wallet tokens - when some already staked - auto stakes tokens to staked validator', function () {
it('Associating wallet tokens - when some already staked - auto stakes tokens to staked validator', function () {
// 1002-STKE-004
stakingPageAssociateTokens('3');
verifyUnstakedBalance(3.0);
@@ -438,7 +436,7 @@ context(
verifyStakedBalance(7.0);
});
it.skip('Associating vesting contract tokens - when some already staked - auto stakes tokens to staked validator', function () {
it('Associating vesting contract tokens - when some already staked - auto stakes tokens to staked validator', function () {
// 1002-STKE-004
stakingPageAssociateTokens('3', { type: 'contract' });
verifyUnstakedBalance(3.0);
@@ -452,7 +450,7 @@ context(
verifyStakedBalance(7.0);
});
it.skip('Associating vesting contract tokens - when wallet tokens already staked - auto stakes tokens to staked validator', function () {
it('Associating vesting contract tokens - when wallet tokens already staked - auto stakes tokens to staked validator', function () {
// 1002-STKE-004
stakingPageAssociateTokens('3', { type: 'wallet' });
verifyUnstakedBalance(3.0);
@@ -466,7 +464,7 @@ context(
verifyStakedBalance(7.0);
});
it.skip('Associating tokens - with multiple validators already staked - auto stakes to staked validators - abiding by existing stake ratio', function () {
it('Associating tokens - with multiple validators already staked - auto stakes to staked validators - abiding by existing stake ratio', function () {
// 1002-STKE-004
stakingPageAssociateTokens('6');
verifyUnstakedBalance(6.0);
@@ -156,7 +156,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
cy.getByTestId('subscription-cell').should('have.text', 'Yes');
});
cy.getByTestId('connect').should('be.disabled');
cy.getByTestId('node-url-custom').click({ force: true });
cy.getByTestId('node-url-custom').click();
cy.get('input').should('exist');
cy.getByTestId('connect').should('be.disabled');
cy.getByTestId('icon-cross').click();
@@ -74,12 +74,25 @@ context(
});
it('should be able to see a working link for - find out more about Vega governance', function () {
// 3001-VOTE-001 // 3002-PROP-001
// 3001-VOTE-001
cy.getByTestId(proposalDocumentationLink)
.should('be.visible')
.and('have.text', 'Find out more about Vega governance')
.and('have.attr', 'href')
.and('equal', governanceDocsUrl);
// 3002-PROP-001
cy.request(governanceDocsUrl)
.its('body')
.then((body) => {
if (!body.includes('Govern the network')) {
assert.include(
body,
'Govern the network',
`Checking that governance link destination includes 'Govern the network' text`
);
}
});
});
// 3007-PNE-021
@@ -11,6 +11,7 @@ import {
waitForBeginningOfEpoch,
} from '../../support/staking.functions';
import { previousEpochData } from '../../fixtures/mocks/previous-epoch';
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
const guideLink = 'staking-guide-link';
const validatorTitle = 'validator-node-title';
@@ -37,11 +38,17 @@ const txTimeout = Cypress.env('txTimeout');
context('Validators Page - verify elements on page', function () {
before('navigate to validators page', () => {
cy.mockChainId();
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
});
cy.visit('/validators');
});
beforeEach(() => {
cy.mockChainId();
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
});
});
describe('with wallets disconnected', { tags: '@smoke' }, function () {
@@ -182,7 +189,10 @@ context('Validators Page - verify elements on page', function () {
{ tags: '@smoke' },
function () {
before('connect wallets and click on validator', function () {
cy.mockChainId();
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
});
cy.visit('/validators');
cy.connectVegaWallet();
clickOnValidatorFromList(0);
@@ -4,6 +4,8 @@ import {
vegaWalletFaucetAssetsWithoutCheck,
vegaWalletTeardown,
} from '../../support/wallet-functions';
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
const walletContainer = 'aside [data-testid="vega-wallet"]';
const walletHeader = '[data-testid="wallet-header"] h1';
@@ -86,7 +88,10 @@ context(
describe('when vega wallet connected', function () {
before('connect vega wallet', function () {
cy.mockChainId();
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
});
cy.visit('/');
cy.wait('@ChainId');
cy.connectVegaWallet();
@@ -271,7 +276,10 @@ context(
];
before('faucet assets to connected vega wallet', function () {
cy.mockChainId();
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
});
for (const { id, amount } of assets) {
vegaWalletFaucetAssetsWithoutCheck(id, amount, vegaWalletPublicKey);
}
+6 -1
View File
@@ -9,6 +9,8 @@ import './wallet-functions.ts';
import './proposal.functions.ts';
import 'cypress-mochawesome-reporter/register';
import registerCypressGrep from '@cypress/grep';
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
import { turnTelemetryOff } from './common.functions.ts';
registerCypressGrep();
@@ -27,7 +29,10 @@ before(() => {
// // Ensuring the telemetry modal doesn't disrupt the tests
turnTelemetryOff();
// Mock chainId fetch which happens on every page for wallet connection
cy.mockChainId();
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
});
// Self stake validators so they are displayed
cy.validatorsSelfDelegate();
});
@@ -46,7 +46,7 @@ export function stakingValidatorPageAddStake(stake: string) {
export function stakingValidatorPageRemoveStake(stake: string) {
cy.highlight(`Removing a stake of ${stake}`);
cy.get(removeStakeRadioButton, epochTimeout).click({ force: true });
cy.get(removeStakeRadioButton, epochTimeout).click();
cy.get(tokenAmountInputBox).type(stake);
waitForBeginningOfEpoch();
cy.get(tokenSubmitButton)
@@ -70,13 +70,9 @@ export function stakingPageAssociateTokens(
cy.highlight(`Associating ${amount} tokens from ${type}`);
cy.get(ethWalletAssociateButton).first().click();
if (type === 'wallet') {
cy.get(associateWalletRadioButton, { timeout: 30000 }).click({
force: true,
});
cy.get(associateWalletRadioButton, { timeout: 30000 }).click();
} else if (type === 'contract') {
cy.get(associateContractRadioButton, { timeout: 30000 }).click({
force: true,
});
cy.get(associateContractRadioButton, { timeout: 30000 }).click();
} else {
cy.highlight(`${type} is not association option`);
}
-2
View File
@@ -8,7 +8,6 @@ NX_FAIRGROUND=false
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","STAGNET1":"https://governance.stagnet1.vega.rocks","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_WALLET_URL=http://localhost:1789
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
@@ -35,4 +34,3 @@ NX_SUCCESSOR_MARKETS=true
NX_METAMASK_SNAPS=true
NX_PRODUCT_PERPETUALS=false
NX_UPDATE_MARKET_STATE=false
NX_GOVERNANCE_TRANSFERS=false
+1 -1
View File
@@ -17,7 +17,7 @@ NX_VEGA_REST_URL=https://api.vega.community/api/v2/
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-mainnet
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
-2
View File
@@ -10,7 +10,6 @@ NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
@@ -23,4 +22,3 @@ NX_SUCCESSOR_MARKETS=true
NX_METAMASK_SNAPS=true
NX_PRODUCT_PERPETUALS=true
NX_UPDATE_MARKET_STATE=true
NX_GOVERNANCE_TRANSFERS=true
-1
View File
@@ -15,7 +15,6 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
NX_VEGA_REST_URL=https://api.n07.testnet.vega.xyz/api/v2/
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
+2 -2
View File
@@ -26,11 +26,11 @@ import {
} from '@vegaprotocol/web3';
import { Web3Provider } from '@vegaprotocol/web3';
import { VegaWalletDialogs } from './components/vega-wallet-dialogs';
import { VegaWalletProvider } from '@vegaprotocol/wallet';
import {
useVegaTransactionManager,
useVegaTransactionUpdater,
} from '@vegaprotocol/web3';
VegaWalletProvider,
} from '@vegaprotocol/wallet';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { useEthereumConfig } from '@vegaprotocol/web3';
import {
@@ -888,7 +888,5 @@
"HowToPropose": "How to make a proposal",
"HowToProposeRawStep1": "1. Sense check your proposal with the community on the forum:",
"HowToProposeRawStep2": "2. Use the appropriate proposal template in the docs:",
"HowToProposeRawStep3": "3. Submit on-chain below",
"proposalTransferDetails": "New governance transfer details",
"proposalCancelTransferDetails": "Cancel governance transfer details"
"HowToProposeRawStep3": "3. Submit on-chain below"
}
@@ -7,17 +7,12 @@ import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import { truncateMiddle } from '../../../../lib/truncate-middle';
import { CurrentProposalState } from '../current-proposal-state';
import { ProposalInfoLabel } from '../proposal-info-label';
import {
useCancelTransferProposalDetails,
useNewTransferProposalDetails,
useSuccessorMarketProposalDetails,
} from '@vegaprotocol/proposals';
import { useSuccessorMarketProposalDetails } from '@vegaprotocol/proposals';
import { FLAGS } from '@vegaprotocol/environment';
import Routes from '../../../routes';
import { Link } from 'react-router-dom';
import type { VoteState } from '../vote-details/use-user-vote';
import { VoteBreakdown } from '../vote-breakdown';
import { GovernanceTransferKindMapping } from '@vegaprotocol/types';
export const ProposalHeader = ({
proposal,
@@ -152,20 +147,6 @@ export const ProposalHeader = ({
);
break;
}
case 'NewTransfer':
proposalType = 'NewTransfer';
fallbackTitle = t('NewTransferProposal');
details = FLAGS.GOVERNANCE_TRANSFERS ? (
<NewTransferSummary proposalId={proposal?.id} />
) : null;
break;
case 'CancelTransfer':
proposalType = 'CancelTransfer';
fallbackTitle = t('CancelTransferProposal');
details = FLAGS.GOVERNANCE_TRANSFERS ? (
<CancelTransferSummary proposalId={proposal?.id} />
) : null;
break;
}
return (
@@ -243,36 +224,3 @@ const SuccessorCode = ({ proposalId }: { proposalId?: string | null }) => {
</span>
) : null;
};
const NewTransferSummary = ({ proposalId }: { proposalId?: string | null }) => {
const { t } = useTranslation();
const details = useNewTransferProposalDetails(proposalId);
if (!details) return null;
return (
<span>
{GovernanceTransferKindMapping[details.kind.__typename]}{' '}
{t('transfer from')} <Lozenge>{truncateMiddle(details.source)}</Lozenge>{' '}
{t('to')} <Lozenge>{truncateMiddle(details.destination)}</Lozenge>
</span>
);
};
const CancelTransferSummary = ({
proposalId,
}: {
proposalId?: string | null;
}) => {
const { t } = useTranslation();
const details = useCancelTransferProposalDetails(proposalId);
if (!details) return null;
return (
<span>
{t('Cancel transfer: ')}{' '}
<Lozenge>{truncateMiddle(details.transferId)}</Lozenge>
</span>
);
};
@@ -1,2 +0,0 @@
export * from './proposal-transfer-details';
export * from './proposal-cancel-transfer-details';
@@ -1,37 +0,0 @@
import { useTranslation } from 'react-i18next';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import { useCancelTransferProposalDetails } from '@vegaprotocol/proposals';
import {
KeyValueTable,
KeyValueTableRow,
RoundedWrapper,
} from '@vegaprotocol/ui-toolkit';
import { SubHeading } from '../../../../components/heading';
export const ProposalCancelTransferDetails = ({
proposal,
}: {
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
}) => {
const { t } = useTranslation();
const details = useCancelTransferProposalDetails(proposal?.id);
if (!details) {
return null;
}
return (
<>
<SubHeading title={t('proposalCancelTransferDetails')} />
<RoundedWrapper paddingBottom={true}>
<KeyValueTable data-testid="proposal-cancel-transfer-details-table">
<KeyValueTableRow noBorder={true}>
{t('transferId')}
{details.transferId}
</KeyValueTableRow>
</KeyValueTable>
</RoundedWrapper>
</>
);
};
@@ -1,145 +0,0 @@
import { useState } from 'react';
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
import { SubHeading } from '../../../../components/heading';
import { useTranslation } from 'react-i18next';
import {
KeyValueTable,
KeyValueTableRow,
RoundedWrapper,
Tooltip,
} from '@vegaprotocol/ui-toolkit';
import { useNewTransferProposalDetails } from '@vegaprotocol/proposals';
import {
AccountTypeMapping,
DescriptionGovernanceTransferTypeMapping,
GovernanceTransferKindMapping,
GovernanceTransferTypeMapping,
} from '@vegaprotocol/types';
import {
addDecimalsFormatNumberQuantum,
formatDateWithLocalTimezone,
} from '@vegaprotocol/utils';
export const ProposalTransferDetails = ({
proposal,
}: {
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
}) => {
const { t } = useTranslation();
const [show, setShow] = useState(false);
const details = useNewTransferProposalDetails(proposal?.id);
if (!details) {
return null;
}
return (
<>
<CollapsibleToggle
toggleState={show}
setToggleState={setShow}
dataTestId="proposal-transfer-details"
>
<SubHeading title={t('proposalTransferDetails')} />
</CollapsibleToggle>
{show && (
<RoundedWrapper paddingBottom={true}>
<KeyValueTable data-testid="proposal-transfer-details-table">
{/* The source account */}
<KeyValueTableRow>
{t('Source')}
{details.source}
</KeyValueTableRow>
{/* The type of source account */}
<KeyValueTableRow>
{t('Source Type')}
{AccountTypeMapping[details.sourceType]}
</KeyValueTableRow>
{/* The destination account */}
<KeyValueTableRow>
{t('Destination')}
{details.destination}
</KeyValueTableRow>
{/* The type of destination account */}
<KeyValueTableRow>
{t('Destination Type')}
{AccountTypeMapping[details.destinationType]}
</KeyValueTableRow>
{/* The asset to transfer */}
<KeyValueTableRow>
{t('Asset')}
{details.asset.symbol}
</KeyValueTableRow>
{/*The fraction of the balance to be transfer */}
<KeyValueTableRow>
{t('Fraction Of Balance')}
{`${Number(details.fraction_of_balance) * 100}%`}
</KeyValueTableRow>
{/* The maximum amount to be transferred */}
<KeyValueTableRow>
{t('Amount')}
{addDecimalsFormatNumberQuantum(
details.amount,
details.asset.decimals,
details.asset.quantum
)}
</KeyValueTableRow>
{/* The type of the governance transfer */}
<KeyValueTableRow>
{t('Transfer Type')}
<Tooltip
description={
DescriptionGovernanceTransferTypeMapping[details.transferType]
}
>
<span>
{GovernanceTransferTypeMapping[details.transferType]}
</span>
</Tooltip>
</KeyValueTableRow>
{/* The type of governance transfer being made, i.e. a one-off or recurring trans */}
<KeyValueTableRow>
{t('Kind')}
{GovernanceTransferKindMapping[details.kind.__typename]}
</KeyValueTableRow>
{details.kind.__typename === 'OneOffGovernanceTransfer' &&
details.kind.deliverOn && (
<KeyValueTableRow noBorder={true}>
{t('Deliver On')}
{formatDateWithLocalTimezone(
new Date(details.kind.deliverOn)
)}
</KeyValueTableRow>
)}
{details.kind.__typename === 'RecurringGovernanceTransfer' && (
<>
<KeyValueTableRow noBorder={!details.kind.endEpoch}>
{t('Start On')}
<span>{details.kind.startEpoch}</span>
</KeyValueTableRow>
{details.kind.endEpoch && (
<KeyValueTableRow noBorder={true}>
{t('End on')}
{details.kind.endEpoch}
</KeyValueTableRow>
)}
</>
)}
</KeyValueTable>
</RoundedWrapper>
)}
</>
);
};
@@ -20,11 +20,6 @@ import { ProposalUpdateMarketState } from '../proposal-update-market-state';
import type { NetworkParamsResult } from '@vegaprotocol/network-parameters';
import { useVoteSubmit } from '@vegaprotocol/proposals';
import { useUserVote } from '../vote-details/use-user-vote';
import {
ProposalCancelTransferDetails,
ProposalTransferDetails,
} from '../proposal-transfer';
import { FLAGS } from '@vegaprotocol/environment';
export interface ProposalProps {
proposal: ProposalQuery['proposal'];
@@ -104,37 +99,9 @@ export const Proposal = ({
minVoterBalance =
networkParams.governance_proposal_freeform_minVoterBalance;
break;
case 'NewTransfer':
// TODO: check minVoterBalance for 'NewTransfer'
minVoterBalance =
networkParams.governance_proposal_freeform_minVoterBalance;
break;
case 'CancelTransfer':
// TODO: check minVoterBalance for 'CancelTransfer'
minVoterBalance =
networkParams.governance_proposal_freeform_minVoterBalance;
}
}
// Show governance transfer details only if the GOVERNANCE_TRANSFERS flag is on.
const governanceTransferDetails = FLAGS.GOVERNANCE_TRANSFERS && (
<>
{proposal.terms.change.__typename === 'NewTransfer' && (
/** Governance New Transfer Details */
<div className="mb-4">
<ProposalTransferDetails proposal={proposal} />
</div>
)}
{proposal.terms.change.__typename === 'CancelTransfer' && (
/** Governance Cancel Transfer Details */
<div className="mb-4">
<ProposalCancelTransferDetails proposal={proposal} />
</div>
)}
</>
);
return (
<section data-testid="proposal">
<div className="flex items-center gap-1 mb-6">
@@ -220,8 +187,6 @@ export const Proposal = ({
</div>
)}
{governanceTransferDetails}
<div className="mb-10">
<RoundedWrapper paddingBottom={true}>
<UserVote
@@ -4,7 +4,7 @@ import {
getProposalDialogTitle,
} from '@vegaprotocol/proposals';
import type { ProposalEventFieldsFragment } from '@vegaprotocol/proposals';
import type { DialogProps } from '@vegaprotocol/proposals';
import type { DialogProps } from '@vegaprotocol/wallet';
interface ProposalFormTransactionDialogProps {
finalizedProposal: ProposalEventFieldsFragment | null;
@@ -6,7 +6,7 @@ import { ConnectToVega } from '../../../../components/connect-to-vega';
import { VoteButtonsContainer } from './vote-buttons';
import { SubHeading } from '../../../../components/heading';
import type { VoteValue } from '@vegaprotocol/types';
import type { DialogProps, VegaTxState } from '@vegaprotocol/proposals';
import type { DialogProps, VegaTxState } from '@vegaprotocol/wallet';
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import type { VoteState } from './use-user-vote';
@@ -1,7 +1,7 @@
import { render, screen } from '@testing-library/react';
import { VoteTransactionDialog } from './vote-transaction-dialog';
import { VoteState } from './use-user-vote';
import { VegaTxStatus } from '@vegaprotocol/proposals';
import { VegaTxStatus } from '@vegaprotocol/wallet';
describe('VoteTransactionDialog', () => {
const mockTransactionDialog = jest.fn(({ title, content }) => (
@@ -17,7 +17,7 @@ import { VoteState } from './use-user-vote';
import { ProposalMinRequirements, ProposalUserAction } from '../shared';
import { VoteTransactionDialog } from './vote-transaction-dialog';
import { useVoteButtonsQuery } from './__generated__/Stake';
import type { DialogProps, VegaTxState } from '@vegaprotocol/proposals';
import type { DialogProps, VegaTxState } from '@vegaprotocol/wallet';
interface VoteButtonsContainerProps {
voteState: VoteState | null;
@@ -1,6 +1,6 @@
import { t } from '@vegaprotocol/i18n';
import { VoteState } from './use-user-vote';
import type { DialogProps, VegaTxState } from '@vegaprotocol/proposals';
import type { DialogProps, VegaTxState } from '@vegaprotocol/wallet';
interface VoteTransactionDialogProps {
voteState: VoteState;
@@ -61,7 +61,7 @@ describe('home', { tags: '@regression' }, () => {
// 0006-NETW-020
cy.getByTestId(nodeHealthTrigger).click();
cy.getByTestId('connect').should('be.disabled');
cy.getByTestId('node-url-custom').click({ force: true });
cy.getByTestId('node-url-custom').click();
cy.getByTestId('connect').should('be.disabled');
cy.get("input[placeholder='https://']")
.focus()
@@ -58,7 +58,7 @@ describe('Market trading page', () => {
// 6002-MDET-003
cy.getByTestId(marketSummaryBlock).within(() => {
cy.getByTestId(marketPrice).within(() => {
cy.getByTestId(itemHeader).should('have.text', 'Mark Price');
cy.getByTestId(itemHeader).should('have.text', 'Price');
cy.getByTestId(itemValue).should('not.be.empty');
});
});
@@ -0,0 +1,179 @@
import { checkSorting } from '@vegaprotocol/cypress';
const dialogClose = 'dialog-close';
describe('accounts', { tags: '@smoke' }, () => {
beforeEach(() => {
cy.mockTradingPage();
cy.mockWeb3Provider();
cy.mockSubscription();
cy.setVegaWallet();
cy.visit('/#/markets/market-0');
});
it('renders accounts', () => {
// 7001-COLL-001
// 7001-COLL-002
// 7001-COLL-003
// 7001-COLL-004
// 7001-COLL-005
// 7001-COLL-006
// 7001-COLL-007
// 1003-TRAN-001
// 7001-COLL-012
const tradingAccountRowId = '[row-id="t-0"]';
cy.getByTestId('Collateral').click();
cy.getByTestId('tab-accounts').should('be.visible');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="asset.symbol"]')
.should('have.text', 'AST0');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="used"]')
.should('have.text', '1.01' + '1.00%');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="available"]')
.should('have.text', '100.00');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="total"]')
.should('have.text', '101.01');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="accounts-actions"]')
.should('have.text', '');
cy.getByTestId('tab-accounts')
.get('[col-id="accounts-actions"]')
.find('[data-testid="dropdown-menu"]')
.eq(1)
.click();
cy.getByTestId('deposit').should('be.visible');
cy.getByTestId('withdraw').should('be.visible');
cy.getByTestId('transfer').should('be.visible');
cy.getByTestId('breakdown').should('be.visible');
cy.getByTestId('Collateral').click({ force: true });
});
it('should open usage breakdown dialog when clicked on used', () => {
// 7001-COLL-009
cy.get('[col-id="used"]').contains('1.01').click();
const headers = ['Market', 'Account type', 'Balance', 'Margin health'];
cy.getByTestId('usage-breakdown').within(($headers) => {
cy.wrap($headers)
.get('.ag-header-cell-text')
.each(($header, i) => {
cy.wrap($header).should('have.text', headers[i]);
});
});
cy.getByTestId(dialogClose).click();
});
describe('sorting by ag-grid columns should work well', () => {
before(() => {
const dialogs = Cypress.$('[data-testid="dialog-close"]:visible');
if (dialogs.length > 0) {
dialogs.each((btn) => {
cy.wrap(btn).click();
});
}
cy.contains('Loading...').should('not.exist');
});
// 7001-COLL-010
it('sorting by asset', () => {
cy.getByTestId('Collateral').click();
const marketsSortedDefault = ['tBTC', 'tEURO', 'tDAI', 'tBTC'];
const marketsSortedAsc = ['tBTC', 'tBTC', 'tDAI', 'tEURO'];
const marketsSortedDesc = Array.from(marketsSortedAsc).reverse();
checkSorting(
'asset.symbol',
marketsSortedDefault,
marketsSortedAsc,
marketsSortedDesc
);
});
it('sorting by total', () => {
cy.getByTestId('Collateral').click();
const marketsSortedDefault = [
'1,000.00002',
'1,000.01',
'1,000.00',
'1,000.00001',
];
const marketsSortedAsc = [
'1,000.00',
'1,000.00001',
'1,000.00002',
'1,000.01',
];
const marketsSortedDesc = Array.from(marketsSortedAsc).reverse();
checkSorting(
'total',
marketsSortedDefault,
marketsSortedAsc,
marketsSortedDesc
);
});
it('sorting by used', () => {
cy.getByTestId('Collateral').click();
// concat actual value with percentage value
// as cypress will pick up the entire cell contes
// textContent
const marketsSortedDefault = [
'0.00' + '0.00%',
'0.01' + '0.00%',
'0.00' + '0.00%',
'0.00' + '0.00%',
];
const marketsSortedAsc = [
'0.00' + '0.00%',
'0.00' + '0.00%',
'0.00' + '0.00%',
'0.01' + '0.00%',
];
const marketsSortedDesc = Array.from(marketsSortedAsc).reverse();
checkSorting(
'used',
marketsSortedDefault,
marketsSortedAsc,
marketsSortedDesc
);
});
it('sorting by available', () => {
cy.getByTestId('Collateral').click();
const marketsSortedDefault = [
'1,000.00002',
'1,000.00',
'1,000.00',
'1,000.00001',
];
const marketsSortedAsc = [
'1,000.00',
'1,000.00',
'1,000.00001',
'1,000.00002',
];
const marketsSortedDesc = Array.from(marketsSortedAsc).reverse();
checkSorting(
'available',
marketsSortedDefault,
marketsSortedAsc,
marketsSortedDesc
);
});
});
});
@@ -1,11 +1,92 @@
import * as Schema from '@vegaprotocol/types';
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import {
accountsQuery,
amendGeneralAccountBalance,
amendMarginAccountBalance,
} from '@vegaprotocol/mock';
import type { OrderSubmission } from '@vegaprotocol/wallet';
import { createOrder } from '../support/create-order';
describe(
'vega wallet - prompt',
describe.skip(
'account validation',
{ tags: '@regression', testIsolation: true },
() => {
describe.skip('zero balance error', () => {
beforeEach(() => {
cy.setVegaWallet();
cy.mockTradingPage();
let accounts = accountsQuery();
accounts = amendMarginAccountBalance(accounts, 'market-0', '1000');
accounts = amendGeneralAccountBalance(accounts, 'market-0', '0');
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Accounts', accounts);
});
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
it('should show an error if your balance is zero', () => {
const accounts = accountsQuery();
amendMarginAccountBalance(accounts, 'market-0', '0');
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Accounts', accounts);
});
// 7002-SORD-060
cy.getByTestId('place-order').should('be.enabled');
// 7002-SORD-003
cy.getByTestId('deal-ticket-error-message-zero-balance').should(
'have.text',
'You need ' +
'tDAI' +
' in your wallet to trade in this market. See all your collateral.Make a deposit'
);
cy.getByTestId('deal-ticket-deposit-dialog-button').should('exist');
});
});
describe('not enough balance warning', () => {
beforeEach(() => {
cy.setVegaWallet();
cy.mockTradingPage();
let accounts = accountsQuery();
accounts = amendMarginAccountBalance(accounts, 'market-0', '1000');
accounts = amendGeneralAccountBalance(accounts, 'market-0', '1');
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Accounts', accounts);
});
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
cy.get('[data-testid="deal-ticket-form"]').then(($form) => {
if (!$form.length) {
cy.getByTestId('Order').click();
}
});
});
it('should display info and button for deposit', () => {
// 7002-SORD-003
// warning should show immediately
cy.getByTestId('deal-ticket-warning-margin').should(
'contain.text',
'You may not have enough margin available to open this position'
);
cy.getByTestId('deal-ticket-warning-margin').should(
'contain.text',
'You may not have enough margin available to open this position. 5.00 tDAI is currently required. You have only 0.01001 tDAI available.'
);
cy.getByTestId('deal-ticket-deposit-dialog-button').click();
cy.getByTestId('sidebar-content')
.find('h2')
.eq(0)
.should('have.text', 'Deposit');
});
});
describe('must submit order', { tags: '@smoke' }, () => {
// 7002-SORD-039
beforeEach(() => {
+4 -1
View File
@@ -7,6 +7,7 @@ import {
assetQuery,
assetsQuery,
candlesQuery,
chainIdQuery,
chartQuery,
depositsQuery,
estimateFeesQuery,
@@ -24,6 +25,7 @@ import {
estimatePositionQuery,
positionsQuery,
proposalListQuery,
statisticsQuery,
tradesQuery,
withdrawalsQuery,
protocolUpgradeProposalsQuery,
@@ -89,6 +91,8 @@ const mockTradingPage = (
tradingMode?: Schema.MarketTradingMode,
trigger?: Schema.AuctionTrigger
) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'NodeCheck', statisticsQuery());
aliasGQLQuery(req, 'NodeGuard', nodeGuardQuery());
aliasGQLQuery(
req,
@@ -214,7 +218,6 @@ export const addMockTradingPage = () => {
trigger,
oracleStatus
) => {
cy.mockChainId();
cy.mockGQL((req) => {
mockTradingPage(req, state, tradingMode, trigger);
});
-1
View File
@@ -16,7 +16,6 @@ NX_VEGA_CONSOLE_URL=https://console.vega.xyz
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-mainnet/codfcglpplgmmlokgilfkpcjnmkbfiel
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-mainnet
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
+1 -1
View File
@@ -16,7 +16,7 @@ NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
-1
View File
@@ -17,7 +17,6 @@ NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
@@ -1,5 +0,0 @@
import MarketPage from '../market';
export const ClosedMarketPage = () => {
return <MarketPage closed />;
};
@@ -1 +0,0 @@
export { ClosedMarketPage as default } from './closed-market';
@@ -1,10 +1,9 @@
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import { DocsLinks, useEnvironment } from '@vegaprotocol/environment';
import { ButtonLink, ExternalLink, Link } from '@vegaprotocol/ui-toolkit';
import { useEnvironment } from '@vegaprotocol/environment';
import { ButtonLink, Link } from '@vegaprotocol/ui-toolkit';
import { MarketProposalNotification } from '@vegaprotocol/proposals';
import type { Market } from '@vegaprotocol/markets';
import {
addDecimalsFormatNumber,
fromNanoSeconds,
getExpiryDate,
getMarketExpiryDate,
@@ -18,7 +17,6 @@ import {
marketInfoProvider,
useFundingPeriodsQuery,
useFundingRate,
useExternalTwap,
} from '@vegaprotocol/markets';
import { MarketState as State } from '@vegaprotocol/types';
import { HeaderStat } from '../../components/header';
@@ -28,7 +26,6 @@ import { MarketState } from '../../components/market-state';
import { MarketLiquiditySupplied } from '../../components/liquidity-supplied';
import { useEffect, useState } from 'react';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { PriceCell } from '@vegaprotocol/datagrid';
interface MarketHeaderStatsProps {
market: Market;
@@ -41,8 +38,34 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
const asset = getAsset(market);
return (
<div className="flex gap-8">
<HeaderStat heading={t('Mark Price')} testId="market-price">
<>
{market.tradableInstrument.instrument.product.__typename === 'Future' && (
<HeaderStat
heading={t('Expiry')}
description={
<ExpiryTooltipContent
market={market}
explorerUrl={VEGA_EXPLORER_URL}
/>
}
testId="market-expiry"
>
<ExpiryLabel market={market} />
</HeaderStat>
)}
{market.tradableInstrument.instrument.product.__typename ===
'Perpetual' && (
<HeaderStat
heading={`${t('Funding')} / ${t('Countdown')}`}
testId="market-funding"
>
<div className="flex justify-between gap-2">
<FundingRate marketId={market.id} />
<FundingCountdown marketId={market.id} />
</div>
</HeaderStat>
)}
<HeaderStat heading={t('Price')} testId="market-price">
<MarketMarkPrice
marketId={market.id}
decimalPlaces={market.decimalPlaces}
@@ -85,64 +108,8 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
marketId={market.id}
assetDecimals={asset?.decimals || 0}
/>
{market.tradableInstrument.instrument.product.__typename === 'Future' && (
<HeaderStat
heading={t('Expiry')}
description={
<ExpiryTooltipContent
market={market}
explorerUrl={VEGA_EXPLORER_URL}
/>
}
testId="market-expiry"
>
<ExpiryLabel market={market} />
</HeaderStat>
)}
{market.tradableInstrument.instrument.product.__typename ===
'Perpetual' && (
<HeaderStat
heading={`${t('Funding Rate')} / ${t('Countdown')}`}
testId="market-funding"
>
<div className="flex justify-between gap-2">
<FundingRate marketId={market.id} />
<FundingCountdown marketId={market.id} />
</div>
</HeaderStat>
)}
{market.tradableInstrument.instrument.product.__typename ===
'Perpetual' && (
<HeaderStat
heading={`${t('Index Price')}`}
description={
<div className="p1">
{t(
'The external time weighted average price (TWAP) received from the data source defined in the data sourcing specification.'
)}
{DocsLinks && (
<ExternalLink
href={DocsLinks.ETH_DATA_SOURCES}
className="mt-2"
>
{t('Find out more')}
</ExternalLink>
)}
</div>
}
testId="index-price"
>
<IndexPrice
marketId={market.id}
decimalPlaces={
market.tradableInstrument.instrument.product.settlementAsset
.decimals
}
/>
</HeaderStat>
)}
<MarketProposalNotification marketId={market.id} />
</div>
</>
);
};
@@ -159,24 +126,6 @@ export const FundingRate = ({ marketId }: { marketId: string }) => {
);
};
export const IndexPrice = ({
marketId,
decimalPlaces,
}: {
marketId: string;
decimalPlaces?: number;
}) => {
const { data: externalTwap } = useExternalTwap(marketId);
return externalTwap && decimalPlaces ? (
<PriceCell
value={Number(externalTwap)}
valueFormatted={addDecimalsFormatNumber(externalTwap, decimalPlaces)}
/>
) : (
'-'
);
};
const useNow = () => {
const [now, setNow] = useState(Date.now());
useEffect(() => {
+6 -24
View File
@@ -9,10 +9,9 @@ import { useGlobalStore, usePageTitleStore } from '../../stores';
import { TradeGrid } from './trade-grid';
import { TradePanels } from './trade-panels';
import { useNavigate, useParams } from 'react-router-dom';
import { Links, Routes } from '../../lib/links';
import { Links } from '../../lib/links';
import { ViewType, useSidebar } from '../../components/sidebar';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
import { MarketState } from '@vegaprotocol/types';
const calculatePrice = (markPrice?: string, decimalPlaces?: number) => {
return markPrice && decimalPlaces
@@ -57,7 +56,7 @@ const TitleUpdater = ({
return null;
};
export const MarketPage = ({ closed }: { closed?: boolean }) => {
export const MarketPage = () => {
const { marketId } = useParams();
const navigate = useNavigate();
const currentRouteId = useGetCurrentRouteId();
@@ -71,33 +70,16 @@ export const MarketPage = ({ closed }: { closed?: boolean }) => {
const { data, error, loading } = useMarket(marketId);
useEffect(() => {
if (
data?.state &&
[
MarketState.STATE_SETTLED,
MarketState.STATE_TRADING_TERMINATED,
].includes(data.state) &&
currentRouteId !== Routes.CLOSED_MARKETS &&
marketId
) {
navigate(Links.CLOSED_MARKETS(marketId));
}
}, [data?.state, currentRouteId, navigate, marketId]);
useEffect(() => {
if (data?.id && data.id !== lastMarketId && !closed) {
if (data?.id && data.id !== lastMarketId) {
update({ marketId: data.id });
}
}, [update, lastMarketId, data?.id, closed]);
}, [update, lastMarketId, data?.id]);
useEffect(() => {
if (largeScreen && view === undefined) {
setViews(
{ type: closed ? ViewType.Info : ViewType.Order },
currentRouteId
);
setViews({ type: ViewType.Order }, currentRouteId);
}
}, [setViews, view, currentRouteId, largeScreen, closed]);
}, [setViews, view, currentRouteId, largeScreen]);
const pinnedAsset = data && getAsset(data);
@@ -136,10 +136,7 @@ const MainGrid = memo(
</Tab>
) : null}
<Tab id="fills" name={t('Fills')}>
<TradingViews.fills.component />
</Tab>
<Tab id="funding-payments" name={t('Funding payments')}>
<TradingViews.fundingPayments.component />
<TradingViews.fills.component marketId={marketId} />
</Tab>
<Tab
id="accounts"
@@ -14,7 +14,6 @@ import { PositionsContainer } from '../../components/positions-container';
import { AccountsContainer } from '../../components/accounts-container';
import { LiquidityContainer } from '../../components/liquidity-container';
import { FundingContainer } from '../../components/funding-container';
import { FundingPaymentsContainer } from '../../components/funding-payments-container';
import type { OrderContainerProps } from '../../components/orders-container';
import { OrdersContainer } from '../../components/orders-container';
import { StopOrdersContainer } from '../../components/stop-orders-container';
@@ -56,10 +55,6 @@ export const TradingViews = {
label: 'Funding',
component: requiresMarket(FundingContainer),
},
fundingPayments: {
label: 'Funding Payments',
component: FundingPaymentsContainer,
},
orderbook: {
label: 'Orderbook',
component: requiresMarket(OrderbookContainer),
@@ -1,4 +1,4 @@
import { act, render, screen, waitFor, within } from '@testing-library/react';
import { act, render, screen, within } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { Closed } from './closed';
import { MarketStateMapping, PropertyKeyType } from '@vegaprotocol/types';
@@ -300,11 +300,9 @@ describe('Closed', () => {
].includes(m.node.state);
});
await waitFor(() => {
// check rows length is correct
const rows = container.getAllByRole('row');
expect(rows).toHaveLength(expectedRows.length);
});
// check rows length is correct
const rows = container.getAllByRole('row');
expect(rows).toHaveLength(expectedRows.length);
// check that only included ids are shown
const cells = screen
@@ -22,8 +22,6 @@ import { SettlementPriceCell } from './settlement-price-cell';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { MarketCodeCell } from './market-code-cell';
import { MarketActionsDropdown } from './market-table-actions';
import type { CellClickedEvent } from 'ag-grid-community';
import { useClosedMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
type SettlementAsset = Pick<
Asset,
@@ -127,7 +125,6 @@ const ClosedMarketsDataGrid = ({
rowData: Row[];
error: Error | undefined;
}) => {
const handleOnSelect = useClosedMarketClickHandler();
const openAssetDialog = useAssetDetailsDialogStore((store) => store.open);
const colDefs = useMemo(() => {
@@ -284,27 +281,6 @@ const ClosedMarketsDataGrid = ({
overlayNoRowsTemplate={error ? error.message : t('No markets')}
components={components}
rowHeight={45}
onCellClicked={({ data, column, event }: CellClickedEvent<Row>) => {
if (!data) return;
// prevent navigating to the market page if any of the below cells are clicked
// event.preventDefault or event.stopPropagation dont seem to apply for aggird
const colId = column.getColId();
if (
[
'settlementDate',
'settlementDataOracleId',
'settlementAsset',
'market-actions',
].includes(colId)
) {
return;
}
// @ts-ignore metaKey exists
handleOnSelect(data.id, event ? event.metaKey : false);
}}
/>
);
};
@@ -9,9 +9,7 @@ import { usePageTitleStore } from '../../stores';
import { AccountsContainer } from '../../components/accounts-container';
import { DepositsContainer } from '../../components/deposits-container';
import { FillsContainer } from '../../components/fills-container';
import { FundingPaymentsContainer } from '../../components/funding-payments-container';
import { PositionsContainer } from '../../components/positions-container';
import { PositionsMenu } from '../../components/positions-menu';
import { WithdrawalsContainer } from '../../components/withdrawals-container';
import { OrdersContainer } from '../../components/orders-container';
import { LedgerContainer } from '../../components/ledger-container';
@@ -70,11 +68,7 @@ export const Portfolio = () => {
<Tab id="account-history" name={t('Account history')}>
<AccountHistoryContainer />
</Tab>
<Tab
id="positions"
name={t('Positions')}
menu={<PositionsMenu />}
>
<Tab id="positions" name={t('Positions')}>
<PositionsContainer allKeys />
</Tab>
<Tab id="orders" name={t('Orders')}>
@@ -83,9 +77,6 @@ export const Portfolio = () => {
<Tab id="fills" name={t('Fills')}>
<FillsContainer />
</Tab>
<Tab id="funding-payments" name={t('Funding payments')}>
<FundingPaymentsContainer />
</Tab>
<Tab id="ledger-entries" name={t('Ledger entries')}>
<LedgerContainer />
</Tab>
@@ -10,10 +10,12 @@ import classNames from 'classnames';
import { Navigate, useSearchParams } from 'react-router-dom';
import { useEffect, useRef, useState } from 'react';
import { Button } from './buttons';
import { useVegaWallet } from '@vegaprotocol/wallet';
import {
useTransactionEventSubscription,
useVegaWallet,
} from '@vegaprotocol/wallet';
import { useReferral } from './hooks/use-referral';
import { Routes } from '../../lib/links';
import { useTransactionEventSubscription } from '@vegaprotocol/web3';
export const ApplyCodeForm = () => {
const [status, setStatus] = useState<
@@ -9,7 +9,7 @@ import type { DataGridSlice } from '../../stores/datagrid-store-slice';
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
export const FillsContainer = () => {
export const FillsContainer = ({ marketId }: { marketId?: string }) => {
const onMarketClick = useMarketClickHandler(true);
const { pubKey } = useVegaWallet();
@@ -31,6 +31,7 @@ export const FillsContainer = () => {
return (
<FillsManager
partyId={pubKey}
marketId={marketId}
onMarketClick={onMarketClick}
gridProps={gridStoreCallbacks}
/>
@@ -1,46 +0,0 @@
import { useVegaWallet } from '@vegaprotocol/wallet';
import { FundingPaymentsManager } from '@vegaprotocol/funding-payments';
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { useDataGridEvents } from '@vegaprotocol/datagrid';
import { t } from '@vegaprotocol/i18n';
import { Splash } from '@vegaprotocol/ui-toolkit';
import type { DataGridSlice } from '../../stores/datagrid-store-slice';
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
export const FundingPaymentsContainer = () => {
const onMarketClick = useMarketClickHandler(true);
const { pubKey } = useVegaWallet();
const gridStore = useFundingPaymentsStore((store) => store.gridStore);
const updateGridStore = useFundingPaymentsStore(
(store) => store.updateGridStore
);
const gridStoreCallbacks = useDataGridEvents(gridStore, (colState) => {
updateGridStore(colState);
});
if (!pubKey) {
return (
<Splash>
<p>{t('Please connect Vega wallet')}</p>
</Splash>
);
}
return (
<FundingPaymentsManager
partyId={pubKey}
onMarketClick={onMarketClick}
gridProps={gridStoreCallbacks}
/>
);
};
const useFundingPaymentsStore = create<DataGridSlice>()(
persist(createDataGridSlice, {
name: 'vega_funding_payments_store',
})
);
@@ -1 +0,0 @@
export * from './funding-payments-container';
@@ -23,10 +23,6 @@ export const LayoutWithSidebar = () => {
<div className="col-span-full">
<Routes>
<Route path="markets/:marketId" element={<MarketHeader />} />
<Route
path="markets/all/closed/:marketId"
element={<MarketHeader />}
/>
<Route path="liquidity/:marketId" element={<LiquidityHeader />} />
</Routes>
</div>
@@ -135,21 +135,6 @@ export const Sidebar = () => {
</>
}
/>
<Route
path="markets/all/closed/:marketId"
element={
<>
<AssetSidebarButtons />
<SidebarDivider />
<SidebarButton
view={ViewType.Info}
icon={VegaIconNames.BREAKDOWN}
tooltip={t('Market specification')}
routeId={currentRouteId}
/>
</>
}
/>
</Routes>
</nav>
<nav className={classNames(navClasses, 'ml-auto lg:mt-auto lg:ml-0')}>
@@ -1,6 +1,6 @@
import { useVegaWallet } from '@vegaprotocol/wallet';
import { WithdrawFormContainer } from '@vegaprotocol/withdraws';
import { useVegaTransactionStore } from '@vegaprotocol/web3';
import { useVegaTransactionStore } from '@vegaprotocol/wallet';
export const WithdrawContainer = ({ assetId }: { assetId?: string }) => {
const { pubKey } = useVegaWallet();
@@ -20,16 +20,3 @@ export const useMarketLiquidityClickHandler = () => {
window.open(`/#/liquidity/${selectedId}`, metaKey ? '_blank' : '_self');
}, []);
};
export const useClosedMarketClickHandler = (replace = false) => {
const navigate = useNavigate();
return (selectedId: string, metaKey?: boolean) => {
const link = Links.CLOSED_MARKETS(selectedId);
if (metaKey) {
window.open(`/#${link}`, '_blank');
} else {
navigate(link, { replace });
}
};
};
-3
View File
@@ -5,7 +5,6 @@ import trimEnd from 'lodash/trimEnd';
export const Routes = {
HOME: '/',
MARKETS: '/markets/all',
CLOSED_MARKETS: '/markets/all/closed/:marketId',
MARKET: '/markets/:marketId',
LIQUIDITY: '/liquidity/:marketId',
PORTFOLIO: '/portfolio',
@@ -29,8 +28,6 @@ export const Links: ConsoleLinks = {
MARKET: (marketId: string) =>
trimEnd(Routes.MARKET.replace(':marketId', marketId)),
MARKETS: () => Routes.MARKETS,
CLOSED_MARKETS: (marketId: string) =>
trimEnd(Routes.CLOSED_MARKETS.replace(':marketId', marketId)),
PORTFOLIO: () => Routes.PORTFOLIO,
LIQUIDITY: (marketId: string) =>
trimEnd(Routes.LIQUIDITY.replace(':marketId', marketId)),
+2 -4
View File
@@ -4,12 +4,10 @@ import type { AppProps } from 'next/app';
import { t } from '@vegaprotocol/i18n';
import {
useEagerConnect as useVegaEagerConnect,
useVegaWallet,
} from '@vegaprotocol/wallet';
import {
useVegaTransactionManager,
useVegaTransactionUpdater,
} from '@vegaprotocol/web3';
useVegaWallet,
} from '@vegaprotocol/wallet';
import {
useEagerConnect as useEthereumEagerConnect,
useEthTransactionManager,
-6
View File
@@ -26,7 +26,6 @@ import { FLAGS } from '@vegaprotocol/environment';
// These must remain dynamically imported as pennant cannot be compiled by nextjs due to ESM
// Using dynamic imports is a workaround for this until pennant is published as ESM
const MarketPage = lazy(() => import('../client-pages/market'));
const ClosedMarketPage = lazy(() => import('../client-pages/closed-market'));
const Portfolio = lazy(() => import('../client-pages/portfolio'));
const NotFound = () => (
@@ -102,11 +101,6 @@ export const routerConfig: RouteObject[] = compact([
element: <MarketPage />,
id: Routes.MARKET,
},
{
path: 'all/closed/:marketId',
element: <ClosedMarketPage />,
id: Routes.CLOSED_MARKETS,
},
],
},
{
@@ -1,75 +0,0 @@
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { AccountsActionsDropdown } from './accounts-actions-dropdown';
import userEvent from '@testing-library/user-event';
describe('AccountsActionsDropdown', () => {
let onClickDeposit: jest.Mock;
let onClickWithdraw: jest.Mock;
let onClickBreakdown: jest.Mock;
let onClickTransfer: jest.Mock;
beforeEach(() => {
onClickDeposit = jest.fn();
onClickWithdraw = jest.fn();
onClickBreakdown = jest.fn();
onClickTransfer = jest.fn();
});
it('should render dropdown items correctly', async () => {
// 7001-COLL-005
// 7001-COLL-006
// 1003-TRAN-001
render(
<AccountsActionsDropdown
assetId="testAssetId"
assetContractAddress="testAssetContractAddress"
onClickDeposit={onClickDeposit}
onClickWithdraw={onClickWithdraw}
onClickBreakdown={onClickBreakdown}
onClickTransfer={onClickTransfer}
/>
);
await userEvent.click(screen.getByTestId('icon-kebab'));
expect(screen.getByTestId('deposit')).toHaveTextContent('Deposit');
expect(screen.getByTestId('withdraw')).toHaveTextContent('Withdraw');
expect(screen.getByTestId('transfer')).toHaveTextContent('Transfer');
expect(screen.getByTestId('breakdown')).toHaveTextContent(
'View usage breakdown'
);
expect(screen.getByText('View asset details')).toBeInTheDocument();
expect(screen.getByText('Copy asset ID')).toBeInTheDocument();
expect(screen.getByText('View on Etherscan')).toBeInTheDocument();
});
it('should call callback functions on click', async () => {
render(
<AccountsActionsDropdown
assetId="testAssetId"
assetContractAddress="testAssetContractAddress"
onClickDeposit={onClickDeposit}
onClickWithdraw={onClickWithdraw}
onClickBreakdown={onClickBreakdown}
onClickTransfer={onClickTransfer}
/>
);
await userEvent.click(screen.getByTestId('icon-kebab'));
await userEvent.click(screen.getByTestId('deposit'));
expect(onClickDeposit).toHaveBeenCalledTimes(1);
await userEvent.click(screen.getByTestId('icon-kebab'));
await userEvent.click(screen.getByTestId('withdraw'));
expect(onClickWithdraw).toHaveBeenCalledTimes(1);
await userEvent.click(screen.getByTestId('icon-kebab'));
await userEvent.click(screen.getByTestId('transfer'));
expect(onClickTransfer).toHaveBeenCalledTimes(1);
await userEvent.click(screen.getByTestId('icon-kebab'));
await userEvent.click(screen.getByTestId('breakdown'));
expect(onClickBreakdown).toHaveBeenCalledTimes(1);
});
});
@@ -3,7 +3,6 @@ import * as Types from '@vegaprotocol/types';
import type { AccountFields } from './accounts-data-provider';
import { getAccountData } from './accounts-data-provider';
import { AccountTable } from './accounts-table';
import userEvent from '@testing-library/user-event';
const singleRow = {
__typename: 'AccountBalance',
@@ -25,35 +24,8 @@ const singleRow = {
} as AccountFields;
const singleRowData = [singleRow];
const secondRow = {
__typename: 'AccountBalance',
type: Types.AccountType.ACCOUNT_TYPE_MARGIN,
balance: '125600002',
market: {
__typename: 'Market',
id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35',
},
asset: {
__typename: 'Asset',
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
symbol: 'aBTC',
decimals: 5,
},
available: '125600001',
used: '125600001',
total: '251200002',
} as AccountFields;
const multiRowData = [singleRow, secondRow];
describe('AccountsTable', () => {
it('should render correct columns', async () => {
// 7001-COLL-001
// 7001-COLL-002
// 7001-COLL-003
// 7001-COLL-004
// 7001-COLL-007
// 1003-TRAN-001
// 7001-COLL-012
await act(async () => {
render(
<AccountTable
@@ -89,25 +61,6 @@ describe('AccountsTable', () => {
expect(rows?.childElementCount).toBe(1);
});
it('should sort assets', async () => {
// 7001-COLL-010
const { container } = render(
<AccountTable
rowData={multiRowData}
onClickAsset={() => null}
isReadOnly={false}
/>
);
const headerCell = screen.getByText('Asset');
await userEvent.click(headerCell);
const rows = container.querySelectorAll(
'.ag-center-cols-container .ag-row'
);
expect(rows[0].textContent).toContain('aBTC');
expect(rows[1].textContent).toContain('tBTC');
});
it('should apply correct formatting in view as user mode', async () => {
const { container } = render(
<AccountTable
@@ -37,7 +37,6 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
headerName: t('Market'),
field: 'market.tradableInstrument.instrument.code',
minWidth: 200,
sort: 'desc',
cellRenderer: ({
value,
data,
@@ -141,7 +140,6 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
tooltipShowDelay={500}
defaultColDef={defaultColDef}
columnDefs={coldefs}
domLayout="autoHeight"
/>
);
}
+1 -2
View File
@@ -7,8 +7,7 @@ import {
} from '@vegaprotocol/network-parameters';
import { useDataProvider } from '@vegaprotocol/data-provider';
import type { Transfer } from '@vegaprotocol/wallet';
import { useVegaTransactionStore } from '@vegaprotocol/web3';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useVegaTransactionStore, useVegaWallet } from '@vegaprotocol/wallet';
import { useCallback, useMemo } from 'react';
import { accountsDataProvider } from './accounts-data-provider';
import { TransferForm } from './transfer-form';
+15 -15
View File
@@ -258,21 +258,21 @@ export const TransferForm = ({
)}
</TradingFormGroup>
<div className="mb-4">
<Tooltip
description={t(
`The fee will be taken from the amount you are transferring.`
)}
>
<div>
<TradingCheckbox
name="include-transfer-fee"
disabled={!transferAmount}
label={t('Include transfer fee')}
checked={includeFee}
onCheckedChange={() => setIncludeFee(!includeFee)}
/>
</div>
</Tooltip>
<TradingCheckbox
name="include-transfer-fee"
disabled={!transferAmount}
label={
<Tooltip
description={t(
`The fee will be taken from the amount you are transferring.`
)}
>
<div>{t('Include transfer fee')}</div>
</Tooltip>
}
checked={includeFee}
onCheckedChange={() => setIncludeFee(!includeFee)}
/>
</div>
{transferAmount && fee && (
<TransferFee
+1 -1
View File
@@ -10,7 +10,6 @@ export * from '../deposits/src/lib/deposit.mock';
export * from '../environment/src/utils/node.mock';
export * from '../environment/src/components/node-guard/node-guard.mock';
export * from '../fills/src/lib/fills.mock';
export * from '../funding-payments/src/lib/funding-payments.mock';
export * from '../proposals/src/lib/proposals-data-provider/proposals.mock';
export * from '../market-depth/src/lib/market-depth.mock';
export * from '../markets/src/lib/components/market-info/market-info.mock';
@@ -23,6 +22,7 @@ export * from '../markets/src/lib/oracle-spec-data-connection.mock';
export * from '../orders/src/lib/components/order-data-provider/orders.mock';
export * from '../positions/src/lib/positions.mock';
export * from '../network-parameters/src/network-params.mock';
export * from '../wallet/src/connect-dialog/chain-id.mock';
export * from '../positions/src/lib/estimate-position.mock';
export * from '../trades/src/lib/trades.mock';
export * from '../withdraws/src/lib/withdrawal.mock';
+1 -2
View File
@@ -1,5 +1,5 @@
import { addGetTestIdcommand } from './lib/commands/get-by-test-id';
import { addMockGQLCommand, addMockStatistics } from './lib/mock-gql';
import { addMockGQLCommand } from './lib/mock-gql';
import { addMockSubscription } from './lib/mock-ws';
import { addMockWalletCommand } from './lib/mock-rest';
import { addMockWeb3ProviderCommand } from './lib/commands/mock-web3-provider';
@@ -28,7 +28,6 @@ import { addMockChainId } from './lib/commands/mock-chain-id';
addGetTestIdcommand();
addMockGQLCommand();
addMockStatistics();
addMockSubscription();
addMockWalletCommand();
addMockWeb3ProviderCommand();
+3 -18
View File
@@ -1,6 +1,6 @@
import { aliasGQLQuery } from '../mock-gql';
// eslint-disable-next-line @nx/enforce-module-boundaries
import { statisticsQuery } from '@vegaprotocol/mock';
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
@@ -12,26 +12,11 @@ declare global {
}
}
const chainId = 'test-id';
export function addMockChainId() {
Cypress.Commands.add('mockChainId', () => {
const result = {
statistics: {
chainId,
},
};
cy.mockGQL((req) => {
aliasGQLQuery(req, 'NodeCheck', statisticsQuery(result));
});
cy.mockStatistics((req) => {
req.reply({
statusCode: 200,
body: result,
headers: {
'Content-Type': 'application/json',
},
});
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
});
});
}
-11
View File
@@ -8,7 +8,6 @@ declare global {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> {
mockGQL(handler: RouteHandler): void;
mockStatistics(handler: RouteHandler): void;
}
}
}
@@ -41,16 +40,6 @@ const extractVariables = (req: CyHttpMessages.IncomingHttpRequest): object => {
);
};
export function addMockStatistics() {
Cypress.Commands.add('mockStatistics', (handler: RouteHandler) => {
cy.intercept(
'GET',
Cypress.env('VEGA_URL').replace('graphql', 'statistics'),
handler
).as('ChainId');
});
}
export function addMockGQLCommand() {
Cypress.Commands.add('mockGQL', (handler: RouteHandler) => {
cy.intercept('POST', Cypress.env('VEGA_URL'), handler).as('GQL');
@@ -1,4 +1,4 @@
import { useVegaTransactionStore } from '@vegaprotocol/web3';
import { useVegaTransactionStore } from '@vegaprotocol/wallet';
import {
isStopOrderType,
useDealTicketFormValues,
@@ -273,7 +273,7 @@ export const DealTicketMarginDetails = ({
key={'value-dropdown'}
className="flex items-center justify-between w-full gap-2"
>
<div className="flex items-center gap-1 text-left">
<div className="flex items-center gap-1">
<Tooltip description={MARGIN_DIFF_TOOLTIP_TEXT(assetSymbol)}>
<span className="text-muted">{t('Margin required')}</span>
</Tooltip>
@@ -494,16 +494,16 @@ const TimeInForce = ({
);
const ReduceOnly = () => (
<Tooltip description={<span>{t(REDUCE_ONLY_TOOLTIP)}</span>}>
<div>
<Checkbox
name="reduce-only"
checked={true}
disabled={true}
label={t('Reduce only')}
/>
</div>
</Tooltip>
<Checkbox
name="reduce-only"
checked={true}
disabled={true}
label={
<Tooltip description={<span>{t(REDUCE_ONLY_TOOLTIP)}</span>}>
<>{t('Reduce only')}</>
</Tooltip>
}
/>
);
const NotionalAndFees = ({
@@ -548,62 +548,62 @@ export const DealTicket = ({
name="postOnly"
control={control}
render={({ field }) => (
<Tooltip
description={
<span>
{disablePostOnlyCheckbox
? t(
'"Post only" can not be used on "Fill or Kill" or "Immediate or Cancel" orders.'
)
: t(
'"Post only" will ensure the order is not filled immediately but is placed on the order book as a passive order. When the order is processed it is either stopped (if it would not be filled immediately), or placed in the order book as a passive order until the price taker matches with it.'
)}
</span>
<Checkbox
name="post-only"
checked={!disablePostOnlyCheckbox && field.value}
disabled={disablePostOnlyCheckbox}
onCheckedChange={(postOnly) => {
field.onChange(postOnly);
setValue('reduceOnly', false);
}}
label={
<Tooltip
description={
<span>
{disablePostOnlyCheckbox
? t(
'"Post only" can not be used on "Fill or Kill" or "Immediate or Cancel" orders.'
)
: t(
'"Post only" will ensure the order is not filled immediately but is placed on the order book as a passive order. When the order is processed it is either stopped (if it would not be filled immediately), or placed in the order book as a passive order until the price taker matches with it.'
)}
</span>
}
>
<span className="text-xs">{t('Post only')}</span>
</Tooltip>
}
>
<div>
<Checkbox
name="post-only"
checked={!disablePostOnlyCheckbox && field.value}
disabled={disablePostOnlyCheckbox}
onCheckedChange={(postOnly) => {
field.onChange(postOnly);
setValue('reduceOnly', false);
}}
label={t('Post only')}
/>
</div>
</Tooltip>
/>
)}
/>
<Controller
name="reduceOnly"
control={control}
render={({ field }) => (
<Tooltip
description={
<span>
{disableReduceOnlyCheckbox
? t(
'"Reduce only" can be used only with non-persistent orders, such as "Fill or Kill" or "Immediate or Cancel".'
)
: t(REDUCE_ONLY_TOOLTIP)}
</span>
<Checkbox
name="reduce-only"
checked={!disableReduceOnlyCheckbox && field.value}
disabled={disableReduceOnlyCheckbox}
onCheckedChange={(reduceOnly) => {
field.onChange(reduceOnly);
setValue('postOnly', false);
}}
label={
<Tooltip
description={
<span>
{disableReduceOnlyCheckbox
? t(
'"Reduce only" can be used only with non-persistent orders, such as "Fill or Kill" or "Immediate or Cancel".'
)
: t(REDUCE_ONLY_TOOLTIP)}
</span>
}
>
<span className="text-xs">{t('Reduce only')}</span>
</Tooltip>
}
>
<div>
<Checkbox
name="reduce-only"
checked={!disableReduceOnlyCheckbox && field.value}
disabled={disableReduceOnlyCheckbox}
onCheckedChange={(reduceOnly) => {
field.onChange(reduceOnly);
setValue('postOnly', false);
}}
label={t('Reduce only')}
/>
</div>
</Tooltip>
/>
)}
/>
</div>
@@ -614,26 +614,26 @@ export const DealTicket = ({
name="iceberg"
control={control}
render={({ field }) => (
<Tooltip
description={
<p>
{t(`Trade only a fraction of the order size at once.
<Checkbox
name="iceberg"
checked={field.value}
onCheckedChange={field.onChange}
disabled={disableIcebergCheckbox}
label={
<Tooltip
description={
<p>
{t(`Trade only a fraction of the order size at once.
After the peak size of the order has traded, the size is reset. This is repeated until the order is cancelled, expires, or its full volume trades away.
For example, an iceberg order with a size of 1000 and a peak size of 100 will effectively be split into 10 orders with a size of 100 each.
Note that the full volume of the order is not hidden and is still reflected in the order book.`)}
</p>
</p>
}
>
<span className="text-xs">{t('Iceberg')}</span>
</Tooltip>
}
>
<div>
<Checkbox
name="iceberg"
checked={field.value}
onCheckedChange={field.onChange}
disabled={disableIcebergCheckbox}
label={t('Iceberg')}
/>
</div>
</Tooltip>
/>
)}
/>
</div>
@@ -25,11 +25,11 @@ export const KeyValue = ({
}: KeyValuePros) => {
const displayValue = `${formattedValue ?? '-'} ${symbol || ''}`;
const valueElement = onClick ? (
<button onClick={onClick} className="font-mono ml-auto">
<button onClick={onClick} className="font-mono">
{displayValue}
</button>
) : (
<div className="font-mono ml-auto">{displayValue}</div>
<div className="font-mono">{displayValue}</div>
);
return (
<div
@@ -40,12 +40,12 @@ export const KeyValue = ({
}`}
key={typeof label === 'string' ? label : 'value-dropdown'}
className={classnames(
'text-xs flex justify-between items-center gap-4 flex-wrap text-right',
'text-xs flex justify-between items-center gap-4 flex-wrap',
{ 'ml-2': indent }
)}
>
<Tooltip description={labelDescription}>
<div className="text-muted text-left">{label}</div>
<div className="text-muted">{label}</div>
</Tooltip>
<Tooltip description={`${value ?? '-'} ${symbol || ''}`}>
{valueElement}
@@ -423,12 +423,6 @@ function compileFeatureFlags(): FeatureFlags {
process.env['NX_UPDATE_MARKET_STATE']
) as string
),
GOVERNANCE_TRANSFERS: TRUTHY.includes(
windowOrDefault(
'NX_GOVERNANCE_TRANSFERS',
process.env['NX_GOVERNANCE_TRANSFERS']
) as string
),
};
const EXPLORER_FLAGS = {
EXPLORER_ASSETS: TRUTHY.includes(
-1
View File
@@ -81,7 +81,6 @@ export const DocsLinks = VEGA_DOCS_URL
WITHDRAWAL_LIMITS: `${VEGA_DOCS_URL}/concepts/assets/deposits-withdrawals#withdrawal-limits`,
VALIDATOR_SCORES_REWARDS: `${VEGA_DOCS_URL}/concepts/vega-chain/validator-scores-and-rewards`,
MARKET_LIFECYCLE: `${VEGA_DOCS_URL}/concepts/trading-on-vega/market-lifecycle`,
ETH_DATA_SOURCES: `${VEGA_DOCS_URL}/concepts/trading-on-vega/data-sources#ethereum-data-sources`,
}
: undefined;
-1
View File
@@ -25,7 +25,6 @@ export type CosmicElevatorFlags = Pick<
| 'METAMASK_SNAPS'
| 'REFERRALS'
| 'UPDATE_MARKET_STATE'
| 'GOVERNANCE_TRANSFERS'
>;
export type Configuration = z.infer<typeof tomlConfigSchema>;
export const CUSTOM_NODE_KEY = 'custom' as const;
@@ -80,7 +80,6 @@ const COSMIC_ELEVATOR_FLAGS = {
METAMASK_SNAPS: z.optional(z.boolean()),
REFERRALS: z.optional(z.boolean()),
UPDATE_MARKET_STATE: z.optional(z.boolean()),
GOVERNANCE_TRANSFERS: z.optional(z.boolean()),
};
const EXPLORER_FLAGS = {
+5
View File
@@ -9,12 +9,14 @@ import { fillsWithMarketProvider } from './fills-data-provider';
interface FillsManagerProps {
partyId: string;
marketId?: string;
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
gridProps: ReturnType<typeof useDataGridEvents>;
}
export const FillsManager = ({
partyId,
marketId,
onMarketClick,
gridProps,
}: FillsManagerProps) => {
@@ -22,6 +24,9 @@ export const FillsManager = ({
const filter: Schema.TradesFilter | Schema.TradesSubscriptionFilter = {
partyIds: [partyId],
};
if (marketId) {
filter.marketIds = [marketId];
}
const { data, error } = useDataProvider({
dataProvider: fillsWithMarketProvider,
update: ({ data }) => {
-13
View File
@@ -1,13 +0,0 @@
{
"sourceType": "unambiguous",
"presets": [
[
"@nx/react/babel",
{
"runtime": "automatic",
"useBuiltIns": "usage"
}
]
],
"plugins": []
}
-18
View File
@@ -1,18 +0,0 @@
{
"extends": ["plugin:@nx/react", "../../.eslintrc.json"],
"ignorePatterns": ["!**/*", "__generated__"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
-7
View File
@@ -1,7 +0,0 @@
# funding-payments
This library was generated with [Nx](https://nx.dev).
## Running unit tests
Run `nx test funding-payments` to execute the unit tests via [Jest](https://jestjs.io).
-6
View File
@@ -1,6 +0,0 @@
function ReactMarkdown({ children }) {
// eslint-disable-next-line react/jsx-no-useless-fragment
return <>{children}</>;
}
export default ReactMarkdown;
-17
View File
@@ -1,17 +0,0 @@
/* eslint-disable */
export default {
displayName: 'funding-payments',
preset: '../../jest.preset.js',
globals: {},
transform: {
'^.+\\.[tj]sx?$': [
'ts-jest',
{
tsconfig: '<rootDir>/tsconfig.spec.json',
},
],
},
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
coverageDirectory: '../../coverage/libs/funding-payments',
setupFilesAfterEnv: ['./src/setup-tests.ts'],
};
-10
View File
@@ -1,10 +0,0 @@
const { join } = require('path');
module.exports = {
plugins: {
tailwindcss: {
config: join(__dirname, 'tailwind.config.js'),
},
autoprefixer: {},
},
};
-37
View File
@@ -1,37 +0,0 @@
{
"name": "funding-payments",
"$schema": "../../node_modules/nx/schemas/project-schema.json",
"sourceRoot": "libs/funding-payments/src",
"projectType": "library",
"tags": [],
"targets": {
"lint": {
"executor": "@nx/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["libs/funding-payments/**/*.{ts,tsx,js,jsx}"]
}
},
"test": {
"executor": "@nx/jest:jest",
"outputs": ["{workspaceRoot}/coverage/libs/funding-payments"],
"options": {
"jestConfig": "libs/funding-payments/jest.config.ts",
"passWithNoTests": true
},
"configurations": {
"ci": {
"ci": true,
"codeCoverage": true
}
}
},
"build-spec": {
"executor": "nx:run-commands",
"outputs": [],
"options": {
"command": "yarn tsc --project ./libs/funding-payments/tsconfig.spec.json"
}
}
}
}
-3
View File
@@ -1,3 +0,0 @@
export * from './lib/funding-payments-manager';
export * from './lib/funding-payments-data-provider';
export * from './lib/__generated__/FundingPayments';
@@ -1,24 +0,0 @@
fragment FundingPaymentFields on FundingPayment {
marketId
partyId
fundingPeriodSeq
amount
timestamp
}
query FundingPayments($partyId: ID!, $pagination: Pagination) {
fundingPayments(partyId: $partyId, pagination: $pagination) {
edges {
node {
...FundingPaymentFields
}
cursor
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
@@ -1,71 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type FundingPaymentFieldsFragment = { __typename?: 'FundingPayment', marketId: string, partyId: string, fundingPeriodSeq: number, amount?: string | null, timestamp: any };
export type FundingPaymentsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
pagination?: Types.InputMaybe<Types.Pagination>;
}>;
export type FundingPaymentsQuery = { __typename?: 'Query', fundingPayments: { __typename?: 'FundingPaymentConnection', edges: Array<{ __typename?: 'FundingPaymentEdge', cursor: string, node: { __typename?: 'FundingPayment', marketId: string, partyId: string, fundingPeriodSeq: number, amount?: string | null, timestamp: any } }>, pageInfo: { __typename?: 'PageInfo', startCursor: string, endCursor: string, hasNextPage: boolean, hasPreviousPage: boolean } } };
export const FundingPaymentFieldsFragmentDoc = gql`
fragment FundingPaymentFields on FundingPayment {
marketId
partyId
fundingPeriodSeq
amount
timestamp
}
`;
export const FundingPaymentsDocument = gql`
query FundingPayments($partyId: ID!, $pagination: Pagination) {
fundingPayments(partyId: $partyId, pagination: $pagination) {
edges {
node {
...FundingPaymentFields
}
cursor
}
pageInfo {
startCursor
endCursor
hasNextPage
hasPreviousPage
}
}
}
${FundingPaymentFieldsFragmentDoc}`;
/**
* __useFundingPaymentsQuery__
*
* To run a query within a React component, call `useFundingPaymentsQuery` and pass it any options that fit your needs.
* When your component renders, `useFundingPaymentsQuery` 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 query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useFundingPaymentsQuery({
* variables: {
* partyId: // value for 'partyId'
* pagination: // value for 'pagination'
* },
* });
*/
export function useFundingPaymentsQuery(baseOptions: Apollo.QueryHookOptions<FundingPaymentsQuery, FundingPaymentsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<FundingPaymentsQuery, FundingPaymentsQueryVariables>(FundingPaymentsDocument, options);
}
export function useFundingPaymentsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<FundingPaymentsQuery, FundingPaymentsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<FundingPaymentsQuery, FundingPaymentsQueryVariables>(FundingPaymentsDocument, options);
}
export type FundingPaymentsQueryHookResult = ReturnType<typeof useFundingPaymentsQuery>;
export type FundingPaymentsLazyQueryHookResult = ReturnType<typeof useFundingPaymentsLazyQuery>;
export type FundingPaymentsQueryResult = Apollo.QueryResult<FundingPaymentsQuery, FundingPaymentsQueryVariables>;
@@ -1,69 +0,0 @@
import type { PageInfo, Cursor } from '@vegaprotocol/data-provider';
import {
makeDataProvider,
makeDerivedDataProvider,
defaultAppend as append,
} from '@vegaprotocol/data-provider';
import type { Market } from '@vegaprotocol/markets';
import { marketsMapProvider } from '@vegaprotocol/markets';
import { FundingPaymentsDocument } from './__generated__/FundingPayments';
import type {
FundingPaymentsQuery,
FundingPaymentsQueryVariables,
FundingPaymentFieldsFragment,
} from './__generated__/FundingPayments';
export type FundingPayment = Omit<FundingPaymentFieldsFragment, 'market'> & {
market?: Market;
};
const getData = (
responseData: FundingPaymentsQuery | null
): (FundingPaymentFieldsFragment & Cursor)[] =>
responseData?.fundingPayments?.edges.map<
FundingPaymentFieldsFragment & Cursor
>((edge) => ({
...edge.node,
cursor: edge.cursor,
})) || [];
const getPageInfo = (
responseData: FundingPaymentsQuery | null
): PageInfo | null => responseData?.fundingPayments?.pageInfo || null;
export const fundingPaymentsProvider = makeDataProvider<
Parameters<typeof getData>['0'],
ReturnType<typeof getData>,
never,
never,
FundingPaymentsQueryVariables
>({
query: FundingPaymentsDocument,
getData,
pagination: {
getPageInfo,
append,
first: 100,
},
});
export const fundingPaymentsWithMarketProvider = makeDerivedDataProvider<
FundingPayment[],
never,
FundingPaymentsQueryVariables
>(
[
fundingPaymentsProvider,
(callback, client) => marketsMapProvider(callback, client, undefined),
],
(partsData): FundingPayment[] | null => {
return ((partsData[0] as ReturnType<typeof getData>) || []).map(
(fundingPayment) => ({
...fundingPayment,
market: (partsData[1] as Record<string, Market>)[
fundingPayment.marketId
],
})
);
}
);
@@ -1,42 +0,0 @@
import type { AgGridReact } from 'ag-grid-react';
import { useRef } from 'react';
import { t } from '@vegaprotocol/i18n';
import { FundingPaymentsTable } from './funding-payments-table';
import type { useDataGridEvents } from '@vegaprotocol/datagrid';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { fundingPaymentsWithMarketProvider } from './funding-payments-data-provider';
interface FundingPaymentsManagerProps {
partyId: string;
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
gridProps: ReturnType<typeof useDataGridEvents>;
}
export const FundingPaymentsManager = ({
partyId,
onMarketClick,
gridProps,
}: FundingPaymentsManagerProps) => {
const gridRef = useRef<AgGridReact | null>(null);
const { data, error } = useDataProvider({
dataProvider: fundingPaymentsWithMarketProvider,
update: ({ data }) => {
if (data?.length && gridRef.current?.api) {
gridRef.current?.api.setRowData(data);
return true;
}
return false;
},
variables: { partyId },
});
return (
<FundingPaymentsTable
ref={gridRef}
rowData={data}
onMarketClick={onMarketClick}
overlayNoRowsTemplate={error ? error.message : t('No funding payments')}
{...gridProps}
/>
);
};
@@ -1,92 +0,0 @@
import { act, render, screen } from '@testing-library/react';
import { getDateTimeFormat } from '@vegaprotocol/utils';
import type { PartialDeep } from 'type-fest';
import type { FundingPayment } from './funding-payments-data-provider';
import { FundingPaymentsTable } from './funding-payments-table';
import { generateFundingPayment } from './test-helpers';
describe('FundingPaymentsTable', () => {
let defaultFundingPayment: PartialDeep<FundingPayment>;
beforeEach(() => {
defaultFundingPayment = {
marketId:
'69abf5c456c20f4d189cea79a11dfd6b0958ead58ab34bd66f73eea48aee600c',
partyId:
'02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65',
fundingPeriodSeq: 84,
amount: '100',
timestamp: '2023-10-06T07:06:43.020994Z',
market: {
decimalPlaces: 2,
positionDecimalPlaces: 5,
tradableInstrument: {
instrument: {
code: 'test market',
product: {
__typename: 'Future',
settlementAsset: {
decimals: 2,
symbol: 'BTC',
},
},
},
},
},
};
});
it('correct columns are rendered', async () => {
await act(async () => {
render(<FundingPaymentsTable rowData={[generateFundingPayment()]} />);
});
const headers = screen.getAllByRole('columnheader');
const expectedHeaders = ['Market', 'Amount', 'Date'];
expect(headers).toHaveLength(expectedHeaders.length);
expect(headers.map((h) => h.textContent?.trim())).toEqual(expectedHeaders);
});
it('formats positive cells', async () => {
const fundingPayment = generateFundingPayment({
...defaultFundingPayment,
});
render(<FundingPaymentsTable rowData={[fundingPayment]} />);
const cells = screen.getAllByRole('gridcell');
const expectedValues = [
fundingPayment.market?.tradableInstrument.instrument.code || '',
'1.00 BTC',
getDateTimeFormat().format(new Date(fundingPayment.timestamp)),
];
cells.forEach((cell, i) => {
expect(cell).toHaveTextContent(expectedValues[i]);
});
const amountCell = cells.find((c) => c.getAttribute('col-id') === 'amount');
expect(
amountCell?.querySelector('.ag-cell-value')?.firstElementChild
).toHaveClass('text-market-green-600');
});
it('formats negative cells', async () => {
const fundingPayment = generateFundingPayment({
...defaultFundingPayment,
amount: `-${defaultFundingPayment.amount}`,
});
render(<FundingPaymentsTable rowData={[fundingPayment]} />);
const cells = screen.getAllByRole('gridcell');
const expectedValues = [
fundingPayment.market?.tradableInstrument.instrument.code || '',
'-1.00 BTC',
getDateTimeFormat().format(new Date(fundingPayment.timestamp)),
];
cells.forEach((cell, i) => {
expect(cell).toHaveTextContent(expectedValues[i]);
});
const amountCell = cells.find((c) => c.getAttribute('col-id') === 'amount');
expect(
amountCell?.querySelector('.ag-cell-value')?.firstElementChild
).toHaveClass('text-market-red dark:text-market-red');
});
});
@@ -1,132 +0,0 @@
import { useMemo } from 'react';
import type {
AgGridReact,
AgGridReactProps,
AgReactUiProps,
} from 'ag-grid-react';
import type { ColDef } from 'ag-grid-community';
import {
addDecimalsFormatNumber,
getDateTimeFormat,
isNumeric,
toBigNum,
} from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import {
AgGrid,
DateRangeFilter,
MarketNameCell,
negativeClassNames,
positiveClassNames,
} from '@vegaprotocol/datagrid';
import type {
VegaValueFormatterParams,
VegaValueGetterParams,
} from '@vegaprotocol/datagrid';
import { forwardRef } from 'react';
import type { FundingPayment } from './funding-payments-data-provider';
import { getAsset } from '@vegaprotocol/markets';
import classNames from 'classnames';
const defaultColDef = {
resizable: true,
sortable: true,
};
export type Props = (AgGridReactProps | AgReactUiProps) & {
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
};
const formatAmount = ({
value,
data,
}: VegaValueFormatterParams<FundingPayment, 'amount'>) => {
if (!data?.market || !isNumeric(value)) {
return '-';
}
const { symbol: assetSymbol, decimals: assetDecimals } = getAsset(
data.market
);
const valueFormatted = addDecimalsFormatNumber(value, assetDecimals);
return `${valueFormatted} ${assetSymbol}`;
};
export const FundingPaymentsTable = forwardRef<AgGridReact, Props>(
({ onMarketClick, ...props }, ref) => {
const columnDefs = useMemo<ColDef[]>(
() => [
{
headerName: t('Market'),
field: 'market.tradableInstrument.instrument.code',
cellRenderer: 'MarketNameCell',
filter: true,
cellRendererParams: { idPath: 'market.id', onMarketClick },
},
{
headerName: t('Amount'),
field: 'amount',
valueFormatter: formatAmount,
type: 'rightAligned',
filter: 'agNumberColumnFilter',
valueGetter: ({ data }: VegaValueGetterParams<FundingPayment>) =>
data?.amount && data?.market
? toBigNum(data.amount, getAsset(data.market).decimals).toNumber()
: 0,
cellRenderer: ({ data }: { data: FundingPayment }) => {
if (!data?.market || !isNumeric(data.amount)) {
return '-';
}
const { symbol: assetSymbol, decimals: assetDecimals } = getAsset(
data.market
);
const valueFormatted = addDecimalsFormatNumber(
data.amount,
assetDecimals
);
return (
<>
<span
className={classNames({
[positiveClassNames]: !data?.amount?.startsWith('-'),
[negativeClassNames]: !!data?.amount?.startsWith('-'),
})}
>
{valueFormatted}
</span>
{` ${assetSymbol}`}
</>
);
},
},
{
headerName: t('Date'),
field: 'timestamp',
type: 'rightAligned',
filter: DateRangeFilter,
valueFormatter: ({
value,
}: VegaValueFormatterParams<FundingPayment, 'timestamp'>) => {
return value ? getDateTimeFormat().format(new Date(value)) : '';
},
},
],
[onMarketClick]
);
return (
<AgGrid
ref={ref}
defaultColDef={defaultColDef}
columnDefs={columnDefs}
overlayNoRowsTemplate={t('No funding payments')}
getRowId={({ data }: { data?: FundingPayment }) =>
`${data?.marketId}-${data?.fundingPeriodSeq}`
}
components={{ MarketNameCell }}
{...props}
/>
);
}
);
@@ -1,74 +0,0 @@
import type {
FundingPaymentsQuery,
FundingPaymentFieldsFragment,
} from './__generated__/FundingPayments';
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
export const fundingPaymentsQuery = (
override?: PartialDeep<FundingPaymentsQuery>,
vegaPublicKey?: string
): FundingPaymentsQuery => {
const defaultResult: FundingPaymentsQuery = {
fundingPayments: {
__typename: 'FundingPaymentConnection',
edges: fundingPayments(vegaPublicKey).map((node) => ({
__typename: 'FundingPaymentEdge',
cursor: '3',
node,
})),
pageInfo: {
__typename: 'PageInfo',
startCursor: '1',
endCursor: '2',
hasNextPage: false,
hasPreviousPage: false,
},
},
};
return merge(defaultResult, override);
};
export const generateFundingPayment = (
override?: PartialDeep<FundingPaymentFieldsFragment>
) => {
const defaultFundingPayment: FundingPaymentFieldsFragment = {
marketId: 'market-0',
partyId: 'partyId',
fundingPeriodSeq: 84,
amount: '126973',
timestamp: '2023-10-06T07:06:43.020994Z',
};
return merge(defaultFundingPayment, override);
};
const fundingPayments = (
partyId = 'partyId'
): FundingPaymentFieldsFragment[] => [
generateFundingPayment({
partyId,
fundingPeriodSeq: 78,
amount: '92503',
timestamp: '2023-10-06T04:06:43.652759Z',
}),
generateFundingPayment({
partyId,
fundingPeriodSeq: 77,
amount: '-37841',
timestamp: '2023-10-06T03:36:43.437139Z',
}),
generateFundingPayment({
partyId,
fundingPeriodSeq: 76,
amount: '32838',
timestamp: '2023-10-06T03:06:43.430384Z',
}),
generateFundingPayment({
partyId,
fundingPeriodSeq: 75,
amount: '-298259',
timestamp: '2023-10-06T02:36:43.51153Z',
}),
];
@@ -1,102 +0,0 @@
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
import * as Schema from '@vegaprotocol/types';
import type { FundingPayment } from './funding-payments-data-provider';
const { MarketState, MarketTradingMode } = Schema;
export const generateFundingPayment = (
override?: PartialDeep<FundingPayment>
) => {
const defaultFundingPayment: FundingPayment = {
marketId:
'69abf5c456c20f4d189cea79a11dfd6b0958ead58ab34bd66f73eea48aee600c',
partyId: '02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65',
fundingPeriodSeq: 84,
amount: '126973',
timestamp: '2023-10-06T07:06:43.020994Z',
market: {
__typename: 'Market',
id: 'market-id',
positionDecimalPlaces: 0,
decimalPlaces: 5,
state: MarketState.STATE_ACTIVE,
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
liquidityMonitoringParameters: {
triggeringRatio: '1',
},
fees: {
__typename: 'Fees',
factors: {
__typename: 'FeeFactors',
infrastructureFee: '0.1',
liquidityFee: '0.1',
makerFee: '0.1',
},
},
marketTimestamps: {
__typename: 'MarketTimestamps',
open: '2005-04-02T19:37:00.000Z',
close: '2005-04-02T19:37:00.000Z',
},
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
id: 'instrument-id',
code: 'instrument-code',
name: 'UNIDAI Monthly (30 Jun 2022)',
metadata: {
__typename: 'InstrumentMetadata',
tags: ['tag-a'],
},
product: {
__typename: 'Future',
settlementAsset: {
__typename: 'Asset',
id: 'asset-id',
name: 'asset-id',
symbol: 'SYM',
decimals: 18,
quantum: '1',
},
quoteName: '',
dataSourceSpecForTradingTermination: {
__typename: 'DataSourceSpec',
id: 'oracleId',
data: {
__typename: 'DataSourceDefinition',
sourceType: {
__typename: 'DataSourceDefinitionExternal',
sourceType: {
__typename: 'DataSourceSpecConfiguration',
},
},
},
},
dataSourceSpecForSettlementData: {
__typename: 'DataSourceSpec',
id: 'oracleId',
data: {
__typename: 'DataSourceDefinition',
sourceType: {
__typename: 'DataSourceDefinitionExternal',
sourceType: {
__typename: 'DataSourceSpecConfiguration',
},
},
},
},
dataSourceSpecBinding: {
__typename: 'DataSourceSpecToFutureBinding',
tradingTerminationProperty: 'trading-termination-property',
settlementDataProperty: 'settlement-data-property',
},
},
},
},
},
};
return merge(defaultFundingPayment, override);
};
-4
View File
@@ -1,4 +0,0 @@
import '@testing-library/jest-dom';
import ResizeObserver from 'resize-observer-polyfill';
global.ResizeObserver = ResizeObserver;
-17
View File
@@ -1,17 +0,0 @@
const { join } = require('path');
const { createGlobPatternsForDependencies } = require('@nx/react/tailwind');
const theme = require('../tailwindcss-config/src/theme');
const vegaCustomClasses = require('../tailwindcss-config/src/vega-custom-classes');
module.exports = {
content: [
join(__dirname, 'src/**/*.{ts,tsx,html,mdx}'),
join(__dirname, '.storybook/preview.js'),
...createGlobPatternsForDependencies(__dirname),
],
darkMode: 'class',
theme: {
extend: theme,
},
plugins: [vegaCustomClasses],
};
-27
View File
@@ -1,27 +0,0 @@
{
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"allowJs": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true
},
"include": [],
"references": [
{
"path": "./tsconfig.lib.json"
},
{
"path": "./tsconfig.spec.json"
},
{
"path": "./.storybook/tsconfig.json"
}
]
}
-27
View File
@@ -1,27 +0,0 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "../../dist/out-tsc",
"types": ["node"]
},
"files": [
"../../node_modules/@nx/react/typings/cssmodule.d.ts",
"../../node_modules/@nx/react/typings/image.d.ts"
],
"exclude": [
"**/*.spec.ts",
"**/*.test.ts",
"**/*.spec.tsx",
"**/*.test.tsx",
"**/*.spec.js",
"**/*.test.js",
"**/*.spec.jsx",
"**/*.test.jsx",
"**/*.stories.ts",
"**/*.stories.js",
"**/*.stories.jsx",
"**/*.stories.tsx",
"jest.config.ts"
],
"include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"]
}

Some files were not shown because too many files have changed in this diff Show More