Compare commits

..

2 Commits

Author SHA1 Message Date
Dariusz Majcherczyk
6bcae926f5
Merge branch 'develop' into fix/proposal-error-in-key-details 2024-03-08 20:52:16 +01:00
Matthew Russell
6344074574
fix: handle batch proposals in key details of info sidebar 2024-03-06 16:24:11 +00:00
15 changed files with 108 additions and 170 deletions

View File

@ -4,5 +4,6 @@ tmp/*
.dockerignore
dockerfiles
node_modules
.git
.github
.vscode

View File

@ -38,7 +38,6 @@ import { differenceInHours, format, formatDistanceToNowStrict } from 'date-fns';
import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats';
import { MarketName } from '../proposal/market-name';
import { Indicator } from '../proposal/indicator';
import { type ProposalNode } from '../proposal/proposal-utils';
const ProposalTypeTags = ({
proposal,
@ -541,12 +540,10 @@ const BatchProposalStateText = ({
export const ProposalHeader = ({
proposal,
restData,
isListItem = true,
voteState,
}: {
proposal: Proposal | BatchProposal;
restData?: ProposalNode | null;
isListItem?: boolean;
voteState?: VoteState | null;
}) => {
@ -598,7 +595,7 @@ export const ProposalHeader = ({
)}
</div>
<ProposalDetails proposal={proposal} />
<VoteBreakdown proposal={proposal} restData={restData} />
<VoteBreakdown proposal={proposal} />
</>
);
};

View File

@ -91,28 +91,6 @@ export type ProposalNode = {
proposal: ProposalData;
proposalType: ProposalNodeType;
proposals: SubProposalData[];
yes?: [
{
partyId: string;
elsPerMarket?: [
{
marketId: string;
els: string;
}
];
}
];
no?: [
{
partyId: string;
elsPerMarket?: [
{
marketId: string;
els: string;
}
];
}
];
};
type SingleProposalNode = ProposalNode & {

View File

@ -48,7 +48,6 @@ export const Proposal = ({ proposal, restData }: ProposalProps) => {
<ProposalHeader
proposal={proposal}
restData={restData}
isListItem={false}
voteState={voteState}
/>

View File

@ -17,7 +17,6 @@ import {
import { useBatchVoteInformation } from '../../hooks/use-vote-information';
import { MarketName } from '../proposal/market-name';
import { Indicator } from '../proposal/indicator';
import { type ProposalNode } from '../proposal/proposal-utils';
export const CompactVotes = ({ number }: { number: BigNumber }) => (
<CompactNumber
@ -111,64 +110,24 @@ const Status = ({ reached, threshold, text, testId }: StatusProps) => {
export const VoteBreakdown = ({
proposal,
restData,
}: {
proposal: Proposal | BatchProposal;
restData?: ProposalNode | null;
}) => {
if (proposal.__typename === 'Proposal') {
return <VoteBreakdownNormal proposal={proposal} />;
}
if (proposal.__typename === 'BatchProposal') {
return <VoteBreakdownBatch proposal={proposal} restData={restData} />;
return <VoteBreakdownBatch proposal={proposal} />;
}
return null;
};
const VoteBreakdownBatch = ({
proposal,
restData,
}: {
proposal: BatchProposal;
restData?: ProposalNode | null;
}) => {
const VoteBreakdownBatch = ({ proposal }: { proposal: BatchProposal }) => {
const [fullBreakdown, setFullBreakdown] = useState(false);
const { t } = useTranslation();
const yesELS =
restData?.yes?.reduce((all, y) => {
if (y.elsPerMarket) {
y.elsPerMarket.forEach((item) => {
const share = Number(item.els);
if (all[item.marketId]) {
all[item.marketId].push(share);
} else {
all[item.marketId] = [share];
}
return all;
});
}
return all;
}, {} as Record<string, number[]>) || {};
const noELS =
restData?.no?.reduce((all, y) => {
if (y.elsPerMarket) {
y.elsPerMarket.forEach((item) => {
const share = Number(item.els);
if (all[item.marketId]) {
all[item.marketId].push(share);
} else {
all[item.marketId] = [share];
}
return all;
});
}
return all;
}, {} as Record<string, number[]>) || {};
const voteInfo = useBatchVoteInformation({
terms: compact(
proposal.subProposals ? proposal.subProposals.map((p) => p?.terms) : []
@ -235,8 +194,6 @@ const VoteBreakdownBatch = ({
proposal={proposal}
votes={proposal.votes}
terms={p.terms}
yesELS={yesELS}
noELS={noELS}
/>
);
})}
@ -297,8 +254,6 @@ const VoteBreakdownBatch = ({
proposal={proposal}
votes={proposal.votes}
terms={p.terms}
yesELS={yesELS}
noELS={noELS}
/>
);
})}
@ -316,17 +271,17 @@ const VoteBreakdownBatchSubProposal = ({
votes,
terms,
indicator,
yesELS,
noELS,
}: {
proposal: BatchProposal;
votes: VoteFieldsFragment;
terms: ProposalTermsFieldsFragment;
indicator?: number;
yesELS: Record<string, number[]>;
noELS: Record<string, number[]>;
}) => {
const { t } = useTranslation();
const voteInfo = useVoteInformation({
votes,
terms,
});
const isProposalOpen = proposal?.state === ProposalState.STATE_OPEN;
const isUpdateMarket = terms?.change?.__typename === 'UpdateMarket';
@ -339,15 +294,6 @@ const VoteBreakdownBatchSubProposal = ({
marketId = terms.change.market.id;
}
const voteInfo = useVoteInformation({
votes,
terms,
// yes votes ELS for this specific proposal (market)
yesELS: marketId ? yesELS[marketId] : undefined,
// no votes ELS for this specific proposal (market)
noELS: marketId ? noELS[marketId] : undefined,
});
const marketName = marketId ? (
<>
: <MarketName marketId={marketId} />

View File

@ -8,18 +8,13 @@ import {
type VoteFieldsFragment,
} from '../__generated__/Proposals';
import { type ProposalChangeType } from '../types';
import sum from 'lodash/sum';
export const useVoteInformation = ({
votes,
terms,
yesELS,
noELS,
}: {
votes: VoteFieldsFragment;
terms: ProposalTermsFieldsFragment;
yesELS?: number[];
noELS?: number[];
}) => {
const {
appState: { totalSupply, decimals },
@ -36,9 +31,7 @@ export const useVoteInformation = ({
paramsForChange,
votes,
totalSupply,
decimals,
yesELS,
noELS
decimals
);
};
@ -79,11 +72,7 @@ const getVoteData = (
},
votes: ProposalFieldsFragment['votes'],
totalSupply: BigNumber,
decimals: number,
/** A list of ELS yes votes */
yesELS?: number[],
/** A list if ELS no votes */
noELS?: number[]
decimals: number
) => {
const requiredMajorityPercentage = params.requiredMajority
? new BigNumber(params.requiredMajority).times(100)
@ -97,31 +86,17 @@ const getVoteData = (
addDecimal(votes.no.totalTokens ?? 0, decimals)
);
let noEquityLikeShareWeight = !votes.no.totalEquityLikeShareWeight
const noEquityLikeShareWeight = !votes.no.totalEquityLikeShareWeight
? new BigNumber(0)
: new BigNumber(votes.no.totalEquityLikeShareWeight).times(100);
// there's no meaningful `totalEquityLikeShareWeight` in batch proposals,
// it has to be deduced from `elsPerMarket` of `no` votes of given proposal
// data. (by REST DATA)
if (noELS != null) {
const noTotalELS = sum(noELS);
noEquityLikeShareWeight = new BigNumber(noTotalELS).times(100);
}
const yesTokens = new BigNumber(
addDecimal(votes.yes.totalTokens ?? 0, decimals)
);
let yesEquityLikeShareWeight = !votes.yes.totalEquityLikeShareWeight
const yesEquityLikeShareWeight = !votes.yes.totalEquityLikeShareWeight
? new BigNumber(0)
: new BigNumber(votes.yes.totalEquityLikeShareWeight).times(100);
// there's no meaningful `totalEquityLikeShareWeight` in batch proposals,
// it has to be deduced from `elsPerMarket` of `yes` votes of given proposal
// data. (by REST DATA)
if (noELS != null) {
const yesTotalELS = sum(yesELS);
yesEquityLikeShareWeight = new BigNumber(yesTotalELS).times(100);
}
const totalTokensVoted = yesTokens.plus(noTokens);

View File

@ -39,8 +39,6 @@ const nextConfig = {
GIT_COMMIT: commitHash,
GIT_TAG: tag,
},
basePath: '/apps/vegas', // Set the base path
assetPrefix: '/apps/vegas', // Set the asset prefix
};
module.exports = SENTRY_AUTH_TOKEN

View File

@ -42,6 +42,7 @@ import type {
EthCallSpec,
MarketTradingMode,
SignerKind,
SuccessorConfiguration,
} from '@vegaprotocol/types';
import {
ConditionOperatorMapping,
@ -69,11 +70,7 @@ import {
useSuccessorMarketIdsQuery,
useSuccessorMarketQuery,
} from '../../__generated__';
import {
useSuccessorMarketProposalDetailsQuery,
type SuccessorMarketProposalDetailsQuery,
type SingleProposal,
} from '@vegaprotocol/proposals';
import { useSuccessorMarketProposalDetailsQuery } from '@vegaprotocol/proposals';
import { getQuoteName, getAsset } from '../../market-utils';
import classNames from 'classnames';
import compact from 'lodash/compact';
@ -254,15 +251,27 @@ export const KeyDetailsInfoPanel = ({
skip: !featureFlags.SUCCESSOR_MARKETS || !market.proposal?.id,
});
const successorProposal = successorProposalDetails?.proposal as
| SingleProposal<SuccessorMarketProposalDetailsQuery['proposal']>
| undefined;
let successorConfiguration: SuccessorConfiguration | false = false;
const successorConfiguration =
successorProposal?.terms.change.__typename === 'NewMarket' &&
successorProposal.terms.change.successorConfiguration?.__typename ===
'SuccessorConfiguration' &&
successorProposal.terms.change.successorConfiguration;
if (successorProposalDetails?.proposal?.__typename === 'Proposal') {
successorConfiguration =
successorProposalDetails.proposal.terms.change.__typename ===
'NewMarket' &&
successorProposalDetails.proposal.terms.change.successorConfiguration
?.__typename === 'SuccessorConfiguration' &&
successorProposalDetails.proposal.terms.change.successorConfiguration;
} else if (
successorProposalDetails?.proposal?.__typename === 'BatchProposal'
) {
const subTerms = successorProposalDetails.proposal.batchTerms?.changes.find(
(c) => c?.change.__typename === 'NewMarket'
);
successorConfiguration =
subTerms?.change.__typename === 'NewMarket' &&
subTerms?.change.successorConfiguration?.__typename ===
'SuccessorConfiguration' &&
subTerms?.change?.successorConfiguration;
}
// The following queries are needed as the parent market could also have been a successor market.
// Note: the parent market is only passed to this component if the successor markets flag is enabled,
@ -281,9 +290,27 @@ export const KeyDetailsInfoPanel = ({
},
skip: !parentMarket?.proposal?.id,
});
const parentProposal = parentSuccessorProposalDetails?.proposal as
| SingleProposal<SuccessorMarketProposalDetailsQuery['proposal']>
| undefined;
let parentSuccessorConfig: SuccessorConfiguration | undefined = undefined;
if (parentSuccessorProposalDetails?.proposal?.__typename === 'Proposal') {
const parentProposal = parentSuccessorProposalDetails?.proposal;
parentSuccessorConfig =
parentProposal.terms.change.__typename === 'NewMarket'
? parentProposal.terms.change.successorConfiguration || undefined
: undefined;
} else if (
parentSuccessorProposalDetails?.proposal?.__typename === 'BatchProposal'
) {
const subTerms =
parentSuccessorProposalDetails.proposal.batchTerms?.changes.find(
(c) => c?.change.__typename === 'NewMarket'
);
parentSuccessorConfig =
subTerms?.change.__typename === 'NewMarket'
? subTerms.change.successorConfiguration || undefined
: undefined;
}
const assetDecimals = getAsset(market).decimals;
@ -339,10 +366,7 @@ export const KeyDetailsInfoPanel = ({
parentMarket && {
name: parentMarket?.tradableInstrument?.instrument?.name,
parentMarketID: grandparentMarketIdData?.market?.parentMarketID,
insurancePoolFraction:
parentProposal?.terms.change.__typename === 'NewMarket' &&
parentProposal?.terms.change.successorConfiguration
?.insurancePoolFraction,
insurancePoolFraction: parentSuccessorConfig?.insurancePoolFraction,
status:
parentMarket?.state && MarketStateMapping[parentMarket.state],
tradingMode:

View File

@ -68,6 +68,7 @@ query SuccessorMarketProposalDetails($proposalId: ID!) {
terms {
change {
... on NewMarket {
__typename
successorConfiguration {
parentMarketId
insurancePoolFraction
@ -76,6 +77,22 @@ query SuccessorMarketProposalDetails($proposalId: ID!) {
}
}
}
... on BatchProposal {
id
batchTerms {
changes {
change {
... on NewMarket {
__typename
successorConfiguration {
parentMarketId
insurancePoolFraction
}
}
}
}
}
}
}
}

View File

@ -32,7 +32,7 @@ export type SuccessorMarketProposalDetailsQueryVariables = Types.Exact<{
}>;
export type SuccessorMarketProposalDetailsQuery = { __typename?: 'Query', proposal?: { __typename?: 'BatchProposal' } | { __typename?: 'Proposal', id?: string | null, terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', successorConfiguration?: { __typename?: 'SuccessorConfiguration', parentMarketId: string, insurancePoolFraction: string } | null } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } } } | null };
export type SuccessorMarketProposalDetailsQuery = { __typename?: 'Query', proposal?: { __typename?: 'BatchProposal', id?: string | null, batchTerms?: { __typename?: 'BatchProposalTerms', changes: Array<{ __typename?: 'BatchProposalTermsChange', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename: 'NewMarket', successorConfiguration?: { __typename?: 'SuccessorConfiguration', parentMarketId: string, insurancePoolFraction: string } | null } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } } | null> } | null } | { __typename?: 'Proposal', id?: string | null, terms: { __typename?: 'ProposalTerms', change: { __typename?: 'CancelTransfer' } | { __typename?: 'NewAsset' } | { __typename?: 'NewFreeform' } | { __typename: 'NewMarket', successorConfiguration?: { __typename?: 'SuccessorConfiguration', parentMarketId: string, insurancePoolFraction: string } | null } | { __typename?: 'NewSpotMarket' } | { __typename?: 'NewTransfer' } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket' } | { __typename?: 'UpdateMarketState' } | { __typename?: 'UpdateNetworkParameter' } | { __typename?: 'UpdateReferralProgram' } | { __typename?: 'UpdateSpotMarket' } | { __typename?: 'UpdateVolumeDiscountProgram' } } } | null };
export type InstrumentDetailsQueryVariables = Types.Exact<{
marketId: Types.Scalars['ID'];
@ -204,6 +204,7 @@ export const SuccessorMarketProposalDetailsDocument = gql`
terms {
change {
... on NewMarket {
__typename
successorConfiguration {
parentMarketId
insurancePoolFraction
@ -212,6 +213,22 @@ export const SuccessorMarketProposalDetailsDocument = gql`
}
}
}
... on BatchProposal {
id
batchTerms {
changes {
change {
... on NewMarket {
__typename
successorConfiguration {
parentMarketId
insurancePoolFraction
}
}
}
}
}
}
}
}
`;

View File

@ -34,21 +34,6 @@
"options": {
"jestConfig": "libs/types/jest.config.ts"
}
},
"generate": {
"executor": "nx:run-commands",
"options": {
"commands": ["npx graphql-codegen --config=libs/types/codegen.yml"],
"parallel": false
}
},
"local-registry": {
"executor": "@nx/js:verdaccio",
"options": {
"port": 4873,
"config": ".verdaccio/config.yml",
"storage": "tmp/local-registry/storage"
}
}
},
"tags": []

View File

@ -35,14 +35,6 @@
"options": {
"jestConfig": "libs/utils/jest.config.ts"
}
},
"local-registry": {
"executor": "@nx/js:verdaccio",
"options": {
"port": 4873,
"config": ".verdaccio/config.yml",
"storage": "tmp/local-registry/storage"
}
}
},
"tags": []

View File

@ -35,14 +35,6 @@
"options": {
"jestConfig": "libs/wallet/jest.config.ts"
}
},
"local-registry": {
"executor": "@nx/js:verdaccio",
"options": {
"port": 4873,
"config": ".verdaccio/config.yml",
"storage": "tmp/local-registry/storage"
}
}
},
"tags": []

View File

@ -241,5 +241,8 @@
"graphql": "15.8.0",
"//": "workaround storybook issue: https://github.com/storybookjs/storybook/issues/21642",
"@storybook/react-docgen-typescript-plugin": "1.0.6--canary.9.cd77847.0"
},
"nx": {
"includedScripts": []
}
}

14
project.json Normal file
View File

@ -0,0 +1,14 @@
{
"name": "nx-monorepo",
"$schema": "node_modules/nx/schemas/project-schema.json",
"targets": {
"local-registry": {
"executor": "@nx/js:verdaccio",
"options": {
"port": 4873,
"config": ".verdaccio/config.yml",
"storage": "tmp/local-registry/storage"
}
}
}
}