feat(trading): show commission earned on referrer stats from last 30 days (#5467)

This commit is contained in:
Bartłomiej Głownia 2023-12-18 15:33:40 +01:00 committed by GitHub
parent 902ee2696c
commit 665ab6693a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 160 additions and 28 deletions

View File

@ -2,6 +2,7 @@ import { removePaginationWrapper } from '@vegaprotocol/utils';
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useRefereesQuery } from './__generated__/Referees'; import { useRefereesQuery } from './__generated__/Referees';
import compact from 'lodash/compact'; import compact from 'lodash/compact';
import pick from 'lodash/pick';
import type { import type {
ReferralSetsQuery, ReferralSetsQuery,
ReferralSetsQueryVariables, ReferralSetsQueryVariables,
@ -122,6 +123,66 @@ 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) => const retrieveReferralSetData = (data: ReferralSetsQuery | undefined) =>
data?.referralSets.edges && data.referralSets.edges.length > 0 data?.referralSets.edges && data.referralSets.edges.length > 0
? data.referralSets.edges[0]?.node ? data.referralSets.edges[0]?.node

View File

@ -151,6 +151,27 @@ 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> = { const programMock: MockedResponse<ReferralProgramQuery> = {
request: { request: {
query: ReferralProgramDocument, query: ReferralProgramDocument,
@ -262,6 +283,19 @@ 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', () => { jest.mock('@vegaprotocol/wallet', () => {
return { return {
...jest.requireActual('@vegaprotocol/wallet'), ...jest.requireActual('@vegaprotocol/wallet'),
@ -297,6 +331,7 @@ describe('ReferralStatistics', () => {
noReferralSetAsRefereeMock, noReferralSetAsRefereeMock,
stakeAvailableMock, stakeAvailableMock,
refereesMock, refereesMock,
refereesMock30,
]} ]}
showWarnings={false} showWarnings={false}
> >
@ -313,6 +348,10 @@ describe('ReferralStatistics', () => {
expect(queryByTestId('referral-statistics')?.dataset.as).toEqual( expect(queryByTestId('referral-statistics')?.dataset.as).toEqual(
'referrer' 'referrer'
); );
// gets commision from 30 epochs query
expect(queryByTestId('total-commission-value')).toHaveTextContent(
'12,340'
);
}); });
}); });

View File

@ -4,10 +4,15 @@ import {
VegaIcon, VegaIcon,
VegaIconNames, VegaIconNames,
truncateMiddle, truncateMiddle,
TextChildrenTooltip as Tooltip,
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import { DEFAULT_AGGREGATION_DAYS, useReferral } from './hooks/use-referral'; import {
DEFAULT_AGGREGATION_DAYS,
useReferral,
useUpdateReferees,
} from './hooks/use-referral';
import classNames from 'classnames'; import classNames from 'classnames';
import { Table } from './table'; import { Table } from './table';
import { import {
@ -41,11 +46,17 @@ export const ReferralStatistics = () => {
role: 'referee', role: 'referee',
aggregationEpochs: program.details?.windowLength, aggregationEpochs: program.details?.windowLength,
}); });
const { data: referrer, refetch: referrerRefetch } = useReferral({
pubKey, const { data: referrer, refetch: referrerRefetch } = useUpdateReferees(
role: 'referrer', useReferral({
aggregationEpochs: program.details?.windowLength, pubKey,
}); role: 'referrer',
aggregationEpochs: program.details?.windowLength,
}),
DEFAULT_AGGREGATION_DAYS,
['totalRefereeGeneratedRewards'],
DEFAULT_AGGREGATION_DAYS === program.details?.windowLength
);
const refetch = useCallback(() => { const refetch = useCallback(() => {
refereeRefetch(); refereeRefetch();
@ -76,11 +87,9 @@ export const ReferralStatistics = () => {
export const useStats = ({ export const useStats = ({
data, data,
program, program,
as,
}: { }: {
data?: NonNullable<ReturnType<typeof useReferral>['data']>; data?: NonNullable<ReturnType<typeof useReferral>['data']>;
program: ReturnType<typeof useReferralProgram>; program: ReturnType<typeof useReferralProgram>;
as?: 'referrer' | 'referee';
}) => { }) => {
const { benefitTiers } = program; const { benefitTiers } = program;
const { data: epochData } = useCurrentEpochInfoQuery({ const { data: epochData } = useCurrentEpochInfoQuery({
@ -181,7 +190,7 @@ export const Statistics = ({
nextBenefitTierValue, nextBenefitTierValue,
nextBenefitTierVolumeValue, nextBenefitTierVolumeValue,
nextBenefitTierEpochsValue, nextBenefitTierEpochsValue,
} = useStats({ data, program, as }); } = useStats({ data, program });
const isApplyCodePreview = useMemo( const isApplyCodePreview = useMemo(
() => data.referee === null, () => data.referee === null,
@ -293,11 +302,27 @@ export const Statistics = ({
.reduce((all, r) => all.plus(r), new BigNumber(0)); .reduce((all, r) => all.plus(r), new BigNumber(0));
const totalCommissionTile = ( const totalCommissionTile = (
<StatTile <StatTile
title={t('totalCommission', 'Total commission (last {{count}} epochs)', {
count: details?.windowLength || DEFAULT_AGGREGATION_DAYS,
})}
description={<QUSDTooltip />}
testId="total-commission" 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>,
]}
/>
}
description={<QUSDTooltip />}
> >
{getNumberFormat(0).format(Number(totalCommissionValue))} {getNumberFormat(0).format(Number(totalCommissionValue))}
</StatTile> </StatTile>
@ -503,12 +528,21 @@ export const RefereesTable = ({
displayName: ( displayName: (
<Trans <Trans
i18nKey="referralStatisticsCommission" i18nKey="referralStatisticsCommission"
defaults="Commission earned in <0>qUSD</0> (last {{count}} epochs)" 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>,
]}
values={{ values={{
count: count: DEFAULT_AGGREGATION_DAYS,
details?.windowLength || DEFAULT_AGGREGATION_DAYS,
}} }}
components={[<QUSDTooltip key="qusd" />]}
ns={ns} ns={ns}
/> />
), ),

View File

@ -31,7 +31,7 @@ export const Tile = ({
}; };
type StatTileProps = { type StatTileProps = {
title: string; title: ReactNode;
testId?: string; testId?: string;
description?: ReactNode; description?: ReactNode;
children?: ReactNode; children?: ReactNode;
@ -70,7 +70,7 @@ export const StatTile = ({
export const NoProgramTile = ({ title }: Pick<StatTileProps, 'title'>) => { export const NoProgramTile = ({ title }: Pick<StatTileProps, 'title'>) => {
const t = useT(); const t = useT();
return ( return (
<Tile title={title}> <Tile>
<h3 className="mb-1 text-sm text-vega-clight-100 dark:text-vega-cdark-100 calt"> <h3 className="mb-1 text-sm text-vega-clight-100 dark:text-vega-cdark-100 calt">
{title} {title}
</h3> </h3>

View File

@ -57,6 +57,7 @@
"Current tier": "Current tier", "Current tier": "Current tier",
"Dark mode": "Dark mode", "Dark mode": "Dark mode",
"Date Joined": "Date Joined", "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": "Deposit",
"Deposit funds": "Deposit funds", "Deposit funds": "Deposit funds",
"Deposits": "Deposits", "Deposits": "Deposits",
@ -224,9 +225,9 @@
"Referral benefits": "Referral benefits", "Referral benefits": "Referral benefits",
"Referral discount": "Referral discount", "Referral discount": "Referral discount",
"Referrals": "Referrals", "Referrals": "Referrals",
"referralStatisticsCommission": "Commission earned in <0>qUSD</0> (last {{count}} epochs)", "referralStatisticsCommission": "Commission earned in <0>qUSD</0> (<1>last {{count}} epochs</1>)",
"referralStatisticsCommission_one": "Commission earned in <0>qUSD</0> (last {{count}} epoch)", "referralStatisticsCommission_one": "Commission earned in <0>qUSD</0> (<1>last {{count}} epoch</1>)",
"referralStatisticsCommission_other": "Commission earned in <0>qUSD</0> (last {{count}} epochs)", "referralStatisticsCommission_other": "Commission earned in <0>qUSD</0> (<1>last {{count}} epochs</1>)",
"Referrer commission": "Referrer commission", "Referrer commission": "Referrer commission",
"Referrer trading discount": "Referrer trading discount", "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", "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",
@ -295,9 +296,9 @@
"Total distributed": "Total distributed", "Total distributed": "Total distributed",
"Total fee after discount": "Total fee after discount", "Total fee after discount": "Total fee after discount",
"Total fee before discount": "Total fee before discount", "Total fee before discount": "Total fee before discount",
"totalCommission": "Total commission (last {{count}}} epochs)", "totalCommission": "Total commission (<0>last {{count}} epochs</0>)",
"totalCommission_one": "Total commission (last {{count}}} epoch)", "totalCommission_one": "Total commission (<0>last {{count}} epoch</0>)",
"totalCommission_other": "Total commission (last {{count}}} epochs)", "totalCommission_other": "Total commission (<0>last {{count}} epochs</0>)",
"Trader": "Trader", "Trader": "Trader",
"Trades": "Trades", "Trades": "Trades",
"Trading": "Trading", "Trading": "Trading",
@ -308,9 +309,6 @@
"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}} 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}}", "Trading on Market {{name}} will stop on {{date}}": "Trading on Market {{name}} will stop on {{date}}",
"Transfer": "Transfer", "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": "Unknown",
"Unknown settlement date": "Unknown settlement date", "Unknown settlement date": "Unknown settlement date",
"Vega chart": "Vega chart", "Vega chart": "Vega chart",