Compare commits

..
294 changed files with 1609 additions and 7403 deletions
+18 -39
View File
@@ -50,7 +50,7 @@ jobs:
secrets: inherit
lint-test-build:
timeout-minutes: 60
timeout-minutes: 35
needs: node-modules
runs-on: ubuntu-22.04
name: '(CI) lint + unit test + build'
@@ -105,44 +105,19 @@ jobs:
affected="$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)"
echo -n "Affected projects: $affected"
branch_slug="$(echo ${{ github.head_ref || github.ref_name }} | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g )"
projects_e2e=""
preview_governance="not deployed"
preview_trading="not deployed"
preview_explorer="not deployed"
if [[ -z "$projects_e2e" ]]; then
projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" '
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$branch_slug")
else
if [[ $affected == *"governance"* ]]; then
projects_e2e+='"governance-e2e" '
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
fi
if [[ $affected == *"trading"* ]]; then
projects_e2e+='"trading-e2e" '
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
fi
if [[ $affected == *"explorer"* ]]; then
projects_e2e+='"explorer-e2e" '
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$branch_slug")
fi
fi
if [[ $affected == *"governance"* ]]; then projects_e2e+='"governance-e2e" '; fi
if [[ $affected == *"trading"* ]]; then projects_e2e+='"trading-e2e" '; fi
if [[ $affected == *"explorer"* ]]; then projects_e2e+='"explorer-e2e" '; fi
if [[ -z "$projects_e2e" ]]; then projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" '; fi
projects_e2e=${projects_e2e%?}
projects_e2e=[${projects_e2e// /,}]
echo PROJECTS_E2E=$projects_e2e >> $GITHUB_ENV
echo PROJECTS=$(echo $projects_e2e | sed 's|-e2e||g') >> $GITHUB_ENV
echo PREVIEW_GOVERNANCE=$preview_governance >> $GITHUB_ENV
echo PREVIEW_TRADING=$preview_trading >> $GITHUB_ENV
echo PREVIEW_EXPLORER=$preview_explorer >> $GITHUB_ENV
outputs:
projects: ${{ env.PROJECTS }}
projects-e2e: ${{ env.PROJECTS_E2E }}
preview_governance: ${{ env.PREVIEW_GOVERNANCE }}
preview_trading: ${{ env.PREVIEW_TRADING }}
preview_explorer: ${{ env.PREVIEW_EXPLORER }}
cypress:
needs: lint-test-build
@@ -165,9 +140,7 @@ jobs:
dist-check:
runs-on: ubuntu-latest
needs:
- publish-dist
- lint-test-build
needs: publish-dist
if: ${{ github.event_name == 'pull_request' }}
name: '(CD) comment preview links'
steps:
@@ -178,16 +151,22 @@ jobs:
issue-number: ${{ github.event.pull_request.number }}
body-includes: Previews
- name: Create comment
uses: peter-evans/create-or-update-comment@v3
- name: Inject slug/short variables
if: ${{ steps.fc.outputs.comment-id == 0 }}
uses: rlespinasse/github-slug-action@v4
with:
prefix: CI_
- name: Create comment
if: ${{ steps.fc.outputs.comment-id == 0 }}
uses: peter-evans/create-or-update-comment@v3
with:
issue-number: ${{ github.event.pull_request.number }}
body: |
Previews:
* governance: ${{ needs.lint-test-build.outputs.preview_governance }}
* explorer: ${{ needs.lint-test-build.outputs.preview_explorer }}
* trading: ${{ needs.lint-test-build.outputs.preview_trading }}
Previews
- explorer https://explorer.${{ env.CI_GITHUB_REF_NAME }}.vega.rocks
- trading https://trading.${{ env.CI_GITHUB_REF_NAME }}.vega.rocks
- governance https://governance.${{ env.CI_GITHUB_REF_NAME }}.vega.rocks
cypress-check:
name: '(CI) cypress - check'
+4 -8
View File
@@ -91,11 +91,7 @@ jobs:
- uses: actions/upload-artifact@v3
if: ${{ failure() }}
with:
name: logs-${{ matrix.project }}
path: /home/runner/.vegacapsule/testnet/logs
- uses: actions/upload-artifact@v3
if: ${{ failure() }}
with:
name: test-report-${{ matrix.project }}
path: frontend-monorepo/apps/trading-e2e/cypress/reports
name: test-report-and-logs-${{ matrix.project }}
path: |
/home/runner/.vegacapsule/testnet/logs
frontend-monorepo/apps/trading-e2e/cypress/reports
Vendored
+19 -1
View File
@@ -1,2 +1,20 @@
@Library('vega-shared-library') _
runApprobation ignoreFailure: false, frontendBranch: env.BRANCH_NAME, type: 'frontend'
def commitHash = 'UNKNOWN'
pipeline {
agent any
options {
skipDefaultCheckout true
parallelsAlwaysFailFast()
}
stages {
stage('approbation') {
steps {
sh 'printenv'
checkout scm
runApprobation ignoreFailure: false, frontendBranch: env.BRANCH_NAME, type: 'frontend'
}
}
}
}
+1 -1
View File
@@ -72,7 +72,7 @@ Run `nx serve my-app` for a dev server. Navigate to the port specified in `app/<
In order to generate the schemas for your GraphQL queries, you can run `GRAPHQL_SCHEMA_PATH=[YOUR SCHEMA FILE / API URL HERE] nx run types:generate`.
```bash
export GRAPHQL_SCHEMA_PATH=https://api.n07.testnet.vega.xyz/graphql
export GRAPHQL_SCHEMA_PATH=https://api.n11.testnet.vega.xyz/graphql
yarn nx run types:generate
```
+2 -2
View File
@@ -1,7 +1,7 @@
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_ENV=CUSTOM
NX_VEGA_CONFIG_URL=
@@ -18,4 +18,4 @@ NX_EXPLORER_PARTIES=1
NX_EXPLORER_VALIDATORS=1
CYPRESS_VEGA_WALLET_API_TOKEN=
CYPRESS_VEGA_URL=http://localhost:3008/graphql
CYPRESS_VEGA_URL=http://localhost:3028/query
+1 -1
View File
@@ -2,7 +2,7 @@
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://tm.n07.testnet.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql
NX_VEGA_ENV=TESTNET
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
+1 -1
View File
@@ -25,7 +25,7 @@ module.exports = defineConfig({
},
env: {
environment: 'CUSTOM',
networkQueryUrl: 'http://localhost:3008/graphql',
networkQueryUrl: 'http://localhost:3028/query',
ethUrl: 'https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8',
commitHash: 'dev',
tsConfig: 'tsconfig.json',
+46 -18
View File
@@ -9,22 +9,21 @@ context('Home Page', function () {
it('should show connected environment stats', function () {
const statTitles = {
0: 'Status',
1: 'Epoch',
2: 'Block height',
3: 'Uptime',
4: 'Total nodes',
5: 'Total staked',
6: 'Backlog',
7: 'Trades / second',
8: 'Orders / block',
9: 'Orders / second',
10: 'Transactions / block',
11: 'Block time',
12: 'Time',
13: 'App',
14: 'Tendermint',
15: 'Up since',
16: 'Chain ID',
1: 'Block height',
2: 'Uptime',
3: 'Total nodes',
4: 'Total staked',
5: 'Backlog',
6: 'Trades / second',
7: 'Orders / block',
8: 'Orders / second',
9: 'Transactions / block',
10: 'Block time',
11: 'Time',
12: 'App',
13: 'Tendermint',
14: 'Up since',
15: 'Chain ID',
};
cy.get('[data-testid="stats-title"]')
@@ -32,13 +31,42 @@ context('Home Page', function () {
cy.wrap($list).should('contain.text', statTitles[index]);
})
.then(($list) => {
cy.wrap($list).should('have.length', 17);
cy.wrap($list).should('have.length', 16);
});
cy.get(statsValue).eq(0).should('contain.text', 'CONNECTED');
cy.get(statsValue).eq(1).should('not.be.empty');
cy.get(statsValue)
.eq(2)
.invoke('text')
.should('match', /\d+d \d+h \d+m \d+s/i);
cy.get(statsValue).eq(3).should('contain.text', '2');
cy.get(statsValue)
.eq(4)
.invoke('text')
.should('match', /\d+\.\d\d(?!\d)/i);
cy.get(statsValue).eq(5).should('contain.text', '0');
cy.get(statsValue).eq(6).should('contain.text', '0');
cy.get(statsValue).eq(7).should('contain.text', '0');
cy.get(statsValue).eq(8).should('contain.text', '0');
cy.get(statsValue).eq(9).should('not.be.empty');
cy.get(statsValue).eq(10).should('not.be.empty');
cy.get(statsValue).eq(11).should('not.be.empty');
cy.get(statsValue)
.eq(12)
.invoke('text')
.should('match', /v\d+\.\d+\.\d+/i);
cy.get(statsValue)
.eq(13)
.invoke('text')
.should('match', /\d+\.\d+\.\d+/i);
cy.get(statsValue).eq(14).should('not.be.empty');
cy.get(statsValue).eq(15).should('not.be.empty');
});
it('Block height should be updating', function () {
cy.get(statsValue)
.eq(2)
.eq(1)
.invoke('text')
.then((blockHeightTxt) => {
cy.get(statsValue)
@@ -6,7 +6,7 @@ const customNodeBtn = 'custom-node';
context.skip('Node switcher', { tags: '@regression' }, function () {
beforeEach('visit home page', function () {
cy.intercept('GET', 'https://static.vega.xyz/assets/capsule-network.json', {
hosts: ['http://localhost:3008/graphql'],
hosts: ['http://localhost:3028/query'],
}).as('nodeData');
cy.visit('/');
cy.wait('@nodeData');
@@ -219,7 +219,7 @@ context.skip('Parties page', { tags: '@regression' }, function () {
balance type asset {id symbol decimals}}}}}}}}';
cy.request({
method: 'POST',
url: `http://localhost:3008/graphql`,
url: `http://localhost:3028/query`,
body: {
query: mutation,
},
@@ -4,7 +4,7 @@ import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridColumn } from 'ag-grid-react';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
import type { VegaICellRendererParams } from '@vegaprotocol/datagrid';
import { useRef, useLayoutEffect } from 'react';
import { BREAKPOINT_MD } from '../../config/breakpoints';
@@ -43,7 +43,7 @@ export const AssetLink = ({
if (asDialog) {
open(assetId, e.target as HTMLElement);
} else {
navigate(`/${Routes.ASSETS}/${asset?.id}`);
navigate(`${Routes.ASSETS}/${asset?.id}`);
}
}}
{...props}
@@ -14,6 +14,7 @@ import {
SettlementAssetInfoPanel,
} from '@vegaprotocol/market-info';
import { MarketInfoTable } from '@vegaprotocol/market-info';
import { Link } from 'react-router-dom';
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
if (!market) return null;
@@ -96,19 +97,22 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
),
},
{
title: t('Settlement Oracle'),
title: t('Oracle'),
content: (
<OracleInfoPanel
noBorder={false}
market={market}
type="settlementData"
/>
),
},
{
title: t('Termination Oracle'),
content: (
<OracleInfoPanel noBorder={false} market={market} type="termination" />
<OracleInfoPanel noBorder={false} market={market}>
<Link
className="text-xs hover:underline"
to={`/oracles#${market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData.id}`}
>
{t('View settlement data oracle specification')}
</Link>
<Link
className="text-xs hover:underline"
to={`/oracles#${market.tradableInstrument.instrument.product.dataSourceSpecForTradingTermination.id}`}
>
{t('View termination oracle specification')}
</Link>
</OracleInfoPanel>
),
},
];
@@ -3,7 +3,7 @@ import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridColumn } from 'ag-grid-react';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
import type {
VegaICellRendererParams,
VegaValueGetterParams,
@@ -9,7 +9,7 @@ import SizeInMarket from '../size-in-market/size-in-market';
export interface DeterministicOrderDetailsProps {
id: string;
// Version to fetch, with 0 being 'latest' and 1 being 'first'. Defaults to 0
version?: number | null;
version?: number;
}
export const wrapperClasses =
@@ -28,7 +28,7 @@ export const wrapperClasses =
*/
const DeterministicOrderDetails = ({
id,
version = null,
version = 0,
}: DeterministicOrderDetailsProps) => {
const { data, error } = useExplorerDeterministicOrderQuery({
variables: { orderId: id, version },
@@ -3,7 +3,7 @@ import { VoteProgress } from '@vegaprotocol/proposals';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridColumn } from 'ag-grid-react';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
import type {
VegaICellRendererParams,
VegaValueFormatterParams,
@@ -71,7 +71,7 @@ export const PartyAccounts = ({ accounts }: PartyAccountsProps) => {
/>
</td>
<td className="text-md">
<AssetLink assetId={account.asset.id} asDialog={true} />
<AssetLink assetId={account.asset.id} />
</td>
</TableRow>
);
-44
View File
@@ -1,7 +1,3 @@
@import 'ag-grid-community/dist/styles/ag-grid.css';
@import 'ag-grid-community/dist/styles/ag-theme-balham.css';
@import 'ag-grid-community/dist/styles/ag-theme-balham-dark.css';
/* You can add global styles to this file, and also import other style files */
@tailwind base;
@tailwind components;
@@ -15,43 +11,3 @@
.react-markdown-container a:before {
content: '🔗 ';
}
/* AG GRID - Do not edit without updating other global stylesheets for each app */
.vega-ag-grid .ag-root-wrapper {
border: solid 0px;
}
.vega-ag-grid .ag-react-container {
overflow: hidden;
text-overflow: ellipsis;
}
.vega-ag-grid .ag-cell,
.vega-ag-grid .ag-full-width-row .ag-cell-wrapper.ag-row-group {
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
}
/* Light variables */
.ag-theme-balham {
--ag-background-color: theme(colors.white);
--ag-border-color: theme(colors.neutral[300]);
--ag-header-background-color: theme(colors.white);
--ag-odd-row-background-color: theme(colors.white);
--ag-header-column-separator-color: theme(colors.neutral[300]);
--ag-row-border-color: theme(colors.white);
--ag-row-hover-color: theme(colors.neutral[100]);
--ag-font-size: 12px;
}
/* Dark variables */
.ag-theme-balham-dark {
--ag-background-color: theme(colors.black);
--ag-border-color: theme(colors.neutral[700]);
--ag-header-background-color: theme(colors.black);
--ag-odd-row-background-color: theme(colors.black);
--ag-header-column-separator-color: theme(colors.neutral[600]);
--ag-row-border-color: theme(colors.black);
--ag-row-hover-color: theme(colors.neutral[800]);
--ag-font-size: 12px;
}
+3 -2
View File
@@ -5,7 +5,7 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_FAIRGROUND=false
NX_VEGA_NETWORKS={}
NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_URL=http://localhost:3028/query
NX_ETHEREUM_CHAIN_ID=1440
NX_ETH_URL_CONNECT=1
NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
@@ -20,7 +20,7 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
#Test configuration variables
CYPRESS_FAIRGROUND=false
CYPRESS_VEGA_URL=http://localhost:3008/graphql
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
CYPRESS_ETHEREUM_PROVIDER_URL=http://localhost:8545
CYPRESS_EXPLORER_URL=https://explorer.fairground.wtf
@@ -31,5 +31,6 @@ CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_WALLET_API_TOKEN=
+1 -1
View File
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_ENV=TESTNET
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
@@ -1,38 +0,0 @@
export const upgradeProposalsData = {
lastBlockHeight: '2014133',
protocolUpgradeProposals: {
edges: [
{
node: {
upgradeBlockHeight: '2015942',
vegaReleaseTag: 'v1',
approvers: [
'02a6531716b7a6d82779b7793c3ad2fcb47290ea2ff0912c56f61219bd9675ff',
'121934387281812a2d5e6913e5d57c0f85a8f169e2752347ee2e23b52d46623c',
'65c80e2f5f84e2109eec30810f137ba04cbbecaba8f27706c146cc6c6f90db29',
'bd6339d2428c79ac3bc9011771236d17bac92bcb1806423388d52fb440043aef',
],
status: 'PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED',
__typename: 'ProtocolUpgradeProposal',
},
__typename: 'ProtocolUpgradeProposalEdge',
},
{
node: {
upgradeBlockHeight: '1955065',
vegaReleaseTag: 'v0.71.0+dev-12156-bca1d57e',
approvers: [
'02a6531716b7a6d82779b7793c3ad2fcb47290ea2ff0912c56f61219bd9675ff',
'121934387281812a2d5e6913e5d57c0f85a8f169e2752347ee2e23b52d46623c',
'65c80e2f5f84e2109eec30810f137ba04cbbecaba8f27706c146cc6c6f90db29',
'bd6339d2428c79ac3bc9011771236d17bac92bcb1806423388d52fb440043aef',
],
status: 'PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED',
__typename: 'ProtocolUpgradeProposal',
},
__typename: 'ProtocolUpgradeProposalEdge',
},
],
__typename: 'ProtocolUpgradeProposalConnection',
},
};
@@ -1,117 +0,0 @@
export const nodeData = {
epoch: {
id: '204731',
timestamps: {
start: '2023-04-14T09:30:09.452005Z',
end: null,
expiry: '2023-04-14T09:31:09.452005Z',
__typename: 'EpochTimestamps',
},
__typename: 'Epoch',
},
nodesConnection: {
edges: [
{
node: {
avatarUrl:
'https://www.gravatar.com/avatar/y2hwc4xjds7zvlam3y4in94q2rcdimsn?d=identicon',
id: 'f337b5cc50c49a928e49129a2eca62277a81b4b7336b6e4131f8f0431e8db029',
name: 'lovely-fisherman',
pubkey:
'02a6531716b7a6d82779b7793c3ad2fcb47290ea2ff0912c56f61219bd9675ff',
stakedByOperator: '3000000000000000000000',
stakedByDelegates: '0',
stakedTotal: '3000000000000000000000',
pendingStake: '0',
rankingScore: {
rankingScore: '0.4999166805532412',
stakeScore: '0.2499583402766206',
performanceScore: '1',
votingPower: '2499',
status: 'VALIDATOR_NODE_STATUS_TENDERMINT',
__typename: 'RankingScore',
},
__typename: 'Node',
},
__typename: 'NodeEdge',
},
{
node: {
avatarUrl:
'https://www.gravatar.com/avatar/g1tw70qnoo0tf8ror30jefwhae92zy16?d=identicon',
id: 'cdadcf885556e372b6b39679d6ad46854d1d9c1e982da7ff2929544df01f9088',
name: 'magnificent-door',
pubkey:
'121934387281812a2d5e6913e5d57c0f85a8f169e2752347ee2e23b52d46623c',
stakedByOperator: '3000000000000000000000',
stakedByDelegates: '0',
stakedTotal: '3000000000000000000000',
pendingStake: '0',
rankingScore: {
rankingScore: '0.4999166805532412',
stakeScore: '0.2499583402766206',
performanceScore: '1',
votingPower: '2499',
status: 'VALIDATOR_NODE_STATUS_TENDERMINT',
__typename: 'RankingScore',
},
__typename: 'Node',
},
__typename: 'NodeEdge',
},
{
node: {
avatarUrl:
'https://www.gravatar.com/avatar/s2e7hp7soq5zdhxeap7p21onetsjiy6w?d=identicon',
id: '9a13de2548fef30d928e71e76004c98ec7ad9d8fc3ddcd16ddee210b28ea4cfc',
name: 'helpful-tree',
pubkey:
'bd6339d2428c79ac3bc9011771236d17bac92bcb1806423388d52fb440043aef',
stakedByOperator: '3000000000000000000000',
stakedByDelegates: '2000000000000000000',
stakedTotal: '3002000000000000000000',
pendingStake: '0',
rankingScore: {
rankingScore: '0.5002499583402766',
stakeScore: '0.2501249791701383',
performanceScore: '1',
votingPower: '2501',
status: 'VALIDATOR_NODE_STATUS_TENDERMINT',
__typename: 'RankingScore',
},
__typename: 'Node',
},
__typename: 'NodeEdge',
},
{
node: {
avatarUrl:
'https://www.gravatar.com/avatar/3gop683kg2cvd8rpv286hzagqt3yjsdq?d=identicon',
id: '93ac271ab95038333587e47d11461e6edc0126e6e77156281c545f4c5650a6d0',
name: 'easy-cookie',
pubkey:
'65c80e2f5f84e2109eec30810f137ba04cbbecaba8f27706c146cc6c6f90db29',
stakedByOperator: '3000000000000000000000',
stakedByDelegates: '0',
stakedTotal: '3000000000000000000000',
pendingStake: '0',
rankingScore: {
rankingScore: '0.4999166805532412',
stakeScore: '0.2499583402766206',
performanceScore: '1',
votingPower: '2499',
status: 'VALIDATOR_NODE_STATUS_TENDERMINT',
__typename: 'RankingScore',
},
__typename: 'Node',
},
__typename: 'NodeEdge',
},
],
__typename: 'NodesConnection',
},
nodeData: {
stakedTotal: '12002000000000000000000',
__typename: 'NodeData',
},
};
@@ -1,325 +0,0 @@
export const proposalsData = {
proposalsConnection: {
edges: [
{
node: {
id: 'e8ba9d268e12514644fd1fc7ff289292f4ce6489cc32cc73133aea52c04aef89',
rationale: {
title: 'Add asset Wrapped Ether',
description: 'Proposal to add asset WETH to Vega network',
__typename: 'ProposalRationale',
},
reference: '',
state: 'STATE_OPEN',
datetime: '2026-12-01T11:41:28.654288Z',
rejectionReason: null,
party: {
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
__typename: 'Party',
},
errorDetails: null,
terms: {
closingDatetime: '2026-12-01T11:45:33Z',
enactmentDatetime: '2026-12-01T11:45:43Z',
change: {
name: 'Wrapped Ether',
symbol: 'WETH',
decimals: 18,
quantum: '0.0008',
source: {
contractAddress: '0x9B18C6CaD886D5653783E2B25759124760F4407F',
withdrawThreshold: '1',
lifetimeLimit: '400000000000000000',
__typename: 'ERC20',
},
__typename: 'NewAsset',
},
__typename: 'ProposalTerms',
},
votes: {
yes: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
no: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
__typename: 'ProposalVotes',
},
__typename: 'Proposal',
},
__typename: 'ProposalEdge',
},
{
node: {
id: 'd848fc7881f13d366df5f61ab139d5fcfa72bf838151bb51b54381870e357931',
rationale: {
title: 'Add asset Dai Stablecoin',
description: 'Proposal to add asset DAI to Vega network',
__typename: 'ProposalRationale',
},
reference: '',
state: 'STATE_ENACTED',
datetime: '2022-11-29T15:49:57.80978Z',
rejectionReason: null,
party: {
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
__typename: 'Party',
},
errorDetails: null,
terms: {
closingDatetime: '2023-04-13T15:52:58Z',
enactmentDatetime: '2023-04-13T15:53:08Z',
change: {
name: 'Dai Stablecoin',
symbol: 'DAI',
decimals: 18,
quantum: '1',
source: {
contractAddress: '0xad018fB8ec00bfd622B91C83E684a6AC7bB8fbA4',
withdrawThreshold: '1',
lifetimeLimit: '500000000000000000000',
__typename: 'ERC20',
},
__typename: 'NewAsset',
},
__typename: 'ProposalTerms',
},
votes: {
yes: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
no: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
__typename: 'ProposalVotes',
},
__typename: 'Proposal',
},
__typename: 'ProposalEdge',
},
{
node: {
id: 'ccbd651b4a1167fd73c4a0340ac759fa0a31ca487ad46a13254b741ad71947ed',
rationale: {
title: 'New DAI market',
description: 'New DAI market',
__typename: 'ProposalRationale',
},
reference: '0VFQusmmESdrP5GuL8naB6lxfoE3RPGaEeo7abdN',
state: 'STATE_ENACTED',
datetime: '2022-11-26T19:36:19.26034Z',
rejectionReason: null,
party: {
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
__typename: 'Party',
},
errorDetails: null,
terms: {
closingDatetime: '2022-11-26T19:36:42Z',
enactmentDatetime: '2023-03-22T13:57:37Z',
change: {
instrument: {
name: 'UNIDAI Monthly (Dec 2022)',
code: 'UNIDAI.MF21',
futureProduct: {
settlementAsset: { symbol: 'tDAI', __typename: 'Asset' },
__typename: 'FutureProduct',
},
__typename: 'InstrumentConfiguration',
},
__typename: 'NewMarket',
},
__typename: 'ProposalTerms',
},
votes: {
yes: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
no: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
__typename: 'ProposalVotes',
},
__typename: 'Proposal',
},
__typename: 'ProposalEdge',
},
{
node: {
id: 'bc70383f0e9515b15542cf4c63590cd2ca46b3363ba7c4a72af0e62112b3951b',
rationale: {
title: 'USDC-III',
description: 'USDC-III D List test',
__typename: 'ProposalRationale',
},
reference: '',
state: 'STATE_ENACTED',
datetime: '2022-11-22T15:17:28.829605Z',
rejectionReason: null,
party: {
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
__typename: 'Party',
},
errorDetails: null,
terms: {
closingDatetime: '2022-11-22T15:18:56Z',
enactmentDatetime: '2022-11-22T15:19:06Z',
change: {
name: 'USDC-III',
symbol: 'USDC-III',
decimals: 18,
quantum: '1',
source: {
contractAddress: '0x1F1A067aEC530b66BA5128C9Db76825eC22c3C6b',
withdrawThreshold: '100000000000000000000000000',
lifetimeLimit: '1000000000000000000000000000',
__typename: 'ERC20',
},
__typename: 'NewAsset',
},
__typename: 'ProposalTerms',
},
votes: {
yes: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
no: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
__typename: 'ProposalVotes',
},
__typename: 'Proposal',
},
__typename: 'ProposalEdge',
},
{
node: {
id: '9d9b2a9d0179d0e4ccb317f6c4a5db0b905d893190bfb5e5499985ef313281c8',
rationale: {
title: 'New BTC market',
description: 'New BTC market',
__typename: 'ProposalRationale',
},
reference: 'AXeRWS3TvLBFDgWOSHQpKFJf3NTbnWK6310q02fZ',
state: 'STATE_ENACTED',
datetime: '2022-11-26T19:36:19.26034Z',
rejectionReason: null,
party: {
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
__typename: 'Party',
},
errorDetails: null,
terms: {
closingDatetime: '2022-11-26T19:36:42Z',
enactmentDatetime: '2023-03-22T13:57:37Z',
change: {
instrument: {
name: 'ETHBTC Quarterly (Feb 2023)',
code: 'ETHBTC.QM21',
futureProduct: {
settlementAsset: { symbol: 'tBTC', __typename: 'Asset' },
__typename: 'FutureProduct',
},
__typename: 'InstrumentConfiguration',
},
__typename: 'NewMarket',
},
__typename: 'ProposalTerms',
},
votes: {
yes: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
no: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
__typename: 'ProposalVotes',
},
__typename: 'Proposal',
},
__typename: 'ProposalEdge',
},
{
node: {
id: '9c48796e7988769ededc2b2b02220b00e93f65f23e8141bf1fd23a6983d95943',
rationale: {
title: 'Update governance.proposal.asset.requiredMajority',
description:
'Proposal to update governance.proposal.asset.requiredMajority to 300}',
__typename: 'ProposalRationale',
},
reference: '',
state: 'STATE_ENACTED',
datetime: '2022-11-22T13:22:52.370655Z',
rejectionReason: null,
party: {
id: '69464e35bcb8e8a2900ca0f87acaf252d50cf2ab2fc73694845a16b7c8a0dc6f',
__typename: 'Party',
},
errorDetails: null,
terms: {
closingDatetime: '2022-11-22T13:27:13Z',
enactmentDatetime: '2022-11-22T13:27:33Z',
change: {
networkParameter: {
key: 'governance.proposal.asset.requiredParticipation',
value: '0.000001',
__typename: 'NetworkParameter',
},
__typename: 'UpdateNetworkParameter',
},
__typename: 'ProposalTerms',
},
votes: {
yes: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
no: {
totalTokens: '0',
totalNumber: '0',
totalEquityLikeShareWeight: '0',
__typename: 'ProposalVoteSide',
},
__typename: 'ProposalVotes',
},
__typename: 'Proposal',
},
__typename: 'ProposalEdge',
},
],
__typename: 'ProposalsConnection',
},
};
@@ -9,7 +9,7 @@
"name": "Token test market",
"code": "Token.24h",
"future": {
"settlementAsset": "73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0",
"settlementAsset": "fBTC",
"quoteName": "fBTC",
"dataSourceSpecForSettlementData": {
"external": {
@@ -49,7 +49,6 @@ describe(
});
beforeEach('visit proposals tab', function () {
cy.clearLocalStorage();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -218,9 +217,9 @@ describe(
vegaWalletSetSpecifiedApprovalAmount('1000');
createRawProposal();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(
rawProposal.rationale.title
).within(() => cy.get(viewProposalButton).click());
getSubmittedProposalFromProposalList(rawProposal.rationale.title)
.as('submittedProposal')
.within(() => cy.get(viewProposalButton).click());
});
voteForProposal('for');
// 3001-VOTE-079
@@ -238,9 +237,9 @@ describe(
);
navigateTo(navigation.proposals);
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(
rawProposal.rationale.title
).within(() => cy.get(viewProposalButton).click());
getSubmittedProposalFromProposalList(rawProposal.rationale.title)
.as('submittedProposal')
.within(() => cy.get(viewProposalButton).click());
});
cy.get(proposalVoteProgressForPercentage)
.contains('100.00%')
@@ -16,7 +16,6 @@ import {
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions';
const proposalListItem = '[data-testid="proposals-list-item"]';
const closedProposals = '[data-testid="closed-proposals"]';
const proposalStatus = '[data-testid="proposal-status"]';
const viewProposalButton = '[data-testid="view-proposal-btn"]';
@@ -36,7 +35,6 @@ context(
});
beforeEach('visit proposals', function () {
cy.clearLocalStorage();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -53,8 +51,7 @@ context(
waitForSpinner();
cy.get(closedProposals).within(() => {
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.last()
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => {
cy.get(proposalStatus).should('have.text', 'Enacted ');
cy.get(viewProposalButton).click();
@@ -81,8 +78,7 @@ context(
waitForSpinner();
cy.get(openProposals).within(() => {
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.last()
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click());
});
getProposalInformationFromTable('State')
@@ -115,8 +111,7 @@ context(
waitForSpinner();
cy.get(openProposals, { timeout: 6000 }).within(() => {
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.last()
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click());
});
getProposalInformationFromTable('State')
@@ -138,8 +133,7 @@ context(
waitForSpinner();
cy.get(openProposals).within(() => {
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.last()
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click());
});
getProposalInformationFromTable('State')
@@ -84,7 +84,6 @@ context(
});
beforeEach('visit governance tab', function () {
cy.clearLocalStorage();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -50,8 +50,6 @@ const liquidityVoteStatus = 'liquidity-votes-status';
const tokenVoteStatus = 'token-votes-status';
const proposalTermsSection = 'proposal';
const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey');
const fUSDCId =
'816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc';
const epochTimeout = Cypress.env('epochTimeout');
const proposalTimeout = { timeout: 14000 };
@@ -76,7 +74,6 @@ context(
});
beforeEach('visit governance tab', function () {
cy.clearLocalStorage();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -267,7 +264,7 @@ context(
it('Unable to submit update market proposal without minimum amount of tokens', function () {
vegaWalletTeardown();
vegaWalletFaucetAssetsWithoutCheck(
fUSDCId,
'fUSDC',
'1000000',
vegaWalletPublicKey
);
@@ -293,7 +290,7 @@ context(
// 3001-VOTE-092 3004-PMAC-001
it('Able to submit update market proposal and vote for proposal', function () {
vegaWalletFaucetAssetsWithoutCheck(
fUSDCId,
'fUSDC',
'1000000',
vegaWalletPublicKey
);
@@ -305,10 +302,7 @@ context(
cy.get('dd').eq(0).should('have.text', 'Test market 1');
cy.get('dd').eq(1).should('have.text', 'TEST.24h');
cy.get('dd').eq(2).should('not.be.empty');
cy.get('dd')
.eq(2)
.invoke('text')
.as('EnactedMarketId', { type: 'static' });
cy.get('dd').eq(2).invoke('text').as('EnactedMarketId');
});
cy.get('@EnactedMarketId').then((marketId) => {
cy.VegaWalletSubmitLiquidityProvision(String(marketId), '1');
@@ -326,7 +320,6 @@ context(
cy.get('@EnactedMarketId').then((marketId) => {
cy.contains(String(marketId))
.parentsUntil(proposalListItem)
.last()
.within(() => {
cy.getByTestId(viewProposalBtn).click();
});
@@ -380,19 +373,16 @@ context(
cy.get(newProposalSubmitButton).should('be.visible').click();
// cannot submit a proposal with ERC20 address already in use
cy.contains('Proposal rejected', proposalTimeout).should('be.visible');
cy.getByTestId('dialog-content')
.last()
.within(() => {
cy.get('p').should(
'have.text',
'PROPOSAL_ERROR_ERC20_ADDRESS_ALREADY_IN_USE'
);
});
cy.getByTestId('dialog-content').within(() => {
cy.get('p').should(
'have.text',
'PROPOSAL_ERROR_ERC20_ADDRESS_ALREADY_IN_USE'
);
});
closeDialog();
navigateTo(navigation.proposals);
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.last()
.within(() => {
cy.getByTestId(viewProposalBtn).click();
});
@@ -430,7 +420,6 @@ context(
cy.get(proposalType)
.contains('Update asset')
.parentsUntil(proposalListItem)
.last()
.within(() => {
cy.get(proposalDetails).should('contain.text', assetId); // 3001-VOTE-029
cy.getByTestId(viewProposalBtn).click();
@@ -35,7 +35,6 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
});
beforeEach('visit proposals tab', function () {
cy.clearLocalStorage();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -60,10 +59,7 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
cy.get(openProposals).within(() => {
cy.get(proposalClosingDate).first().should('contain.text', 'year');
cy.get(proposalClosingDate).should('contain.text', 'months');
cy.get(proposalClosingDate)
.last()
.invoke('text')
.should('match', /days|minutes/);
cy.get(proposalClosingDate).last().should('contain.text', 'days');
});
});
@@ -25,10 +25,9 @@ const rewardsTimeOut = { timeout: 60000 };
context('rewards - flow', { tags: '@slow' }, function () {
before('set up environment to allow rewards', function () {
cy.clearLocalStorage();
cy.visit('/');
waitForSpinner();
depositAsset(vegaAssetAddress, '1000', 18);
depositAsset(vegaAssetAddress, '1000');
cy.validatorsSelfDelegate();
ethereumWalletConnect();
cy.connectVegaWallet();
@@ -57,7 +56,7 @@ context('rewards - flow', { tags: '@slow' }, function () {
cy.getByTestId(rewardsTable)
.first()
.within(() => {
cy.getByTestId('asset', rewardsTimeOut).should('have.text', 'Vega');
cy.getByTestId('asset').should('have.text', 'Vega');
cy.getByTestId('ACCOUNT_TYPE_GLOBAL_REWARD').should('have.text', '1');
cy.getByTestId('ACCOUNT_TYPE_FEES_INFRASTRUCTURE').should(
'have.text',
@@ -94,13 +93,13 @@ context('rewards - flow', { tags: '@slow' }, function () {
.within(() => {
cy.get('h2').first().should('contain.text', 'EPOCH');
cy.getByTestId('individual-rewards-asset').should('have.text', 'Vega');
cy.getByTestId('ACCOUNT_TYPE_GLOBAL_REWARD', rewardsTimeOut)
.should('contain.text', '0.4415')
.and('contain.text', '(44.15%)');
cy.getByTestId('ACCOUNT_TYPE_GLOBAL_REWARD')
.should('contain.text', '0.1177')
.and('contain.text', '(11.7733%)');
cy.getByTestId('ACCOUNT_TYPE_FEES_INFRASTRUCTURE')
.should('contain.text', '0.0004')
.and('contain.text', '(44.15%)');
cy.getByTestId('total').should('have.text', '0.4419');
.should('contain.text', '0.0001')
.and('contain.text', '(11.7733%)');
cy.getByTestId('total').should('have.text', '0.1179');
});
});
});
@@ -55,6 +55,7 @@ context(
function () {
// 2001-STKE-002, 2001-STKE-032
before('visit staking tab and connect vega wallet', function () {
cy.clearAllLocalStorage();
cy.visit('/');
ethereumWalletConnect();
// this is a workaround for #2422 which can be removed once issue is resolved
@@ -66,7 +67,6 @@ context(
beforeEach(
'teardown wallet & drill into a specific validator',
function () {
cy.clearLocalStorage();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -53,7 +53,6 @@ context(
beforeEach(
'teardown wallet & drill into a specific validator',
function () {
cy.clearLocalStorage();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -91,14 +90,9 @@ context(
verifyEthWalletTotalAssociatedBalance('2.0');
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
2.0
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
});
cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', 2.0);
});
@@ -134,38 +128,26 @@ context(
stakingPageAssociateTokens('1001', { approve: true });
verifyEthWalletAssociatedBalance('1,001.00');
verifyEthWalletTotalAssociatedBalance('1,001.00');
cy.get(vegaWallet)
.last()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'1,001.00'
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'1,001.00'
);
});
});
it('Able to disassociate a partial amount of tokens currently associated', function () {
stakingPageAssociateTokens('2');
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
2.0
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
});
cy.get('button').contains('Select a validator to nominate').click();
stakingPageDisassociateTokens('1');
verifyEthWalletAssociatedBalance('1.0');
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
1.0
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 1.0);
});
});
it('Able to disassociate all tokens - using max', function () {
@@ -173,40 +155,26 @@ context(
const warningText =
'Warning: Any tokens that have been nominated to a node will sacrifice rewards they are due for the current epoch. If you do not wish to sacrifice these, you should remove stake from a node at the end of an epoch before disassociation.';
stakingPageAssociateTokens('2');
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
2.0
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
});
cy.get('button').contains('Select a validator to nominate').click();
cy.get(ethWalletDissociateButton).click();
cy.get(disassociationWarning).should('contain', warningText);
stakingPageDisassociateAllTokens();
cy.get(ethWalletContainer)
.first()
.within(() => {
cy.contains(vegaWalletPublicKeyShort, { timeout: 20000 }).should(
'not.exist'
);
});
cy.get(ethWalletContainer)
.first()
.within(() => {
cy.contains(vegaWalletPublicKeyShort, { timeout: 20000 }).should(
'not.exist'
);
});
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
0.0
);
});
cy.get(ethWalletContainer).within(() => {
cy.contains(vegaWalletPublicKeyShort, { timeout: 20000 }).should(
'not.exist'
);
});
cy.get(ethWalletContainer).within(() => {
cy.contains(vegaWalletPublicKeyShort, { timeout: 20000 }).should(
'not.exist'
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 0.0);
});
});
it('Able to associate and disassociate vesting contract tokens', function () {
@@ -232,14 +200,9 @@ context(
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
verifyEthWalletAssociatedBalance('2.0');
verifyEthWalletTotalAssociatedBalance('2.0');
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
2.0
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
});
cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', 2.0);
stakingPageDisassociateTokens('1', {
type: 'contract',
@@ -265,61 +228,38 @@ context(
stakingPageAssociateTokens('21', { type: 'wallet' });
cy.get('button').contains('Select a validator to nominate').click();
stakingPageAssociateTokens('37', { type: 'contract' });
cy.get(vestingContractSection)
.first()
.within(() => {
cy.get(associatedKey).should(
'contain',
Cypress.env('vegaWalletPublicKeyShort')
);
cy.get(associatedAmount, txTimeout).should('contain', 37);
});
cy.get(vegaInWalletSection)
.first()
.within(() => {
cy.get(associatedKey).should(
'contain',
Cypress.env('vegaWalletPublicKeyShort')
);
cy.get(associatedAmount, txTimeout).should('contain', 21);
});
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
58
);
});
cy.get(vestingContractSection).within(() => {
cy.get(associatedKey).should(
'contain',
Cypress.env('vegaWalletPublicKeyShort')
);
cy.get(associatedAmount, txTimeout).should('contain', 37);
});
cy.get(vegaInWalletSection).within(() => {
cy.get(associatedKey).should(
'contain',
Cypress.env('vegaWalletPublicKeyShort')
);
cy.get(associatedAmount, txTimeout).should('contain', 21);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 58);
});
stakingPageDisassociateTokens('6', { type: 'contract' });
cy.get(vestingContractSection)
.first()
.within(() => {
cy.get(associatedAmount, txTimeout).should('contain', 31);
});
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
52
);
});
cy.get(vestingContractSection).within(() => {
cy.get(associatedAmount, txTimeout).should('contain', 31);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 52);
});
navigateTo(navigation.validators);
stakingPageDisassociateTokens('9', { type: 'wallet' });
cy.get(vegaInWalletSection)
.first()
.within(() => {
cy.get(associatedAmount, txTimeout).should('contain', 12);
});
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
43
);
});
cy.get(vegaInWalletSection).within(() => {
cy.get(associatedAmount, txTimeout).should('contain', 12);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 43);
});
});
it('Not able to associate more tokens than owned', function () {
@@ -378,14 +318,9 @@ context(
Cypress.env('vegaWalletPublicKey2')
);
stakingPageAssociateTokens('2');
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
2.0
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
});
cy.get(associateCompleteText).should(
'have.text',
`Vega key ${Cypress.env(
@@ -4,7 +4,10 @@ import {
waitForSpinner,
} from '../../support/common.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import { depositAsset } from '../../support/wallet-teardown.functions';
import {
depositAsset,
vegaWalletTeardown,
} from '../../support/wallet-teardown.functions';
const withdraw = 'withdraw';
const withdrawalForm = 'withdraw-form';
@@ -22,13 +25,6 @@ const withdrawalAmount = 'withdrawal-amount';
const withdrawalRecipient = 'withdrawal-recipient';
const withdrawFundsButton = 'withdraw-funds';
const completeWithdrawalButton = 'complete-withdrawal';
const tableTxHash = '[col-id="txHash"]';
const tableAssetSymbol = '[col-id="asset.symbol"]';
const tableAmount = '[col-id="amount"]';
const tableReceiverAddress = '[col-id="details.receiverAddress"]';
const tableWithdrawnTimeStamp = '[col-id="withdrawnTimestamp"]';
const tableWithdrawnStatus = '[col-id="status"]';
const tableCreatedTimeStamp = '[col-id="createdTimestamp"]';
const usdtName = 'USDC (local)';
const usdcEthAddress = '0x1b8a1B6CBE5c93609b46D1829Cc7f3Cb8eeE23a0';
const usdcSymbol = 'tUSDC';
@@ -46,23 +42,26 @@ context(
cy.visit('/');
// When running tests locally, will fail if run without restarting capsule
cy.updateCapsuleMultiSig().then(() => {
ethereumWalletConnect();
depositAsset(usdcEthAddress, '1000', 5);
depositAsset(usdcEthAddress, '100');
});
});
beforeEach('Navigate to withdrawal page', function () {
cy.clearLocalStorage();
cy.reload();
waitForSpinner();
navigateTo(navigation.withdraw);
cy.connectVegaWallet();
ethereumWalletConnect();
vegaWalletTeardown();
});
it('Able to open withdrawal form with vega wallet connected', function () {
// needs to reload page for withdrawal form to be displayed in ci - not reproducible outside of ci
cy.reload();
waitForSpinner();
ethereumWalletConnect();
cy.getByTestId(withdraw).should('be.visible').click();
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
cy.getByTestId(withdrawalForm).within(() => {
cy.get('select').find('option').should('have.length.at.least', 2);
cy.getByTestId(ethAddressInput).should('be.visible');
cy.getByTestId(amountInput).should('be.visible');
@@ -71,7 +70,7 @@ context(
it('Unable to submit withdrawal with invalid fields', function () {
cy.getByTestId(withdraw).should('be.visible').click();
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
cy.getByTestId(withdrawalForm).within(() => {
cy.get('select').select(usdtSelectValue, { force: true });
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
cy.getByTestId(submitWithdrawalButton).click();
@@ -95,7 +94,7 @@ context(
it('Able to withdraw asset: -eth wallet connected -withdraw funds button', function () {
// fill in withdrawal form
cy.getByTestId(withdraw).should('be.visible').click();
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
cy.getByTestId(withdrawalForm).within(() => {
cy.get('select').select(usdtSelectValue, { force: true });
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
cy.getByTestId(withdrawalThreshold).should(
@@ -103,7 +102,7 @@ context(
'100,000.00000T'
);
cy.getByTestId(delayTime).should('have.text', 'None');
cy.getByTestId(amountInput).click().type('120');
cy.getByTestId(amountInput).click().type('100');
cy.getByTestId(submitWithdrawalButton).click();
});
@@ -117,7 +116,7 @@ context(
.should('have.attr', 'href')
.and('contain', '/txs/');
cy.getByTestId(withdrawalAssetSymbol).should('have.text', usdcSymbol);
cy.getByTestId(withdrawalAmount).should('have.text', '120.00');
cy.getByTestId(withdrawalAmount).should('have.text', '100.00');
cy.getByTestId(withdrawalRecipient)
.should('have.text', truncatedWithdrawalEthAddress)
.and('have.attr', 'href')
@@ -129,20 +128,26 @@ context(
'Withdraw asset complete'
);
cy.getByTestId(dialogClose).click();
// need to reload page to see withdrawal history complete
cy.reload();
waitForAssetsDisplayed(usdtName);
// withdrawal history for complete withdrawal displayed
cy.get(tableWithdrawnStatus)
.eq(1, txTimeout)
.should('have.text', 'Completed')
cy.get('[col-id="txHash"]', txTimeout)
.should('have.length.above', 1)
.eq(1)
.parent()
.within(() => {
cy.get(tableAssetSymbol).should('have.text', usdcSymbol);
cy.get(tableAmount).should('have.text', '120.00');
cy.get(tableReceiverAddress)
cy.get('[col-id="asset.symbol"]').should('have.text', usdcSymbol);
cy.get('[col-id="amount"]').should('have.text', '100.00');
cy.get('[col-id="details.receiverAddress"]')
.find('a')
.should('have.attr', 'href')
.and('contain', 'https://sepolia.etherscan.io/address/');
cy.get(tableWithdrawnTimeStamp).should('not.be.empty');
cy.get(tableTxHash)
cy.get('[col-id="withdrawnTimestamp"]').should('not.be.empty');
cy.get('[col-id="status"]').should('have.text', 'Completed');
cy.get('[col-id="txHash"]')
.find('a')
.should('have.attr', 'href')
.and('contain', 'https://sepolia.etherscan.io/tx/');
@@ -150,16 +155,16 @@ context(
});
// Skipping because of bug #1857
it('Able to withdraw asset: -eth wallet not connected', function () {
it.skip('Able to withdraw asset: -eth wallet not connected', function () {
const ethWalletAddress = Cypress.env('ethWalletPublicKey');
cy.reload();
waitForAssetsDisplayed(usdtName);
// fill in withdrawal form
cy.getByTestId(withdraw).should('be.visible').click();
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
cy.getByTestId(withdrawalForm).within(() => {
cy.get('select').select(usdtSelectValue, { force: true });
cy.getByTestId(ethAddressInput).should('be.empty');
cy.getByTestId(amountInput).click().type('110');
cy.getByTestId(amountInput).click().type('100');
cy.getByTestId(submitWithdrawalButton).click();
// Need eth address to submit withdrawal
@@ -175,20 +180,20 @@ context(
'Transaction complete'
);
cy.getByTestId(dialogClose).click();
cy.get(tableTxHash)
.eq(1)
.should('have.text', 'Complete withdrawal')
cy.getByTestId(completeWithdrawalButton)
.eq(0)
.parent()
.parent()
.within(() => {
cy.get(tableAssetSymbol).should('have.text', usdcSymbol);
cy.get(tableAmount).should('have.text', '110.00');
cy.get(tableReceiverAddress)
cy.get('[col-id="asset.symbol"]').should('have.text', usdcSymbol);
cy.get('[col-id="amount"]').should('have.text', '100.00');
cy.get('[col-id="details.receiverAddress"]')
.find('a')
.should('have.attr', 'href')
.and('contain', 'https://sepolia.etherscan.io/address/');
cy.get(tableCreatedTimeStamp).should('not.be.empty');
cy.get('[col-id="createdTimestamp"]').should('not.be.empty');
cy.getByTestId(completeWithdrawalButton).click();
// Unable to complete withdrawal in Capsule
});
});
@@ -197,28 +202,26 @@ context(
const expectedErrorTxt = `You are connected in a view only state for public key: ${vegaWalletPubKey}. In order to send transactions you must connect to a real wallet.`;
// Disconnect vega wallet
cy.getByTestId('manage-vega-wallet').last().click();
cy.getByTestId('manage-vega-wallet').click();
cy.getByTestId('disconnect').click();
cy.connectPublicKey(vegaWalletPubKey);
cy.getByTestId(withdraw).should('be.visible').click();
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
cy.getByTestId(withdrawalForm).within(() => {
cy.get('select').select(usdtSelectValue, { force: true });
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
cy.getByTestId(amountInput).click().type('100');
cy.getByTestId(submitWithdrawalButton).click();
});
cy.getByTestId('dialog-content')
.last()
.within(() => {
cy.get('h1').should('have.text', 'Transaction failed');
cy.getByTestId('Error').should('have.text', expectedErrorTxt);
});
cy.getByTestId('dialog-content').within(() => {
cy.get('h1').should('have.text', 'Transaction failed');
cy.getByTestId('Error').should('have.text', expectedErrorTxt);
});
});
function waitForAssetsDisplayed(expectedAsset: string) {
cy.getByTestId('currency-title').should('contain.text', expectedAsset);
cy.contains(expectedAsset, txTimeout).should('be.visible');
}
}
);
@@ -131,7 +131,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
.within(() => {
cy.get('span')
.first()
.should('have.text', 'http://localhost:3008/graphql');
.should('have.text', 'http://localhost:3028/query');
cy.getByTestId('link').should('exist');
});
});
@@ -3,14 +3,11 @@ import {
navigation,
verifyPageHeader,
verifyTabHighlighted,
waitForSpinner,
} from '../../support/common.functions';
import {
goToMakeNewProposal,
governanceProposalType,
} from '../../support/governance.functions';
import { mockNetworkUpgradeProposal } from '../../support/proposal.functions';
const proposalDocumentationLink = '[data-testid="proposal-documentation-link"]';
const newProposalButton = '[data-testid="new-proposal-link"]';
const newProposalLink = '[data-testid="new-proposal-link"]';
const governanceDocsUrl = 'https://vega.xyz/governance';
const connectToVegaWalletButton = '[data-testid="connect-to-vega-wallet-btn"]';
@@ -24,140 +21,56 @@ context(
navigateTo(navigation.proposals);
});
it('should have governance tab highlighted', function () {
verifyTabHighlighted(navigation.proposals);
});
it('should have GOVERNANCE header visible', function () {
verifyPageHeader('Proposals');
});
it('should be able to see a working link for - find out more about Vega governance', function () {
// 3001-VOTE-001
cy.get(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`
);
}
});
});
it('should be able to see button for - new proposal', function () {
// 3001-VOTE-002
cy.get(newProposalLink)
.should('be.visible')
.and('have.text', 'New proposal')
.and('have.attr', 'href')
.and('equal', '/proposals/propose');
});
it('should be able to see a connect wallet button - if vega wallet disconnected and user is submitting new proposal', function () {
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
cy.get(connectToVegaWalletButton)
.should('be.visible')
.and('have.text', 'Connect Vega wallet');
});
it('should see open network upgrade proposal on homepage', function () {
mockNetworkUpgradeProposal();
cy.visit('/');
cy.getByTestId('home-proposal-list').within(() => {
cy.getByTestId('protocol-upgrade-proposals-list-item').should('exist');
cy.getByTestId('protocol-upgrade-proposal-title').should(
'have.text',
'Vega release v1'
);
describe('with no network change proposals', function () {
it('should have governance tab highlighted', function () {
verifyTabHighlighted(navigation.proposals);
});
});
it('should see network upgrade proposals in proposals list', function () {
mockNetworkUpgradeProposal();
navigateTo(navigation.proposals);
cy.getByTestId('open-proposals').within(() => {
cy.get('li')
.eq(0)
.should(
'have.attr',
'data-testid',
'protocol-upgrade-proposals-list-item'
)
.within(() => {
cy.get('h2').should('have.text', 'Vega release v1');
cy.getByTestId('protocol-upgrade-proposal-type').should(
'have.text',
'Network Upgrade'
);
cy.getByTestId('protocol-upgrade-proposal-release-tag').should(
'have.text',
'Vega release tagv1'
);
cy.getByTestId('protocol-upgrade-proposal-block-height').should(
'have.text',
'Upgrade block height2015942'
);
cy.getByTestId('protocol-upgrade-proposal-status').should(
'have.text',
'Approved'
);
it('should have GOVERNANCE header visible', function () {
verifyPageHeader('Proposals');
});
it('should be able to see a working link for - find out more about Vega governance', function () {
// 3001-VOTE-001
cy.get(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`
);
}
});
});
cy.getByTestId('closed-proposals').within(() => {
cy.getByTestId('protocol-upgrade-proposals-list-item').should(
'have.length',
1
);
});
});
it('should see details of network upgrade proposal', function () {
mockNetworkUpgradeProposal();
navigateTo(navigation.proposals);
cy.getByTestId('protocol-upgrade-proposals-list-item')
.first()
.find('[data-testid="view-proposal-btn"]')
.click();
cy.getByTestId('protocol-upgrade-proposal').within(() => {
cy.get('h1').should('have.text', 'Vega Release v1');
cy.getByTestId('protocol-upgrade-block-height').should(
'have.text',
'2015942 (currently 2014133)'
);
cy.getByTestId('protocol-upgrade-state').should(
'have.text',
'Approved'
);
cy.getByTestId('protocol-upgrade-release-tag').should(
'have.text',
'v1'
);
cy.getByTestId('protocol-upgrade-approval-status')
.should('contain.text', '99.98% approval (% validator voting power)')
.and('contain.text', '(67% voting power required)');
cy.get('h2').should('contain.text', 'Approvers (4/4 validators)');
cy.getByTestId('validator-name')
.should('have.length', 4)
.each(($validator) => {
cy.wrap($validator).find('a').should('have.attr', 'href');
});
cy.getByTestId('validator-voting-power').each(
($validatorVotingPower) => {
cy.wrap($validatorVotingPower)
.invoke('text')
.should('contain', '%');
}
);
it('should be able to see button for - new proposal', function () {
// 3001-VOTE-002
cy.get(newProposalLink)
.should('be.visible')
.and('have.text', 'New proposal')
.and('have.attr', 'href')
.and('equal', '/proposals/propose');
});
// Skipping this test for now, the new proposal button no longer takes a user directly
// to a proposal form, instead it takes them to a page where they can select a proposal type.
// Keeping this test here for now as it can be repurposed to test the new proposal forms.
it.skip('should be able to see a connect wallet button - if vega wallet disconnected and new proposal button selected', function () {
cy.get(newProposalButton).should('be.visible').click();
cy.get(connectToVegaWalletButton)
.should('be.visible')
.and('have.text', 'Connect Vega wallet');
navigateTo(navigation.proposals);
waitForSpinner();
});
});
}
@@ -17,15 +17,10 @@ const banner = 'view-banner';
context('View functionality with public key', { tags: '@smoke' }, function () {
before('send asset to wallet', function () {
vegaWalletFaucetAssetsWithoutCheck(
'816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc',
'1000000',
vegaWalletPubKey
);
vegaWalletFaucetAssetsWithoutCheck('fUSDC', '1000000', vegaWalletPubKey);
});
beforeEach('visit home page', function () {
cy.clearLocalStorage();
cy.visit('/');
waitForSpinner();
cy.connectPublicKey(vegaWalletPubKey);
@@ -13,7 +13,6 @@ context(
{ tags: '@regression' },
function () {
before('navigate to rewards page', function () {
cy.clearLocalStorage();
cy.visit('/');
navigateTo(navigation.rewards);
});
@@ -282,30 +282,26 @@ context(
describe('Vega wallet with assets', function () {
const assets = [
{
id: '816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc',
id: 'fUSDC',
name: 'USDC (fake)',
symbol: 'fUSDC',
amount: '1000000',
expectedAmount: '10.00',
},
{
id: '8566db7257222b5b7ef2886394ad28b938b28680a54a169bbc795027b89d6665',
id: 'fDAI',
name: 'DAI (fake)',
symbol: 'fDAI',
amount: '200000',
expectedAmount: '2.00',
},
{
id: '73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0',
id: 'fBTC',
name: 'BTC (fake)',
symbol: 'fBTC',
amount: '600000',
expectedAmount: '6.00',
},
{
id: 'e02d4c15d790d1d2dffaf2dcd1cf06a1fe656656cf4ed18c8ce99f9e83643567',
id: 'fEURO',
name: 'EURO (fake)',
symbol: 'fEURO',
amount: '800000',
expectedAmount: '8.00',
},
@@ -326,25 +322,28 @@ context(
});
});
for (const { name, symbol, expectedAmount } of assets) {
it(`should see ${name} within vega wallet`, () => {
for (const { id, name, expectedAmount } of assets) {
it(`should see ${id} within vega wallet`, () => {
cy.get(walletContainer).within(() => {
cy.get(vegaWalletCurrencyTitle)
.contains(name, txTimeout)
.contains(id, txTimeout)
.should('be.visible');
cy.get(vegaWalletCurrencyTitle)
.contains(name)
.contains(id)
.parent()
.siblings()
.invoke('text')
.then(parseFloat)
.should('be.gte', parseFloat(expectedAmount));
.should('have.length.above', 3)
.then((el) => {
const value = parseFloat(el);
cy.wrap(value).should('be.gte', parseFloat(expectedAmount));
});
cy.get(vegaWalletCurrencyTitle)
.contains(name)
.contains(id)
.parent()
.contains(symbol);
.contains(name);
});
});
}
@@ -12,7 +12,6 @@ context(
{ tags: '@smoke' },
function () {
before('navigate to withdrawals page', function () {
cy.clearAllLocalStorage();
cy.visit('/');
navigateTo(navigation.withdraw);
});
@@ -90,7 +90,6 @@ export function getSubmittedProposalFromProposalList(proposalTitle: string) {
export function getProposalIdFromList(proposalTitle: string) {
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.last()
.within(() => {
cy.get(proposalDetails)
.invoke('text')
@@ -134,7 +133,7 @@ export function waitForProposalSync() {
// before proposal appears in the list - so rather than hard coded wait - we just wait on the
// delegation checks that are performed on the governance page.
cy.intercept('POST', '/graphql', (req) => {
cy.intercept('POST', '/query', (req) => {
if (req.body.operationName === 'Delegations') {
req.alias = 'proposalDelegationsCompletion';
}
@@ -144,7 +143,7 @@ export function waitForProposalSync() {
cy.wait(['@proposalDelegationsCompletion', '@proposalDelegationsCompletion']);
// Turn off this intercept from here on in
cy.intercept('POST', '/graphql', (req) => {
cy.intercept('POST', '/query', (req) => {
if (req.body.operationName === 'Delegations') {
req.continue();
}
@@ -1,9 +1,5 @@
import { addSeconds, millisecondsToSeconds } from 'date-fns';
import type { ProposalSubmissionBody } from '@vegaprotocol/wallet';
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { upgradeProposalsData } from '../fixtures/mocks/network-upgrade';
import { proposalsData } from '../fixtures/mocks/proposals';
import { nodeData } from '../fixtures/mocks/nodes';
export function createUpdateNetworkProposalTxBody(): ProposalSubmissionBody {
const MIN_CLOSE_SEC = 5;
@@ -84,11 +80,3 @@ export function createFreeFormProposalTxBody(): ProposalSubmissionBody {
},
};
}
export function mockNetworkUpgradeProposal() {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Nodes', nodeData);
aliasGQLQuery(req, 'Proposals', proposalsData);
aliasGQLQuery(req, 'ProtocolUpgrades', upgradeProposalsData);
});
}
@@ -54,7 +54,6 @@ export function stakingValidatorPageRemoveStake(stake: string) {
.and('contain', `Remove ${stake} $VEGA tokens at the end of epoch`)
.and('be.visible')
.click();
cy.contains('been removed from validator', txTimeout).should('be.visible');
closeDialog();
}
@@ -185,7 +184,7 @@ export function validateValidatorListTotalStakeAndShare(
) {
cy.contains('Loading...', epochTimeout).should('not.exist');
waitForBeginningOfEpoch();
cy.get(`[row-id="${positionOnList}"]`)
cy.get(`[row-id="${positionOnList}"]:visible`)
.eq(1)
.within(() => {
cy.getByTestId(stakeValidatorListTotalStake, epochTimeout).should(
@@ -221,12 +220,12 @@ export function ensureSpecifiedUnstakedTokensAreAssociated(
}
export function closeStakingDialog() {
cy.getByTestId('dialog-title').should(
cy.get('[data-testid="dialog-title"]:visible').should(
'contain.text',
'At the beginning of the next epoch'
);
cy.getByTestId('dialog-content')
.last()
cy.get('[data-testid="dialog-content"]:visible')
.first()
.within(() => {
cy.get('a').should('have.text', 'Back to Staking').click();
});
@@ -9,7 +9,7 @@ import {
import { ethers, Wallet } from 'ethers';
const associatedAmountInWallet = '[data-testid="associated-amount"]:visible';
const vegaWalletContainer = 'aside [data-testid="vega-wallet"]';
const vegaWalletContainer = 'aside [data-testid="vega-wallet"]:visible';
const vegaWalletMnemonic = Cypress.env('vegaWalletMnemonic');
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey');
const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress');
@@ -35,25 +35,18 @@ const stakingBridgeContract = new StakingBridge(
);
const vestingContract = new TokenVesting(vegaTokenContractAddress, signer);
export async function depositAsset(
assetEthAddress: string,
amount: string,
decimalPlaces: number
) {
export async function depositAsset(assetEthAddress: string, amount: string) {
// Approve asset
const faucet = new TokenFaucetable(assetEthAddress, signer);
cy.wrap(
faucet.approve(Erc20BridgeAddress, amount + '0'.repeat(decimalPlaces + 1)),
{
timeout: transactionTimeout,
log: false,
}
).then(() => {
cy.wrap(faucet.approve(Erc20BridgeAddress, amount + '0'.repeat(19)), {
timeout: transactionTimeout,
log: false,
}).then(() => {
const collateralBridge = new CollateralBridge(Erc20BridgeAddress, signer);
cy.wrap(
collateralBridge.deposit_asset(
assetEthAddress,
amount + '0'.repeat(decimalPlaces),
amount + '0'.repeat(18),
'0x' + vegaWalletPubKey
),
{ timeout: transactionTimeout, log: false }
@@ -109,12 +102,11 @@ async function vegaWalletTeardownStaking(stakingBridgeContract: StakingBridge) {
cy.highlight('Tearing down staking tokens from vega wallet if present');
cy.wrap(
stakingBridgeContract.stake_balance(ethWalletPubKey, vegaWalletPubKey),
{ timeout: transactionTimeout }
{ timeout: transactionTimeout, log: false }
).then((stakeBalance) => {
if (Number(stakeBalance) != 0) {
cy.get(vegaWalletContainer).within(() => {
cy.getByTestId('currency-value')
.first()
.invoke('text')
.then(($associatedAmount) => {
cy.wrap(
@@ -122,34 +114,14 @@ async function vegaWalletTeardownStaking(stakingBridgeContract: StakingBridge) {
String(stakeBalance),
vegaWalletPubKey
),
{ timeout: transactionTimeout }
{ timeout: transactionTimeout, log: false }
);
cy.wrap(
vestingContract.stake_balance(ethWalletPubKey, vegaWalletPubKey),
{
cy.get("[data-testid='currency-value']")
.first()
.invoke('text', {
timeout: transactionTimeout,
log: false,
}
).then((vestingAmount) => {
if (Number(vestingAmount) != 0) {
cy.contains('Associated', {
timeout: transactionTimeout,
})
.parent()
.parent()
.within(() => {
cy.getByTestId('currency-value', {
timeout: transactionTimeout,
})
.should('have.length', 1)
.invoke('text')
.as('displayedAmount');
cy.get('@displayedAmount', {
timeout: transactionTimeout,
}).should('not.eq', $associatedAmount);
});
}
});
})
.should('not.eq', $associatedAmount);
});
});
}
@@ -165,7 +137,7 @@ async function vegaWalletTeardownVesting(vestingContract: TokenVesting) {
if (Number(vestingAmount) != 0) {
cy.wrap(
vestingContract.remove_stake(String(vestingAmount), vegaWalletPubKey),
{ timeout: transactionTimeout }
{ timeout: transactionTimeout, log: false }
);
}
});
+1 -1
View File
@@ -8,7 +8,7 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_VEGA_CONFIG_URL=''
NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_URL=http://localhost:3028/query
NX_ETHEREUM_CHAIN_ID=1440
NX_ETH_URL_CONNECT=1
NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
+1 -1
View File
@@ -1,7 +1,7 @@
# App configuration variables
NX_VEGA_ENV=TESTNET
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_VEGA_URL=https://api.n08.testnet.vega.xyz/graphql
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+1 -16
View File
@@ -3,7 +3,7 @@ import './i18n';
import React, { useEffect } from 'react';
import * as Sentry from '@sentry/react';
import { Integrations } from '@sentry/tracing';
import { BrowserRouter as Router, useLocation } from 'react-router-dom';
import { BrowserRouter as Router } from 'react-router-dom';
import { AppLoader } from './app-loader';
import { NetworkInfo } from '@vegaprotocol/network-info';
import { BalanceManager } from './components/balance-manager';
@@ -149,20 +149,6 @@ const Web3Container = ({
);
};
const ScrollToTop = () => {
const { pathname } = useLocation();
useEffect(() => {
// "document.documentElement.scrollTo" is the magic for React Router Dom v6
document.documentElement.scrollTo({
top: 0,
left: 0,
});
}, [pathname]);
return null;
};
const AppContainer = () => {
const { config, loading, error } = useEthereumConfig();
const { VEGA_ENV, GIT_COMMIT_HASH, GIT_BRANCH, ETHEREUM_PROVIDER_URL } =
@@ -197,7 +183,6 @@ const AppContainer = () => {
return (
<Router>
<ScrollToTop />
<AppStateProvider>
<div className="grid min-h-full text-white">
<AsyncRenderer<EthereumConfig | null>
@@ -1,39 +0,0 @@
import { render, screen } from '@testing-library/react';
import { DisconnectedNotice } from './disconnected-notice';
describe('DisconnectedNotice', () => {
it('renders Notification when isDisconnected is true and correctNetworkChainId is valid', () => {
render(
<DisconnectedNotice isDisconnected={true} correctNetworkChainId={'1'} />
);
const disconnectedNotice = screen.getByTestId('disconnected-notice');
expect(disconnectedNotice).toBeInTheDocument();
});
it("doesn't render Notification when isDisconnected is false", () => {
render(
<DisconnectedNotice isDisconnected={false} correctNetworkChainId={'1'} />
);
const disconnectedNotice = screen.queryByTestId('disconnected-notice');
expect(disconnectedNotice).not.toBeInTheDocument();
});
it("doesn't render Notification when correctNetworkChainId is undefined", () => {
render(
<DisconnectedNotice
isDisconnected={true}
correctNetworkChainId={undefined}
/>
);
const disconnectedNotice = screen.queryByTestId('disconnected-notice');
expect(disconnectedNotice).not.toBeInTheDocument();
});
it("doesn't render Notification when correctNetworkChainId is null", () => {
render(
<DisconnectedNotice isDisconnected={true} correctNetworkChainId={null} />
);
const disconnectedNotice = screen.queryByTestId('disconnected-notice');
expect(disconnectedNotice).not.toBeInTheDocument();
});
});
@@ -1,33 +0,0 @@
import { useTranslation } from 'react-i18next';
import { Intent, Notification } from '@vegaprotocol/ui-toolkit';
interface DisconnectedNoticeProps {
isDisconnected: boolean;
correctNetworkChainId?: string | null;
}
export const DisconnectedNotice = ({
isDisconnected,
correctNetworkChainId,
}: DisconnectedNoticeProps) => {
const { t } = useTranslation();
if (
!isDisconnected ||
correctNetworkChainId === undefined ||
correctNetworkChainId === null
) {
return null;
}
return (
<div className="col-span-full" data-testid="disconnected-notice">
<Notification
message={t('disconnectedNotice', {
correctNetwork: correctNetworkChainId,
})}
intent={Intent.Danger}
/>
</div>
);
};
@@ -1 +0,0 @@
export * from './disconnected-notice';
@@ -3,7 +3,6 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { Link } from 'react-router-dom';
import { Button } from '@vegaprotocol/ui-toolkit';
import { DisconnectedNotice } from '../disconnected-notice';
import {
AppStateActionType,
@@ -27,8 +26,7 @@ import {
import { Loader } from '@vegaprotocol/ui-toolkit';
import colors from 'tailwindcss/colors';
import { useBalances } from '../../lib/balances/balances-store';
import { useEthereumConfig, useWeb3Disconnect } from '@vegaprotocol/web3';
import { getChainName } from '@vegaprotocol/web3';
import { useWeb3Disconnect } from '@vegaprotocol/web3';
const removeLeadingAddressSymbol = (key: string) => {
if (key && key.length > 2 && key.slice(0, 2) === '0x') {
@@ -184,21 +182,16 @@ const ConnectedKey = () => {
export const EthWallet = () => {
const { t } = useTranslation();
const { appDispatch, appState } = useAppState();
const { appDispatch } = useAppState();
const { account, connector } = useWeb3React();
const pendingTxs = usePendingTransactions();
const disconnect = useWeb3Disconnect(connector);
const { config } = useEthereumConfig();
return (
<WalletCard>
<section data-testid="ethereum-wallet">
<WalletCardHeader>
<h1 className="m-0 uppercase">{t('ethereumKey')}</h1>
<DisconnectedNotice
isDisconnected={appState.disconnectNotice}
correctNetworkChainId={getChainName(Number(config?.chain_id))}
/>
{account && (
<div className="place-self-end font-mono">
<div
@@ -14,7 +14,7 @@ export const AppLayout = ({ children }: AppLayoutProps) => {
const { isReadOnly } = useVegaWallet();
const AppLayoutClasses = classNames(
'app w-full max-w-[1500px] mx-auto grid',
'font-alpha lg:text-body-large',
'lg:text-body-large',
{
'grid-rows-[repeat(2,min-content)_1fr_min-content]': !isReadOnly,
'grid-rows-[repeat(3,min-content)_1fr_min-content]': isReadOnly,
@@ -1,12 +1,13 @@
import { Button, Splash } from '@vegaprotocol/ui-toolkit';
import {
getChainName,
useWeb3ConnectStore,
useWeb3Disconnect,
Web3ConnectDialog,
} from '@vegaprotocol/web3';
import { useWeb3React } from '@web3-react/core';
import type { ReactElement } from 'react';
import { useCallback, useEffect, useState } from 'react';
import { useCallback, useEffect } from 'react';
import {
AppStateActionType,
useAppState,
@@ -35,7 +36,9 @@ export function Web3Connector({
const appChainId = Number(chainId);
return (
<>
<Web3Content appChainId={appChainId}>{children}</Web3Content>
<Web3Content appChainId={appChainId} setDialogOpen={setDialogOpen}>
{children}
</Web3Content>
<Web3ConnectDialog
connectors={connectors}
dialogOpen={appState.ethConnectOverlay}
@@ -49,59 +52,23 @@ export function Web3Connector({
interface Web3ContentProps {
children: ReactElement;
appChainId: number;
setDialogOpen: (isOpen: boolean) => void;
}
export const Web3Content = ({ children, appChainId }: Web3ContentProps) => {
const { appState, appDispatch } = useAppState();
const { connector, chainId } = useWeb3React();
const [previousChainId, setPreviousChainId] = useState(chainId);
const error = useWeb3ConnectStore((store) => store.error);
const disconnect = useWeb3Disconnect(connector);
const showDisconnectNotice = useCallback(
(isVisible: boolean) =>
appDispatch({
type: AppStateActionType.SET_DISCONNECT_NOTICE,
isVisible,
}),
[appDispatch]
);
useEffect(() => {
if (connector?.connectEagerly) {
connector.connectEagerly();
}
// wallet connect doesn't handle connectEagerly being called when connector is also in the
// wallet connect doesnt handle connectEagerly being called when connector is also in the
// deps array.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
useEffect(() => {
if (chainId !== undefined) {
// We use this to detect when the user switches networks.
setPreviousChainId(chainId);
if (chainId !== appChainId) {
disconnect();
// If the user was previously connected, show the disconnect explanation notice.
if (previousChainId !== undefined && !appState.disconnectNotice) {
showDisconnectNotice(true);
}
} else if (appState.disconnectNotice) {
showDisconnectNotice(false);
}
}
}, [
appChainId,
appDispatch,
appState.disconnectNotice,
chainId,
disconnect,
previousChainId,
showDisconnectNotice,
]);
if (error) {
return (
<Splash>
@@ -113,5 +80,18 @@ export const Web3Content = ({ children, appChainId }: Web3ContentProps) => {
);
}
if (chainId !== undefined && chainId !== appChainId) {
return (
<Splash>
<div className="flex flex-col items-center gap-12">
<p className="text-white">
This app only works on {getChainName(appChainId)}
</p>
<Button onClick={() => disconnect()}>Disconnect</Button>
</div>
</Splash>
);
}
return children;
};
@@ -43,11 +43,6 @@ export interface AppState {
* Message to display in a banner at the top of the screen, currently always shown as a warning/error
*/
bannerMessage: string;
/**
* Displays a notice to the user that they have been disconnected because they've changed their
* ethereum network to an incompatible one.
*/
disconnectNotice: boolean;
}
export enum AppStateActionType {
@@ -63,7 +58,6 @@ export enum AppStateActionType {
SET_ASSOCIATION_BREAKDOWN,
SET_TRANSACTION_OVERLAY,
SET_BANNER_MESSAGE,
SET_DISCONNECT_NOTICE,
}
export type AppStateAction =
@@ -96,10 +90,6 @@ export type AppStateAction =
| {
type: AppStateActionType.SET_BANNER_MESSAGE;
message: string;
}
| {
type: AppStateActionType.SET_DISCONNECT_NOTICE;
isVisible: boolean;
};
type AppStateContextShape = {
@@ -1,8 +1,8 @@
import React from 'react';
import { BigNumber } from '../../lib/bignumber';
import type { AppState, AppStateAction } from './app-state-context';
import { AppStateActionType, AppStateContext } from './app-state-context';
import type { AppState, AppStateAction } from './app-state-context';
interface AppStateProviderProps {
children: React.ReactNode;
@@ -19,7 +19,6 @@ const initialAppState: AppState = {
ethConnectOverlay: false,
transactionOverlay: false,
bannerMessage: '',
disconnectNotice: false,
};
function appStateReducer(state: AppState, action: AppStateAction): AppState {
@@ -69,12 +68,6 @@ function appStateReducer(state: AppState, action: AppStateAction): AppState {
bannerMessage: action.message,
};
}
case AppStateActionType.SET_DISCONNECT_NOTICE: {
return {
...state,
disconnectNotice: action.isVisible,
};
}
}
}
@@ -14,17 +14,13 @@ import { ContractsContext } from './contracts-context';
import { createDefaultProvider } from '../../lib/web3-connectors';
import { useEthereumConfig } from '@vegaprotocol/web3';
import { useEnvironment } from '@vegaprotocol/environment';
import { ENV } from '../../config';
import { ENV } from '../../config/env';
/**
* Provides Vega Ethereum contract instances to its children.
*/
export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
const {
provider: activeProvider,
account,
chainId: activeChainId,
} = useWeb3React();
const { provider: activeProvider, account } = useWeb3React();
const { config } = useEthereumConfig();
const { VEGA_ENV, ETHEREUM_PROVIDER_URL } = useEnvironment();
const [contracts, setContracts] =
@@ -43,11 +39,7 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
ETHEREUM_PROVIDER_URL,
Number(config.chain_id)
);
const provider =
activeProvider && activeChainId === Number(config.chain_id)
? activeProvider
: defaultProvider;
const provider = activeProvider ? activeProvider : defaultProvider;
if (
account &&
@@ -92,14 +84,7 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
// TODO: hacky quick fix for release to prevent race condition, find a better fix for this.
cancelled = true;
};
}, [
activeProvider,
activeChainId,
account,
config,
VEGA_ENV,
ETHEREUM_PROVIDER_URL,
]);
}, [activeProvider, account, config, VEGA_ENV, ETHEREUM_PROVIDER_URL]);
if (!contracts) {
return (
@@ -790,6 +790,5 @@
"approval (% validator voting power)": "approval (% validator voting power)",
"67% voting power required": "67% voting power required",
"Token": "Token",
"associateVegaNow": "Associate $VEGA now",
"disconnectedNotice": "You have been disconnected. Connect your ETH wallet to the {{correctNetwork}} network to use this app."
"associateVegaNow": "Associate $VEGA now"
}
@@ -56,7 +56,6 @@ const mockAppState: AppState = {
ethConnectOverlay: false,
transactionOverlay: false,
bannerMessage: '',
disconnectNotice: false,
};
jest.mock('../../../contexts/app-state/app-state-context', () => ({
@@ -1,7 +1,8 @@
import { render, screen } from '@testing-library/react';
import { ProposalRejectionReason, ProposalState } from '@vegaprotocol/types';
import { formatDateWithLocalTimezone } from '@vegaprotocol/utils';
import { format } from 'date-fns';
import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats';
import { generateProposal } from '../../test-helpers/generate-proposals';
import { ProposalChangeTable } from './proposal-change-table';
@@ -23,15 +24,16 @@ it('Renders all data for table', () => {
expect(screen.getByText('Closes on')).toBeInTheDocument();
expect(
screen.getByText(
formatDateWithLocalTimezone(new Date(proposal?.terms.closingDatetime))
format(new Date(proposal?.terms.closingDatetime), DATE_FORMAT_DETAILED)
)
).toBeInTheDocument();
expect(screen.getByText('Proposed enactment')).toBeInTheDocument();
expect(
screen.getByText(
formatDateWithLocalTimezone(
new Date(proposal?.terms.enactmentDatetime || 0)
format(
new Date(proposal?.terms.enactmentDatetime || 0),
DATE_FORMAT_DETAILED
)
)
).toBeInTheDocument();
@@ -41,7 +43,7 @@ it('Renders all data for table', () => {
expect(screen.getByText('Proposed on')).toBeInTheDocument();
expect(
screen.getByText(formatDateWithLocalTimezone(new Date(proposal?.datetime)))
screen.getByText(format(new Date(proposal?.datetime), DATE_FORMAT_DETAILED))
).toBeInTheDocument();
expect(screen.getByText('Type')).toBeInTheDocument();
@@ -60,15 +62,16 @@ it('Changes data based on if data is in future or past', () => {
expect(screen.getByText('Closed on')).toBeInTheDocument();
expect(
screen.getByText(
formatDateWithLocalTimezone(new Date(proposal?.terms.closingDatetime))
format(new Date(proposal?.terms.closingDatetime), DATE_FORMAT_DETAILED)
)
).toBeInTheDocument();
expect(screen.getByText('Enacted on')).toBeInTheDocument();
expect(
screen.getByText(
formatDateWithLocalTimezone(
new Date(proposal?.terms.enactmentDatetime || 0)
format(
new Date(proposal?.terms.enactmentDatetime || 0),
DATE_FORMAT_DETAILED
)
)
).toBeInTheDocument();
@@ -88,8 +91,9 @@ it('Does not render enactment time for freeform proposal', () => {
expect(screen.queryByText('Enacted on')).not.toBeInTheDocument();
expect(
screen.queryByText(
formatDateWithLocalTimezone(
new Date(proposal?.terms.enactmentDatetime || 0)
format(
new Date(proposal?.terms.enactmentDatetime || 0),
DATE_FORMAT_DETAILED
)
)
).not.toBeInTheDocument();
@@ -1,11 +1,12 @@
import { isFuture } from 'date-fns';
import { format, isFuture } from 'date-fns';
import { useTranslation } from 'react-i18next';
import { formatDateWithLocalTimezone } from '@vegaprotocol/utils';
import {
KeyValueTable,
KeyValueTableRow,
RoundedWrapper,
} from '@vegaprotocol/ui-toolkit';
import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats';
import { CurrentProposalState } from '../current-proposal-state';
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
@@ -34,15 +35,16 @@ export const ProposalChangeTable = ({ proposal }: ProposalChangeTableProps) => {
{isFuture(new Date(terms?.closingDatetime))
? t('closesOn')
: t('closedOn')}
{formatDateWithLocalTimezone(new Date(terms?.closingDatetime))}
{format(new Date(terms?.closingDatetime), DATE_FORMAT_DETAILED)}
</KeyValueTableRow>
{terms?.change.__typename !== 'NewFreeform' ? (
<KeyValueTableRow>
{isFuture(new Date(terms?.enactmentDatetime || 0))
? t('proposedEnactment')
: t('enactedOn')}
{formatDateWithLocalTimezone(
new Date(terms?.enactmentDatetime || 0)
{format(
new Date(terms?.enactmentDatetime || 0),
DATE_FORMAT_DETAILED
)}
</KeyValueTableRow>
) : null}
@@ -52,7 +54,7 @@ export const ProposalChangeTable = ({ proposal }: ProposalChangeTableProps) => {
</KeyValueTableRow>
<KeyValueTableRow>
{t('proposedOn')}
{formatDateWithLocalTimezone(new Date(proposal?.datetime))}
{format(new Date(proposal?.datetime), DATE_FORMAT_DETAILED)}
</KeyValueTableRow>
{proposal?.rejectionReason ? (
<KeyValueTableRow>
@@ -57,7 +57,10 @@ export const ProtocolUpdateProposalDetailApprovals = ({
noBorder={index === consensusApprovals?.length - 1}
key={validator.pubkey}
>
<div className="-mb-3 mt-1" data-testid={'validator-name'}>
<div
className="-mb-3 mt-1"
data-testid={`validator-${validator.id}`}
>
<ValidatorDetailsLink
id={validator.id}
avatarUrl={validator.avatarUrl}
@@ -65,7 +68,7 @@ export const ProtocolUpdateProposalDetailApprovals = ({
/>
</div>
<span data-testid="validator-voting-power">
<span>
{getNormalisedVotingPower(
validator.rankingScore.votingPower,
2
@@ -63,7 +63,7 @@ describe('ProtocolUpdateProposalDetailApprovals', () => {
it('renders the correct number of consensus approvers', () => {
renderComponent();
const validators = screen.getAllByTestId(/validator-name/);
const validators = screen.getAllByTestId(/validator-/i);
expect(validators.length).toBe(mockValidators.length);
});
@@ -19,7 +19,6 @@ const mockAppState: AppState = {
ethConnectOverlay: false,
transactionOverlay: false,
bannerMessage: '',
disconnectNotice: false,
};
jest.mock('../../../contexts/app-state/app-state-context', () => ({
@@ -9,9 +9,6 @@ query ProposalMarketsQuery {
code
}
}
proposal {
state
}
}
}
}
@@ -6,7 +6,7 @@ const defaultOptions = {} as const;
export type ProposalMarketsQueryQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type ProposalMarketsQueryQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string } }, proposal?: { __typename?: 'Proposal', state: Types.ProposalState } | null } }> } | null };
export type ProposalMarketsQueryQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string } } } }> } | null };
export const ProposalMarketsQueryDocument = gql`
@@ -21,9 +21,6 @@ export const ProposalMarketsQueryDocument = gql`
code
}
}
proposal {
state
}
}
}
}
@@ -0,0 +1,94 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ProposalMarketsQueryQueryVariables = Types.Exact<{
[key: string]: never;
}>;
export type ProposalMarketsQueryQuery = {
__typename?: 'Query';
marketsConnection?: {
__typename?: 'MarketConnection';
edges: Array<{
__typename?: 'MarketEdge';
node: {
__typename?: 'Market';
id: string;
tradableInstrument: {
__typename?: 'TradableInstrument';
instrument: { __typename?: 'Instrument'; name: string; code: string };
};
};
}>;
} | null;
};
export const ProposalMarketsQueryDocument = gql`
query ProposalMarketsQuery {
marketsConnection {
edges {
node {
id
tradableInstrument {
instrument {
name
code
}
}
}
}
}
}
`;
/**
* __useProposalMarketsQueryQuery__
*
* To run a query within a React component, call `useProposalMarketsQueryQuery` and pass it any options that fit your needs.
* When your component renders, `useProposalMarketsQueryQuery` 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 } = useProposalMarketsQueryQuery({
* variables: {
* },
* });
*/
export function useProposalMarketsQueryQuery(
baseOptions?: Apollo.QueryHookOptions<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useQuery<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>(ProposalMarketsQueryDocument, options);
}
export function useProposalMarketsQueryLazyQuery(
baseOptions?: Apollo.LazyQueryHookOptions<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>
) {
const options = { ...defaultOptions, ...baseOptions };
return Apollo.useLazyQuery<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>(ProposalMarketsQueryDocument, options);
}
export type ProposalMarketsQueryQueryHookResult = ReturnType<
typeof useProposalMarketsQueryQuery
>;
export type ProposalMarketsQueryLazyQueryHookResult = ReturnType<
typeof useProposalMarketsQueryLazyQuery
>;
export type ProposalMarketsQueryQueryResult = Apollo.QueryResult<
ProposalMarketsQueryQuery,
ProposalMarketsQueryQueryVariables
>;
@@ -1,16 +1,15 @@
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
import { MemoryRouter as Router } from 'react-router-dom';
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { VegaWalletContext } from '@vegaprotocol/wallet';
import { AppStateProvider } from '../../../../contexts/app-state/app-state-provider';
import { mockWalletContext } from '../../test-helpers/mocks';
import { ProposeUpdateMarket } from './propose-update-market';
import type { NetworkParamsQuery } from '@vegaprotocol/react-helpers';
import { NetworkParamsDocument } from '@vegaprotocol/react-helpers';
import type { ProposalMarketsQueryQuery } from './__generated__/UpdateMarket';
import { ProposalMarketsQueryDocument } from './__generated__/UpdateMarket';
import { ProposalState } from '@vegaprotocol/types';
import type { ProposalMarketsQueryQuery } from './__generated___/UpdateMarket';
import { ProposalMarketsQueryDocument } from './__generated___/UpdateMarket';
const updateMarketNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
request: {
@@ -90,10 +89,6 @@ const marketQueryMock: MockedResponse<ProposalMarketsQueryQuery> = {
code: 'ETHiUSDT',
},
},
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_ENACTED,
},
},
},
{
@@ -106,16 +101,11 @@ const marketQueryMock: MockedResponse<ProposalMarketsQueryQuery> = {
instrument: {
__typename: 'Instrument',
name: 'Las Vegas nuggets',
code: 'Nuggets',
code: 'Nuggets2',
},
},
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_OPEN,
},
},
},
{
__typename: 'MarketEdge',
node: {
@@ -125,14 +115,10 @@ const marketQueryMock: MockedResponse<ProposalMarketsQueryQuery> = {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: 'California Nuggets',
code: 'Nuggets2',
name: 'Nuggets',
code: 'Nuggets',
},
},
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_WAITING_FOR_NODE_VOTE,
},
},
},
{
@@ -144,71 +130,10 @@ const marketQueryMock: MockedResponse<ProposalMarketsQueryQuery> = {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: 'Nevada Nuggets',
code: 'Nugetts3',
name: 'CELUSD (June 2022)',
code: 'CELUSD',
},
},
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_REJECTED,
},
},
},
{
__typename: 'MarketEdge',
node: {
__typename: 'Market',
id: 'asdfe1755208914b6f258a28babd19ae8dfbaf4084d8867d8a120c50dca1e17f',
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: 'NZ Nuggets',
code: 'Nugetts4',
},
},
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_DECLINED,
},
},
},
{
__typename: 'MarketEdge',
node: {
__typename: 'Market',
id: 'asdfe1755208914b6f258a28babd19ae8dfbaf4084d8867d8a120c50dca1e17f',
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: 'Aussie Nuggets',
code: 'Nugetts5',
},
},
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_PASSED,
},
},
},
{
__typename: 'MarketEdge',
node: {
__typename: 'Market',
id: 'xcvbe1755208914b6f258a28babd19ae8dfbaf4084d8867d8a120c50dca1e17f',
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: 'Tasmanian Nuggets',
code: 'Nugetts6',
},
},
proposal: {
__typename: 'Proposal',
state: ProposalState.STATE_FAILED,
},
},
},
],
@@ -274,27 +199,6 @@ describe('Propose Update Market', () => {
expect(screen.getByTestId('proposal-market-select')).toHaveValue('');
});
it('should only render enacted markets', async () => {
renderComponent();
expect(
await screen.findByText('Update market proposal')
).toBeInTheDocument();
// (state enacted)
expect(screen.getByText('ETHUSD (September Market)')).toBeInTheDocument();
// (state open)
expect(screen.queryByText('Las Vegas nuggets')).not.toBeInTheDocument();
// (state waiting for node vote)
expect(screen.queryByText('California nuggets')).not.toBeInTheDocument();
// (state rejected)
expect(screen.queryByText('Nevada nuggets')).not.toBeInTheDocument();
// (state declined)
expect(screen.queryByText('NZ nuggets')).not.toBeInTheDocument();
// (state passed)
expect(screen.queryByText('Aussie nuggets')).not.toBeInTheDocument();
// (state failed)
expect(screen.queryByText('Tasmanian nuggets')).not.toBeInTheDocument();
});
it('should render the correct market details when the market select is used', async () => {
renderComponent();
expect(
@@ -2,28 +2,25 @@ import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useForm } from 'react-hook-form';
import {
doesValueEquateToParam,
getClosingTimestamp,
getEnactmentTimestamp,
useProposalSubmit,
doesValueEquateToParam,
} from '@vegaprotocol/proposals';
import { useEnvironment } from '@vegaprotocol/environment';
import { createDocsLinks, validateJson } from '@vegaprotocol/utils';
import { NetworkParams, useNetworkParams } from '@vegaprotocol/react-helpers';
import {
ProposalFormDescription,
ProposalFormDownloadJson,
ProposalFormSubheader,
ProposalFormSubmit,
ProposalFormTerms,
ProposalFormTitle,
ProposalFormTransactionDialog,
ProposalFormDownloadJson,
ProposalFormVoteAndEnactmentDeadline,
} from '../../components/propose';
import {
ProposalMinRequirements,
ProposalUserAction,
} from '../../components/shared';
import { ProposalMinRequirements } from '../../components/shared';
import {
AsyncRenderer,
ExternalLink,
@@ -34,9 +31,9 @@ import {
Select,
} from '@vegaprotocol/ui-toolkit';
import { Heading } from '../../../../components/heading';
import { useProposalMarketsQueryQuery } from './__generated__/UpdateMarket';
import { ProposalUserAction } from '../../components/shared';
import { useProposalMarketsQueryQuery } from './__generated___/UpdateMarket';
import { downloadJson } from '../../../../lib/download-json';
import { ProposalState } from '@vegaprotocol/types';
export interface UpdateMarketProposalFormFields {
proposalVoteDeadline: string;
@@ -76,9 +73,6 @@ export const ProposeUpdateMarket = () => {
return marketsData.marketsConnection.edges
.map((edge) => edge.node)
.filter(
(market) => market.proposal?.state === ProposalState.STATE_ENACTED
)
.sort((a, b) => {
const aName = a.tradableInstrument.instrument.name;
const bName = b.tradableInstrument.instrument.name;
@@ -6,7 +6,6 @@ import { usePreviousEpochQuery } from '../__generated__/PreviousEpoch';
import { ValidatorTables } from './validator-tables';
import { useRefreshAfterEpoch } from '../../../hooks/use-refresh-after-epoch';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { ENV } from '../../../config';
export const EpochData = () => {
// errorPolicy due to vegaprotocol/vega issue 5898
@@ -15,23 +14,11 @@ export const EpochData = () => {
data: nodesData,
error: nodesError,
loading: nodesLoading,
refetch: nodesRefetch,
refetch,
} = useNodesQuery();
const { delegationsPagination } = ENV;
const {
data: userStakingData,
error: userStakingError,
loading: userStakingLoading,
refetch: userStakingRefetch,
} = useStakingQuery({
const { data: userStakingData } = useStakingQuery({
variables: {
partyId: pubKey || '',
delegationsPagination: delegationsPagination
? {
first: Number(delegationsPagination),
}
: undefined,
},
});
const { data: previousEpochData } = usePreviousEpochQuery({
@@ -41,17 +28,10 @@ export const EpochData = () => {
skip: !nodesData?.epoch.id,
});
useRefreshAfterEpoch(nodesData?.epoch.timestamps.expiry, () => {
nodesRefetch();
userStakingRefetch();
});
useRefreshAfterEpoch(nodesData?.epoch.timestamps.expiry, refetch);
return (
<AsyncRenderer
loading={nodesLoading || userStakingLoading}
error={nodesError || userStakingError}
data={nodesData}
>
<AsyncRenderer loading={nodesLoading} error={nodesError} data={nodesData}>
{nodesData?.epoch &&
nodesData.epoch.timestamps.start &&
nodesData?.epoch.timestamps.expiry && (
@@ -3,7 +3,7 @@ import { forwardRef, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { Button, Icon } from '@vegaprotocol/ui-toolkit';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
import { useAppState } from '../../../../contexts/app-state/app-state-context';
import { BigNumber } from '../../../../lib/bignumber';
import {
@@ -17,6 +17,7 @@ import {
} from '../../shared';
import {
defaultColDef,
NODE_LIST_GRID_STYLES,
PendingStakeRenderer,
stakedTotalPercentage,
StakeShareRenderer,
@@ -210,7 +211,7 @@ export const ConsensusValidatorsTable = ({
: undefined,
[ValidatorFields.PENDING_USER_STAKE]: pendingUserStake,
[ValidatorFields.USER_STAKE_SHARE]: userStakeShare
? formatNumberPercentage(new BigNumber(userStakeShare))
? stakedTotalPercentage(userStakeShare)
: undefined,
};
}
@@ -381,14 +382,12 @@ export const ConsensusValidatorsTable = ({
);
return (
<div
data-testid="consensus-validators-table"
className="validators-table"
>
<div data-testid="consensus-validators-table">
{nodes.length > 0 && (
<AgGrid
domLayout="autoHeight"
style={{ width: '100%' }}
customThemeParams={NODE_LIST_GRID_STYLES}
getRowHeight={(params: RowHeightParams) => getRowHeight(params)}
defaultColDef={defaultColDef}
tooltipShowDelay={0}
@@ -59,9 +59,9 @@ export const addUserDataToValidator = (
: undefined,
[ValidatorFields.USER_STAKE_SHARE]:
currentEpochUserStaking && Number(currentEpochUserStaking.amount) > 0
? new BigNumber(currentEpochUserStaking.amount)
.dividedBy(new BigNumber(currentUserStakeAvailable))
.times(100)
? new BigNumber(currentEpochUserStaking.amount).dividedBy(
new BigNumber(currentUserStakeAvailable)
)
: undefined,
};
};
@@ -79,6 +79,17 @@ export interface ValidatorsTableProps {
validatorsView: ValidatorsView;
}
// Custom styling to account for the scrollbar. This is needed because the
// AG Grid places the scrollbar over the bottom validator, which obstructs
export const NODE_LIST_GRID_STYLES = `
.ag-theme-balham-dark .ag-body-horizontal-scroll {
opacity: 0.75;
}
.ag-theme-balham-dark *:hover {
cursor: pointer;
}
`;
export const stakedTotalPercentage = (stakeScore: string) =>
formatNumberPercentage(toBigNum(stakeScore, 0).times(100), 2);
@@ -1,7 +1,7 @@
import { forwardRef, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
import { useAppState } from '../../../../contexts/app-state/app-state-context';
import { BigNumber } from '../../../../lib/bignumber';
import {
@@ -13,6 +13,7 @@ import {
} from '../../shared';
import {
defaultColDef,
NODE_LIST_GRID_STYLES,
StakeNeededForPromotionRenderer,
stakedTotalPercentage,
ValidatorFields,
@@ -25,11 +26,7 @@ import {
import type { AgGridReact } from 'ag-grid-react';
import type { ColDef } from 'ag-grid-community';
import type { ValidatorsTableProps } from './shared';
import {
formatNumber,
formatNumberPercentage,
toBigNum,
} from '@vegaprotocol/utils';
import { formatNumber, toBigNum } from '@vegaprotocol/utils';
interface StandbyPendingValidatorsTableProps extends ValidatorsTableProps {
stakeNeededForPromotion: string | undefined;
@@ -166,7 +163,7 @@ export const StandbyPendingValidatorsTable = ({
: undefined,
[ValidatorFields.PENDING_USER_STAKE]: pendingUserStake,
[ValidatorFields.USER_STAKE_SHARE]: userStakeShare
? formatNumberPercentage(new BigNumber(userStakeShare))
? stakedTotalPercentage(userStakeShare)
: undefined,
};
}
@@ -247,13 +244,11 @@ export const StandbyPendingValidatorsTable = ({
);
return (
<div
data-testid="standby-pending-validators-table"
className="validators-table"
>
<div data-testid="standby-pending-validators-table">
<AgGrid
domLayout="autoHeight"
style={{ width: '100%' }}
customThemeParams={NODE_LIST_GRID_STYLES}
rowHeight={68}
defaultColDef={defaultColDef}
tooltipShowDelay={0}
-39
View File
@@ -1,7 +1,3 @@
@import 'ag-grid-community/dist/styles/ag-grid.css';
@import 'ag-grid-community/dist/styles/ag-theme-balham.css';
@import 'ag-grid-community/dist/styles/ag-theme-balham-dark.css';
@tailwind base;
@tailwind components;
@tailwind utilities;
@@ -23,38 +19,3 @@
@apply border-vega-dark-200;
}
}
/* AG GRID - Do not edit without updating other global stylesheets for each app */
.vega-ag-grid .ag-root-wrapper {
border: solid 0px;
}
.vega-ag-grid .ag-react-container {
overflow: hidden;
text-overflow: ellipsis;
}
.vega-ag-grid .ag-cell,
.vega-ag-grid .ag-full-width-row .ag-cell-wrapper.ag-row-group {
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
}
/* Dark variables */
.ag-theme-balham-dark {
--ag-background-color: theme(colors.black);
--ag-border-color: theme(colors.neutral[700]);
--ag-header-background-color: theme(colors.black);
--ag-odd-row-background-color: theme(colors.black);
--ag-header-column-separator-color: theme(colors.neutral[600]);
--ag-row-border-color: theme(colors.black);
--ag-row-hover-color: theme(colors.neutral[800]);
--ag-font-size: 12px;
}
.validators-table .ag-theme-balham-dark .ag-body-horizontal-scroll {
opacity: 0.75;
}
.validators-table .ag-theme-balham-dark *:hover {
cursor: pointer;
}
+1 -1
View File
@@ -19,7 +19,7 @@ NX_DEPLOY_URL=$DEPLOY_URL
NX_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_ENV = 'TESTNET'
NX_VEGA_URL="https://api.n07.testnet.vega.xyz/graphql"
NX_VEGA_URL="https://api.n11.testnet.vega.xyz/graphql"
NX_VEGA_WALLET_URL=http://localhost:1789
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
@@ -1,3 +1,3 @@
# App configuration variables
NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_ENV=LOCAL
@@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql
NX_VEGA_ENV=TESTNET
NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\",\"TESTNET\":\"https://console.fairground.wtf\"}
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
+1 -1
View File
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_VEGA_URL=https://api.n09.testnet.vega.xyz/graphql
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=TESTNET
+15 -1
View File
@@ -1,3 +1,17 @@
{
"hosts": ["https://vega.xprv.io/datanode/query"]
"hosts": [
"https://vega-data-graphql.chorus.one/query",
"https://vega.xprv.io/datanode/query",
"http://nala.mainnet.vega.community:3008/query",
"http://commodum.mainnet.vega.community:3008/query",
"http://lovali.mainnet.vega.community:3008/query",
"http://b-harvest.mainnet.vega.community:3008/query",
"http://staking-facilities.mainnet.vega.community:3008/query",
"http://figment.mainnet.vega.community:3008/query",
"http://nodes-guru.mainnet.vega.community:3008/query",
"http://p2p.mainnet.vega.community:3008/query",
"http://rockaway.mainnet.vega.community:3008/query",
"http://greenfield-one.mainnet.vega.community:3008/query",
"http://ryabina.mainnet.vega.community:3008/query"
]
}
File diff suppressed because it is too large Load Diff
+6 -2
View File
@@ -1,7 +1,11 @@
{
"hosts": [
"https://api-n00.testnet.vega.rocks/graphql",
"https://api-n06.testnet.vega.rocks/graphql",
"https://api-n07.testnet.vega.rocks/graphql"
"https://api-n07.testnet.vega.rocks/graphql",
"https://api-n08.testnet.vega.rocks/graphql",
"https://api-n09.testnet.vega.rocks/graphql",
"https://api-n10.testnet.vega.rocks/graphql",
"https://api-n11.testnet.vega.rocks/graphql",
"https://api-n12.testnet.vega.rocks/graphql"
]
}
+2 -2
View File
@@ -8,7 +8,7 @@ NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
@@ -27,6 +27,6 @@ CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf
CYPRESS_VEGA_URL=http://localhost:3008/graphql
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_WALLET_API_TOKEN=
+2 -2
View File
@@ -7,7 +7,7 @@ NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
@@ -24,6 +24,6 @@ CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf
CYPRESS_VEGA_URL=http://localhost:3008/graphql
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_WALLET_API_TOKEN=
@@ -1,375 +0,0 @@
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { MarketState, MarketStateMapping } from '@vegaprotocol/types';
import { addDays, subDays } from 'date-fns';
import {
chainIdQuery,
statisticsQuery,
createDataConnection,
oracleSpecDataConnectionQuery,
createMarketFragment,
marketsQuery,
marketsDataQuery,
createMarketsDataFragment,
assetQuery,
networkParamsQuery,
} from '@vegaprotocol/mock';
import {
addDecimalsFormatNumber,
getDateTimeFormat,
} from '@vegaprotocol/utils';
describe('Closed markets', { tags: '@smoke' }, () => {
const rowSelector =
'[data-testid="tab-closed-markets"] .ag-center-cols-container .ag-row';
const assetsResult = assetQuery();
// @ts-ignore asset definitely exists
const settlementAsset = assetsResult.assetsConnection.edges[0].node;
const settledMarket = createMarketFragment({
id: '0',
state: MarketState.STATE_SETTLED,
marketTimestamps: {
open: subDays(new Date(), 10).toISOString(),
close: subDays(new Date(), 4).toISOString(),
},
tradableInstrument: {
instrument: {
product: {
dataSourceSpecForTradingTermination: {
id: 'market-1-trading-termination-oracle-id',
},
dataSourceSpecForSettlementData: {
id: 'market-1-settlement-data-oracle-id',
},
settlementAsset,
},
},
},
});
const terminatedMarket = createMarketFragment({
id: '1',
state: MarketState.STATE_TRADING_TERMINATED,
marketTimestamps: {
open: subDays(new Date(), 10).toISOString(),
close: null, // market
},
tradableInstrument: {
instrument: {
metadata: {
tags: [
`settlement-expiry-date:${addDays(new Date(), 4).toISOString()}`,
],
},
},
},
});
const delayedSettledMarket = createMarketFragment({
id: '2',
state: MarketState.STATE_TRADING_TERMINATED,
marketTimestamps: {
open: subDays(new Date(), 10).toISOString(),
close: null, // market
},
tradableInstrument: {
instrument: {
metadata: {
tags: [
`settlement-expiry-date:${subDays(new Date(), 2).toISOString()}`,
],
},
},
},
});
const unknownMarket = createMarketFragment({
id: '3',
state: MarketState.STATE_SETTLED,
});
const closedMarketsResult = [
{
node: settledMarket,
},
{
node: terminatedMarket,
},
{
node: delayedSettledMarket,
},
{ node: unknownMarket },
{
node: createMarketFragment({ id: '4', state: MarketState.STATE_PENDING }),
},
{
node: createMarketFragment({ id: '5', state: MarketState.STATE_ACTIVE }),
},
];
const settledMarketData = createMarketsDataFragment({
market: {
id: settledMarket.id,
},
bestBidPrice: '1000',
bestOfferPrice: '2000',
markPrice: '1500',
});
const closedMarketsDataResult = [
{
node: {
data: settledMarketData,
},
},
{
node: {
data: createMarketsDataFragment({
market: {
id: terminatedMarket.id,
},
}),
},
},
{
node: {
data: createMarketsDataFragment({
market: {
id: delayedSettledMarket.id,
},
}),
},
},
{
node: {
data: createMarketsDataFragment({
market: {
id: unknownMarket.id,
},
}),
},
},
];
const specDataConnection = createDataConnection();
before(() => {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
aliasGQLQuery(req, 'NetworkParams', networkParamsQuery());
aliasGQLQuery(
req,
'Markets',
marketsQuery({
marketsConnection: {
edges: closedMarketsResult,
},
})
);
aliasGQLQuery(
req,
'MarketsData',
marketsDataQuery({
marketsConnection: {
edges: closedMarketsDataResult,
},
})
);
aliasGQLQuery(
req,
'OracleSpecDataConnection',
oracleSpecDataConnectionQuery()
);
});
cy.mockSubscription();
cy.visit('/#/markets/all');
cy.get('[data-testid="Closed markets"]').click();
});
it('renders a settled market', () => {
const expectedMarkets = closedMarketsResult.filter((edge) => {
return [
MarketState.STATE_SETTLED,
MarketState.STATE_TRADING_TERMINATED,
].includes(edge.node.state);
});
const product = settledMarket.tradableInstrument.instrument.product;
// rows should be filtered to only include settled/terminated markets
cy.get(rowSelector).should('have.length', expectedMarkets.length);
// check each column in the first row renders correctly
// 6001-MARK-001
cy.get(rowSelector)
.first()
.find('[col-id="code"]')
.should('have.text', settledMarket.tradableInstrument.instrument.code);
// 6001-MARK-002
cy.get(rowSelector)
.first()
.find('[col-id="name"]')
.should('have.text', settledMarket.tradableInstrument.instrument.name);
// 6001-MARK-003
cy.get(rowSelector)
.first()
.find('[col-id="state"]')
.should('have.text', MarketStateMapping[settledMarket.state]);
// 6001-MARK-004
// 6001-MARK-005
// 6001-MARK-009
// 6001-MARK-008
// 6001-MARK-010
cy.get(rowSelector)
.first()
.find('[col-id="settlementDate"]')
.find('[data-testid="link"]')
.should(($el) => {
const href = $el.attr('href');
expect(href).to.match(
new RegExp(
`/oracles/${product.dataSourceSpecForTradingTermination.id}`
)
);
})
.should('have.text', '4 days ago')
.should(
'have.attr',
'title',
getDateTimeFormat().format(
new Date(settledMarket.marketTimestamps.close)
)
);
// 6001-MARK-011
cy.get(rowSelector)
.first()
.find('[col-id="bestBidPrice"]')
.should(
'have.text',
addDecimalsFormatNumber(
settledMarketData.bestBidPrice,
settledMarket.decimalPlaces
)
);
// 6001-MARK-012
cy.get(rowSelector)
.first()
.find('[col-id="bestOfferPrice"]')
.should(
'have.text',
addDecimalsFormatNumber(
settledMarketData.bestOfferPrice,
settledMarket.decimalPlaces
)
);
// 6001-MARK-013
cy.get(rowSelector).first().find('[col-id="markPrice"]').should(
'have.text',
addDecimalsFormatNumber(
settledMarketData.markPrice,
settledMarket.decimalPlaces
)
);
// 6001-MARK-014
// 6001-MARK-015
// 6001-MARK-016
cy.get(rowSelector)
.first()
.find('[col-id="settlementDataOracleId"]')
.find('[data-testid="link"]')
.should(($el) => {
const href = $el.attr('href');
expect(href).to.match(
new RegExp(`/oracles/${product.dataSourceSpecForSettlementData.id}`)
);
})
.should(
'have.text',
addDecimalsFormatNumber(
// @ts-ignore cannot deep un-partial
specDataConnection.externalData.data.data[0].value,
settledMarket.decimalPlaces
)
);
// 6001-MARK-017
cy.get(rowSelector)
.first()
.find('[col-id="realisedPNL"]')
.should('have.text', '-');
// 6001-MARK-018
cy.get(rowSelector)
.first()
.find('[col-id="settlementAsset"]')
.should('have.text', product.settlementAsset.symbol);
// 6001-MARK-020
cy.get(rowSelector)
.first()
.find('[col-id="id"]')
.should('have.text', settledMarket.id);
});
// test market list for market in terminated state
it('renders a terminated market', () => {
cy.get(rowSelector)
.eq(1)
.find('[col-id="state"]')
.should('have.text', MarketStateMapping[terminatedMarket.state]);
// 6001-MARK-006
// 6001-MARK-007
cy.get(rowSelector)
.eq(1)
.find('[col-id="settlementDate"]')
.find('[data-testid="link"]')
.should('have.text', 'Expected in 4 days');
});
it('renders a terminated market which was expected to have settled', () => {
cy.get(rowSelector)
.eq(2)
.find('[col-id="settlementDate"]')
.should('have.class', 'text-danger')
.find('[data-testid="link"]')
.should('have.text', 'Expected 2 days ago');
});
it('renders terminated market which doesnt have settlement date metadata', () => {
cy.get(rowSelector)
.eq(3)
.find('[col-id="settlementDate"]')
.find('[data-testid="link"]')
.should('have.text', 'Unknown');
});
it('can open asset detail dialog', () => {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Asset', assetsResult);
});
cy.get(rowSelector)
.first()
.find('[col-id="settlementAsset"]')
.find('button')
.click();
// 6001-MARK-019
cy.get('[data-testid="dialog-title"]').should(
'have.text',
`Asset details - ${settlementAsset.symbol}`
);
});
});
@@ -101,7 +101,7 @@ describe('deposit actions', { tags: '@smoke' }, () => {
cy.mockTradingPage();
cy.mockSubscription();
cy.setVegaWallet();
cy.visit('/#/markets/market-1');
cy.visit('/');
cy.wait('@MarketsCandles');
cy.getByTestId('dialog-close').click();
});
@@ -112,6 +112,7 @@ describe('deposit actions', { tags: '@smoke' }, () => {
'be.visible'
);
cy.contains('[data-testid="deposit"]', 'Deposit to trade').click();
connectEthereumWallet('MetaMask');
cy.getByTestId('deposit-submit').should('be.visible');
});
});
+1 -2
View File
@@ -153,7 +153,7 @@ describe('home', { tags: '@regression' }, () => {
// the choose market overlay is no longer showing
cy.contains('Select a market to get started').should('not.exist');
cy.contains('Loading...').should('not.exist');
cy.url().should('eq', Cypress.config().baseUrl + '/#/markets/market-0');
cy.url().should('eq', Cypress.config().baseUrl + '/#/markets/market-1');
});
});
@@ -172,7 +172,6 @@ describe('home', { tags: '@regression' }, () => {
],
},
};
// @ts-ignore partial deep check failing
const data = marketsDataQuery(override);
cy.mockGQL((req) => {
aliasGQLQuery(req, 'MarketsData', data);
@@ -1,5 +1,4 @@
import { MarketTradingModeMapping } from '@vegaprotocol/types';
import { MarketState } from '@vegaprotocol/types';
const marketInfoBtn = 'Info';
const row = 'key-value-table-row';
@@ -13,12 +12,7 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
});
before(() => {
cy.mockTradingPage(
MarketState.STATE_ACTIVE,
undefined,
undefined,
'COMPROMISED'
);
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
@@ -26,11 +20,6 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
cy.wait('@MarketInfo');
});
it('show oracle banner', () => {
cy.getByTestId(marketTitle).contains('Oracle').click();
cy.getByTestId('oracle-status').should('contain.text', 'COMPROMISED');
});
it('current fees displayed', () => {
cy.getByTestId(marketTitle).contains('Current fees').click();
validateMarketDataRow(0, 'Maker Fee', '0.02%');
@@ -180,21 +169,25 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
it('oracle displayed', () => {
cy.getByTestId(marketTitle).contains('Oracle').click();
validateMarketDataRow(0, 'Settlement Data Property', 'prices.BTC.value');
validateMarketDataRow(
1,
'Trading Termination Property',
'termination.BTC.value'
);
// check that links to github for oracle proofs are shown
cy.getByTestId(accordionContent)
.getByTestId('provider-name')
.and('contain', 'Another oracle');
.getByTestId('oracle-proof-links')
.find(`[data-testid="${externalLink}"]`)
.should('have.attr', 'href')
.and('contain', 'https://github.com/vegaprotocol/well-known');
cy.getByTestId(accordionContent)
.getByTestId('signed-proofs')
.and('contain', '1');
cy.getByTestId(accordionContent)
.getByTestId('verified-proofs')
.and('contain', '1');
cy.getByTestId(accordionContent)
.getByTestId('signed-proofs')
.and('contain', '1');
.getByTestId('oracle-spec-links')
.find(`[data-testid="${externalLink}"]`)
.should('have.attr', 'href')
.and('contain', '/oracles');
});
it('proposal displayed', () => {
@@ -222,7 +222,6 @@ describe('markets table', { tags: '@smoke' }, () => {
],
},
};
// @ts-ignore partial deep check failing
const market = marketsQuery(override);
aliasGQLQuery(req, 'Market', market);
aliasGQLQuery(req, 'ProposalOfMarket', {
@@ -32,7 +32,7 @@ describe('Navbar', { tags: '@smoke' }, () => {
});
it('Resources dropdown should be correctly rendered', () => {
const resourceSelector = 'ul li:contains(Resources)';
const resourceSelector = 'ul li:last-child';
['Docs', 'Give Feedback'].forEach((text, index) => {
cy.get('nav').find(resourceSelector).contains('Resources').click();
cy.get('nav')
@@ -91,7 +91,7 @@ describe('Navbar', { tags: '@smoke' }, () => {
cy.getByTestId('button-menu-drawer').click();
cy.getByTestId('menu-drawer').should('be.visible');
cy.getByTestId('menu-drawer')
.find('[data-testid="Settings"]')
.find('[data-testid="theme-switcher"]')
.should('be.visible');
cy.getByTestId('button-menu-drawer').click();
cy.getByTestId('menu-drawer').should('not.be.visible');
@@ -1,45 +0,0 @@
import { closeWelcomeDialog } from '../support/helpers';
describe('Settings page', { tags: '@smoke' }, () => {
beforeEach(() => {
cy.clearLocalStorage().then(() => {
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/');
closeWelcomeDialog();
cy.get('[aria-label="cog icon"]').click();
});
});
it('telemetry checkbox should work well', () => {
cy.location('hash').should('equal', '#/settings');
cy.getByTestId('telemetry-approval').should(
'have.attr',
'data-state',
'unchecked'
);
cy.get('[for="telemetry-approval"]').click();
cy.getByTestId('telemetry-approval').should(
'have.attr',
'data-state',
'checked'
);
cy.reload();
cy.getByTestId('telemetry-approval').should(
'have.attr',
'data-state',
'checked'
);
cy.get('[for="telemetry-approval"]').click();
cy.getByTestId('telemetry-approval').should(
'have.attr',
'data-state',
'unchecked'
);
cy.reload();
cy.getByTestId('telemetry-approval').should(
'have.attr',
'data-state',
'unchecked'
);
});
});
@@ -1,25 +1,17 @@
import { checkSorting } from '@vegaprotocol/cypress';
const dialogClose = 'dialog-close';
describe('accounts', { tags: '@smoke' }, () => {
beforeEach(() => {
before(() => {
cy.clearAllLocalStorage();
cy.mockTradingPage();
cy.mockWeb3Provider();
cy.mockSubscription();
cy.setVegaWallet();
cy.visit('/#/markets/market-0');
cy.wait('@Assets');
});
it('renders accounts', () => {
// 7001-COLL-001
// 7001-COLL-002
// 7001-COLL-003
// 7001-COLL-004
// 7001-COLL-005
// 7001-COLL-006
// 7001-COLL-007
const tradingAccountRowId = '[row-id="t-0"]';
cy.getByTestId('Collateral').click();
@@ -30,115 +22,31 @@ describe('accounts', { tags: '@smoke' }, () => {
.find('[col-id="asset.symbol"]')
.should('have.text', 'AST0');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="used"]')
.should('have.text', '1.010.00%');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="available"]')
.should('have.text', '100,000.00');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="total"]')
.should('have.text', '100,001.01');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="accounts-actions"]')
.should('have.text', ' ');
.should('have.text', 'DepositWithdraw');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[data-testid="deposit"]')
.should('have.text', 'Deposit');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="accounts-actions"] [data-testid="withdraw"]')
.should('have.text', 'Withdraw');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="total"]')
.should('have.text', '100,001.01');
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('breakdown').should('be.visible');
cy.getByTestId('Collateral').click({ force: true });
});
it('should open asset details dialog when clicked on symbol', () => {
// 7001-COLL-008
// 6501-ASSE-001
// 6501-ASSE-002
// 6501-ASSE-003
// 6501-ASSE-004
// 6501-ASSE-005
// 6501-ASSE-006
// 6501-ASSE-007
// 6501-ASSE-008
// 6501-ASSE-009
// 6501-ASSE-010
// 6501-ASSE-011
// 6501-ASSE-012
// 6501-ASSE-013
const titles = [
'ID',
'Type',
'Name',
'Symbol',
'Decimals',
'Quantum',
'Status',
'Contract address',
'Withdrawal threshold',
'Lifetime limit',
'Infrastructure fee account balance',
'Global reward pool account balance',
'Maker paid fees account balance',
'Maker received fees account balance',
'Liquidity provision fee reward account balance',
'Market proposer reward account balance',
];
cy.getByTestId('asset').contains('tEURO').click();
cy.get('[data-testid$="_label"]').should('have.length', 16);
cy.get('[data-testid$="_label"]').each((element, index) => {
cy.wrap(element).should('have.text', titles[index]);
});
cy.getByTestId(dialogClose).click();
cy.getByTestId(dialogClose).should('not.exist');
});
it('should open usage breakdown dialog when clicked on used', () => {
// 7001-COLL-009
cy.getByTestId('breakdown').contains('1.01').click();
const headers = ['Market', 'Account type', 'Balance'];
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();
});
it('sorting usage breakdown columns should work well', () => {
// 7001-COLL-010
cy.getByTestId('breakdown').contains('1.01').click();
cy.getByTestId('usage-breakdown')
.find('[col-id="type"]')
.eq(1)
.should('have.text', 'Margin');
cy.getByTestId('usage-breakdown')
.find('[col-id="type"]')
.eq(2)
.should('have.text', 'Margin');
cy.getByTestId('usage-breakdown')
.find('[col-id="type"]')
.eq(3)
.should('have.text', 'General');
cy.getByTestId(dialogClose).click();
cy.get('[data-testid="dialog-content"]:visible').should('exist');
cy.get('[data-testid="dialog-close"]:visible').click();
});
describe('sorting by ag-grid columns should work well', () => {
@@ -88,18 +88,5 @@ describe('deal ticker order validation', { tags: '@smoke' }, () => {
'Size cannot be lower than 1'
);
});
it('must have total margin available', () => {
// 7001-COLL-011
cy.getByTestId('tab-ticket')
.find('.text-xs')
.eq(5)
.within(() => {
cy.get('[data-state="closed"]').should(
'have.text',
'Total margin available'
);
cy.get('.text-neutral-500').should('have.text', '~100,000.01 tDAI');
});
});
});
});
@@ -1,18 +1,7 @@
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { fillsQuery } from '@vegaprotocol/mock';
const tabFills = 'tab-fills';
describe('fills', { tags: '@regression' }, () => {
// 7005-FILL-001
// 7005-FILL-002
// 7005-FILL-003
// 7005-FILL-004
// 7005-FILL-005
// 7005-FILL-006
// 7005-FILL-007
// 7005-FILL-008
beforeEach(() => {
// Ensure page loads with correct key
cy.window().then((window) => {
@@ -49,55 +38,47 @@ describe('fills', { tags: '@regression' }, () => {
});
function validateFillsDisplayed() {
cy.getByTestId(tabFills).should('be.visible');
cy.getByTestId(tabFills).contains('Market');
cy.getByTestId(tabFills)
cy.getByTestId('tab-fills').should('be.visible');
cy.getByTestId('tab-fills')
.get(
'[role="gridcell"][col-id="market.tradableInstrument.instrument.name"]'
)
.each(($marketSymbol) => {
cy.wrap($marketSymbol).invoke('text').should('not.be.empty');
});
cy.getByTestId(tabFills).contains('Size');
cy.get(`[col-id='size']`).eq(1).should('contain.text', '+');
cy.get(`[col-id='size']`).eq(2).should('contain.text', '-');
cy.getByTestId(tabFills)
cy.getByTestId('tab-fills')
.get('[role="gridcell"][col-id="size"]')
.each(($amount) => {
cy.wrap($amount).invoke('text').should('not.be.empty');
});
cy.getByTestId(tabFills).contains('Price');
cy.getByTestId(tabFills)
cy.getByTestId('tab-fills')
.get('[role="gridcell"][col-id="price"]')
.each(($prices) => {
cy.wrap($prices).invoke('text').should('not.be.empty');
});
cy.getByTestId(tabFills).contains('Notional');
cy.getByTestId(tabFills)
cy.getByTestId('tab-fills')
.get('[role="gridcell"][col-id="price_1"]')
.each(($total) => {
cy.wrap($total).invoke('text').should('not.be.empty');
});
cy.getByTestId(tabFills).contains('Role');
cy.getByTestId(tabFills)
cy.getByTestId('tab-fills')
.get('[role="gridcell"][col-id="aggressor"]')
.each(($role) => {
cy.wrap($role)
.invoke('text')
.then((text) => {
const roles = ['Maker', 'Taker', '-'];
const roles = ['Maker', 'Taker'];
expect(roles.indexOf(text.trim())).to.be.greaterThan(-1);
});
});
cy.getByTestId(tabFills).contains('Fee');
cy.getByTestId(tabFills)
cy.getByTestId('tab-fills')
.get(
'[role="gridcell"][col-id="market.tradableInstrument.instrument.product"]'
)
.each(($fees) => {
cy.wrap($fees).invoke('text').should('not.be.empty');
});
cy.getByTestId(tabFills).contains('Date');
const dateTimeRegex =
/(\d{1,2})\/(\d{1,2})\/(\d{4}), (\d{1,2}):(\d{1,2}):(\d{1,2})/gm;
cy.get('[col-id="createdAt"]').each(($tradeDateTime, index) => {
@@ -455,7 +455,7 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
});
});
it('must be warned (pre-submit) if the input price has too many digits after the decimal place for the market', () => {
// 7003-MORD-013
// 7003-MORD-016
updateOrder({
id: orderId,
status: Schema.OrderStatus.STATUS_ACTIVE,
-5
View File
@@ -9,8 +9,3 @@ export const selectAsset = (assetIndex: number) => {
// eslint-disable-next-line
cy.wait(100);
};
export const closeWelcomeDialog = () => {
cy.getByTestId('select-market-list').should('exist');
cy.getByTestId('dialog-close').click();
};
@@ -26,7 +26,6 @@ export function updateOrder(
override?: PartialDeep<OrderUpdateFieldsFragment>
): void {
const update: OrdersUpdateSubscription = orderUpdateSubscription({
// @ts-ignore partial deep check failing
orders: [override],
});
if (!sendOrderUpdate) {
+29 -38
View File
@@ -1,7 +1,6 @@
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import * as Schema from '@vegaprotocol/types';
import type { CyHttpMessages } from 'cypress/types/net-stubbing';
import type { Provider, Status } from '@vegaprotocol/oracles';
import {
accountsQuery,
assetQuery,
@@ -46,9 +45,7 @@ const marketDataOverride = (
{
node: {
data: {
// @ts-ignore conflict between incoming and outgoing types
trigger: data.trigger,
// @ts-ignore same as above
marketTradingMode: data.tradingMode,
marketState: data.state,
},
@@ -65,7 +62,6 @@ const marketsDataOverride = (
edges: [
{
node: {
// @ts-ignore conflict between incoming and outgoing types
tradingMode: data.tradingMode,
state: data.state,
},
@@ -159,6 +155,7 @@ const mockTradingPage = (
aliasGQLQuery(req, 'ProposalsList', proposalListQuery());
aliasGQLQuery(req, 'Deposits', depositsQuery());
};
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
@@ -167,56 +164,50 @@ declare global {
mockTradingPage(
state?: Schema.MarketState,
tradingMode?: Schema.MarketTradingMode,
trigger?: Schema.AuctionTrigger,
oracleStatus?: Status
trigger?: Schema.AuctionTrigger
): void;
}
}
}
export const addMockTradingPage = () => {
Cypress.Commands.add(
'mockTradingPage',
(
state = Schema.MarketState.STATE_ACTIVE,
tradingMode,
trigger,
oracleStatus
) => {
(state = Schema.MarketState.STATE_ACTIVE, tradingMode, trigger) => {
cy.mockGQL((req) => {
mockTradingPage(req, state, tradingMode, trigger);
});
const oracle: Provider = {
name: 'Another oracle',
url: 'https://zombo.com',
description_markdown:
'Some markdown describing the oracle provider.\n\nTwitter: @FacesPics2\n',
oracle: {
status: oracleStatus || 'GOOD',
status_reason: '',
first_verified: '2022-01-01T00:00:00.000Z',
last_verified: '2022-12-31T00:00:00.000Z',
type: 'public_key',
public_key: ORACLE_PUBKEY,
},
proofs: [
{
format: 'signed_message',
available: true,
type: 'public_key',
public_key: ORACLE_PUBKEY,
message: 'SOMEHEX',
},
],
github_link: `https://github.com/vegaprotocol/well-known/blob/main/oracle-providers/public_key-${ORACLE_PUBKEY}.toml`,
};
// Prevent request to github, return some dummy content
cy.intercept(
'GET',
/^https:\/\/raw.githubusercontent.com\/vegaprotocol\/well-known/,
{
body: [oracle],
body: [
{
name: 'Another oracle',
url: 'https://zombo.com',
description_markdown:
'Some markdown describing the oracle provider.\n\nTwitter: @FacesPics2\n',
oracle: {
status: 'GOOD',
status_reason: '',
first_verified: '2022-01-01T00:00:00.000Z',
last_verified: '2022-12-31T00:00:00.000Z',
type: 'public_key',
public_key: ORACLE_PUBKEY,
},
proofs: [
{
format: 'signed_message',
available: true,
type: 'public_key',
public_key: ORACLE_PUBKEY,
message: 'SOMEHEX',
},
],
github_link: `https://github.com/vegaprotocol/well-known/blob/main/oracle-providers/public_key-${ORACLE_PUBKEY}.toml`,
},
],
}
);
}
+1 -1
View File
@@ -7,7 +7,7 @@ NX_VEGA_ENV=CUSTOM
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
+1 -1
View File
@@ -11,4 +11,4 @@ NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
@@ -7,6 +7,7 @@ import {
useThrottledDataProvider,
} from '@vegaprotocol/react-helpers';
import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit';
import { marketProvider, marketDataProvider } from '@vegaprotocol/market-list';
import { useGlobalStore, usePageTitleStore } from '../../stores';
import { TradeGrid, TradePanels } from './trade-grid';
+21 -41
View File
@@ -12,10 +12,11 @@ import { memo, useState } from 'react';
import type { ReactNode, ComponentProps } from 'react';
import { DepthChartContainer } from '@vegaprotocol/market-depth';
import { CandlesChartContainer } from '@vegaprotocol/candles-chart';
import { OracleBanner } from '../../components/banner';
import {
Tab,
LocalStoragePersistTabs as Tabs,
ResizableGrid,
ResizableGridPanel,
Splash,
} from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
@@ -27,18 +28,11 @@ import { NO_MARKET } from './constants';
import { LiquidityContainer } from '../liquidity/liquidity';
import { useNavigate } from 'react-router-dom';
import type { PinnedAsset } from '@vegaprotocol/accounts';
import {
usePaneLayout,
useScreenDimensions,
} from '@vegaprotocol/react-helpers';
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
import {
useMarketClickHandler,
useMarketLiquidityClickHandler,
} from '../../lib/hooks/use-market-click-handler';
import {
ResizableGrid,
ResizableGridPanel,
} from '../../components/resizable-grid';
type MarketDependantView =
| typeof CandlesChartContainer
@@ -86,20 +80,15 @@ interface BottomPanelProps {
const MarketBottomPanel = memo(
({ marketId, pinnedAsset }: BottomPanelProps) => {
const [sizes, handleOnLayoutChange] = usePaneLayout({ id: 'bottom' });
const { screenSize } = useScreenDimensions();
const onMarketClick = useMarketClickHandler(true);
const onOrderTypeClick = useMarketLiquidityClickHandler(true);
return 'xxxl' === screenSize ? (
<ResizableGrid
proportionalLayout
minSize={200}
onChange={handleOnLayoutChange}
>
<ResizableGrid proportionalLayout minSize={200}>
<ResizableGridPanel
priority={LayoutPriority.Low}
preferredSize={sizes[0] || '50%'}
preferredSize="50%"
minSize={50}
>
<TradeGridChild>
@@ -127,7 +116,7 @@ const MarketBottomPanel = memo(
</ResizableGridPanel>
<ResizableGridPanel
priority={LayoutPriority.Low}
preferredSize={sizes[1] || '50%'}
preferredSize="50%"
minSize={50}
>
<TradeGridChild>
@@ -194,29 +183,22 @@ MarketBottomPanel.displayName = 'MarketBottomPanel';
const MainGrid = memo(
({
marketId,
onSelect,
pinnedAsset,
}: {
marketId: string;
onSelect: (marketId: string, metaKey?: boolean) => void;
pinnedAsset?: PinnedAsset;
}) => {
const navigate = useNavigate();
const [sizes, handleOnLayoutChange] = usePaneLayout({ id: 'top' });
const [sizesMiddle, handleOnMiddleLayoutChange] = usePaneLayout({
id: 'middle',
});
return (
<ResizableGrid vertical onChange={handleOnLayoutChange}>
<ResizableGrid vertical>
<ResizableGridPanel minSize={75} priority={LayoutPriority.High}>
<ResizableGrid
proportionalLayout={false}
minSize={200}
onChange={handleOnMiddleLayoutChange}
>
<ResizableGrid proportionalLayout={false} minSize={200}>
<ResizableGridPanel
priority={LayoutPriority.High}
minSize={200}
preferredSize={sizesMiddle[0] || '50%'}
preferredSize="50%"
>
<TradeGridChild>
<Tabs storageKey="console-trade-grid-main-left">
@@ -234,7 +216,7 @@ const MainGrid = memo(
</ResizableGridPanel>
<ResizableGridPanel
priority={LayoutPriority.Low}
preferredSize={sizesMiddle[1] || 330}
preferredSize={330}
minSize={300}
>
<TradeGridChild>
@@ -253,7 +235,7 @@ const MainGrid = memo(
</ResizableGridPanel>
<ResizableGridPanel
priority={LayoutPriority.Low}
preferredSize={sizesMiddle[2] || 430}
preferredSize={430}
minSize={200}
>
<TradeGridChild>
@@ -271,7 +253,7 @@ const MainGrid = memo(
</ResizableGridPanel>
<ResizableGridPanel
priority={LayoutPriority.Low}
preferredSize={sizes[1] || '25%'}
preferredSize="25%"
minSize={50}
>
<MarketBottomPanel marketId={marketId} pinnedAsset={pinnedAsset} />
@@ -289,11 +271,12 @@ export const TradeGrid = ({
}: TradeGridProps) => {
return (
<div className="h-full grid grid-rows-[min-content_1fr]">
<div>
<TradeMarketHeader market={market} onSelect={onSelect} />
<OracleBanner marketId={market?.id || ''} />
</div>
<MainGrid marketId={market?.id || ''} pinnedAsset={pinnedAsset} />
<TradeMarketHeader market={market} onSelect={onSelect} />
<MainGrid
marketId={market?.id || ''}
onSelect={onSelect}
pinnedAsset={pinnedAsset}
/>
</div>
);
};
@@ -361,10 +344,7 @@ export const TradePanels = ({
return (
<div className="h-full grid grid-rows-[min-content_1fr_min-content]">
<div>
<TradeMarketHeader market={market} onSelect={onSelect} />
<OracleBanner marketId={market?.id || ''} />
</div>
<TradeMarketHeader market={market} onSelect={onSelect} />
<div className="h-full">
<AutoSizer>
{({ width, height }) => (
@@ -1,335 +0,0 @@
import { act, render, screen, within } from '@testing-library/react';
import { Closed } from './closed';
import { MarketStateMapping } from '@vegaprotocol/types';
import { PositionStatus } from '@vegaprotocol/types';
import { MarketState } from '@vegaprotocol/types';
import { subDays } from 'date-fns';
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
import type { OracleSpecDataConnectionQuery } from '@vegaprotocol/oracles';
import { OracleSpecDataConnectionDocument } from '@vegaprotocol/oracles';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { VegaWalletContext } from '@vegaprotocol/wallet';
import type {
PositionsQuery,
PositionFieldsFragment,
} from '@vegaprotocol/positions';
import { PositionsDocument } from '@vegaprotocol/positions';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import type { MarketsDataQuery, MarketsQuery } from '@vegaprotocol/market-list';
import { MarketsDataDocument } from '@vegaprotocol/market-list';
import { MarketsDocument } from '@vegaprotocol/market-list';
import {
createMarketFragment,
marketsQuery,
marketsDataQuery,
createMarketsDataFragment,
} from '@vegaprotocol/mock';
describe('Closed', () => {
let originalNow: typeof Date.now;
const mockNowTimestamp = 1672531200000;
const settlementDateMetaDate = subDays(
new Date(mockNowTimestamp),
3
).toISOString();
const settlementDateTag = `settlement-expiry-date:${settlementDateMetaDate}`;
const pubKey = 'pubKey';
const marketId = 'market-0';
const settlementDataProperty = 'spec-binding';
const settlementDataId = 'settlement-data-oracle-id';
const market = createMarketFragment({
id: marketId,
state: MarketState.STATE_SETTLED,
tradableInstrument: {
instrument: {
metadata: {
tags: [settlementDateTag],
},
product: {
dataSourceSpecForSettlementData: {
id: settlementDataId,
},
dataSourceSpecBinding: {
settlementDataProperty,
},
},
},
},
});
const marketsMock: MockedResponse<MarketsQuery> = {
request: {
query: MarketsDocument,
},
result: {
data: marketsQuery({
marketsConnection: {
edges: [
{
node: market,
},
],
},
}),
},
};
const marketsData = createMarketsDataFragment({
__typename: 'MarketData',
market: {
__typename: 'Market',
id: marketId,
},
bestBidPrice: '1000',
bestOfferPrice: '2000',
markPrice: '1500',
});
const marketsDataMock: MockedResponse<MarketsDataQuery> = {
request: {
query: MarketsDataDocument,
},
result: {
data: marketsDataQuery({
marketsConnection: {
edges: [
{
node: {
data: marketsData,
},
},
],
},
}),
},
};
// Create mock oracle data
const property = {
__typename: 'Property' as const,
name: settlementDataProperty,
value: '12345',
};
const oracleDataMock: MockedResponse<OracleSpecDataConnectionQuery> = {
request: {
query: OracleSpecDataConnectionDocument,
variables: {
oracleSpecId: settlementDataId,
},
},
result: {
data: {
oracleSpec: {
dataConnection: {
edges: [
{
node: {
externalData: {
data: {
data: [property],
},
},
},
},
],
},
},
},
},
};
// Create mock position
const createPosition = (): PositionFieldsFragment => {
return {
__typename: 'Position' as const,
realisedPNL: '1000',
unrealisedPNL: '2000',
openVolume: '3000',
averageEntryPrice: '100',
updatedAt: new Date().toISOString(),
positionStatus: PositionStatus.POSITION_STATUS_UNSPECIFIED,
lossSocializationAmount: '1000',
market: {
__typename: 'Market',
id: marketId,
},
};
};
const position = createPosition();
const positionsMock: MockedResponse<PositionsQuery> = {
request: {
query: PositionsDocument,
variables: {
partyId: pubKey,
},
},
result: {
data: {
party: {
__typename: 'Party',
id: pubKey,
positionsConnection: {
__typename: 'PositionConnection',
edges: [{ __typename: 'PositionEdge', node: position }],
},
},
},
},
};
beforeAll(() => {
originalNow = Date.now;
Date.now = jest.fn().mockReturnValue(mockNowTimestamp);
});
afterAll(() => {
Date.now = originalNow;
});
it('renders correctly formatted and filtered rows', async () => {
await act(async () => {
render(
<MockedProvider
mocks={[marketsMock, marketsDataMock, positionsMock, oracleDataMock]}
>
<VegaWalletContext.Provider
value={{ pubKey } as VegaWalletContextShape}
>
<Closed />
</VegaWalletContext.Provider>
</MockedProvider>
);
});
// screen.debug(document, Infinity);
const headers = screen.getAllByRole('columnheader');
const expectedHeaders = [
'Market',
'Description',
'Status',
'Settlement date',
'Best bid',
'Best offer',
'Mark price',
'Settlement price',
'Realised PNL',
'Settlement asset',
'Market ID',
];
expect(headers).toHaveLength(expectedHeaders.length);
expect(headers.map((h) => h.textContent?.trim())).toEqual(expectedHeaders);
const cells = screen.getAllByRole('gridcell');
const expectedValues = [
market.tradableInstrument.instrument.code,
market.tradableInstrument.instrument.name,
MarketStateMapping[market.state],
'3 days ago',
/* eslint-disable @typescript-eslint/no-non-null-assertion */
addDecimalsFormatNumber(marketsData.bestBidPrice, market.decimalPlaces),
addDecimalsFormatNumber(
marketsData!.bestOfferPrice,
market.decimalPlaces
),
addDecimalsFormatNumber(marketsData!.markPrice, market.decimalPlaces),
/* eslint-enable @typescript-eslint/no-non-null-assertion */
addDecimalsFormatNumber(property.value, market.decimalPlaces),
addDecimalsFormatNumber(position.realisedPNL, market.decimalPlaces),
market.tradableInstrument.instrument.product.settlementAsset.symbol,
market.id,
];
cells.forEach((cell, i) => {
expect(cell).toHaveTextContent(expectedValues[i]);
});
});
it('only renders settled and terminated markets', async () => {
const mixedMarkets = [
{
// inlclude as settled
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: 'include-0',
state: MarketState.STATE_SETTLED,
}),
},
{
// omit this market
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: 'discard-0',
state: MarketState.STATE_SUSPENDED,
}),
},
{
// include as terminated
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: 'include-1',
state: MarketState.STATE_TRADING_TERMINATED,
}),
},
{
// omit this market
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: 'discard-1',
state: MarketState.STATE_ACTIVE,
}),
},
];
const mixedMarketsMock: MockedResponse<MarketsQuery> = {
request: {
query: MarketsDocument,
},
result: {
data: {
marketsConnection: {
__typename: 'MarketConnection',
edges: mixedMarkets,
},
},
},
};
await act(async () => {
render(
<MockedProvider
mocks={[
mixedMarketsMock,
marketsDataMock,
positionsMock,
oracleDataMock,
]}
>
<VegaWalletContext.Provider
value={{ pubKey } as VegaWalletContextShape}
>
<Closed />
</VegaWalletContext.Provider>
</MockedProvider>
);
});
// check that the number of rows in datagrid is 2
const container = within(
document.querySelector('.ag-center-cols-container') as HTMLElement
);
const expectedRows = mixedMarkets.filter((m) => {
return [
MarketState.STATE_SETTLED,
MarketState.STATE_TRADING_TERMINATED,
].includes(m.node.state);
});
// 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
.getAllByRole('gridcell')
.filter((cell) => cell.getAttribute('col-id') === 'id')
.map((cell) => cell.textContent?.trim());
expect(cells).toEqual(expectedRows.map((m) => m.node.id));
});
});

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