Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ce2c117be |
@@ -1,4 +1,3 @@
|
||||
* text eol=lf
|
||||
*.png binary
|
||||
*.ico binary
|
||||
*.woff2 binary
|
||||
|
||||
@@ -54,7 +54,7 @@ const Block = () => {
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
{blockData && 'result' in blockData && (
|
||||
{blockData && (
|
||||
<>
|
||||
<TableWithTbody className="mb-8">
|
||||
<TableRow modifier="bordered">
|
||||
|
||||
@@ -32,7 +32,7 @@ CYPRESS_FAIRGROUND=false
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
NX_REFERRALS=true
|
||||
|
||||
@@ -23,7 +23,7 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
NX_REFERRALS=true
|
||||
|
||||
@@ -22,7 +22,7 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
NX_REFERRALS=true
|
||||
|
||||
@@ -21,7 +21,7 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.
|
||||
|
||||
# Cosmic elevator flags
|
||||
NX_SUCCESSOR_MARKETS=true
|
||||
NX_METAMASK_SNAPS=true
|
||||
NX_METAMASK_SNAPS=false
|
||||
NX_PRODUCT_PERPETUALS=true
|
||||
NX_UPDATE_MARKET_STATE=true
|
||||
NX_REFERRALS=true
|
||||
|
||||
+2
-2
@@ -281,8 +281,8 @@ describe('VoteBreakdown', () => {
|
||||
});
|
||||
|
||||
it('Progress bar displays status - LP majority', () => {
|
||||
const yesVotesLP = 0.8;
|
||||
const noVotesLP = 0.2;
|
||||
const yesVotesLP = 800;
|
||||
const noVotesLP = 200;
|
||||
const expectedProgress = (yesVotesLP / (yesVotesLP + noVotesLP)) * 100; // 80%
|
||||
|
||||
renderComponent(
|
||||
|
||||
@@ -133,7 +133,6 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
|
||||
.multipliedBy(100),
|
||||
new BigNumber(100)
|
||||
);
|
||||
|
||||
const willPass = willPassByTokenVote || willPassByLPVote;
|
||||
const updateMarketVotePassMethod = willPassByTokenVote
|
||||
? t('byTokenVote')
|
||||
@@ -205,7 +204,7 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
|
||||
<span>{yesLPPercentage.toFixed(defaultDP)}%</span>
|
||||
}
|
||||
>
|
||||
<button>{yesLPPercentage.toFixed(1)}%</button>
|
||||
<button>{yesLPPercentage.toFixed(0)}%</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
@@ -217,7 +216,7 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
|
||||
<span>{noLPPercentage.toFixed(defaultDP)}%</span>
|
||||
}
|
||||
>
|
||||
<button>{noLPPercentage.toFixed(1)}%</button>
|
||||
<button>{noLPPercentage.toFixed(0)}%</button>
|
||||
</Tooltip>
|
||||
</span>
|
||||
</div>
|
||||
@@ -255,7 +254,9 @@ export const VoteBreakdown = ({ proposal }: VoteBreakdownProps) => {
|
||||
defaultDP
|
||||
)}
|
||||
>
|
||||
<span>{totalEquityLikeShareWeight.toFixed(1)}%</span>
|
||||
<span>
|
||||
{totalEquityLikeShareWeight.times(100).toString()}%
|
||||
</span>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -54,8 +54,8 @@ describe('use-vote-information', () => {
|
||||
it('returns all required vote information', () => {
|
||||
const yesVotes = 40;
|
||||
const noVotes = 60;
|
||||
const yesEquityLikeShareWeight = '0.30';
|
||||
const noEquityLikeShareWeight = '0.70';
|
||||
const yesEquityLikeShareWeight = '30';
|
||||
const noEquityLikeShareWeight = '70';
|
||||
// Note - giving a fixedTokenValue of 1 means a ratio of 1:1 votes to tokens, making sums easier :)
|
||||
const fixedTokenValue = 1000000000000000000;
|
||||
|
||||
@@ -195,10 +195,10 @@ describe('use-vote-information', () => {
|
||||
});
|
||||
|
||||
it('correctly shows whether an update market proposal will pass by token or LP vote - both failing', () => {
|
||||
const yesVotes = 0.2;
|
||||
const noVotes = 0.7;
|
||||
const yesEquityLikeShareWeight = '0.30';
|
||||
const noEquityLikeShareWeight = '0.60';
|
||||
const yesVotes = 20;
|
||||
const noVotes = 70;
|
||||
const yesEquityLikeShareWeight = '30';
|
||||
const noEquityLikeShareWeight = '60';
|
||||
const fixedTokenValue = 1000000000000000000;
|
||||
|
||||
const proposal = generateProposal({
|
||||
|
||||
@@ -61,7 +61,7 @@ export const useVoteInformation = ({
|
||||
const noEquityLikeShareWeight = !proposal?.votes.no
|
||||
.totalEquityLikeShareWeight
|
||||
? new BigNumber(0)
|
||||
: new BigNumber(proposal.votes.no.totalEquityLikeShareWeight).times(100);
|
||||
: new BigNumber(proposal.votes.no.totalEquityLikeShareWeight);
|
||||
|
||||
const yesTokens = new BigNumber(
|
||||
addDecimal(proposal?.votes.yes.totalTokens ?? 0, decimals)
|
||||
@@ -70,7 +70,7 @@ export const useVoteInformation = ({
|
||||
const yesEquityLikeShareWeight = !proposal?.votes.yes
|
||||
.totalEquityLikeShareWeight
|
||||
? new BigNumber(0)
|
||||
: new BigNumber(proposal.votes.yes.totalEquityLikeShareWeight).times(100);
|
||||
: new BigNumber(proposal.votes.yes.totalEquityLikeShareWeight);
|
||||
|
||||
const totalTokensVoted = yesTokens.plus(noTokens);
|
||||
|
||||
@@ -81,7 +81,7 @@ export const useVoteInformation = ({
|
||||
const yesPercentage = totalTokensVoted.isZero()
|
||||
? new BigNumber(0)
|
||||
: yesTokens.multipliedBy(100).dividedBy(totalTokensVoted);
|
||||
const yesLPPercentage = yesEquityLikeShareWeight;
|
||||
const yesLPPercentage = yesEquityLikeShareWeight.multipliedBy(100);
|
||||
|
||||
const noPercentage = totalTokensVoted.isZero()
|
||||
? new BigNumber(0)
|
||||
@@ -98,7 +98,9 @@ export const useVoteInformation = ({
|
||||
);
|
||||
|
||||
const participationLPMet = requiredParticipationLP
|
||||
? totalEquityLikeShareWeight.isGreaterThan(requiredParticipationLP)
|
||||
? totalEquityLikeShareWeight.isGreaterThan(
|
||||
totalSupply.multipliedBy(requiredParticipationLP)
|
||||
)
|
||||
: false;
|
||||
|
||||
const majorityMet = yesPercentage.isGreaterThanOrEqualTo(
|
||||
@@ -113,7 +115,9 @@ export const useVoteInformation = ({
|
||||
.multipliedBy(100)
|
||||
.dividedBy(totalSupply);
|
||||
|
||||
const totalLPTokensPercentage = totalEquityLikeShareWeight;
|
||||
const totalLPTokensPercentage = totalEquityLikeShareWeight
|
||||
.multipliedBy(100)
|
||||
.dividedBy(totalSupply);
|
||||
|
||||
const willPassByTokenVote =
|
||||
participationMet &&
|
||||
|
||||
+1
-1
@@ -95,7 +95,7 @@ export const ProtocolUpgradeProposalContainer = () => {
|
||||
time={
|
||||
pending && time ? (
|
||||
convertToCountdownString(time, '0:00:00:00')
|
||||
) : blockInfo && 'result' in blockInfo && blockInfo?.result ? (
|
||||
) : blockInfo?.result ? (
|
||||
<span title={blockInfo.result.block.header.time}>
|
||||
{formatDateWithLocalTimezone(
|
||||
new Date(blockInfo.result.block.header.time)
|
||||
|
||||
@@ -116,8 +116,7 @@ export const generateYesVotes = (
|
||||
fixedTokenValue?: number,
|
||||
totalEquityLikeShareWeight?: string
|
||||
): Votes => {
|
||||
const votes = [];
|
||||
for (let i = 0; i < numberOfVotes; i++) {
|
||||
const votes = Array.from(Array(numberOfVotes)).map(() => {
|
||||
const vote: Vote = {
|
||||
__typename: 'Vote',
|
||||
value: Schema.VoteValue.VALUE_YES,
|
||||
@@ -153,9 +152,8 @@ export const generateYesVotes = (
|
||||
datetime: faker.date.past().toISOString(),
|
||||
};
|
||||
|
||||
votes.push(vote);
|
||||
}
|
||||
|
||||
return vote;
|
||||
});
|
||||
return {
|
||||
__typename: 'ProposalVoteSide',
|
||||
totalNumber: votes.length.toString(),
|
||||
@@ -174,8 +172,7 @@ export const generateNoVotes = (
|
||||
fixedTokenValue?: number,
|
||||
totalEquityLikeShareWeight?: string
|
||||
): Votes => {
|
||||
const votes = [];
|
||||
for (let i = 0; i < numberOfVotes; i++) {
|
||||
const votes = Array.from(Array(numberOfVotes)).map(() => {
|
||||
const vote: Vote = {
|
||||
__typename: 'Vote',
|
||||
value: Schema.VoteValue.VALUE_NO,
|
||||
@@ -210,9 +207,8 @@ export const generateNoVotes = (
|
||||
},
|
||||
datetime: faker.date.past().toISOString(),
|
||||
};
|
||||
votes.push(vote);
|
||||
}
|
||||
|
||||
return vote;
|
||||
});
|
||||
return {
|
||||
__typename: 'ProposalVoteSide',
|
||||
totalNumber: votes.length.toString(),
|
||||
|
||||
@@ -54,5 +54,3 @@ To run the UI automation tests with a mocked API, run:
|
||||
```bash
|
||||
yarn nx run trading-e2e:e2e
|
||||
```
|
||||
|
||||
To run tests with market sim please read [the readme](e2e/README.md).
|
||||
|
||||
@@ -188,11 +188,12 @@ const useNow = () => {
|
||||
return now;
|
||||
};
|
||||
|
||||
const useEvery = (marketId: string, skip: boolean) => {
|
||||
const useEvery = (marketId: string) => {
|
||||
const { data: marketTradingMode } = useMarketTradingMode(marketId);
|
||||
const { data: marketInfo } = useDataProvider({
|
||||
dataProvider: marketInfoProvider,
|
||||
variables: { marketId },
|
||||
skip,
|
||||
skip: !marketTradingMode || isMarketInAuction(marketTradingMode),
|
||||
});
|
||||
let every: number | undefined = undefined;
|
||||
const sourceType =
|
||||
@@ -210,10 +211,8 @@ const useEvery = (marketId: string, skip: boolean) => {
|
||||
return every;
|
||||
};
|
||||
|
||||
const useStartTime = (marketId: string, skip: boolean) => {
|
||||
const useStartTime = (marketId: string) => {
|
||||
const { data: fundingPeriods } = useFundingPeriodsQuery({
|
||||
pollInterval: 5000,
|
||||
skip,
|
||||
variables: {
|
||||
marketId: marketId,
|
||||
pagination: { first: 1 },
|
||||
@@ -247,10 +246,8 @@ const useFormatCountdown = (
|
||||
|
||||
export const FundingCountdown = ({ marketId }: { marketId: string }) => {
|
||||
const now = useNow();
|
||||
const { data: marketTradingMode } = useMarketTradingMode(marketId);
|
||||
const skip = !marketTradingMode || isMarketInAuction(marketTradingMode);
|
||||
const startTime = useStartTime(marketId, skip);
|
||||
const every = useEvery(marketId, skip);
|
||||
const startTime = useStartTime(marketId);
|
||||
const every = useEvery(marketId);
|
||||
|
||||
return (
|
||||
<div data-testid="funding-countdown">
|
||||
|
||||
@@ -2,7 +2,6 @@ import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import { useCallback } from 'react';
|
||||
import { useRefereesQuery } from './__generated__/Referees';
|
||||
import compact from 'lodash/compact';
|
||||
import pick from 'lodash/pick';
|
||||
import type {
|
||||
ReferralSetsQuery,
|
||||
ReferralSetsQueryVariables,
|
||||
@@ -123,66 +122,6 @@ export const useReferral = (args: UseReferralArgs) => {
|
||||
};
|
||||
};
|
||||
|
||||
type Referee = NonNullable<
|
||||
NonNullable<ReturnType<typeof useReferral>['data']>['referee']
|
||||
>;
|
||||
|
||||
type RefereeProperties = (keyof Referee)[];
|
||||
|
||||
const findReferee = (referee: Referee, referees: Referee[]) =>
|
||||
referees.find((r) => r.refereeId === referee?.refereeId) || referee;
|
||||
|
||||
const updateReferee = (
|
||||
referee: Referee,
|
||||
referees: Referee[],
|
||||
properties: RefereeProperties
|
||||
) => ({
|
||||
...referee,
|
||||
...pick(findReferee(referee, referees), properties),
|
||||
});
|
||||
|
||||
export const useUpdateReferees = (
|
||||
referral: ReturnType<typeof useReferral>,
|
||||
aggregationEpochs: number,
|
||||
properties: RefereeProperties,
|
||||
skip?: boolean
|
||||
): ReturnType<typeof useReferral> => {
|
||||
const { data, loading, error, refetch } = useRefereesQuery({
|
||||
variables: {
|
||||
code: referral?.data?.code as string,
|
||||
aggregationEpochs,
|
||||
},
|
||||
skip: skip || !referral?.data?.code,
|
||||
fetchPolicy: 'cache-and-network',
|
||||
context: { isEnlargedTimeout: true },
|
||||
});
|
||||
const refetchAll = useCallback(() => {
|
||||
refetch();
|
||||
referral.refetch();
|
||||
}, [refetch, referral]);
|
||||
if (!referral.data || skip) {
|
||||
return referral;
|
||||
}
|
||||
const referees = compact(
|
||||
removePaginationWrapper(data?.referralSetReferees.edges)
|
||||
);
|
||||
|
||||
return {
|
||||
data: data && {
|
||||
...referral.data,
|
||||
referees: referral.data.referees.map((referee) =>
|
||||
updateReferee(referee, referees, properties)
|
||||
),
|
||||
referee:
|
||||
referral.data.referee &&
|
||||
updateReferee(referral.data.referee, referees, properties),
|
||||
},
|
||||
loading: loading || referral.loading,
|
||||
error: error || referral.error,
|
||||
refetch: refetchAll,
|
||||
};
|
||||
};
|
||||
|
||||
const retrieveReferralSetData = (data: ReferralSetsQuery | undefined) =>
|
||||
data?.referralSets.edges && data.referralSets.edges.length > 0
|
||||
? data.referralSets.edges[0]?.node
|
||||
|
||||
@@ -151,27 +151,6 @@ const MOCK_REFEREES: RefereesQuery = {
|
||||
},
|
||||
};
|
||||
|
||||
const MOCK_REFEREES_30: RefereesQuery = {
|
||||
referralSetReferees: {
|
||||
__typename: 'ReferralSetRefereeConnection',
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
atEpoch: 1,
|
||||
joinedAt: '2023-11-21T14:17:09.257235Z',
|
||||
refereeId:
|
||||
'0987654321098765432109876543210987654321098765432109876543219876',
|
||||
referralSetId:
|
||||
'3772e570fbab89e50e563036b01dd949c554e5b5fe7908449672dfce9a8adffa',
|
||||
totalRefereeGeneratedRewards: '12340',
|
||||
totalRefereeNotionalTakerVolume: '56780',
|
||||
__typename: 'ReferralSetReferee',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
const programMock: MockedResponse<ReferralProgramQuery> = {
|
||||
request: {
|
||||
query: ReferralProgramDocument,
|
||||
@@ -283,19 +262,6 @@ const refereesMock: MockedResponse<RefereesQuery, RefereesQueryVariables> = {
|
||||
},
|
||||
};
|
||||
|
||||
const refereesMock30: MockedResponse<RefereesQuery, RefereesQueryVariables> = {
|
||||
request: {
|
||||
query: RefereesDocument,
|
||||
variables: {
|
||||
code: MOCK_REFERRER_SET.referralSets.edges[0]?.node.id as string,
|
||||
aggregationEpochs: 30,
|
||||
},
|
||||
},
|
||||
result: {
|
||||
data: MOCK_REFEREES_30,
|
||||
},
|
||||
};
|
||||
|
||||
jest.mock('@vegaprotocol/wallet', () => {
|
||||
return {
|
||||
...jest.requireActual('@vegaprotocol/wallet'),
|
||||
@@ -331,7 +297,6 @@ describe('ReferralStatistics', () => {
|
||||
noReferralSetAsRefereeMock,
|
||||
stakeAvailableMock,
|
||||
refereesMock,
|
||||
refereesMock30,
|
||||
]}
|
||||
showWarnings={false}
|
||||
>
|
||||
@@ -348,10 +313,6 @@ describe('ReferralStatistics', () => {
|
||||
expect(queryByTestId('referral-statistics')?.dataset.as).toEqual(
|
||||
'referrer'
|
||||
);
|
||||
// gets commision from 30 epochs query
|
||||
expect(queryByTestId('total-commission-value')).toHaveTextContent(
|
||||
'12,340'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -4,15 +4,10 @@ import {
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
truncateMiddle,
|
||||
TextChildrenTooltip as Tooltip,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import {
|
||||
DEFAULT_AGGREGATION_DAYS,
|
||||
useReferral,
|
||||
useUpdateReferees,
|
||||
} from './hooks/use-referral';
|
||||
import { DEFAULT_AGGREGATION_DAYS, useReferral } from './hooks/use-referral';
|
||||
import classNames from 'classnames';
|
||||
import { Table } from './table';
|
||||
import {
|
||||
@@ -46,17 +41,11 @@ export const ReferralStatistics = () => {
|
||||
role: 'referee',
|
||||
aggregationEpochs: program.details?.windowLength,
|
||||
});
|
||||
|
||||
const { data: referrer, refetch: referrerRefetch } = useUpdateReferees(
|
||||
useReferral({
|
||||
pubKey,
|
||||
role: 'referrer',
|
||||
aggregationEpochs: program.details?.windowLength,
|
||||
}),
|
||||
DEFAULT_AGGREGATION_DAYS,
|
||||
['totalRefereeGeneratedRewards'],
|
||||
DEFAULT_AGGREGATION_DAYS === program.details?.windowLength
|
||||
);
|
||||
const { data: referrer, refetch: referrerRefetch } = useReferral({
|
||||
pubKey,
|
||||
role: 'referrer',
|
||||
aggregationEpochs: program.details?.windowLength,
|
||||
});
|
||||
|
||||
const refetch = useCallback(() => {
|
||||
refereeRefetch();
|
||||
@@ -87,9 +76,11 @@ export const ReferralStatistics = () => {
|
||||
export const useStats = ({
|
||||
data,
|
||||
program,
|
||||
as,
|
||||
}: {
|
||||
data?: NonNullable<ReturnType<typeof useReferral>['data']>;
|
||||
program: ReturnType<typeof useReferralProgram>;
|
||||
as?: 'referrer' | 'referee';
|
||||
}) => {
|
||||
const { benefitTiers } = program;
|
||||
const { data: epochData } = useCurrentEpochInfoQuery({
|
||||
@@ -190,7 +181,7 @@ export const Statistics = ({
|
||||
nextBenefitTierValue,
|
||||
nextBenefitTierVolumeValue,
|
||||
nextBenefitTierEpochsValue,
|
||||
} = useStats({ data, program });
|
||||
} = useStats({ data, program, as });
|
||||
|
||||
const isApplyCodePreview = useMemo(
|
||||
() => data.referee === null,
|
||||
@@ -302,27 +293,11 @@ export const Statistics = ({
|
||||
.reduce((all, r) => all.plus(r), new BigNumber(0));
|
||||
const totalCommissionTile = (
|
||||
<StatTile
|
||||
testId="total-commission"
|
||||
title={
|
||||
<Trans
|
||||
i18nKey="totalCommission"
|
||||
defaults="Total commission (<0>last {{count}} epochs</0>)"
|
||||
values={{
|
||||
count: DEFAULT_AGGREGATION_DAYS,
|
||||
}}
|
||||
components={[
|
||||
<Tooltip
|
||||
key="1"
|
||||
description={t(
|
||||
'Depending on data node retention you may not be able see the full 30 days'
|
||||
)}
|
||||
>
|
||||
last 30 epochs
|
||||
</Tooltip>,
|
||||
]}
|
||||
/>
|
||||
}
|
||||
title={t('totalCommission', 'Total commission (last {{count}} epochs)', {
|
||||
count: details?.windowLength || DEFAULT_AGGREGATION_DAYS,
|
||||
})}
|
||||
description={<QUSDTooltip />}
|
||||
testId="total-commission"
|
||||
>
|
||||
{getNumberFormat(0).format(Number(totalCommissionValue))}
|
||||
</StatTile>
|
||||
@@ -528,21 +503,12 @@ export const RefereesTable = ({
|
||||
displayName: (
|
||||
<Trans
|
||||
i18nKey="referralStatisticsCommission"
|
||||
defaults="Commission earned in <0>qUSD</0> (<1>last {{count}} epochs</1>)"
|
||||
components={[
|
||||
<QUSDTooltip key="0" />,
|
||||
<Tooltip
|
||||
key="1"
|
||||
description={t(
|
||||
'Depending on data node retention you may not be able see the full 30 days'
|
||||
)}
|
||||
>
|
||||
last 30 epochs
|
||||
</Tooltip>,
|
||||
]}
|
||||
defaults="Commission earned in <0>qUSD</0> (last {{count}} epochs)"
|
||||
values={{
|
||||
count: DEFAULT_AGGREGATION_DAYS,
|
||||
count:
|
||||
details?.windowLength || DEFAULT_AGGREGATION_DAYS,
|
||||
}}
|
||||
components={[<QUSDTooltip key="qusd" />]}
|
||||
ns={ns}
|
||||
/>
|
||||
),
|
||||
|
||||
@@ -31,7 +31,7 @@ export const Tile = ({
|
||||
};
|
||||
|
||||
type StatTileProps = {
|
||||
title: ReactNode;
|
||||
title: string;
|
||||
testId?: string;
|
||||
description?: ReactNode;
|
||||
children?: ReactNode;
|
||||
@@ -70,7 +70,7 @@ export const StatTile = ({
|
||||
export const NoProgramTile = ({ title }: Pick<StatTileProps, 'title'>) => {
|
||||
const t = useT();
|
||||
return (
|
||||
<Tile>
|
||||
<Tile title={title}>
|
||||
<h3 className="mb-1 text-sm text-vega-clight-100 dark:text-vega-cdark-100 calt">
|
||||
{title}
|
||||
</h3>
|
||||
|
||||
@@ -8,18 +8,15 @@ export const Card = ({
|
||||
className,
|
||||
loading = false,
|
||||
highlight = false,
|
||||
testId,
|
||||
}: {
|
||||
children: ReactNode;
|
||||
title: string;
|
||||
className?: string;
|
||||
loading?: boolean;
|
||||
highlight?: boolean;
|
||||
testId?: string;
|
||||
}) => {
|
||||
return (
|
||||
<div
|
||||
data-testid={testId}
|
||||
className={classNames(
|
||||
'bg-vega-clight-800 dark:bg-vega-cdark-800 col-span-full p-0.5 lg:col-auto',
|
||||
'rounded-lg',
|
||||
|
||||
@@ -84,10 +84,7 @@ export const FeesContainer = () => {
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="grid auto-rows-min grid-cols-4 gap-3"
|
||||
data-testid="fees-container"
|
||||
>
|
||||
<div className="grid auto-rows-min grid-cols-4 gap-3">
|
||||
{isConnected && (
|
||||
<>
|
||||
<Card
|
||||
@@ -127,10 +124,7 @@ export const FeesContainer = () => {
|
||||
windowLength={volumeDiscountWindowLength}
|
||||
/>
|
||||
) : (
|
||||
<p
|
||||
className="text-muted pt-3 text-sm"
|
||||
data-testid="no-volume-discount"
|
||||
>
|
||||
<p className="text-muted pt-3 text-sm">
|
||||
{t('No volume discount program active')}
|
||||
</p>
|
||||
)}
|
||||
@@ -139,22 +133,17 @@ export const FeesContainer = () => {
|
||||
title={t('Referral benefits')}
|
||||
className="sm:col-span-2"
|
||||
loading={loading}
|
||||
data-testid="referral-benefits-card"
|
||||
>
|
||||
{isReferrer ? (
|
||||
<ReferrerInfo code={code} data-testid="referrer-info" />
|
||||
<ReferrerInfo code={code} />
|
||||
) : isReferralProgramRunning ? (
|
||||
<ReferralBenefits
|
||||
setRunningNotionalTakerVolume={referralVolumeInWindow}
|
||||
epochsInSet={epochsInSet}
|
||||
epochs={referralDiscountWindowLength}
|
||||
data-testid="referral-benefits"
|
||||
/>
|
||||
) : (
|
||||
<p
|
||||
className="text-muted pt-3 text-sm"
|
||||
data-testid="no-referral-program"
|
||||
>
|
||||
<p className="text-muted pt-3 text-sm">
|
||||
{t('No referral program active')}
|
||||
</p>
|
||||
)}
|
||||
@@ -165,7 +154,6 @@ export const FeesContainer = () => {
|
||||
title={t('Volume discount')}
|
||||
className="lg:col-span-full xl:col-span-2"
|
||||
loading={loading}
|
||||
data-testid="volume-discount-card"
|
||||
>
|
||||
<VolumeTiers
|
||||
tiers={volumeTiers}
|
||||
@@ -178,7 +166,6 @@ export const FeesContainer = () => {
|
||||
title={t('Referral discount')}
|
||||
className="lg:col-span-full xl:col-span-2"
|
||||
loading={loading}
|
||||
data-testid="referral-discount-card"
|
||||
>
|
||||
<ReferralTiers
|
||||
tiers={referralTiers}
|
||||
@@ -191,7 +178,6 @@ export const FeesContainer = () => {
|
||||
title={t('Fees by market')}
|
||||
className="lg:col-span-full"
|
||||
loading={marketsLoading}
|
||||
data-testid="fees-by-market-card"
|
||||
>
|
||||
<MarketFees
|
||||
markets={markets}
|
||||
@@ -259,7 +245,7 @@ export const TradingFees = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="pt-4" data-testid="trading-fees">
|
||||
<div className="pt-4">
|
||||
<div className="leading-none">
|
||||
<p className="block text-3xl leading-none" data-testid="adjusted-fees">
|
||||
{minAdjustedTotal !== undefined && maxAdjustedTotal !== undefined
|
||||
@@ -269,7 +255,7 @@ export const TradingFees = ({
|
||||
: `${formatPercentage(adjustedTotal)}%`}
|
||||
</p>
|
||||
<CardTable>
|
||||
<tr className="text-default" data-testid="total-fee-before-discount">
|
||||
<tr className="text-default">
|
||||
<CardTableTH>{t('Total fee before discount')}</CardTableTH>
|
||||
<CardTableTD>
|
||||
{minTotal !== undefined && maxTotal !== undefined
|
||||
@@ -279,7 +265,7 @@ export const TradingFees = ({
|
||||
: `${formatPercentage(total.toNumber())}%`}
|
||||
</CardTableTD>
|
||||
</tr>
|
||||
<tr data-testid="infrastructure-fees">
|
||||
<tr>
|
||||
<CardTableTH>{t('Infrastructure')}</CardTableTH>
|
||||
<CardTableTD>
|
||||
{formatPercentage(
|
||||
@@ -288,14 +274,14 @@ export const TradingFees = ({
|
||||
%
|
||||
</CardTableTD>
|
||||
</tr>
|
||||
<tr data-testid="maker-fees">
|
||||
<tr>
|
||||
<CardTableTH>{t('Maker')}</CardTableTH>
|
||||
<CardTableTD>
|
||||
{formatPercentage(Number(params.market_fee_factors_makerFee))}%
|
||||
</CardTableTD>
|
||||
</tr>
|
||||
{minLiq && maxLiq && (
|
||||
<tr data-testid="liquidity-fees">
|
||||
<tr>
|
||||
<CardTableTH>{t('Liquidity')}</CardTableTH>
|
||||
<CardTableTD>
|
||||
{formatPercentage(Number(minLiq.fees.factors.liquidityFee))}%
|
||||
@@ -331,19 +317,21 @@ export const CurrentVolume = ({
|
||||
const currentVolume = new BigNumber(windowLengthVolume);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3 pt-4" data-testid="current-volume">
|
||||
<div className="flex flex-col gap-3 pt-4">
|
||||
<CardStat
|
||||
value={formatNumberRounded(currentVolume)}
|
||||
value={
|
||||
currentVolume.isZero()
|
||||
? `<${formatNumberRounded(requiredForNextTier)}`
|
||||
: formatNumberRounded(currentVolume)
|
||||
}
|
||||
text={t('pastEpochs', 'Past {{count}} epochs', {
|
||||
count: windowLength,
|
||||
})}
|
||||
testId="past-epochs-volume"
|
||||
/>
|
||||
{requiredForNextTier.isGreaterThan(0) && (
|
||||
<CardStat
|
||||
value={formatNumber(requiredForNextTier)}
|
||||
text={t('Required for next tier')}
|
||||
testId="required-for-next-tier"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@@ -361,7 +349,7 @@ const ReferralBenefits = ({
|
||||
}) => {
|
||||
const t = useT();
|
||||
return (
|
||||
<div className="flex flex-col gap-3 pt-4" data-testid="referral-benefits">
|
||||
<div className="flex flex-col gap-3 pt-4">
|
||||
<CardStat
|
||||
// all sets volume (not just current party)
|
||||
value={formatNumber(setRunningNotionalTakerVolume)}
|
||||
@@ -372,13 +360,8 @@ const ReferralBenefits = ({
|
||||
count: epochs,
|
||||
}
|
||||
)}
|
||||
testId="running-notional-taker-volume"
|
||||
/>
|
||||
<CardStat
|
||||
value={epochsInSet}
|
||||
text={t('epochs in referral set')}
|
||||
testId="epochs-in-referral-set"
|
||||
/>
|
||||
<CardStat value={epochsInSet} text={t('epochs in referral set')} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -406,7 +389,7 @@ const TotalDiscount = ({
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="pt-4" data-testid="total-discount-card-stats">
|
||||
<div className="pt-4">
|
||||
<CardStat
|
||||
description={
|
||||
<>
|
||||
@@ -416,10 +399,9 @@ const TotalDiscount = ({
|
||||
}
|
||||
value={formatPercentage(totalDiscount) + '%'}
|
||||
highlight={true}
|
||||
testId="total-discount"
|
||||
/>
|
||||
<CardTable>
|
||||
<tr data-testid="volume-discount-row">
|
||||
<tr>
|
||||
<CardTableTH>{t('Volume discount')}</CardTableTH>
|
||||
<CardTableTD>
|
||||
{formatPercentage(volumeDiscount)}%
|
||||
@@ -433,7 +415,7 @@ const TotalDiscount = ({
|
||||
)}
|
||||
</CardTableTD>
|
||||
</tr>
|
||||
<tr data-testid="referral-discount-row">
|
||||
<tr>
|
||||
<CardTableTH>{t('Referral discount')}</CardTableTH>
|
||||
<CardTableTD>
|
||||
{formatPercentage(referralDiscount)}%
|
||||
@@ -479,37 +461,29 @@ const VolumeTiers = ({
|
||||
<div>
|
||||
<Table>
|
||||
<THead>
|
||||
<Tr>
|
||||
<Th data-testid="tier-header">{t('Tier')}</Th>
|
||||
<Th data-testid="discount-header">{t('Discount')}</Th>
|
||||
<Th data-testid="min-volume-header">{t('Min. trading volume')}</Th>
|
||||
<Th data-testid="my-volume-header">
|
||||
<tr>
|
||||
<Th>{t('Tier')}</Th>
|
||||
<Th>{t('Discount')}</Th>
|
||||
<Th>{t('Min. trading volume')}</Th>
|
||||
<Th>
|
||||
{t('myVolume', 'My volume (last {{count}} epochs)', {
|
||||
count: windowLength,
|
||||
})}
|
||||
</Th>
|
||||
<Th data-testid="actions-header" />
|
||||
</Tr>
|
||||
<Th />
|
||||
</tr>
|
||||
</THead>
|
||||
<tbody>
|
||||
{Array.from(tiers).map((tier, i) => {
|
||||
const isUserTier = tierIndex === i;
|
||||
|
||||
return (
|
||||
<Tr key={i} data-testid={`tier-row-${i}`}>
|
||||
<Td data-testid={`tier-value-${i}`}>{i + 1}</Td>
|
||||
<Td data-testid={`discount-value-${i}`}>
|
||||
{formatPercentage(Number(tier.volumeDiscountFactor))}%
|
||||
</Td>
|
||||
<Td data-testid={`min-volume-value-${i}`}>
|
||||
{formatNumber(tier.minimumRunningNotionalTakerVolume)}
|
||||
</Td>
|
||||
<Td data-testid={`my-volume-value-${i}`}>
|
||||
{isUserTier ? formatNumber(lastEpochVolume) : ''}
|
||||
</Td>
|
||||
<Td data-testid={`your-tier-${i}`}>
|
||||
{isUserTier ? <YourTier /> : null}
|
||||
</Td>
|
||||
<Tr key={i}>
|
||||
<Td>{i + 1}</Td>
|
||||
<Td>{formatPercentage(Number(tier.volumeDiscountFactor))}%</Td>
|
||||
<Td>{formatNumber(tier.minimumRunningNotionalTakerVolume)}</Td>
|
||||
<Td>{isUserTier ? formatNumber(lastEpochVolume) : ''}</Td>
|
||||
<Td>{isUserTier ? <YourTier /> : null}</Td>
|
||||
</Tr>
|
||||
);
|
||||
})}
|
||||
@@ -546,53 +520,39 @@ const ReferralTiers = ({
|
||||
<div>
|
||||
<Table>
|
||||
<THead>
|
||||
<Tr>
|
||||
<Th data-testid="tier-header">{t('Tier')}</Th>
|
||||
<Th data-testid="discount-header">{t('Discount')}</Th>
|
||||
<Th data-testid="min-volume-header">{t('Min. trading volume')}</Th>
|
||||
<Th data-testid="required-epochs-header">{t('Required epochs')}</Th>
|
||||
<Th data-testid="extra-header" />
|
||||
</Tr>
|
||||
<tr>
|
||||
<Th>{t('Tier')}</Th>
|
||||
<Th>{t('Discount')}</Th>
|
||||
<Th>{t('Min. trading volume')}</Th>
|
||||
<Th>{t('Required epochs')}</Th>
|
||||
<Th />
|
||||
</tr>
|
||||
</THead>
|
||||
<tbody>
|
||||
{Array.from(tiers).map((tier, i) => {
|
||||
{Array.from(tiers).map((t, i) => {
|
||||
const isUserTier = tierIndex === i;
|
||||
|
||||
const requiredVolume = Number(
|
||||
tier.minimumRunningNotionalTakerVolume
|
||||
);
|
||||
const requiredVolume = Number(t.minimumRunningNotionalTakerVolume);
|
||||
let unlocksIn = null;
|
||||
|
||||
if (
|
||||
referralVolumeInWindow >= requiredVolume &&
|
||||
epochsInSet < tier.minimumEpochs
|
||||
epochsInSet < t.minimumEpochs
|
||||
) {
|
||||
unlocksIn = (
|
||||
<span className="text-muted">
|
||||
Unlocks in {tier.minimumEpochs - epochsInSet} epochs
|
||||
Unlocks in {t.minimumEpochs - epochsInSet} epochs
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Tr key={i} data-testid={`tier-row-${i}`}>
|
||||
<Td data-testid={`tier-value-${i}`}>{i + 1}</Td>
|
||||
<Td data-testid={`discount-value-${i}`}>
|
||||
{formatPercentage(Number(tier.referralDiscountFactor))}%
|
||||
</Td>
|
||||
<Td data-testid={`min-volume-value-${i}`}>
|
||||
{formatNumber(tier.minimumRunningNotionalTakerVolume)}
|
||||
</Td>
|
||||
<Td data-testid={`required-epochs-value-${i}`}>
|
||||
{tier.minimumEpochs}
|
||||
</Td>
|
||||
<Td data-testid={`user-tier-or-unlocks-${i}`}>
|
||||
{isUserTier ? (
|
||||
<YourTier testId={`your-tier-${i}`} />
|
||||
) : (
|
||||
unlocksIn
|
||||
)}
|
||||
</Td>
|
||||
<Tr key={i}>
|
||||
<Td>{i + 1}</Td>
|
||||
<Td>{formatPercentage(Number(t.referralDiscountFactor))}%</Td>
|
||||
<Td>{formatNumber(t.minimumRunningNotionalTakerVolume)}</Td>
|
||||
<Td>{t.minimumEpochs}</Td>
|
||||
<Td>{isUserTier ? <YourTier /> : unlocksIn}</Td>
|
||||
</Tr>
|
||||
);
|
||||
})}
|
||||
@@ -602,18 +562,11 @@ const ReferralTiers = ({
|
||||
);
|
||||
};
|
||||
|
||||
interface YourTierProps {
|
||||
testId?: string;
|
||||
}
|
||||
|
||||
const YourTier = ({ testId }: YourTierProps) => {
|
||||
const YourTier = () => {
|
||||
const t = useT();
|
||||
|
||||
return (
|
||||
<span
|
||||
className="bg-rainbow whitespace-nowrap rounded-xl px-4 py-1.5 text-white"
|
||||
data-testid={testId}
|
||||
>
|
||||
<span className="bg-rainbow whitespace-nowrap rounded-xl px-4 py-1.5 text-white">
|
||||
{t('Your tier')}
|
||||
</span>
|
||||
);
|
||||
|
||||
@@ -3,31 +3,21 @@ import type { ReactNode } from 'react';
|
||||
|
||||
const cellClass = 'px-4 py-2 text-xs font-normal text-left last:text-right';
|
||||
|
||||
export const Th = ({ children, ...props }: { children?: ReactNode }) => {
|
||||
export const Th = ({ children }: { children?: ReactNode }) => {
|
||||
return (
|
||||
<th
|
||||
className={classNames(cellClass, 'text-secondary leading-none py-3')}
|
||||
{...props}
|
||||
>
|
||||
<th className={classNames(cellClass, 'text-secondary leading-none py-3')}>
|
||||
{children}
|
||||
</th>
|
||||
);
|
||||
};
|
||||
|
||||
export const Td = ({ children, ...props }: { children?: ReactNode }) => {
|
||||
return (
|
||||
<th className={cellClass} {...props}>
|
||||
{children}
|
||||
</th>
|
||||
);
|
||||
export const Td = ({ children }: { children?: ReactNode }) => {
|
||||
return <th className={cellClass}>{children}</th>;
|
||||
};
|
||||
|
||||
export const Tr = ({ children, ...props }: { children?: ReactNode }) => {
|
||||
export const Tr = ({ children }: { children?: ReactNode }) => {
|
||||
return (
|
||||
<tr
|
||||
className="hover:bg-vega-clight-600 dark:hover:bg-vega-cdark-700"
|
||||
{...props}
|
||||
>
|
||||
<tr className="hover:bg-vega-clight-600 dark:hover:bg-vega-cdark-700">
|
||||
{children}
|
||||
</tr>
|
||||
);
|
||||
|
||||
@@ -69,13 +69,11 @@ describe('RewardPot', () => {
|
||||
balance: '100',
|
||||
asset: rewardAsset,
|
||||
},
|
||||
// should include this in total:
|
||||
{
|
||||
type: AccountType.ACCOUNT_TYPE_VESTED_REWARDS,
|
||||
balance: '100',
|
||||
asset: rewardAsset,
|
||||
},
|
||||
// should include this in total:
|
||||
{
|
||||
type: AccountType.ACCOUNT_TYPE_VESTED_REWARDS,
|
||||
balance: '50',
|
||||
@@ -140,20 +138,20 @@ describe('RewardPot', () => {
|
||||
|
||||
renderComponent(props);
|
||||
|
||||
expect(screen.getByTestId('total-rewards')).toHaveTextContent(
|
||||
`7.00 ${rewardAsset.symbol}`
|
||||
);
|
||||
|
||||
expect(screen.getByText(/Locked/).nextElementSibling).toHaveTextContent(
|
||||
'2.50'
|
||||
);
|
||||
expect(screen.getByText(/Vesting/).nextElementSibling).toHaveTextContent(
|
||||
'4.50'
|
||||
);
|
||||
|
||||
expect(
|
||||
screen.getByText(/Available to withdraw/).nextElementSibling
|
||||
).toHaveTextContent('1.50');
|
||||
|
||||
// should be sum of the above
|
||||
expect(screen.getByTestId('total-rewards')).toHaveTextContent(
|
||||
`8.50 ${rewardAsset.symbol}`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -62,10 +62,6 @@ export const RewardsContainer = () => {
|
||||
},
|
||||
// Inclusion of activity streak in query currently fails
|
||||
errorPolicy: 'ignore',
|
||||
// polling here so that as rewards are are moved to ACCOUNT_TYPE_VESTED_REWARDS the vesting stats information stays
|
||||
// almost up to sync with accounts updating from subscriptions. There is a chance the data could be out
|
||||
// of sync for 10s if you happen to be on the page at the end of an epoch
|
||||
pollInterval: 10000,
|
||||
});
|
||||
|
||||
if (!epochData?.epoch || !assetMap) return null;
|
||||
@@ -299,9 +295,7 @@ export const RewardPot = ({
|
||||
: [0];
|
||||
const totalVesting = BigNumber.sum.apply(null, vestingBalances);
|
||||
|
||||
const totalRewards = totalLocked
|
||||
.plus(totalVesting)
|
||||
.plus(totalVestedRewardsByRewardAsset);
|
||||
const totalRewards = totalLocked.plus(totalVesting);
|
||||
|
||||
let rewardAsset = undefined;
|
||||
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
CONSOLE_IMAGE_NAME=vegaprotocol/trading:latest
|
||||
VEGA_VERSION=v0.73.9
|
||||
LOCAL_SERVER=false
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
CONSOLE_IMAGE_NAME=vegaprotocol/trading:main
|
||||
VEGA_VERSION=v0.73.8
|
||||
LOCAL_SERVER=false
|
||||
@@ -24,12 +24,6 @@ poetry shell
|
||||
|
||||
5. **Install python dependencies**
|
||||
|
||||
To make sure you are on the latest version of our market-sim branch.
|
||||
|
||||
```bash
|
||||
poetry update vega-sim
|
||||
```
|
||||
|
||||
```bash
|
||||
poetry install
|
||||
```
|
||||
@@ -127,7 +121,11 @@ yarn nx serve trading
|
||||
|
||||
```
|
||||
|
||||
Once console is served you can update the .env file to have local_server to true.
|
||||
Once console is served you can use the flag --local-server
|
||||
|
||||
```bash
|
||||
poetry run pytest -k "test_name" -s --headed --local-server
|
||||
```
|
||||
|
||||
## Running Tests in Parallel 🔢
|
||||
|
||||
|
||||
@@ -55,14 +55,14 @@ def change_keys(page: Page, vega: VegaServiceNull, key_name):
|
||||
page.reload()
|
||||
|
||||
|
||||
def forward_time(vega:VegaServiceNull, forward_epoch: bool = False):
|
||||
|
||||
def forward_time(vega: VegaServiceNull, forward_epoch: bool = False):
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
if forward_epoch:
|
||||
next_epoch(vega)
|
||||
|
||||
|
||||
# This is for when the element will initially load but contain an outdated value. It will wait for the element to contain the expected text, returning False after a timeout or exception
|
||||
def selector_contains_text(page: Page, selector, expected_text, timeout=5000):
|
||||
try:
|
||||
@@ -71,4 +71,3 @@ def selector_contains_text(page: Page, selector, expected_text, timeout=5000):
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
|
||||
@@ -6,10 +6,9 @@ import requests
|
||||
import time
|
||||
import docker
|
||||
import http.server
|
||||
import sys
|
||||
from dotenv import load_dotenv
|
||||
|
||||
from contextlib import contextmanager
|
||||
from vega_sim.null_service import VegaServiceNull, Ports
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from playwright.sync_api import Browser, Page
|
||||
from config import console_image_name, vega_version
|
||||
from datetime import datetime, timedelta
|
||||
@@ -20,6 +19,7 @@ from fixtures.market import (
|
||||
setup_perps_market,
|
||||
)
|
||||
|
||||
import sys
|
||||
|
||||
# Workaround for current xdist issue with displaying live logs from multiple workers
|
||||
# https://github.com/pytest-dev/pytest-xdist/issues/402
|
||||
@@ -28,8 +28,6 @@ sys.stdout = sys.stderr
|
||||
docker_client = docker.from_env()
|
||||
logger = logging.getLogger()
|
||||
|
||||
load_dotenv()
|
||||
|
||||
|
||||
@pytest.hookimpl(tryfirst=True)
|
||||
def pytest_runtest_makereport(item, call):
|
||||
@@ -51,24 +49,16 @@ def pytest_configure(config):
|
||||
level=config.getini("log_file_level"),
|
||||
)
|
||||
|
||||
|
||||
class CustomHttpRequestHandler(http.server.SimpleHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
# Set the path to your website's directory here
|
||||
if self.path == "/":
|
||||
self.path = "dist/apps/trading/exported/index.html"
|
||||
if self.path == '/':
|
||||
self.path = 'dist/apps/trading/exported/index.html'
|
||||
return http.server.SimpleHTTPRequestHandler.do_GET(self)
|
||||
|
||||
|
||||
# Start VegaServiceNull
|
||||
@contextmanager
|
||||
def init_vega(request=None):
|
||||
local_server = os.getenv("LOCAL_SERVER", "false").lower() == "true"
|
||||
port_config = None
|
||||
if local_server:
|
||||
port_config = {
|
||||
Ports.DATA_NODE_REST: 8001,
|
||||
}
|
||||
default_seconds = 1
|
||||
seconds_per_block = default_seconds
|
||||
if request and hasattr(request, "param"):
|
||||
@@ -80,26 +70,21 @@ def init_vega(request=None):
|
||||
)
|
||||
logger.info(f"Using console image: {console_image_name}")
|
||||
logger.info(f"Using vega version: {vega_version}")
|
||||
|
||||
vega_service_args = {
|
||||
"run_with_console": False,
|
||||
"launch_graphql": False,
|
||||
"retain_log_files": True,
|
||||
"use_full_vega_wallet": True,
|
||||
"store_transactions": True,
|
||||
"transactions_per_block": 1000,
|
||||
"seconds_per_block": seconds_per_block,
|
||||
"genesis_time": datetime.now() - timedelta(days=1),
|
||||
}
|
||||
|
||||
if port_config is not None:
|
||||
vega_service_args["port_config"] = port_config
|
||||
|
||||
with VegaServiceNull(**vega_service_args) as vega:
|
||||
with VegaServiceNull(
|
||||
run_with_console=False,
|
||||
launch_graphql=False,
|
||||
retain_log_files=True,
|
||||
use_full_vega_wallet=True,
|
||||
store_transactions=True,
|
||||
transactions_per_block=1000,
|
||||
seconds_per_block=seconds_per_block,
|
||||
genesis_time= datetime.now() - timedelta(days=1),
|
||||
) as vega:
|
||||
try:
|
||||
container = docker_client.containers.run(
|
||||
console_image_name, detach=True, ports={"80/tcp": vega.console_port}
|
||||
)
|
||||
# docker setup
|
||||
logger.info(
|
||||
f"Container {container.id} started",
|
||||
extra={"worker_id": os.environ.get("PYTEST_XDIST_WORKER")},
|
||||
@@ -112,13 +97,23 @@ def init_vega(request=None):
|
||||
finally:
|
||||
logger.info(f"Stopping container {container.id}")
|
||||
container.stop()
|
||||
# Remove the container
|
||||
logger.info(f"Removing container {container.id}")
|
||||
container.remove()
|
||||
|
||||
|
||||
def pytest_addoption(parser):
|
||||
parser.addoption(
|
||||
"--local-server", action="store_true", default=False,
|
||||
help="Build and serve locally instead of using a container"
|
||||
)
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def local_server(pytestconfig):
|
||||
return pytestconfig.getoption("--local-server")
|
||||
|
||||
@contextmanager
|
||||
def init_page(vega: VegaServiceNull, browser: Browser, request: pytest.FixtureRequest):
|
||||
local_server = os.getenv("LOCAL_SERVER", "false").lower() == "true"
|
||||
def init_page(vega: VegaServiceNull, browser: Browser, request: pytest.FixtureRequest, local_server: bool):
|
||||
server_port = "4200" if local_server else str(vega.console_port)
|
||||
with browser.new_context(
|
||||
viewport={"width": 1920, "height": 1080},
|
||||
@@ -130,7 +125,9 @@ def init_page(vega: VegaServiceNull, browser: Browser, request: pytest.FixtureRe
|
||||
attempts = 0
|
||||
while attempts < 100:
|
||||
try:
|
||||
code = requests.get(f"http://localhost:{server_port}/").status_code
|
||||
code = requests.get(
|
||||
f"http://localhost:{server_port}/"
|
||||
).status_code
|
||||
if code == 200:
|
||||
break
|
||||
except requests.exceptions.ConnectionError as e:
|
||||
@@ -175,8 +172,8 @@ def vega(request):
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page_instance:
|
||||
def page(vega, browser, request, local_server):
|
||||
with init_page(vega, browser, request, local_server) as page_instance:
|
||||
yield page_instance
|
||||
|
||||
|
||||
|
||||
@@ -245,11 +245,3 @@ def setup_perps_market(
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
return market_id
|
||||
|
||||
|
||||
def market_exists(vega: VegaService, market_id: str):
|
||||
if market_id is None:
|
||||
return False
|
||||
all_markets = vega.all_markets()
|
||||
market_ids = [market.id for market in all_markets]
|
||||
return market_id in market_ids
|
||||
|
||||
Generated
+2
-2
@@ -1,4 +1,4 @@
|
||||
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
|
||||
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
@@ -1161,7 +1161,7 @@ profile = ["pytest-profiling", "snakeviz"]
|
||||
type = "git"
|
||||
url = "https://github.com/vegaprotocol/vega-market-sim.git/"
|
||||
reference = "fix/genesis_panic"
|
||||
resolved_reference = "de30d2d4c7a1b81a830527ca76473e23ef59de12"
|
||||
resolved_reference = "7ab04931924380db8000544b7f3d65fcb39b5467"
|
||||
|
||||
[[package]]
|
||||
name = "websocket-client"
|
||||
|
||||
@@ -1,682 +0,0 @@
|
||||
import pytest
|
||||
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import VegaService
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import init_vega, init_page, auth_setup
|
||||
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"
|
||||
YOUR_TIER_0 = "your-tier-0"
|
||||
YOUR_TIER_1 = "your-tier-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"
|
||||
ROW_LOCATOR = ".ag-center-cols-container .ag-row"
|
||||
# Col-Ids:
|
||||
COL_INSTRUMENT_CODE = '[col-id="market.tradableInstrument.instrument.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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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:
|
||||
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: VegaService, 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: VegaService, 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: VegaService):
|
||||
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-tier-0"),
|
||||
(2, "volume", "my-volume-value-1", "206", "your-tier-1"),
|
||||
(1, "referral", "my-volume-value-0", "103", "your-tier-0"),
|
||||
(2, "referral", "my-volume-value-1", "206", "your-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)).to_be_visible()
|
||||
expect(page.get_by_test_id(your_tier)).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")
|
||||
row = page.locator(ROW_LOCATOR)
|
||||
expect(row.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_INSTRUMENT_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
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_INSTRUMENT_CODE)).to_have_text("BTC:DAI_2023Futr")
|
||||
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
|
||||
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
|
||||
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"
|
||||
)
|
||||
@@ -208,11 +208,11 @@ def test_auction_uncross_fees(continuous_market, vega: VegaService, page: Page):
|
||||
expect(page.locator(COL_ID_FEE)).to_have_text("0.00 tDAI")
|
||||
page.locator(COL_ID_FEE).hover()
|
||||
expect(page.get_by_test_id("fee-breakdown-tooltip")).to_have_text(
|
||||
"If the market was suspendedDuring auction, half the infrastructure and liquidity fees will be paid.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee0.00 tDAITotal fees0.00 tDAI"
|
||||
"If the market was suspendedIf the market is in monitoring auction, half of the infrastructure and liquidity fees will be paid.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee0.00 tDAITotal fees0.00 tDAI"
|
||||
)
|
||||
change_keys(page, vega, "market_maker")
|
||||
expect(page.locator(COL_ID_FEE)).to_have_text("0.00 tDAI")
|
||||
page.locator(COL_ID_FEE).hover()
|
||||
expect(page.get_by_test_id("fee-breakdown-tooltip")).to_have_text(
|
||||
"If the market was suspendedDuring auction, half the infrastructure and liquidity fees will be paid.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee0.00 tDAITotal fees0.00 tDAI"
|
||||
"If the market was suspendedIf the market is in monitoring auction, half of the infrastructure and liquidity fees will be paid.Infrastructure fee0.00 tDAILiquidity fee0.00 tDAIMaker fee0.00 tDAITotal fees0.00 tDAI"
|
||||
)
|
||||
|
||||
@@ -15,8 +15,8 @@ def vega():
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
def page(vega, browser, request, local_server):
|
||||
with init_page(vega, browser, request, local_server) as page:
|
||||
setup_continuous_market(vega)
|
||||
risk_accepted_setup(page)
|
||||
page.goto("/")
|
||||
@@ -280,7 +280,7 @@ def test_market_info_proposal(page: Page, vega: VegaService):
|
||||
"href", re.compile(r"(\/proposals\/propose\/update-market)")
|
||||
)
|
||||
|
||||
@pytest.mark.skip("tbd-market-sim")
|
||||
|
||||
def test_market_info_succession_line(page: Page, vega: VegaService):
|
||||
page.get_by_test_id(market_title_test_id).get_by_text("Succession line").click()
|
||||
market_id = vega.find_market_id("BTC:DAI_2023")
|
||||
|
||||
@@ -11,8 +11,8 @@ def vega(request):
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
def page(vega, browser, request, local_server):
|
||||
with init_page(vega, browser, request, local_server) as page:
|
||||
risk_accepted_setup(page)
|
||||
page.goto("/#/markets/all")
|
||||
yield page
|
||||
|
||||
@@ -12,8 +12,8 @@ def vega():
|
||||
|
||||
# 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:
|
||||
def page(vega, browser, request, local_server):
|
||||
with init_page(vega, browser, request, local_server) as page:
|
||||
yield page
|
||||
|
||||
|
||||
|
||||
@@ -223,8 +223,8 @@ def markets(vega: VegaService):
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
def page(vega, browser, request, local_server):
|
||||
with init_page(vega, browser, request, local_server) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
page.goto("/")
|
||||
|
||||
@@ -141,8 +141,8 @@ def test_perps_market_terminated(page: Page, vega: VegaService):
|
||||
page.goto(f"/#/markets/{perpetual_market}")
|
||||
# TODO change back to have text once bug #5465 is fixed
|
||||
expect(page.get_by_test_id("market-price")).to_have_text("Mark Price100.00")
|
||||
expect(page.get_by_test_id("market-change")).to_contain_text("Change (24h)")
|
||||
expect(page.get_by_test_id("market-volume")).to_contain_text("Volume (24h)")
|
||||
expect(page.get_by_test_id("market-change")).to_contain_text("Change (24h)-")
|
||||
expect(page.get_by_test_id("market-volume")).to_contain_text("Volume (24h)-")
|
||||
expect(page.get_by_test_id("market-trading-mode")).to_have_text(
|
||||
"Trading modeNo trading"
|
||||
)
|
||||
|
||||
@@ -13,7 +13,7 @@ export default function Document() {
|
||||
{/* preload fonts */}
|
||||
<link
|
||||
rel="preload"
|
||||
href="/AlphaLyrae.woff2"
|
||||
href="/AlphaLyrae-Medium.woff2"
|
||||
as="font"
|
||||
type="font/woff2"
|
||||
/>
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
/** Load AlphaLyrae font */
|
||||
@font-face {
|
||||
font-family: AlphaLyrae;
|
||||
src: url('/AlphaLyrae.woff2') format('woff2');
|
||||
src: url('/AlphaLyrae-Medium.woff2') format('woff2'),
|
||||
url('/AlphaLyrae-Medium.woff') format('woff');
|
||||
}
|
||||
|
||||
@tailwind base;
|
||||
|
||||
Binary file not shown.
@@ -7,7 +7,6 @@ import type {
|
||||
FetchResult,
|
||||
ErrorPolicy,
|
||||
ApolloQueryResult,
|
||||
QueryOptions,
|
||||
} from '@apollo/client';
|
||||
import type { GraphQLErrors } from '@apollo/client/errors';
|
||||
import type { Subscription } from 'zen-observable-ts';
|
||||
@@ -159,7 +158,6 @@ interface DataProviderParams<
|
||||
};
|
||||
fetchPolicy?: FetchPolicy;
|
||||
resetDelay?: number;
|
||||
pollInterval?: number;
|
||||
additionalContext?: Record<string, unknown>;
|
||||
errorPolicyGuard?: (graphqlErrors: GraphQLErrors) => boolean;
|
||||
getQueryVariables?: (variables: Variables) => QueryVariables;
|
||||
@@ -200,7 +198,6 @@ function makeDataProviderInternal<
|
||||
errorPolicyGuard,
|
||||
getQueryVariables,
|
||||
getSubscriptionVariables,
|
||||
pollInterval,
|
||||
}: DataProviderParams<
|
||||
QueryData,
|
||||
Data,
|
||||
@@ -225,7 +222,6 @@ function makeDataProviderInternal<
|
||||
let client: ApolloClient<object>;
|
||||
let subscription: Subscription[] | undefined;
|
||||
let pageInfo: PageInfo | null = null;
|
||||
let watchQuerySubscription: Subscription | null = null;
|
||||
|
||||
// notify single callback about current state, delta is passes optionally only if notify was invoked onNext
|
||||
const notify = (
|
||||
@@ -247,100 +243,34 @@ function makeDataProviderInternal<
|
||||
callbacks.forEach((callback) => notify(callback, updateData));
|
||||
};
|
||||
|
||||
const getQueryOptions = (
|
||||
pagination?: Pagination,
|
||||
policy?: ErrorPolicy
|
||||
): QueryOptions<OperationVariables, QueryData> => ({
|
||||
query,
|
||||
variables: {
|
||||
...(getQueryVariables ? getQueryVariables(variables) : variables),
|
||||
...(pagination && {
|
||||
// let the variables pagination be prior to provider param
|
||||
pagination: {
|
||||
...pagination,
|
||||
...(variables?.['pagination'] ?? null),
|
||||
},
|
||||
}),
|
||||
},
|
||||
fetchPolicy: fetchPolicy || 'no-cache',
|
||||
context: additionalContext,
|
||||
errorPolicy: policy || 'none',
|
||||
pollInterval,
|
||||
});
|
||||
|
||||
const onNext = (res: ApolloQueryResult<QueryData>) => {
|
||||
data = getData(res.data, variables);
|
||||
if (data && pagination) {
|
||||
if (!(data instanceof Array)) {
|
||||
throw new Error(
|
||||
'data needs to be instance of Edge[] when using pagination'
|
||||
);
|
||||
}
|
||||
pageInfo = pagination.getPageInfo(res.data);
|
||||
}
|
||||
// if there was some updates received from subscription during initial query loading apply them on just received data
|
||||
if (update && data && updateQueue && updateQueue.length > 0) {
|
||||
while (updateQueue.length) {
|
||||
const delta = updateQueue.shift();
|
||||
if (delta) {
|
||||
setData(update(data, delta, reload, variables));
|
||||
}
|
||||
}
|
||||
}
|
||||
loaded = true;
|
||||
};
|
||||
|
||||
const onError = (e: Error) => {
|
||||
if (isNotFoundGraphQLError(e, ['party'])) {
|
||||
data = getData(null, variables);
|
||||
loaded = true;
|
||||
return;
|
||||
}
|
||||
// if error will occur data provider stops subscription
|
||||
error = e;
|
||||
subscriptionUnsubscribe();
|
||||
};
|
||||
|
||||
const onComplete = (isUpdate?: boolean) => {
|
||||
loading = false;
|
||||
notifyAll({ isUpdate });
|
||||
};
|
||||
|
||||
const callWatchQuery = (pagination?: Pagination, policy?: ErrorPolicy) => {
|
||||
let onNextCalled = false;
|
||||
try {
|
||||
watchQuerySubscription = client
|
||||
.watchQuery(getQueryOptions(pagination, policy))
|
||||
.subscribe(
|
||||
(res) => {
|
||||
onNext(res);
|
||||
onComplete(onNextCalled);
|
||||
onNextCalled = true;
|
||||
},
|
||||
(error) => {
|
||||
onError(error as Error);
|
||||
onComplete();
|
||||
}
|
||||
);
|
||||
} catch (e) {
|
||||
onError(e as Error);
|
||||
onComplete();
|
||||
}
|
||||
};
|
||||
|
||||
const callQuery = (
|
||||
const call = (
|
||||
pagination?: Pagination,
|
||||
policy?: ErrorPolicy
|
||||
): Promise<ApolloQueryResult<QueryData>> =>
|
||||
client
|
||||
.query<QueryData>(getQueryOptions(pagination, policy))
|
||||
.query<QueryData>({
|
||||
query,
|
||||
variables: {
|
||||
...(getQueryVariables ? getQueryVariables(variables) : variables),
|
||||
...(pagination && {
|
||||
// let the variables pagination be prior to provider param
|
||||
pagination: {
|
||||
...pagination,
|
||||
...(variables?.['pagination'] ?? null),
|
||||
},
|
||||
}),
|
||||
},
|
||||
fetchPolicy: fetchPolicy || 'no-cache',
|
||||
context: additionalContext,
|
||||
errorPolicy: policy || 'none',
|
||||
})
|
||||
.catch((err) => {
|
||||
if (
|
||||
err.graphQLErrors &&
|
||||
errorPolicyGuard &&
|
||||
errorPolicyGuard(err.graphQLErrors)
|
||||
) {
|
||||
return callQuery(pagination, 'ignore');
|
||||
return call(pagination, 'ignore');
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
@@ -364,7 +294,7 @@ function makeDataProviderInternal<
|
||||
}
|
||||
}
|
||||
|
||||
const res = await callQuery(paginationVariables);
|
||||
const res = await call(paginationVariables);
|
||||
|
||||
const insertionData = getData(res.data, variables);
|
||||
const insertionPageInfo = pagination.getPageInfo(res.data);
|
||||
@@ -399,7 +329,7 @@ function makeDataProviderInternal<
|
||||
variables,
|
||||
fetchPolicy,
|
||||
})
|
||||
.subscribe(subscriptionOnNext, subscriptionOnError)
|
||||
.subscribe(onNext, onError)
|
||||
);
|
||||
};
|
||||
|
||||
@@ -417,16 +347,39 @@ function makeDataProviderInternal<
|
||||
const paginationVariables = pagination
|
||||
? { first: pagination.first }
|
||||
: undefined;
|
||||
if (pollInterval) {
|
||||
callWatchQuery();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
onNext(await callQuery(paginationVariables));
|
||||
const res = await call(paginationVariables);
|
||||
data = getData(res.data, variables);
|
||||
if (data && pagination) {
|
||||
if (!(data instanceof Array)) {
|
||||
throw new Error(
|
||||
'data needs to be instance of Edge[] when using pagination'
|
||||
);
|
||||
}
|
||||
pageInfo = pagination.getPageInfo(res.data);
|
||||
}
|
||||
// if there was some updates received from subscription during initial query loading apply them on just received data
|
||||
if (update && data && updateQueue && updateQueue.length > 0) {
|
||||
while (updateQueue.length) {
|
||||
const delta = updateQueue.shift();
|
||||
if (delta) {
|
||||
setData(update(data, delta, reload, variables));
|
||||
}
|
||||
}
|
||||
}
|
||||
loaded = true;
|
||||
} catch (e) {
|
||||
onError(e as Error);
|
||||
if (isNotFoundGraphQLError(e as Error, ['party'])) {
|
||||
data = getData(null, variables);
|
||||
loaded = true;
|
||||
return;
|
||||
}
|
||||
// if error will occur data provider stops subscription
|
||||
error = e as Error;
|
||||
subscriptionUnsubscribe();
|
||||
} finally {
|
||||
onComplete(isUpdate);
|
||||
loading = false;
|
||||
notifyAll({ isUpdate });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -446,7 +399,7 @@ function makeDataProviderInternal<
|
||||
}
|
||||
};
|
||||
|
||||
const subscriptionOnNext = ({
|
||||
const onNext = ({
|
||||
data: subscriptionData,
|
||||
}: FetchResult<SubscriptionData>) => {
|
||||
if (!subscriptionData || !getDelta || !update) {
|
||||
@@ -465,7 +418,7 @@ function makeDataProviderInternal<
|
||||
}
|
||||
};
|
||||
|
||||
const subscriptionOnError = (e: Error) => {
|
||||
const onError = (e: Error) => {
|
||||
error = e;
|
||||
subscriptionUnsubscribe();
|
||||
notifyAll();
|
||||
@@ -489,9 +442,6 @@ function makeDataProviderInternal<
|
||||
};
|
||||
|
||||
const reset = () => {
|
||||
if (watchQuerySubscription) {
|
||||
watchQuerySubscription.unsubscribe();
|
||||
}
|
||||
subscriptionUnsubscribe();
|
||||
initialized = false;
|
||||
data = null;
|
||||
|
||||
@@ -76,14 +76,9 @@ export const DealTicketFeeDetails = ({
|
||||
<KeyValue
|
||||
label={
|
||||
<>
|
||||
<span data-testid="fees-text">{t('Fees')}</span>
|
||||
{t('Fees')}
|
||||
{totalDiscountFactor !== '0' ? (
|
||||
<Pill
|
||||
size="xxs"
|
||||
intent={Intent.Info}
|
||||
className="ml-1"
|
||||
data-testid="discount-pill"
|
||||
>
|
||||
<Pill size="xxs" intent={Intent.Info} className="ml-1">
|
||||
{formatNumberPercentage(
|
||||
new BigNumber(totalDiscountFactor).multipliedBy(100)
|
||||
)}
|
||||
|
||||
@@ -23,23 +23,19 @@ const FeesBreakdownItem = ({
|
||||
value,
|
||||
symbol,
|
||||
decimals,
|
||||
testId,
|
||||
}: {
|
||||
label: string;
|
||||
factor?: string | number;
|
||||
value: string;
|
||||
symbol?: string;
|
||||
decimals: number;
|
||||
testId?: string;
|
||||
}) => (
|
||||
<>
|
||||
<dt className="col-span-2" data-testid={`${testId}-label`}>
|
||||
{label}
|
||||
</dt>
|
||||
<dd className="text-right col-span-1" data-testid={`${testId}-factor`}>
|
||||
<dt className="col-span-2">{label}</dt>
|
||||
<dd className="text-right col-span-1">
|
||||
{factor ? formatNumberPercentage(new BigNumber(factor).times(100)) : ''}
|
||||
</dd>
|
||||
<dd className="text-right col-span-3" data-testid={`${testId}-value`}>
|
||||
<dd className="text-right col-span-3">
|
||||
{formatValue(value, decimals)} {symbol || ''}
|
||||
</dd>
|
||||
</>
|
||||
@@ -77,7 +73,6 @@ export const FeesBreakdown = ({
|
||||
value={fees.infrastructureFee}
|
||||
symbol={symbol}
|
||||
decimals={decimals}
|
||||
testId="infrastructure-fee"
|
||||
/>
|
||||
|
||||
<FeesBreakdownItem
|
||||
@@ -86,7 +81,6 @@ export const FeesBreakdown = ({
|
||||
value={fees.liquidityFee}
|
||||
symbol={symbol}
|
||||
decimals={decimals}
|
||||
testId="liquidity-fee"
|
||||
/>
|
||||
|
||||
<FeesBreakdownItem
|
||||
@@ -95,7 +89,6 @@ export const FeesBreakdown = ({
|
||||
value={fees.makerFee}
|
||||
symbol={symbol}
|
||||
decimals={decimals}
|
||||
testId="maker-fee"
|
||||
/>
|
||||
{totalDiscount && totalDiscount !== '0' ? (
|
||||
<>
|
||||
@@ -107,7 +100,6 @@ export const FeesBreakdown = ({
|
||||
}
|
||||
symbol={symbol}
|
||||
decimals={decimals}
|
||||
testId="subtotal-fee"
|
||||
/>
|
||||
<div className="col-span-6 mt-2"></div>
|
||||
<FeesBreakdownItem
|
||||
@@ -116,14 +108,12 @@ export const FeesBreakdown = ({
|
||||
value={`-${totalDiscount}`}
|
||||
symbol={symbol}
|
||||
decimals={decimals}
|
||||
testId="discount-fee"
|
||||
/>
|
||||
<FeesBreakdownItem
|
||||
label={t('Total')}
|
||||
value={discountedTotalFeeAmount}
|
||||
symbol={symbol}
|
||||
decimals={decimals}
|
||||
testId="total-fee"
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
@@ -137,7 +127,6 @@ export const FeesBreakdown = ({
|
||||
value={totalFeeAmount}
|
||||
symbol={symbol}
|
||||
decimals={decimals}
|
||||
testId="full-total-fee"
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -87,9 +87,9 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
|
||||
colId: 'fee',
|
||||
field: 'market',
|
||||
valueFormatter: formatFee(partyId),
|
||||
tooltipComponent: FeesBreakdownTooltip,
|
||||
type: 'rightAligned',
|
||||
tooltipField: 'market',
|
||||
tooltipComponent: FeesBreakdownTooltip,
|
||||
tooltipComponentParams: { partyId },
|
||||
},
|
||||
{
|
||||
@@ -97,13 +97,13 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
|
||||
colId: 'fee-discount',
|
||||
field: 'market',
|
||||
valueFormatter: formatFeeDiscount(partyId),
|
||||
type: 'rightAligned',
|
||||
// return null to disable tooltip if fee discount is 0 or empty
|
||||
tooltipValueGetter: ({ valueFormatted, value }) => {
|
||||
return valueFormatted && /[1-9]/.test(valueFormatted)
|
||||
? valueFormatted
|
||||
: null;
|
||||
},
|
||||
type: 'rightAligned',
|
||||
// return null to disable tooltip if fee discount is 0 or empty
|
||||
cellRenderer: ({
|
||||
value,
|
||||
valueFormatted,
|
||||
@@ -146,7 +146,7 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
|
||||
overlayNoRowsTemplate={t('No fills')}
|
||||
getRowId={({ data }) => data?.id}
|
||||
tooltipShowDelay={0}
|
||||
tooltipHideDelay={10000}
|
||||
tooltipHideDelay={2000}
|
||||
components={{ MarketNameCell }}
|
||||
{...props}
|
||||
/>
|
||||
@@ -292,27 +292,21 @@ const FeesBreakdownTooltip = ({
|
||||
)}
|
||||
{role === MAKER && (
|
||||
<>
|
||||
<p className="mb-1">{t('The maker will receive the maker fee.')}</p>
|
||||
<p className="mb-1">
|
||||
{t(
|
||||
`Fee revenue to be received by the maker, takers' fee discounts already applied.`
|
||||
)}
|
||||
</p>
|
||||
<p className="mb-1">
|
||||
{t(
|
||||
'During continuous trading the maker pays no infrastructure and liquidity fees.'
|
||||
'If the market is active the maker will pay zero infrastructure and liquidity fees.'
|
||||
)}
|
||||
</p>
|
||||
</>
|
||||
)}
|
||||
{role === TAKER && (
|
||||
<p className="mb-1">
|
||||
{t('Fees to be paid by the taker; discounts are already applied.')}
|
||||
</p>
|
||||
<p className="mb-1">{t('Fees to be paid by the taker.')}</p>
|
||||
)}
|
||||
{(role === '-' || marketState === Schema.MarketState.STATE_SUSPENDED) && (
|
||||
<p className="mb-1">
|
||||
{t(
|
||||
'During auction, half the infrastructure and liquidity fees will be paid.'
|
||||
'If the market is in monitoring auction, half of the infrastructure and liquidity fees will be paid.'
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
"Date": "Date",
|
||||
"Fee": "Fee",
|
||||
"Fee Discount": "Fee Discount",
|
||||
"Fees to be paid by the taker; discounts are already applied.": "Fees to be paid by the taker; discounts are already applied.",
|
||||
"During continuous trading the maker pays no infrastructure and liquidity fees.": "During continuous trading the maker pays no infrastructure and liquidity fees.",
|
||||
"During auction, half the infrastructure and liquidity fees will be paid.": "During auction, half the infrastructure and liquidity fees will be paid.",
|
||||
"Fees to be paid by the taker.": "Fees to be paid by the taker.",
|
||||
"If the market is active the maker will pay zero infrastructure and liquidity fees.": "If the market is active the maker will pay zero infrastructure and liquidity fees.",
|
||||
"If the market is in monitoring auction, half of the infrastructure and liquidity fees will be paid.": "If the market is in monitoring auction, half of the infrastructure and liquidity fees will be paid.",
|
||||
"Infrastructure Fee": "Infrastructure Fee",
|
||||
"Market": "Market",
|
||||
"No fills": "No fills",
|
||||
|
||||
@@ -383,7 +383,7 @@
|
||||
"MoreMarketsInfo": "To see Explorer data on existing markets visit",
|
||||
"MoreNetParamsInfo": "To see Explorer data on network params visit",
|
||||
"MoreProposalsInfo": "To see Explorer data on proposals visit",
|
||||
"multisigContractIncorrect": "was incorrectly configured as at the end of the last epoch so rewards were penalised. Validator and delegator rewards will continue to be penalised until this is resolved.",
|
||||
"multisigContractIncorrect": "is incorrectly configured. Validator and delegator rewards will be penalised until this is resolved.",
|
||||
"multisigContractLink": "Ethereum Multisig Contract",
|
||||
"multisigPenalty": "Multisig penalty",
|
||||
"myPendingStake": "My pending stake",
|
||||
|
||||
@@ -57,7 +57,6 @@
|
||||
"Current tier": "Current tier",
|
||||
"Dark mode": "Dark mode",
|
||||
"Date Joined": "Date Joined",
|
||||
"Depending on data node retention you may not be able see the full 30 days": "Depending on data node retention you may not be able see the full 30 days",
|
||||
"Deposit": "Deposit",
|
||||
"Deposit funds": "Deposit funds",
|
||||
"Deposits": "Deposits",
|
||||
@@ -225,9 +224,9 @@
|
||||
"Referral benefits": "Referral benefits",
|
||||
"Referral discount": "Referral discount",
|
||||
"Referrals": "Referrals",
|
||||
"referralStatisticsCommission": "Commission earned in <0>qUSD</0> (<1>last {{count}} epochs</1>)",
|
||||
"referralStatisticsCommission_one": "Commission earned in <0>qUSD</0> (<1>last {{count}} epoch</1>)",
|
||||
"referralStatisticsCommission_other": "Commission earned in <0>qUSD</0> (<1>last {{count}} epochs</1>)",
|
||||
"referralStatisticsCommission": "Commission earned in <0>qUSD</0> (last {{count}} epochs)",
|
||||
"referralStatisticsCommission_one": "Commission earned in <0>qUSD</0> (last {{count}} epoch)",
|
||||
"referralStatisticsCommission_other": "Commission earned in <0>qUSD</0> (last {{count}} epochs)",
|
||||
"Referrer commission": "Referrer commission",
|
||||
"Referrer trading discount": "Referrer trading discount",
|
||||
"Referrers earn commission based on a percentage of the taker fees their referees pay": "Referrers earn commission based on a percentage of the taker fees their referees pay",
|
||||
@@ -296,9 +295,9 @@
|
||||
"Total distributed": "Total distributed",
|
||||
"Total fee after discount": "Total fee after discount",
|
||||
"Total fee before discount": "Total fee before discount",
|
||||
"totalCommission": "Total commission (<0>last {{count}} epochs</0>)",
|
||||
"totalCommission_one": "Total commission (<0>last {{count}} epoch</0>)",
|
||||
"totalCommission_other": "Total commission (<0>last {{count}} epochs</0>)",
|
||||
"totalCommission": "Total commission (last {{count}}} epochs)",
|
||||
"totalCommission_one": "Total commission (last {{count}}} epoch)",
|
||||
"totalCommission_other": "Total commission (last {{count}}} epochs)",
|
||||
"Trader": "Trader",
|
||||
"Trades": "Trades",
|
||||
"Trading": "Trading",
|
||||
@@ -309,6 +308,9 @@
|
||||
"Trading on Market {{name}} may stop. There are open proposals to close this market": "Trading on Market {{name}} may stop. There are open proposals to close this market",
|
||||
"Trading on Market {{name}} will stop on {{date}}": "Trading on Market {{name}} will stop on {{date}}",
|
||||
"Transfer": "Transfer",
|
||||
"totalCommission": "Total commission (last {{count}} epochs)",
|
||||
"totalCommission_one": "Total commission (last {{count}} epoch)",
|
||||
"totalCommission_other": "Total commission (last {{count}} epochs)",
|
||||
"Unknown": "Unknown",
|
||||
"Unknown settlement date": "Unknown settlement date",
|
||||
"Vega chart": "Vega chart",
|
||||
|
||||
@@ -34,7 +34,6 @@ export const marketInfoProvider = makeDataProvider<
|
||||
query: MarketInfoDocument,
|
||||
getData,
|
||||
errorPolicyGuard: marketDataErrorPolicyGuard,
|
||||
pollInterval: 5000,
|
||||
});
|
||||
|
||||
export const marketInfoWithDataProvider = makeDerivedDataProvider<
|
||||
|
||||
@@ -68,13 +68,10 @@ export const useBlockRising = (skip = false) => {
|
||||
}
|
||||
);
|
||||
|
||||
const heights = compact([...results.map((r) => r?.blockHeight)]);
|
||||
|
||||
// Handles TendermintErrorResponses
|
||||
if (blockInfo && 'result' in blockInfo) {
|
||||
heights.push(blockInfo.result.block.header.height);
|
||||
}
|
||||
|
||||
const heights = compact([
|
||||
...results.map((r) => r?.blockHeight),
|
||||
blockInfo?.result.block.header.height,
|
||||
]);
|
||||
const current = max(heights);
|
||||
if (current && Number(current) > prev) {
|
||||
setBlock(Number(current));
|
||||
|
||||
@@ -76,26 +76,16 @@ export const useFetch = <T>(
|
||||
...options,
|
||||
body: body ? body : options?.body,
|
||||
});
|
||||
|
||||
data = (await response.json()) as T;
|
||||
|
||||
if (!response.ok && !data) {
|
||||
if (!response.ok) {
|
||||
throw new Error(response.statusText);
|
||||
}
|
||||
|
||||
data = (await response.json()) as T;
|
||||
// @ts-ignore - 'error' in data
|
||||
if (data && data.error) {
|
||||
// Explicit check for TendermintErrorResponse style error
|
||||
// @ts-ignore - 'error' in data
|
||||
if (data.error.data) {
|
||||
// @ts-ignore - 'error' in data
|
||||
|
||||
throw new Error(data.error.data);
|
||||
}
|
||||
if (data && 'error' in data) {
|
||||
// @ts-ignore - data.error
|
||||
throw new Error(data.error);
|
||||
}
|
||||
|
||||
if (cancelRequest.current) return;
|
||||
|
||||
dispatch({ type: ActionType.FETCHED, payload: data });
|
||||
|
||||
@@ -1,11 +1,6 @@
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { useFetch } from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
TendermintBlockResponse,
|
||||
TendermintErrorResponse,
|
||||
} from '../types';
|
||||
|
||||
type TendermintResponse = TendermintBlockResponse | TendermintErrorResponse;
|
||||
import { type TendermintBlockResponse } from '../types';
|
||||
|
||||
export const useBlockInfo = (blockHeight?: number, canFetch = true) => {
|
||||
const { TENDERMINT_URL } = useEnvironment();
|
||||
@@ -15,7 +10,7 @@ export const useBlockInfo = (blockHeight?: number, canFetch = true) => {
|
||||
TENDERMINT_URL && blockHeight && !isNaN(blockHeight) && canFetch
|
||||
);
|
||||
|
||||
const { state, refetch } = useFetch<TendermintResponse>(
|
||||
const { state, refetch } = useFetch<TendermintBlockResponse>(
|
||||
url,
|
||||
{ cache: 'force-cache' },
|
||||
canFetchData
|
||||
|
||||
@@ -7,16 +7,6 @@ export type TendermintBlockResponse = {
|
||||
};
|
||||
};
|
||||
|
||||
export type TendermintErrorResponse = {
|
||||
jsonrpc: string;
|
||||
id: number;
|
||||
error: {
|
||||
code: number;
|
||||
message: string;
|
||||
data: string;
|
||||
};
|
||||
};
|
||||
|
||||
type Id = {
|
||||
hash: string;
|
||||
parts: {
|
||||
@@ -44,7 +34,7 @@ type Header = {
|
||||
proposer_address: string;
|
||||
};
|
||||
|
||||
export type Block = {
|
||||
type Block = {
|
||||
header: Header;
|
||||
data: {
|
||||
txs: string[];
|
||||
|
||||
Reference in New Issue
Block a user