Compare commits

...
Author SHA1 Message Date
Matthew Russell 5eb25db969 feat(trading): team page (#5593) 2024-01-12 15:20:52 +00:00
19 changed files with 1354 additions and 37 deletions
@@ -0,0 +1,89 @@
fragment TeamFields on Team {
teamId
referrer
name
teamUrl
avatarUrl
createdAt
createdAtEpoch
closed
}
fragment TeamStatsFields on TeamStatistics {
teamId
totalQuantumVolume
totalQuantumRewards
totalGamesPlayed
quantumRewards {
epoch
total_quantum_rewards
}
gamesPlayed
}
fragment TeamRefereeFields on TeamReferee {
teamId
referee
joinedAt
joinedAtEpoch
}
fragment TeamEntity on TeamGameEntity {
rank
volume
rewardMetric
rewardEarned
totalRewardsEarned
team {
teamId
}
}
fragment TeamGameFields on Game {
id
epoch
numberOfParticipants
entities {
... on TeamGameEntity {
...TeamEntity
}
}
}
query Team($teamId: ID!, $partyId: ID) {
teams(teamId: $teamId) {
edges {
node {
...TeamFields
}
}
}
partyTeams: teams(partyId: $partyId) {
edges {
node {
...TeamFields
}
}
}
teamsStatistics(teamId: $teamId) {
edges {
node {
...TeamStatsFields
}
}
}
teamReferees(teamId: $teamId) {
edges {
node {
...TeamRefereeFields
}
}
}
games(entityScope: ENTITY_SCOPE_TEAMS) {
edges {
node {
...TeamGameFields
}
}
}
}
+151
View File
@@ -0,0 +1,151 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type TeamFieldsFragment = { __typename?: 'Team', teamId: string, referrer: string, name: string, teamUrl: string, avatarUrl: string, createdAt: any, createdAtEpoch: number, closed: boolean };
export type TeamStatsFieldsFragment = { __typename?: 'TeamStatistics', teamId: string, totalQuantumVolume: string, totalQuantumRewards: string, totalGamesPlayed: number, gamesPlayed: Array<string>, quantumRewards: Array<{ __typename?: 'QuantumRewardsPerEpoch', epoch: number, total_quantum_rewards: string }> };
export type TeamRefereeFieldsFragment = { __typename?: 'TeamReferee', teamId: string, referee: string, joinedAt: any, joinedAtEpoch: number };
export type TeamEntityFragment = { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: string, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string } };
export type TeamGameFieldsFragment = { __typename?: 'Game', id: string, epoch: number, numberOfParticipants: number, entities: Array<{ __typename?: 'IndividualGameEntity' } | { __typename?: 'TeamGameEntity', rank: number, volume: string, rewardMetric: string, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string } }> };
export type TeamQueryVariables = Types.Exact<{
teamId: Types.Scalars['ID'];
partyId?: Types.InputMaybe<Types.Scalars['ID']>;
}>;
export type TeamQuery = { __typename?: 'Query', teams?: { __typename?: 'TeamConnection', edges: Array<{ __typename?: 'TeamEdge', node: { __typename?: 'Team', teamId: string, referrer: string, name: string, teamUrl: string, avatarUrl: string, createdAt: any, createdAtEpoch: number, closed: boolean } }> } | null, partyTeams?: { __typename?: 'TeamConnection', edges: Array<{ __typename?: 'TeamEdge', node: { __typename?: 'Team', teamId: string, referrer: string, name: string, teamUrl: string, avatarUrl: string, createdAt: any, createdAtEpoch: number, closed: boolean } }> } | null, teamsStatistics?: { __typename?: 'TeamsStatisticsConnection', edges: Array<{ __typename?: 'TeamStatisticsEdge', node: { __typename?: 'TeamStatistics', teamId: string, totalQuantumVolume: string, totalQuantumRewards: string, totalGamesPlayed: number, gamesPlayed: Array<string>, quantumRewards: Array<{ __typename?: 'QuantumRewardsPerEpoch', epoch: number, total_quantum_rewards: string }> } }> } | null, teamReferees?: { __typename?: 'TeamRefereeConnection', edges: Array<{ __typename?: 'TeamRefereeEdge', node: { __typename?: 'TeamReferee', teamId: string, referee: string, joinedAt: any, joinedAtEpoch: number } }> } | null, 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: string, rewardEarned: string, totalRewardsEarned: string, team: { __typename?: 'TeamParticipation', teamId: string } }> } } | null> | null } };
export const TeamFieldsFragmentDoc = gql`
fragment TeamFields on Team {
teamId
referrer
name
teamUrl
avatarUrl
createdAt
createdAtEpoch
closed
}
`;
export const TeamStatsFieldsFragmentDoc = gql`
fragment TeamStatsFields on TeamStatistics {
teamId
totalQuantumVolume
totalQuantumRewards
totalGamesPlayed
quantumRewards {
epoch
total_quantum_rewards
}
gamesPlayed
}
`;
export const TeamRefereeFieldsFragmentDoc = gql`
fragment TeamRefereeFields on TeamReferee {
teamId
referee
joinedAt
joinedAtEpoch
}
`;
export const TeamEntityFragmentDoc = gql`
fragment TeamEntity on TeamGameEntity {
rank
volume
rewardMetric
rewardEarned
totalRewardsEarned
team {
teamId
}
}
`;
export const TeamGameFieldsFragmentDoc = gql`
fragment TeamGameFields on Game {
id
epoch
numberOfParticipants
entities {
... on TeamGameEntity {
...TeamEntity
}
}
}
${TeamEntityFragmentDoc}`;
export const TeamDocument = gql`
query Team($teamId: ID!, $partyId: ID) {
teams(teamId: $teamId) {
edges {
node {
...TeamFields
}
}
}
partyTeams: teams(partyId: $partyId) {
edges {
node {
...TeamFields
}
}
}
teamsStatistics(teamId: $teamId) {
edges {
node {
...TeamStatsFields
}
}
}
teamReferees(teamId: $teamId) {
edges {
node {
...TeamRefereeFields
}
}
}
games(entityScope: ENTITY_SCOPE_TEAMS) {
edges {
node {
...TeamGameFields
}
}
}
}
${TeamFieldsFragmentDoc}
${TeamStatsFieldsFragmentDoc}
${TeamRefereeFieldsFragmentDoc}
${TeamGameFieldsFragmentDoc}`;
/**
* __useTeamQuery__
*
* To run a query within a React component, call `useTeamQuery` and pass it any options that fit your needs.
* When your component renders, `useTeamQuery` returns an object from Apollo Client that contains loading, error, and data properties
* 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;
*
* @example
* const { data, loading, error } = useTeamQuery({
* variables: {
* teamId: // value for 'teamId'
* partyId: // value for 'partyId'
* },
* });
*/
export function useTeamQuery(baseOptions: Apollo.QueryHookOptions<TeamQuery, TeamQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<TeamQuery, TeamQueryVariables>(TeamDocument, options);
}
export function useTeamLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<TeamQuery, TeamQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<TeamQuery, TeamQueryVariables>(TeamDocument, options);
}
export type TeamQueryHookResult = ReturnType<typeof useTeamQuery>;
export type TeamLazyQueryHookResult = ReturnType<typeof useTeamLazyQuery>;
export type TeamQueryResult = Apollo.QueryResult<TeamQuery, TeamQueryVariables>;
+1
View File
@@ -0,0 +1 @@
export { Team } from './team';
+395
View File
@@ -0,0 +1,395 @@
import { useState, type ReactNode, type ButtonHTMLAttributes } from 'react';
import { Link, useParams } from 'react-router-dom';
import orderBy from 'lodash/orderBy';
import countBy from 'lodash/countBy';
import {
TradingButton as Button,
Intent,
Pill,
VegaIcon,
VegaIconNames,
Tooltip,
Splash,
truncateMiddle,
} from '@vegaprotocol/ui-toolkit';
import classNames from 'classnames';
import { useT } from '../../lib/use-t';
import { Table } from '../../components/table';
import { formatNumberRounded, getDateTimeFormat } from '@vegaprotocol/utils';
import {
useTeam,
type Team as TeamType,
type TeamStats,
type Member,
type TeamGame,
} from './use-team';
import { DApp, EXPLORER_PARTIES, useLinks } from '@vegaprotocol/environment';
import BigNumber from 'bignumber.js';
export const Team = () => {
const t = useT();
const { teamId } = useParams<{ teamId: string }>();
const { team, stats, partyInTeam, members, games } = useTeam(teamId);
if (!team) {
return (
<Splash>
<p>{t('Page not found')}</p>
</Splash>
);
}
return (
<TeamPage
team={team}
stats={stats}
partyInTeam={partyInTeam}
members={members}
games={games}
/>
);
};
export const TeamPage = ({
team,
stats,
partyInTeam,
members,
games,
}: {
team: TeamType;
stats?: TeamStats;
partyInTeam: boolean;
members?: Member[];
games?: TeamGame[];
}) => {
const t = useT();
const [showGames, setShowGames] = useState(true);
return (
<div className="relative h-full overflow-y-auto">
<div className="absolute top-0 left-0 w-full h-[40%] -z-10 bg-[40%_0px] bg-cover bg-no-repeat bg-local bg-[url(/cover.png)]">
<div className="absolute top-o left-0 w-full h-full bg-gradient-to-t from-white dark:from-vega-cdark-900 to-transparent from-20% to-60%" />
</div>
<div className="flex flex-col gap-4 lg:gap-6 container p-4 mx-auto">
<header className="flex gap-3 lg:gap-4 pt-5 lg:pt-10">
<TeamAvatar imgUrl={team.avatarUrl} />
<div className="flex flex-col items-start gap-1 lg:gap-3">
<h1 className="calt text-2xl lg:text-3xl xl:text-5xl">
{team.name}
</h1>
<JoinButton joined={partyInTeam} />
</div>
</header>
<StatSection>
<StatList>
<Stat value={members ? members.length : 0} label={t('Members')} />
<Stat
value={stats ? stats.totalGamesPlayed : 0}
label={t('Total games')}
tooltip={t('Total number of games this team has participated in')}
/>
<StatSectionSeparator />
<Stat
value={
stats
? formatNumberRounded(
new BigNumber(stats.totalQuantumVolume),
'1e3'
)
: 0
}
label={t('Total volume')}
/>
<Stat
value={
stats
? formatNumberRounded(
new BigNumber(stats.totalQuantumRewards),
'1e3'
)
: 0
}
label={t('Rewards paid')}
tooltip={'Total amount of rewards paid out to this team in qUSD'}
/>
</StatList>
</StatSection>
{games && games.length ? (
<StatSection>
<FavoriteGame games={games} />
<StatSectionSeparator />
<LatestResults games={games} />
</StatSection>
) : null}
<section>
<div className="flex gap-4 lg:gap-8 mb-4 border-b border-default">
<ToggleButton active={showGames} onClick={() => setShowGames(true)}>
{t('Games ({{count}})', { count: games ? games.length : 0 })}
</ToggleButton>
<ToggleButton
active={!showGames}
onClick={() => setShowGames(false)}
>
{t('Members ({{count}})', {
count: members ? members.length : 0,
})}
</ToggleButton>
</div>
{showGames ? <Games games={games} /> : <Members members={members} />}
</section>
</div>
</div>
);
};
const Games = ({ games }: { games?: TeamGame[] }) => {
const t = useT();
if (!games?.length) {
return <p>{t('No games')}</p>;
}
return (
<Table
columns={[
{ name: 'rank', displayName: t('Rank') },
{
name: 'epoch',
displayName: t('Epoch'),
headerClassName: 'hidden md:block',
className: 'hidden md:block',
},
{ name: 'type', displayName: t('Type') },
{ name: 'amount', displayName: t('Amount earned') },
{
name: 'teams',
displayName: t('No. of participating teams'),
headerClassName: 'hidden md:block',
className: 'hidden md:block',
},
{ name: 'status', displayName: t('Status') },
]}
data={games.map((game) => ({
rank: game.team.rank,
epoch: game.epoch,
type: game.team.rewardMetric,
amount: game.team.totalRewardsEarned,
teams: game.numberOfParticipants,
}))}
noCollapse={true}
/>
);
};
const TeamAvatar = ({ imgUrl }: { imgUrl: string }) => {
// TODO: add fallback avatars
return (
// eslint-disable-next-line @next/next/no-img-element
<img
src={imgUrl}
alt="Team avatar"
className="rounded-full w-20 h-20 lg:w-[112px] lg:h-[112px] bg-vega-clight-700 dark:bg-vega-cdark-700 shrink-0"
/>
);
};
const Members = ({ members }: { members?: Member[] }) => {
const t = useT();
if (!members?.length) {
return <p>{t('No members')}</p>;
}
const data = orderBy(
members.map((m) => ({
referee: <RefereeCell pubkey={m.referee} />,
joinedAt: getDateTimeFormat().format(new Date(m.joinedAt)),
joinedAtEpoch: Number(m.joinedAtEpoch),
explorerLink: <RefereeLink pubkey={m.referee} />,
})),
'joinedAtEpoch',
'desc'
);
return (
<Table
columns={[
{ name: 'referee', displayName: t('Referee') },
{
name: 'joinedAt',
displayName: t('Joined at'),
},
{
name: 'joinedAtEpoch',
displayName: t('Joined epoch'),
headerClassName: 'text-right',
className: 'text-right',
},
{
name: 'explorerLink',
displayName: '',
headerClassName: 'hidden md:block',
className: 'hidden md:block text-right',
},
]}
data={data}
noCollapse={true}
/>
);
};
const RefereeCell = ({ pubkey }: { pubkey: string }) => {
return <span title={pubkey}>{truncateMiddle(pubkey)}</span>;
};
const RefereeLink = ({ pubkey }: { pubkey: string }) => {
const t = useT();
const linkCreator = useLinks(DApp.Explorer);
const link = linkCreator(EXPLORER_PARTIES.replace(':id', pubkey));
return (
<Link to={link} className="underline underline-offset-4">
{t('View on explorer')}
</Link>
);
};
const JoinButton = ({ joined }: { joined: boolean }) => {
const t = useT();
if (joined) {
return (
<Button intent={Intent.None} disabled={true}>
<span className="flex items-center gap-2">
{t('Joined')}{' '}
<span className="text-vega-green-600 dark:text-vega-green">
<VegaIcon name={VegaIconNames.TICK} />
</span>
</span>
</Button>
);
}
return <Button intent={Intent.Primary}>{t('Join this team')}</Button>;
};
const LatestResults = ({ games }: { games: TeamGame[] }) => {
const t = useT();
const latestGames = games.slice(0, 5);
return (
<dl>
<dt className="text-muted text-sm">
{t('Last {{count}} game results', { count: latestGames.length })}
</dt>
<dd className="flex gap-1">
{latestGames.map((game) => {
return (
<Pill key={game.id} className="text-sm">
{t('place', { count: game.team.rank, ordinal: true })}
</Pill>
);
})}
</dd>
</dl>
);
};
const FavoriteGame = ({ games }: { games: TeamGame[] }) => {
const t = useT();
const rewardMetrics = games.map((game) => game.team.rewardMetric);
const count = countBy(rewardMetrics);
let favoriteMetric = '';
let mostOccurances = 0;
for (const key in count) {
if (count[key] > mostOccurances) {
favoriteMetric = key;
mostOccurances = count[key];
}
}
if (!favoriteMetric) return null;
return (
<dl>
<dt className="text-muted text-sm">{t('Favorite game')}</dt>
<dd>
<Pill className="flex-inline items-center gap-2 bg-transparent text-sm">
<VegaIcon
name={VegaIconNames.STAR}
className="text-vega-yellow-400"
/>{' '}
{favoriteMetric}
</Pill>
</dd>
</dl>
);
};
const ToggleButton = ({
active,
...props
}: ButtonHTMLAttributes<HTMLButtonElement> & { active: boolean }) => {
return (
<button
{...props}
className={classNames('relative top-px uppercase border-b-2 py-4', {
'text-muted border-transparent': !active,
'border-vega-yellow': active,
})}
/>
);
};
const StatSection = ({ children }: { children: ReactNode }) => {
return (
<section className="flex flex-col lg:flex-row gap-2 lg:gap-8">
{children}
</section>
);
};
const StatSectionSeparator = () => {
return <div className="hidden md:block border-r border-default" />;
};
const StatList = ({ children }: { children: ReactNode }) => {
return (
<dl className="grid grid-cols-[min-content_min-content] md:flex gap-4 md:gap-6 lg:gap-8 whitespace-nowrap">
{children}
</dl>
);
};
const Stat = ({
value,
label,
tooltip,
}: {
value: ReactNode;
label: ReactNode;
tooltip?: string;
}) => {
return (
<div>
<dd className="text-3xl lg:text-4xl">{value}</dd>
<dt className="text-sm text-muted">
{tooltip ? (
<Tooltip description={tooltip} underline={false}>
<span className="flex items-center gap-2">
{label}
<VegaIcon name={VegaIconNames.INFO} size={12} />
</span>
</Tooltip>
) : (
label
)}
</dt>
</div>
);
};
@@ -0,0 +1,64 @@
import compact from 'lodash/compact';
import orderBy from 'lodash/orderBy';
import {
useTeamQuery,
type TeamFieldsFragment,
type TeamStatsFieldsFragment,
type TeamRefereeFieldsFragment,
type TeamEntityFragment,
} from './__generated__/Team';
import { useVegaWallet } from '@vegaprotocol/wallet';
export type Team = TeamFieldsFragment;
export type TeamStats = TeamStatsFieldsFragment;
export type Member = TeamRefereeFieldsFragment;
export type TeamEntity = TeamEntityFragment;
export type TeamGame = ReturnType<typeof useTeam>['games'][number];
export const useTeam = (teamId?: string) => {
const { pubKey } = useVegaWallet();
const { data, loading, error } = useTeamQuery({
variables: { teamId: teamId || '', partyId: pubKey },
skip: !teamId,
});
const teamEdge = data?.teams?.edges.find((e) => e.node.teamId === teamId);
const partyTeamEdge = data?.partyTeams?.edges[0];
const teamStatsEdge = data?.teamsStatistics?.edges.find(
(e) => e.node.teamId === teamId
);
const members = data?.teamReferees?.edges
.filter((e) => e.node.teamId === teamId)
.map((e) => e.node);
// Find games where the current team participated in
const gamesWithTeam = compact(data?.games.edges).map((edge) => {
const team = edge.node.entities.find((e) => {
if (e.__typename !== 'TeamGameEntity') return false;
if (e.team.teamId !== teamId) return false;
return true;
});
if (!team) return null;
return {
id: edge.node.id,
epoch: edge.node.epoch,
numberOfParticipants: edge.node.numberOfParticipants,
team: team as TeamEntity, // TS can't infer that all the game entities are teams
};
});
const games = orderBy(compact(gamesWithTeam), 'epoch', 'desc');
return {
data,
loading,
error,
stats: teamStatsEdge?.node,
team: teamEdge?.node,
members,
games,
partyInTeam: Boolean(partyTeamEdge),
};
};
-1
View File
@@ -1 +0,0 @@
export { Teams } from './teams';
@@ -1,7 +0,0 @@
export const Teams = () => {
return (
<div>
<h1>Teams</h1>
</div>
);
};
+4 -2
View File
@@ -11,6 +11,7 @@ type TableColumnDefinition = {
name: string;
tooltip?: string;
className?: string;
headerClassName?: string;
testId?: string;
};
@@ -41,13 +42,14 @@ export const Table = forwardRef<
const header = (
<thead className={classNames({ 'max-md:hidden': !noCollapse })}>
<tr>
{columns.map(({ displayName, name, tooltip }) => (
{columns.map(({ displayName, name, tooltip, headerClassName }) => (
<th
key={name}
col-id={name}
className={classNames(
'px-5 py-3 text-xs text-vega-clight-100 dark:text-vega-cdark-100 font-normal',
INNER_BORDER_STYLE
INNER_BORDER_STYLE,
headerClassName
)}
>
<span className="flex flex-row items-center gap-2">
+1 -1
View File
@@ -1,3 +1,3 @@
CONSOLE_IMAGE_NAME=vegaprotocol/trading:latest
VEGA_VERSION=v0.73.10
LOCAL_SERVER=false
LOCAL_SERVER=true
@@ -0,0 +1,58 @@
import pytest
from playwright.sync_api import expect, Page
from vega_sim.null_service import VegaServiceNull
from actions.utils import next_epoch
from wallet_config import PARTY_A, PARTY_B, PARTY_C, PARTY_D
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_teams(vega: VegaServiceNull, page: Page):
# submit_transaction will fail with spam statistics error if block height is 0
# so go forward at least one block
vega.wait_fn(1)
for key in [PARTY_A, PARTY_B, PARTY_C, PARTY_D]:
vega.wallet.create_key(key.name)
team_name = create_team(vega)
next_epoch(vega)
# would be better to derive the team id from the signature if possible but
# vega.submit_transaction does not return anything
teams = vega.list_teams()
# list_teams actually returns a dictionary {"team_id": Team}
team_id = list(teams.keys())[0]
vega.apply_referral_code(PARTY_B.name, team_id)
# go to next epoch so we can check joinedAt and joinedAtEpoch appropriately
next_epoch(vega)
vega.apply_referral_code(PARTY_C.name, team_id)
next_epoch(vega)
vega.apply_referral_code(PARTY_D.name, team_id)
vega.wait_fn(1)
vega.forward("10s")
vega.wait_for_total_catchup()
page.goto(f"/#/competitions/team/{team_id}")
expect(page.get_by_role('heading', level=1)).to_have_text(team_name)
expect(page.get_by_text('Members (3)')).to_be_visible()
def create_team(vega: VegaServiceNull):
team_name = "Foobar"
vega.create_referral_set(
key_name=PARTY_A.name,
name=team_name,
team_url="https://vega.xyz",
avatar_url="http://placekitten.com/200/200",
closed=False
)
return team_name
+2 -2
View File
@@ -16,7 +16,7 @@ export const Routes = {
REFERRALS: '/referrals',
REFERRALS_APPLY_CODE: '/referrals/apply-code',
REFERRALS_CREATE_CODE: '/referrals/create-code',
TEAMS: '/teams',
TEAM: '/competitions/team/:teamId',
FEES: '/fees',
REWARDS: '/rewards',
} as const;
@@ -41,7 +41,7 @@ export const Links: ConsoleLinks = {
REFERRALS: () => Routes.REFERRALS,
REFERRALS_APPLY_CODE: () => Routes.REFERRALS_APPLY_CODE,
REFERRALS_CREATE_CODE: () => Routes.REFERRALS_CREATE_CODE,
TEAMS: () => Routes.TEAMS,
TEAM: (teamId: string) => trimEnd(Routes.TEAM.replace(':teamId', teamId)),
FEES: () => Routes.FEES,
REWARDS: () => Routes.REWARDS,
};
+3 -3
View File
@@ -14,7 +14,7 @@ import { Withdraw } from '../client-pages/withdraw';
import { Transfer } from '../client-pages/transfer';
import { Fees } from '../client-pages/fees';
import { Rewards } from '../client-pages/rewards';
import { Teams } from '../client-pages/teams';
import { Team } from '../client-pages/team';
import { Routes as AppRoutes } from '../lib/links';
import { LayoutWithSky } from '../client-pages/referrals/layout';
import { Referrals } from '../client-pages/referrals/referrals';
@@ -95,8 +95,8 @@ export const useRouterConfig = (): RouteObject[] => {
: undefined,
featureFlags.TEAM_COMPETITION
? {
path: AppRoutes.TEAMS,
element: <Teams />,
path: AppRoutes.TEAM,
element: <Team />,
}
: undefined,
{
Binary file not shown.

After

Width:  |  Height:  |  Size: 668 KiB

+1
View File
@@ -161,6 +161,7 @@ export const useProtocolUpgradeProposalLink = () => {
export const EXPLORER_TX = '/txs/:hash';
export const EXPLORER_ORACLE = '/oracles/:id';
export const EXPLORER_MARKET = '/markets/:id';
export const EXPLORER_PARTIES = '/parties/:id';
// Etherscan pages
export const ETHERSCAN_ADDRESS = '/address/:hash';
+27 -1
View File
@@ -14,6 +14,7 @@
"About the referral program": "About the referral program",
"Active": "Active",
"All": "All",
"Amount earned": "Amount earned",
"An unknown error occurred.": "An unknown error occurred.",
"Anonymous": "Anonymous",
"Anyone with the referral link can apply it to their key(s) of choice via an on chain transaction": "Anyone with the referral link can apply it to their key(s) of choice via an on chain transaction",
@@ -79,6 +80,7 @@
"Earned by me": "Earned by me",
"Enactment date reached and usual auction exit checks pass": "Enactment date reached and usual auction exit checks pass",
"Environment not configured": "Environment not configured",
"Epoch": "Epoch",
"epochs in referral set": "epochs in referral set",
"Epochs in set": "Epochs in set",
"Epochs to next tier": "Epochs to next tier",
@@ -87,6 +89,7 @@
"Experiment for free with virtual assets on <0>Fairground Testnet</0>": "Experiment for free with virtual assets on <0>Fairground Testnet</0>",
"Expiry": "Expiry",
"Explore": "Explore",
"Favorite game": "Favorite game",
"Fees": "Fees",
"Fees paid": "Fees paid",
"Fees work like a CEX with no per-transaction gas for orders": "Fees work like a CEX with no per-transaction gas for orders",
@@ -103,6 +106,7 @@
"Funding Rate": "Funding Rate",
"Funding rate": "Funding rate",
"Futures": "Futures",
"Games ({{count}})": "Games ({{count}})",
"Generate a referral code to share with your friends and start earning commission.": "Generate a referral code to share with your friends and start earning commission.",
"Generate code": "Generate code",
"Get started": "Get started",
@@ -132,6 +136,11 @@
"INTERVAL_I6H": "6H",
"INTERVAL_I1D": "1D",
"Invite friends and earn rewards from the trading fees they pay. Stake those rewards to earn multipliers on future rewards.": "Invite friends and earn rewards from the trading fees they pay. Stake those rewards to earn multipliers on future rewards.",
"Join this team": "Join this team",
"Joined": "Joined",
"Joined at": "Joined at",
"Joined epoch": "Joined epoch",
"Last {{count}} game results": "Last {{count}} game results",
"Learn about providing liquidity": "Learn about providing liquidity",
"Learn more": "Learn more",
"Ledger entries": "Ledger entries",
@@ -150,6 +159,8 @@
"Market specification": "Market specification",
"Market triggers cancellation or governance vote has passed to cancel": "Market triggers cancellation or governance vote has passed to cancel",
"Markets": "Markets",
"Members": "Members",
"Members ({{count}})": "Members ({{count}})",
"Menu": "Menu",
"Metamask Snap <0>quick start</0>": "Metamask Snap <0>quick start</0>",
"Min. epochs": "Min. epochs",
@@ -169,10 +180,12 @@
"No deposits": "No deposits",
"No funding history data": "No funding history data",
"No future markets.": "No future markets.",
"No games": "No games",
"No ledger entries to export": "No ledger entries to export",
"No market": "No market",
"No markets": "No markets",
"No markets.": "No markets.",
"No members": "No members",
"No MetaMask version that supports snaps detected. Learn more about <0>MetaMask Snaps</0>": "No MetaMask version that supports snaps detected. Learn more about <0>MetaMask Snaps</0>",
"No open orders": "No open orders",
"No orders": "No orders",
@@ -185,6 +198,7 @@
"No third party has access to your funds.": "No third party has access to your funds.",
"No volume discount program active": "No volume discount program active",
"No withdrawals": "No withdrawals",
"No. of participating teams": "No. of participating teams",
"Node: {{VEGA_URL}} is unsuitable": "Node: {{VEGA_URL}} is unsuitable",
"Non-custodial and pseudonymous": "Non-custodial and pseudonymous",
"None": "None",
@@ -204,6 +218,10 @@
"pastEpochs_other": "Past {{count}} epochs",
"Pennant": "Pennant",
"Perpetuals": "Perpetuals",
"place_ordinal_one": "{{count}}st",
"place_ordinal_two": "{{count}}nd",
"place_ordinal_few": "{{count}}rd",
"place_ordinal_other": "{{count}}th",
"Please choose another market from the <0>market list</0>": "Please choose another market from the <0>market list</0>",
"Please connect Vega wallet": "Please connect Vega wallet",
"Portfolio": "Portfolio",
@@ -218,10 +236,12 @@
"Purpose built proof of stake blockchain": "Purpose built proof of stake blockchain",
"qUSD": "qUSD",
"qUSD provides a rough USD equivalent of balances across all assets using the value of \"Quantum\" for that asset": "qUSD provides a rough USD equivalent of balances across all assets using the value of \"Quantum\" for that asset",
"Rank": "Rank",
"Read the terms": "Read the terms",
"Ready to trade": "Ready to trade",
"Ready to trade with real funds? <0>Switch to Mainnet</0>": "Ready to trade with real funds? <0>Switch to Mainnet</0>",
"Redeem rewards": "Redeem rewards",
"Referee": "Referee",
"Referral benefits": "Referral benefits",
"Referral discount": "Referral discount",
"Referrals": "Referrals",
@@ -293,10 +313,14 @@
"to": "to",
"To protect the network from spam, you must have at least {{requiredFunds}} qUSD of any asset on the network to proceed.": "To protect the network from spam, you must have at least {{requiredFunds}} qUSD of any asset on the network to proceed.",
"Toast location": "Toast location",
"Total amount of rewards paid out to this team in qUSD": "Total amount of rewards paid out to this team in qUSD",
"Total discount": "Total discount",
"Total distributed": "Total distributed",
"Total fee after discount": "Total fee after discount",
"Total fee before discount": "Total fee before discount",
"Total games": "Total games",
"Total number of games this team has participated in": "Total number of games this team has participated in",
"Total volume": "Total volume",
"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>)",
@@ -310,6 +334,7 @@
"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",
"Type": "Type",
"Unknown": "Unknown",
"Unknown settlement date": "Unknown settlement date",
"Vega chart": "Vega chart",
@@ -365,10 +390,11 @@
"Rewards funded using the pro-rata strategy should be distributed pro-rata by each entity's reward metric scaled by any active multipliers that party has": " Rewards funded using the pro-rata strategy should be distributed pro-rata by each entity's reward metric scaled by any active multipliers that party has",
"Tier {{tier}}": "Tier {{tier}}",
"Reward {{reward}}x": "Reward {{reward}}x",
"Rewards paid": "Rewards paid",
"Reward bonus": "Reward bonus",
"Vesting {{vesting}}x": "Vesting {{vesting}}x",
"Tier {{userTier}}": "Tier {{userTier}}",
"{{reward}}x": "{{reward}}x",
"Reward bonus": "Reward bonus",
"Activity Streak": "Activity Streak",
"userActive": "{{active}} trader: {{count}} epochs so far",
"(Tier {{tier}} as of last epoch)": "(Tier {{tier}} as of last epoch)",
+505 -14
View File
@@ -444,6 +444,31 @@ export type CandleEdge = {
node: Candle;
};
export type CompositePriceConfiguration = {
__typename?: 'CompositePriceConfiguration';
/** Composite price calculation methodology */
CompositePriceType: CompositePriceType;
/** Staleness tolerance duration for each given price sources in the order mentioned above */
SourceStalenessTolerance: Array<Scalars['String']>;
/** Weights for each given price source, first entry is price from trade, then price from book, then first oracle, next oracle, etc. And last entry is for median price */
SourceWeights?: Maybe<Array<Scalars['String']>>;
/** Cash amount used in calculating mark price from the order book */
cashAmount: Scalars['String'];
/** Decay power used in calculating time weight for a given trade */
decayPower: Scalars['Int'];
/** Decay weight used in calculating time weight for a given trade */
decayWeight: Scalars['String'];
};
export enum CompositePriceType {
/** Composite price is set to the last trade (legacy) */
COMPOSITE_PRICE_TYPE_LAST_TRADE = 'COMPOSITE_PRICE_TYPE_LAST_TRADE',
/** Composite price is calculated as a median of the underlying price sources */
COMPOSITE_PRICE_TYPE_MEDIAN = 'COMPOSITE_PRICE_TYPE_MEDIAN',
/** Composite price is calculated as a weighted average of the underlying price sources */
COMPOSITE_PRICE_TYPE_WEIGHTED = 'COMPOSITE_PRICE_TYPE_WEIGHTED'
}
/** Condition describes the condition that must be validated by the data source engine */
export type Condition = {
__typename?: 'Condition';
@@ -1135,6 +1160,15 @@ export type Erc20WithdrawalDetails = {
receiverAddress: Scalars['String'];
};
/** EstimatedTransferFee Results of estimation of transfer fee and the fee discount */
export type EstimatedTransferFee = {
__typename?: 'EstimatedTransferFee';
/** Discount applied to the fee. */
discount: Scalars['String'];
/** Estimated fee for the transfer. */
fee: Scalars['String'];
};
/**
* Specifies a data source that derives its content from calling a read method
* on an Ethereum contract.
@@ -1274,6 +1308,8 @@ export type Fees = {
__typename?: 'Fees';
/** The factors used to calculate the different fees */
factors: FeeFactors;
/** Liquidity fee settings for the market describing how the fee was calculated */
liquidityFeeSettings?: Maybe<LiquidityFeeSettings>;
};
/** Fees that have been applied on a specific market/asset up to the given epoch. */
@@ -1476,6 +1512,39 @@ export type FutureProduct = {
settlementAsset: Asset;
};
/** Game metrics for a given epoch */
export type Game = {
__typename?: 'Game';
/** Entities that were rewarded during the epoch. */
entities: Array<GameEntity>;
/** Epoch during which the metrics were calculated. */
epoch: Scalars['Int'];
/** ID of the game. */
id: Scalars['ID'];
/** Number of participants that took part in the game during the epoch. */
numberOfParticipants: Scalars['Int'];
};
/** Edge type containing the game metrics and cursor information returned by a GameConnection */
export type GameEdge = {
__typename?: 'GameEdge';
/** Cursor identifying the game */
cursor: Scalars['String'];
/** Game information and metrics. */
node: Game;
};
export type GameEntity = IndividualGameEntity | TeamGameEntity;
/** Connection type for retrieving cursor-based paginated game information */
export type GamesConnection = {
__typename?: 'GamesConnection';
/** Page of game edges for the connection */
edges?: Maybe<Array<Maybe<GameEdge>>>;
/** Current page information */
pageInfo?: Maybe<PageInfo>;
};
export type GovernanceTransferKind = OneOffGovernanceTransfer | RecurringGovernanceTransfer;
export enum GovernanceTransferType {
@@ -1509,6 +1578,23 @@ export type IcebergOrder = {
reservedRemaining: Scalars['String'];
};
/** Individual party participating in a game and their metrics */
export type IndividualGameEntity = {
__typename?: 'IndividualGameEntity';
/** Party ID of the participant */
individual: Scalars['ID'];
/** The rank of the individual within the game. If the individual is in a team, then the rank of the individual in the team */
rank: Scalars['Int'];
/** The rewards earned by the individual during the epoch */
rewardEarned: Scalars['String'];
/** The reward metric applied to the game */
rewardMetric: Scalars['String'];
/** Total rewards earned by the individual during the game */
totalRewardsEarned: Scalars['String'];
/** The volume traded by the individual */
volume: Scalars['String'];
};
export enum IndividualScope {
/** All parties on the network are within the scope of this reward */
INDIVIDUAL_SCOPE_ALL = 'INDIVIDUAL_SCOPE_ALL',
@@ -1576,12 +1662,22 @@ export enum Interval {
INTERVAL_I1H = 'INTERVAL_I1H',
/** 1 minute interval */
INTERVAL_I1M = 'INTERVAL_I1M',
/** 4 hour interval */
INTERVAL_I4H = 'INTERVAL_I4H',
/** 5 minute interval */
INTERVAL_I5M = 'INTERVAL_I5M',
/** 6 hour interval */
INTERVAL_I6H = 'INTERVAL_I6H',
/** 7 day interval */
INTERVAL_I7D = 'INTERVAL_I7D',
/** 8 hour interval */
INTERVAL_I8H = 'INTERVAL_I8H',
/** 12 hour interval */
INTERVAL_I12H = 'INTERVAL_I12H',
/** 15 minute interval (default) */
INTERVAL_I15M = 'INTERVAL_I15M'
INTERVAL_I15M = 'INTERVAL_I15M',
/** 30 minute interval */
INTERVAL_I30M = 'INTERVAL_I30M'
}
/** A node's key rotation event */
@@ -1650,6 +1746,8 @@ export type LedgerEntryFilter = {
FromAccountFilter?: InputMaybe<AccountFilter>;
/** Used to set values for filtering receiver accounts. Party must be provided in this filter or from_account_filter, or both. */
ToAccountFilter?: InputMaybe<AccountFilter>;
/** Optional transfer ID to filter by. If provided, all other filters are ignored. */
TransferId?: InputMaybe<Scalars['ID']>;
/** List of transfer types that is used for filtering sender and receiver accounts. */
TransferTypes?: InputMaybe<Array<InputMaybe<TransferType>>>;
};
@@ -1674,6 +1772,37 @@ export type LiquidationPrice = {
open_volume_only: Scalars['String'];
};
export type LiquidationStrategy = {
__typename?: 'LiquidationStrategy';
/** Specifies the fraction of its position the network will try to reduce its position by in a single disposal attempt. */
disposalFraction: Scalars['String'];
/** Specifies the interval, in seconds, at which point the network will try to unload its position. */
disposalTimeStep: Scalars['Int'];
/** Specifies the size of the position held by the network that it will try to dispose of in one attempt. */
fullDisposalSize: Scalars['Int'];
/** Specifies the maximum size by which the network can reduce its position as a fraction of the volume on the book. */
maxFractionConsumed: Scalars['String'];
};
export enum LiquidityFeeMethod {
/** Fee is set by the market to a constant value irrespective of any liquidity provider's nominated fee */
METHOD_CONSTANT = 'METHOD_CONSTANT',
/** Fee is smallest value of all bids, such that liquidity providers with nominated fees less than or equal to this value still have sufficient commitment to fulfil the market's target stake. */
METHOD_MARGINAL_COST = 'METHOD_MARGINAL_COST',
METHOD_UNSPECIFIED = 'METHOD_UNSPECIFIED',
/** Fee is the weighted average of all liquidity providers' nominated fees, weighted by their commitment */
METHOD_WEIGHTED_AVERAGE = 'METHOD_WEIGHTED_AVERAGE'
}
/** Market settings that describe how the liquidity fee is calculated */
export type LiquidityFeeSettings = {
__typename?: 'LiquidityFeeSettings';
/** Constant liquidity fee used when using the constant fee method */
feeConstant?: Maybe<Scalars['String']>;
/** Method used to calculate the market's liquidity fee */
method: LiquidityFeeMethod;
};
/** Configuration of a market liquidity monitoring parameters */
export type LiquidityMonitoringParameters = {
__typename?: 'LiquidityMonitoringParameters';
@@ -1986,8 +2115,14 @@ export type MarginLevels = {
initialLevel: Scalars['String'];
/** Minimal margin for the position to be maintained in the network (unsigned integer) */
maintenanceLevel: Scalars['String'];
/** Margin factor, only relevant for isolated margin mode, else 0 */
marginFactor: Scalars['String'];
/** Margin mode of the party, cross margin or isolated margin */
marginMode: MarginMode;
/** Market in which the margin is required for this party */
market: Market;
/** When in isolated margin, the required order margin level, otherwise, 0 */
orderMarginLevel: Scalars['String'];
/** The party for this margin */
party: Party;
/** If the margin is between maintenance and search, the network will initiate a collateral search, expressed as unsigned integer */
@@ -2010,8 +2145,14 @@ export type MarginLevelsUpdate = {
initialLevel: Scalars['String'];
/** Minimal margin for the position to be maintained in the network (unsigned integer) */
maintenanceLevel: Scalars['String'];
/** Margin factor, only relevant for isolated margin mode, else 0 */
marginFactor: Scalars['String'];
/** Margin mode of the party, cross margin or isolated margin */
marginMode: MarginMode;
/** Market in which the margin is required for this party */
marketId: Scalars['ID'];
/** When in isolated margin, the required order margin level, otherwise, 0 */
orderMarginLevel: Scalars['String'];
/** The party for this margin */
partyId: Scalars['ID'];
/** If the margin is between maintenance and search, the network will initiate a collateral search (unsigned integer) */
@@ -2020,6 +2161,13 @@ export type MarginLevelsUpdate = {
timestamp: Scalars['Timestamp'];
};
export enum MarginMode {
/** Party is in cross margin mode */
MARGIN_MODE_CROSS_MARGIN = 'MARGIN_MODE_CROSS_MARGIN',
/** Party is in isolated margin mode */
MARGIN_MODE_ISOLATED_MARGIN = 'MARGIN_MODE_ISOLATED_MARGIN'
}
/** Represents a product & associated parameters that can be traded on Vega, has an associated OrderBook and Trade history */
export type Market = {
__typename?: 'Market';
@@ -2056,6 +2204,8 @@ export type Market = {
insurancePoolFraction?: Maybe<Scalars['String']>;
/** Linear slippage factor is used to cap the slippage component of maintainence margin - it is applied to the slippage volume */
linearSlippageFactor: Scalars['String'];
/** Optional: Liquidation strategy for the market */
liquidationStrategy?: Maybe<LiquidationStrategy>;
/** Liquidity monitoring parameters for the market */
liquidityMonitoringParameters: LiquidityMonitoringParameters;
/** The list of the liquidity provision commitments for this market */
@@ -2092,7 +2242,10 @@ export type Market = {
priceMonitoringSettings: PriceMonitoringSettings;
/** The proposal that initiated this market */
proposal?: Maybe<Proposal>;
/** Quadratic slippage factor is used to cap the slippage component of maintainence margin - it is applied to the square of the slippage volume */
/**
* Quadratic slippage factor is used to cap the slippage component of maintainence margin - it is applied to the square of the slippage volume
* @deprecated This field will be removed in a future release
*/
quadraticSlippageFactor: Scalars['String'];
/** Risk factors for the market */
riskFactors?: Maybe<RiskFactor>;
@@ -2208,6 +2361,8 @@ export type MarketData = {
liquidityProviderSla?: Maybe<Array<LiquidityProviderSLA>>;
/** The mark price (an unsigned integer) */
markPrice: Scalars['String'];
/** The methodology used for the calculation of the mark price */
markPriceType: CompositePriceType;
/** Market of the associated mark price */
market: Market;
/** The market growth factor for the last market time window */
@@ -2222,6 +2377,8 @@ export type MarketData = {
midPrice: Scalars['String'];
/** RFC3339Nano time indicating the next time positions will be marked to market */
nextMarkToMarket: Scalars['String'];
/** RFC3339Nano time indicating the next time the network will attempt to close part of its position */
nextNetworkCloseout: Scalars['String'];
/** The sum of the size of all positions greater than 0. */
openInterest: Scalars['String'];
/** A list of valid price ranges per associated trigger */
@@ -2485,17 +2642,26 @@ export type NewMarket = {
instrument: InstrumentConfiguration;
/** Linear slippage factor is used to cap the slippage component of maintenance margin - it is applied to the slippage volume */
linearSlippageFactor: Scalars['String'];
/** Liquidation strategy for the market */
liquidationStrategy?: Maybe<LiquidationStrategy>;
/** Specifies how the liquidity fee for the market will be calculated */
liquidityFeeSettings?: Maybe<LiquidityFeeSettings>;
/** Liquidity monitoring parameters */
liquidityMonitoringParameters: LiquidityMonitoringParameters;
/** Liquidity SLA Parameters */
liquiditySLAParameters?: Maybe<LiquiditySLAParameters>;
/** Configuration for mark price calculation for the market */
markPriceConfiguration: CompositePriceConfiguration;
/** Metadata for this instrument, tags */
metadata?: Maybe<Array<Scalars['String']>>;
/** Decimal places for order sizes, sets what size the smallest order / position on the market can be */
positionDecimalPlaces: Scalars['Int'];
/** Price monitoring parameters */
priceMonitoringParameters: PriceMonitoringParameters;
/** Quadratic slippage factor is used to cap the slippage component of maintenance margin - it is applied to the square of the slippage volume */
/**
* Quadratic slippage factor is used to cap the slippage component of maintenance margin - it is applied to the square of the slippage volume
* @deprecated This field will be removed in a future release
*/
quadraticSlippageFactor: Scalars['String'];
/** New market risk configuration */
riskParameters: RiskModel;
@@ -2510,6 +2676,8 @@ export type NewSpotMarket = {
decimal_places: Scalars['Int'];
/** New spot market instrument configuration */
instrument: InstrumentConfiguration;
/** Specifies how the liquidity fee for the market will be calculated */
liquidityFeeSettings?: Maybe<LiquidityFeeSettings>;
/** Specifies the liquidity provision SLA parameters */
liquiditySLAParams: LiquiditySLAParameters;
/** Optional spot market metadata tags */
@@ -2798,6 +2966,8 @@ export type ObservableMarketData = {
liquidityProviderSla?: Maybe<Array<ObservableLiquidityProviderSLA>>;
/** The mark price (an unsigned integer) */
markPrice: Scalars['String'];
/** The methodology used to calculated mark price */
markPriceType: CompositePriceType;
/** The market growth factor for the last market time window */
marketGrowth: Scalars['String'];
/** Market ID of the associated mark price */
@@ -3118,6 +3288,8 @@ export enum OrderRejectionReason {
ORDER_ERROR_INVALID_TIME_IN_FORCE = 'ORDER_ERROR_INVALID_TIME_IN_FORCE',
/** Invalid type */
ORDER_ERROR_INVALID_TYPE = 'ORDER_ERROR_INVALID_TYPE',
/** Party has insufficient funds to cover for the order margin for the new or amended order */
ORDER_ERROR_ISOLATED_MARGIN_CHECK_FAILED = 'ORDER_ERROR_ISOLATED_MARGIN_CHECK_FAILED',
/** Margin check failed - not enough available margin */
ORDER_ERROR_MARGIN_CHECK_FAILED = 'ORDER_ERROR_MARGIN_CHECK_FAILED',
/** Market is closed */
@@ -3138,6 +3310,8 @@ export enum OrderRejectionReason {
ORDER_ERROR_OFFSET_MUST_BE_GREATER_THAN_ZERO = 'ORDER_ERROR_OFFSET_MUST_BE_GREATER_THAN_ZERO',
/** Order is out of sequence */
ORDER_ERROR_OUT_OF_SEQUENCE = 'ORDER_ERROR_OUT_OF_SEQUENCE',
/** Pegged orders are not allowed for a party in isolated margin mode */
ORDER_ERROR_PEGGED_ORDERS_NOT_ALLOWED_IN_ISOLATED_MARGIN_MODE = 'ORDER_ERROR_PEGGED_ORDERS_NOT_ALLOWED_IN_ISOLATED_MARGIN_MODE',
/** A post-only order would produce an aggressive trade and thus it has been rejected */
ORDER_ERROR_POST_ONLY_ORDER_WOULD_TRADE = 'ORDER_ERROR_POST_ONLY_ORDER_WOULD_TRADE',
/** A reduce-ony order would not reduce the party's position and thus it has been rejected */
@@ -3482,7 +3656,9 @@ export type PartyrewardSummariesArgs = {
export type PartyrewardsConnectionArgs = {
assetId?: InputMaybe<Scalars['ID']>;
fromEpoch?: InputMaybe<Scalars['Int']>;
gameId?: InputMaybe<Scalars['ID']>;
pagination?: InputMaybe<Pagination>;
teamId?: InputMaybe<Scalars['ID']>;
toEpoch?: InputMaybe<Scalars['Int']>;
};
@@ -3504,8 +3680,12 @@ export type PartytradesConnectionArgs = {
/** Represents a party on Vega, could be an ethereum wallet address in the future */
export type PartytransfersConnectionArgs = {
direction?: InputMaybe<TransferDirection>;
fromEpoch?: InputMaybe<Scalars['Int']>;
isReward?: InputMaybe<Scalars['Boolean']>;
pagination?: InputMaybe<Pagination>;
scope?: InputMaybe<TransferScope>;
status?: InputMaybe<TransferStatus>;
toEpoch?: InputMaybe<Scalars['Int']>;
};
@@ -3586,6 +3766,41 @@ export type PartyLockedBalance = {
untilEpoch: Scalars['Int'];
};
/** Margin mode selected for the given party and market. */
export type PartyMarginMode = {
__typename?: 'PartyMarginMode';
/** Epoch at which the update happened. */
atEpoch: Scalars['Int'];
/** Selected margin mode. */
marginMode: MarginMode;
/** Margin factor for the market. Isolated mode only. */
margin_factor?: Maybe<Scalars['String']>;
/** Unique ID of the market. */
marketId: Scalars['ID'];
/** Maximum theoretical leverage for the market. Isolated mode only. */
max_theoretical_leverage?: Maybe<Scalars['String']>;
/** Minimum theoretical margin factor for the market. Isolated mode only. */
min_theoretical_margin_factor?: Maybe<Scalars['String']>;
/** Unique ID of the party. */
partyId: Scalars['ID'];
};
/** Edge type containing the deposit and cursor information returned by a PartyMarginModeConnection */
export type PartyMarginModeEdge = {
__typename?: 'PartyMarginModeEdge';
cursor: Scalars['String'];
node: PartyMarginMode;
};
/** Connection type for retrieving cursor-based paginated party margin modes information */
export type PartyMarginModesConnection = {
__typename?: 'PartyMarginModesConnection';
/** The party margin modes */
edges?: Maybe<Array<Maybe<PartyMarginModeEdge>>>;
/** The pagination information */
pageInfo?: Maybe<PageInfo>;
};
/**
* All staking information related to a Party.
* Contains the current recognised balance by the network and
@@ -3662,6 +3877,14 @@ export type Perpetual = {
dataSourceSpecForSettlementData: DataSourceSpec;
/** Data source specification describing the data source for settlement schedule */
dataSourceSpecForSettlementSchedule: DataSourceSpec;
/** Lower bound for the funding-rate such that the funding-rate will never be lower than this value */
fundingRateLowerBound: Scalars['String'];
/** Factor applied to funding-rates. This scales the impact that spot price deviations have on funding payments */
fundingRateScalingFactor: Scalars['String'];
/** Upper bound for the funding-rate such that the funding-rate will never be higher than this value */
fundingRateUpperBound: Scalars['String'];
/** Optional configuration driving the index price calculation for perpetual product */
indexPriceConfig?: Maybe<CompositePriceConfiguration>;
/** Continuously compounded interest rate used in funding rate calculation, in the range [-1, 1] */
interestRate: Scalars['String'];
/** Controls how much the upcoming funding payment liability contributes to party's margin, in the range [0, 1] */
@@ -3681,8 +3904,18 @@ export type PerpetualData = {
fundingPayment?: Maybe<Scalars['String']>;
/** Percentage difference between the time-weighted average price of the external and internal data point. */
fundingRate?: Maybe<Scalars['String']>;
/** The index price used for external VWAP calculation */
indexPrice: Scalars['String'];
/** The methodology used to calculated index price for perps */
indexPriceType: CompositePriceType;
/** Time-weighted average price calculated from data points for this period from the internal data source. */
internalTwap?: Maybe<Scalars['String']>;
/** RFC3339Nano time indicating the next time index price will be calculated for perps where applicable */
nextIndexPriceCalc: Scalars['String'];
/** Funding period sequence number */
seqNum: Scalars['Int'];
/** Time at which the funding period started */
startTime: Scalars['Timestamp'];
};
export type PerpetualProduct = {
@@ -3697,6 +3930,12 @@ export type PerpetualProduct = {
dataSourceSpecForSettlementData: DataSourceDefinition;
/** Data source specification describing the data source for settlement schedule */
dataSourceSpecForSettlementSchedule: DataSourceDefinition;
/** Lower bound for the funding-rate such that the funding-rate will never be lower than this value */
fundingRateLowerBound: Scalars['String'];
/** Factor applied to funding-rates. This scales the impact that spot price deviations have on funding payments. */
fundingRateScalingFactor: Scalars['String'];
/** Upper bound for the funding-rate such that the funding-rate will never be higher than this value */
fundingRateUpperBound: Scalars['String'];
/** Continuously compounded interest rate used in funding rate calculation, in the range [-1, 1] */
interestRate: Scalars['String'];
/** Controls how much the upcoming funding payment liability contributes to party's margin, in the range [0, 1] */
@@ -4310,6 +4549,14 @@ export type PubKey = {
key?: Maybe<Scalars['String']>;
};
export type QuantumRewardsPerEpoch = {
__typename?: 'QuantumRewardsPerEpoch';
/** Epoch for which this information is valid. */
epoch: Scalars['Int'];
/** Total of rewards accumulated over the epoch period expressed in quantum value. */
total_quantum_rewards: Scalars['String'];
};
/** Queries allow a caller to read data and filter data via GraphQL. */
export type Query = {
__typename?: 'Query';
@@ -4354,6 +4601,8 @@ export type Query = {
estimateOrder: OrderEstimate;
/** Return a margin range for the specified position and liquidation price range if available collateral is supplied */
estimatePosition?: Maybe<PositionEstimate>;
/** Estimate transfer fee */
estimateTransferFee?: Maybe<EstimatedTransferFee>;
/** Query for historic ethereum key rotations */
ethereumKeyRotations: EthereumKeyRotationsConnection;
/** Get fees statistics */
@@ -4369,6 +4618,8 @@ export type Query = {
fundingPeriodDataPoints: FundingPeriodDataPointConnection;
/** Funding periods for perpetual markets */
fundingPeriods: FundingPeriodConnection;
/** Get a list of games and their metrics. */
games: GamesConnection;
/** Get market data history for a specific market. If no dates are given, the latest snapshot will be returned. If only the start date is provided all history from the given date will be provided, and if only the end date is provided, all history from the start up to and including the end date will be provided. */
getMarketDataHistoryConnectionByID?: Maybe<MarketDataConnection>;
/** Query for historic key rotations */
@@ -4384,10 +4635,10 @@ export type Query = {
* At least one party ID must be specified in the from or to account filter.
*
* Entries can be filtered by:
* - the sending account (market ID, asset ID, account type)
* - receiving account (market ID, asset ID, account type)
* - sending AND receiving account
* - transfer type either in addition to the above filters or as a standalone option
* - the sending account (market ID, asset ID, account type)
* - receiving account (market ID, asset ID, account type)
* - sending AND receiving account
* - transfer type either in addition to the above filters or as a standalone option
*
* Note: The date range is restricted to any 5 days.
* If no start or end date is provided, only ledger entries from the last 5 days will be returned.
@@ -4432,12 +4683,18 @@ export type Query = {
orderByReference: Order;
/** Order versions (created via amendments if any) found by orderID */
orderVersionsConnection?: Maybe<OrderConnection>;
/** List paid liquidity fees statistics */
/** List statistics about paid liquidity fees */
paidLiquidityFees?: Maybe<PaidLiquidityFeesConnection>;
/** One or more entities that are trading on the Vega network */
partiesConnection?: Maybe<PartyConnection>;
/** An entity that is trading on the Vega network */
party?: Maybe<Party>;
/**
* List margin modes per party per market
*
* Get a list of all margin modes, or for a specific market ID, or party ID.
*/
partyMarginModes?: Maybe<PartyMarginModesConnection>;
/** Fetch all positions */
positions?: Maybe<PositionConnection>;
/** A governance proposal located by either its ID or reference. If both are set, ID is used. */
@@ -4461,6 +4718,12 @@ export type Query = {
stopOrders?: Maybe<StopOrderConnection>;
/** List markets in a succession line */
successorMarkets?: Maybe<SuccessorMarketConnection>;
/**
* List team members' statistics for a given team
* Get the statistics of all team members for a given team ID, or for a specific member by using party ID, over a number of epochs.
* If a team does not have at least the number of epochs worth of data, it is ignored.
*/
teamMembersStatistics?: Maybe<TeamMembersStatisticsConnection>;
/** List a referee's team history */
teamRefereeHistory?: Maybe<TeamRefereeHistoryConnection>;
/** List all referees for a team */
@@ -4473,10 +4736,18 @@ export type Query = {
* If both team ID and party ID is provided, only the team ID will be used.
*/
teams?: Maybe<TeamConnection>;
/**
* List teams statistics
* Get the statistics of all teams, or for a specific team by using team ID, over a number of epochs.
* If a team does not have at least the number of epochs worth of data, it is ignored.
*/
teamsStatistics?: Maybe<TeamsStatisticsConnection>;
/** Get total transfer fee discount available */
totalTransferFeeDiscount?: Maybe<TotalTransferFeeDiscount>;
/** Get a list of all trades and apply any given filters to the results */
trades?: Maybe<TradeConnection>;
/** Find a transfer using its ID */
transfer?: Maybe<Transfer>;
transfer?: Maybe<TransferNode>;
/** Get a list of all transfers for a public key */
transfersConnection?: Maybe<TransferConnection>;
/** Get volume discount statistics */
@@ -4620,6 +4891,16 @@ export type QueryestimatePositionArgs = {
};
/** Queries allow a caller to read data and filter data via GraphQL. */
export type QueryestimateTransferFeeArgs = {
amount: Scalars['String'];
assetId: Scalars['String'];
fromAccount: Scalars['ID'];
fromAccountType: AccountType;
toAccount: Scalars['ID'];
};
/** Queries allow a caller to read data and filter data via GraphQL. */
export type QueryethereumKeyRotationsArgs = {
nodeId?: InputMaybe<Scalars['ID']>;
@@ -4669,6 +4950,16 @@ export type QueryfundingPeriodsArgs = {
};
/** Queries allow a caller to read data and filter data via GraphQL. */
export type QuerygamesArgs = {
entityScope?: InputMaybe<EntityScope>;
epochFrom?: InputMaybe<Scalars['Int']>;
epochTo?: InputMaybe<Scalars['Int']>;
gameId?: InputMaybe<Scalars['ID']>;
pagination?: InputMaybe<Pagination>;
};
/** Queries allow a caller to read data and filter data via GraphQL. */
export type QuerygetMarketDataHistoryConnectionByIDArgs = {
end?: InputMaybe<Scalars['Timestamp']>;
@@ -4813,6 +5104,14 @@ export type QuerypartyArgs = {
};
/** Queries allow a caller to read data and filter data via GraphQL. */
export type QuerypartyMarginModesArgs = {
marketId?: InputMaybe<Scalars['ID']>;
pagination?: InputMaybe<Pagination>;
partyId?: InputMaybe<Scalars['ID']>;
};
/** Queries allow a caller to read data and filter data via GraphQL. */
export type QuerypositionsArgs = {
filter?: InputMaybe<PositionsFilter>;
@@ -4892,6 +5191,15 @@ export type QuerysuccessorMarketsArgs = {
};
/** Queries allow a caller to read data and filter data via GraphQL. */
export type QueryteamMembersStatisticsArgs = {
aggregationEpochs?: InputMaybe<Scalars['Int']>;
pagination?: InputMaybe<Pagination>;
partyId?: InputMaybe<Scalars['ID']>;
teamId: Scalars['ID'];
};
/** Queries allow a caller to read data and filter data via GraphQL. */
export type QueryteamRefereeHistoryArgs = {
pagination?: InputMaybe<Pagination>;
@@ -4914,6 +5222,21 @@ export type QueryteamsArgs = {
};
/** Queries allow a caller to read data and filter data via GraphQL. */
export type QueryteamsStatisticsArgs = {
aggregationEpochs?: InputMaybe<Scalars['Int']>;
pagination?: InputMaybe<Pagination>;
teamId?: InputMaybe<Scalars['ID']>;
};
/** Queries allow a caller to read data and filter data via GraphQL. */
export type QuerytotalTransferFeeDiscountArgs = {
assetId: Scalars['String'];
partyId: Scalars['String'];
};
/** Queries allow a caller to read data and filter data via GraphQL. */
export type QuerytradesArgs = {
dateRange?: InputMaybe<DateRange>;
@@ -4931,9 +5254,13 @@ export type QuerytransferArgs = {
/** Queries allow a caller to read data and filter data via GraphQL. */
export type QuerytransfersConnectionArgs = {
direction?: InputMaybe<TransferDirection>;
fromEpoch?: InputMaybe<Scalars['Int']>;
isReward?: InputMaybe<Scalars['Boolean']>;
pagination?: InputMaybe<Pagination>;
partyId?: InputMaybe<Scalars['ID']>;
scope?: InputMaybe<TransferScope>;
status?: InputMaybe<TransferStatus>;
toEpoch?: InputMaybe<Scalars['Int']>;
};
@@ -5150,18 +5477,27 @@ export type Reward = {
asset: Asset;
/** Epoch for which this reward was distributed */
epoch: Epoch;
/** Optional game ID for rewards that are paid for participation in a game */
gameId?: Maybe<Scalars['ID']>;
/** The epoch when the reward is released */
lockedUntilEpoch: Epoch;
/** The market ID for which this reward is paid if any */
/**
* The market ID for which this reward is paid if any
* @deprecated Use gameId
*/
marketId: Scalars['ID'];
/** Party receiving the reward */
party: Party;
/** Percentage out of the total distributed reward */
percentageOfTotal: Scalars['String'];
/** Amount paid as a reward, expressed in asset's quantum unit */
quantumAmount: Scalars['String'];
/** RFC3339Nano time when the rewards were received */
receivedAt: Scalars['Timestamp'];
/** The type of reward */
rewardType: AccountType;
/** Optional team ID for rewards that are paid if the party is a member of a team, and for participation in a game. */
teamId?: Maybe<Scalars['ID']>;
};
/** Edge type containing the reward and cursor information returned by a RewardsConnection */
@@ -5515,6 +5851,10 @@ export type StopOrder = {
partyId: Scalars['ID'];
/** Optional rejection reason for an order */
rejectionReason?: Maybe<StopOrderRejectionReason>;
/** Size override setting */
sizeOverrideSetting: StopOrderSizeOverrideSetting;
/** Size override value */
sizeOverrideValue?: Maybe<Scalars['String']>;
/** Status of the stop order */
status: StopOrderStatus;
/** Order to submit when the stop order is triggered. */
@@ -5585,6 +5925,8 @@ export enum StopOrderRejectionReason {
REJECTION_REASON_MAX_STOP_ORDERS_PER_PARTY_REACHED = 'REJECTION_REASON_MAX_STOP_ORDERS_PER_PARTY_REACHED',
/** Stop orders submission must be reduce only */
REJECTION_REASON_MUST_BE_REDUCE_ONLY = 'REJECTION_REASON_MUST_BE_REDUCE_ONLY',
/** Stop orders are not allowed during the opening auction */
REJECTION_REASON_STOP_ORDER_NOT_ALLOWED_DURING_OPENING_AUCTION = 'REJECTION_REASON_STOP_ORDER_NOT_ALLOWED_DURING_OPENING_AUCTION',
/** Stop orders are not allowed without a position */
REJECTION_REASON_STOP_ORDER_NOT_ALLOWED_WITHOUT_A_POSITION = 'REJECTION_REASON_STOP_ORDER_NOT_ALLOWED_WITHOUT_A_POSITION',
/** This stop order does not close the position */
@@ -5593,6 +5935,16 @@ export enum StopOrderRejectionReason {
REJECTION_REASON_TRADING_NOT_ALLOWED = 'REJECTION_REASON_TRADING_NOT_ALLOWED'
}
/** Stop order size override settings */
export enum StopOrderSizeOverrideSetting {
/** No size override, the size within the contained normal order submission will be used */
SIZE_OVERRIDE_SETTING_NONE = 'SIZE_OVERRIDE_SETTING_NONE',
/** Use the total position of the trader */
SIZE_OVERRIDE_SETTING_POSITION = 'SIZE_OVERRIDE_SETTING_POSITION',
/** The size override has not been specified, this should never happen! */
SIZE_OVERRIDE_SETTING_UNSPECIFIED = 'SIZE_OVERRIDE_SETTING_UNSPECIFIED'
}
/** Valid stop order statuses, these determine several states for a stop order that cannot be expressed with other fields in StopOrder. */
export enum StopOrderStatus {
/** Stop order has been cancelled. This could be by the trader or by the network. */
@@ -5805,9 +6157,11 @@ export type TargetStakeParameters = {
/** Team record containing the team information. */
export type Team = {
__typename?: 'Team';
/** List of public keys that are allowed to join the team. Only applicable to closed teams. */
allowList: Array<Scalars['String']>;
/** Link to an image of the team's avatar. */
avatarURL: Scalars['String'];
/** Tells if a party can join the team or not. */
avatarUrl: Scalars['String'];
/** Whether or not the team is closed to new party members. When closed, only parties specified in the allow list can join the team. */
closed: Scalars['Boolean'];
/** Time in RFC3339Nano format when the team was created. */
createdAt: Scalars['Timestamp'];
@@ -5820,7 +6174,7 @@ export type Team = {
/** Unique ID of the team. */
teamId: Scalars['ID'];
/** Link to the team's homepage. */
teamURL: Scalars['String'];
teamUrl: Scalars['String'];
};
/** Connection type for retrieving cursor-based paginated team data */
@@ -5841,6 +6195,67 @@ export type TeamEdge = {
node: Team;
};
/** Team participating in a game and their metrics. */
export type TeamGameEntity = {
__typename?: 'TeamGameEntity';
/** Rank of the team within the game. */
rank: Scalars['Int'];
/** Total rewards earned by the team during the epoch */
rewardEarned: Scalars['String'];
/** Reward metric applied to the game. */
rewardMetric: Scalars['String'];
/** Breakdown of the team members and their contributions to the total team metrics. */
team: TeamParticipation;
/** Total rewards earned by the team for the game */
totalRewardsEarned: Scalars['String'];
/** Total volume traded by the team */
volume: Scalars['String'];
};
/** Team member's statistics record containing the member's information. */
export type TeamMemberStatistics = {
__typename?: 'TeamMemberStatistics';
/** List of games played over the requested epoch period. */
gamesPlayed: Array<Scalars['String']>;
/** Party ID the statistics are related to. */
partyId: Scalars['String'];
/** List of rewards over the requested epoch period, expressed in quantum value for each epoch */
quantumRewards: Array<QuantumRewardsPerEpoch>;
/** Total number of games played. */
totalGamesPlayed: Scalars['Int'];
/** Total of rewards accumulated over the requested epoch period, expressed in quantum value. */
totalQuantumRewards: Scalars['String'];
/** Total of volume accumulated over the requested epoch period, expressed in quantum value. */
totalQuantumVolume: Scalars['String'];
};
/** Edge type containing a team member statistics cursor and its associated statistics data */
export type TeamMemberStatisticsEdge = {
__typename?: 'TeamMemberStatisticsEdge';
/** Cursor identifying the team data */
cursor: Scalars['String'];
/** Team member's statistics data */
node: TeamMemberStatistics;
};
/** Connection type for retrieving cursor-based paginated team member statistics data */
export type TeamMembersStatisticsConnection = {
__typename?: 'TeamMembersStatisticsConnection';
/** Team members' statistics in this connection */
edges: Array<TeamMemberStatisticsEdge>;
/** Pagination information */
pageInfo: PageInfo;
};
/** Team participation information, i.e. the team ID and the metrics for each participating team member. */
export type TeamParticipation = {
__typename?: 'TeamParticipation';
/** List of participating team members and their metrics. */
membersParticipating: Array<IndividualGameEntity>;
/** Team ID */
teamId: Scalars['ID'];
};
/** A team's referee info */
export type TeamReferee = {
__typename?: 'TeamReferee';
@@ -5901,12 +6316,54 @@ export type TeamRefereeHistoryEdge = {
node: TeamRefereeHistory;
};
/** Team's statistics record containing the team information. */
export type TeamStatistics = {
__typename?: 'TeamStatistics';
/** List of games played over the requested epoch period. */
gamesPlayed: Array<Scalars['String']>;
/** List of rewards over the requested epoch period, expressed in quantum value for each epoch */
quantumRewards: Array<QuantumRewardsPerEpoch>;
/** Team ID the statistics are related to. */
teamId: Scalars['String'];
/** Total of games played. */
totalGamesPlayed: Scalars['Int'];
/** Total of rewards accumulated over the requested epoch period, expressed in quantum value. */
totalQuantumRewards: Scalars['String'];
/** Total of volume accumulated over the requested epoch period, expressed in quantum value. */
totalQuantumVolume: Scalars['String'];
};
/** Edge type containing a team statistics cursor and its associated team's statistics data */
export type TeamStatisticsEdge = {
__typename?: 'TeamStatisticsEdge';
/** Cursor identifying the team data */
cursor: Scalars['String'];
/** Team's statistics data */
node: TeamStatistics;
};
/** Connection type for retrieving cursor-based paginated team statistics data */
export type TeamsStatisticsConnection = {
__typename?: 'TeamsStatisticsConnection';
/** Teams' statistics in this connection */
edges: Array<TeamStatisticsEdge>;
/** Pagination information */
pageInfo: PageInfo;
};
export type TimeUpdate = {
__typename?: 'TimeUpdate';
/** RFC3339Nano time of new block time */
timestamp: Scalars['Timestamp'];
};
/** Returns total transfer fee discount available */
export type TotalTransferFeeDiscount = {
__typename?: 'TotalTransferFeeDiscount';
/** Total per party per asset discount available. */
totalDiscount: Scalars['String'];
};
/** A tradable instrument is a combination of an instrument and a risk model */
export type TradableInstrument = {
__typename?: 'TradableInstrument';
@@ -6089,6 +6546,8 @@ export type Transfer = {
from: Scalars['String'];
/** The account type from which funds have been sent */
fromAccountType: AccountType;
/** An optional game ID to filter for transfers that are made for rewarding participation in games */
gameId?: Maybe<Scalars['ID']>;
/** ID of this transfer */
id: Scalars['ID'];
/** The type of transfer being made, i.e. a one-off or recurring transfer */
@@ -6172,6 +6631,14 @@ export type TransferResponses = {
responses?: Maybe<Array<TransferResponse>>;
};
/** Defines the types of a dispatch strategy's scope the API can filter on. */
export enum TransferScope {
/** Matches transfers that have dispatch strategy scope of individual set. */
SCOPE_INDIVIDUAL = 'SCOPE_INDIVIDUAL',
/** Matches transfers that have dispatch strategy scope of team set. */
SCOPE_TEAM = 'SCOPE_TEAM'
}
/** All the states a transfer can transition between */
export enum TransferStatus {
/** Indication of a transfer cancelled by the user */
@@ -6211,6 +6678,8 @@ export enum TransferType {
TRANSFER_TYPE_INFRASTRUCTURE_FEE_DISTRIBUTE = 'TRANSFER_TYPE_INFRASTRUCTURE_FEE_DISTRIBUTE',
/** Infrastructure fee paid from general account */
TRANSFER_TYPE_INFRASTRUCTURE_FEE_PAY = 'TRANSFER_TYPE_INFRASTRUCTURE_FEE_PAY',
/** Funds moved from order margin account to margin account. */
TRANSFER_TYPE_ISOLATED_MARGIN_LOW = 'TRANSFER_TYPE_ISOLATED_MARGIN_LOW',
/** Allocates liquidity fee earnings to each liquidity provider's network controlled liquidity fee account. */
TRANSFER_TYPE_LIQUIDITY_FEE_ALLOCATE = 'TRANSFER_TYPE_LIQUIDITY_FEE_ALLOCATE',
/** Liquidity fee received into general account */
@@ -6237,6 +6706,10 @@ export enum TransferType {
TRANSFER_TYPE_MTM_LOSS = 'TRANSFER_TYPE_MTM_LOSS',
/** Funds added to margin account after mark to market gain */
TRANSFER_TYPE_MTM_WIN = 'TRANSFER_TYPE_MTM_WIN',
/** Funds released from order margin account to general. */
TRANSFER_TYPE_ORDER_MARGIN_HIGH = 'TRANSFER_TYPE_ORDER_MARGIN_HIGH',
/** Funds moved from general account to order margin account. */
TRANSFER_TYPE_ORDER_MARGIN_LOW = 'TRANSFER_TYPE_ORDER_MARGIN_LOW',
/** Funds deducted from margin account after a perpetuals funding loss. */
TRANSFER_TYPE_PERPETUALS_FUNDING_LOSS = 'TRANSFER_TYPE_PERPETUALS_FUNDING_LOSS',
/** Funds added to margin account after a perpetuals funding gain. */
@@ -6310,6 +6783,7 @@ export type UpdateFutureProduct = {
export type UpdateInstrumentConfiguration = {
__typename?: 'UpdateInstrumentConfiguration';
code: Scalars['String'];
name: Scalars['String'];
product: UpdateProductConfiguration;
};
@@ -6329,15 +6803,24 @@ export type UpdateMarketConfiguration = {
instrument: UpdateInstrumentConfiguration;
/** Linear slippage factor is used to cap the slippage component of maintenance margin - it is applied to the slippage volume. */
linearSlippageFactor: Scalars['String'];
/** Liquidation strategy for the market */
liquidationStrategy?: Maybe<LiquidationStrategy>;
/** Specifies how the liquidity fee for the market will be calculated */
liquidityFeeSettings?: Maybe<LiquidityFeeSettings>;
/** Liquidity monitoring parameters. */
liquidityMonitoringParameters: LiquidityMonitoringParameters;
/** Liquidity SLA Parameters. */
liquiditySLAParameters?: Maybe<LiquiditySLAParameters>;
/** Configuration for mark price calculation for the market */
markPriceConfiguration?: Maybe<CompositePriceConfiguration>;
/** Optional futures market metadata, tags. */
metadata?: Maybe<Array<Maybe<Scalars['String']>>>;
/** Price monitoring parameters. */
priceMonitoringParameters: PriceMonitoringParameters;
/** Quadratic slippage factor is used to cap the slippage component of maintenance margin - it is applied to the square of the slippage volume. */
/**
* Quadratic slippage factor is used to cap the slippage component of maintenance margin - it is applied to the square of the slippage volume.
* @deprecated This field will be removed in a future release
*/
quadraticSlippageFactor: Scalars['String'];
/** Updated futures market risk model parameters. */
riskParameters: UpdateMarketRiskParameters;
@@ -6383,6 +6866,12 @@ export type UpdatePerpetualProduct = {
dataSourceSpecForSettlementData: DataSourceDefinition;
/** Data source specification describing the data source for settlement schedule */
dataSourceSpecForSettlementSchedule: DataSourceDefinition;
/** Lower bound for the funding-rate such that the funding-rate will never be lower than this value */
fundingRateLowerBound: Scalars['String'];
/** Factor applied to funding-rates. This scales the impact that spot price deviations have on funding payments. */
fundingRateScalingFactor: Scalars['String'];
/** Upper bound for the funding-rate such that the funding-rate will never be higher than this value */
fundingRateUpperBound: Scalars['String'];
/** Continuously compounded interest rate used in funding rate calculation, in the range [-1, 1] */
interestRate: Scalars['String'];
/** Controls how much the upcoming funding payment liability contributes to party's margin, in the range [0, 1] */
@@ -6420,6 +6909,8 @@ export type UpdateSpotMarket = {
export type UpdateSpotMarketConfiguration = {
__typename?: 'UpdateSpotMarketConfiguration';
/** Specifies how the liquidity fee for the market will be calculated */
liquidityFeeSettings?: Maybe<LiquidityFeeSettings>;
/** Specifies the liquidity provision SLA parameters */
liquiditySLAParams: LiquiditySLAParameters;
/** Optional spot market metadata tags */
@@ -8,13 +8,15 @@ export type VegaIconSize = 8 | 10 | 12 | 13 | 14 | 16 | 18 | 20 | 24 | 28 | 32;
export interface VegaIconProps {
name: VegaIconNames;
size?: VegaIconSize;
className?: string;
}
export const VegaIcon = ({ size = 16, name }: VegaIconProps) => {
export const VegaIcon = ({ size = 16, name, className }: VegaIconProps) => {
const effectiveClassName = classNames(
'inline-block',
'align-text-bottom',
'fill-current stroke-none'
'fill-current stroke-none',
className
);
const Element = VegaIconNameMap[name];
return (
+28
View File
@@ -12,6 +12,7 @@ import {
quantumDecimalPlaces,
toDecimal,
toNumberParts,
formatNumberRounded,
} from './number';
describe('number utils', () => {
@@ -246,3 +247,30 @@ describe('getUnlimitedThreshold', () => {
}
);
});
describe('formatNumberRounded', () => {
it('rounds number with symbol', () => {
expect(formatNumberRounded(new BigNumber(1))).toBe('1');
expect(formatNumberRounded(new BigNumber(1_000))).toBe('1,000');
expect(formatNumberRounded(new BigNumber(1_000_000))).toBe('1m');
expect(formatNumberRounded(new BigNumber(1_000_000_000))).toBe('1b');
expect(formatNumberRounded(new BigNumber(1_000_000_000_000))).toBe('1t');
});
it('respects the limit parameter', () => {
expect(formatNumberRounded(new BigNumber(1_000), '1e3')).toBe('1k');
expect(formatNumberRounded(new BigNumber(1_000_000), '1e9')).toBe(
'1,000,000'
);
expect(formatNumberRounded(new BigNumber(9_999_999), '1e9')).toBe(
'9,999,999'
);
expect(formatNumberRounded(new BigNumber(1_000_000_000), '1e9')).toBe('1b');
expect(formatNumberRounded(new BigNumber(1_000_000_000), '1e12')).toBe(
'1,000,000,000'
);
expect(formatNumberRounded(new BigNumber(1_000_000_000_000), '1e9')).toBe(
'1t'
);
});
});
+21 -4
View File
@@ -184,7 +184,10 @@ export const isNumeric = (
* Format a number greater than 1 million with m for million, b for billion
* and t for trillion
*/
export const formatNumberRounded = (num: BigNumber) => {
export const formatNumberRounded = (
num: BigNumber,
limit: '1e12' | '1e9' | '1e6' | '1e3' = '1e6'
) => {
let value = '';
const format = (divisor: string) => {
@@ -194,15 +197,29 @@ export const formatNumberRounded = (num: BigNumber) => {
if (num.isGreaterThan(new BigNumber('1e14'))) {
value = '>100t';
} else if (num.isGreaterThanOrEqualTo(new BigNumber('1e12'))) {
} else if (
num.isGreaterThanOrEqualTo(limit) &&
num.isGreaterThanOrEqualTo(new BigNumber('1e12'))
) {
// Trillion
value = `${format('1e12')}t`;
} else if (num.isGreaterThanOrEqualTo(new BigNumber('1e9'))) {
} else if (
num.isGreaterThanOrEqualTo(limit) &&
num.isGreaterThanOrEqualTo(new BigNumber('1e9'))
) {
// Billion
value = `${format('1e9')}b`;
} else if (num.isGreaterThanOrEqualTo(new BigNumber('1e6'))) {
} else if (
num.isGreaterThanOrEqualTo(limit) &&
num.isGreaterThanOrEqualTo(new BigNumber('1e6'))
) {
// Million
value = `${format('1e6')}m`;
} else if (
num.isGreaterThanOrEqualTo(limit) &&
num.isGreaterThanOrEqualTo(new BigNumber('1e3'))
) {
value = `${format('1e3')}k`;
} else {
value = formatNumber(num);
}