Compare commits
26
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05b39e2c08 | ||
|
|
654dd1e7b0 | ||
|
|
7ea7362a7d | ||
|
|
bbfe42ddb1 | ||
|
|
b163af3e8a | ||
|
|
82df401611 | ||
|
|
4733bc169c | ||
|
|
2b91aebc2a | ||
|
|
375f4da541 | ||
|
|
bc413ed314 | ||
|
|
2fab3daebd | ||
|
|
2e07ada966 | ||
|
|
b81c4bc948 | ||
|
|
4f8d6bd876 | ||
|
|
52e5a37da3 | ||
|
|
22599673ec | ||
|
|
3c6a806ad3 | ||
|
|
7101d49d1d | ||
|
|
72e0cb76aa | ||
|
|
ca64516a52 | ||
|
|
55d692ea6f | ||
|
|
f235c03abe | ||
|
|
546deb0e1c | ||
|
|
042919eca9 | ||
|
|
c4a56e0de3 | ||
|
|
3c3bfb7dac |
@@ -25,7 +25,7 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
rm package.json
|
rm package.json
|
||||||
npm install --no-save @commitlint/cli @commitlint/config-conventional @commitlint/config-nx-scopes nx
|
npm install --no-save @commitlint/cli@16.3.0 @commitlint/config-conventional@18.6.1 @commitlint/config-nx-scopes@18.6.1 nx@17.1.2
|
||||||
|
|
||||||
- name: Check PR title
|
- name: Check PR title
|
||||||
run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js
|
run: echo "${{ github.event.pull_request.title }}" | npx @commitlint/cli@16.3.0 --config ./commitlint.config-ci.js
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { getNewAssetTxBody } from '../support/governance.functions';
|
import { getNewAssetTxBody } from '../support/governance.functions';
|
||||||
|
|
||||||
context('Proposal page', { tags: '@smoke' }, function () {
|
context('Proposal page', { tags: '@smoke' }, function () {
|
||||||
describe('Verify elements on page', function () {
|
describe.skip('Verify elements on page', function () {
|
||||||
const proposalHeading = 'proposals-heading';
|
const proposalHeading = 'proposals-heading';
|
||||||
const dateTimeRegex =
|
const dateTimeRegex =
|
||||||
/(\d{1,2})\/(\d{1,2})\/(\d{4}), (\d{1,2}):(\d{1,2}):(\d{1,2})/gm;
|
/(\d{1,2})\/(\d{1,2})\/(\d{4}), (\d{1,2}):(\d{1,2}):(\d{1,2})/gm;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe('Links and buttons', function () {
|
describe('Links and buttons', function () {
|
||||||
it.skip('should have link for proposal page', function () {
|
it('should have link for proposal page', function () {
|
||||||
cy.getByTestId('home-proposals').within(() => {
|
cy.getByTestId('home-proposals').within(() => {
|
||||||
cy.get('[href="/proposals"]')
|
cy.get('[href="/proposals"]')
|
||||||
.should('exist')
|
.should('exist')
|
||||||
@@ -51,7 +51,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should have external link for governance', function () {
|
it('should have external link for governance', function () {
|
||||||
cy.getByTestId('home-proposals').within(() => {
|
cy.getByTestId('home-proposals').within(() => {
|
||||||
cy.getByTestId('external-link')
|
cy.getByTestId('external-link')
|
||||||
.should('have.attr', 'href')
|
.should('have.attr', 'href')
|
||||||
@@ -59,7 +59,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should have link for validator page', function () {
|
it('should have link for validator page', function () {
|
||||||
cy.getByTestId('home-validators').within(() => {
|
cy.getByTestId('home-validators').within(() => {
|
||||||
cy.get('[href="/validators"]')
|
cy.get('[href="/validators"]')
|
||||||
.first()
|
.first()
|
||||||
@@ -68,7 +68,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should have external link for validators', function () {
|
it('should have external link for validators', function () {
|
||||||
cy.getByTestId('home-validators').within(() => {
|
cy.getByTestId('home-validators').within(() => {
|
||||||
cy.getByTestId('external-link')
|
cy.getByTestId('external-link')
|
||||||
.should('have.attr', 'href')
|
.should('have.attr', 'href')
|
||||||
@@ -79,29 +79,29 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should have information on active nodes', function () {
|
it('should have information on active nodes', function () {
|
||||||
cy.getByTestId('node-information')
|
cy.getByTestId('node-information')
|
||||||
.first()
|
.first()
|
||||||
.should('contain.text', '2')
|
.should('contain.text', '1')
|
||||||
.and('contain.text', 'active nodes');
|
.and('contain.text', 'active nodes');
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should have information on consensus nodes', function () {
|
it('should have information on consensus nodes', function () {
|
||||||
cy.getByTestId('node-information')
|
cy.getByTestId('node-information')
|
||||||
.last()
|
.last()
|
||||||
.should('contain.text', '2')
|
.should('contain.text', '1')
|
||||||
.and('contain.text', 'consensus nodes');
|
.and('contain.text', 'consensus nodes');
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should contain link to specific validators', function () {
|
it('should contain link to specific validators', function () {
|
||||||
cy.getByTestId('validators')
|
cy.getByTestId('validators')
|
||||||
.should('have.length', '2')
|
.should('have.length', '1')
|
||||||
.each(($validator) => {
|
.each(($validator) => {
|
||||||
cy.wrap($validator).find('a').should('have.attr', 'href');
|
cy.wrap($validator).find('a').should('have.attr', 'href');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should have link for rewards page', function () {
|
it('should have link for rewards page', function () {
|
||||||
cy.getByTestId('home-rewards').within(() => {
|
cy.getByTestId('home-rewards').within(() => {
|
||||||
cy.get('[href="/rewards"]')
|
cy.get('[href="/rewards"]')
|
||||||
.first()
|
.first()
|
||||||
@@ -110,7 +110,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should have link for withdrawal page', function () {
|
it('should have link for withdrawal page', function () {
|
||||||
cy.getByTestId('home-vega-token').within(() => {
|
cy.getByTestId('home-vega-token').within(() => {
|
||||||
cy.get('[href="/token/withdraw"]')
|
cy.get('[href="/token/withdraw"]')
|
||||||
.first()
|
.first()
|
||||||
@@ -132,7 +132,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 0006-NETW-003 0006-NETW-008 0006-NETW-009 0006-NETW-010 0006-NETW-012 0006-NETW-013 0006-NETW-017 0006-NETW-018 0006-NETW-019 0006-NETW-020
|
// 0006-NETW-003 0006-NETW-008 0006-NETW-009 0006-NETW-010 0006-NETW-012 0006-NETW-013 0006-NETW-017 0006-NETW-018 0006-NETW-019 0006-NETW-020
|
||||||
it.skip('should have option to switch to different network node', function () {
|
it('should have option to switch to different network node', function () {
|
||||||
cy.getByTestId('git-network-data').within(() => {
|
cy.getByTestId('git-network-data').within(() => {
|
||||||
cy.getByTestId('link').click();
|
cy.getByTestId('link').click();
|
||||||
});
|
});
|
||||||
@@ -159,7 +159,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
|
|||||||
cy.getByTestId('node-url-custom').click({ force: true });
|
cy.getByTestId('node-url-custom').click({ force: true });
|
||||||
cy.get('input').should('exist');
|
cy.get('input').should('exist');
|
||||||
cy.getByTestId('connect').should('be.disabled');
|
cy.getByTestId('connect').should('be.disabled');
|
||||||
cy.getByTestId('icon-cross').click();
|
cy.getByTestId('dialog-close').click();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display eth data', function () {
|
it('should display eth data', function () {
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ context(
|
|||||||
verifyTabHighlighted(navigation.proposals);
|
verifyTabHighlighted(navigation.proposals);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should have GOVERNANCE header visible', function () {
|
it('should have GOVERNANCE header visible', function () {
|
||||||
verifyPageHeader('Proposals');
|
verifyPageHeader('Proposals');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 3002-PROP-023 3004-PMAC-002 3005-PASN-002 3006-PASC-002 3007-PNEC-002 3008-PFRO-003
|
// 3002-PROP-023 3004-PMAC-002 3005-PASN-002 3006-PASC-002 3007-PNEC-002 3008-PFRO-003
|
||||||
it.skip('new proposal page should have button for link to more information on proposals', function () {
|
it('new proposal page should have button for link to more information on proposals', function () {
|
||||||
cy.getByTestId('new-proposal-link').click();
|
cy.getByTestId('new-proposal-link').click();
|
||||||
cy.url().should('include', '/proposals/propose/raw');
|
cy.url().should('include', '/proposals/propose/raw');
|
||||||
cy.contains('To see Explorer data on proposals visit').within(() => {
|
cy.contains('To see Explorer data on proposals visit').within(() => {
|
||||||
@@ -73,7 +73,7 @@ context(
|
|||||||
navigateTo(navigation.proposals);
|
navigateTo(navigation.proposals);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('should be able to see a working link for - find out more about Vega governance', function () {
|
it('should be able to see a working link for - find out more about Vega governance', function () {
|
||||||
// 3001-VOTE-001 // 3002-PROP-001
|
// 3001-VOTE-001 // 3002-PROP-001
|
||||||
cy.getByTestId(proposalDocumentationLink)
|
cy.getByTestId(proposalDocumentationLink)
|
||||||
.should('be.visible')
|
.should('be.visible')
|
||||||
|
|||||||
@@ -40,10 +40,10 @@ context('View functionality with public key', { tags: '@smoke' }, function () {
|
|||||||
verifyConnectedToPubKey();
|
verifyConnectedToPubKey();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Able to connect public key via wallet and view assets in wallet', function () {
|
it.skip('Able to connect public key via wallet and view assets in wallet', function () {
|
||||||
verifyConnectedToPubKey();
|
verifyConnectedToPubKey();
|
||||||
cy.getByTestId('currency-title', { timeout: 10000 })
|
cy.getByTestId('currency-title', { timeout: 10000 })
|
||||||
.should('have.length.at.least', 4)
|
.should('have.length.at.least', 2)
|
||||||
.and('contain.text', 'USDC (fake)');
|
.and('contain.text', 'USDC (fake)');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -46,11 +46,11 @@ context('Validators Page - verify elements on page', function () {
|
|||||||
|
|
||||||
// @ts-ignore clash between jest and cypress
|
// @ts-ignore clash between jest and cypress
|
||||||
describe('with wallets disconnected', { tags: '@smoke' }, function () {
|
describe('with wallets disconnected', { tags: '@smoke' }, function () {
|
||||||
it.skip('Should have validators tab highlighted', function () {
|
it('Should have validators tab highlighted', function () {
|
||||||
verifyTabHighlighted(navigation.validators);
|
verifyTabHighlighted(navigation.validators);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('Should have validators ON VEGA header visible', function () {
|
it('Should have validators ON VEGA header visible', function () {
|
||||||
verifyPageHeader('Validators');
|
verifyPageHeader('Validators');
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ context('Validators Page - verify elements on page', function () {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// 1002-STKE-006
|
// 1002-STKE-006
|
||||||
it.skip('Should be able to see validator name', function () {
|
it('Should be able to see validator name', function () {
|
||||||
cy.getByTestId(validatorTitle).should('not.be.empty');
|
cy.getByTestId(validatorTitle).should('not.be.empty');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/m
|
|||||||
|
|
||||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
|
||||||
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
|
||||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||||
@@ -24,7 +23,7 @@ NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks
|
|||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
||||||
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/en-GB/firefox/addon/vega-wallet-beta/
|
||||||
|
|
||||||
#Test configuration variables
|
#Test configuration variables
|
||||||
CYPRESS_FAIRGROUND=false
|
CYPRESS_FAIRGROUND=false
|
||||||
@@ -33,7 +32,7 @@ LC_ALL="en_US.UTF-8"
|
|||||||
# Cosmic elevator flags
|
# Cosmic elevator flags
|
||||||
NX_SUCCESSOR_MARKETS=true
|
NX_SUCCESSOR_MARKETS=true
|
||||||
NX_METAMASK_SNAPS=true
|
NX_METAMASK_SNAPS=true
|
||||||
NX_PRODUCT_PERPETUALS=false
|
NX_PRODUCT_PERPETUALS=true
|
||||||
NX_UPDATE_MARKET_STATE=false
|
NX_UPDATE_MARKET_STATE=true
|
||||||
NX_REFERRALS=true
|
NX_REFERRALS=true
|
||||||
NX_GOVERNANCE_TRANSFERS=false
|
NX_GOVERNANCE_TRANSFERS=true
|
||||||
|
|||||||
@@ -15,12 +15,11 @@ NX_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit suppl
|
|||||||
NX_LOCAL_PROVIDER_URL=http://localhost:8545/
|
NX_LOCAL_PROVIDER_URL=http://localhost:8545/
|
||||||
NX_VEGA_WALLET_URL=http://localhost:1789
|
NX_VEGA_WALLET_URL=http://localhost:1789
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
|
||||||
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
||||||
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
||||||
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/en-GB/firefox/addon/vega-wallet-beta/
|
||||||
|
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,13 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
|||||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||||
NX_VEGA_EXPLORER_URL=#
|
NX_VEGA_EXPLORER_URL=#
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
|
||||||
NX_TRANCHES_SERVICE_URL=https://tranches-devnet1-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-devnet1-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
NX_VEGA_REST_URL=https://api.n00.devnet1.vega.xyz/api/v2/
|
NX_VEGA_REST_URL=https://api.n00.devnet1.vega.xyz/api/v2/
|
||||||
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
||||||
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/en-GB/firefox/addon/vega-wallet-beta/
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
|
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/
|
|||||||
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
|
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
||||||
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
|
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
|
||||||
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||||
NX_VEGA_REST_URL=https://api.vega.community/api/v2/
|
NX_VEGA_REST_URL=https://api.vega.community/api/v2/
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
|||||||
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
||||||
NX_VEGA_EXPLORER_URL=https://explorer.mainnet-mirror.vega.rocks
|
NX_VEGA_EXPLORER_URL=https://explorer.mainnet-mirror.vega.rocks
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
|
||||||
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-mirror-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-mirror-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||||
NX_VEGA_REST_URL=https://api.mainnet-mirror.vega.rocks/api/v2/
|
NX_VEGA_REST_URL=https://api.mainnet-mirror.vega.rocks/api/v2/
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","STAGNET1":"https:
|
|||||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
|
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
|
||||||
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
|
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
|
||||||
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
|
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
|
||||||
@@ -13,7 +12,7 @@ NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/m
|
|||||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||||
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/en-GB/firefox/addon/vega-wallet-beta/
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks
|
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.rocks
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
|||||||
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
|
||||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||||
NX_DELEGATIONS_PAGINATION=50
|
|
||||||
NX_TRANCHES_SERVICE_URL=https://tranches-testnet-k8s.ops.vega.xyz
|
NX_TRANCHES_SERVICE_URL=https://tranches-testnet-k8s.ops.vega.xyz
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||||
NX_VEGA_REST_URL=https://api.n07.testnet.vega.xyz/api/v2/
|
NX_VEGA_REST_URL=https://api.n07.testnet.vega.xyz/api/v2/
|
||||||
@@ -18,7 +17,7 @@ NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/m
|
|||||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||||
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/en-GB/firefox/addon/vega-wallet-beta/
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
|
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/
|
|||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||||
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/en-GB/firefox/addon/vega-wallet-beta/
|
||||||
|
|
||||||
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
|
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
|
||||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.
|
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.
|
||||||
|
|||||||
@@ -15,19 +15,16 @@ export const CollapsibleToggle = ({
|
|||||||
dataTestId,
|
dataTestId,
|
||||||
children,
|
children,
|
||||||
}: CollapsibleToggleProps) => {
|
}: CollapsibleToggleProps) => {
|
||||||
const classes = classnames(
|
const classes = classnames('transition-transform ease-in-out duration-300', {
|
||||||
'mb-4 transition-transform ease-in-out duration-300',
|
'rotate-180': toggleState,
|
||||||
{
|
});
|
||||||
'rotate-180': toggleState,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
onClick={() => setToggleState(!toggleState)}
|
onClick={() => setToggleState(!toggleState)}
|
||||||
data-testid={dataTestId}
|
data-testid={dataTestId}
|
||||||
>
|
>
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-baseline gap-3">
|
||||||
{children}
|
{children}
|
||||||
<div className={classes} data-testid="toggle-icon-wrapper">
|
<div className={classes} data-testid="toggle-icon-wrapper">
|
||||||
<VegaIcon name={VegaIconNames.CHEVRON_DOWN} size={20} />
|
<VegaIcon name={VegaIconNames.CHEVRON_DOWN} size={20} />
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
|
import { type ReactNode } from 'react';
|
||||||
|
|
||||||
interface HeadingProps {
|
interface HeadingProps {
|
||||||
title?: string;
|
title?: ReactNode;
|
||||||
centerContent?: boolean;
|
centerContent?: boolean;
|
||||||
marginTop?: boolean;
|
marginTop?: boolean;
|
||||||
marginBottom?: boolean;
|
marginBottom?: boolean;
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
import {
|
||||||
|
useLinks,
|
||||||
|
DApp,
|
||||||
|
CONSOLE_REWARDS_PAGE,
|
||||||
|
} from '@vegaprotocol/environment';
|
||||||
|
import {
|
||||||
|
ExternalLink,
|
||||||
|
Intent,
|
||||||
|
NotificationBanner,
|
||||||
|
VegaIcon,
|
||||||
|
VegaIconNames,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { Trans } from 'react-i18next';
|
||||||
|
import { useMatch } from 'react-router-dom';
|
||||||
|
import Routes from '../../routes/routes';
|
||||||
|
import { type ReactNode } from 'react';
|
||||||
|
|
||||||
|
const ConsoleRewardsLink = ({ children }: { children: ReactNode }) => {
|
||||||
|
const consoleLink = useLinks(DApp.Console);
|
||||||
|
return (
|
||||||
|
<ExternalLink
|
||||||
|
href={consoleLink(CONSOLE_REWARDS_PAGE)}
|
||||||
|
className="underline inline-flex gap-1 items-center"
|
||||||
|
title="Rewards in Console"
|
||||||
|
>
|
||||||
|
<span>{children}</span>
|
||||||
|
<VegaIcon size={12} name={VegaIconNames.OPEN_EXTERNAL} />
|
||||||
|
</ExternalLink>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RewardsMovedNotification = () => {
|
||||||
|
const onRewardsPage = useMatch(Routes.REWARDS);
|
||||||
|
if (!onRewardsPage) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<NotificationBanner intent={Intent.Warning}>
|
||||||
|
<Trans
|
||||||
|
i18nKey="rewardsMovedNotification"
|
||||||
|
components={[<ConsoleRewardsLink>Console</ConsoleRewardsLink>]}
|
||||||
|
/>
|
||||||
|
</NotificationBanner>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
ProtocolUpgradeProposalNotification,
|
ProtocolUpgradeProposalNotification,
|
||||||
} from '@vegaprotocol/proposals';
|
} from '@vegaprotocol/proposals';
|
||||||
import { ViewingAsBanner } from '@vegaprotocol/ui-toolkit';
|
import { ViewingAsBanner } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { RewardsMovedNotification } from '../notifications/rewards-moved-notification';
|
||||||
|
|
||||||
interface AppLayoutProps {
|
interface AppLayoutProps {
|
||||||
children: ReactNode;
|
children: ReactNode;
|
||||||
@@ -45,8 +46,10 @@ export const AppLayout = ({ children }: AppLayoutProps) => {
|
|||||||
|
|
||||||
const NotificationsContainer = () => {
|
const NotificationsContainer = () => {
|
||||||
const { isReadOnly, pubKey, disconnect } = useVegaWallet();
|
const { isReadOnly, pubKey, disconnect } = useVegaWallet();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div data-testid="banners">
|
<div data-testid="banners">
|
||||||
|
<RewardsMovedNotification />
|
||||||
<ProtocolUpgradeProposalNotification
|
<ProtocolUpgradeProposalNotification
|
||||||
mode={ProtocolUpgradeCountdownMode.IN_ESTIMATED_TIME_REMAINING}
|
mode={ProtocolUpgradeCountdownMode.IN_ESTIMATED_TIME_REMAINING}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import keyBy from 'lodash/keyBy';
|
|||||||
import uniq from 'lodash/uniq';
|
import uniq from 'lodash/uniq';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { ENV } from '../../config';
|
|
||||||
|
|
||||||
import noIcon from '../../images/token-no-icon.png';
|
import noIcon from '../../images/token-no-icon.png';
|
||||||
import vegaBlack from '../../images/vega_black.png';
|
import vegaBlack from '../../images/vega_black.png';
|
||||||
@@ -37,7 +36,6 @@ export const usePollForDelegations = () => {
|
|||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { pubKey } = useVegaWallet();
|
const { pubKey } = useVegaWallet();
|
||||||
const client = useApolloClient();
|
const client = useApolloClient();
|
||||||
const { delegationsPagination } = ENV;
|
|
||||||
const [delegations, setDelegations] = React.useState<
|
const [delegations, setDelegations] = React.useState<
|
||||||
WalletDelegationFieldsFragment[]
|
WalletDelegationFieldsFragment[]
|
||||||
>([]);
|
>([]);
|
||||||
@@ -68,11 +66,9 @@ export const usePollForDelegations = () => {
|
|||||||
query: DelegationsDocument,
|
query: DelegationsDocument,
|
||||||
variables: {
|
variables: {
|
||||||
partyId: pubKey,
|
partyId: pubKey,
|
||||||
delegationsPagination: delegationsPagination
|
delegationsPagination: {
|
||||||
? {
|
first: 50,
|
||||||
first: Number(delegationsPagination),
|
},
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
},
|
},
|
||||||
fetchPolicy: 'network-only',
|
fetchPolicy: 'network-only',
|
||||||
})
|
})
|
||||||
@@ -236,14 +232,14 @@ export const usePollForDelegations = () => {
|
|||||||
// will just continue to fail
|
// will just continue to fail
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
});
|
});
|
||||||
}, 1000);
|
}, 20000);
|
||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
mounted = false;
|
mounted = false;
|
||||||
};
|
};
|
||||||
}, [delegationsPagination, client, decimals, pubKey, t, vegaToken.address]);
|
}, [client, decimals, pubKey, t, vegaToken.address]);
|
||||||
|
|
||||||
return { delegations, currentStakeAvailable, delegatedNodes, accounts };
|
return { delegations, currentStakeAvailable, delegatedNodes, accounts };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ export const ENV = {
|
|||||||
docsUrl: windowOrDefault('NX_VEGA_DOCS_URL'),
|
docsUrl: windowOrDefault('NX_VEGA_DOCS_URL'),
|
||||||
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
|
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
|
||||||
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
|
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
|
||||||
delegationsPagination: windowOrDefault('NX_DELEGATIONS_PAGINATION'),
|
|
||||||
rest: windowOrDefault('NX_VEGA_REST_URL'),
|
rest: windowOrDefault('NX_VEGA_REST_URL'),
|
||||||
addresses:
|
addresses:
|
||||||
ContractAddresses[(envName === 'local' ? 'CUSTOM' : envName) as Networks],
|
ContractAddresses[(envName === 'local' ? 'CUSTOM' : envName) as Networks],
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ describe('getMultisigStatus', () => {
|
|||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
multisigStatus: MultisigStatus.noNodes,
|
multisigStatus: MultisigStatus.noNodes,
|
||||||
showMultisigStatusError: true,
|
showMultisigStatusError: true,
|
||||||
|
zeroScoreNodes: [],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -35,6 +36,7 @@ describe('getMultisigStatus', () => {
|
|||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
multisigStatus: MultisigStatus.correct,
|
multisigStatus: MultisigStatus.correct,
|
||||||
showMultisigStatusError: false,
|
showMultisigStatusError: false,
|
||||||
|
zeroScoreNodes: [],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -50,6 +52,22 @@ describe('getMultisigStatus', () => {
|
|||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
multisigStatus: MultisigStatus.nodeNeedsRemoving,
|
multisigStatus: MultisigStatus.nodeNeedsRemoving,
|
||||||
showMultisigStatusError: true,
|
showMultisigStatusError: true,
|
||||||
|
zeroScoreNodes: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
rewardScore: {
|
||||||
|
multisigScore: '0',
|
||||||
|
},
|
||||||
|
stakedTotal: '1000',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
rewardScore: {
|
||||||
|
multisigScore: '0',
|
||||||
|
},
|
||||||
|
stakedTotal: '1000',
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -65,6 +83,15 @@ describe('getMultisigStatus', () => {
|
|||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
multisigStatus: MultisigStatus.nodeNeedsAdding,
|
multisigStatus: MultisigStatus.nodeNeedsAdding,
|
||||||
showMultisigStatusError: true,
|
showMultisigStatusError: true,
|
||||||
|
zeroScoreNodes: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
rewardScore: {
|
||||||
|
multisigScore: '0',
|
||||||
|
},
|
||||||
|
stakedTotal: '1000',
|
||||||
|
},
|
||||||
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||||
import type { PreviousEpochQuery } from '../routes/staking/__generated__/PreviousEpoch';
|
import type {
|
||||||
|
PreviousEpochQuery,
|
||||||
|
ValidatorNodeFragment,
|
||||||
|
} from '../routes/staking/__generated__/PreviousEpoch';
|
||||||
|
|
||||||
export enum MultisigStatus {
|
export enum MultisigStatus {
|
||||||
'correct' = 'correct',
|
'correct' = 'correct',
|
||||||
@@ -17,12 +20,15 @@ export const getMultisigStatusInfo = (
|
|||||||
previousEpochData?.epoch.validatorsConnection?.edges
|
previousEpochData?.epoch.validatorsConnection?.edges
|
||||||
);
|
);
|
||||||
|
|
||||||
const hasZero = allNodesInPreviousEpoch.some(
|
const zeroScore = (node: ValidatorNodeFragment) =>
|
||||||
(node) => Number(node?.rewardScore?.multisigScore) === 0
|
Number(node.rewardScore?.multisigScore) === 0;
|
||||||
);
|
const oneScore = (node: ValidatorNodeFragment) =>
|
||||||
const hasOne = allNodesInPreviousEpoch.some(
|
Number(node.rewardScore?.multisigScore) === 1;
|
||||||
(node) => Number(node?.rewardScore?.multisigScore) === 1
|
|
||||||
);
|
const hasZero = allNodesInPreviousEpoch.some(zeroScore);
|
||||||
|
const hasOne = allNodesInPreviousEpoch.some(oneScore);
|
||||||
|
|
||||||
|
const zeroScoreNodes = allNodesInPreviousEpoch.filter(zeroScore);
|
||||||
|
|
||||||
if (hasZero && hasOne) {
|
if (hasZero && hasOne) {
|
||||||
// If any individual node has 0 it means that node is missing from the multisig and needs to be added
|
// If any individual node has 0 it means that node is missing from the multisig and needs to be added
|
||||||
@@ -38,5 +44,6 @@ export const getMultisigStatusInfo = (
|
|||||||
return {
|
return {
|
||||||
showMultisigStatusError: status !== MultisigStatus.correct,
|
showMultisigStatusError: status !== MultisigStatus.correct,
|
||||||
multisigStatus: status,
|
multisigStatus: status,
|
||||||
|
zeroScoreNodes,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
+9
-9
@@ -36,8 +36,8 @@ import { type Proposal, type BatchProposal } from '../../types';
|
|||||||
import { type ProposalTermsFieldsFragment } from '../../__generated__/Proposals';
|
import { type ProposalTermsFieldsFragment } from '../../__generated__/Proposals';
|
||||||
import { differenceInHours, format, formatDistanceToNowStrict } from 'date-fns';
|
import { differenceInHours, format, formatDistanceToNowStrict } from 'date-fns';
|
||||||
import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats';
|
import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats';
|
||||||
import { getIndicatorStyle } from '../proposal/colours';
|
|
||||||
import { MarketName } from '../proposal/market-name';
|
import { MarketName } from '../proposal/market-name';
|
||||||
|
import { Indicator } from '../proposal/indicator';
|
||||||
|
|
||||||
const ProposalTypeTags = ({
|
const ProposalTypeTags = ({
|
||||||
proposal,
|
proposal,
|
||||||
@@ -54,11 +54,8 @@ const ProposalTypeTags = ({
|
|||||||
|
|
||||||
if (proposal.__typename === 'BatchProposal') {
|
if (proposal.__typename === 'BatchProposal') {
|
||||||
return (
|
return (
|
||||||
<div data-testid="proposal-type" className="flex gap-1">
|
<div data-testid="proposal-type">
|
||||||
{proposal.subProposals?.map((subProposal, i) => {
|
<ProposalInfoLabel variant="secondary">BatchProposal</ProposalInfoLabel>
|
||||||
if (!subProposal?.terms) return null;
|
|
||||||
return <ProposalTypeTag key={i} terms={subProposal.terms} />;
|
|
||||||
})}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -253,7 +250,7 @@ const ProposalDetails = ({
|
|||||||
}}
|
}}
|
||||||
components={{
|
components={{
|
||||||
// @ts-ignore children passed by i18next
|
// @ts-ignore children passed by i18next
|
||||||
lozenge: <Lozenge />,
|
lozenge: <Lozenge className="text-xs" />,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@@ -315,8 +312,11 @@ const ProposalDetails = ({
|
|||||||
{proposal.subProposals.map((p, i) => {
|
{proposal.subProposals.map((p, i) => {
|
||||||
if (!p?.terms) return null;
|
if (!p?.terms) return null;
|
||||||
return (
|
return (
|
||||||
<li key={i} className="flex gap-3">
|
<li
|
||||||
<span className={getIndicatorStyle(i + 1)}>{i + 1}</span>
|
key={i}
|
||||||
|
className="grid grid-cols-[40px_minmax(0,1fr)] grid-rows-1 gap-3 items-center"
|
||||||
|
>
|
||||||
|
<Indicator indicator={i + 1} />
|
||||||
<span>
|
<span>
|
||||||
<div>{renderDetails(p.terms)}</div>
|
<div>{renderDetails(p.terms)}</div>
|
||||||
<SubProposalStateText
|
<SubProposalStateText
|
||||||
|
|||||||
@@ -3,16 +3,8 @@ import { useTranslation } from 'react-i18next';
|
|||||||
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||||
import { SubHeading } from '../../../../components/heading';
|
import { SubHeading } from '../../../../components/heading';
|
||||||
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
||||||
import {
|
|
||||||
type BatchProposalFieldsFragment,
|
|
||||||
type ProposalFieldsFragment,
|
|
||||||
} from '../../__generated__/Proposals';
|
|
||||||
|
|
||||||
export const ProposalJson = ({
|
export const ProposalJson = ({ proposal }: { proposal?: unknown }) => {
|
||||||
proposal,
|
|
||||||
}: {
|
|
||||||
proposal: ProposalFieldsFragment | BatchProposalFieldsFragment;
|
|
||||||
}) => {
|
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [showDetails, setShowDetails] = useState(false);
|
const [showDetails, setShowDetails] = useState(false);
|
||||||
|
|
||||||
@@ -26,7 +18,7 @@ export const ProposalJson = ({
|
|||||||
<SubHeading title={t('proposalJson')} />
|
<SubHeading title={t('proposalJson')} />
|
||||||
</CollapsibleToggle>
|
</CollapsibleToggle>
|
||||||
|
|
||||||
{showDetails && <SyntaxHighlighter data={proposal} />}
|
{showDetails && <SyntaxHighlighter size="smaller" data={proposal} />}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
+8
-3
@@ -5,6 +5,11 @@ import {
|
|||||||
} from './proposal-market-changes';
|
} from './proposal-market-changes';
|
||||||
import type { JsonValue } from '../../../../components/json-diff';
|
import type { JsonValue } from '../../../../components/json-diff';
|
||||||
|
|
||||||
|
jest.mock('../proposal/market-name.tsx', () => ({
|
||||||
|
...jest.requireActual('../proposal/market-name.tsx'),
|
||||||
|
MarketName: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
describe('applyImmutableKeysFromEarlierVersion', () => {
|
describe('applyImmutableKeysFromEarlierVersion', () => {
|
||||||
it('returns an empty object if any argument is not an object or null', () => {
|
it('returns an empty object if any argument is not an object or null', () => {
|
||||||
const earlierVersion: JsonValue = null;
|
const earlierVersion: JsonValue = null;
|
||||||
@@ -57,21 +62,21 @@ describe('applyImmutableKeysFromEarlierVersion', () => {
|
|||||||
describe('ProposalMarketChanges', () => {
|
describe('ProposalMarketChanges', () => {
|
||||||
it('renders correctly', () => {
|
it('renders correctly', () => {
|
||||||
const { getByTestId } = render(
|
const { getByTestId } = render(
|
||||||
<ProposalMarketChanges marketId="market-id" updatedProposal={{}} />
|
<ProposalMarketChanges marketId="market-id" updateProposalNode={null} />
|
||||||
);
|
);
|
||||||
expect(getByTestId('proposal-market-changes')).toBeInTheDocument();
|
expect(getByTestId('proposal-market-changes')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('JsonDiff is not visible when showChanges is false', () => {
|
it('JsonDiff is not visible when showChanges is false', () => {
|
||||||
const { queryByTestId } = render(
|
const { queryByTestId } = render(
|
||||||
<ProposalMarketChanges marketId="market-id" updatedProposal={{}} />
|
<ProposalMarketChanges marketId="market-id" updateProposalNode={null} />
|
||||||
);
|
);
|
||||||
expect(queryByTestId('json-diff')).not.toBeInTheDocument();
|
expect(queryByTestId('json-diff')).not.toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('JsonDiff is visible when showChanges is true', async () => {
|
it('JsonDiff is visible when showChanges is true', async () => {
|
||||||
const { getByTestId } = render(
|
const { getByTestId } = render(
|
||||||
<ProposalMarketChanges marketId="market-id" updatedProposal={{}} />
|
<ProposalMarketChanges marketId="market-id" updateProposalNode={null} />
|
||||||
);
|
);
|
||||||
fireEvent.click(getByTestId('proposal-market-changes-toggle'));
|
fireEvent.click(getByTestId('proposal-market-changes-toggle'));
|
||||||
expect(getByTestId('json-diff')).toBeInTheDocument();
|
expect(getByTestId('json-diff')).toBeInTheDocument();
|
||||||
|
|||||||
+92
-53
@@ -1,14 +1,24 @@
|
|||||||
import cloneDeep from 'lodash/cloneDeep';
|
import cloneDeep from 'lodash/cloneDeep';
|
||||||
import set from 'lodash/set';
|
import set from 'lodash/set';
|
||||||
import get from 'lodash/get';
|
import get from 'lodash/get';
|
||||||
import { JsonDiff } from '../../../../components/json-diff';
|
import compact from 'lodash/compact';
|
||||||
|
import orderBy from 'lodash/orderBy';
|
||||||
|
import { JsonDiff, type JsonValue } from '../../../../components/json-diff';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
||||||
import { SubHeading } from '../../../../components/heading';
|
import { SubHeading } from '../../../../components/heading';
|
||||||
import type { JsonValue } from '../../../../components/json-diff';
|
import {
|
||||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
useFetchProposal,
|
||||||
import { ENV } from '../../../../config';
|
useFetchProposals,
|
||||||
|
flatten,
|
||||||
|
isBatchProposalNode,
|
||||||
|
isSingleProposalNode,
|
||||||
|
type ProposalNode,
|
||||||
|
type SingleProposalData,
|
||||||
|
type SubProposalData,
|
||||||
|
} from '../proposal/proposal-utils';
|
||||||
|
import { MarketName } from '../proposal/market-name';
|
||||||
|
|
||||||
const immutableKeys = [
|
const immutableKeys = [
|
||||||
'decimalPlaces',
|
'decimalPlaces',
|
||||||
@@ -18,8 +28,8 @@ const immutableKeys = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const applyImmutableKeysFromEarlierVersion = (
|
export const applyImmutableKeysFromEarlierVersion = (
|
||||||
earlierVersion: JsonValue,
|
earlierVersion: unknown,
|
||||||
updatedVersion: JsonValue
|
updatedVersion: unknown
|
||||||
) => {
|
) => {
|
||||||
if (
|
if (
|
||||||
typeof earlierVersion !== 'object' ||
|
typeof earlierVersion !== 'object' ||
|
||||||
@@ -35,7 +45,8 @@ export const applyImmutableKeysFromEarlierVersion = (
|
|||||||
|
|
||||||
// Overwrite the immutable keys in the updatedVersionCopy with the earlier values
|
// Overwrite the immutable keys in the updatedVersionCopy with the earlier values
|
||||||
immutableKeys.forEach((key) => {
|
immutableKeys.forEach((key) => {
|
||||||
set(updatedVersionCopy, key, get(earlierVersion, key));
|
const earlier = get(earlierVersion, key);
|
||||||
|
if (earlier) set(updatedVersionCopy, key, earlier);
|
||||||
});
|
});
|
||||||
|
|
||||||
return updatedVersionCopy;
|
return updatedVersionCopy;
|
||||||
@@ -43,49 +54,84 @@ export const applyImmutableKeysFromEarlierVersion = (
|
|||||||
|
|
||||||
interface ProposalMarketChangesProps {
|
interface ProposalMarketChangesProps {
|
||||||
marketId: string;
|
marketId: string;
|
||||||
updatedProposal: JsonValue;
|
/** This are the changes from proposal */
|
||||||
|
updateProposalNode: ProposalNode | null;
|
||||||
|
indicator?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ProposalMarketChanges = ({
|
export const ProposalMarketChanges = ({
|
||||||
marketId,
|
marketId,
|
||||||
updatedProposal,
|
updateProposalNode,
|
||||||
|
indicator,
|
||||||
}: ProposalMarketChangesProps) => {
|
}: ProposalMarketChangesProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [showChanges, setShowChanges] = useState(false);
|
const [showChanges, setShowChanges] = useState(false);
|
||||||
|
|
||||||
const {
|
const { data: originalProposalData } = useFetchProposal({
|
||||||
state: { data },
|
proposalId: marketId,
|
||||||
} = useFetch(`${ENV.rest}governance?proposalId=${marketId}`, undefined, true);
|
});
|
||||||
|
|
||||||
const {
|
const { data: enactedProposalsData } = useFetchProposals({
|
||||||
state: { data: enactedProposalData },
|
proposalState: 'STATE_ENACTED',
|
||||||
} = useFetch(
|
proposalType: 'TYPE_UPDATE_MARKET',
|
||||||
`${ENV.rest}governances?proposalState=STATE_ENACTED&proposalType=TYPE_UPDATE_MARKET`,
|
});
|
||||||
undefined,
|
|
||||||
true
|
let updateProposal: SingleProposalData | SubProposalData | undefined;
|
||||||
|
if (isBatchProposalNode(updateProposalNode)) {
|
||||||
|
updateProposal = updateProposalNode.proposals.find(
|
||||||
|
(p, i) =>
|
||||||
|
p.terms.updateMarket?.marketId === marketId &&
|
||||||
|
(indicator != null ? i === indicator - 1 : true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (isSingleProposalNode(updateProposalNode)) {
|
||||||
|
updateProposal = updateProposalNode.proposal;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this should get the proposal before the current one
|
||||||
|
const enactedUpdateMarketProposals = orderBy(
|
||||||
|
compact(
|
||||||
|
flatten(enactedProposalsData).filter((enacted) => {
|
||||||
|
const related = enacted.terms.updateMarket?.marketId === marketId;
|
||||||
|
const notCurrent =
|
||||||
|
enacted.id !== updateProposal?.id ||
|
||||||
|
('batchId' in enacted && enacted.batchId !== updateProposal.id);
|
||||||
|
const beforeCurrent =
|
||||||
|
Number(enacted.terms.enactmentTimestamp) <
|
||||||
|
Number(updateProposal?.terms.enactmentTimestamp);
|
||||||
|
return related && notCurrent && beforeCurrent;
|
||||||
|
})
|
||||||
|
),
|
||||||
|
[(proposal) => Number(proposal.terms.enactmentTimestamp)],
|
||||||
|
'desc'
|
||||||
);
|
);
|
||||||
|
|
||||||
// @ts-ignore no types here :-/
|
const latestEnactedProposal =
|
||||||
const enacted = enactedProposalData?.connection?.edges
|
enactedUpdateMarketProposals.length > 0
|
||||||
.filter(
|
? enactedUpdateMarketProposals[0]
|
||||||
// @ts-ignore no type here
|
: undefined;
|
||||||
({ node }) => node?.proposal?.terms?.updateMarket?.marketId === marketId
|
|
||||||
)
|
|
||||||
// @ts-ignore no type here
|
|
||||||
.sort((a, b) => {
|
|
||||||
return (
|
|
||||||
new Date(a?.node?.terms?.enactmentTimestamp).getTime() -
|
|
||||||
new Date(b?.node?.terms?.enactmentTimestamp).getTime()
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const latestEnactedProposal = enacted?.length
|
let originalProposal;
|
||||||
? enacted[enacted.length - 1]
|
if (isBatchProposalNode(originalProposalData)) {
|
||||||
: undefined;
|
originalProposal = originalProposalData.proposals.find(
|
||||||
|
(proposal) => proposal.id === marketId && proposal.terms.newMarket != null
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (isSingleProposalNode(originalProposalData)) {
|
||||||
|
originalProposal = originalProposalData.proposal;
|
||||||
|
}
|
||||||
|
|
||||||
const originalProposal =
|
// LEFT SIDE: update market proposal enacted just before this one
|
||||||
// @ts-ignore no types with useFetch TODO: check this is good
|
// or original new market proposal
|
||||||
data?.data?.proposal?.terms?.newMarket?.changes;
|
const left =
|
||||||
|
latestEnactedProposal?.terms.updateMarket?.changes ||
|
||||||
|
originalProposal?.terms.newMarket?.changes;
|
||||||
|
|
||||||
|
// RIGHT SIDE: this update market proposal
|
||||||
|
const right = applyImmutableKeysFromEarlierVersion(
|
||||||
|
left,
|
||||||
|
updateProposal?.terms.updateMarket?.changes
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section data-testid="proposal-market-changes">
|
<section data-testid="proposal-market-changes">
|
||||||
@@ -94,25 +140,18 @@ export const ProposalMarketChanges = ({
|
|||||||
setToggleState={setShowChanges}
|
setToggleState={setShowChanges}
|
||||||
dataTestId={'proposal-market-changes-toggle'}
|
dataTestId={'proposal-market-changes-toggle'}
|
||||||
>
|
>
|
||||||
<SubHeading title={t('updatesToMarket')} />
|
<SubHeading
|
||||||
|
title={
|
||||||
|
<>
|
||||||
|
{t('UpdateToMarket')}: <MarketName marketId={marketId} truncate />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</CollapsibleToggle>
|
</CollapsibleToggle>
|
||||||
|
|
||||||
{showChanges && (
|
{showChanges && (
|
||||||
<div className="mb-6">
|
<div className="mb-6 bg-vega-cdark-900 p-2 rounded-lg">
|
||||||
<JsonDiff
|
<JsonDiff left={left as JsonValue} right={right as JsonValue} />
|
||||||
left={latestEnactedProposal || originalProposal}
|
|
||||||
right={
|
|
||||||
latestEnactedProposal
|
|
||||||
? applyImmutableKeysFromEarlierVersion(
|
|
||||||
latestEnactedProposal,
|
|
||||||
updatedProposal
|
|
||||||
)
|
|
||||||
: applyImmutableKeysFromEarlierVersion(
|
|
||||||
originalProposal,
|
|
||||||
updatedProposal
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
+5
@@ -2,6 +2,11 @@ import { fireEvent, render, screen } from '@testing-library/react';
|
|||||||
import { ProposalUpdateMarketState } from './proposal-update-market-state';
|
import { ProposalUpdateMarketState } from './proposal-update-market-state';
|
||||||
import { MarketUpdateType } from '@vegaprotocol/types';
|
import { MarketUpdateType } from '@vegaprotocol/types';
|
||||||
|
|
||||||
|
jest.mock('../proposal/market-name.tsx', () => ({
|
||||||
|
...jest.requireActual('../proposal/market-name.tsx'),
|
||||||
|
MarketName: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
describe('<ProposalUpdateMarketState />', () => {
|
describe('<ProposalUpdateMarketState />', () => {
|
||||||
const suspendProposal = {
|
const suspendProposal = {
|
||||||
__typename: 'UpdateMarketState' as const,
|
__typename: 'UpdateMarketState' as const,
|
||||||
|
|||||||
+16
-7
@@ -10,6 +10,7 @@ import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
|||||||
import { SubHeading } from '../../../../components/heading';
|
import { SubHeading } from '../../../../components/heading';
|
||||||
import { type UpdateMarketStatesFragment } from '../../__generated__/Proposals';
|
import { type UpdateMarketStatesFragment } from '../../__generated__/Proposals';
|
||||||
import { MarketUpdateTypeMapping } from '@vegaprotocol/types';
|
import { MarketUpdateTypeMapping } from '@vegaprotocol/types';
|
||||||
|
import { MarketName } from '../proposal/market-name';
|
||||||
|
|
||||||
interface ProposalUpdateMarketStateProps {
|
interface ProposalUpdateMarketStateProps {
|
||||||
change: UpdateMarketStatesFragment | null;
|
change: UpdateMarketStatesFragment | null;
|
||||||
@@ -20,16 +21,18 @@ export const ProposalUpdateMarketState = ({
|
|||||||
}: ProposalUpdateMarketStateProps) => {
|
}: ProposalUpdateMarketStateProps) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const [showDetails, setShowDetails] = useState(false);
|
const [showDetails, setShowDetails] = useState(false);
|
||||||
let market;
|
|
||||||
let isTerminate = false;
|
|
||||||
|
|
||||||
if (!change) {
|
if (!change || change.__typename !== 'UpdateMarketState') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (change.__typename === 'UpdateMarketState') {
|
const market = change?.market;
|
||||||
market = change?.market;
|
const isTerminate =
|
||||||
isTerminate = change?.updateType === 'MARKET_STATE_UPDATE_TYPE_TERMINATE';
|
change?.updateType === 'MARKET_STATE_UPDATE_TYPE_TERMINATE';
|
||||||
|
|
||||||
|
let toggleTitle = t(change.updateType);
|
||||||
|
if (toggleTitle.length === 0) {
|
||||||
|
toggleTitle = t('MarketDetails');
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -39,7 +42,13 @@ export const ProposalUpdateMarketState = ({
|
|||||||
setToggleState={setShowDetails}
|
setToggleState={setShowDetails}
|
||||||
dataTestId="proposal-market-data-toggle"
|
dataTestId="proposal-market-data-toggle"
|
||||||
>
|
>
|
||||||
<SubHeading title={t('MarketDetails')} />
|
<SubHeading
|
||||||
|
title={
|
||||||
|
<>
|
||||||
|
{toggleTitle}: <MarketName marketId={market?.id} />
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
/>
|
||||||
</CollapsibleToggle>
|
</CollapsibleToggle>
|
||||||
|
|
||||||
{showDetails && (
|
{showDetails && (
|
||||||
|
|||||||
@@ -16,18 +16,31 @@ const getColour = (indicator: number, max = COLOURS.length) => {
|
|||||||
|
|
||||||
export const getStyle = (indicator: number, max = COLOURS.length) =>
|
export const getStyle = (indicator: number, max = COLOURS.length) =>
|
||||||
classNames({
|
classNames({
|
||||||
'bg-vega-yellow-400': 'yellow' === getColour(indicator, max),
|
'bg-vega-yellow-400 before:bg-vega-yellow-400':
|
||||||
'bg-vega-green-400': 'green' === getColour(indicator, max),
|
'yellow' === getColour(indicator, max),
|
||||||
'bg-vega-blue-400': 'blue' === getColour(indicator, max),
|
'bg-vega-green-400 before:bg-vega-green-400':
|
||||||
'bg-vega-purple-400': 'purple' === getColour(indicator, max),
|
'green' === getColour(indicator, max),
|
||||||
'bg-vega-pink-400': 'pink' === getColour(indicator, max),
|
'bg-vega-blue-400 before:bg-vega-blue-400':
|
||||||
'bg-vega-orange-400': 'orange' === getColour(indicator, max),
|
'blue' === getColour(indicator, max),
|
||||||
'bg-vega-red-400': 'red' === getColour(indicator, max),
|
'bg-vega-purple-400 before:bg-vega-purple-400':
|
||||||
'bg-vega-clight-600': 'none' === getColour(indicator, max),
|
'purple' === getColour(indicator, max),
|
||||||
|
'bg-vega-pink-400 before:bg-vega-pink-400':
|
||||||
|
'pink' === getColour(indicator, max),
|
||||||
|
'bg-vega-orange-400 before:bg-vega-orange-400':
|
||||||
|
'orange' === getColour(indicator, max),
|
||||||
|
'bg-vega-red-400 before:bg-vega-red-400':
|
||||||
|
'red' === getColour(indicator, max),
|
||||||
|
'bg-vega-clight-600 before:bg-vega-clight-600':
|
||||||
|
'none' === getColour(indicator, max),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const getIndicatorStyle = (indicator: number) =>
|
export const getIndicatorStyle = (indicator: number) =>
|
||||||
classNames(
|
classNames(
|
||||||
'rounded-sm text-black inline-block px-1 py-1 font-alpha calt h-8',
|
'rounded-sm text-black inline-block px-1 py-1 font-alpha calt h-8 w-7 text-center',
|
||||||
getStyle(indicator)
|
'text-border-1',
|
||||||
|
getStyle(indicator),
|
||||||
|
// Comment below if you want to remove the "chevron"
|
||||||
|
'relative mr-[11px] z-1',
|
||||||
|
'before:absolute before:z-0 before:top-1 before:right-[-11px] before:rounded-sm',
|
||||||
|
"before:w-[22.62px] before:h-[22.62px] before:rotate-45 before:content-['']"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import { getIndicatorStyle } from './colours';
|
||||||
|
|
||||||
|
export const Indicator = ({ indicator }: { indicator: number }) => (
|
||||||
|
<div className={getIndicatorStyle(indicator)}>
|
||||||
|
<span className="absolute top-0 left-0 p-1 w-full text-center z-1">
|
||||||
|
{indicator}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
@@ -1,6 +1,13 @@
|
|||||||
import { useMarketInfoQuery } from '@vegaprotocol/markets';
|
import { useMarketInfoQuery } from '@vegaprotocol/markets';
|
||||||
|
import { truncateMiddle } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
export const MarketName = ({ marketId }: { marketId?: string }) => {
|
export const MarketName = ({
|
||||||
|
marketId,
|
||||||
|
truncate,
|
||||||
|
}: {
|
||||||
|
marketId?: string;
|
||||||
|
truncate?: boolean;
|
||||||
|
}) => {
|
||||||
const { data } = useMarketInfoQuery({
|
const { data } = useMarketInfoQuery({
|
||||||
variables: {
|
variables: {
|
||||||
marketId: marketId || '',
|
marketId: marketId || '',
|
||||||
@@ -8,7 +15,7 @@ export const MarketName = ({ marketId }: { marketId?: string }) => {
|
|||||||
skip: !marketId,
|
skip: !marketId,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
const id = truncate ? truncateMiddle(marketId || '') : marketId;
|
||||||
<span>{data?.market?.tradableInstrument.instrument.code || marketId}</span>
|
|
||||||
);
|
return <span>{data?.market?.tradableInstrument.instrument.code || id}</span>;
|
||||||
};
|
};
|
||||||
|
|||||||
+33
-25
@@ -1,3 +1,4 @@
|
|||||||
|
import { Trans, useTranslation } from 'react-i18next';
|
||||||
import { type ProposalTermsFieldsFragment } from '../../__generated__/Proposals';
|
import { type ProposalTermsFieldsFragment } from '../../__generated__/Proposals';
|
||||||
import { type Proposal, type BatchProposal } from '../../types';
|
import { type Proposal, type BatchProposal } from '../../types';
|
||||||
import { ListAsset } from '../list-asset';
|
import { ListAsset } from '../list-asset';
|
||||||
@@ -12,7 +13,10 @@ import {
|
|||||||
import { ProposalUpdateBenefitTiers } from '../proposal-update-benefit-tiers';
|
import { ProposalUpdateBenefitTiers } from '../proposal-update-benefit-tiers';
|
||||||
import { ProposalUpdateMarketState } from '../proposal-update-market-state';
|
import { ProposalUpdateMarketState } from '../proposal-update-market-state';
|
||||||
import { ProposalVolumeDiscountProgramDetails } from '../proposal-volume-discount-program-details';
|
import { ProposalVolumeDiscountProgramDetails } from '../proposal-volume-discount-program-details';
|
||||||
import { getIndicatorStyle } from './colours';
|
import { type ProposalNode } from './proposal-utils';
|
||||||
|
import { Lozenge } from '@vegaprotocol/ui-toolkit';
|
||||||
|
import { Indicator } from './indicator';
|
||||||
|
import { SubHeading } from '../../../../components/heading';
|
||||||
|
|
||||||
export const ProposalChangeDetails = ({
|
export const ProposalChangeDetails = ({
|
||||||
proposal,
|
proposal,
|
||||||
@@ -22,10 +26,10 @@ export const ProposalChangeDetails = ({
|
|||||||
}: {
|
}: {
|
||||||
proposal: Proposal | BatchProposal;
|
proposal: Proposal | BatchProposal;
|
||||||
terms: ProposalTermsFieldsFragment;
|
terms: ProposalTermsFieldsFragment;
|
||||||
// eslint-disable-next-line
|
restData: ProposalNode | null;
|
||||||
restData: any;
|
|
||||||
indicator?: number;
|
indicator?: number;
|
||||||
}) => {
|
}) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
let details = null;
|
let details = null;
|
||||||
|
|
||||||
switch (terms.change.__typename) {
|
switch (terms.change.__typename) {
|
||||||
@@ -63,30 +67,13 @@ export const ProposalChangeDetails = ({
|
|||||||
}
|
}
|
||||||
case 'UpdateMarket': {
|
case 'UpdateMarket': {
|
||||||
if (proposal.id) {
|
if (proposal.id) {
|
||||||
const marketId = terms.change.marketId;
|
|
||||||
const proposalData = restData?.data?.proposal;
|
|
||||||
let updatedProposal = null;
|
|
||||||
// single proposal
|
|
||||||
if ('terms' in proposalData) {
|
|
||||||
updatedProposal = proposalData?.terms?.updateMarket?.changes;
|
|
||||||
}
|
|
||||||
// batch proposal - need to fish for the actual changes
|
|
||||||
if (
|
|
||||||
'batchTerms' in proposalData &&
|
|
||||||
Array.isArray(proposalData.batchTerms?.changes)
|
|
||||||
) {
|
|
||||||
updatedProposal = proposalData?.batchTerms?.changes.find(
|
|
||||||
(ch: { updateMarket?: { marketId: string } }) =>
|
|
||||||
ch?.updateMarket?.marketId === marketId
|
|
||||||
)?.updateMarket?.changes;
|
|
||||||
}
|
|
||||||
|
|
||||||
details = (
|
details = (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
<ProposalMarketData proposalId={proposal.id} />
|
<ProposalMarketData proposalId={proposal.id} />
|
||||||
<ProposalMarketChanges
|
<ProposalMarketChanges
|
||||||
|
indicator={indicator}
|
||||||
marketId={terms.change.marketId}
|
marketId={terms.change.marketId}
|
||||||
updatedProposal={updatedProposal}
|
updateProposalNode={restData}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -125,6 +112,25 @@ export const ProposalChangeDetails = ({
|
|||||||
'rewards.activityStreak.benefitTiers'
|
'rewards.activityStreak.benefitTiers'
|
||||||
) {
|
) {
|
||||||
details = <ProposalUpdateBenefitTiers change={terms.change} />;
|
details = <ProposalUpdateBenefitTiers change={terms.change} />;
|
||||||
|
} else {
|
||||||
|
details = (
|
||||||
|
<div className="mb-4">
|
||||||
|
<SubHeading title={t(terms.change.__typename as string)} />
|
||||||
|
<span>
|
||||||
|
<Trans
|
||||||
|
i18nKey="Change <lozenge>{{key}}</lozenge> to <lozenge>{{value}}</lozenge>"
|
||||||
|
values={{
|
||||||
|
key: terms.change.networkParameter.key,
|
||||||
|
value: terms.change.networkParameter.value,
|
||||||
|
}}
|
||||||
|
components={{
|
||||||
|
// @ts-ignore children passed by i18next
|
||||||
|
lozenge: <Lozenge />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -137,10 +143,12 @@ export const ProposalChangeDetails = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (indicator != null) {
|
if (indicator != null && details != null) {
|
||||||
details = (
|
details = (
|
||||||
<div className="flex gap-3 mb-3">
|
<div className="grid grid-cols-[40px_minmax(0,1fr)] grid-rows-1 gap-3 mb-3">
|
||||||
<div className={getIndicatorStyle(indicator)}>{indicator}</div>
|
<div className="w-10">
|
||||||
|
<Indicator indicator={indicator} />
|
||||||
|
</div>
|
||||||
<div>{details}</div>
|
<div>{details}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,261 @@
|
|||||||
|
import compact from 'lodash/compact';
|
||||||
|
import { ENV } from '../../../../config';
|
||||||
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
|
type Maybe<T> = T | null | undefined;
|
||||||
|
|
||||||
|
type ProposalState =
|
||||||
|
| 'STATE_UNSPECIFIED'
|
||||||
|
| 'STATE_FAILED'
|
||||||
|
| 'STATE_OPEN'
|
||||||
|
| 'STATE_PASSED'
|
||||||
|
| 'STATE_REJECTED'
|
||||||
|
| 'STATE_DECLINED'
|
||||||
|
| 'STATE_ENACTED'
|
||||||
|
| 'STATE_WAITING_FOR_NODE_VOTE';
|
||||||
|
|
||||||
|
type ProposalType =
|
||||||
|
| 'TYPE_UNSPECIFIED'
|
||||||
|
| 'TYPE_ALL'
|
||||||
|
| 'TYPE_NEW_MARKET'
|
||||||
|
| 'TYPE_UPDATE_MARKET'
|
||||||
|
| 'TYPE_NETWORK_PARAMETERS'
|
||||||
|
| 'TYPE_NEW_ASSET'
|
||||||
|
| 'TYPE_NEW_FREE_FORM'
|
||||||
|
| 'TYPE_UPDATE_ASSET'
|
||||||
|
| 'TYPE_NEW_SPOT_MARKET'
|
||||||
|
| 'TYPE_UPDATE_SPOT_MARKET'
|
||||||
|
| 'TYPE_NEW_TRANSFER'
|
||||||
|
| 'TYPE_CANCEL_TRANSFER'
|
||||||
|
| 'TYPE_UPDATE_MARKET_STATE'
|
||||||
|
| 'TYPE_UPDATE_REFERRAL_PROGRAM'
|
||||||
|
| 'TYPE_UPDATE_VOLUME_DISCOUNT_PROGRAM';
|
||||||
|
|
||||||
|
type ProposalNodeType = 'TYPE_SINGLE_OR_UNSPECIFIED' | 'TYPE_BATCH';
|
||||||
|
|
||||||
|
type ProposalData = {
|
||||||
|
id: string;
|
||||||
|
rationale: {
|
||||||
|
description: string;
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
state: ProposalState;
|
||||||
|
timestamp: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type Terms = {
|
||||||
|
cancelTransfer?: { changes: unknown };
|
||||||
|
enactmentTimestamp: string;
|
||||||
|
newAsset?: { changes: unknown };
|
||||||
|
newFreeform: object;
|
||||||
|
newMarket?: { changes: unknown };
|
||||||
|
newSpotMarket?: { changes: unknown };
|
||||||
|
newTransfer?: { changes: unknown };
|
||||||
|
updateAsset?: { assetId: string; changes: unknown };
|
||||||
|
updateMarket?: { marketId: string; changes: unknown };
|
||||||
|
updateMarketState?: {
|
||||||
|
changes: {
|
||||||
|
marketId: string;
|
||||||
|
price: string;
|
||||||
|
updateType:
|
||||||
|
| 'MARKET_STATE_UPDATE_TYPE_UNSPECIFIED'
|
||||||
|
| 'MARKET_STATE_UPDATE_TYPE_TERMINATE'
|
||||||
|
| 'MARKET_STATE_UPDATE_TYPE_SUSPEND'
|
||||||
|
| 'MARKET_STATE_UPDATE_TYPE_RESUME';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
updateNetworkParameter?: { changes: unknown };
|
||||||
|
updateReferralProgram?: { changes: unknown };
|
||||||
|
updateSpotMarket?: { marketId: string; changes: unknown };
|
||||||
|
updateVolumeDiscountProgram?: { changes: unknown };
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SingleProposalData = ProposalData & {
|
||||||
|
terms: Terms & {
|
||||||
|
closingTimestamp: string;
|
||||||
|
validationTimestamp: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
type BatchProposalData = ProposalData & {
|
||||||
|
batchTerms: {
|
||||||
|
changes: Terms[];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SubProposalData = SingleProposalData & {
|
||||||
|
batchId: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ProposalNode = {
|
||||||
|
proposal: ProposalData;
|
||||||
|
proposalType: ProposalNodeType;
|
||||||
|
proposals: SubProposalData[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type SingleProposalNode = ProposalNode & {
|
||||||
|
proposal: SingleProposalData;
|
||||||
|
proposalType: 'TYPE_SINGLE_OR_UNSPECIFIED';
|
||||||
|
proposals: [];
|
||||||
|
};
|
||||||
|
|
||||||
|
type BatchProposalNode = ProposalNode & {
|
||||||
|
proposal: BatchProposalData;
|
||||||
|
proposalType: 'TYPE_BATCH';
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isProposalNode = (node: unknown): node is ProposalNode =>
|
||||||
|
Boolean(
|
||||||
|
typeof node === 'object' &&
|
||||||
|
node &&
|
||||||
|
'proposal' in node &&
|
||||||
|
typeof node.proposal === 'object' &&
|
||||||
|
node?.proposal &&
|
||||||
|
'id' in node.proposal &&
|
||||||
|
node?.proposal?.id
|
||||||
|
);
|
||||||
|
|
||||||
|
export const isSingleProposalNode = (
|
||||||
|
node: Maybe<ProposalNode>
|
||||||
|
): node is SingleProposalNode =>
|
||||||
|
Boolean(
|
||||||
|
node &&
|
||||||
|
node?.proposalType === 'TYPE_SINGLE_OR_UNSPECIFIED' &&
|
||||||
|
node?.proposal
|
||||||
|
);
|
||||||
|
|
||||||
|
export const isBatchProposalNode = (
|
||||||
|
node: Maybe<ProposalNode>
|
||||||
|
): node is BatchProposalNode =>
|
||||||
|
Boolean(
|
||||||
|
node &&
|
||||||
|
node?.proposalType === 'TYPE_BATCH' &&
|
||||||
|
node?.proposal &&
|
||||||
|
'batchTerms' in node.proposal &&
|
||||||
|
node?.proposals?.length > 0
|
||||||
|
);
|
||||||
|
|
||||||
|
// this includes also batch proposals with `updateMarket`s 👍
|
||||||
|
const PROPOSALS_ENDPOINT = `${ENV.rest}governances?proposalState=:proposalState&proposalType=:proposalType`;
|
||||||
|
|
||||||
|
// this can be queried also by sub proposal id as `proposalId` and it will
|
||||||
|
// return full batch proposal data with all of its sub proposals including
|
||||||
|
// the requested one inside `proposals` array.
|
||||||
|
const PROPOSAL_ENDPOINT = `${ENV.rest}governance?proposalId=:proposalId`;
|
||||||
|
|
||||||
|
export const getProposals = async ({
|
||||||
|
proposalState,
|
||||||
|
proposalType,
|
||||||
|
}: {
|
||||||
|
proposalState: ProposalState;
|
||||||
|
proposalType: ProposalType;
|
||||||
|
}) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
PROPOSALS_ENDPOINT.replace(':proposalState', proposalState).replace(
|
||||||
|
':proposalType',
|
||||||
|
proposalType
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json();
|
||||||
|
if (
|
||||||
|
data &&
|
||||||
|
'connection' in data &&
|
||||||
|
data.connection &&
|
||||||
|
'edges' in data.connection &&
|
||||||
|
data.connection.edges?.length > 0
|
||||||
|
) {
|
||||||
|
const nodes = compact(
|
||||||
|
data.connection.edges.map((e: { node?: object }) => e?.node)
|
||||||
|
).filter(isProposalNode);
|
||||||
|
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// NOOP - ignore errors
|
||||||
|
}
|
||||||
|
|
||||||
|
return [];
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getProposal = async ({ proposalId }: { proposalId: string }) => {
|
||||||
|
try {
|
||||||
|
const response = await fetch(
|
||||||
|
PROPOSAL_ENDPOINT.replace(':proposalId', proposalId)
|
||||||
|
);
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json();
|
||||||
|
if (data && 'data' in data && isProposalNode(data.data)) {
|
||||||
|
return data.data as ProposalNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
// NOOP - ignore errors
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useFetchProposal = ({ proposalId }: { proposalId?: string }) => {
|
||||||
|
const [data, setData] = useState<ProposalNode | null>(null);
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const cb = async () => {
|
||||||
|
if (!proposalId) return;
|
||||||
|
|
||||||
|
setLoading(true);
|
||||||
|
const data = await getProposal({ proposalId });
|
||||||
|
setLoading(false);
|
||||||
|
if (data) {
|
||||||
|
setData(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
cb();
|
||||||
|
}, [proposalId]);
|
||||||
|
|
||||||
|
return { data, loading };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useFetchProposals = ({
|
||||||
|
proposalState,
|
||||||
|
proposalType,
|
||||||
|
}: {
|
||||||
|
proposalState: ProposalState;
|
||||||
|
proposalType: ProposalType;
|
||||||
|
}) => {
|
||||||
|
const [data, setData] = useState<ProposalNode[]>([]);
|
||||||
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const cb = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
const data = await getProposals({ proposalState, proposalType });
|
||||||
|
setLoading(false);
|
||||||
|
if (data) {
|
||||||
|
setData(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
cb();
|
||||||
|
}, [proposalState, proposalType]);
|
||||||
|
|
||||||
|
return { data, loading };
|
||||||
|
};
|
||||||
|
|
||||||
|
export const flatten = (
|
||||||
|
nodes: ProposalNode[]
|
||||||
|
): (SingleProposalData | SubProposalData)[] => {
|
||||||
|
const flattenNodes = [];
|
||||||
|
for (const node of nodes) {
|
||||||
|
if (isSingleProposalNode(node)) {
|
||||||
|
flattenNodes.push(node.proposal);
|
||||||
|
}
|
||||||
|
if (isBatchProposalNode(node)) {
|
||||||
|
for (const sub of node.proposals) {
|
||||||
|
flattenNodes.push(sub);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return flattenNodes;
|
||||||
|
};
|
||||||
@@ -61,7 +61,7 @@ const renderComponent = (proposal: IProposal) => {
|
|||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<MockedProvider>
|
<MockedProvider>
|
||||||
<VegaWalletProvider config={vegaWalletConfig}>
|
<VegaWalletProvider config={vegaWalletConfig}>
|
||||||
<Proposal restData={{}} proposal={proposal} />
|
<Proposal restData={null} proposal={proposal} />
|
||||||
</VegaWalletProvider>
|
</VegaWalletProvider>
|
||||||
</MockedProvider>
|
</MockedProvider>
|
||||||
</MemoryRouter>
|
</MemoryRouter>
|
||||||
|
|||||||
@@ -8,15 +8,17 @@ import { ProposalJson } from '../proposal-json';
|
|||||||
import { UserVote } from '../vote-details';
|
import { UserVote } from '../vote-details';
|
||||||
import Routes from '../../../routes';
|
import Routes from '../../../routes';
|
||||||
import { ProposalState } from '@vegaprotocol/types';
|
import { ProposalState } from '@vegaprotocol/types';
|
||||||
|
import { type ProposalNode } from './proposal-utils';
|
||||||
import { useVoteSubmit } from '@vegaprotocol/proposals';
|
import { useVoteSubmit } from '@vegaprotocol/proposals';
|
||||||
import { useUserVote } from '../vote-details/use-user-vote';
|
import { useUserVote } from '../vote-details/use-user-vote';
|
||||||
import { type Proposal as IProposal, type BatchProposal } from '../../types';
|
import { type Proposal as IProposal, type BatchProposal } from '../../types';
|
||||||
import { ProposalChangeDetails } from './proposal-change-details';
|
import { ProposalChangeDetails } from './proposal-change-details';
|
||||||
|
import { type JsonValue } from 'type-fest';
|
||||||
|
|
||||||
export interface ProposalProps {
|
export interface ProposalProps {
|
||||||
proposal: IProposal | BatchProposal;
|
proposal: IProposal | BatchProposal;
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
restData: any;
|
restData: ProposalNode | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Proposal = ({ proposal, restData }: ProposalProps) => {
|
export const Proposal = ({ proposal, restData }: ProposalProps) => {
|
||||||
@@ -58,7 +60,7 @@ export const Proposal = ({ proposal, restData }: ProposalProps) => {
|
|||||||
<ProposalDescription description={proposal.rationale.description} />
|
<ProposalDescription description={proposal.rationale.description} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-4">
|
<div className="mb-4 flex flex-col gap-0">
|
||||||
{proposal.__typename === 'Proposal' ? (
|
{proposal.__typename === 'Proposal' ? (
|
||||||
<ProposalChangeDetails
|
<ProposalChangeDetails
|
||||||
proposal={proposal}
|
proposal={proposal}
|
||||||
@@ -95,7 +97,7 @@ export const Proposal = ({ proposal, restData }: ProposalProps) => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mb-6">
|
<div className="mb-6">
|
||||||
<ProposalJson proposal={restData?.data?.proposal} />
|
<ProposalJson proposal={restData?.proposal as unknown as JsonValue} />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ export const ProposalsList = ({
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<section className="-mx-4 p-4 mb-8 bg-vega-dark-100">
|
<section className="-mx-4 p-4 mb-8 bg-vega-cdark-900 rounded-l-sm">
|
||||||
<SubHeading title={t('openProposals')} />
|
<SubHeading title={t('openProposals')} />
|
||||||
|
|
||||||
{sortedProposals.open.length > 0 ||
|
{sortedProposals.open.length > 0 ||
|
||||||
|
|||||||
+156
-124
@@ -15,7 +15,8 @@ import {
|
|||||||
type VoteFieldsFragment,
|
type VoteFieldsFragment,
|
||||||
} from '../../__generated__/Proposals';
|
} from '../../__generated__/Proposals';
|
||||||
import { useBatchVoteInformation } from '../../hooks/use-vote-information';
|
import { useBatchVoteInformation } from '../../hooks/use-vote-information';
|
||||||
import { getIndicatorStyle } from '../proposal/colours';
|
import { MarketName } from '../proposal/market-name';
|
||||||
|
import { Indicator } from '../proposal/indicator';
|
||||||
|
|
||||||
export const CompactVotes = ({ number }: { number: BigNumber }) => (
|
export const CompactVotes = ({ number }: { number: BigNumber }) => (
|
||||||
<CompactNumber
|
<CompactNumber
|
||||||
@@ -40,8 +41,9 @@ const VoteProgress = ({
|
|||||||
children,
|
children,
|
||||||
}: VoteProgressProps) => {
|
}: VoteProgressProps) => {
|
||||||
const containerClasses = classNames(
|
const containerClasses = classNames(
|
||||||
'relative h-10 rounded-md border border-vega-dark-300 overflow-hidden',
|
'relative h-2 rounded-md overflow-hidden',
|
||||||
colourfulBg ? 'bg-vega-pink' : 'bg-vega-dark-400'
|
// 'border border-vega-dark-300',
|
||||||
|
colourfulBg ? 'bg-vega-red' : 'bg-vega-dark-200'
|
||||||
);
|
);
|
||||||
|
|
||||||
const progressClasses = classNames(
|
const progressClasses = classNames(
|
||||||
@@ -50,17 +52,19 @@ const VoteProgress = ({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const textClasses = classNames(
|
const textClasses = classNames(
|
||||||
'absolute top-0 left-0 w-full h-full flex items-center justify-start px-3 text-black'
|
'w-full flex items-center justify-start text-white text-sm pb-1'
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={containerClasses}>
|
<div>
|
||||||
<div
|
|
||||||
className={progressClasses}
|
|
||||||
style={{ width: `${percentageFor}%` }}
|
|
||||||
data-testid={testId}
|
|
||||||
/>
|
|
||||||
<div className={textClasses}>{children}</div>
|
<div className={textClasses}>{children}</div>
|
||||||
|
<div className={containerClasses}>
|
||||||
|
<div
|
||||||
|
className={progressClasses}
|
||||||
|
style={{ width: `${percentageFor}%` }}
|
||||||
|
data-testid={testId}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -79,14 +83,22 @@ const Status = ({ reached, threshold, text, testId }: StatusProps) => {
|
|||||||
<div data-testid={testId}>
|
<div data-testid={testId}>
|
||||||
{reached ? (
|
{reached ? (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<VegaIcon name={VegaIconNames.TICK} size={20} />
|
<VegaIcon
|
||||||
|
name={VegaIconNames.TICK}
|
||||||
|
className="text-vega-green"
|
||||||
|
size={20}
|
||||||
|
/>
|
||||||
<span>
|
<span>
|
||||||
{threshold.toString()}% {text} {t('met')}
|
{threshold.toString()}% {text} {t('met')}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<VegaIcon name={VegaIconNames.CROSS} size={20} />
|
<VegaIcon
|
||||||
|
name={VegaIconNames.CROSS}
|
||||||
|
className="text-vega-red"
|
||||||
|
size={20}
|
||||||
|
/>
|
||||||
<span>
|
<span>
|
||||||
{threshold.toString()}% {text} {t('not met')}
|
{threshold.toString()}% {text} {t('not met')}
|
||||||
</span>
|
</span>
|
||||||
@@ -152,7 +164,7 @@ const VoteBreakdownBatch = ({ proposal }: { proposal: BatchProposal }) => {
|
|||||||
<p className="flex gap-2 m-0 items-center">
|
<p className="flex gap-2 m-0 items-center">
|
||||||
<VegaIcon
|
<VegaIcon
|
||||||
name={VegaIconNames.CROSS}
|
name={VegaIconNames.CROSS}
|
||||||
className="text-vega-pink"
|
className="text-vega-red"
|
||||||
size={20}
|
size={20}
|
||||||
/>
|
/>
|
||||||
{t(
|
{t(
|
||||||
@@ -215,7 +227,7 @@ const VoteBreakdownBatch = ({ proposal }: { proposal: BatchProposal }) => {
|
|||||||
<p className="flex gap-2 m-0 items-center">
|
<p className="flex gap-2 m-0 items-center">
|
||||||
<VegaIcon
|
<VegaIcon
|
||||||
name={VegaIconNames.CROSS}
|
name={VegaIconNames.CROSS}
|
||||||
className="text-vega-pink"
|
className="text-vega-red"
|
||||||
size={20}
|
size={20}
|
||||||
/>
|
/>
|
||||||
{t('Proposal failed: {{count}} of {{total}} proposals passed', {
|
{t('Proposal failed: {{count}} of {{total}} proposals passed', {
|
||||||
@@ -237,6 +249,7 @@ const VoteBreakdownBatch = ({ proposal }: { proposal: BatchProposal }) => {
|
|||||||
if (!p?.terms) return null;
|
if (!p?.terms) return null;
|
||||||
return (
|
return (
|
||||||
<VoteBreakdownBatchSubProposal
|
<VoteBreakdownBatchSubProposal
|
||||||
|
indicator={i + 1}
|
||||||
key={i}
|
key={i}
|
||||||
proposal={proposal}
|
proposal={proposal}
|
||||||
votes={proposal.votes}
|
votes={proposal.votes}
|
||||||
@@ -273,21 +286,37 @@ const VoteBreakdownBatchSubProposal = ({
|
|||||||
const isProposalOpen = proposal?.state === ProposalState.STATE_OPEN;
|
const isProposalOpen = proposal?.state === ProposalState.STATE_OPEN;
|
||||||
const isUpdateMarket = terms?.change?.__typename === 'UpdateMarket';
|
const isUpdateMarket = terms?.change?.__typename === 'UpdateMarket';
|
||||||
|
|
||||||
const indicatorElement = indicator && (
|
let marketId = undefined;
|
||||||
<span className={getIndicatorStyle(indicator)}>{indicator}</span>
|
if (terms?.change?.__typename === 'UpdateMarket') {
|
||||||
);
|
marketId = terms.change.marketId;
|
||||||
|
}
|
||||||
|
if (terms?.change?.__typename === 'UpdateMarketState') {
|
||||||
|
marketId = terms.change.market.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const marketName = marketId ? (
|
||||||
|
<>
|
||||||
|
: <MarketName marketId={marketId} />
|
||||||
|
</>
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
const indicatorElement = indicator && <Indicator indicator={indicator} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="mb-6">
|
||||||
<div className="flex items-baseline gap-3">
|
<div className="flex items-center gap-3 mb-3">
|
||||||
{indicatorElement}
|
{indicatorElement}
|
||||||
<h4>{t(terms.change.__typename)}</h4>
|
<h4>
|
||||||
|
{t(terms.change.__typename)} {marketName}
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
<div className="rounded-sm bg-vega-dark-100 p-3">
|
||||||
|
<VoteBreakDownUI
|
||||||
|
voteInfo={voteInfo}
|
||||||
|
isProposalOpen={isProposalOpen}
|
||||||
|
isUpdateMarket={isUpdateMarket}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<VoteBreakDownUI
|
|
||||||
voteInfo={voteInfo}
|
|
||||||
isProposalOpen={isProposalOpen}
|
|
||||||
isUpdateMarket={isUpdateMarket}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -302,11 +331,13 @@ const VoteBreakdownNormal = ({ proposal }: { proposal: Proposal }) => {
|
|||||||
const isUpdateMarket = proposal?.terms?.change?.__typename === 'UpdateMarket';
|
const isUpdateMarket = proposal?.terms?.change?.__typename === 'UpdateMarket';
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<VoteBreakDownUI
|
<div className="mb-6">
|
||||||
voteInfo={voteInfo}
|
<VoteBreakDownUI
|
||||||
isProposalOpen={isProposalOpen}
|
voteInfo={voteInfo}
|
||||||
isUpdateMarket={isUpdateMarket}
|
isProposalOpen={isProposalOpen}
|
||||||
/>
|
isUpdateMarket={isUpdateMarket}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -370,13 +401,13 @@ const VoteBreakDownUI = ({
|
|||||||
'flex justify-between flex-wrap gap-6'
|
'flex justify-between flex-wrap gap-6'
|
||||||
);
|
);
|
||||||
const sectionClasses = classNames('min-w-[300px] flex-1 flex-grow');
|
const sectionClasses = classNames('min-w-[300px] flex-1 flex-grow');
|
||||||
const headingClasses = classNames('mb-2 text-vega-dark-400');
|
const headingClasses = classNames('mb-2 text-sm text-white font-bold');
|
||||||
const progressDetailsClasses = classNames(
|
const progressDetailsClasses = classNames(
|
||||||
'flex justify-between flex-wrap mt-2 text-sm'
|
'flex justify-between flex-wrap mt-2 text-sm'
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-6">
|
<div>
|
||||||
{isProposalOpen && (
|
{isProposalOpen && (
|
||||||
<div
|
<div
|
||||||
data-testid="vote-status"
|
data-testid="vote-status"
|
||||||
@@ -393,7 +424,7 @@ const VoteBreakDownUI = ({
|
|||||||
<VegaIcon
|
<VegaIcon
|
||||||
name={VegaIconNames.CROSS}
|
name={VegaIconNames.CROSS}
|
||||||
size={20}
|
size={20}
|
||||||
className="text-vega-pink"
|
className="text-vega-red"
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</span>
|
</span>
|
||||||
@@ -409,103 +440,13 @@ const VoteBreakDownUI = ({
|
|||||||
<p className="m-0">
|
<p className="m-0">
|
||||||
<Trans
|
<Trans
|
||||||
i18nKey={'Currently expected to <0>fail</0>'}
|
i18nKey={'Currently expected to <0>fail</0>'}
|
||||||
components={[<span className="text-vega-pink" />]}
|
components={[<span className="text-vega-red" />]}
|
||||||
/>
|
/>
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{isUpdateMarket && (
|
|
||||||
<div className="mb-4">
|
|
||||||
<h3 className={headingClasses}>{t('liquidityProviderVote')}</h3>
|
|
||||||
<div className={sectionWrapperClasses}>
|
|
||||||
<section
|
|
||||||
className={sectionClasses}
|
|
||||||
data-testid="lp-majority-breakdown"
|
|
||||||
>
|
|
||||||
<VoteProgress
|
|
||||||
percentageFor={lpVoteWeight}
|
|
||||||
colourfulBg={true}
|
|
||||||
testId="lp-majority-progress"
|
|
||||||
>
|
|
||||||
<Status
|
|
||||||
reached={majorityLPMet}
|
|
||||||
threshold={requiredMajorityLPPercentage}
|
|
||||||
text={t('majorityThreshold')}
|
|
||||||
testId={
|
|
||||||
majorityLPMet ? 'lp-majority-met' : 'lp-majority-not-met'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</VoteProgress>
|
|
||||||
|
|
||||||
<div className={progressDetailsClasses}>
|
|
||||||
<div className="flex items-center gap-1">
|
|
||||||
<span>{t('liquidityProviderVotesFor')}:</span>
|
|
||||||
<Tooltip
|
|
||||||
description={
|
|
||||||
<span>{lpVoteWeight.toFixed(defaultDP)}%</span>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<button>{lpVoteWeight.toFixed(1)}%</button>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex items-center gap-1">
|
|
||||||
<span>{t('liquidityProviderVotesAgainst')}:</span>
|
|
||||||
<span>
|
|
||||||
<Tooltip
|
|
||||||
description={
|
|
||||||
<span>{noLPPercentage.toFixed(defaultDP)}%</span>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<button>{noLPPercentage.toFixed(1)}%</button>
|
|
||||||
</Tooltip>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section
|
|
||||||
className={sectionClasses}
|
|
||||||
data-testid="lp-participation-breakdown"
|
|
||||||
>
|
|
||||||
<VoteProgress
|
|
||||||
percentageFor={
|
|
||||||
lpParticipationThresholdProgress || new BigNumber(0)
|
|
||||||
}
|
|
||||||
testId="lp-participation-progress"
|
|
||||||
>
|
|
||||||
<Status
|
|
||||||
reached={participationLPMet}
|
|
||||||
threshold={requiredParticipationLP || new BigNumber(1)}
|
|
||||||
text={t('participationThreshold')}
|
|
||||||
testId={
|
|
||||||
participationLPMet
|
|
||||||
? 'lp-participation-met'
|
|
||||||
: 'lp-participation-not-met'
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</VoteProgress>
|
|
||||||
|
|
||||||
<div className="flex mt-2 text-sm">
|
|
||||||
<div className="flex items-center gap-1">
|
|
||||||
<span>{t('totalLiquidityProviderTokensVoted')}:</span>
|
|
||||||
<Tooltip
|
|
||||||
description={formatNumber(
|
|
||||||
totalEquityLikeShareWeight,
|
|
||||||
defaultDP
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<span>{totalEquityLikeShareWeight.toFixed(1)}%</span>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{isUpdateMarket && <h3 className={headingClasses}>{t('tokenVote')}</h3>}
|
{isUpdateMarket && <h3 className={headingClasses}>{t('tokenVote')}</h3>}
|
||||||
<div className={sectionWrapperClasses}>
|
<div className={sectionWrapperClasses}>
|
||||||
<section
|
<section
|
||||||
@@ -605,6 +546,97 @@ const VoteBreakDownUI = ({
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/** Liquidity provider vote */}
|
||||||
|
{isUpdateMarket && (
|
||||||
|
<div className="mt-3">
|
||||||
|
<h3 className={headingClasses}>{t('liquidityProviderVote')}</h3>
|
||||||
|
<div className={sectionWrapperClasses}>
|
||||||
|
<section
|
||||||
|
className={sectionClasses}
|
||||||
|
data-testid="lp-majority-breakdown"
|
||||||
|
>
|
||||||
|
<VoteProgress
|
||||||
|
percentageFor={lpVoteWeight}
|
||||||
|
colourfulBg={true}
|
||||||
|
testId="lp-majority-progress"
|
||||||
|
>
|
||||||
|
<Status
|
||||||
|
reached={majorityLPMet}
|
||||||
|
threshold={requiredMajorityLPPercentage}
|
||||||
|
text={t('majorityThreshold')}
|
||||||
|
testId={
|
||||||
|
majorityLPMet ? 'lp-majority-met' : 'lp-majority-not-met'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</VoteProgress>
|
||||||
|
|
||||||
|
<div className={progressDetailsClasses}>
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<span>{t('liquidityProviderVotesFor')}:</span>
|
||||||
|
<Tooltip
|
||||||
|
description={
|
||||||
|
<span>{lpVoteWeight.toFixed(defaultDP)}%</span>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<button>{lpVoteWeight.toFixed(1)}%</button>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<span>{t('liquidityProviderVotesAgainst')}:</span>
|
||||||
|
<span>
|
||||||
|
<Tooltip
|
||||||
|
description={
|
||||||
|
<span>{noLPPercentage.toFixed(defaultDP)}%</span>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<button>{noLPPercentage.toFixed(1)}%</button>
|
||||||
|
</Tooltip>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section
|
||||||
|
className={sectionClasses}
|
||||||
|
data-testid="lp-participation-breakdown"
|
||||||
|
>
|
||||||
|
<VoteProgress
|
||||||
|
percentageFor={
|
||||||
|
lpParticipationThresholdProgress || new BigNumber(0)
|
||||||
|
}
|
||||||
|
testId="lp-participation-progress"
|
||||||
|
>
|
||||||
|
<Status
|
||||||
|
reached={participationLPMet}
|
||||||
|
threshold={requiredParticipationLP || new BigNumber(1)}
|
||||||
|
text={t('participationThreshold')}
|
||||||
|
testId={
|
||||||
|
participationLPMet
|
||||||
|
? 'lp-participation-met'
|
||||||
|
: 'lp-participation-not-met'
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</VoteProgress>
|
||||||
|
|
||||||
|
<div className="flex mt-2 text-sm">
|
||||||
|
<div className="flex items-center gap-1">
|
||||||
|
<span>{t('totalLiquidityProviderTokensVoted')}:</span>
|
||||||
|
<Tooltip
|
||||||
|
description={formatNumber(
|
||||||
|
totalEquityLikeShareWeight,
|
||||||
|
defaultDP
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<span>{totalEquityLikeShareWeight.toFixed(1)}%</span>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,17 +1,16 @@
|
|||||||
import { useParams } from 'react-router-dom';
|
import { useParams } from 'react-router-dom';
|
||||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
|
||||||
import { ENV } from '../../../config';
|
|
||||||
import { Proposal } from '../components/proposal';
|
import { Proposal } from '../components/proposal';
|
||||||
import { ProposalNotFound } from '../components/proposal-not-found';
|
import { ProposalNotFound } from '../components/proposal-not-found';
|
||||||
import { useProposalQuery } from '../__generated__/Proposals';
|
import { useProposalQuery } from '../__generated__/Proposals';
|
||||||
|
import { useFetchProposal } from '../components/proposal/proposal-utils';
|
||||||
|
|
||||||
export const ProposalContainer = () => {
|
export const ProposalContainer = () => {
|
||||||
const params = useParams<{ proposalId: string }>();
|
const params = useParams<{ proposalId: string }>();
|
||||||
|
|
||||||
const {
|
const { data: restData, loading: restLoading } = useFetchProposal({
|
||||||
state: { data: restData, loading: restLoading, error: restError },
|
proposalId: params.proposalId,
|
||||||
} = useFetch(`${ENV.rest}governance?proposalId=${params.proposalId}`);
|
});
|
||||||
|
|
||||||
const { data, loading, error } = useProposalQuery({
|
const { data, loading, error } = useProposalQuery({
|
||||||
fetchPolicy: 'network-only',
|
fetchPolicy: 'network-only',
|
||||||
@@ -26,7 +25,7 @@ export const ProposalContainer = () => {
|
|||||||
return (
|
return (
|
||||||
<AsyncRenderer
|
<AsyncRenderer
|
||||||
loading={Boolean(loading || restLoading)}
|
loading={Boolean(loading || restLoading)}
|
||||||
error={error || restError}
|
error={error}
|
||||||
data={{
|
data={{
|
||||||
...data,
|
...data,
|
||||||
...(restData ? { restData } : {}),
|
...(restData ? { restData } : {}),
|
||||||
|
|||||||
+8
-45
@@ -1,10 +1,9 @@
|
|||||||
import { useMemo, useEffect, useState, useCallback, useRef } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { AsyncRenderer, Pagination } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer, Pagination } from '@vegaprotocol/ui-toolkit';
|
||||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||||
import type { EpochFieldsFragment } from '../home/__generated__/Rewards';
|
import type { EpochFieldsFragment } from '../home/__generated__/Rewards';
|
||||||
import { useRewardsQuery } from '../home/__generated__/Rewards';
|
import { useRewardsQuery } from '../home/__generated__/Rewards';
|
||||||
import { ENV } from '../../../config';
|
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
import { EpochIndividualRewardsTable } from './epoch-individual-rewards-table';
|
import { EpochIndividualRewardsTable } from './epoch-individual-rewards-table';
|
||||||
import { generateEpochIndividualRewardsList } from './generate-epoch-individual-rewards-list';
|
import { generateEpochIndividualRewardsList } from './generate-epoch-individual-rewards-list';
|
||||||
@@ -27,22 +26,16 @@ export const EpochIndividualRewards = ({
|
|||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { pubKey } = useVegaWallet();
|
const { pubKey } = useVegaWallet();
|
||||||
const { delegationsPagination } = ENV;
|
|
||||||
const { param: marketCreationQuantumMultiple } = useNetworkParam(
|
const { param: marketCreationQuantumMultiple } = useNetworkParam(
|
||||||
'rewards_marketCreationQuantumMultiple'
|
'rewards_marketCreationQuantumMultiple'
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data, loading, error, refetch } = useRewardsQuery({
|
const { data, loading, error } = useRewardsQuery({
|
||||||
notifyOnNetworkStatusChange: true,
|
notifyOnNetworkStatusChange: true,
|
||||||
variables: {
|
variables: {
|
||||||
partyId: pubKey || '',
|
partyId: pubKey || '',
|
||||||
fromEpoch: epochId - EPOCHS_PAGE_SIZE,
|
...calculateEpochOffset({ epochId, page, size: EPOCHS_PAGE_SIZE }),
|
||||||
toEpoch: epochId,
|
delegationsPagination: { first: 50 },
|
||||||
delegationsPagination: delegationsPagination
|
|
||||||
? {
|
|
||||||
first: Number(delegationsPagination),
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
},
|
},
|
||||||
skip: !pubKey,
|
skip: !pubKey,
|
||||||
});
|
});
|
||||||
@@ -70,36 +63,6 @@ export const EpochIndividualRewards = ({
|
|||||||
});
|
});
|
||||||
}, [data?.party, epochId, epochRewardSummaries, page, rewards]);
|
}, [data?.party, epochId, epochRewardSummaries, page, rewards]);
|
||||||
|
|
||||||
const refetchData = useCallback(
|
|
||||||
async (toPage?: number) => {
|
|
||||||
const targetPage = toPage ?? page;
|
|
||||||
await refetch({
|
|
||||||
partyId: pubKey || '',
|
|
||||||
...calculateEpochOffset({ epochId, page, size: EPOCHS_PAGE_SIZE }),
|
|
||||||
delegationsPagination: delegationsPagination
|
|
||||||
? {
|
|
||||||
first: Number(delegationsPagination),
|
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
});
|
|
||||||
setPage(targetPage);
|
|
||||||
},
|
|
||||||
[epochId, page, refetch, delegationsPagination, pubKey]
|
|
||||||
);
|
|
||||||
|
|
||||||
const prevEpochIdRef = useRef<number | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (prevEpochIdRef.current === null) {
|
|
||||||
prevEpochIdRef.current = epochId;
|
|
||||||
} else if (epochId !== prevEpochIdRef.current) {
|
|
||||||
// When the epoch changes, we want to refetch the data to update the current page
|
|
||||||
refetchData();
|
|
||||||
}
|
|
||||||
|
|
||||||
prevEpochIdRef.current = epochId;
|
|
||||||
}, [epochId, refetchData]);
|
|
||||||
|
|
||||||
// Workarounds for the error handling of AsyncRenderer
|
// Workarounds for the error handling of AsyncRenderer
|
||||||
const filteredErrors = filterAcceptableGraphqlErrors(error);
|
const filteredErrors = filterAcceptableGraphqlErrors(error);
|
||||||
const filteredData = data || [];
|
const filteredData = data || [];
|
||||||
@@ -131,10 +94,10 @@ export const EpochIndividualRewards = ({
|
|||||||
isLoading={loading}
|
isLoading={loading}
|
||||||
hasPrevPage={page > 1}
|
hasPrevPage={page > 1}
|
||||||
hasNextPage={page < totalPages}
|
hasNextPage={page < totalPages}
|
||||||
onBack={() => refetchData(page - 1)}
|
onBack={() => setPage((x) => x - 1)}
|
||||||
onNext={() => refetchData(page + 1)}
|
onNext={() => setPage((x) => x + 1)}
|
||||||
onFirst={() => refetchData(1)}
|
onFirst={() => setPage(1)}
|
||||||
onLast={() => refetchData(totalPages)}
|
onLast={() => setPage(totalPages)}
|
||||||
>
|
>
|
||||||
{t('Page')} {page}
|
{t('Page')} {page}
|
||||||
</Pagination>
|
</Pagination>
|
||||||
|
|||||||
+7
-211
@@ -23,36 +23,6 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
epoch: { id: '2' },
|
epoch: { id: '2' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const reward3: RewardFieldsFragment = {
|
|
||||||
rewardType: AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
amount: '200',
|
|
||||||
percentageOfTotal: '0.2',
|
|
||||||
receivedAt: new Date(),
|
|
||||||
asset: { id: 'gbp', symbol: 'GBP', name: 'GBP', decimals: 7 },
|
|
||||||
party: { id: 'blah' },
|
|
||||||
epoch: { id: '2' },
|
|
||||||
};
|
|
||||||
|
|
||||||
const reward4: RewardFieldsFragment = {
|
|
||||||
rewardType: AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
amount: '100',
|
|
||||||
percentageOfTotal: '0.1',
|
|
||||||
receivedAt: new Date(),
|
|
||||||
asset: { id: 'usd', symbol: 'USD', name: 'USD', decimals: 6 },
|
|
||||||
party: { id: 'blah' },
|
|
||||||
epoch: { id: '1' },
|
|
||||||
};
|
|
||||||
|
|
||||||
const reward5: RewardFieldsFragment = {
|
|
||||||
rewardType: AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
amount: '150',
|
|
||||||
percentageOfTotal: '0.15',
|
|
||||||
receivedAt: new Date(),
|
|
||||||
asset: { id: 'usd', symbol: 'USD', name: 'USD', decimals: 6 },
|
|
||||||
party: { id: 'blah' },
|
|
||||||
epoch: { id: '3' },
|
|
||||||
};
|
|
||||||
|
|
||||||
const rewardWrongType: RewardFieldsFragment = {
|
const rewardWrongType: RewardFieldsFragment = {
|
||||||
rewardType: AccountType.ACCOUNT_TYPE_INSURANCE,
|
rewardType: AccountType.ACCOUNT_TYPE_INSURANCE,
|
||||||
amount: '50',
|
amount: '50',
|
||||||
@@ -120,26 +90,10 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
amount: '0',
|
amount: '0',
|
||||||
percentageOfTotal: '0',
|
percentageOfTotal: '0',
|
||||||
},
|
},
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
||||||
amount: '100',
|
amount: '100',
|
||||||
percentageOfTotal: '0.1',
|
percentageOfTotal: '0.1',
|
||||||
},
|
},
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -147,7 +101,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should return an array sorted by epoch descending', () => {
|
it('should return an array sorted by epoch descending', () => {
|
||||||
const rewards = [reward1, reward2, reward3, reward4];
|
const rewards = [reward1, reward2];
|
||||||
const result1 = generateEpochIndividualRewardsList({
|
const result1 = generateEpochIndividualRewardsList({
|
||||||
rewards,
|
rewards,
|
||||||
epochId: 2,
|
epochId: 2,
|
||||||
@@ -157,7 +111,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
expect(result1[0].epoch).toEqual(2);
|
expect(result1[0].epoch).toEqual(2);
|
||||||
expect(result1[1].epoch).toEqual(1);
|
expect(result1[1].epoch).toEqual(1);
|
||||||
|
|
||||||
const reorderedRewards = [reward4, reward3, reward2, reward1];
|
const reorderedRewards = [reward2, reward1];
|
||||||
const result2 = generateEpochIndividualRewardsList({
|
const result2 = generateEpochIndividualRewardsList({
|
||||||
rewards: reorderedRewards,
|
rewards: reorderedRewards,
|
||||||
epochId: 2,
|
epochId: 2,
|
||||||
@@ -170,7 +124,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
|
|
||||||
it('returns data in the expected shape', () => {
|
it('returns data in the expected shape', () => {
|
||||||
// Just sanity checking the whole structure here
|
// Just sanity checking the whole structure here
|
||||||
const rewards = [reward1, reward2, reward3, reward4];
|
const rewards = [reward1, reward2];
|
||||||
const result = generateEpochIndividualRewardsList({
|
const result = generateEpochIndividualRewardsList({
|
||||||
rewards,
|
rewards,
|
||||||
epochId: 2,
|
epochId: 2,
|
||||||
@@ -181,37 +135,6 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
{
|
{
|
||||||
epoch: 2,
|
epoch: 2,
|
||||||
rewards: [
|
rewards: [
|
||||||
{
|
|
||||||
asset: 'GBP',
|
|
||||||
totalAmount: '200',
|
|
||||||
decimals: 7,
|
|
||||||
rewardTypes: {
|
|
||||||
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
|
||||||
amount: '200',
|
|
||||||
percentageOfTotal: '0.2',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
asset: 'EUR',
|
asset: 'EUR',
|
||||||
totalAmount: '50',
|
totalAmount: '50',
|
||||||
@@ -221,26 +144,10 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
amount: '0',
|
amount: '0',
|
||||||
percentageOfTotal: '0',
|
percentageOfTotal: '0',
|
||||||
},
|
},
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
||||||
amount: '50',
|
amount: '50',
|
||||||
percentageOfTotal: '0.05',
|
percentageOfTotal: '0.05',
|
||||||
},
|
},
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -250,33 +157,17 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
rewards: [
|
rewards: [
|
||||||
{
|
{
|
||||||
asset: 'USD',
|
asset: 'USD',
|
||||||
totalAmount: '200',
|
totalAmount: '100',
|
||||||
decimals: 6,
|
decimals: 6,
|
||||||
rewardTypes: {
|
rewardTypes: {
|
||||||
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
|
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
|
||||||
amount: '0',
|
amount: '0',
|
||||||
percentageOfTotal: '0',
|
percentageOfTotal: '0',
|
||||||
},
|
},
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
|
||||||
amount: '100',
|
|
||||||
percentageOfTotal: '0.1',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
||||||
amount: '100',
|
amount: '100',
|
||||||
percentageOfTotal: '0.1',
|
percentageOfTotal: '0.1',
|
||||||
},
|
},
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -285,7 +176,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('returns data correctly for the requested epoch range', () => {
|
it('returns data correctly for the requested epoch range', () => {
|
||||||
const rewards = [reward1, reward2, reward3, reward4, reward5];
|
const rewards = [reward1, reward2];
|
||||||
const resultPageOne = generateEpochIndividualRewardsList({
|
const resultPageOne = generateEpochIndividualRewardsList({
|
||||||
rewards,
|
rewards,
|
||||||
epochId: 3,
|
epochId: 3,
|
||||||
@@ -297,74 +188,11 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
expect(resultPageOne).toEqual([
|
expect(resultPageOne).toEqual([
|
||||||
{
|
{
|
||||||
epoch: 3,
|
epoch: 3,
|
||||||
rewards: [
|
rewards: [],
|
||||||
{
|
|
||||||
asset: 'USD',
|
|
||||||
decimals: 6,
|
|
||||||
totalAmount: '150',
|
|
||||||
rewardTypes: {
|
|
||||||
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
|
||||||
amount: '150',
|
|
||||||
percentageOfTotal: '0.15',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
epoch: 2,
|
epoch: 2,
|
||||||
rewards: [
|
rewards: [
|
||||||
{
|
|
||||||
asset: 'GBP',
|
|
||||||
totalAmount: '200',
|
|
||||||
decimals: 7,
|
|
||||||
rewardTypes: {
|
|
||||||
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
|
||||||
amount: '200',
|
|
||||||
percentageOfTotal: '0.2',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
asset: 'EUR',
|
asset: 'EUR',
|
||||||
totalAmount: '50',
|
totalAmount: '50',
|
||||||
@@ -374,26 +202,10 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
amount: '0',
|
amount: '0',
|
||||||
percentageOfTotal: '0',
|
percentageOfTotal: '0',
|
||||||
},
|
},
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
||||||
amount: '50',
|
amount: '50',
|
||||||
percentageOfTotal: '0.05',
|
percentageOfTotal: '0.05',
|
||||||
},
|
},
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
@@ -414,33 +226,17 @@ describe('generateEpochIndividualRewardsList', () => {
|
|||||||
rewards: [
|
rewards: [
|
||||||
{
|
{
|
||||||
asset: 'USD',
|
asset: 'USD',
|
||||||
totalAmount: '200',
|
totalAmount: '100',
|
||||||
decimals: 6,
|
decimals: 6,
|
||||||
rewardTypes: {
|
rewardTypes: {
|
||||||
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
|
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
|
||||||
amount: '0',
|
amount: '0',
|
||||||
percentageOfTotal: '0',
|
percentageOfTotal: '0',
|
||||||
},
|
},
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
|
||||||
amount: '100',
|
|
||||||
percentageOfTotal: '0.1',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
||||||
amount: '100',
|
amount: '100',
|
||||||
percentageOfTotal: '0.1',
|
percentageOfTotal: '0.1',
|
||||||
},
|
},
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
|
|
||||||
amount: '0',
|
|
||||||
percentageOfTotal: '0',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { useState, useCallback, useEffect } from 'react';
|
import { useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { AsyncRenderer, Pagination } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer, Pagination } from '@vegaprotocol/ui-toolkit';
|
||||||
import type { EpochFieldsFragment } from '../home/__generated__/Rewards';
|
import type { EpochFieldsFragment } from '../home/__generated__/Rewards';
|
||||||
@@ -23,37 +23,17 @@ export const EpochTotalRewards = ({ currentEpoch }: EpochTotalRewardsProps) => {
|
|||||||
'rewards_marketCreationQuantumMultiple'
|
'rewards_marketCreationQuantumMultiple'
|
||||||
);
|
);
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const { data, loading, error, refetch } = useEpochAssetsRewardsQuery({
|
const { data, loading, error } = useEpochAssetsRewardsQuery({
|
||||||
notifyOnNetworkStatusChange: true,
|
notifyOnNetworkStatusChange: true,
|
||||||
variables: {
|
variables: {
|
||||||
epochRewardSummariesFilter: {
|
epochRewardSummariesFilter: calculateEpochOffset({
|
||||||
fromEpoch: epochId - EPOCHS_PAGE_SIZE,
|
epochId,
|
||||||
},
|
page: page,
|
||||||
|
size: EPOCHS_PAGE_SIZE,
|
||||||
|
}),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const refetchData = useCallback(
|
|
||||||
async (toPage?: number) => {
|
|
||||||
const targetPage = toPage ?? page;
|
|
||||||
await refetch({
|
|
||||||
epochRewardSummariesFilter: calculateEpochOffset({
|
|
||||||
epochId,
|
|
||||||
page: targetPage,
|
|
||||||
size: EPOCHS_PAGE_SIZE,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
setPage(targetPage);
|
|
||||||
},
|
|
||||||
[epochId, page, refetch]
|
|
||||||
);
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
// when the epoch changes, we want to refetch the data to update the current page
|
|
||||||
if (data) {
|
|
||||||
refetchData();
|
|
||||||
}
|
|
||||||
}, [epochId, data, refetchData]);
|
|
||||||
|
|
||||||
const epochTotalRewardSummaries =
|
const epochTotalRewardSummaries =
|
||||||
generateEpochTotalRewardsList({
|
generateEpochTotalRewardsList({
|
||||||
data,
|
data,
|
||||||
@@ -85,10 +65,10 @@ export const EpochTotalRewards = ({ currentEpoch }: EpochTotalRewardsProps) => {
|
|||||||
isLoading={loading}
|
isLoading={loading}
|
||||||
hasPrevPage={page > 1}
|
hasPrevPage={page > 1}
|
||||||
hasNextPage={page < totalPages}
|
hasNextPage={page < totalPages}
|
||||||
onBack={() => refetchData(page - 1)}
|
onBack={() => setPage((x) => x - 1)}
|
||||||
onNext={() => refetchData(page + 1)}
|
onNext={() => setPage((x) => x + 1)}
|
||||||
onFirst={() => refetchData(1)}
|
onFirst={() => setPage(1)}
|
||||||
onLast={() => refetchData(totalPages)}
|
onLast={() => setPage(totalPages)}
|
||||||
>
|
>
|
||||||
{t('Page')} {page}
|
{t('Page')} {page}
|
||||||
</Pagination>
|
</Pagination>
|
||||||
|
|||||||
+4
-250
@@ -149,38 +149,6 @@ describe('generateEpochAssetRewardsList', () => {
|
|||||||
amount: '0',
|
amount: '0',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]),
|
]),
|
||||||
totalAmount: '123',
|
totalAmount: '123',
|
||||||
},
|
},
|
||||||
@@ -291,40 +259,8 @@ describe('generateEpochAssetRewardsList', () => {
|
|||||||
amount: '100',
|
amount: '100',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
|
||||||
amount: '123',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]),
|
]),
|
||||||
totalAmount: '223',
|
totalAmount: '100',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
]),
|
]),
|
||||||
@@ -334,66 +270,7 @@ describe('generateEpochAssetRewardsList', () => {
|
|||||||
'2',
|
'2',
|
||||||
{
|
{
|
||||||
epoch: 2,
|
epoch: 2,
|
||||||
assetRewards: new Map([
|
assetRewards: new Map(),
|
||||||
[
|
|
||||||
'1',
|
|
||||||
{
|
|
||||||
assetId: '1',
|
|
||||||
decimals: 18,
|
|
||||||
name: 'Asset 1',
|
|
||||||
rewards: new Map([
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
|
|
||||||
{
|
|
||||||
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
amount: '5',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]),
|
|
||||||
totalAmount: '5',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
])
|
])
|
||||||
@@ -489,66 +366,7 @@ describe('generateEpochAssetRewardsList', () => {
|
|||||||
'2',
|
'2',
|
||||||
{
|
{
|
||||||
epoch: 2,
|
epoch: 2,
|
||||||
assetRewards: new Map([
|
assetRewards: new Map(),
|
||||||
[
|
|
||||||
'1',
|
|
||||||
{
|
|
||||||
assetId: '1',
|
|
||||||
name: 'Asset 1',
|
|
||||||
decimals: 18,
|
|
||||||
rewards: new Map([
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
|
|
||||||
{
|
|
||||||
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
amount: '33',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]),
|
|
||||||
totalAmount: '33',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]),
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
@@ -578,38 +396,6 @@ describe('generateEpochAssetRewardsList', () => {
|
|||||||
amount: '15',
|
amount: '15',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]),
|
]),
|
||||||
totalAmount: '15',
|
totalAmount: '15',
|
||||||
},
|
},
|
||||||
@@ -656,40 +442,8 @@ describe('generateEpochAssetRewardsList', () => {
|
|||||||
amount: '100',
|
amount: '100',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
|
||||||
amount: '123',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
|
|
||||||
{
|
|
||||||
rewardType:
|
|
||||||
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
|
|
||||||
amount: '0',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
]),
|
]),
|
||||||
totalAmount: '223',
|
totalAmount: '100',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
]),
|
]),
|
||||||
|
|||||||
+1
-17
@@ -18,22 +18,6 @@ export const RowAccountTypes = {
|
|||||||
columnTitle: 'rewardsColInfraHeader',
|
columnTitle: 'rewardsColInfraHeader',
|
||||||
description: 'rewardsColInfraTooltip',
|
description: 'rewardsColInfraTooltip',
|
||||||
},
|
},
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
|
|
||||||
columnTitle: 'rewardsColPriceTakingHeader',
|
|
||||||
description: 'rewardsColPriceTakingTooltip',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
|
|
||||||
columnTitle: 'rewardsColPriceMakingHeader',
|
|
||||||
description: 'rewardsColPriceMakingTooltip',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
|
||||||
columnTitle: 'rewardsColLiquidityProvisionHeader',
|
|
||||||
description: 'rewardsColLiquidityProvisionTooltip',
|
|
||||||
},
|
|
||||||
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
|
|
||||||
columnTitle: 'rewardsColMarketCreationHeader',
|
|
||||||
description: 'rewardsColMarketCreationTooltip',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
interface ColumnHeaderProps {
|
interface ColumnHeaderProps {
|
||||||
@@ -55,7 +39,7 @@ export const rowGridItemStyles = (last = false) =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
const gridStyles = classNames(
|
const gridStyles = classNames(
|
||||||
'grid grid-cols-[repeat(8,minmax(100px,auto))] max-w-full overflow-auto',
|
'grid grid-cols-[repeat(4,minmax(100px,auto))] max-w-full overflow-auto',
|
||||||
`border-t border-vega-dark-200`,
|
`border-t border-vega-dark-200`,
|
||||||
'text-sm'
|
'text-sm'
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,27 +1,31 @@
|
|||||||
|
fragment ValidatorNode on Node {
|
||||||
|
id
|
||||||
|
stakedTotal
|
||||||
|
rewardScore {
|
||||||
|
rawValidatorScore
|
||||||
|
performanceScore
|
||||||
|
multisigScore
|
||||||
|
validatorScore
|
||||||
|
normalisedScore
|
||||||
|
validatorStatus
|
||||||
|
}
|
||||||
|
rankingScore {
|
||||||
|
status
|
||||||
|
previousStatus
|
||||||
|
rankingScore
|
||||||
|
stakeScore
|
||||||
|
performanceScore
|
||||||
|
votingPower
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
query PreviousEpoch($epochId: ID) {
|
query PreviousEpoch($epochId: ID) {
|
||||||
epoch(id: $epochId) {
|
epoch(id: $epochId) {
|
||||||
id
|
id
|
||||||
validatorsConnection {
|
validatorsConnection {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
...ValidatorNode
|
||||||
stakedTotal
|
|
||||||
rewardScore {
|
|
||||||
rawValidatorScore
|
|
||||||
performanceScore
|
|
||||||
multisigScore
|
|
||||||
validatorScore
|
|
||||||
normalisedScore
|
|
||||||
validatorStatus
|
|
||||||
}
|
|
||||||
rankingScore {
|
|
||||||
status
|
|
||||||
previousStatus
|
|
||||||
rankingScore
|
|
||||||
stakeScore
|
|
||||||
performanceScore
|
|
||||||
votingPower
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+26
-20
@@ -3,6 +3,8 @@ import * as Types from '@vegaprotocol/types';
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
import * as Apollo from '@apollo/client';
|
import * as Apollo from '@apollo/client';
|
||||||
const defaultOptions = {} as const;
|
const defaultOptions = {} as const;
|
||||||
|
export type ValidatorNodeFragment = { __typename?: 'Node', id: string, stakedTotal: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string, performanceScore: string, multisigScore: string, validatorScore: string, normalisedScore: string, validatorStatus: Types.ValidatorStatus } | null, rankingScore: { __typename?: 'RankingScore', status: Types.ValidatorStatus, previousStatus: Types.ValidatorStatus, rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string } };
|
||||||
|
|
||||||
export type PreviousEpochQueryVariables = Types.Exact<{
|
export type PreviousEpochQueryVariables = Types.Exact<{
|
||||||
epochId?: Types.InputMaybe<Types.Scalars['ID']>;
|
epochId?: Types.InputMaybe<Types.Scalars['ID']>;
|
||||||
}>;
|
}>;
|
||||||
@@ -10,7 +12,28 @@ export type PreviousEpochQueryVariables = Types.Exact<{
|
|||||||
|
|
||||||
export type PreviousEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, validatorsConnection?: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, stakedTotal: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string, performanceScore: string, multisigScore: string, validatorScore: string, normalisedScore: string, validatorStatus: Types.ValidatorStatus } | null, rankingScore: { __typename?: 'RankingScore', status: Types.ValidatorStatus, previousStatus: Types.ValidatorStatus, rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string } } } | null> | null } | null } };
|
export type PreviousEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, validatorsConnection?: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, stakedTotal: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string, performanceScore: string, multisigScore: string, validatorScore: string, normalisedScore: string, validatorStatus: Types.ValidatorStatus } | null, rankingScore: { __typename?: 'RankingScore', status: Types.ValidatorStatus, previousStatus: Types.ValidatorStatus, rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string } } } | null> | null } | null } };
|
||||||
|
|
||||||
|
export const ValidatorNodeFragmentDoc = gql`
|
||||||
|
fragment ValidatorNode on Node {
|
||||||
|
id
|
||||||
|
stakedTotal
|
||||||
|
rewardScore {
|
||||||
|
rawValidatorScore
|
||||||
|
performanceScore
|
||||||
|
multisigScore
|
||||||
|
validatorScore
|
||||||
|
normalisedScore
|
||||||
|
validatorStatus
|
||||||
|
}
|
||||||
|
rankingScore {
|
||||||
|
status
|
||||||
|
previousStatus
|
||||||
|
rankingScore
|
||||||
|
stakeScore
|
||||||
|
performanceScore
|
||||||
|
votingPower
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
export const PreviousEpochDocument = gql`
|
export const PreviousEpochDocument = gql`
|
||||||
query PreviousEpoch($epochId: ID) {
|
query PreviousEpoch($epochId: ID) {
|
||||||
epoch(id: $epochId) {
|
epoch(id: $epochId) {
|
||||||
@@ -18,30 +41,13 @@ export const PreviousEpochDocument = gql`
|
|||||||
validatorsConnection {
|
validatorsConnection {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
id
|
...ValidatorNode
|
||||||
stakedTotal
|
|
||||||
rewardScore {
|
|
||||||
rawValidatorScore
|
|
||||||
performanceScore
|
|
||||||
multisigScore
|
|
||||||
validatorScore
|
|
||||||
normalisedScore
|
|
||||||
validatorStatus
|
|
||||||
}
|
|
||||||
rankingScore {
|
|
||||||
status
|
|
||||||
previousStatus
|
|
||||||
rankingScore
|
|
||||||
stakeScore
|
|
||||||
performanceScore
|
|
||||||
votingPower
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
${ValidatorNodeFragmentDoc}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __usePreviousEpochQuery__
|
* __usePreviousEpochQuery__
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import { usePreviousEpochQuery } from '../__generated__/PreviousEpoch';
|
|||||||
import { ValidatorTables } from './validator-tables';
|
import { ValidatorTables } from './validator-tables';
|
||||||
import { useRefreshAfterEpoch } from '../../../hooks/use-refresh-after-epoch';
|
import { useRefreshAfterEpoch } from '../../../hooks/use-refresh-after-epoch';
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
import { ENV } from '../../../config';
|
|
||||||
import { getMultisigStatusInfo } from '../../../lib/get-multisig-status-info';
|
import { getMultisigStatusInfo } from '../../../lib/get-multisig-status-info';
|
||||||
import { MultisigIncorrectNotice } from '../../../components/multisig-incorrect-notice';
|
import { MultisigIncorrectNotice } from '../../../components/multisig-incorrect-notice';
|
||||||
|
|
||||||
@@ -20,7 +19,6 @@ export const EpochData = () => {
|
|||||||
refetch: nodesRefetch,
|
refetch: nodesRefetch,
|
||||||
} = useNodesQuery();
|
} = useNodesQuery();
|
||||||
|
|
||||||
const { delegationsPagination } = ENV;
|
|
||||||
const {
|
const {
|
||||||
data: userStakingData,
|
data: userStakingData,
|
||||||
error: userStakingError,
|
error: userStakingError,
|
||||||
@@ -29,11 +27,9 @@ export const EpochData = () => {
|
|||||||
} = useStakingQuery({
|
} = useStakingQuery({
|
||||||
variables: {
|
variables: {
|
||||||
partyId: pubKey || '',
|
partyId: pubKey || '',
|
||||||
delegationsPagination: delegationsPagination
|
delegationsPagination: {
|
||||||
? {
|
first: 50,
|
||||||
first: Number(delegationsPagination),
|
},
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const { data: previousEpochData } = usePreviousEpochQuery({
|
const { data: previousEpochData } = usePreviousEpochQuery({
|
||||||
|
|||||||
+1
-1
@@ -288,7 +288,7 @@ describe('Consensus validators table', () => {
|
|||||||
|
|
||||||
expect(
|
expect(
|
||||||
grid.querySelector('[role="gridcell"][col-id="totalPenalties"]')
|
grid.querySelector('[role="gridcell"][col-id="totalPenalties"]')
|
||||||
).toHaveTextContent('13.16%');
|
).toHaveTextContent('10.07%');
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
grid.querySelector('[role="gridcell"][col-id="normalisedVotingPower"]')
|
grid.querySelector('[role="gridcell"][col-id="normalisedVotingPower"]')
|
||||||
|
|||||||
+13
-3
@@ -185,15 +185,19 @@ export const ConsensusValidatorsTable = ({
|
|||||||
const { rawValidatorScore: previousEpochValidatorScore } =
|
const { rawValidatorScore: previousEpochValidatorScore } =
|
||||||
getLastEpochScoreAndPerformance(previousEpochData, id);
|
getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||||
|
|
||||||
const overstakingPenalty = calculateOverallPenalty(
|
const overstakingPenalty = calculateOverstakedPenalty(
|
||||||
id,
|
id,
|
||||||
allNodesInPreviousEpoch
|
allNodesInPreviousEpoch
|
||||||
);
|
);
|
||||||
const totalPenalty = calculateOverstakedPenalty(
|
const totalPenalty = calculateOverallPenalty(
|
||||||
id,
|
id,
|
||||||
allNodesInPreviousEpoch
|
allNodesInPreviousEpoch
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const lastEpochDataForNode = allNodesInPreviousEpoch.find(
|
||||||
|
(node) => node.id === id
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
[ValidatorFields.RANKING_INDEX]: stakedTotalRanking,
|
[ValidatorFields.RANKING_INDEX]: stakedTotalRanking,
|
||||||
@@ -239,6 +243,12 @@ export const ConsensusValidatorsTable = ({
|
|||||||
: undefined,
|
: undefined,
|
||||||
[ValidatorFields.MULTISIG_ERROR]:
|
[ValidatorFields.MULTISIG_ERROR]:
|
||||||
multisigStatus?.showMultisigStatusError,
|
multisigStatus?.showMultisigStatusError,
|
||||||
|
[ValidatorFields.MULTISIG_PENALTY]: formatNumberPercentage(
|
||||||
|
new BigNumber(1)
|
||||||
|
.minus(lastEpochDataForNode?.rewardScore?.multisigScore ?? 1)
|
||||||
|
.times(100),
|
||||||
|
2
|
||||||
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
@@ -378,7 +388,6 @@ export const ConsensusValidatorsTable = ({
|
|||||||
headerTooltip: t('StakeDescription').toString(),
|
headerTooltip: t('StakeDescription').toString(),
|
||||||
cellRenderer: TotalStakeRenderer,
|
cellRenderer: TotalStakeRenderer,
|
||||||
width: 120,
|
width: 120,
|
||||||
sort: 'desc',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: ValidatorFields.PENDING_STAKE,
|
field: ValidatorFields.PENDING_STAKE,
|
||||||
@@ -400,6 +409,7 @@ export const ConsensusValidatorsTable = ({
|
|||||||
headerTooltip: t('NormalisedVotingPowerDescription').toString(),
|
headerTooltip: t('NormalisedVotingPowerDescription').toString(),
|
||||||
cellRenderer: VotingPowerRenderer,
|
cellRenderer: VotingPowerRenderer,
|
||||||
width: 120,
|
width: 120,
|
||||||
|
sort: 'desc',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: ValidatorFields.TOTAL_PENALTIES,
|
field: ValidatorFields.TOTAL_PENALTIES,
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ export enum ValidatorFields {
|
|||||||
PENDING_USER_STAKE = 'pendingUserStake',
|
PENDING_USER_STAKE = 'pendingUserStake',
|
||||||
USER_STAKE_SHARE = 'userStakeShare',
|
USER_STAKE_SHARE = 'userStakeShare',
|
||||||
MULTISIG_ERROR = 'multisigError',
|
MULTISIG_ERROR = 'multisigError',
|
||||||
|
MULTISIG_PENALTY = 'multisigPenalty',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const addUserDataToValidator = (
|
export const addUserDataToValidator = (
|
||||||
@@ -327,7 +328,7 @@ interface TotalPenaltiesRendererProps {
|
|||||||
overstakedAmount: string;
|
overstakedAmount: string;
|
||||||
overstakingPenalty: string;
|
overstakingPenalty: string;
|
||||||
totalPenalties: string;
|
totalPenalties: string;
|
||||||
multisigError?: boolean;
|
multisigPenalty: string;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,11 +347,9 @@ export const TotalPenaltiesRenderer = ({
|
|||||||
<div data-testid="overstaked-penalty-tooltip">
|
<div data-testid="overstaked-penalty-tooltip">
|
||||||
{t('overstakedPenalty')}: {data.overstakingPenalty}
|
{t('overstakedPenalty')}: {data.overstakingPenalty}
|
||||||
</div>
|
</div>
|
||||||
{data.multisigError && (
|
<div data-testid="multisig-error-tooltip">
|
||||||
<div data-testid="multisig-error-tooltip">
|
{t('multisigPenalty')}: {data.multisigPenalty}
|
||||||
{t('multisigPenalty')}: 100%
|
</div>
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { ENV } from '../../../config';
|
|
||||||
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
@@ -28,16 +27,13 @@ export const NodeContainer = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { pubKey } = useVegaWallet();
|
const { pubKey } = useVegaWallet();
|
||||||
const { delegationsPagination } = ENV;
|
|
||||||
|
|
||||||
const { data, loading, error, refetch } = useStakingQuery({
|
const { data, loading, error, refetch } = useStakingQuery({
|
||||||
variables: {
|
variables: {
|
||||||
partyId: pubKey || '',
|
partyId: pubKey || '',
|
||||||
delegationsPagination: delegationsPagination
|
delegationsPagination: {
|
||||||
? {
|
first: 50,
|
||||||
first: Number(delegationsPagination),
|
},
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
},
|
},
|
||||||
errorPolicy: 'all',
|
errorPolicy: 'all',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import * as Sentry from '@sentry/react';
|
|||||||
import React, { useCallback, useState } from 'react';
|
import React, { useCallback, useState } from 'react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { ENV } from '../../../config';
|
|
||||||
import { usePartyDelegationsLazyQuery } from './__generated__/PartyDelegations';
|
import { usePartyDelegationsLazyQuery } from './__generated__/PartyDelegations';
|
||||||
import { TokenInput } from '../../../components/token-input';
|
import { TokenInput } from '../../../components/token-input';
|
||||||
import { useAppState } from '../../../contexts/app-state/app-state-context';
|
import { useAppState } from '../../../contexts/app-state/app-state-context';
|
||||||
@@ -79,7 +78,6 @@ export const StakingForm = ({
|
|||||||
const [error, setError] = useState<Error | null>(null);
|
const [error, setError] = useState<Error | null>(null);
|
||||||
const [isDialogVisible, setIsDialogVisible] = useState(false);
|
const [isDialogVisible, setIsDialogVisible] = useState(false);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { delegationsPagination } = ENV;
|
|
||||||
const [action, setAction] = React.useState<StakeAction>(
|
const [action, setAction] = React.useState<StakeAction>(
|
||||||
params.action as StakeAction
|
params.action as StakeAction
|
||||||
);
|
);
|
||||||
@@ -154,11 +152,9 @@ export const StakingForm = ({
|
|||||||
const [delegationSearch, { data }] = usePartyDelegationsLazyQuery({
|
const [delegationSearch, { data }] = usePartyDelegationsLazyQuery({
|
||||||
variables: {
|
variables: {
|
||||||
partyId: pubKey,
|
partyId: pubKey,
|
||||||
delegationsPagination: delegationsPagination
|
delegationsPagination: {
|
||||||
? {
|
first: 50,
|
||||||
first: Number(delegationsPagination),
|
},
|
||||||
}
|
|
||||||
: undefined,
|
|
||||||
},
|
},
|
||||||
fetchPolicy: 'network-only',
|
fetchPolicy: 'network-only',
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -104,6 +104,11 @@ export const ValidatorTable = ({
|
|||||||
};
|
};
|
||||||
}, [node, previousEpochData?.epoch.validatorsConnection?.edges]);
|
}, [node, previousEpochData?.epoch.validatorsConnection?.edges]);
|
||||||
|
|
||||||
|
const previousNodeData =
|
||||||
|
previousEpochData?.epoch.validatorsConnection?.edges?.find(
|
||||||
|
(e) => e?.node.id === node.id
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p className="mb-12">
|
<p className="mb-12">
|
||||||
@@ -281,6 +286,28 @@ export const ValidatorTable = ({
|
|||||||
</span>
|
</span>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</KeyValueTableRow>
|
</KeyValueTableRow>
|
||||||
|
<KeyValueTableRow>
|
||||||
|
<span className="uppercase">{t('multisigPenalty')}</span>
|
||||||
|
|
||||||
|
<span
|
||||||
|
data-testid="multisig-penalty"
|
||||||
|
className="flex gap-2 items-baseline"
|
||||||
|
>
|
||||||
|
<Tooltip description={t('multisigPenaltyDescription')}>
|
||||||
|
<span>
|
||||||
|
{formatNumberPercentage(
|
||||||
|
new BigNumber(1)
|
||||||
|
.minus(
|
||||||
|
previousNodeData?.node.rewardScore?.multisigScore ??
|
||||||
|
1
|
||||||
|
)
|
||||||
|
.times(100),
|
||||||
|
2
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
</Tooltip>
|
||||||
|
</span>
|
||||||
|
</KeyValueTableRow>
|
||||||
<KeyValueTableRow noBorder={true}>
|
<KeyValueTableRow noBorder={true}>
|
||||||
<span>
|
<span>
|
||||||
<strong>{t('TOTAL PENALTIES')}</strong>
|
<strong>{t('TOTAL PENALTIES')}</strong>
|
||||||
|
|||||||
+1
-1
@@ -14,7 +14,7 @@ NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
|
|||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
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
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/en-GB/firefox/addon/vega-wallet-beta/
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
|||||||
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
|
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
|
||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
|
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/en-GB/firefox/addon/vega-wallet-beta/
|
||||||
|
|
||||||
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
|
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
|
||||||
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
|
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega-dev-releases/releases
|
|||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
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
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/en-GB/firefox/addon/vega-wallet-beta/
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||||
|
|
||||||
# Cosmic elevator flags
|
# Cosmic elevator flags
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
|
|||||||
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
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
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/en-GB/firefox/addon/vega-wallet-beta/
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
|
|||||||
NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
|
NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
|
||||||
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/en-GB/firefox/addon/vega-wallet-beta/
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||||
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
|
|||||||
NX_VEGA_CONSOLE_URL=https://trading.validators-testnet.vega.rocks
|
NX_VEGA_CONSOLE_URL=https://trading.validators-testnet.vega.rocks
|
||||||
|
|
||||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/en-GB/firefox/addon/vega-wallet-beta/
|
||||||
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
|
||||||
|
|
||||||
# Cosmic elevator flags
|
# Cosmic elevator flags
|
||||||
|
|||||||
@@ -30,8 +30,6 @@ export const ChartContainer = ({ marketId }: { marketId: string }) => {
|
|||||||
setStudies,
|
setStudies,
|
||||||
setStudySizes,
|
setStudySizes,
|
||||||
setOverlays,
|
setOverlays,
|
||||||
state,
|
|
||||||
setState,
|
|
||||||
} = useChartSettings();
|
} = useChartSettings();
|
||||||
|
|
||||||
const pennantChart = (
|
const pennantChart = (
|
||||||
@@ -68,10 +66,6 @@ export const ChartContainer = ({ marketId }: { marketId: string }) => {
|
|||||||
onIntervalChange={(newInterval) => {
|
onIntervalChange={(newInterval) => {
|
||||||
setInterval(fromTradingViewResolution(newInterval));
|
setInterval(fromTradingViewResolution(newInterval));
|
||||||
}}
|
}}
|
||||||
onAutoSaveNeeded={(data) => {
|
|
||||||
setState(data);
|
|
||||||
}}
|
|
||||||
state={state}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ type StudySizes = { [S in Study]?: number };
|
|||||||
export type Chartlib = 'pennant' | 'tradingview';
|
export type Chartlib = 'pennant' | 'tradingview';
|
||||||
|
|
||||||
interface StoredSettings {
|
interface StoredSettings {
|
||||||
state: object | undefined; // Don't see a better type provided from TradingView type definitions
|
|
||||||
chartlib: Chartlib;
|
chartlib: Chartlib;
|
||||||
// For interval we use the enum from @vegaprotocol/types, this is to make mapping between different
|
// For interval we use the enum from @vegaprotocol/types, this is to make mapping between different
|
||||||
// chart types easier and more consistent
|
// chart types easier and more consistent
|
||||||
@@ -30,7 +29,6 @@ const STUDY_ORDER: Study[] = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
export const DEFAULT_CHART_SETTINGS = {
|
export const DEFAULT_CHART_SETTINGS = {
|
||||||
state: undefined,
|
|
||||||
chartlib: 'pennant' as const,
|
chartlib: 'pennant' as const,
|
||||||
interval: Interval.INTERVAL_I15M,
|
interval: Interval.INTERVAL_I15M,
|
||||||
type: ChartType.CANDLE,
|
type: ChartType.CANDLE,
|
||||||
@@ -47,7 +45,6 @@ export const useChartSettingsStore = create<
|
|||||||
setStudies: (studies?: Study[]) => void;
|
setStudies: (studies?: Study[]) => void;
|
||||||
setStudySizes: (sizes: number[]) => void;
|
setStudySizes: (sizes: number[]) => void;
|
||||||
setChartlib: (lib: Chartlib) => void;
|
setChartlib: (lib: Chartlib) => void;
|
||||||
setState: (state: object) => void;
|
|
||||||
}
|
}
|
||||||
>()(
|
>()(
|
||||||
persist(
|
persist(
|
||||||
@@ -95,9 +92,6 @@ export const useChartSettingsStore = create<
|
|||||||
state.chartlib = lib;
|
state.chartlib = lib;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
setState: (state) => {
|
|
||||||
set({ state });
|
|
||||||
},
|
|
||||||
})),
|
})),
|
||||||
{
|
{
|
||||||
name: 'vega_candles_chart_store',
|
name: 'vega_candles_chart_store',
|
||||||
@@ -151,7 +145,5 @@ export const useChartSettings = () => {
|
|||||||
setOverlays: settings.setOverlays,
|
setOverlays: settings.setOverlays,
|
||||||
setStudySizes: settings.setStudySizes,
|
setStudySizes: settings.setStudySizes,
|
||||||
setChartlib: settings.setChartlib,
|
setChartlib: settings.setChartlib,
|
||||||
state: settings.state,
|
|
||||||
setState: settings.setState,
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,18 +21,13 @@ const useFeesTableColumnDefs = (): ColDef[] => {
|
|||||||
pinned: 'left',
|
pinned: 'left',
|
||||||
width: 150,
|
width: 150,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
field: 'liquidityFee',
|
|
||||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
field: 'feeAfterDiscount',
|
field: 'feeAfterDiscount',
|
||||||
headerName: t('Total fee after discount'),
|
headerName: t('Total fee after discount'),
|
||||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
field: 'totalFee',
|
field: 'liquidityFee',
|
||||||
headerName: t('Total fee before discount'),
|
|
||||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -43,6 +38,11 @@ const useFeesTableColumnDefs = (): ColDef[] => {
|
|||||||
field: 'makerFee',
|
field: 'makerFee',
|
||||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
field: 'totalFee',
|
||||||
|
headerName: t('Total fee before discount'),
|
||||||
|
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||||
|
},
|
||||||
] as ColDef[],
|
] as ColDef[],
|
||||||
[t]
|
[t]
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import {
|
|||||||
lpAggregatedDataProvider,
|
lpAggregatedDataProvider,
|
||||||
type Filter,
|
type Filter,
|
||||||
LiquidityTable,
|
LiquidityTable,
|
||||||
liquidityProvisionsDataProvider,
|
|
||||||
} from '@vegaprotocol/liquidity';
|
} from '@vegaprotocol/liquidity';
|
||||||
import { getAsset, useMarket } from '@vegaprotocol/markets';
|
import { getAsset, useMarket } from '@vegaprotocol/markets';
|
||||||
import {
|
import {
|
||||||
@@ -71,7 +70,7 @@ export const LiquidityContainer = ({
|
|||||||
|
|
||||||
const useReloadLiquidityData = (marketId: string | undefined) => {
|
const useReloadLiquidityData = (marketId: string | undefined) => {
|
||||||
const { reload } = useDataProvider({
|
const { reload } = useDataProvider({
|
||||||
dataProvider: liquidityProvisionsDataProvider,
|
dataProvider: lpAggregatedDataProvider,
|
||||||
variables: { marketId: marketId || '' },
|
variables: { marketId: marketId || '' },
|
||||||
update: () => true,
|
update: () => true,
|
||||||
skip: !marketId,
|
skip: !marketId,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import {
|
|||||||
useMaliciousOracle,
|
useMaliciousOracle,
|
||||||
} from '@vegaprotocol/markets';
|
} from '@vegaprotocol/markets';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { type MarketViewProposalFieldsFragment } from '@vegaprotocol/proposals';
|
import { type ProposalFragment } from '@vegaprotocol/proposals';
|
||||||
import { MarketSuspendedBanner } from './market-suspended-banner';
|
import { MarketSuspendedBanner } from './market-suspended-banner';
|
||||||
import { MarketUpdateBanner } from './market-update-banner';
|
import { MarketUpdateBanner } from './market-update-banner';
|
||||||
import { MarketUpdateStateBanner } from './market-update-state-banner';
|
import { MarketUpdateStateBanner } from './market-update-state-banner';
|
||||||
@@ -22,17 +22,17 @@ import {
|
|||||||
|
|
||||||
type UpdateMarketBanner = {
|
type UpdateMarketBanner = {
|
||||||
kind: 'UpdateMarket';
|
kind: 'UpdateMarket';
|
||||||
proposals: MarketViewProposalFieldsFragment[];
|
proposals: ProposalFragment[];
|
||||||
};
|
};
|
||||||
|
|
||||||
type UpdateMarketStateBanner = {
|
type UpdateMarketStateBanner = {
|
||||||
kind: 'UpdateMarketState';
|
kind: 'UpdateMarketState';
|
||||||
proposals: MarketViewProposalFieldsFragment[];
|
proposals: ProposalFragment[];
|
||||||
};
|
};
|
||||||
|
|
||||||
type NewMarketBanner = {
|
type NewMarketBanner = {
|
||||||
kind: 'NewMarket'; // aka a proposal of NewMarket which succeeds the current market
|
kind: 'NewMarket'; // aka a proposal of NewMarket which succeeds the current market
|
||||||
proposals: MarketViewProposalFieldsFragment[];
|
proposals: ProposalFragment[];
|
||||||
};
|
};
|
||||||
|
|
||||||
type SettledBanner = {
|
type SettledBanner = {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Fragment } from 'react';
|
import { Fragment } from 'react';
|
||||||
import { type MarketViewProposalFieldsFragment } from '@vegaprotocol/proposals';
|
import { type ProposalFragment } from '@vegaprotocol/proposals';
|
||||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import { DApp, TOKEN_PROPOSAL, useLinks } from '@vegaprotocol/environment';
|
import { DApp, TOKEN_PROPOSAL, useLinks } from '@vegaprotocol/environment';
|
||||||
import { useT } from '../../lib/use-t';
|
import { useT } from '../../lib/use-t';
|
||||||
@@ -7,7 +7,7 @@ import { useT } from '../../lib/use-t';
|
|||||||
export const MarketSuccessorProposalBanner = ({
|
export const MarketSuccessorProposalBanner = ({
|
||||||
proposals,
|
proposals,
|
||||||
}: {
|
}: {
|
||||||
proposals: MarketViewProposalFieldsFragment[];
|
proposals: ProposalFragment[];
|
||||||
}) => {
|
}) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const tokenLink = useLinks(DApp.Governance);
|
const tokenLink = useLinks(DApp.Governance);
|
||||||
@@ -28,7 +28,7 @@ export const MarketSuccessorProposalBanner = ({
|
|||||||
}
|
}
|
||||||
)}{' '}
|
)}{' '}
|
||||||
{proposals.map((item, i) => {
|
{proposals.map((item, i) => {
|
||||||
if (item.terms.change.__typename !== 'NewMarket') {
|
if (item.terms?.change.__typename !== 'NewMarket') {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
import { render, screen } from '@testing-library/react';
|
||||||
import { ProposalState } from '@vegaprotocol/types';
|
import { ProposalState } from '@vegaprotocol/types';
|
||||||
import { MarketUpdateBanner } from './market-update-banner';
|
import { MarketUpdateBanner } from './market-update-banner';
|
||||||
import { type MarketViewProposalFieldsFragment } from '@vegaprotocol/proposals';
|
import { type ProposalFragment } from '@vegaprotocol/proposals';
|
||||||
|
|
||||||
describe('MarketUpdateBanner', () => {
|
describe('MarketUpdateBanner', () => {
|
||||||
const change = {
|
const change = {
|
||||||
@@ -34,9 +34,7 @@ describe('MarketUpdateBanner', () => {
|
|||||||
|
|
||||||
it('renders content for a single open proposal', () => {
|
it('renders content for a single open proposal', () => {
|
||||||
render(
|
render(
|
||||||
<MarketUpdateBanner
|
<MarketUpdateBanner proposals={[openProposal as ProposalFragment]} />
|
||||||
proposals={[openProposal as MarketViewProposalFieldsFragment]}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -50,9 +48,7 @@ describe('MarketUpdateBanner', () => {
|
|||||||
|
|
||||||
it('renders content for a single passed proposal', () => {
|
it('renders content for a single passed proposal', () => {
|
||||||
render(
|
render(
|
||||||
<MarketUpdateBanner
|
<MarketUpdateBanner proposals={[passedProposal as ProposalFragment]} />
|
||||||
proposals={[passedProposal as MarketViewProposalFieldsFragment]}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
@@ -65,10 +61,7 @@ describe('MarketUpdateBanner', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('renders content for multiple passed proposals', () => {
|
it('renders content for multiple passed proposals', () => {
|
||||||
const proposals = [
|
const proposals = [openProposal, openProposal] as ProposalFragment[];
|
||||||
openProposal,
|
|
||||||
openProposal,
|
|
||||||
] as MarketViewProposalFieldsFragment[];
|
|
||||||
|
|
||||||
render(<MarketUpdateBanner proposals={proposals} />);
|
render(<MarketUpdateBanner proposals={proposals} />);
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import {
|
|||||||
TOKEN_PROPOSALS,
|
TOKEN_PROPOSALS,
|
||||||
useLinks,
|
useLinks,
|
||||||
} from '@vegaprotocol/environment';
|
} from '@vegaprotocol/environment';
|
||||||
import { type MarketViewProposalFieldsFragment } from '@vegaprotocol/proposals';
|
import { type ProposalFragment } from '@vegaprotocol/proposals';
|
||||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||||
import { ProposalState } from '@vegaprotocol/types';
|
import { ProposalState } from '@vegaprotocol/types';
|
||||||
import { useT } from '../../lib/use-t';
|
import { useT } from '../../lib/use-t';
|
||||||
@@ -14,17 +14,17 @@ import { useT } from '../../lib/use-t';
|
|||||||
export const MarketUpdateBanner = ({
|
export const MarketUpdateBanner = ({
|
||||||
proposals,
|
proposals,
|
||||||
}: {
|
}: {
|
||||||
proposals: MarketViewProposalFieldsFragment[];
|
proposals: ProposalFragment[];
|
||||||
}) => {
|
}) => {
|
||||||
const governanceLink = useLinks(DApp.Governance);
|
const governanceLink = useLinks(DApp.Governance);
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const openProposals = sortBy(
|
const openProposals = sortBy(
|
||||||
proposals.filter((p) => p.state === ProposalState.STATE_OPEN),
|
proposals.filter((p) => p.state === ProposalState.STATE_OPEN),
|
||||||
(p) => p.terms.enactmentDatetime
|
(p) => p.terms?.enactmentDatetime
|
||||||
);
|
);
|
||||||
const passedProposals = sortBy(
|
const passedProposals = sortBy(
|
||||||
proposals.filter((p) => p.state === ProposalState.STATE_PASSED),
|
proposals.filter((p) => p.state === ProposalState.STATE_PASSED),
|
||||||
(p) => p.terms.enactmentDatetime
|
(p) => p.terms?.enactmentDatetime
|
||||||
);
|
);
|
||||||
|
|
||||||
let content = null;
|
let content = null;
|
||||||
@@ -49,7 +49,7 @@ export const MarketUpdateBanner = ({
|
|||||||
content = (
|
content = (
|
||||||
<p>
|
<p>
|
||||||
{t('Proposal set to change market on {{date}}.', {
|
{t('Proposal set to change market on {{date}}.', {
|
||||||
date: format(new Date(proposal.terms.enactmentDatetime), 'dd MMMM'),
|
date: format(new Date(proposal.terms?.enactmentDatetime), 'dd MMMM'),
|
||||||
})}
|
})}
|
||||||
<ExternalLink href={proposalLink}>{t('View proposal')}</ExternalLink>,
|
<ExternalLink href={proposalLink}>{t('View proposal')}</ExternalLink>,
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { type ReactNode } from 'react';
|
import { type ReactNode } from 'react';
|
||||||
import sortBy from 'lodash/sortBy';
|
import sortBy from 'lodash/sortBy';
|
||||||
import { format, formatDuration, intervalToDuration } from 'date-fns';
|
import { format, formatDuration, intervalToDuration } from 'date-fns';
|
||||||
import { type MarketViewProposalFieldsFragment } from '@vegaprotocol/proposals';
|
import { type ProposalFragment } from '@vegaprotocol/proposals';
|
||||||
import { ProposalState } from '@vegaprotocol/types';
|
import { MarketUpdateType, ProposalState } from '@vegaprotocol/types';
|
||||||
import {
|
import {
|
||||||
DApp,
|
DApp,
|
||||||
TOKEN_PROPOSAL,
|
TOKEN_PROPOSAL,
|
||||||
@@ -19,18 +19,29 @@ export const MarketUpdateStateBanner = ({
|
|||||||
proposals,
|
proposals,
|
||||||
}: {
|
}: {
|
||||||
market: Market;
|
market: Market;
|
||||||
proposals: MarketViewProposalFieldsFragment[];
|
proposals: ProposalFragment[];
|
||||||
}) => {
|
}) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const governanceLink = useLinks(DApp.Governance);
|
const governanceLink = useLinks(DApp.Governance);
|
||||||
|
|
||||||
|
const openTradingProposals = sortBy(
|
||||||
|
proposals.filter(
|
||||||
|
(p) =>
|
||||||
|
p.terms &&
|
||||||
|
p.terms.change.__typename === 'UpdateMarketState' &&
|
||||||
|
p.terms.change.updateType ===
|
||||||
|
MarketUpdateType.MARKET_STATE_UPDATE_TYPE_RESUME
|
||||||
|
),
|
||||||
|
(p) => p.terms?.enactmentDatetime
|
||||||
|
);
|
||||||
|
|
||||||
const openProposals = sortBy(
|
const openProposals = sortBy(
|
||||||
proposals.filter((p) => p.state === ProposalState.STATE_OPEN),
|
proposals.filter((p) => p.state === ProposalState.STATE_OPEN),
|
||||||
(p) => p.terms.enactmentDatetime
|
(p) => p.terms?.enactmentDatetime
|
||||||
);
|
);
|
||||||
const passedProposals = sortBy(
|
const passedProposals = sortBy(
|
||||||
proposals.filter((p) => p.state === ProposalState.STATE_PASSED),
|
proposals.filter((p) => p.state === ProposalState.STATE_PASSED),
|
||||||
(p) => p.terms.enactmentDatetime
|
(p) => p.terms?.enactmentDatetime
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!passedProposals.length && !openProposals.length) {
|
if (!passedProposals.length && !openProposals.length) {
|
||||||
@@ -45,12 +56,41 @@ export const MarketUpdateStateBanner = ({
|
|||||||
? governanceLink(TOKEN_PROPOSAL.replace(':id', openProposals[0]?.id))
|
? governanceLink(TOKEN_PROPOSAL.replace(':id', openProposals[0]?.id))
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
const openTradingProposalsLink =
|
||||||
|
openTradingProposals[0]?.__typename === 'Proposal' &&
|
||||||
|
openTradingProposals[0]?.id
|
||||||
|
? governanceLink(
|
||||||
|
TOKEN_PROPOSAL.replace(':id', openTradingProposals[0].id)
|
||||||
|
)
|
||||||
|
: openTradingProposals[0]?.__typename === 'ProposalDetail' &&
|
||||||
|
openTradingProposals[0]?.batchId
|
||||||
|
? governanceLink(
|
||||||
|
TOKEN_PROPOSAL.replace(':id', openTradingProposals[0].batchId)
|
||||||
|
)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const proposalsLink =
|
const proposalsLink =
|
||||||
openProposals.length > 1 ? governanceLink(TOKEN_PROPOSALS) : undefined;
|
openProposals.length > 1 ? governanceLink(TOKEN_PROPOSALS) : undefined;
|
||||||
|
|
||||||
let content: ReactNode;
|
let content: ReactNode;
|
||||||
|
|
||||||
if (passedProposals.length) {
|
if (openTradingProposals.length >= 1) {
|
||||||
|
content = (
|
||||||
|
<>
|
||||||
|
<p className="mb-1">
|
||||||
|
{t(
|
||||||
|
'Trading on market {{name}} was suspended by governance. There are open proposals to resume trading on this market.',
|
||||||
|
{ name }
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<ExternalLink href={openTradingProposalsLink}>
|
||||||
|
{t('View proposals')}
|
||||||
|
</ExternalLink>
|
||||||
|
</p>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
} else if (passedProposals.length) {
|
||||||
const { date, duration, price } = getMessageVariables(passedProposals[0]);
|
const { date, duration, price } = getMessageVariables(passedProposals[0]);
|
||||||
content = (
|
content = (
|
||||||
<>
|
<>
|
||||||
@@ -116,20 +156,23 @@ export const MarketUpdateStateBanner = ({
|
|||||||
return <div data-testid={`update-state-banner-${market.id}`}>{content}</div>;
|
return <div data-testid={`update-state-banner-${market.id}`}>{content}</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getMessageVariables = (proposal: MarketViewProposalFieldsFragment) => {
|
const getMessageVariables = (proposal: ProposalFragment) => {
|
||||||
const enactmentDatetime = new Date(proposal.terms.enactmentDatetime);
|
const enactmentDatetime =
|
||||||
const date = format(enactmentDatetime, 'dd MMMM');
|
proposal.terms && new Date(proposal.terms.enactmentDatetime);
|
||||||
const duration = formatDuration(
|
const date = enactmentDatetime && format(enactmentDatetime, 'dd MMMM');
|
||||||
intervalToDuration({
|
const duration =
|
||||||
start: new Date(),
|
enactmentDatetime &&
|
||||||
end: enactmentDatetime,
|
formatDuration(
|
||||||
}),
|
intervalToDuration({
|
||||||
{
|
start: new Date(),
|
||||||
format: ['days', 'hours'],
|
end: enactmentDatetime,
|
||||||
}
|
}),
|
||||||
);
|
{
|
||||||
|
format: ['days', 'hours'],
|
||||||
|
}
|
||||||
|
);
|
||||||
const price =
|
const price =
|
||||||
proposal.terms.change.__typename === 'UpdateMarketState'
|
proposal.terms?.change.__typename === 'UpdateMarketState'
|
||||||
? proposal.terms.change.price
|
? proposal.terms.change.price
|
||||||
: '';
|
: '';
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import {
|
import {
|
||||||
useMarketProposals,
|
useMarketProposals,
|
||||||
type MarketViewProposalFieldsFragment,
|
type ProposalFragment,
|
||||||
} from '@vegaprotocol/proposals';
|
} from '@vegaprotocol/proposals';
|
||||||
import { ProposalState, ProposalType } from '@vegaprotocol/types';
|
import { ProposalState, ProposalType } from '@vegaprotocol/types';
|
||||||
|
|
||||||
const isPending = (p: MarketViewProposalFieldsFragment) => {
|
const isPending = (p: ProposalFragment) => {
|
||||||
return [ProposalState.STATE_OPEN, ProposalState.STATE_PASSED].includes(
|
return [ProposalState.STATE_OPEN, ProposalState.STATE_PASSED].includes(
|
||||||
p.state
|
p.state
|
||||||
);
|
);
|
||||||
@@ -21,9 +21,10 @@ export const useUpdateMarketStateProposals = (
|
|||||||
|
|
||||||
const proposals = data
|
const proposals = data
|
||||||
? data.filter(isPending).filter((p) => {
|
? data.filter(isPending).filter((p) => {
|
||||||
const change = p.terms.change;
|
const change = p.terms?.change;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
change &&
|
||||||
change.__typename === 'UpdateMarketState' &&
|
change.__typename === 'UpdateMarketState' &&
|
||||||
change.market.id === marketId
|
change.market.id === marketId
|
||||||
) {
|
) {
|
||||||
@@ -48,8 +49,9 @@ export const useUpdateMarketProposals = (
|
|||||||
|
|
||||||
const proposals = data
|
const proposals = data
|
||||||
? data.filter(isPending).filter((p) => {
|
? data.filter(isPending).filter((p) => {
|
||||||
const change = p.terms.change;
|
const change = p.terms?.change;
|
||||||
if (
|
if (
|
||||||
|
change &&
|
||||||
change.__typename === 'UpdateMarket' &&
|
change.__typename === 'UpdateMarket' &&
|
||||||
change.marketId === marketId
|
change.marketId === marketId
|
||||||
) {
|
) {
|
||||||
@@ -73,8 +75,9 @@ export const useSuccessorMarketProposals = (
|
|||||||
|
|
||||||
const proposals = data
|
const proposals = data
|
||||||
? data.filter(isPending).filter((p) => {
|
? data.filter(isPending).filter((p) => {
|
||||||
const change = p.terms.change;
|
const change = p.terms?.change;
|
||||||
if (
|
if (
|
||||||
|
change &&
|
||||||
change.__typename === 'NewMarket' &&
|
change.__typename === 'NewMarket' &&
|
||||||
change.successorConfiguration?.parentMarketId === marketId
|
change.successorConfiguration?.parentMarketId === marketId
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { useT } from '../../lib/use-t';
|
|||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { MarketHeaderStats } from '../../client-pages/market/market-header-stats';
|
import { MarketHeaderStats } from '../../client-pages/market/market-header-stats';
|
||||||
import { MarketMarkPrice } from '../market-mark-price';
|
import { MarketMarkPrice } from '../market-mark-price';
|
||||||
|
import { MarketBanner } from '../market-banner';
|
||||||
/**
|
/**
|
||||||
* This is only rendered for the mobile navigation
|
* This is only rendered for the mobile navigation
|
||||||
*/
|
*/
|
||||||
@@ -108,8 +109,11 @@ export const MobileMarketHeader = () => {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
{data && (
|
{data && (
|
||||||
<div className="px-3 py-6 text-sm grid grid-cols-2 items-center gap-x-4 gap-y-6">
|
<div>
|
||||||
<MarketHeaderStats market={data} />
|
<MarketBanner market={data} />
|
||||||
|
<div className="px-3 py-6 text-sm grid grid-cols-2 items-center gap-x-4 gap-y-6">
|
||||||
|
<MarketHeaderStats market={data} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</FullScreenPopover>
|
</FullScreenPopover>
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import {
|
|||||||
type DispatchStrategy,
|
type DispatchStrategy,
|
||||||
IndividualScopeMapping,
|
IndividualScopeMapping,
|
||||||
IndividualScopeDescriptionMapping,
|
IndividualScopeDescriptionMapping,
|
||||||
|
type Asset,
|
||||||
} from '@vegaprotocol/types';
|
} from '@vegaprotocol/types';
|
||||||
import { Card } from '../card/card';
|
import { Card } from '../card/card';
|
||||||
import { type ReactNode, useState } from 'react';
|
import { type ReactNode, useState } from 'react';
|
||||||
@@ -200,7 +201,8 @@ export const ActiveRewardCard = ({
|
|||||||
transferNode.transfer.asset?.decimals || 0,
|
transferNode.transfer.asset?.decimals || 0,
|
||||||
6
|
6
|
||||||
)}
|
)}
|
||||||
rewardAsset={transferNode.asset}
|
rewardAsset={transferNode.dispatchAsset}
|
||||||
|
transferAsset={transferNode.transfer.asset || undefined}
|
||||||
endsIn={
|
endsIn={
|
||||||
transferNode.transfer.kind.endEpoch != null
|
transferNode.transfer.kind.endEpoch != null
|
||||||
? transferNode.transfer.kind.endEpoch - currentEpoch
|
? transferNode.transfer.kind.endEpoch - currentEpoch
|
||||||
@@ -216,6 +218,8 @@ const RewardCard = ({
|
|||||||
colour,
|
colour,
|
||||||
rewardAmount,
|
rewardAmount,
|
||||||
rewardAsset,
|
rewardAsset,
|
||||||
|
transferAsset,
|
||||||
|
vegaAsset,
|
||||||
dispatchStrategy,
|
dispatchStrategy,
|
||||||
endsIn,
|
endsIn,
|
||||||
dispatchMetricInfo,
|
dispatchMetricInfo,
|
||||||
@@ -224,12 +228,14 @@ const RewardCard = ({
|
|||||||
rewardAmount: string;
|
rewardAmount: string;
|
||||||
/** The asset linked to the dispatch strategy via `dispatchMetricAssetId` property. */
|
/** The asset linked to the dispatch strategy via `dispatchMetricAssetId` property. */
|
||||||
rewardAsset?: BasicAssetDetails;
|
rewardAsset?: BasicAssetDetails;
|
||||||
|
/** The VEGA asset details, required to format the min staking amount. */
|
||||||
|
transferAsset?: Asset | undefined;
|
||||||
|
/** The VEGA asset details, required to format the min staking amount. */
|
||||||
|
vegaAsset?: BasicAssetDetails;
|
||||||
/** The transfer's dispatch strategy. */
|
/** The transfer's dispatch strategy. */
|
||||||
dispatchStrategy: DispatchStrategy;
|
dispatchStrategy: DispatchStrategy;
|
||||||
/** The number of epochs until the transfer stops. */
|
/** The number of epochs until the transfer stops. */
|
||||||
endsIn?: number;
|
endsIn?: number;
|
||||||
/** The VEGA asset details, required to format the min staking amount. */
|
|
||||||
vegaAsset?: BasicAssetDetails;
|
|
||||||
dispatchMetricInfo?: ReactNode;
|
dispatchMetricInfo?: ReactNode;
|
||||||
}) => {
|
}) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
@@ -269,7 +275,9 @@ const RewardCard = ({
|
|||||||
{rewardAmount}
|
{rewardAmount}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span className="font-alpha">{rewardAsset?.symbol || ''}</span>
|
<span className="font-alpha" data-testid="reward-asset">
|
||||||
|
{transferAsset?.symbol || ''}
|
||||||
|
</span>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
{/** DISTRIBUTION STRATEGY */}
|
{/** DISTRIBUTION STRATEGY */}
|
||||||
@@ -357,6 +365,7 @@ const RewardCard = ({
|
|||||||
<RewardRequirements
|
<RewardRequirements
|
||||||
dispatchStrategy={dispatchStrategy}
|
dispatchStrategy={dispatchStrategy}
|
||||||
rewardAsset={rewardAsset}
|
rewardAsset={rewardAsset}
|
||||||
|
vegaAsset={vegaAsset}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@@ -379,8 +388,8 @@ export const DispatchMetricInfo = ({
|
|||||||
let additionalDispatchMetricInfo = null;
|
let additionalDispatchMetricInfo = null;
|
||||||
|
|
||||||
// if asset found then display asset symbol
|
// if asset found then display asset symbol
|
||||||
if (reward.asset) {
|
if (reward.dispatchAsset) {
|
||||||
additionalDispatchMetricInfo = <span>{reward.asset.symbol}</span>;
|
additionalDispatchMetricInfo = <span>{reward.dispatchAsset.symbol}</span>;
|
||||||
}
|
}
|
||||||
// but if scoped to only one market then display market name
|
// but if scoped to only one market then display market name
|
||||||
if (marketNames.length === 1) {
|
if (marketNames.length === 1) {
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
CONSOLE_IMAGE_NAME=vegaprotocol/trading:latest
|
CONSOLE_IMAGE_NAME=vegaprotocol/trading:latest
|
||||||
VEGA_VERSION=v0.74.3
|
VEGA_VERSION=v0.74.6
|
||||||
LOCAL_SERVER=false
|
LOCAL_SERVER=false
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
CONSOLE_IMAGE_NAME=vegaprotocol/trading:develop
|
CONSOLE_IMAGE_NAME=vegaprotocol/trading:develop
|
||||||
VEGA_VERSION=v0.74.3
|
VEGA_VERSION=v0.74.6
|
||||||
LOCAL_SERVER=false
|
LOCAL_SERVER=false
|
||||||
|
|||||||
+63
-119
@@ -1,156 +1,100 @@
|
|||||||
# Trading Market-Sim End-To-End Tests
|
# Trading Market-Sim End-To-End Tests
|
||||||
|
|
||||||
This direcotry contains end-to-end tests for the trading application using vega-market-sim. This README will guide you through setting up your environment and running the tests.
|
This directory contains end-to-end tests for the Trading application using Vega-market-sim. This guide will help you set up your environment and run the tests efficiently.
|
||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer)
|
Ensure you have the following installed:
|
||||||
- [Docker](https://www.docker.com/)
|
|
||||||
- [Python versions ">=3.9,<3.11"](https://www.python.org/)
|
|
||||||
|
|
||||||
## Getting Started
|
- [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer) for dependency management.
|
||||||
|
- [Docker](https://www.docker.com/) for running isolated application containers.
|
||||||
|
- Python, versions ">=3.9,<3.11". Install from the [official Python website](https://www.python.org/).
|
||||||
|
|
||||||
1. **Install Poetry**: Follow the instructions on the [official Poetry website](https://python-poetry.org/docs/#installing-with-the-official-installer).
|
## Setup
|
||||||
2. **Install Docker**: Follow the instructions on the [official Docker website](https://docs.docker.com/desktop/).
|
|
||||||
3. **Install Python**: Follow the instructions on the [official Python website](https://www.python.org/)
|
|
||||||
**ensure you install a version between 3.9 and 3.11.**
|
|
||||||
4. **Start up a Poetry environment**: Execute the commands below to configure the Poetry environment.
|
|
||||||
|
|
||||||
### Ensure you are in the tests folder before running commands
|
### 1. Install Dependencies
|
||||||
|
|
||||||
|
- **Poetry**: Follow the installation guide on the [official Poetry website](https://python-poetry.org/docs/#installing-with-the-official-installer).
|
||||||
|
- **Docker**: Installation instructions are available on the [official Docker website](https://docs.docker.com/desktop/).
|
||||||
|
- **Python**: Install a version between 3.9 and 3.11, as detailed on the [official Python website](https://www.python.org/).
|
||||||
|
|
||||||
|
### 2. Configure Your Environment
|
||||||
|
|
||||||
|
Ensure you're in the tests folder before executing commands.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
poetry shell
|
poetry shell
|
||||||
```
|
poetry update vega-sim # Updates to the latest version of the market-sim branch
|
||||||
|
|
||||||
5. **Install python dependencies**
|
|
||||||
|
|
||||||
To make sure you are on the latest version of our market-sim branch.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
poetry update vega-sim
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
poetry install
|
poetry install
|
||||||
|
playwright install chromium # Installs necessary browsers for Playwright
|
||||||
```
|
```
|
||||||
|
|
||||||
6. **Install Playwright Browsers**: Execute the command below to browsers for Playwright.
|
### 3. Prepare Binaries and Docker Images
|
||||||
|
|
||||||
```bash
|
Download necessary binaries for the desired Vega version:
|
||||||
playwright install chromium
|
|
||||||
```
|
|
||||||
|
|
||||||
7. **Download necessary binaries**:
|
|
||||||
Use the following command within your Python environment. The `--force` flag ensures the binaries are overwritten, and the `--version` specifies the desired version. e.g. `v0.73.4`
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
python -m vega_sim.tools.load_binaries --force --version $VEGA_VERSION
|
python -m vega_sim.tools.load_binaries --force --version $VEGA_VERSION
|
||||||
```
|
```
|
||||||
|
|
||||||
8. **Pull the desired Docker image**
|
Pull Docker images for your environment:
|
||||||
|
|
||||||
```bash
|
- **Development**: `docker pull vegaprotocol/trading:develop`
|
||||||
docker pull vegaprotocol/trading:develop
|
- **Production**: `docker pull vegaprotocol/trading:main`
|
||||||
```
|
|
||||||
|
|
||||||
9. **Run tests**: Poetry/Python will serve the app from docker
|
### 4. Build a Docker Image of Your Locally Built Trading App
|
||||||
|
|
||||||
### Update the .env file with the correct trading image.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
poetry run pytest
|
|
||||||
```
|
|
||||||
|
|
||||||
### Docker images
|
|
||||||
|
|
||||||
Pull the desired image:
|
|
||||||
|
|
||||||
**Testnet**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker pull vegaprotocol/trading:develop
|
|
||||||
```
|
|
||||||
|
|
||||||
**Mainnet**
|
|
||||||
|
|
||||||
```bash
|
|
||||||
docker pull vegaprotocol/trading:main
|
|
||||||
```
|
|
||||||
|
|
||||||
Find all available images on [Docker Hub](https://hub.docker.com/r/vegaprotocol/trading/tags).
|
|
||||||
|
|
||||||
#### Create a Docker Image of Your Locally Built Trading App
|
|
||||||
|
|
||||||
To build your Docker image, use the following commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn nx build trading ./docker/prepare-dist.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
./docker/prepare-dist.sh
|
||||||
docker build -f docker/node-outside-docker.Dockerfile --build-arg APP=trading --build-arg ENV_NAME=stagnet1 -t vegaprotocol/trading:latest .
|
docker build -f docker/node-outside-docker.Dockerfile --build-arg APP=trading --build-arg ENV_NAME=stagnet1 -t vegaprotocol/trading:latest .
|
||||||
```
|
```
|
||||||
|
|
||||||
## Running Tests 🧪
|
## Running Tests
|
||||||
|
|
||||||
Before running make sure the docker daemon is running.
|
Ensure the Docker daemon is running. Update the `.env` file with the correct trading image before proceeding.
|
||||||
|
|
||||||
To run a specific test, use the `-k` option followed by the name of the test.
|
- **Run all tests**: `poetry run pytest`
|
||||||
Run all tests:
|
- **Run a specific test**: `poetry run pytest -k "test_name" -s --headed`
|
||||||
|
- **Run tests using your locally served console**:
|
||||||
|
|
||||||
```bash
|
In one terminal window, build and serve the trading console:
|
||||||
poetry run pytest
|
|
||||||
|
```bash
|
||||||
|
yarn nx build trading
|
||||||
|
yarn nx serve trading
|
||||||
|
```
|
||||||
|
|
||||||
|
Once the console is served, update the `.env` file to set `local_server=true`. You can then run your tests using the same commands as above.
|
||||||
|
NOTE: Parallel running of tests will not work against locally served console.
|
||||||
|
|
||||||
|
## Test Strategy and Container Cleanup
|
||||||
|
|
||||||
|
### Strategy
|
||||||
|
|
||||||
|
We aim for each test file to use a single Vega instance to ensure test isolation and manage resources efficiently. This approach helps in maintaining test performance and reliability.
|
||||||
|
|
||||||
|
### Cleanup Procedure
|
||||||
|
|
||||||
|
To ensure proper cleanup of containers after each test, use the following fixture pattern:
|
||||||
|
|
||||||
|
```python
|
||||||
|
@pytest.fixture
|
||||||
|
def vega(request):
|
||||||
|
with init_vega(request) as vega_instance:
|
||||||
|
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||||
|
yield vega_instance
|
||||||
```
|
```
|
||||||
|
|
||||||
Run a targeted test:
|
## Running Tests in Parallel
|
||||||
|
|
||||||
```bash
|
For running tests in parallel:
|
||||||
poetry run pytest -k "test_name" -s --headed
|
|
||||||
```
|
|
||||||
|
|
||||||
Run from anywhere:
|
- **Within the e2e folder**: `poetry run pytest -s --numprocesses auto --dist loadfile`
|
||||||
|
- **From anywhere**: `yarn trading:test:all`
|
||||||
|
|
||||||
```bash
|
## Troubleshooting
|
||||||
yarn trading:test -- "test_name" -s --headed
|
|
||||||
```
|
|
||||||
|
|
||||||
Run using your locally served console:
|
If IntelliSense is not working in VSCode, follow these steps:
|
||||||
|
|
||||||
Within one terminal
|
1. Find the Poetry environment's Python binary: `poetry run which python`
|
||||||
|
2. In VSCode, open the command menu (`cmd + shift + p`), search for `Python: Select Interpreter`, select `Enter interpreter path`, and paste the path from step 1.
|
||||||
```bash
|
|
||||||
yarn nx build trading
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn nx serve trading
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Once console is served you can update the .env file to have local_server to true.
|
|
||||||
|
|
||||||
## Running Tests in Parallel 🔢
|
|
||||||
|
|
||||||
To run tests in parallel, use the `--numprocesses auto` option. The `--dist loadfile` setting ensures that multiple runners are not assigned to a single test file.
|
|
||||||
|
|
||||||
### From within the e2e folder:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
poetry run pytest -s --numprocesses auto --dist loadfile
|
|
||||||
```
|
|
||||||
|
|
||||||
### From anywhere:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn trading:test:all
|
|
||||||
```
|
|
||||||
|
|
||||||
# Things to know
|
|
||||||
|
|
||||||
If you "intellisense" isn't working follow these steps:
|
|
||||||
|
|
||||||
1. ```bash
|
|
||||||
poetry run which python
|
|
||||||
```
|
|
||||||
|
|
||||||
2. Then open the command menu in vscode (cmd + shift + p) and type `select interpreter` , press enter, select enter interpreter path press enter then paste in the output from that above command you should get the right python again
|
|
||||||
|
|||||||
Generated
+396
-391
File diff suppressed because it is too large
Load Diff
@@ -235,7 +235,7 @@ def test_submit_stop_oco_market_order_pending(
|
|||||||
"PendingOCO"
|
"PendingOCO"
|
||||||
)
|
)
|
||||||
|
|
||||||
@pytest.mark.usefixtures("page", "continuous_market", "auth", "risk_accepted")
|
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||||
def test_submit_stop_oco_limit_order_pending(
|
def test_submit_stop_oco_limit_order_pending(
|
||||||
continuous_market, vega: VegaServiceNull, page: Page
|
continuous_market, vega: VegaServiceNull, page: Page
|
||||||
):
|
):
|
||||||
|
|||||||
@@ -15,8 +15,7 @@ deal_ticket_deposit_dialog_button = "deal-ticket-deposit-dialog-button"
|
|||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def vega(request):
|
def vega(request):
|
||||||
with init_vega(request) as vega_instance:
|
with init_vega(request) as vega_instance:
|
||||||
request.addfinalizer(lambda: cleanup_container(
|
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||||
vega_instance)) # Register the cleanup function
|
|
||||||
yield vega_instance
|
yield vega_instance
|
||||||
|
|
||||||
|
|
||||||
@@ -25,7 +24,6 @@ def continuous_market(vega):
|
|||||||
return setup_continuous_market(vega)
|
return setup_continuous_market(vega)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip("tbd - issue only on the sim, should work in vega 0.74.0")
|
|
||||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||||
def test_should_display_info_and_button_for_deposit(continuous_market, page: Page):
|
def test_should_display_info_and_button_for_deposit(continuous_market, page: Page):
|
||||||
page.goto(f"/#/markets/{continuous_market}")
|
page.goto(f"/#/markets/{continuous_market}")
|
||||||
@@ -33,17 +31,20 @@ def test_should_display_info_and_button_for_deposit(continuous_market, page: Pag
|
|||||||
page.get_by_test_id(order_price).fill("20")
|
page.get_by_test_id(order_price).fill("20")
|
||||||
# 7002-SORD-060
|
# 7002-SORD-060
|
||||||
expect(page.get_by_test_id(deal_ticket_warning_margin)).to_have_text(
|
expect(page.get_by_test_id(deal_ticket_warning_margin)).to_have_text(
|
||||||
"You may not have enough margin available to open this position.")
|
"You may not have enough margin available to open this position."
|
||||||
|
)
|
||||||
page.get_by_test_id(deal_ticket_warning_margin).hover()
|
page.get_by_test_id(deal_ticket_warning_margin).hover()
|
||||||
expect(page.get_by_test_id("tooltip-content").nth(0)).to_have_text(
|
expect(page.get_by_test_id("tooltip-content").nth(0)).to_have_text(
|
||||||
"1,661,888.12901 tDAI is currently required.You have only 999,991.49731.Deposit tDAI")
|
"1,661,888.12901 tDAI is currently required.You have only 999,991.49731.Deposit tDAI"
|
||||||
|
)
|
||||||
page.get_by_test_id(deal_ticket_deposit_dialog_button).nth(0).click()
|
page.get_by_test_id(deal_ticket_deposit_dialog_button).nth(0).click()
|
||||||
expect(page.get_by_test_id("sidebar-content")
|
expect(page.get_by_test_id("sidebar-content")).to_contain_text("DepositFrom")
|
||||||
).to_contain_text("DepositFrom")
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||||
def test_should_show_an_error_if_your_balance_is_zero(continuous_market, vega: VegaServiceNull, page: Page):
|
def test_should_show_an_error_if_your_balance_is_zero(
|
||||||
|
continuous_market, vega: VegaServiceNull, page: Page
|
||||||
|
):
|
||||||
page.goto(f"/#/markets/{continuous_market}")
|
page.goto(f"/#/markets/{continuous_market}")
|
||||||
vega.create_key("key_empty")
|
vega.create_key("key_empty")
|
||||||
change_keys(page, vega, "key_empty")
|
change_keys(page, vega, "key_empty")
|
||||||
@@ -52,6 +53,7 @@ def test_should_show_an_error_if_your_balance_is_zero(continuous_market, vega: V
|
|||||||
# 7002-SORD-060
|
# 7002-SORD-060
|
||||||
expect(page.get_by_test_id(place_order)).to_be_enabled()
|
expect(page.get_by_test_id(place_order)).to_be_enabled()
|
||||||
# 7002-SORD-003
|
# 7002-SORD-003
|
||||||
expect(page.get_by_test_id("deal-ticket-error-message-zero-balance")
|
expect(page.get_by_test_id("deal-ticket-error-message-zero-balance")).to_have_text(
|
||||||
).to_have_text("You need tDAI in your wallet to trade in this market.Make a deposit")
|
"You need tDAI in your wallet to trade in this market.Make a deposit"
|
||||||
|
)
|
||||||
expect(page.get_by_test_id(deal_ticket_deposit_dialog_button)).to_be_visible()
|
expect(page.get_by_test_id(deal_ticket_deposit_dialog_button)).to_be_visible()
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ def test_market_info_market_volume(page: Page):
|
|||||||
page.get_by_test_id(market_title_test_id).get_by_text(
|
page.get_by_test_id(market_title_test_id).get_by_text(
|
||||||
"Market volume").click()
|
"Market volume").click()
|
||||||
fields = [
|
fields = [
|
||||||
["24 Hour Volume", "-"],
|
["24 Hour Volume", "0 (0 )"],
|
||||||
["Open Interest", "1"],
|
["Open Interest", "1"],
|
||||||
["Best Bid Volume", "99"],
|
["Best Bid Volume", "99"],
|
||||||
["Best Offer Volume", "99"],
|
["Best Offer Volume", "99"],
|
||||||
@@ -107,7 +107,6 @@ def test_market_info_liquidation(page: Page):
|
|||||||
validate_info_section(page, fields)
|
validate_info_section(page, fields)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip("core issue #5681")
|
|
||||||
def test_market_info_key_details(page: Page, vega: VegaServiceNull):
|
def test_market_info_key_details(page: Page, vega: VegaServiceNull):
|
||||||
# 6002-MDET-201
|
# 6002-MDET-201
|
||||||
page.get_by_test_id(market_title_test_id).get_by_text(
|
page.get_by_test_id(market_title_test_id).get_by_text(
|
||||||
@@ -117,8 +116,6 @@ def test_market_info_key_details(page: Page, vega: VegaServiceNull):
|
|||||||
fields = [
|
fields = [
|
||||||
["Market ID", short_market_id],
|
["Market ID", short_market_id],
|
||||||
["Name", "BTC:DAI_2023"],
|
["Name", "BTC:DAI_2023"],
|
||||||
["Parent Market ID", "-"],
|
|
||||||
["Insurance Pool Fraction", "-"],
|
|
||||||
["Status", "Active"],
|
["Status", "Active"],
|
||||||
["Trading Mode", "Continuous"],
|
["Trading Mode", "Continuous"],
|
||||||
["Market Decimal Places", "5"],
|
["Market Decimal Places", "5"],
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ from actions.utils import next_epoch
|
|||||||
from wallet_config import MM_WALLET, MM_WALLET2, GOVERNANCE_WALLET
|
from wallet_config import MM_WALLET, MM_WALLET2, GOVERNANCE_WALLET
|
||||||
from vega_sim.api import governance
|
from vega_sim.api import governance
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("risk_accepted")
|
@pytest.mark.usefixtures("risk_accepted")
|
||||||
def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
|
def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
|
||||||
# 7002-SORD-001
|
# 7002-SORD-001
|
||||||
@@ -16,15 +17,18 @@ def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
|
|||||||
trading_mode = page.get_by_test_id("market-trading-mode").get_by_test_id(
|
trading_mode = page.get_by_test_id("market-trading-mode").get_by_test_id(
|
||||||
"item-value"
|
"item-value"
|
||||||
)
|
)
|
||||||
market_state = page.get_by_test_id("market-state").get_by_test_id("item-value")
|
market_state = page.get_by_test_id(
|
||||||
|
"market-state").get_by_test_id("item-value")
|
||||||
|
|
||||||
# setup market in proposed step, without liquidity provided
|
# setup market in proposed step, without liquidity provided
|
||||||
market_id = proposed_market
|
market_id = proposed_market
|
||||||
page.goto(f"/#/markets/{market_id}")
|
page.goto(f"/#/markets/{market_id}")
|
||||||
# 6002-MDET-001
|
# 6002-MDET-001
|
||||||
expect(page.get_by_test_id("header-title")).to_have_text("BTC:DAI_2023Futr")
|
expect(page.get_by_test_id("header-title")
|
||||||
|
).to_have_text("BTC:DAI_2023Futr")
|
||||||
# 6002-MDET-002
|
# 6002-MDET-002
|
||||||
expect(page.get_by_test_id("market-expiry")).to_have_text("ExpiryNot time-based")
|
expect(page.get_by_test_id("market-expiry")
|
||||||
|
).to_have_text("ExpiryNot time-based")
|
||||||
page.get_by_test_id("market-expiry").hover()
|
page.get_by_test_id("market-expiry").hover()
|
||||||
expect(page.get_by_test_id("expiry-tooltip").first).to_have_text(
|
expect(page.get_by_test_id("expiry-tooltip").first).to_have_text(
|
||||||
"This market expires when triggered by its oracle, not on a set date.View oracle specification"
|
"This market expires when triggered by its oracle, not on a set date.View oracle specification"
|
||||||
@@ -123,16 +127,16 @@ def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
|
|||||||
expect(market_state).to_have_text("Active")
|
expect(market_state).to_have_text("Active")
|
||||||
|
|
||||||
vega.update_market_state(
|
vega.update_market_state(
|
||||||
market_id = market_id,
|
market_id=market_id,
|
||||||
proposal_key = MM_WALLET.name,
|
proposal_key=MM_WALLET.name,
|
||||||
market_state = MarketStateUpdateType.Suspend,
|
market_state=MarketStateUpdateType.Suspend,
|
||||||
forward_time_to_enactment = False
|
forward_time_to_enactment=False
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
page
|
page
|
||||||
.get_by_test_id("market-banner")
|
.get_by_test_id("market-banner")
|
||||||
.get_by_test_id(f"update-state-banner-{market_id}")
|
.get_by_test_id(f"update-state-banner-{market_id}")
|
||||||
).to_be_visible()
|
).to_be_visible()
|
||||||
|
|
||||||
next_epoch(vega=vega)
|
next_epoch(vega=vega)
|
||||||
@@ -143,12 +147,14 @@ def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
|
|||||||
|
|
||||||
# banner should not show after resume
|
# banner should not show after resume
|
||||||
vega.update_market_state(
|
vega.update_market_state(
|
||||||
market_id = market_id,
|
market_id=market_id,
|
||||||
proposal_key = MM_WALLET.name,
|
proposal_key=MM_WALLET.name,
|
||||||
market_state = MarketStateUpdateType.Resume,
|
market_state=MarketStateUpdateType.Resume,
|
||||||
forward_time_to_enactment = False
|
forward_time_to_enactment=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
expect(page.get_by_test_id("market-banner")
|
||||||
|
).to_have_text(" Trading on market BTC:DAI_2023 was suspended by governance. There are open proposals to resume trading on this market.View proposals1/2")
|
||||||
next_epoch(vega=vega)
|
next_epoch(vega=vega)
|
||||||
|
|
||||||
expect(page.get_by_test_id("market-banner")).not_to_be_visible()
|
expect(page.get_by_test_id("market-banner")).not_to_be_visible()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
""" import pytest
|
import pytest
|
||||||
from playwright.sync_api import Page, expect
|
from playwright.sync_api import Page, expect
|
||||||
from vega_sim.service import PeggedOrder
|
from vega_sim.service import PeggedOrder
|
||||||
from vega_sim.null_service import VegaServiceNull
|
from vega_sim.null_service import VegaServiceNull
|
||||||
@@ -49,7 +49,7 @@ def markets(vega: VegaServiceNull):
|
|||||||
price=130,
|
price=130,
|
||||||
)
|
)
|
||||||
|
|
||||||
vega.forward("10s")
|
vega.forward("2s")
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ def markets(vega: VegaServiceNull):
|
|||||||
price=88,
|
price=88,
|
||||||
)
|
)
|
||||||
|
|
||||||
vega.forward("10s")
|
vega.forward("2s")
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -77,7 +77,7 @@ def markets(vega: VegaServiceNull):
|
|||||||
price=88,
|
price=88,
|
||||||
)
|
)
|
||||||
|
|
||||||
vega.forward("10s")
|
vega.forward("2s")
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -92,7 +92,7 @@ def markets(vega: VegaServiceNull):
|
|||||||
wait=False,
|
wait=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
vega.forward("10s")
|
vega.forward("2s")
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ def markets(vega: VegaServiceNull):
|
|||||||
volume=100,
|
volume=100,
|
||||||
price=104,
|
price=104,
|
||||||
)
|
)
|
||||||
vega.forward("10s")
|
vega.forward("2s")
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -120,7 +120,7 @@ def markets(vega: VegaServiceNull):
|
|||||||
expires_at=vega.get_blockchain_time() + 5 * 1e9,
|
expires_at=vega.get_blockchain_time() + 5 * 1e9,
|
||||||
)
|
)
|
||||||
|
|
||||||
vega.forward("10s")
|
vega.forward("2s")
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@ def markets(vega: VegaServiceNull):
|
|||||||
volume=20,
|
volume=20,
|
||||||
)
|
)
|
||||||
|
|
||||||
vega.forward("10s")
|
vega.forward("2s")
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -148,7 +148,7 @@ def markets(vega: VegaServiceNull):
|
|||||||
volume=40,
|
volume=40,
|
||||||
)
|
)
|
||||||
|
|
||||||
vega.forward("10s")
|
vega.forward("2s")
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -162,7 +162,7 @@ def markets(vega: VegaServiceNull):
|
|||||||
volume=60,
|
volume=60,
|
||||||
)
|
)
|
||||||
|
|
||||||
vega.forward("10s")
|
vega.forward("2s")
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -177,7 +177,7 @@ def markets(vega: VegaServiceNull):
|
|||||||
volume=60,
|
volume=60,
|
||||||
)
|
)
|
||||||
|
|
||||||
vega.forward("10s")
|
vega.forward("2s")
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -190,8 +190,7 @@ def markets(vega: VegaServiceNull):
|
|||||||
volume=10,
|
volume=10,
|
||||||
price=150,
|
price=150,
|
||||||
)
|
)
|
||||||
|
|
||||||
vega.forward("10s")
|
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -205,7 +204,6 @@ def markets(vega: VegaServiceNull):
|
|||||||
price=160,
|
price=160,
|
||||||
)
|
)
|
||||||
|
|
||||||
vega.forward("10s")
|
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -219,7 +217,6 @@ def markets(vega: VegaServiceNull):
|
|||||||
price=60,
|
price=60,
|
||||||
)
|
)
|
||||||
|
|
||||||
vega.forward("10s")
|
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -395,7 +392,6 @@ def test_order_amend_order(vega: VegaServiceNull, page: Page):
|
|||||||
page.get_by_role("button", name="Update").click()
|
page.get_by_role("button", name="Update").click()
|
||||||
|
|
||||||
wait_for_toast_confirmation(page, timeout=5000)
|
wait_for_toast_confirmation(page, timeout=5000)
|
||||||
vega.forward("10s")
|
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
expect(page.locator('[row-index="1"]').first).to_contain_text(
|
expect(page.locator('[row-index="1"]').first).to_contain_text(
|
||||||
@@ -414,7 +410,6 @@ def test_order_cancel_single_order(vega: VegaServiceNull, page: Page):
|
|||||||
page.get_by_test_id("cancel").first.click()
|
page.get_by_test_id("cancel").first.click()
|
||||||
|
|
||||||
wait_for_toast_confirmation(page, timeout=5000)
|
wait_for_toast_confirmation(page, timeout=5000)
|
||||||
vega.forward("10s")
|
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
expect(page.locator('[row-index="0"]').first).to_contain_text(
|
expect(page.locator('[row-index="0"]').first).to_contain_text(
|
||||||
@@ -434,7 +429,6 @@ def test_order_cancel_all_orders(vega: VegaServiceNull, page: Page):
|
|||||||
page.get_by_test_id("cancelAll").click()
|
page.get_by_test_id("cancelAll").click()
|
||||||
|
|
||||||
wait_for_toast_confirmation(page, timeout=5000)
|
wait_for_toast_confirmation(page, timeout=5000)
|
||||||
vega.forward("10s")
|
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
@@ -443,4 +437,3 @@ def test_order_cancel_all_orders(vega: VegaServiceNull, page: Page):
|
|||||||
expect(
|
expect(
|
||||||
page.locator('.ag-cell[col-id="status"]', has_text="Cancelled")
|
page.locator('.ag-cell[col-id="status"]', has_text="Cancelled")
|
||||||
).to_have_count(7)
|
).to_have_count(7)
|
||||||
"""
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
import pytest
|
import pytest
|
||||||
from playwright.sync_api import Page, expect
|
from playwright.sync_api import Page, expect
|
||||||
|
from vega_sim.null_service import VegaServiceNull
|
||||||
from typing import List
|
from typing import List
|
||||||
from actions.vega import submit_order, submit_liquidity, submit_multiple_orders
|
from actions.vega import submit_order, submit_liquidity, submit_multiple_orders
|
||||||
from conftest import init_vega, cleanup_container
|
from conftest import init_vega, cleanup_container
|
||||||
from fixtures.market import setup_simple_market
|
from fixtures.market import setup_simple_market
|
||||||
from wallet_config import MM_WALLET, MM_WALLET2
|
from wallet_config import MM_WALLET, MM_WALLET2
|
||||||
|
from actions.utils import next_epoch
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
@@ -15,7 +17,7 @@ def vega(request):
|
|||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def setup_market(vega):
|
def setup_market(vega: VegaServiceNull):
|
||||||
market_id = setup_simple_market(vega)
|
market_id = setup_simple_market(vega)
|
||||||
submit_liquidity(vega, MM_WALLET.name, market_id)
|
submit_liquidity(vega, MM_WALLET.name, market_id)
|
||||||
submit_multiple_orders(
|
submit_multiple_orders(
|
||||||
@@ -33,10 +35,9 @@ def setup_market(vega):
|
|||||||
[[10, 69.995], [5, 70], [5, 85], [3, 90], [3, 95]],
|
[[10, 69.995], [5, 70], [5, 85], [3, 90], [3, 95]],
|
||||||
)
|
)
|
||||||
|
|
||||||
vega.forward("10s")
|
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
|
||||||
return [
|
return [
|
||||||
vega,
|
vega,
|
||||||
market_id,
|
market_id,
|
||||||
@@ -46,19 +47,19 @@ def setup_market(vega):
|
|||||||
# these values don't align with the multiple orders above as
|
# these values don't align with the multiple orders above as
|
||||||
# creating a trade triggers the liquidity provision
|
# creating a trade triggers the liquidity provision
|
||||||
orderbook_content = [
|
orderbook_content = [
|
||||||
[130.00500, 10, 94],
|
[130.00500, 10, 126],
|
||||||
[130.00000, 3, 84],
|
[130.00000, 3, 116],
|
||||||
[120.00000, 7, 81],
|
[120.00000, 7, 113],
|
||||||
[110.00000, 5, 74],
|
[110.00000, 5, 106],
|
||||||
[105.00000, 2, 69],
|
[105.00000, 2, 101],
|
||||||
[101.00000, 67, 67],
|
[101.00000, 99, 99],
|
||||||
# mid
|
# mid
|
||||||
[99.00000, 102, 102],
|
[99.00000, 99, 99],
|
||||||
[95.00000, 3, 105],
|
[95.00000, 3, 102],
|
||||||
[90.00000, 3, 108],
|
[90.00000, 3, 105],
|
||||||
[85.00000, 5, 113],
|
[85.00000, 5, 110],
|
||||||
[70.00000, 5, 118],
|
[70.00000, 5, 115],
|
||||||
[69.99500, 10, 128],
|
[69.99500, 10, 125],
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
@@ -81,7 +82,6 @@ def verify_prices_descending(page: Page):
|
|||||||
assert prices == sorted(prices, reverse=True)
|
assert prices == sorted(prices, reverse=True)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip("tbd")
|
|
||||||
@pytest.mark.usefixtures("risk_accepted")
|
@pytest.mark.usefixtures("risk_accepted")
|
||||||
def test_orderbook_grid_content(setup_market, page: Page):
|
def test_orderbook_grid_content(setup_market, page: Page):
|
||||||
vega = setup_market[0]
|
vega = setup_market[0]
|
||||||
@@ -109,6 +109,7 @@ def test_orderbook_grid_content(setup_market, page: Page):
|
|||||||
|
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
|
next_epoch(vega)
|
||||||
|
|
||||||
# 6003-ORDB-001
|
# 6003-ORDB-001
|
||||||
# 6003-ORDB-002
|
# 6003-ORDB-002
|
||||||
@@ -120,7 +121,6 @@ def test_orderbook_grid_content(setup_market, page: Page):
|
|||||||
page.goto(f"/#/markets/{market_id}")
|
page.goto(f"/#/markets/{market_id}")
|
||||||
|
|
||||||
page.locator("[data-testid=Orderbook]").click()
|
page.locator("[data-testid=Orderbook]").click()
|
||||||
|
|
||||||
# 6003-ORDB-013
|
# 6003-ORDB-013
|
||||||
assert (
|
assert (
|
||||||
float(page.locator("[data-testid*=last-traded]").text_content())
|
float(page.locator("[data-testid*=last-traded]").text_content())
|
||||||
@@ -144,50 +144,46 @@ def test_orderbook_grid_content(setup_market, page: Page):
|
|||||||
def test_orderbook_resolution_change(setup_market, page: Page):
|
def test_orderbook_resolution_change(setup_market, page: Page):
|
||||||
market_id = setup_market[1]
|
market_id = setup_market[1]
|
||||||
# 6003-ORDB-008
|
# 6003-ORDB-008
|
||||||
orderbook_content_0_00 = [
|
orderbook_content_0_01 = [
|
||||||
[130.01, 10, 94],
|
[130.01, 10, 126],
|
||||||
[130.00, 3, 84],
|
[130.00, 3, 116],
|
||||||
[120.00, 7, 81],
|
[120.00, 7, 113],
|
||||||
[110.00, 5, 74],
|
[110.00, 5, 106],
|
||||||
[105.00, 2, 69],
|
[105.00, 2, 101],
|
||||||
[101.00, 67, 67],
|
[101.00, 99, 99],
|
||||||
# mid
|
# mid
|
||||||
[99.00, 102, 102],
|
[99.00, 99, 99],
|
||||||
[95.00, 3, 105],
|
[95.00, 3, 102],
|
||||||
[90.00, 3, 108],
|
[90.00, 3, 105],
|
||||||
[85.00, 5, 113],
|
[85.00, 5, 110],
|
||||||
[70.00, 15, 128],
|
[70.00, 15, 125],
|
||||||
]
|
]
|
||||||
|
|
||||||
orderbook_content_10 = [
|
orderbook_content_1 = [
|
||||||
[130, 13, 94],
|
[130, 13, 126],
|
||||||
[120, 7, 81],
|
[120, 7, 113],
|
||||||
[110, 7, 74],
|
[110, 5, 106],
|
||||||
[100, 67, 67],
|
[105, 2, 101],
|
||||||
|
[101, 99, 99],
|
||||||
# mid
|
# mid
|
||||||
[100, 105, 105],
|
[99, 99, 99],
|
||||||
[90, 8, 113],
|
[95, 3, 102],
|
||||||
[70, 15, 128],
|
[90, 3, 105],
|
||||||
|
[85, 5, 110],
|
||||||
|
[70, 15, 125],
|
||||||
]
|
]
|
||||||
|
|
||||||
orderbook_content_100 = [
|
|
||||||
[100, 94, 94],
|
|
||||||
# mid
|
|
||||||
[100, 128, 128],
|
|
||||||
]
|
|
||||||
|
|
||||||
resolutions = [
|
resolutions = [
|
||||||
["0.00", orderbook_content_0_00],
|
["0.01", orderbook_content_0_01],
|
||||||
["10", orderbook_content_10],
|
["1", orderbook_content_1],
|
||||||
["100", orderbook_content_100],
|
|
||||||
]
|
]
|
||||||
|
|
||||||
page.goto(f"/#/markets/{market_id}")
|
page.goto(f"/#/markets/{market_id}")
|
||||||
# temporary skip
|
for resolution in resolutions:
|
||||||
# for resolution in resolutions:
|
page.get_by_test_id("resolution").click()
|
||||||
# page.get_by_test_id("resolution").click()
|
page.get_by_role("menuitem").get_by_text(resolution[0], exact=True).click()
|
||||||
# page.get_by_role("menu").get_by_text(resolution[0], exact=True).click()
|
verify_orderbook_grid(page, resolution[1])
|
||||||
# verify_orderbook_grid(page, resolution[1])
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("risk_accepted")
|
@pytest.mark.usefixtures("risk_accepted")
|
||||||
@@ -209,7 +205,6 @@ def test_orderbook_price_size_copy(setup_market, page: Page):
|
|||||||
expect(page.get_by_test_id("order-size")).to_have_value(volume.text_content())
|
expect(page.get_by_test_id("order-size")).to_have_value(volume.text_content())
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.skip("tbd")
|
|
||||||
@pytest.mark.usefixtures("risk_accepted")
|
@pytest.mark.usefixtures("risk_accepted")
|
||||||
def test_orderbook_price_movement(setup_market, page: Page):
|
def test_orderbook_price_movement(setup_market, page: Page):
|
||||||
vega = setup_market[0]
|
vega = setup_market[0]
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ def setup_market_and_referral_scheme(vega: VegaServiceNull, continuous_market: s
|
|||||||
forward_time(vega)
|
forward_time(vega)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||||
def test_can_traverse_up_and_down_through_tiers(continuous_market, vega: VegaServiceNull, page: Page):
|
def test_can_traverse_up_and_down_through_tiers(continuous_market, vega: VegaServiceNull, page: Page):
|
||||||
setup_market_and_referral_scheme(vega, continuous_market, page)
|
setup_market_and_referral_scheme(vega, continuous_market, page)
|
||||||
change_keys(page, vega, PARTY_B.name)
|
change_keys(page, vega, PARTY_B.name)
|
||||||
@@ -163,7 +163,7 @@ def test_can_traverse_up_and_down_through_tiers(continuous_market, vega: VegaSer
|
|||||||
"1%", "1", "1%", "0", "1", "1"))
|
"1%", "1", "1%", "0", "1", "1"))
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.usefixtures("page", "auth", "risk_accepted")
|
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||||
def test_does_not_move_up_tiers_when_not_enough_epochs(continuous_market, vega: VegaServiceNull, page: Page):
|
def test_does_not_move_up_tiers_when_not_enough_epochs(continuous_market, vega: VegaServiceNull, page: Page):
|
||||||
setup_market_and_referral_scheme(vega, continuous_market, page)
|
setup_market_and_referral_scheme(vega, continuous_market, page)
|
||||||
change_keys(page, vega, PARTY_B.name)
|
change_keys(page, vega, PARTY_B.name)
|
||||||
|
|||||||
@@ -52,8 +52,25 @@ def setup_teams_and_games(vega: VegaServiceNull):
|
|||||||
vega.update_network_parameter(
|
vega.update_network_parameter(
|
||||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
next_epoch(vega=vega)
|
next_epoch(vega=vega)
|
||||||
|
vega.create_asset(
|
||||||
|
MM_WALLET.name,
|
||||||
|
name="VEGA",
|
||||||
|
symbol="VEGA",
|
||||||
|
decimals=5,
|
||||||
|
max_faucet_amount=1e10,
|
||||||
|
quantum=100000,
|
||||||
|
)
|
||||||
|
|
||||||
|
vega.wait_fn(1)
|
||||||
|
vega.wait_for_total_catchup()
|
||||||
|
VEGA_asset_id = vega.find_asset_id(symbol="VEGA")
|
||||||
|
vega.mint(PARTY_A.name, VEGA_asset_id, 1e5)
|
||||||
|
vega.mint(PARTY_B.name, VEGA_asset_id, 1e5)
|
||||||
|
vega.wait_fn(1)
|
||||||
|
vega.wait_for_total_catchup()
|
||||||
team_name = create_team(vega)
|
team_name = create_team(vega)
|
||||||
|
|
||||||
next_epoch(vega)
|
next_epoch(vega)
|
||||||
@@ -101,7 +118,7 @@ def setup_teams_and_games(vega: VegaServiceNull):
|
|||||||
from_key_name=PARTY_A.name,
|
from_key_name=PARTY_A.name,
|
||||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||||
asset=tDAI_asset_id,
|
asset=VEGA_asset_id,
|
||||||
reference="reward",
|
reference="reward",
|
||||||
asset_for_metric=tDAI_asset_id,
|
asset_for_metric=tDAI_asset_id,
|
||||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||||
@@ -119,7 +136,7 @@ def setup_teams_and_games(vega: VegaServiceNull):
|
|||||||
from_key_name=PARTY_B.name,
|
from_key_name=PARTY_B.name,
|
||||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||||
asset=tDAI_asset_id,
|
asset=VEGA_asset_id,
|
||||||
reference="reward",
|
reference="reward",
|
||||||
asset_for_metric=tDAI_asset_id,
|
asset_for_metric=tDAI_asset_id,
|
||||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||||
@@ -288,6 +305,7 @@ def test_game_card(competitions_page: Page):
|
|||||||
expect(game_1.get_by_test_id("entity-scope")).to_have_text("Individual")
|
expect(game_1.get_by_test_id("entity-scope")).to_have_text("Individual")
|
||||||
expect(game_1.get_by_test_id("locked-for")).to_have_text("1 epoch")
|
expect(game_1.get_by_test_id("locked-for")).to_have_text("1 epoch")
|
||||||
expect(game_1.get_by_test_id("reward-value")).to_have_text("100.00")
|
expect(game_1.get_by_test_id("reward-value")).to_have_text("100.00")
|
||||||
|
expect(game_1.get_by_test_id("reward-asset")).to_have_text("VEGA")
|
||||||
expect(game_1.get_by_test_id("distribution-strategy")).to_have_text("Pro rata")
|
expect(game_1.get_by_test_id("distribution-strategy")).to_have_text("Pro rata")
|
||||||
expect(game_1.get_by_test_id("dispatch-metric-info")).to_have_text(
|
expect(game_1.get_by_test_id("dispatch-metric-info")).to_have_text(
|
||||||
"Price maker fees paid • tDAI"
|
"Price maker fees paid • tDAI"
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { ENV, Networks } from '@vegaprotocol/environment';
|
||||||
|
|
||||||
|
const TEAMS_STATS_EPOCHS_MAINNET = 30;
|
||||||
|
const TEAMS_STATS_EPOCHS_TESTNET = 192;
|
||||||
|
export const TEAMS_STATS_EPOCHS =
|
||||||
|
ENV.VEGA_ENV === Networks.MAINNET
|
||||||
|
? TEAMS_STATS_EPOCHS_MAINNET
|
||||||
|
: TEAMS_STATS_EPOCHS_TESTNET;
|
||||||
@@ -7,8 +7,7 @@ import orderBy from 'lodash/orderBy';
|
|||||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||||
import { useEpochInfoQuery } from './__generated__/Epoch';
|
import { useEpochInfoQuery } from './__generated__/Epoch';
|
||||||
import { type ApolloError } from '@apollo/client';
|
import { type ApolloError } from '@apollo/client';
|
||||||
|
import { TEAMS_STATS_EPOCHS } from './constants';
|
||||||
const TAKE_EPOCHS = 30; // TODO: should this be DEFAULT_AGGREGATION_EPOCHS?
|
|
||||||
|
|
||||||
const findTeam = (entities: GameFieldsFragment['entities'], teamId: string) => {
|
const findTeam = (entities: GameFieldsFragment['entities'], teamId: string) => {
|
||||||
const team = entities.find(
|
const team = entities.find(
|
||||||
@@ -45,7 +44,7 @@ export const useGames = (teamId?: string, epochFrom?: number): GamesData => {
|
|||||||
|
|
||||||
let from = epochFrom;
|
let from = epochFrom;
|
||||||
if (!from && epochData) {
|
if (!from && epochData) {
|
||||||
from = Number(epochData.epoch.id) - TAKE_EPOCHS;
|
from = Number(epochData.epoch.id) - TEAMS_STATS_EPOCHS;
|
||||||
if (from < 1) from = 1; // make sure it's not negative
|
if (from < 1) from = 1; // make sure it's not negative
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export type RewardTransfer = TransferNode & {
|
|||||||
|
|
||||||
export type EnrichedRewardTransfer = RewardTransfer & {
|
export type EnrichedRewardTransfer = RewardTransfer & {
|
||||||
/** Dispatch metric asset (reward asset) */
|
/** Dispatch metric asset (reward asset) */
|
||||||
asset?: AssetFieldsFragment;
|
dispatchAsset?: AssetFieldsFragment;
|
||||||
/** A flag determining whether a reward asset is being traded on any of the active markets */
|
/** A flag determining whether a reward asset is being traded on any of the active markets */
|
||||||
isAssetTraded?: boolean;
|
isAssetTraded?: boolean;
|
||||||
/** A list of markets in scope */
|
/** A list of markets in scope */
|
||||||
@@ -142,9 +142,10 @@ export const useRewards = ({
|
|||||||
.filter((node) => (scopeToTeams ? isScopedToTeams(node) : true))
|
.filter((node) => (scopeToTeams ? isScopedToTeams(node) : true))
|
||||||
// enrich with dispatch asset and markets in scope details
|
// enrich with dispatch asset and markets in scope details
|
||||||
.map((node) => {
|
.map((node) => {
|
||||||
const asset =
|
const dispatchAsset =
|
||||||
assets &&
|
(assets &&
|
||||||
assets[node.transfer.kind.dispatchStrategy.dispatchMetricAssetId];
|
assets[node.transfer.kind.dispatchStrategy.dispatchMetricAssetId]) ||
|
||||||
|
undefined;
|
||||||
const marketsInScope = compact(
|
const marketsInScope = compact(
|
||||||
node.transfer.kind.dispatchStrategy.marketIdsInScope?.map(
|
node.transfer.kind.dispatchStrategy.marketIdsInScope?.map(
|
||||||
(id) => markets && markets[id]
|
(id) => markets && markets[id]
|
||||||
@@ -167,7 +168,7 @@ export const useRewards = ({
|
|||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
...node,
|
...node,
|
||||||
asset: asset ? asset : undefined,
|
dispatchAsset,
|
||||||
isAssetTraded: isAssetTraded != null ? isAssetTraded : undefined,
|
isAssetTraded: isAssetTraded != null ? isAssetTraded : undefined,
|
||||||
markets: marketsInScope.length > 0 ? marketsInScope : undefined,
|
markets: marketsInScope.length > 0 ? marketsInScope : undefined,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import {
|
|||||||
type TeamRefereeFieldsFragment,
|
type TeamRefereeFieldsFragment,
|
||||||
type TeamMemberStatsFieldsFragment,
|
type TeamMemberStatsFieldsFragment,
|
||||||
} from './__generated__/Team';
|
} from './__generated__/Team';
|
||||||
import { DEFAULT_AGGREGATION_EPOCHS } from './use-teams';
|
import { TEAMS_STATS_EPOCHS } from './constants';
|
||||||
|
|
||||||
export type Team = TeamFieldsFragment;
|
export type Team = TeamFieldsFragment;
|
||||||
export type TeamStats = TeamStatsFieldsFragment;
|
export type TeamStats = TeamStatsFieldsFragment;
|
||||||
@@ -22,7 +22,7 @@ export const useTeam = (teamId?: string, partyId?: string) => {
|
|||||||
variables: {
|
variables: {
|
||||||
teamId: teamId || '',
|
teamId: teamId || '',
|
||||||
partyId,
|
partyId,
|
||||||
aggregationEpochs: DEFAULT_AGGREGATION_EPOCHS,
|
aggregationEpochs: TEAMS_STATS_EPOCHS,
|
||||||
},
|
},
|
||||||
skip: !teamId,
|
skip: !teamId,
|
||||||
fetchPolicy: 'cache-and-network',
|
fetchPolicy: 'cache-and-network',
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ import { useTeamsQuery } from './__generated__/Teams';
|
|||||||
import { useTeamsStatisticsQuery } from './__generated__/TeamsStatistics';
|
import { useTeamsStatisticsQuery } from './__generated__/TeamsStatistics';
|
||||||
import compact from 'lodash/compact';
|
import compact from 'lodash/compact';
|
||||||
import { type TeamStatsFieldsFragment } from './__generated__/Team';
|
import { type TeamStatsFieldsFragment } from './__generated__/Team';
|
||||||
|
import { TEAMS_STATS_EPOCHS } from './constants';
|
||||||
// 192
|
|
||||||
export const DEFAULT_AGGREGATION_EPOCHS = 192;
|
|
||||||
|
|
||||||
const EMPTY_STATS: Partial<TeamStatsFieldsFragment> = {
|
const EMPTY_STATS: Partial<TeamStatsFieldsFragment> = {
|
||||||
totalQuantumVolume: '0',
|
totalQuantumVolume: '0',
|
||||||
@@ -16,7 +14,7 @@ const EMPTY_STATS: Partial<TeamStatsFieldsFragment> = {
|
|||||||
quantumRewards: [],
|
quantumRewards: [],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useTeams = (aggregationEpochs = DEFAULT_AGGREGATION_EPOCHS) => {
|
export const useTeams = (aggregationEpochs = TEAMS_STATS_EPOCHS) => {
|
||||||
const {
|
const {
|
||||||
data: teamsData,
|
data: teamsData,
|
||||||
loading: teamsLoading,
|
loading: teamsLoading,
|
||||||
|
|||||||
@@ -62,3 +62,10 @@ export const DENY_LIST: Record<string, string[]> = {
|
|||||||
'fdf0ec118d98393a7702cf72e46fc87ad680b152f64b2aac59e093ac2d688fbb',
|
'fdf0ec118d98393a7702cf72e46fc87ad680b152f64b2aac59e093ac2d688fbb',
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We need a record of USDT on mainnet as it needs special handling for
|
||||||
|
// deposits and approvals due to the contract not conforming exactly
|
||||||
|
// to ERC20
|
||||||
|
export const USDT_ID = {
|
||||||
|
MAINNET: 'bf1e88d19db4b3ca0d1d5bdb73718a01686b18cf731ca26adedf3c8b83802bba',
|
||||||
|
} as const;
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ function waitForStake(vegaPublicKey: string) {
|
|||||||
let tick = 1;
|
let tick = 1;
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
log(`confirming stake (attempt: ${tick})`);
|
log(`confirming stake (attempt: ${tick})`);
|
||||||
if (tick >= 30) {
|
if (tick >= 90) {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
reject(new Error('stake link never seen'));
|
reject(new Error('stake link never seen'));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export const addCreateMarket = () => {
|
|||||||
cy.highlight('creating market on capsule environment');
|
cy.highlight('creating market on capsule environment');
|
||||||
|
|
||||||
cy.wrap(createMarket(config), {
|
cy.wrap(createMarket(config), {
|
||||||
timeout: 5 * 60 * 1000,
|
timeout: 9 * 60 * 1000,
|
||||||
})
|
})
|
||||||
// register market list result so it can be retrieved in tests later
|
// register market list result so it can be retrieved in tests later
|
||||||
.as('markets');
|
.as('markets');
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ export const addValidatorsSelfDelegate = () => {
|
|||||||
String(node0ApiToken),
|
String(node0ApiToken),
|
||||||
String(node0Id)
|
String(node0Id)
|
||||||
),
|
),
|
||||||
{ timeout: 60000 }
|
{ timeout: 90000 }
|
||||||
);
|
);
|
||||||
// Self delegating Node 1 wallet
|
// Self delegating Node 1 wallet
|
||||||
cy.get('@node1PubKey').then((node1PubKey) => {
|
cy.get('@node1PubKey').then((node1PubKey) => {
|
||||||
@@ -124,7 +124,7 @@ export const addValidatorsSelfDelegate = () => {
|
|||||||
String(node1ApiToken),
|
String(node1ApiToken),
|
||||||
String(node1Id)
|
String(node1Id)
|
||||||
),
|
),
|
||||||
{ timeout: 60000 }
|
{ timeout: 90000 }
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import type { Asset } from '@vegaprotocol/assets';
|
import { USDT_ID, type Asset } from '@vegaprotocol/assets';
|
||||||
import { EtherscanLink } from '@vegaprotocol/environment';
|
import {
|
||||||
|
EtherscanLink,
|
||||||
|
Networks,
|
||||||
|
useEnvironment,
|
||||||
|
} from '@vegaprotocol/environment';
|
||||||
import { Intent, Notification } from '@vegaprotocol/ui-toolkit';
|
import { Intent, Notification } from '@vegaprotocol/ui-toolkit';
|
||||||
import {
|
import {
|
||||||
formatNumber,
|
formatNumber,
|
||||||
@@ -15,7 +19,7 @@ import { useT } from './use-t';
|
|||||||
interface ApproveNotificationProps {
|
interface ApproveNotificationProps {
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
selectedAsset?: Asset;
|
selectedAsset?: Asset;
|
||||||
onApprove: () => void;
|
onApprove: (amount?: string) => void;
|
||||||
approved: boolean;
|
approved: boolean;
|
||||||
balances: DepositBalances | null;
|
balances: DepositBalances | null;
|
||||||
amount: string;
|
amount: string;
|
||||||
@@ -33,6 +37,7 @@ export const ApproveNotification = ({
|
|||||||
approveTxId,
|
approveTxId,
|
||||||
intent = Intent.Warning,
|
intent = Intent.Warning,
|
||||||
}: ApproveNotificationProps) => {
|
}: ApproveNotificationProps) => {
|
||||||
|
const { VEGA_ENV } = useEnvironment();
|
||||||
const t = useT();
|
const t = useT();
|
||||||
const tx = useEthTransactionStore((state) => {
|
const tx = useEthTransactionStore((state) => {
|
||||||
return state.transactions.find((t) => t?.id === approveTxId);
|
return state.transactions.find((t) => t?.id === approveTxId);
|
||||||
@@ -64,28 +69,45 @@ export const ApproveNotification = ({
|
|||||||
text: t('Approve {{assetSymbol}}', {
|
text: t('Approve {{assetSymbol}}', {
|
||||||
assetSymbol: selectedAsset?.symbol,
|
assetSymbol: selectedAsset?.symbol,
|
||||||
}),
|
}),
|
||||||
action: onApprove,
|
action: () => onApprove(),
|
||||||
dataTestId: 'approve-submit',
|
dataTestId: 'approve-submit',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let message = t('Approve again to deposit more than {{allowance}}', {
|
||||||
|
allowance: formatNumber(balances.allowance.toString()),
|
||||||
|
});
|
||||||
|
const buttonProps = {
|
||||||
|
size: 'small' as const,
|
||||||
|
text: t('Approve {{assetSymbol}}', {
|
||||||
|
assetSymbol: selectedAsset?.symbol,
|
||||||
|
}),
|
||||||
|
action: () => onApprove(),
|
||||||
|
dataTestId: 'reapprove-submit',
|
||||||
|
};
|
||||||
|
|
||||||
|
if (VEGA_ENV === Networks.MAINNET && selectedAsset.id === USDT_ID[VEGA_ENV]) {
|
||||||
|
message = t(
|
||||||
|
'USDT approved amount cannot be changed, only revoked. Revoke and reapprove to deposit more than {{allowance}}.',
|
||||||
|
{
|
||||||
|
allowance: formatNumber(balances.allowance.toString()),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
buttonProps.text = t('Revoke {{assetSymbol}} approval', {
|
||||||
|
assetSymbol: selectedAsset?.symbol,
|
||||||
|
});
|
||||||
|
buttonProps.action = () => onApprove('0');
|
||||||
|
}
|
||||||
|
|
||||||
const reApprovePrompt = (
|
const reApprovePrompt = (
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
<Notification
|
<Notification
|
||||||
intent={intent}
|
intent={intent}
|
||||||
testId="reapprove-default"
|
testId="reapprove-default"
|
||||||
message={t('Approve again to deposit more than {{allowance}}', {
|
message={message}
|
||||||
allowance: formatNumber(balances.allowance.toString()),
|
buttonProps={buttonProps}
|
||||||
})}
|
|
||||||
buttonProps={{
|
|
||||||
size: 'small',
|
|
||||||
text: t('Approve {{assetSymbol}}', {
|
|
||||||
assetSymbol: selectedAsset?.symbol,
|
|
||||||
}),
|
|
||||||
action: onApprove,
|
|
||||||
dataTestId: 'reapprove-submit',
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export interface DepositFormProps {
|
|||||||
onSelectAsset: (assetId: string) => void;
|
onSelectAsset: (assetId: string) => void;
|
||||||
handleAmountChange: (amount: string) => void;
|
handleAmountChange: (amount: string) => void;
|
||||||
onDisconnect: () => void;
|
onDisconnect: () => void;
|
||||||
submitApprove: () => void;
|
submitApprove: (amount?: string) => void;
|
||||||
approveTxId: number | null;
|
approveTxId: number | null;
|
||||||
submitFaucet: () => void;
|
submitFaucet: () => void;
|
||||||
faucetTxId: number | null;
|
faucetTxId: number | null;
|
||||||
@@ -423,8 +423,8 @@ export const DepositForm = ({
|
|||||||
isActive={isActive}
|
isActive={isActive}
|
||||||
approveTxId={approveTxId}
|
approveTxId={approveTxId}
|
||||||
selectedAsset={selectedAsset}
|
selectedAsset={selectedAsset}
|
||||||
onApprove={() => {
|
onApprove={(amount) => {
|
||||||
submitApprove();
|
submitApprove(amount);
|
||||||
setApproveNotificationIntent(Intent.Warning);
|
setApproveNotificationIntent(Intent.Warning);
|
||||||
}}
|
}}
|
||||||
balances={balances}
|
balances={balances}
|
||||||
|
|||||||
@@ -35,11 +35,11 @@ export const useSubmitApproval = (
|
|||||||
reset: () => {
|
reset: () => {
|
||||||
setId(null);
|
setId(null);
|
||||||
},
|
},
|
||||||
perform: () => {
|
perform: (amount?: string) => {
|
||||||
if (!asset || !config) return;
|
if (!asset || !config) return;
|
||||||
const id = createEthTransaction(contract, 'approve', [
|
const id = createEthTransaction(contract, 'approve', [
|
||||||
config?.collateral_bridge_contract.address,
|
config?.collateral_bridge_contract.address,
|
||||||
MaxUint256.toString(),
|
amount ? amount : MaxUint256.toString(),
|
||||||
]);
|
]);
|
||||||
setId(id);
|
setId(id);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -134,6 +134,7 @@ export const CONSOLE_TRANSFER = '#/portfolio/assets/transfer';
|
|||||||
export const CONSOLE_TRANSFER_ASSET =
|
export const CONSOLE_TRANSFER_ASSET =
|
||||||
'#/portfolio/assets/transfer?assetId=:assetId';
|
'#/portfolio/assets/transfer?assetId=:assetId';
|
||||||
export const CONSOLE_MARKET_PAGE = '#/markets/:marketId';
|
export const CONSOLE_MARKET_PAGE = '#/markets/:marketId';
|
||||||
|
export const CONSOLE_REWARDS_PAGE = '#/rewards';
|
||||||
|
|
||||||
// Governance pages
|
// Governance pages
|
||||||
export const TOKEN_NEW_MARKET_PROPOSAL = '/proposals/propose/new-market';
|
export const TOKEN_NEW_MARKET_PROPOSAL = '/proposals/propose/new-market';
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
"Approval failed": "Approval failed",
|
"Approval failed": "Approval failed",
|
||||||
"Approve {{assetSymbol}}": "Approve {{assetSymbol}}",
|
"Approve {{assetSymbol}}": "Approve {{assetSymbol}}",
|
||||||
"Approve again to deposit more than {{allowance}}": "Approve again to deposit more than {{allowance}}",
|
"Approve again to deposit more than {{allowance}}": "Approve again to deposit more than {{allowance}}",
|
||||||
|
"USDT approved amount cannot be changed, only revoked. Revoke and reapprove to deposit more than {{allowance}}.": "USDT approved amount cannot be changed, only revoked. Revoke and reapprove to deposit more than {{allowance}}.",
|
||||||
"Asset": "Asset",
|
"Asset": "Asset",
|
||||||
"Balance available": "Balance available",
|
"Balance available": "Balance available",
|
||||||
"Before you can make a deposit of your chosen asset, {{assetSymbol}}, you need to approve its use in your Ethereum wallet": "Before you can make a deposit of your chosen asset, {{assetSymbol}}, you need to approve its use in your Ethereum wallet",
|
"Before you can make a deposit of your chosen asset, {{assetSymbol}}, you need to approve its use in your Ethereum wallet": "Before you can make a deposit of your chosen asset, {{assetSymbol}}, you need to approve its use in your Ethereum wallet",
|
||||||
@@ -23,6 +24,7 @@
|
|||||||
"Please select": "Please select",
|
"Please select": "Please select",
|
||||||
"Please select an asset": "Please select an asset",
|
"Please select an asset": "Please select an asset",
|
||||||
"Remaining deposit allowance": "Remaining deposit allowance",
|
"Remaining deposit allowance": "Remaining deposit allowance",
|
||||||
|
"Revoke {{assetSymbol}} approval": "Revoke {{assetSymbol}} approval",
|
||||||
"Select from wallet": "Select from wallet",
|
"Select from wallet": "Select from wallet",
|
||||||
"The {{symbol}} faucet is not available at this time": "The {{symbol}} faucet is not available at this time",
|
"The {{symbol}} faucet is not available at this time": "The {{symbol}} faucet is not available at this time",
|
||||||
"The deposit cap is set when you approve an asset for use with this app. To increase this cap, approve {{assetSymbol}} again and choose a higher cap. Check the documentation for your Ethereum wallet app for details.": "The deposit cap is set when you approve an asset for use with this app. To increase this cap, approve {{assetSymbol}} again and choose a higher cap. Check the documentation for your Ethereum wallet app for details.",
|
"The deposit cap is set when you approve an asset for use with this app. To increase this cap, approve {{assetSymbol}} again and choose a higher cap. Check the documentation for your Ethereum wallet app for details.": "The deposit cap is set when you approve an asset for use with this app. To increase this cap, approve {{assetSymbol}} again and choose a higher cap. Check the documentation for your Ethereum wallet app for details.",
|
||||||
|
|||||||
@@ -391,6 +391,8 @@
|
|||||||
"multisigContractIncorrect": "was incorrectly configured as at the end of the last epoch so rewards were penalised. Validator and delegator rewards will continue to be penalised until this is resolved.",
|
"multisigContractIncorrect": "was incorrectly configured as at the end of the last epoch so rewards were penalised. Validator and delegator rewards will continue to be penalised until this is resolved.",
|
||||||
"multisigContractLink": "Ethereum Multisig Contract",
|
"multisigContractLink": "Ethereum Multisig Contract",
|
||||||
"multisigPenalty": "Multisig penalty",
|
"multisigPenalty": "Multisig penalty",
|
||||||
|
"multisigPenaltyThisNodeIndicator": "The multisig score for this node is equal to zero.",
|
||||||
|
"multisigPenaltyDescription": "The multisig score is used in the calculation of rewards. For each validator that gets a multisig score of zero, no staking rewards are paid to that consensus validators and their nominators until the epoch following the one in which the configuration issue is resolved.",
|
||||||
"myPendingStake": "My pending stake",
|
"myPendingStake": "My pending stake",
|
||||||
"myStake": "My stake",
|
"myStake": "My stake",
|
||||||
"n/a": "N/A",
|
"n/a": "N/A",
|
||||||
@@ -967,5 +969,6 @@
|
|||||||
"YourIdentityAnonymous": "Your identity is always anonymous on Vega",
|
"YourIdentityAnonymous": "Your identity is always anonymous on Vega",
|
||||||
"yourStake": "Your stake",
|
"yourStake": "Your stake",
|
||||||
"yourVote": "Your vote",
|
"yourVote": "Your vote",
|
||||||
"youVoted": "You voted"
|
"youVoted": "You voted",
|
||||||
|
"rewardsMovedNotification": "Trading and liquidity rewards have moved. Visit <0>Console</0> to view your rewards."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
{
|
{
|
||||||
"{{liquidityPriceRange}} of mid price": "{{liquidityPriceRange}} of mid price",
|
"{{liquidityPriceRange}} of mid price": "{{liquidityPriceRange}} of mid price",
|
||||||
"{{probability}} probability price bounds": "{{probability}} probability price bounds",
|
"{{probability}} probability price bounds": "{{probability}} probability price bounds",
|
||||||
"24 hour change is unavailable at this time. The price change in the last 120 hours is:": "24 hour change is unavailable at this time. The price change in the last 120 hours is:",
|
|
||||||
"24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}": "24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}",
|
|
||||||
"A concept derived from traditional markets. It is a calculated value for the ‘current market price’ on a market.": "A concept derived from traditional markets. It is a calculated value for the ‘current market price’ on a market.",
|
"A concept derived from traditional markets. It is a calculated value for the ‘current market price’ on a market.": "A concept derived from traditional markets. It is a calculated value for the ‘current market price’ on a market.",
|
||||||
"A number that will be calculated by an appropriate stochastic risk model, dependent on the type of risk model used and its parameters.": "A number that will be calculated by an appropriate stochastic risk model, dependent on the type of risk model used and its parameters.",
|
"A number that will be calculated by an appropriate stochastic risk model, dependent on the type of risk model used and its parameters.": "A number that will be calculated by an appropriate stochastic risk model, dependent on the type of risk model used and its parameters.",
|
||||||
"A sliding penalty for how much an LP bond is slashed if an LP fails to reach the minimum SLA. This is a network parameter.": "A sliding penalty for how much an LP bond is slashed if an LP fails to reach the minimum SLA. This is a network parameter.",
|
"A sliding penalty for how much an LP bond is slashed if an LP fails to reach the minimum SLA. This is a network parameter.": "A sliding penalty for how much an LP bond is slashed if an LP fails to reach the minimum SLA. This is a network parameter.",
|
||||||
@@ -51,9 +49,6 @@
|
|||||||
"Market": "Market",
|
"Market": "Market",
|
||||||
"Market data": "Market data",
|
"Market data": "Market data",
|
||||||
"Market governance": "Market governance",
|
"Market governance": "Market governance",
|
||||||
"Market has not been active for 24 hours. The price change between {{start}} and {{end}} is:": "Market has not been active for 24 hours. The price change between {{start}} and {{end}} is:",
|
|
||||||
"Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is:": "Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is:",
|
|
||||||
"Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}": "Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}",
|
|
||||||
"Market ID": "Market ID",
|
"Market ID": "Market ID",
|
||||||
"Market price": "Market price",
|
"Market price": "Market price",
|
||||||
"Market specification": "Market specification",
|
"Market specification": "Market specification",
|
||||||
|
|||||||
@@ -2,16 +2,14 @@ import { type ReactNode } from 'react';
|
|||||||
import {
|
import {
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
formatNumberPercentage,
|
formatNumberPercentage,
|
||||||
getDateTimeFormat,
|
|
||||||
priceChange,
|
priceChange,
|
||||||
priceChangePercentage,
|
priceChangePercentage,
|
||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { PriceChangeCell, signedNumberCssClass } from '@vegaprotocol/datagrid';
|
import { signedNumberCssClass } from '@vegaprotocol/datagrid';
|
||||||
import { Tooltip, VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useCandles } from '../../hooks/use-candles';
|
import { useCandles } from '../../hooks/use-candles';
|
||||||
import BigNumber from 'bignumber.js';
|
import BigNumber from 'bignumber.js';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useT } from '../../use-t';
|
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
marketId?: string;
|
marketId?: string;
|
||||||
@@ -24,7 +22,6 @@ export const Last24hPriceChange = ({
|
|||||||
decimalPlaces,
|
decimalPlaces,
|
||||||
fallback,
|
fallback,
|
||||||
}: Props) => {
|
}: Props) => {
|
||||||
const t = useT();
|
|
||||||
const { oneDayCandles, fiveDaysCandles, error } = useCandles({
|
const { oneDayCandles, fiveDaysCandles, error } = useCandles({
|
||||||
marketId,
|
marketId,
|
||||||
});
|
});
|
||||||
@@ -35,56 +32,6 @@ export const Last24hPriceChange = ({
|
|||||||
return nonIdeal;
|
return nonIdeal;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fiveDaysCandles.length < 24) {
|
|
||||||
return (
|
|
||||||
<Tooltip
|
|
||||||
description={
|
|
||||||
<span className="justify-start">
|
|
||||||
{t(
|
|
||||||
'Market has not been active for 24 hours. The price change between {{start}} and {{end}} is:',
|
|
||||||
{
|
|
||||||
start: getDateTimeFormat().format(
|
|
||||||
new Date(fiveDaysCandles[0].periodStart)
|
|
||||||
),
|
|
||||||
end: getDateTimeFormat().format(
|
|
||||||
new Date(
|
|
||||||
fiveDaysCandles[fiveDaysCandles.length - 1].periodStart
|
|
||||||
)
|
|
||||||
),
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
<PriceChangeCell
|
|
||||||
candles={fiveDaysCandles.map((c) => c.close) || []}
|
|
||||||
decimalPlaces={decimalPlaces}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span>{nonIdeal}</span>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oneDayCandles.length < 24) {
|
|
||||||
return (
|
|
||||||
<Tooltip
|
|
||||||
description={
|
|
||||||
<span className="justify-start">
|
|
||||||
{t(
|
|
||||||
'24 hour change is unavailable at this time. The price change in the last 120 hours is:'
|
|
||||||
)}{' '}
|
|
||||||
<PriceChangeCell
|
|
||||||
candles={fiveDaysCandles.map((c) => c.close) || []}
|
|
||||||
decimalPlaces={decimalPlaces}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span>{nonIdeal}</span>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const candles = oneDayCandles?.map((c) => c.close) || [];
|
const candles = oneDayCandles?.map((c) => c.close) || [];
|
||||||
const change = priceChange(candles);
|
const change = priceChange(candles);
|
||||||
const changePercentage = priceChangePercentage(candles);
|
const changePercentage = priceChangePercentage(candles);
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import { calcCandleVolume, calcCandleVolumePrice } from '../../market-utils';
|
|||||||
import {
|
import {
|
||||||
addDecimalsFormatNumber,
|
addDecimalsFormatNumber,
|
||||||
formatNumber,
|
formatNumber,
|
||||||
getDateTimeFormat,
|
|
||||||
isNumeric,
|
isNumeric,
|
||||||
} from '@vegaprotocol/utils';
|
} from '@vegaprotocol/utils';
|
||||||
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||||
@@ -37,83 +36,6 @@ export const Last24hVolume = ({
|
|||||||
return nonIdeal;
|
return nonIdeal;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fiveDaysCandles.length < 24) {
|
|
||||||
const candleVolume = calcCandleVolume(fiveDaysCandles);
|
|
||||||
const candleVolumePrice = calcCandleVolumePrice(
|
|
||||||
fiveDaysCandles,
|
|
||||||
marketDecimals,
|
|
||||||
positionDecimalPlaces
|
|
||||||
);
|
|
||||||
const candleVolumeValue =
|
|
||||||
candleVolume && isNumeric(positionDecimalPlaces)
|
|
||||||
? addDecimalsFormatNumber(
|
|
||||||
candleVolume,
|
|
||||||
positionDecimalPlaces,
|
|
||||||
formatDecimals
|
|
||||||
)
|
|
||||||
: '-';
|
|
||||||
return (
|
|
||||||
<Tooltip
|
|
||||||
description={
|
|
||||||
<div>
|
|
||||||
<span className="flex flex-col">
|
|
||||||
{t(
|
|
||||||
'Market has not been active for 24 hours. The volume traded between {{start}} and {{end}} is {{candleVolumeValue}} for a total of {{candleVolumePrice}} {{quoteUnit}}',
|
|
||||||
{
|
|
||||||
start: getDateTimeFormat().format(
|
|
||||||
new Date(fiveDaysCandles[0].periodStart)
|
|
||||||
),
|
|
||||||
end: getDateTimeFormat().format(
|
|
||||||
new Date(
|
|
||||||
fiveDaysCandles[fiveDaysCandles.length - 1].periodStart
|
|
||||||
)
|
|
||||||
),
|
|
||||||
candleVolumeValue,
|
|
||||||
candleVolumePrice,
|
|
||||||
quoteUnit,
|
|
||||||
}
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span>{nonIdeal}</span>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oneDayCandles.length < 24) {
|
|
||||||
const candleVolume = calcCandleVolume(fiveDaysCandles);
|
|
||||||
const candleVolumePrice = calcCandleVolumePrice(
|
|
||||||
fiveDaysCandles,
|
|
||||||
marketDecimals,
|
|
||||||
positionDecimalPlaces
|
|
||||||
);
|
|
||||||
const candleVolumeValue =
|
|
||||||
candleVolume && isNumeric(positionDecimalPlaces)
|
|
||||||
? addDecimalsFormatNumber(
|
|
||||||
candleVolume,
|
|
||||||
positionDecimalPlaces,
|
|
||||||
formatDecimals
|
|
||||||
)
|
|
||||||
: '-';
|
|
||||||
return (
|
|
||||||
<Tooltip
|
|
||||||
description={
|
|
||||||
<div>
|
|
||||||
<span className="flex flex-col">
|
|
||||||
{t(
|
|
||||||
'24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}} for a total of ({{candleVolumePrice}} {{quoteUnit}})',
|
|
||||||
{ candleVolumeValue, candleVolumePrice, quoteUnit }
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span>{nonIdeal}</span>
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
const candleVolume = oneDayCandles
|
const candleVolume = oneDayCandles
|
||||||
? calcCandleVolume(oneDayCandles)
|
? calcCandleVolume(oneDayCandles)
|
||||||
: initialValue;
|
: initialValue;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user