Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3dd7496a9a | ||
|
|
80d576d484 | ||
|
|
4733bc169c | ||
|
|
2b91aebc2a | ||
|
|
375f4da541 | ||
|
|
bc413ed314 | ||
|
|
2fab3daebd | ||
|
|
2e07ada966 | ||
|
|
b81c4bc948 | ||
|
|
4f8d6bd876 | ||
|
|
52e5a37da3 | ||
|
|
22599673ec | ||
|
|
3c6a806ad3 | ||
|
|
7101d49d1d | ||
|
|
72e0cb76aa | ||
|
|
ca64516a52 | ||
|
|
55d692ea6f | ||
|
|
f235c03abe | ||
|
|
546deb0e1c | ||
|
|
042919eca9 | ||
|
|
c4a56e0de3 | ||
|
|
3c3bfb7dac | ||
|
|
196ba78806 | ||
|
|
53ac2dadee | ||
|
|
e532f88daa | ||
|
|
7b06c05853 |
@@ -25,7 +25,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
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
|
||||
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';
|
||||
|
||||
context('Proposal page', { tags: '@smoke' }, function () {
|
||||
describe('Verify elements on page', function () {
|
||||
describe.skip('Verify elements on page', function () {
|
||||
const proposalHeading = 'proposals-heading';
|
||||
const dateTimeRegex =
|
||||
/(\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 () {
|
||||
it.skip('should have link for proposal page', function () {
|
||||
it('should have link for proposal page', function () {
|
||||
cy.getByTestId('home-proposals').within(() => {
|
||||
cy.get('[href="/proposals"]')
|
||||
.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('external-link')
|
||||
.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.get('[href="/validators"]')
|
||||
.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('external-link')
|
||||
.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')
|
||||
.first()
|
||||
.should('contain.text', '2')
|
||||
.should('contain.text', '1')
|
||||
.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')
|
||||
.last()
|
||||
.should('contain.text', '2')
|
||||
.should('contain.text', '1')
|
||||
.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')
|
||||
.should('have.length', '2')
|
||||
.should('have.length', '1')
|
||||
.each(($validator) => {
|
||||
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.get('[href="/rewards"]')
|
||||
.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.get('[href="/token/withdraw"]')
|
||||
.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
|
||||
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('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.get('input').should('exist');
|
||||
cy.getByTestId('connect').should('be.disabled');
|
||||
cy.getByTestId('icon-cross').click();
|
||||
cy.getByTestId('dialog-close').click();
|
||||
});
|
||||
|
||||
it('should display eth data', function () {
|
||||
|
||||
@@ -33,12 +33,12 @@ context(
|
||||
verifyTabHighlighted(navigation.proposals);
|
||||
});
|
||||
|
||||
it.skip('should have GOVERNANCE header visible', function () {
|
||||
it('should have GOVERNANCE header visible', function () {
|
||||
verifyPageHeader('Proposals');
|
||||
});
|
||||
|
||||
// 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.url().should('include', '/proposals/propose/raw');
|
||||
cy.contains('To see Explorer data on proposals visit').within(() => {
|
||||
@@ -73,7 +73,7 @@ context(
|
||||
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
|
||||
cy.getByTestId(proposalDocumentationLink)
|
||||
.should('be.visible')
|
||||
|
||||
@@ -40,10 +40,10 @@ context('View functionality with public key', { tags: '@smoke' }, function () {
|
||||
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();
|
||||
cy.getByTestId('currency-title', { timeout: 10000 })
|
||||
.should('have.length.at.least', 4)
|
||||
.should('have.length.at.least', 2)
|
||||
.and('contain.text', 'USDC (fake)');
|
||||
});
|
||||
|
||||
|
||||
@@ -46,11 +46,11 @@ context('Validators Page - verify elements on page', function () {
|
||||
|
||||
// @ts-ignore clash between jest and cypress
|
||||
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);
|
||||
});
|
||||
|
||||
it.skip('Should have validators ON VEGA header visible', function () {
|
||||
it('Should have validators ON VEGA header visible', function () {
|
||||
verifyPageHeader('Validators');
|
||||
});
|
||||
|
||||
@@ -192,7 +192,7 @@ context('Validators Page - verify elements on page', function () {
|
||||
});
|
||||
|
||||
// 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');
|
||||
});
|
||||
|
||||
|
||||
@@ -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_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
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_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_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
|
||||
CYPRESS_FAIRGROUND=false
|
||||
@@ -33,7 +32,7 @@ LC_ALL="en_US.UTF-8"
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_PRODUCT_PERPETUALS=false
|
||||
NX_UPDATE_MARKET_STATE=false
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=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_VEGA_WALLET_URL=http://localhost:1789
|
||||
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
NX_DELEGATIONS_PAGINATION=50
|
||||
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
|
||||
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
|
||||
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-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
|
||||
|
||||
|
||||
@@ -8,14 +8,13 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_VEGA_EXPLORER_URL=#
|
||||
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_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_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
|
||||
|
||||
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_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_DOCS_URL=https://docs.vega.xyz/mainnet
|
||||
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_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||
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_VEGA_EXPLORER_URL=https://explorer.mainnet-mirror.vega.rocks
|
||||
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_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
|
||||
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_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
|
||||
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_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
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_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_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_DOCS_URL=https://docs.vega.xyz/testnet
|
||||
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_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
|
||||
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_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_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_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_WEBSOCKET_URL=wss://be.validators-testnet.vega.
|
||||
|
||||
@@ -15,19 +15,16 @@ export const CollapsibleToggle = ({
|
||||
dataTestId,
|
||||
children,
|
||||
}: CollapsibleToggleProps) => {
|
||||
const classes = classnames(
|
||||
'mb-4 transition-transform ease-in-out duration-300',
|
||||
{
|
||||
'rotate-180': toggleState,
|
||||
}
|
||||
);
|
||||
const classes = classnames('transition-transform ease-in-out duration-300', {
|
||||
'rotate-180': toggleState,
|
||||
});
|
||||
|
||||
return (
|
||||
<button
|
||||
onClick={() => setToggleState(!toggleState)}
|
||||
data-testid={dataTestId}
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex items-baseline gap-3">
|
||||
{children}
|
||||
<div className={classes} data-testid="toggle-icon-wrapper">
|
||||
<VegaIcon name={VegaIconNames.CHEVRON_DOWN} size={20} />
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import classNames from 'classnames';
|
||||
import { type ReactNode } from 'react';
|
||||
|
||||
interface HeadingProps {
|
||||
title?: string;
|
||||
title?: ReactNode;
|
||||
centerContent?: boolean;
|
||||
marginTop?: boolean;
|
||||
marginBottom?: boolean;
|
||||
|
||||
@@ -4,7 +4,6 @@ import keyBy from 'lodash/keyBy';
|
||||
import uniq from 'lodash/uniq';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ENV } from '../../config';
|
||||
|
||||
import noIcon from '../../images/token-no-icon.png';
|
||||
import vegaBlack from '../../images/vega_black.png';
|
||||
@@ -37,7 +36,6 @@ export const usePollForDelegations = () => {
|
||||
const { t } = useTranslation();
|
||||
const { pubKey } = useVegaWallet();
|
||||
const client = useApolloClient();
|
||||
const { delegationsPagination } = ENV;
|
||||
const [delegations, setDelegations] = React.useState<
|
||||
WalletDelegationFieldsFragment[]
|
||||
>([]);
|
||||
@@ -68,11 +66,9 @@ export const usePollForDelegations = () => {
|
||||
query: DelegationsDocument,
|
||||
variables: {
|
||||
partyId: pubKey,
|
||||
delegationsPagination: delegationsPagination
|
||||
? {
|
||||
first: Number(delegationsPagination),
|
||||
}
|
||||
: undefined,
|
||||
delegationsPagination: {
|
||||
first: 50,
|
||||
},
|
||||
},
|
||||
fetchPolicy: 'network-only',
|
||||
})
|
||||
@@ -236,14 +232,14 @@ export const usePollForDelegations = () => {
|
||||
// will just continue to fail
|
||||
clearInterval(interval);
|
||||
});
|
||||
}, 1000);
|
||||
}, 20000);
|
||||
}
|
||||
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
mounted = false;
|
||||
};
|
||||
}, [delegationsPagination, client, decimals, pubKey, t, vegaToken.address]);
|
||||
}, [client, decimals, pubKey, t, vegaToken.address]);
|
||||
|
||||
return { delegations, currentStakeAvailable, delegatedNodes, accounts };
|
||||
};
|
||||
|
||||
@@ -65,7 +65,6 @@ export const ENV = {
|
||||
docsUrl: windowOrDefault('NX_VEGA_DOCS_URL'),
|
||||
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
|
||||
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
|
||||
delegationsPagination: windowOrDefault('NX_DELEGATIONS_PAGINATION'),
|
||||
rest: windowOrDefault('NX_VEGA_REST_URL'),
|
||||
addresses:
|
||||
ContractAddresses[(envName === 'local' ? 'CUSTOM' : envName) as Networks],
|
||||
|
||||
@@ -20,6 +20,7 @@ describe('getMultisigStatus', () => {
|
||||
expect(result).toEqual({
|
||||
multisigStatus: MultisigStatus.noNodes,
|
||||
showMultisigStatusError: true,
|
||||
zeroScoreNodes: [],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -35,6 +36,7 @@ describe('getMultisigStatus', () => {
|
||||
expect(result).toEqual({
|
||||
multisigStatus: MultisigStatus.correct,
|
||||
showMultisigStatusError: false,
|
||||
zeroScoreNodes: [],
|
||||
});
|
||||
});
|
||||
|
||||
@@ -50,6 +52,22 @@ describe('getMultisigStatus', () => {
|
||||
expect(result).toEqual({
|
||||
multisigStatus: MultisigStatus.nodeNeedsRemoving,
|
||||
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({
|
||||
multisigStatus: MultisigStatus.nodeNeedsAdding,
|
||||
showMultisigStatusError: true,
|
||||
zeroScoreNodes: [
|
||||
{
|
||||
id: '1',
|
||||
rewardScore: {
|
||||
multisigScore: '0',
|
||||
},
|
||||
stakedTotal: '1000',
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
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 {
|
||||
'correct' = 'correct',
|
||||
@@ -17,12 +20,15 @@ export const getMultisigStatusInfo = (
|
||||
previousEpochData?.epoch.validatorsConnection?.edges
|
||||
);
|
||||
|
||||
const hasZero = allNodesInPreviousEpoch.some(
|
||||
(node) => Number(node?.rewardScore?.multisigScore) === 0
|
||||
);
|
||||
const hasOne = allNodesInPreviousEpoch.some(
|
||||
(node) => Number(node?.rewardScore?.multisigScore) === 1
|
||||
);
|
||||
const zeroScore = (node: ValidatorNodeFragment) =>
|
||||
Number(node.rewardScore?.multisigScore) === 0;
|
||||
const oneScore = (node: ValidatorNodeFragment) =>
|
||||
Number(node.rewardScore?.multisigScore) === 1;
|
||||
|
||||
const hasZero = allNodesInPreviousEpoch.some(zeroScore);
|
||||
const hasOne = allNodesInPreviousEpoch.some(oneScore);
|
||||
|
||||
const zeroScoreNodes = allNodesInPreviousEpoch.filter(zeroScore);
|
||||
|
||||
if (hasZero && hasOne) {
|
||||
// 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 {
|
||||
showMultisigStatusError: status !== MultisigStatus.correct,
|
||||
multisigStatus: status,
|
||||
zeroScoreNodes,
|
||||
};
|
||||
};
|
||||
|
||||
+9
-9
@@ -36,8 +36,8 @@ import { type Proposal, type BatchProposal } from '../../types';
|
||||
import { type ProposalTermsFieldsFragment } from '../../__generated__/Proposals';
|
||||
import { differenceInHours, format, formatDistanceToNowStrict } from 'date-fns';
|
||||
import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats';
|
||||
import { getIndicatorStyle } from '../proposal/colours';
|
||||
import { MarketName } from '../proposal/market-name';
|
||||
import { Indicator } from '../proposal/indicator';
|
||||
|
||||
const ProposalTypeTags = ({
|
||||
proposal,
|
||||
@@ -54,11 +54,8 @@ const ProposalTypeTags = ({
|
||||
|
||||
if (proposal.__typename === 'BatchProposal') {
|
||||
return (
|
||||
<div data-testid="proposal-type" className="flex gap-1">
|
||||
{proposal.subProposals?.map((subProposal, i) => {
|
||||
if (!subProposal?.terms) return null;
|
||||
return <ProposalTypeTag key={i} terms={subProposal.terms} />;
|
||||
})}
|
||||
<div data-testid="proposal-type">
|
||||
<ProposalInfoLabel variant="secondary">BatchProposal</ProposalInfoLabel>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -253,7 +250,7 @@ const ProposalDetails = ({
|
||||
}}
|
||||
components={{
|
||||
// @ts-ignore children passed by i18next
|
||||
lozenge: <Lozenge />,
|
||||
lozenge: <Lozenge className="text-xs" />,
|
||||
}}
|
||||
/>
|
||||
);
|
||||
@@ -315,8 +312,11 @@ const ProposalDetails = ({
|
||||
{proposal.subProposals.map((p, i) => {
|
||||
if (!p?.terms) return null;
|
||||
return (
|
||||
<li key={i} className="flex gap-3">
|
||||
<span className={getIndicatorStyle(i + 1)}>{i + 1}</span>
|
||||
<li
|
||||
key={i}
|
||||
className="grid grid-cols-[40px_minmax(0,1fr)] grid-rows-1 gap-3 items-center"
|
||||
>
|
||||
<Indicator indicator={i + 1} />
|
||||
<span>
|
||||
<div>{renderDetails(p.terms)}</div>
|
||||
<SubProposalStateText
|
||||
|
||||
@@ -3,16 +3,8 @@ import { useTranslation } from 'react-i18next';
|
||||
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { SubHeading } from '../../../../components/heading';
|
||||
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
||||
import {
|
||||
type BatchProposalFieldsFragment,
|
||||
type ProposalFieldsFragment,
|
||||
} from '../../__generated__/Proposals';
|
||||
|
||||
export const ProposalJson = ({
|
||||
proposal,
|
||||
}: {
|
||||
proposal: ProposalFieldsFragment | BatchProposalFieldsFragment;
|
||||
}) => {
|
||||
export const ProposalJson = ({ proposal }: { proposal?: unknown }) => {
|
||||
const { t } = useTranslation();
|
||||
const [showDetails, setShowDetails] = useState(false);
|
||||
|
||||
@@ -26,7 +18,7 @@ export const ProposalJson = ({
|
||||
<SubHeading title={t('proposalJson')} />
|
||||
</CollapsibleToggle>
|
||||
|
||||
{showDetails && <SyntaxHighlighter data={proposal} />}
|
||||
{showDetails && <SyntaxHighlighter size="smaller" data={proposal} />}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
+8
-3
@@ -5,6 +5,11 @@ import {
|
||||
} from './proposal-market-changes';
|
||||
import type { JsonValue } from '../../../../components/json-diff';
|
||||
|
||||
jest.mock('../proposal/market-name.tsx', () => ({
|
||||
...jest.requireActual('../proposal/market-name.tsx'),
|
||||
MarketName: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('applyImmutableKeysFromEarlierVersion', () => {
|
||||
it('returns an empty object if any argument is not an object or null', () => {
|
||||
const earlierVersion: JsonValue = null;
|
||||
@@ -57,21 +62,21 @@ describe('applyImmutableKeysFromEarlierVersion', () => {
|
||||
describe('ProposalMarketChanges', () => {
|
||||
it('renders correctly', () => {
|
||||
const { getByTestId } = render(
|
||||
<ProposalMarketChanges marketId="market-id" updatedProposal={{}} />
|
||||
<ProposalMarketChanges marketId="market-id" updateProposalNode={null} />
|
||||
);
|
||||
expect(getByTestId('proposal-market-changes')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('JsonDiff is not visible when showChanges is false', () => {
|
||||
const { queryByTestId } = render(
|
||||
<ProposalMarketChanges marketId="market-id" updatedProposal={{}} />
|
||||
<ProposalMarketChanges marketId="market-id" updateProposalNode={null} />
|
||||
);
|
||||
expect(queryByTestId('json-diff')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('JsonDiff is visible when showChanges is true', async () => {
|
||||
const { getByTestId } = render(
|
||||
<ProposalMarketChanges marketId="market-id" updatedProposal={{}} />
|
||||
<ProposalMarketChanges marketId="market-id" updateProposalNode={null} />
|
||||
);
|
||||
fireEvent.click(getByTestId('proposal-market-changes-toggle'));
|
||||
expect(getByTestId('json-diff')).toBeInTheDocument();
|
||||
|
||||
+92
-53
@@ -1,14 +1,24 @@
|
||||
import cloneDeep from 'lodash/cloneDeep';
|
||||
import set from 'lodash/set';
|
||||
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 { useState } from 'react';
|
||||
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
||||
import { SubHeading } from '../../../../components/heading';
|
||||
import type { JsonValue } from '../../../../components/json-diff';
|
||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { ENV } from '../../../../config';
|
||||
import {
|
||||
useFetchProposal,
|
||||
useFetchProposals,
|
||||
flatten,
|
||||
isBatchProposalNode,
|
||||
isSingleProposalNode,
|
||||
type ProposalNode,
|
||||
type SingleProposalData,
|
||||
type SubProposalData,
|
||||
} from '../proposal/proposal-utils';
|
||||
import { MarketName } from '../proposal/market-name';
|
||||
|
||||
const immutableKeys = [
|
||||
'decimalPlaces',
|
||||
@@ -18,8 +28,8 @@ const immutableKeys = [
|
||||
];
|
||||
|
||||
export const applyImmutableKeysFromEarlierVersion = (
|
||||
earlierVersion: JsonValue,
|
||||
updatedVersion: JsonValue
|
||||
earlierVersion: unknown,
|
||||
updatedVersion: unknown
|
||||
) => {
|
||||
if (
|
||||
typeof earlierVersion !== 'object' ||
|
||||
@@ -35,7 +45,8 @@ export const applyImmutableKeysFromEarlierVersion = (
|
||||
|
||||
// Overwrite the immutable keys in the updatedVersionCopy with the earlier values
|
||||
immutableKeys.forEach((key) => {
|
||||
set(updatedVersionCopy, key, get(earlierVersion, key));
|
||||
const earlier = get(earlierVersion, key);
|
||||
if (earlier) set(updatedVersionCopy, key, earlier);
|
||||
});
|
||||
|
||||
return updatedVersionCopy;
|
||||
@@ -43,49 +54,84 @@ export const applyImmutableKeysFromEarlierVersion = (
|
||||
|
||||
interface ProposalMarketChangesProps {
|
||||
marketId: string;
|
||||
updatedProposal: JsonValue;
|
||||
/** This are the changes from proposal */
|
||||
updateProposalNode: ProposalNode | null;
|
||||
indicator?: number;
|
||||
}
|
||||
|
||||
export const ProposalMarketChanges = ({
|
||||
marketId,
|
||||
updatedProposal,
|
||||
updateProposalNode,
|
||||
indicator,
|
||||
}: ProposalMarketChangesProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [showChanges, setShowChanges] = useState(false);
|
||||
|
||||
const {
|
||||
state: { data },
|
||||
} = useFetch(`${ENV.rest}governance?proposalId=${marketId}`, undefined, true);
|
||||
const { data: originalProposalData } = useFetchProposal({
|
||||
proposalId: marketId,
|
||||
});
|
||||
|
||||
const {
|
||||
state: { data: enactedProposalData },
|
||||
} = useFetch(
|
||||
`${ENV.rest}governances?proposalState=STATE_ENACTED&proposalType=TYPE_UPDATE_MARKET`,
|
||||
undefined,
|
||||
true
|
||||
const { data: enactedProposalsData } = useFetchProposals({
|
||||
proposalState: 'STATE_ENACTED',
|
||||
proposalType: 'TYPE_UPDATE_MARKET',
|
||||
});
|
||||
|
||||
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 enacted = enactedProposalData?.connection?.edges
|
||||
.filter(
|
||||
// @ts-ignore no type here
|
||||
({ 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 =
|
||||
enactedUpdateMarketProposals.length > 0
|
||||
? enactedUpdateMarketProposals[0]
|
||||
: undefined;
|
||||
|
||||
const latestEnactedProposal = enacted?.length
|
||||
? enacted[enacted.length - 1]
|
||||
: undefined;
|
||||
let originalProposal;
|
||||
if (isBatchProposalNode(originalProposalData)) {
|
||||
originalProposal = originalProposalData.proposals.find(
|
||||
(proposal) => proposal.id === marketId && proposal.terms.newMarket != null
|
||||
);
|
||||
}
|
||||
if (isSingleProposalNode(originalProposalData)) {
|
||||
originalProposal = originalProposalData.proposal;
|
||||
}
|
||||
|
||||
const originalProposal =
|
||||
// @ts-ignore no types with useFetch TODO: check this is good
|
||||
data?.data?.proposal?.terms?.newMarket?.changes;
|
||||
// LEFT SIDE: update market proposal enacted just before this one
|
||||
// or original new market proposal
|
||||
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 (
|
||||
<section data-testid="proposal-market-changes">
|
||||
@@ -94,25 +140,18 @@ export const ProposalMarketChanges = ({
|
||||
setToggleState={setShowChanges}
|
||||
dataTestId={'proposal-market-changes-toggle'}
|
||||
>
|
||||
<SubHeading title={t('updatesToMarket')} />
|
||||
<SubHeading
|
||||
title={
|
||||
<>
|
||||
{t('UpdateToMarket')}: <MarketName marketId={marketId} truncate />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</CollapsibleToggle>
|
||||
|
||||
{showChanges && (
|
||||
<div className="mb-6">
|
||||
<JsonDiff
|
||||
left={latestEnactedProposal || originalProposal}
|
||||
right={
|
||||
latestEnactedProposal
|
||||
? applyImmutableKeysFromEarlierVersion(
|
||||
latestEnactedProposal,
|
||||
updatedProposal
|
||||
)
|
||||
: applyImmutableKeysFromEarlierVersion(
|
||||
originalProposal,
|
||||
updatedProposal
|
||||
)
|
||||
}
|
||||
/>
|
||||
<div className="mb-6 bg-vega-cdark-900 p-2 rounded-lg">
|
||||
<JsonDiff left={left as JsonValue} right={right as JsonValue} />
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
|
||||
+5
@@ -2,6 +2,11 @@ import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { ProposalUpdateMarketState } from './proposal-update-market-state';
|
||||
import { MarketUpdateType } from '@vegaprotocol/types';
|
||||
|
||||
jest.mock('../proposal/market-name.tsx', () => ({
|
||||
...jest.requireActual('../proposal/market-name.tsx'),
|
||||
MarketName: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('<ProposalUpdateMarketState />', () => {
|
||||
const suspendProposal = {
|
||||
__typename: 'UpdateMarketState' as const,
|
||||
|
||||
+16
-7
@@ -10,6 +10,7 @@ import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
||||
import { SubHeading } from '../../../../components/heading';
|
||||
import { type UpdateMarketStatesFragment } from '../../__generated__/Proposals';
|
||||
import { MarketUpdateTypeMapping } from '@vegaprotocol/types';
|
||||
import { MarketName } from '../proposal/market-name';
|
||||
|
||||
interface ProposalUpdateMarketStateProps {
|
||||
change: UpdateMarketStatesFragment | null;
|
||||
@@ -20,16 +21,18 @@ export const ProposalUpdateMarketState = ({
|
||||
}: ProposalUpdateMarketStateProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [showDetails, setShowDetails] = useState(false);
|
||||
let market;
|
||||
let isTerminate = false;
|
||||
|
||||
if (!change) {
|
||||
if (!change || change.__typename !== 'UpdateMarketState') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (change.__typename === 'UpdateMarketState') {
|
||||
market = change?.market;
|
||||
isTerminate = change?.updateType === 'MARKET_STATE_UPDATE_TYPE_TERMINATE';
|
||||
const market = change?.market;
|
||||
const isTerminate =
|
||||
change?.updateType === 'MARKET_STATE_UPDATE_TYPE_TERMINATE';
|
||||
|
||||
let toggleTitle = t(change.updateType);
|
||||
if (toggleTitle.length === 0) {
|
||||
toggleTitle = t('MarketDetails');
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -39,7 +42,13 @@ export const ProposalUpdateMarketState = ({
|
||||
setToggleState={setShowDetails}
|
||||
dataTestId="proposal-market-data-toggle"
|
||||
>
|
||||
<SubHeading title={t('MarketDetails')} />
|
||||
<SubHeading
|
||||
title={
|
||||
<>
|
||||
{toggleTitle}: <MarketName marketId={market?.id} />
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</CollapsibleToggle>
|
||||
|
||||
{showDetails && (
|
||||
|
||||
@@ -16,18 +16,31 @@ const getColour = (indicator: number, max = COLOURS.length) => {
|
||||
|
||||
export const getStyle = (indicator: number, max = COLOURS.length) =>
|
||||
classNames({
|
||||
'bg-vega-yellow-400': 'yellow' === getColour(indicator, max),
|
||||
'bg-vega-green-400': 'green' === getColour(indicator, max),
|
||||
'bg-vega-blue-400': 'blue' === getColour(indicator, max),
|
||||
'bg-vega-purple-400': 'purple' === getColour(indicator, max),
|
||||
'bg-vega-pink-400': 'pink' === getColour(indicator, max),
|
||||
'bg-vega-orange-400': 'orange' === getColour(indicator, max),
|
||||
'bg-vega-red-400': 'red' === getColour(indicator, max),
|
||||
'bg-vega-clight-600': 'none' === getColour(indicator, max),
|
||||
'bg-vega-yellow-400 before:bg-vega-yellow-400':
|
||||
'yellow' === getColour(indicator, max),
|
||||
'bg-vega-green-400 before:bg-vega-green-400':
|
||||
'green' === getColour(indicator, max),
|
||||
'bg-vega-blue-400 before:bg-vega-blue-400':
|
||||
'blue' === getColour(indicator, max),
|
||||
'bg-vega-purple-400 before:bg-vega-purple-400':
|
||||
'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) =>
|
||||
classNames(
|
||||
'rounded-sm text-black inline-block px-1 py-1 font-alpha calt h-8',
|
||||
getStyle(indicator)
|
||||
'rounded-sm text-black inline-block px-1 py-1 font-alpha calt h-8 w-7 text-center',
|
||||
'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 { truncateMiddle } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
export const MarketName = ({ marketId }: { marketId?: string }) => {
|
||||
export const MarketName = ({
|
||||
marketId,
|
||||
truncate,
|
||||
}: {
|
||||
marketId?: string;
|
||||
truncate?: boolean;
|
||||
}) => {
|
||||
const { data } = useMarketInfoQuery({
|
||||
variables: {
|
||||
marketId: marketId || '',
|
||||
@@ -8,7 +15,7 @@ export const MarketName = ({ marketId }: { marketId?: string }) => {
|
||||
skip: !marketId,
|
||||
});
|
||||
|
||||
return (
|
||||
<span>{data?.market?.tradableInstrument.instrument.code || marketId}</span>
|
||||
);
|
||||
const id = truncate ? truncateMiddle(marketId || '') : marketId;
|
||||
|
||||
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 Proposal, type BatchProposal } from '../../types';
|
||||
import { ListAsset } from '../list-asset';
|
||||
@@ -12,7 +13,10 @@ import {
|
||||
import { ProposalUpdateBenefitTiers } from '../proposal-update-benefit-tiers';
|
||||
import { ProposalUpdateMarketState } from '../proposal-update-market-state';
|
||||
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 = ({
|
||||
proposal,
|
||||
@@ -22,10 +26,10 @@ export const ProposalChangeDetails = ({
|
||||
}: {
|
||||
proposal: Proposal | BatchProposal;
|
||||
terms: ProposalTermsFieldsFragment;
|
||||
// eslint-disable-next-line
|
||||
restData: any;
|
||||
restData: ProposalNode | null;
|
||||
indicator?: number;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
let details = null;
|
||||
|
||||
switch (terms.change.__typename) {
|
||||
@@ -63,30 +67,13 @@ export const ProposalChangeDetails = ({
|
||||
}
|
||||
case 'UpdateMarket': {
|
||||
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 = (
|
||||
<div className="flex flex-col gap-4">
|
||||
<ProposalMarketData proposalId={proposal.id} />
|
||||
<ProposalMarketChanges
|
||||
indicator={indicator}
|
||||
marketId={terms.change.marketId}
|
||||
updatedProposal={updatedProposal}
|
||||
updateProposalNode={restData}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@@ -125,6 +112,25 @@ export const ProposalChangeDetails = ({
|
||||
'rewards.activityStreak.benefitTiers'
|
||||
) {
|
||||
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;
|
||||
@@ -137,10 +143,12 @@ export const ProposalChangeDetails = ({
|
||||
}
|
||||
}
|
||||
|
||||
if (indicator != null) {
|
||||
if (indicator != null && details != null) {
|
||||
details = (
|
||||
<div className="flex gap-3 mb-3">
|
||||
<div className={getIndicatorStyle(indicator)}>{indicator}</div>
|
||||
<div className="grid grid-cols-[40px_minmax(0,1fr)] grid-rows-1 gap-3 mb-3">
|
||||
<div className="w-10">
|
||||
<Indicator indicator={indicator} />
|
||||
</div>
|
||||
<div>{details}</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>
|
||||
<MockedProvider>
|
||||
<VegaWalletProvider config={vegaWalletConfig}>
|
||||
<Proposal restData={{}} proposal={proposal} />
|
||||
<Proposal restData={null} proposal={proposal} />
|
||||
</VegaWalletProvider>
|
||||
</MockedProvider>
|
||||
</MemoryRouter>
|
||||
|
||||
@@ -8,15 +8,17 @@ import { ProposalJson } from '../proposal-json';
|
||||
import { UserVote } from '../vote-details';
|
||||
import Routes from '../../../routes';
|
||||
import { ProposalState } from '@vegaprotocol/types';
|
||||
import { type ProposalNode } from './proposal-utils';
|
||||
import { useVoteSubmit } from '@vegaprotocol/proposals';
|
||||
import { useUserVote } from '../vote-details/use-user-vote';
|
||||
import { type Proposal as IProposal, type BatchProposal } from '../../types';
|
||||
import { ProposalChangeDetails } from './proposal-change-details';
|
||||
import { type JsonValue } from 'type-fest';
|
||||
|
||||
export interface ProposalProps {
|
||||
proposal: IProposal | BatchProposal;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
restData: any;
|
||||
restData: ProposalNode | null;
|
||||
}
|
||||
|
||||
export const Proposal = ({ proposal, restData }: ProposalProps) => {
|
||||
@@ -58,7 +60,7 @@ export const Proposal = ({ proposal, restData }: ProposalProps) => {
|
||||
<ProposalDescription description={proposal.rationale.description} />
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<div className="mb-4 flex flex-col gap-0">
|
||||
{proposal.__typename === 'Proposal' ? (
|
||||
<ProposalChangeDetails
|
||||
proposal={proposal}
|
||||
@@ -95,7 +97,7 @@ export const Proposal = ({ proposal, restData }: ProposalProps) => {
|
||||
</div>
|
||||
|
||||
<div className="mb-6">
|
||||
<ProposalJson proposal={restData?.data?.proposal} />
|
||||
<ProposalJson proposal={restData?.proposal as unknown as JsonValue} />
|
||||
</div>
|
||||
</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')} />
|
||||
|
||||
{sortedProposals.open.length > 0 ||
|
||||
|
||||
+156
-124
@@ -15,7 +15,8 @@ import {
|
||||
type VoteFieldsFragment,
|
||||
} from '../../__generated__/Proposals';
|
||||
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 }) => (
|
||||
<CompactNumber
|
||||
@@ -40,8 +41,9 @@ const VoteProgress = ({
|
||||
children,
|
||||
}: VoteProgressProps) => {
|
||||
const containerClasses = classNames(
|
||||
'relative h-10 rounded-md border border-vega-dark-300 overflow-hidden',
|
||||
colourfulBg ? 'bg-vega-pink' : 'bg-vega-dark-400'
|
||||
'relative h-2 rounded-md overflow-hidden',
|
||||
// 'border border-vega-dark-300',
|
||||
colourfulBg ? 'bg-vega-red' : 'bg-vega-dark-200'
|
||||
);
|
||||
|
||||
const progressClasses = classNames(
|
||||
@@ -50,17 +52,19 @@ const VoteProgress = ({
|
||||
);
|
||||
|
||||
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 (
|
||||
<div className={containerClasses}>
|
||||
<div
|
||||
className={progressClasses}
|
||||
style={{ width: `${percentageFor}%` }}
|
||||
data-testid={testId}
|
||||
/>
|
||||
<div>
|
||||
<div className={textClasses}>{children}</div>
|
||||
<div className={containerClasses}>
|
||||
<div
|
||||
className={progressClasses}
|
||||
style={{ width: `${percentageFor}%` }}
|
||||
data-testid={testId}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -79,14 +83,22 @@ const Status = ({ reached, threshold, text, testId }: StatusProps) => {
|
||||
<div data-testid={testId}>
|
||||
{reached ? (
|
||||
<div className="flex items-center gap-2">
|
||||
<VegaIcon name={VegaIconNames.TICK} size={20} />
|
||||
<VegaIcon
|
||||
name={VegaIconNames.TICK}
|
||||
className="text-vega-green"
|
||||
size={20}
|
||||
/>
|
||||
<span>
|
||||
{threshold.toString()}% {text} {t('met')}
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex items-center gap-2">
|
||||
<VegaIcon name={VegaIconNames.CROSS} size={20} />
|
||||
<VegaIcon
|
||||
name={VegaIconNames.CROSS}
|
||||
className="text-vega-red"
|
||||
size={20}
|
||||
/>
|
||||
<span>
|
||||
{threshold.toString()}% {text} {t('not met')}
|
||||
</span>
|
||||
@@ -152,7 +164,7 @@ const VoteBreakdownBatch = ({ proposal }: { proposal: BatchProposal }) => {
|
||||
<p className="flex gap-2 m-0 items-center">
|
||||
<VegaIcon
|
||||
name={VegaIconNames.CROSS}
|
||||
className="text-vega-pink"
|
||||
className="text-vega-red"
|
||||
size={20}
|
||||
/>
|
||||
{t(
|
||||
@@ -215,7 +227,7 @@ const VoteBreakdownBatch = ({ proposal }: { proposal: BatchProposal }) => {
|
||||
<p className="flex gap-2 m-0 items-center">
|
||||
<VegaIcon
|
||||
name={VegaIconNames.CROSS}
|
||||
className="text-vega-pink"
|
||||
className="text-vega-red"
|
||||
size={20}
|
||||
/>
|
||||
{t('Proposal failed: {{count}} of {{total}} proposals passed', {
|
||||
@@ -237,6 +249,7 @@ const VoteBreakdownBatch = ({ proposal }: { proposal: BatchProposal }) => {
|
||||
if (!p?.terms) return null;
|
||||
return (
|
||||
<VoteBreakdownBatchSubProposal
|
||||
indicator={i + 1}
|
||||
key={i}
|
||||
proposal={proposal}
|
||||
votes={proposal.votes}
|
||||
@@ -273,21 +286,37 @@ const VoteBreakdownBatchSubProposal = ({
|
||||
const isProposalOpen = proposal?.state === ProposalState.STATE_OPEN;
|
||||
const isUpdateMarket = terms?.change?.__typename === 'UpdateMarket';
|
||||
|
||||
const indicatorElement = indicator && (
|
||||
<span className={getIndicatorStyle(indicator)}>{indicator}</span>
|
||||
);
|
||||
let marketId = undefined;
|
||||
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 (
|
||||
<div>
|
||||
<div className="flex items-baseline gap-3">
|
||||
<div className="mb-6">
|
||||
<div className="flex items-center gap-3 mb-3">
|
||||
{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>
|
||||
<VoteBreakDownUI
|
||||
voteInfo={voteInfo}
|
||||
isProposalOpen={isProposalOpen}
|
||||
isUpdateMarket={isUpdateMarket}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -302,11 +331,13 @@ const VoteBreakdownNormal = ({ proposal }: { proposal: Proposal }) => {
|
||||
const isUpdateMarket = proposal?.terms?.change?.__typename === 'UpdateMarket';
|
||||
|
||||
return (
|
||||
<VoteBreakDownUI
|
||||
voteInfo={voteInfo}
|
||||
isProposalOpen={isProposalOpen}
|
||||
isUpdateMarket={isUpdateMarket}
|
||||
/>
|
||||
<div className="mb-6">
|
||||
<VoteBreakDownUI
|
||||
voteInfo={voteInfo}
|
||||
isProposalOpen={isProposalOpen}
|
||||
isUpdateMarket={isUpdateMarket}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -370,13 +401,13 @@ const VoteBreakDownUI = ({
|
||||
'flex justify-between flex-wrap gap-6'
|
||||
);
|
||||
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(
|
||||
'flex justify-between flex-wrap mt-2 text-sm'
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="mb-6">
|
||||
<div>
|
||||
{isProposalOpen && (
|
||||
<div
|
||||
data-testid="vote-status"
|
||||
@@ -393,7 +424,7 @@ const VoteBreakDownUI = ({
|
||||
<VegaIcon
|
||||
name={VegaIconNames.CROSS}
|
||||
size={20}
|
||||
className="text-vega-pink"
|
||||
className="text-vega-red"
|
||||
/>
|
||||
)}
|
||||
</span>
|
||||
@@ -409,103 +440,13 @@ const VoteBreakDownUI = ({
|
||||
<p className="m-0">
|
||||
<Trans
|
||||
i18nKey={'Currently expected to <0>fail</0>'}
|
||||
components={[<span className="text-vega-pink" />]}
|
||||
components={[<span className="text-vega-red" />]}
|
||||
/>
|
||||
</p>
|
||||
)}
|
||||
</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>}
|
||||
<div className={sectionWrapperClasses}>
|
||||
<section
|
||||
@@ -605,6 +546,97 @@ const VoteBreakDownUI = ({
|
||||
</div>
|
||||
</section>
|
||||
</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>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { ENV } from '../../../config';
|
||||
import { Proposal } from '../components/proposal';
|
||||
import { ProposalNotFound } from '../components/proposal-not-found';
|
||||
import { useProposalQuery } from '../__generated__/Proposals';
|
||||
import { useFetchProposal } from '../components/proposal/proposal-utils';
|
||||
|
||||
export const ProposalContainer = () => {
|
||||
const params = useParams<{ proposalId: string }>();
|
||||
|
||||
const {
|
||||
state: { data: restData, loading: restLoading, error: restError },
|
||||
} = useFetch(`${ENV.rest}governance?proposalId=${params.proposalId}`);
|
||||
const { data: restData, loading: restLoading } = useFetchProposal({
|
||||
proposalId: params.proposalId,
|
||||
});
|
||||
|
||||
const { data, loading, error } = useProposalQuery({
|
||||
fetchPolicy: 'network-only',
|
||||
@@ -26,7 +25,7 @@ export const ProposalContainer = () => {
|
||||
return (
|
||||
<AsyncRenderer
|
||||
loading={Boolean(loading || restLoading)}
|
||||
error={error || restError}
|
||||
error={error}
|
||||
data={{
|
||||
...data,
|
||||
...(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 { AsyncRenderer, Pagination } from '@vegaprotocol/ui-toolkit';
|
||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import type { EpochFieldsFragment } from '../home/__generated__/Rewards';
|
||||
import { useRewardsQuery } from '../home/__generated__/Rewards';
|
||||
import { ENV } from '../../../config';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { EpochIndividualRewardsTable } from './epoch-individual-rewards-table';
|
||||
import { generateEpochIndividualRewardsList } from './generate-epoch-individual-rewards-list';
|
||||
@@ -27,22 +26,16 @@ export const EpochIndividualRewards = ({
|
||||
const [page, setPage] = useState(1);
|
||||
const { t } = useTranslation();
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { delegationsPagination } = ENV;
|
||||
const { param: marketCreationQuantumMultiple } = useNetworkParam(
|
||||
'rewards_marketCreationQuantumMultiple'
|
||||
);
|
||||
|
||||
const { data, loading, error, refetch } = useRewardsQuery({
|
||||
const { data, loading, error } = useRewardsQuery({
|
||||
notifyOnNetworkStatusChange: true,
|
||||
variables: {
|
||||
partyId: pubKey || '',
|
||||
fromEpoch: epochId - EPOCHS_PAGE_SIZE,
|
||||
toEpoch: epochId,
|
||||
delegationsPagination: delegationsPagination
|
||||
? {
|
||||
first: Number(delegationsPagination),
|
||||
}
|
||||
: undefined,
|
||||
...calculateEpochOffset({ epochId, page, size: EPOCHS_PAGE_SIZE }),
|
||||
delegationsPagination: { first: 50 },
|
||||
},
|
||||
skip: !pubKey,
|
||||
});
|
||||
@@ -70,36 +63,6 @@ export const EpochIndividualRewards = ({
|
||||
});
|
||||
}, [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
|
||||
const filteredErrors = filterAcceptableGraphqlErrors(error);
|
||||
const filteredData = data || [];
|
||||
@@ -131,10 +94,10 @@ export const EpochIndividualRewards = ({
|
||||
isLoading={loading}
|
||||
hasPrevPage={page > 1}
|
||||
hasNextPage={page < totalPages}
|
||||
onBack={() => refetchData(page - 1)}
|
||||
onNext={() => refetchData(page + 1)}
|
||||
onFirst={() => refetchData(1)}
|
||||
onLast={() => refetchData(totalPages)}
|
||||
onBack={() => setPage((x) => x - 1)}
|
||||
onNext={() => setPage((x) => x + 1)}
|
||||
onFirst={() => setPage(1)}
|
||||
onLast={() => setPage(totalPages)}
|
||||
>
|
||||
{t('Page')} {page}
|
||||
</Pagination>
|
||||
|
||||
+7
-211
@@ -23,36 +23,6 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
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 = {
|
||||
rewardType: AccountType.ACCOUNT_TYPE_INSURANCE,
|
||||
amount: '50',
|
||||
@@ -120,26 +90,10 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
||||
amount: '100',
|
||||
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', () => {
|
||||
const rewards = [reward1, reward2, reward3, reward4];
|
||||
const rewards = [reward1, reward2];
|
||||
const result1 = generateEpochIndividualRewardsList({
|
||||
rewards,
|
||||
epochId: 2,
|
||||
@@ -157,7 +111,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
expect(result1[0].epoch).toEqual(2);
|
||||
expect(result1[1].epoch).toEqual(1);
|
||||
|
||||
const reorderedRewards = [reward4, reward3, reward2, reward1];
|
||||
const reorderedRewards = [reward2, reward1];
|
||||
const result2 = generateEpochIndividualRewardsList({
|
||||
rewards: reorderedRewards,
|
||||
epochId: 2,
|
||||
@@ -170,7 +124,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
|
||||
it('returns data in the expected shape', () => {
|
||||
// Just sanity checking the whole structure here
|
||||
const rewards = [reward1, reward2, reward3, reward4];
|
||||
const rewards = [reward1, reward2];
|
||||
const result = generateEpochIndividualRewardsList({
|
||||
rewards,
|
||||
epochId: 2,
|
||||
@@ -181,37 +135,6 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
{
|
||||
epoch: 2,
|
||||
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',
|
||||
totalAmount: '50',
|
||||
@@ -221,26 +144,10 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
||||
amount: '50',
|
||||
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: [
|
||||
{
|
||||
asset: 'USD',
|
||||
totalAmount: '200',
|
||||
totalAmount: '100',
|
||||
decimals: 6,
|
||||
rewardTypes: {
|
||||
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
amount: '100',
|
||||
percentageOfTotal: '0.1',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
||||
amount: '100',
|
||||
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', () => {
|
||||
const rewards = [reward1, reward2, reward3, reward4, reward5];
|
||||
const rewards = [reward1, reward2];
|
||||
const resultPageOne = generateEpochIndividualRewardsList({
|
||||
rewards,
|
||||
epochId: 3,
|
||||
@@ -297,74 +188,11 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
expect(resultPageOne).toEqual([
|
||||
{
|
||||
epoch: 3,
|
||||
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',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
rewards: [],
|
||||
},
|
||||
{
|
||||
epoch: 2,
|
||||
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',
|
||||
totalAmount: '50',
|
||||
@@ -374,26 +202,10 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
||||
amount: '50',
|
||||
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: [
|
||||
{
|
||||
asset: 'USD',
|
||||
totalAmount: '200',
|
||||
totalAmount: '100',
|
||||
decimals: 6,
|
||||
rewardTypes: {
|
||||
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
amount: '100',
|
||||
percentageOfTotal: '0.1',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
|
||||
amount: '100',
|
||||
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 { AsyncRenderer, Pagination } from '@vegaprotocol/ui-toolkit';
|
||||
import type { EpochFieldsFragment } from '../home/__generated__/Rewards';
|
||||
@@ -23,37 +23,17 @@ export const EpochTotalRewards = ({ currentEpoch }: EpochTotalRewardsProps) => {
|
||||
'rewards_marketCreationQuantumMultiple'
|
||||
);
|
||||
const [page, setPage] = useState(1);
|
||||
const { data, loading, error, refetch } = useEpochAssetsRewardsQuery({
|
||||
const { data, loading, error } = useEpochAssetsRewardsQuery({
|
||||
notifyOnNetworkStatusChange: true,
|
||||
variables: {
|
||||
epochRewardSummariesFilter: {
|
||||
fromEpoch: epochId - EPOCHS_PAGE_SIZE,
|
||||
},
|
||||
epochRewardSummariesFilter: calculateEpochOffset({
|
||||
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 =
|
||||
generateEpochTotalRewardsList({
|
||||
data,
|
||||
@@ -85,10 +65,10 @@ export const EpochTotalRewards = ({ currentEpoch }: EpochTotalRewardsProps) => {
|
||||
isLoading={loading}
|
||||
hasPrevPage={page > 1}
|
||||
hasNextPage={page < totalPages}
|
||||
onBack={() => refetchData(page - 1)}
|
||||
onNext={() => refetchData(page + 1)}
|
||||
onFirst={() => refetchData(1)}
|
||||
onLast={() => refetchData(totalPages)}
|
||||
onBack={() => setPage((x) => x - 1)}
|
||||
onNext={() => setPage((x) => x + 1)}
|
||||
onFirst={() => setPage(1)}
|
||||
onLast={() => setPage(totalPages)}
|
||||
>
|
||||
{t('Page')} {page}
|
||||
</Pagination>
|
||||
|
||||
+4
-250
@@ -149,38 +149,6 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
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',
|
||||
},
|
||||
@@ -291,40 +259,8 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
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',
|
||||
{
|
||||
epoch: 2,
|
||||
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',
|
||||
},
|
||||
],
|
||||
]),
|
||||
assetRewards: new Map(),
|
||||
},
|
||||
],
|
||||
])
|
||||
@@ -489,66 +366,7 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
'2',
|
||||
{
|
||||
epoch: 2,
|
||||
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',
|
||||
},
|
||||
],
|
||||
]),
|
||||
assetRewards: new Map(),
|
||||
},
|
||||
],
|
||||
[
|
||||
@@ -578,38 +396,6 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
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',
|
||||
},
|
||||
@@ -656,40 +442,8 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
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',
|
||||
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 {
|
||||
@@ -55,7 +39,7 @@ export const rowGridItemStyles = (last = false) =>
|
||||
});
|
||||
|
||||
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`,
|
||||
'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) {
|
||||
epoch(id: $epochId) {
|
||||
id
|
||||
validatorsConnection {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
stakedTotal
|
||||
rewardScore {
|
||||
rawValidatorScore
|
||||
performanceScore
|
||||
multisigScore
|
||||
validatorScore
|
||||
normalisedScore
|
||||
validatorStatus
|
||||
}
|
||||
rankingScore {
|
||||
status
|
||||
previousStatus
|
||||
rankingScore
|
||||
stakeScore
|
||||
performanceScore
|
||||
votingPower
|
||||
}
|
||||
...ValidatorNode
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+26
-20
@@ -3,6 +3,8 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
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<{
|
||||
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 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`
|
||||
query PreviousEpoch($epochId: ID) {
|
||||
epoch(id: $epochId) {
|
||||
@@ -18,30 +41,13 @@ export const PreviousEpochDocument = gql`
|
||||
validatorsConnection {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
stakedTotal
|
||||
rewardScore {
|
||||
rawValidatorScore
|
||||
performanceScore
|
||||
multisigScore
|
||||
validatorScore
|
||||
normalisedScore
|
||||
validatorStatus
|
||||
}
|
||||
rankingScore {
|
||||
status
|
||||
previousStatus
|
||||
rankingScore
|
||||
stakeScore
|
||||
performanceScore
|
||||
votingPower
|
||||
}
|
||||
...ValidatorNode
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
${ValidatorNodeFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __usePreviousEpochQuery__
|
||||
|
||||
@@ -6,7 +6,6 @@ import { usePreviousEpochQuery } from '../__generated__/PreviousEpoch';
|
||||
import { ValidatorTables } from './validator-tables';
|
||||
import { useRefreshAfterEpoch } from '../../../hooks/use-refresh-after-epoch';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { ENV } from '../../../config';
|
||||
import { getMultisigStatusInfo } from '../../../lib/get-multisig-status-info';
|
||||
import { MultisigIncorrectNotice } from '../../../components/multisig-incorrect-notice';
|
||||
|
||||
@@ -20,7 +19,6 @@ export const EpochData = () => {
|
||||
refetch: nodesRefetch,
|
||||
} = useNodesQuery();
|
||||
|
||||
const { delegationsPagination } = ENV;
|
||||
const {
|
||||
data: userStakingData,
|
||||
error: userStakingError,
|
||||
@@ -29,11 +27,9 @@ export const EpochData = () => {
|
||||
} = useStakingQuery({
|
||||
variables: {
|
||||
partyId: pubKey || '',
|
||||
delegationsPagination: delegationsPagination
|
||||
? {
|
||||
first: Number(delegationsPagination),
|
||||
}
|
||||
: undefined,
|
||||
delegationsPagination: {
|
||||
first: 50,
|
||||
},
|
||||
},
|
||||
});
|
||||
const { data: previousEpochData } = usePreviousEpochQuery({
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { ENV } from '../../../config';
|
||||
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -28,16 +27,13 @@ export const NodeContainer = ({
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const { pubKey } = useVegaWallet();
|
||||
const { delegationsPagination } = ENV;
|
||||
|
||||
const { data, loading, error, refetch } = useStakingQuery({
|
||||
variables: {
|
||||
partyId: pubKey || '',
|
||||
delegationsPagination: delegationsPagination
|
||||
? {
|
||||
first: Number(delegationsPagination),
|
||||
}
|
||||
: undefined,
|
||||
delegationsPagination: {
|
||||
first: 50,
|
||||
},
|
||||
},
|
||||
errorPolicy: 'all',
|
||||
});
|
||||
|
||||
@@ -3,7 +3,6 @@ import * as Sentry from '@sentry/react';
|
||||
import React, { useCallback, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { ENV } from '../../../config';
|
||||
import { usePartyDelegationsLazyQuery } from './__generated__/PartyDelegations';
|
||||
import { TokenInput } from '../../../components/token-input';
|
||||
import { useAppState } from '../../../contexts/app-state/app-state-context';
|
||||
@@ -79,7 +78,6 @@ export const StakingForm = ({
|
||||
const [error, setError] = useState<Error | null>(null);
|
||||
const [isDialogVisible, setIsDialogVisible] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
const { delegationsPagination } = ENV;
|
||||
const [action, setAction] = React.useState<StakeAction>(
|
||||
params.action as StakeAction
|
||||
);
|
||||
@@ -154,11 +152,9 @@ export const StakingForm = ({
|
||||
const [delegationSearch, { data }] = usePartyDelegationsLazyQuery({
|
||||
variables: {
|
||||
partyId: pubKey,
|
||||
delegationsPagination: delegationsPagination
|
||||
? {
|
||||
first: Number(delegationsPagination),
|
||||
}
|
||||
: undefined,
|
||||
delegationsPagination: {
|
||||
first: 50,
|
||||
},
|
||||
},
|
||||
fetchPolicy: 'network-only',
|
||||
});
|
||||
|
||||
@@ -37,6 +37,7 @@ import {
|
||||
import type { ReactNode } from 'react';
|
||||
import type { StakingNodeFieldsFragment } from '../__generated__/Staking';
|
||||
import type { PreviousEpochQuery } from '../__generated__/PreviousEpoch';
|
||||
import { getMultisigStatusInfo } from '../../../lib/get-multisig-status-info';
|
||||
|
||||
const statuses = {
|
||||
[Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_ERSATZ]: 'status-ersatz',
|
||||
@@ -104,6 +105,10 @@ export const ValidatorTable = ({
|
||||
};
|
||||
}, [node, previousEpochData?.epoch.validatorsConnection?.edges]);
|
||||
|
||||
const multisigStatus = previousEpochData
|
||||
? getMultisigStatusInfo(previousEpochData)
|
||||
: undefined;
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className="mb-12">
|
||||
@@ -281,6 +286,34 @@ export const ValidatorTable = ({
|
||||
</span>
|
||||
</Tooltip>
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow>
|
||||
<span className="uppercase">{t('multisigPenalty')}</span>
|
||||
|
||||
<span
|
||||
data-testid="multisig-penalty"
|
||||
className="flex gap-2 items-baseline"
|
||||
>
|
||||
{multisigStatus?.zeroScoreNodes.find(
|
||||
(n) => n.id === node.id
|
||||
) ? (
|
||||
<Tooltip
|
||||
description={t('multisigPenaltyThisNodeIndicator')}
|
||||
>
|
||||
<span className="inline-block w-2 h-2 rounded-full bg-vega-red-500"></span>
|
||||
</Tooltip>
|
||||
) : null}
|
||||
<Tooltip description={t('multisigPenaltyDescription')}>
|
||||
<span>
|
||||
{formatNumberPercentage(
|
||||
BigNumber(
|
||||
multisigStatus?.showMultisigStatusError ? 100 : 0
|
||||
),
|
||||
2
|
||||
)}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</span>
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow noBorder={true}>
|
||||
<span>
|
||||
<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_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
||||
NX_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_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_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_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_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_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
||||
NX_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
|
||||
|
||||
# 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_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
|
||||
NX_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_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
|
||||
|
||||
@@ -15,14 +15,14 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
|
||||
NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
|
||||
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
|
||||
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
|
||||
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_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_STOP_ORDERS=true
|
||||
NX_ISOLATED_MARGIN=false
|
||||
NX_ISOLATED_MARGIN=true
|
||||
NX_ICEBERG_ORDERS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_REFERRALS=true
|
||||
|
||||
@@ -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_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
|
||||
|
||||
# Cosmic elevator flags
|
||||
|
||||
@@ -21,18 +21,13 @@ const useFeesTableColumnDefs = (): ColDef[] => {
|
||||
pinned: 'left',
|
||||
width: 150,
|
||||
},
|
||||
{
|
||||
field: 'liquidityFee',
|
||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||
},
|
||||
{
|
||||
field: 'feeAfterDiscount',
|
||||
headerName: t('Total fee after discount'),
|
||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||
},
|
||||
{
|
||||
field: 'totalFee',
|
||||
headerName: t('Total fee before discount'),
|
||||
field: 'liquidityFee',
|
||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||
},
|
||||
{
|
||||
@@ -43,6 +38,11 @@ const useFeesTableColumnDefs = (): ColDef[] => {
|
||||
field: 'makerFee',
|
||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||
},
|
||||
{
|
||||
field: 'totalFee',
|
||||
headerName: t('Total fee before discount'),
|
||||
valueFormatter: ({ value }: { value: number }) => value + '%',
|
||||
},
|
||||
] as ColDef[],
|
||||
[t]
|
||||
);
|
||||
|
||||
@@ -4,7 +4,6 @@ import {
|
||||
lpAggregatedDataProvider,
|
||||
type Filter,
|
||||
LiquidityTable,
|
||||
liquidityProvisionsDataProvider,
|
||||
} from '@vegaprotocol/liquidity';
|
||||
import { getAsset, useMarket } from '@vegaprotocol/markets';
|
||||
import {
|
||||
@@ -71,7 +70,7 @@ export const LiquidityContainer = ({
|
||||
|
||||
const useReloadLiquidityData = (marketId: string | undefined) => {
|
||||
const { reload } = useDataProvider({
|
||||
dataProvider: liquidityProvisionsDataProvider,
|
||||
dataProvider: lpAggregatedDataProvider,
|
||||
variables: { marketId: marketId || '' },
|
||||
update: () => true,
|
||||
skip: !marketId,
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
useMaliciousOracle,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { useState } from 'react';
|
||||
import { type MarketViewProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { type ProposalFragment } from '@vegaprotocol/proposals';
|
||||
import { MarketSuspendedBanner } from './market-suspended-banner';
|
||||
import { MarketUpdateBanner } from './market-update-banner';
|
||||
import { MarketUpdateStateBanner } from './market-update-state-banner';
|
||||
@@ -22,17 +22,17 @@ import {
|
||||
|
||||
type UpdateMarketBanner = {
|
||||
kind: 'UpdateMarket';
|
||||
proposals: MarketViewProposalFieldsFragment[];
|
||||
proposals: ProposalFragment[];
|
||||
};
|
||||
|
||||
type UpdateMarketStateBanner = {
|
||||
kind: 'UpdateMarketState';
|
||||
proposals: MarketViewProposalFieldsFragment[];
|
||||
proposals: ProposalFragment[];
|
||||
};
|
||||
|
||||
type NewMarketBanner = {
|
||||
kind: 'NewMarket'; // aka a proposal of NewMarket which succeeds the current market
|
||||
proposals: MarketViewProposalFieldsFragment[];
|
||||
proposals: ProposalFragment[];
|
||||
};
|
||||
|
||||
type SettledBanner = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Fragment } from 'react';
|
||||
import { type MarketViewProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { type ProposalFragment } from '@vegaprotocol/proposals';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { DApp, TOKEN_PROPOSAL, useLinks } from '@vegaprotocol/environment';
|
||||
import { useT } from '../../lib/use-t';
|
||||
@@ -7,7 +7,7 @@ import { useT } from '../../lib/use-t';
|
||||
export const MarketSuccessorProposalBanner = ({
|
||||
proposals,
|
||||
}: {
|
||||
proposals: MarketViewProposalFieldsFragment[];
|
||||
proposals: ProposalFragment[];
|
||||
}) => {
|
||||
const t = useT();
|
||||
const tokenLink = useLinks(DApp.Governance);
|
||||
@@ -28,7 +28,7 @@ export const MarketSuccessorProposalBanner = ({
|
||||
}
|
||||
)}{' '}
|
||||
{proposals.map((item, i) => {
|
||||
if (item.terms.change.__typename !== 'NewMarket') {
|
||||
if (item.terms?.change.__typename !== 'NewMarket') {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { ProposalState } from '@vegaprotocol/types';
|
||||
import { MarketUpdateBanner } from './market-update-banner';
|
||||
import { type MarketViewProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { type ProposalFragment } from '@vegaprotocol/proposals';
|
||||
|
||||
describe('MarketUpdateBanner', () => {
|
||||
const change = {
|
||||
@@ -34,9 +34,7 @@ describe('MarketUpdateBanner', () => {
|
||||
|
||||
it('renders content for a single open proposal', () => {
|
||||
render(
|
||||
<MarketUpdateBanner
|
||||
proposals={[openProposal as MarketViewProposalFieldsFragment]}
|
||||
/>
|
||||
<MarketUpdateBanner proposals={[openProposal as ProposalFragment]} />
|
||||
);
|
||||
|
||||
expect(
|
||||
@@ -50,9 +48,7 @@ describe('MarketUpdateBanner', () => {
|
||||
|
||||
it('renders content for a single passed proposal', () => {
|
||||
render(
|
||||
<MarketUpdateBanner
|
||||
proposals={[passedProposal as MarketViewProposalFieldsFragment]}
|
||||
/>
|
||||
<MarketUpdateBanner proposals={[passedProposal as ProposalFragment]} />
|
||||
);
|
||||
|
||||
expect(
|
||||
@@ -65,10 +61,7 @@ describe('MarketUpdateBanner', () => {
|
||||
});
|
||||
|
||||
it('renders content for multiple passed proposals', () => {
|
||||
const proposals = [
|
||||
openProposal,
|
||||
openProposal,
|
||||
] as MarketViewProposalFieldsFragment[];
|
||||
const proposals = [openProposal, openProposal] as ProposalFragment[];
|
||||
|
||||
render(<MarketUpdateBanner proposals={proposals} />);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import {
|
||||
TOKEN_PROPOSALS,
|
||||
useLinks,
|
||||
} from '@vegaprotocol/environment';
|
||||
import { type MarketViewProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { type ProposalFragment } from '@vegaprotocol/proposals';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { ProposalState } from '@vegaprotocol/types';
|
||||
import { useT } from '../../lib/use-t';
|
||||
@@ -14,17 +14,17 @@ import { useT } from '../../lib/use-t';
|
||||
export const MarketUpdateBanner = ({
|
||||
proposals,
|
||||
}: {
|
||||
proposals: MarketViewProposalFieldsFragment[];
|
||||
proposals: ProposalFragment[];
|
||||
}) => {
|
||||
const governanceLink = useLinks(DApp.Governance);
|
||||
const t = useT();
|
||||
const openProposals = sortBy(
|
||||
proposals.filter((p) => p.state === ProposalState.STATE_OPEN),
|
||||
(p) => p.terms.enactmentDatetime
|
||||
(p) => p.terms?.enactmentDatetime
|
||||
);
|
||||
const passedProposals = sortBy(
|
||||
proposals.filter((p) => p.state === ProposalState.STATE_PASSED),
|
||||
(p) => p.terms.enactmentDatetime
|
||||
(p) => p.terms?.enactmentDatetime
|
||||
);
|
||||
|
||||
let content = null;
|
||||
@@ -49,7 +49,7 @@ export const MarketUpdateBanner = ({
|
||||
content = (
|
||||
<p>
|
||||
{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>,
|
||||
</p>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { type ReactNode } from 'react';
|
||||
import sortBy from 'lodash/sortBy';
|
||||
import { format, formatDuration, intervalToDuration } from 'date-fns';
|
||||
import { type MarketViewProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { ProposalState } from '@vegaprotocol/types';
|
||||
import { type ProposalFragment } from '@vegaprotocol/proposals';
|
||||
import { MarketUpdateType, ProposalState } from '@vegaprotocol/types';
|
||||
import {
|
||||
DApp,
|
||||
TOKEN_PROPOSAL,
|
||||
@@ -19,18 +19,29 @@ export const MarketUpdateStateBanner = ({
|
||||
proposals,
|
||||
}: {
|
||||
market: Market;
|
||||
proposals: MarketViewProposalFieldsFragment[];
|
||||
proposals: ProposalFragment[];
|
||||
}) => {
|
||||
const t = useT();
|
||||
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(
|
||||
proposals.filter((p) => p.state === ProposalState.STATE_OPEN),
|
||||
(p) => p.terms.enactmentDatetime
|
||||
(p) => p.terms?.enactmentDatetime
|
||||
);
|
||||
const passedProposals = sortBy(
|
||||
proposals.filter((p) => p.state === ProposalState.STATE_PASSED),
|
||||
(p) => p.terms.enactmentDatetime
|
||||
(p) => p.terms?.enactmentDatetime
|
||||
);
|
||||
|
||||
if (!passedProposals.length && !openProposals.length) {
|
||||
@@ -45,12 +56,41 @@ export const MarketUpdateStateBanner = ({
|
||||
? governanceLink(TOKEN_PROPOSAL.replace(':id', openProposals[0]?.id))
|
||||
: 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 =
|
||||
openProposals.length > 1 ? governanceLink(TOKEN_PROPOSALS) : undefined;
|
||||
|
||||
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]);
|
||||
content = (
|
||||
<>
|
||||
@@ -116,20 +156,23 @@ export const MarketUpdateStateBanner = ({
|
||||
return <div data-testid={`update-state-banner-${market.id}`}>{content}</div>;
|
||||
};
|
||||
|
||||
const getMessageVariables = (proposal: MarketViewProposalFieldsFragment) => {
|
||||
const enactmentDatetime = new Date(proposal.terms.enactmentDatetime);
|
||||
const date = format(enactmentDatetime, 'dd MMMM');
|
||||
const duration = formatDuration(
|
||||
intervalToDuration({
|
||||
start: new Date(),
|
||||
end: enactmentDatetime,
|
||||
}),
|
||||
{
|
||||
format: ['days', 'hours'],
|
||||
}
|
||||
);
|
||||
const getMessageVariables = (proposal: ProposalFragment) => {
|
||||
const enactmentDatetime =
|
||||
proposal.terms && new Date(proposal.terms.enactmentDatetime);
|
||||
const date = enactmentDatetime && format(enactmentDatetime, 'dd MMMM');
|
||||
const duration =
|
||||
enactmentDatetime &&
|
||||
formatDuration(
|
||||
intervalToDuration({
|
||||
start: new Date(),
|
||||
end: enactmentDatetime,
|
||||
}),
|
||||
{
|
||||
format: ['days', 'hours'],
|
||||
}
|
||||
);
|
||||
const price =
|
||||
proposal.terms.change.__typename === 'UpdateMarketState'
|
||||
proposal.terms?.change.__typename === 'UpdateMarketState'
|
||||
? proposal.terms.change.price
|
||||
: '';
|
||||
return {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import {
|
||||
useMarketProposals,
|
||||
type MarketViewProposalFieldsFragment,
|
||||
type ProposalFragment,
|
||||
} from '@vegaprotocol/proposals';
|
||||
import { ProposalState, ProposalType } from '@vegaprotocol/types';
|
||||
|
||||
const isPending = (p: MarketViewProposalFieldsFragment) => {
|
||||
const isPending = (p: ProposalFragment) => {
|
||||
return [ProposalState.STATE_OPEN, ProposalState.STATE_PASSED].includes(
|
||||
p.state
|
||||
);
|
||||
@@ -21,9 +21,10 @@ export const useUpdateMarketStateProposals = (
|
||||
|
||||
const proposals = data
|
||||
? data.filter(isPending).filter((p) => {
|
||||
const change = p.terms.change;
|
||||
const change = p.terms?.change;
|
||||
|
||||
if (
|
||||
change &&
|
||||
change.__typename === 'UpdateMarketState' &&
|
||||
change.market.id === marketId
|
||||
) {
|
||||
@@ -48,8 +49,9 @@ export const useUpdateMarketProposals = (
|
||||
|
||||
const proposals = data
|
||||
? data.filter(isPending).filter((p) => {
|
||||
const change = p.terms.change;
|
||||
const change = p.terms?.change;
|
||||
if (
|
||||
change &&
|
||||
change.__typename === 'UpdateMarket' &&
|
||||
change.marketId === marketId
|
||||
) {
|
||||
@@ -73,8 +75,9 @@ export const useSuccessorMarketProposals = (
|
||||
|
||||
const proposals = data
|
||||
? data.filter(isPending).filter((p) => {
|
||||
const change = p.terms.change;
|
||||
const change = p.terms?.change;
|
||||
if (
|
||||
change &&
|
||||
change.__typename === 'NewMarket' &&
|
||||
change.successorConfiguration?.parentMarketId === marketId
|
||||
) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { useT } from '../../lib/use-t';
|
||||
import classNames from 'classnames';
|
||||
import { MarketHeaderStats } from '../../client-pages/market/market-header-stats';
|
||||
import { MarketMarkPrice } from '../market-mark-price';
|
||||
import { MarketBanner } from '../market-banner';
|
||||
/**
|
||||
* This is only rendered for the mobile navigation
|
||||
*/
|
||||
@@ -108,8 +109,11 @@ export const MobileMarketHeader = () => {
|
||||
}
|
||||
>
|
||||
{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>
|
||||
<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>
|
||||
)}
|
||||
</FullScreenPopover>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useT } from '../../lib/use-t';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
import { addDecimalsFormatNumber, formatNumber } from '@vegaprotocol/utils';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
type VegaIconSize,
|
||||
@@ -24,6 +24,10 @@ import {
|
||||
type DispatchStrategy,
|
||||
IndividualScopeMapping,
|
||||
IndividualScopeDescriptionMapping,
|
||||
AccountType,
|
||||
DistributionStrategy,
|
||||
IndividualScope,
|
||||
type Asset,
|
||||
} from '@vegaprotocol/types';
|
||||
import { Card } from '../card/card';
|
||||
import { type ReactNode, useState } from 'react';
|
||||
@@ -61,22 +65,27 @@ export const applyFilter = (
|
||||
filter: Filter
|
||||
) => {
|
||||
const { transfer } = node;
|
||||
if (
|
||||
transfer.kind.__typename !== 'RecurringTransfer' ||
|
||||
!transfer.kind.dispatchStrategy?.dispatchMetric
|
||||
) {
|
||||
|
||||
// if the transfer is a staking reward then it should be displayed
|
||||
if (transfer.toAccountType === AccountType.ACCOUNT_TYPE_GLOBAL_REWARD) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (transfer.kind.__typename !== 'RecurringTransfer') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
DispatchMetricLabels[transfer.kind.dispatchStrategy.dispatchMetric]
|
||||
.toLowerCase()
|
||||
.includes(filter.searchTerm.toLowerCase()) ||
|
||||
(transfer.kind.dispatchStrategy?.dispatchMetric &&
|
||||
DispatchMetricLabels[transfer.kind.dispatchStrategy.dispatchMetric]
|
||||
.toLowerCase()
|
||||
.includes(filter.searchTerm.toLowerCase())) ||
|
||||
transfer.asset?.symbol
|
||||
.toLowerCase()
|
||||
.includes(filter.searchTerm.toLowerCase()) ||
|
||||
(
|
||||
EntityScopeLabelMapping[transfer.kind.dispatchStrategy.entityScope] ||
|
||||
(transfer.kind.dispatchStrategy &&
|
||||
EntityScopeLabelMapping[transfer.kind.dispatchStrategy.entityScope]) ||
|
||||
'Unspecified'
|
||||
)
|
||||
.toLowerCase()
|
||||
@@ -92,6 +101,7 @@ export const applyFilter = (
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
@@ -173,6 +183,29 @@ export const ActiveRewardCard = ({
|
||||
return null;
|
||||
}
|
||||
|
||||
if (
|
||||
!transferNode.transfer.kind.dispatchStrategy &&
|
||||
transferNode.transfer.toAccountType ===
|
||||
AccountType.ACCOUNT_TYPE_GLOBAL_REWARD
|
||||
) {
|
||||
return (
|
||||
<StakingRewardCard
|
||||
colour={CardColour.WHITE}
|
||||
rewardAmount={addDecimalsFormatNumber(
|
||||
transferNode.transfer.amount,
|
||||
transferNode.transfer.asset?.decimals || 0,
|
||||
6
|
||||
)}
|
||||
rewardAsset={transferNode.transfer.asset || undefined}
|
||||
endsIn={
|
||||
transferNode.transfer.kind.endEpoch != null
|
||||
? transferNode.transfer.kind.endEpoch - currentEpoch
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
let colour =
|
||||
DispatchMetricColourMap[
|
||||
transferNode.transfer.kind.dispatchStrategy.dispatchMetric
|
||||
@@ -200,7 +233,8 @@ export const ActiveRewardCard = ({
|
||||
transferNode.transfer.asset?.decimals || 0,
|
||||
6
|
||||
)}
|
||||
rewardAsset={transferNode.asset}
|
||||
rewardAsset={transferNode.dispatchAsset}
|
||||
transferAsset={transferNode.transfer.asset || undefined}
|
||||
endsIn={
|
||||
transferNode.transfer.kind.endEpoch != null
|
||||
? transferNode.transfer.kind.endEpoch - currentEpoch
|
||||
@@ -216,6 +250,8 @@ const RewardCard = ({
|
||||
colour,
|
||||
rewardAmount,
|
||||
rewardAsset,
|
||||
transferAsset,
|
||||
vegaAsset,
|
||||
dispatchStrategy,
|
||||
endsIn,
|
||||
dispatchMetricInfo,
|
||||
@@ -224,12 +260,14 @@ const RewardCard = ({
|
||||
rewardAmount: string;
|
||||
/** The asset linked to the dispatch strategy via `dispatchMetricAssetId` property. */
|
||||
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. */
|
||||
dispatchStrategy: DispatchStrategy;
|
||||
/** The number of epochs until the transfer stops. */
|
||||
endsIn?: number;
|
||||
/** The VEGA asset details, required to format the min staking amount. */
|
||||
vegaAsset?: BasicAssetDetails;
|
||||
dispatchMetricInfo?: ReactNode;
|
||||
}) => {
|
||||
const t = useT();
|
||||
@@ -269,7 +307,9 @@ const RewardCard = ({
|
||||
{rewardAmount}
|
||||
</span>
|
||||
|
||||
<span className="font-alpha">{rewardAsset?.symbol || ''}</span>
|
||||
<span className="font-alpha" data-testid="reward-asset">
|
||||
{transferAsset?.symbol || ''}
|
||||
</span>
|
||||
</h3>
|
||||
|
||||
{/** DISTRIBUTION STRATEGY */}
|
||||
@@ -310,7 +350,7 @@ const RewardCard = ({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span className="border-[0.5px] border-gray-700" />
|
||||
<span className="border-[0.5px] dark:border-vega-cdark-500 border-vega-clight-500" />
|
||||
{/** DISPATCH METRIC */}
|
||||
{dispatchMetricInfo ? (
|
||||
dispatchMetricInfo
|
||||
@@ -347,16 +387,17 @@ const RewardCard = ({
|
||||
</div>
|
||||
{/** DISPATCH METRIC DESCRIPTION */}
|
||||
{dispatchStrategy?.dispatchMetric && (
|
||||
<span className="text-muted text-sm h-[3rem]">
|
||||
<p className="text-muted text-sm h-[3rem]">
|
||||
{t(DispatchMetricDescription[dispatchStrategy?.dispatchMetric])}
|
||||
</span>
|
||||
</p>
|
||||
)}
|
||||
<span className="border-[0.5px] border-gray-700" />
|
||||
<span className="border-[0.5px] dark:border-vega-cdark-500 border-vega-clight-500" />
|
||||
{/** REQUIREMENTS */}
|
||||
{dispatchStrategy && (
|
||||
<RewardRequirements
|
||||
dispatchStrategy={dispatchStrategy}
|
||||
rewardAsset={rewardAsset}
|
||||
vegaAsset={vegaAsset}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -365,6 +406,190 @@ const RewardCard = ({
|
||||
);
|
||||
};
|
||||
|
||||
const StakingRewardCard = ({
|
||||
colour,
|
||||
rewardAmount,
|
||||
rewardAsset,
|
||||
endsIn,
|
||||
}: {
|
||||
colour: CardColour;
|
||||
rewardAmount: string;
|
||||
/** The asset linked to the dispatch strategy via `dispatchMetricAssetId` property. */
|
||||
rewardAsset?: Asset;
|
||||
/** The number of epochs until the transfer stops. */
|
||||
endsIn?: number;
|
||||
/** The VEGA asset details, required to format the min staking amount. */
|
||||
vegaAsset?: BasicAssetDetails;
|
||||
}) => {
|
||||
const t = useT();
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className={classNames(
|
||||
'bg-gradient-to-r col-span-full p-0.5 lg:col-auto h-full',
|
||||
'rounded-lg',
|
||||
CardColourStyles[colour].gradientClassName
|
||||
)}
|
||||
data-testid="active-rewards-card"
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
CardColourStyles[colour].mainClassName,
|
||||
'bg-gradient-to-b bg-vega-clight-800 dark:bg-vega-cdark-800 h-full w-full rounded-md p-4 flex flex-col gap-4'
|
||||
)}
|
||||
>
|
||||
<div className="flex justify-between gap-4">
|
||||
{/** ENTITY SCOPE */}
|
||||
<div className="flex flex-col gap-2 items-center text-center">
|
||||
<EntityIcon entityScope={EntityScope.ENTITY_SCOPE_INDIVIDUALS} />
|
||||
{
|
||||
<span className="text-muted text-xs" data-testid="entity-scope">
|
||||
{EntityScopeLabelMapping[
|
||||
EntityScope.ENTITY_SCOPE_INDIVIDUALS
|
||||
] || t('Unspecified')}
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
|
||||
{/** AMOUNT AND DISTRIBUTION STRATEGY */}
|
||||
<div className="flex flex-col gap-2 items-center text-center">
|
||||
{/** AMOUNT */}
|
||||
<h3 className="flex flex-col gap-1 text-2xl shrink-1 text-center">
|
||||
<span className="font-glitch" data-testid="reward-value">
|
||||
{rewardAmount}
|
||||
</span>
|
||||
|
||||
<span className="font-alpha">{rewardAsset?.symbol || ''}</span>
|
||||
</h3>
|
||||
|
||||
{/** DISTRIBUTION STRATEGY */}
|
||||
<Tooltip
|
||||
description={t(
|
||||
DistributionStrategyDescriptionMapping[
|
||||
DistributionStrategy.DISTRIBUTION_STRATEGY_PRO_RATA
|
||||
]
|
||||
)}
|
||||
underline={true}
|
||||
>
|
||||
<span className="text-xs" data-testid="distribution-strategy">
|
||||
{
|
||||
DistributionStrategyMapping[
|
||||
DistributionStrategy.DISTRIBUTION_STRATEGY_PRO_RATA
|
||||
]
|
||||
}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
{/** DISTRIBUTION DELAY */}
|
||||
<div className="flex flex-col gap-2 items-center text-center">
|
||||
<CardIcon
|
||||
iconName={VegaIconNames.LOCK}
|
||||
tooltip={t(
|
||||
'Number of epochs after distribution to delay vesting of rewards by'
|
||||
)}
|
||||
/>
|
||||
<span
|
||||
className="text-muted text-xs whitespace-nowrap"
|
||||
data-testid="locked-for"
|
||||
>
|
||||
{t('numberEpochs', '{{count}} epochs', {
|
||||
count: 0,
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span className="border-[0.5px] dark:border-vega-cdark-500 border-vega-clight-500" />
|
||||
{/** DISPATCH METRIC */}
|
||||
{
|
||||
<span data-testid="dispatch-metric-info">
|
||||
{t('Staking rewards')}
|
||||
</span>
|
||||
}
|
||||
<div className="flex items-center gap-8 flex-wrap">
|
||||
{/** ENDS IN */}
|
||||
{endsIn != null && (
|
||||
<span className="flex flex-col">
|
||||
<span className="text-muted text-xs">{t('Ends in')} </span>
|
||||
<span data-testid="ends-in" data-endsin={endsIn}>
|
||||
{endsIn >= 0
|
||||
? t('numberEpochs', '{{count}} epochs', {
|
||||
count: endsIn,
|
||||
})
|
||||
: t('Ended')}
|
||||
</span>
|
||||
</span>
|
||||
)}
|
||||
|
||||
{/** WINDOW LENGTH */}
|
||||
<span className="flex flex-col">
|
||||
<span className="text-muted text-xs">{t('Assessed over')}</span>
|
||||
<span data-testid="assessed-over">
|
||||
{t('numberEpochs', '{{count}} epochs', {
|
||||
count: 1,
|
||||
})}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
{/** DISPATCH METRIC DESCRIPTION */}
|
||||
{
|
||||
<p className="text-muted text-sm h-[3rem]">
|
||||
{t(
|
||||
'Global staking reward for staking $VEGA on the network via the Governance app'
|
||||
)}
|
||||
</p>
|
||||
}
|
||||
<span className="border-[0.5px] dark:border-vega-cdark-500 border-vega-clight-500" />
|
||||
{/** REQUIREMENTS */}
|
||||
<dl className="flex justify-between flex-wrap items-center gap-3 text-xs">
|
||||
<div className="flex flex-col gap-1">
|
||||
<dt className="flex items-center gap-1 text-muted">
|
||||
{t('Team scope')}
|
||||
</dt>
|
||||
<dd className="flex items-center gap-1" data-testid="scope">
|
||||
<Tooltip
|
||||
description={
|
||||
IndividualScopeDescriptionMapping[
|
||||
IndividualScope.INDIVIDUAL_SCOPE_ALL
|
||||
]
|
||||
}
|
||||
>
|
||||
<span>{t('Individual')}</span>
|
||||
</Tooltip>
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1">
|
||||
<dt className="flex items-center gap-1 text-muted">
|
||||
{t('Staked VEGA')}
|
||||
</dt>
|
||||
<dd
|
||||
className="flex items-center gap-1"
|
||||
data-testid="staking-requirement"
|
||||
>
|
||||
{formatNumber(1, 2)}
|
||||
</dd>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-1">
|
||||
<dt className="flex items-center gap-1 text-muted">
|
||||
{t('Average position')}
|
||||
</dt>
|
||||
<dd
|
||||
className="flex items-center gap-1"
|
||||
data-testid="average-position"
|
||||
>
|
||||
{formatNumber(0, 2)}
|
||||
</dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const DispatchMetricInfo = ({
|
||||
reward,
|
||||
}: {
|
||||
@@ -379,8 +604,8 @@ export const DispatchMetricInfo = ({
|
||||
let additionalDispatchMetricInfo = null;
|
||||
|
||||
// if asset found then display asset symbol
|
||||
if (reward.asset) {
|
||||
additionalDispatchMetricInfo = <span>{reward.asset.symbol}</span>;
|
||||
if (reward.dispatchAsset) {
|
||||
additionalDispatchMetricInfo = <span>{reward.dispatchAsset.symbol}</span>;
|
||||
}
|
||||
// but if scoped to only one market then display market name
|
||||
if (marketNames.length === 1) {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
CONSOLE_IMAGE_NAME=vegaprotocol/trading:latest
|
||||
VEGA_VERSION=v0.74.1
|
||||
VEGA_VERSION=v0.74.6
|
||||
LOCAL_SERVER=false
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
CONSOLE_IMAGE_NAME=vegaprotocol/trading:develop
|
||||
VEGA_VERSION=v0.74.1
|
||||
VEGA_VERSION=v0.74.6
|
||||
LOCAL_SERVER=false
|
||||
|
||||
+63
-119
@@ -1,156 +1,100 @@
|
||||
# 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
|
||||
|
||||
- [Poetry](https://python-poetry.org/docs/#installing-with-the-official-installer)
|
||||
- [Docker](https://www.docker.com/)
|
||||
- [Python versions ">=3.9,<3.11"](https://www.python.org/)
|
||||
Ensure you have the following installed:
|
||||
|
||||
## 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).
|
||||
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.
|
||||
## Setup
|
||||
|
||||
### 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
|
||||
poetry shell
|
||||
```
|
||||
|
||||
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 update vega-sim # Updates to the latest version of the market-sim branch
|
||||
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
|
||||
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`
|
||||
Download necessary binaries for the desired Vega version:
|
||||
|
||||
```bash
|
||||
python -m vega_sim.tools.load_binaries --force --version $VEGA_VERSION
|
||||
```
|
||||
|
||||
8. **Pull the desired Docker image**
|
||||
Pull Docker images for your environment:
|
||||
|
||||
```bash
|
||||
docker pull vegaprotocol/trading:develop
|
||||
```
|
||||
- **Development**: `docker pull vegaprotocol/trading:develop`
|
||||
- **Production**: `docker pull vegaprotocol/trading:main`
|
||||
|
||||
9. **Run tests**: Poetry/Python will serve the app from docker
|
||||
|
||||
### 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
|
||||
```
|
||||
### 4. Build a Docker Image of Your Locally Built Trading App
|
||||
|
||||
```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 .
|
||||
```
|
||||
|
||||
## 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:
|
||||
- **Run all tests**: `poetry run pytest`
|
||||
- **Run a specific test**: `poetry run pytest -k "test_name" -s --headed`
|
||||
- **Run tests using your locally served console**:
|
||||
|
||||
```bash
|
||||
poetry run pytest
|
||||
In one terminal window, build and serve the trading console:
|
||||
|
||||
```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
|
||||
poetry run pytest -k "test_name" -s --headed
|
||||
```
|
||||
For running tests in parallel:
|
||||
|
||||
Run from anywhere:
|
||||
- **Within the e2e folder**: `poetry run pytest -s --numprocesses auto --dist loadfile`
|
||||
- **From anywhere**: `yarn trading:test:all`
|
||||
|
||||
```bash
|
||||
yarn trading:test -- "test_name" -s --headed
|
||||
```
|
||||
## Troubleshooting
|
||||
|
||||
Run using your locally served console:
|
||||
If IntelliSense is not working in VSCode, follow these steps:
|
||||
|
||||
Within one terminal
|
||||
|
||||
```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
|
||||
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.
|
||||
|
||||
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"
|
||||
)
|
||||
|
||||
@pytest.mark.usefixtures("page", "continuous_market", "auth", "risk_accepted")
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_submit_stop_oco_limit_order_pending(
|
||||
continuous_market, vega: VegaServiceNull, page: Page
|
||||
):
|
||||
|
||||
@@ -15,8 +15,7 @@ deal_ticket_deposit_dialog_button = "deal-ticket-deposit-dialog-button"
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(
|
||||
vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@@ -25,7 +24,6 @@ def 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")
|
||||
def test_should_display_info_and_button_for_deposit(continuous_market, page: Page):
|
||||
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")
|
||||
# 7002-SORD-060
|
||||
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()
|
||||
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()
|
||||
expect(page.get_by_test_id("sidebar-content")
|
||||
).to_contain_text("DepositFrom")
|
||||
expect(page.get_by_test_id("sidebar-content")).to_contain_text("DepositFrom")
|
||||
|
||||
|
||||
@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}")
|
||||
vega.create_key("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
|
||||
expect(page.get_by_test_id(place_order)).to_be_enabled()
|
||||
# 7002-SORD-003
|
||||
expect(page.get_by_test_id("deal-ticket-error-message-zero-balance")
|
||||
).to_have_text("You need tDAI in your wallet to trade in this market.Make a deposit")
|
||||
expect(page.get_by_test_id("deal-ticket-error-message-zero-balance")).to_have_text(
|
||||
"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()
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
# test_ids.py
|
||||
|
||||
# Constants for test IDs
|
||||
ADJUSTED_FEES = "adjusted-fees"
|
||||
TOTAL_FEE_BEFORE_DISCOUNT = "total-fee-before-discount"
|
||||
INFRASTRUCTURE_FEES = "infrastructure-fees"
|
||||
MAKER_FEES = "maker-fees"
|
||||
LIQUIDITY_FEES = "liquidity-fees"
|
||||
TOTAL_DISCOUNT = "total-discount"
|
||||
VOLUME_DISCOUNT_ROW = "volume-discount-row"
|
||||
REFERRAL_DISCOUNT_ROW = "referral-discount-row"
|
||||
PAST_EPOCHS_VOLUME = "past-epochs-volume"
|
||||
REQUIRED_FOR_NEXT_TIER = "required-for-next-tier"
|
||||
TIER_VALUE_0 = "tier-value-0"
|
||||
TIER_VALUE_1 = "tier-value-1"
|
||||
DISCOUNT_VALUE_0 = "discount-value-0"
|
||||
DISCOUNT_VALUE_1 = "discount-value-1"
|
||||
MIN_VOLUME_VALUE_0 = "min-volume-value-0"
|
||||
MIN_VOLUME_VALUE_1 = "min-volume-value-1"
|
||||
MY_VOLUME_VALUE_0 = "my-volume-value-0"
|
||||
MY_VOLUME_VALUE_1 = "my-volume-value-1"
|
||||
ORDER_SIZE = "order-size"
|
||||
ORDER_PRICE = "order-price"
|
||||
DISCOUNT_PILL = "discount-pill"
|
||||
FEES_TEXT = "fees-text"
|
||||
TOOLTIP_CONTENT = "tooltip-content"
|
||||
INFRASTRUCTURE_FEE_FACTOR = "infrastructure-fee-factor"
|
||||
INFRASTRUCTURE_FEE_VALUE = "infrastructure-fee-value"
|
||||
LIQUIDITY_FEE_FACTOR = "liquidity-fee-factor"
|
||||
LIQUIDITY_FEE_VALUE = "liquidity-fee-value"
|
||||
MAKER_FEE_FACTOR = "maker-fee-factor"
|
||||
MAKER_FEE_VALUE = "maker-fee-value"
|
||||
SUBTOTAL_FEE_FACTOR = "subtotal-fee-factor"
|
||||
SUBTOTAL_FEE_VALUE = "subtotal-fee-value"
|
||||
DISCOUNT_FEE_FACTOR = "discount-fee-factor"
|
||||
DISCOUNT_FEE_VALUE = "discount-fee-value"
|
||||
TOTAL_FEE_VALUE = "total-fee-value"
|
||||
RUNNING_NOTIONAL_TAKER_VOLUME = "running-notional-taker-volume"
|
||||
EPOCHS_IN_REFERRAL_SET = "epochs-in-referral-set"
|
||||
REQUIRED_EPOCHS_VALUE_0 = "required-epochs-value-0"
|
||||
REQUIRED_EPOCHS_VALUE_1 = "required-epochs-value-1"
|
||||
FILLS = "Fills"
|
||||
TAB_FILLS = "tab-fills"
|
||||
FEE_BREAKDOWN_TOOLTIP = "fee-breakdown-tooltip"
|
||||
PINNED_ROW_LOCATOR = ".ag-pinned-left-cols-container .ag-row"
|
||||
ROW_LOCATOR = ".ag-center-cols-container .ag-row"
|
||||
# Col-Ids:
|
||||
COL_INSTRUMENT_CODE = '[data-testid="market-code"]'
|
||||
COL_CODE = '[col-id="code"]'
|
||||
COL_SIZE = '[col-id="size"]'
|
||||
COL_PRICE = '[col-id="price"]'
|
||||
COL_PRICE_1 = '[col-id="price_1"]'
|
||||
COL_AGGRESSOR = '[col-id="aggressor"]'
|
||||
COL_FEE = '[col-id="fee"]'
|
||||
COL_FEE_DISCOUNT = '[col-id="fee-discount"]'
|
||||
COL_FEE_AFTER_DISCOUNT = '[col-id="feeAfterDiscount"]'
|
||||
COL_INFRA_FEE = '[col-id="infraFee"]'
|
||||
COL_MAKER_FEE = '[col-id="makerFee"]'
|
||||
COL_LIQUIDITY_FEE = '[col-id="liquidityFee"]'
|
||||
COL_TOTAL_FEE = '[col-id="totalFee"]'
|
||||
@@ -1,689 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import init_vega, init_page, auth_setup, cleanup_container
|
||||
from actions.utils import next_epoch, change_keys, forward_time
|
||||
from fixtures.market import market_exists, setup_continuous_market
|
||||
|
||||
# region Constants for test IDs
|
||||
ADJUSTED_FEES = "adjusted-fees"
|
||||
TOTAL_FEE_BEFORE_DISCOUNT = "total-fee-before-discount"
|
||||
INFRASTRUCTURE_FEES = "infrastructure-fees"
|
||||
MAKER_FEES = "maker-fees"
|
||||
LIQUIDITY_FEES = "liquidity-fees"
|
||||
TOTAL_DISCOUNT = "total-discount"
|
||||
VOLUME_DISCOUNT_ROW = "volume-discount-row"
|
||||
REFERRAL_DISCOUNT_ROW = "referral-discount-row"
|
||||
PAST_EPOCHS_VOLUME = "past-epochs-volume"
|
||||
REQUIRED_FOR_NEXT_TIER = "required-for-next-tier"
|
||||
TIER_VALUE_0 = "tier-value-0"
|
||||
TIER_VALUE_1 = "tier-value-1"
|
||||
DISCOUNT_VALUE_0 = "discount-value-0"
|
||||
DISCOUNT_VALUE_1 = "discount-value-1"
|
||||
MIN_VOLUME_VALUE_0 = "min-volume-value-0"
|
||||
MIN_VOLUME_VALUE_1 = "min-volume-value-1"
|
||||
MY_VOLUME_VALUE_0 = "my-volume-value-0"
|
||||
MY_VOLUME_VALUE_1 = "my-volume-value-1"
|
||||
ORDER_SIZE = "order-size"
|
||||
ORDER_PRICE = "order-price"
|
||||
DISCOUNT_PILL = "discount-pill"
|
||||
FEES_TEXT = "fees-text"
|
||||
TOOLTIP_CONTENT = "tooltip-content"
|
||||
INFRASTRUCTURE_FEE_FACTOR = "infrastructure-fee-factor"
|
||||
INFRASTRUCTURE_FEE_VALUE = "infrastructure-fee-value"
|
||||
LIQUIDITY_FEE_FACTOR = "liquidity-fee-factor"
|
||||
LIQUIDITY_FEE_VALUE = "liquidity-fee-value"
|
||||
MAKER_FEE_FACTOR = "maker-fee-factor"
|
||||
MAKER_FEE_VALUE = "maker-fee-value"
|
||||
SUBTOTAL_FEE_FACTOR = "subtotal-fee-factor"
|
||||
SUBTOTAL_FEE_VALUE = "subtotal-fee-value"
|
||||
DISCOUNT_FEE_FACTOR = "discount-fee-factor"
|
||||
DISCOUNT_FEE_VALUE = "discount-fee-value"
|
||||
TOTAL_FEE_VALUE = "total-fee-value"
|
||||
RUNNING_NOTIONAL_TAKER_VOLUME = "running-notional-taker-volume"
|
||||
EPOCHS_IN_REFERRAL_SET = "epochs-in-referral-set"
|
||||
REQUIRED_EPOCHS_VALUE_0 = "required-epochs-value-0"
|
||||
REQUIRED_EPOCHS_VALUE_1 = "required-epochs-value-1"
|
||||
FILLS = "Fills"
|
||||
TAB_FILLS = "tab-fills"
|
||||
FEE_BREAKDOWN_TOOLTIP = "fee-breakdown-tooltip"
|
||||
PINNED_ROW_LOCATOR = ".ag-pinned-left-cols-container .ag-row"
|
||||
ROW_LOCATOR = ".ag-center-cols-container .ag-row"
|
||||
# Col-Ids:
|
||||
COL_INSTRUMENT_CODE = '[data-testid="market-code"]'
|
||||
COL_CODE = '[col-id="code"]'
|
||||
COL_SIZE = '[col-id="size"]'
|
||||
COL_PRICE = '[col-id="price"]'
|
||||
COL_PRICE_1 = '[col-id="price_1"]'
|
||||
COL_AGGRESSOR = '[col-id="aggressor"]'
|
||||
COL_FEE = '[col-id="fee"]'
|
||||
COL_FEE_DISCOUNT = '[col-id="fee-discount"]'
|
||||
COL_FEE_AFTER_DISCOUNT = '[col-id="feeAfterDiscount"]'
|
||||
COL_INFRA_FEE = '[col-id="infraFee"]'
|
||||
COL_MAKER_FEE = '[col-id="makerFee"]'
|
||||
COL_LIQUIDITY_FEE = '[col-id="liquidityFee"]'
|
||||
COL_TOTAL_FEE = '[col-id="totalFee"]'
|
||||
# endregion
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def market_ids():
|
||||
return {
|
||||
"tier_1_volume": "default_id",
|
||||
"tier_2_volume": "default_id",
|
||||
"tier_1_referral": "default_id",
|
||||
"tier_2_referral": "default_id",
|
||||
"combo": "default_id",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_volume_discount_tier_1(request):
|
||||
with init_vega(request) as vega_volume_discount_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_volume_discount_tier_1)) # Register the cleanup function
|
||||
yield vega_volume_discount_tier_1
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_volume_discount_tier_2(request):
|
||||
with init_vega(request) as vega_volume_discount_tier_2:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_volume_discount_tier_2)) # Register the cleanup function
|
||||
yield vega_volume_discount_tier_2
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_referral_discount_tier_1(request):
|
||||
with init_vega(request) as vega_referral_discount_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_referral_discount_tier_1)) # Register the cleanup function
|
||||
yield vega_referral_discount_tier_1
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_referral_discount_tier_2(request):
|
||||
with init_vega(request) as vega_referral_discount_tier_2:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_referral_discount_tier_2)) # Register the cleanup function
|
||||
yield vega_referral_discount_tier_2
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_referral_and_volume_discount(request):
|
||||
with init_vega(request) as vega_referral_and_volume_discount:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_referral_and_volume_discount)) # Register the cleanup function
|
||||
yield vega_referral_and_volume_discount
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def page(vega_instance, browser, request):
|
||||
with init_page(vega_instance, browser, request) as page_instance:
|
||||
yield page_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vega_instance(
|
||||
tier,
|
||||
discount_program,
|
||||
vega_volume_discount_tier_1,
|
||||
vega_volume_discount_tier_2,
|
||||
vega_referral_discount_tier_1,
|
||||
vega_referral_discount_tier_2,
|
||||
vega_referral_and_volume_discount,
|
||||
):
|
||||
if discount_program == "volume":
|
||||
return vega_volume_discount_tier_1 if tier == 1 else vega_volume_discount_tier_2
|
||||
elif discount_program == "referral":
|
||||
return (
|
||||
vega_referral_discount_tier_1
|
||||
if tier == 1
|
||||
else vega_referral_discount_tier_2
|
||||
)
|
||||
elif discount_program == "combo":
|
||||
return vega_referral_and_volume_discount
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def auth(vega_instance, page):
|
||||
return auth_setup(vega_instance, page)
|
||||
|
||||
|
||||
def setup_market_with_volume_discount_program(vega: VegaServiceNull, tier: int):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_volume_discount_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"volume_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"volume_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
window_length=7,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
order_count = 2 if tier == 1 else 3
|
||||
for _ in range(order_count):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", 1, 110)
|
||||
forward_time(vega, True if _ < order_count - 1 else False)
|
||||
|
||||
return market
|
||||
|
||||
|
||||
def setup_market_with_referral_discount_program(vega: VegaServiceNull, tier: int):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_referral_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"minimum_epochs": 1,
|
||||
"referral_reward_factor": 0.1,
|
||||
"referral_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"minimum_epochs": 2,
|
||||
"referral_reward_factor": 0.2,
|
||||
"referral_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
staking_tiers=[
|
||||
{"minimum_staked_tokens": 100, "referral_reward_multiplier": 1.1},
|
||||
{"minimum_staked_tokens": 200, "referral_reward_multiplier": 1.2},
|
||||
],
|
||||
window_length=1,
|
||||
)
|
||||
vega.create_referral_set(key_name=MM_WALLET.name)
|
||||
next_epoch(vega=vega)
|
||||
referral_set_id = list(vega.list_referral_sets().keys())[0]
|
||||
vega.apply_referral_code(key_name="Key 1", id=referral_set_id)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
order_count = 2
|
||||
order_size = 1 if tier == 1 else 2
|
||||
for _ in range(order_count):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", order_size, 110)
|
||||
forward_time(vega, True if _ < order_count - 1 else False)
|
||||
|
||||
return market
|
||||
|
||||
|
||||
def setup_combined_market(vega: VegaServiceNull):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_volume_discount_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"volume_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"volume_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
window_length=7,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
vega.update_referral_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"minimum_epochs": 1,
|
||||
"referral_reward_factor": 0.1,
|
||||
"referral_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"minimum_epochs": 2,
|
||||
"referral_reward_factor": 0.2,
|
||||
"referral_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
staking_tiers=[
|
||||
{"minimum_staked_tokens": 100, "referral_reward_multiplier": 1.1},
|
||||
{"minimum_staked_tokens": 200, "referral_reward_multiplier": 1.2},
|
||||
],
|
||||
window_length=1,
|
||||
)
|
||||
vega.create_referral_set(key_name=MM_WALLET.name)
|
||||
next_epoch(vega=vega)
|
||||
referral_set_id = list(vega.list_referral_sets().keys())[0]
|
||||
vega.apply_referral_code(key_name="Key 1", id=referral_set_id)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
order_count = 2
|
||||
order_size = 2
|
||||
for _ in range(order_count):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", order_size, 110)
|
||||
forward_time(vega, True if _ < order_count - 1 else False)
|
||||
return market
|
||||
|
||||
|
||||
def set_market_volume_discount(vega, tier, discount_program, market_ids):
|
||||
market_id_key = f"tier_{tier}_{discount_program}"
|
||||
if discount_program == "combo":
|
||||
market_id_key = "combo"
|
||||
|
||||
market_id = market_ids.get(market_id_key, "default_id")
|
||||
|
||||
print(f"Checking if market exists: {market_id}")
|
||||
if not market_exists(vega, market_id):
|
||||
print(
|
||||
f"Market doesn't exist for {discount_program} tier {tier}. Setting up new market."
|
||||
)
|
||||
|
||||
if discount_program == "volume":
|
||||
market_id = setup_market_with_volume_discount_program(vega, tier)
|
||||
elif discount_program == "referral":
|
||||
market_id = setup_market_with_referral_discount_program(vega, tier)
|
||||
elif discount_program == "combo":
|
||||
market_id = setup_combined_market(vega)
|
||||
|
||||
market_ids[market_id_key] = market_id
|
||||
|
||||
print(f"Using market ID: {market_id}")
|
||||
return market_ids
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, expected_text",
|
||||
[
|
||||
(1, "volume", "9.045%-9.045%"),
|
||||
(2, "volume", "8.04%-8.04%"),
|
||||
(1, "referral", "9.045%-9.045%"),
|
||||
(2, "referral", "8.04%-8.04%"),
|
||||
(2, "combo", "6.432%-6.432%"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fees_page_discount_program_my_trading_fees(
|
||||
tier, expected_text, discount_program, vega_instance, page: Page, market_ids
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(ADJUSTED_FEES)).to_have_text(expected_text)
|
||||
expect(page.get_by_test_id(TOTAL_FEE_BEFORE_DISCOUNT)).to_have_text(
|
||||
"Total fee before discount10.05%-10.05%"
|
||||
)
|
||||
expect(page.get_by_test_id(INFRASTRUCTURE_FEES)).to_have_text("Infrastructure0.05%")
|
||||
expect(page.get_by_test_id(MAKER_FEES)).to_have_text("Maker10%")
|
||||
expect(page.get_by_test_id(LIQUIDITY_FEES)).to_have_text("Liquidity0%-0%")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, volume_discount, total_discount, referral_discount",
|
||||
[
|
||||
(1, "volume", "Volume discount10%", "10%", "Referral discount0%"),
|
||||
(2, "volume", "Volume discount20%", "20%", "Referral discount0%"),
|
||||
(1, "referral", "Volume discount0%", "10%", "Referral discount10%"),
|
||||
(2, "referral", "Volume discount0%", "20%", "Referral discount20%"),
|
||||
(2, "combo", "Volume discount20%", "36%", "Referral discount20%"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fees_page_discount_program_total_discount(
|
||||
tier,
|
||||
discount_program,
|
||||
volume_discount,
|
||||
referral_discount,
|
||||
total_discount,
|
||||
vega_instance,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TOTAL_DISCOUNT)).to_have_text(total_discount)
|
||||
expect(page.get_by_test_id(VOLUME_DISCOUNT_ROW)).to_have_text(volume_discount)
|
||||
expect(page.get_by_test_id(REFERRAL_DISCOUNT_ROW)).to_have_text(referral_discount)
|
||||
page.get_by_test_id(TOTAL_DISCOUNT).hover()
|
||||
expect(page.get_by_test_id(TOOLTIP_CONTENT).nth(0)).to_have_text(
|
||||
"The total discount is calculated according to the following formula: 1 - (1 - dvolume) ⋇ (1 - dreferral)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, past_epochs_volume, required_for_next_tier",
|
||||
[(1, "volume", "103", "97"), (2, "volume", "206", "")],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fees_page_volume_discount_program_my_current_volume(
|
||||
tier,
|
||||
discount_program,
|
||||
past_epochs_volume,
|
||||
required_for_next_tier,
|
||||
vega_instance,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(PAST_EPOCHS_VOLUME)).to_have_text(past_epochs_volume)
|
||||
|
||||
if tier == 1:
|
||||
expect(page.get_by_test_id(REQUIRED_FOR_NEXT_TIER)).to_have_text(
|
||||
required_for_next_tier
|
||||
)
|
||||
else:
|
||||
expect(page.get_by_test_id(REQUIRED_FOR_NEXT_TIER)).not_to_be_visible()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, notional_taker_volume, epochs_in_set",
|
||||
[(1, "referral", "103", "1"), (2, "referral", "207", "1")],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fees_page_referral_discount_program_referral_benefits(
|
||||
tier,
|
||||
vega_instance,
|
||||
discount_program,
|
||||
notional_taker_volume,
|
||||
epochs_in_set,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(RUNNING_NOTIONAL_TAKER_VOLUME)).to_have_text(
|
||||
notional_taker_volume
|
||||
)
|
||||
expect(page.get_by_test_id(EPOCHS_IN_REFERRAL_SET)).to_have_text(epochs_in_set)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, my_volume_test_id, my_volume_value, your_tier",
|
||||
[
|
||||
(1, "volume", "my-volume-value-0", "103", "your-volume-tier-0"),
|
||||
(2, "volume", "my-volume-value-1", "206", "your-volume-tier-1"),
|
||||
(1, "referral", "my-volume-value-0", "103", "your-referral-tier-0"),
|
||||
(2, "referral", "my-volume-value-1", "206", "your-referral-tier-1"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fees_page_discount_program_discount(
|
||||
tier,
|
||||
discount_program,
|
||||
my_volume_test_id,
|
||||
my_volume_value,
|
||||
your_tier,
|
||||
vega_instance,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TIER_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(TIER_VALUE_1)).to_have_text("2")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_0)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_1)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_0)).to_have_text("100")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_1)).to_have_text("200")
|
||||
|
||||
if discount_program == "volume":
|
||||
expect(page.get_by_test_id(my_volume_test_id)).to_have_text(my_volume_value)
|
||||
else:
|
||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_1)).to_have_text("2")
|
||||
|
||||
expect(page.get_by_test_id(your_tier).nth(1)).to_be_visible()
|
||||
expect(page.get_by_test_id(your_tier).nth(1)).to_have_text("Your tier")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, fees_after_discount",
|
||||
[
|
||||
(1, "volume", "9.045%"),
|
||||
(2, "volume", "8.04%"),
|
||||
(1, "referral", "9.045%"),
|
||||
(2, "referral", "8.04%"),
|
||||
(2, "combo", "6.432%"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fees_page_discount_program_fees_by_market(
|
||||
tier, discount_program, fees_after_discount, vega_instance, page: Page, market_ids
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
page.goto("/#/fees")
|
||||
pinned = page.locator(PINNED_ROW_LOCATOR)
|
||||
row = page.locator(ROW_LOCATOR)
|
||||
expect(pinned.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text(fees_after_discount)
|
||||
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
||||
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
||||
expect(row.locator(COL_LIQUIDITY_FEE)).to_have_text("0%")
|
||||
expect(row.locator(COL_TOTAL_FEE)).to_have_text("10.05%")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, discount, discount_value, total_fee",
|
||||
[
|
||||
(1, "volume", "-10%", "-0.01005 tDAI", "0.09045 tDAI"),
|
||||
(2, "volume", "-20%", "-0.0201 tDAI", "0.0804 tDAI"),
|
||||
(1, "referral", "-10%", "-0.01005 tDAI", "0.09045 tDAI"),
|
||||
(2, "referral", "-20%", "-0.0201 tDAI", "0.0804 tDAI"),
|
||||
(2, "combo", "-36%", "-0.03618 tDAI", "0.06432 tDAI"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_deal_ticket_discount_program(
|
||||
tier,
|
||||
discount_program,
|
||||
discount,
|
||||
discount_value,
|
||||
total_fee,
|
||||
vega_instance,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
market_id_key = f"tier_{tier}_{discount_program}"
|
||||
if discount_program == "combo":
|
||||
market_id_key = "combo"
|
||||
market_id = market_ids.get(market_id_key)
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(ORDER_SIZE).fill("1")
|
||||
page.get_by_test_id(ORDER_PRICE).fill("1")
|
||||
expect(page.get_by_test_id(DISCOUNT_PILL)).to_have_text(discount)
|
||||
page.get_by_test_id(FEES_TEXT).hover()
|
||||
tooltip = page.get_by_test_id(TOOLTIP_CONTENT).first
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_FACTOR)).to_have_text("0.05%")
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_VALUE)).to_have_text("0.0005 tDAI")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_FACTOR)).to_have_text("0%")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_VALUE)).to_have_text("0.00 tDAI")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_FACTOR)).to_have_text("10%")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_VALUE)).to_have_text("0.10 tDAI")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_FACTOR)).to_have_text("10.05%")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_VALUE)).to_have_text("0.1005 tDAI")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_FACTOR)).to_have_text(discount)
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_VALUE)).to_have_text(discount_value)
|
||||
expect(tooltip.get_by_test_id(TOTAL_FEE_VALUE)).to_have_text(total_fee)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, fee, fee_discount, price_1, size",
|
||||
[
|
||||
(1, "volume", "9.36158 tDAI", "1.04017 tDAI", "103.50 tDAI", "+1"),
|
||||
(2, "volume", "8.3214 tDAI", "2.08035 tDAI", "103.50 tDAI", "+1"),
|
||||
(
|
||||
1,
|
||||
"referral",
|
||||
"8.42543 tDAI ",
|
||||
"1.04017 tDAI",
|
||||
"103.50 tDAI",
|
||||
"+1",
|
||||
),
|
||||
(
|
||||
2,
|
||||
"referral",
|
||||
"13.31424 tDAI",
|
||||
"4.1607 tDAI",
|
||||
"207.00 tDAI",
|
||||
"+2",
|
||||
),
|
||||
(2, "combo", "10.6514 tDAI ", "7.48926 tDAI", "207.00 tDAI", "+2"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fills_taker_discount_program(
|
||||
tier,
|
||||
discount_program,
|
||||
fee,
|
||||
fee_discount,
|
||||
price_1,
|
||||
size,
|
||||
vega_instance,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
market_id_key = f"tier_{tier}_{discount_program}"
|
||||
if discount_program == "combo":
|
||||
market_id_key = "combo"
|
||||
market_id = market_ids.get(market_id_key)
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text(size)
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text(price_1)
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Taker")
|
||||
expect(row.locator(COL_FEE)).to_have_text(fee)
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text(fee_discount)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, fee, fee_discount, size, price_1",
|
||||
[
|
||||
(1, "volume", "-9.315 tDAI", "1.035 tDAI", "-1", "103.50 tDAI"),
|
||||
(2, "volume", "-8.28 tDAI", "2.07 tDAI", "-1", "103.50 tDAI"),
|
||||
(1, "referral", "-8.3835 tDAI", "1.035 tDAI", "-1", "103.50 tDAI"),
|
||||
(2, "referral", "-13.248 tDAI", "4.14 tDAI", "-2", "207.00 tDAI"),
|
||||
(2, "combo", "-10.5984 tDAI ", "7.452 tDAI", "-2", "207.00 tDAI"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fills_maker_discount_program(
|
||||
tier,
|
||||
discount_program,
|
||||
vega_instance,
|
||||
fee,
|
||||
fee_discount,
|
||||
size,
|
||||
price_1,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
market_id_key = f"tier_{tier}_{discount_program}"
|
||||
if discount_program == "combo":
|
||||
market_id_key = "combo"
|
||||
market_id = market_ids.get(market_id_key)
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
change_keys(page, vega_instance, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text(size)
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text(price_1)
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Maker")
|
||||
expect(row.locator(COL_FEE)).to_have_text(fee)
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text(fee_discount)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, fee",
|
||||
[
|
||||
(1, "volume", "9.315"),
|
||||
(2, "volume", "8.28"),
|
||||
(1, "referral", "8.3835"),
|
||||
(2, "referral", "13.248"),
|
||||
(2, "combo", "10.5984"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fills_maker_fee_tooltip_discount_program(
|
||||
tier, discount_program, fee, vega_instance, page: Page, market_ids
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
market_id_key = f"tier_{tier}_{discount_program}"
|
||||
if discount_program == "combo":
|
||||
market_id_key = "combo"
|
||||
market_id = market_ids.get(market_id_key)
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
change_keys(page, vega_instance, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
f"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-{fee} tDAITotal fees-{fee} tDAI"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, maker_fee, total_fee, infra_fee",
|
||||
[
|
||||
(1, "volume", "9.315", "9.36158", "0.04658"),
|
||||
(2, "volume", "8.28", "8.3214", "0.0414"),
|
||||
(1, "referral", "8.3835", "8.42543", "0.04193"),
|
||||
(2, "referral", "13.248", "13.31424", "0.06624"),
|
||||
(2, "combo", "10.5984", "10.6514", "0.053"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fills_taker_fee_tooltip_discount_program(
|
||||
tier,
|
||||
discount_program,
|
||||
vega_instance,
|
||||
maker_fee,
|
||||
total_fee,
|
||||
infra_fee,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
market_id_key = f"tier_{tier}_{discount_program}"
|
||||
if discount_program == "combo":
|
||||
market_id_key = "combo"
|
||||
market_id = market_ids.get(market_id_key)
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
f"If the market was activeFees to be paid by the taker; discounts are already applied.Infrastructure fee{infra_fee} tDAILiquidity fee0.00 tDAIMaker fee{maker_fee} tDAITotal fees{total_fee} tDAI"
|
||||
)
|
||||
@@ -0,0 +1,216 @@
|
||||
import pytest
|
||||
from fees_test_ids import *
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import (
|
||||
init_vega,
|
||||
init_page,
|
||||
auth_setup,
|
||||
risk_accepted_setup,
|
||||
cleanup_container,
|
||||
)
|
||||
from actions.utils import next_epoch, change_keys, forward_time
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(
|
||||
lambda: cleanup_container(vega_instance)
|
||||
)
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_combined_market(vega: VegaServiceNull):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_volume_discount_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"volume_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"volume_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
window_length=7,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
vega.update_referral_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"minimum_epochs": 1,
|
||||
"referral_reward_factor": 0.1,
|
||||
"referral_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"minimum_epochs": 2,
|
||||
"referral_reward_factor": 0.2,
|
||||
"referral_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
staking_tiers=[
|
||||
{"minimum_staked_tokens": 100, "referral_reward_multiplier": 1.1},
|
||||
{"minimum_staked_tokens": 200, "referral_reward_multiplier": 1.2},
|
||||
],
|
||||
window_length=1,
|
||||
)
|
||||
vega.create_referral_set(key_name=MM_WALLET.name)
|
||||
next_epoch(vega=vega)
|
||||
referral_set_id = list(vega.list_referral_sets().keys())[0]
|
||||
vega.apply_referral_code(key_name="Key 1", id=referral_set_id)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
for _ in range(2):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", 2, 110)
|
||||
forward_time(vega, True if _ < 2 - 1 else False)
|
||||
return market
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fees_page_discount_program_my_trading_fees(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(ADJUSTED_FEES)).to_have_text("6.432%-6.432%")
|
||||
expect(page.get_by_test_id(TOTAL_FEE_BEFORE_DISCOUNT)).to_have_text(
|
||||
"Total fee before discount10.05%-10.05%"
|
||||
)
|
||||
expect(page.get_by_test_id(INFRASTRUCTURE_FEES)).to_have_text("Infrastructure0.05%")
|
||||
expect(page.get_by_test_id(MAKER_FEES)).to_have_text("Maker10%")
|
||||
expect(page.get_by_test_id(LIQUIDITY_FEES)).to_have_text("Liquidity0%-0%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fees_page_discount_program_total_discount(
|
||||
page: Page,
|
||||
):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TOTAL_DISCOUNT)).to_have_text("36%")
|
||||
expect(page.get_by_test_id(VOLUME_DISCOUNT_ROW)).to_have_text("Volume discount20%")
|
||||
expect(page.get_by_test_id(REFERRAL_DISCOUNT_ROW)).to_have_text(
|
||||
"Referral discount20%"
|
||||
)
|
||||
page.get_by_test_id(TOTAL_DISCOUNT).hover()
|
||||
expect(page.get_by_test_id(TOOLTIP_CONTENT).nth(0)).to_have_text(
|
||||
"The total discount is calculated according to the following formula: 1 - (1 - dvolume) ⋇ (1 - dreferral)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fees_page_discount_program_fees_by_market(page: Page):
|
||||
page.goto("/#/fees")
|
||||
pinned = page.locator(PINNED_ROW_LOCATOR)
|
||||
row = page.locator(ROW_LOCATOR)
|
||||
expect(pinned.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text("6.432%")
|
||||
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
||||
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
||||
expect(row.locator(COL_LIQUIDITY_FEE)).to_have_text("0%")
|
||||
expect(row.locator(COL_TOTAL_FEE)).to_have_text("10.05%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_deal_ticket_discount_program(
|
||||
page: Page,
|
||||
setup_combined_market,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_combined_market}")
|
||||
page.get_by_test_id(ORDER_SIZE).fill("1")
|
||||
page.get_by_test_id(ORDER_PRICE).fill("1")
|
||||
expect(page.get_by_test_id(DISCOUNT_PILL)).to_have_text("-36%")
|
||||
page.get_by_test_id(FEES_TEXT).hover()
|
||||
tooltip = page.get_by_test_id(TOOLTIP_CONTENT).first
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_FACTOR)).to_have_text("0.05%")
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_VALUE)).to_have_text("0.0005 tDAI")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_FACTOR)).to_have_text("0%")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_VALUE)).to_have_text("0.00 tDAI")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_FACTOR)).to_have_text("10%")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_VALUE)).to_have_text("0.10 tDAI")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_FACTOR)).to_have_text("10.05%")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_VALUE)).to_have_text("0.1005 tDAI")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_FACTOR)).to_have_text("-36%")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_VALUE)).to_have_text("-0.03618 tDAI")
|
||||
expect(tooltip.get_by_test_id(TOTAL_FEE_VALUE)).to_have_text("0.06432 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fills_taker_discount_program(
|
||||
page: Page,
|
||||
setup_combined_market,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_combined_market}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("+2")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("207.00 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Taker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("10.6514 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("7.48926 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fills_maker_discount_program(
|
||||
vega: VegaServiceNull,
|
||||
page: Page,
|
||||
setup_combined_market,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_combined_market}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("-2")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("207.00 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Maker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("-10.5984 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("7.452 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fills_maker_fee_tooltip_discount_program(
|
||||
vega: VegaServiceNull, page: Page, setup_combined_market
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_combined_market}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-10.5984 tDAITotal fees-10.5984 tDAI"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fills_taker_fee_tooltip_discount_program(
|
||||
page: Page,
|
||||
setup_combined_market,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_combined_market}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-10.5984 tDAITotal fees-10.5984 tDAI"
|
||||
)
|
||||
@@ -0,0 +1,221 @@
|
||||
import pytest
|
||||
from fees_test_ids import *
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import (
|
||||
init_vega,
|
||||
init_page,
|
||||
auth_setup,
|
||||
risk_accepted_setup,
|
||||
cleanup_container,
|
||||
)
|
||||
from actions.utils import next_epoch, change_keys, forward_time
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(
|
||||
lambda: cleanup_container(vega_instance)
|
||||
)
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_referral_discount_program(vega: VegaServiceNull):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_referral_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"minimum_epochs": 1,
|
||||
"referral_reward_factor": 0.1,
|
||||
"referral_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"minimum_epochs": 2,
|
||||
"referral_reward_factor": 0.2,
|
||||
"referral_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
staking_tiers=[
|
||||
{"minimum_staked_tokens": 100, "referral_reward_multiplier": 1.1},
|
||||
{"minimum_staked_tokens": 200, "referral_reward_multiplier": 1.2},
|
||||
],
|
||||
window_length=1,
|
||||
)
|
||||
vega.create_referral_set(key_name=MM_WALLET.name)
|
||||
next_epoch(vega=vega)
|
||||
referral_set_id = list(vega.list_referral_sets().keys())[0]
|
||||
vega.apply_referral_code(key_name="Key 1", id=referral_set_id)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
for _ in range(2):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", 1, 110)
|
||||
forward_time(vega, True if _ < 2 - 1 else False)
|
||||
|
||||
return market
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fees_page_discount_program_my_trading_fees(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(ADJUSTED_FEES)).to_have_text("9.045%-9.045%")
|
||||
expect(page.get_by_test_id(TOTAL_FEE_BEFORE_DISCOUNT)).to_have_text(
|
||||
"Total fee before discount10.05%-10.05%"
|
||||
)
|
||||
expect(page.get_by_test_id(INFRASTRUCTURE_FEES)).to_have_text("Infrastructure0.05%")
|
||||
expect(page.get_by_test_id(MAKER_FEES)).to_have_text("Maker10%")
|
||||
expect(page.get_by_test_id(LIQUIDITY_FEES)).to_have_text("Liquidity0%-0%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fees_page_discount_program_total_discount(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TOTAL_DISCOUNT)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(VOLUME_DISCOUNT_ROW)).to_have_text("Volume discount0%")
|
||||
expect(page.get_by_test_id(REFERRAL_DISCOUNT_ROW)).to_have_text(
|
||||
"Referral discount10%"
|
||||
)
|
||||
page.get_by_test_id(TOTAL_DISCOUNT).hover()
|
||||
expect(page.get_by_test_id(TOOLTIP_CONTENT).nth(0)).to_have_text(
|
||||
"The total discount is calculated according to the following formula: 1 - (1 - dvolume) ⋇ (1 - dreferral)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fees_page_referral_discount_program_referral_benefits(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(RUNNING_NOTIONAL_TAKER_VOLUME)).to_have_text("103")
|
||||
expect(page.get_by_test_id(EPOCHS_IN_REFERRAL_SET)).to_have_text("1")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fees_page_discount_program_discount(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TIER_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(TIER_VALUE_1)).to_have_text("2")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_0)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_1)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_0)).to_have_text("100")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_1)).to_have_text("200")
|
||||
|
||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_1)).to_have_text("2")
|
||||
|
||||
expect(page.get_by_test_id("your-referral-tier-0").nth(1)).to_be_visible()
|
||||
expect(page.get_by_test_id("your-referral-tier-0").nth(1)).to_have_text("Your tier")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fees_page_discount_program_fees_by_market(page: Page):
|
||||
page.goto("/#/fees")
|
||||
pinned = page.locator(PINNED_ROW_LOCATOR)
|
||||
row = page.locator(ROW_LOCATOR)
|
||||
expect(pinned.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text("9.045%")
|
||||
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
||||
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
||||
expect(row.locator(COL_LIQUIDITY_FEE)).to_have_text("0%")
|
||||
expect(row.locator(COL_TOTAL_FEE)).to_have_text("10.05%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_deal_ticket_discount_program(
|
||||
page: Page, setup_market_with_referral_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
page.get_by_test_id(ORDER_SIZE).fill("1")
|
||||
page.get_by_test_id(ORDER_PRICE).fill("1")
|
||||
expect(page.get_by_test_id(DISCOUNT_PILL)).to_have_text("-10%")
|
||||
page.get_by_test_id(FEES_TEXT).hover()
|
||||
tooltip = page.get_by_test_id(TOOLTIP_CONTENT).first
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_FACTOR)).to_have_text("0.05%")
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_VALUE)).to_have_text("0.0005 tDAI")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_FACTOR)).to_have_text("0%")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_VALUE)).to_have_text("0.00 tDAI")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_FACTOR)).to_have_text("10%")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_VALUE)).to_have_text("0.10 tDAI")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_FACTOR)).to_have_text("10.05%")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_VALUE)).to_have_text("0.1005 tDAI")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_FACTOR)).to_have_text("-10%")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_VALUE)).to_have_text("-0.01005 tDAI")
|
||||
expect(tooltip.get_by_test_id(TOTAL_FEE_VALUE)).to_have_text("0.09045 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fills_taker_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_referral_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("+1")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Taker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("8.42543 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("1.04017 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fills_maker_discount_program(
|
||||
vega: VegaServiceNull,
|
||||
page: Page,
|
||||
setup_market_with_referral_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("-1")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Maker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("-8.3835 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("1.035 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fills_maker_fee_tooltip_discount_program(
|
||||
vega: VegaServiceNull, page: Page, setup_market_with_referral_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-8.3835 tDAITotal fees-8.3835 tDAI"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fills_taker_fee_tooltip_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_referral_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-8.3835 tDAITotal fees-8.3835 tDAI"
|
||||
)
|
||||
@@ -0,0 +1,222 @@
|
||||
import pytest
|
||||
from fees_test_ids import *
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import (
|
||||
init_vega,
|
||||
init_page,
|
||||
auth_setup,
|
||||
risk_accepted_setup,
|
||||
cleanup_container,
|
||||
)
|
||||
from actions.utils import next_epoch, change_keys, forward_time
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(
|
||||
lambda: cleanup_container(vega_instance)
|
||||
)
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_referral_discount_program(vega: VegaServiceNull):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_referral_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"minimum_epochs": 1,
|
||||
"referral_reward_factor": 0.1,
|
||||
"referral_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"minimum_epochs": 2,
|
||||
"referral_reward_factor": 0.2,
|
||||
"referral_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
staking_tiers=[
|
||||
{"minimum_staked_tokens": 100, "referral_reward_multiplier": 1.1},
|
||||
{"minimum_staked_tokens": 200, "referral_reward_multiplier": 1.2},
|
||||
],
|
||||
window_length=1,
|
||||
)
|
||||
vega.create_referral_set(key_name=MM_WALLET.name)
|
||||
next_epoch(vega=vega)
|
||||
referral_set_id = list(vega.list_referral_sets().keys())[0]
|
||||
vega.apply_referral_code(key_name="Key 1", id=referral_set_id)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
for _ in range(2):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", 2, 110)
|
||||
forward_time(vega, True if _ < 2 - 1 else False)
|
||||
|
||||
return market
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fees_page_discount_program_my_trading_fees(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(ADJUSTED_FEES)).to_have_text("8.04%-8.04%")
|
||||
expect(page.get_by_test_id(TOTAL_FEE_BEFORE_DISCOUNT)).to_have_text(
|
||||
"Total fee before discount10.05%-10.05%"
|
||||
)
|
||||
expect(page.get_by_test_id(INFRASTRUCTURE_FEES)).to_have_text("Infrastructure0.05%")
|
||||
expect(page.get_by_test_id(MAKER_FEES)).to_have_text("Maker10%")
|
||||
expect(page.get_by_test_id(LIQUIDITY_FEES)).to_have_text("Liquidity0%-0%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fees_page_discount_program_total_discount(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TOTAL_DISCOUNT)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(VOLUME_DISCOUNT_ROW)).to_have_text("Volume discount0%")
|
||||
expect(page.get_by_test_id(REFERRAL_DISCOUNT_ROW)).to_have_text(
|
||||
"Referral discount20%"
|
||||
)
|
||||
page.get_by_test_id(TOTAL_DISCOUNT).hover()
|
||||
expect(page.get_by_test_id(TOOLTIP_CONTENT).nth(0)).to_have_text(
|
||||
"The total discount is calculated according to the following formula: 1 - (1 - dvolume) ⋇ (1 - dreferral)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fees_page_referral_discount_program_referral_benefits(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(RUNNING_NOTIONAL_TAKER_VOLUME)).to_have_text("207")
|
||||
expect(page.get_by_test_id(REQUIRED_FOR_NEXT_TIER)).not_to_be_visible()
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fees_page_discount_program_discount(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TIER_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(TIER_VALUE_1)).to_have_text("2")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_0)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_1)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_0)).to_have_text("100")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_1)).to_have_text("200")
|
||||
|
||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_1)).to_have_text("2")
|
||||
|
||||
expect(page.get_by_test_id("your-referral-tier-1").nth(1)).to_be_visible()
|
||||
expect(page.get_by_test_id("your-referral-tier-1").nth(1)).to_have_text("Your tier")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fees_page_discount_program_fees_by_market(page: Page):
|
||||
page.goto("/#/fees")
|
||||
pinned = page.locator(PINNED_ROW_LOCATOR)
|
||||
row = page.locator(ROW_LOCATOR)
|
||||
expect(pinned.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text("8.04%")
|
||||
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
||||
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
||||
expect(row.locator(COL_LIQUIDITY_FEE)).to_have_text("0%")
|
||||
expect(row.locator(COL_TOTAL_FEE)).to_have_text("10.05%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_deal_ticket_discount_program(
|
||||
page: Page, setup_market_with_referral_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
page.get_by_test_id(ORDER_SIZE).fill("1")
|
||||
page.get_by_test_id(ORDER_PRICE).fill("1")
|
||||
expect(page.get_by_test_id(DISCOUNT_PILL)).to_have_text("-20%")
|
||||
page.get_by_test_id(FEES_TEXT).hover()
|
||||
tooltip = page.get_by_test_id(TOOLTIP_CONTENT).first
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_FACTOR)).to_have_text("0.05%")
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_VALUE)).to_have_text("0.0005 tDAI")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_FACTOR)).to_have_text("0%")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_VALUE)).to_have_text("0.00 tDAI")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_FACTOR)).to_have_text("10%")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_VALUE)).to_have_text("0.10 tDAI")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_FACTOR)).to_have_text("10.05%")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_VALUE)).to_have_text("0.1005 tDAI")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_FACTOR)).to_have_text("-20%")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_VALUE)).to_have_text("-0.0201 tDAI")
|
||||
expect(tooltip.get_by_test_id(TOTAL_FEE_VALUE)).to_have_text("0.0804 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fills_taker_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_referral_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("+2")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("207.00 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Taker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("13.31424 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("4.1607 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fills_maker_discount_program(
|
||||
vega: VegaServiceNull,
|
||||
page: Page,
|
||||
setup_market_with_referral_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("-2")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("207.00 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Maker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("-13.248 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("4.14 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fills_maker_fee_tooltip_discount_program(
|
||||
vega: VegaServiceNull, page: Page, setup_market_with_referral_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
" If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-13.248 tDAITotal fees-13.248 tDAI "
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fills_taker_fee_tooltip_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_referral_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-13.248 tDAITotal fees-13.248 tDAI "
|
||||
)
|
||||
@@ -0,0 +1,210 @@
|
||||
import pytest
|
||||
from fees_test_ids import *
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import (
|
||||
init_vega,
|
||||
init_page,
|
||||
auth_setup,
|
||||
risk_accepted_setup,
|
||||
cleanup_container,
|
||||
)
|
||||
from actions.utils import next_epoch, change_keys, forward_time
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(
|
||||
lambda: cleanup_container(vega_instance)
|
||||
)
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_volume_discount_program(vega: VegaServiceNull):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_volume_discount_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"volume_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"volume_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
window_length=7,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
for _ in range(2):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", 1, 110)
|
||||
forward_time(vega, True if _ < 2 - 1 else False)
|
||||
return market
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fees_page_discount_program_my_trading_fees(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(ADJUSTED_FEES)).to_have_text("9.045%-9.045%")
|
||||
expect(page.get_by_test_id(TOTAL_FEE_BEFORE_DISCOUNT)).to_have_text(
|
||||
"Total fee before discount10.05%-10.05%"
|
||||
)
|
||||
expect(page.get_by_test_id(INFRASTRUCTURE_FEES)).to_have_text("Infrastructure0.05%")
|
||||
expect(page.get_by_test_id(MAKER_FEES)).to_have_text("Maker10%")
|
||||
expect(page.get_by_test_id(LIQUIDITY_FEES)).to_have_text("Liquidity0%-0%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fees_page_discount_program_total_discount(
|
||||
page: Page,
|
||||
):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TOTAL_DISCOUNT)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(VOLUME_DISCOUNT_ROW)).to_have_text("Volume discount10%")
|
||||
expect(page.get_by_test_id(REFERRAL_DISCOUNT_ROW)).to_have_text(
|
||||
"Referral discount0%"
|
||||
)
|
||||
page.get_by_test_id(TOTAL_DISCOUNT).hover()
|
||||
expect(page.get_by_test_id(TOOLTIP_CONTENT).nth(0)).to_have_text(
|
||||
"The total discount is calculated according to the following formula: 1 - (1 - dvolume) ⋇ (1 - dreferral)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fees_page_volume_discount_program_my_current_volume(
|
||||
page: Page,
|
||||
):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(PAST_EPOCHS_VOLUME)).to_have_text("103")
|
||||
|
||||
expect(page.get_by_test_id(REQUIRED_FOR_NEXT_TIER)).to_have_text("97")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fees_page_discount_program_discount(
|
||||
page: Page,
|
||||
):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TIER_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(TIER_VALUE_1)).to_have_text("2")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_0)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_1)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_0)).to_have_text("100")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_1)).to_have_text("200")
|
||||
expect(page.get_by_test_id("my-volume-value-0")).to_have_text("103")
|
||||
expect(page.get_by_test_id("your-volume-tier-0").nth(1)).to_be_visible()
|
||||
expect(page.get_by_test_id("your-volume-tier-0").nth(1)).to_have_text("Your tier")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fees_page_discount_program_fees_by_market(page: Page):
|
||||
page.goto("/#/fees")
|
||||
pinned = page.locator(PINNED_ROW_LOCATOR)
|
||||
row = page.locator(ROW_LOCATOR)
|
||||
expect(pinned.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text("9.045%")
|
||||
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
||||
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
||||
expect(row.locator(COL_LIQUIDITY_FEE)).to_have_text("0%")
|
||||
expect(row.locator(COL_TOTAL_FEE)).to_have_text("10.05%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_deal_ticket_discount_program_testing(
|
||||
page: Page, setup_market_with_volume_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
page.get_by_test_id(ORDER_SIZE).fill("1")
|
||||
page.get_by_test_id(ORDER_PRICE).fill("1")
|
||||
expect(page.get_by_test_id(DISCOUNT_PILL)).to_have_text("-10%")
|
||||
page.get_by_test_id(FEES_TEXT).hover()
|
||||
tooltip = page.get_by_test_id(TOOLTIP_CONTENT).first
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_FACTOR)).to_have_text("0.05%")
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_VALUE)).to_have_text("0.0005 tDAI")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_FACTOR)).to_have_text("0%")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_VALUE)).to_have_text("0.00 tDAI")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_FACTOR)).to_have_text("10%")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_VALUE)).to_have_text("0.10 tDAI")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_FACTOR)).to_have_text("10.05%")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_VALUE)).to_have_text("0.1005 tDAI")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_FACTOR)).to_have_text("-10%")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_VALUE)).to_have_text("-0.01005 tDAI")
|
||||
expect(tooltip.get_by_test_id(TOTAL_FEE_VALUE)).to_have_text("0.09045 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fills_taker_discount_program(
|
||||
page: Page, setup_market_with_volume_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("+1")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Taker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("9.36158 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("1.04017 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fills_maker_discount_program(
|
||||
page: Page, setup_market_with_volume_discount_program, vega: VegaServiceNull
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("-1")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Maker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("-9.315 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("1.035 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fills_maker_fee_tooltip_discount_program(
|
||||
vega: VegaServiceNull, page: Page, setup_market_with_volume_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-9.315 tDAITotal fees-9.315 tDAI"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fills_taker_fee_tooltip_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_volume_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-9.315 tDAITotal fees-9.315 tDAI"
|
||||
)
|
||||
@@ -0,0 +1,209 @@
|
||||
import pytest
|
||||
from fees_test_ids import *
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import (
|
||||
init_vega,
|
||||
init_page,
|
||||
auth_setup,
|
||||
risk_accepted_setup,
|
||||
cleanup_container,
|
||||
)
|
||||
from actions.utils import next_epoch, change_keys, forward_time
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(
|
||||
lambda: cleanup_container(vega_instance)
|
||||
)
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_volume_discount_program(vega: VegaServiceNull):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_volume_discount_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"volume_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"volume_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
window_length=7,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
for _ in range(3):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", 1, 110)
|
||||
forward_time(vega, True if _ < 3 - 1 else False)
|
||||
|
||||
return market
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fees_page_discount_program_my_trading_fees(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(ADJUSTED_FEES)).to_have_text("8.04%-8.04%")
|
||||
expect(page.get_by_test_id(TOTAL_FEE_BEFORE_DISCOUNT)).to_have_text(
|
||||
"Total fee before discount10.05%-10.05%"
|
||||
)
|
||||
expect(page.get_by_test_id(INFRASTRUCTURE_FEES)).to_have_text("Infrastructure0.05%")
|
||||
expect(page.get_by_test_id(MAKER_FEES)).to_have_text("Maker10%")
|
||||
expect(page.get_by_test_id(LIQUIDITY_FEES)).to_have_text("Liquidity0%-0%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fees_page_discount_program_total_discount(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TOTAL_DISCOUNT)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(VOLUME_DISCOUNT_ROW)).to_have_text("Volume discount20%")
|
||||
expect(page.get_by_test_id(REFERRAL_DISCOUNT_ROW)).to_have_text(
|
||||
"Referral discount0%"
|
||||
)
|
||||
page.get_by_test_id(TOTAL_DISCOUNT).hover()
|
||||
expect(page.get_by_test_id(TOOLTIP_CONTENT).nth(0)).to_have_text(
|
||||
"The total discount is calculated according to the following formula: 1 - (1 - dvolume) ⋇ (1 - dreferral)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fees_page_volume_discount_program_my_current_volume(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(PAST_EPOCHS_VOLUME)).to_have_text("206")
|
||||
expect(page.get_by_test_id(REQUIRED_FOR_NEXT_TIER)).not_to_be_visible()
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fees_page_discount_program_discount(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TIER_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(TIER_VALUE_1)).to_have_text("2")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_0)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_1)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_0)).to_have_text("100")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_1)).to_have_text("200")
|
||||
expect(page.get_by_test_id("my-volume-value-1")).to_have_text("206")
|
||||
expect(page.get_by_test_id("your-volume-tier-1").nth(1)).to_be_visible()
|
||||
expect(page.get_by_test_id("your-volume-tier-1").nth(1)).to_have_text("Your tier")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fees_page_discount_program_fees_by_market(page: Page):
|
||||
page.goto("/#/fees")
|
||||
pinned = page.locator(PINNED_ROW_LOCATOR)
|
||||
row = page.locator(ROW_LOCATOR)
|
||||
expect(pinned.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text("8.04%")
|
||||
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
||||
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
||||
expect(row.locator(COL_LIQUIDITY_FEE)).to_have_text("0%")
|
||||
expect(row.locator(COL_TOTAL_FEE)).to_have_text("10.05%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_deal_ticket_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_volume_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
page.get_by_test_id(ORDER_SIZE).fill("1")
|
||||
page.get_by_test_id(ORDER_PRICE).fill("1")
|
||||
expect(page.get_by_test_id(DISCOUNT_PILL)).to_have_text("-20%")
|
||||
page.get_by_test_id(FEES_TEXT).hover()
|
||||
tooltip = page.get_by_test_id(TOOLTIP_CONTENT).first
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_FACTOR)).to_have_text("0.05%")
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_VALUE)).to_have_text("0.0005 tDAI")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_FACTOR)).to_have_text("0%")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_VALUE)).to_have_text("0.00 tDAI")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_FACTOR)).to_have_text("10%")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_VALUE)).to_have_text("0.10 tDAI")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_FACTOR)).to_have_text("10.05%")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_VALUE)).to_have_text("0.1005 tDAI")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_FACTOR)).to_have_text("-20%")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_VALUE)).to_have_text("-0.0201 tDAI")
|
||||
expect(tooltip.get_by_test_id(TOTAL_FEE_VALUE)).to_have_text("0.0804 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fills_taker_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_volume_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("+1")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Taker")
|
||||
expect(row.locator(COL_FEE)).to_have_text(
|
||||
"8.3214 tDAI",
|
||||
)
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("2.08035 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fills_maker_discount_program(
|
||||
vega: VegaServiceNull,
|
||||
page: Page,
|
||||
setup_market_with_volume_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("-1")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Maker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("-8.28 tDAI ")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("2.07 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fills_maker_fee_tooltip_discount_program(
|
||||
vega, page: Page, setup_market_with_volume_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-8.28 tDAITotal fees-8.28 tDAI"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fills_taker_fee_tooltip_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_volume_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-8.28 tDAITotal fees-8.28 tDAI "
|
||||
)
|
||||
@@ -14,7 +14,7 @@ logger = logging.getLogger()
|
||||
@pytest.fixture(scope="class")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@@ -142,8 +142,7 @@ class TestGetStarted:
|
||||
def test_get_started_seen_already(self, simple_market, page: Page):
|
||||
page.goto(f"/#/markets/{simple_market}")
|
||||
get_started_locator = page.get_by_test_id("connect-vega-wallet")
|
||||
page.wait_for_selector(
|
||||
'[data-testid="connect-vega-wallet"]', state="attached")
|
||||
page.wait_for_selector('[data-testid="connect-vega-wallet"]', state="attached")
|
||||
expect(get_started_locator).to_be_enabled
|
||||
expect(get_started_locator).to_be_visible
|
||||
# 0007-FUGS-015
|
||||
@@ -153,7 +152,9 @@ class TestGetStarted:
|
||||
expect(page.get_by_test_id("dialog-content").nth(1)).to_be_visible()
|
||||
|
||||
@pytest.mark.skip("tbd-market-sim")
|
||||
def test_redirect_default_market(self, continuous_market, vega: VegaServiceNull, page: Page):
|
||||
def test_redirect_default_market(
|
||||
self, continuous_market, vega: VegaServiceNull, page: Page
|
||||
):
|
||||
page.goto("/")
|
||||
# 0007-FUGS-012
|
||||
expect(page).to_have_url(
|
||||
|
||||
@@ -8,7 +8,7 @@ from actions.utils import next_epoch, truncate_middle, change_keys
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from actions.utils import next_epoch
|
||||
@pytest.fixture(scope="class")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ market_title_test_id = "accordion-title"
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@@ -107,7 +107,6 @@ def test_market_info_liquidation(page: Page):
|
||||
validate_info_section(page, fields)
|
||||
|
||||
|
||||
@pytest.mark.skip("core issue #5681")
|
||||
def test_market_info_key_details(page: Page, vega: VegaServiceNull):
|
||||
# 6002-MDET-201
|
||||
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 = [
|
||||
["Market ID", short_market_id],
|
||||
["Name", "BTC:DAI_2023"],
|
||||
["Parent Market ID", "-"],
|
||||
["Insurance Pool Fraction", "-"],
|
||||
["Status", "Active"],
|
||||
["Trading Mode", "Continuous"],
|
||||
["Market Decimal Places", "5"],
|
||||
|
||||
@@ -14,7 +14,7 @@ col_market_id = '[col-id="market"] [data-testid="stack-cell-primary"]'
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ COL_ID_FEE = ".ag-center-cols-container [col-id='fee'] .ag-cell-value"
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ from actions.utils import next_epoch
|
||||
from wallet_config import MM_WALLET, MM_WALLET2, GOVERNANCE_WALLET
|
||||
from vega_sim.api import governance
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
|
||||
# 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(
|
||||
"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
|
||||
market_id = proposed_market
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
# 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
|
||||
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()
|
||||
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"
|
||||
@@ -123,16 +127,16 @@ def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
|
||||
expect(market_state).to_have_text("Active")
|
||||
|
||||
vega.update_market_state(
|
||||
market_id = market_id,
|
||||
proposal_key = MM_WALLET.name,
|
||||
market_state = MarketStateUpdateType.Suspend,
|
||||
forward_time_to_enactment = False
|
||||
market_id=market_id,
|
||||
proposal_key=MM_WALLET.name,
|
||||
market_state=MarketStateUpdateType.Suspend,
|
||||
forward_time_to_enactment=False
|
||||
)
|
||||
|
||||
expect(
|
||||
page
|
||||
.get_by_test_id("market-banner")
|
||||
.get_by_test_id(f"update-state-banner-{market_id}")
|
||||
.get_by_test_id("market-banner")
|
||||
.get_by_test_id(f"update-state-banner-{market_id}")
|
||||
).to_be_visible()
|
||||
|
||||
next_epoch(vega=vega)
|
||||
@@ -143,12 +147,14 @@ def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
|
||||
|
||||
# banner should not show after resume
|
||||
vega.update_market_state(
|
||||
market_id = market_id,
|
||||
proposal_key = MM_WALLET.name,
|
||||
market_state = MarketStateUpdateType.Resume,
|
||||
forward_time_to_enactment = False
|
||||
market_id=market_id,
|
||||
proposal_key=MM_WALLET.name,
|
||||
market_state=MarketStateUpdateType.Resume,
|
||||
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)
|
||||
|
||||
expect(page.get_by_test_id("market-banner")).not_to_be_visible()
|
||||
|
||||
@@ -7,11 +7,10 @@ from conftest import init_page, init_vega, cleanup_container
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
# we can reuse single page instance in all tests
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
|
||||
@@ -49,7 +49,7 @@ def markets(vega: VegaServiceNull):
|
||||
price=130,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.forward("2s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -63,7 +63,7 @@ def markets(vega: VegaServiceNull):
|
||||
price=88,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.forward("2s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -77,7 +77,7 @@ def markets(vega: VegaServiceNull):
|
||||
price=88,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.forward("2s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -92,7 +92,7 @@ def markets(vega: VegaServiceNull):
|
||||
wait=False,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.forward("2s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -105,7 +105,7 @@ def markets(vega: VegaServiceNull):
|
||||
volume=100,
|
||||
price=104,
|
||||
)
|
||||
vega.forward("10s")
|
||||
vega.forward("2s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -120,7 +120,7 @@ def markets(vega: VegaServiceNull):
|
||||
expires_at=vega.get_blockchain_time() + 5 * 1e9,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.forward("2s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -134,7 +134,7 @@ def markets(vega: VegaServiceNull):
|
||||
volume=20,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.forward("2s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -148,7 +148,7 @@ def markets(vega: VegaServiceNull):
|
||||
volume=40,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.forward("2s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -162,7 +162,7 @@ def markets(vega: VegaServiceNull):
|
||||
volume=60,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.forward("2s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -177,7 +177,7 @@ def markets(vega: VegaServiceNull):
|
||||
volume=60,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.forward("2s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -190,8 +190,7 @@ def markets(vega: VegaServiceNull):
|
||||
volume=10,
|
||||
price=150,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -205,7 +204,6 @@ def markets(vega: VegaServiceNull):
|
||||
price=160,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -219,7 +217,6 @@ def markets(vega: VegaServiceNull):
|
||||
price=60,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
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()
|
||||
|
||||
wait_for_toast_confirmation(page, timeout=5000)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
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()
|
||||
|
||||
wait_for_toast_confirmation(page, timeout=5000)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
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()
|
||||
|
||||
wait_for_toast_confirmation(page, timeout=5000)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
|
||||
@@ -1,21 +1,23 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from typing import List
|
||||
from actions.vega import submit_order, submit_liquidity, submit_multiple_orders
|
||||
from conftest import init_vega, cleanup_container
|
||||
from fixtures.market import setup_simple_market
|
||||
from wallet_config import MM_WALLET, MM_WALLET2
|
||||
from actions.utils import next_epoch
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def setup_market(vega):
|
||||
def setup_market(vega: VegaServiceNull):
|
||||
market_id = setup_simple_market(vega)
|
||||
submit_liquidity(vega, MM_WALLET.name, market_id)
|
||||
submit_multiple_orders(
|
||||
@@ -33,10 +35,9 @@ def setup_market(vega):
|
||||
[[10, 69.995], [5, 70], [5, 85], [3, 90], [3, 95]],
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
|
||||
return [
|
||||
vega,
|
||||
market_id,
|
||||
@@ -46,19 +47,19 @@ def setup_market(vega):
|
||||
# these values don't align with the multiple orders above as
|
||||
# creating a trade triggers the liquidity provision
|
||||
orderbook_content = [
|
||||
[130.00500, 10, 94],
|
||||
[130.00000, 3, 84],
|
||||
[120.00000, 7, 81],
|
||||
[110.00000, 5, 74],
|
||||
[105.00000, 2, 69],
|
||||
[101.00000, 67, 67],
|
||||
[130.00500, 10, 126],
|
||||
[130.00000, 3, 116],
|
||||
[120.00000, 7, 113],
|
||||
[110.00000, 5, 106],
|
||||
[105.00000, 2, 101],
|
||||
[101.00000, 99, 99],
|
||||
# mid
|
||||
[99.00000, 102, 102],
|
||||
[95.00000, 3, 105],
|
||||
[90.00000, 3, 108],
|
||||
[85.00000, 5, 113],
|
||||
[70.00000, 5, 118],
|
||||
[69.99500, 10, 128],
|
||||
[99.00000, 99, 99],
|
||||
[95.00000, 3, 102],
|
||||
[90.00000, 3, 105],
|
||||
[85.00000, 5, 110],
|
||||
[70.00000, 5, 115],
|
||||
[69.99500, 10, 125],
|
||||
]
|
||||
|
||||
|
||||
@@ -81,7 +82,6 @@ def verify_prices_descending(page: Page):
|
||||
assert prices == sorted(prices, reverse=True)
|
||||
|
||||
|
||||
@pytest.mark.skip("tbd")
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_orderbook_grid_content(setup_market, page: Page):
|
||||
vega = setup_market[0]
|
||||
@@ -109,6 +109,7 @@ def test_orderbook_grid_content(setup_market, page: Page):
|
||||
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega)
|
||||
|
||||
# 6003-ORDB-001
|
||||
# 6003-ORDB-002
|
||||
@@ -120,7 +121,6 @@ def test_orderbook_grid_content(setup_market, page: Page):
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
|
||||
page.locator("[data-testid=Orderbook]").click()
|
||||
|
||||
# 6003-ORDB-013
|
||||
assert (
|
||||
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):
|
||||
market_id = setup_market[1]
|
||||
# 6003-ORDB-008
|
||||
orderbook_content_0_00 = [
|
||||
[130.01, 10, 94],
|
||||
[130.00, 3, 84],
|
||||
[120.00, 7, 81],
|
||||
[110.00, 5, 74],
|
||||
[105.00, 2, 69],
|
||||
[101.00, 67, 67],
|
||||
orderbook_content_0_01 = [
|
||||
[130.01, 10, 126],
|
||||
[130.00, 3, 116],
|
||||
[120.00, 7, 113],
|
||||
[110.00, 5, 106],
|
||||
[105.00, 2, 101],
|
||||
[101.00, 99, 99],
|
||||
# mid
|
||||
[99.00, 102, 102],
|
||||
[95.00, 3, 105],
|
||||
[90.00, 3, 108],
|
||||
[85.00, 5, 113],
|
||||
[70.00, 15, 128],
|
||||
[99.00, 99, 99],
|
||||
[95.00, 3, 102],
|
||||
[90.00, 3, 105],
|
||||
[85.00, 5, 110],
|
||||
[70.00, 15, 125],
|
||||
]
|
||||
|
||||
orderbook_content_10 = [
|
||||
[130, 13, 94],
|
||||
[120, 7, 81],
|
||||
[110, 7, 74],
|
||||
[100, 67, 67],
|
||||
orderbook_content_1 = [
|
||||
[130, 13, 126],
|
||||
[120, 7, 113],
|
||||
[110, 5, 106],
|
||||
[105, 2, 101],
|
||||
[101, 99, 99],
|
||||
# mid
|
||||
[100, 105, 105],
|
||||
[90, 8, 113],
|
||||
[70, 15, 128],
|
||||
[99, 99, 99],
|
||||
[95, 3, 102],
|
||||
[90, 3, 105],
|
||||
[85, 5, 110],
|
||||
[70, 15, 125],
|
||||
]
|
||||
|
||||
orderbook_content_100 = [
|
||||
[100, 94, 94],
|
||||
# mid
|
||||
[100, 128, 128],
|
||||
]
|
||||
|
||||
resolutions = [
|
||||
["0.00", orderbook_content_0_00],
|
||||
["10", orderbook_content_10],
|
||||
["100", orderbook_content_100],
|
||||
["0.01", orderbook_content_0_01],
|
||||
["1", orderbook_content_1],
|
||||
]
|
||||
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
# temporary skip
|
||||
# for resolution in resolutions:
|
||||
# page.get_by_test_id("resolution").click()
|
||||
# page.get_by_role("menu").get_by_text(resolution[0], exact=True).click()
|
||||
# verify_orderbook_grid(page, resolution[1])
|
||||
for resolution in resolutions:
|
||||
page.get_by_test_id("resolution").click()
|
||||
page.get_by_role("menuitem").get_by_text(resolution[0], exact=True).click()
|
||||
verify_orderbook_grid(page, resolution[1])
|
||||
|
||||
|
||||
@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())
|
||||
|
||||
|
||||
@pytest.mark.skip("tbd")
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
def test_orderbook_price_movement(setup_market, page: Page):
|
||||
vega = setup_market[0]
|
||||
|
||||
@@ -18,7 +18,7 @@ class TestPerpetuals:
|
||||
@pytest.fixture(scope="class")
|
||||
def vega(self, request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
|
||||
@@ -12,7 +12,7 @@ COL_ID_USED = ".ag-center-cols-container [col-id='used'] .ag-cell-value"
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ BUY_ORDERS = [[1, 106], [1, 107], [1, 108]]
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ def setup_market_and_referral_scheme(vega: VegaServiceNull, continuous_market: s
|
||||
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):
|
||||
setup_market_and_referral_scheme(vega, continuous_market, page)
|
||||
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"))
|
||||
|
||||
|
||||
@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):
|
||||
setup_market_and_referral_scheme(vega, continuous_market, page)
|
||||
change_keys(page, vega, PARTY_B.name)
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
from actions.utils import create_and_faucet_wallet
|
||||
from wallet_config import WalletConfig
|
||||
# region Constants
|
||||
ACTIVITY = "activity"
|
||||
HOARDER = "hoarder"
|
||||
COMBO = "combo"
|
||||
|
||||
REWARDS_URL = "/#/rewards"
|
||||
|
||||
# test IDs
|
||||
COMBINED_MULTIPLIERS = "combined-multipliers"
|
||||
TOTAL_REWARDS = "total-rewards"
|
||||
PRICE_TAKING_COL_ID = '[col-id="priceTaking"]'
|
||||
TOTAL_COL_ID = '[col-id="total"]'
|
||||
ROW = "row"
|
||||
STREAK_REWARD_MULTIPLIER_VALUE = "streak-reward-multiplier-value"
|
||||
HOARDER_REWARD_MULTIPLIER_VALUE = "hoarder-reward-multiplier-value"
|
||||
HOARDER_BONUS_TOTAL_HOARDED = "hoarder-bonus-total-hoarded"
|
||||
EARNED_BY_ME_BUTTON = "earned-by-me-button"
|
||||
TRANSFER_AMOUNT = "transfer-amount"
|
||||
EPOCH_STREAK = "epoch-streak"
|
||||
|
||||
# endregion
|
||||
|
||||
# Keys
|
||||
PARTY_A = "PARTY_A"
|
||||
PARTY_B = "PARTY_B"
|
||||
PARTY_C = "PARTY_C"
|
||||
PARTY_D = "PARTY_D"
|
||||
|
||||
ACTIVITY_STREAKS = """
|
||||
{
|
||||
"tiers": [
|
||||
{
|
||||
"minimum_activity_streak": 2,
|
||||
"reward_multiplier": "2.0",
|
||||
"vesting_multiplier": "1.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
VESTING = """
|
||||
{
|
||||
"tiers": [
|
||||
{
|
||||
"minimum_quantum_balance": "10000000",
|
||||
"reward_multiplier": "2"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
def keys(vega):
|
||||
PARTY_A = WalletConfig("PARTY_A", "PARTY_A")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_A)
|
||||
PARTY_B = WalletConfig("PARTY_B", "PARTY_B")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_B)
|
||||
PARTY_C = WalletConfig("PARTY_C", "PARTY_C")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_C)
|
||||
PARTY_D = WalletConfig("PARTY_D", "PARTY_D")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_D)
|
||||
return PARTY_A, PARTY_B, PARTY_C, PARTY_D
|
||||
@@ -0,0 +1,121 @@
|
||||
import pytest
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from rewards_test_ids import *
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup, risk_accepted_setup, cleanup_container
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega, PARTY_B)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_reward_program(vega: VegaServiceNull):
|
||||
tDAI_market = setup_continuous_market(vega)
|
||||
PARTY_A, PARTY_B, PARTY_C, PARTY_D = keys(vega)
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_C.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_D.name, asset=tDAI_asset_id, amount=100000)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.vesting.benefitTiers",
|
||||
new_value=VESTING,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||
)
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.recurring_transfer(
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_A.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_0")
|
||||
def test_network_reward_pot(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text("50.00 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_0")
|
||||
def test_reward_multiplier(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text("1x")
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_0")
|
||||
def test_hoarder_bonus(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(HOARDER_BONUS_TOTAL_HOARDED)).to_contain_text(
|
||||
"5,000,000"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_0")
|
||||
def test_reward_history(
|
||||
page: Page,
|
||||
):
|
||||
page.locator('[name="fromEpoch"]').fill("1")
|
||||
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
||||
"100.00100.00%"
|
||||
)
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("100.00")
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("50.00")
|
||||
@@ -0,0 +1,173 @@
|
||||
import pytest
|
||||
from rewards_test_ids import *
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup, risk_accepted_setup, cleanup_container
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega, PARTY_B)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_reward_program(vega: VegaServiceNull):
|
||||
tDAI_market = setup_continuous_market(vega)
|
||||
PARTY_A, PARTY_B, PARTY_C, PARTY_D = keys(vega)
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_C.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_D.name, asset=tDAI_asset_id, amount=100000)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.vesting.benefitTiers",
|
||||
new_value=VESTING,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||
)
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.recurring_transfer(
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_A.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_LIMIT",
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
side="SIDE_BUY",
|
||||
price=1,
|
||||
volume=1,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_1")
|
||||
def test_network_reward_pot(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text("166.66666 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_1")
|
||||
def test_reward_multiplier(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text("2x")
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text("2x")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_1")
|
||||
def test_hoarder_bonus(page: Page):
|
||||
expect(page.get_by_test_id(HOARDER_BONUS_TOTAL_HOARDED)).to_contain_text(
|
||||
"16,666,666"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_1")
|
||||
def test_reward_history(page: Page):
|
||||
page.locator('[name="fromEpoch"]').fill("1")
|
||||
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
||||
"299.99999100.00%"
|
||||
)
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(
|
||||
"299.99999"
|
||||
)
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(
|
||||
"166.66666"
|
||||
)
|
||||
@@ -1,475 +0,0 @@
|
||||
import pytest
|
||||
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup, cleanup_container
|
||||
from fixtures.market import setup_continuous_market, market_exists
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET, PARTY_A, PARTY_B, PARTY_C, PARTY_D
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
# region Constants
|
||||
ACTIVITY = "activity"
|
||||
HOARDER = "hoarder"
|
||||
COMBO = "combo"
|
||||
|
||||
REWARDS_URL = "/#/rewards"
|
||||
|
||||
# test IDs
|
||||
COMBINED_MULTIPLIERS = "combined-multipliers"
|
||||
TOTAL_REWARDS = "total-rewards"
|
||||
PRICE_TAKING_COL_ID = '[col-id="priceTaking"]'
|
||||
TOTAL_COL_ID = '[col-id="total"]'
|
||||
ROW = "row"
|
||||
STREAK_REWARD_MULTIPLIER_VALUE = "streak-reward-multiplier-value"
|
||||
HOARDER_REWARD_MULTIPLIER_VALUE = "hoarder-reward-multiplier-value"
|
||||
HOARDER_BONUS_TOTAL_HOARDED = "hoarder-bonus-total-hoarded"
|
||||
EARNED_BY_ME_BUTTON = "earned-by-me-button"
|
||||
TRANSFER_AMOUNT = "transfer-amount"
|
||||
EPOCH_STREAK = "epoch-streak"
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def market_ids():
|
||||
return {
|
||||
"vega_activity_tier_0": "default_id",
|
||||
"vega_hoarder_tier_0": "default_id",
|
||||
"vega_combo_tier_0": "default_id",
|
||||
"vega_activity_tier_1": "default_id",
|
||||
"vega_hoarder_tier_1": "default_id",
|
||||
"vega_combo_tier_1": "default_id",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_activity_tier_0(request):
|
||||
with init_vega(request) as vega_activity_tier_0:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_activity_tier_0)) # Register the cleanup function
|
||||
yield vega_activity_tier_0
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_hoarder_tier_0(request):
|
||||
with init_vega(request) as vega_hoarder_tier_0:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_hoarder_tier_0)) # Register the cleanup function
|
||||
yield vega_hoarder_tier_0
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_combo_tier_0(request):
|
||||
with init_vega(request) as vega_combo_tier_0:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_combo_tier_0)) # Register the cleanup function
|
||||
yield vega_combo_tier_0
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_activity_tier_1(request):
|
||||
with init_vega(request) as vega_activity_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_activity_tier_1)) # Register the cleanup function
|
||||
yield vega_activity_tier_1
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_hoarder_tier_1(request):
|
||||
with init_vega(request) as vega_hoarder_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_hoarder_tier_1)) # Register the cleanup function
|
||||
yield vega_hoarder_tier_1
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_combo_tier_1(request):
|
||||
with init_vega(request) as vega_combo_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_combo_tier_1)) # Register the cleanup function
|
||||
yield vega_combo_tier_1
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def auth(vega_instance, page):
|
||||
return auth_setup(vega_instance, page)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def page(vega_instance, browser, request):
|
||||
with init_page(vega_instance, browser, request) as page_instance:
|
||||
yield page_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vega_instance(
|
||||
reward_program,
|
||||
vega_activity_tier_0,
|
||||
vega_hoarder_tier_0,
|
||||
vega_combo_tier_0,
|
||||
vega_activity_tier_1,
|
||||
vega_hoarder_tier_1,
|
||||
vega_combo_tier_1,
|
||||
tier,
|
||||
):
|
||||
if reward_program == "activity":
|
||||
return vega_activity_tier_0 if tier == 1 else vega_activity_tier_1
|
||||
elif reward_program == "hoarder":
|
||||
return vega_hoarder_tier_0 if tier == 1 else vega_hoarder_tier_1
|
||||
elif reward_program == "combo":
|
||||
return vega_combo_tier_0 if tier == 1 else vega_combo_tier_1
|
||||
|
||||
|
||||
def setup_market_with_reward_program(vega: VegaServiceNull, reward_programs, tier):
|
||||
print(f"Started setup_market_with_{reward_programs}_{tier}")
|
||||
tDAI_market = setup_continuous_market(vega)
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_C.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_D.name, asset=tDAI_asset_id, amount=100000)
|
||||
next_epoch(vega=vega)
|
||||
if ACTIVITY in reward_programs:
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.activityStreak.benefitTiers",
|
||||
new_value=ACTIVITY_STREAKS,
|
||||
)
|
||||
print("update_network_parameter activity done")
|
||||
next_epoch(vega=vega)
|
||||
|
||||
if HOARDER in reward_programs:
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.vesting.benefitTiers",
|
||||
new_value=VESTING,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||
)
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.recurring_transfer(
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
# lock_period= 5,
|
||||
# TODO test lock period
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_A.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
|
||||
vega.wait_for_total_catchup()
|
||||
if tier == 1:
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_LIMIT",
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
side="SIDE_BUY",
|
||||
price=1,
|
||||
volume=1,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
if HOARDER in reward_programs:
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
def set_market_reward_program(vega, reward_program, market_ids, tier):
|
||||
market_id_key = f"vega_{reward_program}_tier_{tier}"
|
||||
if reward_program == COMBO:
|
||||
market_id_key = COMBO
|
||||
market_id = market_ids.get(market_id_key, "default_id")
|
||||
|
||||
print(f"Checking if market exists: {market_id}")
|
||||
if not market_exists(vega, market_id):
|
||||
print(
|
||||
f"Market doesn't exist for {reward_program} {tier}. Setting up new market."
|
||||
)
|
||||
|
||||
reward_programs = [reward_program]
|
||||
if reward_program == COMBO:
|
||||
reward_programs = [ACTIVITY, HOARDER]
|
||||
|
||||
market_id, _ = setup_market_with_reward_program(vega, reward_programs, tier)
|
||||
market_ids[market_id_key] = market_id
|
||||
|
||||
return market_id, market_ids
|
||||
|
||||
|
||||
ACTIVITY_STREAKS = """
|
||||
{
|
||||
"tiers": [
|
||||
{
|
||||
"minimum_activity_streak": 2,
|
||||
"reward_multiplier": "2.0",
|
||||
"vesting_multiplier": "1.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
VESTING = """
|
||||
{
|
||||
"tiers": [
|
||||
{
|
||||
"minimum_quantum_balance": "10000000",
|
||||
"reward_multiplier": "2"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, total_rewards",
|
||||
[
|
||||
(ACTIVITY, 0, "50.00 tDAI"),
|
||||
(HOARDER, 0, "50.00 tDAI"),
|
||||
(COMBO, 0, "50.00 tDAI"),
|
||||
(ACTIVITY, 1, "116.66666 tDAI"),
|
||||
(HOARDER, 1, "166.66666 tDAI "),
|
||||
(COMBO, 1, "183.33333 tDAI"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_network_reward_pot(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
total_rewards,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text(total_rewards)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, reward_multiplier, streak_multiplier, hoarder_multiplier",
|
||||
[
|
||||
(ACTIVITY, 0, "1x", "1x", "1x"),
|
||||
(HOARDER, 0, "1x", "1x", "1x"),
|
||||
(COMBO, 0, "1x", "1x", "1x"),
|
||||
(ACTIVITY, 1, "2x", "2x", "1x"),
|
||||
(HOARDER, 1, "2x", "1x", "2x"),
|
||||
(COMBO, 1, "4x", "2x", "2x"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_reward_multiplier(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
reward_multiplier,
|
||||
streak_multiplier,
|
||||
hoarder_multiplier,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text(reward_multiplier)
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text(
|
||||
streak_multiplier
|
||||
)
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text(
|
||||
hoarder_multiplier
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, epoch_streak",
|
||||
[
|
||||
(ACTIVITY, 0, "1"),
|
||||
(ACTIVITY, 1, "7"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_activity_streak(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
epoch_streak,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
if tier == 1:
|
||||
expect(page.get_by_test_id(EPOCH_STREAK)).to_have_text(
|
||||
"Active trader: " + epoch_streak + " epochs so far (Tier 1 as of last epoch)"
|
||||
)
|
||||
else:
|
||||
expect(page.get_by_test_id(EPOCH_STREAK)).to_have_text(
|
||||
"Active trader: " + epoch_streak + " epochs so far "
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, rewards_hoarded",
|
||||
[
|
||||
(HOARDER, 0, "5,000,000"),
|
||||
(HOARDER, 1, "16,666,666"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_hoarder_bonus(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
rewards_hoarded,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
expect(page.get_by_test_id(HOARDER_BONUS_TOTAL_HOARDED)).to_contain_text(
|
||||
rewards_hoarded
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, price_taking, total, earned_by_me",
|
||||
[
|
||||
(ACTIVITY, 0, "100.00100.00%", "100.00", "50.00"),
|
||||
(HOARDER, 0, "100.00100.00%", "100.00", "50.00"),
|
||||
(COMBO, 0, "100.00100.00%", "100.00", "50.00"),
|
||||
(ACTIVITY, 1, "300.00100.00%", "300.00", "116.66666"),
|
||||
(HOARDER, 1, "299.99999100.00%", "299.99999", "166.66666"),
|
||||
(COMBO, 1, "299.99999100.00%", "299.99999", "183.33333"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_reward_history(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
price_taking,
|
||||
total,
|
||||
earned_by_me,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
page.locator('[name="fromEpoch"]').fill("1")
|
||||
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
||||
price_taking
|
||||
)
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(total)
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(
|
||||
earned_by_me
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier",
|
||||
[
|
||||
(ACTIVITY, 1),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_redeem(
|
||||
reward_program, vega_instance: VegaServiceNull, page: Page, tier, market_ids
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
page.get_by_test_id("redeem-rewards-button").click()
|
||||
available_to_withdraw = page.get_by_test_id(
|
||||
"available-to-withdraw-value"
|
||||
).text_content()
|
||||
option_value = page.locator(
|
||||
'[data-testid="transfer-form"] [name="fromAccount"] option[value^="ACCOUNT_TYPE_VESTED_REWARDS"]'
|
||||
).first.get_attribute("value")
|
||||
|
||||
page.select_option(
|
||||
'[data-testid="transfer-form"] [name="fromAccount"]', option_value
|
||||
)
|
||||
|
||||
page.get_by_test_id("use-max-button").first.click()
|
||||
expect(page.get_by_test_id(TRANSFER_AMOUNT)).to_have_text(available_to_withdraw)
|
||||
@@ -1,49 +1,27 @@
|
||||
import pytest
|
||||
from rewards_test_ids import *
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup, risk_accepted_setup, cleanup_container
|
||||
from conftest import (
|
||||
init_vega,
|
||||
init_page,
|
||||
auth_setup,
|
||||
risk_accepted_setup,
|
||||
cleanup_container,
|
||||
)
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import next_epoch, change_keys, create_and_faucet_wallet
|
||||
from wallet_config import MM_WALLET, WalletConfig
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
# region Constants
|
||||
ACTIVITY = "activity"
|
||||
HOARDER = "hoarder"
|
||||
COMBO = "combo"
|
||||
|
||||
REWARDS_URL = "/#/rewards"
|
||||
|
||||
# test IDs
|
||||
COMBINED_MULTIPLIERS = "combined-multipliers"
|
||||
TOTAL_REWARDS = "total-rewards"
|
||||
PRICE_TAKING_COL_ID = '[col-id="priceTaking"]'
|
||||
TOTAL_COL_ID = '[col-id="total"]'
|
||||
ROW = "row"
|
||||
STREAK_REWARD_MULTIPLIER_VALUE = "streak-reward-multiplier-value"
|
||||
HOARDER_REWARD_MULTIPLIER_VALUE = "hoarder-reward-multiplier-value"
|
||||
HOARDER_BONUS_TOTAL_HOARDED = "hoarder-bonus-total-hoarded"
|
||||
EARNED_BY_ME_BUTTON = "earned-by-me-button"
|
||||
TRANSFER_AMOUNT = "transfer-amount"
|
||||
EPOCH_STREAK = "epoch-streak"
|
||||
|
||||
# endregion
|
||||
|
||||
# Keys
|
||||
PARTY_A = "PARTY_A"
|
||||
PARTY_B = "PARTY_B"
|
||||
PARTY_C = "PARTY_C"
|
||||
PARTY_D = "PARTY_D"
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
@@ -106,55 +84,31 @@ def setup_market_with_reward_program(vega: VegaServiceNull):
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
ACTIVITY_STREAKS = """
|
||||
{
|
||||
"tiers": [
|
||||
{
|
||||
"minimum_activity_streak": 2,
|
||||
"reward_multiplier": "2.0",
|
||||
"vesting_multiplier": "1.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def keys(vega):
|
||||
PARTY_A = WalletConfig("PARTY_A", "PARTY_A")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_A)
|
||||
PARTY_B = WalletConfig("PARTY_B", "PARTY_B")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_B)
|
||||
PARTY_C = WalletConfig("PARTY_C", "PARTY_C")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_C)
|
||||
PARTY_D = WalletConfig("PARTY_D", "PARTY_D")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_D)
|
||||
return PARTY_A, PARTY_B, PARTY_C, PARTY_D
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_0")
|
||||
def test_network_reward_pot(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text("50.00 tDAI")
|
||||
page.pause()
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_0")
|
||||
def test_reward_multiplier(
|
||||
page: Page,
|
||||
):
|
||||
page.pause()
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text("1x")
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_0")
|
||||
""" @pytest.mark.xdist_group(name="test_rewards_activity_tier_0")
|
||||
def test_activity_streak(
|
||||
page: Page,
|
||||
):
|
||||
@@ -174,3 +128,4 @@ def test_reward_history(
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("100.00")
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("50.00")
|
||||
"""
|
||||
@@ -0,0 +1,187 @@
|
||||
import pytest
|
||||
from rewards_test_ids import *
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup, risk_accepted_setup, cleanup_container
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega, PARTY_B)
|
||||
yield page
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_reward_program(vega: VegaServiceNull):
|
||||
tDAI_market = setup_continuous_market(vega)
|
||||
PARTY_A, PARTY_B, PARTY_C, PARTY_D = keys(vega)
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_C.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_D.name, asset=tDAI_asset_id, amount=100000)
|
||||
next_epoch(vega=vega)
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.activityStreak.benefitTiers",
|
||||
new_value=ACTIVITY_STREAKS,
|
||||
)
|
||||
print("update_network_parameter activity done")
|
||||
next_epoch(vega=vega)
|
||||
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||
)
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.recurring_transfer(
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
# lock_period= 5,
|
||||
# TODO test lock period
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_A.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_LIMIT",
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
side="SIDE_BUY",
|
||||
price=1,
|
||||
volume=1,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_1")
|
||||
def test_network_reward_pot(page: Page):
|
||||
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text("116.66666 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_1")
|
||||
def test_reward_multiplier(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text("2x")
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text("2x")
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_1")
|
||||
def test_activity_streak(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(EPOCH_STREAK)).to_have_text(
|
||||
"Active trader: 7 epochs so far (Tier 1 as of last epoch)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_1")
|
||||
def test_reward_history(
|
||||
page: Page,
|
||||
):
|
||||
page.locator('[name="fromEpoch"]').fill("1")
|
||||
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
||||
"300.00100.00%"
|
||||
)
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("300.00")
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(
|
||||
"116.66666"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_1")
|
||||
def test_redeem(
|
||||
page: Page,
|
||||
):
|
||||
page.get_by_test_id("redeem-rewards-button").click()
|
||||
available_to_withdraw = page.get_by_test_id(
|
||||
"available-to-withdraw-value"
|
||||
).text_content()
|
||||
option_value = page.locator(
|
||||
'[data-testid="transfer-form"] [name="fromAccount"] option[value^="ACCOUNT_TYPE_VESTED_REWARDS"]'
|
||||
).first.get_attribute("value")
|
||||
|
||||
page.select_option(
|
||||
'[data-testid="transfer-form"] [name="fromAccount"]', option_value
|
||||
)
|
||||
|
||||
page.get_by_test_id("use-max-button").first.click()
|
||||
expect(page.get_by_test_id(TRANSFER_AMOUNT)).to_have_text(available_to_withdraw)
|
||||
@@ -0,0 +1,174 @@
|
||||
import pytest
|
||||
from rewards_test_ids import *
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup, risk_accepted_setup, cleanup_container
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega, PARTY_B)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_reward_program(vega: VegaServiceNull):
|
||||
tDAI_market = setup_continuous_market(vega)
|
||||
PARTY_A, PARTY_B, PARTY_C, PARTY_D = keys(vega)
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_C.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_D.name, asset=tDAI_asset_id, amount=100000)
|
||||
next_epoch(vega=vega)
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.activityStreak.benefitTiers",
|
||||
new_value=ACTIVITY_STREAKS,
|
||||
)
|
||||
print("update_network_parameter activity done")
|
||||
next_epoch(vega=vega)
|
||||
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.vesting.benefitTiers",
|
||||
new_value=VESTING,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||
)
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.recurring_transfer(
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_A.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_LIMIT",
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
side="SIDE_BUY",
|
||||
price=1,
|
||||
volume=1,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_combo_tier_1")
|
||||
def test_network_reward_pot( page: Page
|
||||
):
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text("183.33333 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_combo_tier_1")
|
||||
def test_reward_multiplier(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text("4x")
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text(
|
||||
"2x"
|
||||
)
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text(
|
||||
"2x"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_combo_tier_1")
|
||||
def test_reward_history(
|
||||
page: Page,
|
||||
):
|
||||
page.locator('[name="fromEpoch"]').fill("1")
|
||||
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
||||
"299.99999100.00%"
|
||||
)
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("299.99999")
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(
|
||||
"183.33333"
|
||||
)
|
||||
@@ -43,6 +43,7 @@ def test_vesting(continuous_market, vega: VegaServiceNull, page: Page):
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
page.goto("/#/rewards")
|
||||
|
||||
@@ -6,7 +6,7 @@ from conftest import init_vega, cleanup_container
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(
|
||||
lambda: cleanup_container(vega_instance)
|
||||
) # Register the cleanup function
|
||||
)
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@@ -52,8 +52,25 @@ def setup_teams_and_games(vega: VegaServiceNull):
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||
)
|
||||
|
||||
|
||||
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)
|
||||
|
||||
next_epoch(vega)
|
||||
@@ -101,7 +118,7 @@ def setup_teams_and_games(vega: VegaServiceNull):
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
asset=VEGA_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
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_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
asset=VEGA_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
@@ -242,12 +259,12 @@ def test_team_page_headline(team_page: Page, setup_teams_and_games):
|
||||
expect(team_page.get_by_test_id("team-name")).to_have_text(team_name)
|
||||
expect(team_page.get_by_test_id("members-count-stat")).to_have_text("4")
|
||||
|
||||
expect(team_page.get_by_test_id("total-games-stat")).to_have_text("2")
|
||||
expect(team_page.get_by_test_id("total-games-stat")).to_have_text("1")
|
||||
|
||||
# TODO this still seems wrong as its always 0
|
||||
expect(team_page.get_by_test_id("total-volume-stat")).to_have_text("0")
|
||||
|
||||
expect(team_page.get_by_test_id("rewards-paid-stat")).to_have_text("1.2k")
|
||||
expect(team_page.get_by_test_id("rewards-paid-stat")).to_have_text("500")
|
||||
|
||||
|
||||
def test_switch_teams(team_page: Page, vega: VegaServiceNull):
|
||||
@@ -264,19 +281,18 @@ def test_switch_teams(team_page: Page, vega: VegaServiceNull):
|
||||
def test_leaderboard(competitions_page: Page, setup_teams_and_games):
|
||||
team_name = setup_teams_and_games["team_name"]
|
||||
competitions_page.reload()
|
||||
competitions_page.pause()
|
||||
expect(
|
||||
competitions_page.get_by_test_id("rank-0").locator(".text-yellow-300")
|
||||
).to_have_count(1)
|
||||
expect(
|
||||
competitions_page.get_by_test_id("rank-1").locator(".text-vega-clight-500")
|
||||
).to_have_count(1)
|
||||
expect(competitions_page.get_by_test_id("team-0")).to_have_text(team_name)
|
||||
expect(competitions_page.get_by_test_id("team-1")).to_have_text(team_name)
|
||||
expect(competitions_page.get_by_test_id("status-1")).to_have_text("Open")
|
||||
|
||||
# FIXME: the numbers are different we need to clarify this with the backend
|
||||
# expect(competitions_page.get_by_test_id("earned-1")).to_have_text("160")
|
||||
expect(competitions_page.get_by_test_id("games-1")).to_have_text("2")
|
||||
expect(competitions_page.get_by_test_id("games-1")).to_have_text("1")
|
||||
|
||||
# TODO still odd that this is 0
|
||||
expect(competitions_page.get_by_test_id("volume-0")).to_have_text("0")
|
||||
@@ -289,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("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-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("dispatch-metric-info")).to_have_text(
|
||||
"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;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user