Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4090c05900 | ||
|
|
5d6fd389d2 | ||
|
|
8654b33efa | ||
|
|
a27fce0844 | ||
|
|
f6cf99e183 | ||
|
|
207098315f | ||
|
|
f1d5817658 |
@@ -175,7 +175,6 @@ describe('Amend order details', () => {
|
||||
|
||||
const res = renderExistingAmend('123', 1, amend);
|
||||
expect(await res.findByText('New size')).toBeInTheDocument();
|
||||
expect(await res.findByText('Size ±')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Renders Reference if provided', async () => {
|
||||
|
||||
@@ -82,7 +82,7 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
|
||||
{amend.sizeDelta && amend.sizeDelta !== '0' ? (
|
||||
<div className="mb-12 md:mb-0">
|
||||
<h2 className="text-dark mb-4 text-2xl font-bold">
|
||||
{t('Size ±')}
|
||||
{t('New size')}
|
||||
</h2>
|
||||
<h5
|
||||
className={`mb-0 text-lg font-medium capitalize text-gray-500 ${getSideDeltaColour(
|
||||
@@ -93,16 +93,6 @@ const AmendOrderDetails = ({ id, version, amend }: AmendOrderDetailsProps) => {
|
||||
</h5>
|
||||
</div>
|
||||
) : null}
|
||||
{o && (
|
||||
<div className="">
|
||||
<h2 className="text-dark mb-4 text-2xl font-bold">
|
||||
{t('New size')}
|
||||
</h2>
|
||||
<h5 className="mb-0 text-lg font-medium text-gray-500">
|
||||
{o ? o.size : null}
|
||||
</h5>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{amend.price && amend.price !== '0' ? (
|
||||
<div className="">
|
||||
|
||||
@@ -62,9 +62,6 @@ const cache: InMemoryCacheConfig = {
|
||||
Account: {
|
||||
keyFields: false,
|
||||
},
|
||||
Instrument: {
|
||||
keyFields: ['code'],
|
||||
},
|
||||
Delegation: {
|
||||
keyFields: false,
|
||||
// Only get full updates
|
||||
|
||||
+1
-1
@@ -160,7 +160,7 @@ describe('Proposal header', () => {
|
||||
screen.queryByTestId('proposal-description')
|
||||
).not.toBeInTheDocument();
|
||||
expect(screen.getByTestId('proposal-details')).toHaveTextContent(
|
||||
'Update to market: MarketId'
|
||||
'Update to market ID: MarketId'
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
+23
-55
@@ -36,8 +36,6 @@ import { type Proposal, type BatchProposal } from '../../types';
|
||||
import { type ProposalTermsFieldsFragment } from '../../__generated__/Proposals';
|
||||
import { differenceInHours, format, formatDistanceToNowStrict } from 'date-fns';
|
||||
import { DATE_FORMAT_DETAILED } from '../../../../lib/date-formats';
|
||||
import { getIndicatorStyle } from '../proposal/colours';
|
||||
import { MarketName } from '../proposal/market-name';
|
||||
|
||||
const ProposalTypeTags = ({
|
||||
proposal,
|
||||
@@ -140,77 +138,50 @@ const ProposalDetails = ({
|
||||
);
|
||||
}
|
||||
case 'UpdateMarketState': {
|
||||
const marketPageLink = consoleLink(
|
||||
CONSOLE_MARKET_PAGE.replace(':marketId', terms.change.market.id)
|
||||
);
|
||||
return (
|
||||
<span>
|
||||
{featureFlags.UPDATE_MARKET_STATE &&
|
||||
terms.change?.market?.id &&
|
||||
terms.change.updateType ? (
|
||||
<>
|
||||
<span>{t(terms.change.updateType)}: </span>
|
||||
<span className="inline-flex gap-2">
|
||||
<span className="break-all">
|
||||
<MarketName marketId={terms.change.market.id} />
|
||||
</span>
|
||||
<span className="inline-flex items-end gap-0">
|
||||
<CopyWithTooltip
|
||||
text={terms.change.market.id}
|
||||
description={t('copyId')}
|
||||
>
|
||||
<button className="inline-block px-1">
|
||||
<VegaIcon size={20} name={VegaIconNames.COPY} />
|
||||
</button>
|
||||
</CopyWithTooltip>
|
||||
<Tooltip description={t('OpenInConsole')} align="center">
|
||||
<Link
|
||||
className="inline-block px-1"
|
||||
to={marketPageLink}
|
||||
target="_blank"
|
||||
>
|
||||
<VegaIcon
|
||||
size={20}
|
||||
name={VegaIconNames.OPEN_EXTERNAL}
|
||||
/>
|
||||
</Link>
|
||||
</Tooltip>
|
||||
</span>
|
||||
</span>
|
||||
{t(terms.change.updateType)}:{' '}
|
||||
{truncateMiddle(terms.change.market.id)}
|
||||
</>
|
||||
) : null}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
case 'UpdateMarket': {
|
||||
const marketPageLink = consoleLink(
|
||||
CONSOLE_MARKET_PAGE.replace(':marketId', terms.change.marketId)
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<span>{t('UpdateToMarket')}: </span>
|
||||
<span>{t('UpdateToMarket')}:</span>{' '}
|
||||
<span className="inline-flex items-start gap-2">
|
||||
<span className="break-all">
|
||||
<MarketName marketId={terms.change.marketId} />
|
||||
</span>
|
||||
<span className="break-all">{terms.change.marketId} </span>
|
||||
<span className="inline-flex items-end gap-0">
|
||||
<CopyWithTooltip
|
||||
text={terms.change.marketId}
|
||||
description={t('copyId')}
|
||||
description={t('copyToClipboard')}
|
||||
>
|
||||
<button className="inline-block px-1">
|
||||
<VegaIcon size={20} name={VegaIconNames.COPY} />
|
||||
</button>
|
||||
</CopyWithTooltip>
|
||||
<Tooltip description={t('OpenInConsole')} align="center">
|
||||
<Link
|
||||
<button
|
||||
className="inline-block px-1"
|
||||
target="_blank"
|
||||
to={marketPageLink}
|
||||
onClick={() => {
|
||||
const marketPageLink = consoleLink(
|
||||
CONSOLE_MARKET_PAGE.replace(
|
||||
':marketId',
|
||||
// @ts-ignore ts doesn't like this field even though its already a string above???
|
||||
terms.change.marketId
|
||||
)
|
||||
);
|
||||
window.open(marketPageLink, '_blank');
|
||||
}}
|
||||
>
|
||||
<VegaIcon size={20} name={VegaIconNames.OPEN_EXTERNAL} />
|
||||
</Link>
|
||||
</button>
|
||||
</Tooltip>
|
||||
</span>
|
||||
</span>
|
||||
@@ -315,15 +286,12 @@ const ProposalDetails = ({
|
||||
{proposal.subProposals.map((p, i) => {
|
||||
if (!p?.terms) return null;
|
||||
return (
|
||||
<li key={i} className="flex gap-3">
|
||||
<span className={getIndicatorStyle(i + 1)}>{i + 1}</span>
|
||||
<span>
|
||||
<div>{renderDetails(p.terms)}</div>
|
||||
<SubProposalStateText
|
||||
state={proposal.state}
|
||||
enactmentDatetime={p.terms.enactmentDatetime}
|
||||
/>
|
||||
</span>
|
||||
<li key={i}>
|
||||
<div>{renderDetails(p.terms)}</div>
|
||||
<SubProposalStateText
|
||||
state={proposal.state}
|
||||
enactmentDatetime={p.terms.enactmentDatetime}
|
||||
/>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
|
||||
-7
@@ -9,7 +9,6 @@ import { useState } from 'react';
|
||||
import { CollapsibleToggle } from '../../../../components/collapsible-toggle';
|
||||
import { SubHeading } from '../../../../components/heading';
|
||||
import { type UpdateMarketStatesFragment } from '../../__generated__/Proposals';
|
||||
import { MarketUpdateTypeMapping } from '@vegaprotocol/types';
|
||||
|
||||
interface ProposalUpdateMarketStateProps {
|
||||
change: UpdateMarketStatesFragment | null;
|
||||
@@ -50,12 +49,6 @@ export const ProposalUpdateMarketState = ({
|
||||
{t('marketId')}
|
||||
{market?.id}
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow>
|
||||
{t('State')}
|
||||
<span className="bg-vega-green-650 px-1">
|
||||
{MarketUpdateTypeMapping[change.updateType]}
|
||||
</span>
|
||||
</KeyValueTableRow>
|
||||
<KeyValueTableRow>
|
||||
{t('marketName')}
|
||||
{market?.tradableInstrument?.instrument?.name}
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
import classNames from 'classnames';
|
||||
|
||||
// rainbow-ish order
|
||||
const COLOURS = ['red', 'pink', 'orange', 'yellow', 'green', 'blue', 'purple'];
|
||||
|
||||
const getColour = (indicator: number, max = COLOURS.length) => {
|
||||
const available =
|
||||
max < COLOURS.length ? COLOURS.slice(COLOURS.length - max) : COLOURS;
|
||||
const tiers = Object.keys(available).length;
|
||||
let index = Math.abs(indicator - 1);
|
||||
if (indicator >= tiers) {
|
||||
index = index % tiers;
|
||||
}
|
||||
return available[index];
|
||||
};
|
||||
|
||||
export const getStyle = (indicator: number, max = COLOURS.length) =>
|
||||
classNames({
|
||||
'bg-vega-yellow-400': 'yellow' === getColour(indicator, max),
|
||||
'bg-vega-green-400': 'green' === getColour(indicator, max),
|
||||
'bg-vega-blue-400': 'blue' === getColour(indicator, max),
|
||||
'bg-vega-purple-400': 'purple' === getColour(indicator, max),
|
||||
'bg-vega-pink-400': 'pink' === getColour(indicator, max),
|
||||
'bg-vega-orange-400': 'orange' === getColour(indicator, max),
|
||||
'bg-vega-red-400': 'red' === getColour(indicator, max),
|
||||
'bg-vega-clight-600': 'none' === getColour(indicator, max),
|
||||
});
|
||||
|
||||
export const getIndicatorStyle = (indicator: number) =>
|
||||
classNames(
|
||||
'rounded-sm text-black inline-block px-1 py-1 font-alpha calt h-8',
|
||||
getStyle(indicator)
|
||||
);
|
||||
@@ -1,14 +0,0 @@
|
||||
import { useMarketInfoQuery } from '@vegaprotocol/markets';
|
||||
|
||||
export const MarketName = ({ marketId }: { marketId?: string }) => {
|
||||
const { data } = useMarketInfoQuery({
|
||||
variables: {
|
||||
marketId: marketId || '',
|
||||
},
|
||||
skip: !marketId,
|
||||
});
|
||||
|
||||
return (
|
||||
<span>{data?.market?.tradableInstrument.instrument.code || marketId}</span>
|
||||
);
|
||||
};
|
||||
+24
-57
@@ -12,26 +12,21 @@ import {
|
||||
import { ProposalUpdateBenefitTiers } from '../proposal-update-benefit-tiers';
|
||||
import { ProposalUpdateMarketState } from '../proposal-update-market-state';
|
||||
import { ProposalVolumeDiscountProgramDetails } from '../proposal-volume-discount-program-details';
|
||||
import { getIndicatorStyle } from './colours';
|
||||
|
||||
export const ProposalChangeDetails = ({
|
||||
proposal,
|
||||
terms,
|
||||
restData,
|
||||
indicator,
|
||||
}: {
|
||||
proposal: Proposal | BatchProposal;
|
||||
terms: ProposalTermsFieldsFragment;
|
||||
// eslint-disable-next-line
|
||||
restData: any;
|
||||
indicator?: number;
|
||||
}) => {
|
||||
let details = null;
|
||||
|
||||
switch (terms.change.__typename) {
|
||||
case 'NewAsset': {
|
||||
if (proposal.id && terms.change.source.__typename === 'ERC20') {
|
||||
details = (
|
||||
return (
|
||||
<div>
|
||||
<ListAsset
|
||||
assetId={proposal.id}
|
||||
@@ -42,81 +37,62 @@ export const ProposalChangeDetails = ({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
break;
|
||||
return null;
|
||||
}
|
||||
case 'UpdateAsset': {
|
||||
if (proposal.id) {
|
||||
details = (
|
||||
return (
|
||||
<ProposalAssetDetails
|
||||
change={terms.change}
|
||||
assetId={terms.change.assetId}
|
||||
/>
|
||||
);
|
||||
}
|
||||
break;
|
||||
return null;
|
||||
}
|
||||
case 'NewMarket': {
|
||||
if (proposal.id) {
|
||||
details = <ProposalMarketData proposalId={proposal.id} />;
|
||||
return <ProposalMarketData proposalId={proposal.id} />;
|
||||
}
|
||||
break;
|
||||
return null;
|
||||
}
|
||||
case 'UpdateMarket': {
|
||||
if (proposal.id) {
|
||||
const marketId = terms.change.marketId;
|
||||
const proposalData = restData?.data?.proposal;
|
||||
let updatedProposal = null;
|
||||
// single proposal
|
||||
if ('terms' in proposalData) {
|
||||
updatedProposal = proposalData?.terms?.updateMarket?.changes;
|
||||
}
|
||||
// batch proposal - need to fish for the actual changes
|
||||
if (
|
||||
'batchTerms' in proposalData &&
|
||||
Array.isArray(proposalData.batchTerms?.changes)
|
||||
) {
|
||||
updatedProposal = proposalData?.batchTerms?.changes.find(
|
||||
(ch: { updateMarket?: { marketId: string } }) =>
|
||||
ch?.updateMarket?.marketId === marketId
|
||||
)?.updateMarket?.changes;
|
||||
}
|
||||
|
||||
details = (
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<ProposalMarketData proposalId={proposal.id} />
|
||||
<ProposalMarketChanges
|
||||
marketId={terms.change.marketId}
|
||||
updatedProposal={updatedProposal}
|
||||
updatedProposal={
|
||||
restData?.data?.proposal?.terms?.updateMarket?.changes
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
return null;
|
||||
}
|
||||
case 'NewTransfer': {
|
||||
if (proposal.id) {
|
||||
details = <ProposalTransferDetails proposalId={proposal.id} />;
|
||||
return <ProposalTransferDetails proposalId={proposal.id} />;
|
||||
}
|
||||
break;
|
||||
return null;
|
||||
}
|
||||
case 'CancelTransfer': {
|
||||
if (proposal.id) {
|
||||
details = <ProposalCancelTransferDetails proposalId={proposal.id} />;
|
||||
return <ProposalCancelTransferDetails proposalId={proposal.id} />;
|
||||
}
|
||||
break;
|
||||
return null;
|
||||
}
|
||||
case 'UpdateMarketState': {
|
||||
details = <ProposalUpdateMarketState change={terms.change} />;
|
||||
break;
|
||||
return <ProposalUpdateMarketState change={terms.change} />;
|
||||
}
|
||||
case 'UpdateReferralProgram': {
|
||||
details = <ProposalReferralProgramDetails change={terms.change} />;
|
||||
break;
|
||||
return <ProposalReferralProgramDetails change={terms.change} />;
|
||||
}
|
||||
case 'UpdateVolumeDiscountProgram': {
|
||||
details = <ProposalVolumeDiscountProgramDetails change={terms.change} />;
|
||||
break;
|
||||
return <ProposalVolumeDiscountProgramDetails change={terms.change} />;
|
||||
}
|
||||
case 'UpdateNetworkParameter': {
|
||||
if (
|
||||
@@ -124,27 +100,18 @@ export const ProposalChangeDetails = ({
|
||||
terms.change.networkParameter.key ===
|
||||
'rewards.activityStreak.benefitTiers'
|
||||
) {
|
||||
details = <ProposalUpdateBenefitTiers change={terms.change} />;
|
||||
return <ProposalUpdateBenefitTiers change={terms.change} />;
|
||||
}
|
||||
|
||||
break;
|
||||
return null;
|
||||
}
|
||||
case 'NewFreeform':
|
||||
case 'NewSpotMarket':
|
||||
case 'UpdateSpotMarket':
|
||||
case 'UpdateSpotMarket': {
|
||||
return null;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (indicator != null) {
|
||||
details = (
|
||||
<div className="flex gap-3 mb-3">
|
||||
<div className={getIndicatorStyle(indicator)}>{indicator}</div>
|
||||
<div>{details}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return details;
|
||||
};
|
||||
|
||||
@@ -70,7 +70,6 @@ export const Proposal = ({ proposal, restData }: ProposalProps) => {
|
||||
if (!p?.terms) return null;
|
||||
return (
|
||||
<ProposalChangeDetails
|
||||
indicator={i + 1}
|
||||
key={i}
|
||||
proposal={proposal}
|
||||
terms={p.terms}
|
||||
|
||||
@@ -15,7 +15,6 @@ import {
|
||||
type VoteFieldsFragment,
|
||||
} from '../../__generated__/Proposals';
|
||||
import { useBatchVoteInformation } from '../../hooks/use-vote-information';
|
||||
import { getIndicatorStyle } from '../proposal/colours';
|
||||
|
||||
export const CompactVotes = ({ number }: { number: BigNumber }) => (
|
||||
<CompactNumber
|
||||
@@ -177,7 +176,6 @@ const VoteBreakdownBatch = ({ proposal }: { proposal: BatchProposal }) => {
|
||||
if (!p?.terms) return null;
|
||||
return (
|
||||
<VoteBreakdownBatchSubProposal
|
||||
indicator={i + 1}
|
||||
key={i}
|
||||
proposal={proposal}
|
||||
votes={proposal.votes}
|
||||
@@ -257,12 +255,10 @@ const VoteBreakdownBatchSubProposal = ({
|
||||
proposal,
|
||||
votes,
|
||||
terms,
|
||||
indicator,
|
||||
}: {
|
||||
proposal: BatchProposal;
|
||||
votes: VoteFieldsFragment;
|
||||
terms: ProposalTermsFieldsFragment;
|
||||
indicator?: number;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const voteInfo = useVoteInformation({
|
||||
@@ -273,16 +269,9 @@ const VoteBreakdownBatchSubProposal = ({
|
||||
const isProposalOpen = proposal?.state === ProposalState.STATE_OPEN;
|
||||
const isUpdateMarket = terms?.change?.__typename === 'UpdateMarket';
|
||||
|
||||
const indicatorElement = indicator && (
|
||||
<span className={getIndicatorStyle(indicator)}>{indicator}</span>
|
||||
);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex items-baseline gap-3">
|
||||
{indicatorElement}
|
||||
<h4>{t(terms.change.__typename)}</h4>
|
||||
</div>
|
||||
<h4>{t(terms.change.__typename)}</h4>
|
||||
<VoteBreakDownUI
|
||||
voteInfo={voteInfo}
|
||||
isProposalOpen={isProposalOpen}
|
||||
@@ -333,6 +322,7 @@ const VoteBreakDownUI = ({
|
||||
noPercentage,
|
||||
noLPPercentage,
|
||||
yesPercentage,
|
||||
yesLPPercentage,
|
||||
yesTokens,
|
||||
noTokens,
|
||||
totalEquityLikeShareWeight,
|
||||
@@ -345,7 +335,6 @@ const VoteBreakDownUI = ({
|
||||
majorityLPMet,
|
||||
willPassByTokenVote,
|
||||
willPassByLPVote,
|
||||
lpVoteWeight,
|
||||
} = voteInfo;
|
||||
|
||||
const participationThresholdProgress = BigNumber.min(
|
||||
@@ -425,7 +414,7 @@ const VoteBreakDownUI = ({
|
||||
data-testid="lp-majority-breakdown"
|
||||
>
|
||||
<VoteProgress
|
||||
percentageFor={lpVoteWeight}
|
||||
percentageFor={yesLPPercentage}
|
||||
colourfulBg={true}
|
||||
testId="lp-majority-progress"
|
||||
>
|
||||
@@ -444,10 +433,10 @@ const VoteBreakDownUI = ({
|
||||
<span>{t('liquidityProviderVotesFor')}:</span>
|
||||
<Tooltip
|
||||
description={
|
||||
<span>{lpVoteWeight.toFixed(defaultDP)}%</span>
|
||||
<span>{yesLPPercentage.toFixed(defaultDP)}%</span>
|
||||
}
|
||||
>
|
||||
<button>{lpVoteWeight.toFixed(1)}%</button>
|
||||
<button>{yesLPPercentage.toFixed(1)}%</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -273,74 +273,4 @@ describe('use-vote-information', () => {
|
||||
expect(current?.willPassByTokenVote).toEqual(false);
|
||||
expect(current?.willPassByLPVote).toEqual(true);
|
||||
});
|
||||
|
||||
it('mainnet recreation: only yes LP votes equal passing', () => {
|
||||
const yesVotes = 0;
|
||||
const noVotes = 70;
|
||||
const yesEquityLikeShareWeight = '0.21';
|
||||
const noEquityLikeShareWeight = '0';
|
||||
const fixedTokenValue = 1000000000000000000;
|
||||
|
||||
const proposal = generateProposal({
|
||||
terms: {
|
||||
change: {
|
||||
__typename: 'UpdateMarket',
|
||||
marketId: '12345',
|
||||
},
|
||||
},
|
||||
votes: {
|
||||
__typename: 'ProposalVotes',
|
||||
yes: generateYesVotes(
|
||||
yesVotes,
|
||||
fixedTokenValue,
|
||||
yesEquityLikeShareWeight
|
||||
),
|
||||
no: generateNoVotes(noVotes, fixedTokenValue, noEquityLikeShareWeight),
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
result: { current },
|
||||
} = renderHook(() =>
|
||||
useVoteInformation({ terms: proposal.terms, votes: proposal.votes })
|
||||
);
|
||||
|
||||
expect(current?.willPassByTokenVote).toEqual(false);
|
||||
expect(current?.willPassByLPVote).toEqual(true);
|
||||
});
|
||||
|
||||
it('mainnet recreation: mixed yes and no LP votes equal failing', () => {
|
||||
const yesVotes = 0;
|
||||
const noVotes = 70;
|
||||
const yesEquityLikeShareWeight = '0.21';
|
||||
const noEquityLikeShareWeight = '0.22';
|
||||
const fixedTokenValue = 1000000000000000000;
|
||||
|
||||
const proposal = generateProposal({
|
||||
terms: {
|
||||
change: {
|
||||
__typename: 'UpdateMarket',
|
||||
marketId: '12345',
|
||||
},
|
||||
},
|
||||
votes: {
|
||||
__typename: 'ProposalVotes',
|
||||
yes: generateYesVotes(
|
||||
yesVotes,
|
||||
fixedTokenValue,
|
||||
yesEquityLikeShareWeight
|
||||
),
|
||||
no: generateNoVotes(noVotes, fixedTokenValue, noEquityLikeShareWeight),
|
||||
},
|
||||
});
|
||||
|
||||
const {
|
||||
result: { current },
|
||||
} = renderHook(() =>
|
||||
useVoteInformation({ terms: proposal.terms, votes: proposal.votes })
|
||||
);
|
||||
|
||||
expect(current?.willPassByTokenVote).toEqual(false);
|
||||
expect(current?.willPassByLPVote).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -123,19 +123,15 @@ const getVoteData = (
|
||||
totalSupply.multipliedBy(params.requiredParticipation)
|
||||
);
|
||||
|
||||
const lpVoteWeight = yesEquityLikeShareWeight
|
||||
.dividedBy(totalEquityLikeShareWeight)
|
||||
.multipliedBy(100);
|
||||
|
||||
const participationLPMet = params.requiredParticipationLP
|
||||
? lpVoteWeight.isGreaterThan(params.requiredParticipationLP)
|
||||
? totalEquityLikeShareWeight.isGreaterThan(params.requiredParticipationLP)
|
||||
: false;
|
||||
|
||||
const majorityMet = yesPercentage.isGreaterThanOrEqualTo(
|
||||
requiredMajorityPercentage
|
||||
);
|
||||
|
||||
const majorityLPMet = lpVoteWeight.isGreaterThanOrEqualTo(
|
||||
const majorityLPMet = yesLPPercentage.isGreaterThanOrEqualTo(
|
||||
requiredMajorityLPPercentage
|
||||
);
|
||||
|
||||
@@ -153,12 +149,14 @@ const getVoteData = (
|
||||
|
||||
const willPassByLPVote =
|
||||
participationLPMet &&
|
||||
lpVoteWeight.isGreaterThanOrEqualTo(requiredMajorityLPPercentage);
|
||||
new BigNumber(yesLPPercentage).isGreaterThanOrEqualTo(
|
||||
requiredMajorityLPPercentage
|
||||
);
|
||||
|
||||
let willPass = false;
|
||||
|
||||
if (changeType === 'UpdateMarket' || changeType === 'UpdateMarketState') {
|
||||
willPass = willPassByTokenVote || willPassByLPVote;
|
||||
willPass = willPassByTokenVote && willPassByLPVote;
|
||||
} else {
|
||||
willPass = willPassByTokenVote;
|
||||
}
|
||||
@@ -184,7 +182,6 @@ const getVoteData = (
|
||||
totalLPTokensPercentage,
|
||||
willPassByTokenVote,
|
||||
willPassByLPVote,
|
||||
lpVoteWeight: lpVoteWeight.isNaN() ? new BigNumber(0) : lpVoteWeight,
|
||||
yesVotes: new BigNumber(votes.yes.totalNumber ?? 0),
|
||||
noVotes: new BigNumber(votes.no.totalNumber ?? 0),
|
||||
totalVotes: new BigNumber(votes.yes.totalNumber ?? 0).plus(
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
import { useT } from '../../lib/use-t';
|
||||
import { ErrorBoundary } from '@sentry/react';
|
||||
import { CompetitionsHeader } from '../../components/competitions/competitions-header';
|
||||
import {
|
||||
ExternalLink,
|
||||
Intent,
|
||||
Loader,
|
||||
TradingButton,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { Intent, Loader, TradingButton } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
import { useGameCards } from '../../lib/hooks/use-game-cards';
|
||||
import { useEpochInfoQuery } from '../../lib/hooks/__generated__/Epoch';
|
||||
import { Link, useNavigate } from 'react-router-dom';
|
||||
import { Links } from '../../lib/links';
|
||||
@@ -21,9 +18,6 @@ import take from 'lodash/take';
|
||||
import { usePageTitle } from '../../lib/hooks/use-page-title';
|
||||
import { TeamCard } from '../../components/competitions/team-card';
|
||||
import { useMyTeam } from '../../lib/hooks/use-my-team';
|
||||
import { useRewards } from '../../lib/hooks/use-rewards';
|
||||
import { Trans } from 'react-i18next';
|
||||
import { DocsLinks } from '@vegaprotocol/environment';
|
||||
|
||||
export const CompetitionsHome = () => {
|
||||
const t = useT();
|
||||
@@ -34,9 +28,9 @@ export const CompetitionsHome = () => {
|
||||
const { data: epochData } = useEpochInfoQuery();
|
||||
const currentEpoch = Number(epochData?.epoch.id);
|
||||
|
||||
const { data: gamesData, loading: gamesLoading } = useRewards({
|
||||
const { data: gamesData, loading: gamesLoading } = useGameCards({
|
||||
onlyActive: true,
|
||||
scopeToTeams: true,
|
||||
currentEpoch,
|
||||
});
|
||||
|
||||
const { data: teamsData, loading: teamsLoading } = useTeams();
|
||||
@@ -51,34 +45,10 @@ export const CompetitionsHome = () => {
|
||||
return (
|
||||
<ErrorBoundary>
|
||||
<CompetitionsHeader title={t('Competitions')}>
|
||||
<p className="text-lg mb-3">
|
||||
<Trans
|
||||
i18nKey={
|
||||
'Check the cards below to see what community-created, on-chain games are active and how to compete. Joining a team also lets you take part in the on-chain <0>referral program</0>.'
|
||||
}
|
||||
components={[
|
||||
<Link className="underline" key="ref-prog" to={Links.REFERRALS()}>
|
||||
referral program
|
||||
</Link>,
|
||||
]}
|
||||
/>
|
||||
</p>
|
||||
<p className="text-lg mb-1">
|
||||
<Trans
|
||||
i18nKey={
|
||||
'Got an idea for a competition? Anyone can define and fund one -- <0>propose an on-chain game</0> yourself.'
|
||||
}
|
||||
components={[
|
||||
<ExternalLink
|
||||
className="underline"
|
||||
key="propose"
|
||||
href={DocsLinks?.ASSET_TRANSFER_PROPOSAL}
|
||||
>
|
||||
propose an on-chain game
|
||||
</ExternalLink>,
|
||||
]}
|
||||
/>
|
||||
{/** Docs: https://docs.vega.xyz/mainnet/tutorials/proposals/asset-transfer-proposal */}
|
||||
{t(
|
||||
'Be a team player! Participate in games and work together to rake in as much profit to win.'
|
||||
)}
|
||||
</p>
|
||||
</CompetitionsHeader>
|
||||
|
||||
@@ -105,7 +75,7 @@ export const CompetitionsHome = () => {
|
||||
variant="A"
|
||||
title={t('Create a team')}
|
||||
description={t(
|
||||
'Create a new team, share your code with potential members, or set a whitelist for an exclusive group.'
|
||||
'Lorem ipsum dolor sit amet, consectetur adipisicing elit placeat ipsum minus nemo error dicta.'
|
||||
)}
|
||||
actionElement={
|
||||
<TradingButton
|
||||
@@ -124,7 +94,7 @@ export const CompetitionsHome = () => {
|
||||
variant="B"
|
||||
title={t('Solo team / lone wolf')}
|
||||
description={t(
|
||||
'Want to compete but think the best team size is one? This is the option for you.'
|
||||
'Lorem ipsum dolor sit amet, consectetur adipisicing elit placeat ipsum minus nemo error dicta.'
|
||||
)}
|
||||
actionElement={
|
||||
<TradingButton
|
||||
@@ -142,7 +112,7 @@ export const CompetitionsHome = () => {
|
||||
variant="C"
|
||||
title={t('Join a team')}
|
||||
description={t(
|
||||
'Browse existing public teams to find your perfect match.'
|
||||
'Lorem ipsum dolor sit amet, consectetur adipisicing elit placeat ipsum minus nemo error dicta.'
|
||||
)}
|
||||
actionElement={
|
||||
<TradingButton
|
||||
@@ -161,57 +131,27 @@ export const CompetitionsHome = () => {
|
||||
)}
|
||||
|
||||
{/** List of available games */}
|
||||
<h2 className="text-2xl mb-1">{t('Games')}</h2>
|
||||
<p className="mb-6 text-sm">
|
||||
<Trans
|
||||
i18nKey={
|
||||
'See all the live games on the cards below. Every on-chain game is community funded and designed. <0>Find out how to create one</0>.'
|
||||
}
|
||||
components={[
|
||||
<ExternalLink
|
||||
className="underline"
|
||||
key="find-out"
|
||||
href={DocsLinks?.ASSET_TRANSFER_PROPOSAL}
|
||||
>
|
||||
Find out how to create one
|
||||
</ExternalLink>,
|
||||
]}
|
||||
/>
|
||||
{/** Docs: https://docs.vega.xyz/mainnet/tutorials/proposals/asset-transfer-proposal */}
|
||||
</p>
|
||||
<h2 className="text-2xl mb-6">{t('Games')}</h2>
|
||||
|
||||
<div className="mb-12 flex">
|
||||
{gamesLoading ? (
|
||||
<Loader size="small" />
|
||||
) : (
|
||||
<GamesContainer data={gamesData} currentEpoch={currentEpoch} />
|
||||
)}
|
||||
</div>
|
||||
{gamesLoading ? (
|
||||
<Loader size="small" />
|
||||
) : (
|
||||
<GamesContainer data={gamesData} currentEpoch={currentEpoch} />
|
||||
)}
|
||||
|
||||
{/** The teams ranking */}
|
||||
<div className="mb-1 flex flex-row items-baseline gap-3 justify-between">
|
||||
<h2 className="text-2xl">
|
||||
<Link to={Links.COMPETITIONS_TEAMS()} className=" underline">
|
||||
{t('Leaderboard')}
|
||||
</Link>
|
||||
</h2>
|
||||
<div className="mb-6 flex flex-row items-baseline justify-between">
|
||||
<h2 className="text-2xl">{t('Leaderboard')}</h2>
|
||||
<Link to={Links.COMPETITIONS_TEAMS()} className="text-sm underline">
|
||||
{t('View all teams')}
|
||||
</Link>
|
||||
</div>
|
||||
<p className="mb-6 text-sm">
|
||||
{t(
|
||||
'Teams can earn rewards if they meet the goals set in the on-chain trading competitions. Track your earned rewards here, and see which teams are top of the leaderboard this month.'
|
||||
)}
|
||||
</p>
|
||||
|
||||
<div className="flex">
|
||||
{teamsLoading ? (
|
||||
<Loader size="small" />
|
||||
) : (
|
||||
<CompetitionsLeaderboard data={take(teamsData, 10)} />
|
||||
)}
|
||||
</div>
|
||||
{teamsLoading ? (
|
||||
<Loader size="small" />
|
||||
) : (
|
||||
<CompetitionsLeaderboard data={take(teamsData, 10)} />
|
||||
)}
|
||||
</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -10,7 +10,11 @@ import {
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { TransferStatus, type Asset } from '@vegaprotocol/types';
|
||||
import {
|
||||
TransferStatus,
|
||||
type Asset,
|
||||
type RecurringTransfer,
|
||||
} from '@vegaprotocol/types';
|
||||
import classNames from 'classnames';
|
||||
import { useT } from '../../lib/use-t';
|
||||
import { Table } from '../../components/table';
|
||||
@@ -40,6 +44,11 @@ import {
|
||||
areTeamGames,
|
||||
} from '../../lib/hooks/use-games';
|
||||
import { useEpochInfoQuery } from '../../lib/hooks/__generated__/Epoch';
|
||||
import {
|
||||
type EnrichedTransfer,
|
||||
isScopedToTeams,
|
||||
useGameCards,
|
||||
} from '../../lib/hooks/use-game-cards';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import {
|
||||
ActiveRewardCard,
|
||||
@@ -47,11 +56,6 @@ import {
|
||||
} from '../../components/rewards-container/active-rewards';
|
||||
import { type MarketMap, useMarketsMapProvider } from '@vegaprotocol/markets';
|
||||
import format from 'date-fns/format';
|
||||
import {
|
||||
type EnrichedRewardTransfer,
|
||||
isScopedToTeams,
|
||||
useRewards,
|
||||
} from '../../lib/hooks/use-rewards';
|
||||
|
||||
export const CompetitionsTeam = () => {
|
||||
const t = useT();
|
||||
@@ -74,9 +78,10 @@ const TeamPageContainer = ({ teamId }: { teamId: string | undefined }) => {
|
||||
|
||||
const { data: games, loading: gamesLoading } = useGames(teamId);
|
||||
|
||||
const { data: transfersData, loading: transfersLoading } = useRewards({
|
||||
const { data: epochData, loading: epochLoading } = useEpochInfoQuery();
|
||||
const { data: transfersData, loading: transfersLoading } = useGameCards({
|
||||
currentEpoch: Number(epochData?.epoch.id),
|
||||
onlyActive: false,
|
||||
scopeToTeams: true,
|
||||
});
|
||||
|
||||
const { data: markets } = useMarketsMapProvider();
|
||||
@@ -107,7 +112,7 @@ const TeamPageContainer = ({ teamId }: { teamId: string | undefined }) => {
|
||||
games={areTeamGames(games) ? games : undefined}
|
||||
gamesLoading={gamesLoading}
|
||||
transfers={transfersData}
|
||||
transfersLoading={transfersLoading}
|
||||
transfersLoading={epochLoading || transfersLoading}
|
||||
allMarkets={markets || undefined}
|
||||
refetch={refetch}
|
||||
/>
|
||||
@@ -132,7 +137,7 @@ const TeamPage = ({
|
||||
members?: Member[];
|
||||
games?: TeamGame[];
|
||||
gamesLoading?: boolean;
|
||||
transfers?: EnrichedRewardTransfer[];
|
||||
transfers?: EnrichedTransfer[];
|
||||
transfersLoading?: boolean;
|
||||
allMarkets?: MarketMap;
|
||||
refetch: () => void;
|
||||
@@ -206,7 +211,7 @@ const Games = ({
|
||||
}: {
|
||||
games?: TeamGame[];
|
||||
gamesLoading?: boolean;
|
||||
transfers?: EnrichedRewardTransfer[];
|
||||
transfers?: EnrichedTransfer[];
|
||||
transfersLoading?: boolean;
|
||||
allMarkets?: MarketMap;
|
||||
}) => {
|
||||
@@ -446,7 +451,7 @@ const GameTypeCell = ({
|
||||
transfer,
|
||||
allMarkets,
|
||||
}: {
|
||||
transfer?: EnrichedRewardTransfer;
|
||||
transfer?: EnrichedTransfer;
|
||||
allMarkets?: MarketMap;
|
||||
}) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
@@ -469,7 +474,7 @@ const GameTypeCell = ({
|
||||
ref={ref}
|
||||
className="border-b border-dashed border-vega-clight-200 dark:border-vega-cdark-200 text-left md:truncate md:max-w-[25vw]"
|
||||
>
|
||||
<DispatchMetricInfo reward={transfer} />
|
||||
<DispatchMetricInfo transferNode={transfer} allMarkets={allMarkets} />
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
@@ -485,7 +490,7 @@ const ActiveRewardCardDialog = ({
|
||||
open: boolean;
|
||||
onChange: (isOpen: boolean) => void;
|
||||
trigger?: HTMLElement | null;
|
||||
transfer: EnrichedRewardTransfer;
|
||||
transfer: EnrichedTransfer;
|
||||
allMarkets?: MarketMap;
|
||||
}) => {
|
||||
const t = useT();
|
||||
@@ -511,6 +516,8 @@ const ActiveRewardCardDialog = ({
|
||||
<ActiveRewardCard
|
||||
transferNode={transfer}
|
||||
currentEpoch={Number(data?.epoch.id)}
|
||||
kind={transfer.transfer.kind as RecurringTransfer}
|
||||
allMarkets={allMarkets}
|
||||
/>
|
||||
</div>
|
||||
<div className="w-1/4">
|
||||
|
||||
@@ -75,7 +75,6 @@ export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
|
||||
{[
|
||||
'chart',
|
||||
'orderbook',
|
||||
'depth',
|
||||
'trades',
|
||||
'liquidity',
|
||||
'fundingPayments',
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { formatNumber } from '@vegaprotocol/utils';
|
||||
import { type useTeams } from '../../lib/hooks/use-teams';
|
||||
import { useT } from '../../lib/use-t';
|
||||
@@ -17,11 +18,7 @@ export const CompetitionsLeaderboard = ({
|
||||
const num = (n?: number | string) => (!n ? '-' : formatNumber(n, 0));
|
||||
|
||||
if (!data || data.length === 0) {
|
||||
return (
|
||||
<p className="text-sm">
|
||||
{t('Currently no active teams on the network.')}
|
||||
</p>
|
||||
);
|
||||
return <Splash>{t('Could not find any teams')}</Splash>;
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,26 +1,28 @@
|
||||
import { ActiveRewardCard } from '../rewards-container/active-rewards';
|
||||
import { useT } from '../../lib/use-t';
|
||||
import { type EnrichedRewardTransfer } from '../../lib/hooks/use-rewards';
|
||||
import { type EnrichedTransfer } from '../../lib/hooks/use-game-cards';
|
||||
import { useMarketsMapProvider } from '@vegaprotocol/markets';
|
||||
|
||||
export const GamesContainer = ({
|
||||
data,
|
||||
currentEpoch,
|
||||
}: {
|
||||
data: EnrichedRewardTransfer[];
|
||||
data: EnrichedTransfer[];
|
||||
currentEpoch: number;
|
||||
}) => {
|
||||
const t = useT();
|
||||
const { data: markets } = useMarketsMapProvider();
|
||||
|
||||
if (!data || data.length === 0) {
|
||||
return (
|
||||
<p className="text-sm">
|
||||
{t('Currently no active games on the network.')}
|
||||
<p className="mb-6 text-muted">
|
||||
{t('There are currently no games available.')}
|
||||
</p>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<div className="mb-12 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{data.map((game, i) => {
|
||||
// TODO: Remove `kind` prop from ActiveRewardCard
|
||||
const { transfer } = game;
|
||||
@@ -35,6 +37,8 @@ export const GamesContainer = ({
|
||||
key={i}
|
||||
transferNode={game}
|
||||
currentEpoch={currentEpoch}
|
||||
kind={transfer.kind}
|
||||
allMarkets={markets || undefined}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
lpAggregatedDataProvider,
|
||||
type Filter,
|
||||
LiquidityTable,
|
||||
liquidityProvisionsDataProvider,
|
||||
} from '@vegaprotocol/liquidity';
|
||||
import { getAsset, useMarket } from '@vegaprotocol/markets';
|
||||
import {
|
||||
@@ -70,7 +71,7 @@ export const LiquidityContainer = ({
|
||||
|
||||
const useReloadLiquidityData = (marketId: string | undefined) => {
|
||||
const { reload } = useDataProvider({
|
||||
dataProvider: lpAggregatedDataProvider,
|
||||
dataProvider: liquidityProvisionsDataProvider,
|
||||
variables: { marketId: marketId || '' },
|
||||
update: () => true,
|
||||
skip: !marketId,
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { ActiveRewardCard, applyFilter } from './active-rewards';
|
||||
import {
|
||||
ActiveRewardCard,
|
||||
applyFilter,
|
||||
isActiveReward,
|
||||
} from './active-rewards';
|
||||
import {
|
||||
AccountType,
|
||||
AssetStatus,
|
||||
@@ -7,13 +11,54 @@ import {
|
||||
DistributionStrategy,
|
||||
EntityScope,
|
||||
IndividualScope,
|
||||
type RecurringTransfer,
|
||||
type TransferNode,
|
||||
TransferStatus,
|
||||
type Transfer,
|
||||
} from '@vegaprotocol/types';
|
||||
import { type EnrichedRewardTransfer } from '../../lib/hooks/use-rewards';
|
||||
|
||||
jest.mock('./__generated__/Rewards', () => ({
|
||||
useMarketForRewardsQuery: () => ({
|
||||
data: undefined,
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('@vegaprotocol/assets', () => ({
|
||||
useAssetDataProvider: () => {
|
||||
return {
|
||||
data: {
|
||||
assetId: 'asset-1',
|
||||
},
|
||||
};
|
||||
},
|
||||
}));
|
||||
|
||||
describe('ActiveRewards', () => {
|
||||
const reward: EnrichedRewardTransfer = {
|
||||
const mockRecurringTransfer: RecurringTransfer = {
|
||||
__typename: 'RecurringTransfer',
|
||||
startEpoch: 115332,
|
||||
endEpoch: 115432,
|
||||
factor: '1',
|
||||
dispatchStrategy: {
|
||||
__typename: 'DispatchStrategy',
|
||||
dispatchMetric: DispatchMetric.DISPATCH_METRIC_LP_FEES_RECEIVED,
|
||||
dispatchMetricAssetId:
|
||||
'c9fe6fc24fce121b2cc72680543a886055abb560043fda394ba5376203b7527d',
|
||||
marketIdsInScope: null,
|
||||
entityScope: EntityScope.ENTITY_SCOPE_INDIVIDUALS,
|
||||
individualScope: IndividualScope.INDIVIDUAL_SCOPE_ALL,
|
||||
teamScope: null,
|
||||
nTopPerformers: '',
|
||||
stakingRequirement: '',
|
||||
notionalTimeWeightedAveragePositionRequirement: '',
|
||||
windowLength: 1,
|
||||
lockPeriod: 0,
|
||||
distributionStrategy: DistributionStrategy.DISTRIBUTION_STRATEGY_PRO_RATA,
|
||||
rankTable: null,
|
||||
},
|
||||
};
|
||||
|
||||
const mockTransferNode: TransferNode = {
|
||||
__typename: 'TransferNode',
|
||||
transfer: {
|
||||
__typename: 'Transfer',
|
||||
@@ -41,37 +86,21 @@ describe('ActiveRewards', () => {
|
||||
reference: 'reward',
|
||||
status: TransferStatus.STATUS_PENDING,
|
||||
timestamp: '2023-12-18T13:05:35.948706Z',
|
||||
kind: {
|
||||
__typename: 'RecurringTransfer',
|
||||
startEpoch: 115332,
|
||||
endEpoch: 115432,
|
||||
factor: '1',
|
||||
dispatchStrategy: {
|
||||
__typename: 'DispatchStrategy',
|
||||
dispatchMetric: DispatchMetric.DISPATCH_METRIC_LP_FEES_RECEIVED,
|
||||
dispatchMetricAssetId:
|
||||
'c9fe6fc24fce121b2cc72680543a886055abb560043fda394ba5376203b7527d',
|
||||
marketIdsInScope: null,
|
||||
entityScope: EntityScope.ENTITY_SCOPE_INDIVIDUALS,
|
||||
individualScope: IndividualScope.INDIVIDUAL_SCOPE_ALL,
|
||||
teamScope: null,
|
||||
nTopPerformers: '',
|
||||
stakingRequirement: '',
|
||||
notionalTimeWeightedAveragePositionRequirement: '',
|
||||
windowLength: 1,
|
||||
lockPeriod: 0,
|
||||
distributionStrategy:
|
||||
DistributionStrategy.DISTRIBUTION_STRATEGY_PRO_RATA,
|
||||
rankTable: null,
|
||||
},
|
||||
},
|
||||
kind: mockRecurringTransfer,
|
||||
reason: null,
|
||||
},
|
||||
fees: [],
|
||||
};
|
||||
|
||||
it('renders with valid props', () => {
|
||||
render(<ActiveRewardCard transferNode={reward} currentEpoch={115432} />);
|
||||
render(
|
||||
<ActiveRewardCard
|
||||
transferNode={mockTransferNode}
|
||||
currentEpoch={1}
|
||||
kind={mockRecurringTransfer}
|
||||
allMarkets={{}}
|
||||
/>
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByText(/Liquidity provision fees received/i)
|
||||
@@ -79,11 +108,41 @@ describe('ActiveRewards', () => {
|
||||
expect(screen.getByText('Individual scope')).toBeInTheDocument();
|
||||
expect(screen.getByText('Average position')).toBeInTheDocument();
|
||||
expect(screen.getByText('Ends in')).toBeInTheDocument();
|
||||
expect(screen.getByText('1 epoch')).toBeInTheDocument();
|
||||
expect(screen.getByText('115431 epochs')).toBeInTheDocument();
|
||||
expect(screen.getByText('Assessed over')).toBeInTheDocument();
|
||||
expect(screen.getByText('1 epoch')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
describe('isActiveReward', () => {
|
||||
it('returns true for valid active reward', () => {
|
||||
const node = {
|
||||
transfer: {
|
||||
kind: {
|
||||
__typename: 'RecurringTransfer',
|
||||
dispatchStrategy: {},
|
||||
endEpoch: 10,
|
||||
},
|
||||
status: TransferStatus.STATUS_PENDING,
|
||||
},
|
||||
} as TransferNode;
|
||||
expect(isActiveReward(node, 5)).toBeTruthy();
|
||||
});
|
||||
|
||||
it('returns false for invalid active reward', () => {
|
||||
const node = {
|
||||
transfer: {
|
||||
kind: {
|
||||
__typename: 'RecurringTransfer',
|
||||
dispatchStrategy: {},
|
||||
endEpoch: 10,
|
||||
},
|
||||
status: TransferStatus.STATUS_PENDING,
|
||||
},
|
||||
} as TransferNode;
|
||||
expect(isActiveReward(node, 15)).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('applyFilter', () => {
|
||||
it('returns true when filter matches dispatch metric label', () => {
|
||||
const transfer = {
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
import { useActiveRewardsQuery } from './__generated__/Rewards';
|
||||
import { useT } from '../../lib/use-t';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
type IconName,
|
||||
type VegaIconSize,
|
||||
Icon,
|
||||
Intent,
|
||||
Tooltip,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
@@ -10,12 +14,18 @@ import {
|
||||
TinyScroll,
|
||||
truncateMiddle,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import {
|
||||
type Maybe,
|
||||
type Transfer,
|
||||
type TransferNode,
|
||||
type RecurringTransfer,
|
||||
DistributionStrategyDescriptionMapping,
|
||||
DistributionStrategyMapping,
|
||||
EntityScope,
|
||||
EntityScopeMapping,
|
||||
TransferStatus,
|
||||
TransferStatusMapping,
|
||||
DispatchMetric,
|
||||
DispatchMetricDescription,
|
||||
DispatchMetricLabels,
|
||||
@@ -26,33 +36,43 @@ import {
|
||||
IndividualScopeDescriptionMapping,
|
||||
} from '@vegaprotocol/types';
|
||||
import { Card } from '../card/card';
|
||||
import { type ReactNode, useState } from 'react';
|
||||
import { useMemo, useState } from 'react';
|
||||
import {
|
||||
type AssetFieldsFragment,
|
||||
type BasicAssetDetails,
|
||||
useAssetsMapProvider,
|
||||
} from '@vegaprotocol/assets';
|
||||
import { type MarketFieldsFragment } from '@vegaprotocol/markets';
|
||||
import {
|
||||
type EnrichedRewardTransfer,
|
||||
useRewards,
|
||||
} from '../../lib/hooks/use-rewards';
|
||||
import compact from 'lodash/compact';
|
||||
|
||||
enum CardColour {
|
||||
BLUE = 'BLUE',
|
||||
GREEN = 'GREEN',
|
||||
GREY = 'GREY',
|
||||
ORANGE = 'ORANGE',
|
||||
PINK = 'PINK',
|
||||
PURPLE = 'PURPLE',
|
||||
WHITE = 'WHITE',
|
||||
YELLOW = 'YELLOW',
|
||||
}
|
||||
type MarketFieldsFragment,
|
||||
useMarketsMapProvider,
|
||||
getAsset,
|
||||
} from '@vegaprotocol/markets';
|
||||
|
||||
export type Filter = {
|
||||
searchTerm: string;
|
||||
};
|
||||
|
||||
export const isActiveReward = (node: TransferNode, currentEpoch: number) => {
|
||||
const { transfer } = node;
|
||||
if (transfer.kind.__typename !== 'RecurringTransfer') {
|
||||
return false;
|
||||
}
|
||||
const { dispatchStrategy } = transfer.kind;
|
||||
|
||||
if (!dispatchStrategy) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (transfer.kind.endEpoch && transfer.kind.endEpoch < currentEpoch) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (transfer.status !== TransferStatus.STATUS_PENDING) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
export const applyFilter = (
|
||||
node: TransferNode & {
|
||||
asset?: AssetFieldsFragment | null;
|
||||
@@ -75,10 +95,7 @@ export const applyFilter = (
|
||||
transfer.asset?.symbol
|
||||
.toLowerCase()
|
||||
.includes(filter.searchTerm.toLowerCase()) ||
|
||||
(
|
||||
EntityScopeLabelMapping[transfer.kind.dispatchStrategy.entityScope] ||
|
||||
'Unspecified'
|
||||
)
|
||||
EntityScopeLabelMapping[transfer.kind.dispatchStrategy.entityScope]
|
||||
.toLowerCase()
|
||||
.includes(filter.searchTerm.toLowerCase()) ||
|
||||
node.asset?.name
|
||||
@@ -97,15 +114,42 @@ export const applyFilter = (
|
||||
|
||||
export const ActiveRewards = ({ currentEpoch }: { currentEpoch: number }) => {
|
||||
const t = useT();
|
||||
const { data } = useRewards({
|
||||
onlyActive: true,
|
||||
const { data: activeRewardsData } = useActiveRewardsQuery({
|
||||
variables: {
|
||||
isReward: true,
|
||||
},
|
||||
});
|
||||
|
||||
const [filter, setFilter] = useState<Filter>({
|
||||
searchTerm: '',
|
||||
});
|
||||
|
||||
if (!data || !data.length) return null;
|
||||
const { data: assets } = useAssetsMapProvider();
|
||||
const { data: markets } = useMarketsMapProvider();
|
||||
|
||||
const enrichedTransfers = activeRewardsData?.transfersConnection?.edges
|
||||
?.map((e) => e?.node as TransferNode)
|
||||
.filter((node) => isActiveReward(node, currentEpoch))
|
||||
.map((node) => {
|
||||
if (node.transfer.kind.__typename !== 'RecurringTransfer') {
|
||||
return node;
|
||||
}
|
||||
|
||||
const asset =
|
||||
assets &&
|
||||
assets[
|
||||
node.transfer.kind.dispatchStrategy?.dispatchMetricAssetId || ''
|
||||
];
|
||||
|
||||
const marketsInScope =
|
||||
node.transfer.kind.dispatchStrategy?.marketIdsInScope?.map(
|
||||
(id) => markets && markets[id]
|
||||
);
|
||||
|
||||
return { ...node, asset, markets: marketsInScope };
|
||||
});
|
||||
|
||||
if (!enrichedTransfers || !enrichedTransfers.length) return null;
|
||||
|
||||
return (
|
||||
<Card
|
||||
@@ -113,8 +157,7 @@ export const ActiveRewards = ({ currentEpoch }: { currentEpoch: number }) => {
|
||||
className="lg:col-span-full"
|
||||
data-testid="active-rewards-card"
|
||||
>
|
||||
{/** CARDS FILTER */}
|
||||
{data.length > 1 && (
|
||||
{enrichedTransfers.length > 1 && (
|
||||
<TradingInput
|
||||
onChange={(e) =>
|
||||
setFilter((curr) => ({ ...curr, searchTerm: e.target.value }))
|
||||
@@ -129,32 +172,142 @@ export const ActiveRewards = ({ currentEpoch }: { currentEpoch: number }) => {
|
||||
prependElement={<VegaIcon name={VegaIconNames.SEARCH} />}
|
||||
/>
|
||||
)}
|
||||
{/** CARDS */}
|
||||
<TinyScroll className="grid gap-x-8 gap-y-10 h-fit grid-cols-[repeat(auto-fill,_minmax(230px,_1fr))] md:grid-cols-[repeat(auto-fill,_minmax(230px,_1fr))] lg:grid-cols-[repeat(auto-fill,_minmax(320px,_1fr))] xl:grid-cols-[repeat(auto-fill,_minmax(335px,_1fr))] max-h-[40rem] overflow-auto pr-2">
|
||||
{data
|
||||
{enrichedTransfers
|
||||
.filter((n) => applyFilter(n, filter))
|
||||
.map((node, i) => (
|
||||
<ActiveRewardCard
|
||||
key={i}
|
||||
transferNode={node}
|
||||
currentEpoch={currentEpoch}
|
||||
/>
|
||||
))}
|
||||
.map((node, i) => {
|
||||
const { transfer } = node;
|
||||
if (
|
||||
transfer.kind.__typename !== 'RecurringTransfer' ||
|
||||
!transfer.kind.dispatchStrategy?.dispatchMetric
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
node && (
|
||||
<ActiveRewardCard
|
||||
key={i}
|
||||
transferNode={node}
|
||||
kind={transfer.kind}
|
||||
currentEpoch={currentEpoch}
|
||||
allMarkets={markets || {}}
|
||||
/>
|
||||
)
|
||||
);
|
||||
})}
|
||||
</TinyScroll>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
// This was built to be a status indicator for the rewards based on the transfer status
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const StatusIndicator = ({
|
||||
status,
|
||||
reason,
|
||||
}: {
|
||||
status: TransferStatus;
|
||||
reason?: Maybe<string> | undefined;
|
||||
}) => {
|
||||
const t = useT();
|
||||
const getIconIntent = (status: string) => {
|
||||
switch (status) {
|
||||
case TransferStatus.STATUS_DONE:
|
||||
return { icon: IconNames.TICK_CIRCLE, intent: Intent.Success };
|
||||
case TransferStatus.STATUS_REJECTED:
|
||||
return { icon: IconNames.ERROR, intent: Intent.Danger };
|
||||
default:
|
||||
return { icon: IconNames.HELP, intent: Intent.Primary };
|
||||
}
|
||||
};
|
||||
const { icon, intent } = getIconIntent(status);
|
||||
return (
|
||||
<Tooltip
|
||||
description={
|
||||
<span>
|
||||
{t('Transfer status: {{status}} {{reason}}', {
|
||||
status: TransferStatusMapping[status],
|
||||
reason: reason ? `(${reason})` : '',
|
||||
})}
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<span
|
||||
className={classNames(
|
||||
{
|
||||
'text-gray-700 dark:text-gray-300': intent === Intent.None,
|
||||
'text-vega-blue': intent === Intent.Primary,
|
||||
'text-vega-green dark:text-vega-green': intent === Intent.Success,
|
||||
'dark:text-yellow text-yellow-600': intent === Intent.Warning,
|
||||
'text-vega-red': intent === Intent.Danger,
|
||||
},
|
||||
'flex items-start p-1 align-text-bottom'
|
||||
)}
|
||||
>
|
||||
<Icon size={3} name={icon as IconName} />
|
||||
</span>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
type ActiveRewardCardProps = {
|
||||
transferNode: EnrichedRewardTransfer;
|
||||
transferNode: TransferNode & {
|
||||
asset?: AssetFieldsFragment | null;
|
||||
markets?: (MarketFieldsFragment | null)[];
|
||||
};
|
||||
currentEpoch: number;
|
||||
kind: RecurringTransfer;
|
||||
allMarkets?: Record<string, MarketFieldsFragment | null>;
|
||||
};
|
||||
export const ActiveRewardCard = ({
|
||||
transferNode,
|
||||
currentEpoch,
|
||||
kind,
|
||||
allMarkets,
|
||||
}: ActiveRewardCardProps) => {
|
||||
// don't display the cards that are scoped to not trading markets
|
||||
const marketSettled = transferNode.markets?.filter(
|
||||
const t = useT();
|
||||
|
||||
const { transfer } = transferNode;
|
||||
const { dispatchStrategy } = kind;
|
||||
|
||||
const marketIdsInScope = dispatchStrategy?.marketIdsInScope;
|
||||
const firstMarketData = transferNode.markets?.[0];
|
||||
|
||||
const specificMarkets = useMemo(() => {
|
||||
if (
|
||||
!firstMarketData ||
|
||||
!marketIdsInScope ||
|
||||
marketIdsInScope.length === 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
if (marketIdsInScope.length > 1) {
|
||||
const marketNames =
|
||||
allMarkets &&
|
||||
marketIdsInScope
|
||||
.map((id) => allMarkets[id]?.tradableInstrument?.instrument?.name)
|
||||
.join(', ');
|
||||
|
||||
return (
|
||||
<Tooltip description={marketNames}>
|
||||
<span>Specific markets</span>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<span>{firstMarketData?.tradableInstrument?.instrument?.name || ''}</span>
|
||||
);
|
||||
}, [firstMarketData, marketIdsInScope, allMarkets]);
|
||||
|
||||
const dispatchAsset = transferNode.asset;
|
||||
|
||||
if (!dispatchStrategy) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Gray out/hide the cards that are related to not trading markets
|
||||
const marketSettled = transferNode.markets?.some(
|
||||
(m) =>
|
||||
m?.state &&
|
||||
[
|
||||
@@ -165,133 +318,97 @@ export const ActiveRewardCard = ({
|
||||
].includes(m.state)
|
||||
);
|
||||
|
||||
// hide the card if all of the markets are being marked as e.g. settled
|
||||
if (
|
||||
marketSettled?.length === transferNode.markets?.length &&
|
||||
Boolean(transferNode.markets && transferNode.markets.length > 0)
|
||||
) {
|
||||
if (marketSettled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
let colour =
|
||||
DispatchMetricColourMap[
|
||||
transferNode.transfer.kind.dispatchStrategy.dispatchMetric
|
||||
];
|
||||
|
||||
// grey out of any of the markets is suspended or
|
||||
// if the asset is not currently traded on any of the active markets
|
||||
const marketSuspended =
|
||||
transferNode.markets?.filter(
|
||||
(m) =>
|
||||
m?.state === MarketState.STATE_SUSPENDED ||
|
||||
m?.state === MarketState.STATE_SUSPENDED_VIA_GOVERNANCE
|
||||
).length === transferNode.markets?.length &&
|
||||
Boolean(transferNode.markets && transferNode.markets.length > 0);
|
||||
|
||||
if (marketSuspended || !transferNode.isAssetTraded) {
|
||||
colour = CardColour.GREY;
|
||||
}
|
||||
|
||||
return (
|
||||
<RewardCard
|
||||
colour={colour}
|
||||
rewardAmount={addDecimalsFormatNumber(
|
||||
transferNode.transfer.amount,
|
||||
transferNode.transfer.asset?.decimals || 0,
|
||||
6
|
||||
)}
|
||||
rewardAsset={transferNode.asset}
|
||||
endsIn={
|
||||
transferNode.transfer.kind.endEpoch != null
|
||||
? transferNode.transfer.kind.endEpoch - currentEpoch
|
||||
: undefined
|
||||
const assetInActiveMarket =
|
||||
allMarkets &&
|
||||
Object.values(allMarkets).some((m: MarketFieldsFragment | null) => {
|
||||
if (m && getAsset(m).id === dispatchStrategy.dispatchMetricAssetId) {
|
||||
return m?.state && MarketState.STATE_ACTIVE === m.state;
|
||||
}
|
||||
dispatchStrategy={transferNode.transfer.kind.dispatchStrategy}
|
||||
dispatchMetricInfo={<DispatchMetricInfo reward={transferNode} />}
|
||||
/>
|
||||
return false;
|
||||
});
|
||||
|
||||
const marketSuspended = transferNode.markets?.some(
|
||||
(m) =>
|
||||
m?.state === MarketState.STATE_SUSPENDED ||
|
||||
m?.state === MarketState.STATE_SUSPENDED_VIA_GOVERNANCE
|
||||
);
|
||||
};
|
||||
|
||||
// Gray out the cards that are related to suspended markets
|
||||
// Or settlement assets in markets that are not active and eligible for rewards
|
||||
const { gradientClassName, mainClassName } =
|
||||
marketSuspended || !assetInActiveMarket
|
||||
? {
|
||||
gradientClassName: 'from-vega-cdark-500 to-vega-clight-400',
|
||||
mainClassName: 'from-vega-cdark-400 dark:from-vega-cdark-600 to-20%',
|
||||
}
|
||||
: getGradientClasses(dispatchStrategy.dispatchMetric);
|
||||
|
||||
const entityScope = dispatchStrategy.entityScope;
|
||||
|
||||
const RewardCard = ({
|
||||
colour,
|
||||
rewardAmount,
|
||||
rewardAsset,
|
||||
dispatchStrategy,
|
||||
endsIn,
|
||||
dispatchMetricInfo,
|
||||
}: {
|
||||
colour: CardColour;
|
||||
rewardAmount: string;
|
||||
/** The asset linked to the dispatch strategy via `dispatchMetricAssetId` property. */
|
||||
rewardAsset?: BasicAssetDetails;
|
||||
/** The transfer's dispatch strategy. */
|
||||
dispatchStrategy: DispatchStrategy;
|
||||
/** The number of epochs until the transfer stops. */
|
||||
endsIn?: number;
|
||||
/** The VEGA asset details, required to format the min staking amount. */
|
||||
vegaAsset?: BasicAssetDetails;
|
||||
dispatchMetricInfo?: ReactNode;
|
||||
}) => {
|
||||
const t = useT();
|
||||
return (
|
||||
<div>
|
||||
<div
|
||||
className={classNames(
|
||||
'bg-gradient-to-r col-span-full p-0.5 lg:col-auto h-full',
|
||||
'rounded-lg',
|
||||
CardColourStyles[colour].gradientClassName
|
||||
gradientClassName
|
||||
)}
|
||||
data-testid="active-rewards-card"
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
CardColourStyles[colour].mainClassName,
|
||||
'bg-gradient-to-b bg-vega-clight-800 dark:bg-vega-cdark-800 h-full w-full rounded-md p-4 flex flex-col gap-4'
|
||||
mainClassName,
|
||||
'bg-gradient-to-b bg-vega-clight-800 dark:bg-vega-cdark-800 h-full w-full rounded p-4 flex flex-col gap-4'
|
||||
)}
|
||||
>
|
||||
<div className="flex justify-between gap-4">
|
||||
{/** ENTITY SCOPE */}
|
||||
<div className="flex flex-col gap-2 items-center text-center">
|
||||
<EntityIcon entityScope={dispatchStrategy.entityScope} />
|
||||
{dispatchStrategy.entityScope && (
|
||||
<EntityIcon transfer={transfer} />
|
||||
{entityScope && (
|
||||
<span className="text-muted text-xs" data-testid="entity-scope">
|
||||
{EntityScopeLabelMapping[dispatchStrategy.entityScope] ||
|
||||
t('Unspecified')}
|
||||
{EntityScopeLabelMapping[entityScope] || t('Unspecified')}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/** AMOUNT AND DISTRIBUTION STRATEGY */}
|
||||
<div className="flex flex-col gap-2 items-center text-center">
|
||||
{/** AMOUNT */}
|
||||
<h3 className="flex flex-col gap-1 text-2xl shrink-1 text-center">
|
||||
<span className="font-glitch" data-testid="reward-value">
|
||||
{rewardAmount}
|
||||
{addDecimalsFormatNumber(
|
||||
transferNode.transfer.amount,
|
||||
transferNode.transfer.asset?.decimals || 0,
|
||||
6
|
||||
)}
|
||||
</span>
|
||||
|
||||
<span className="font-alpha">{rewardAsset?.symbol || ''}</span>
|
||||
<span className="font-alpha">
|
||||
{transferNode.transfer.asset?.symbol}
|
||||
</span>
|
||||
</h3>
|
||||
|
||||
{/** DISTRIBUTION STRATEGY */}
|
||||
<Tooltip
|
||||
description={t(
|
||||
DistributionStrategyDescriptionMapping[
|
||||
dispatchStrategy.distributionStrategy
|
||||
]
|
||||
)}
|
||||
underline={true}
|
||||
>
|
||||
<span className="text-xs" data-testid="distribution-strategy">
|
||||
{
|
||||
DistributionStrategyMapping[
|
||||
{
|
||||
<Tooltip
|
||||
description={t(
|
||||
DistributionStrategyDescriptionMapping[
|
||||
dispatchStrategy.distributionStrategy
|
||||
]
|
||||
}
|
||||
</span>
|
||||
</Tooltip>
|
||||
)}
|
||||
underline={true}
|
||||
>
|
||||
<span className="text-xs" data-testid="distribution-strategy">
|
||||
{
|
||||
DistributionStrategyMapping[
|
||||
dispatchStrategy.distributionStrategy
|
||||
]
|
||||
}
|
||||
</span>
|
||||
</Tooltip>
|
||||
}
|
||||
</div>
|
||||
|
||||
{/** DISTRIBUTION DELAY */}
|
||||
<div className="flex flex-col gap-2 items-center text-center">
|
||||
<CardIcon
|
||||
iconName={VegaIconNames.LOCK}
|
||||
@@ -304,59 +421,63 @@ const RewardCard = ({
|
||||
data-testid="locked-for"
|
||||
>
|
||||
{t('numberEpochs', '{{count}} epochs', {
|
||||
count: dispatchStrategy.lockPeriod,
|
||||
count: kind.dispatchStrategy?.lockPeriod,
|
||||
})}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<span className="border-[0.5px] border-gray-700" />
|
||||
{/** DISPATCH METRIC */}
|
||||
{dispatchMetricInfo ? (
|
||||
dispatchMetricInfo
|
||||
) : (
|
||||
<span data-testid="dispatch-metric-info">
|
||||
{DispatchMetricLabels[dispatchStrategy.dispatchMetric]}
|
||||
</span>
|
||||
)}
|
||||
<span data-testid="dispatch-metric-info">
|
||||
{DispatchMetricLabels[dispatchStrategy.dispatchMetric]} •{' '}
|
||||
<Tooltip
|
||||
underline={marketSuspended}
|
||||
description={
|
||||
(marketSuspended || !assetInActiveMarket) &&
|
||||
(specificMarkets
|
||||
? t('Eligible market(s) currently suspended')
|
||||
: !assetInActiveMarket
|
||||
? t('Currently no markets eligible for reward')
|
||||
: '')
|
||||
}
|
||||
>
|
||||
<span>{specificMarkets || dispatchAsset?.name}</span>
|
||||
</Tooltip>
|
||||
</span>
|
||||
|
||||
<div className="flex items-center gap-8 flex-wrap">
|
||||
{/** ENDS IN */}
|
||||
{endsIn != null && (
|
||||
{kind.endEpoch && (
|
||||
<span className="flex flex-col">
|
||||
<span className="text-muted text-xs">{t('Ends in')} </span>
|
||||
<span data-testid="ends-in" data-endsin={endsIn}>
|
||||
{endsIn >= 0
|
||||
? t('numberEpochs', '{{count}} epochs', {
|
||||
count: endsIn,
|
||||
})
|
||||
: t('Ended')}
|
||||
<span data-testid="ends-in">
|
||||
{t('numberEpochs', '{{count}} epochs', {
|
||||
count: kind.endEpoch - currentEpoch,
|
||||
})}
|
||||
</span>
|
||||
</span>
|
||||
)}
|
||||
|
||||
{/** WINDOW LENGTH */}
|
||||
<span className="flex flex-col">
|
||||
<span className="text-muted text-xs">{t('Assessed over')}</span>
|
||||
<span data-testid="assessed-over">
|
||||
{t('numberEpochs', '{{count}} epochs', {
|
||||
count: dispatchStrategy.windowLength,
|
||||
})}
|
||||
{
|
||||
<span className="flex flex-col">
|
||||
<span className="text-muted text-xs">{t('Assessed over')}</span>
|
||||
<span data-testid="assessed-over">
|
||||
{t('numberEpochs', '{{count}} epochs', {
|
||||
count: dispatchStrategy.windowLength,
|
||||
})}
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
}
|
||||
</div>
|
||||
{/** DISPATCH METRIC DESCRIPTION */}
|
||||
{dispatchStrategy?.dispatchMetric && (
|
||||
<span className="text-muted text-sm h-[3rem]">
|
||||
{t(DispatchMetricDescription[dispatchStrategy?.dispatchMetric])}
|
||||
</span>
|
||||
)}
|
||||
<span className="border-[0.5px] border-gray-700" />
|
||||
{/** REQUIREMENTS */}
|
||||
{dispatchStrategy && (
|
||||
{kind.dispatchStrategy && (
|
||||
<RewardRequirements
|
||||
dispatchStrategy={dispatchStrategy}
|
||||
rewardAsset={rewardAsset}
|
||||
dispatchStrategy={kind.dispatchStrategy}
|
||||
assetDecimalPlaces={transfer.asset?.decimals}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -366,67 +487,77 @@ const RewardCard = ({
|
||||
};
|
||||
|
||||
export const DispatchMetricInfo = ({
|
||||
reward,
|
||||
transferNode,
|
||||
allMarkets,
|
||||
}: {
|
||||
reward: EnrichedRewardTransfer;
|
||||
transferNode: ActiveRewardCardProps['transferNode'];
|
||||
allMarkets?: ActiveRewardCardProps['allMarkets'];
|
||||
}) => {
|
||||
const t = useT();
|
||||
const dispatchStrategy = reward.transfer.kind.dispatchStrategy;
|
||||
const marketNames = compact(
|
||||
reward.markets?.map((m) => m.tradableInstrument.instrument.name)
|
||||
);
|
||||
const dispatchStrategy =
|
||||
transferNode.transfer.kind.__typename === 'RecurringTransfer'
|
||||
? transferNode.transfer.kind.dispatchStrategy
|
||||
: null;
|
||||
|
||||
let additionalDispatchMetricInfo = null;
|
||||
const dispatchAsset = transferNode.transfer.asset;
|
||||
|
||||
// if asset found then display asset symbol
|
||||
if (reward.asset) {
|
||||
additionalDispatchMetricInfo = <span>{reward.asset.symbol}</span>;
|
||||
}
|
||||
// but if scoped to only one market then display market name
|
||||
if (marketNames.length === 1) {
|
||||
additionalDispatchMetricInfo = <span>{marketNames[0]}</span>;
|
||||
}
|
||||
// or if scoped to many markets then indicate it's scoped to "specific markets"
|
||||
if (marketNames.length > 1) {
|
||||
additionalDispatchMetricInfo = (
|
||||
<Tooltip description={marketNames}>
|
||||
<span>{t('Specific markets')}</span>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
const marketIdsInScope = dispatchStrategy?.marketIdsInScope;
|
||||
const firstMarketData = transferNode.markets?.[0];
|
||||
const specificMarkets = useMemo(() => {
|
||||
if (
|
||||
!firstMarketData ||
|
||||
!marketIdsInScope ||
|
||||
marketIdsInScope.length === 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
if (marketIdsInScope.length > 1) {
|
||||
const marketNames =
|
||||
allMarkets &&
|
||||
marketIdsInScope
|
||||
.map((id) => allMarkets[id]?.tradableInstrument?.instrument?.name)
|
||||
.join(', ');
|
||||
|
||||
return (
|
||||
<Tooltip description={marketNames}>
|
||||
<span>Specific markets</span>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
const name = firstMarketData?.tradableInstrument?.instrument?.name;
|
||||
if (name) {
|
||||
return <span>{name}</span>;
|
||||
}
|
||||
|
||||
return null;
|
||||
}, [firstMarketData, marketIdsInScope, allMarkets]);
|
||||
|
||||
if (!dispatchStrategy) return null;
|
||||
|
||||
return (
|
||||
<span data-testid="dispatch-metric-info">
|
||||
{DispatchMetricLabels[dispatchStrategy.dispatchMetric]}
|
||||
{additionalDispatchMetricInfo != null && (
|
||||
<> • {additionalDispatchMetricInfo}</>
|
||||
)}
|
||||
{DispatchMetricLabels[dispatchStrategy.dispatchMetric]} •{' '}
|
||||
<span>{specificMarkets || dispatchAsset?.name}</span>
|
||||
</span>
|
||||
);
|
||||
};
|
||||
|
||||
const RewardRequirements = ({
|
||||
dispatchStrategy,
|
||||
rewardAsset,
|
||||
vegaAsset,
|
||||
assetDecimalPlaces = 0,
|
||||
}: {
|
||||
dispatchStrategy: DispatchStrategy;
|
||||
rewardAsset?: BasicAssetDetails;
|
||||
vegaAsset?: BasicAssetDetails;
|
||||
assetDecimalPlaces: number | undefined;
|
||||
}) => {
|
||||
const t = useT();
|
||||
|
||||
const entityLabel = EntityScopeLabelMapping[dispatchStrategy.entityScope];
|
||||
|
||||
return (
|
||||
<dl className="flex justify-between flex-wrap items-center gap-3 text-xs">
|
||||
<div className="flex flex-col gap-1">
|
||||
<dt className="flex items-center gap-1 text-muted">
|
||||
{entityLabel
|
||||
? t('{{entity}} scope', {
|
||||
entity: entityLabel,
|
||||
})
|
||||
: t('Scope')}
|
||||
{t('{{entity}} scope', {
|
||||
entity: EntityScopeLabelMapping[dispatchStrategy.entityScope],
|
||||
})}
|
||||
</dt>
|
||||
<dd className="flex items-center gap-1" data-testid="scope">
|
||||
<RewardEntityScope dispatchStrategy={dispatchStrategy} />
|
||||
@@ -443,7 +574,7 @@ const RewardRequirements = ({
|
||||
>
|
||||
{addDecimalsFormatNumber(
|
||||
dispatchStrategy?.stakingRequirement || 0,
|
||||
vegaAsset?.decimals || 18
|
||||
assetDecimalPlaces
|
||||
)}
|
||||
</dd>
|
||||
</div>
|
||||
@@ -456,7 +587,7 @@ const RewardRequirements = ({
|
||||
{addDecimalsFormatNumber(
|
||||
dispatchStrategy?.notionalTimeWeightedAveragePositionRequirement ||
|
||||
0,
|
||||
rewardAsset?.decimals || 0
|
||||
assetDecimalPlaces
|
||||
)}
|
||||
</dd>
|
||||
</div>
|
||||
@@ -514,65 +645,44 @@ const RewardEntityScope = ({
|
||||
);
|
||||
}
|
||||
|
||||
return t('Unspecified');
|
||||
return null;
|
||||
};
|
||||
|
||||
const CardColourStyles: Record<
|
||||
CardColour,
|
||||
{ gradientClassName: string; mainClassName: string }
|
||||
> = {
|
||||
[CardColour.BLUE]: {
|
||||
gradientClassName: 'from-vega-blue-500 to-vega-green-400',
|
||||
mainClassName: 'from-vega-blue-400 dark:from-vega-blue-600 to-20%',
|
||||
},
|
||||
[CardColour.GREEN]: {
|
||||
gradientClassName: 'from-vega-green-500 to-vega-yellow-500',
|
||||
mainClassName: 'from-vega-green-400 dark:from-vega-green-600 to-20%',
|
||||
},
|
||||
[CardColour.GREY]: {
|
||||
gradientClassName: 'from-vega-cdark-500 to-vega-clight-200',
|
||||
mainClassName: 'from-vega-cdark-400 dark:from-vega-cdark-600 to-20%',
|
||||
},
|
||||
[CardColour.ORANGE]: {
|
||||
gradientClassName: 'from-vega-orange-500 to-vega-pink-400',
|
||||
mainClassName: 'from-vega-orange-400 dark:from-vega-orange-600 to-20%',
|
||||
},
|
||||
[CardColour.PINK]: {
|
||||
gradientClassName: 'from-vega-pink-500 to-vega-purple-400',
|
||||
mainClassName: 'from-vega-pink-400 dark:from-vega-pink-600 to-20%',
|
||||
},
|
||||
[CardColour.PURPLE]: {
|
||||
gradientClassName: 'from-vega-purple-500 to-vega-blue-400',
|
||||
mainClassName: 'from-vega-purple-400 dark:from-vega-purple-600 to-20%',
|
||||
},
|
||||
[CardColour.WHITE]: {
|
||||
gradientClassName:
|
||||
'from-vega-clight-600 dark:from-vega-clight-900 to-vega-yellow-500 dark:to-vega-yellow-400',
|
||||
mainClassName: 'from-white dark:from-vega-clight-100 to-20%',
|
||||
},
|
||||
[CardColour.YELLOW]: {
|
||||
gradientClassName: 'from-vega-yellow-500 to-vega-orange-400',
|
||||
mainClassName: 'from-vega-yellow-400 dark:from-vega-yellow-600 to-20%',
|
||||
},
|
||||
};
|
||||
|
||||
const DispatchMetricColourMap: Record<DispatchMetric, CardColour> = {
|
||||
// Liquidity provision fees received
|
||||
[DispatchMetric.DISPATCH_METRIC_LP_FEES_RECEIVED]: CardColour.BLUE,
|
||||
// Price maker fees paid
|
||||
[DispatchMetric.DISPATCH_METRIC_MAKER_FEES_PAID]: CardColour.PINK,
|
||||
// Price maker fees earned
|
||||
[DispatchMetric.DISPATCH_METRIC_MAKER_FEES_RECEIVED]: CardColour.GREEN,
|
||||
// Total market value
|
||||
[DispatchMetric.DISPATCH_METRIC_MARKET_VALUE]: CardColour.WHITE,
|
||||
// Average position
|
||||
[DispatchMetric.DISPATCH_METRIC_AVERAGE_POSITION]: CardColour.ORANGE,
|
||||
// Relative return
|
||||
[DispatchMetric.DISPATCH_METRIC_RELATIVE_RETURN]: CardColour.PURPLE,
|
||||
// Return volatility
|
||||
[DispatchMetric.DISPATCH_METRIC_RETURN_VOLATILITY]: CardColour.YELLOW,
|
||||
// Validator ranking
|
||||
[DispatchMetric.DISPATCH_METRIC_VALIDATOR_RANKING]: CardColour.WHITE,
|
||||
const getGradientClasses = (d: DispatchMetric | undefined) => {
|
||||
switch (d) {
|
||||
case DispatchMetric.DISPATCH_METRIC_AVERAGE_POSITION:
|
||||
return {
|
||||
gradientClassName: 'from-vega-pink-500 to-vega-purple-400',
|
||||
mainClassName: 'from-vega-pink-400 dark:from-vega-pink-600 to-20%',
|
||||
};
|
||||
case DispatchMetric.DISPATCH_METRIC_LP_FEES_RECEIVED:
|
||||
return {
|
||||
gradientClassName: 'from-vega-green-500 to-vega-yellow-500',
|
||||
mainClassName: 'from-vega-green-400 dark:from-vega-green-600 to-20%',
|
||||
};
|
||||
case DispatchMetric.DISPATCH_METRIC_MAKER_FEES_PAID:
|
||||
return {
|
||||
gradientClassName: 'from-vega-orange-500 to-vega-pink-400',
|
||||
mainClassName: 'from-vega-orange-400 dark:from-vega-orange-600 to-20%',
|
||||
};
|
||||
case DispatchMetric.DISPATCH_METRIC_MARKET_VALUE:
|
||||
case DispatchMetric.DISPATCH_METRIC_RELATIVE_RETURN:
|
||||
return {
|
||||
gradientClassName: 'from-vega-purple-500 to-vega-blue-400',
|
||||
mainClassName: 'from-vega-purple-400 dark:from-vega-purple-600 to-20%',
|
||||
};
|
||||
case DispatchMetric.DISPATCH_METRIC_RETURN_VOLATILITY:
|
||||
return {
|
||||
gradientClassName: 'from-vega-blue-500 to-vega-green-400',
|
||||
mainClassName: 'from-vega-blue-400 dark:from-vega-blue-600 to-20%',
|
||||
};
|
||||
case DispatchMetric.DISPATCH_METRIC_VALIDATOR_RANKING:
|
||||
default:
|
||||
return {
|
||||
gradientClassName: 'from-vega-pink-500 to-vega-purple-400',
|
||||
mainClassName: 'from-vega-pink-400 dark:from-vega-pink-600 to-20%',
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const CardIcon = ({
|
||||
@@ -593,29 +703,36 @@ const CardIcon = ({
|
||||
);
|
||||
};
|
||||
|
||||
const EntityScopeIconMap: Record<EntityScope, VegaIconNames> = {
|
||||
[EntityScope.ENTITY_SCOPE_TEAMS]: VegaIconNames.TEAM,
|
||||
[EntityScope.ENTITY_SCOPE_INDIVIDUALS]: VegaIconNames.MAN,
|
||||
};
|
||||
|
||||
const EntityIcon = ({
|
||||
entityScope,
|
||||
transfer,
|
||||
size = 18,
|
||||
}: {
|
||||
entityScope: EntityScope;
|
||||
transfer: Transfer;
|
||||
size?: VegaIconSize;
|
||||
}) => {
|
||||
if (transfer.kind.__typename !== 'RecurringTransfer') {
|
||||
return null;
|
||||
}
|
||||
const entityScope = transfer.kind.dispatchStrategy?.entityScope;
|
||||
const getIconName = () => {
|
||||
switch (entityScope) {
|
||||
case EntityScope.ENTITY_SCOPE_TEAMS:
|
||||
return VegaIconNames.TEAM;
|
||||
case EntityScope.ENTITY_SCOPE_INDIVIDUALS:
|
||||
return VegaIconNames.MAN;
|
||||
default:
|
||||
return VegaIconNames.QUESTION_MARK;
|
||||
}
|
||||
};
|
||||
const iconName = getIconName();
|
||||
return (
|
||||
<Tooltip
|
||||
description={
|
||||
entityScope ? <span>{EntityScopeMapping[entityScope]}</span> : undefined
|
||||
<span>{entityScope ? EntityScopeMapping[entityScope] : ''}</span>
|
||||
}
|
||||
>
|
||||
<span className="flex items-center p-2 rounded-full border border-gray-600">
|
||||
<VegaIcon
|
||||
name={EntityScopeIconMap[entityScope] || VegaIconNames.QUESTION_MARK}
|
||||
size={size}
|
||||
/>
|
||||
{iconName && <VegaIcon name={iconName} size={size} />}
|
||||
</span>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
@@ -20,7 +20,7 @@ import {
|
||||
type RewardsPageQuery,
|
||||
useRewardsPageQuery,
|
||||
useRewardsEpochQuery,
|
||||
} from '../../lib/hooks/__generated__/Rewards';
|
||||
} from './__generated__/Rewards';
|
||||
import {
|
||||
TradingButton,
|
||||
VegaIcon,
|
||||
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
import {
|
||||
useRewardsHistoryQuery,
|
||||
type RewardsHistoryQuery,
|
||||
} from '../../lib/hooks/__generated__/Rewards';
|
||||
} from './__generated__/Rewards';
|
||||
import { useRewardsRowData } from './use-reward-row-data';
|
||||
import { useT } from '../../lib/use-t';
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import BigNumber from 'bignumber.js';
|
||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import { type Asset } from '@vegaprotocol/assets';
|
||||
import { type PartyRewardsConnection } from './rewards-history';
|
||||
import { type RewardsHistoryQuery } from '../../lib/hooks/__generated__/Rewards';
|
||||
import { type RewardsHistoryQuery } from './__generated__/Rewards';
|
||||
|
||||
const REWARD_ACCOUNT_TYPES = [
|
||||
AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
CONSOLE_IMAGE_NAME=vegaprotocol/trading:latest
|
||||
VEGA_VERSION=v0.74.3
|
||||
VEGA_VERSION=v0.74.1
|
||||
LOCAL_SERVER=false
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
CONSOLE_IMAGE_NAME=vegaprotocol/trading:develop
|
||||
VEGA_VERSION=v0.74.3
|
||||
VEGA_VERSION=v0.74.1
|
||||
LOCAL_SERVER=false
|
||||
|
||||
Generated
+390
-394
File diff suppressed because it is too large
Load Diff
@@ -1,60 +0,0 @@
|
||||
# test_ids.py
|
||||
|
||||
# Constants for test IDs
|
||||
ADJUSTED_FEES = "adjusted-fees"
|
||||
TOTAL_FEE_BEFORE_DISCOUNT = "total-fee-before-discount"
|
||||
INFRASTRUCTURE_FEES = "infrastructure-fees"
|
||||
MAKER_FEES = "maker-fees"
|
||||
LIQUIDITY_FEES = "liquidity-fees"
|
||||
TOTAL_DISCOUNT = "total-discount"
|
||||
VOLUME_DISCOUNT_ROW = "volume-discount-row"
|
||||
REFERRAL_DISCOUNT_ROW = "referral-discount-row"
|
||||
PAST_EPOCHS_VOLUME = "past-epochs-volume"
|
||||
REQUIRED_FOR_NEXT_TIER = "required-for-next-tier"
|
||||
TIER_VALUE_0 = "tier-value-0"
|
||||
TIER_VALUE_1 = "tier-value-1"
|
||||
DISCOUNT_VALUE_0 = "discount-value-0"
|
||||
DISCOUNT_VALUE_1 = "discount-value-1"
|
||||
MIN_VOLUME_VALUE_0 = "min-volume-value-0"
|
||||
MIN_VOLUME_VALUE_1 = "min-volume-value-1"
|
||||
MY_VOLUME_VALUE_0 = "my-volume-value-0"
|
||||
MY_VOLUME_VALUE_1 = "my-volume-value-1"
|
||||
ORDER_SIZE = "order-size"
|
||||
ORDER_PRICE = "order-price"
|
||||
DISCOUNT_PILL = "discount-pill"
|
||||
FEES_TEXT = "fees-text"
|
||||
TOOLTIP_CONTENT = "tooltip-content"
|
||||
INFRASTRUCTURE_FEE_FACTOR = "infrastructure-fee-factor"
|
||||
INFRASTRUCTURE_FEE_VALUE = "infrastructure-fee-value"
|
||||
LIQUIDITY_FEE_FACTOR = "liquidity-fee-factor"
|
||||
LIQUIDITY_FEE_VALUE = "liquidity-fee-value"
|
||||
MAKER_FEE_FACTOR = "maker-fee-factor"
|
||||
MAKER_FEE_VALUE = "maker-fee-value"
|
||||
SUBTOTAL_FEE_FACTOR = "subtotal-fee-factor"
|
||||
SUBTOTAL_FEE_VALUE = "subtotal-fee-value"
|
||||
DISCOUNT_FEE_FACTOR = "discount-fee-factor"
|
||||
DISCOUNT_FEE_VALUE = "discount-fee-value"
|
||||
TOTAL_FEE_VALUE = "total-fee-value"
|
||||
RUNNING_NOTIONAL_TAKER_VOLUME = "running-notional-taker-volume"
|
||||
EPOCHS_IN_REFERRAL_SET = "epochs-in-referral-set"
|
||||
REQUIRED_EPOCHS_VALUE_0 = "required-epochs-value-0"
|
||||
REQUIRED_EPOCHS_VALUE_1 = "required-epochs-value-1"
|
||||
FILLS = "Fills"
|
||||
TAB_FILLS = "tab-fills"
|
||||
FEE_BREAKDOWN_TOOLTIP = "fee-breakdown-tooltip"
|
||||
PINNED_ROW_LOCATOR = ".ag-pinned-left-cols-container .ag-row"
|
||||
ROW_LOCATOR = ".ag-center-cols-container .ag-row"
|
||||
# Col-Ids:
|
||||
COL_INSTRUMENT_CODE = '[data-testid="market-code"]'
|
||||
COL_CODE = '[col-id="code"]'
|
||||
COL_SIZE = '[col-id="size"]'
|
||||
COL_PRICE = '[col-id="price"]'
|
||||
COL_PRICE_1 = '[col-id="price_1"]'
|
||||
COL_AGGRESSOR = '[col-id="aggressor"]'
|
||||
COL_FEE = '[col-id="fee"]'
|
||||
COL_FEE_DISCOUNT = '[col-id="fee-discount"]'
|
||||
COL_FEE_AFTER_DISCOUNT = '[col-id="feeAfterDiscount"]'
|
||||
COL_INFRA_FEE = '[col-id="infraFee"]'
|
||||
COL_MAKER_FEE = '[col-id="makerFee"]'
|
||||
COL_LIQUIDITY_FEE = '[col-id="liquidityFee"]'
|
||||
COL_TOTAL_FEE = '[col-id="totalFee"]'
|
||||
@@ -0,0 +1,689 @@
|
||||
import pytest
|
||||
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import init_vega, init_page, auth_setup, cleanup_container
|
||||
from actions.utils import next_epoch, change_keys, forward_time
|
||||
from fixtures.market import market_exists, setup_continuous_market
|
||||
|
||||
# region Constants for test IDs
|
||||
ADJUSTED_FEES = "adjusted-fees"
|
||||
TOTAL_FEE_BEFORE_DISCOUNT = "total-fee-before-discount"
|
||||
INFRASTRUCTURE_FEES = "infrastructure-fees"
|
||||
MAKER_FEES = "maker-fees"
|
||||
LIQUIDITY_FEES = "liquidity-fees"
|
||||
TOTAL_DISCOUNT = "total-discount"
|
||||
VOLUME_DISCOUNT_ROW = "volume-discount-row"
|
||||
REFERRAL_DISCOUNT_ROW = "referral-discount-row"
|
||||
PAST_EPOCHS_VOLUME = "past-epochs-volume"
|
||||
REQUIRED_FOR_NEXT_TIER = "required-for-next-tier"
|
||||
TIER_VALUE_0 = "tier-value-0"
|
||||
TIER_VALUE_1 = "tier-value-1"
|
||||
DISCOUNT_VALUE_0 = "discount-value-0"
|
||||
DISCOUNT_VALUE_1 = "discount-value-1"
|
||||
MIN_VOLUME_VALUE_0 = "min-volume-value-0"
|
||||
MIN_VOLUME_VALUE_1 = "min-volume-value-1"
|
||||
MY_VOLUME_VALUE_0 = "my-volume-value-0"
|
||||
MY_VOLUME_VALUE_1 = "my-volume-value-1"
|
||||
ORDER_SIZE = "order-size"
|
||||
ORDER_PRICE = "order-price"
|
||||
DISCOUNT_PILL = "discount-pill"
|
||||
FEES_TEXT = "fees-text"
|
||||
TOOLTIP_CONTENT = "tooltip-content"
|
||||
INFRASTRUCTURE_FEE_FACTOR = "infrastructure-fee-factor"
|
||||
INFRASTRUCTURE_FEE_VALUE = "infrastructure-fee-value"
|
||||
LIQUIDITY_FEE_FACTOR = "liquidity-fee-factor"
|
||||
LIQUIDITY_FEE_VALUE = "liquidity-fee-value"
|
||||
MAKER_FEE_FACTOR = "maker-fee-factor"
|
||||
MAKER_FEE_VALUE = "maker-fee-value"
|
||||
SUBTOTAL_FEE_FACTOR = "subtotal-fee-factor"
|
||||
SUBTOTAL_FEE_VALUE = "subtotal-fee-value"
|
||||
DISCOUNT_FEE_FACTOR = "discount-fee-factor"
|
||||
DISCOUNT_FEE_VALUE = "discount-fee-value"
|
||||
TOTAL_FEE_VALUE = "total-fee-value"
|
||||
RUNNING_NOTIONAL_TAKER_VOLUME = "running-notional-taker-volume"
|
||||
EPOCHS_IN_REFERRAL_SET = "epochs-in-referral-set"
|
||||
REQUIRED_EPOCHS_VALUE_0 = "required-epochs-value-0"
|
||||
REQUIRED_EPOCHS_VALUE_1 = "required-epochs-value-1"
|
||||
FILLS = "Fills"
|
||||
TAB_FILLS = "tab-fills"
|
||||
FEE_BREAKDOWN_TOOLTIP = "fee-breakdown-tooltip"
|
||||
PINNED_ROW_LOCATOR = ".ag-pinned-left-cols-container .ag-row"
|
||||
ROW_LOCATOR = ".ag-center-cols-container .ag-row"
|
||||
# Col-Ids:
|
||||
COL_INSTRUMENT_CODE = '[data-testid="market-code"]'
|
||||
COL_CODE = '[col-id="code"]'
|
||||
COL_SIZE = '[col-id="size"]'
|
||||
COL_PRICE = '[col-id="price"]'
|
||||
COL_PRICE_1 = '[col-id="price_1"]'
|
||||
COL_AGGRESSOR = '[col-id="aggressor"]'
|
||||
COL_FEE = '[col-id="fee"]'
|
||||
COL_FEE_DISCOUNT = '[col-id="fee-discount"]'
|
||||
COL_FEE_AFTER_DISCOUNT = '[col-id="feeAfterDiscount"]'
|
||||
COL_INFRA_FEE = '[col-id="infraFee"]'
|
||||
COL_MAKER_FEE = '[col-id="makerFee"]'
|
||||
COL_LIQUIDITY_FEE = '[col-id="liquidityFee"]'
|
||||
COL_TOTAL_FEE = '[col-id="totalFee"]'
|
||||
# endregion
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def market_ids():
|
||||
return {
|
||||
"tier_1_volume": "default_id",
|
||||
"tier_2_volume": "default_id",
|
||||
"tier_1_referral": "default_id",
|
||||
"tier_2_referral": "default_id",
|
||||
"combo": "default_id",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_volume_discount_tier_1(request):
|
||||
with init_vega(request) as vega_volume_discount_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_volume_discount_tier_1)) # Register the cleanup function
|
||||
yield vega_volume_discount_tier_1
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_volume_discount_tier_2(request):
|
||||
with init_vega(request) as vega_volume_discount_tier_2:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_volume_discount_tier_2)) # Register the cleanup function
|
||||
yield vega_volume_discount_tier_2
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_referral_discount_tier_1(request):
|
||||
with init_vega(request) as vega_referral_discount_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_referral_discount_tier_1)) # Register the cleanup function
|
||||
yield vega_referral_discount_tier_1
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_referral_discount_tier_2(request):
|
||||
with init_vega(request) as vega_referral_discount_tier_2:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_referral_discount_tier_2)) # Register the cleanup function
|
||||
yield vega_referral_discount_tier_2
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_referral_and_volume_discount(request):
|
||||
with init_vega(request) as vega_referral_and_volume_discount:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_referral_and_volume_discount)) # Register the cleanup function
|
||||
yield vega_referral_and_volume_discount
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def page(vega_instance, browser, request):
|
||||
with init_page(vega_instance, browser, request) as page_instance:
|
||||
yield page_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vega_instance(
|
||||
tier,
|
||||
discount_program,
|
||||
vega_volume_discount_tier_1,
|
||||
vega_volume_discount_tier_2,
|
||||
vega_referral_discount_tier_1,
|
||||
vega_referral_discount_tier_2,
|
||||
vega_referral_and_volume_discount,
|
||||
):
|
||||
if discount_program == "volume":
|
||||
return vega_volume_discount_tier_1 if tier == 1 else vega_volume_discount_tier_2
|
||||
elif discount_program == "referral":
|
||||
return (
|
||||
vega_referral_discount_tier_1
|
||||
if tier == 1
|
||||
else vega_referral_discount_tier_2
|
||||
)
|
||||
elif discount_program == "combo":
|
||||
return vega_referral_and_volume_discount
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def auth(vega_instance, page):
|
||||
return auth_setup(vega_instance, page)
|
||||
|
||||
|
||||
def setup_market_with_volume_discount_program(vega: VegaServiceNull, tier: int):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_volume_discount_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"volume_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"volume_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
window_length=7,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
order_count = 2 if tier == 1 else 3
|
||||
for _ in range(order_count):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", 1, 110)
|
||||
forward_time(vega, True if _ < order_count - 1 else False)
|
||||
|
||||
return market
|
||||
|
||||
|
||||
def setup_market_with_referral_discount_program(vega: VegaServiceNull, tier: int):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_referral_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"minimum_epochs": 1,
|
||||
"referral_reward_factor": 0.1,
|
||||
"referral_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"minimum_epochs": 2,
|
||||
"referral_reward_factor": 0.2,
|
||||
"referral_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
staking_tiers=[
|
||||
{"minimum_staked_tokens": 100, "referral_reward_multiplier": 1.1},
|
||||
{"minimum_staked_tokens": 200, "referral_reward_multiplier": 1.2},
|
||||
],
|
||||
window_length=1,
|
||||
)
|
||||
vega.create_referral_set(key_name=MM_WALLET.name)
|
||||
next_epoch(vega=vega)
|
||||
referral_set_id = list(vega.list_referral_sets().keys())[0]
|
||||
vega.apply_referral_code(key_name="Key 1", id=referral_set_id)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
order_count = 2
|
||||
order_size = 1 if tier == 1 else 2
|
||||
for _ in range(order_count):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", order_size, 110)
|
||||
forward_time(vega, True if _ < order_count - 1 else False)
|
||||
|
||||
return market
|
||||
|
||||
|
||||
def setup_combined_market(vega: VegaServiceNull):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_volume_discount_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"volume_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"volume_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
window_length=7,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
vega.update_referral_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"minimum_epochs": 1,
|
||||
"referral_reward_factor": 0.1,
|
||||
"referral_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"minimum_epochs": 2,
|
||||
"referral_reward_factor": 0.2,
|
||||
"referral_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
staking_tiers=[
|
||||
{"minimum_staked_tokens": 100, "referral_reward_multiplier": 1.1},
|
||||
{"minimum_staked_tokens": 200, "referral_reward_multiplier": 1.2},
|
||||
],
|
||||
window_length=1,
|
||||
)
|
||||
vega.create_referral_set(key_name=MM_WALLET.name)
|
||||
next_epoch(vega=vega)
|
||||
referral_set_id = list(vega.list_referral_sets().keys())[0]
|
||||
vega.apply_referral_code(key_name="Key 1", id=referral_set_id)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
order_count = 2
|
||||
order_size = 2
|
||||
for _ in range(order_count):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", order_size, 110)
|
||||
forward_time(vega, True if _ < order_count - 1 else False)
|
||||
return market
|
||||
|
||||
|
||||
def set_market_volume_discount(vega, tier, discount_program, market_ids):
|
||||
market_id_key = f"tier_{tier}_{discount_program}"
|
||||
if discount_program == "combo":
|
||||
market_id_key = "combo"
|
||||
|
||||
market_id = market_ids.get(market_id_key, "default_id")
|
||||
|
||||
print(f"Checking if market exists: {market_id}")
|
||||
if not market_exists(vega, market_id):
|
||||
print(
|
||||
f"Market doesn't exist for {discount_program} tier {tier}. Setting up new market."
|
||||
)
|
||||
|
||||
if discount_program == "volume":
|
||||
market_id = setup_market_with_volume_discount_program(vega, tier)
|
||||
elif discount_program == "referral":
|
||||
market_id = setup_market_with_referral_discount_program(vega, tier)
|
||||
elif discount_program == "combo":
|
||||
market_id = setup_combined_market(vega)
|
||||
|
||||
market_ids[market_id_key] = market_id
|
||||
|
||||
print(f"Using market ID: {market_id}")
|
||||
return market_ids
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, expected_text",
|
||||
[
|
||||
(1, "volume", "9.045%-9.045%"),
|
||||
(2, "volume", "8.04%-8.04%"),
|
||||
(1, "referral", "9.045%-9.045%"),
|
||||
(2, "referral", "8.04%-8.04%"),
|
||||
(2, "combo", "6.432%-6.432%"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fees_page_discount_program_my_trading_fees(
|
||||
tier, expected_text, discount_program, vega_instance, page: Page, market_ids
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(ADJUSTED_FEES)).to_have_text(expected_text)
|
||||
expect(page.get_by_test_id(TOTAL_FEE_BEFORE_DISCOUNT)).to_have_text(
|
||||
"Total fee before discount10.05%-10.05%"
|
||||
)
|
||||
expect(page.get_by_test_id(INFRASTRUCTURE_FEES)).to_have_text("Infrastructure0.05%")
|
||||
expect(page.get_by_test_id(MAKER_FEES)).to_have_text("Maker10%")
|
||||
expect(page.get_by_test_id(LIQUIDITY_FEES)).to_have_text("Liquidity0%-0%")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, volume_discount, total_discount, referral_discount",
|
||||
[
|
||||
(1, "volume", "Volume discount10%", "10%", "Referral discount0%"),
|
||||
(2, "volume", "Volume discount20%", "20%", "Referral discount0%"),
|
||||
(1, "referral", "Volume discount0%", "10%", "Referral discount10%"),
|
||||
(2, "referral", "Volume discount0%", "20%", "Referral discount20%"),
|
||||
(2, "combo", "Volume discount20%", "36%", "Referral discount20%"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fees_page_discount_program_total_discount(
|
||||
tier,
|
||||
discount_program,
|
||||
volume_discount,
|
||||
referral_discount,
|
||||
total_discount,
|
||||
vega_instance,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TOTAL_DISCOUNT)).to_have_text(total_discount)
|
||||
expect(page.get_by_test_id(VOLUME_DISCOUNT_ROW)).to_have_text(volume_discount)
|
||||
expect(page.get_by_test_id(REFERRAL_DISCOUNT_ROW)).to_have_text(referral_discount)
|
||||
page.get_by_test_id(TOTAL_DISCOUNT).hover()
|
||||
expect(page.get_by_test_id(TOOLTIP_CONTENT).nth(0)).to_have_text(
|
||||
"The total discount is calculated according to the following formula: 1 - (1 - dvolume) ⋇ (1 - dreferral)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, past_epochs_volume, required_for_next_tier",
|
||||
[(1, "volume", "103", "97"), (2, "volume", "206", "")],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fees_page_volume_discount_program_my_current_volume(
|
||||
tier,
|
||||
discount_program,
|
||||
past_epochs_volume,
|
||||
required_for_next_tier,
|
||||
vega_instance,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(PAST_EPOCHS_VOLUME)).to_have_text(past_epochs_volume)
|
||||
|
||||
if tier == 1:
|
||||
expect(page.get_by_test_id(REQUIRED_FOR_NEXT_TIER)).to_have_text(
|
||||
required_for_next_tier
|
||||
)
|
||||
else:
|
||||
expect(page.get_by_test_id(REQUIRED_FOR_NEXT_TIER)).not_to_be_visible()
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, notional_taker_volume, epochs_in_set",
|
||||
[(1, "referral", "103", "1"), (2, "referral", "207", "1")],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fees_page_referral_discount_program_referral_benefits(
|
||||
tier,
|
||||
vega_instance,
|
||||
discount_program,
|
||||
notional_taker_volume,
|
||||
epochs_in_set,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(RUNNING_NOTIONAL_TAKER_VOLUME)).to_have_text(
|
||||
notional_taker_volume
|
||||
)
|
||||
expect(page.get_by_test_id(EPOCHS_IN_REFERRAL_SET)).to_have_text(epochs_in_set)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, my_volume_test_id, my_volume_value, your_tier",
|
||||
[
|
||||
(1, "volume", "my-volume-value-0", "103", "your-volume-tier-0"),
|
||||
(2, "volume", "my-volume-value-1", "206", "your-volume-tier-1"),
|
||||
(1, "referral", "my-volume-value-0", "103", "your-referral-tier-0"),
|
||||
(2, "referral", "my-volume-value-1", "206", "your-referral-tier-1"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fees_page_discount_program_discount(
|
||||
tier,
|
||||
discount_program,
|
||||
my_volume_test_id,
|
||||
my_volume_value,
|
||||
your_tier,
|
||||
vega_instance,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TIER_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(TIER_VALUE_1)).to_have_text("2")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_0)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_1)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_0)).to_have_text("100")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_1)).to_have_text("200")
|
||||
|
||||
if discount_program == "volume":
|
||||
expect(page.get_by_test_id(my_volume_test_id)).to_have_text(my_volume_value)
|
||||
else:
|
||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_1)).to_have_text("2")
|
||||
|
||||
expect(page.get_by_test_id(your_tier).nth(1)).to_be_visible()
|
||||
expect(page.get_by_test_id(your_tier).nth(1)).to_have_text("Your tier")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, fees_after_discount",
|
||||
[
|
||||
(1, "volume", "9.045%"),
|
||||
(2, "volume", "8.04%"),
|
||||
(1, "referral", "9.045%"),
|
||||
(2, "referral", "8.04%"),
|
||||
(2, "combo", "6.432%"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fees_page_discount_program_fees_by_market(
|
||||
tier, discount_program, fees_after_discount, vega_instance, page: Page, market_ids
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
page.goto("/#/fees")
|
||||
pinned = page.locator(PINNED_ROW_LOCATOR)
|
||||
row = page.locator(ROW_LOCATOR)
|
||||
expect(pinned.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text(fees_after_discount)
|
||||
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
||||
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
||||
expect(row.locator(COL_LIQUIDITY_FEE)).to_have_text("0%")
|
||||
expect(row.locator(COL_TOTAL_FEE)).to_have_text("10.05%")
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, discount, discount_value, total_fee",
|
||||
[
|
||||
(1, "volume", "-10%", "-0.01005 tDAI", "0.09045 tDAI"),
|
||||
(2, "volume", "-20%", "-0.0201 tDAI", "0.0804 tDAI"),
|
||||
(1, "referral", "-10%", "-0.01005 tDAI", "0.09045 tDAI"),
|
||||
(2, "referral", "-20%", "-0.0201 tDAI", "0.0804 tDAI"),
|
||||
(2, "combo", "-36%", "-0.03618 tDAI", "0.06432 tDAI"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_deal_ticket_discount_program(
|
||||
tier,
|
||||
discount_program,
|
||||
discount,
|
||||
discount_value,
|
||||
total_fee,
|
||||
vega_instance,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
market_id_key = f"tier_{tier}_{discount_program}"
|
||||
if discount_program == "combo":
|
||||
market_id_key = "combo"
|
||||
market_id = market_ids.get(market_id_key)
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(ORDER_SIZE).fill("1")
|
||||
page.get_by_test_id(ORDER_PRICE).fill("1")
|
||||
expect(page.get_by_test_id(DISCOUNT_PILL)).to_have_text(discount)
|
||||
page.get_by_test_id(FEES_TEXT).hover()
|
||||
tooltip = page.get_by_test_id(TOOLTIP_CONTENT).first
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_FACTOR)).to_have_text("0.05%")
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_VALUE)).to_have_text("0.0005 tDAI")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_FACTOR)).to_have_text("0%")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_VALUE)).to_have_text("0.00 tDAI")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_FACTOR)).to_have_text("10%")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_VALUE)).to_have_text("0.10 tDAI")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_FACTOR)).to_have_text("10.05%")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_VALUE)).to_have_text("0.1005 tDAI")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_FACTOR)).to_have_text(discount)
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_VALUE)).to_have_text(discount_value)
|
||||
expect(tooltip.get_by_test_id(TOTAL_FEE_VALUE)).to_have_text(total_fee)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, fee, fee_discount, price_1, size",
|
||||
[
|
||||
(1, "volume", "9.36158 tDAI", "1.04017 tDAI", "103.50 tDAI", "+1"),
|
||||
(2, "volume", "8.3214 tDAI", "2.08035 tDAI", "103.50 tDAI", "+1"),
|
||||
(
|
||||
1,
|
||||
"referral",
|
||||
"8.42543 tDAI ",
|
||||
"1.04017 tDAI",
|
||||
"103.50 tDAI",
|
||||
"+1",
|
||||
),
|
||||
(
|
||||
2,
|
||||
"referral",
|
||||
"13.31424 tDAI",
|
||||
"4.1607 tDAI",
|
||||
"207.00 tDAI",
|
||||
"+2",
|
||||
),
|
||||
(2, "combo", "10.6514 tDAI ", "7.48926 tDAI", "207.00 tDAI", "+2"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fills_taker_discount_program(
|
||||
tier,
|
||||
discount_program,
|
||||
fee,
|
||||
fee_discount,
|
||||
price_1,
|
||||
size,
|
||||
vega_instance,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
market_id_key = f"tier_{tier}_{discount_program}"
|
||||
if discount_program == "combo":
|
||||
market_id_key = "combo"
|
||||
market_id = market_ids.get(market_id_key)
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text(size)
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text(price_1)
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Taker")
|
||||
expect(row.locator(COL_FEE)).to_have_text(fee)
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text(fee_discount)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, fee, fee_discount, size, price_1",
|
||||
[
|
||||
(1, "volume", "-9.315 tDAI", "1.035 tDAI", "-1", "103.50 tDAI"),
|
||||
(2, "volume", "-8.28 tDAI", "2.07 tDAI", "-1", "103.50 tDAI"),
|
||||
(1, "referral", "-8.3835 tDAI", "1.035 tDAI", "-1", "103.50 tDAI"),
|
||||
(2, "referral", "-13.248 tDAI", "4.14 tDAI", "-2", "207.00 tDAI"),
|
||||
(2, "combo", "-10.5984 tDAI ", "7.452 tDAI", "-2", "207.00 tDAI"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fills_maker_discount_program(
|
||||
tier,
|
||||
discount_program,
|
||||
vega_instance,
|
||||
fee,
|
||||
fee_discount,
|
||||
size,
|
||||
price_1,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
market_id_key = f"tier_{tier}_{discount_program}"
|
||||
if discount_program == "combo":
|
||||
market_id_key = "combo"
|
||||
market_id = market_ids.get(market_id_key)
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
change_keys(page, vega_instance, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text(size)
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text(price_1)
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Maker")
|
||||
expect(row.locator(COL_FEE)).to_have_text(fee)
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text(fee_discount)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, fee",
|
||||
[
|
||||
(1, "volume", "9.315"),
|
||||
(2, "volume", "8.28"),
|
||||
(1, "referral", "8.3835"),
|
||||
(2, "referral", "13.248"),
|
||||
(2, "combo", "10.5984"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fills_maker_fee_tooltip_discount_program(
|
||||
tier, discount_program, fee, vega_instance, page: Page, market_ids
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
market_id_key = f"tier_{tier}_{discount_program}"
|
||||
if discount_program == "combo":
|
||||
market_id_key = "combo"
|
||||
market_id = market_ids.get(market_id_key)
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
change_keys(page, vega_instance, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
f"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-{fee} tDAITotal fees-{fee} tDAI"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"tier, discount_program, maker_fee, total_fee, infra_fee",
|
||||
[
|
||||
(1, "volume", "9.315", "9.36158", "0.04658"),
|
||||
(2, "volume", "8.28", "8.3214", "0.0414"),
|
||||
(1, "referral", "8.3835", "8.42543", "0.04193"),
|
||||
(2, "referral", "13.248", "13.31424", "0.06624"),
|
||||
(2, "combo", "10.5984", "10.6514", "0.053"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("risk_accepted", "auth", "market_ids")
|
||||
def test_fills_taker_fee_tooltip_discount_program(
|
||||
tier,
|
||||
discount_program,
|
||||
vega_instance,
|
||||
maker_fee,
|
||||
total_fee,
|
||||
infra_fee,
|
||||
page: Page,
|
||||
market_ids,
|
||||
):
|
||||
market_ids = set_market_volume_discount(
|
||||
vega_instance, tier, discount_program, market_ids
|
||||
)
|
||||
market_id_key = f"tier_{tier}_{discount_program}"
|
||||
if discount_program == "combo":
|
||||
market_id_key = "combo"
|
||||
market_id = market_ids.get(market_id_key)
|
||||
page.goto(f"/#/markets/{market_id}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
f"If the market was activeFees to be paid by the taker; discounts are already applied.Infrastructure fee{infra_fee} tDAILiquidity fee0.00 tDAIMaker fee{maker_fee} tDAITotal fees{total_fee} tDAI"
|
||||
)
|
||||
@@ -1,216 +0,0 @@
|
||||
import pytest
|
||||
from fees_test_ids import *
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import (
|
||||
init_vega,
|
||||
init_page,
|
||||
auth_setup,
|
||||
risk_accepted_setup,
|
||||
cleanup_container,
|
||||
)
|
||||
from actions.utils import next_epoch, change_keys, forward_time
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(
|
||||
lambda: cleanup_container(vega_instance)
|
||||
)
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_combined_market(vega: VegaServiceNull):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_volume_discount_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"volume_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"volume_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
window_length=7,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
vega.update_referral_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"minimum_epochs": 1,
|
||||
"referral_reward_factor": 0.1,
|
||||
"referral_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"minimum_epochs": 2,
|
||||
"referral_reward_factor": 0.2,
|
||||
"referral_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
staking_tiers=[
|
||||
{"minimum_staked_tokens": 100, "referral_reward_multiplier": 1.1},
|
||||
{"minimum_staked_tokens": 200, "referral_reward_multiplier": 1.2},
|
||||
],
|
||||
window_length=1,
|
||||
)
|
||||
vega.create_referral_set(key_name=MM_WALLET.name)
|
||||
next_epoch(vega=vega)
|
||||
referral_set_id = list(vega.list_referral_sets().keys())[0]
|
||||
vega.apply_referral_code(key_name="Key 1", id=referral_set_id)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
for _ in range(2):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", 2, 110)
|
||||
forward_time(vega, True if _ < 2 - 1 else False)
|
||||
return market
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fees_page_discount_program_my_trading_fees(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(ADJUSTED_FEES)).to_have_text("6.432%-6.432%")
|
||||
expect(page.get_by_test_id(TOTAL_FEE_BEFORE_DISCOUNT)).to_have_text(
|
||||
"Total fee before discount10.05%-10.05%"
|
||||
)
|
||||
expect(page.get_by_test_id(INFRASTRUCTURE_FEES)).to_have_text("Infrastructure0.05%")
|
||||
expect(page.get_by_test_id(MAKER_FEES)).to_have_text("Maker10%")
|
||||
expect(page.get_by_test_id(LIQUIDITY_FEES)).to_have_text("Liquidity0%-0%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fees_page_discount_program_total_discount(
|
||||
page: Page,
|
||||
):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TOTAL_DISCOUNT)).to_have_text("36%")
|
||||
expect(page.get_by_test_id(VOLUME_DISCOUNT_ROW)).to_have_text("Volume discount20%")
|
||||
expect(page.get_by_test_id(REFERRAL_DISCOUNT_ROW)).to_have_text(
|
||||
"Referral discount20%"
|
||||
)
|
||||
page.get_by_test_id(TOTAL_DISCOUNT).hover()
|
||||
expect(page.get_by_test_id(TOOLTIP_CONTENT).nth(0)).to_have_text(
|
||||
"The total discount is calculated according to the following formula: 1 - (1 - dvolume) ⋇ (1 - dreferral)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fees_page_discount_program_fees_by_market(page: Page):
|
||||
page.goto("/#/fees")
|
||||
pinned = page.locator(PINNED_ROW_LOCATOR)
|
||||
row = page.locator(ROW_LOCATOR)
|
||||
expect(pinned.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text("6.432%")
|
||||
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
||||
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
||||
expect(row.locator(COL_LIQUIDITY_FEE)).to_have_text("0%")
|
||||
expect(row.locator(COL_TOTAL_FEE)).to_have_text("10.05%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_deal_ticket_discount_program(
|
||||
page: Page,
|
||||
setup_combined_market,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_combined_market}")
|
||||
page.get_by_test_id(ORDER_SIZE).fill("1")
|
||||
page.get_by_test_id(ORDER_PRICE).fill("1")
|
||||
expect(page.get_by_test_id(DISCOUNT_PILL)).to_have_text("-36%")
|
||||
page.get_by_test_id(FEES_TEXT).hover()
|
||||
tooltip = page.get_by_test_id(TOOLTIP_CONTENT).first
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_FACTOR)).to_have_text("0.05%")
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_VALUE)).to_have_text("0.0005 tDAI")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_FACTOR)).to_have_text("0%")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_VALUE)).to_have_text("0.00 tDAI")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_FACTOR)).to_have_text("10%")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_VALUE)).to_have_text("0.10 tDAI")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_FACTOR)).to_have_text("10.05%")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_VALUE)).to_have_text("0.1005 tDAI")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_FACTOR)).to_have_text("-36%")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_VALUE)).to_have_text("-0.03618 tDAI")
|
||||
expect(tooltip.get_by_test_id(TOTAL_FEE_VALUE)).to_have_text("0.06432 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fills_taker_discount_program(
|
||||
page: Page,
|
||||
setup_combined_market,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_combined_market}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("+2")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("207.00 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Taker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("10.6514 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("7.48926 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fills_maker_discount_program(
|
||||
vega: VegaServiceNull,
|
||||
page: Page,
|
||||
setup_combined_market,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_combined_market}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("-2")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("207.00 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Maker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("-10.5984 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("7.452 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fills_maker_fee_tooltip_discount_program(
|
||||
vega: VegaServiceNull, page: Page, setup_combined_market
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_combined_market}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-10.5984 tDAITotal fees-10.5984 tDAI"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_combo_tier_2")
|
||||
def test_fills_taker_fee_tooltip_discount_program(
|
||||
page: Page,
|
||||
setup_combined_market,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_combined_market}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-10.5984 tDAITotal fees-10.5984 tDAI"
|
||||
)
|
||||
@@ -1,221 +0,0 @@
|
||||
import pytest
|
||||
from fees_test_ids import *
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import (
|
||||
init_vega,
|
||||
init_page,
|
||||
auth_setup,
|
||||
risk_accepted_setup,
|
||||
cleanup_container,
|
||||
)
|
||||
from actions.utils import next_epoch, change_keys, forward_time
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(
|
||||
lambda: cleanup_container(vega_instance)
|
||||
)
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_referral_discount_program(vega: VegaServiceNull):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_referral_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"minimum_epochs": 1,
|
||||
"referral_reward_factor": 0.1,
|
||||
"referral_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"minimum_epochs": 2,
|
||||
"referral_reward_factor": 0.2,
|
||||
"referral_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
staking_tiers=[
|
||||
{"minimum_staked_tokens": 100, "referral_reward_multiplier": 1.1},
|
||||
{"minimum_staked_tokens": 200, "referral_reward_multiplier": 1.2},
|
||||
],
|
||||
window_length=1,
|
||||
)
|
||||
vega.create_referral_set(key_name=MM_WALLET.name)
|
||||
next_epoch(vega=vega)
|
||||
referral_set_id = list(vega.list_referral_sets().keys())[0]
|
||||
vega.apply_referral_code(key_name="Key 1", id=referral_set_id)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
for _ in range(2):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", 1, 110)
|
||||
forward_time(vega, True if _ < 2 - 1 else False)
|
||||
|
||||
return market
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fees_page_discount_program_my_trading_fees(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(ADJUSTED_FEES)).to_have_text("9.045%-9.045%")
|
||||
expect(page.get_by_test_id(TOTAL_FEE_BEFORE_DISCOUNT)).to_have_text(
|
||||
"Total fee before discount10.05%-10.05%"
|
||||
)
|
||||
expect(page.get_by_test_id(INFRASTRUCTURE_FEES)).to_have_text("Infrastructure0.05%")
|
||||
expect(page.get_by_test_id(MAKER_FEES)).to_have_text("Maker10%")
|
||||
expect(page.get_by_test_id(LIQUIDITY_FEES)).to_have_text("Liquidity0%-0%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fees_page_discount_program_total_discount(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TOTAL_DISCOUNT)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(VOLUME_DISCOUNT_ROW)).to_have_text("Volume discount0%")
|
||||
expect(page.get_by_test_id(REFERRAL_DISCOUNT_ROW)).to_have_text(
|
||||
"Referral discount10%"
|
||||
)
|
||||
page.get_by_test_id(TOTAL_DISCOUNT).hover()
|
||||
expect(page.get_by_test_id(TOOLTIP_CONTENT).nth(0)).to_have_text(
|
||||
"The total discount is calculated according to the following formula: 1 - (1 - dvolume) ⋇ (1 - dreferral)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fees_page_referral_discount_program_referral_benefits(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(RUNNING_NOTIONAL_TAKER_VOLUME)).to_have_text("103")
|
||||
expect(page.get_by_test_id(EPOCHS_IN_REFERRAL_SET)).to_have_text("1")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fees_page_discount_program_discount(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TIER_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(TIER_VALUE_1)).to_have_text("2")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_0)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_1)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_0)).to_have_text("100")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_1)).to_have_text("200")
|
||||
|
||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_1)).to_have_text("2")
|
||||
|
||||
expect(page.get_by_test_id("your-referral-tier-0").nth(1)).to_be_visible()
|
||||
expect(page.get_by_test_id("your-referral-tier-0").nth(1)).to_have_text("Your tier")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fees_page_discount_program_fees_by_market(page: Page):
|
||||
page.goto("/#/fees")
|
||||
pinned = page.locator(PINNED_ROW_LOCATOR)
|
||||
row = page.locator(ROW_LOCATOR)
|
||||
expect(pinned.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text("9.045%")
|
||||
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
||||
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
||||
expect(row.locator(COL_LIQUIDITY_FEE)).to_have_text("0%")
|
||||
expect(row.locator(COL_TOTAL_FEE)).to_have_text("10.05%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_deal_ticket_discount_program(
|
||||
page: Page, setup_market_with_referral_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
page.get_by_test_id(ORDER_SIZE).fill("1")
|
||||
page.get_by_test_id(ORDER_PRICE).fill("1")
|
||||
expect(page.get_by_test_id(DISCOUNT_PILL)).to_have_text("-10%")
|
||||
page.get_by_test_id(FEES_TEXT).hover()
|
||||
tooltip = page.get_by_test_id(TOOLTIP_CONTENT).first
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_FACTOR)).to_have_text("0.05%")
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_VALUE)).to_have_text("0.0005 tDAI")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_FACTOR)).to_have_text("0%")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_VALUE)).to_have_text("0.00 tDAI")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_FACTOR)).to_have_text("10%")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_VALUE)).to_have_text("0.10 tDAI")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_FACTOR)).to_have_text("10.05%")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_VALUE)).to_have_text("0.1005 tDAI")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_FACTOR)).to_have_text("-10%")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_VALUE)).to_have_text("-0.01005 tDAI")
|
||||
expect(tooltip.get_by_test_id(TOTAL_FEE_VALUE)).to_have_text("0.09045 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fills_taker_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_referral_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("+1")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Taker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("8.42543 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("1.04017 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fills_maker_discount_program(
|
||||
vega: VegaServiceNull,
|
||||
page: Page,
|
||||
setup_market_with_referral_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("-1")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Maker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("-8.3835 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("1.035 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fills_maker_fee_tooltip_discount_program(
|
||||
vega: VegaServiceNull, page: Page, setup_market_with_referral_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-8.3835 tDAITotal fees-8.3835 tDAI"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_1")
|
||||
def test_fills_taker_fee_tooltip_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_referral_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-8.3835 tDAITotal fees-8.3835 tDAI"
|
||||
)
|
||||
@@ -1,222 +0,0 @@
|
||||
import pytest
|
||||
from fees_test_ids import *
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import (
|
||||
init_vega,
|
||||
init_page,
|
||||
auth_setup,
|
||||
risk_accepted_setup,
|
||||
cleanup_container,
|
||||
)
|
||||
from actions.utils import next_epoch, change_keys, forward_time
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(
|
||||
lambda: cleanup_container(vega_instance)
|
||||
)
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_referral_discount_program(vega: VegaServiceNull):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_referral_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"minimum_epochs": 1,
|
||||
"referral_reward_factor": 0.1,
|
||||
"referral_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"minimum_epochs": 2,
|
||||
"referral_reward_factor": 0.2,
|
||||
"referral_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
staking_tiers=[
|
||||
{"minimum_staked_tokens": 100, "referral_reward_multiplier": 1.1},
|
||||
{"minimum_staked_tokens": 200, "referral_reward_multiplier": 1.2},
|
||||
],
|
||||
window_length=1,
|
||||
)
|
||||
vega.create_referral_set(key_name=MM_WALLET.name)
|
||||
next_epoch(vega=vega)
|
||||
referral_set_id = list(vega.list_referral_sets().keys())[0]
|
||||
vega.apply_referral_code(key_name="Key 1", id=referral_set_id)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
for _ in range(2):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", 2, 110)
|
||||
forward_time(vega, True if _ < 2 - 1 else False)
|
||||
|
||||
return market
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fees_page_discount_program_my_trading_fees(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(ADJUSTED_FEES)).to_have_text("8.04%-8.04%")
|
||||
expect(page.get_by_test_id(TOTAL_FEE_BEFORE_DISCOUNT)).to_have_text(
|
||||
"Total fee before discount10.05%-10.05%"
|
||||
)
|
||||
expect(page.get_by_test_id(INFRASTRUCTURE_FEES)).to_have_text("Infrastructure0.05%")
|
||||
expect(page.get_by_test_id(MAKER_FEES)).to_have_text("Maker10%")
|
||||
expect(page.get_by_test_id(LIQUIDITY_FEES)).to_have_text("Liquidity0%-0%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fees_page_discount_program_total_discount(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TOTAL_DISCOUNT)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(VOLUME_DISCOUNT_ROW)).to_have_text("Volume discount0%")
|
||||
expect(page.get_by_test_id(REFERRAL_DISCOUNT_ROW)).to_have_text(
|
||||
"Referral discount20%"
|
||||
)
|
||||
page.get_by_test_id(TOTAL_DISCOUNT).hover()
|
||||
expect(page.get_by_test_id(TOOLTIP_CONTENT).nth(0)).to_have_text(
|
||||
"The total discount is calculated according to the following formula: 1 - (1 - dvolume) ⋇ (1 - dreferral)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fees_page_referral_discount_program_referral_benefits(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(RUNNING_NOTIONAL_TAKER_VOLUME)).to_have_text("207")
|
||||
expect(page.get_by_test_id(REQUIRED_FOR_NEXT_TIER)).not_to_be_visible()
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fees_page_discount_program_discount(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TIER_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(TIER_VALUE_1)).to_have_text("2")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_0)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_1)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_0)).to_have_text("100")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_1)).to_have_text("200")
|
||||
|
||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(REQUIRED_EPOCHS_VALUE_1)).to_have_text("2")
|
||||
|
||||
expect(page.get_by_test_id("your-referral-tier-1").nth(1)).to_be_visible()
|
||||
expect(page.get_by_test_id("your-referral-tier-1").nth(1)).to_have_text("Your tier")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fees_page_discount_program_fees_by_market(page: Page):
|
||||
page.goto("/#/fees")
|
||||
pinned = page.locator(PINNED_ROW_LOCATOR)
|
||||
row = page.locator(ROW_LOCATOR)
|
||||
expect(pinned.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text("8.04%")
|
||||
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
||||
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
||||
expect(row.locator(COL_LIQUIDITY_FEE)).to_have_text("0%")
|
||||
expect(row.locator(COL_TOTAL_FEE)).to_have_text("10.05%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_deal_ticket_discount_program(
|
||||
page: Page, setup_market_with_referral_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
page.get_by_test_id(ORDER_SIZE).fill("1")
|
||||
page.get_by_test_id(ORDER_PRICE).fill("1")
|
||||
expect(page.get_by_test_id(DISCOUNT_PILL)).to_have_text("-20%")
|
||||
page.get_by_test_id(FEES_TEXT).hover()
|
||||
tooltip = page.get_by_test_id(TOOLTIP_CONTENT).first
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_FACTOR)).to_have_text("0.05%")
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_VALUE)).to_have_text("0.0005 tDAI")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_FACTOR)).to_have_text("0%")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_VALUE)).to_have_text("0.00 tDAI")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_FACTOR)).to_have_text("10%")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_VALUE)).to_have_text("0.10 tDAI")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_FACTOR)).to_have_text("10.05%")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_VALUE)).to_have_text("0.1005 tDAI")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_FACTOR)).to_have_text("-20%")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_VALUE)).to_have_text("-0.0201 tDAI")
|
||||
expect(tooltip.get_by_test_id(TOTAL_FEE_VALUE)).to_have_text("0.0804 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fills_taker_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_referral_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("+2")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("207.00 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Taker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("13.31424 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("4.1607 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fills_maker_discount_program(
|
||||
vega: VegaServiceNull,
|
||||
page: Page,
|
||||
setup_market_with_referral_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("-2")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("207.00 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Maker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("-13.248 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("4.14 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fills_maker_fee_tooltip_discount_program(
|
||||
vega: VegaServiceNull, page: Page, setup_market_with_referral_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
" If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-13.248 tDAITotal fees-13.248 tDAI "
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_referral_tier_2")
|
||||
def test_fills_taker_fee_tooltip_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_referral_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_referral_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-13.248 tDAITotal fees-13.248 tDAI "
|
||||
)
|
||||
@@ -1,210 +0,0 @@
|
||||
import pytest
|
||||
from fees_test_ids import *
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import (
|
||||
init_vega,
|
||||
init_page,
|
||||
auth_setup,
|
||||
risk_accepted_setup,
|
||||
cleanup_container,
|
||||
)
|
||||
from actions.utils import next_epoch, change_keys, forward_time
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(
|
||||
lambda: cleanup_container(vega_instance)
|
||||
)
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_volume_discount_program(vega: VegaServiceNull):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_volume_discount_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"volume_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"volume_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
window_length=7,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
for _ in range(2):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", 1, 110)
|
||||
forward_time(vega, True if _ < 2 - 1 else False)
|
||||
return market
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fees_page_discount_program_my_trading_fees(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(ADJUSTED_FEES)).to_have_text("9.045%-9.045%")
|
||||
expect(page.get_by_test_id(TOTAL_FEE_BEFORE_DISCOUNT)).to_have_text(
|
||||
"Total fee before discount10.05%-10.05%"
|
||||
)
|
||||
expect(page.get_by_test_id(INFRASTRUCTURE_FEES)).to_have_text("Infrastructure0.05%")
|
||||
expect(page.get_by_test_id(MAKER_FEES)).to_have_text("Maker10%")
|
||||
expect(page.get_by_test_id(LIQUIDITY_FEES)).to_have_text("Liquidity0%-0%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fees_page_discount_program_total_discount(
|
||||
page: Page,
|
||||
):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TOTAL_DISCOUNT)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(VOLUME_DISCOUNT_ROW)).to_have_text("Volume discount10%")
|
||||
expect(page.get_by_test_id(REFERRAL_DISCOUNT_ROW)).to_have_text(
|
||||
"Referral discount0%"
|
||||
)
|
||||
page.get_by_test_id(TOTAL_DISCOUNT).hover()
|
||||
expect(page.get_by_test_id(TOOLTIP_CONTENT).nth(0)).to_have_text(
|
||||
"The total discount is calculated according to the following formula: 1 - (1 - dvolume) ⋇ (1 - dreferral)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fees_page_volume_discount_program_my_current_volume(
|
||||
page: Page,
|
||||
):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(PAST_EPOCHS_VOLUME)).to_have_text("103")
|
||||
|
||||
expect(page.get_by_test_id(REQUIRED_FOR_NEXT_TIER)).to_have_text("97")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fees_page_discount_program_discount(
|
||||
page: Page,
|
||||
):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TIER_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(TIER_VALUE_1)).to_have_text("2")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_0)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_1)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_0)).to_have_text("100")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_1)).to_have_text("200")
|
||||
expect(page.get_by_test_id("my-volume-value-0")).to_have_text("103")
|
||||
expect(page.get_by_test_id("your-volume-tier-0").nth(1)).to_be_visible()
|
||||
expect(page.get_by_test_id("your-volume-tier-0").nth(1)).to_have_text("Your tier")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fees_page_discount_program_fees_by_market(page: Page):
|
||||
page.goto("/#/fees")
|
||||
pinned = page.locator(PINNED_ROW_LOCATOR)
|
||||
row = page.locator(ROW_LOCATOR)
|
||||
expect(pinned.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text("9.045%")
|
||||
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
||||
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
||||
expect(row.locator(COL_LIQUIDITY_FEE)).to_have_text("0%")
|
||||
expect(row.locator(COL_TOTAL_FEE)).to_have_text("10.05%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_deal_ticket_discount_program_testing(
|
||||
page: Page, setup_market_with_volume_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
page.get_by_test_id(ORDER_SIZE).fill("1")
|
||||
page.get_by_test_id(ORDER_PRICE).fill("1")
|
||||
expect(page.get_by_test_id(DISCOUNT_PILL)).to_have_text("-10%")
|
||||
page.get_by_test_id(FEES_TEXT).hover()
|
||||
tooltip = page.get_by_test_id(TOOLTIP_CONTENT).first
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_FACTOR)).to_have_text("0.05%")
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_VALUE)).to_have_text("0.0005 tDAI")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_FACTOR)).to_have_text("0%")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_VALUE)).to_have_text("0.00 tDAI")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_FACTOR)).to_have_text("10%")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_VALUE)).to_have_text("0.10 tDAI")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_FACTOR)).to_have_text("10.05%")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_VALUE)).to_have_text("0.1005 tDAI")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_FACTOR)).to_have_text("-10%")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_VALUE)).to_have_text("-0.01005 tDAI")
|
||||
expect(tooltip.get_by_test_id(TOTAL_FEE_VALUE)).to_have_text("0.09045 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fills_taker_discount_program(
|
||||
page: Page, setup_market_with_volume_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("+1")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Taker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("9.36158 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("1.04017 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fills_maker_discount_program(
|
||||
page: Page, setup_market_with_volume_discount_program, vega: VegaServiceNull
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("-1")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Maker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("-9.315 tDAI")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("1.035 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fills_maker_fee_tooltip_discount_program(
|
||||
vega: VegaServiceNull, page: Page, setup_market_with_volume_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-9.315 tDAITotal fees-9.315 tDAI"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_1")
|
||||
def test_fills_taker_fee_tooltip_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_volume_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-9.315 tDAITotal fees-9.315 tDAI"
|
||||
)
|
||||
@@ -1,209 +0,0 @@
|
||||
import pytest
|
||||
from fees_test_ids import *
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import (
|
||||
init_vega,
|
||||
init_page,
|
||||
auth_setup,
|
||||
risk_accepted_setup,
|
||||
cleanup_container,
|
||||
)
|
||||
from actions.utils import next_epoch, change_keys, forward_time
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(
|
||||
lambda: cleanup_container(vega_instance)
|
||||
)
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_volume_discount_program(vega: VegaServiceNull):
|
||||
market = setup_continuous_market(vega, custom_quantum=100000)
|
||||
vega.update_volume_discount_program(
|
||||
proposal_key=MM_WALLET.name,
|
||||
benefit_tiers=[
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 100,
|
||||
"volume_discount_factor": 0.1,
|
||||
},
|
||||
{
|
||||
"minimum_running_notional_taker_volume": 200,
|
||||
"volume_discount_factor": 0.2,
|
||||
},
|
||||
],
|
||||
window_length=7,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
for _ in range(3):
|
||||
submit_order(vega, "Key 1", market, "SIDE_BUY", 1, 110)
|
||||
forward_time(vega, True if _ < 3 - 1 else False)
|
||||
|
||||
return market
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fees_page_discount_program_my_trading_fees(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(ADJUSTED_FEES)).to_have_text("8.04%-8.04%")
|
||||
expect(page.get_by_test_id(TOTAL_FEE_BEFORE_DISCOUNT)).to_have_text(
|
||||
"Total fee before discount10.05%-10.05%"
|
||||
)
|
||||
expect(page.get_by_test_id(INFRASTRUCTURE_FEES)).to_have_text("Infrastructure0.05%")
|
||||
expect(page.get_by_test_id(MAKER_FEES)).to_have_text("Maker10%")
|
||||
expect(page.get_by_test_id(LIQUIDITY_FEES)).to_have_text("Liquidity0%-0%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fees_page_discount_program_total_discount(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TOTAL_DISCOUNT)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(VOLUME_DISCOUNT_ROW)).to_have_text("Volume discount20%")
|
||||
expect(page.get_by_test_id(REFERRAL_DISCOUNT_ROW)).to_have_text(
|
||||
"Referral discount0%"
|
||||
)
|
||||
page.get_by_test_id(TOTAL_DISCOUNT).hover()
|
||||
expect(page.get_by_test_id(TOOLTIP_CONTENT).nth(0)).to_have_text(
|
||||
"The total discount is calculated according to the following formula: 1 - (1 - dvolume) ⋇ (1 - dreferral)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fees_page_volume_discount_program_my_current_volume(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(PAST_EPOCHS_VOLUME)).to_have_text("206")
|
||||
expect(page.get_by_test_id(REQUIRED_FOR_NEXT_TIER)).not_to_be_visible()
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fees_page_discount_program_discount(page: Page):
|
||||
page.goto("/#/fees")
|
||||
expect(page.get_by_test_id(TIER_VALUE_0)).to_have_text("1")
|
||||
expect(page.get_by_test_id(TIER_VALUE_1)).to_have_text("2")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_0)).to_have_text("10%")
|
||||
expect(page.get_by_test_id(DISCOUNT_VALUE_1)).to_have_text("20%")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_0)).to_have_text("100")
|
||||
expect(page.get_by_test_id(MIN_VOLUME_VALUE_1)).to_have_text("200")
|
||||
expect(page.get_by_test_id("my-volume-value-1")).to_have_text("206")
|
||||
expect(page.get_by_test_id("your-volume-tier-1").nth(1)).to_be_visible()
|
||||
expect(page.get_by_test_id("your-volume-tier-1").nth(1)).to_have_text("Your tier")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fees_page_discount_program_fees_by_market(page: Page):
|
||||
page.goto("/#/fees")
|
||||
pinned = page.locator(PINNED_ROW_LOCATOR)
|
||||
row = page.locator(ROW_LOCATOR)
|
||||
expect(pinned.locator(COL_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
expect(row.locator(COL_FEE_AFTER_DISCOUNT)).to_have_text("8.04%")
|
||||
expect(row.locator(COL_INFRA_FEE)).to_have_text("0.05%")
|
||||
expect(row.locator(COL_MAKER_FEE)).to_have_text("10%")
|
||||
expect(row.locator(COL_LIQUIDITY_FEE)).to_have_text("0%")
|
||||
expect(row.locator(COL_TOTAL_FEE)).to_have_text("10.05%")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_deal_ticket_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_volume_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
page.get_by_test_id(ORDER_SIZE).fill("1")
|
||||
page.get_by_test_id(ORDER_PRICE).fill("1")
|
||||
expect(page.get_by_test_id(DISCOUNT_PILL)).to_have_text("-20%")
|
||||
page.get_by_test_id(FEES_TEXT).hover()
|
||||
tooltip = page.get_by_test_id(TOOLTIP_CONTENT).first
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_FACTOR)).to_have_text("0.05%")
|
||||
expect(tooltip.get_by_test_id(INFRASTRUCTURE_FEE_VALUE)).to_have_text("0.0005 tDAI")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_FACTOR)).to_have_text("0%")
|
||||
expect(tooltip.get_by_test_id(LIQUIDITY_FEE_VALUE)).to_have_text("0.00 tDAI")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_FACTOR)).to_have_text("10%")
|
||||
expect(tooltip.get_by_test_id(MAKER_FEE_VALUE)).to_have_text("0.10 tDAI")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_FACTOR)).to_have_text("10.05%")
|
||||
expect(tooltip.get_by_test_id(SUBTOTAL_FEE_VALUE)).to_have_text("0.1005 tDAI")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_FACTOR)).to_have_text("-20%")
|
||||
expect(tooltip.get_by_test_id(DISCOUNT_FEE_VALUE)).to_have_text("-0.0201 tDAI")
|
||||
expect(tooltip.get_by_test_id(TOTAL_FEE_VALUE)).to_have_text("0.0804 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fills_taker_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_volume_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("+1")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Taker")
|
||||
expect(row.locator(COL_FEE)).to_have_text(
|
||||
"8.3214 tDAI",
|
||||
)
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("2.08035 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fills_maker_discount_program(
|
||||
vega: VegaServiceNull,
|
||||
page: Page,
|
||||
setup_market_with_volume_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
expect(row.locator(COL_SIZE)).to_have_text("-1")
|
||||
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_PRICE_1)).to_have_text("103.50 tDAI")
|
||||
expect(row.locator(COL_AGGRESSOR)).to_have_text("Maker")
|
||||
expect(row.locator(COL_FEE)).to_have_text("-8.28 tDAI ")
|
||||
expect(row.locator(COL_FEE_DISCOUNT)).to_have_text("2.07 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fills_maker_fee_tooltip_discount_program(
|
||||
vega, page: Page, setup_market_with_volume_discount_program
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
change_keys(page, vega, MM_WALLET.name)
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-8.28 tDAITotal fees-8.28 tDAI"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_fees_volume_tier_2")
|
||||
def test_fills_taker_fee_tooltip_discount_program(
|
||||
page: Page,
|
||||
setup_market_with_volume_discount_program,
|
||||
):
|
||||
page.goto(f"/#/markets/{setup_market_with_volume_discount_program}")
|
||||
page.get_by_test_id(FILLS).click()
|
||||
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
|
||||
# tbd - tooltip is not visible without this wait
|
||||
page.wait_for_timeout(1000)
|
||||
row.locator(COL_FEE).hover()
|
||||
expect(page.get_by_test_id(FEE_BREAKDOWN_TOOLTIP)).to_have_text(
|
||||
"If the market was activeFee revenue to be received by the maker, takers' fee discounts already applied.During continuous trading the maker pays no infrastructure and liquidity fees.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee-8.28 tDAITotal fees-8.28 tDAI "
|
||||
)
|
||||
@@ -14,7 +14,7 @@ logger = logging.getLogger()
|
||||
@pytest.fixture(scope="class")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@@ -142,7 +142,8 @@ class TestGetStarted:
|
||||
def test_get_started_seen_already(self, simple_market, page: Page):
|
||||
page.goto(f"/#/markets/{simple_market}")
|
||||
get_started_locator = page.get_by_test_id("connect-vega-wallet")
|
||||
page.wait_for_selector('[data-testid="connect-vega-wallet"]', state="attached")
|
||||
page.wait_for_selector(
|
||||
'[data-testid="connect-vega-wallet"]', state="attached")
|
||||
expect(get_started_locator).to_be_enabled
|
||||
expect(get_started_locator).to_be_visible
|
||||
# 0007-FUGS-015
|
||||
@@ -152,9 +153,7 @@ class TestGetStarted:
|
||||
expect(page.get_by_test_id("dialog-content").nth(1)).to_be_visible()
|
||||
|
||||
@pytest.mark.skip("tbd-market-sim")
|
||||
def test_redirect_default_market(
|
||||
self, continuous_market, vega: VegaServiceNull, page: Page
|
||||
):
|
||||
def test_redirect_default_market(self, continuous_market, vega: VegaServiceNull, page: Page):
|
||||
page.goto("/")
|
||||
# 0007-FUGS-012
|
||||
expect(page).to_have_url(
|
||||
|
||||
@@ -8,7 +8,7 @@ from actions.utils import next_epoch, truncate_middle, change_keys
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ from actions.utils import next_epoch
|
||||
@pytest.fixture(scope="class")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ market_title_test_id = "accordion-title"
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ col_market_id = '[col-id="market"] [data-testid="stack-cell-primary"]'
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ COL_ID_FEE = ".ag-center-cols-container [col-id='fee'] .ag-cell-value"
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -7,10 +7,11 @@ from conftest import init_page, init_vega, cleanup_container
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
# we can reuse single page instance in all tests
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
|
||||
@@ -49,7 +49,7 @@ def markets(vega: VegaServiceNull):
|
||||
price=130,
|
||||
)
|
||||
|
||||
vega.forward("2s")
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -63,7 +63,7 @@ def markets(vega: VegaServiceNull):
|
||||
price=88,
|
||||
)
|
||||
|
||||
vega.forward("2s")
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -77,7 +77,7 @@ def markets(vega: VegaServiceNull):
|
||||
price=88,
|
||||
)
|
||||
|
||||
vega.forward("2s")
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -92,7 +92,7 @@ def markets(vega: VegaServiceNull):
|
||||
wait=False,
|
||||
)
|
||||
|
||||
vega.forward("2s")
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -105,7 +105,7 @@ def markets(vega: VegaServiceNull):
|
||||
volume=100,
|
||||
price=104,
|
||||
)
|
||||
vega.forward("2s")
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -120,7 +120,7 @@ def markets(vega: VegaServiceNull):
|
||||
expires_at=vega.get_blockchain_time() + 5 * 1e9,
|
||||
)
|
||||
|
||||
vega.forward("2s")
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -134,7 +134,7 @@ def markets(vega: VegaServiceNull):
|
||||
volume=20,
|
||||
)
|
||||
|
||||
vega.forward("2s")
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -148,7 +148,7 @@ def markets(vega: VegaServiceNull):
|
||||
volume=40,
|
||||
)
|
||||
|
||||
vega.forward("2s")
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -162,7 +162,7 @@ def markets(vega: VegaServiceNull):
|
||||
volume=60,
|
||||
)
|
||||
|
||||
vega.forward("2s")
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -177,7 +177,7 @@ def markets(vega: VegaServiceNull):
|
||||
volume=60,
|
||||
)
|
||||
|
||||
vega.forward("2s")
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -190,7 +190,8 @@ def markets(vega: VegaServiceNull):
|
||||
volume=10,
|
||||
price=150,
|
||||
)
|
||||
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -204,6 +205,7 @@ def markets(vega: VegaServiceNull):
|
||||
price=160,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -217,6 +219,7 @@ def markets(vega: VegaServiceNull):
|
||||
price=60,
|
||||
)
|
||||
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
@@ -392,6 +395,7 @@ def test_order_amend_order(vega: VegaServiceNull, page: Page):
|
||||
page.get_by_role("button", name="Update").click()
|
||||
|
||||
wait_for_toast_confirmation(page, timeout=5000)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
expect(page.locator('[row-index="1"]').first).to_contain_text(
|
||||
@@ -410,6 +414,7 @@ def test_order_cancel_single_order(vega: VegaServiceNull, page: Page):
|
||||
page.get_by_test_id("cancel").first.click()
|
||||
|
||||
wait_for_toast_confirmation(page, timeout=5000)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
expect(page.locator('[row-index="0"]').first).to_contain_text(
|
||||
@@ -429,6 +434,7 @@ def test_order_cancel_all_orders(vega: VegaServiceNull, page: Page):
|
||||
page.get_by_test_id("cancelAll").click()
|
||||
|
||||
wait_for_toast_confirmation(page, timeout=5000)
|
||||
vega.forward("10s")
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ from wallet_config import MM_WALLET, MM_WALLET2
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ class TestPerpetuals:
|
||||
@pytest.fixture(scope="class")
|
||||
def vega(self, request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
|
||||
@@ -12,7 +12,7 @@ COL_ID_USED = ".ag-center-cols-container [col-id='used'] .ag-cell-value"
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ BUY_ORDERS = [[1, 106], [1, 107], [1, 108]]
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
from actions.utils import create_and_faucet_wallet
|
||||
from wallet_config import WalletConfig
|
||||
# region Constants
|
||||
ACTIVITY = "activity"
|
||||
HOARDER = "hoarder"
|
||||
COMBO = "combo"
|
||||
|
||||
REWARDS_URL = "/#/rewards"
|
||||
|
||||
# test IDs
|
||||
COMBINED_MULTIPLIERS = "combined-multipliers"
|
||||
TOTAL_REWARDS = "total-rewards"
|
||||
PRICE_TAKING_COL_ID = '[col-id="priceTaking"]'
|
||||
TOTAL_COL_ID = '[col-id="total"]'
|
||||
ROW = "row"
|
||||
STREAK_REWARD_MULTIPLIER_VALUE = "streak-reward-multiplier-value"
|
||||
HOARDER_REWARD_MULTIPLIER_VALUE = "hoarder-reward-multiplier-value"
|
||||
HOARDER_BONUS_TOTAL_HOARDED = "hoarder-bonus-total-hoarded"
|
||||
EARNED_BY_ME_BUTTON = "earned-by-me-button"
|
||||
TRANSFER_AMOUNT = "transfer-amount"
|
||||
EPOCH_STREAK = "epoch-streak"
|
||||
|
||||
# endregion
|
||||
|
||||
# Keys
|
||||
PARTY_A = "PARTY_A"
|
||||
PARTY_B = "PARTY_B"
|
||||
PARTY_C = "PARTY_C"
|
||||
PARTY_D = "PARTY_D"
|
||||
|
||||
ACTIVITY_STREAKS = """
|
||||
{
|
||||
"tiers": [
|
||||
{
|
||||
"minimum_activity_streak": 2,
|
||||
"reward_multiplier": "2.0",
|
||||
"vesting_multiplier": "1.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
VESTING = """
|
||||
{
|
||||
"tiers": [
|
||||
{
|
||||
"minimum_quantum_balance": "10000000",
|
||||
"reward_multiplier": "2"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
def keys(vega):
|
||||
PARTY_A = WalletConfig("PARTY_A", "PARTY_A")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_A)
|
||||
PARTY_B = WalletConfig("PARTY_B", "PARTY_B")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_B)
|
||||
PARTY_C = WalletConfig("PARTY_C", "PARTY_C")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_C)
|
||||
PARTY_D = WalletConfig("PARTY_D", "PARTY_D")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_D)
|
||||
return PARTY_A, PARTY_B, PARTY_C, PARTY_D
|
||||
@@ -1,121 +0,0 @@
|
||||
import pytest
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from rewards_test_ids import *
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup, risk_accepted_setup, cleanup_container
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega, PARTY_B)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_reward_program(vega: VegaServiceNull):
|
||||
tDAI_market = setup_continuous_market(vega)
|
||||
PARTY_A, PARTY_B, PARTY_C, PARTY_D = keys(vega)
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_C.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_D.name, asset=tDAI_asset_id, amount=100000)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.vesting.benefitTiers",
|
||||
new_value=VESTING,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||
)
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.recurring_transfer(
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_A.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_0")
|
||||
def test_network_reward_pot(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text("50.00 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_0")
|
||||
def test_reward_multiplier(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text("1x")
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_0")
|
||||
def test_hoarder_bonus(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(HOARDER_BONUS_TOTAL_HOARDED)).to_contain_text(
|
||||
"5,000,000"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_0")
|
||||
def test_reward_history(
|
||||
page: Page,
|
||||
):
|
||||
page.locator('[name="fromEpoch"]').fill("1")
|
||||
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
||||
"100.00100.00%"
|
||||
)
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("100.00")
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("50.00")
|
||||
@@ -1,173 +0,0 @@
|
||||
import pytest
|
||||
from rewards_test_ids import *
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup, risk_accepted_setup, cleanup_container
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega, PARTY_B)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_reward_program(vega: VegaServiceNull):
|
||||
tDAI_market = setup_continuous_market(vega)
|
||||
PARTY_A, PARTY_B, PARTY_C, PARTY_D = keys(vega)
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_C.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_D.name, asset=tDAI_asset_id, amount=100000)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.vesting.benefitTiers",
|
||||
new_value=VESTING,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||
)
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.recurring_transfer(
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_A.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_LIMIT",
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
side="SIDE_BUY",
|
||||
price=1,
|
||||
volume=1,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_1")
|
||||
def test_network_reward_pot(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text("166.66666 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_1")
|
||||
def test_reward_multiplier(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text("2x")
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text("2x")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_1")
|
||||
def test_hoarder_bonus(page: Page):
|
||||
expect(page.get_by_test_id(HOARDER_BONUS_TOTAL_HOARDED)).to_contain_text(
|
||||
"16,666,666"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_hoarder_tier_1")
|
||||
def test_reward_history(page: Page):
|
||||
page.locator('[name="fromEpoch"]').fill("1")
|
||||
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
||||
"299.99999100.00%"
|
||||
)
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(
|
||||
"299.99999"
|
||||
)
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(
|
||||
"166.66666"
|
||||
)
|
||||
@@ -0,0 +1,475 @@
|
||||
import pytest
|
||||
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup, cleanup_container
|
||||
from fixtures.market import setup_continuous_market, market_exists
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET, PARTY_A, PARTY_B, PARTY_C, PARTY_D
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
# region Constants
|
||||
ACTIVITY = "activity"
|
||||
HOARDER = "hoarder"
|
||||
COMBO = "combo"
|
||||
|
||||
REWARDS_URL = "/#/rewards"
|
||||
|
||||
# test IDs
|
||||
COMBINED_MULTIPLIERS = "combined-multipliers"
|
||||
TOTAL_REWARDS = "total-rewards"
|
||||
PRICE_TAKING_COL_ID = '[col-id="priceTaking"]'
|
||||
TOTAL_COL_ID = '[col-id="total"]'
|
||||
ROW = "row"
|
||||
STREAK_REWARD_MULTIPLIER_VALUE = "streak-reward-multiplier-value"
|
||||
HOARDER_REWARD_MULTIPLIER_VALUE = "hoarder-reward-multiplier-value"
|
||||
HOARDER_BONUS_TOTAL_HOARDED = "hoarder-bonus-total-hoarded"
|
||||
EARNED_BY_ME_BUTTON = "earned-by-me-button"
|
||||
TRANSFER_AMOUNT = "transfer-amount"
|
||||
EPOCH_STREAK = "epoch-streak"
|
||||
|
||||
# endregion
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def market_ids():
|
||||
return {
|
||||
"vega_activity_tier_0": "default_id",
|
||||
"vega_hoarder_tier_0": "default_id",
|
||||
"vega_combo_tier_0": "default_id",
|
||||
"vega_activity_tier_1": "default_id",
|
||||
"vega_hoarder_tier_1": "default_id",
|
||||
"vega_combo_tier_1": "default_id",
|
||||
}
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_activity_tier_0(request):
|
||||
with init_vega(request) as vega_activity_tier_0:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_activity_tier_0)) # Register the cleanup function
|
||||
yield vega_activity_tier_0
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_hoarder_tier_0(request):
|
||||
with init_vega(request) as vega_hoarder_tier_0:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_hoarder_tier_0)) # Register the cleanup function
|
||||
yield vega_hoarder_tier_0
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_combo_tier_0(request):
|
||||
with init_vega(request) as vega_combo_tier_0:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_combo_tier_0)) # Register the cleanup function
|
||||
yield vega_combo_tier_0
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_activity_tier_1(request):
|
||||
with init_vega(request) as vega_activity_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_activity_tier_1)) # Register the cleanup function
|
||||
yield vega_activity_tier_1
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_hoarder_tier_1(request):
|
||||
with init_vega(request) as vega_hoarder_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_hoarder_tier_1)) # Register the cleanup function
|
||||
yield vega_hoarder_tier_1
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_combo_tier_1(request):
|
||||
with init_vega(request) as vega_combo_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_combo_tier_1)) # Register the cleanup function
|
||||
yield vega_combo_tier_1
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def auth(vega_instance, page):
|
||||
return auth_setup(vega_instance, page)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def page(vega_instance, browser, request):
|
||||
with init_page(vega_instance, browser, request) as page_instance:
|
||||
yield page_instance
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def vega_instance(
|
||||
reward_program,
|
||||
vega_activity_tier_0,
|
||||
vega_hoarder_tier_0,
|
||||
vega_combo_tier_0,
|
||||
vega_activity_tier_1,
|
||||
vega_hoarder_tier_1,
|
||||
vega_combo_tier_1,
|
||||
tier,
|
||||
):
|
||||
if reward_program == "activity":
|
||||
return vega_activity_tier_0 if tier == 1 else vega_activity_tier_1
|
||||
elif reward_program == "hoarder":
|
||||
return vega_hoarder_tier_0 if tier == 1 else vega_hoarder_tier_1
|
||||
elif reward_program == "combo":
|
||||
return vega_combo_tier_0 if tier == 1 else vega_combo_tier_1
|
||||
|
||||
|
||||
def setup_market_with_reward_program(vega: VegaServiceNull, reward_programs, tier):
|
||||
print(f"Started setup_market_with_{reward_programs}_{tier}")
|
||||
tDAI_market = setup_continuous_market(vega)
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_C.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_D.name, asset=tDAI_asset_id, amount=100000)
|
||||
next_epoch(vega=vega)
|
||||
if ACTIVITY in reward_programs:
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.activityStreak.benefitTiers",
|
||||
new_value=ACTIVITY_STREAKS,
|
||||
)
|
||||
print("update_network_parameter activity done")
|
||||
next_epoch(vega=vega)
|
||||
|
||||
if HOARDER in reward_programs:
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.vesting.benefitTiers",
|
||||
new_value=VESTING,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||
)
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.recurring_transfer(
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
# lock_period= 5,
|
||||
# TODO test lock period
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_A.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
|
||||
vega.wait_for_total_catchup()
|
||||
if tier == 1:
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_LIMIT",
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
side="SIDE_BUY",
|
||||
price=1,
|
||||
volume=1,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
if HOARDER in reward_programs:
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
def set_market_reward_program(vega, reward_program, market_ids, tier):
|
||||
market_id_key = f"vega_{reward_program}_tier_{tier}"
|
||||
if reward_program == COMBO:
|
||||
market_id_key = COMBO
|
||||
market_id = market_ids.get(market_id_key, "default_id")
|
||||
|
||||
print(f"Checking if market exists: {market_id}")
|
||||
if not market_exists(vega, market_id):
|
||||
print(
|
||||
f"Market doesn't exist for {reward_program} {tier}. Setting up new market."
|
||||
)
|
||||
|
||||
reward_programs = [reward_program]
|
||||
if reward_program == COMBO:
|
||||
reward_programs = [ACTIVITY, HOARDER]
|
||||
|
||||
market_id, _ = setup_market_with_reward_program(vega, reward_programs, tier)
|
||||
market_ids[market_id_key] = market_id
|
||||
|
||||
return market_id, market_ids
|
||||
|
||||
|
||||
ACTIVITY_STREAKS = """
|
||||
{
|
||||
"tiers": [
|
||||
{
|
||||
"minimum_activity_streak": 2,
|
||||
"reward_multiplier": "2.0",
|
||||
"vesting_multiplier": "1.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
VESTING = """
|
||||
{
|
||||
"tiers": [
|
||||
{
|
||||
"minimum_quantum_balance": "10000000",
|
||||
"reward_multiplier": "2"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, total_rewards",
|
||||
[
|
||||
(ACTIVITY, 0, "50.00 tDAI"),
|
||||
(HOARDER, 0, "50.00 tDAI"),
|
||||
(COMBO, 0, "50.00 tDAI"),
|
||||
(ACTIVITY, 1, "116.66666 tDAI"),
|
||||
(HOARDER, 1, "166.66666 tDAI "),
|
||||
(COMBO, 1, "183.33333 tDAI"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_network_reward_pot(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
total_rewards,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text(total_rewards)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, reward_multiplier, streak_multiplier, hoarder_multiplier",
|
||||
[
|
||||
(ACTIVITY, 0, "1x", "1x", "1x"),
|
||||
(HOARDER, 0, "1x", "1x", "1x"),
|
||||
(COMBO, 0, "1x", "1x", "1x"),
|
||||
(ACTIVITY, 1, "2x", "2x", "1x"),
|
||||
(HOARDER, 1, "2x", "1x", "2x"),
|
||||
(COMBO, 1, "4x", "2x", "2x"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_reward_multiplier(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
reward_multiplier,
|
||||
streak_multiplier,
|
||||
hoarder_multiplier,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text(reward_multiplier)
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text(
|
||||
streak_multiplier
|
||||
)
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text(
|
||||
hoarder_multiplier
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, epoch_streak",
|
||||
[
|
||||
(ACTIVITY, 0, "1"),
|
||||
(ACTIVITY, 1, "7"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_activity_streak(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
epoch_streak,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
if tier == 1:
|
||||
expect(page.get_by_test_id(EPOCH_STREAK)).to_have_text(
|
||||
"Active trader: " + epoch_streak + " epochs so far (Tier 1 as of last epoch)"
|
||||
)
|
||||
else:
|
||||
expect(page.get_by_test_id(EPOCH_STREAK)).to_have_text(
|
||||
"Active trader: " + epoch_streak + " epochs so far "
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, rewards_hoarded",
|
||||
[
|
||||
(HOARDER, 0, "5,000,000"),
|
||||
(HOARDER, 1, "16,666,666"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_hoarder_bonus(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
rewards_hoarded,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
expect(page.get_by_test_id(HOARDER_BONUS_TOTAL_HOARDED)).to_contain_text(
|
||||
rewards_hoarded
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier, price_taking, total, earned_by_me",
|
||||
[
|
||||
(ACTIVITY, 0, "100.00100.00%", "100.00", "50.00"),
|
||||
(HOARDER, 0, "100.00100.00%", "100.00", "50.00"),
|
||||
(COMBO, 0, "100.00100.00%", "100.00", "50.00"),
|
||||
(ACTIVITY, 1, "300.00100.00%", "300.00", "116.66666"),
|
||||
(HOARDER, 1, "299.99999100.00%", "299.99999", "166.66666"),
|
||||
(COMBO, 1, "299.99999100.00%", "299.99999", "183.33333"),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_reward_history(
|
||||
reward_program,
|
||||
vega_instance: VegaServiceNull,
|
||||
page: Page,
|
||||
price_taking,
|
||||
total,
|
||||
earned_by_me,
|
||||
tier,
|
||||
market_ids,
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
page.locator('[name="fromEpoch"]').fill("1")
|
||||
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
||||
price_taking
|
||||
)
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(total)
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(
|
||||
earned_by_me
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"reward_program, tier",
|
||||
[
|
||||
(ACTIVITY, 1),
|
||||
],
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
|
||||
def test_redeem(
|
||||
reward_program, vega_instance: VegaServiceNull, page: Page, tier, market_ids
|
||||
):
|
||||
print("reward program: " + reward_program, " tier:", tier)
|
||||
market_id, market_ids = set_market_reward_program(
|
||||
vega_instance, reward_program, market_ids, tier
|
||||
)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega_instance, PARTY_B.name)
|
||||
page.get_by_test_id("redeem-rewards-button").click()
|
||||
available_to_withdraw = page.get_by_test_id(
|
||||
"available-to-withdraw-value"
|
||||
).text_content()
|
||||
option_value = page.locator(
|
||||
'[data-testid="transfer-form"] [name="fromAccount"] option[value^="ACCOUNT_TYPE_VESTED_REWARDS"]'
|
||||
).first.get_attribute("value")
|
||||
|
||||
page.select_option(
|
||||
'[data-testid="transfer-form"] [name="fromAccount"]', option_value
|
||||
)
|
||||
|
||||
page.get_by_test_id("use-max-button").first.click()
|
||||
expect(page.get_by_test_id(TRANSFER_AMOUNT)).to_have_text(available_to_withdraw)
|
||||
@@ -1,27 +1,49 @@
|
||||
import pytest
|
||||
from rewards_test_ids import *
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import (
|
||||
init_vega,
|
||||
init_page,
|
||||
auth_setup,
|
||||
risk_accepted_setup,
|
||||
cleanup_container,
|
||||
)
|
||||
from conftest import init_vega, init_page, auth_setup, risk_accepted_setup, cleanup_container
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET
|
||||
from actions.utils import next_epoch, change_keys, create_and_faucet_wallet
|
||||
from wallet_config import MM_WALLET, WalletConfig
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
# region Constants
|
||||
ACTIVITY = "activity"
|
||||
HOARDER = "hoarder"
|
||||
COMBO = "combo"
|
||||
|
||||
REWARDS_URL = "/#/rewards"
|
||||
|
||||
# test IDs
|
||||
COMBINED_MULTIPLIERS = "combined-multipliers"
|
||||
TOTAL_REWARDS = "total-rewards"
|
||||
PRICE_TAKING_COL_ID = '[col-id="priceTaking"]'
|
||||
TOTAL_COL_ID = '[col-id="total"]'
|
||||
ROW = "row"
|
||||
STREAK_REWARD_MULTIPLIER_VALUE = "streak-reward-multiplier-value"
|
||||
HOARDER_REWARD_MULTIPLIER_VALUE = "hoarder-reward-multiplier-value"
|
||||
HOARDER_BONUS_TOTAL_HOARDED = "hoarder-bonus-total-hoarded"
|
||||
EARNED_BY_ME_BUTTON = "earned-by-me-button"
|
||||
TRANSFER_AMOUNT = "transfer-amount"
|
||||
EPOCH_STREAK = "epoch-streak"
|
||||
|
||||
# endregion
|
||||
|
||||
# Keys
|
||||
PARTY_A = "PARTY_A"
|
||||
PARTY_B = "PARTY_B"
|
||||
PARTY_C = "PARTY_C"
|
||||
PARTY_D = "PARTY_D"
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
@@ -84,31 +106,55 @@ def setup_market_with_reward_program(vega: VegaServiceNull):
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
ACTIVITY_STREAKS = """
|
||||
{
|
||||
"tiers": [
|
||||
{
|
||||
"minimum_activity_streak": 2,
|
||||
"reward_multiplier": "2.0",
|
||||
"vesting_multiplier": "1.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def keys(vega):
|
||||
PARTY_A = WalletConfig("PARTY_A", "PARTY_A")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_A)
|
||||
PARTY_B = WalletConfig("PARTY_B", "PARTY_B")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_B)
|
||||
PARTY_C = WalletConfig("PARTY_C", "PARTY_C")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_C)
|
||||
PARTY_D = WalletConfig("PARTY_D", "PARTY_D")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_D)
|
||||
return PARTY_A, PARTY_B, PARTY_C, PARTY_D
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_0")
|
||||
def test_network_reward_pot(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text("50.00 tDAI")
|
||||
page.pause()
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_0")
|
||||
def test_reward_multiplier(
|
||||
page: Page,
|
||||
):
|
||||
page.pause()
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text("1x")
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
|
||||
|
||||
""" @pytest.mark.xdist_group(name="test_rewards_activity_tier_0")
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_0")
|
||||
def test_activity_streak(
|
||||
page: Page,
|
||||
):
|
||||
@@ -128,4 +174,3 @@ def test_reward_history(
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("100.00")
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("50.00")
|
||||
"""
|
||||
@@ -1,187 +0,0 @@
|
||||
import pytest
|
||||
from rewards_test_ids import *
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup, risk_accepted_setup, cleanup_container
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega, PARTY_B)
|
||||
yield page
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_reward_program(vega: VegaServiceNull):
|
||||
tDAI_market = setup_continuous_market(vega)
|
||||
PARTY_A, PARTY_B, PARTY_C, PARTY_D = keys(vega)
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_C.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_D.name, asset=tDAI_asset_id, amount=100000)
|
||||
next_epoch(vega=vega)
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.activityStreak.benefitTiers",
|
||||
new_value=ACTIVITY_STREAKS,
|
||||
)
|
||||
print("update_network_parameter activity done")
|
||||
next_epoch(vega=vega)
|
||||
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||
)
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.recurring_transfer(
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
# lock_period= 5,
|
||||
# TODO test lock period
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_A.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_LIMIT",
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
side="SIDE_BUY",
|
||||
price=1,
|
||||
volume=1,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_1")
|
||||
def test_network_reward_pot(page: Page):
|
||||
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text("116.66666 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_1")
|
||||
def test_reward_multiplier(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text("2x")
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text("2x")
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_1")
|
||||
def test_activity_streak(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(EPOCH_STREAK)).to_have_text(
|
||||
"Active trader: 7 epochs so far (Tier 1 as of last epoch)"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_1")
|
||||
def test_reward_history(
|
||||
page: Page,
|
||||
):
|
||||
page.locator('[name="fromEpoch"]').fill("1")
|
||||
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
||||
"300.00100.00%"
|
||||
)
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("300.00")
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(
|
||||
"116.66666"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_1")
|
||||
def test_redeem(
|
||||
page: Page,
|
||||
):
|
||||
page.get_by_test_id("redeem-rewards-button").click()
|
||||
available_to_withdraw = page.get_by_test_id(
|
||||
"available-to-withdraw-value"
|
||||
).text_content()
|
||||
option_value = page.locator(
|
||||
'[data-testid="transfer-form"] [name="fromAccount"] option[value^="ACCOUNT_TYPE_VESTED_REWARDS"]'
|
||||
).first.get_attribute("value")
|
||||
|
||||
page.select_option(
|
||||
'[data-testid="transfer-form"] [name="fromAccount"]', option_value
|
||||
)
|
||||
|
||||
page.get_by_test_id("use-max-button").first.click()
|
||||
expect(page.get_by_test_id(TRANSFER_AMOUNT)).to_have_text(available_to_withdraw)
|
||||
@@ -1,174 +0,0 @@
|
||||
import pytest
|
||||
from rewards_test_ids import *
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup, risk_accepted_setup, cleanup_container
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega, PARTY_B)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_reward_program(vega: VegaServiceNull):
|
||||
tDAI_market = setup_continuous_market(vega)
|
||||
PARTY_A, PARTY_B, PARTY_C, PARTY_D = keys(vega)
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_C.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_D.name, asset=tDAI_asset_id, amount=100000)
|
||||
next_epoch(vega=vega)
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.activityStreak.benefitTiers",
|
||||
new_value=ACTIVITY_STREAKS,
|
||||
)
|
||||
print("update_network_parameter activity done")
|
||||
next_epoch(vega=vega)
|
||||
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.vesting.benefitTiers",
|
||||
new_value=VESTING,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||
)
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.recurring_transfer(
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_A.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_LIMIT",
|
||||
time_in_force="TIME_IN_FORCE_GTC",
|
||||
side="SIDE_BUY",
|
||||
price=1,
|
||||
volume=1,
|
||||
)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_D.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_for_total_catchup()
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_combo_tier_1")
|
||||
def test_network_reward_pot( page: Page
|
||||
):
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text("183.33333 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_combo_tier_1")
|
||||
def test_reward_multiplier(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text("4x")
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text(
|
||||
"2x"
|
||||
)
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text(
|
||||
"2x"
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_combo_tier_1")
|
||||
def test_reward_history(
|
||||
page: Page,
|
||||
):
|
||||
page.locator('[name="fromEpoch"]').fill("1")
|
||||
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
||||
"299.99999100.00%"
|
||||
)
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("299.99999")
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(
|
||||
"183.33333"
|
||||
)
|
||||
@@ -43,7 +43,6 @@ def test_vesting(continuous_market, vega: VegaServiceNull, page: Page):
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
page.goto("/#/rewards")
|
||||
|
||||
@@ -6,7 +6,7 @@ from conftest import init_vega, cleanup_container
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(
|
||||
lambda: cleanup_container(vega_instance)
|
||||
)
|
||||
) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
@@ -242,12 +242,12 @@ def test_team_page_headline(team_page: Page, setup_teams_and_games):
|
||||
expect(team_page.get_by_test_id("team-name")).to_have_text(team_name)
|
||||
expect(team_page.get_by_test_id("members-count-stat")).to_have_text("4")
|
||||
|
||||
expect(team_page.get_by_test_id("total-games-stat")).to_have_text("1")
|
||||
expect(team_page.get_by_test_id("total-games-stat")).to_have_text("2")
|
||||
|
||||
# TODO this still seems wrong as its always 0
|
||||
expect(team_page.get_by_test_id("total-volume-stat")).to_have_text("0")
|
||||
|
||||
expect(team_page.get_by_test_id("rewards-paid-stat")).to_have_text("500")
|
||||
expect(team_page.get_by_test_id("rewards-paid-stat")).to_have_text("1.2k")
|
||||
|
||||
|
||||
def test_switch_teams(team_page: Page, vega: VegaServiceNull):
|
||||
@@ -264,18 +264,19 @@ def test_switch_teams(team_page: Page, vega: VegaServiceNull):
|
||||
def test_leaderboard(competitions_page: Page, setup_teams_and_games):
|
||||
team_name = setup_teams_and_games["team_name"]
|
||||
competitions_page.reload()
|
||||
competitions_page.pause()
|
||||
expect(
|
||||
competitions_page.get_by_test_id("rank-0").locator(".text-yellow-300")
|
||||
).to_have_count(1)
|
||||
expect(
|
||||
competitions_page.get_by_test_id("rank-1").locator(".text-vega-clight-500")
|
||||
).to_have_count(1)
|
||||
expect(competitions_page.get_by_test_id("team-1")).to_have_text(team_name)
|
||||
expect(competitions_page.get_by_test_id("team-0")).to_have_text(team_name)
|
||||
expect(competitions_page.get_by_test_id("status-1")).to_have_text("Open")
|
||||
|
||||
# FIXME: the numbers are different we need to clarify this with the backend
|
||||
# expect(competitions_page.get_by_test_id("earned-1")).to_have_text("160")
|
||||
expect(competitions_page.get_by_test_id("games-1")).to_have_text("1")
|
||||
expect(competitions_page.get_by_test_id("games-1")).to_have_text("2")
|
||||
|
||||
# TODO still odd that this is 0
|
||||
expect(competitions_page.get_by_test_id("volume-0")).to_have_text("0")
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
import compact from 'lodash/compact';
|
||||
import { useActiveRewardsQuery } from '../../components/rewards-container/__generated__/Rewards';
|
||||
import { isActiveReward } from '../../components/rewards-container/active-rewards';
|
||||
import {
|
||||
type RecurringTransfer,
|
||||
type TransferNode,
|
||||
EntityScope,
|
||||
IndividualScope,
|
||||
} from '@vegaprotocol/types';
|
||||
import {
|
||||
type AssetFieldsFragment,
|
||||
useAssetsMapProvider,
|
||||
} from '@vegaprotocol/assets';
|
||||
import {
|
||||
type MarketFieldsFragment,
|
||||
useMarketsMapProvider,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { type ApolloError } from '@apollo/client';
|
||||
|
||||
export type EnrichedTransfer = TransferNode & {
|
||||
asset?: AssetFieldsFragment | null;
|
||||
markets?: (MarketFieldsFragment | null)[];
|
||||
};
|
||||
|
||||
type RecurringTransferKind = EnrichedTransfer & {
|
||||
transfer: {
|
||||
kind: RecurringTransfer;
|
||||
};
|
||||
};
|
||||
|
||||
export const isScopedToTeams = (
|
||||
node: TransferNode
|
||||
): node is RecurringTransferKind =>
|
||||
node.transfer.kind.__typename === 'RecurringTransfer' &&
|
||||
// scoped to teams
|
||||
(node.transfer.kind.dispatchStrategy?.entityScope ===
|
||||
EntityScope.ENTITY_SCOPE_TEAMS ||
|
||||
// or to individuals
|
||||
(node.transfer.kind.dispatchStrategy?.entityScope ===
|
||||
EntityScope.ENTITY_SCOPE_INDIVIDUALS &&
|
||||
// but they have to be in a team
|
||||
node.transfer.kind.dispatchStrategy.individualScope ===
|
||||
IndividualScope.INDIVIDUAL_SCOPE_IN_TEAM));
|
||||
|
||||
export const useGameCards = ({
|
||||
currentEpoch,
|
||||
onlyActive,
|
||||
}: {
|
||||
currentEpoch: number;
|
||||
onlyActive: boolean;
|
||||
}): { data: EnrichedTransfer[]; loading: boolean; error?: ApolloError } => {
|
||||
const { data, loading, error } = useActiveRewardsQuery({
|
||||
variables: {
|
||||
isReward: true,
|
||||
},
|
||||
fetchPolicy: 'cache-and-network',
|
||||
});
|
||||
|
||||
const { data: assets, loading: assetsLoading } = useAssetsMapProvider();
|
||||
const { data: markets, loading: marketsLoading } = useMarketsMapProvider();
|
||||
|
||||
const games = compact(data?.transfersConnection?.edges?.map((n) => n?.node))
|
||||
.map((n) => n as TransferNode)
|
||||
.filter((node) => {
|
||||
const active = onlyActive ? isActiveReward(node, currentEpoch) : true;
|
||||
return active && isScopedToTeams(node);
|
||||
})
|
||||
.map((node) => {
|
||||
if (node.transfer.kind.__typename !== 'RecurringTransfer') {
|
||||
return node;
|
||||
}
|
||||
|
||||
const asset =
|
||||
assets &&
|
||||
assets[
|
||||
node.transfer.kind.dispatchStrategy?.dispatchMetricAssetId || ''
|
||||
];
|
||||
|
||||
const marketsInScope =
|
||||
node.transfer.kind.dispatchStrategy?.marketIdsInScope?.map(
|
||||
(id) => markets && markets[id]
|
||||
);
|
||||
|
||||
return { ...node, asset, markets: marketsInScope };
|
||||
});
|
||||
|
||||
return {
|
||||
data: games,
|
||||
loading: loading || assetsLoading || marketsLoading,
|
||||
error,
|
||||
};
|
||||
};
|
||||
@@ -1,242 +0,0 @@
|
||||
import {
|
||||
type DispatchStrategy,
|
||||
type TransferNode,
|
||||
EntityScope,
|
||||
type TransferKind,
|
||||
TransferStatus,
|
||||
IndividualScope,
|
||||
} from '@vegaprotocol/types';
|
||||
import {
|
||||
type RewardTransfer,
|
||||
isActiveReward,
|
||||
isReward,
|
||||
isScopedToTeams,
|
||||
} from './use-rewards';
|
||||
|
||||
const makeDispatchStrategy = (
|
||||
entityScope: EntityScope,
|
||||
individualScope?: IndividualScope
|
||||
): DispatchStrategy =>
|
||||
({
|
||||
entityScope,
|
||||
individualScope,
|
||||
} as DispatchStrategy);
|
||||
|
||||
const makeReward = (
|
||||
status: TransferStatus,
|
||||
startEpoch: number,
|
||||
endEpoch?: number,
|
||||
dispatchStrategy?: DispatchStrategy,
|
||||
kind: TransferKind['__typename'] = 'OneOffTransfer'
|
||||
): RewardTransfer =>
|
||||
({
|
||||
transfer: {
|
||||
status,
|
||||
kind: {
|
||||
__typename: kind,
|
||||
dispatchStrategy,
|
||||
startEpoch,
|
||||
endEpoch,
|
||||
},
|
||||
},
|
||||
} as RewardTransfer);
|
||||
|
||||
describe('isReward', () => {
|
||||
it.each([
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
1,
|
||||
undefined,
|
||||
makeDispatchStrategy(EntityScope.ENTITY_SCOPE_TEAMS),
|
||||
'RecurringTransfer'
|
||||
),
|
||||
true,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
1,
|
||||
undefined,
|
||||
makeDispatchStrategy(EntityScope.ENTITY_SCOPE_INDIVIDUALS),
|
||||
'RecurringTransfer'
|
||||
),
|
||||
true,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
1,
|
||||
undefined,
|
||||
undefined,
|
||||
'RecurringTransfer'
|
||||
),
|
||||
false,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
1,
|
||||
undefined,
|
||||
makeDispatchStrategy(EntityScope.ENTITY_SCOPE_TEAMS),
|
||||
'OneOffTransfer'
|
||||
),
|
||||
false,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
1,
|
||||
undefined,
|
||||
makeDispatchStrategy(EntityScope.ENTITY_SCOPE_INDIVIDUALS),
|
||||
'OneOffTransfer'
|
||||
),
|
||||
false,
|
||||
],
|
||||
])('checks if given transfer is a reward or not', (input, output) => {
|
||||
expect(isReward(input as TransferNode)).toEqual(output);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isActiveReward', () => {
|
||||
it.each([
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
1,
|
||||
undefined,
|
||||
makeDispatchStrategy(EntityScope.ENTITY_SCOPE_TEAMS),
|
||||
'RecurringTransfer'
|
||||
),
|
||||
true,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
2,
|
||||
undefined,
|
||||
makeDispatchStrategy(EntityScope.ENTITY_SCOPE_TEAMS),
|
||||
'RecurringTransfer'
|
||||
),
|
||||
true,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
3,
|
||||
undefined,
|
||||
makeDispatchStrategy(EntityScope.ENTITY_SCOPE_TEAMS),
|
||||
'RecurringTransfer'
|
||||
),
|
||||
true,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
4, // start in 1 epoch
|
||||
undefined,
|
||||
makeDispatchStrategy(EntityScope.ENTITY_SCOPE_TEAMS),
|
||||
'RecurringTransfer'
|
||||
),
|
||||
false,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_DONE, // done, not active any more
|
||||
1,
|
||||
undefined,
|
||||
makeDispatchStrategy(EntityScope.ENTITY_SCOPE_TEAMS),
|
||||
'RecurringTransfer'
|
||||
),
|
||||
false,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
1,
|
||||
2, // ended 1 epoch ago
|
||||
makeDispatchStrategy(EntityScope.ENTITY_SCOPE_TEAMS),
|
||||
'RecurringTransfer'
|
||||
),
|
||||
false,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
1,
|
||||
3, // ends now, but active until end of epoch
|
||||
makeDispatchStrategy(EntityScope.ENTITY_SCOPE_TEAMS),
|
||||
'RecurringTransfer'
|
||||
),
|
||||
true,
|
||||
],
|
||||
])('checks if given reward is active or not', (input, output) => {
|
||||
expect(isActiveReward(input, 3)).toEqual(output);
|
||||
});
|
||||
});
|
||||
|
||||
describe('isScopedToTeams', () => {
|
||||
it.each([
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
1,
|
||||
undefined,
|
||||
makeDispatchStrategy(EntityScope.ENTITY_SCOPE_TEAMS), // only teams
|
||||
'RecurringTransfer'
|
||||
),
|
||||
true,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
1,
|
||||
undefined,
|
||||
makeDispatchStrategy(
|
||||
EntityScope.ENTITY_SCOPE_INDIVIDUALS,
|
||||
IndividualScope.INDIVIDUAL_SCOPE_IN_TEAM // individual in teams
|
||||
),
|
||||
'RecurringTransfer'
|
||||
),
|
||||
true,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
1,
|
||||
undefined,
|
||||
makeDispatchStrategy(EntityScope.ENTITY_SCOPE_INDIVIDUALS), // not in team
|
||||
'RecurringTransfer'
|
||||
),
|
||||
false,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
1,
|
||||
undefined,
|
||||
makeDispatchStrategy(
|
||||
EntityScope.ENTITY_SCOPE_INDIVIDUALS,
|
||||
IndividualScope.INDIVIDUAL_SCOPE_ALL // not only in team
|
||||
),
|
||||
'RecurringTransfer'
|
||||
),
|
||||
false,
|
||||
],
|
||||
[
|
||||
makeReward(
|
||||
TransferStatus.STATUS_PENDING,
|
||||
1,
|
||||
undefined,
|
||||
makeDispatchStrategy(
|
||||
EntityScope.ENTITY_SCOPE_INDIVIDUALS,
|
||||
IndividualScope.INDIVIDUAL_SCOPE_NOT_IN_TEAM // not in team
|
||||
),
|
||||
'RecurringTransfer'
|
||||
),
|
||||
false,
|
||||
],
|
||||
])('checks if given reward is scoped to teams or not', (input, output) => {
|
||||
expect(isScopedToTeams(input)).toEqual(output);
|
||||
});
|
||||
});
|
||||
@@ -1,181 +0,0 @@
|
||||
import {
|
||||
type AssetFieldsFragment,
|
||||
useAssetsMapProvider,
|
||||
} from '@vegaprotocol/assets';
|
||||
import { useActiveRewardsQuery } from './__generated__/Rewards';
|
||||
import {
|
||||
type MarketFieldsFragment,
|
||||
useMarketsMapProvider,
|
||||
getAsset,
|
||||
} from '@vegaprotocol/markets';
|
||||
import {
|
||||
type RecurringTransfer,
|
||||
type TransferNode,
|
||||
TransferStatus,
|
||||
type DispatchStrategy,
|
||||
EntityScope,
|
||||
IndividualScope,
|
||||
MarketState,
|
||||
} from '@vegaprotocol/types';
|
||||
import { type ApolloError } from '@apollo/client';
|
||||
import compact from 'lodash/compact';
|
||||
import { useEpochInfoQuery } from './__generated__/Epoch';
|
||||
|
||||
export type RewardTransfer = TransferNode & {
|
||||
transfer: {
|
||||
kind: RecurringTransfer & {
|
||||
dispatchStrategy: DispatchStrategy;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export type EnrichedRewardTransfer = RewardTransfer & {
|
||||
/** Dispatch metric asset (reward asset) */
|
||||
asset?: AssetFieldsFragment;
|
||||
/** A flag determining whether a reward asset is being traded on any of the active markets */
|
||||
isAssetTraded?: boolean;
|
||||
/** A list of markets in scope */
|
||||
markets?: MarketFieldsFragment[];
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if given transfer is a reward.
|
||||
*
|
||||
* A reward has to be a recurring transfer and has to have a
|
||||
* dispatch strategy.
|
||||
*/
|
||||
export const isReward = (node: TransferNode): node is RewardTransfer => {
|
||||
if (
|
||||
node.transfer.kind.__typename === 'RecurringTransfer' &&
|
||||
node.transfer.kind.dispatchStrategy != null
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if given reward (transfer) is active.
|
||||
*/
|
||||
export const isActiveReward = (node: RewardTransfer, currentEpoch: number) => {
|
||||
const { transfer } = node;
|
||||
|
||||
const pending = transfer.status === TransferStatus.STATUS_PENDING;
|
||||
const withinEpochs =
|
||||
transfer.kind.startEpoch <= currentEpoch &&
|
||||
(transfer.kind.endEpoch != null
|
||||
? transfer.kind.endEpoch >= currentEpoch
|
||||
: true);
|
||||
|
||||
if (pending && withinEpochs) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if given reward (transfer) is scoped to teams.
|
||||
*
|
||||
* A reward is scoped to teams if it's entity scope is set to teams or
|
||||
* if the scope is set to individuals but the individuals are in a team.
|
||||
*/
|
||||
export const isScopedToTeams = (node: EnrichedRewardTransfer) =>
|
||||
// scoped to teams
|
||||
node.transfer.kind.dispatchStrategy.entityScope ===
|
||||
EntityScope.ENTITY_SCOPE_TEAMS ||
|
||||
// or to individuals
|
||||
(node.transfer.kind.dispatchStrategy.entityScope ===
|
||||
EntityScope.ENTITY_SCOPE_INDIVIDUALS &&
|
||||
// but they have to be in a team
|
||||
node.transfer.kind.dispatchStrategy.individualScope ===
|
||||
IndividualScope.INDIVIDUAL_SCOPE_IN_TEAM);
|
||||
|
||||
/** Retrieves rewards (transfers) */
|
||||
export const useRewards = ({
|
||||
// get active by default
|
||||
onlyActive = true,
|
||||
scopeToTeams = false,
|
||||
}: {
|
||||
onlyActive: boolean;
|
||||
scopeToTeams?: boolean;
|
||||
}): {
|
||||
data: EnrichedRewardTransfer[];
|
||||
loading: boolean;
|
||||
error?: ApolloError | Error;
|
||||
} => {
|
||||
const {
|
||||
data: epochData,
|
||||
loading: epochLoading,
|
||||
error: epochError,
|
||||
} = useEpochInfoQuery({
|
||||
fetchPolicy: 'network-only',
|
||||
});
|
||||
|
||||
const currentEpoch = Number(epochData?.epoch.id);
|
||||
|
||||
const { data, loading, error } = useActiveRewardsQuery({
|
||||
variables: {
|
||||
isReward: true,
|
||||
},
|
||||
skip: onlyActive && isNaN(currentEpoch),
|
||||
fetchPolicy: 'cache-and-network',
|
||||
});
|
||||
|
||||
const {
|
||||
data: assets,
|
||||
loading: assetsLoading,
|
||||
error: assetsError,
|
||||
} = useAssetsMapProvider();
|
||||
const {
|
||||
data: markets,
|
||||
loading: marketsLoading,
|
||||
error: marketsError,
|
||||
} = useMarketsMapProvider();
|
||||
|
||||
const enriched = compact(
|
||||
data?.transfersConnection?.edges?.map((n) => n?.node)
|
||||
)
|
||||
.map((n) => n as TransferNode)
|
||||
// make sure we have only rewards here
|
||||
.filter(isReward)
|
||||
// take only active rewards if required, otherwise take all
|
||||
.filter((node) => (onlyActive ? isActiveReward(node, currentEpoch) : true))
|
||||
// take only those rewards that are scoped to teams if required, otherwise take all
|
||||
.filter((node) => (scopeToTeams ? isScopedToTeams(node) : true))
|
||||
// enrich with dispatch asset and markets in scope details
|
||||
.map((node) => {
|
||||
const asset =
|
||||
assets &&
|
||||
assets[node.transfer.kind.dispatchStrategy.dispatchMetricAssetId];
|
||||
const marketsInScope = compact(
|
||||
node.transfer.kind.dispatchStrategy.marketIdsInScope?.map(
|
||||
(id) => markets && markets[id]
|
||||
)
|
||||
);
|
||||
const isAssetTraded =
|
||||
markets &&
|
||||
Object.values(markets).some((m) => {
|
||||
try {
|
||||
const mAsset = getAsset(m);
|
||||
return (
|
||||
mAsset.id ===
|
||||
node.transfer.kind.dispatchStrategy.dispatchMetricAssetId &&
|
||||
m.state === MarketState.STATE_ACTIVE
|
||||
);
|
||||
} catch {
|
||||
// NOOP
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return {
|
||||
...node,
|
||||
asset: asset ? asset : undefined,
|
||||
isAssetTraded: isAssetTraded != null ? isAssetTraded : undefined,
|
||||
markets: marketsInScope.length > 0 ? marketsInScope : undefined,
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
data: enriched,
|
||||
loading: loading || assetsLoading || marketsLoading || epochLoading,
|
||||
error: error || assetsError || marketsError || epochError,
|
||||
};
|
||||
};
|
||||
@@ -93,23 +93,16 @@ export const useEnabledAssets = () => {
|
||||
|
||||
/** Wrapped ETH symbol */
|
||||
const WETH = 'WETH';
|
||||
|
||||
/** VEGA */
|
||||
const VEGA = 'VEGA';
|
||||
|
||||
export type BasicAssetDetails = Pick<
|
||||
AssetFieldsFragment,
|
||||
'symbol' | 'decimals' | 'quantum'
|
||||
>;
|
||||
type WETHDetails = Pick<AssetFieldsFragment, 'symbol' | 'decimals' | 'quantum'>;
|
||||
/**
|
||||
* Tries to find WETH asset configuration on Vega in order to provide its
|
||||
* details, otherwise it returns hardcoded values.
|
||||
*/
|
||||
export const useWETH = (): BasicAssetDetails => {
|
||||
export const useWETH = (): WETHDetails => {
|
||||
const { data } = useAssetsDataProvider();
|
||||
if (data) {
|
||||
const details = data.find((a) => a.symbol.toUpperCase() === WETH);
|
||||
if (details) return details;
|
||||
const weth = data.find((a) => a.symbol.toUpperCase() === WETH);
|
||||
if (weth) return weth;
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -118,17 +111,3 @@ export const useWETH = (): BasicAssetDetails => {
|
||||
quantum: '500000000000000', // 1 WETH ~= 2000 qUSD
|
||||
};
|
||||
};
|
||||
|
||||
export const useVEGA = (): BasicAssetDetails => {
|
||||
const { data } = useAssetsDataProvider();
|
||||
if (data) {
|
||||
const details = data.find((a) => a.symbol.toUpperCase() === VEGA);
|
||||
if (details) return details;
|
||||
}
|
||||
|
||||
return {
|
||||
symbol: VEGA,
|
||||
decimals: 18,
|
||||
quantum: '1000000000000000000', // 1 VEGA ~= 1 qUSD
|
||||
};
|
||||
};
|
||||
|
||||
@@ -87,7 +87,6 @@ export const DocsLinks = VEGA_DOCS_URL
|
||||
QUANTUM: `${VEGA_DOCS_URL}/concepts/assets/asset-framework#quantum`,
|
||||
REFERRALS: `${VEGA_DOCS_URL}/tutorials/proposals/referral-program-proposal`,
|
||||
LIQUIDITY_FEE_PERCENTAGE: `${VEGA_DOCS_URL}/concepts/liquidity/rewards-penalties#determining-the-liquidity-fee-percentage`,
|
||||
ASSET_TRANSFER_PROPOSAL: `${VEGA_DOCS_URL}/tutorials/proposals/asset-transfer-proposal`,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
|
||||
@@ -159,7 +159,6 @@
|
||||
"ContinueSharingData": "Continue sharing data",
|
||||
"copied!": "Copied!",
|
||||
"copyToClipboard": "Copy to clipboard",
|
||||
"copyId": "Copy ID to clipboard",
|
||||
"CouldNotInstantiateMarket": "Could not instantiate market",
|
||||
"created": "Created",
|
||||
"CreateProposalAndDownloadJSONToShare": "Create proposal and download JSON to share",
|
||||
@@ -808,7 +807,7 @@
|
||||
"unsupportedVersion": "Looks like you're running an outdated version of GoWallet. You're running {{version}} but {{requiredVersion}} is required.",
|
||||
"UpdateAsset": "Update asset",
|
||||
"UpdateAssetProposal": "Update asset proposal",
|
||||
"UpdateToMarket": "Update to market",
|
||||
"UpdateToMarket": "Update to market ID",
|
||||
"OpenInConsole": "Open in Console",
|
||||
"UpdateMarket": "Update market",
|
||||
"UpdateMarketProposal": "Update market proposal",
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
"Ethereum Oracle": "Ethereum Oracle",
|
||||
"every {{duration}}": "every {{duration}}",
|
||||
"every {{duration}} from {{initialTime}}": "every {{duration}} from {{initialTime}}",
|
||||
"Factor applied to funding-rates. This scales the impact that spot price deviations have on funding payments.": "Factor applied to funding-rates. This scales the impact that spot price deviations have on funding payments.",
|
||||
"Fees paid to validators as a reward for running the infrastructure of the network.": "Fees paid to validators as a reward for running the infrastructure of the network.",
|
||||
"Filters": "Filters",
|
||||
"For liquidity orders to count towards a commitment, they must be within the liquidity monitoring bounds.": "For liquidity orders to count towards a commitment, they must be within the liquidity monitoring bounds.",
|
||||
@@ -45,7 +44,6 @@
|
||||
"Liquidity portion of the fee is paid to liquidity providers, and is transferred to the liquidity fee pool for the market.": "Liquidity portion of the fee is paid to liquidity providers, and is transferred to the liquidity fee pool for the market.",
|
||||
"Liquidity price range": "Liquidity price range",
|
||||
"Liquidity SLA protocol": "Liquidity SLA protocol",
|
||||
"Lower bound for the funding-rate such that the funding-rate will never be lower than this value.": "Lower bound for the funding-rate such that the funding-rate will never be lower than this value.",
|
||||
"Maker portion of the fee is transferred to the non-aggressive, or passive party in the trade (the maker, as opposed to the taker).": "Maker portion of the fee is transferred to the non-aggressive, or passive party in the trade (the maker, as opposed to the taker).",
|
||||
"Margin scaling factors": "Margin scaling factors",
|
||||
"Market": "Market",
|
||||
@@ -140,7 +138,6 @@
|
||||
"This public key's proofs have not been verified yet, or no proofs have been provided yet.": "This public key's proofs have not been verified yet, or no proofs have been provided yet.",
|
||||
"Time horizon of the price projection in seconds.": "Time horizon of the price projection in seconds.",
|
||||
"Updated": "Updated",
|
||||
"Upper bound for the funding-rate such that the funding-rate will never be higher than this value.": "Upper bound for the funding-rate such that the funding-rate will never be higher than this value.",
|
||||
"Used to calculate the penalty to liquidity providers when they cannot support their open position with the assets in their margin and general accounts. This is a network parameter.": "Used to calculate the penalty to liquidity providers when they cannot support their open position with the assets in their margin and general accounts. This is a network parameter.",
|
||||
"Verified since {{lastVerified}}": "Verified since {{lastVerified}}",
|
||||
"verifyProofs_one": "Verify {{count}} proof of ownership",
|
||||
|
||||
@@ -445,6 +445,7 @@
|
||||
"Leaderboard": "Leaderboard",
|
||||
"View all teams": "View all teams",
|
||||
"Competitions": "Competitions",
|
||||
"Be a team player! Participate in games and work together to rake in as much profit to win.": "Be a team player! Participate in games and work together to rake in as much profit to win.",
|
||||
"Create a public team": "Create a public team",
|
||||
"Create a private team": "Create a private team",
|
||||
"Choose a team": "Choose a team",
|
||||
@@ -461,14 +462,5 @@
|
||||
"Daily reward amount": "Daily reward amount",
|
||||
"Amount earned this epoch": "Amount earned this epoch",
|
||||
"Cumulative amount earned": "Cumulative amount earned",
|
||||
"Game details": "Game details",
|
||||
"Check the cards below to see what community-created, on-chain games are active and how to compete. Joining a team also lets you take part in the on-chain <0>referral program</0>.": "Check the cards below to see what community-created, on-chain games are active and how to compete. Joining a team also lets you take part in the on-chain <0>referral program</0>.",
|
||||
"Got an idea for a competition? Anyone can define and fund one -- <0>propose an on-chain game</0> yourself.": "Got an idea for a competition? Anyone can define and fund one -- <0>propose an on-chain game</0> yourself.",
|
||||
"Create a new team, share your code with potential members, or set a whitelist for an exclusive group.": "Create a new team, share your code with potential members, or set a whitelist for an exclusive group.",
|
||||
"Want to compete but think the best team size is one? This is the option for you.": "Want to compete but think the best team size is one? This is the option for you.",
|
||||
"Browse existing public teams to find your perfect match.": "Browse existing public teams to find your perfect match.",
|
||||
"See all the live games on the cards below. Every on-chain game is community funded and designed. <0>Find out how to create one</0>.": "See all the live games on the cards below. Every on-chain game is community funded and designed. <0>Find out how to create one</0>.",
|
||||
"Teams can earn rewards if they meet the goals set in the on-chain trading competitions. Track your earned rewards here, and see which teams are top of the leaderboard this month.": "Teams can earn rewards if they meet the goals set in the on-chain trading competitions. Track your earned rewards here, and see which teams are top of the leaderboard this month.",
|
||||
"Currently no active games on the network.": "Currently no active games on the network.",
|
||||
"Currently no active teams on the network.": "Currently no active teams on the network."
|
||||
"Game details": "Game details"
|
||||
}
|
||||
|
||||
+2
-2
File diff suppressed because one or more lines are too long
+2
-2
File diff suppressed because one or more lines are too long
@@ -112,9 +112,6 @@ fragment Future on Future {
|
||||
|
||||
fragment Perpetual on Perpetual {
|
||||
quoteName
|
||||
fundingRateScalingFactor
|
||||
fundingRateLowerBound
|
||||
fundingRateUpperBound
|
||||
settlementAsset {
|
||||
id
|
||||
symbol
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -181,10 +181,7 @@ export const MarketInfoAccordion = ({
|
||||
itemId="funding"
|
||||
title={t('Funding')}
|
||||
content={
|
||||
<FundingInfoPanel
|
||||
dataSource={settlementScheduleDataSource}
|
||||
market={market}
|
||||
/>
|
||||
<FundingInfoPanel dataSource={settlementScheduleDataSource} />
|
||||
}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -84,7 +84,6 @@ import type { DataSourceFragment } from './__generated__/MarketInfo';
|
||||
import { formatDuration } from 'date-fns';
|
||||
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
||||
import { useT } from '../../use-t';
|
||||
import { isPerpetual } from '../../product';
|
||||
|
||||
type MarketInfoProps = {
|
||||
market: MarketInfo;
|
||||
@@ -921,8 +920,8 @@ export const EthOraclePanel = ({ sourceType }: { sourceType: EthCallSpec }) => {
|
||||
<>
|
||||
<MarketInfoTable key={i} data={filter.key} />
|
||||
<h3 className={header}>{t('Conditions')}</h3>
|
||||
{filter.conditions?.map((condition, i) => (
|
||||
<span key={i}>
|
||||
{filter.conditions?.map((condition) => (
|
||||
<span>
|
||||
{ConditionOperatorMapping[condition.operator]} {condition.value}
|
||||
</span>
|
||||
))}
|
||||
@@ -1150,10 +1149,8 @@ export const LiquidityInfoPanel = ({ market, children }: MarketInfoProps) => {
|
||||
|
||||
export const FundingInfoPanel = ({
|
||||
dataSource,
|
||||
market,
|
||||
}: {
|
||||
dataSource: DataSourceFragment;
|
||||
market: MarketInfo;
|
||||
}) => {
|
||||
const t = useT();
|
||||
const sourceType = dataSource.data.sourceType.sourceType;
|
||||
@@ -1170,30 +1167,12 @@ export const FundingInfoPanel = ({
|
||||
hours,
|
||||
minutes,
|
||||
});
|
||||
const { product } = market.tradableInstrument.instrument;
|
||||
return (
|
||||
<>
|
||||
<p
|
||||
className="first-letter:uppercase text-x;w
|
||||
"
|
||||
>
|
||||
{initial
|
||||
? t('every {{duration}} from {{initialTime}}', {
|
||||
duration,
|
||||
initialTime: getDateTimeFormat().format(new Date(initial * 1000)),
|
||||
})
|
||||
: t('every {{duration}}', { duration })}
|
||||
</p>
|
||||
<MarketInfoTable
|
||||
data={{
|
||||
rateScalingFactor:
|
||||
isPerpetual(product) && product.fundingRateScalingFactor,
|
||||
rateLowerBound: isPerpetual(product) && product.fundingRateLowerBound,
|
||||
rateUpperBound: isPerpetual(product) && product.fundingRateUpperBound,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
return initial
|
||||
? t('every {{duration}} from {{initialTime}}', {
|
||||
duration,
|
||||
initialTime: getDateTimeFormat().format(new Date(initial * 1000)),
|
||||
})
|
||||
: t('every {{duration}}', { duration });
|
||||
};
|
||||
|
||||
export const OracleInfoPanel = ({
|
||||
|
||||
@@ -157,14 +157,5 @@ export const useTooltipMapping: () => Record<string, ReactNode> = () => {
|
||||
feeConstant: t(
|
||||
'The constant liquidity fee used when using the constant fee method .'
|
||||
),
|
||||
rateScalingFactor: t(
|
||||
'Factor applied to funding-rates. This scales the impact that spot price deviations have on funding payments.'
|
||||
),
|
||||
rateLowerBound: t(
|
||||
'Lower bound for the funding-rate such that the funding-rate will never be lower than this value.'
|
||||
),
|
||||
rateUpperBound: t(
|
||||
'Upper bound for the funding-rate such that the funding-rate will never be higher than this value.'
|
||||
),
|
||||
};
|
||||
};
|
||||
|
||||
Generated
+9
-13
@@ -3831,7 +3831,6 @@ export type PartytradesConnectionArgs = {
|
||||
export type PartytransfersConnectionArgs = {
|
||||
direction?: InputMaybe<TransferDirection>;
|
||||
fromEpoch?: InputMaybe<Scalars['Int']>;
|
||||
gameId?: InputMaybe<Scalars['ID']>;
|
||||
isReward?: InputMaybe<Scalars['Boolean']>;
|
||||
pagination?: InputMaybe<Pagination>;
|
||||
scope?: InputMaybe<TransferScope>;
|
||||
@@ -4048,11 +4047,11 @@ export type Perpetual = {
|
||||
/** Data source specification describing the data source for settlement schedule */
|
||||
dataSourceSpecForSettlementSchedule: DataSourceSpec;
|
||||
/** Lower bound for the funding-rate such that the funding-rate will never be lower than this value */
|
||||
fundingRateLowerBound?: Maybe<Scalars['String']>;
|
||||
fundingRateLowerBound: Scalars['String'];
|
||||
/** Factor applied to funding-rates. This scales the impact that spot price deviations have on funding payments */
|
||||
fundingRateScalingFactor?: Maybe<Scalars['String']>;
|
||||
fundingRateScalingFactor: Scalars['String'];
|
||||
/** Upper bound for the funding-rate such that the funding-rate will never be higher than this value */
|
||||
fundingRateUpperBound?: Maybe<Scalars['String']>;
|
||||
fundingRateUpperBound: Scalars['String'];
|
||||
/** Continuously compounded interest rate used in funding rate calculation, in the range [-1, 1] */
|
||||
interestRate: Scalars['String'];
|
||||
/** Optional configuration driving the internal composite price calculation for perpetual product */
|
||||
@@ -4105,11 +4104,11 @@ export type PerpetualProduct = {
|
||||
/** Data source specification describing the data source for settlement schedule */
|
||||
dataSourceSpecForSettlementSchedule: DataSourceDefinition;
|
||||
/** Lower bound for the funding-rate such that the funding-rate will never be lower than this value */
|
||||
fundingRateLowerBound?: Maybe<Scalars['String']>;
|
||||
fundingRateLowerBound: Scalars['String'];
|
||||
/** Factor applied to funding-rates. This scales the impact that spot price deviations have on funding payments. */
|
||||
fundingRateScalingFactor?: Maybe<Scalars['String']>;
|
||||
fundingRateScalingFactor: Scalars['String'];
|
||||
/** Upper bound for the funding-rate such that the funding-rate will never be higher than this value */
|
||||
fundingRateUpperBound?: Maybe<Scalars['String']>;
|
||||
fundingRateUpperBound: Scalars['String'];
|
||||
/** Continuously compounded interest rate used in funding rate calculation, in the range [-1, 1] */
|
||||
interestRate: Scalars['String'];
|
||||
/** Controls how much the upcoming funding payment liability contributes to party's margin, in the range [0, 1] */
|
||||
@@ -5160,8 +5159,6 @@ export type QuerygamesArgs = {
|
||||
epochTo?: InputMaybe<Scalars['Int']>;
|
||||
gameId?: InputMaybe<Scalars['ID']>;
|
||||
pagination?: InputMaybe<Pagination>;
|
||||
partyId?: InputMaybe<Scalars['ID']>;
|
||||
teamId?: InputMaybe<Scalars['ID']>;
|
||||
};
|
||||
|
||||
|
||||
@@ -5467,7 +5464,6 @@ export type QuerytransferArgs = {
|
||||
export type QuerytransfersConnectionArgs = {
|
||||
direction?: InputMaybe<TransferDirection>;
|
||||
fromEpoch?: InputMaybe<Scalars['Int']>;
|
||||
gameId?: InputMaybe<Scalars['ID']>;
|
||||
isReward?: InputMaybe<Scalars['Boolean']>;
|
||||
pagination?: InputMaybe<Pagination>;
|
||||
partyId?: InputMaybe<Scalars['ID']>;
|
||||
@@ -7103,11 +7099,11 @@ export type UpdatePerpetualProduct = {
|
||||
/** Data source specification describing the data source for settlement schedule */
|
||||
dataSourceSpecForSettlementSchedule: DataSourceDefinition;
|
||||
/** Lower bound for the funding-rate such that the funding-rate will never be lower than this value */
|
||||
fundingRateLowerBound?: Maybe<Scalars['String']>;
|
||||
fundingRateLowerBound: Scalars['String'];
|
||||
/** Factor applied to funding-rates. This scales the impact that spot price deviations have on funding payments. */
|
||||
fundingRateScalingFactor?: Maybe<Scalars['String']>;
|
||||
fundingRateScalingFactor: Scalars['String'];
|
||||
/** Upper bound for the funding-rate such that the funding-rate will never be higher than this value */
|
||||
fundingRateUpperBound?: Maybe<Scalars['String']>;
|
||||
fundingRateUpperBound: Scalars['String'];
|
||||
/** Continuously compounded interest rate used in funding rate calculation, in the range [-1, 1] */
|
||||
interestRate: Scalars['String'];
|
||||
/** Controls how much the upcoming funding payment liability contributes to party's margin, in the range [0, 1] */
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
type PeggedReference,
|
||||
type ProposalChange,
|
||||
type TransferStatus,
|
||||
MarketUpdateType,
|
||||
} from './__generated__/types';
|
||||
import type { AccountType } from './__generated__/types';
|
||||
import type {
|
||||
@@ -756,10 +755,3 @@ export const LiquidityFeeMethodMappingDescription: {
|
||||
METHOD_UNSPECIFIED: 'Unspecified',
|
||||
METHOD_WEIGHTED_AVERAGE: `This liquidity fee is the weighted average of all liquidity providers' nominated fees, weighted by their commitment.`,
|
||||
};
|
||||
|
||||
export const MarketUpdateTypeMapping = {
|
||||
[MarketUpdateType.MARKET_STATE_UPDATE_TYPE_RESUME]: 'Resume',
|
||||
[MarketUpdateType.MARKET_STATE_UPDATE_TYPE_SUSPEND]: 'Suspend',
|
||||
[MarketUpdateType.MARKET_STATE_UPDATE_TYPE_TERMINATE]: 'Terminate',
|
||||
[MarketUpdateType.MARKET_STATE_UPDATE_TYPE_UNSPECIFIED]: 'Unspecified',
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user