Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c687d1a275 | ||
|
|
6dc9c006b3 | ||
|
|
e431ae8968 | ||
|
|
c65f07eee6 | ||
|
|
5bd18cc127 | ||
|
|
ff3519279d | ||
|
|
fd338c7400 | ||
|
|
0db5d0ce87 | ||
|
|
42c316c8e1 | ||
|
|
9e2474d39a | ||
|
|
2533e5ec44 | ||
|
|
22a43249ea | ||
|
|
b40ee0caf5 | ||
|
|
95aca70434 | ||
|
|
5e13266250 |
@@ -20,12 +20,10 @@ import isEqual from 'lodash/isEqual';
|
||||
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
if (!market) return null;
|
||||
|
||||
const settlementData =
|
||||
market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData
|
||||
.data;
|
||||
const terminationData =
|
||||
market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForTradingTermination.data;
|
||||
const settlementData = market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForSettlementData.data as DataSourceDefinition;
|
||||
const terminationData = market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForTradingTermination.data as DataSourceDefinition;
|
||||
|
||||
const getSigners = (data: DataSourceDefinition) => {
|
||||
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
import type { Proposal } from './tx-proposal';
|
||||
import { proposalRequiresSignatureBundle } from './tx-proposal';
|
||||
|
||||
describe('proposalRequiresSignatureBundle', () => {
|
||||
it('should return false for freeform proposals, which do not require a signature bundle to enact', () => {
|
||||
const mock = {
|
||||
terms: {
|
||||
newFreeform: {},
|
||||
},
|
||||
};
|
||||
|
||||
expect(proposalRequiresSignatureBundle(mock)).toEqual(false);
|
||||
});
|
||||
|
||||
it('should return false for newMarket proposals, which do not require a signature bundle to enact', () => {
|
||||
const mock = {
|
||||
terms: {
|
||||
newMarket: {},
|
||||
},
|
||||
};
|
||||
|
||||
expect(proposalRequiresSignatureBundle(mock)).toEqual(false);
|
||||
});
|
||||
|
||||
it('should return true for newAsset proposals, which do require a signature bundle to enact', () => {
|
||||
const mock = {
|
||||
terms: {
|
||||
newAsset: {},
|
||||
},
|
||||
};
|
||||
|
||||
expect(proposalRequiresSignatureBundle(mock)).toEqual(true);
|
||||
});
|
||||
|
||||
it('should return true for updateAsset proposals, which do require a signature bundle to enact', () => {
|
||||
const mock = {
|
||||
terms: {
|
||||
updateAsset: {},
|
||||
},
|
||||
};
|
||||
|
||||
expect(proposalRequiresSignatureBundle(mock)).toEqual(true);
|
||||
});
|
||||
|
||||
it('should return false when bad data is supplied', () => {
|
||||
expect(
|
||||
proposalRequiresSignatureBundle(false as unknown as Proposal)
|
||||
).toEqual(false);
|
||||
expect(
|
||||
proposalRequiresSignatureBundle(undefined as unknown as Proposal)
|
||||
).toEqual(false);
|
||||
expect(
|
||||
proposalRequiresSignatureBundle({ test: false } as unknown as Proposal)
|
||||
).toEqual(false);
|
||||
});
|
||||
});
|
||||
@@ -28,11 +28,16 @@ interface TxProposalProps {
|
||||
* @returns boolean True if a signature bundle is required. Used to fetch a signature bundle
|
||||
*/
|
||||
export function proposalRequiresSignatureBundle(proposal?: Proposal): boolean {
|
||||
const proposalsThatRequireBundles = ['newAsset', 'updateAsset'];
|
||||
|
||||
if (!proposal?.terms) {
|
||||
return false;
|
||||
}
|
||||
return !!['newAsset', 'updateAsset'].filter((requiredIfExists) =>
|
||||
has(proposal.terms, requiredIfExists)
|
||||
|
||||
return (
|
||||
proposalsThatRequireBundles.filter((requiredIfExists) =>
|
||||
has(proposal.terms, requiredIfExists)
|
||||
).length > 0
|
||||
);
|
||||
}
|
||||
|
||||
@@ -81,6 +86,7 @@ export const TxProposal = ({ txData, pubKey, blockData }: TxProposalProps) => {
|
||||
|
||||
const tx = proposal.terms?.newAsset || proposal.terms?.updateAsset;
|
||||
|
||||
// This component is not rendered if no bundle is required
|
||||
const SignatureBundleComponent = proposal.terms?.newAsset
|
||||
? ProposalSignatureBundleNewAsset
|
||||
: ProposalSignatureBundleUpdateAsset;
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
{
|
||||
"rationale": {
|
||||
"title": "New Market Proposal E2E submission",
|
||||
"description": "E2E new market proposal"
|
||||
},
|
||||
"terms": {
|
||||
"newMarket": {
|
||||
"changes": {
|
||||
"decimalPlaces": "5",
|
||||
"positionDecimalPlaces": "5",
|
||||
"linearSlippageFactor": "0.001",
|
||||
"quadraticSlippageFactor": "0",
|
||||
"lpPriceRange": "10",
|
||||
"instrument": {
|
||||
"name": "Token test market",
|
||||
"code": "TEST.24h",
|
||||
"future": {
|
||||
"settlementAsset": "73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0",
|
||||
"quoteName": "fBTC",
|
||||
"dataSourceSpecForSettlementData": {
|
||||
"external": {
|
||||
"oracle": {
|
||||
"signers": [
|
||||
{
|
||||
"pubKey": {
|
||||
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
|
||||
}
|
||||
}
|
||||
],
|
||||
"filters": [
|
||||
{
|
||||
"key": {
|
||||
"name": "prices.ETH.value",
|
||||
"type": "TYPE_INTEGER",
|
||||
"numberDecimalPlaces": "0"
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"operator": "OPERATOR_GREATER_THAN",
|
||||
"value": "0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"dataSourceSpecForTradingTermination": {
|
||||
"external": {
|
||||
"oracle": {
|
||||
"signers": [
|
||||
{
|
||||
"pubKey": {
|
||||
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
|
||||
}
|
||||
}
|
||||
],
|
||||
"filters": [
|
||||
{
|
||||
"key": {
|
||||
"name": "trading.terminated.ETH5",
|
||||
"type": "TYPE_BOOLEAN"
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"operator": "OPERATOR_EQUALS",
|
||||
"value": "true"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"dataSourceSpecBinding": {
|
||||
"settlementDataProperty": "prices.ETH.value",
|
||||
"tradingTerminationProperty": "trading.terminated.ETH5"
|
||||
}
|
||||
}
|
||||
},
|
||||
"metadata": ["sector:energy", "sector:tech", "source:docs.vega.xyz"],
|
||||
"priceMonitoringParameters": {
|
||||
"triggers": [
|
||||
{
|
||||
"horizon": "43200",
|
||||
"probability": "0.9999999",
|
||||
"auctionExtension": "600"
|
||||
}
|
||||
]
|
||||
},
|
||||
"liquidityMonitoringParameters": {
|
||||
"targetStakeParameters": {
|
||||
"timeWindow": "3600",
|
||||
"scalingFactor": 10
|
||||
},
|
||||
"triggeringRatio": "0.7",
|
||||
"auctionExtension": "1"
|
||||
},
|
||||
"logNormal": {
|
||||
"tau": 0.0001140771161,
|
||||
"riskAversionParameter": 0.01,
|
||||
"params": {
|
||||
"mu": 0,
|
||||
"r": 0.016,
|
||||
"sigma": 0.5
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"closingTimestamp": 0,
|
||||
"enactmentTimestamp": 0
|
||||
}
|
||||
}
|
||||
@@ -7,17 +7,12 @@ import {
|
||||
import {
|
||||
createRawProposal,
|
||||
createTenDigitUnixTimeStampForSpecifiedDays,
|
||||
enterUniqueFreeFormProposalBody,
|
||||
generateFreeFormProposalTitle,
|
||||
getDateFormatForSpecifiedDays,
|
||||
getProposalIdFromList,
|
||||
getProposalFromTitle,
|
||||
getProposalInformationFromTable,
|
||||
getSubmittedProposalFromProposalList,
|
||||
goToMakeNewProposal,
|
||||
governanceProposalType,
|
||||
submitUniqueRawProposal,
|
||||
voteForProposal,
|
||||
waitForProposalSubmitted,
|
||||
waitForProposalSync,
|
||||
} from '../../../../governance-e2e/src/support/governance.functions';
|
||||
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../../../governance-e2e/src/support/staking.functions';
|
||||
import { ethereumWalletConnect } from '../../../../governance-e2e/src/support/wallet-eth.functions';
|
||||
@@ -38,6 +33,8 @@ const proposalDetailsTitle = '[data-testid="proposal-title"]';
|
||||
const proposalDetailsDescription = '[data-testid="proposal-description"]';
|
||||
const openProposals = '[data-testid="open-proposals"]';
|
||||
const viewProposalButton = '[data-testid="view-proposal-btn"]';
|
||||
const voteBreakdownToggle = 'vote-breakdown-toggle';
|
||||
const proposalTermsToggle = 'proposal-terms-toggle';
|
||||
|
||||
describe(
|
||||
'Governance flow for proposal details',
|
||||
@@ -62,23 +59,25 @@ describe(
|
||||
|
||||
// 3001-VOTE-050 3001-VOTE-054 3001-VOTE-055 3002-PROP-019
|
||||
it('Newly created raw proposal details - shows proposal title and full description', function () {
|
||||
const proposalDescription =
|
||||
'I propose that everyone evaluate the following IPFS document and vote Yes if they agree. bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si';
|
||||
|
||||
createRawProposal();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getProposalIdFromList(rawProposal.rationale.title);
|
||||
cy.get('@proposalIdText').then((proposalId) => {
|
||||
cy.get(openProposals).within(() => {
|
||||
cy.get(`#${proposalId}`).within(() => {
|
||||
cy.get(viewProposalButton).should('be.visible').click();
|
||||
});
|
||||
cy.get(openProposals).within(() => {
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||
cy.get(viewProposalButton).should('be.visible').click();
|
||||
});
|
||||
});
|
||||
cy.get(proposalDetailsTitle)
|
||||
.should('contain', rawProposal.rationale.title)
|
||||
.and('be.visible');
|
||||
cy.get(proposalDetailsTitle).should(
|
||||
'contain.text',
|
||||
rawProposal.rationale.title
|
||||
);
|
||||
cy.get(proposalDetailsDescription)
|
||||
.should('contain', rawProposal.rationale.description)
|
||||
.and('be.visible');
|
||||
.find('p')
|
||||
.should('have.text', proposalDescription);
|
||||
});
|
||||
cy.getByTestId(proposalTermsToggle).click();
|
||||
// 3001-VOTE-052
|
||||
cy.get('code.language-json')
|
||||
.should('exist')
|
||||
@@ -89,33 +88,36 @@ describe(
|
||||
|
||||
// 3001-VOTE-043
|
||||
it('Newly created freeform proposal details - shows proposed and closing dates', function () {
|
||||
const closingVoteHrs = '72';
|
||||
const proposalTitle = generateFreeFormProposalTitle();
|
||||
const proposalTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
||||
// const currentDate = new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000)
|
||||
// const proposedDate = new Date(currentDate.getTime() + 60000)
|
||||
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
enterUniqueFreeFormProposalBody(closingVoteHrs, proposalTitle);
|
||||
waitForProposalSubmitted();
|
||||
waitForProposalSync();
|
||||
submitUniqueRawProposal({
|
||||
proposalTitle: proposalTitle,
|
||||
closingTimestamp: proposalTimeStamp,
|
||||
});
|
||||
navigateTo(navigation.proposals);
|
||||
getSubmittedProposalFromProposalList(proposalTitle).within(() =>
|
||||
getProposalFromTitle(proposalTitle).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
cy.wrap(
|
||||
formatDateWithLocalTimezone(new Date(proposalTimeStamp * 1000))
|
||||
).then((closingDate) => {
|
||||
getProposalInformationFromTable('Closes on')
|
||||
.contains(closingDate)
|
||||
.should('be.visible');
|
||||
getProposalInformationFromTable('Closes on').should(
|
||||
'have.text',
|
||||
closingDate
|
||||
);
|
||||
});
|
||||
cy.wrap(
|
||||
formatDateWithLocalTimezone(
|
||||
new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000)
|
||||
)
|
||||
).then((proposalDate) => {
|
||||
getProposalInformationFromTable('Proposed on')
|
||||
.contains(proposalDate)
|
||||
.should('be.visible');
|
||||
getProposalInformationFromTable('Proposed on').should(
|
||||
'have.text',
|
||||
proposalDate
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -125,13 +127,14 @@ describe(
|
||||
// 3001-VOTE-067
|
||||
createRawProposal();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(
|
||||
rawProposal.rationale.title
|
||||
).within(() => cy.get(viewProposalButton).click());
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
});
|
||||
cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.getByTestId(voteBreakdownToggle).click();
|
||||
getProposalInformationFromTable('Expected to pass')
|
||||
.contains('👎')
|
||||
.should('be.visible');
|
||||
@@ -151,9 +154,9 @@ describe(
|
||||
it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () {
|
||||
createRawProposal();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(
|
||||
rawProposal.rationale.title
|
||||
).within(() => cy.get(viewProposalButton).click());
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
});
|
||||
// 3001-VOTE-080
|
||||
cy.getByTestId('vote-buttons').contains('against').should('be.visible');
|
||||
@@ -179,6 +182,7 @@ describe(
|
||||
cy.get(proposalVoteProgressAgainstTokens)
|
||||
.contains('0.00')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(voteBreakdownToggle).click();
|
||||
getProposalInformationFromTable('Tokens for proposal')
|
||||
.should('have.text', (1).toFixed(2))
|
||||
.and('be.visible');
|
||||
@@ -220,14 +224,15 @@ describe(
|
||||
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||
createRawProposal();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(
|
||||
rawProposal.rationale.title
|
||||
).within(() => cy.get(viewProposalButton).click());
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
});
|
||||
voteForProposal('for');
|
||||
// 3001-VOTE-079
|
||||
cy.contains('You voted: For').should('be.visible');
|
||||
cy.get(proposalVoteProgressForTokens).contains('1').and('be.visible');
|
||||
cy.getByTestId(voteBreakdownToggle).click();
|
||||
getProposalInformationFromTable('Total Supply')
|
||||
.invoke('text')
|
||||
.then((totalSupply) => {
|
||||
@@ -235,14 +240,15 @@ describe(
|
||||
(Number(totalSupply.replace(/,/g, '')) * 0.001) /
|
||||
100
|
||||
).toFixed(2);
|
||||
ethereumWalletConnect();
|
||||
ensureSpecifiedUnstakedTokensAreAssociated(
|
||||
tokensRequiredToAchieveResult
|
||||
);
|
||||
navigateTo(navigation.proposals);
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(
|
||||
rawProposal.rationale.title
|
||||
).within(() => cy.get(viewProposalButton).click());
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
});
|
||||
cy.get(proposalVoteProgressForPercentage)
|
||||
.contains('100.00%')
|
||||
@@ -259,6 +265,7 @@ describe(
|
||||
cy.get(proposalVoteProgressAgainstTokens)
|
||||
.contains('0.00')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(voteBreakdownToggle).click();
|
||||
getProposalInformationFromTable('Total tokens voted percentage')
|
||||
.should('have.text', '0.00%')
|
||||
.and('be.visible');
|
||||
|
||||
@@ -58,14 +58,12 @@ context(
|
||||
.parentsUntil(proposalListItem)
|
||||
.last()
|
||||
.within(() => {
|
||||
cy.get(proposalStatus).should('have.text', 'Enacted ');
|
||||
cy.get(proposalStatus).should('have.text', 'Enacted');
|
||||
cy.get(viewProposalButton).click();
|
||||
});
|
||||
});
|
||||
cy.getByTestId('proposal-type').should('have.text', 'New market');
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Enacted')
|
||||
.and('be.visible');
|
||||
cy.get(proposalStatus).should('have.text', 'Enacted');
|
||||
cy.get(votesTable).within(() => {
|
||||
cy.contains('Vote passed.').should('be.visible');
|
||||
cy.contains('Voting has ended.').should('be.visible');
|
||||
@@ -87,16 +85,10 @@ context(
|
||||
.last()
|
||||
.within(() => cy.get(viewProposalButton).click());
|
||||
});
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Open')
|
||||
.and('be.visible');
|
||||
cy.get(proposalStatus).should('have.text', 'Open');
|
||||
voteForProposal('for');
|
||||
getProposalInformationFromTable('State') // 3001-VOTE-047
|
||||
.contains('Passed', proposalTimeout)
|
||||
.and('be.visible');
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Enacted', proposalTimeout)
|
||||
.and('be.visible');
|
||||
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Passed');
|
||||
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Enacted');
|
||||
cy.get(votesTable).within(() => {
|
||||
cy.contains('Vote passed.').should('be.visible');
|
||||
cy.contains('Voting has ended.').should('be.visible');
|
||||
@@ -121,13 +113,9 @@ context(
|
||||
.last()
|
||||
.within(() => cy.get(viewProposalButton).click());
|
||||
});
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Open')
|
||||
.and('be.visible');
|
||||
cy.get(proposalStatus).should('have.text', 'Open');
|
||||
voteForProposal('for');
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Enacted', proposalTimeout)
|
||||
.and('be.visible');
|
||||
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Enacted');
|
||||
});
|
||||
|
||||
// 3001-VOTE-048 3001-VOTE-049 3001-VOTE-050
|
||||
@@ -144,12 +132,8 @@ context(
|
||||
.last()
|
||||
.within(() => cy.get(viewProposalButton).click());
|
||||
});
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Open')
|
||||
.and('be.visible');
|
||||
getProposalInformationFromTable('State') // 3001-VOTE-047
|
||||
.contains('Declined', proposalTimeout)
|
||||
.and('be.visible');
|
||||
cy.get(proposalStatus).should('have.text', 'Open');
|
||||
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Declined');
|
||||
getProposalInformationFromTable('Rejection reason')
|
||||
.contains('PROPOSAL_ERROR_PARTICIPATION_THRESHOLD_NOT_REACHED')
|
||||
.and('be.visible');
|
||||
|
||||
@@ -5,10 +5,11 @@ import {
|
||||
enterRawProposalBody,
|
||||
enterUniqueFreeFormProposalBody,
|
||||
generateFreeFormProposalTitle,
|
||||
getProposalFromTitle,
|
||||
getProposalInformationFromTable,
|
||||
getSubmittedProposalFromProposalList,
|
||||
goToMakeNewProposal,
|
||||
governanceProposalType,
|
||||
submitUniqueRawProposal,
|
||||
voteForProposal,
|
||||
waitForProposalSubmitted,
|
||||
waitForProposalSync,
|
||||
@@ -81,7 +82,6 @@ context(
|
||||
});
|
||||
|
||||
vegaWalletSetSpecifiedApprovalAmount('1000');
|
||||
cy.associateTokensToVegaWallet('1');
|
||||
});
|
||||
|
||||
beforeEach('visit governance tab', function () {
|
||||
@@ -95,7 +95,8 @@ context(
|
||||
navigateTo(navigation.proposals);
|
||||
});
|
||||
|
||||
it('Should be able to see that no proposals exist', function () {
|
||||
// Test can only pass if run before other proposal tests.
|
||||
it.skip('Should be able to see that no proposals exist', function () {
|
||||
// 3001-VOTE-003
|
||||
cy.get(noOpenProposals)
|
||||
.should('be.visible')
|
||||
@@ -107,7 +108,7 @@ context(
|
||||
|
||||
// 3002-PROP-002
|
||||
// 3002-PROP-003
|
||||
it('Submit a proposal form - shows how many vega tokens are required to make a proposal', function () {
|
||||
it('Proposal form - shows how many vega tokens are required to make a proposal', function () {
|
||||
// 3002-PROP-005
|
||||
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
|
||||
cy.contains(
|
||||
@@ -115,8 +116,9 @@ context(
|
||||
).should('be.visible');
|
||||
});
|
||||
|
||||
// Skipping as currently unable to propose using forms other than raw
|
||||
// 3002-PROP-011
|
||||
it('Able to submit a valid freeform proposal - with minimum required tokens associated', function () {
|
||||
it.skip('Able to submit a valid freeform proposal - with minimum required tokens associated', function () {
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
cy.get(minVoteButton).should('be.visible'); // 3002-PROP-008
|
||||
cy.get(maxVoteButton).should('be.visible');
|
||||
@@ -140,16 +142,13 @@ context(
|
||||
closeStakingDialog();
|
||||
|
||||
cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2');
|
||||
|
||||
navigateTo(navigation.proposals);
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
enterUniqueFreeFormProposalBody('50', generateFreeFormProposalTitle());
|
||||
waitForProposalSubmitted();
|
||||
createRawProposal();
|
||||
});
|
||||
|
||||
it('Creating a proposal - proposal rejected - when closing time sooner than system default', function () {
|
||||
it.skip('Creating a proposal - proposal rejected - when closing time sooner than system default', function () {
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
enterUniqueFreeFormProposalBody('0.1', generateFreeFormProposalTitle());
|
||||
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'not.exist'
|
||||
);
|
||||
@@ -158,7 +157,7 @@ context(
|
||||
.should('equal', 'Value must be greater than or equal to 1.');
|
||||
});
|
||||
|
||||
it('Creating a proposal - proposal rejected - when closing time later than system default', function () {
|
||||
it.skip('Creating a proposal - proposal rejected - when closing time later than system default', function () {
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
enterUniqueFreeFormProposalBody(
|
||||
'100000',
|
||||
@@ -185,17 +184,13 @@ context(
|
||||
navigateTo(navigation.proposals);
|
||||
cy.get(rejectProposalsLink).click();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(
|
||||
rawProposal.rationale.title
|
||||
).within(() => {
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||
cy.contains('Rejected').should('be.visible');
|
||||
cy.contains('Close time too late').should('be.visible');
|
||||
cy.get(viewProposalButton).click();
|
||||
});
|
||||
});
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Rejected')
|
||||
.and('be.visible');
|
||||
cy.getByTestId('proposal-status').should('have.text', 'Rejected');
|
||||
getProposalInformationFromTable('Rejection reason')
|
||||
.contains('PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE')
|
||||
.and('be.visible');
|
||||
@@ -290,18 +285,19 @@ context(
|
||||
const proposalTitle = generateFreeFormProposalTitle();
|
||||
|
||||
ensureSpecifiedUnstakedTokensAreAssociated('1');
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
enterUniqueFreeFormProposalBody('50', proposalTitle);
|
||||
waitForProposalSubmitted();
|
||||
submitUniqueRawProposal({ proposalTitle: proposalTitle });
|
||||
ethereumWalletConnect();
|
||||
stakingPageDisassociateTokens('0.0001');
|
||||
cy.get(vegaWallet).within(() => {
|
||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
||||
'contain',
|
||||
'0.9999'
|
||||
);
|
||||
});
|
||||
cy.get(vegaWallet)
|
||||
.first()
|
||||
.within(() => {
|
||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
|
||||
'contain',
|
||||
'0.9999'
|
||||
);
|
||||
});
|
||||
navigateTo(navigation.proposals);
|
||||
getSubmittedProposalFromProposalList(proposalTitle).within(() =>
|
||||
getProposalFromTitle(proposalTitle).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
cy.contains('Vote breakdown').should('be.visible', {
|
||||
@@ -319,9 +315,9 @@ context(
|
||||
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
|
||||
cy.get('[data-testid="disconnect"]').click();
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(
|
||||
rawProposal.rationale.title
|
||||
).within(() => cy.get(viewProposalButton).click());
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
});
|
||||
// 3001-VOTE-075
|
||||
// 3001-VOTE-076
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
import {
|
||||
getProposalInformationFromTable,
|
||||
goToMakeNewProposal,
|
||||
governanceProposalType,
|
||||
voteForProposal,
|
||||
waitForProposalSubmitted,
|
||||
} from '../../support/governance.functions';
|
||||
@@ -56,18 +57,8 @@ const fUSDCId =
|
||||
const epochTimeout = Cypress.env('epochTimeout');
|
||||
const proposalTimeout = { timeout: 14000 };
|
||||
|
||||
const governanceProposalType = {
|
||||
NETWORK_PARAMETER: 'Network parameter',
|
||||
NEW_MARKET: 'New market',
|
||||
UPDATE_MARKET: 'Update market',
|
||||
NEW_ASSET: 'New asset',
|
||||
UPDATE_ASSET: 'Update asset',
|
||||
FREEFORM: 'Freeform',
|
||||
RAW: 'raw proposal',
|
||||
};
|
||||
|
||||
// 3001-VOTE-007
|
||||
context(
|
||||
context.skip(
|
||||
'Governance flow - form validations for different governance proposals',
|
||||
{ tags: '@slow' },
|
||||
function () {
|
||||
|
||||
@@ -6,16 +6,15 @@ import {
|
||||
waitForSpinner,
|
||||
} from '../../support/common.functions';
|
||||
import {
|
||||
createFreeformProposal,
|
||||
createRawProposal,
|
||||
createTenDigitUnixTimeStampForSpecifiedDays,
|
||||
enterRawProposalBody,
|
||||
generateFreeFormProposalTitle,
|
||||
getProposalIdFromList,
|
||||
getProposalFromTitle,
|
||||
getProposalInformationFromTable,
|
||||
getSubmittedProposalFromProposalList,
|
||||
goToMakeNewProposal,
|
||||
governanceProposalType,
|
||||
submitUniqueRawProposal,
|
||||
voteForProposal,
|
||||
waitForProposalSubmitted,
|
||||
waitForProposalSync,
|
||||
@@ -24,10 +23,14 @@ import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/stakin
|
||||
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
|
||||
import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions';
|
||||
|
||||
const proposalListItem = 'proposals-list-item';
|
||||
const openProposals = '[data-testid="open-proposals"]';
|
||||
const voteStatus = '[data-testid="vote-status"]';
|
||||
const voteStatus = 'vote-status';
|
||||
const proposalType = 'proposal-type';
|
||||
const proposalStatus = 'proposal-status';
|
||||
const proposalClosingDate = '[data-testid="vote-details"]';
|
||||
const viewProposalButton = '[data-testid="view-proposal-btn"]';
|
||||
const voteBreakDownToggle = 'vote-breakdown-toggle';
|
||||
|
||||
describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||
before('connect wallets and set approval limit', function () {
|
||||
@@ -60,12 +63,12 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||
|
||||
navigateTo(navigation.proposals);
|
||||
cy.get(openProposals).within(() => {
|
||||
cy.get(proposalClosingDate).first().should('contain.text', 'year');
|
||||
cy.get(proposalClosingDate).should('contain.text', 'months');
|
||||
cy.get(proposalClosingDate)
|
||||
.last()
|
||||
.first()
|
||||
.invoke('text')
|
||||
.should('match', /days|minutes/);
|
||||
cy.get(proposalClosingDate).should('contain.text', 'months');
|
||||
cy.get(proposalClosingDate).last().should('contain.text', 'year');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -73,36 +76,27 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||
const proposerId = Cypress.env('vegaWalletPublicKey');
|
||||
const proposalTitle = generateFreeFormProposalTitle();
|
||||
|
||||
createFreeformProposal(proposalTitle);
|
||||
getProposalIdFromList(proposalTitle);
|
||||
cy.get('@proposalIdText').then((proposalId) => {
|
||||
cy.get('[data-testid="set-proposals-filter-visible"]').click();
|
||||
cy.get('[data-testid="filter-input"]').type(proposerId);
|
||||
cy.get(`#${proposalId}`).should('contain', proposalId);
|
||||
});
|
||||
submitUniqueRawProposal({ proposalTitle: proposalTitle });
|
||||
cy.get('[data-testid="set-proposals-filter-visible"]').click();
|
||||
cy.get('[data-testid="filter-input"]').type(proposerId);
|
||||
// cy.get(`#${proposalId}`).should('contain', proposalId);
|
||||
cy.contains(proposalTitle).should('be.visible');
|
||||
cy.get('[data-testid="filter-input"]').type('123');
|
||||
cy.getByTestId(proposalListItem).should('not.exist');
|
||||
});
|
||||
|
||||
it('Newly created proposals list - shows title and portion of summary', function () {
|
||||
createRawProposal(this.minProposerBalance); // 3001-VOTE-052
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getProposalIdFromList(rawProposal.rationale.title);
|
||||
cy.get('@proposalIdText').then((proposalId) => {
|
||||
cy.get(openProposals).within(() => {
|
||||
// 3001-VOTE-008
|
||||
// 3001-VOTE-034
|
||||
cy.get(`#${proposalId}`)
|
||||
// 3001-VOTE-097
|
||||
.should('contain', rawProposal.rationale.title)
|
||||
.and('be.visible');
|
||||
cy.get(`#${proposalId}`)
|
||||
.should(
|
||||
'contain',
|
||||
rawProposal.rationale.description.substring(0, 59)
|
||||
)
|
||||
.and('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
const proposalPath = '/proposals/new-market-raw.json';
|
||||
const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
|
||||
submitUniqueRawProposal({
|
||||
proposalBody: proposalPath,
|
||||
enactmentTimestamp: enactmentTimestamp,
|
||||
}); // 3001-VOTE-052
|
||||
// 3001-VOTE-008
|
||||
// 3001-VOTE-034
|
||||
// 3001-VOTE-097
|
||||
cy.contains('New Market Proposal E2E submission');
|
||||
cy.contains('Code: TEST.24h. fBTC settled future.').should('be.visible');
|
||||
});
|
||||
|
||||
it('Newly created proposals list - shows open proposals in an open state', function () {
|
||||
@@ -110,23 +104,11 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||
// 3001-VOTE-035
|
||||
createRawProposal(this.minProposerBalance);
|
||||
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
|
||||
getSubmittedProposalFromProposalList(rawProposal.rationale.title).within(
|
||||
() => {
|
||||
cy.get(viewProposalButton).should('be.visible').click();
|
||||
}
|
||||
);
|
||||
|
||||
cy.get('@proposalIdText').then((proposalId) => {
|
||||
getProposalInformationFromTable('ID')
|
||||
.contains(String(proposalId))
|
||||
.and('be.visible');
|
||||
getProposalFromTitle(rawProposal.rationale.title).within(() => {
|
||||
cy.get(viewProposalButton).should('be.visible');
|
||||
cy.getByTestId(proposalType).should('have.text', 'Freeform');
|
||||
cy.getByTestId(proposalStatus).should('have.text', 'Open');
|
||||
});
|
||||
getProposalInformationFromTable('State')
|
||||
.contains('Open')
|
||||
.and('be.visible');
|
||||
getProposalInformationFromTable('Type')
|
||||
.contains('Freeform')
|
||||
.and('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -134,18 +116,22 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
|
||||
it('Newly created freeform proposals list - shows proposal participation - both met and not', function () {
|
||||
const proposalTitle = generateFreeFormProposalTitle();
|
||||
|
||||
createFreeformProposal(proposalTitle);
|
||||
getSubmittedProposalFromProposalList(proposalTitle).within(() => {
|
||||
submitUniqueRawProposal({ proposalTitle: proposalTitle });
|
||||
getProposalFromTitle(proposalTitle).within(() => {
|
||||
// 3001-VOTE-039
|
||||
cy.get(voteStatus).should('have.text', 'Participation not reached');
|
||||
cy.getByTestId(voteStatus).should(
|
||||
'have.text',
|
||||
'Participation not reached'
|
||||
);
|
||||
cy.get(viewProposalButton).click();
|
||||
});
|
||||
voteForProposal('for');
|
||||
navigateTo(navigation.proposals);
|
||||
getSubmittedProposalFromProposalList(proposalTitle).within(() => {
|
||||
cy.get(voteStatus).should('have.text', 'Set to pass');
|
||||
getProposalFromTitle(proposalTitle).within(() => {
|
||||
cy.getByTestId(voteStatus).should('have.text', 'Set to pass');
|
||||
cy.get(viewProposalButton).click();
|
||||
});
|
||||
cy.getByTestId(voteBreakDownToggle).click();
|
||||
getProposalInformationFromTable('Token participation met')
|
||||
.contains('👍')
|
||||
.should('be.visible');
|
||||
|
||||
@@ -96,7 +96,7 @@ context(
|
||||
navigateTo(navigation.validators);
|
||||
|
||||
// 2002-SINC-007
|
||||
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
|
||||
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
|
||||
});
|
||||
|
||||
it('Able to view validators staked by me', function () {
|
||||
@@ -146,7 +146,7 @@ context(
|
||||
verifyThisEpochValue(2.0);
|
||||
closeStakingDialog();
|
||||
navigateTo(navigation.validators);
|
||||
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
|
||||
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
|
||||
});
|
||||
|
||||
it('Able to stake against a validator - using vega from both wallet and vesting contract', function () {
|
||||
@@ -166,10 +166,11 @@ context(
|
||||
verifyThisEpochValue(6.0);
|
||||
closeStakingDialog();
|
||||
navigateTo(navigation.validators);
|
||||
validateValidatorListTotalStakeAndShare('0', '6.00', '100.00%');
|
||||
validateValidatorListTotalStakeAndShare('0', '3,006.00', '50.05%');
|
||||
});
|
||||
|
||||
it('Able to stake against multiple validators', function () {
|
||||
vegaWalletTeardown();
|
||||
stakingPageAssociateTokens('5');
|
||||
verifyUnstakedBalance(5.0);
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
@@ -197,14 +198,10 @@ context(
|
||||
.eq(1)
|
||||
.within(() => {
|
||||
cy.getByTestId(stakeValidatorListTotalStake)
|
||||
.should('have.text', '2.00')
|
||||
.should('have.text', '3,002.00')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(stakeValidatorListTotalShare)
|
||||
.should('have.text', '66.67%')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(stakeValidatorListTotalStake)
|
||||
.scrollIntoView()
|
||||
.should('have.text', '2.00')
|
||||
.should('have.text', '50.01%')
|
||||
.and('be.visible');
|
||||
});
|
||||
cy.get(`[row-id="${1}"]`)
|
||||
@@ -212,14 +209,10 @@ context(
|
||||
.within(() => {
|
||||
cy.getByTestId(stakeValidatorListTotalStake)
|
||||
.scrollIntoView()
|
||||
.should('have.text', '1.00')
|
||||
.should('have.text', '3,001.00')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(stakeValidatorListTotalShare)
|
||||
.should('have.text', '33.33%')
|
||||
.and('be.visible');
|
||||
cy.getByTestId(stakeValidatorListTotalStake)
|
||||
.scrollIntoView()
|
||||
.should('have.text', '1.00')
|
||||
.should('have.text', '49.99%')
|
||||
.and('be.visible');
|
||||
});
|
||||
});
|
||||
@@ -282,7 +275,7 @@ context(
|
||||
txTimeout
|
||||
);
|
||||
navigateTo(navigation.validators);
|
||||
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
|
||||
validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%');
|
||||
|
||||
cy.getByTestId(userStakeBtn).should('not.exist');
|
||||
cy.getByTestId(userStake).should('not.exist');
|
||||
@@ -354,7 +347,7 @@ context(
|
||||
txTimeout
|
||||
);
|
||||
navigateTo(navigation.validators);
|
||||
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
|
||||
validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%');
|
||||
});
|
||||
|
||||
it('Disassociating all vesting contract tokens max - removes all staked tokens', function () {
|
||||
@@ -382,7 +375,7 @@ context(
|
||||
txTimeout
|
||||
);
|
||||
navigateTo(navigation.validators);
|
||||
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
|
||||
validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%');
|
||||
});
|
||||
|
||||
it('Disassociating some tokens - prioritizes unstaked tokens', function () {
|
||||
@@ -404,7 +397,7 @@ context(
|
||||
});
|
||||
verifyStakedBalance(2.0);
|
||||
navigateTo(navigation.validators);
|
||||
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
|
||||
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
|
||||
});
|
||||
|
||||
it('Associating wallet tokens - when some already staked - auto stakes tokens to staked validator', function () {
|
||||
|
||||
@@ -111,10 +111,10 @@ context(
|
||||
// 1004-ASSO-028
|
||||
// 1004-ASSO-029
|
||||
// 1004-ASSO-031
|
||||
|
||||
vegaWalletTeardown();
|
||||
stakingPageAssociateTokens('2');
|
||||
verifyEthWalletAssociatedBalance('2.0');
|
||||
verifyEthWalletTotalAssociatedBalance('2.0');
|
||||
verifyEthWalletTotalAssociatedBalance('6,002.00');
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
stakingPageDisassociateTokens('2');
|
||||
cy.getByTestId('currency-title', txTimeout).should(
|
||||
@@ -125,17 +125,18 @@ context(
|
||||
validateWalletCurrency('Pending association', '2.00');
|
||||
validateWalletCurrency('Total associated after pending', '0.00');
|
||||
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
|
||||
cy.getByTestId('eth-wallet-associated-balances', txTimeout).should(
|
||||
'not.exist'
|
||||
);
|
||||
verifyEthWalletTotalAssociatedBalance('0.00');
|
||||
cy.get(
|
||||
'[data-testid="eth-wallet-associated-balances"]:visible',
|
||||
txTimeout
|
||||
).should('have.length', 2);
|
||||
verifyEthWalletTotalAssociatedBalance('6,000.00');
|
||||
});
|
||||
|
||||
it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () {
|
||||
//1004-ASSO-011
|
||||
stakingPageAssociateTokens('1001', { approve: true });
|
||||
verifyEthWalletAssociatedBalance('1,001.00');
|
||||
verifyEthWalletTotalAssociatedBalance('1,001.00');
|
||||
verifyEthWalletTotalAssociatedBalance('7,001.00');
|
||||
cy.get(vegaWallet)
|
||||
.last()
|
||||
.within(() => {
|
||||
|
||||
@@ -47,11 +47,8 @@ context(
|
||||
function () {
|
||||
before('visit withdrawals and connect vega wallet', function () {
|
||||
cy.visit('/');
|
||||
// When running tests locally, will fail if run without restarting capsule
|
||||
cy.updateCapsuleMultiSig().then(() => {
|
||||
ethereumWalletConnect();
|
||||
depositAsset(usdcEthAddress, '1000', 5);
|
||||
});
|
||||
ethereumWalletConnect();
|
||||
depositAsset(usdcEthAddress, '1000', 5);
|
||||
});
|
||||
|
||||
beforeEach('Navigate to withdrawal page', function () {
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
import {
|
||||
enterUniqueFreeFormProposalBody,
|
||||
goToMakeNewProposal,
|
||||
governanceProposalType,
|
||||
} from '../../support/governance.functions';
|
||||
import { vegaWalletFaucetAssetsWithoutCheck } from '../../support/wallet-vega.functions';
|
||||
|
||||
@@ -50,7 +51,7 @@ context('View functionality with public key', { tags: '@smoke' }, function () {
|
||||
const expectedErrorTxt = `You are connected in a view only state for public key: ${vegaWalletPubKey}. In order to send transactions you must connect to a real wallet.`;
|
||||
|
||||
navigateTo(navigation.proposals);
|
||||
goToMakeNewProposal('Freeform');
|
||||
goToMakeNewProposal(governanceProposalType.FREEFORM);
|
||||
enterUniqueFreeFormProposalBody('50', 'pub key proposal test');
|
||||
cy.getByTestId('dialog-content')
|
||||
.first()
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { format } from 'date-fns';
|
||||
import { closeDialog, navigateTo, navigation } from './common.functions';
|
||||
import {
|
||||
closeDialog,
|
||||
navigateTo,
|
||||
navigation,
|
||||
waitForSpinner,
|
||||
} from './common.functions';
|
||||
import { ensureSpecifiedUnstakedTokensAreAssociated } from './staking.functions';
|
||||
|
||||
const newProposalButton = '[data-testid="new-proposal-link"]';
|
||||
const proposalInformationTableRows = '[data-testid="key-value-table-row"]';
|
||||
const proposalListItem = '[data-testid="proposals-list-item"]';
|
||||
const newProposalTitle = '[data-testid="proposal-title"]';
|
||||
@@ -46,6 +50,53 @@ export function enterRawProposalBody(timestamp: number) {
|
||||
});
|
||||
}
|
||||
|
||||
export function submitUniqueRawProposal(proposalFields: {
|
||||
proposalBody?: string;
|
||||
proposalTitle?: string;
|
||||
proposalDescription?: string;
|
||||
closingTimestamp?: number;
|
||||
enactmentTimestamp?: number;
|
||||
submit?: boolean;
|
||||
}) {
|
||||
goToMakeNewProposal(governanceProposalType.RAW);
|
||||
let proposalBodyPath = '/proposals/raw.json';
|
||||
if (proposalFields.proposalBody) {
|
||||
proposalBodyPath = proposalFields.proposalBody;
|
||||
}
|
||||
cy.fixture(proposalBodyPath).then((rawProposal) => {
|
||||
if (proposalFields.proposalTitle) {
|
||||
rawProposal.rationale.title = proposalFields.proposalTitle;
|
||||
cy.wrap(proposalFields.proposalTitle).as('proposalTitle');
|
||||
}
|
||||
if (proposalFields.proposalDescription) {
|
||||
rawProposal.rationale.description = proposalFields.proposalDescription;
|
||||
}
|
||||
if (proposalFields.closingTimestamp) {
|
||||
rawProposal.terms.closingTimestamp = proposalFields.closingTimestamp;
|
||||
} else {
|
||||
const minTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
|
||||
rawProposal.terms.closingTimestamp = minTimeStamp;
|
||||
}
|
||||
if (proposalFields.enactmentTimestamp) {
|
||||
rawProposal.terms.enactmentTimestamp = proposalFields.enactmentTimestamp;
|
||||
}
|
||||
|
||||
const proposalPayload = JSON.stringify(rawProposal);
|
||||
cy.get(rawProposalData).type(proposalPayload, {
|
||||
parseSpecialCharSequences: false,
|
||||
delay: 2,
|
||||
});
|
||||
|
||||
if (proposalFields.submit !== false) {
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.wrap(rawProposal).as('rawProposal');
|
||||
waitForProposalSubmitted();
|
||||
waitForProposalSync();
|
||||
navigateTo(navigation.proposals);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function enterUniqueFreeFormProposalBody(
|
||||
timestamp: string,
|
||||
proposalTitle: string
|
||||
@@ -58,6 +109,10 @@ export function enterUniqueFreeFormProposalBody(
|
||||
cy.getByTestId('proposal-submit').should('be.visible').click();
|
||||
}
|
||||
|
||||
export function getProposalFromTitle(proposalTitle: string) {
|
||||
return cy.contains(proposalTitle).parentsUntil(proposalListItem).last();
|
||||
}
|
||||
|
||||
export function getSubmittedProposalFromProposalList(proposalTitle: string) {
|
||||
getProposalIdFromList(proposalTitle);
|
||||
cy.get('@proposalIdText').then((proposalId) => {
|
||||
@@ -120,13 +175,17 @@ export function waitForProposalSync() {
|
||||
});
|
||||
}
|
||||
|
||||
export function goToMakeNewProposal(proposalType: string) {
|
||||
navigateTo(navigation.proposals);
|
||||
cy.get(newProposalButton).should('be.visible').click();
|
||||
export function goToMakeNewProposal(proposalType: governanceProposalType) {
|
||||
cy.visit('/proposals/propose');
|
||||
waitForSpinner();
|
||||
cy.url().should('include', '/proposals/propose');
|
||||
cy.get(navigation.pageSpinner, { timeout: 20000 }).should('not.exist');
|
||||
cy.get('li').should('contain.text', proposalType).and('be.visible');
|
||||
cy.get('li').contains(proposalType).click();
|
||||
if (proposalType == governanceProposalType.RAW) {
|
||||
cy.get('[href="/proposals/propose/raw"]').click();
|
||||
} else {
|
||||
cy.get('li').should('contain.text', proposalType).and('be.visible');
|
||||
cy.get('li').contains(proposalType).click();
|
||||
}
|
||||
}
|
||||
|
||||
export function waitForProposalSubmitted() {
|
||||
@@ -163,11 +222,12 @@ export function createFreeformProposal(proposalTitle: string) {
|
||||
navigateTo(navigation.proposals);
|
||||
}
|
||||
|
||||
export const governanceProposalType = {
|
||||
NETWORK_PARAMETER: 'Network parameter',
|
||||
NEW_MARKET: 'New market',
|
||||
UPDATE_MARKET: 'Update market',
|
||||
NEW_ASSET: 'New asset',
|
||||
FREEFORM: 'Freeform',
|
||||
RAW: 'raw proposal',
|
||||
};
|
||||
export enum governanceProposalType {
|
||||
NETWORK_PARAMETER = 'Network parameter',
|
||||
NEW_MARKET = 'New market',
|
||||
UPDATE_MARKET = 'Update market',
|
||||
NEW_ASSET = 'New asset',
|
||||
UPDATE_ASSET = 'Update asset',
|
||||
FREEFORM = 'Freeform',
|
||||
RAW = 'raw proposal',
|
||||
}
|
||||
|
||||
@@ -85,6 +85,132 @@ export function createFreeFormProposalTxBody(): ProposalSubmissionBody {
|
||||
};
|
||||
}
|
||||
|
||||
export function createNewMarketProposalTxBody(): ProposalSubmissionBody {
|
||||
const MIN_CLOSE_SEC = 5;
|
||||
const MIN_ENACT_SEC = 7;
|
||||
|
||||
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
|
||||
const enactmentDate = addSeconds(closingDate, MIN_ENACT_SEC);
|
||||
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
|
||||
const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime());
|
||||
return {
|
||||
proposalSubmission: {
|
||||
rationale: {
|
||||
title: 'New Market Proposal E2E submission',
|
||||
description: 'E2E new market proposal',
|
||||
},
|
||||
terms: {
|
||||
newMarket: {
|
||||
changes: {
|
||||
decimalPlaces: '5',
|
||||
positionDecimalPlaces: '5',
|
||||
linearSlippageFactor: '0.001',
|
||||
quadraticSlippageFactor: '0',
|
||||
lpPriceRange: '10',
|
||||
instrument: {
|
||||
name: 'Token test market',
|
||||
code: 'TEST.24h',
|
||||
future: {
|
||||
settlementAsset:
|
||||
'73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0',
|
||||
quoteName: 'fBTC',
|
||||
dataSourceSpecForSettlementData: {
|
||||
external: {
|
||||
oracle: {
|
||||
signers: [
|
||||
{
|
||||
pubKey: {
|
||||
key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680',
|
||||
},
|
||||
},
|
||||
],
|
||||
filters: [
|
||||
{
|
||||
key: {
|
||||
name: 'prices.ETH.value',
|
||||
type: 'TYPE_INTEGER' as const,
|
||||
numberDecimalPlaces: '0',
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
operator: 'OPERATOR_GREATER_THAN' as const,
|
||||
value: '0',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
external: {
|
||||
oracle: {
|
||||
signers: [
|
||||
{
|
||||
pubKey: {
|
||||
key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680',
|
||||
},
|
||||
},
|
||||
],
|
||||
filters: [
|
||||
{
|
||||
key: {
|
||||
name: 'trading.terminated.ETH5',
|
||||
type: 'TYPE_BOOLEAN' as const,
|
||||
},
|
||||
conditions: [
|
||||
{
|
||||
operator: 'OPERATOR_EQUALS' as const,
|
||||
value: 'true',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecBinding: {
|
||||
settlementDataProperty: 'prices.ETH.value',
|
||||
tradingTerminationProperty: 'trading.terminated.ETH5',
|
||||
},
|
||||
},
|
||||
},
|
||||
metadata: ['sector:energy', 'sector:tech', 'source:docs.vega.xyz'],
|
||||
priceMonitoringParameters: {
|
||||
triggers: [
|
||||
{
|
||||
horizon: '43200',
|
||||
probability: '0.9999999',
|
||||
auctionExtension: '600',
|
||||
},
|
||||
],
|
||||
},
|
||||
liquidityMonitoringParameters: {
|
||||
targetStakeParameters: {
|
||||
timeWindow: '3600',
|
||||
scalingFactor: 10,
|
||||
},
|
||||
triggeringRatio: '0.7',
|
||||
auctionExtension: '1',
|
||||
},
|
||||
logNormal: {
|
||||
tau: 0.0001140771161,
|
||||
riskAversionParameter: 0.01,
|
||||
params: {
|
||||
mu: 0,
|
||||
r: 0.016,
|
||||
sigma: 0.5,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
closingTimestamp,
|
||||
enactmentTimestamp,
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function mockNetworkUpgradeProposal() {
|
||||
cy.mockGQL((req) => {
|
||||
aliasGQLQuery(req, 'Nodes', nodeData);
|
||||
|
||||
@@ -67,7 +67,6 @@ export async function faucetAsset(assetEthAddress: string) {
|
||||
|
||||
export async function vegaWalletTeardown() {
|
||||
cy.get(associatedAmountInWallet)
|
||||
.should('be.visible')
|
||||
.invoke('text')
|
||||
.then((associatedAmount) => {
|
||||
cy.get('body').then(($body) => {
|
||||
@@ -82,9 +81,11 @@ export async function vegaWalletTeardown() {
|
||||
cy.get(vegaWalletContainer).within(() => {
|
||||
cy.get(associatedAmountInWallet, {
|
||||
timeout: transactionTimeout,
|
||||
}).contains('0.00', {
|
||||
timeout: transactionTimeout,
|
||||
});
|
||||
})
|
||||
.should('have.length', 1, { timeout: transactionTimeout })
|
||||
.contains('0.00', {
|
||||
timeout: transactionTimeout,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -27,6 +27,10 @@ import type { ProposalFieldsFragment } from '../proposals/proposals/__generated_
|
||||
import type { NodesFragmentFragment } from '../staking/home/__generated__/Nodes';
|
||||
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
|
||||
import {
|
||||
orderByDate,
|
||||
orderByUpgradeBlockHeight,
|
||||
} from '../proposals/components/proposals-list/proposals-list';
|
||||
|
||||
const nodesToShow = 6;
|
||||
|
||||
@@ -200,17 +204,17 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
|
||||
const proposals = useMemo(
|
||||
() =>
|
||||
proposalsData
|
||||
? getNotRejectedProposals<ProposalFieldsFragment>(
|
||||
proposalsData.proposalsConnection
|
||||
)
|
||||
? getNotRejectedProposals(proposalsData.proposalsConnection)
|
||||
: [],
|
||||
[proposalsData]
|
||||
);
|
||||
|
||||
const sortedProposals = useMemo(() => orderByDate(proposals), [proposals]);
|
||||
|
||||
const protocolUpgradeProposals = useMemo(
|
||||
() =>
|
||||
protocolUpgradesData
|
||||
? getNotRejectedProtocolUpgradeProposals<ProtocolUpgradeProposalFieldsFragment>(
|
||||
? getNotRejectedProtocolUpgradeProposals(
|
||||
protocolUpgradesData.protocolUpgradeProposals
|
||||
).filter(
|
||||
(p) =>
|
||||
@@ -221,15 +225,20 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
|
||||
[protocolUpgradesData]
|
||||
);
|
||||
|
||||
const sortedProtocolUpgradeProposals = useMemo(
|
||||
() => orderByUpgradeBlockHeight(protocolUpgradeProposals),
|
||||
[protocolUpgradeProposals]
|
||||
);
|
||||
|
||||
const totalProposalsDesired = 4;
|
||||
const protocolUpgradeProposalsToShow = protocolUpgradeProposals.slice(
|
||||
const protocolUpgradeProposalsToShow = sortedProtocolUpgradeProposals.slice(
|
||||
0,
|
||||
totalProposalsDesired
|
||||
);
|
||||
const proposalsToShow =
|
||||
protocolUpgradeProposalsToShow.length === totalProposalsDesired
|
||||
? []
|
||||
: proposals.slice(
|
||||
: sortedProposals.slice(
|
||||
0,
|
||||
totalProposalsDesired - protocolUpgradeProposalsToShow.length
|
||||
);
|
||||
|
||||
+1
-1
@@ -124,7 +124,7 @@ describe('Proposal header', () => {
|
||||
})
|
||||
);
|
||||
expect(screen.getByTestId('proposal-title')).toHaveTextContent(
|
||||
'Unknown proposal'
|
||||
'New asset proposal'
|
||||
);
|
||||
expect(screen.getByTestId('proposal-type')).toHaveTextContent('New asset');
|
||||
expect(screen.getByTestId('proposal-details')).toHaveTextContent(
|
||||
|
||||
+13
-2
@@ -21,6 +21,7 @@ export const ProposalHeader = ({
|
||||
|
||||
let details: ReactNode;
|
||||
let proposalType = '';
|
||||
let fallbackTitle = '';
|
||||
|
||||
const title = proposal?.rationale.title.trim();
|
||||
|
||||
@@ -29,6 +30,7 @@ export const ProposalHeader = ({
|
||||
switch (change?.__typename) {
|
||||
case 'NewMarket': {
|
||||
proposalType = 'NewMarket';
|
||||
fallbackTitle = t('NewMarketProposal');
|
||||
details = (
|
||||
<>
|
||||
<span>
|
||||
@@ -50,6 +52,7 @@ export const ProposalHeader = ({
|
||||
}
|
||||
case 'UpdateMarket': {
|
||||
proposalType = 'UpdateMarket';
|
||||
fallbackTitle = t('UpdateMarketProposal');
|
||||
details = (
|
||||
<>
|
||||
<span>{t('Market change')}:</span>{' '}
|
||||
@@ -60,6 +63,7 @@ export const ProposalHeader = ({
|
||||
}
|
||||
case 'NewAsset': {
|
||||
proposalType = 'NewAsset';
|
||||
fallbackTitle = t('NewAssetProposal');
|
||||
details = (
|
||||
<>
|
||||
<span>{t('Symbol')}:</span> <Lozenge>{change.symbol}.</Lozenge>{' '}
|
||||
@@ -81,6 +85,7 @@ export const ProposalHeader = ({
|
||||
}
|
||||
case 'UpdateNetworkParameter': {
|
||||
proposalType = 'NetworkParameter';
|
||||
fallbackTitle = t('NetworkParameterProposal');
|
||||
details = (
|
||||
<>
|
||||
<span>{t('Change')}:</span>{' '}
|
||||
@@ -95,11 +100,13 @@ export const ProposalHeader = ({
|
||||
}
|
||||
case 'NewFreeform': {
|
||||
proposalType = 'Freeform';
|
||||
fallbackTitle = t('FreeformProposal');
|
||||
details = <span />;
|
||||
break;
|
||||
}
|
||||
case 'UpdateAsset': {
|
||||
proposalType = 'UpdateAsset';
|
||||
fallbackTitle = t('UpdateAssetProposal');
|
||||
details = (
|
||||
<>
|
||||
<span>{t('AssetID')}:</span>{' '}
|
||||
@@ -115,10 +122,14 @@ export const ProposalHeader = ({
|
||||
<div data-testid="proposal-title">
|
||||
{isListItem ? (
|
||||
<header>
|
||||
<SubHeading title={titleContent || t('Unknown proposal')} />
|
||||
<SubHeading
|
||||
title={titleContent || fallbackTitle || t('Unknown proposal')}
|
||||
/>
|
||||
</header>
|
||||
) : (
|
||||
<Heading title={titleContent || t('Unknown proposal')} />
|
||||
<Heading
|
||||
title={titleContent || fallbackTitle || t('Unknown proposal')}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
|
||||
@@ -101,9 +101,12 @@ export const Proposal = ({ proposal, restData }: ProposalProps) => {
|
||||
<ProposalDescription description={proposal.rationale.description} />
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<ProposalTerms data={proposal.terms} />
|
||||
</div>
|
||||
{proposal.terms.change.__typename !== 'NewMarket' &&
|
||||
proposal.terms.change.__typename !== 'UpdateMarket' && (
|
||||
<div className="mb-4">
|
||||
<ProposalTerms data={proposal.terms} />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mb-6">
|
||||
<ProposalJson proposal={restData?.data?.proposal} />
|
||||
|
||||
+4
-4
@@ -132,10 +132,10 @@ describe('Proposals list', () => {
|
||||
const closedProposalsItems = closedProposals.getAllByTestId(
|
||||
'proposals-list-item'
|
||||
);
|
||||
expect(openProposalsItems[0]).toHaveAttribute('id', 'proposal1');
|
||||
expect(openProposalsItems[1]).toHaveAttribute('id', 'proposal2');
|
||||
expect(closedProposalsItems[0]).toHaveAttribute('id', 'proposal4');
|
||||
expect(closedProposalsItems[1]).toHaveAttribute('id', 'proposal3');
|
||||
expect(openProposalsItems[0]).toHaveAttribute('id', 'proposal2');
|
||||
expect(openProposalsItems[1]).toHaveAttribute('id', 'proposal1');
|
||||
expect(closedProposalsItems[0]).toHaveAttribute('id', 'proposal3');
|
||||
expect(closedProposalsItems[1]).toHaveAttribute('id', 'proposal4');
|
||||
});
|
||||
|
||||
it('Displays info on no proposals', () => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import { isFuture } from 'date-fns';
|
||||
import { useState } from 'react';
|
||||
import { useState, useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Heading, SubHeading } from '../../../../components/heading';
|
||||
import { ProposalsListItem } from '../proposals-list-item';
|
||||
@@ -30,6 +31,25 @@ interface SortedProtocolUpgradeProposalsProps {
|
||||
closed: ProtocolUpgradeProposalFieldsFragment[];
|
||||
}
|
||||
|
||||
export const orderByDate = (arr: ProposalFieldsFragment[]) =>
|
||||
orderBy(
|
||||
arr,
|
||||
[
|
||||
(p) => new Date(p?.terms?.closingDatetime).getTime(),
|
||||
(p) => new Date(p?.datetime).getTime(),
|
||||
],
|
||||
['asc', 'asc']
|
||||
);
|
||||
|
||||
export const orderByUpgradeBlockHeight = (
|
||||
arr: ProtocolUpgradeProposalFieldsFragment[]
|
||||
) =>
|
||||
orderBy(
|
||||
arr,
|
||||
[(p) => p?.upgradeBlockHeight, (p) => p.vegaReleaseTag],
|
||||
['desc', 'desc']
|
||||
);
|
||||
|
||||
export const ProposalsList = ({
|
||||
proposals,
|
||||
protocolUpgradeProposals,
|
||||
@@ -37,35 +57,57 @@ export const ProposalsList = ({
|
||||
}: ProposalsListProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [filterString, setFilterString] = useState('');
|
||||
const sortedProposals = proposals.reduce(
|
||||
(acc: SortedProposalsProps, proposal) => {
|
||||
if (isFuture(new Date(proposal?.terms.closingDatetime))) {
|
||||
acc.open.push(proposal);
|
||||
} else {
|
||||
acc.closed.push(proposal);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
open: [],
|
||||
closed: [],
|
||||
}
|
||||
);
|
||||
|
||||
const sortedProtocolUpgradeProposals = protocolUpgradeProposals.reduce(
|
||||
(acc: SortedProtocolUpgradeProposalsProps, proposal) => {
|
||||
if (Number(proposal?.upgradeBlockHeight) > Number(lastBlockHeight)) {
|
||||
acc.open.push(proposal);
|
||||
} else {
|
||||
acc.closed.push(proposal);
|
||||
const sortedProposals: SortedProposalsProps = useMemo(() => {
|
||||
const initialSorting = proposals.reduce(
|
||||
(acc: SortedProposalsProps, proposal) => {
|
||||
if (isFuture(new Date(proposal?.terms.closingDatetime))) {
|
||||
acc.open.push(proposal);
|
||||
} else {
|
||||
acc.closed.push(proposal);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
open: [],
|
||||
closed: [],
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
open: [],
|
||||
closed: [],
|
||||
}
|
||||
);
|
||||
);
|
||||
return {
|
||||
open:
|
||||
initialSorting.open.length > 0
|
||||
? orderByDate(initialSorting.open as ProposalFieldsFragment[])
|
||||
: [],
|
||||
closed:
|
||||
initialSorting.closed.length > 0
|
||||
? orderByDate(
|
||||
initialSorting.closed as ProposalFieldsFragment[]
|
||||
).reverse()
|
||||
: [],
|
||||
};
|
||||
}, [proposals]);
|
||||
|
||||
const sortedProtocolUpgradeProposals: SortedProtocolUpgradeProposalsProps =
|
||||
useMemo(() => {
|
||||
const initialSorting = protocolUpgradeProposals.reduce(
|
||||
(acc: SortedProtocolUpgradeProposalsProps, proposal) => {
|
||||
if (Number(proposal?.upgradeBlockHeight) > Number(lastBlockHeight)) {
|
||||
acc.open.push(proposal);
|
||||
} else {
|
||||
acc.closed.push(proposal);
|
||||
}
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
open: [],
|
||||
closed: [],
|
||||
}
|
||||
);
|
||||
return {
|
||||
open: orderByUpgradeBlockHeight(initialSorting.open),
|
||||
closed: orderByUpgradeBlockHeight(initialSorting.closed).reverse(),
|
||||
};
|
||||
}, [protocolUpgradeProposals, lastBlockHeight]);
|
||||
|
||||
const filterPredicate = (
|
||||
p: ProposalFieldsFragment | ProposalQuery['proposal']
|
||||
|
||||
+1
-1
@@ -107,7 +107,7 @@ export const ProtocolUpgradeProposalsListItem = ({
|
||||
<div className="grid grid-cols-1 mt-3">
|
||||
<div className="justify-self-end">
|
||||
<Link
|
||||
to={`${Routes.PROPOSALS}/protocol-upgrade/${stripFullStops(
|
||||
to={`${Routes.PROTOCOL_UPGRADES}/${stripFullStops(
|
||||
proposal.vegaReleaseTag
|
||||
)}`}
|
||||
>
|
||||
|
||||
@@ -11,9 +11,8 @@ import { ENV } from '../../../config';
|
||||
export const ProposalContainer = () => {
|
||||
const params = useParams<{ proposalId: string }>();
|
||||
const {
|
||||
state: { loading: restLoading, error: restError, data: restData },
|
||||
state: { data: restData },
|
||||
} = useFetch(`${ENV.rest}governance?proposalId=${params.proposalId}`);
|
||||
console.log(restLoading, restError, restData);
|
||||
const { data, loading, error, refetch } = useProposalQuery({
|
||||
fetchPolicy: 'network-only',
|
||||
errorPolicy: 'ignore',
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import flow from 'lodash/flow';
|
||||
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
@@ -6,36 +7,15 @@ import { SplashLoader } from '../../../components/splash-loader';
|
||||
import { ProposalsList } from '../components/proposals-list';
|
||||
import { useProposalsQuery } from './__generated__/Proposals';
|
||||
import { getNodes } from '@vegaprotocol/utils';
|
||||
import flow from 'lodash/flow';
|
||||
import {
|
||||
ProposalState,
|
||||
ProtocolUpgradeProposalStatus,
|
||||
} from '@vegaprotocol/types';
|
||||
import type { NodeConnection, NodeEdge } from '@vegaprotocol/utils';
|
||||
import type { ProposalFieldsFragment } from './__generated__/Proposals';
|
||||
import orderBy from 'lodash/orderBy';
|
||||
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
|
||||
|
||||
const orderByDate = (arr: ProposalFieldsFragment[]) =>
|
||||
orderBy(
|
||||
arr,
|
||||
[
|
||||
(p) => new Date(p?.terms?.closingDatetime).getTime(),
|
||||
(p) => new Date(p?.datetime).getTime(),
|
||||
],
|
||||
['asc', 'asc']
|
||||
);
|
||||
|
||||
const orderByUpgradeBlockHeight = (
|
||||
arr: ProtocolUpgradeProposalFieldsFragment[]
|
||||
) =>
|
||||
orderBy(
|
||||
arr,
|
||||
[(p) => p?.upgradeBlockHeight, (p) => p.vegaReleaseTag],
|
||||
['desc', 'desc']
|
||||
);
|
||||
|
||||
export function getNotRejectedProposals<T extends ProposalFieldsFragment>(
|
||||
data?: NodeConnection<NodeEdge<T>> | null
|
||||
): T[] {
|
||||
@@ -44,7 +24,6 @@ export function getNotRejectedProposals<T extends ProposalFieldsFragment>(
|
||||
getNodes<ProposalFieldsFragment>(data, (p) =>
|
||||
p ? p.state !== ProposalState.STATE_REJECTED : false
|
||||
),
|
||||
orderByDate,
|
||||
])(data);
|
||||
}
|
||||
|
||||
@@ -59,7 +38,6 @@ export function getNotRejectedProtocolUpgradeProposals<
|
||||
ProtocolUpgradeProposalStatus.PROTOCOL_UPGRADE_PROPOSAL_STATUS_REJECTED
|
||||
: false
|
||||
),
|
||||
orderByUpgradeBlockHeight,
|
||||
])(data);
|
||||
}
|
||||
|
||||
@@ -82,17 +60,14 @@ export const ProposalsContainer = () => {
|
||||
});
|
||||
|
||||
const proposals = useMemo(
|
||||
() =>
|
||||
getNotRejectedProposals<ProposalFieldsFragment>(
|
||||
data?.proposalsConnection
|
||||
),
|
||||
() => getNotRejectedProposals(data?.proposalsConnection),
|
||||
[data]
|
||||
);
|
||||
|
||||
const protocolUpgradeProposals = useMemo(
|
||||
() =>
|
||||
protocolUpgradesData
|
||||
? getNotRejectedProtocolUpgradeProposals<ProtocolUpgradeProposalFieldsFragment>(
|
||||
? getNotRejectedProtocolUpgradeProposals(
|
||||
protocolUpgradesData.protocolUpgradeProposals
|
||||
)
|
||||
: [],
|
||||
|
||||
@@ -49,6 +49,7 @@ export const ProposeFreeform = () => {
|
||||
formState: { errors },
|
||||
setValue,
|
||||
watch,
|
||||
trigger,
|
||||
} = useForm<FreeformProposalFormFields>();
|
||||
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
|
||||
|
||||
@@ -85,7 +86,13 @@ export const ProposeFreeform = () => {
|
||||
await submit(assembleProposal(fields));
|
||||
};
|
||||
|
||||
const viewJson = () => {
|
||||
const viewJson = async () => {
|
||||
const isValid = await trigger();
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = watch();
|
||||
downloadJson(
|
||||
JSON.stringify(assembleProposal(formData)),
|
||||
|
||||
+8
-1
@@ -89,6 +89,7 @@ export const ProposeNetworkParameter = () => {
|
||||
formState: { errors },
|
||||
setValue,
|
||||
watch,
|
||||
trigger,
|
||||
} = useForm<NetworkParameterProposalFormFields>();
|
||||
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
|
||||
|
||||
@@ -148,7 +149,13 @@ export const ProposeNetworkParameter = () => {
|
||||
await submit(assembleProposal(fields));
|
||||
};
|
||||
|
||||
const viewJson = () => {
|
||||
const viewJson = async () => {
|
||||
const isValid = await trigger();
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = watch();
|
||||
downloadJson(
|
||||
JSON.stringify(assembleProposal(formData)),
|
||||
|
||||
@@ -61,6 +61,7 @@ export const ProposeNewAsset = () => {
|
||||
formState: { errors },
|
||||
setValue,
|
||||
watch,
|
||||
trigger,
|
||||
} = useForm<NewAssetProposalFormFields>();
|
||||
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
|
||||
|
||||
@@ -117,7 +118,13 @@ export const ProposeNewAsset = () => {
|
||||
await submit(assembleProposal(fields));
|
||||
};
|
||||
|
||||
const viewJson = () => {
|
||||
const viewJson = async () => {
|
||||
const isValid = await trigger();
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = watch();
|
||||
downloadJson(
|
||||
JSON.stringify(assembleProposal(formData)),
|
||||
|
||||
@@ -59,6 +59,7 @@ export const ProposeNewMarket = () => {
|
||||
formState: { errors },
|
||||
setValue,
|
||||
watch,
|
||||
trigger,
|
||||
} = useForm<NewMarketProposalFormFields>();
|
||||
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
|
||||
|
||||
@@ -107,7 +108,13 @@ export const ProposeNewMarket = () => {
|
||||
await submit(assembleProposal(fields));
|
||||
};
|
||||
|
||||
const viewJson = () => {
|
||||
const viewJson = async () => {
|
||||
const isValid = await trigger();
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = watch();
|
||||
downloadJson(
|
||||
JSON.stringify(assembleProposal(formData)),
|
||||
|
||||
@@ -59,6 +59,7 @@ export const ProposeUpdateAsset = () => {
|
||||
formState: { errors },
|
||||
setValue,
|
||||
watch,
|
||||
trigger,
|
||||
} = useForm<UpdateAssetProposalFormFields>();
|
||||
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
|
||||
|
||||
@@ -107,7 +108,13 @@ export const ProposeUpdateAsset = () => {
|
||||
await submit(assembleProposal(fields));
|
||||
};
|
||||
|
||||
const viewJson = () => {
|
||||
const viewJson = async () => {
|
||||
const isValid = await trigger();
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = watch();
|
||||
downloadJson(
|
||||
JSON.stringify(assembleProposal(formData)),
|
||||
|
||||
+8
-1
@@ -106,6 +106,7 @@ export const ProposeUpdateMarket = () => {
|
||||
formState: { errors },
|
||||
setValue,
|
||||
watch,
|
||||
trigger,
|
||||
} = useForm<UpdateMarketProposalFormFields>();
|
||||
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
|
||||
|
||||
@@ -157,7 +158,13 @@ export const ProposeUpdateMarket = () => {
|
||||
await submit(assembleProposal(fields));
|
||||
};
|
||||
|
||||
const viewJson = () => {
|
||||
const viewJson = async () => {
|
||||
const isValid = await trigger();
|
||||
|
||||
if (!isValid) {
|
||||
return;
|
||||
}
|
||||
|
||||
const formData = watch();
|
||||
downloadJson(
|
||||
JSON.stringify(assembleProposal(formData)),
|
||||
|
||||
@@ -16,11 +16,10 @@ const orderByDate = (arr: ProposalFieldsFragment[]) =>
|
||||
orderBy(
|
||||
arr,
|
||||
[
|
||||
(p) => new Date(p?.terms?.enactmentDatetime || 0).getTime(), // has to be defaulted to 0 because new Date(null).getTime() -> NaN which is first when ordered.
|
||||
(p) => new Date(p?.terms?.closingDatetime).getTime(),
|
||||
(p) => new Date(p?.terms?.closingDatetime || 0).getTime(), // has to be defaulted to 0 because new Date(null).getTime() -> NaN which is first when ordered
|
||||
(p) => p.id,
|
||||
],
|
||||
['desc', 'desc', 'desc']
|
||||
['desc', 'desc']
|
||||
);
|
||||
|
||||
export function getRejectedProposals<T extends ProposalFieldsFragment>(
|
||||
|
||||
@@ -224,6 +224,10 @@ const redirects = [
|
||||
path: '/vesting',
|
||||
element: <Navigate to={Routes.REDEEM} replace />,
|
||||
},
|
||||
{
|
||||
path: Routes.PROTOCOL_UPGRADES,
|
||||
element: <Navigate to={Routes.PROPOSALS} replace />,
|
||||
},
|
||||
];
|
||||
|
||||
const routerConfig = [
|
||||
@@ -264,13 +268,13 @@ const routerConfig = [
|
||||
},
|
||||
{ path: 'proposals', element: <LazyProposalsList /> },
|
||||
{ path: ':proposalId', element: <LazyProposal /> },
|
||||
{
|
||||
path: 'protocol-upgrade/:proposalReleaseTag',
|
||||
element: <LazyProtocolUpgradeProposal />,
|
||||
},
|
||||
{ path: 'rejected', element: <LazyRejectedProposalsList /> },
|
||||
],
|
||||
},
|
||||
{
|
||||
path: `${Routes.PROTOCOL_UPGRADES}/:proposalReleaseTag`,
|
||||
element: <LazyProtocolUpgradeProposal />,
|
||||
},
|
||||
{
|
||||
path: Routes.VALIDATORS,
|
||||
element: <LazyStaking name="Staking" />,
|
||||
|
||||
@@ -5,6 +5,7 @@ const Routes = {
|
||||
REWARDS: '/rewards',
|
||||
PROPOSALS: '/proposals',
|
||||
PROPOSALS_REJECTED: '/proposals/rejected',
|
||||
PROTOCOL_UPGRADES: '/protocol-upgrades',
|
||||
NOT_PERMITTED: '/not-permitted',
|
||||
NOT_FOUND: '/not-found',
|
||||
CONTRACTS: '/contracts',
|
||||
|
||||
@@ -5,12 +5,22 @@ query PreviousEpoch($epochId: ID) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
stakedTotal
|
||||
rewardScore {
|
||||
rawValidatorScore
|
||||
performanceScore
|
||||
multisigScore
|
||||
validatorScore
|
||||
normalisedScore
|
||||
validatorStatus
|
||||
}
|
||||
rankingScore {
|
||||
status
|
||||
previousStatus
|
||||
rankingScore
|
||||
stakeScore
|
||||
performanceScore
|
||||
votingPower
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ 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, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string, performanceScore: string } | null, rankingScore: { __typename?: 'RankingScore', stakeScore: string } } } | null> | null } | null } };
|
||||
export type PreviousEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, validatorsConnection?: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, stakedTotal: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string, performanceScore: string, multisigScore: string, validatorScore: string, normalisedScore: string, validatorStatus: Types.ValidatorStatus } | null, rankingScore: { __typename?: 'RankingScore', status: Types.ValidatorStatus, previousStatus: Types.ValidatorStatus, rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string } } } | null> | null } | null } };
|
||||
|
||||
|
||||
export const PreviousEpochDocument = gql`
|
||||
@@ -19,12 +19,22 @@ export const PreviousEpochDocument = gql`
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
stakedTotal
|
||||
rewardScore {
|
||||
rawValidatorScore
|
||||
performanceScore
|
||||
multisigScore
|
||||
validatorScore
|
||||
normalisedScore
|
||||
validatorStatus
|
||||
}
|
||||
rankingScore {
|
||||
status
|
||||
previousStatus
|
||||
rankingScore
|
||||
stakeScore
|
||||
performanceScore
|
||||
votingPower
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+36
@@ -79,36 +79,72 @@ const MOCK_PREVIOUS_EPOCH: PreviousEpochQuery = {
|
||||
{
|
||||
node: {
|
||||
id: 'ccc022b7e63a4d0a6d3a193c3940c88574060e58a184964c994998d86835a1b4',
|
||||
stakedTotal: '14182454495731682635157',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.25',
|
||||
performanceScore: '0.9998677767864936',
|
||||
multisigScore: '',
|
||||
validatorScore: '',
|
||||
normalisedScore: '',
|
||||
validatorStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
},
|
||||
rankingScore: {
|
||||
stakeScore: '0.2499583402766206',
|
||||
performanceScore: '0.9998677767864936',
|
||||
status: Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
previousStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
rankingScore: '',
|
||||
votingPower: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: '966438c6bffac737cfb08173ffcb3f393c4692b099ad80cb45a82e2dc0a8cf99',
|
||||
stakedTotal: '9618711883996159534058',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.3',
|
||||
performanceScore: '1',
|
||||
multisigScore: '',
|
||||
validatorScore: '0.31067',
|
||||
normalisedScore: '',
|
||||
validatorStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
},
|
||||
rankingScore: {
|
||||
stakeScore: '0.25',
|
||||
performanceScore: '0.9998677767864936',
|
||||
status: Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
previousStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
rankingScore: '',
|
||||
votingPower: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: '12c81b738e8051152e1afe44376ec37bca9216466e6d44cdd772194bad0ada81',
|
||||
stakedTotal: '4041343338923442976709',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.35',
|
||||
performanceScore: '0.999629748500531',
|
||||
multisigScore: '',
|
||||
validatorScore: '',
|
||||
normalisedScore: '',
|
||||
validatorStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
},
|
||||
rankingScore: {
|
||||
stakeScore: '0.2312',
|
||||
performanceScore: '0.9998677767864936',
|
||||
status: Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
previousStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
rankingScore: '',
|
||||
votingPower: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
+23
-23
@@ -7,12 +7,12 @@ import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { useAppState } from '../../../../contexts/app-state/app-state-context';
|
||||
import { BigNumber } from '../../../../lib/bignumber';
|
||||
import {
|
||||
calculateOverallPenalty,
|
||||
calculateOverstakedPenalty,
|
||||
calculatesPerformancePenalty,
|
||||
getFormattedPerformanceScore,
|
||||
getLastEpochScoreAndPerformance,
|
||||
getNormalisedVotingPower,
|
||||
getOverstakingPenalty,
|
||||
getPerformancePenalty,
|
||||
getTotalPenalties,
|
||||
getUnnormalisedVotingPower,
|
||||
} from '../../shared';
|
||||
import {
|
||||
@@ -32,6 +32,7 @@ import type { ValidatorsTableProps } from './shared';
|
||||
import {
|
||||
formatNumber,
|
||||
formatNumberPercentage,
|
||||
removePaginationWrapper,
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { VALIDATOR_LOGO_MAP } from './logo-map';
|
||||
@@ -136,6 +137,10 @@ export const ConsensusValidatorsTable = ({
|
||||
[totalStake]
|
||||
);
|
||||
|
||||
const allNodesInPreviousEpoch = removePaginationWrapper(
|
||||
previousEpochData?.epoch.validatorsConnection?.edges
|
||||
);
|
||||
|
||||
const nodes = useMemo(() => {
|
||||
if (!data) return [];
|
||||
let canonisedNodes = data
|
||||
@@ -160,7 +165,7 @@ export const ConsensusValidatorsTable = ({
|
||||
stakedByDelegates,
|
||||
stakedByOperator,
|
||||
stakedTotal,
|
||||
rankingScore: { stakeScore, votingPower },
|
||||
rankingScore: { stakeScore, votingPower, performanceScore },
|
||||
pendingStake,
|
||||
stakedTotalRanking,
|
||||
stakedByUser,
|
||||
@@ -172,11 +177,8 @@ export const ConsensusValidatorsTable = ({
|
||||
: avatarUrl
|
||||
? avatarUrl
|
||||
: null;
|
||||
const {
|
||||
rawValidatorScore: previousEpochValidatorScore,
|
||||
performanceScore: previousEpochPerformanceScore,
|
||||
stakeScore: previousEpochStakeScore,
|
||||
} = getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
const { rawValidatorScore: previousEpochValidatorScore } =
|
||||
getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
|
||||
return {
|
||||
id,
|
||||
@@ -199,21 +201,19 @@ export const ConsensusValidatorsTable = ({
|
||||
toBigNum(stakedByOperator, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PERFORMANCE_SCORE]: getFormattedPerformanceScore(
|
||||
previousEpochPerformanceScore
|
||||
).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]: getPerformancePenalty(
|
||||
previousEpochPerformanceScore
|
||||
[ValidatorFields.PERFORMANCE_SCORE]:
|
||||
getFormattedPerformanceScore(performanceScore).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]: formatNumberPercentage(
|
||||
calculatesPerformancePenalty(performanceScore),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
|
||||
previousEpochValidatorScore,
|
||||
previousEpochStakeScore
|
||||
[ValidatorFields.OVERSTAKING_PENALTY]: formatNumberPercentage(
|
||||
calculateOverstakedPenalty(id, allNodesInPreviousEpoch),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
|
||||
previousEpochValidatorScore,
|
||||
previousEpochPerformanceScore,
|
||||
stakedTotal,
|
||||
totalStake
|
||||
[ValidatorFields.TOTAL_PENALTIES]: formatNumberPercentage(
|
||||
calculateOverallPenalty(id, allNodesInPreviousEpoch),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PENDING_STAKE]: pendingStake,
|
||||
[ValidatorFields.STAKED_BY_USER]: stakedByUser
|
||||
@@ -328,12 +328,12 @@ export const ConsensusValidatorsTable = ({
|
||||
...remaining,
|
||||
];
|
||||
}, [
|
||||
allNodesInPreviousEpoch,
|
||||
data,
|
||||
decimals,
|
||||
hideTopThird,
|
||||
previousEpochData,
|
||||
thirdOfTotalStake,
|
||||
totalStake,
|
||||
validatorsView,
|
||||
]);
|
||||
|
||||
|
||||
+33
-34
@@ -5,15 +5,14 @@ import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { useAppState } from '../../../../contexts/app-state/app-state-context';
|
||||
import { BigNumber } from '../../../../lib/bignumber';
|
||||
import {
|
||||
calculatesPerformancePenalty,
|
||||
calculateOverallPenalty,
|
||||
calculateOverstakedPenalty,
|
||||
getFormattedPerformanceScore,
|
||||
getLastEpochScoreAndPerformance,
|
||||
getOverstakingPenalty,
|
||||
getPerformancePenalty,
|
||||
getTotalPenalties,
|
||||
} from '../../shared';
|
||||
import {
|
||||
defaultColDef,
|
||||
StakeNeededForPromotionRenderer,
|
||||
stakedTotalPercentage,
|
||||
ValidatorFields,
|
||||
ValidatorRenderer,
|
||||
@@ -28,6 +27,7 @@ import type { ValidatorsTableProps } from './shared';
|
||||
import {
|
||||
formatNumber,
|
||||
formatNumberPercentage,
|
||||
removePaginationWrapper,
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
|
||||
@@ -52,6 +52,10 @@ export const StandbyPendingValidatorsTable = ({
|
||||
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
|
||||
const allNodesInPreviousEpoch = removePaginationWrapper(
|
||||
previousEpochData?.epoch.validatorsConnection?.edges
|
||||
);
|
||||
|
||||
let nodes = useMemo(() => {
|
||||
if (!data) return [];
|
||||
|
||||
@@ -77,18 +81,15 @@ export const StandbyPendingValidatorsTable = ({
|
||||
stakedByDelegates,
|
||||
stakedByOperator,
|
||||
stakedTotal,
|
||||
rankingScore: { stakeScore },
|
||||
rankingScore: { stakeScore, performanceScore },
|
||||
pendingStake,
|
||||
stakedTotalRanking,
|
||||
stakedByUser,
|
||||
pendingUserStake,
|
||||
userStakeShare,
|
||||
}) => {
|
||||
const {
|
||||
rawValidatorScore: previousEpochValidatorScore,
|
||||
performanceScore: previousEpochPerformanceScore,
|
||||
stakeScore: previousEpochStakeScore,
|
||||
} = getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
const { performanceScore: previousEpochPerformanceScore } =
|
||||
getLastEpochScoreAndPerformance(previousEpochData, id);
|
||||
|
||||
let individualStakeNeededForPromotion,
|
||||
individualStakeNeededForPromotionDescription;
|
||||
@@ -144,21 +145,19 @@ export const StandbyPendingValidatorsTable = ({
|
||||
toBigNum(stakedByOperator, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PERFORMANCE_SCORE]: getFormattedPerformanceScore(
|
||||
previousEpochPerformanceScore
|
||||
).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]: getPerformancePenalty(
|
||||
previousEpochPerformanceScore
|
||||
[ValidatorFields.PERFORMANCE_SCORE]:
|
||||
getFormattedPerformanceScore(performanceScore).toString(),
|
||||
[ValidatorFields.PERFORMANCE_PENALTY]: formatNumberPercentage(
|
||||
calculatesPerformancePenalty(performanceScore),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
|
||||
previousEpochValidatorScore,
|
||||
previousEpochStakeScore
|
||||
[ValidatorFields.OVERSTAKING_PENALTY]: formatNumberPercentage(
|
||||
calculateOverstakedPenalty(id, allNodesInPreviousEpoch),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
|
||||
previousEpochValidatorScore,
|
||||
previousEpochPerformanceScore,
|
||||
stakedTotal,
|
||||
totalStake
|
||||
[ValidatorFields.TOTAL_PENALTIES]: formatNumberPercentage(
|
||||
calculateOverallPenalty(id, allNodesInPreviousEpoch),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PENDING_STAKE]: pendingStake,
|
||||
[ValidatorFields.STAKED_BY_USER]: stakedByUser
|
||||
@@ -172,13 +171,13 @@ export const StandbyPendingValidatorsTable = ({
|
||||
}
|
||||
);
|
||||
}, [
|
||||
allNodesInPreviousEpoch,
|
||||
data,
|
||||
decimals,
|
||||
previousEpochData,
|
||||
stakeNeededForPromotion,
|
||||
stakeNeededForPromotionDescription,
|
||||
t,
|
||||
totalStake,
|
||||
]);
|
||||
|
||||
if (validatorsView === 'myStake') {
|
||||
@@ -226,21 +225,21 @@ export const StandbyPendingValidatorsTable = ({
|
||||
cellRenderer: StakeShareRenderer,
|
||||
width: 100,
|
||||
},
|
||||
{
|
||||
field: ValidatorFields.STAKE_NEEDED_FOR_PROMOTION,
|
||||
headerName: t(ValidatorFields.STAKE_NEEDED_FOR_PROMOTION).toString(),
|
||||
headerTooltip: t(stakeNeededForPromotionDescription, {
|
||||
prefix: t('The'),
|
||||
}),
|
||||
cellRenderer: StakeNeededForPromotionRenderer,
|
||||
width: 210,
|
||||
},
|
||||
// {
|
||||
// field: ValidatorFields.STAKE_NEEDED_FOR_PROMOTION,
|
||||
// headerName: t(ValidatorFields.STAKE_NEEDED_FOR_PROMOTION).toString(),
|
||||
// headerTooltip: t(stakeNeededForPromotionDescription, {
|
||||
// prefix: t('The'),
|
||||
// }),
|
||||
// cellRenderer: StakeNeededForPromotionRenderer,
|
||||
// width: 210,
|
||||
// },
|
||||
{
|
||||
field: ValidatorFields.TOTAL_PENALTIES,
|
||||
headerName: t(ValidatorFields.TOTAL_PENALTIES).toString(),
|
||||
headerTooltip: t('TotalPenaltiesDescription').toString(),
|
||||
cellRenderer: TotalPenaltiesRenderer,
|
||||
width: 120,
|
||||
width: 120 + 210,
|
||||
},
|
||||
],
|
||||
[]
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
useEnvironment,
|
||||
DocsLinks,
|
||||
ExternalLinks,
|
||||
} from '@vegaprotocol/environment';
|
||||
import { toBigNum } from '@vegaprotocol/utils';
|
||||
import {
|
||||
formatNumberPercentage,
|
||||
removePaginationWrapper,
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import {
|
||||
Link as UTLink,
|
||||
@@ -24,11 +28,11 @@ import { SubHeading } from '../../../components/heading';
|
||||
import {
|
||||
getLastEpochScoreAndPerformance,
|
||||
getNormalisedVotingPower,
|
||||
getOverstakingPenalty,
|
||||
getPerformancePenalty,
|
||||
getTotalPenalties,
|
||||
getUnnormalisedVotingPower,
|
||||
getStakePercentage,
|
||||
calculatesPerformancePenalty,
|
||||
calculateOverstakedPenalty,
|
||||
calculateOverallPenalty,
|
||||
} from '../shared';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { StakingNodeFieldsFragment } from '../__generated__/Staking';
|
||||
@@ -78,17 +82,27 @@ export const ValidatorTable = ({
|
||||
|
||||
const stakedOnNode = toBigNum(node.stakedTotal, decimals);
|
||||
|
||||
const { rawValidatorScore, performanceScore, stakeScore } =
|
||||
getLastEpochScoreAndPerformance(previousEpochData, node.id);
|
||||
const { rawValidatorScore } = getLastEpochScoreAndPerformance(
|
||||
previousEpochData,
|
||||
node.id
|
||||
);
|
||||
|
||||
const stakePercentage = getStakePercentage(total, stakedOnNode);
|
||||
|
||||
const totalPenaltiesAmount = getTotalPenalties(
|
||||
rawValidatorScore,
|
||||
performanceScore,
|
||||
stakedOnNode.toString(),
|
||||
total.toString()
|
||||
);
|
||||
const penalties = useMemo(() => {
|
||||
const allNodesInPreviousEpoch = removePaginationWrapper(
|
||||
previousEpochData?.epoch.validatorsConnection?.edges
|
||||
);
|
||||
return {
|
||||
// current epoch
|
||||
performance: calculatesPerformancePenalty(
|
||||
node.rankingScore.performanceScore
|
||||
),
|
||||
// previous epoch
|
||||
overstaked: calculateOverstakedPenalty(node.id, allNodesInPreviousEpoch),
|
||||
overall: calculateOverallPenalty(node.id, allNodesInPreviousEpoch),
|
||||
};
|
||||
}, [node, previousEpochData?.epoch.validatorsConnection?.edges]);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -242,7 +256,7 @@ export const ValidatorTable = ({
|
||||
|
||||
<Tooltip description={t('OverstakedPenaltyDescription')}>
|
||||
<span data-testid="overstaking-penalty">
|
||||
{getOverstakingPenalty(rawValidatorScore, stakeScore)}
|
||||
{formatNumberPercentage(penalties.overstaked, 2)}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</KeyValueTableRow>
|
||||
@@ -251,7 +265,7 @@ export const ValidatorTable = ({
|
||||
|
||||
<Tooltip description={t('PerformancePenaltyDescription')}>
|
||||
<span data-testid="performance-penalty">
|
||||
{getPerformancePenalty(performanceScore)}
|
||||
{formatNumberPercentage(penalties.performance, 2)}
|
||||
</span>
|
||||
</Tooltip>
|
||||
</KeyValueTableRow>
|
||||
@@ -260,7 +274,7 @@ export const ValidatorTable = ({
|
||||
<strong>{t('TOTAL PENALTIES')}</strong>
|
||||
</span>
|
||||
<span data-testid="total-penalties">
|
||||
<strong>{totalPenaltiesAmount}</strong>
|
||||
<strong>{formatNumberPercentage(penalties.overall, 2)}</strong>
|
||||
</span>
|
||||
</KeyValueTableRow>
|
||||
</KeyValueTable>
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
getTotalPenalties,
|
||||
getStakePercentage,
|
||||
} from './shared';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
|
||||
describe('getLastEpochScoreAndPerformance', () => {
|
||||
const mockPreviousEpochData = {
|
||||
@@ -19,24 +20,48 @@ describe('getLastEpochScoreAndPerformance', () => {
|
||||
{
|
||||
node: {
|
||||
id: '0x123',
|
||||
stakedTotal: '',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.25',
|
||||
performanceScore: '0.75',
|
||||
multisigScore: '',
|
||||
validatorScore: '',
|
||||
normalisedScore: '',
|
||||
validatorStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
},
|
||||
rankingScore: {
|
||||
stakeScore: '0.25',
|
||||
performanceScore: '0.75',
|
||||
status: Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
previousStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
rankingScore: '',
|
||||
votingPower: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: '0x234',
|
||||
stakedTotal: '',
|
||||
rewardScore: {
|
||||
rawValidatorScore: '0.35',
|
||||
performanceScore: '0.85',
|
||||
multisigScore: '',
|
||||
validatorScore: '',
|
||||
normalisedScore: '',
|
||||
validatorStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
},
|
||||
rankingScore: {
|
||||
stakeScore: '0.25',
|
||||
performanceScore: '0.85',
|
||||
status: Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
previousStatus:
|
||||
Schema.ValidatorStatus.VALIDATOR_NODE_STATUS_TENDERMINT,
|
||||
rankingScore: '',
|
||||
votingPower: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -4,6 +4,94 @@ import {
|
||||
} from '@vegaprotocol/utils';
|
||||
import type { PreviousEpochQuery } from './__generated__/PreviousEpoch';
|
||||
import { BigNumber } from '../../lib/bignumber';
|
||||
import type { LastArrayElement } from 'type-fest';
|
||||
|
||||
type Node = NonNullable<
|
||||
LastArrayElement<
|
||||
NonNullable<
|
||||
NonNullable<PreviousEpochQuery['epoch']['validatorsConnection']>['edges']
|
||||
>
|
||||
>
|
||||
>['node'];
|
||||
|
||||
/**
|
||||
* Calculates theoretical stake score for a given node
|
||||
* @param nodeId Id of a node for which a score is calculated
|
||||
* @param nodes A collection of all nodes
|
||||
* @returns Theoretical stake score for given node based on the staked total
|
||||
* of all node of the same type (status)
|
||||
*/
|
||||
const calculateTheoreticalStakeScore = (nodeId: string, nodes: Node[]) => {
|
||||
const node = nodes.find((n) => n.id === nodeId);
|
||||
if (!node) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
const all = nodes
|
||||
.filter((n) => n.rankingScore.status === node.rankingScore.status)
|
||||
.map((n) => new BigNumber(n.stakedTotal));
|
||||
const sumOfSameType = all.reduce((acc, a) => acc.plus(a), new BigNumber(0));
|
||||
if (sumOfSameType.isZero()) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
return new BigNumber(node.stakedTotal).dividedBy(sumOfSameType);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates overall penalty for a given node
|
||||
* @param nodeId Id of a node for which a penalty is calculated
|
||||
* @param nodes A collection of all nodes - needed to calculate theoretical stake score
|
||||
* @returns %
|
||||
*/
|
||||
export const calculateOverallPenalty = (nodeId: string, nodes: Node[]) => {
|
||||
const node = nodes.find((n) => n.id === nodeId);
|
||||
const tts = calculateTheoreticalStakeScore(nodeId, nodes);
|
||||
if (!node || tts.isZero()) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
const penalty = new BigNumber(1)
|
||||
.minus(new BigNumber(node.rewardScore?.validatorScore || 0).dividedBy(tts))
|
||||
.times(100);
|
||||
return penalty.isLessThan(0) ? new BigNumber(0) : penalty;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates over-staked penalty for a given node
|
||||
* @param nodeId Id of a node for which a penalty is calculated
|
||||
* @param nodes A collection of all nodes - needed to calculate theoretical stake score
|
||||
* @returns %
|
||||
*/
|
||||
export const calculateOverstakedPenalty = (nodeId: string, nodes: Node[]) => {
|
||||
const node = nodes.find((n) => n.id === nodeId);
|
||||
const tts = calculateTheoreticalStakeScore(nodeId, nodes);
|
||||
if (!node || tts.isZero()) {
|
||||
return new BigNumber(0);
|
||||
}
|
||||
const penalty = new BigNumber(1)
|
||||
.minus(
|
||||
new BigNumber(node.rewardScore?.rawValidatorScore || 0).dividedBy(tts)
|
||||
)
|
||||
.times(100);
|
||||
console.log(
|
||||
nodeId,
|
||||
new BigNumber(node.rewardScore?.rawValidatorScore || 0).toString(),
|
||||
tts.toString(),
|
||||
new BigNumber(node.rewardScore?.rawValidatorScore || 0)
|
||||
.dividedBy(tts)
|
||||
.toString()
|
||||
);
|
||||
return penalty.isLessThan(0) ? new BigNumber(0) : penalty;
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates performance penalty based on the given performance score.
|
||||
* @returns %
|
||||
*/
|
||||
export const calculatesPerformancePenalty = (performanceScore: string) => {
|
||||
const penalty = new BigNumber(1)
|
||||
.minus(new BigNumber(performanceScore))
|
||||
.times(100);
|
||||
return penalty.isLessThan(0) ? new BigNumber(0) : penalty;
|
||||
};
|
||||
|
||||
export const getLastEpochScoreAndPerformance = (
|
||||
previousEpochData: PreviousEpochQuery | undefined,
|
||||
@@ -15,7 +103,7 @@ export const getLastEpochScoreAndPerformance = (
|
||||
|
||||
return {
|
||||
rawValidatorScore: validator?.rewardScore?.rawValidatorScore,
|
||||
performanceScore: validator?.rewardScore?.performanceScore,
|
||||
performanceScore: validator?.rankingScore?.performanceScore,
|
||||
stakeScore: validator?.rankingScore?.stakeScore,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -36,9 +36,9 @@
|
||||
"tranche_id": 58,
|
||||
"tranche_start": "2023-05-11T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-11T00:00:00.000Z",
|
||||
"total_added": "21906",
|
||||
"total_added": "22171",
|
||||
"total_removed": "215.8495183664",
|
||||
"locked_amount": "16071.2783400537630666",
|
||||
"locked_amount": "16087.5421553912796572",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "11447",
|
||||
@@ -134,6 +134,16 @@
|
||||
"amount": "27",
|
||||
"user": "0x697cEF6741F519621fE14c72041e4B8B1f7e2c8A",
|
||||
"tx": "0x219dd6f5a742fc8c99add1df269ea16bac53db20d2b1f11ff75e2cd557904065"
|
||||
},
|
||||
{
|
||||
"amount": "30",
|
||||
"user": "0x90Cf7B9958C3BbBCddAb52Ecc408535D4f3C4241",
|
||||
"tx": "0x13eb5324590141c3cbdf8b22237c0290f609021321ec0584d94249bac2401c74"
|
||||
},
|
||||
{
|
||||
"amount": "235",
|
||||
"user": "0x2f1C71D4134B4C154BF946aeb9A94cc2Da1efe59",
|
||||
"tx": "0x4b9137c5b07d4a07e864dfbe3810ad7b78f276e1017c9ccc8d99ced6fea3e9ae"
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
@@ -411,6 +421,36 @@
|
||||
"total_tokens": "4765",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "4765"
|
||||
},
|
||||
{
|
||||
"address": "0x90Cf7B9958C3BbBCddAb52Ecc408535D4f3C4241",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "30",
|
||||
"user": "0x90Cf7B9958C3BbBCddAb52Ecc408535D4f3C4241",
|
||||
"tranche_id": 58,
|
||||
"tx": "0x13eb5324590141c3cbdf8b22237c0290f609021321ec0584d94249bac2401c74"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "30",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "30"
|
||||
},
|
||||
{
|
||||
"address": "0x2f1C71D4134B4C154BF946aeb9A94cc2Da1efe59",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "235",
|
||||
"user": "0x2f1C71D4134B4C154BF946aeb9A94cc2Da1efe59",
|
||||
"tranche_id": 58,
|
||||
"tx": "0x4b9137c5b07d4a07e864dfbe3810ad7b78f276e1017c9ccc8d99ced6fea3e9ae"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "235",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "235"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -452,8 +492,8 @@
|
||||
"tranche_start": "2023-04-20T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-20T00:00:00.000Z",
|
||||
"total_added": "21431.125",
|
||||
"total_removed": "4874.82783147815125",
|
||||
"locked_amount": "530.8254846161266649175",
|
||||
"total_removed": "5063.63195980021375",
|
||||
"locked_amount": "352.877694396219380540625",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "897",
|
||||
@@ -777,6 +817,16 @@
|
||||
"user": "0x9E53F72210479BF46aE7ABF77c48B0d611b3c3dB",
|
||||
"tx": "0xa6fd18e4158f18bdd8bf5294e69847a229e9b6dacd1772f94e95f0c56285729d"
|
||||
},
|
||||
{
|
||||
"amount": "92.7240241607625",
|
||||
"user": "0xdC483901425B2EA6494EaE01ADB6565936E25124",
|
||||
"tx": "0x0fb773aaa35072e4a5129d4815ad5f1f0808fb4a41c9ca119bf8c4caa1b64bf8"
|
||||
},
|
||||
{
|
||||
"amount": "96.0801041613",
|
||||
"user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756",
|
||||
"tx": "0xbc77fce0ebe70c829a12092a26249b1db5456186ba6b11c874bd59e8aca77b03"
|
||||
},
|
||||
{
|
||||
"amount": "202.093666077975",
|
||||
"user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756",
|
||||
@@ -1081,6 +1131,12 @@
|
||||
"tranche_id": 56,
|
||||
"tx": "0x682c6453a6c681312a81e15f244e4885c0ceaab35c7dc041c02d536ff42ca62f"
|
||||
},
|
||||
{
|
||||
"amount": "96.0801041613",
|
||||
"user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756",
|
||||
"tranche_id": 56,
|
||||
"tx": "0xbc77fce0ebe70c829a12092a26249b1db5456186ba6b11c874bd59e8aca77b03"
|
||||
},
|
||||
{
|
||||
"amount": "202.093666077975",
|
||||
"user": "0x1447Efc62d5077d7AbB20492dF831Dd6c9Eb1756",
|
||||
@@ -1107,8 +1163,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "1207.5",
|
||||
"withdrawn_tokens": "1086.548284142475",
|
||||
"remaining_tokens": "120.951715857525"
|
||||
"withdrawn_tokens": "1182.628388303775",
|
||||
"remaining_tokens": "24.871611696225"
|
||||
},
|
||||
{
|
||||
"address": "0x33Ce1D9E53AFb7367E34749517C086405a651a95",
|
||||
@@ -1360,10 +1416,17 @@
|
||||
"tx": "0x14ca69443a14b0f35538856a4fdda6a2b287d7ac6e7c4e600fb797c4c6d44098"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "92.7240241607625",
|
||||
"user": "0xdC483901425B2EA6494EaE01ADB6565936E25124",
|
||||
"tranche_id": 56,
|
||||
"tx": "0x0fb773aaa35072e4a5129d4815ad5f1f0808fb4a41c9ca119bf8c4caa1b64bf8"
|
||||
}
|
||||
],
|
||||
"total_tokens": "94.875",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "94.875"
|
||||
"withdrawn_tokens": "92.7240241607625",
|
||||
"remaining_tokens": "2.1509758392375"
|
||||
},
|
||||
{
|
||||
"address": "0xE9F41a0090fcc7eaf626037003AAD44B17098E7C",
|
||||
@@ -6152,7 +6215,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "86666.297",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "47427.3752864312792701068",
|
||||
"locked_amount": "47368.22916631352482661",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "86666.297",
|
||||
@@ -6218,7 +6281,7 @@
|
||||
"tranche_end": "2023-06-01T00:00:00.000Z",
|
||||
"total_added": "2500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "175.042130901506",
|
||||
"locked_amount": "171.620465761090625",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2500",
|
||||
@@ -6251,7 +6314,7 @@
|
||||
"tranche_end": "2023-11-01T00:00:00.000Z",
|
||||
"total_added": "15000.000000000000015",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "13511.663081219808013511663081219808",
|
||||
"locked_amount": "13491.356242451691013491356242451691",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1.5e-14",
|
||||
@@ -6359,7 +6422,7 @@
|
||||
"tranche_end": "2023-09-01T00:00:00.000Z",
|
||||
"total_added": "17500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "9961.97649330716525",
|
||||
"locked_amount": "9938.2851814110305",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "12500",
|
||||
@@ -6626,7 +6689,7 @@
|
||||
"tranche_end": "2023-08-01T00:00:00.000Z",
|
||||
"total_added": "37500",
|
||||
"total_removed": "18592.291570575",
|
||||
"locked_amount": "15278.259764426026125",
|
||||
"locked_amount": "15226.651223910375",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -7078,7 +7141,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "129999.45",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "47384.103774023588476863",
|
||||
"locked_amount": "47325.01161729839244873",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129999.45",
|
||||
@@ -7111,7 +7174,7 @@
|
||||
"tranche_end": "2024-04-01T00:00:00.000Z",
|
||||
"total_added": "54144.7663",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "47005.80358792078600524149",
|
||||
"locked_amount": "46968.95301173717592265927",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "54144.7663",
|
||||
@@ -7144,7 +7207,7 @@
|
||||
"tranche_end": "2023-09-03T00:00:00.000Z",
|
||||
"total_added": "62600",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "18307.16712962962592",
|
||||
"locked_amount": "18264.44524987316222",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10000",
|
||||
@@ -7337,7 +7400,7 @@
|
||||
"tranche_end": "2023-09-17T00:00:00.000Z",
|
||||
"total_added": "5000",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "1654.01461821410465",
|
||||
"locked_amount": "1650.6023274987315",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "5000",
|
||||
@@ -8406,7 +8469,7 @@
|
||||
"tranche_end": "2023-06-02T00:00:00.000Z",
|
||||
"total_added": "1939928.38",
|
||||
"total_removed": "1709370.7872515768348",
|
||||
"locked_amount": "73042.6464466127914863066",
|
||||
"locked_amount": "71718.7265267003714855776",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1852091.69",
|
||||
@@ -13927,7 +13990,7 @@
|
||||
"tranche_id": 11,
|
||||
"tranche_start": "2021-09-03T00:00:00.000Z",
|
||||
"tranche_end": "2022-09-03T00:00:00.000Z",
|
||||
"total_added": "58128.000000000000000003",
|
||||
"total_added": "58393.000000000000000003",
|
||||
"total_removed": "51151.35141572991",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
@@ -14006,6 +14069,76 @@
|
||||
"user": "0x84D58afeeCd6E2640aF84C329f401AA8a5C9c9E7",
|
||||
"tx": "0x05b5fd46cee5634d9a657a11f66a3ac8d9734e1acc2e2b22015cea69235a0ce5"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0xeaa18356de12943a056aa6b91a8ade1aa10db8c89f23ef31e53282ae773a5d35"
|
||||
},
|
||||
{
|
||||
"amount": "15",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0x2c27ae0e62ab334b724c9db3bb396f2bd77339f95c40a8a225ae5384894d3349"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0x986a29849a0d1c408b01c2c70ec5a2e1a2aeb3f54069fac37430f94bee4147fa"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0xa8c3f59f63559f01f6260f3351e5f91be1c679ef0c43994797db4cdfd1ff946e"
|
||||
},
|
||||
{
|
||||
"amount": "15",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0x28f5216d95bb0ff69afbbeecd3920f94288cb767e3c90b92a4d93c1f2ea3e424"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0xdf3778608599b3309e33cbba17313263bcacb07d3159be0f1793e544559cc1cf"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0xa97f847bcefd46d5ff2485f8fe990b19f5c46594e862c82769303be5845575bd"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0xc5e3724ea798bc88eb4fab300c381bbedaa84c3bf8778639147041e1a62d28fe"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0x977e6fcbf640e3b330db19ae85515ef9d991f170a8ac8068309254f5ff0141b1"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0xc2e8f773c7c9b1014fec441fed237663163f144cebb409476cc6e7297290d602"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0xfa1c7ea4e8e5ecfeddf1b6ebb651cd54ea39cb486d1f4acc2b7e7ab792431db4"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0x5de72ac4f446d6ca03903247470c38f80f8871686cbeaeffe302e009c4d897ac"
|
||||
},
|
||||
{
|
||||
"amount": "15",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0x4a71f43fcf7c8d857620114c2badd2d18ba1da5766be5d4ff03f9fad7da122b0"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tx": "0x4100d9d8cf5661c18bd61d524179fc8df09b8d7c7687a689d6c6e6d40a6f9de0"
|
||||
},
|
||||
{
|
||||
"amount": "10",
|
||||
"user": "0xfb269c54dC4b43Fe98EdacE28Ce0a36A03B375D8",
|
||||
@@ -26088,6 +26221,90 @@
|
||||
"tranche_id": 11,
|
||||
"tx": "0x4b3961d8d870d4259603a8f6ee74c94a7bd525ed2dadc2de6e1a08813a51b9da"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0xeaa18356de12943a056aa6b91a8ade1aa10db8c89f23ef31e53282ae773a5d35"
|
||||
},
|
||||
{
|
||||
"amount": "15",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0x2c27ae0e62ab334b724c9db3bb396f2bd77339f95c40a8a225ae5384894d3349"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0x986a29849a0d1c408b01c2c70ec5a2e1a2aeb3f54069fac37430f94bee4147fa"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0xa8c3f59f63559f01f6260f3351e5f91be1c679ef0c43994797db4cdfd1ff946e"
|
||||
},
|
||||
{
|
||||
"amount": "15",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0x28f5216d95bb0ff69afbbeecd3920f94288cb767e3c90b92a4d93c1f2ea3e424"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0xdf3778608599b3309e33cbba17313263bcacb07d3159be0f1793e544559cc1cf"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0xa97f847bcefd46d5ff2485f8fe990b19f5c46594e862c82769303be5845575bd"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0xc5e3724ea798bc88eb4fab300c381bbedaa84c3bf8778639147041e1a62d28fe"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0x977e6fcbf640e3b330db19ae85515ef9d991f170a8ac8068309254f5ff0141b1"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0xc2e8f773c7c9b1014fec441fed237663163f144cebb409476cc6e7297290d602"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0xfa1c7ea4e8e5ecfeddf1b6ebb651cd54ea39cb486d1f4acc2b7e7ab792431db4"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0x5de72ac4f446d6ca03903247470c38f80f8871686cbeaeffe302e009c4d897ac"
|
||||
},
|
||||
{
|
||||
"amount": "15",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0x4a71f43fcf7c8d857620114c2badd2d18ba1da5766be5d4ff03f9fad7da122b0"
|
||||
},
|
||||
{
|
||||
"amount": "20",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
"tranche_id": 11,
|
||||
"tx": "0x4100d9d8cf5661c18bd61d524179fc8df09b8d7c7687a689d6c6e6d40a6f9de0"
|
||||
},
|
||||
{
|
||||
"amount": "15",
|
||||
"user": "0xaaaaFd67947Ef241D8C24C863893800083855Ed6",
|
||||
@@ -27177,9 +27394,9 @@
|
||||
"tx": "0x26f83e1b57a646b5266f07b00f13f47d3983978d96e921349b24a8b2df0fbc3d"
|
||||
}
|
||||
],
|
||||
"total_tokens": "3680",
|
||||
"total_tokens": "3945",
|
||||
"withdrawn_tokens": "3680",
|
||||
"remaining_tokens": "0"
|
||||
"remaining_tokens": "265"
|
||||
},
|
||||
{
|
||||
"address": "0x9E53F72210479BF46aE7ABF77c48B0d611b3c3dB",
|
||||
@@ -42718,7 +42935,7 @@
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "3732368.4671",
|
||||
"total_removed": "747515.181114080043393",
|
||||
"locked_amount": "136742.44156929554179493785",
|
||||
"locked_amount": "134708.03759234934331725506",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1998.95815",
|
||||
@@ -44122,7 +44339,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "15870102.715470999700000001",
|
||||
"total_removed": "890096.86511001003331852",
|
||||
"locked_amount": "5784567.50374168041959439240960384604676934",
|
||||
"locked_amount": "5777353.6378606511430622943118666710719114",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "16249.93",
|
||||
@@ -61084,8 +61301,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "472355.6199999996",
|
||||
"total_removed": "45798.0743154683416",
|
||||
"locked_amount": "21667.621519774832869363582597674",
|
||||
"total_removed": "46179.9572555963416",
|
||||
"locked_amount": "21345.2585804788058432314598274936",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "3000",
|
||||
@@ -67764,6 +67981,11 @@
|
||||
"user": "0xd2033db9c5370aC76ABD80823b5c5adC097E2FBF",
|
||||
"tx": "0x492598e81b545c857d7a1d5a10b291a595c4d76c85af5a282a96948e7702c5da"
|
||||
},
|
||||
{
|
||||
"amount": "381.882940128",
|
||||
"user": "0x78805Dd0a19ac89AF3CC334C79330e6Ad9cDaf0c",
|
||||
"tx": "0xa6658830025cac3d4376ed5ad5191623ee9d1572eb5eb95f26e529aa2e2c4ee9"
|
||||
},
|
||||
{
|
||||
"amount": "182.662252664",
|
||||
"user": "0xb1169C6daAc76bAcaf0D8f87641Fc38fbabe569F",
|
||||
@@ -89530,10 +89752,17 @@
|
||||
"tx": "0xb59405747c8088945a412703637a7b422f3639439ec2ee15e180c0a2a0d71ee4"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "381.882940128",
|
||||
"user": "0x78805Dd0a19ac89AF3CC334C79330e6Ad9cDaf0c",
|
||||
"tranche_id": 5,
|
||||
"tx": "0xa6658830025cac3d4376ed5ad5191623ee9d1572eb5eb95f26e529aa2e2c4ee9"
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "400"
|
||||
"withdrawn_tokens": "381.882940128",
|
||||
"remaining_tokens": "18.117059872"
|
||||
},
|
||||
{
|
||||
"address": "0xC17d05223BB7BDE1Aa98d5f4196e44eF02e059b3",
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||
import { MarketState, MarketStateMapping } from '@vegaprotocol/types';
|
||||
import type { DataSourceDefinition } from '@vegaprotocol/types';
|
||||
import {
|
||||
MarketState,
|
||||
MarketStateMapping,
|
||||
PropertyKeyType,
|
||||
} from '@vegaprotocol/types';
|
||||
import { addDays, subDays } from 'date-fns';
|
||||
import {
|
||||
chainIdQuery,
|
||||
@@ -20,6 +25,25 @@ import {
|
||||
} from '@vegaprotocol/utils';
|
||||
|
||||
describe('Closed markets', { tags: '@smoke' }, () => {
|
||||
const settlementDataProperty = 'settlement-data-property';
|
||||
const settlementDataPropertyKey = {
|
||||
__typename: 'PropertyKey' as const,
|
||||
name: settlementDataProperty,
|
||||
type: PropertyKeyType.TYPE_INTEGER,
|
||||
numberDecimalPlaces: 2,
|
||||
};
|
||||
const settlementDataSourceData: DataSourceDefinition = {
|
||||
sourceType: {
|
||||
sourceType: {
|
||||
filters: [
|
||||
{
|
||||
__typename: 'Filter',
|
||||
key: settlementDataPropertyKey,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
const rowSelector =
|
||||
'[data-testid="tab-closed-markets"] .ag-center-cols-container .ag-row';
|
||||
|
||||
@@ -37,11 +61,15 @@ describe('Closed markets', { tags: '@smoke' }, () => {
|
||||
tradableInstrument: {
|
||||
instrument: {
|
||||
product: {
|
||||
dataSourceSpecBinding: {
|
||||
settlementDataProperty,
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
id: 'market-1-trading-termination-oracle-id',
|
||||
},
|
||||
dataSourceSpecForSettlementData: {
|
||||
id: 'market-1-settlement-data-oracle-id',
|
||||
data: settlementDataSourceData,
|
||||
},
|
||||
settlementAsset,
|
||||
},
|
||||
@@ -63,6 +91,15 @@ describe('Closed markets', { tags: '@smoke' }, () => {
|
||||
`settlement-expiry-date:${addDays(new Date(), 4).toISOString()}`,
|
||||
],
|
||||
},
|
||||
product: {
|
||||
dataSourceSpecBinding: {
|
||||
settlementDataProperty,
|
||||
},
|
||||
dataSourceSpecForSettlementData: {
|
||||
id: 'market-1-settlement-data-oracle-id',
|
||||
data: settlementDataSourceData,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -81,6 +118,15 @@ describe('Closed markets', { tags: '@smoke' }, () => {
|
||||
`settlement-expiry-date:${subDays(new Date(), 2).toISOString()}`,
|
||||
],
|
||||
},
|
||||
product: {
|
||||
dataSourceSpecBinding: {
|
||||
settlementDataProperty,
|
||||
},
|
||||
dataSourceSpecForSettlementData: {
|
||||
id: 'market-1-settlement-data-oracle-id',
|
||||
data: settlementDataSourceData,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -301,7 +347,7 @@ describe('Closed markets', { tags: '@smoke' }, () => {
|
||||
addDecimalsFormatNumber(
|
||||
// @ts-ignore cannot deep un-partial
|
||||
specDataConnection.externalData.data.data[0].value,
|
||||
settledMarket.decimalPlaces
|
||||
settlementDataPropertyKey.numberDecimalPlaces
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
@@ -5,14 +5,15 @@ const nodeHealth = 'node-health';
|
||||
|
||||
describe('home', { tags: '@regression' }, () => {
|
||||
before(() => {
|
||||
cy.clearLocalStorage();
|
||||
cy.clearAllLocalStorage();
|
||||
cy.mockTradingPage();
|
||||
cy.mockSubscription();
|
||||
cy.visit('/');
|
||||
closeWelcomeDialog();
|
||||
});
|
||||
|
||||
describe('footer', () => {
|
||||
it('shows current block height', () => {
|
||||
it.skip('shows current block height', () => {
|
||||
closeWelcomeDialog();
|
||||
// 0006-NETW-004
|
||||
// 0006-NETW-005
|
||||
@@ -22,7 +23,7 @@ describe('home', { tags: '@regression' }, () => {
|
||||
|
||||
cy.intercept('POST', 'http://localhost:3008/graphql', (req) => {
|
||||
req.on('response', (res) => {
|
||||
res.setDelay(3000);
|
||||
res.setDelay(3001);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -53,7 +54,6 @@ describe('home', { tags: '@regression' }, () => {
|
||||
// 0006-NETW-014
|
||||
// 0006-NETW-015
|
||||
// 0006-NETW-016
|
||||
|
||||
cy.getByTestId(nodeHealth).click();
|
||||
cy.getByTestId(dialogContent).should('contain.text', 'Connected node');
|
||||
cy.getByTestId(dialogContent).should(
|
||||
@@ -78,7 +78,6 @@ describe('home', { tags: '@regression' }, () => {
|
||||
// 0006-NETW-018
|
||||
// 0006-NETW-019
|
||||
// 0006-NETW-020
|
||||
|
||||
cy.getByTestId(nodeHealth).click();
|
||||
cy.getByTestId('connect').should('be.disabled');
|
||||
cy.getByTestId('node-url-custom').click();
|
||||
|
||||
@@ -82,20 +82,12 @@ const generateProposal = (code: string): ProposalListFieldsFragment => ({
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -482,7 +482,7 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
|
||||
testOrderCancellation(order);
|
||||
});
|
||||
});
|
||||
it('must be able to cancel all orders on a market', () => {
|
||||
it('must be able to cancel all orders on all markets', () => {
|
||||
// 7003-MORD-009
|
||||
// 7003-MORD-010
|
||||
// 7003-MORD-011
|
||||
@@ -496,9 +496,7 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
|
||||
.should('have.text', 'Cancel all')
|
||||
.then(($btn) => {
|
||||
cy.wrap($btn).click({ force: true });
|
||||
const order: OrderCancellation = {
|
||||
marketId: 'market-0',
|
||||
};
|
||||
const order: OrderCancellation = {};
|
||||
testOrderCancellation(order);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { act, render, screen, within } from '@testing-library/react';
|
||||
import { Closed } from './closed';
|
||||
import { MarketStateMapping } from '@vegaprotocol/types';
|
||||
import { MarketStateMapping, PropertyKeyType } from '@vegaprotocol/types';
|
||||
import { PositionStatus } from '@vegaprotocol/types';
|
||||
import { MarketState } from '@vegaprotocol/types';
|
||||
import { subDays } from 'date-fns';
|
||||
@@ -55,6 +55,23 @@ describe('Closed', () => {
|
||||
product: {
|
||||
dataSourceSpecForSettlementData: {
|
||||
id: settlementDataId,
|
||||
data: {
|
||||
sourceType: {
|
||||
sourceType: {
|
||||
filters: [
|
||||
{
|
||||
__typename: 'Filter',
|
||||
key: {
|
||||
__typename: 'PropertyKey',
|
||||
name: settlementDataProperty,
|
||||
type: PropertyKeyType.TYPE_INTEGER,
|
||||
numberDecimalPlaces: 5,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecBinding: {
|
||||
settlementDataProperty,
|
||||
|
||||
@@ -13,7 +13,10 @@ import {
|
||||
getMarketExpiryDate,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { usePositionsQuery } from '@vegaprotocol/positions';
|
||||
import type { MarketMaybeWithData } from '@vegaprotocol/markets';
|
||||
import type {
|
||||
DataSourceFilterFragment,
|
||||
MarketMaybeWithData,
|
||||
} from '@vegaprotocol/markets';
|
||||
import {
|
||||
MarketTableActions,
|
||||
closedMarketsWithDataProvider,
|
||||
@@ -42,6 +45,7 @@ interface Row {
|
||||
markPrice: string | undefined;
|
||||
settlementDataOracleId: string;
|
||||
settlementDataSpecBinding: string;
|
||||
setlementDataSourceFilter: DataSourceFilterFragment | undefined;
|
||||
tradingTerminationOracleId: string;
|
||||
settlementAsset: SettlementAsset;
|
||||
realisedPNL: string | undefined;
|
||||
@@ -74,28 +78,40 @@ export const Closed = () => {
|
||||
}
|
||||
);
|
||||
|
||||
const instrument = market.tradableInstrument.instrument;
|
||||
|
||||
const spec =
|
||||
instrument.product.dataSourceSpecForSettlementData.data.sourceType
|
||||
.__typename === 'DataSourceDefinitionExternal'
|
||||
? instrument.product.dataSourceSpecForSettlementData.data.sourceType
|
||||
.sourceType
|
||||
: undefined;
|
||||
const filters = spec?.filters || [];
|
||||
|
||||
const settlementDataSpecBinding =
|
||||
instrument.product.dataSourceSpecBinding.settlementDataProperty;
|
||||
const filter = filters?.find((filter) => {
|
||||
return filter.key.name === settlementDataSpecBinding;
|
||||
});
|
||||
|
||||
const row: Row = {
|
||||
id: market.id,
|
||||
code: market.tradableInstrument.instrument.code,
|
||||
name: market.tradableInstrument.instrument.name,
|
||||
code: instrument.code,
|
||||
name: instrument.name,
|
||||
decimalPlaces: market.decimalPlaces,
|
||||
state: market.state,
|
||||
metadata: market.tradableInstrument.instrument.metadata.tags ?? [],
|
||||
metadata: instrument.metadata.tags ?? [],
|
||||
closeTimestamp: market.marketTimestamps.close,
|
||||
bestBidPrice: market.data?.bestBidPrice,
|
||||
bestOfferPrice: market.data?.bestOfferPrice,
|
||||
markPrice: market.data?.markPrice,
|
||||
settlementDataOracleId:
|
||||
market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForSettlementData.id,
|
||||
settlementDataSpecBinding:
|
||||
market.tradableInstrument.instrument.product.dataSourceSpecBinding
|
||||
.settlementDataProperty,
|
||||
instrument.product.dataSourceSpecForSettlementData.id,
|
||||
settlementDataSpecBinding,
|
||||
setlementDataSourceFilter: filter,
|
||||
tradingTerminationOracleId:
|
||||
market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForTradingTermination.id,
|
||||
settlementAsset:
|
||||
market.tradableInstrument.instrument.product.settlementAsset,
|
||||
instrument.product.dataSourceSpecForTradingTermination.id,
|
||||
settlementAsset: instrument.product.settlementAsset,
|
||||
realisedPNL: position?.node.realisedPNL,
|
||||
};
|
||||
|
||||
@@ -238,8 +254,8 @@ const ClosedMarketsDataGrid = ({ rowData }: { rowData: Row[] }) => {
|
||||
}: VegaICellRendererParams<Row, 'settlementDataOracleId'>) => (
|
||||
<SettlementPriceCell
|
||||
oracleSpecId={value}
|
||||
decimalPlaces={data?.decimalPlaces ?? 0}
|
||||
settlementDataSpecBinding={data?.settlementDataSpecBinding}
|
||||
filter={data?.setlementDataSourceFilter}
|
||||
/>
|
||||
),
|
||||
},
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import type { Property } from '@vegaprotocol/types';
|
||||
import { PropertyKeyType } from '@vegaprotocol/types';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import type { OracleSpecDataConnectionQuery } from '@vegaprotocol/markets';
|
||||
import { OracleSpecDataConnectionDocument } from '@vegaprotocol/markets';
|
||||
import type { SettlementPriceCellProps } from './settlement-price-cell';
|
||||
import { SettlementPriceCell } from './settlement-price-cell';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
|
||||
describe('SettlementPriceCell', () => {
|
||||
const settlementDataSpecBinding = 'settlement-data-spec-binding';
|
||||
|
||||
const createMock = (
|
||||
id: string,
|
||||
property: Property
|
||||
@@ -40,11 +44,19 @@ describe('SettlementPriceCell', () => {
|
||||
},
|
||||
};
|
||||
};
|
||||
const createProps = (): SettlementPriceCellProps => {
|
||||
const createProps = (
|
||||
filterKey = {
|
||||
name: settlementDataSpecBinding,
|
||||
type: PropertyKeyType.TYPE_INTEGER,
|
||||
numberDecimalPlaces: 2,
|
||||
}
|
||||
): SettlementPriceCellProps => {
|
||||
return {
|
||||
oracleSpecId: 'oracle-spec-id',
|
||||
decimalPlaces: 2,
|
||||
settlementDataSpecBinding: 'settlement-data-spec-binding',
|
||||
filter: {
|
||||
key: filterKey,
|
||||
},
|
||||
settlementDataSpecBinding,
|
||||
};
|
||||
};
|
||||
it('renders fetches and renders the settlment data value', async () => {
|
||||
@@ -65,14 +77,19 @@ describe('SettlementPriceCell', () => {
|
||||
|
||||
expect(screen.getByText('-')).toBeInTheDocument();
|
||||
const link = await screen.findByRole('link');
|
||||
expect(link).toHaveTextContent('12.34');
|
||||
expect(link).toHaveTextContent(
|
||||
addDecimalsFormatNumber(
|
||||
property.value,
|
||||
props.filter?.key.numberDecimalPlaces || 0
|
||||
)
|
||||
);
|
||||
expect(link).toHaveAttribute(
|
||||
'href',
|
||||
expect.stringContaining(`/oracles/${props.oracleSpecId}`)
|
||||
);
|
||||
});
|
||||
|
||||
it('renders "-" if no spec value is found', async () => {
|
||||
it('renders "Unknown" if no spec value is found', async () => {
|
||||
const props = createProps();
|
||||
const property = {
|
||||
__typename: 'Property' as const,
|
||||
@@ -90,7 +107,7 @@ describe('SettlementPriceCell', () => {
|
||||
|
||||
expect(screen.getByText('-')).toBeInTheDocument();
|
||||
const link = await screen.findByRole('link');
|
||||
expect(link).toHaveTextContent('-');
|
||||
expect(link).toHaveTextContent('Unknown');
|
||||
expect(link).toHaveAttribute(
|
||||
'href',
|
||||
expect.stringContaining(`/oracles/${props.oracleSpecId}`)
|
||||
@@ -110,4 +127,33 @@ describe('SettlementPriceCell', () => {
|
||||
expect(screen.getByText('-')).toBeInTheDocument();
|
||||
expect(screen.queryByRole('link')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('does not format value if property key type is not integer', async () => {
|
||||
const props = createProps({
|
||||
name: settlementDataSpecBinding,
|
||||
type: PropertyKeyType.TYPE_TIMESTAMP,
|
||||
numberDecimalPlaces: 2,
|
||||
});
|
||||
const property = {
|
||||
__typename: 'Property' as const,
|
||||
name: props.settlementDataSpecBinding as string,
|
||||
value: '1234',
|
||||
};
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
const mock = createMock(props.oracleSpecId!, property);
|
||||
|
||||
render(
|
||||
<MockedProvider mocks={[mock]}>
|
||||
<SettlementPriceCell {...props} />
|
||||
</MockedProvider>
|
||||
);
|
||||
|
||||
expect(screen.getByText('-')).toBeInTheDocument();
|
||||
const link = await screen.findByRole('link');
|
||||
expect(link).toHaveTextContent(property.value);
|
||||
expect(link).toHaveAttribute(
|
||||
'href',
|
||||
expect.stringContaining(`/oracles/${props.oracleSpecId}`)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
import { DApp, EXPLORER_ORACLE, useLinks } from '@vegaprotocol/environment';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type { DataSourceFilterFragment } from '@vegaprotocol/markets';
|
||||
import { useOracleSpecBindingData } from '@vegaprotocol/markets';
|
||||
import { PropertyKeyType } from '@vegaprotocol/types';
|
||||
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
|
||||
export interface SettlementPriceCellProps {
|
||||
oracleSpecId: string | undefined;
|
||||
decimalPlaces: number;
|
||||
settlementDataSpecBinding: string | undefined;
|
||||
filter: DataSourceFilterFragment | undefined;
|
||||
}
|
||||
|
||||
export const SettlementPriceCell = ({
|
||||
oracleSpecId,
|
||||
decimalPlaces,
|
||||
settlementDataSpecBinding,
|
||||
filter,
|
||||
}: SettlementPriceCellProps) => {
|
||||
const linkCreator = useLinks(DApp.Explorer);
|
||||
const { property, loading } = useOracleSpecBindingData(
|
||||
@@ -25,15 +27,32 @@ export const SettlementPriceCell = ({
|
||||
return <span>-</span>;
|
||||
}
|
||||
|
||||
const renderText = () => {
|
||||
if (!property || !filter) {
|
||||
return t('Unknown');
|
||||
}
|
||||
|
||||
if (
|
||||
filter.key.type === PropertyKeyType.TYPE_INTEGER &&
|
||||
filter.key.numberDecimalPlaces !== null &&
|
||||
filter.key.numberDecimalPlaces !== undefined
|
||||
) {
|
||||
return addDecimalsFormatNumber(
|
||||
property.value,
|
||||
filter.key.numberDecimalPlaces
|
||||
);
|
||||
}
|
||||
|
||||
return property.value;
|
||||
};
|
||||
|
||||
return (
|
||||
<Link
|
||||
href={linkCreator(EXPLORER_ORACLE.replace(':id', oracleSpecId))}
|
||||
className="underline font-mono"
|
||||
target="_blank"
|
||||
>
|
||||
{property
|
||||
? addDecimalsFormatNumber(property.value, decimalPlaces)
|
||||
: t('-')}
|
||||
{renderText()}
|
||||
</Link>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -115,7 +115,19 @@ export function createClient({
|
||||
)
|
||||
: httpLink;
|
||||
|
||||
const errorLink = onError(({ graphQLErrors, networkError }) => {
|
||||
const errorLink = onError(({ graphQLErrors, networkError, operation }) => {
|
||||
// if any of these queries error don't capture any errors, its
|
||||
// likely the user is connecting to a dodgy node, NodeGuard gets
|
||||
// called on startup, NodeCheck and NodeCheckTimeUpdate are called
|
||||
// by the NodeSwitcher component and the useNodeHealth hook
|
||||
if (
|
||||
['NodeGuard', 'NodeCheck', 'NodeCheckTimeUpdate'].includes(
|
||||
operation.operationName
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (graphQLErrors) {
|
||||
graphQLErrors.forEach((e) => {
|
||||
if (e.extensions && e.extensions['type'] !== NOT_FOUND) {
|
||||
|
||||
@@ -3,11 +3,13 @@ import { MockedProvider } from '@apollo/react-testing';
|
||||
import { act, render, screen, waitFor } from '@testing-library/react';
|
||||
import { RadioGroup } from '@vegaprotocol/ui-toolkit';
|
||||
import type {
|
||||
BlockTimeSubscription,
|
||||
StatisticsQuery,
|
||||
} from '../../utils/__generated__/Node';
|
||||
import { BlockTimeDocument } from '../../utils/__generated__/Node';
|
||||
import { StatisticsDocument } from '../../utils/__generated__/Node';
|
||||
NodeCheckTimeUpdateSubscription,
|
||||
NodeCheckQuery,
|
||||
} from '../../utils/__generated__/NodeCheck';
|
||||
import {
|
||||
NodeCheckDocument,
|
||||
NodeCheckTimeUpdateDocument,
|
||||
} from '../../utils/__generated__/NodeCheck';
|
||||
import type { RowDataProps } from './row-data';
|
||||
import { POLL_INTERVAL } from './row-data';
|
||||
import { BLOCK_THRESHOLD, RowData } from './row-data';
|
||||
@@ -19,9 +21,9 @@ jest.mock('@vegaprotocol/apollo-client', () => ({
|
||||
useHeaderStore: jest.fn().mockReturnValue({}),
|
||||
}));
|
||||
|
||||
const statsQueryMock: MockedResponse<StatisticsQuery> = {
|
||||
const statsQueryMock: MockedResponse<NodeCheckQuery> = {
|
||||
request: {
|
||||
query: StatisticsDocument,
|
||||
query: NodeCheckDocument,
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
@@ -34,9 +36,9 @@ const statsQueryMock: MockedResponse<StatisticsQuery> = {
|
||||
},
|
||||
};
|
||||
|
||||
const subMock: MockedResponse<BlockTimeSubscription> = {
|
||||
const subMock: MockedResponse<NodeCheckTimeUpdateSubscription> = {
|
||||
request: {
|
||||
query: BlockTimeDocument,
|
||||
query: NodeCheckTimeUpdateDocument,
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
@@ -71,8 +73,8 @@ const mockHeaders = (
|
||||
|
||||
const renderComponent = (
|
||||
props: RowDataProps,
|
||||
queryMock: MockedResponse<StatisticsQuery>,
|
||||
subMock: MockedResponse<BlockTimeSubscription>
|
||||
queryMock: MockedResponse<NodeCheckQuery>,
|
||||
subMock: MockedResponse<NodeCheckTimeUpdateSubscription>
|
||||
) => {
|
||||
return (
|
||||
<MockedProvider mocks={[queryMock, subMock, subMock, subMock]}>
|
||||
@@ -127,16 +129,16 @@ describe('RowData', () => {
|
||||
it('radio button still enabled if query fails', async () => {
|
||||
mockHeaders(props.url, {});
|
||||
|
||||
const failedQueryMock: MockedResponse<StatisticsQuery> = {
|
||||
const failedQueryMock: MockedResponse<NodeCheckQuery> = {
|
||||
request: {
|
||||
query: StatisticsDocument,
|
||||
query: NodeCheckDocument,
|
||||
},
|
||||
error: new Error('failed'),
|
||||
};
|
||||
|
||||
const failedSubMock: MockedResponse<BlockTimeSubscription> = {
|
||||
const failedSubMock: MockedResponse<NodeCheckTimeUpdateSubscription> = {
|
||||
request: {
|
||||
query: BlockTimeDocument,
|
||||
query: NodeCheckTimeUpdateDocument,
|
||||
},
|
||||
error: new Error('failed'),
|
||||
};
|
||||
@@ -244,10 +246,10 @@ describe('RowData', () => {
|
||||
jest.useFakeTimers();
|
||||
const createStatsQueryMock = (
|
||||
blockHeight: string
|
||||
): MockedResponse<StatisticsQuery> => {
|
||||
): MockedResponse<NodeCheckQuery> => {
|
||||
return {
|
||||
request: {
|
||||
query: StatisticsDocument,
|
||||
query: NodeCheckDocument,
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
@@ -261,10 +263,10 @@ describe('RowData', () => {
|
||||
};
|
||||
};
|
||||
|
||||
const createFailedStatsQueryMock = (): MockedResponse<StatisticsQuery> => {
|
||||
const createFailedStatsQueryMock = (): MockedResponse<NodeCheckQuery> => {
|
||||
return {
|
||||
request: {
|
||||
query: StatisticsDocument,
|
||||
query: NodeCheckDocument,
|
||||
},
|
||||
result: {
|
||||
data: undefined,
|
||||
|
||||
@@ -6,9 +6,9 @@ import { Radio } from '@vegaprotocol/ui-toolkit';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { CUSTOM_NODE_KEY } from '../../types';
|
||||
import {
|
||||
useBlockTimeSubscription,
|
||||
useStatisticsQuery,
|
||||
} from '../../utils/__generated__/Node';
|
||||
useNodeCheckQuery,
|
||||
useNodeCheckTimeUpdateSubscription,
|
||||
} from '../../utils/__generated__/NodeCheck';
|
||||
import { LayoutCell } from './layout-cell';
|
||||
|
||||
export const POLL_INTERVAL = 1000;
|
||||
@@ -30,13 +30,14 @@ export const RowData = ({
|
||||
const [subFailed, setSubFailed] = useState(false);
|
||||
const [time, setTime] = useState<number>();
|
||||
// no use of data here as we need the data nodes reference to block height
|
||||
const { data, error, loading, startPolling, stopPolling } =
|
||||
useStatisticsQuery({
|
||||
const { data, error, loading, startPolling, stopPolling } = useNodeCheckQuery(
|
||||
{
|
||||
pollInterval: POLL_INTERVAL,
|
||||
// fix for pollInterval
|
||||
// https://github.com/apollographql/apollo-client/issues/9819
|
||||
ssr: false,
|
||||
});
|
||||
}
|
||||
);
|
||||
const headerStore = useHeaderStore();
|
||||
const headers = headerStore[url];
|
||||
|
||||
@@ -44,7 +45,7 @@ export const RowData = ({
|
||||
data: subData,
|
||||
error: subError,
|
||||
loading: subLoading,
|
||||
} = useBlockTimeSubscription();
|
||||
} = useNodeCheckTimeUpdateSubscription();
|
||||
|
||||
useEffect(() => {
|
||||
const timeout = setTimeout(() => {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import {
|
||||
StatisticsDocument,
|
||||
BlockTimeDocument,
|
||||
} from '../../utils/__generated__/Node';
|
||||
NodeCheckDocument,
|
||||
NodeCheckTimeUpdateDocument,
|
||||
} from '../../utils/__generated__/NodeCheck';
|
||||
import type {
|
||||
StatisticsQuery,
|
||||
BlockTimeSubscription,
|
||||
} from '../../utils/__generated__/Node';
|
||||
NodeCheckQuery,
|
||||
NodeCheckTimeUpdateSubscription,
|
||||
} from '../../utils/__generated__/NodeCheck';
|
||||
import { Networks } from '../../types';
|
||||
import type { RequestHandlerResponse } from 'mock-apollo-client';
|
||||
import { createMockClient } from 'mock-apollo-client';
|
||||
@@ -21,7 +21,7 @@ type MockClientProps = {
|
||||
busEvents?: MockRequestConfig;
|
||||
};
|
||||
|
||||
export const getMockBusEventsResult = (): BlockTimeSubscription => ({
|
||||
export const getMockBusEventsResult = (): NodeCheckTimeUpdateSubscription => ({
|
||||
busEvents: [
|
||||
{
|
||||
__typename: 'BusEvent',
|
||||
@@ -32,19 +32,21 @@ export const getMockBusEventsResult = (): BlockTimeSubscription => ({
|
||||
|
||||
export const getMockStatisticsResult = (
|
||||
env: Networks = Networks.TESTNET
|
||||
): StatisticsQuery => ({
|
||||
): NodeCheckQuery => ({
|
||||
statistics: {
|
||||
__typename: 'Statistics',
|
||||
chainId: `${env.toLowerCase()}-0123`,
|
||||
blockHeight: '11',
|
||||
vegaTime: new Date().toISOString(),
|
||||
},
|
||||
});
|
||||
|
||||
export const getMockQueryResult = (env: Networks): StatisticsQuery => ({
|
||||
export const getMockQueryResult = (env: Networks): NodeCheckQuery => ({
|
||||
statistics: {
|
||||
__typename: 'Statistics',
|
||||
chainId: `${env.toLowerCase()}-0123`,
|
||||
blockHeight: '11',
|
||||
vegaTime: new Date().toISOString(),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -72,11 +74,11 @@ export default function ({
|
||||
const mockClient = createMockClient();
|
||||
|
||||
mockClient.setRequestHandler(
|
||||
StatisticsDocument,
|
||||
NodeCheckDocument,
|
||||
getHandler(statistics, getMockStatisticsResult(network))
|
||||
);
|
||||
mockClient.setRequestHandler(
|
||||
BlockTimeDocument,
|
||||
NodeCheckTimeUpdateDocument,
|
||||
getHandler(busEvents, getMockBusEventsResult())
|
||||
);
|
||||
|
||||
|
||||
@@ -5,11 +5,13 @@ import { useEffect } from 'react';
|
||||
import { create } from 'zustand';
|
||||
import { createClient } from '@vegaprotocol/apollo-client';
|
||||
import type {
|
||||
BlockTimeSubscription,
|
||||
StatisticsQuery,
|
||||
} from '../utils/__generated__/Node';
|
||||
import { BlockTimeDocument } from '../utils/__generated__/Node';
|
||||
import { StatisticsDocument } from '../utils/__generated__/Node';
|
||||
NodeCheckTimeUpdateSubscription,
|
||||
NodeCheckQuery,
|
||||
} from '../utils/__generated__/NodeCheck';
|
||||
import {
|
||||
NodeCheckDocument,
|
||||
NodeCheckTimeUpdateDocument,
|
||||
} from '../utils/__generated__/NodeCheck';
|
||||
import type { Environment } from '../types';
|
||||
import { Networks } from '../types';
|
||||
import { compileErrors } from '../utils/compile-errors';
|
||||
@@ -220,8 +222,8 @@ const testNode = async (
|
||||
*/
|
||||
const testQuery = async (client: Client) => {
|
||||
try {
|
||||
const result = await client.query<StatisticsQuery>({
|
||||
query: StatisticsDocument,
|
||||
const result = await client.query<NodeCheckQuery>({
|
||||
query: NodeCheckDocument,
|
||||
});
|
||||
if (!result || result.error) {
|
||||
return false;
|
||||
@@ -240,8 +242,8 @@ const testQuery = async (client: Client) => {
|
||||
const testSubscription = (client: Client) => {
|
||||
return new Promise((resolve) => {
|
||||
const sub = client
|
||||
.subscribe<BlockTimeSubscription>({
|
||||
query: BlockTimeDocument,
|
||||
.subscribe<NodeCheckTimeUpdateSubscription>({
|
||||
query: NodeCheckTimeUpdateDocument,
|
||||
errorPolicy: 'all',
|
||||
})
|
||||
.subscribe({
|
||||
|
||||
@@ -2,8 +2,8 @@ import { renderHook, waitFor } from '@testing-library/react';
|
||||
import { useNodeHealth } from './use-node-health';
|
||||
import type { MockedResponse } from '@apollo/react-testing';
|
||||
import { MockedProvider } from '@apollo/react-testing';
|
||||
import type { StatisticsQuery } from '../utils/__generated__/Node';
|
||||
import { StatisticsDocument } from '../utils/__generated__/Node';
|
||||
import type { NodeCheckQuery } from '../utils/__generated__/NodeCheck';
|
||||
import { NodeCheckDocument } from '../utils/__generated__/NodeCheck';
|
||||
import { useHeaderStore } from '@vegaprotocol/apollo-client';
|
||||
import { Intent } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
@@ -16,10 +16,10 @@ jest.mock('@vegaprotocol/apollo-client');
|
||||
|
||||
const createStatsMock = (
|
||||
blockHeight: number
|
||||
): MockedResponse<StatisticsQuery> => {
|
||||
): MockedResponse<NodeCheckQuery> => {
|
||||
return {
|
||||
request: {
|
||||
query: StatisticsDocument,
|
||||
query: NodeCheckDocument,
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
@@ -34,7 +34,7 @@ const createStatsMock = (
|
||||
};
|
||||
|
||||
function setup(
|
||||
mock: MockedResponse<StatisticsQuery>,
|
||||
mock: MockedResponse<NodeCheckQuery>,
|
||||
headers:
|
||||
| {
|
||||
blockHeight: number;
|
||||
@@ -93,9 +93,9 @@ describe('useNodeHealth', () => {
|
||||
);
|
||||
|
||||
it('block diff is null if query fails indicating non operational', async () => {
|
||||
const failedQuery: MockedResponse<StatisticsQuery> = {
|
||||
const failedQuery: MockedResponse<NodeCheckQuery> = {
|
||||
request: {
|
||||
query: StatisticsDocument,
|
||||
query: NodeCheckDocument,
|
||||
},
|
||||
result: {
|
||||
// @ts-ignore failed query with no result
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEffect, useMemo } from 'react';
|
||||
import { useStatisticsQuery } from '../utils/__generated__/Node';
|
||||
import { useNodeCheckQuery } from '../utils/__generated__/NodeCheck';
|
||||
import { useHeaderStore } from '@vegaprotocol/apollo-client';
|
||||
import { useEnvironment } from './use-environment';
|
||||
import { useNavigatorOnline } from '@vegaprotocol/react-helpers';
|
||||
@@ -16,7 +16,7 @@ export const useNodeHealth = () => {
|
||||
const url = useEnvironment((store) => store.VEGA_URL);
|
||||
const headerStore = useHeaderStore();
|
||||
const headers = url ? headerStore[url] : undefined;
|
||||
const { data, error, startPolling, stopPolling } = useStatisticsQuery({
|
||||
const { data, error, startPolling, stopPolling } = useNodeCheckQuery({
|
||||
fetchPolicy: 'no-cache',
|
||||
});
|
||||
|
||||
|
||||
@@ -8,4 +8,4 @@ export * from './hooks';
|
||||
export * from './types';
|
||||
|
||||
// Utils
|
||||
export * from './utils/__generated__/Node';
|
||||
export * from './utils/__generated__/NodeCheck';
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
query Statistics {
|
||||
query NodeCheck {
|
||||
statistics {
|
||||
chainId
|
||||
blockHeight
|
||||
@@ -6,7 +6,7 @@ query Statistics {
|
||||
}
|
||||
}
|
||||
|
||||
subscription BlockTime {
|
||||
subscription NodeCheckTimeUpdate {
|
||||
busEvents(types: TimeUpdate, batchSize: 1) {
|
||||
id
|
||||
}
|
||||
-81
@@ -1,81 +0,0 @@
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type StatisticsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type StatisticsQuery = { __typename?: 'Query', statistics: { __typename?: 'Statistics', chainId: string, blockHeight: string, vegaTime: any } };
|
||||
|
||||
export type BlockTimeSubscriptionVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type BlockTimeSubscription = { __typename?: 'Subscription', busEvents?: Array<{ __typename?: 'BusEvent', id: string }> | null };
|
||||
|
||||
|
||||
export const StatisticsDocument = gql`
|
||||
query Statistics {
|
||||
statistics {
|
||||
chainId
|
||||
blockHeight
|
||||
vegaTime
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useStatisticsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useStatisticsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useStatisticsQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useStatisticsQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useStatisticsQuery(baseOptions?: Apollo.QueryHookOptions<StatisticsQuery, StatisticsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<StatisticsQuery, StatisticsQueryVariables>(StatisticsDocument, options);
|
||||
}
|
||||
export function useStatisticsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<StatisticsQuery, StatisticsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<StatisticsQuery, StatisticsQueryVariables>(StatisticsDocument, options);
|
||||
}
|
||||
export type StatisticsQueryHookResult = ReturnType<typeof useStatisticsQuery>;
|
||||
export type StatisticsLazyQueryHookResult = ReturnType<typeof useStatisticsLazyQuery>;
|
||||
export type StatisticsQueryResult = Apollo.QueryResult<StatisticsQuery, StatisticsQueryVariables>;
|
||||
export const BlockTimeDocument = gql`
|
||||
subscription BlockTime {
|
||||
busEvents(types: TimeUpdate, batchSize: 1) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useBlockTimeSubscription__
|
||||
*
|
||||
* To run a query within a React component, call `useBlockTimeSubscription` and pass it any options that fit your needs.
|
||||
* When your component renders, `useBlockTimeSubscription` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the subscription, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useBlockTimeSubscription({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useBlockTimeSubscription(baseOptions?: Apollo.SubscriptionHookOptions<BlockTimeSubscription, BlockTimeSubscriptionVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useSubscription<BlockTimeSubscription, BlockTimeSubscriptionVariables>(BlockTimeDocument, options);
|
||||
}
|
||||
export type BlockTimeSubscriptionHookResult = ReturnType<typeof useBlockTimeSubscription>;
|
||||
export type BlockTimeSubscriptionResult = Apollo.SubscriptionResult<BlockTimeSubscription>;
|
||||
@@ -0,0 +1,81 @@
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type NodeCheckQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type NodeCheckQuery = { __typename?: 'Query', statistics: { __typename?: 'Statistics', chainId: string, blockHeight: string, vegaTime: any } };
|
||||
|
||||
export type NodeCheckTimeUpdateSubscriptionVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type NodeCheckTimeUpdateSubscription = { __typename?: 'Subscription', busEvents?: Array<{ __typename?: 'BusEvent', id: string }> | null };
|
||||
|
||||
|
||||
export const NodeCheckDocument = gql`
|
||||
query NodeCheck {
|
||||
statistics {
|
||||
chainId
|
||||
blockHeight
|
||||
vegaTime
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useNodeCheckQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useNodeCheckQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useNodeCheckQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useNodeCheckQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useNodeCheckQuery(baseOptions?: Apollo.QueryHookOptions<NodeCheckQuery, NodeCheckQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<NodeCheckQuery, NodeCheckQueryVariables>(NodeCheckDocument, options);
|
||||
}
|
||||
export function useNodeCheckLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<NodeCheckQuery, NodeCheckQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<NodeCheckQuery, NodeCheckQueryVariables>(NodeCheckDocument, options);
|
||||
}
|
||||
export type NodeCheckQueryHookResult = ReturnType<typeof useNodeCheckQuery>;
|
||||
export type NodeCheckLazyQueryHookResult = ReturnType<typeof useNodeCheckLazyQuery>;
|
||||
export type NodeCheckQueryResult = Apollo.QueryResult<NodeCheckQuery, NodeCheckQueryVariables>;
|
||||
export const NodeCheckTimeUpdateDocument = gql`
|
||||
subscription NodeCheckTimeUpdate {
|
||||
busEvents(types: TimeUpdate, batchSize: 1) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useNodeCheckTimeUpdateSubscription__
|
||||
*
|
||||
* To run a query within a React component, call `useNodeCheckTimeUpdateSubscription` and pass it any options that fit your needs.
|
||||
* When your component renders, `useNodeCheckTimeUpdateSubscription` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the subscription, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useNodeCheckTimeUpdateSubscription({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useNodeCheckTimeUpdateSubscription(baseOptions?: Apollo.SubscriptionHookOptions<NodeCheckTimeUpdateSubscription, NodeCheckTimeUpdateSubscriptionVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useSubscription<NodeCheckTimeUpdateSubscription, NodeCheckTimeUpdateSubscriptionVariables>(NodeCheckTimeUpdateDocument, options);
|
||||
}
|
||||
export type NodeCheckTimeUpdateSubscriptionHookResult = ReturnType<typeof useNodeCheckTimeUpdateSubscription>;
|
||||
export type NodeCheckTimeUpdateSubscriptionResult = Apollo.SubscriptionResult<NodeCheckTimeUpdateSubscription>;
|
||||
@@ -1,11 +1,11 @@
|
||||
import type { StatisticsQuery } from './__generated__/Node';
|
||||
import type { NodeCheckQuery } from './__generated__/NodeCheck';
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const statisticsQuery = (
|
||||
override?: PartialDeep<StatisticsQuery>
|
||||
): StatisticsQuery => {
|
||||
const defaultResult: StatisticsQuery = {
|
||||
override?: PartialDeep<NodeCheckQuery>
|
||||
): NodeCheckQuery => {
|
||||
const defaultResult: NodeCheckQuery = {
|
||||
statistics: {
|
||||
__typename: 'Statistics',
|
||||
chainId: 'chain-id',
|
||||
|
||||
@@ -31,27 +31,6 @@ fragment OracleMarketSpecFields on Market {
|
||||
}
|
||||
}
|
||||
|
||||
fragment DataSourceSpec on DataSourceDefinition {
|
||||
sourceType {
|
||||
... on DataSourceDefinitionExternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfiguration {
|
||||
signers {
|
||||
signer {
|
||||
... on PubKey {
|
||||
key
|
||||
}
|
||||
... on ETHAddress {
|
||||
address
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query OracleMarketsSpec {
|
||||
marketsConnection {
|
||||
edges {
|
||||
|
||||
+3
-26
@@ -1,39 +1,16 @@
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import { DataSourceSpecFragmentDoc } from './markets';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type OracleMarketSpecFieldsFragment = { __typename?: 'Market', id: string, state: Types.MarketState, tradingMode: Types.MarketTradingMode, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } } };
|
||||
|
||||
export type DataSourceSpecFragment = { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } };
|
||||
export type OracleMarketSpecFieldsFragment = { __typename?: 'Market', id: string, state: Types.MarketState, tradingMode: Types.MarketTradingMode, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } } };
|
||||
|
||||
export type OracleMarketsSpecQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type OracleMarketsSpecQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, state: Types.MarketState, tradingMode: Types.MarketTradingMode, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } } } }> } | null };
|
||||
export type OracleMarketsSpecQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, state: Types.MarketState, tradingMode: Types.MarketTradingMode, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } } } }> } | null };
|
||||
|
||||
export const DataSourceSpecFragmentDoc = gql`
|
||||
fragment DataSourceSpec on DataSourceDefinition {
|
||||
sourceType {
|
||||
... on DataSourceDefinitionExternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfiguration {
|
||||
signers {
|
||||
signer {
|
||||
... on PubKey {
|
||||
key
|
||||
}
|
||||
... on ETHAddress {
|
||||
address
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const OracleMarketSpecFieldsFragmentDoc = gql`
|
||||
fragment OracleMarketSpecFields on Market {
|
||||
id
|
||||
|
||||
+40
-3
@@ -1,16 +1,53 @@
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import { DataSourceSpecFragmentDoc } from './OracleMarketsSpec';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type MarketFieldsFragment = { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } };
|
||||
export type DataSourceFilterFragment = { __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } };
|
||||
|
||||
export type DataSourceSpecFragment = { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } };
|
||||
|
||||
export type MarketFieldsFragment = { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } };
|
||||
|
||||
export type MarketsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type MarketsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } } }> } | null };
|
||||
export type MarketsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType, numberDecimalPlaces?: number | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } } }, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any } } }> } | null };
|
||||
|
||||
export const DataSourceFilterFragmentDoc = gql`
|
||||
fragment DataSourceFilter on Filter {
|
||||
key {
|
||||
name
|
||||
type
|
||||
numberDecimalPlaces
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const DataSourceSpecFragmentDoc = gql`
|
||||
fragment DataSourceSpec on DataSourceDefinition {
|
||||
sourceType {
|
||||
... on DataSourceDefinitionExternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfiguration {
|
||||
signers {
|
||||
signer {
|
||||
... on PubKey {
|
||||
key
|
||||
}
|
||||
... on ETHAddress {
|
||||
address
|
||||
}
|
||||
}
|
||||
}
|
||||
filters {
|
||||
...DataSourceFilter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${DataSourceFilterFragmentDoc}`;
|
||||
export const MarketFieldsFragmentDoc = gql`
|
||||
fragment MarketFields on Market {
|
||||
id
|
||||
|
||||
@@ -16,16 +16,6 @@ fragment DataSource on DataSourceDefinition {
|
||||
}
|
||||
}
|
||||
}
|
||||
... on DataSourceDefinitionInternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfigurationTime {
|
||||
conditions {
|
||||
operator
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,14 +3,14 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type DataSourceFragment = { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } } };
|
||||
export type DataSourceFragment = { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } };
|
||||
|
||||
export type MarketInfoQueryVariables = Types.Exact<{
|
||||
marketId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type MarketInfoQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, lpPriceRange: string, proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string } } } | null> | null } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, riskFactors?: { __typename?: 'RiskFactor', market: string, short: string, long: string } | null, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } } } }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', operator: Types.ConditionOperator, value?: string | null } | null> } } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } }, riskModel: { __typename?: 'LogNormalRiskModel', tau: number, riskAversionParameter: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } }, marginCalculator?: { __typename?: 'MarginCalculator', scalingFactors: { __typename?: 'ScalingFactors', searchLevel: number, initialMargin: number, collateralRelease: number } } | null } } | null };
|
||||
export type MarketInfoQuery = { __typename?: 'Query', market?: { __typename?: 'Market', id: string, decimalPlaces: number, positionDecimalPlaces: number, state: Types.MarketState, tradingMode: Types.MarketTradingMode, lpPriceRange: string, proposal?: { __typename?: 'Proposal', id?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string } } | null, marketTimestamps: { __typename?: 'MarketTimestamps', open: any, close: any }, openingAuction: { __typename?: 'AuctionDuration', durationSecs: number, volume: number }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string } } } | null> | null } | null, fees: { __typename?: 'Fees', factors: { __typename?: 'FeeFactors', makerFee: string, infrastructureFee: string, liquidityFee: string } }, priceMonitoringSettings: { __typename?: 'PriceMonitoringSettings', parameters?: { __typename?: 'PriceMonitoringParameters', triggers?: Array<{ __typename?: 'PriceMonitoringTrigger', horizonSecs: number, probability: number, auctionExtensionSecs: number }> | null } | null }, riskFactors?: { __typename?: 'RiskFactor', market: string, short: string, long: string } | null, liquidityMonitoringParameters: { __typename?: 'LiquidityMonitoringParameters', triggeringRatio: string, targetStakeParameters: { __typename?: 'TargetStakeParameters', timeWindow: number, scalingFactor: number } }, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', id: string, name: string, code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename?: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number }, dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } } | { __typename?: 'DataSourceDefinitionInternal' } } }, dataSourceSpecBinding: { __typename?: 'DataSourceSpecToFutureBinding', settlementDataProperty: string, tradingTerminationProperty: string } } }, riskModel: { __typename?: 'LogNormalRiskModel', tau: number, riskAversionParameter: number, params: { __typename?: 'LogNormalModelParams', r: number, sigma: number, mu: number } } | { __typename?: 'SimpleRiskModel', params: { __typename?: 'SimpleRiskModelParams', factorLong: number, factorShort: number } }, marginCalculator?: { __typename?: 'MarginCalculator', scalingFactors: { __typename?: 'ScalingFactors', searchLevel: number, initialMargin: number, collateralRelease: number } } | null } } | null };
|
||||
|
||||
export const DataSourceFragmentDoc = gql`
|
||||
fragment DataSource on DataSourceDefinition {
|
||||
@@ -31,16 +31,6 @@ export const DataSourceFragmentDoc = gql`
|
||||
}
|
||||
}
|
||||
}
|
||||
... on DataSourceDefinitionInternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfigurationTime {
|
||||
conditions {
|
||||
operator
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -105,12 +105,10 @@ export const MarketInfoAccordion = ({
|
||||
content: <InsurancePoolInfoPanel market={market} account={a} />,
|
||||
})),
|
||||
];
|
||||
const settlementData =
|
||||
market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData
|
||||
.data;
|
||||
const terminationData =
|
||||
market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForTradingTermination.data;
|
||||
const settlementData = market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForSettlementData.data as DataSourceDefinition;
|
||||
const terminationData = market.tradableInstrument.instrument.product
|
||||
.dataSourceSpecForTradingTermination.data as DataSourceDefinition;
|
||||
|
||||
const getSigners = (data: DataSourceDefinition) => {
|
||||
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
|
||||
|
||||
@@ -462,15 +462,17 @@ export const OracleInfoPanel = ({
|
||||
? product.dataSourceSpecForSettlementData.id
|
||||
: product.dataSourceSpecForTradingTermination.id;
|
||||
|
||||
const dataSourceSpec = (
|
||||
type === 'settlementData'
|
||||
? product.dataSourceSpecForSettlementData.data
|
||||
: product.dataSourceSpecForTradingTermination.data
|
||||
) as DataSourceDefinition;
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<DataSourceProof
|
||||
data-testid="oracle-proof-links"
|
||||
data={
|
||||
type === 'settlementData'
|
||||
? product.dataSourceSpecForSettlementData.data
|
||||
: product.dataSourceSpecForTradingTermination.data
|
||||
}
|
||||
data={dataSourceSpec}
|
||||
providers={data}
|
||||
type={type}
|
||||
dataSourceSpecId={dataSourceSpecId}
|
||||
@@ -527,19 +529,27 @@ export const DataSourceProof = ({
|
||||
}
|
||||
|
||||
if (data.sourceType.__typename === 'DataSourceDefinitionInternal') {
|
||||
return (
|
||||
<div>
|
||||
<h3>{t('Internal conditions')}</h3>
|
||||
{data.sourceType.sourceType.conditions.map((condition, i) => {
|
||||
if (!condition) return null;
|
||||
return (
|
||||
<p key={i}>
|
||||
{ConditionOperatorMapping[condition.operator]} {condition.value}
|
||||
</p>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
if (data.sourceType.sourceType) {
|
||||
return (
|
||||
<div>
|
||||
<h3>{t('Internal conditions')}</h3>
|
||||
{data.sourceType.sourceType?.conditions.map((condition, i) => {
|
||||
if (!condition) return null;
|
||||
return (
|
||||
<p key={i}>
|
||||
{ConditionOperatorMapping[condition.operator]} {condition.value}
|
||||
</p>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
{t('No oracle spec for trading termination. Internal timestamp used')}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return <div>{t('Invalid data source')}</div>;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { useMarket } from '../markets-provider';
|
||||
|
||||
import { useMemo } from 'react';
|
||||
import type { Provider } from '../oracle-schema';
|
||||
import type { DataSourceSpecFragment } from '../__generated__/OracleMarketsSpec';
|
||||
import type { DataSourceSpecFragment } from '../__generated__';
|
||||
|
||||
export const getMatchingOracleProvider = (
|
||||
dataSourceSpec: DataSourceSpecFragment,
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
fragment DataSourceFilter on Filter {
|
||||
key {
|
||||
name
|
||||
type
|
||||
numberDecimalPlaces
|
||||
}
|
||||
}
|
||||
|
||||
fragment DataSourceSpec on DataSourceDefinition {
|
||||
sourceType {
|
||||
... on DataSourceDefinitionExternal {
|
||||
@@ -13,6 +21,9 @@ fragment DataSourceSpec on DataSourceDefinition {
|
||||
}
|
||||
}
|
||||
}
|
||||
filters {
|
||||
...DataSourceFilter
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,6 +80,17 @@ export const createMarketFragment = (
|
||||
},
|
||||
},
|
||||
],
|
||||
filters: [
|
||||
{
|
||||
__typename: 'Filter',
|
||||
key: {
|
||||
__typename: 'PropertyKey',
|
||||
name: 'settlement-data-property',
|
||||
type: Schema.PropertyKeyType.TYPE_TIMESTAMP,
|
||||
numberDecimalPlaces: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -102,6 +113,17 @@ export const createMarketFragment = (
|
||||
},
|
||||
},
|
||||
],
|
||||
filters: [
|
||||
{
|
||||
__typename: 'Filter',
|
||||
key: {
|
||||
__typename: 'PropertyKey',
|
||||
name: 'settlement-data-property',
|
||||
type: Schema.PropertyKeyType.TYPE_INTEGER,
|
||||
numberDecimalPlaces: 2,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -133,11 +133,9 @@ export const OrderListManager = ({
|
||||
|
||||
const cancelAll = useCallback(() => {
|
||||
create({
|
||||
orderCancellation: {
|
||||
marketId,
|
||||
},
|
||||
orderCancellation: {},
|
||||
});
|
||||
}, [create, marketId]);
|
||||
}, [create]);
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -226,8 +226,8 @@ describe('OrderListTable', () => {
|
||||
const amendCell = getAmendCell();
|
||||
const typeCell = screen.getAllByRole('gridcell')[2];
|
||||
expect(typeCell).toHaveTextContent('Mid - 10.0 Peg limit');
|
||||
expect(amendCell.queryByTestId('edit')).not.toBeInTheDocument();
|
||||
expect(amendCell.queryByTestId('cancel')).not.toBeInTheDocument();
|
||||
expect(amendCell.queryByTestId('edit')).toBeInTheDocument();
|
||||
expect(amendCell.queryByTestId('cancel')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.each([
|
||||
|
||||
@@ -329,7 +329,7 @@ export const isOrderActive = (status: Schema.OrderStatus) => {
|
||||
};
|
||||
|
||||
export const isOrderAmendable = (order: Order | undefined) => {
|
||||
if (!order || order.peggedOrder || order.liquidityProvision) {
|
||||
if (!order || order.liquidityProvision) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ export const useColumnDefs = () => {
|
||||
colId: 'market',
|
||||
headerName: t('Market'),
|
||||
field: 'terms.change.instrument.code',
|
||||
width: 150,
|
||||
minWidth: 150,
|
||||
cellStyle: { lineHeight: '14px' },
|
||||
cellRenderer: ({
|
||||
data,
|
||||
|
||||
@@ -13,16 +13,6 @@ fragment NewMarketFields on NewMarket {
|
||||
quoteName
|
||||
dataSourceSpecForSettlementData {
|
||||
sourceType {
|
||||
... on DataSourceDefinitionInternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfigurationTime {
|
||||
conditions {
|
||||
operator
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on DataSourceDefinitionExternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfiguration {
|
||||
@@ -53,16 +43,6 @@ fragment NewMarketFields on NewMarket {
|
||||
}
|
||||
dataSourceSpecForTradingTermination {
|
||||
sourceType {
|
||||
... on DataSourceDefinitionInternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfigurationTime {
|
||||
conditions {
|
||||
operator
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on DataSourceDefinitionExternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfiguration {
|
||||
@@ -145,16 +125,6 @@ fragment UpdateMarketFields on UpdateMarket {
|
||||
quoteName
|
||||
dataSourceSpecForSettlementData {
|
||||
sourceType {
|
||||
... on DataSourceDefinitionInternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfigurationTime {
|
||||
conditions {
|
||||
operator
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on DataSourceDefinitionExternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfiguration {
|
||||
@@ -185,16 +155,6 @@ fragment UpdateMarketFields on UpdateMarket {
|
||||
}
|
||||
dataSourceSpecForTradingTermination {
|
||||
sourceType {
|
||||
... on DataSourceDefinitionInternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfigurationTime {
|
||||
conditions {
|
||||
operator
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on DataSourceDefinitionExternal {
|
||||
sourceType {
|
||||
... on DataSourceSpecConfiguration {
|
||||
|
||||
+4
-44
File diff suppressed because one or more lines are too long
@@ -76,20 +76,12 @@ export const marketUpdateProposal: ProposalListFieldsFragment = {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -185,20 +177,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename: 'FutureProduct',
|
||||
@@ -283,20 +267,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename: 'FutureProduct',
|
||||
@@ -381,20 +357,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename: 'FutureProduct',
|
||||
@@ -479,20 +447,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename: 'FutureProduct',
|
||||
@@ -577,20 +537,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename: 'FutureProduct',
|
||||
@@ -675,20 +627,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename: 'FutureProduct',
|
||||
@@ -773,20 +717,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename: 'FutureProduct',
|
||||
@@ -871,20 +807,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename: 'FutureProduct',
|
||||
@@ -969,20 +897,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename: 'FutureProduct',
|
||||
@@ -1067,20 +987,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename: 'FutureProduct',
|
||||
@@ -1165,20 +1077,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename: 'FutureProduct',
|
||||
@@ -1263,20 +1167,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename: 'FutureProduct',
|
||||
@@ -1361,20 +1257,12 @@ const proposalListFields: ProposalListFieldsFragment[] = [
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
__typename: 'DataSourceDefinition',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename: 'FutureProduct',
|
||||
|
||||
@@ -133,19 +133,11 @@ const generateUpdateMarketProposal = (
|
||||
dataSourceSpecForSettlementData: {
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
dataSourceSpecForTradingTermination: {
|
||||
sourceType: {
|
||||
__typename: 'DataSourceDefinitionInternal',
|
||||
sourceType: {
|
||||
__typename: 'DataSourceSpecConfigurationTime',
|
||||
conditions: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
__typename:
|
||||
|
||||
Reference in New Issue
Block a user