Compare commits
6 Commits
develop
...
feat/5767-
Author | SHA1 | Date | |
---|---|---|---|
|
7176ff63f1 | ||
|
fb7860ec4f | ||
|
034afe7e54 | ||
|
725b5f1b23 | ||
|
f50e813ed2 | ||
|
80620abaff |
@ -4,7 +4,7 @@ import { CompetitionsHeader } from '../../components/competitions/competitions-h
|
|||||||
import { Intent, Loader, TradingButton } from '@vegaprotocol/ui-toolkit';
|
import { Intent, Loader, TradingButton } from '@vegaprotocol/ui-toolkit';
|
||||||
|
|
||||||
import { useGameCards } from '../../lib/hooks/use-game-cards';
|
import { useGameCards } from '../../lib/hooks/use-game-cards';
|
||||||
import { useCurrentEpochInfoQuery } from '../../lib/hooks/__generated__/Epoch';
|
import { useEpochInfoQuery } from '../../lib/hooks/__generated__/Epoch';
|
||||||
import { Link, useNavigate } from 'react-router-dom';
|
import { Link, useNavigate } from 'react-router-dom';
|
||||||
import { Links } from '../../lib/links';
|
import { Links } from '../../lib/links';
|
||||||
import {
|
import {
|
||||||
@ -25,7 +25,7 @@ export const CompetitionsHome = () => {
|
|||||||
|
|
||||||
usePageTitle(t('Competitions'));
|
usePageTitle(t('Competitions'));
|
||||||
|
|
||||||
const { data: epochData } = useCurrentEpochInfoQuery();
|
const { data: epochData } = useEpochInfoQuery();
|
||||||
const currentEpoch = Number(epochData?.epoch.id);
|
const currentEpoch = Number(epochData?.epoch.id);
|
||||||
|
|
||||||
const { data: gamesData, loading: gamesLoading } = useGameCards({
|
const { data: gamesData, loading: gamesLoading } = useGameCards({
|
||||||
|
@ -1,12 +1,28 @@
|
|||||||
import { useState, type ButtonHTMLAttributes } from 'react';
|
import { useState, type ButtonHTMLAttributes, useRef } from 'react';
|
||||||
import { Link, useParams } from 'react-router-dom';
|
import { Link, useParams } from 'react-router-dom';
|
||||||
import orderBy from 'lodash/orderBy';
|
import orderBy from 'lodash/orderBy';
|
||||||
import { Splash, truncateMiddle, Loader } from '@vegaprotocol/ui-toolkit';
|
import {
|
||||||
import { DispatchMetricLabels, type DispatchMetric } from '@vegaprotocol/types';
|
Splash,
|
||||||
|
truncateMiddle,
|
||||||
|
Loader,
|
||||||
|
Dialog,
|
||||||
|
Button,
|
||||||
|
VegaIcon,
|
||||||
|
VegaIconNames,
|
||||||
|
} from '@vegaprotocol/ui-toolkit';
|
||||||
|
import {
|
||||||
|
TransferStatus,
|
||||||
|
type Asset,
|
||||||
|
type RecurringTransfer,
|
||||||
|
} from '@vegaprotocol/types';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { useT } from '../../lib/use-t';
|
import { useT } from '../../lib/use-t';
|
||||||
import { Table } from '../../components/table';
|
import { Table } from '../../components/table';
|
||||||
import { formatNumber, getDateTimeFormat } from '@vegaprotocol/utils';
|
import {
|
||||||
|
addDecimalsFormatNumberQuantum,
|
||||||
|
formatNumber,
|
||||||
|
getDateTimeFormat,
|
||||||
|
} from '@vegaprotocol/utils';
|
||||||
import {
|
import {
|
||||||
useTeam,
|
useTeam,
|
||||||
type TeamStats as ITeamStats,
|
type TeamStats as ITeamStats,
|
||||||
@ -27,6 +43,19 @@ import {
|
|||||||
useGames,
|
useGames,
|
||||||
areTeamGames,
|
areTeamGames,
|
||||||
} from '../../lib/hooks/use-games';
|
} from '../../lib/hooks/use-games';
|
||||||
|
import { useEpochInfoQuery } from '../../lib/hooks/__generated__/Epoch';
|
||||||
|
import {
|
||||||
|
type EnrichedTransfer,
|
||||||
|
isScopedToTeams,
|
||||||
|
useGameCards,
|
||||||
|
} from '../../lib/hooks/use-game-cards';
|
||||||
|
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||||
|
import {
|
||||||
|
ActiveRewardCard,
|
||||||
|
DispatchMetricInfo,
|
||||||
|
} from '../../components/rewards-container/active-rewards';
|
||||||
|
import { type MarketMap, useMarketsMapProvider } from '@vegaprotocol/markets';
|
||||||
|
import format from 'date-fns/format';
|
||||||
|
|
||||||
export const CompetitionsTeam = () => {
|
export const CompetitionsTeam = () => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
@ -49,6 +78,14 @@ const TeamPageContainer = ({ teamId }: { teamId: string | undefined }) => {
|
|||||||
|
|
||||||
const { data: games, loading: gamesLoading } = useGames(teamId);
|
const { data: games, loading: gamesLoading } = useGames(teamId);
|
||||||
|
|
||||||
|
const { data: epochData, loading: epochLoading } = useEpochInfoQuery();
|
||||||
|
const { data: transfersData, loading: transfersLoading } = useGameCards({
|
||||||
|
currentEpoch: Number(epochData?.epoch.id),
|
||||||
|
onlyActive: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { data: markets } = useMarketsMapProvider();
|
||||||
|
|
||||||
// only show spinner on first load so when users join teams its smoother
|
// only show spinner on first load so when users join teams its smoother
|
||||||
if (!data && loading) {
|
if (!data && loading) {
|
||||||
return (
|
return (
|
||||||
@ -74,6 +111,9 @@ const TeamPageContainer = ({ teamId }: { teamId: string | undefined }) => {
|
|||||||
members={members}
|
members={members}
|
||||||
games={areTeamGames(games) ? games : undefined}
|
games={areTeamGames(games) ? games : undefined}
|
||||||
gamesLoading={gamesLoading}
|
gamesLoading={gamesLoading}
|
||||||
|
transfers={transfersData}
|
||||||
|
transfersLoading={epochLoading || transfersLoading}
|
||||||
|
allMarkets={markets || undefined}
|
||||||
refetch={refetch}
|
refetch={refetch}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
@ -86,6 +126,9 @@ const TeamPage = ({
|
|||||||
members,
|
members,
|
||||||
games,
|
games,
|
||||||
gamesLoading,
|
gamesLoading,
|
||||||
|
transfers,
|
||||||
|
transfersLoading,
|
||||||
|
allMarkets,
|
||||||
refetch,
|
refetch,
|
||||||
}: {
|
}: {
|
||||||
team: TeamType;
|
team: TeamType;
|
||||||
@ -94,6 +137,9 @@ const TeamPage = ({
|
|||||||
members?: Member[];
|
members?: Member[];
|
||||||
games?: TeamGame[];
|
games?: TeamGame[];
|
||||||
gamesLoading?: boolean;
|
gamesLoading?: boolean;
|
||||||
|
transfers?: EnrichedTransfer[];
|
||||||
|
transfersLoading?: boolean;
|
||||||
|
allMarkets?: MarketMap;
|
||||||
refetch: () => void;
|
refetch: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
@ -141,7 +187,13 @@ const TeamPage = ({
|
|||||||
</ToggleButton>
|
</ToggleButton>
|
||||||
</div>
|
</div>
|
||||||
{showGames ? (
|
{showGames ? (
|
||||||
<Games games={games} gamesLoading={gamesLoading} />
|
<Games
|
||||||
|
games={games}
|
||||||
|
gamesLoading={gamesLoading}
|
||||||
|
transfers={transfers}
|
||||||
|
transfersLoading={transfersLoading}
|
||||||
|
allMarkets={allMarkets}
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Members members={members} />
|
<Members members={members} />
|
||||||
)}
|
)}
|
||||||
@ -153,9 +205,15 @@ const TeamPage = ({
|
|||||||
const Games = ({
|
const Games = ({
|
||||||
games,
|
games,
|
||||||
gamesLoading,
|
gamesLoading,
|
||||||
|
transfers,
|
||||||
|
transfersLoading,
|
||||||
|
allMarkets,
|
||||||
}: {
|
}: {
|
||||||
games?: TeamGame[];
|
games?: TeamGame[];
|
||||||
gamesLoading?: boolean;
|
gamesLoading?: boolean;
|
||||||
|
transfers?: EnrichedTransfer[];
|
||||||
|
transfersLoading?: boolean;
|
||||||
|
allMarkets?: MarketMap;
|
||||||
}) => {
|
}) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
|
|
||||||
@ -171,40 +229,106 @@ const Games = ({
|
|||||||
return <p>{t('No game results available')}</p>;
|
return <p>{t('No game results available')}</p>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const dependable = (value: string | JSX.Element) => {
|
||||||
|
if (transfersLoading) return <Loader size="small" />;
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Table
|
<Table
|
||||||
columns={[
|
columns={[
|
||||||
{ name: 'rank', displayName: t('Rank') },
|
|
||||||
{
|
{
|
||||||
name: 'epoch',
|
name: 'epoch',
|
||||||
displayName: t('Epoch'),
|
displayName: t('Epoch'),
|
||||||
headerClassName: 'hidden md:table-cell',
|
},
|
||||||
className: 'hidden md:table-cell',
|
{
|
||||||
|
name: 'endtime',
|
||||||
|
displayName: t('End time'),
|
||||||
},
|
},
|
||||||
{ name: 'type', displayName: t('Type') },
|
{ name: 'type', displayName: t('Type') },
|
||||||
{ name: 'amount', displayName: t('Amount earned') },
|
{
|
||||||
|
name: 'asset',
|
||||||
|
displayName: t('Reward asset'),
|
||||||
|
},
|
||||||
|
{ name: 'daily', displayName: t('Daily reward amount') },
|
||||||
|
{ name: 'rank', displayName: t('Rank') },
|
||||||
|
{ name: 'amount', displayName: t('Amount earned this epoch') },
|
||||||
|
{ name: 'total', displayName: t('Cumulative amount earned') },
|
||||||
{
|
{
|
||||||
name: 'participatingTeams',
|
name: 'participatingTeams',
|
||||||
displayName: t('No. of participating teams'),
|
displayName: t('No. of participating teams'),
|
||||||
headerClassName: 'hidden md:table-cell',
|
|
||||||
className: 'hidden md:table-cell',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'participatingMembers',
|
name: 'participatingMembers',
|
||||||
displayName: t('No. of participating members'),
|
displayName: t('No. of participating members'),
|
||||||
headerClassName: 'hidden md:table-cell',
|
|
||||||
className: 'hidden md:table-cell',
|
|
||||||
},
|
},
|
||||||
]}
|
].map((c) => ({ ...c, headerClassName: 'text-left' }))}
|
||||||
data={games.map((game) => ({
|
data={games.map((game) => {
|
||||||
rank: game.team.rank,
|
let transfer = transfers?.find((t) => {
|
||||||
|
if (!isScopedToTeams(t)) return false;
|
||||||
|
|
||||||
|
const idMatch = t.transfer.gameId === game.id;
|
||||||
|
const metricMatch =
|
||||||
|
t.transfer.kind.dispatchStrategy?.dispatchMetric ===
|
||||||
|
game.team.rewardMetric;
|
||||||
|
|
||||||
|
const start = t.transfer.kind.startEpoch <= game.epoch;
|
||||||
|
const end = t.transfer.kind.endEpoch
|
||||||
|
? t.transfer.kind.endEpoch >= game.epoch
|
||||||
|
: true;
|
||||||
|
|
||||||
|
const rejected = t.transfer.status === TransferStatus.STATUS_REJECTED;
|
||||||
|
|
||||||
|
return idMatch && metricMatch && start && end && !rejected;
|
||||||
|
});
|
||||||
|
if (!transfer || !isScopedToTeams(transfer)) transfer = undefined;
|
||||||
|
const asset = transfer?.transfer.asset;
|
||||||
|
|
||||||
|
const dailyAmount =
|
||||||
|
asset && transfer
|
||||||
|
? addDecimalsFormatNumberQuantum(
|
||||||
|
transfer.transfer.amount,
|
||||||
|
asset.decimals,
|
||||||
|
asset.quantum
|
||||||
|
)
|
||||||
|
: '-';
|
||||||
|
|
||||||
|
const earnedAmount = asset
|
||||||
|
? addDecimalsFormatNumberQuantum(
|
||||||
|
game.team.rewardEarned,
|
||||||
|
asset.decimals,
|
||||||
|
asset.quantum
|
||||||
|
)
|
||||||
|
: '-';
|
||||||
|
|
||||||
|
const totalAmount = asset
|
||||||
|
? addDecimalsFormatNumberQuantum(
|
||||||
|
game.team.totalRewardsEarned,
|
||||||
|
asset.decimals,
|
||||||
|
asset.quantum
|
||||||
|
)
|
||||||
|
: '-';
|
||||||
|
|
||||||
|
const assetSymbol = asset ? <RewardAssetCell asset={asset} /> : '-';
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: game.id,
|
||||||
|
amount: dependable(earnedAmount),
|
||||||
|
asset: dependable(assetSymbol),
|
||||||
|
daily: dependable(dailyAmount),
|
||||||
|
endtime: <EndTimeCell epoch={game.epoch} />,
|
||||||
epoch: game.epoch,
|
epoch: game.epoch,
|
||||||
type: DispatchMetricLabels[game.team.rewardMetric as DispatchMetric],
|
|
||||||
amount: formatNumber(game.team.totalRewardsEarned),
|
|
||||||
participatingTeams: game.entities.length,
|
|
||||||
participatingMembers: game.numberOfParticipants,
|
participatingMembers: game.numberOfParticipants,
|
||||||
}))}
|
participatingTeams: game.entities.length,
|
||||||
noCollapse={true}
|
rank: game.team.rank,
|
||||||
|
total: totalAmount,
|
||||||
|
// type: DispatchMetricLabels[game.team.rewardMetric as DispatchMetric],
|
||||||
|
type: dependable(
|
||||||
|
<GameTypeCell transfer={transfer} allMarkets={allMarkets} />
|
||||||
|
),
|
||||||
|
};
|
||||||
|
})}
|
||||||
|
noCollapse={false}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -286,3 +410,126 @@ const ToggleButton = ({
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const EndTimeCell = ({ epoch }: { epoch?: number }) => {
|
||||||
|
const { data, loading } = useEpochInfoQuery({
|
||||||
|
variables: {
|
||||||
|
epochId: epoch ? epoch.toString() : undefined,
|
||||||
|
},
|
||||||
|
fetchPolicy: 'cache-and-network',
|
||||||
|
});
|
||||||
|
|
||||||
|
if (loading) return <Loader size="small" />;
|
||||||
|
if (data) {
|
||||||
|
return format(
|
||||||
|
new Date(data.epoch.timestamps.expiry),
|
||||||
|
'yyyy/MM/dd hh:mm:ss'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const RewardAssetCell = ({ asset }: { asset: Asset }) => {
|
||||||
|
const open = useAssetDetailsDialogStore((state) => state.open);
|
||||||
|
const ref = useRef<HTMLButtonElement>(null);
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
ref={ref}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
open(asset.id, ref.current);
|
||||||
|
}}
|
||||||
|
className="border-b border-dashed border-vega-clight-200 dark:border-vega-cdark-200 text-left text-nowrap whitespace-nowrap"
|
||||||
|
>
|
||||||
|
{asset.symbol}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const GameTypeCell = ({
|
||||||
|
transfer,
|
||||||
|
allMarkets,
|
||||||
|
}: {
|
||||||
|
transfer?: EnrichedTransfer;
|
||||||
|
allMarkets?: MarketMap;
|
||||||
|
}) => {
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
const ref = useRef<HTMLButtonElement>(null);
|
||||||
|
if (!transfer) return '-';
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<ActiveRewardCardDialog
|
||||||
|
open={open}
|
||||||
|
onChange={(isOpen) => setOpen(isOpen)}
|
||||||
|
trigger={ref.current}
|
||||||
|
transfer={transfer}
|
||||||
|
allMarkets={allMarkets}
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setOpen(true);
|
||||||
|
}}
|
||||||
|
ref={ref}
|
||||||
|
className="border-b border-dashed border-vega-clight-200 dark:border-vega-cdark-200 text-left md:truncate md:max-w-[25vw]"
|
||||||
|
>
|
||||||
|
<DispatchMetricInfo transferNode={transfer} allMarkets={allMarkets} />
|
||||||
|
</button>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const ActiveRewardCardDialog = ({
|
||||||
|
open,
|
||||||
|
onChange,
|
||||||
|
trigger,
|
||||||
|
transfer,
|
||||||
|
allMarkets,
|
||||||
|
}: {
|
||||||
|
open: boolean;
|
||||||
|
onChange: (isOpen: boolean) => void;
|
||||||
|
trigger?: HTMLElement | null;
|
||||||
|
transfer: EnrichedTransfer;
|
||||||
|
allMarkets?: MarketMap;
|
||||||
|
}) => {
|
||||||
|
const t = useT();
|
||||||
|
const { data } = useEpochInfoQuery();
|
||||||
|
return (
|
||||||
|
<Dialog
|
||||||
|
open={open}
|
||||||
|
title={t('Game details')}
|
||||||
|
onChange={(isOpen) => onChange(isOpen)}
|
||||||
|
icon={<VegaIcon name={VegaIconNames.INFO} />}
|
||||||
|
onCloseAutoFocus={(e) => {
|
||||||
|
/**
|
||||||
|
* This mimics radix's default behaviour that focuses the dialog's
|
||||||
|
* trigger after closing itself
|
||||||
|
*/
|
||||||
|
if (trigger) {
|
||||||
|
e.preventDefault();
|
||||||
|
trigger.focus();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className="py-5 max-w-[454px]">
|
||||||
|
<ActiveRewardCard
|
||||||
|
transferNode={transfer}
|
||||||
|
currentEpoch={Number(data?.epoch.id)}
|
||||||
|
kind={transfer.transfer.kind as RecurringTransfer}
|
||||||
|
allMarkets={allMarkets}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-1/4">
|
||||||
|
<Button
|
||||||
|
data-testid="close-asset-details-dialog"
|
||||||
|
fill={true}
|
||||||
|
size="sm"
|
||||||
|
onClick={() => onChange(false)}
|
||||||
|
>
|
||||||
|
{t('Close')}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
@ -11,7 +11,7 @@ import { useEffect } from 'react';
|
|||||||
import { useT } from '../../../lib/use-t';
|
import { useT } from '../../../lib/use-t';
|
||||||
import { matchPath, useLocation, useNavigate } from 'react-router-dom';
|
import { matchPath, useLocation, useNavigate } from 'react-router-dom';
|
||||||
import { Routes } from '../../../lib/links';
|
import { Routes } from '../../../lib/links';
|
||||||
import { useCurrentEpochInfoQuery } from '../../../lib/hooks/__generated__/Epoch';
|
import { useEpochInfoQuery } from '../../../lib/hooks/__generated__/Epoch';
|
||||||
|
|
||||||
const REFETCH_INTERVAL = 60 * 60 * 1000; // 1h
|
const REFETCH_INTERVAL = 60 * 60 * 1000; // 1h
|
||||||
const NON_ELIGIBLE_REFERRAL_SET_TOAST_ID = 'non-eligible-referral-set';
|
const NON_ELIGIBLE_REFERRAL_SET_TOAST_ID = 'non-eligible-referral-set';
|
||||||
@ -23,7 +23,7 @@ const useNonEligibleReferralSet = () => {
|
|||||||
data: epochData,
|
data: epochData,
|
||||||
loading: epochLoading,
|
loading: epochLoading,
|
||||||
refetch: epochRefetch,
|
refetch: epochRefetch,
|
||||||
} = useCurrentEpochInfoQuery();
|
} = useEpochInfoQuery();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(() => {
|
||||||
|
@ -34,7 +34,7 @@ import {
|
|||||||
} from './hooks/use-referral';
|
} from './hooks/use-referral';
|
||||||
import { ApplyCodeForm, ApplyCodeFormContainer } from './apply-code-form';
|
import { ApplyCodeForm, ApplyCodeFormContainer } from './apply-code-form';
|
||||||
import { useReferralProgram } from './hooks/use-referral-program';
|
import { useReferralProgram } from './hooks/use-referral-program';
|
||||||
import { useCurrentEpochInfoQuery } from '../../lib/hooks/__generated__/Epoch';
|
import { useEpochInfoQuery } from '../../lib/hooks/__generated__/Epoch';
|
||||||
import { QUSDTooltip } from './qusd-tooltip';
|
import { QUSDTooltip } from './qusd-tooltip';
|
||||||
import { CodeTile, StatTile, Tile } from './tile';
|
import { CodeTile, StatTile, Tile } from './tile';
|
||||||
import { areTeamGames, useGames } from '../../lib/hooks/use-games';
|
import { areTeamGames, useGames } from '../../lib/hooks/use-games';
|
||||||
@ -95,7 +95,7 @@ export const useStats = ({
|
|||||||
program: ReturnType<typeof useReferralProgram>;
|
program: ReturnType<typeof useReferralProgram>;
|
||||||
}) => {
|
}) => {
|
||||||
const { benefitTiers } = program;
|
const { benefitTiers } = program;
|
||||||
const { data: epochData } = useCurrentEpochInfoQuery({
|
const { data: epochData } = useEpochInfoQuery({
|
||||||
fetchPolicy: 'network-only',
|
fetchPolicy: 'network-only',
|
||||||
});
|
});
|
||||||
const { data: statsData } = useReferralSetStatsQuery({
|
const { data: statsData } = useReferralSetStatsQuery({
|
||||||
|
@ -1,49 +1,19 @@
|
|||||||
import { type TransferNode } from '@vegaprotocol/types';
|
import { ActiveRewardCard } from '../rewards-container/active-rewards';
|
||||||
import {
|
|
||||||
ActiveRewardCard,
|
|
||||||
isActiveReward,
|
|
||||||
} from '../rewards-container/active-rewards';
|
|
||||||
import { useT } from '../../lib/use-t';
|
import { useT } from '../../lib/use-t';
|
||||||
import { useAssetsMapProvider } from '@vegaprotocol/assets';
|
import { type EnrichedTransfer } from '../../lib/hooks/use-game-cards';
|
||||||
import { useMarketsMapProvider } from '@vegaprotocol/markets';
|
import { useMarketsMapProvider } from '@vegaprotocol/markets';
|
||||||
|
|
||||||
export const GamesContainer = ({
|
export const GamesContainer = ({
|
||||||
data,
|
data,
|
||||||
currentEpoch,
|
currentEpoch,
|
||||||
}: {
|
}: {
|
||||||
data: TransferNode[];
|
data: EnrichedTransfer[];
|
||||||
currentEpoch: number;
|
currentEpoch: number;
|
||||||
}) => {
|
}) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
// Re-load markets and assets in the games container to ensure that the
|
|
||||||
// the cards are updated (not grayed out) when the user navigates to the games page
|
|
||||||
const { data: assets } = useAssetsMapProvider();
|
|
||||||
const { data: markets } = useMarketsMapProvider();
|
const { data: markets } = useMarketsMapProvider();
|
||||||
|
|
||||||
const enrichedTransfers = data
|
if (!data || data.length === 0) {
|
||||||
.filter((node) => isActiveReward(node, currentEpoch))
|
|
||||||
.map((node) => {
|
|
||||||
if (node.transfer.kind.__typename !== 'RecurringTransfer') {
|
|
||||||
return node;
|
|
||||||
}
|
|
||||||
|
|
||||||
const asset =
|
|
||||||
assets &&
|
|
||||||
assets[
|
|
||||||
node.transfer.kind.dispatchStrategy?.dispatchMetricAssetId || ''
|
|
||||||
];
|
|
||||||
|
|
||||||
const marketsInScope =
|
|
||||||
node.transfer.kind.dispatchStrategy?.marketIdsInScope?.map(
|
|
||||||
(id) => markets && markets[id]
|
|
||||||
);
|
|
||||||
|
|
||||||
return { ...node, asset, markets: marketsInScope };
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!enrichedTransfers || !enrichedTransfers.length) return null;
|
|
||||||
|
|
||||||
if (!enrichedTransfers || enrichedTransfers.length === 0) {
|
|
||||||
return (
|
return (
|
||||||
<p className="mb-6 text-muted">
|
<p className="mb-6 text-muted">
|
||||||
{t('There are currently no games available.')}
|
{t('There are currently no games available.')}
|
||||||
@ -53,7 +23,7 @@ export const GamesContainer = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="mb-12 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
<div className="mb-12 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||||
{enrichedTransfers.map((game, i) => {
|
{data.map((game, i) => {
|
||||||
// TODO: Remove `kind` prop from ActiveRewardCard
|
// TODO: Remove `kind` prop from ActiveRewardCard
|
||||||
const { transfer } = game;
|
const { transfer } = game;
|
||||||
if (
|
if (
|
||||||
|
@ -73,6 +73,7 @@ query ActiveRewards(
|
|||||||
reference
|
reference
|
||||||
status
|
status
|
||||||
timestamp
|
timestamp
|
||||||
|
gameId
|
||||||
kind {
|
kind {
|
||||||
... on RecurringTransfer {
|
... on RecurringTransfer {
|
||||||
startEpoch
|
startEpoch
|
||||||
|
@ -18,7 +18,7 @@ export type ActiveRewardsQueryVariables = Types.Exact<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type ActiveRewardsQuery = { __typename?: 'Query', transfersConnection?: { __typename?: 'TransferConnection', edges?: Array<{ __typename?: 'TransferEdge', node: { __typename?: 'TransferNode', transfer: { __typename?: 'Transfer', amount: string, id: string, from: string, fromAccountType: Types.AccountType, to: string, toAccountType: Types.AccountType, reference?: string | null, status: Types.TransferStatus, timestamp: any, reason?: string | null, asset?: { __typename?: 'Asset', id: string, symbol: string, decimals: number, name: string, quantum: string, status: Types.AssetStatus } | null, kind: { __typename?: 'OneOffGovernanceTransfer' } | { __typename?: 'OneOffTransfer' } | { __typename?: 'RecurringGovernanceTransfer' } | { __typename?: 'RecurringTransfer', startEpoch: number, endEpoch?: number | null, dispatchStrategy?: { __typename?: 'DispatchStrategy', dispatchMetric: Types.DispatchMetric, dispatchMetricAssetId: string, marketIdsInScope?: Array<string> | null, entityScope: Types.EntityScope, individualScope?: Types.IndividualScope | null, teamScope?: Array<string | null> | null, nTopPerformers?: string | null, stakingRequirement: string, notionalTimeWeightedAveragePositionRequirement: string, windowLength: number, lockPeriod: number, distributionStrategy: Types.DistributionStrategy, rankTable?: Array<{ __typename?: 'RankTable', startRank: number, shareRatio: number } | null> | null } | null } }, fees?: Array<{ __typename?: 'TransferFee', transferId: string, amount: string, epoch: number } | null> | null } } | null> | null } | null };
|
export type ActiveRewardsQuery = { __typename?: 'Query', transfersConnection?: { __typename?: 'TransferConnection', edges?: Array<{ __typename?: 'TransferEdge', node: { __typename?: 'TransferNode', transfer: { __typename?: 'Transfer', amount: string, id: string, from: string, fromAccountType: Types.AccountType, to: string, toAccountType: Types.AccountType, reference?: string | null, status: Types.TransferStatus, timestamp: any, gameId?: string | null, reason?: string | null, asset?: { __typename?: 'Asset', id: string, symbol: string, decimals: number, name: string, quantum: string, status: Types.AssetStatus } | null, kind: { __typename?: 'OneOffGovernanceTransfer' } | { __typename?: 'OneOffTransfer' } | { __typename?: 'RecurringGovernanceTransfer' } | { __typename?: 'RecurringTransfer', startEpoch: number, endEpoch?: number | null, dispatchStrategy?: { __typename?: 'DispatchStrategy', dispatchMetric: Types.DispatchMetric, dispatchMetricAssetId: string, marketIdsInScope?: Array<string> | null, entityScope: Types.EntityScope, individualScope?: Types.IndividualScope | null, teamScope?: Array<string | null> | null, nTopPerformers?: string | null, stakingRequirement: string, notionalTimeWeightedAveragePositionRequirement: string, windowLength: number, lockPeriod: number, distributionStrategy: Types.DistributionStrategy, rankTable?: Array<{ __typename?: 'RankTable', startRank: number, shareRatio: number } | null> | null } | null } }, fees?: Array<{ __typename?: 'TransferFee', transferId: string, amount: string, epoch: number } | null> | null } } | null> | null } | null };
|
||||||
|
|
||||||
export type RewardsHistoryQueryVariables = Types.Exact<{
|
export type RewardsHistoryQueryVariables = Types.Exact<{
|
||||||
partyId: Types.Scalars['ID'];
|
partyId: Types.Scalars['ID'];
|
||||||
@ -144,6 +144,7 @@ export const ActiveRewardsDocument = gql`
|
|||||||
reference
|
reference
|
||||||
status
|
status
|
||||||
timestamp
|
timestamp
|
||||||
|
gameId
|
||||||
kind {
|
kind {
|
||||||
... on RecurringTransfer {
|
... on RecurringTransfer {
|
||||||
startEpoch
|
startEpoch
|
||||||
|
@ -251,12 +251,7 @@ const StatusIndicator = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ActiveRewardCard = ({
|
type ActiveRewardCardProps = {
|
||||||
transferNode,
|
|
||||||
currentEpoch,
|
|
||||||
kind,
|
|
||||||
allMarkets,
|
|
||||||
}: {
|
|
||||||
transferNode: TransferNode & {
|
transferNode: TransferNode & {
|
||||||
asset?: AssetFieldsFragment | null;
|
asset?: AssetFieldsFragment | null;
|
||||||
markets?: (MarketFieldsFragment | null)[];
|
markets?: (MarketFieldsFragment | null)[];
|
||||||
@ -264,7 +259,13 @@ export const ActiveRewardCard = ({
|
|||||||
currentEpoch: number;
|
currentEpoch: number;
|
||||||
kind: RecurringTransfer;
|
kind: RecurringTransfer;
|
||||||
allMarkets?: Record<string, MarketFieldsFragment | null>;
|
allMarkets?: Record<string, MarketFieldsFragment | null>;
|
||||||
}) => {
|
};
|
||||||
|
export const ActiveRewardCard = ({
|
||||||
|
transferNode,
|
||||||
|
currentEpoch,
|
||||||
|
kind,
|
||||||
|
allMarkets,
|
||||||
|
}: ActiveRewardCardProps) => {
|
||||||
const t = useT();
|
const t = useT();
|
||||||
|
|
||||||
const { transfer } = transferNode;
|
const { transfer } = transferNode;
|
||||||
@ -485,6 +486,62 @@ export const ActiveRewardCard = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DispatchMetricInfo = ({
|
||||||
|
transferNode,
|
||||||
|
allMarkets,
|
||||||
|
}: {
|
||||||
|
transferNode: ActiveRewardCardProps['transferNode'];
|
||||||
|
allMarkets?: ActiveRewardCardProps['allMarkets'];
|
||||||
|
}) => {
|
||||||
|
const dispatchStrategy =
|
||||||
|
transferNode.transfer.kind.__typename === 'RecurringTransfer'
|
||||||
|
? transferNode.transfer.kind.dispatchStrategy
|
||||||
|
: null;
|
||||||
|
|
||||||
|
const dispatchAsset = transferNode.transfer.asset;
|
||||||
|
|
||||||
|
const marketIdsInScope = dispatchStrategy?.marketIdsInScope;
|
||||||
|
const firstMarketData = transferNode.markets?.[0];
|
||||||
|
const specificMarkets = useMemo(() => {
|
||||||
|
if (
|
||||||
|
!firstMarketData ||
|
||||||
|
!marketIdsInScope ||
|
||||||
|
marketIdsInScope.length === 0
|
||||||
|
) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (marketIdsInScope.length > 1) {
|
||||||
|
const marketNames =
|
||||||
|
allMarkets &&
|
||||||
|
marketIdsInScope
|
||||||
|
.map((id) => allMarkets[id]?.tradableInstrument?.instrument?.name)
|
||||||
|
.join(', ');
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip description={marketNames}>
|
||||||
|
<span>Specific markets</span>
|
||||||
|
</Tooltip>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = firstMarketData?.tradableInstrument?.instrument?.name;
|
||||||
|
if (name) {
|
||||||
|
return <span>{name}</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}, [firstMarketData, marketIdsInScope, allMarkets]);
|
||||||
|
|
||||||
|
if (!dispatchStrategy) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span data-testid="dispatch-metric-info">
|
||||||
|
{DispatchMetricLabels[dispatchStrategy.dispatchMetric]} •{' '}
|
||||||
|
<span>{specificMarkets || dispatchAsset?.name}</span>
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
const RewardRequirements = ({
|
const RewardRequirements = ({
|
||||||
dispatchStrategy,
|
dispatchStrategy,
|
||||||
assetDecimalPlaces = 0,
|
assetDecimalPlaces = 0,
|
||||||
|
@ -93,6 +93,9 @@ export const Table = forwardRef<
|
|||||||
key={i}
|
key={i}
|
||||||
className={classNames(dataEntry['className'] as string, {
|
className={classNames(dataEntry['className'] as string, {
|
||||||
'max-md:flex flex-col w-full': !noCollapse,
|
'max-md:flex flex-col w-full': !noCollapse,
|
||||||
|
// collapsed (mobile) row divider
|
||||||
|
'first:border-t-0 max-md:border-t border-vega-clight-500 dark:border-vega-cdark-500 first:mt-0 mt-1':
|
||||||
|
!noCollapse,
|
||||||
})}
|
})}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (onRowClick) {
|
if (onRowClick) {
|
||||||
|
@ -8,10 +8,13 @@ from fixtures.market import setup_continuous_market
|
|||||||
from conftest import auth_setup, init_page, init_vega, risk_accepted_setup
|
from conftest import auth_setup, init_page, init_vega, risk_accepted_setup
|
||||||
from wallet_config import PARTY_A, PARTY_B, PARTY_C, PARTY_D, MM_WALLET
|
from wallet_config import PARTY_A, PARTY_B, PARTY_C, PARTY_D, MM_WALLET
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def vega(request):
|
def vega(request):
|
||||||
with init_vega(request) as vega_instance:
|
with init_vega(request) as vega_instance:
|
||||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
request.addfinalizer(
|
||||||
|
lambda: cleanup_container(vega_instance)
|
||||||
|
) # Register the cleanup function
|
||||||
yield vega_instance
|
yield vega_instance
|
||||||
|
|
||||||
|
|
||||||
@ -125,7 +128,7 @@ def setup_teams_and_games(vega: VegaServiceNull):
|
|||||||
n_top_performers=1,
|
n_top_performers=1,
|
||||||
amount=100,
|
amount=100,
|
||||||
factor=1.0,
|
factor=1.0,
|
||||||
window_length=15
|
window_length=15,
|
||||||
)
|
)
|
||||||
vega.wait_fn(1)
|
vega.wait_fn(1)
|
||||||
vega.wait_for_total_catchup()
|
vega.wait_for_total_catchup()
|
||||||
@ -213,23 +216,22 @@ def create_team(vega: VegaServiceNull):
|
|||||||
|
|
||||||
|
|
||||||
def test_team_page_games_table(team_page: Page):
|
def test_team_page_games_table(team_page: Page):
|
||||||
team_page.pause()
|
|
||||||
team_page.get_by_test_id("games-toggle").click()
|
team_page.get_by_test_id("games-toggle").click()
|
||||||
expect(team_page.get_by_test_id("games-toggle")).to_have_text("Results (10)")
|
expect(team_page.get_by_test_id("games-toggle")).to_have_text("Results (10)")
|
||||||
expect(team_page.get_by_test_id("rank-0")).to_have_text("1")
|
expect(team_page.get_by_test_id("rank-0")).to_have_text("1")
|
||||||
expect(team_page.get_by_test_id("epoch-0")).to_have_text("19")
|
expect(team_page.get_by_test_id("epoch-0")).to_have_text("19")
|
||||||
expect(team_page.get_by_test_id("type-0")
|
expect(team_page.get_by_test_id("type-0")).to_have_text(
|
||||||
).to_have_text("Price maker fees paid")
|
"Price maker fees paid • tDAI "
|
||||||
#TODO skipped as the amount is wrong
|
)
|
||||||
#expect(team_page.get_by_test_id("amount-0")).to_have_text("74") # 50,000,000 on 74.1
|
# TODO skipped as the amount is wrong
|
||||||
|
# expect(team_page.get_by_test_id("amount-0")).to_have_text("74") # 50,000,000 on 74.1
|
||||||
expect(team_page.get_by_test_id("participatingTeams-0")).to_have_text("2")
|
expect(team_page.get_by_test_id("participatingTeams-0")).to_have_text("2")
|
||||||
expect(team_page.get_by_test_id("participatingMembers-0")).to_have_text("3")
|
expect(team_page.get_by_test_id("participatingMembers-0")).to_have_text("3")
|
||||||
|
|
||||||
|
|
||||||
def test_team_page_members_table(team_page: Page):
|
def test_team_page_members_table(team_page: Page):
|
||||||
team_page.get_by_test_id("members-toggle").click()
|
team_page.get_by_test_id("members-toggle").click()
|
||||||
expect(team_page.get_by_test_id("members-toggle")
|
expect(team_page.get_by_test_id("members-toggle")).to_have_text("Members (4)")
|
||||||
).to_have_text("Members (4)")
|
|
||||||
expect(team_page.get_by_test_id("referee-0")).to_be_visible()
|
expect(team_page.get_by_test_id("referee-0")).to_be_visible()
|
||||||
expect(team_page.get_by_test_id("joinedAt-0")).to_be_visible()
|
expect(team_page.get_by_test_id("joinedAt-0")).to_be_visible()
|
||||||
expect(team_page.get_by_test_id("joinedAtEpoch-0")).to_have_text("9")
|
expect(team_page.get_by_test_id("joinedAtEpoch-0")).to_have_text("9")
|
||||||
@ -267,8 +269,7 @@ def test_leaderboard(competitions_page: Page, setup_teams_and_games):
|
|||||||
competitions_page.get_by_test_id("rank-0").locator(".text-yellow-300")
|
competitions_page.get_by_test_id("rank-0").locator(".text-yellow-300")
|
||||||
).to_have_count(1)
|
).to_have_count(1)
|
||||||
expect(
|
expect(
|
||||||
competitions_page.get_by_test_id(
|
competitions_page.get_by_test_id("rank-1").locator(".text-vega-clight-500")
|
||||||
"rank-1").locator(".text-vega-clight-500")
|
|
||||||
).to_have_count(1)
|
).to_have_count(1)
|
||||||
expect(competitions_page.get_by_test_id("team-0")).to_have_text(team_name)
|
expect(competitions_page.get_by_test_id("team-0")).to_have_text(team_name)
|
||||||
expect(competitions_page.get_by_test_id("status-1")).to_have_text("Open")
|
expect(competitions_page.get_by_test_id("status-1")).to_have_text("Open")
|
||||||
@ -282,17 +283,16 @@ def test_leaderboard(competitions_page: Page, setup_teams_and_games):
|
|||||||
|
|
||||||
|
|
||||||
def test_game_card(competitions_page: Page):
|
def test_game_card(competitions_page: Page):
|
||||||
expect(competitions_page.get_by_test_id(
|
expect(competitions_page.get_by_test_id("active-rewards-card")).to_have_count(2)
|
||||||
"active-rewards-card")).to_have_count(2)
|
|
||||||
game_1 = competitions_page.get_by_test_id("active-rewards-card").first
|
game_1 = competitions_page.get_by_test_id("active-rewards-card").first
|
||||||
expect(game_1).to_be_visible()
|
expect(game_1).to_be_visible()
|
||||||
expect(game_1.get_by_test_id("entity-scope")).to_have_text("Individual")
|
expect(game_1.get_by_test_id("entity-scope")).to_have_text("Individual")
|
||||||
expect(game_1.get_by_test_id("locked-for")).to_have_text("1 epoch")
|
expect(game_1.get_by_test_id("locked-for")).to_have_text("1 epoch")
|
||||||
expect(game_1.get_by_test_id("reward-value")).to_have_text("100.00")
|
expect(game_1.get_by_test_id("reward-value")).to_have_text("100.00")
|
||||||
expect(game_1.get_by_test_id("distribution-strategy")
|
expect(game_1.get_by_test_id("distribution-strategy")).to_have_text("Pro rata")
|
||||||
).to_have_text("Pro rata")
|
expect(game_1.get_by_test_id("dispatch-metric-info")).to_have_text(
|
||||||
expect(game_1.get_by_test_id("dispatch-metric-info")
|
"Price maker fees paid • tDAI"
|
||||||
).to_have_text("Price maker fees paid • tDAI")
|
)
|
||||||
expect(game_1.get_by_test_id("assessed-over")).to_have_text("15 epochs")
|
expect(game_1.get_by_test_id("assessed-over")).to_have_text("15 epochs")
|
||||||
expect(game_1.get_by_test_id("scope")).to_have_text("In team")
|
expect(game_1.get_by_test_id("scope")).to_have_text("In team")
|
||||||
expect(game_1.get_by_test_id("staking-requirement")).to_have_text("0.00")
|
expect(game_1.get_by_test_id("staking-requirement")).to_have_text("0.00")
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
query CurrentEpochInfo {
|
query EpochInfo($epochId: ID) {
|
||||||
epoch {
|
epoch(id: $epochId) {
|
||||||
id
|
id
|
||||||
timestamps {
|
timestamps {
|
||||||
start
|
start
|
||||||
end
|
end
|
||||||
|
expiry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@ fragment GameFields on Game {
|
|||||||
id
|
id
|
||||||
epoch
|
epoch
|
||||||
numberOfParticipants
|
numberOfParticipants
|
||||||
|
rewardAssetId
|
||||||
entities {
|
entities {
|
||||||
... on TeamGameEntity {
|
... on TeamGameEntity {
|
||||||
...TeamEntity
|
...TeamEntity
|
||||||
|
36
apps/trading/lib/hooks/__generated__/Epoch.ts
generated
36
apps/trading/lib/hooks/__generated__/Epoch.ts
generated
@ -3,47 +3,51 @@ import * as Types from '@vegaprotocol/types';
|
|||||||
import { gql } from '@apollo/client';
|
import { gql } from '@apollo/client';
|
||||||
import * as Apollo from '@apollo/client';
|
import * as Apollo from '@apollo/client';
|
||||||
const defaultOptions = {} as const;
|
const defaultOptions = {} as const;
|
||||||
export type CurrentEpochInfoQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
export type EpochInfoQueryVariables = Types.Exact<{
|
||||||
|
epochId?: Types.InputMaybe<Types.Scalars['ID']>;
|
||||||
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type CurrentEpochInfoQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null } } };
|
export type EpochInfoQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, expiry?: any | null } } };
|
||||||
|
|
||||||
|
|
||||||
export const CurrentEpochInfoDocument = gql`
|
export const EpochInfoDocument = gql`
|
||||||
query CurrentEpochInfo {
|
query EpochInfo($epochId: ID) {
|
||||||
epoch {
|
epoch(id: $epochId) {
|
||||||
id
|
id
|
||||||
timestamps {
|
timestamps {
|
||||||
start
|
start
|
||||||
end
|
end
|
||||||
|
expiry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* __useCurrentEpochInfoQuery__
|
* __useEpochInfoQuery__
|
||||||
*
|
*
|
||||||
* To run a query within a React component, call `useCurrentEpochInfoQuery` and pass it any options that fit your needs.
|
* To run a query within a React component, call `useEpochInfoQuery` and pass it any options that fit your needs.
|
||||||
* When your component renders, `useCurrentEpochInfoQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
* When your component renders, `useEpochInfoQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||||
* you can use to render your UI.
|
* you can use to render your UI.
|
||||||
*
|
*
|
||||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
* const { data, loading, error } = useCurrentEpochInfoQuery({
|
* const { data, loading, error } = useEpochInfoQuery({
|
||||||
* variables: {
|
* variables: {
|
||||||
|
* epochId: // value for 'epochId'
|
||||||
* },
|
* },
|
||||||
* });
|
* });
|
||||||
*/
|
*/
|
||||||
export function useCurrentEpochInfoQuery(baseOptions?: Apollo.QueryHookOptions<CurrentEpochInfoQuery, CurrentEpochInfoQueryVariables>) {
|
export function useEpochInfoQuery(baseOptions?: Apollo.QueryHookOptions<EpochInfoQuery, EpochInfoQueryVariables>) {
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
return Apollo.useQuery<CurrentEpochInfoQuery, CurrentEpochInfoQueryVariables>(CurrentEpochInfoDocument, options);
|
return Apollo.useQuery<EpochInfoQuery, EpochInfoQueryVariables>(EpochInfoDocument, options);
|
||||||
}
|
}
|
||||||
export function useCurrentEpochInfoLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<CurrentEpochInfoQuery, CurrentEpochInfoQueryVariables>) {
|
export function useEpochInfoLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<EpochInfoQuery, EpochInfoQueryVariables>) {
|
||||||
const options = {...defaultOptions, ...baseOptions}
|
const options = {...defaultOptions, ...baseOptions}
|
||||||
return Apollo.useLazyQuery<CurrentEpochInfoQuery, CurrentEpochInfoQueryVariables>(CurrentEpochInfoDocument, options);
|
return Apollo.useLazyQuery<EpochInfoQuery, EpochInfoQueryVariables>(EpochInfoDocument, options);
|
||||||
}
|
}
|
||||||
export type CurrentEpochInfoQueryHookResult = ReturnType<typeof useCurrentEpochInfoQuery>;
|
export type EpochInfoQueryHookResult = ReturnType<typeof useEpochInfoQuery>;
|
||||||
export type CurrentEpochInfoLazyQueryHookResult = ReturnType<typeof useCurrentEpochInfoLazyQuery>;
|
export type EpochInfoLazyQueryHookResult = ReturnType<typeof useEpochInfoLazyQuery>;
|
||||||
export type CurrentEpochInfoQueryResult = Apollo.QueryResult<CurrentEpochInfoQuery, CurrentEpochInfoQueryVariables>;
|
export type EpochInfoQueryResult = Apollo.QueryResult<EpochInfoQuery, EpochInfoQueryVariables>;
|
5
apps/trading/lib/hooks/__generated__/Games.ts
generated
5
apps/trading/lib/hooks/__generated__/Games.ts
generated
@ -5,14 +5,14 @@ import * as Apollo from '@apollo/client';
|
|||||||
const defaultOptions = {} as const;
|
const defaultOptions = {} as const;
|
||||||
export type TeamEntityFragment = { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: Types.DispatchMetric, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string, membersParticipating: Array<{ __typename?: 'IndividualGameEntity', individual: string, rank: number }> } };
|
export type TeamEntityFragment = { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: Types.DispatchMetric, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string, membersParticipating: Array<{ __typename?: 'IndividualGameEntity', individual: string, rank: number }> } };
|
||||||
|
|
||||||
export type GameFieldsFragment = { __typename?: 'Game', id: string, epoch: number, numberOfParticipants: number, entities: Array<{ __typename?: 'IndividualGameEntity' } | { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: Types.DispatchMetric, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string, membersParticipating: Array<{ __typename?: 'IndividualGameEntity', individual: string, rank: number }> } }> };
|
export type GameFieldsFragment = { __typename?: 'Game', id: string, epoch: number, numberOfParticipants: number, rewardAssetId: string, entities: Array<{ __typename?: 'IndividualGameEntity' } | { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: Types.DispatchMetric, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string, membersParticipating: Array<{ __typename?: 'IndividualGameEntity', individual: string, rank: number }> } }> };
|
||||||
|
|
||||||
export type GamesQueryVariables = Types.Exact<{
|
export type GamesQueryVariables = Types.Exact<{
|
||||||
epochFrom?: Types.InputMaybe<Types.Scalars['Int']>;
|
epochFrom?: Types.InputMaybe<Types.Scalars['Int']>;
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
|
|
||||||
export type GamesQuery = { __typename?: 'Query', games: { __typename?: 'GamesConnection', edges?: Array<{ __typename?: 'GameEdge', node: { __typename?: 'Game', id: string, epoch: number, numberOfParticipants: number, entities: Array<{ __typename?: 'IndividualGameEntity' } | { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: Types.DispatchMetric, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string, membersParticipating: Array<{ __typename?: 'IndividualGameEntity', individual: string, rank: number }> } }> } } | null> | null } };
|
export type GamesQuery = { __typename?: 'Query', games: { __typename?: 'GamesConnection', edges?: Array<{ __typename?: 'GameEdge', node: { __typename?: 'Game', id: string, epoch: number, numberOfParticipants: number, rewardAssetId: string, entities: Array<{ __typename?: 'IndividualGameEntity' } | { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: Types.DispatchMetric, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string, membersParticipating: Array<{ __typename?: 'IndividualGameEntity', individual: string, rank: number }> } }> } } | null> | null } };
|
||||||
|
|
||||||
export const TeamEntityFragmentDoc = gql`
|
export const TeamEntityFragmentDoc = gql`
|
||||||
fragment TeamEntity on TeamGameEntity {
|
fragment TeamEntity on TeamGameEntity {
|
||||||
@ -35,6 +35,7 @@ export const GameFieldsFragmentDoc = gql`
|
|||||||
id
|
id
|
||||||
epoch
|
epoch
|
||||||
numberOfParticipants
|
numberOfParticipants
|
||||||
|
rewardAssetId
|
||||||
entities {
|
entities {
|
||||||
... on TeamGameEntity {
|
... on TeamGameEntity {
|
||||||
...TeamEntity
|
...TeamEntity
|
||||||
|
@ -2,12 +2,35 @@ import compact from 'lodash/compact';
|
|||||||
import { useActiveRewardsQuery } from '../../components/rewards-container/__generated__/Rewards';
|
import { useActiveRewardsQuery } from '../../components/rewards-container/__generated__/Rewards';
|
||||||
import { isActiveReward } from '../../components/rewards-container/active-rewards';
|
import { isActiveReward } from '../../components/rewards-container/active-rewards';
|
||||||
import {
|
import {
|
||||||
|
type RecurringTransfer,
|
||||||
|
type TransferNode,
|
||||||
EntityScope,
|
EntityScope,
|
||||||
IndividualScope,
|
IndividualScope,
|
||||||
type TransferNode,
|
|
||||||
} from '@vegaprotocol/types';
|
} from '@vegaprotocol/types';
|
||||||
|
import {
|
||||||
|
type AssetFieldsFragment,
|
||||||
|
useAssetsMapProvider,
|
||||||
|
} from '@vegaprotocol/assets';
|
||||||
|
import {
|
||||||
|
type MarketFieldsFragment,
|
||||||
|
useMarketsMapProvider,
|
||||||
|
} from '@vegaprotocol/markets';
|
||||||
|
import { type ApolloError } from '@apollo/client';
|
||||||
|
|
||||||
const isScopedToTeams = (node: TransferNode) =>
|
export type EnrichedTransfer = TransferNode & {
|
||||||
|
asset?: AssetFieldsFragment | null;
|
||||||
|
markets?: (MarketFieldsFragment | null)[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type RecurringTransferKind = EnrichedTransfer & {
|
||||||
|
transfer: {
|
||||||
|
kind: RecurringTransfer;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const isScopedToTeams = (
|
||||||
|
node: TransferNode
|
||||||
|
): node is RecurringTransferKind =>
|
||||||
node.transfer.kind.__typename === 'RecurringTransfer' &&
|
node.transfer.kind.__typename === 'RecurringTransfer' &&
|
||||||
// scoped to teams
|
// scoped to teams
|
||||||
(node.transfer.kind.dispatchStrategy?.entityScope ===
|
(node.transfer.kind.dispatchStrategy?.entityScope ===
|
||||||
@ -25,7 +48,7 @@ export const useGameCards = ({
|
|||||||
}: {
|
}: {
|
||||||
currentEpoch: number;
|
currentEpoch: number;
|
||||||
onlyActive: boolean;
|
onlyActive: boolean;
|
||||||
}) => {
|
}): { data: EnrichedTransfer[]; loading: boolean; error?: ApolloError } => {
|
||||||
const { data, loading, error } = useActiveRewardsQuery({
|
const { data, loading, error } = useActiveRewardsQuery({
|
||||||
variables: {
|
variables: {
|
||||||
isReward: true,
|
isReward: true,
|
||||||
@ -33,16 +56,37 @@ export const useGameCards = ({
|
|||||||
fetchPolicy: 'cache-and-network',
|
fetchPolicy: 'cache-and-network',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { data: assets, loading: assetsLoading } = useAssetsMapProvider();
|
||||||
|
const { data: markets, loading: marketsLoading } = useMarketsMapProvider();
|
||||||
|
|
||||||
const games = compact(data?.transfersConnection?.edges?.map((n) => n?.node))
|
const games = compact(data?.transfersConnection?.edges?.map((n) => n?.node))
|
||||||
.map((n) => n as TransferNode)
|
.map((n) => n as TransferNode)
|
||||||
.filter((node) => {
|
.filter((node) => {
|
||||||
const active = onlyActive ? isActiveReward(node, currentEpoch) : true;
|
const active = onlyActive ? isActiveReward(node, currentEpoch) : true;
|
||||||
return active && isScopedToTeams(node);
|
return active && isScopedToTeams(node);
|
||||||
|
})
|
||||||
|
.map((node) => {
|
||||||
|
if (node.transfer.kind.__typename !== 'RecurringTransfer') {
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
const asset =
|
||||||
|
assets &&
|
||||||
|
assets[
|
||||||
|
node.transfer.kind.dispatchStrategy?.dispatchMetricAssetId || ''
|
||||||
|
];
|
||||||
|
|
||||||
|
const marketsInScope =
|
||||||
|
node.transfer.kind.dispatchStrategy?.marketIdsInScope?.map(
|
||||||
|
(id) => markets && markets[id]
|
||||||
|
);
|
||||||
|
|
||||||
|
return { ...node, asset, markets: marketsInScope };
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
data: games,
|
data: games,
|
||||||
loading,
|
loading: loading || assetsLoading || marketsLoading,
|
||||||
error,
|
error,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
} from './__generated__/Games';
|
} from './__generated__/Games';
|
||||||
import orderBy from 'lodash/orderBy';
|
import orderBy from 'lodash/orderBy';
|
||||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||||
import { useCurrentEpochInfoQuery } from './__generated__/Epoch';
|
import { useEpochInfoQuery } from './__generated__/Epoch';
|
||||||
import { type ApolloError } from '@apollo/client';
|
import { type ApolloError } from '@apollo/client';
|
||||||
|
|
||||||
const TAKE_EPOCHS = 30; // TODO: should this be DEFAULT_AGGREGATION_EPOCHS?
|
const TAKE_EPOCHS = 30; // TODO: should this be DEFAULT_AGGREGATION_EPOCHS?
|
||||||
@ -39,7 +39,7 @@ export const useGames = (teamId?: string, epochFrom?: number): GamesData => {
|
|||||||
data: epochData,
|
data: epochData,
|
||||||
loading: epochLoading,
|
loading: epochLoading,
|
||||||
error: epochError,
|
error: epochError,
|
||||||
} = useCurrentEpochInfoQuery({
|
} = useEpochInfoQuery({
|
||||||
skip: Boolean(epochFrom),
|
skip: Boolean(epochFrom),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -455,5 +455,12 @@
|
|||||||
"Go back to the team's profile": "Go back to the team's profile",
|
"Go back to the team's profile": "Go back to the team's profile",
|
||||||
"Go back to the competitions": "Go back to the competitions",
|
"Go back to the competitions": "Go back to the competitions",
|
||||||
"Your team ID:": "Your team ID:",
|
"Your team ID:": "Your team ID:",
|
||||||
"Changes successfully saved to your team.": "Changes successfully saved to your team."
|
"Changes successfully saved to your team.": "Changes successfully saved to your team.",
|
||||||
|
"Results {{games}}": "Results {{games}}",
|
||||||
|
"End time": "End time",
|
||||||
|
"Reward asset": "Reward asset",
|
||||||
|
"Daily reward amount": "Daily reward amount",
|
||||||
|
"Amount earned this epoch": "Amount earned this epoch",
|
||||||
|
"Cumulative amount earned": "Cumulative amount earned",
|
||||||
|
"Game details": "Game details"
|
||||||
}
|
}
|
||||||
|
@ -47,8 +47,9 @@ export const marketsProvider = makeDataProvider<
|
|||||||
errorPolicy: 'all',
|
errorPolicy: 'all',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export type MarketMap = Record<string, Market>;
|
||||||
export const marketsMapProvider = makeDerivedDataProvider<
|
export const marketsMapProvider = makeDerivedDataProvider<
|
||||||
Record<string, Market>,
|
MarketMap,
|
||||||
never,
|
never,
|
||||||
undefined
|
undefined
|
||||||
>(
|
>(
|
||||||
@ -59,7 +60,7 @@ export const marketsMapProvider = makeDerivedDataProvider<
|
|||||||
markets[market.id] = market;
|
markets[market.id] = market;
|
||||||
return markets;
|
return markets;
|
||||||
},
|
},
|
||||||
{} as Record<string, Market>
|
{} as MarketMap
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
22
libs/types/src/__generated__/types.ts
generated
22
libs/types/src/__generated__/types.ts
generated
@ -1640,6 +1640,8 @@ export type Game = {
|
|||||||
id: Scalars['ID'];
|
id: Scalars['ID'];
|
||||||
/** Number of participants that took part in the game during the epoch. */
|
/** Number of participants that took part in the game during the epoch. */
|
||||||
numberOfParticipants: Scalars['Int'];
|
numberOfParticipants: Scalars['Int'];
|
||||||
|
/** ID of asset in which the rewards were paid. */
|
||||||
|
rewardAssetId: Scalars['ID'];
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Edge type containing the game metrics and cursor information returned by a GameConnection */
|
/** Edge type containing the game metrics and cursor information returned by a GameConnection */
|
||||||
@ -1704,10 +1706,14 @@ export type IndividualGameEntity = {
|
|||||||
rank: Scalars['Int'];
|
rank: Scalars['Int'];
|
||||||
/** The rewards earned by the individual during the epoch */
|
/** The rewards earned by the individual during the epoch */
|
||||||
rewardEarned: Scalars['String'];
|
rewardEarned: Scalars['String'];
|
||||||
|
/** The rewards earned by the individual during the epoch in quantum value */
|
||||||
|
rewardEarnedQuantum: Scalars['String'];
|
||||||
/** The reward metric applied to the game */
|
/** The reward metric applied to the game */
|
||||||
rewardMetric: DispatchMetric;
|
rewardMetric: DispatchMetric;
|
||||||
/** Total rewards earned by the individual during the game */
|
/** Total rewards earned by the individual during the game */
|
||||||
totalRewardsEarned: Scalars['String'];
|
totalRewardsEarned: Scalars['String'];
|
||||||
|
/** Total rewards earned by the individual during the game in quantum value */
|
||||||
|
totalRewardsEarnedQuantum: Scalars['String'];
|
||||||
/** The volume traded by the individual */
|
/** The volume traded by the individual */
|
||||||
volume: Scalars['String'];
|
volume: Scalars['String'];
|
||||||
};
|
};
|
||||||
@ -4737,6 +4743,14 @@ export type QuantumRewardsPerEpoch = {
|
|||||||
totalQuantumRewards: Scalars['String'];
|
totalQuantumRewards: Scalars['String'];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type QuantumVolumesPerEpoch = {
|
||||||
|
__typename?: 'QuantumVolumesPerEpoch';
|
||||||
|
/** Epoch for which this information is valid. */
|
||||||
|
epoch: Scalars['Int'];
|
||||||
|
/** Total volume across all markets, accumulated over the epoch period, expressed in quantum value. */
|
||||||
|
totalQuantumVolumes: Scalars['String'];
|
||||||
|
};
|
||||||
|
|
||||||
/** Queries allow a caller to read data and filter data via GraphQL. */
|
/** Queries allow a caller to read data and filter data via GraphQL. */
|
||||||
export type Query = {
|
export type Query = {
|
||||||
__typename?: 'Query';
|
__typename?: 'Query';
|
||||||
@ -6412,12 +6426,16 @@ export type TeamGameEntity = {
|
|||||||
rank: Scalars['Int'];
|
rank: Scalars['Int'];
|
||||||
/** Total rewards earned by the team during the epoch */
|
/** Total rewards earned by the team during the epoch */
|
||||||
rewardEarned: Scalars['String'];
|
rewardEarned: Scalars['String'];
|
||||||
|
/** Total rewards earned by the team during the epoch in quantum value */
|
||||||
|
rewardEarnedQuantum: Scalars['String'];
|
||||||
/** Reward metric applied to the game. */
|
/** Reward metric applied to the game. */
|
||||||
rewardMetric: DispatchMetric;
|
rewardMetric: DispatchMetric;
|
||||||
/** Breakdown of the team members and their contributions to the total team metrics. */
|
/** Breakdown of the team members and their contributions to the total team metrics. */
|
||||||
team: TeamParticipation;
|
team: TeamParticipation;
|
||||||
/** Total rewards earned by the team for the game */
|
/** Total rewards earned by the team for the game */
|
||||||
totalRewardsEarned: Scalars['String'];
|
totalRewardsEarned: Scalars['String'];
|
||||||
|
/** Total rewards earned by the team for the game in quantum value */
|
||||||
|
totalRewardsEarnedQuantum: Scalars['String'];
|
||||||
/** Total volume traded by the team */
|
/** Total volume traded by the team */
|
||||||
volume: Scalars['String'];
|
volume: Scalars['String'];
|
||||||
};
|
};
|
||||||
@ -6431,6 +6449,8 @@ export type TeamMemberStatistics = {
|
|||||||
partyId: Scalars['String'];
|
partyId: Scalars['String'];
|
||||||
/** List of rewards over the requested epoch period, expressed in quantum value for each epoch */
|
/** List of rewards over the requested epoch period, expressed in quantum value for each epoch */
|
||||||
quantumRewards: Array<QuantumRewardsPerEpoch>;
|
quantumRewards: Array<QuantumRewardsPerEpoch>;
|
||||||
|
/** List of trading volume totals per epoch, for the requested epoch period, expressed in quantum value */
|
||||||
|
quantumVolumes: Array<QuantumVolumesPerEpoch>;
|
||||||
/** Total number of games played. */
|
/** Total number of games played. */
|
||||||
totalGamesPlayed: Scalars['Int'];
|
totalGamesPlayed: Scalars['Int'];
|
||||||
/** Total of rewards accumulated over the requested epoch period, expressed in quantum value. */
|
/** Total of rewards accumulated over the requested epoch period, expressed in quantum value. */
|
||||||
@ -6533,6 +6553,8 @@ export type TeamStatistics = {
|
|||||||
gamesPlayed: Array<Scalars['String']>;
|
gamesPlayed: Array<Scalars['String']>;
|
||||||
/** List of rewards over the requested epoch period, expressed in quantum value for each epoch */
|
/** List of rewards over the requested epoch period, expressed in quantum value for each epoch */
|
||||||
quantumRewards: Array<QuantumRewardsPerEpoch>;
|
quantumRewards: Array<QuantumRewardsPerEpoch>;
|
||||||
|
/** List of trading volume totals per epoch, over the requested epoch period, expressed in quantum value */
|
||||||
|
quantumVolumes: Array<QuantumVolumesPerEpoch>;
|
||||||
/** Team ID the statistics are related to. */
|
/** Team ID the statistics are related to. */
|
||||||
teamId: Scalars['String'];
|
teamId: Scalars['String'];
|
||||||
/** Total of games played. */
|
/** Total of games played. */
|
||||||
|
Loading…
Reference in New Issue
Block a user