Compare commits

..

2 Commits

291 changed files with 3733 additions and 8403 deletions

View File

@ -10,7 +10,7 @@ on:
inputs:
console-test-branch:
type: choice
description: 'main: v0.74.10, develop: v0.75.5'
description: 'main: v0.73.13, develop: v0.74.0'
options:
- main
- develop
@ -57,14 +57,15 @@ jobs:
#----------------------------------------------
- name: Build trading app
run: |
ENV_NAME="${{ needs.console-test-branch.outputs.console-branch == 'main' && 'mainnet' || 'stagnet1' }}"
yarn env-cmd -f ./apps/trading/.env.$ENV_NAME yarn nx export trading
yarn env-cmd -f ./apps/trading/.env.stagnet1 yarn nx export trading
DIST_LOCATION=dist/apps/trading/exported
mv $DIST_LOCATION dist-result
tree dist-result
#----------------------------------------------
# export trading app docker image
#----------------------------------------------
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
@ -77,7 +78,7 @@ jobs:
load: true
build-args: |
APP=trading
ENV_NAME=${{ needs.console-test-branch.outputs.console-branch == 'main' && 'mainnet' || 'stagnet1' }}
ENV_NAME=stagnet1
tags: ci/trading:local
outputs: type=docker,dest=/tmp/console-image.tar
@ -181,22 +182,12 @@ jobs:
virtualenvs-create: true
virtualenvs-in-project: true
virtualenvs-path: .venv
#----------------------------------------------
# Set up pyproject.toml based on branch
#----------------------------------------------
- name: Create pyproject.toml based on branch
run: |
if [ "${{ needs.console-test-branch.outputs.console-branch }}" = "main" ]; then
mv pyproject.main.toml pyproject.toml
elif [ "${{ needs.console-test-branch.outputs.console-branch }}" = "develop" ]; then
mv pyproject.develop.toml pyproject.toml
fi
working-directory: apps/trading/e2e
#----------------------------------------------
# install python dependencies
#----------------------------------------------
- name: Install dependencies
run: poetry lock && poetry install --no-interaction --no-root
run: poetry install --no-interaction --no-root
working-directory: apps/trading/e2e
#----------------------------------------------
# install vega binaries

1
.gitignore vendored
View File

@ -58,6 +58,5 @@ __pycache__/
apps/trading/e2e/logs/
apps/trading/e2e/.pytest_cache/
apps/trading/e2e/traces/
apps/trading/e2e/pyproject.toml
.nx/

View File

@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_ENV=VALIDATORS_TESTNET
NX_VEGA_ENV=VALIDATOR_TESTNET
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.toml
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
NX_VEGA_REST=https://api-validators-testnet.vega.rocks/

View File

@ -8,14 +8,12 @@ import EpochMissingOverview from './epoch-missing';
import { Icon, Tooltip } from '@vegaprotocol/ui-toolkit';
import type { IconProps } from '@vegaprotocol/ui-toolkit';
import isPast from 'date-fns/isPast';
import { EpochSymbol } from '../links/block-link/block-link';
const borderClass =
'border-solid border-2 border-vega-dark-200 border-collapse';
export type EpochOverviewProps = {
id?: string;
icon?: boolean;
};
/**
@ -26,7 +24,7 @@ export type EpochOverviewProps = {
*
* The details are hidden in a tooltip, behind the epoch number
*/
const EpochOverview = ({ id, icon = true }: EpochOverviewProps) => {
const EpochOverview = ({ id }: EpochOverviewProps) => {
const { data, error, loading } = useExplorerEpochQuery({
variables: { id: id || '' },
});
@ -40,12 +38,7 @@ const EpochOverview = ({ id, icon = true }: EpochOverviewProps) => {
}
if (!ti || loading || error) {
return (
<span>
<EpochSymbol />
{id}
</span>
);
return <span>{id}</span>;
}
const description = (
@ -97,11 +90,7 @@ const EpochOverview = ({ id, icon = true }: EpochOverviewProps) => {
return (
<Tooltip description={description}>
<p>
{icon ? (
<IconForEpoch start={ti.start} end={ti.end} />
) : (
<EpochSymbol />
)}
<IconForEpoch start={ti.start} end={ti.end} />
{id}
</p>
</Tooltip>

View File

@ -1,10 +0,0 @@
query ExplorerEpochForBlock($block: String!) {
epoch(block: $block) {
id
timestamps {
start
end
lastBlock
}
}
}

View File

@ -1,53 +0,0 @@
import * as Types from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ExplorerEpochForBlockQueryVariables = Types.Exact<{
block: Types.Scalars['String'];
}>;
export type ExplorerEpochForBlockQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, lastBlock?: string | null } } };
export const ExplorerEpochForBlockDocument = gql`
query ExplorerEpochForBlock($block: String!) {
epoch(block: $block) {
id
timestamps {
start
end
lastBlock
}
}
}
`;
/**
* __useExplorerEpochForBlockQuery__
*
* To run a query within a React component, call `useExplorerEpochForBlockQuery` and pass it any options that fit your needs.
* When your component renders, `useExplorerEpochForBlockQuery` 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 } = useExplorerEpochForBlockQuery({
* variables: {
* block: // value for 'block'
* },
* });
*/
export function useExplorerEpochForBlockQuery(baseOptions: Apollo.QueryHookOptions<ExplorerEpochForBlockQuery, ExplorerEpochForBlockQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ExplorerEpochForBlockQuery, ExplorerEpochForBlockQueryVariables>(ExplorerEpochForBlockDocument, options);
}
export function useExplorerEpochForBlockLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerEpochForBlockQuery, ExplorerEpochForBlockQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ExplorerEpochForBlockQuery, ExplorerEpochForBlockQueryVariables>(ExplorerEpochForBlockDocument, options);
}
export type ExplorerEpochForBlockQueryHookResult = ReturnType<typeof useExplorerEpochForBlockQuery>;
export type ExplorerEpochForBlockLazyQueryHookResult = ReturnType<typeof useExplorerEpochForBlockLazyQuery>;
export type ExplorerEpochForBlockQueryResult = Apollo.QueryResult<ExplorerEpochForBlockQuery, ExplorerEpochForBlockQueryVariables>;

View File

@ -4,56 +4,17 @@ import { Link } from 'react-router-dom';
import type { ComponentProps } from 'react';
import Hash from '../hash';
import { useExplorerEpochForBlockQuery } from './__generated__/EpochByBlock';
import { t } from '@vegaprotocol/i18n';
export type BlockLinkProps = Partial<ComponentProps<typeof Link>> & {
height: string;
showEpoch?: boolean;
};
const BlockLink = ({ height, showEpoch = false, ...props }: BlockLinkProps) => {
const BlockLink = ({ height, ...props }: BlockLinkProps) => {
return (
<>
<Link className="underline" {...props} to={`/${Routes.BLOCKS}/${height}`}>
<Hash text={height} />
</Link>
{showEpoch && <EpochForBlock block={height} />}
</>
<Link className="underline" {...props} to={`/${Routes.BLOCKS}/${height}`}>
<Hash text={height} />
</Link>
);
};
export function EpochForBlock(props: { block: string }) {
const { error, data, loading } = useExplorerEpochForBlockQuery({
errorPolicy: 'ignore',
variables: { block: props.block },
});
// NOTE: 0.73.x & <0.74.2 can error showing epoch, so for now we hide loading
// or error states and only display if we get usable data
if (error || loading || !data) {
return null;
}
return (
<span className="ml-2" title={t('Epoch')}>
<EpochSymbol />
{data.epoch.id}
</span>
);
}
export const EPOCH_SYMBOL = 'ⓔ';
export function EpochSymbol() {
return (
<em
title={t('Epoch')}
className="mr-1 cursor-default text-xl leading-none align-text-bottom not-italic"
>
{EPOCH_SYMBOL}
</em>
);
}
export default BlockLink;

View File

@ -1,8 +1,5 @@
import type { ChainIdMapping } from '@vegaprotocol/environment';
import {
SUPPORTED_CHAIN_IDS,
SUPPORTED_CHAIN_LABELS,
} from '@vegaprotocol/environment';
import type { ChainIdMapping } from './external-chain';
import { SUPPORTED_CHAIN_IDS, SUPPORTED_CHAIN_LABELS } from './external-chain';
export const SUPPORTED_CHAIN_ICON_URLS: ChainIdMapping = {
'1': '/assets/chain-eth-logo.svg',

View File

@ -10,7 +10,7 @@ export const SUPPORTED_CHAIN_LABELS: ChainIdMapping = {
'11155111': 'Sepolia',
};
export function getExternalExplorerLink(chainId: string) {
export function getExternalExplorerLink(chainId: string, type: string) {
if (SUPPORTED_CHAIN_IDS.includes(chainId)) {
switch (chainId) {
case '1':

View File

@ -1,5 +1,5 @@
import Hash from '../hash';
import { getExternalExplorerLink } from '@vegaprotocol/environment';
import { getExternalExplorerLink } from './external-chain';
import { ExternalChainIcon } from './external-chain-icon';
export enum EthExplorerLinkTypes {
@ -23,7 +23,7 @@ export const ExternalExplorerLink = ({
code = false,
...props
}: ExternalExplorerLinkProps) => {
const link = `${getExternalExplorerLink(chain)}/${type}/${id}${
const link = `${getExternalExplorerLink(chain, type)}/${type}/${id}${
code ? '#code' : ''
}`;
return (

View File

@ -1,16 +0,0 @@
import { render, screen } from '@testing-library/react';
import GovernanceLink from './governance-link';
describe('GovernanceLink', () => {
it('renders the link with the correct text', () => {
render(<GovernanceLink text="Governance internet website" />);
const linkElement = screen.getByText('Governance internet website');
expect(linkElement).toBeInTheDocument();
});
it('renders the link with the correct href and sensible default text', () => {
render(<GovernanceLink />);
const linkElement = screen.getByText('Governance');
expect(linkElement).toBeInTheDocument();
});
});

View File

@ -1,18 +0,0 @@
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import { ENV } from '../../../config/env';
import { t } from '@vegaprotocol/i18n';
export type GovernanceLinkProps = {
text?: string;
};
/**
* Just a link to the governance page, with optional text
*/
const GovernanceLink = ({ text = t('Governance') }: GovernanceLinkProps) => {
const base = ENV.dataSources.governanceUrl;
return <ExternalLink href={base}>{text}</ExternalLink>;
};
export default GovernanceLink;

View File

@ -6,7 +6,6 @@ import {
LiquiditySLAParametersInfoPanel,
MarginScalingFactorsPanel,
PriceMonitoringBoundsInfoPanel,
PriceMonitoringSettingsInfoPanel,
SuccessionLineInfoPanel,
getDataSourceSpecForSettlementData,
getDataSourceSpecForTradingTermination,
@ -22,6 +21,7 @@ import {
RiskModelInfoPanel,
SettlementAssetInfoPanel,
} from '@vegaprotocol/markets';
import { MarketInfoTable } from '@vegaprotocol/markets';
import type { DataSourceFragment } from '@vegaprotocol/markets';
import isEqual from 'lodash/isEqual';
@ -74,14 +74,27 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
<MarginScalingFactorsPanel market={market} />
<h2 className={headerClassName}>{t('Risk factors')}</h2>
<RiskFactorsInfoPanel market={market} />
<h2 className={headerClassName}>{t('Price monitoring bounds')}</h2>
<div className="mt-3">
<PriceMonitoringBoundsInfoPanel market={market} />
</div>
<h2 className={headerClassName}>{t('Price monitoring settings')}</h2>
<div className="mt-3">
<PriceMonitoringSettingsInfoPanel market={market} />
</div>
{(market.data?.priceMonitoringBounds || []).map((trigger, i) => (
<>
<h2 className={headerClassName}>
{t('Price monitoring bounds %s', [(i + 1).toString()])}
</h2>
<PriceMonitoringBoundsInfoPanel
market={market}
triggerIndex={i + 1}
/>
</>
))}
{(market.priceMonitoringSettings?.parameters?.triggers || []).map(
(trigger, i) => (
<>
<h2 className={headerClassName}>
{t('Price monitoring settings %s', [(i + 1).toString()])}
</h2>
<MarketInfoTable data={trigger} key={i} />
</>
)
)}
<h2 className={headerClassName}>{t('Liquidation strategy')}</h2>
<LiquidationStrategyInfoPanel market={market} />
<h2 className={headerClassName}>{t('Liquidity monitoring')}</h2>

View File

@ -1,5 +1,5 @@
import { useMemo } from 'react';
import { getAsset, type MarketMaybeWithData } from '@vegaprotocol/markets';
import { getAsset, type MarketFieldsFragment } from '@vegaprotocol/markets';
import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import { type AgGridReact } from 'ag-grid-react';
@ -17,7 +17,7 @@ import { type RowClickedEvent } from 'ag-grid-community';
import { Link, useNavigate } from 'react-router-dom';
type MarketsTableProps = {
data: MarketMaybeWithData[] | null;
data: MarketFieldsFragment[] | null;
};
export const MarketsTable = ({ data }: MarketsTableProps) => {
const openAssetDetailsDialog = useAssetDetailsDialogStore(
@ -56,10 +56,10 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
headerName: t('Status'),
field: 'state',
hide: window.innerWidth <= BREAKPOINT_MD,
valueGetter: ({ data }: VegaValueGetterParams<MarketMaybeWithData>) => {
return data?.data?.marketState
? MarketStateMapping[data?.data.marketState]
: '-';
valueGetter: ({
data,
}: VegaValueGetterParams<MarketFieldsFragment>) => {
return data?.state ? MarketStateMapping[data?.state] : '-';
},
},
{
@ -70,7 +70,7 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
cellRenderer: ({
data,
}: VegaICellRendererParams<
MarketMaybeWithData,
MarketFieldsFragment,
'tradableInstrument.instrument.product.settlementAsset.symbol'
>) => {
const value = data && getAsset(data);
@ -99,7 +99,7 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
field: 'id',
cellRenderer: ({
value,
}: VegaICellRendererParams<MarketMaybeWithData, 'id'>) =>
}: VegaICellRendererParams<MarketFieldsFragment, 'id'>) =>
value ? (
<Link className="underline" to={value}>
{t('View details')}
@ -116,7 +116,7 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
<AgGrid
ref={gridRef}
rowData={data}
getRowId={({ data }: { data: MarketMaybeWithData }) => data.id}
getRowId={({ data }: { data: MarketFieldsFragment }) => data.id}
overlayNoRowsTemplate={t('This chain has no markets')}
domLayout="autoHeight"
defaultColDef={{

View File

@ -1,159 +0,0 @@
import compact from 'lodash/compact';
import { MarketLink } from '../links';
import { type MarketState, MarketStateMapping } from '@vegaprotocol/types';
import OracleLink from '../links/oracle-link/oracle-link';
import type {
ExplorerOracleForMarketQuery,
ExplorerOracleFormMarketsQuery,
} from '../../routes/oracles/__generated__/OraclesForMarkets';
import { useState } from 'react';
export type OraclesTableProps = {
data?: ExplorerOracleFormMarketsQuery | ExplorerOracleForMarketQuery;
};
const cellSpacing = 'px-3';
export function OraclesTable({ data }: OraclesTableProps) {
const [hoveredOracle, setHoveredOracle] = useState('');
return (
<table className="text-left">
<thead>
<tr>
<th className={cellSpacing}>Market</th>
<th className={cellSpacing}>Type</th>
<th className={cellSpacing}>State</th>
<th className={cellSpacing}>Settlement</th>
<th className={cellSpacing}>Termination</th>
</tr>
</thead>
<tbody>
{data?.marketsConnection?.edges
? data.marketsConnection.edges.map((o) => {
let hasSeenOracleReports = false;
let settlementOracle = '-';
let settlementOracleStatus = '-';
let terminationOracle = '-';
let terminationOracleStatus = '-';
const id = o?.node.id;
if (!id) {
return null;
}
if (
o.node.tradableInstrument.instrument.product.__typename ===
'Future'
) {
settlementOracle =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForSettlementData.id;
terminationOracle =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForTradingTermination.id;
settlementOracleStatus =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForSettlementData.status;
terminationOracleStatus =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForTradingTermination.status;
} else if (
o.node.tradableInstrument.instrument.product.__typename ===
'Perpetual'
) {
settlementOracle =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForSettlementData.id;
terminationOracle =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForSettlementSchedule.id;
settlementOracleStatus =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForSettlementData.status;
terminationOracleStatus =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForSettlementSchedule.status;
}
const oracleInformationUnfiltered =
data?.oracleSpecsConnection?.edges?.map((e) =>
e && e.node ? e.node : undefined
) || [];
const oracleInformation = compact(oracleInformationUnfiltered)
.filter(
(o) =>
o.dataConnection.edges &&
o.dataConnection.edges.length > 0 &&
(o.dataSourceSpec.spec.id === settlementOracle ||
o.dataSourceSpec.spec.id === terminationOracle)
)
.at(0);
if (oracleInformation) {
hasSeenOracleReports = true;
}
const oracleList = `${settlementOracle} ${terminationOracle}`;
return (
<tr
id={id}
key={id}
className={
hoveredOracle.length > 0 &&
oracleList.indexOf(hoveredOracle) > -1
? 'bg-gray-100 dark:bg-gray-800'
: ''
}
data-testid="oracle-details"
data-oracles={oracleList}
>
<td className={cellSpacing}>
<MarketLink id={id} />
</td>
<td className={cellSpacing}>
{o.node.tradableInstrument.instrument.product.__typename}
</td>
<td className={cellSpacing}>
{MarketStateMapping[o.node.state as MarketState]}
</td>
<td
className={
hoveredOracle.length > 0 &&
hoveredOracle === settlementOracle
? `indent-1 ${cellSpacing}`
: cellSpacing
}
>
<OracleLink
id={settlementOracle}
status={settlementOracleStatus}
hasSeenOracleReports={hasSeenOracleReports}
onMouseOver={() => setHoveredOracle(settlementOracle)}
onMouseOut={() => setHoveredOracle('')}
/>
</td>
<td
className={
hoveredOracle.length > 0 &&
hoveredOracle === terminationOracle
? `indent-1 ${cellSpacing}`
: cellSpacing
}
>
<OracleLink
id={terminationOracle}
status={terminationOracleStatus}
hasSeenOracleReports={hasSeenOracleReports}
onMouseOver={() => setHoveredOracle(terminationOracle)}
onMouseOut={() => setHoveredOracle('')}
/>
</td>
</tr>
);
})
: null}
</tbody>
</table>
);
}

View File

@ -33,10 +33,10 @@ const SizeInAsset = ({
}
return (
<span>
<p>
<span>{label}</span>&nbsp;
<AssetLink assetId={assetId} showAssetSymbol={true} asDialog={true} />
</span>
</p>
);
};

View File

@ -4,7 +4,7 @@ import {
ExternalExplorerLink,
EthExplorerLinkTypes,
} from '../../../links/external-explorer-link/external-explorer-link';
import { getExternalChainLabel } from '@vegaprotocol/environment';
import { getExternalChainLabel } from '../../../links/external-explorer-link/external-chain';
import type { components } from '../../../../../types/explorer';
import { defaultAbiCoder, base64 } from 'ethers/lib/utils';
import { BigNumber } from 'ethers';

View File

@ -10,8 +10,6 @@ import { ChainResponseCode } from '../chain-response-code/chain-reponse.code';
import { TxDataView } from '../../tx-data-view';
import Hash from '../../../links/hash';
import { Signature } from '../../../signature/signature';
import { useExplorerEpochForBlockQuery } from '../../../links/block-link/__generated__/EpochByBlock';
import EpochOverview from '../../../epoch-overview/epoch';
interface TxDetailsSharedProps {
txData: BlockExplorerTransactionResult | undefined;
@ -46,11 +44,6 @@ export const TxDetailsShared = ({
blockData,
hideTypeRow = false,
}: TxDetailsSharedProps) => {
const { data } = useExplorerEpochForBlockQuery({
errorPolicy: 'ignore',
variables: { block: txData?.block?.toString() || '' },
});
if (!txData) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
@ -81,7 +74,7 @@ export const TxDetailsShared = ({
<TableRow modifier="bordered">
<TableCell {...sharedHeaderProps}>{t('Block')}</TableCell>
<TableCell>
<BlockLink height={height} showEpoch={false} />
<BlockLink height={height} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
@ -90,7 +83,6 @@ export const TxDetailsShared = ({
<Signature signature={txData.signature} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell {...sharedHeaderProps}>{t('Time')}</TableCell>
<TableCell>
@ -108,14 +100,6 @@ export const TxDetailsShared = ({
)}
</TableCell>
</TableRow>
{data && data.epoch && (
<TableRow modifier="bordered">
<TableCell scope="row">{t('Epoch')}</TableCell>
<TableCell modifier="bordered">
<EpochOverview id={data.epoch.id} icon={false} />
</TableCell>
</TableRow>
)}
<TableRow modifier="bordered">
<TableCell {...sharedHeaderProps}>{t('Response code')}</TableCell>
<TableCell>

View File

@ -1,9 +1,5 @@
query ExplorerTransferStatus($id: ID!) {
transfer(id: $id) {
fees {
amount
epoch
}
transfer {
reference
timestamp

View File

@ -8,16 +8,12 @@ export type ExplorerTransferStatusQueryVariables = Types.Exact<{
}>;
export type ExplorerTransferStatusQuery = { __typename?: 'Query', transfer?: { __typename?: 'TransferNode', fees?: Array<{ __typename?: 'TransferFee', amount: string, epoch: number } | null> | null, transfer: { __typename?: 'Transfer', reference?: string | null, timestamp: any, status: Types.TransferStatus, reason?: string | null, fromAccountType: Types.AccountType, from: string, to: string, toAccountType: Types.AccountType, amount: string, asset?: { __typename?: 'Asset', id: string } | null } } | null };
export type ExplorerTransferStatusQuery = { __typename?: 'Query', transfer?: { __typename?: 'TransferNode', transfer: { __typename?: 'Transfer', reference?: string | null, timestamp: any, status: Types.TransferStatus, reason?: string | null, fromAccountType: Types.AccountType, from: string, to: string, toAccountType: Types.AccountType, amount: string, asset?: { __typename?: 'Asset', id: string } | null } } | null };
export const ExplorerTransferStatusDocument = gql`
query ExplorerTransferStatus($id: ID!) {
transfer(id: $id) {
fees {
amount
epoch
}
transfer {
reference
timestamp

View File

@ -44,14 +44,8 @@ const AccountType: Record<AccountTypes, string> = {
ACCOUNT_TYPE_ORDER_MARGIN: 'Order Margin',
};
export type TransferFee = {
amount?: string;
epoch?: number;
};
interface TransferParticipantsProps {
transfer: Transfer;
fees?: TransferFee[] | null;
from: string;
}
@ -66,7 +60,6 @@ interface TransferParticipantsProps {
export function TransferParticipants({
transfer,
from,
fees,
}: TransferParticipantsProps) {
// This mapping is required as the global account types require a type to be set, while
// the underlying protobufs allow for every field to be undefined.
@ -111,9 +104,6 @@ export function TransferParticipants({
{transfer.asset ? (
<SizeInAsset assetId={transfer.asset} size={transfer.amount} />
) : null}
{transfer.asset && fees && (
<TransferFees assetId={transfer.asset} fees={fees} />
)}
</div>
{/* Empty divs for the top arrow and the bottom arrow of the transfer inset */}
@ -135,6 +125,10 @@ export function TransferParticipants({
<path d="M0,0L8,9l8,-9Z" />
</svg>
</div>
{/*
<div className="z-10 absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-1/2 rotate-45 w-4 h-4 dark:border-vega-dark-200 border-vega-light-200 bg-white dark:bg-black border-r border-b"></div>
<div className="z-10 absolute bottom-0 left-1/2 transform -translate-x-1/2 translate-y-1/2 rotate-45 w-4 h-4 border-vega-light-200 dark:border-vega-dark-200 bg-vega-light-200 dark:bg-vega-dark-200 border-r border-b"></div>
*/}
</div>
</div>
@ -175,38 +169,3 @@ export function TransferRecurringRecipient({
// Fallback should not happen
return null;
}
export function TransferFees({
assetId,
fees,
}: {
assetId: string;
fees: TransferFee[];
}) {
// A recurring transfer that is rejected or cancelled will have an array of fees of 0 length
if (assetId && fees && fees.length > 0) {
if (fees.length === 1) {
return (
<p className="mt-2">
Fee: <SizeInAsset assetId={assetId} size={fees[0].amount} />
</p>
);
} else {
return (
<details className="cursor-pointer mt-2">
<summary>{t('Fees')}</summary>
<ul>
{fees.map((fee) => (
<li className="text-nowrap leading-normal">
<SizeInAsset assetId={assetId} size={fee.amount} />{' '}
{t('in epoch')} {fee.epoch}
</li>
))}
</ul>
</details>
);
}
}
return null;
}

View File

@ -41,16 +41,9 @@ export function TransferDetails({ transfer, from, id }: TransferDetailsProps) {
? TransferStatus.STATUS_REJECTED
: data?.transfer?.transfer.status;
const fees = data?.transfer?.fees?.map((fee) => {
return {
amount: fee?.amount ? fee.amount : '0',
epoch: fee?.epoch ? fee.epoch : 0,
};
});
return (
<div className="flex flex-wrap">
<TransferParticipants from={from} transfer={transfer} fees={fees} />
<TransferParticipants from={from} transfer={transfer} />
{recurring ? <TransferRepeat recurring={transfer.recurring} /> : null}
<TransferStatusView status={status} error={error} loading={loading} />
{recurring && recurring.dispatchStrategy ? (

View File

@ -113,16 +113,13 @@ export const TxDetailsTransfer = ({
/**
* Gets a string description of this transfer
* @param tx A full transfer
* @param txData A full transfer
* @returns string Transfer label
*/
export function getTypeLabelForTransfer(tx: Transfer) {
if (tx.to === SPECIAL_CASE_NETWORK || tx.to === SPECIAL_CASE_NETWORK_ID) {
if (tx.toAccountType === 'ACCOUNT_TYPE_NETWORK_TREASURY') {
return 'Treasury transfer';
}
if (tx.recurring && tx.recurring.dispatchStrategy) {
return 'Reward transfer';
return 'Reward top up transfer';
}
// Else: we don't know that it's a reward transfer, so let's not guess
} else if (tx.recurring) {

View File

@ -16,12 +16,12 @@ import { FilterLabel } from './tx-filter-label';
// All possible transaction types. Should be generated.
export type FilterOption =
| 'Amend Liquidity Provision Order'
| 'Amend LiquidityProvision Order'
| 'Amend Order'
| 'Apply Referral Code'
| 'Batch Market Instructions'
| 'Batch Proposal'
| 'Cancel Liquidity Provision Order'
| 'Cancel LiquidityProvision Order'
| 'Cancel Order'
| 'Cancel Transfer Funds'
| 'Chain Event'
@ -53,10 +53,10 @@ export type FilterOption =
export const filterOptions: Record<string, FilterOption[]> = {
'Market Instructions': [
'Amend Liquidity Provision Order',
'Amend LiquidityProvision Order',
'Amend Order',
'Batch Market Instructions',
'Cancel Liquidity Provision Order',
'Cancel LiquidityProvision Order',
'Cancel Order',
'Liquidity Provision Order',
'Stop Orders Submission',

View File

@ -2,7 +2,6 @@ import { t } from '@vegaprotocol/i18n';
import type { components } from '../../../types/explorer';
import { VoteIcon } from '../vote-icon/vote-icon';
import { ExternalChainIcon } from '../links/external-explorer-link/external-chain-icon';
import { getTypeLabelForTransfer } from './details/tx-transfer';
interface TxOrderTypeProps {
orderType: string;
@ -96,7 +95,7 @@ export function getLabelForOrderType(
/**
* Given a proposal, will return a specific label
* @param proposal
* @param chainEvent
* @returns
*/
export function getLabelForProposal(
@ -143,36 +142,6 @@ export function getLabelForProposal(
}
}
type label = {
type: string;
colours: string;
};
export function getLabelForTransfer(
transfer: components['schemas']['commandsv1Transfer']
): label {
const type = getTypeLabelForTransfer(transfer);
if (transfer.toAccountType === 'ACCOUNT_TYPE_NETWORK_TREASURY') {
return {
type,
colours:
'text-vega-green dark:text-green bg-vega-dark-150 dark:bg-vega-dark-250',
};
} else if (transfer.recurring) {
return {
type,
colours:
'text-vega-yellow dark:text-yellow bg-vega-dark-150 dark:bg-vega-dark-250',
};
}
return {
type,
colours:
'text-white dark:text-white bg-vega-dark-150 dark:bg-vega-dark-250',
};
}
/**
* Given a chain event, will try to provide a more useful label
* @param chainEvent
@ -256,10 +225,9 @@ export const TxOrderType = ({ orderType, command }: TxOrderTypeProps) => {
if (type === 'Chain Event' && !!command?.chainEvent) {
type = getLabelForChainEvent(command.chainEvent);
colours = 'text-white dark-text-white bg-vega-pink dark:bg-vega-pink';
} else if (type === 'Transfer Funds' && command?.transfer) {
const res = getLabelForTransfer(command.transfer);
type = res.type;
colours = res.colours;
} else if (type === 'Validator Heartbeat') {
colours =
'text-white dark-text-white bg-vega-light-200 dark:bg-vega-dark-100';
} else if (type === 'Proposal' || type === 'Governance Proposal') {
if (command && !!command.proposalSubmission) {
type = getLabelForProposal(command.proposalSubmission);

View File

@ -21,7 +21,7 @@ describe('TX: Transfer: getLabelForTransfer', () => {
},
};
expect(getTypeLabelForTransfer(mock)).toEqual('Reward transfer');
expect(getTypeLabelForTransfer(mock)).toEqual('Reward top up transfer');
});
it('renders reward top up label if the TO party is network', () => {
@ -32,7 +32,7 @@ describe('TX: Transfer: getLabelForTransfer', () => {
},
};
expect(getTypeLabelForTransfer(mock)).toEqual('Reward transfer');
expect(getTypeLabelForTransfer(mock)).toEqual('Reward top up transfer');
});
it('renders recurring label if the tx has a recurring property', () => {
@ -81,7 +81,6 @@ describe('TxDetailsTransfer', () => {
hash: 'test',
submitter:
'e1943eea46fed576cf2be42972f3c5515ad3d0ac7ac013f56677c12a53a1b3ed',
block: '100',
command: {
nonce: '5188810881378065222',
blockHeight: '14951513',

View File

@ -16,8 +16,6 @@ import { useBlockInfo } from '@vegaprotocol/tendermint';
import { NodeLink } from '../../../components/links';
import { useDocumentTitle } from '../../../hooks/use-document-title';
import EmptyList from '../../../components/empty-list/empty-list';
import { useExplorerEpochForBlockQuery } from '../../../components/links/block-link/__generated__/EpochByBlock';
import EpochOverview from '../../../components/epoch-overview/epoch';
type Params = { block: string };
@ -28,11 +26,6 @@ const Block = () => {
state: { data: blockData, loading, error },
} = useBlockInfo(Number(block));
const { data } = useExplorerEpochForBlockQuery({
errorPolicy: 'ignore',
variables: { block: block?.toString() || '' },
});
return (
<section>
<RouteTitle data-testid="block-header">{t(`BLOCK ${block}`)}</RouteTitle>
@ -82,7 +75,6 @@ const Block = () => {
<code>{blockData.result.block.header.consensus_hash}</code>
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableHeader scope="row">Mined by</TableHeader>
<TableCell modifier="bordered">
@ -105,14 +97,6 @@ const Block = () => {
)}
</TableCell>
</TableRow>
{data && data.epoch && (
<TableRow modifier="bordered">
<TableCell scope="row">{t('Epoch')}</TableCell>
<TableCell modifier="bordered">
<EpochOverview id={data.epoch.id} icon={false} />
</TableCell>
</TableRow>
)}
<TableRow modifier="bordered">
<TableHeader scope="row">Transactions</TableHeader>
<TableCell modifier="bordered">

View File

@ -1,42 +0,0 @@
import { t } from '@vegaprotocol/i18n';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { useParams } from 'react-router-dom';
import { useScrollToLocation } from '../../hooks/scroll-to-location';
import { useDocumentTitle } from '../../hooks/use-document-title';
import { PageTitle } from '../../components/page-helpers/page-title';
import { useExplorerOracleForMarketQuery } from '../oracles/__generated__/OraclesForMarkets';
import { OraclesTable } from '../../components/oracle-table';
type Params = { marketId: string };
export const MarketOraclesPage = () => {
useScrollToLocation();
const { marketId } = useParams<Params>();
const { data, error, loading } = useExplorerOracleForMarketQuery({
errorPolicy: 'ignore',
variables: {
id: marketId || '1',
},
});
useDocumentTitle([marketId ? marketId : 'market', 'Oracles for Market']);
return (
<section className="relative">
<PageTitle
data-testid="markets-heading"
title={t('Oracles for market')}
/>
<AsyncRenderer
noDataMessage={t('This chain has no markets')}
errorMessage={t('Could not fetch market') + ' ' + marketId}
data={data}
loading={loading}
error={error}
>
<OraclesTable data={data} />
</AsyncRenderer>
</section>
);
};

View File

@ -1,6 +1,6 @@
import { useScrollToLocation } from '../../hooks/scroll-to-location';
import { useDocumentTitle } from '../../hooks/use-document-title';
import { marketsWithDataProvider } from '@vegaprotocol/markets';
import { marketsProvider } from '@vegaprotocol/markets';
import { RouteTitle } from '../../components/route-title';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
@ -12,7 +12,7 @@ export const MarketsPage = () => {
useScrollToLocation();
const { data, loading, error } = useDataProvider({
dataProvider: marketsWithDataProvider,
dataProvider: marketsProvider,
variables: undefined,
skipUpdates: true,
});

View File

@ -89,40 +89,7 @@ fragment ExplorerOracleDataSourceSpec on ExternalDataSourceSpec {
}
query ExplorerOracleFormMarkets {
marketsConnection(includeSettled: false, pagination: { first: 20 }) {
edges {
node {
...ExplorerOracleForMarketsMarket
}
}
}
oracleSpecsConnection {
edges {
node {
dataSourceSpec {
...ExplorerOracleDataSourceSpec
}
dataConnection(pagination: { first: 1 }) {
edges {
node {
externalData {
data {
data {
name
value
}
}
}
}
}
}
}
}
}
}
query ExplorerOracleForMarket($id: ID!) {
marketsConnection(id: $id) {
marketsConnection {
edges {
node {
...ExplorerOracleForMarketsMarket

View File

@ -16,13 +16,6 @@ export type ExplorerOracleFormMarketsQueryVariables = Types.Exact<{ [key: string
export type ExplorerOracleFormMarketsQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, status: Types.DataSourceSpecStatus }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, status: Types.DataSourceSpecStatus } } | { __typename?: 'Perpetual', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, status: Types.DataSourceSpecStatus }, dataSourceSpecForSettlementSchedule: { __typename?: 'DataSourceSpec', id: string, status: Types.DataSourceSpecStatus } } | { __typename?: 'Spot' } } } } }> } | null, oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } | { __typename?: 'EthCallSpec', address: string, sourceChainId: number } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null>, triggers: Array<{ __typename?: 'InternalTimeTrigger', initial?: number | null, every?: number | null } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } } | null> | null } | null };
export type ExplorerOracleForMarketQueryVariables = Types.Exact<{
id: Types.Scalars['ID'];
}>;
export type ExplorerOracleForMarketQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, state: Types.MarketState, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', product: { __typename?: 'Future', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, status: Types.DataSourceSpecStatus }, dataSourceSpecForTradingTermination: { __typename?: 'DataSourceSpec', id: string, status: Types.DataSourceSpecStatus } } | { __typename?: 'Perpetual', dataSourceSpecForSettlementData: { __typename?: 'DataSourceSpec', id: string, status: Types.DataSourceSpecStatus }, dataSourceSpecForSettlementSchedule: { __typename?: 'DataSourceSpec', id: string, status: Types.DataSourceSpecStatus } } | { __typename?: 'Spot' } } } } }> } | null, oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null } | { __typename?: 'EthCallSpec', address: string, sourceChainId: number } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } | { __typename?: 'DataSourceSpecConfigurationTimeTrigger', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null>, triggers: Array<{ __typename?: 'InternalTimeTrigger', initial?: number | null, every?: number | null } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } } | null> | null } | null };
export const ExplorerOracleFutureFragmentDoc = gql`
fragment ExplorerOracleFuture on Future {
dataSourceSpecForSettlementData {
@ -120,7 +113,7 @@ export const ExplorerOracleDataSourceSpecFragmentDoc = gql`
`;
export const ExplorerOracleFormMarketsDocument = gql`
query ExplorerOracleFormMarkets {
marketsConnection(includeSettled: false, pagination: {first: 20}) {
marketsConnection {
edges {
node {
...ExplorerOracleForMarketsMarket
@ -133,7 +126,7 @@ export const ExplorerOracleFormMarketsDocument = gql`
dataSourceSpec {
...ExplorerOracleDataSourceSpec
}
dataConnection(pagination: {first: 1}) {
dataConnection(pagination: {last: 1}) {
edges {
node {
externalData {
@ -179,67 +172,4 @@ export function useExplorerOracleFormMarketsLazyQuery(baseOptions?: Apollo.LazyQ
}
export type ExplorerOracleFormMarketsQueryHookResult = ReturnType<typeof useExplorerOracleFormMarketsQuery>;
export type ExplorerOracleFormMarketsLazyQueryHookResult = ReturnType<typeof useExplorerOracleFormMarketsLazyQuery>;
export type ExplorerOracleFormMarketsQueryResult = Apollo.QueryResult<ExplorerOracleFormMarketsQuery, ExplorerOracleFormMarketsQueryVariables>;
export const ExplorerOracleForMarketDocument = gql`
query ExplorerOracleForMarket($id: ID!) {
marketsConnection(id: $id) {
edges {
node {
...ExplorerOracleForMarketsMarket
}
}
}
oracleSpecsConnection {
edges {
node {
dataSourceSpec {
...ExplorerOracleDataSourceSpec
}
dataConnection(pagination: {last: 1}) {
edges {
node {
externalData {
data {
data {
name
value
}
}
}
}
}
}
}
}
}
}
${ExplorerOracleForMarketsMarketFragmentDoc}
${ExplorerOracleDataSourceSpecFragmentDoc}`;
/**
* __useExplorerOracleForMarketQuery__
*
* To run a query within a React component, call `useExplorerOracleForMarketQuery` and pass it any options that fit your needs.
* When your component renders, `useExplorerOracleForMarketQuery` 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 } = useExplorerOracleForMarketQuery({
* variables: {
* id: // value for 'id'
* },
* });
*/
export function useExplorerOracleForMarketQuery(baseOptions: Apollo.QueryHookOptions<ExplorerOracleForMarketQuery, ExplorerOracleForMarketQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<ExplorerOracleForMarketQuery, ExplorerOracleForMarketQueryVariables>(ExplorerOracleForMarketDocument, options);
}
export function useExplorerOracleForMarketLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerOracleForMarketQuery, ExplorerOracleForMarketQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<ExplorerOracleForMarketQuery, ExplorerOracleForMarketQueryVariables>(ExplorerOracleForMarketDocument, options);
}
export type ExplorerOracleForMarketQueryHookResult = ReturnType<typeof useExplorerOracleForMarketQuery>;
export type ExplorerOracleForMarketLazyQueryHookResult = ReturnType<typeof useExplorerOracleForMarketLazyQuery>;
export type ExplorerOracleForMarketQueryResult = Apollo.QueryResult<ExplorerOracleForMarketQuery, ExplorerOracleForMarketQueryVariables>;
export type ExplorerOracleFormMarketsQueryResult = Apollo.QueryResult<ExplorerOracleFormMarketsQuery, ExplorerOracleFormMarketsQueryVariables>;

View File

@ -4,13 +4,8 @@ import {
ExternalExplorerLink,
EthExplorerLinkTypes,
} from '../../../components/links/external-explorer-link/external-explorer-link';
import { getExternalChainLabel } from '@vegaprotocol/environment';
import { getExternalChainLabel } from '../../../components/links/external-explorer-link/external-chain';
import { t } from 'i18next';
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
import isArray from 'lodash/isArray';
import type { components } from '../../../../types/explorer';
type Normalisers = components['schemas']['vegaNormaliser'][];
interface OracleDetailsEthSourceProps {
sourceType: SourceType;
@ -39,117 +34,21 @@ export function OracleEthSource({
const chainLabel = getExternalChainLabel(chain);
const abi = prepareOracleSpecField(sourceType?.sourceType?.abi);
const args = prepareOracleSpecField(sourceType?.sourceType?.args);
const normalisers = serialiseNormalisers(sourceType.sourceType.normalisers);
return (
<TableRow modifier="bordered">
<TableHeader scope="row" className="pt-1 align-text-top">
<TableHeader scope="row">
{chainLabel} {t('Contract')}
</TableHeader>
<TableCell modifier="bordered">
<details>
<summary className="cursor-pointer">
<ExternalExplorerLink
chain={chain}
id={address}
type={EthExplorerLinkTypes.address}
code={true}
/>
<span className="mx-3">&rArr;</span>
<code>{sourceType.sourceType.method}</code>
</summary>
{args && (
<>
<h2 className={'mt-5 mb-1 text-xl'}>{t('Arguments')}</h2>
<div className="max-w-3">
<SyntaxHighlighter
data={JSON.parse(
sourceType.sourceType.args as unknown as string
)}
/>
</div>
</>
)}
{abi && (
<>
<h2 className={'mt-5 mb-1 text-xl'}>{t('ABI')}</h2>
<div className="max-w-3">
<SyntaxHighlighter data={abi} />
</div>
</>
)}
{normalisers && (
<>
<h2 className={'mt-5 mb-1 text-xl'}>{t('Normalisers')}</h2>
<div className="max-w-3 mb-3">
<SyntaxHighlighter data={normalisers} />
</div>
</>
)}
</details>
<ExternalExplorerLink
chain={chain}
id={address}
type={EthExplorerLinkTypes.address}
code={true}
/>
<span className="mx-3">&rArr;</span>
<code>{sourceType.sourceType.method}</code>
</TableCell>
</TableRow>
);
}
// Constant to define the absence of a valid string from the Oracle Spec fields
const NO_DATA = false;
/**
* The ABI and args are stored as either a (JSON escaped, probably) string
* or array of strings. Given that OracleEthSource is simply throwing the
* data in to a SyntaxHighlighter, we don't really care about the format,
* so this function will just try to parse the data and return it as a string.
*
* @param abi
* @returns
*/
export function prepareOracleSpecField(
specField?: string[] | null
): string | false {
if (!specField) {
return NO_DATA;
}
try {
if (isArray(specField)) {
return JSON.parse(specField.join(''));
} else {
return JSON.parse(specField);
}
} catch (e) {
return NO_DATA;
}
}
/**
* Similar to prepareOracleSpecField above, but processes an array of normaliser objects
* removing the __typename and returning a serialised array of normalisers for
* SyntaxHighlighter
*
* @param normalisers
* @returns
*/
export function serialiseNormalisers(
normalisers?: Normalisers | null
): Normalisers | false {
if (!normalisers) {
return NO_DATA;
}
try {
return normalisers.map((normaliser) => {
return {
name: normaliser.name,
expression: normaliser.expression,
};
});
} catch (e) {
return NO_DATA;
}
}

View File

@ -1,9 +1,38 @@
import { render } from '@testing-library/react';
import { OracleFilter } from './oracle-filter';
import type { ExplorerOracleDataSourceFragment } from '../__generated__/Oracles';
import { ConditionOperator, DataSourceSpecStatus } from '@vegaprotocol/types';
import {
ConditionOperator,
DataSourceSpecStatus,
PropertyKeyType,
} from '@vegaprotocol/types';
import type { Condition } from '@vegaprotocol/types';
type Spec =
ExplorerOracleDataSourceFragment['dataSourceSpec']['spec']['data']['sourceType'];
const mockExternalSpec: Spec = {
sourceType: {
__typename: 'DataSourceSpecConfiguration',
filters: [
{
__typename: 'Filter',
key: {
type: PropertyKeyType.TYPE_INTEGER,
name: 'testKey',
},
conditions: [
{
__typename: 'Condition',
value: 'testValue',
operator: ConditionOperator.OPERATOR_EQUALS,
},
],
},
],
},
};
function renderComponent(data: ExplorerOracleDataSourceFragment) {
return <OracleFilter data={data} />;
}
@ -21,6 +50,31 @@ describe('Oracle Filter view', () => {
expect(res.container).toBeEmptyDOMElement();
});
it('Renders filters if type is DataSourceSpecConfiguration', () => {
const res = render(
renderComponent({
dataSourceSpec: {
spec: {
id: 'irrelevant-test-data',
createdAt: 'irrelevant-test-data',
status: DataSourceSpecStatus.STATUS_ACTIVE,
data: {
sourceType: mockExternalSpec,
},
},
},
dataConnection: {
edges: [],
},
})
);
// Renders a comprehensible summary of key = value
expect(res.getByText('testKey')).toBeInTheDocument();
expect(res.getByText('=')).toBeInTheDocument();
expect(res.getByText('testValue')).toBeInTheDocument();
});
it('Renders conditions if type is DataSourceSpecConfigurationTime', () => {
const res = render(
renderComponent({
@ -82,7 +136,7 @@ describe('Oracle Filter view', () => {
})
);
// This should never happen, but for coverage we test that it does this
// This should never happen, but for coverage sake we test that it does this
const ul = res.getByRole('list');
expect(ul).toBeInTheDocument();
expect(ul).toBeEmptyDOMElement();

View File

@ -1,8 +1,5 @@
import type { ExplorerOracleDataSourceFragment } from '../__generated__/Oracles';
import {
OracleSpecInternalTimeTrigger,
TimeTrigger,
} from './oracle-spec/internal-time-trigger';
import { OracleSpecInternalTimeTrigger } from './oracle-spec/internal-time-trigger';
import { OracleSpecCondition } from './oracle-spec/condition';
import { getCharacterForOperator } from './oracle-spec/operator';
@ -14,7 +11,7 @@ interface OracleFilterProps {
* Shows the conditions that this oracle is using to filter
* data sources, as a list.
*
* Renders nothing if there is no data (which will frequently
* Renders nothing if there is no data (which will frequently)
* be the case) and if there is data, currently renders a simple
* JSON view.
*/
@ -24,7 +21,6 @@ export function OracleFilter({ data }: OracleFilterProps) {
}
const s = data.dataSourceSpec.spec.data.sourceType.sourceType;
if (s.__typename === 'DataSourceSpecConfigurationTime' && s.conditions) {
return (
<ul>
@ -45,30 +41,30 @@ export function OracleFilter({ data }: OracleFilterProps) {
s.triggers
) {
return <OracleSpecInternalTimeTrigger data={s} />;
} else if (s.__typename === 'EthCallSpec') {
} else if (
s.__typename === 'EthCallSpec' ||
s.__typename === 'DataSourceSpecConfiguration'
) {
if (s.filters !== null && s.filters && 'filters' in s) {
return (
<div>
<ul>
{s.filters.map((f) => {
const prop = <code title={f.key.type}>{f.key.name}</code>;
<ul>
{s.filters.map((f) => {
const prop = <code title={f.key.type}>{f.key.name}</code>;
if (!f.conditions || f.conditions.length === 0) {
return prop;
} else {
return f.conditions.map((c) => {
return (
<li key={`${prop}${c.value}`}>
{prop} {getCharacterForOperator(c.operator)}{' '}
<code>{c.value ? c.value : '-'}</code>
</li>
);
});
}
})}
</ul>
{s.trigger && <TimeTrigger data={s.trigger.trigger} />}
</div>
if (!f.conditions || f.conditions.length === 0) {
return prop;
} else {
return f.conditions.map((c) => {
return (
<li key={`${prop}${c.value}`}>
{prop} {getCharacterForOperator(c.operator)}{' '}
<code>{c.value ? c.value : '-'}</code>
</li>
);
});
}
})}
</ul>
);
}
}

View File

@ -1,10 +1,5 @@
import { t } from '@vegaprotocol/i18n';
import type {
DataSourceSpecConfigurationTimeTrigger,
EthTimeTrigger,
InternalTimeTrigger,
Maybe,
} from '@vegaprotocol/types';
import type { DataSourceSpecConfigurationTimeTrigger } from '@vegaprotocol/types';
import secondsToMinutes from 'date-fns/secondsToMinutes';
import fromUnixTime from 'date-fns/fromUnixTime';
@ -18,60 +13,32 @@ export function OracleSpecInternalTimeTrigger({
return (
<div>
<span>{t('Time')}</span>,&nbsp;
{data.triggers.map((tr) => (
<TimeTrigger data={tr} />
))}
{data.triggers.map((tr) => {
return (
<span>
{tr?.initial ? (
<span title={`${tr.initial}`}>
<strong>{t('starting at')}</strong>{' '}
<em className="not-italic underline decoration-dotted">
{fromUnixTime(tr.initial).toLocaleString()}
</em>
</span>
) : (
''
)}
{tr?.every ? (
<span title={`${tr.every} ${t('seconds')}`}>
, <strong>{t('every')}</strong>{' '}
<em className="not-italic underline decoration-dotted">
{secondsToMinutes(tr.every)} {t('minutes')}
</em>{' '}
</span>
) : (
''
)}
</span>
);
})}
</div>
);
}
export interface TimeTriggerProps {
data: Maybe<InternalTimeTrigger> | Maybe<EthTimeTrigger>;
}
export function TimeTrigger({ data }: TimeTriggerProps) {
const d = parseDate(data?.initial);
return (
<span key={JSON.stringify(data)}>
{data?.initial ? (
<span title={`${data.initial}`}>
<strong>{t('starting at')}</strong>{' '}
<em className="not-italic underline decoration-dotted">{d}</em>
</span>
) : (
''
)}
{data?.every ? (
<span title={`${data.every} ${t('seconds')}`}>
, <strong>{t('every')}</strong>{' '}
<em className="not-italic underline decor</em>ation-dotted">
{secondsToMinutes(data.every)} {t('minutes')}
</em>{' '}
</span>
) : (
''
)}
</span>
);
}
/**
* Dates in oracle triggers can be (or maybe were previously) Unix Time or timestamps
* depending on type. This function handles both cases and returns a nicely formatted date.
*
* @param date
* @returns string Localestring for date
*/
export function parseDate(date?: string | number): string {
if (!date) {
return 'Invalid date';
}
const d = fromUnixTime(+date).toLocaleString();
if (d === 'Invalid Date') {
return new Date(date).toLocaleString();
}
return d;
}

View File

@ -48,11 +48,6 @@ export const OracleDetails = ({
? dataSource.dataSourceSpec.spec.data.sourceType.sourceType.sourceChainId.toString()
: undefined;
const requiredConfirmations =
(sourceType.sourceType.__typename === 'EthCallSpec' &&
sourceType.sourceType.requiredConfirmations) ||
'';
return (
<div>
<TableWithTbody className="mb-2">
@ -69,23 +64,15 @@ export const OracleDetails = ({
{getStatusString(dataSource.dataSourceSpec.spec.status)}
</TableCell>
</TableRow>
<OracleMarkets id={id} />
<OracleSigners sourceType={sourceType} />
<OracleEthSource sourceType={sourceType} chain={chain} />
<OracleMarkets id={id} />
<TableRow modifier="bordered">
<TableHeader scope="row" className="pt-1 align-text-top">
{t('Filter')}
</TableHeader>
<TableHeader scope="row">{t('Filter')}</TableHeader>
<TableCell modifier="bordered">
<OracleFilter data={dataSource} />
</TableCell>
</TableRow>
{requiredConfirmations && requiredConfirmations > 0 && (
<TableRow modifier="bordered">
<TableHeader scope="row">{t('Required Confirmations')}</TableHeader>
<TableCell modifier="bordered">{requiredConfirmations}</TableCell>
</TableRow>
)}
</TableWithTbody>
{dataConnection ? <OracleData data={dataConnection} /> : null}
</div>

View File

@ -1,10 +1,17 @@
import compact from 'lodash/compact';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { RouteTitle } from '../../../components/route-title';
import { t } from '@vegaprotocol/i18n';
import { useDocumentTitle } from '../../../hooks/use-document-title';
import { useScrollToLocation } from '../../../hooks/scroll-to-location';
import { useExplorerOracleFormMarketsQuery } from '../__generated__/OraclesForMarkets';
import { OraclesTable } from '../../../components/oracle-table';
import { MarketLink } from '../../../components/links';
import { OracleLink } from '../../../components/links/oracle-link/oracle-link';
import { useState } from 'react';
import { MarketStateMapping } from '@vegaprotocol/types';
import type { MarketState } from '@vegaprotocol/types';
const cellSpacing = 'px-3';
const Oracles = () => {
const { data, loading, error } = useExplorerOracleFormMarketsQuery({
@ -14,6 +21,8 @@ const Oracles = () => {
useDocumentTitle(['Oracles']);
useScrollToLocation();
const [hoveredOracle, setHoveredOracle] = useState('');
return (
<section>
<RouteTitle data-testid="oracle-specs-heading">{t('Oracles')}</RouteTitle>
@ -29,7 +38,148 @@ const Oracles = () => {
data.oracleSpecsConnection.edges?.length === 0
}
>
<OraclesTable data={data} />
<table className="text-left">
<thead>
<tr>
<th className={cellSpacing}>Market</th>
<th className={cellSpacing}>Type</th>
<th className={cellSpacing}>State</th>
<th className={cellSpacing}>Settlement</th>
<th className={cellSpacing}>Termination</th>
</tr>
</thead>
<tbody>
{data?.marketsConnection?.edges
? data.marketsConnection.edges.map((o) => {
let hasSeenOracleReports = false;
let settlementOracle = '-';
let settlementOracleStatus = '-';
let terminationOracle = '-';
let terminationOracleStatus = '-';
const id = o?.node.id;
if (!id) {
return null;
}
if (
o.node.tradableInstrument.instrument.product.__typename ===
'Future'
) {
settlementOracle =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForSettlementData.id;
terminationOracle =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForTradingTermination.id;
settlementOracleStatus =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForSettlementData.status;
terminationOracleStatus =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForTradingTermination.status;
} else if (
o.node.tradableInstrument.instrument.product.__typename ===
'Perpetual'
) {
settlementOracle =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForSettlementData.id;
terminationOracle =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForSettlementSchedule.id;
settlementOracleStatus =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForSettlementData.status;
terminationOracleStatus =
o.node.tradableInstrument.instrument.product
.dataSourceSpecForSettlementSchedule.status;
}
const oracleInformationUnfiltered =
data?.oracleSpecsConnection?.edges?.map((e) =>
e && e.node ? e.node : undefined
) || [];
const oracleInformation = compact(oracleInformationUnfiltered)
.filter(
(o) =>
o.dataConnection.edges &&
o.dataConnection.edges.length > 0 &&
(o.dataSourceSpec.spec.id === settlementOracle ||
o.dataSourceSpec.spec.id === terminationOracle)
)
.at(0);
if (oracleInformation) {
hasSeenOracleReports = true;
}
const oracleList = `${settlementOracle} ${terminationOracle}`;
return (
<tr
id={id}
key={id}
className={
hoveredOracle.length > 0 &&
oracleList.indexOf(hoveredOracle) > -1
? 'bg-gray-100 dark:bg-gray-800'
: ''
}
data-testid="oracle-details"
data-oracles={oracleList}
>
<td className={cellSpacing}>
<MarketLink id={id} />
</td>
<td className={cellSpacing}>
{
o.node.tradableInstrument.instrument.product
.__typename
}
</td>
<td className={cellSpacing}>
{MarketStateMapping[o.node.state as MarketState]}
</td>
<td
className={
hoveredOracle.length > 0 &&
hoveredOracle === settlementOracle
? `indent-1 ${cellSpacing}`
: cellSpacing
}
>
<OracleLink
id={settlementOracle}
status={settlementOracleStatus}
hasSeenOracleReports={hasSeenOracleReports}
onMouseOver={() => setHoveredOracle(settlementOracle)}
onMouseOut={() => setHoveredOracle('')}
/>
</td>
<td
className={
hoveredOracle.length > 0 &&
hoveredOracle === terminationOracle
? `indent-1 ${cellSpacing}`
: cellSpacing
}
>
<OracleLink
id={terminationOracle}
status={terminationOracleStatus}
hasSeenOracleReports={hasSeenOracleReports}
onMouseOver={() =>
setHoveredOracle(terminationOracle)
}
onMouseOut={() => setHoveredOracle('')}
/>
</td>
</tr>
);
})
: null}
</tbody>
</table>
</AsyncRenderer>
</section>
);

View File

@ -4,7 +4,7 @@ import { useMemo, useState } from 'react';
import { useNavigate, useParams } from 'react-router-dom';
import { SubHeading } from '../../../components/sub-heading';
import { toNonHex } from '../../../components/search/detect-search';
import { getInitialFilters, useTxsData } from '../../../hooks/use-txs-data';
import { useTxsData } from '../../../hooks/use-txs-data';
import { TxsInfiniteList } from '../../../components/txs';
import { PageHeader } from '../../../components/page-header';
import { useDocumentTitle } from '../../../hooks/use-document-title';
@ -15,18 +15,16 @@ import { PartyBlockAccounts } from './components/party-block-accounts';
import { isValidPartyId } from './components/party-id-error';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { TxsListNavigation } from '../../../components/txs/tx-list-navigation';
import {
TxsFilter,
type FilterOption,
} from '../../../components/txs/tx-filter';
import type { FilterOption } from '../../../components/txs/tx-filter';
import { AllFilterOptions, TxsFilter } from '../../../components/txs/tx-filter';
import { useSearchParams } from 'react-router-dom';
type Params = { party: string };
const Party = () => {
const [params] = useSearchParams();
const [filters, setFilters] = useState(getInitialFilters(params));
const [filters, setFilters] = useState(new Set(AllFilterOptions));
const { party } = useParams<Params>();
useDocumentTitle(['Public keys', party || '-']);

View File

@ -5,8 +5,9 @@ import Home from './home';
import OraclePage from './oracles';
import Oracles from './oracles/home';
import { Oracle } from './oracles/id';
import Party from './parties';
import { Parties } from './parties/home';
import { Party } from './parties/id';
import { Party as PartySingle } from './parties/id';
import { ValidatorsPage } from './validators';
import Genesis from './genesis';
import { Block } from './blocks/id';
@ -16,7 +17,6 @@ import { TxsList } from './txs/home';
import { t } from '@vegaprotocol/i18n';
import { Routes } from './route-names';
import { NetworkParameters } from './network-parameters';
import { Outlet } from 'react-router-dom';
import type { Params, RouteObject } from 'react-router-dom';
import { Link } from 'react-router-dom';
import { MarketPage, MarketsPage } from './markets';
@ -31,7 +31,6 @@ import { Disclaimer } from './pages/disclaimer';
import { useFeatureFlags } from '@vegaprotocol/environment';
import RestrictedPage from './restricted';
import { NetworkTreasury } from './treasury';
import { MarketOraclesPage } from './markets/market-oracles-page';
export type Navigable = {
path: string;
@ -68,7 +67,7 @@ export const useRouterConfig = () => {
? [
{
path: Routes.PARTIES,
element: <Outlet />,
element: <Party />,
handle: {
name: t('Parties'),
text: t('Parties'),
@ -81,12 +80,12 @@ export const useRouterConfig = () => {
},
{
path: ':party',
element: <Outlet />,
element: <Party />,
children: [
{
index: true,
element: <Party />,
element: <PartySingle />,
handle: {
breadcrumb: (params: Params<string>) => (
<Link to={linkTo(Routes.PARTIES, params.party)}>
@ -97,7 +96,7 @@ export const useRouterConfig = () => {
},
{
path: 'assets',
element: <Outlet />,
element: <Party />,
handle: {
breadcrumb: (params: Params<string>) => (
<Link to={linkTo(Routes.PARTIES, params.party)}>
@ -200,36 +199,12 @@ export const useRouterConfig = () => {
},
{
path: ':marketId',
element: <Outlet />,
children: [
{
index: true,
element: <MarketPage />,
handle: {
breadcrumb: (params: Params<string>) => (
<MarketLink id={params.marketId as string} />
),
},
},
{
path: 'oracles',
element: <Outlet />,
handle: {
breadcrumb: (params: Params<string>) => (
<MarketLink id={params.marketId as string} />
),
},
children: [
{
index: true,
element: <MarketOraclesPage />,
handle: {
breadcrumb: (params: Params<string>) => t('Oracles'),
},
},
],
},
],
element: <MarketPage />,
handle: {
breadcrumb: (params: Params<string>) => (
<MarketLink id={params.marketId as string} />
),
},
},
],
},

View File

@ -33,10 +33,7 @@ export const NetworkAccountsTable = () => {
return (
<section className="md:flex md:flex-row flex-wrap">
{c.map((a) => (
<div
className="basis-1/2 md:basis-1/4"
key={`${a.assetId}-${a.balance}`}
>
<div className="basis-1/2 md:basis-1/4">
<div className="bg-white rounded overflow-hidden shadow-lg dark:bg-black dark:border-slate-500 dark:border">
<div className="text-center p-6 bg-gray-100 dark:bg-slate-900 border-b dark:border-slate-500">
<p className="flex justify-center">

View File

@ -16,21 +16,19 @@ import type { DeepPartial } from '@apollo/client/utilities';
describe('typeLabel', () => {
it('should return "Transfer" for "OneOffTransfer" kind', () => {
expect(typeLabel('OneOffTransfer')).toBe('Transfer - one time');
expect(typeLabel('OneOffTransfer')).toBe('Transfer');
});
it('should return "Transfer" for "RecurringTransfer" kind', () => {
expect(typeLabel('RecurringTransfer')).toBe('Transfer - repeating');
expect(typeLabel('RecurringTransfer')).toBe('Transfer');
});
it('should return "Governance" for "OneOffGovernanceTransfer" kind', () => {
expect(typeLabel('OneOffGovernanceTransfer')).toBe('Governance - one time');
expect(typeLabel('OneOffGovernanceTransfer')).toBe('Governance');
});
it('should return "Governance" for "RecurringGovernanceTransfer" kind', () => {
expect(typeLabel('RecurringGovernanceTransfer')).toBe(
'Governance - repeating'
);
expect(typeLabel('RecurringGovernanceTransfer')).toBe('Governance');
});
it('should return "Unknown" for unknown kind', () => {
@ -258,7 +256,7 @@ describe('NetworkTransfersTable', () => {
expect(screen.getByTestId('from-account').textContent).toEqual('Treasury');
expect(screen.getByTestId('to-account').textContent).toEqual('7100…97a0');
expect(screen.getByTestId('transfer-kind').textContent).toEqual(
'Governance - one time'
'Governance'
);
});
});

View File

@ -12,7 +12,6 @@ import { t } from '@vegaprotocol/i18n';
import { IconNames } from '@blueprintjs/icons';
import { useMemo } from 'react';
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
import ProposalLink from '../../../components/links/proposal-link/proposal-link';
export const colours = {
INCOMING: '!fill-vega-green-600 text-vega-green-600 mr-2',
@ -51,24 +50,14 @@ export function getToAccountTypeLabel(type?: AccountType): string {
}
}
export function isGovernanceTransfer(kind?: string): boolean {
if (kind && kind.includes('Governance')) {
return true;
}
return false;
}
export function typeLabel(kind?: string): string {
switch (kind) {
case 'OneOffTransfer':
return t('Transfer - one time');
case 'RecurringTransfer':
return t('Transfer - repeating');
return t('Transfer');
case 'OneOffGovernanceTransfer':
return t('Governance - one time');
case 'RecurringGovernanceTransfer':
return t('Governance - repeating');
return t('Governance');
default:
return t('Unknown');
}
@ -250,11 +239,6 @@ export const NetworkTransfersTable = () => {
>
{a && typeLabel(a.kind.__typename)}
</span>
{isGovernanceTransfer(a?.kind.__typename) && a?.id && (
<span className="ml-4">
<ProposalLink id={a?.id} text="View" />
</span>
)}
</td>
</tr>
);

View File

@ -4,7 +4,6 @@ import { t } from '@vegaprotocol/i18n';
import { RouteTitle } from '../../components/route-title';
import { NetworkAccountsTable } from './components/network-accounts-table';
import { NetworkTransfersTable } from './components/network-transfers-table';
import GovernanceLink from '../../components/links/governance-link/governance-link';
export type NonZeroAccount = {
assetId: string;
@ -17,33 +16,7 @@ export const NetworkTreasury = () => {
return (
<section>
<RouteTitle data-testid="block-header">{t(`Treasury`)}</RouteTitle>
<details className="w-full md:w-3/5 cursor-pointer shadow-lg p-5 dark:border-l-2 dark:border-vega-green">
<summary>{t('About the Network Treasury')}</summary>
<section className="mt-4 b-1 border-grey">
<p className="mb-2">
The network treasury can hold funds from any active settlement asset
on the network. It is funded periodically by transfers from Gobalsky
as part of the Community Adoption Fund (CAF), but in future may
receive funds from any sources.
</p>
<p className="mb-2">
Funds in the network treasury can be used by creating governance
initiated transfers via{' '}
<GovernanceLink text={t('community governance')} />. These transfers
can be initiated by anyone and be used to fund reward pools, or can
be used to fund other activities the{' '}
<abbr className="decoration-dotted" title="Community Adoption Fund">
CAF
</abbr>{' '}
is exploring.
</p>
<p>
This page shows details of the balances in the treasury, pending
transfers, and historic transfer movements to and from the treasury.
</p>
</section>
</details>
<div className="mt-6">
<div>
<NetworkAccountsTable />
</div>
<div className="mt-5">

View File

@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_ENV=VALIDATORS_TESTNET
NX_VEGA_ENV=VALIDATOR_TESTNET
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.toml
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
NX_VEGA_REST=https://api-validators-testnet.vega.rocks/

View File

@ -47,7 +47,7 @@ export const SubHeading = ({
return (
<h2
className={classNames('text-2xl font-alpha calt break-words', {
className={classNames('text-2xl font-alpha calt uppercase break-words', {
'mx-auto': centerContent,
'mb-0': !marginBottom,
'mb-4': marginBottom,

View File

@ -41,7 +41,7 @@ export const ContractAddresses: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
lockedAddress: '0x0', // TODO not deployed to this env
},
VALIDATORS_TESTNET: {
VALIDATOR_TESTNET: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
lockedAddress: '0x0', // TODO not deployed to this env
// This is a fallback contract address for the validator testnet network which does not

View File

@ -6,11 +6,10 @@ import {
ViewPartyConnector,
createConfig,
fairground,
validatorsTestnet,
stagnet,
mainnet,
} from '@vegaprotocol/wallet';
import { CHAIN_IDS, useEnvironment } from '@vegaprotocol/environment';
import { useEnvironment } from '@vegaprotocol/environment';
export const useVegaWalletConfig = () => {
const { VEGA_ENV, VEGA_URL, VEGA_WALLET_URL } = useEnvironment();
@ -32,8 +31,8 @@ export const useVegaWalletConfig = () => {
const viewParty = new ViewPartyConnector();
const config = createConfig({
chains: [mainnet, fairground, validatorsTestnet, stagnet],
defaultChainId: CHAIN_IDS[VEGA_ENV],
chains: [mainnet, fairground, stagnet],
defaultChainId: fairground.id,
connectors: [injected, snap, jsonRpc, viewParty],
});

View File

@ -31,7 +31,7 @@ i18n
load: 'languageOnly',
debug: isInDev,
// have a common namespace used around the full app
ns: ['governance', 'wallet', 'wallet-react', 'assets', 'utils'],
ns: ['governance', 'wallet', 'wallet-react'],
defaultNS: 'governance',
keySeparator: false, // we use content as keys
nsSeparator: false,

View File

@ -19,7 +19,6 @@ import {
getSigners,
MarginScalingFactorsPanel,
marketInfoProvider,
PriceMonitoringSettingsInfoPanel,
} from '@vegaprotocol/markets';
import {
Button,
@ -50,7 +49,7 @@ export const useMarketDataDialogStore = create<MarketDataDialogState>(
const marketDataHeaderStyles =
'font-alpha calt text-base border-b border-vega-dark-200 mt-2 py-2';
export const ProposalMarketData = ({ marketId }: { marketId: string }) => {
export const ProposalMarketData = ({ proposalId }: { proposalId: string }) => {
const { t } = useTranslation();
const { isOpen, open, close } = useMarketDataDialogStore();
const [showDetails, setShowDetails] = useState(false);
@ -59,7 +58,7 @@ export const ProposalMarketData = ({ marketId }: { marketId: string }) => {
dataProvider: marketInfoProvider,
skipUpdates: true,
variables: {
marketId: marketId,
marketId: proposalId,
},
});
@ -72,7 +71,7 @@ export const ProposalMarketData = ({ marketId }: { marketId: string }) => {
},
});
if (!marketData) {
if (!marketData || !parentMarketData) {
return null;
}
@ -134,13 +133,13 @@ export const ProposalMarketData = ({ marketId }: { marketId: string }) => {
<h2 className={marketDataHeaderStyles}>{t('Key details')}</h2>
<KeyDetailsInfoPanel
market={marketData}
parentMarket={parentMarketData ? parentMarketData : undefined}
parentMarket={parentMarketData}
/>
<h2 className={marketDataHeaderStyles}>{t('Instrument')}</h2>
<InstrumentInfoPanel
market={marketData}
parentMarket={parentMarketData ? parentMarketData : undefined}
parentMarket={parentMarketData}
/>
{settlementData &&
@ -156,7 +155,7 @@ export const ProposalMarketData = ({ marketId }: { marketId: string }) => {
isParentSettlementDataEqual ||
isParentSettlementScheduleDataEqual
? undefined
: parentMarketData || undefined
: parentMarketData
}
/>
</>
@ -169,9 +168,7 @@ export const ProposalMarketData = ({ marketId }: { marketId: string }) => {
market={marketData}
type="settlementData"
parentMarket={
isParentSettlementDataEqual
? undefined
: parentMarketData || undefined
isParentSettlementDataEqual ? undefined : parentMarketData
}
/>
@ -187,7 +184,7 @@ export const ProposalMarketData = ({ marketId }: { marketId: string }) => {
parentMarket={
isParentTerminationDataEqual
? undefined
: parentMarketData || undefined
: parentMarketData
}
/>
</div>
@ -205,7 +202,7 @@ export const ProposalMarketData = ({ marketId }: { marketId: string }) => {
parentMarket={
isParentSettlementScheduleDataEqual
? undefined
: parentMarketData || undefined
: parentMarketData
}
/>
</div>
@ -219,19 +216,19 @@ export const ProposalMarketData = ({ marketId }: { marketId: string }) => {
<h2 className={marketDataHeaderStyles}>{t('Settlement assets')}</h2>
<SettlementAssetInfoPanel
market={marketData}
parentMarket={parentMarketData || undefined}
parentMarket={parentMarketData}
/>
<h2 className={marketDataHeaderStyles}>{t('Metadata')}</h2>
<MetadataInfoPanel
market={marketData}
parentMarket={parentMarketData || undefined}
parentMarket={parentMarketData}
/>
<h2 className={marketDataHeaderStyles}>{t('Risk model')}</h2>
<RiskModelInfoPanel
market={marketData}
parentMarket={parentMarketData || undefined}
parentMarket={parentMarketData}
/>
<h2 className={marketDataHeaderStyles}>
@ -239,45 +236,61 @@ export const ProposalMarketData = ({ marketId }: { marketId: string }) => {
</h2>
<MarginScalingFactorsPanel
market={marketData}
parentMarket={parentMarketData || undefined}
parentMarket={parentMarketData}
/>
<h2 className={marketDataHeaderStyles}>{t('Risk factors')}</h2>
<RiskFactorsInfoPanel
market={marketData}
parentMarket={parentMarketData || undefined}
parentMarket={parentMarketData}
/>
{showParentPriceMonitoringBounds && (
// shows bounds for parent market
{showParentPriceMonitoringBounds &&
(
parentMarketData?.priceMonitoringSettings?.parameters
?.triggers || []
).map((_, triggerIndex) => (
<>
<h2 className={marketDataHeaderStyles}>
{t(`Parent price monitoring bounds ${triggerIndex + 1}`)}
</h2>
<div className="text-vega-dark-300 line-through">
<PriceMonitoringBoundsInfoPanel
market={parentMarketData}
triggerIndex={triggerIndex}
/>
</div>
</>
))}
{(
marketData.priceMonitoringSettings?.parameters?.triggers || []
).map((_, triggerIndex) => (
<>
<h2 className={marketDataHeaderStyles}>
{t('Parent price monitoring bounds')}
{t(`Price monitoring bounds ${triggerIndex + 1}`)}
</h2>
<div className="text-vega-dark-300 line-through">
<PriceMonitoringBoundsInfoPanel market={parentMarketData} />
</div>
<PriceMonitoringBoundsInfoPanel
market={marketData}
triggerIndex={triggerIndex}
/>
</>
)}
<h2 className={marketDataHeaderStyles}>
{t('Price monitoring settings')}
</h2>
<PriceMonitoringSettingsInfoPanel market={marketData} />
))}
<h2 className={marketDataHeaderStyles}>
{t('Liquidity monitoring parameters')}
</h2>
<LiquidityMonitoringParametersInfoPanel
market={marketData}
parentMarket={parentMarketData || undefined}
parentMarket={parentMarketData}
/>
<h2 className={marketDataHeaderStyles}>
{t('Liquidity price range')}
</h2>
<LiquidityPriceRangeInfoPanel
market={marketData}
parentMarket={parentMarketData || undefined}
parentMarket={parentMarketData}
/>
<h2 className={marketDataHeaderStyles}>
@ -285,7 +298,7 @@ export const ProposalMarketData = ({ marketId }: { marketId: string }) => {
</h2>
<LiquiditySLAParametersInfoPanel
market={marketData}
parentMarket={parentMarketData || undefined}
parentMarket={parentMarketData}
/>
</div>
</>

View File

@ -17,20 +17,17 @@ import { type ProposalNode } from './proposal-utils';
import { Lozenge } from '@vegaprotocol/ui-toolkit';
import { Indicator } from './indicator';
import { SubHeading } from '../../../../components/heading';
import { determineId } from '@vegaprotocol/wallet';
export const ProposalChangeDetails = ({
proposal,
terms,
restData,
indicator,
termsCount = 0,
}: {
proposal: Proposal | BatchProposal;
terms: ProposalTermsFieldsFragment;
restData: ProposalNode | null;
indicator?: number;
termsCount?: number;
}) => {
const { t } = useTranslation();
let details = null;
@ -64,18 +61,7 @@ export const ProposalChangeDetails = ({
}
case 'NewMarket': {
if (proposal.id) {
let marketId = proposal.id;
// TODO: when https://github.com/vegaprotocol/vega/issues/11005 gets merged
// this will need to be updated to loop forward from 0. Right now subProposals
// are returned (when using GQL) in the reverse order
if (proposal.__typename === 'BatchProposal') {
for (let i = termsCount - 1; i >= 0; i--) {
marketId = determineId(marketId);
}
}
details = <ProposalMarketData marketId={marketId} />;
details = <ProposalMarketData proposalId={proposal.id} />;
}
break;
}
@ -83,7 +69,7 @@ export const ProposalChangeDetails = ({
if (proposal.id) {
details = (
<div className="flex flex-col gap-4">
<ProposalMarketData marketId={proposal.id} />
<ProposalMarketData proposalId={proposal.id} />
<ProposalMarketChanges
indicator={indicator}
marketId={terms.change.marketId}

View File

@ -78,7 +78,6 @@ export const Proposal = ({ proposal, restData }: ProposalProps) => {
proposal={proposal}
terms={p.terms}
restData={restData}
termsCount={proposal.subProposals?.length}
/>
);
})

View File

@ -61,7 +61,6 @@ const mockConsensusValidators: NodesFragmentFragment[] = [
];
jest.mock('@vegaprotocol/environment', () => ({
...jest.requireActual('@vegaprotocol/environment'),
useVegaRelease: jest.fn(),
useVegaReleases: jest.fn(),
}));

View File

@ -3,6 +3,8 @@ export const VALIDATOR_LOGO_MAP: { [key: string]: string } = {
'https://pbs.twimg.com/profile_images/1586047492629712897/ZVMWBE94_400x400.jpg',
efbdf943443bd7595e83b0d7e88f37b7932d487d1b94aab3d004997273bb43fc:
'https://pbs.twimg.com/profile_images/1026823609979949057/3e-LCHHm_400x400.jpg',
'126751c5830b50d39eb85412fb2964f46338cce6946ff455b73f1b1be3f5e8cc':
'https://pbs.twimg.com/profile_images/1228627868542029824/9aoaLiIx_400x400.jpg',
'43697a3e911d8b70c0ce672adde17a5c38ca8f6a0486bf85ed0546e1b9a82887':
'https://pbs.twimg.com/profile_images/1352167987478843392/XzX82gIb_400x400.jpg',
ac735acc9ab11cf1d8c59c2df2107e00092b4ac96451cb137a1629af5b66242a:

View File

@ -13,7 +13,7 @@
}
h1 {
@apply text-2xl text-white mb-4;
@apply text-2xl text-white uppercase mb-4;
}
h2 {
@apply text-xl text-white mb-4;

View File

@ -2,4 +2,4 @@
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.tom
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
NX_VEGA_NETWORKS={'{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=VALIDATORS_TESTNET
NX_VEGA_ENV=VALIDATOR_TESTNET

View File

@ -21,7 +21,6 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
NX_STOP_ORDERS=true
NX_TAKE_PROFIT_STOP_LOSS=true
NX_ISOLATED_MARGIN=true
NX_ICEBERG_ORDERS=true
NX_METAMASK_SNAPS=true

View File

@ -21,8 +21,6 @@ NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supp
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=false
NX_STOP_ORDERS=false
NX_TAKE_PROFIT_STOP_LOSS=false
NX_TAKE_PROFIT_STOP_LOSS=true
NX_ISOLATED_MARGIN=true
# NX_ICEBERG_ORDERS
# NX_PRODUCT_PERPETUALS

View File

@ -21,7 +21,6 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
NX_STOP_ORDERS=true
NX_TAKE_PROFIT_STOP_LOSS=false
NX_ISOLATED_MARGIN=false
NX_ICEBERG_ORDERS=true
NX_METAMASK_SNAPS=true

View File

@ -21,7 +21,6 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
NX_STOP_ORDERS=true
NX_TAKE_PROFIT_STOP_LOSS=true
NX_ISOLATED_MARGIN=true
NX_ICEBERG_ORDERS=true
# NX_PRODUCT_PERPETUALS

View File

@ -22,7 +22,6 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
NX_STOP_ORDERS=true
NX_TAKE_PROFIT_STOP_LOSS=true
NX_ISOLATED_MARGIN=true
NX_ICEBERG_ORDERS=true
NX_METAMASK_SNAPS=true

View File

@ -4,7 +4,7 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_SENTRY_DSN=https://2ffce43721964aafa78277c50654ece4@o286262.ingest.sentry.io/6300613
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.toml
NX_VEGA_ENV=VALIDATORS_TESTNET
NX_VEGA_ENV=VALIDATOR_TESTNET
NX_VEGA_EXPLORER_URL=https://explorer.validators-testnet.vega.rocks
NX_VEGA_NETWORKS={\"MAINNET\":\"https://console.vega.xyz\",\"STAGNET1\":\"https://trading.stagnet1.vega.rocks\",\"TESTNET\":\"https://console.fairground.wtf\"}
NX_VEGA_TOKEN_URL=https://governance.validators-testnet.vega.rocks
@ -22,7 +22,6 @@ NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/m
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
NX_STOP_ORDERS=true
NX_TAKE_PROFIT_STOP_LOSS=true
NX_ISOLATED_MARGIN=true
NX_ICEBERG_ORDERS=true
# NX_PRODUCT_PERPETUALS

View File

@ -9,10 +9,6 @@ import {
Button,
VegaIcon,
VegaIconNames,
Tooltip,
TradingAnchorButton,
Intent,
CopyWithTooltip,
} from '@vegaprotocol/ui-toolkit';
import { TransferStatus, type Asset } from '@vegaprotocol/types';
import classNames from 'classnames';
@ -21,7 +17,7 @@ import { Table } from '../../components/table';
import {
addDecimalsFormatNumberQuantum,
formatNumber,
removePaginationWrapper,
getDateTimeFormat,
} from '@vegaprotocol/utils';
import {
useTeam,
@ -45,6 +41,10 @@ import {
} from '../../lib/hooks/use-games';
import { useEpochInfoQuery } from '../../lib/hooks/__generated__/Epoch';
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';
import {
@ -52,13 +52,6 @@ import {
isScopedToTeams,
useRewards,
} from '../../lib/hooks/use-rewards';
import {
ActiveRewardCard,
DispatchMetricInfo,
} from '../../components/rewards-container/reward-card';
import { usePartyProfilesQuery } from '../../components/vega-wallet-connect-button/__generated__/PartyProfiles';
const formatDate = (date: Date) => format(date, 'yyyy/MM/dd hh:mm:ss');
export const CompetitionsTeam = () => {
const t = useT();
@ -147,25 +140,11 @@ const TeamPage = ({
const t = useT();
const [showGames, setShowGames] = useState(true);
const createdAt = new Date(team.createdAt);
const closedIndicator = team.closed ? (
<div className="border rounded border-vega-clight-300 dark:border-vega-cdark-300 px-1 pt-[1px] flex items-baseline gap-1">
<VegaIcon name={VegaIconNames.LOCK} size={10} />
<span>{t('Private')}</span>
</div>
) : (
<div className="border rounded border-vega-clight-300 dark:border-vega-cdark-300 px-1 pt-[1px] flex items-baseline gap-1">
<VegaIcon name={VegaIconNames.GLOBE} size={10} />
<span>{t('Public')}</span>
</div>
);
return (
<LayoutWithGradient>
<header className="flex gap-3 lg:gap-4 pt-5 lg:pt-10">
<TeamAvatar teamId={team.teamId} imgUrl={team.avatarUrl} />
<div className="flex flex-col items-start gap-1 lg:gap-2">
<div className="flex flex-col items-start gap-1 lg:gap-3">
<h1
className="calt text-2xl lg:text-3xl xl:text-5xl"
data-testid="team-name"
@ -175,38 +154,6 @@ const TeamPage = ({
<div className="flex gap-2">
<JoinTeam team={team} partyTeam={partyTeam} refetch={refetch} />
<UpdateTeamButton team={team} />
{team.teamUrl && team.teamUrl.length > 0 && (
<Tooltip description={t("Visit the team's page.")}>
<span>
<TradingAnchorButton
intent={Intent.Info}
target="_blank"
referrerPolicy="no-referrer"
href={team.teamUrl}
>
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} />
</TradingAnchorButton>
</span>
</Tooltip>
)}
<CopyWithTooltip
description={t('Copy this page url.')}
text={globalThis.location.href}
>
<button className="h-10 w-7">
<VegaIcon name={VegaIconNames.COPY} size={16} />
</button>
</CopyWithTooltip>
</div>
<div className="flex gap-2 items-baseline text-xs text-muted font-alpha calt">
{closedIndicator}
<div className="">
{t('Created at')}:{' '}
<span className="text-vega-cdark-600 dark:text-vega-clight-600 ">
{formatDate(createdAt)}
</span>{' '}
({t('epoch')}: {team.createdAtEpoch})
</div>
</div>
</div>
</header>
@ -283,138 +230,118 @@ const Games = ({
};
return (
<div className="text-sm">
<Table
columns={[
{
name: 'epoch',
displayName: t('Epoch'),
},
{
name: 'endtime',
displayName: t('End time'),
},
{ name: 'type', displayName: t('Type') },
{
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',
displayName: t('No. of participating teams'),
},
{
name: 'participatingMembers',
displayName: t('No. of participating members'),
},
].map((c) => ({ ...c, headerClassName: 'text-left' }))}
data={games.map((game) => {
let transfer = transfers?.find((t) => {
if (!isScopedToTeams(t)) return false;
<Table
columns={[
{
name: 'epoch',
displayName: t('Epoch'),
},
{
name: 'endtime',
displayName: t('End time'),
},
{ name: 'type', displayName: t('Type') },
{
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',
displayName: t('No. of participating teams'),
},
{
name: 'participatingMembers',
displayName: t('No. of participating members'),
},
].map((c) => ({ ...c, headerClassName: 'text-left' }))}
data={games.map((game) => {
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 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 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;
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;
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
const dailyAmount =
asset && transfer
? addDecimalsFormatNumberQuantum(
game.team.rewardEarned,
transfer.transfer.amount,
asset.decimals,
asset.quantum
)
: '-';
const totalAmount = asset
? addDecimalsFormatNumberQuantum(
game.team.totalRewardsEarned,
asset.decimals,
asset.quantum
)
: '-';
const earnedAmount = asset
? addDecimalsFormatNumberQuantum(
game.team.rewardEarned,
asset.decimals,
asset.quantum
)
: '-';
const assetSymbol = asset ? <RewardAssetCell asset={asset} /> : '-';
const totalAmount = asset
? addDecimalsFormatNumberQuantum(
game.team.totalRewardsEarned,
asset.decimals,
asset.quantum
)
: '-';
return {
id: game.id,
amount: dependable(earnedAmount),
asset: dependable(assetSymbol),
daily: dependable(dailyAmount),
endtime: <EndTimeCell epoch={game.epoch} />,
epoch: game.epoch,
participatingMembers: game.numberOfParticipants,
participatingTeams: game.entities.length,
rank: game.team.rank,
total: totalAmount,
// type: DispatchMetricLabels[game.team.rewardMetric as DispatchMetric],
type: dependable(
<GameTypeCell transfer={transfer} allMarkets={allMarkets} />
),
};
})}
noCollapse={false}
/>
</div>
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,
participatingMembers: game.numberOfParticipants,
participatingTeams: game.entities.length,
rank: game.team.rank,
total: totalAmount,
// type: DispatchMetricLabels[game.team.rewardMetric as DispatchMetric],
type: dependable(
<GameTypeCell transfer={transfer} allMarkets={allMarkets} />
),
};
})}
noCollapse={false}
/>
);
};
const Members = ({ members }: { members?: Member[] }) => {
const t = useT();
const partyIds = members?.map((m) => m.referee) || [];
const { data: profilesData } = usePartyProfilesQuery({
variables: {
partyIds,
},
skip: partyIds.length === 0,
});
const profiles = removePaginationWrapper(
profilesData?.partiesProfilesConnection?.edges
);
if (!members?.length) {
return <p>{t('No members')}</p>;
}
const data = orderBy(
members.map((m) => ({
referee: (
<RefereeLink
pubkey={m.referee}
isCreator={m.isCreator}
profiles={profiles}
/>
),
referee: <RefereeLink pubkey={m.referee} isCreator={m.isCreator} />,
rewards: formatNumber(m.totalQuantumRewards),
volume: formatNumber(m.totalQuantumVolume),
gamesPlayed: formatNumber(m.totalGamesPlayed),
joinedAt: formatDate(new Date(m.joinedAt)),
joinedAt: getDateTimeFormat().format(new Date(m.joinedAt)),
joinedAtEpoch: Number(m.joinedAtEpoch),
})),
'joinedAtEpoch',
@ -422,69 +349,45 @@ const Members = ({ members }: { members?: Member[] }) => {
);
return (
<div className="text-sm">
<Table
columns={[
{ name: 'referee', displayName: t('Member') },
{ name: 'rewards', displayName: t('Rewards earned') },
{ name: 'volume', displayName: t('Total volume') },
{ name: 'gamesPlayed', displayName: t('Games played') },
{
name: 'joinedAt',
displayName: t('Joined at'),
},
{
name: 'joinedAtEpoch',
displayName: t('Joined epoch'),
},
]}
data={data}
noCollapse={true}
/>
</div>
<Table
columns={[
{ name: 'referee', displayName: t('Member ID') },
{ name: 'rewards', displayName: t('Rewards earned') },
{ name: 'volume', displayName: t('Total volume') },
{ name: 'gamesPlayed', displayName: t('Games played') },
{
name: 'joinedAt',
displayName: t('Joined at'),
},
{
name: 'joinedAtEpoch',
displayName: t('Joined epoch'),
},
]}
data={data}
noCollapse={true}
/>
);
};
const RefereeLink = ({
pubkey,
isCreator,
profiles,
}: {
pubkey: string;
isCreator: boolean;
profiles?: { partyId: string; alias: string }[];
}) => {
const t = useT();
const linkCreator = useLinks(DApp.Explorer);
const link = linkCreator(EXPLORER_PARTIES.replace(':id', pubkey));
const alias = profiles?.find((p) => p.partyId === pubkey)?.alias;
return (
<div className="flex items-baseline gap-2">
<>
<Link to={link} target="_blank" className="underline underline-offset-4">
{alias || truncateMiddle(pubkey)}
</Link>
{!alias && (
<Tooltip
description={t(
'You can set your pubkey alias by using the key selector in the top right corner.'
)}
>
<button className="text-muted text-xs">
<VegaIcon name={VegaIconNames.QUESTION_MARK} size={14} />
</button>
</Tooltip>
)}
{alias && (
<span className="text-muted text-xs">{truncateMiddle(pubkey)}</span>
)}
{isCreator && (
<span className="text-muted text-xs border border-vega-clight-300 dark:border-vega-cdark-300 rounded px-1 py-[1px]">
{t('Owner')}
</span>
)}
</div>
{truncateMiddle(pubkey)}
</Link>{' '}
<span className="text-muted text-xs">{isCreator ? t('Owner') : ''}</span>
</>
);
};
@ -508,12 +411,15 @@ const EndTimeCell = ({ epoch }: { epoch?: number }) => {
variables: {
epochId: epoch ? epoch.toString() : undefined,
},
fetchPolicy: 'cache-first',
fetchPolicy: 'cache-and-network',
});
if (loading) return <Loader size="small" />;
if (data) {
return formatDate(new Date(data.epoch.timestamps.expiry));
return format(
new Date(data.epoch.timestamps.expiry),
'yyyy/MM/dd hh:mm:ss'
);
}
return null;

View File

@ -70,12 +70,6 @@ export const JoinButton = ({
}) => {
const t = useT();
/**
* A team cannot be joined (closed) when set as such
* and the currently connected pubkey is not whitelisted.
*/
const isTeamClosed = team.closed && !team.allowList.includes(pubKey || '');
if (!pubKey || isReadOnly) {
return (
<Tooltip description={t('Connect your wallet to join the team')}>
@ -85,9 +79,8 @@ export const JoinButton = ({
</Tooltip>
);
}
// Party is the creator of a team
if (partyTeam && partyTeam.referrer === pubKey) {
else if (partyTeam && partyTeam.referrer === pubKey) {
// Party is the creator of THIS team
if (partyTeam.teamId === team.teamId) {
return (
@ -112,24 +105,8 @@ export const JoinButton = ({
);
}
}
// Party is in a team, but not this one
if (partyTeam && partyTeam.teamId !== team.teamId) {
// This team is closed.
if (isTeamClosed) {
return (
<Tooltip description={t('You cannot join a private team')}>
<Button
intent={Intent.Primary}
data-testid="switch-team-button"
disabled={true}
>
{t('Switch team')}{' '}
</Button>
</Tooltip>
);
}
// This team is open.
else if (partyTeam && partyTeam.teamId !== team.teamId) {
return (
<Button
onClick={() => onJoin('switch')}
@ -140,9 +117,8 @@ export const JoinButton = ({
</Button>
);
}
// Joined. Current party is already in this team
if (partyTeam && partyTeam.teamId === team.teamId) {
else if (partyTeam && partyTeam.teamId === team.teamId) {
return (
<Button intent={Intent.None} disabled={true}>
<span className="flex items-center gap-2">
@ -155,17 +131,6 @@ export const JoinButton = ({
);
}
// This team is closed.
if (isTeamClosed) {
return (
<Tooltip description={t('You cannot join a closed team')}>
<Button intent={Intent.Primary} disabled={true}>
{t('Join team')}
</Button>
</Tooltip>
);
}
// This team is open.
return (
<Button onClick={() => onJoin('join')} intent={Intent.Primary}>
{t('Join team')}

View File

@ -5,8 +5,8 @@ import type { Market } from '@vegaprotocol/markets';
import {
addDecimalsFormatNumber,
fromNanoSeconds,
getExpiryDate,
getMarketExpiryDate,
useExpiryDate,
} from '@vegaprotocol/utils';
import {
Last24hPriceChange,
@ -20,7 +20,6 @@ import {
useMarketTradingMode,
useExternalTwap,
getQuoteName,
useMarketState,
} from '@vegaprotocol/markets';
import { MarketState as State } from '@vegaprotocol/types';
import { HeaderStat } from '../../components/header';
@ -45,12 +44,6 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
const asset = getAsset(market);
const quoteUnit = getQuoteName(market);
const dataSourceSpec = market.markPriceConfiguration?.dataSourcesSpec?.[1];
const sourceType =
dataSourceSpec?.sourceType.__typename === 'DataSourceDefinitionExternal' &&
dataSourceSpec?.sourceType.sourceType.__typename === 'EthCallSpec' &&
dataSourceSpec?.sourceType.sourceType;
return (
<>
<HeaderStat heading={t('Mark Price')} testId="market-price">
@ -68,13 +61,16 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
<HeaderStat heading={t('Volume (24h)')} testId="market-volume">
<Last24hVolume
marketId={market.id}
marketDecimals={market.decimalPlaces}
positionDecimalPlaces={market.positionDecimalPlaces}
marketDecimals={market.decimalPlaces}
quoteUnit={quoteUnit}
/>
</HeaderStat>
<HeaderStatMarketTradingMode marketId={market.id} />
<MarketState marketId={market.id} />
<HeaderStatMarketTradingMode
marketId={market.id}
initialTradingMode={market.tradingMode}
/>
<MarketState market={market} />
{asset ? (
<HeaderStat
heading={t('Settlement asset')}
@ -131,25 +127,14 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
{t(
'The external time weighted average price (TWAP) received from the data source defined in the data sourcing specification.'
)}
<div className="flex flex-col gap-1">
{DocsLinks && (
<ExternalLink
href={DocsLinks.ETH_DATA_SOURCES}
className="mt-2"
>
{t('Find out more')}
</ExternalLink>
)}
{sourceType && (
<ExternalLink
data-testid="oracle-spec-links"
href={`${VEGA_EXPLORER_URL}/markets/${market.id}/oracles#${sourceType.address}`}
className="text-xs my-1"
>
{t('Oracle specification')}
</ExternalLink>
)}
</div>
{DocsLinks && (
<ExternalLink
href={DocsLinks.ETH_DATA_SOURCES}
className="mt-2"
>
{t('Find out more')}
</ExternalLink>
)}
</div>
}
testId="index-price"
@ -279,13 +264,13 @@ export const FundingCountdown = ({ marketId }: { marketId: string }) => {
};
const ExpiryLabel = ({ market }: ExpiryLabelProps) => {
const { data: marketState } = useMarketState(market.id);
const content =
useExpiryDate(
market.tradableInstrument.instrument.metadata.tags,
market.marketTimestamps.close,
marketState
) || '-';
const content = market.tradableInstrument.instrument.metadata.tags
? getExpiryDate(
market.tradableInstrument.instrument.metadata.tags,
market.marketTimestamps.close,
market.state
)
: '-';
return <div data-testid="trading-expiry">{content}</div>;
};
@ -298,7 +283,6 @@ const ExpiryTooltipContent = ({
market,
explorerUrl,
}: ExpiryTooltipContentProps) => {
const { data: state } = useMarketState(market.id);
const t = useT();
if (market.marketTimestamps.close === null) {
const oracleId =
@ -314,8 +298,8 @@ const ExpiryTooltipContent = ({
const isExpired =
metadataExpiryDate &&
Date.now() - metadataExpiryDate.valueOf() > 0 &&
(state === State.STATE_TRADING_TERMINATED ||
state === State.STATE_SETTLED);
(market.state === State.STATE_TRADING_TERMINATED ||
market.state === State.STATE_SETTLED);
return (
<section data-testid="expiry-tooltip">

View File

@ -40,6 +40,7 @@ describe('Closed', () => {
const market = createMarketFragment({
id: marketId,
state: MarketState.STATE_SETTLED,
tradableInstrument: {
instrument: {
metadata: {
@ -95,7 +96,6 @@ describe('Closed', () => {
const marketsData = createMarketsDataFragment({
__typename: 'MarketData',
marketState: MarketState.STATE_SETTLED,
market: {
__typename: 'Market',
id: marketId,
@ -199,16 +199,13 @@ describe('Closed', () => {
it('renders correctly formatted and filtered rows', async () => {
await renderComponent([marketsMock, marketsDataMock, oracleDataMock]);
await waitFor(() => {
expect(screen.getAllByRole('gridcell').length).toBeGreaterThan(0);
});
const assetSymbol = getAsset(market).symbol;
const cells = screen.getAllByRole('gridcell');
const expectedValues = [
market.tradableInstrument.instrument.code,
MarketStateMapping[marketsData.marketState],
MarketStateMapping[market.state],
'3 days ago',
/* eslint-disable @typescript-eslint/no-non-null-assertion */
addDecimalsFormatNumber(marketsData.bestBidPrice, market.decimalPlaces),
@ -227,6 +224,87 @@ describe('Closed', () => {
});
});
it('only renders settled and terminated markets', async () => {
const mixedMarkets = [
{
// include as settled
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: 'include-0',
state: MarketState.STATE_SETTLED,
}),
},
{
// omit this market
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: 'discard-0',
state: MarketState.STATE_SUSPENDED,
}),
},
{
// include as terminated
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: 'include-1',
state: MarketState.STATE_TRADING_TERMINATED,
}),
},
{
// omit this market
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: 'discard-1',
state: MarketState.STATE_ACTIVE,
}),
},
];
const mixedMarketsMock: MockedResponse<MarketsQuery> = {
request: {
query: MarketsDocument,
},
result: {
data: {
marketsConnection: {
__typename: 'MarketConnection',
edges: mixedMarkets,
},
},
},
};
await renderComponent([mixedMarketsMock, marketsDataMock, oracleDataMock]);
// check that the number of rows in datagrid is 2
const container = within(
document.querySelector('.ag-center-cols-container') as HTMLElement
);
const expectedRows = mixedMarkets.filter((m) => {
return [
MarketState.STATE_SETTLED,
MarketState.STATE_TRADING_TERMINATED,
].includes(m.node.state);
});
await waitFor(() => {
// check rows length is correct
const rows = container.getAllByRole('row');
expect(rows).toHaveLength(expectedRows.length);
});
// check that only included ids are shown
const cells = screen
.getAllByRole('gridcell')
.filter((cell) => cell.getAttribute('col-id') === 'code')
.map((cell) => {
const marketCode = within(cell).getByTestId('stack-cell-primary');
return marketCode.textContent;
});
expect(cells).toEqual(
expectedRows.map((m) => m.node.tradableInstrument.instrument.code)
);
});
it('display market actions', async () => {
// Use market with a successor Id as the actions dropdown will optionally
// show a link to the successor market
@ -234,7 +312,8 @@ describe('Closed', () => {
{
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: marketId,
id: 'include-0',
state: MarketState.STATE_SETTLED,
successorMarketID: 'successor',
parentMarketID: 'parent',
}),
@ -259,33 +338,31 @@ describe('Closed', () => {
oracleDataMock,
]);
await waitFor(async () => {
const actionCell = screen
.getAllByRole('gridcell')
.find((el) => el.getAttribute('col-id') === 'market-actions');
const actionCell = screen
.getAllByRole('gridcell')
.find((el) => el.getAttribute('col-id') === 'market-actions');
await userEvent.click(
within(actionCell as HTMLElement).getByTestId('dropdown-menu')
);
await userEvent.click(
within(actionCell as HTMLElement).getByTestId('dropdown-menu')
);
expect(screen.getByRole('menu')).toBeInTheDocument();
expect(screen.getByRole('menu')).toBeInTheDocument();
expect(
screen.getByRole('menuitem', { name: 'Copy Market ID' })
).toBeInTheDocument();
expect(
screen.getByRole('menuitem', { name: 'View on Explorer' })
).toBeInTheDocument();
expect(
screen.getByRole('menuitem', { name: 'View settlement asset details' })
).toBeInTheDocument();
expect(
screen.getByRole('menuitem', { name: 'View parent market' })
).toBeInTheDocument();
expect(
screen.getByRole('menuitem', { name: 'View successor market' })
).toBeInTheDocument();
});
expect(
screen.getByRole('menuitem', { name: 'Copy Market ID' })
).toBeInTheDocument();
expect(
screen.getByRole('menuitem', { name: 'View on Explorer' })
).toBeInTheDocument();
expect(
screen.getByRole('menuitem', { name: 'View settlement asset details' })
).toBeInTheDocument();
expect(
screen.getByRole('menuitem', { name: 'View parent market' })
).toBeInTheDocument();
expect(
screen.getByRole('menuitem', { name: 'View successor market' })
).toBeInTheDocument();
});
it('successor market should be visible', async () => {
@ -293,7 +370,8 @@ describe('Closed', () => {
{
__typename: 'MarketEdge' as const,
node: createMarketFragment({
id: marketId,
id: 'include-0',
state: MarketState.STATE_SETTLED,
successorMarketID: 'successor',
}),
},

View File

@ -15,7 +15,7 @@ import {
addDecimalsFormatNumber,
getMarketExpiryDate,
} from '@vegaprotocol/utils';
import { closedMarketsProvider, getAsset } from '@vegaprotocol/markets';
import { closedMarketsWithDataProvider, getAsset } from '@vegaprotocol/markets';
import type { DataSourceFilterFragment } from '@vegaprotocol/markets';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
@ -35,7 +35,7 @@ interface Row {
code: string;
name: string;
decimalPlaces: number;
state?: MarketState;
state: MarketState;
metadata: string[];
closeTimestamp: string | null;
bestBidPrice: string | undefined;
@ -53,7 +53,7 @@ interface Row {
export const Closed = () => {
const { data: marketData, error } = useDataProvider({
dataProvider: closedMarketsProvider,
dataProvider: closedMarketsWithDataProvider,
variables: undefined,
});
@ -87,7 +87,7 @@ export const Closed = () => {
code: instrument.code,
name: instrument.name,
decimalPlaces: market.decimalPlaces,
state: market.data?.marketState,
state: market.state,
metadata: instrument.metadata.tags ?? [],
closeTimestamp: market.marketTimestamps.close,
bestBidPrice: market.data?.bestBidPrice,

View File

@ -1 +0,0 @@
export { ProposalsList } from './proposals-list';

View File

@ -1,37 +0,0 @@
import type { FC } from 'react';
import { AgGrid } from '@vegaprotocol/datagrid';
import { useProposedMarketsList } from '@vegaprotocol/markets';
import { type ProposalListFieldsFragment } from '@vegaprotocol/proposals';
import { useColumnDefs } from './use-column-defs';
import { useT } from '../../../lib/use-t';
const defaultColDef = {
sortable: true,
filter: true,
resizable: true,
filterParams: { buttons: ['reset'] },
};
interface ProposalListProps {
cellRenderers: {
[name: string]: FC<{ value: string; data: ProposalListFieldsFragment }>;
};
}
export const ProposalsList = ({ cellRenderers }: ProposalListProps) => {
const t = useT();
const { data } = useProposedMarketsList();
const columnDefs = useColumnDefs();
return (
<AgGrid
columnDefs={columnDefs}
rowData={data}
defaultColDef={defaultColDef}
getRowId={({ data }) => data.id}
overlayNoRowsTemplate={t('No proposed markets')}
components={cellRenderers}
rowHeight={45}
/>
);
};

View File

@ -1,4 +1,4 @@
import { ProposalsList } from './proposals-list';
import { ProposalsList } from '@vegaprotocol/proposals';
import { ParentMarketCell } from './parent-market-cell';
const cellRenderers = {

View File

@ -9,7 +9,7 @@ export interface SettlementDataCellProps {
oracleSpecId: string;
metaDate: Date | null;
closeTimestamp: string | null;
marketState?: MarketState;
marketState: MarketState;
}
export const SettlementDateCell = ({

View File

@ -15,6 +15,7 @@ import {
import { ButtonLink, Tooltip } from '@vegaprotocol/ui-toolkit';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import type {
MarketFieldsFragment,
MarketMaybeWithData,
MarketMaybeWithDataAndCandles,
} from '@vegaprotocol/markets';
@ -125,9 +126,7 @@ export const useMarketsColumnDefs = () => {
valueFormatter: ({
data,
}: VegaValueFormatterParams<MarketMaybeWithData, 'state'>) => {
return data?.data?.marketState
? Schema.MarketStateMapping[data?.data?.marketState]
: '-';
return data?.state ? Schema.MarketStateMapping[data.state] : '-';
},
filter: SetFilter,
filterParams: {
@ -167,10 +166,9 @@ export const useMarketsColumnDefs = () => {
valueFormatter: ({
data,
}: ValueFormatterParams<MarketMaybeWithDataAndCandles, 'candles'>) => {
if (!data) return '-';
const candles = data.candles;
const candles = data?.candles;
const vol = candles ? calcCandleVolume(candles) : '0';
const quoteName = getQuoteName(data);
const quoteName = getQuoteName(data as MarketFieldsFragment);
const volPrice =
candles &&
calcCandleVolumePrice(

View File

@ -1,5 +1,6 @@
import type { InMemoryCacheConfig } from '@apollo/client';
import {
AppLoader,
NetworkLoader,
useEnvironment,
useNodeSwitcherStore,
@ -85,6 +86,10 @@ export const Bootstrapper = ({ children }: { children: ReactNode }) => {
}));
const config = useVegaWalletConfig();
if (!config) {
return <AppLoader />;
}
const ERR_DATA_LOADER = (
<Trans
i18nKey="It appears that the connection to the node <0>{{VEGA_URL}}</0> does not return necessary data, try switching to another node."
@ -113,11 +118,7 @@ export const Bootstrapper = ({ children }: { children: ReactNode }) => {
skeleton={<Loading />}
failure={<Failure reason={t('Could not configure web3 provider')} />}
>
{config ? (
<WalletProvider config={config}>{children}</WalletProvider>
) : (
<Failure reason={t('Could not configure the wallet provider')} />
)}
<WalletProvider config={config}>{children}</WalletProvider>
</Web3Provider>
</DataLoader>
</NetworkLoader>
@ -144,30 +145,6 @@ const cacheConfig: InMemoryCacheConfig = {
Product: {
keyFields: ['settlementAsset', ['id']],
},
Market: {
fields: {
/**
* Intercept cache field for tickSize because mainnet specific queries have been
* set up, marking this field as client only. The following can be removed when mainnet
* supports ticksize:
*
* 1. The typePolicy for tickSize below
* 2. The MarketInfoMainnet query in libs/markets/src/lib/components/market-info/MarketInfo.graphql
* 3. The ternary to switch queries in libs/markets/src/lib/components/market-info/market-info-data-provider.ts
* 4. The MarketsMainnet query in libs/markets/src/lib/markets.graphql
* 5. The ternary to switch queries in libs/markets/src/lib/markets-provider.ts
*/
tickSize: {
read(value) {
// value is not present, we have probably marked tickSize as a client only field
if (!value) return '1';
// Use fetch response value
return value;
},
},
},
},
MarketData: {
keyFields: ['market', ['id']],
},

View File

@ -44,7 +44,6 @@ export const CompetitionsLeaderboard = ({
const avatar = (
<TeamAvatar
key={td.teamId}
teamId={td.teamId}
imgUrl={td.avatarUrl}
alt={td.name}
@ -68,7 +67,7 @@ export const CompetitionsLeaderboard = ({
),
earned: num(td.totalQuantumRewards),
games: num(td.totalGamesPlayed),
status: td.closed ? t('Private') : t('Public'),
status: td.closed ? t('Closed') : t('Open'),
volume: num(td.totalQuantumVolume),
};
})}

View File

@ -1,81 +1,6 @@
import { ActiveRewardCard } from '../rewards-container/active-rewards';
import { useT } from '../../lib/use-t';
import { type EnrichedRewardTransfer } from '../../lib/hooks/use-rewards';
import { useVegaWallet } from '@vegaprotocol/wallet-react';
import { useStakeAvailable } from '../../lib/hooks/use-stake-available';
import { useMyTeam } from '../../lib/hooks/use-my-team';
import {
ActiveRewardCard,
areAllMarketsSettled,
} from '../rewards-container/reward-card';
import {
VegaIcon,
VegaIconNames,
TradingInput,
} from '@vegaprotocol/ui-toolkit';
import { useState } from 'react';
import { type AssetFieldsFragment } from '@vegaprotocol/assets';
import { type MarketFieldsFragment } from '@vegaprotocol/markets';
import {
type TransferNode,
DispatchMetricLabels,
EntityScopeLabelMapping,
AccountType,
} from '@vegaprotocol/types';
export type Filter = {
searchTerm: string;
};
export const applyFilter = (
node: TransferNode & {
asset?: AssetFieldsFragment | null;
markets?: (MarketFieldsFragment | null)[];
},
filter: Filter
) => {
const { transfer } = node;
// if the transfer is a staking reward then it should be displayed
if (transfer.toAccountType === AccountType.ACCOUNT_TYPE_GLOBAL_REWARD) {
return true;
}
if (
transfer.kind.__typename !== 'RecurringTransfer' &&
transfer.kind.__typename !== 'RecurringGovernanceTransfer'
) {
return false;
}
if (
(transfer.kind.dispatchStrategy?.dispatchMetric &&
DispatchMetricLabels[transfer.kind.dispatchStrategy.dispatchMetric]
.toLowerCase()
.includes(filter.searchTerm.toLowerCase())) ||
transfer.asset?.symbol
.toLowerCase()
.includes(filter.searchTerm.toLowerCase()) ||
(
(transfer.kind.dispatchStrategy &&
EntityScopeLabelMapping[transfer.kind.dispatchStrategy.entityScope]) ||
'Unspecified'
)
.toLowerCase()
.includes(filter.searchTerm.toLowerCase()) ||
node.asset?.name
.toLocaleLowerCase()
.includes(filter.searchTerm.toLowerCase()) ||
node.markets?.some((m) =>
m?.tradableInstrument?.instrument?.name
.toLocaleLowerCase()
.includes(filter.searchTerm.toLowerCase())
)
) {
return true;
}
return false;
};
export const GamesContainer = ({
data,
@ -85,23 +10,6 @@ export const GamesContainer = ({
currentEpoch: number;
}) => {
const t = useT();
const { pubKey } = useVegaWallet();
const { team } = useMyTeam();
const { stakeAvailable, isEligible, requiredStake } = useStakeAvailable();
const requirements = pubKey
? {
isEligible,
stakeAvailable,
requiredStake,
team,
pubKey,
}
: undefined;
const [filter, setFilter] = useState<Filter>({
searchTerm: '',
});
if (!data || data.length === 0) {
return (
@ -112,46 +20,24 @@ export const GamesContainer = ({
}
return (
<div>
{/** CARDS FILTER */}
{data.length > 1 && (
<TradingInput
onChange={(e) =>
setFilter((curr) => ({ ...curr, searchTerm: e.target.value }))
}
value={filter.searchTerm}
type="text"
placeholder={t(
'Search by reward dispatch metric, entity scope or asset name'
)}
data-testid="search-term"
className="mb-4 w-20 mr-2 max-w-xl"
prependElement={<VegaIcon name={VegaIconNames.SEARCH} />}
/>
)}
{/** CARDS */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{data
.filter((n) => applyFilter(n, filter))
// filter out the cards (rewards) for which all of the markets
// are settled
.filter((n) => !areAllMarketsSettled(n))
.map((game, i) => {
// TODO: Remove `kind` prop from ActiveRewardCard
const { transfer } = game;
if (!transfer.kind.dispatchStrategy?.dispatchMetric) {
return null;
}
return (
<ActiveRewardCard
key={i}
transferNode={game}
currentEpoch={currentEpoch}
requirements={requirements}
/>
);
})}
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{data.map((game, i) => {
// TODO: Remove `kind` prop from ActiveRewardCard
const { transfer } = game;
if (
transfer.kind.__typename !== 'RecurringTransfer' ||
!transfer.kind.dispatchStrategy?.dispatchMetric
) {
return null;
}
return (
<ActiveRewardCard
key={i}
transferNode={game}
currentEpoch={currentEpoch}
/>
);
})}
</div>
);
};

View File

@ -1,4 +1,6 @@
import { isValidUrl } from '@vegaprotocol/utils';
import classNames from 'classnames';
import { useEffect, useState } from 'react';
const NUM_AVATARS = 20;
const AVATAR_PATHNAME_PATTERN = '/team-avatars/{id}.png';
@ -11,6 +13,26 @@ export const getFallbackAvatar = (teamId: string) => {
return AVATAR_PATHNAME_PATTERN.replace('{id}', avatarId);
};
const useAvatar = (teamId: string, url: string) => {
const fallback = getFallbackAvatar(teamId);
const [avatar, setAvatar] = useState<string>(fallback);
useEffect(() => {
if (!isValidUrl(url)) return;
fetch(url, { cache: 'force-cache' })
.then((response) => {
if (response.ok) {
setAvatar(url);
}
})
.catch(() => {
/** noop */
});
});
return avatar;
};
export const TeamAvatar = ({
teamId,
imgUrl,
@ -22,11 +44,11 @@ export const TeamAvatar = ({
alt?: string;
size?: 'large' | 'small';
}) => {
// const img = useAvatar(teamId, imgUrl);
const img = useAvatar(teamId, imgUrl);
return (
// eslint-disable-next-line @next/next/no-img-element
<img
src={imgUrl}
src={img}
alt={alt || 'Team avatar'}
className={classNames(
'rounded-full bg-vega-clight-700 dark:bg-vega-cdark-700 shrink-0',
@ -36,9 +58,6 @@ export const TeamAvatar = ({
}
)}
referrerPolicy="no-referrer"
onError={(e) => {
e.currentTarget.src = getFallbackAvatar(teamId);
}}
/>
);
};

View File

@ -115,7 +115,6 @@ describe('MarketSettledBanner', () => {
open: '100',
close: '100',
volume: '100',
notional: '10000',
periodStart: subHours(new Date(now), 1).toISOString(),
},
},
@ -126,7 +125,6 @@ describe('MarketSettledBanner', () => {
open: '100',
close: '200',
volume: '100',
notional: '10000',
periodStart: subHours(new Date(now), 2).toISOString(),
},
},
@ -163,7 +161,6 @@ describe('MarketSettledBanner', () => {
open: '100',
close: '100',
volume: '100',
notional: '10000',
periodStart: '2020-01-01T00:00:00',
},
},

View File

@ -79,7 +79,6 @@ describe('MarketSelectorItem', () => {
high: '5',
low: '5',
volume: '50',
notional: '10000',
periodStart: yesterday.toISOString(),
},
{
@ -88,7 +87,6 @@ describe('MarketSelectorItem', () => {
high: '10',
low: '10',
volume: '50',
notional: '10000',
periodStart: yesterday.toISOString(),
},
];

View File

@ -72,17 +72,17 @@ const MarketData = ({
const marketTradingMode = marketData
? marketData.marketTradingMode
: market.data?.marketTradingMode;
: market.data
? market.data.marketTradingMode
: market.tradingMode;
const mode =
marketTradingMode &&
[
MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
].includes(marketTradingMode)
? MarketTradingModeMapping[marketTradingMode]
: '';
const mode = [
MarketTradingMode.TRADING_MODE_BATCH_AUCTION,
MarketTradingMode.TRADING_MODE_MONITORING_AUCTION,
MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
].includes(marketTradingMode)
? MarketTradingModeMapping[marketTradingMode]
: '';
const { oneDayCandles } = useCandles({ marketId: market.id });

View File

@ -120,7 +120,7 @@ export const MarketSelector = ({
<div data-testid="market-selector-list">
<MarketList
data={markets}
loading={loading && !data}
loading={loading}
error={error}
searchTerm={filter.searchTerm}
currentMarketId={currentMarketId}

View File

@ -409,6 +409,7 @@ describe('useMarketSelectorList', () => {
}),
createMarketFragment({
id: 'market-1',
state: MarketState.STATE_ACTIVE,
// @ts-ignore data not on fragment
data: createMarketsDataFragment({
marketState: MarketState.STATE_ACTIVE,
@ -423,6 +424,7 @@ describe('useMarketSelectorList', () => {
}),
createMarketFragment({
id: 'market-2',
state: MarketState.STATE_ACTIVE,
// @ts-ignore data not on fragment
data: createMarketsDataFragment({
marketState: MarketState.STATE_ACTIVE,
@ -437,6 +439,7 @@ describe('useMarketSelectorList', () => {
}),
createMarketFragment({
id: 'market-3',
state: MarketState.STATE_ACTIVE,
// @ts-ignore data not on fragment
data: createMarketsDataFragment({
marketState: MarketState.STATE_ACTIVE,

View File

@ -63,11 +63,7 @@ export const useMarketSelectorList = ({
[
(m) => {
if (!m.candles?.length) return 0;
return Number(
priceChangePercentage(
m.candles.filter((c) => c.close !== '').map((c) => c.close)
)
);
return Number(priceChangePercentage(m.candles.map((c) => c.close)));
},
],
[dir]

View File

@ -1,18 +1,48 @@
import { useMarketState } from '@vegaprotocol/markets';
import throttle from 'lodash/throttle';
import type { MarketData, Market } from '@vegaprotocol/markets';
import { marketDataProvider } from '@vegaprotocol/markets';
import { useDataProvider } from '@vegaprotocol/data-provider';
import * as Schema from '@vegaprotocol/types';
import { HeaderStat } from '../header';
import { useCallback, useRef, useState } from 'react';
import * as constants from '../constants';
import { DocsLinks } from '@vegaprotocol/environment';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import { useT } from '../../lib/use-t';
export const MarketState = ({ marketId }: { marketId?: string }) => {
export const MarketState = ({ market }: { market: Market | null }) => {
const t = useT();
const { data: marketState } = useMarketState(marketId);
const [marketState, setMarketState] = useState<Schema.MarketState | null>(
null
);
const throttledSetMarketState = useRef(
throttle((state: Schema.MarketState) => {
setMarketState(state);
}, constants.THROTTLE_UPDATE_TIME)
).current;
const update = useCallback(
({ data: marketData }: { data: MarketData | null }) => {
if (marketData) {
throttledSetMarketState(marketData.marketState);
}
return true;
},
[throttledSetMarketState]
);
useDataProvider({
dataProvider: marketDataProvider,
update,
variables: { marketId: market?.id || '' },
skip: !market?.id,
});
return (
<HeaderStat
heading={t('Status')}
description={useGetMarketStateTooltip(marketState ?? undefined)}
description={useGetMarketStateTooltip(marketState)}
testId="market-state"
>
{marketState ? Schema.MarketStateMapping[marketState] : '-'}
@ -20,7 +50,7 @@ export const MarketState = ({ marketId }: { marketId?: string }) => {
);
};
const useGetMarketStateTooltip = (state?: Schema.MarketState) => {
const useGetMarketStateTooltip = (state: Schema.MarketState | null) => {
const t = useT();
if (state === Schema.MarketState.STATE_ACTIVE) {
return t('Enactment date reached and usual auction exit checks pass');

View File

@ -26,15 +26,20 @@ const getTradingModeLabel = (
interface HeaderStatMarketTradingModeProps {
marketId?: string;
onSelect?: (marketId: string, metaKey?: boolean) => void;
initialTradingMode?: Schema.MarketTradingMode;
initialTrigger?: Schema.AuctionTrigger;
}
export const HeaderStatMarketTradingMode = ({
marketId,
onSelect,
initialTradingMode,
initialTrigger,
}: HeaderStatMarketTradingModeProps) => {
const t = useT();
const { data } = useStaticMarketData(marketId);
const { marketTradingMode, trigger } = data || {};
const marketTradingMode = data?.marketTradingMode ?? initialTradingMode;
const trigger = data?.trigger ?? initialTrigger;
return (
<HeaderStat
@ -51,6 +56,8 @@ export const HeaderStatMarketTradingMode = ({
export const MarketTradingMode = ({
marketId,
initialTradingMode,
initialTrigger,
inViewRoot,
}: Omit<HeaderStatMarketTradingModeProps, 'onUpdate'> & {
inViewRoot?: RefObject<Element>;
@ -65,7 +72,10 @@ export const MarketTradingMode = ({
}
>
<span ref={ref}>
{getTradingModeLabel(data?.marketTradingMode, data?.trigger)}
{getTradingModeLabel(
data?.marketTradingMode ?? initialTradingMode,
data?.trigger ?? initialTrigger
)}
</span>
</Tooltip>
);

View File

@ -1,11 +1,7 @@
import { render, screen, waitFor, within } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { NodeHealthContainer, NodeUrl } from './node-health';
import { MockedProvider, type MockedResponse } from '@apollo/client/testing';
import {
NodeCheckDocument,
type NodeCheckQuery,
} from '@vegaprotocol/environment';
import { MockedProvider } from '@apollo/client/testing';
const mockSetNodeSwitcher = jest.fn();
@ -19,50 +15,20 @@ jest.mock('@vegaprotocol/environment', () => ({
}));
describe('NodeHealthContainer', () => {
const blockHeight = '1';
const nodeCheckMock: MockedResponse<NodeCheckQuery, never> = {
request: {
query: NodeCheckDocument,
},
result: {
data: {
statistics: {
chainId: 'chain-id',
blockHeight: blockHeight,
vegaTime: '12345',
},
networkParametersConnection: {
edges: [
{
node: {
key: 'a',
value: '1',
},
},
],
},
},
},
};
const renderComponent = (mocks: MockedResponse[] = []) => {
return render(
<MockedProvider mocks={mocks}>
<NodeHealthContainer />
</MockedProvider>
);
};
it('controls the node switcher dialog', async () => {
renderComponent([nodeCheckMock]);
expect(await screen.findByRole('button')).toBeInTheDocument();
render(<NodeHealthContainer />, { wrapper: MockedProvider });
await waitFor(() => {
expect(screen.getByRole('button')).toBeInTheDocument();
});
await userEvent.click(screen.getByRole('button'));
expect(mockSetNodeSwitcher).toHaveBeenCalled();
});
it('Shows node health data on hover', async () => {
renderComponent([nodeCheckMock]);
expect(await screen.findByRole('button')).toBeInTheDocument();
render(<NodeHealthContainer />, { wrapper: MockedProvider });
await waitFor(() => {
expect(screen.getByRole('button')).toBeInTheDocument();
});
await userEvent.hover(screen.getByRole('button'));
await waitFor(() => {
const portal = within(
@ -70,13 +36,12 @@ describe('NodeHealthContainer', () => {
'[data-radix-popper-content-wrapper]'
) as HTMLElement
);
// two tooltips get rendered, I believe for animation purposes
const tooltip = within(portal.getAllByTestId('tooltip-content')[0]);
expect(
tooltip.getByRole('link', { name: /^Mainnet status & incidents/ })
).toBeInTheDocument();
expect(tooltip.getByText('Operational')).toBeInTheDocument();
expect(tooltip.getByText('Non operational')).toBeInTheDocument();
expect(tooltip.getByTitle('Connected node')).toHaveTextContent(
'vega-url.wtf'
);

View File

@ -1,6 +1,6 @@
import { OrderbookManager } from '@vegaprotocol/market-depth';
import { ViewType, useSidebar } from '../sidebar';
import { useDealTicketFormValues } from '@vegaprotocol/react-helpers';
import { useDealTicketFormValues } from '@vegaprotocol/deal-ticket';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
export const OrderbookContainer = ({ marketId }: { marketId: string }) => {

View File

@ -1,5 +1,5 @@
import { render, screen } from '@testing-library/react';
import { applyFilter } from './active-rewards';
import { ActiveRewardCard, applyFilter } from './active-rewards';
import {
AccountType,
AssetStatus,
@ -11,17 +11,6 @@ import {
type Transfer,
} from '@vegaprotocol/types';
import { type EnrichedRewardTransfer } from '../../lib/hooks/use-rewards';
import { ActiveRewardCard } from './reward-card';
jest.mock('../../lib/hooks/__generated__/Rewards', () => ({
useTWAPQuery: () => ({
data: {
timeWeightedNotionalPosition: {
timeWeightedNotionalPosition: '1.00',
},
},
}),
}));
describe('ActiveRewards', () => {
const reward: EnrichedRewardTransfer = {
@ -82,7 +71,7 @@ describe('ActiveRewards', () => {
};
it('renders with valid props', () => {
render(<ActiveRewardCard transferNode={reward} currentEpoch={115500} />);
render(<ActiveRewardCard transferNode={reward} currentEpoch={115432} />);
expect(
screen.getByText(/Liquidity provision fees received/i)

View File

@ -1,24 +1,57 @@
import { useT } from '../../lib/use-t';
import { addDecimalsFormatNumber, formatNumber } from '@vegaprotocol/utils';
import classNames from 'classnames';
import {
type VegaIconSize,
Tooltip,
VegaIcon,
VegaIconNames,
TradingInput,
TinyScroll,
truncateMiddle,
} from '@vegaprotocol/ui-toolkit';
import {
type TransferNode,
DistributionStrategyDescriptionMapping,
DistributionStrategyMapping,
EntityScope,
EntityScopeMapping,
DispatchMetric,
DispatchMetricDescription,
DispatchMetricLabels,
EntityScopeLabelMapping,
MarketState,
type DispatchStrategy,
IndividualScopeMapping,
IndividualScopeDescriptionMapping,
AccountType,
DistributionStrategy,
IndividualScope,
type Asset,
} from '@vegaprotocol/types';
import { Card } from '../card/card';
import { useState } from 'react';
import { type AssetFieldsFragment } from '@vegaprotocol/assets';
import { type ReactNode, useState } from 'react';
import {
type AssetFieldsFragment,
type BasicAssetDetails,
} from '@vegaprotocol/assets';
import { type MarketFieldsFragment } from '@vegaprotocol/markets';
import { useRewards } from '../../lib/hooks/use-rewards';
import { useMyTeam } from '../../lib/hooks/use-my-team';
import { useVegaWallet } from '@vegaprotocol/wallet-react';
import { useStakeAvailable } from '../../lib/hooks/use-stake-available';
import { ActiveRewardCard, areAllMarketsSettled } from './reward-card';
import {
type EnrichedRewardTransfer,
useRewards,
} from '../../lib/hooks/use-rewards';
import compact from 'lodash/compact';
enum CardColour {
BLUE = 'BLUE',
GREEN = 'GREEN',
GREY = 'GREY',
ORANGE = 'ORANGE',
PINK = 'PINK',
PURPLE = 'PURPLE',
WHITE = 'WHITE',
YELLOW = 'YELLOW',
}
export type Filter = {
searchTerm: string;
@ -38,10 +71,7 @@ export const applyFilter = (
return true;
}
if (
transfer.kind.__typename !== 'RecurringTransfer' &&
transfer.kind.__typename !== 'RecurringGovernanceTransfer'
) {
if (transfer.kind.__typename !== 'RecurringTransfer') {
return false;
}
@ -80,18 +110,6 @@ export const ActiveRewards = ({ currentEpoch }: { currentEpoch: number }) => {
const { data } = useRewards({
onlyActive: true,
});
const { pubKey } = useVegaWallet();
const { team } = useMyTeam();
const { stakeAvailable, isEligible, requiredStake } = useStakeAvailable();
const requirements = pubKey
? {
isEligible,
stakeAvailable,
requiredStake,
team,
pubKey,
}
: undefined;
const [filter, setFilter] = useState<Filter>({
searchTerm: '',
@ -117,26 +135,713 @@ export const ActiveRewards = ({ currentEpoch }: { currentEpoch: number }) => {
'Search by reward dispatch metric, entity scope or asset name'
)}
data-testid="search-term"
className="mb-4 w-20 mr-2 max-w-xl"
className="mb-4 w-20 mr-2"
prependElement={<VegaIcon name={VegaIconNames.SEARCH} />}
/>
)}
{/** CARDS */}
<div className="grid gap-x-8 gap-y-10 h-fit grid-cols-[repeat(auto-fill,_minmax(230px,_1fr))] md:grid-cols-[repeat(auto-fill,_minmax(230px,_1fr))] lg:grid-cols-[repeat(auto-fill,_minmax(320px,_1fr))] xl:grid-cols-[repeat(auto-fill,_minmax(335px,_1fr))] pr-2">
<TinyScroll className="grid gap-x-8 gap-y-10 h-fit grid-cols-[repeat(auto-fill,_minmax(230px,_1fr))] md:grid-cols-[repeat(auto-fill,_minmax(230px,_1fr))] lg:grid-cols-[repeat(auto-fill,_minmax(320px,_1fr))] xl:grid-cols-[repeat(auto-fill,_minmax(335px,_1fr))] max-h-[40rem] overflow-auto pr-2">
{data
.filter((n) => applyFilter(n, filter))
// filter out the cards (rewards) for which all of the markets
// are settled
.filter((n) => !areAllMarketsSettled(n))
.map((node, i) => (
<ActiveRewardCard
key={i}
transferNode={node}
currentEpoch={currentEpoch}
requirements={requirements}
/>
))}
</div>
</TinyScroll>
</Card>
);
};
type ActiveRewardCardProps = {
transferNode: EnrichedRewardTransfer;
currentEpoch: number;
};
export const ActiveRewardCard = ({
transferNode,
currentEpoch,
}: ActiveRewardCardProps) => {
// don't display the cards that are scoped to not trading markets
const marketSettled = transferNode.markets?.filter(
(m) =>
m?.state &&
[
MarketState.STATE_TRADING_TERMINATED,
MarketState.STATE_SETTLED,
MarketState.STATE_CANCELLED,
MarketState.STATE_CLOSED,
].includes(m.state)
);
// hide the card if all of the markets are being marked as e.g. settled
if (
marketSettled?.length === transferNode.markets?.length &&
Boolean(transferNode.markets && transferNode.markets.length > 0)
) {
return null;
}
if (
!transferNode.transfer.kind.dispatchStrategy &&
transferNode.transfer.toAccountType ===
AccountType.ACCOUNT_TYPE_GLOBAL_REWARD
) {
return (
<StakingRewardCard
colour={CardColour.WHITE}
rewardAmount={addDecimalsFormatNumber(
transferNode.transfer.amount,
transferNode.transfer.asset?.decimals || 0,
6
)}
rewardAsset={transferNode.transfer.asset || undefined}
endsIn={
transferNode.transfer.kind.endEpoch != null
? transferNode.transfer.kind.endEpoch - currentEpoch
: undefined
}
/>
);
}
let colour =
DispatchMetricColourMap[
transferNode.transfer.kind.dispatchStrategy.dispatchMetric
];
// grey out of any of the markets is suspended or
// if the asset is not currently traded on any of the active markets
const marketSuspended =
transferNode.markets?.filter(
(m) =>
m?.state === MarketState.STATE_SUSPENDED ||
m?.state === MarketState.STATE_SUSPENDED_VIA_GOVERNANCE
).length === transferNode.markets?.length &&
Boolean(transferNode.markets && transferNode.markets.length > 0);
if (marketSuspended || !transferNode.isAssetTraded) {
colour = CardColour.GREY;
}
return (
<RewardCard
colour={colour}
rewardAmount={addDecimalsFormatNumber(
transferNode.transfer.amount,
transferNode.transfer.asset?.decimals || 0,
6
)}
rewardAsset={transferNode.dispatchAsset}
transferAsset={transferNode.transfer.asset || undefined}
endsIn={
transferNode.transfer.kind.endEpoch != null
? transferNode.transfer.kind.endEpoch - currentEpoch
: undefined
}
dispatchStrategy={transferNode.transfer.kind.dispatchStrategy}
dispatchMetricInfo={<DispatchMetricInfo reward={transferNode} />}
/>
);
};
const RewardCard = ({
colour,
rewardAmount,
rewardAsset,
transferAsset,
vegaAsset,
dispatchStrategy,
endsIn,
dispatchMetricInfo,
}: {
colour: CardColour;
rewardAmount: string;
/** The asset linked to the dispatch strategy via `dispatchMetricAssetId` property. */
rewardAsset?: BasicAssetDetails;
/** The VEGA asset details, required to format the min staking amount. */
transferAsset?: Asset | undefined;
/** The VEGA asset details, required to format the min staking amount. */
vegaAsset?: BasicAssetDetails;
/** The transfer's dispatch strategy. */
dispatchStrategy: DispatchStrategy;
/** The number of epochs until the transfer stops. */
endsIn?: number;
dispatchMetricInfo?: ReactNode;
}) => {
const t = useT();
return (
<div>
<div
className={classNames(
'bg-gradient-to-r col-span-full p-0.5 lg:col-auto h-full',
'rounded-lg',
CardColourStyles[colour].gradientClassName
)}
data-testid="active-rewards-card"
>
<div
className={classNames(
CardColourStyles[colour].mainClassName,
'bg-gradient-to-b bg-vega-clight-800 dark:bg-vega-cdark-800 h-full w-full rounded-md p-4 flex flex-col gap-4'
)}
>
<div className="flex justify-between gap-4">
{/** ENTITY SCOPE */}
<div className="flex flex-col gap-2 items-center text-center">
<EntityIcon entityScope={dispatchStrategy.entityScope} />
{dispatchStrategy.entityScope && (
<span className="text-muted text-xs" data-testid="entity-scope">
{EntityScopeLabelMapping[dispatchStrategy.entityScope] ||
t('Unspecified')}
</span>
)}
</div>
{/** AMOUNT AND DISTRIBUTION STRATEGY */}
<div className="flex flex-col gap-2 items-center text-center">
{/** AMOUNT */}
<h3 className="flex flex-col gap-1 text-2xl shrink-1 text-center">
<span className="font-glitch" data-testid="reward-value">
{rewardAmount}
</span>
<span className="font-alpha" data-testid="reward-asset">
{transferAsset?.symbol || ''}
</span>
</h3>
{/** DISTRIBUTION STRATEGY */}
<Tooltip
description={t(
DistributionStrategyDescriptionMapping[
dispatchStrategy.distributionStrategy
]
)}
underline={true}
>
<span className="text-xs" data-testid="distribution-strategy">
{
DistributionStrategyMapping[
dispatchStrategy.distributionStrategy
]
}
</span>
</Tooltip>
</div>
{/** DISTRIBUTION DELAY */}
<div className="flex flex-col gap-2 items-center text-center">
<CardIcon
iconName={VegaIconNames.LOCK}
tooltip={t(
'Number of epochs after distribution to delay vesting of rewards by'
)}
/>
<span
className="text-muted text-xs whitespace-nowrap"
data-testid="locked-for"
>
{t('numberEpochs', '{{count}} epochs', {
count: dispatchStrategy.lockPeriod,
})}
</span>
</div>
</div>
<span className="border-[0.5px] dark:border-vega-cdark-500 border-vega-clight-500" />
{/** DISPATCH METRIC */}
{dispatchMetricInfo ? (
dispatchMetricInfo
) : (
<span data-testid="dispatch-metric-info">
{DispatchMetricLabels[dispatchStrategy.dispatchMetric]}
</span>
)}
<div className="flex items-center gap-8 flex-wrap">
{/** ENDS IN */}
{endsIn != null && (
<span className="flex flex-col">
<span className="text-muted text-xs">{t('Ends in')} </span>
<span data-testid="ends-in" data-endsin={endsIn}>
{endsIn >= 0
? t('numberEpochs', '{{count}} epochs', {
count: endsIn,
})
: t('Ended')}
</span>
</span>
)}
{/** WINDOW LENGTH */}
<span className="flex flex-col">
<span className="text-muted text-xs">{t('Assessed over')}</span>
<span data-testid="assessed-over">
{t('numberEpochs', '{{count}} epochs', {
count: dispatchStrategy.windowLength,
})}
</span>
</span>
</div>
{/** DISPATCH METRIC DESCRIPTION */}
{dispatchStrategy?.dispatchMetric && (
<p className="text-muted text-sm h-[3rem]">
{t(DispatchMetricDescription[dispatchStrategy?.dispatchMetric])}
</p>
)}
<span className="border-[0.5px] dark:border-vega-cdark-500 border-vega-clight-500" />
{/** REQUIREMENTS */}
{dispatchStrategy && (
<RewardRequirements
dispatchStrategy={dispatchStrategy}
rewardAsset={rewardAsset}
vegaAsset={vegaAsset}
/>
)}
</div>
</div>
</div>
);
};
const StakingRewardCard = ({
colour,
rewardAmount,
rewardAsset,
endsIn,
}: {
colour: CardColour;
rewardAmount: string;
/** The asset linked to the dispatch strategy via `dispatchMetricAssetId` property. */
rewardAsset?: Asset;
/** The number of epochs until the transfer stops. */
endsIn?: number;
/** The VEGA asset details, required to format the min staking amount. */
vegaAsset?: BasicAssetDetails;
}) => {
const t = useT();
return (
<div>
<div
className={classNames(
'bg-gradient-to-r col-span-full p-0.5 lg:col-auto h-full',
'rounded-lg',
CardColourStyles[colour].gradientClassName
)}
data-testid="active-rewards-card"
>
<div
className={classNames(
CardColourStyles[colour].mainClassName,
'bg-gradient-to-b bg-vega-clight-800 dark:bg-vega-cdark-800 h-full w-full rounded-md p-4 flex flex-col gap-4'
)}
>
<div className="flex justify-between gap-4">
{/** ENTITY SCOPE */}
<div className="flex flex-col gap-2 items-center text-center">
<EntityIcon entityScope={EntityScope.ENTITY_SCOPE_INDIVIDUALS} />
{
<span className="text-muted text-xs" data-testid="entity-scope">
{EntityScopeLabelMapping[
EntityScope.ENTITY_SCOPE_INDIVIDUALS
] || t('Unspecified')}
</span>
}
</div>
{/** AMOUNT AND DISTRIBUTION STRATEGY */}
<div className="flex flex-col gap-2 items-center text-center">
{/** AMOUNT */}
<h3 className="flex flex-col gap-1 text-2xl shrink-1 text-center">
<span className="font-glitch" data-testid="reward-value">
{rewardAmount}
</span>
<span className="font-alpha">{rewardAsset?.symbol || ''}</span>
</h3>
{/** DISTRIBUTION STRATEGY */}
<Tooltip
description={t(
DistributionStrategyDescriptionMapping[
DistributionStrategy.DISTRIBUTION_STRATEGY_PRO_RATA
]
)}
underline={true}
>
<span className="text-xs" data-testid="distribution-strategy">
{
DistributionStrategyMapping[
DistributionStrategy.DISTRIBUTION_STRATEGY_PRO_RATA
]
}
</span>
</Tooltip>
</div>
{/** DISTRIBUTION DELAY */}
<div className="flex flex-col gap-2 items-center text-center">
<CardIcon
iconName={VegaIconNames.LOCK}
tooltip={t(
'Number of epochs after distribution to delay vesting of rewards by'
)}
/>
<span
className="text-muted text-xs whitespace-nowrap"
data-testid="locked-for"
>
{t('numberEpochs', '{{count}} epochs', {
count: 0,
})}
</span>
</div>
</div>
<span className="border-[0.5px] dark:border-vega-cdark-500 border-vega-clight-500" />
{/** DISPATCH METRIC */}
{
<span data-testid="dispatch-metric-info">
{t('Staking rewards')}
</span>
}
<div className="flex items-center gap-8 flex-wrap">
{/** ENDS IN */}
{endsIn != null && (
<span className="flex flex-col">
<span className="text-muted text-xs">{t('Ends in')} </span>
<span data-testid="ends-in" data-endsin={endsIn}>
{endsIn >= 0
? t('numberEpochs', '{{count}} epochs', {
count: endsIn,
})
: t('Ended')}
</span>
</span>
)}
{/** WINDOW LENGTH */}
<span className="flex flex-col">
<span className="text-muted text-xs">{t('Assessed over')}</span>
<span data-testid="assessed-over">
{t('numberEpochs', '{{count}} epochs', {
count: 1,
})}
</span>
</span>
</div>
{/** DISPATCH METRIC DESCRIPTION */}
{
<p className="text-muted text-sm h-[3rem]">
{t(
'Global staking reward for staking $VEGA on the network via the Governance app'
)}
</p>
}
<span className="border-[0.5px] dark:border-vega-cdark-500 border-vega-clight-500" />
{/** REQUIREMENTS */}
<dl className="flex justify-between flex-wrap items-center gap-3 text-xs">
<div className="flex flex-col gap-1">
<dt className="flex items-center gap-1 text-muted">
{t('Team scope')}
</dt>
<dd className="flex items-center gap-1" data-testid="scope">
<Tooltip
description={
IndividualScopeDescriptionMapping[
IndividualScope.INDIVIDUAL_SCOPE_ALL
]
}
>
<span>{t('Individual')}</span>
</Tooltip>
</dd>
</div>
<div className="flex flex-col gap-1">
<dt className="flex items-center gap-1 text-muted">
{t('Staked VEGA')}
</dt>
<dd
className="flex items-center gap-1"
data-testid="staking-requirement"
>
{formatNumber(1, 2)}
</dd>
</div>
<div className="flex flex-col gap-1">
<dt className="flex items-center gap-1 text-muted">
{t('Average position')}
</dt>
<dd
className="flex items-center gap-1"
data-testid="average-position"
>
{formatNumber(0, 2)}
</dd>
</div>
</dl>
</div>
</div>
</div>
);
};
export const DispatchMetricInfo = ({
reward,
}: {
reward: EnrichedRewardTransfer;
}) => {
const t = useT();
const dispatchStrategy = reward.transfer.kind.dispatchStrategy;
const marketNames = compact(
reward.markets?.map((m) => m.tradableInstrument.instrument.name)
);
let additionalDispatchMetricInfo = null;
// if asset found then display asset symbol
if (reward.dispatchAsset) {
additionalDispatchMetricInfo = <span>{reward.dispatchAsset.symbol}</span>;
}
// but if scoped to only one market then display market name
if (marketNames.length === 1) {
additionalDispatchMetricInfo = <span>{marketNames[0]}</span>;
}
// or if scoped to many markets then indicate it's scoped to "specific markets"
if (marketNames.length > 1) {
additionalDispatchMetricInfo = (
<Tooltip description={marketNames}>
<span>{t('Specific markets')}</span>
</Tooltip>
);
}
return (
<span data-testid="dispatch-metric-info">
{DispatchMetricLabels[dispatchStrategy.dispatchMetric]}
{additionalDispatchMetricInfo != null && (
<> {additionalDispatchMetricInfo}</>
)}
</span>
);
};
const RewardRequirements = ({
dispatchStrategy,
rewardAsset,
vegaAsset,
}: {
dispatchStrategy: DispatchStrategy;
rewardAsset?: BasicAssetDetails;
vegaAsset?: BasicAssetDetails;
}) => {
const t = useT();
const entityLabel = EntityScopeLabelMapping[dispatchStrategy.entityScope];
return (
<dl className="flex justify-between flex-wrap items-center gap-3 text-xs">
<div className="flex flex-col gap-1">
<dt className="flex items-center gap-1 text-muted">
{entityLabel
? t('{{entity}} scope', {
entity: entityLabel,
})
: t('Scope')}
</dt>
<dd className="flex items-center gap-1" data-testid="scope">
<RewardEntityScope dispatchStrategy={dispatchStrategy} />
</dd>
</div>
<div className="flex flex-col gap-1">
<dt className="flex items-center gap-1 text-muted">
{t('Staked VEGA')}
</dt>
<dd
className="flex items-center gap-1"
data-testid="staking-requirement"
>
{addDecimalsFormatNumber(
dispatchStrategy?.stakingRequirement || 0,
vegaAsset?.decimals || 18
)}
</dd>
</div>
<div className="flex flex-col gap-1">
<dt className="flex items-center gap-1 text-muted">
{t('Average position')}
</dt>
<dd className="flex items-center gap-1" data-testid="average-position">
{addDecimalsFormatNumber(
dispatchStrategy?.notionalTimeWeightedAveragePositionRequirement ||
0,
rewardAsset?.decimals || 0
)}
</dd>
</div>
</dl>
);
};
const RewardEntityScope = ({
dispatchStrategy,
}: {
dispatchStrategy: DispatchStrategy;
}) => {
const t = useT();
if (dispatchStrategy.entityScope === EntityScope.ENTITY_SCOPE_TEAMS) {
return (
<Tooltip
description={
dispatchStrategy.teamScope?.length ? (
<div className="text-xs">
<p className="mb-1">{t('Eligible teams')}</p>
<ul>
{dispatchStrategy.teamScope.map((teamId) => {
if (!teamId) return null;
return <li key={teamId}>{truncateMiddle(teamId)}</li>;
})}
</ul>
</div>
) : (
t('All teams are eligible')
)
}
>
<span>
{dispatchStrategy.teamScope?.length
? t('Some teams')
: t('All teams')}
</span>
</Tooltip>
);
}
if (
dispatchStrategy.entityScope === EntityScope.ENTITY_SCOPE_INDIVIDUALS &&
dispatchStrategy.individualScope
) {
return (
<Tooltip
description={
IndividualScopeDescriptionMapping[dispatchStrategy.individualScope]
}
>
<span>{IndividualScopeMapping[dispatchStrategy.individualScope]}</span>
</Tooltip>
);
}
return t('Unspecified');
};
const CardColourStyles: Record<
CardColour,
{ gradientClassName: string; mainClassName: string }
> = {
[CardColour.BLUE]: {
gradientClassName: 'from-vega-blue-500 to-vega-green-400',
mainClassName: 'from-vega-blue-400 dark:from-vega-blue-600 to-20%',
},
[CardColour.GREEN]: {
gradientClassName: 'from-vega-green-500 to-vega-yellow-500',
mainClassName: 'from-vega-green-400 dark:from-vega-green-600 to-20%',
},
[CardColour.GREY]: {
gradientClassName: 'from-vega-cdark-500 to-vega-clight-200',
mainClassName: 'from-vega-cdark-400 dark:from-vega-cdark-600 to-20%',
},
[CardColour.ORANGE]: {
gradientClassName: 'from-vega-orange-500 to-vega-pink-400',
mainClassName: 'from-vega-orange-400 dark:from-vega-orange-600 to-20%',
},
[CardColour.PINK]: {
gradientClassName: 'from-vega-pink-500 to-vega-purple-400',
mainClassName: 'from-vega-pink-400 dark:from-vega-pink-600 to-20%',
},
[CardColour.PURPLE]: {
gradientClassName: 'from-vega-purple-500 to-vega-blue-400',
mainClassName: 'from-vega-purple-400 dark:from-vega-purple-600 to-20%',
},
[CardColour.WHITE]: {
gradientClassName:
'from-vega-clight-600 dark:from-vega-clight-900 to-vega-yellow-500 dark:to-vega-yellow-400',
mainClassName: 'from-white dark:from-vega-clight-100 to-20%',
},
[CardColour.YELLOW]: {
gradientClassName: 'from-vega-yellow-500 to-vega-orange-400',
mainClassName: 'from-vega-yellow-400 dark:from-vega-yellow-600 to-20%',
},
};
const DispatchMetricColourMap: Record<DispatchMetric, CardColour> = {
// Liquidity provision fees received
[DispatchMetric.DISPATCH_METRIC_LP_FEES_RECEIVED]: CardColour.BLUE,
// Price maker fees paid
[DispatchMetric.DISPATCH_METRIC_MAKER_FEES_PAID]: CardColour.PINK,
// Price maker fees earned
[DispatchMetric.DISPATCH_METRIC_MAKER_FEES_RECEIVED]: CardColour.GREEN,
// Total market value
[DispatchMetric.DISPATCH_METRIC_MARKET_VALUE]: CardColour.WHITE,
// Average position
[DispatchMetric.DISPATCH_METRIC_AVERAGE_POSITION]: CardColour.ORANGE,
// Relative return
[DispatchMetric.DISPATCH_METRIC_RELATIVE_RETURN]: CardColour.PURPLE,
// Return volatility
[DispatchMetric.DISPATCH_METRIC_RETURN_VOLATILITY]: CardColour.YELLOW,
// Validator ranking
[DispatchMetric.DISPATCH_METRIC_VALIDATOR_RANKING]: CardColour.WHITE,
};
const CardIcon = ({
size = 18,
iconName,
tooltip,
}: {
size?: VegaIconSize;
iconName: VegaIconNames;
tooltip: string;
}) => {
return (
<Tooltip description={<span>{tooltip}</span>}>
<span className="flex items-center p-2 rounded-full border border-gray-600">
<VegaIcon name={iconName} size={size} />
</span>
</Tooltip>
);
};
const EntityScopeIconMap: Record<EntityScope, VegaIconNames> = {
[EntityScope.ENTITY_SCOPE_TEAMS]: VegaIconNames.TEAM,
[EntityScope.ENTITY_SCOPE_INDIVIDUALS]: VegaIconNames.MAN,
};
const EntityIcon = ({
entityScope,
size = 18,
}: {
entityScope: EntityScope;
size?: VegaIconSize;
}) => {
return (
<Tooltip
description={
entityScope ? <span>{EntityScopeMapping[entityScope]}</span> : undefined
}
>
<span className="flex items-center p-2 rounded-full border border-gray-600">
<VegaIcon
name={EntityScopeIconMap[entityScope] || VegaIconNames.QUESTION_MARK}
size={size}
/>
</span>
</Tooltip>
);
};

View File

@ -1,41 +0,0 @@
import { usePayoutPerRank } from './rank-table';
// Test case as per https://docs.google.com/spreadsheets/d/1RpWKnGEf4eYMxjI-feauRa9vWz3pNGdP05ejQrwWatg/
describe('usePayoutPerRank', () => {
it('should return payouts per person', () => {
const rankTable = [
{
startRank: 1,
shareRatio: 10,
},
{
startRank: 2,
shareRatio: 5,
},
{
startRank: 5,
shareRatio: 5,
},
{
startRank: 10,
shareRatio: 3,
},
{
startRank: 20,
shareRatio: 0,
},
];
const result = usePayoutPerRank(rankTable);
expect(result).toEqual({
numPayouts: [1, 3, 5, 10, 0],
ratioShares: [10, 15, 25, 30, 0],
payoutsPerTier: [0.125, 0.1875, 0.3125, 0.375, 0],
payoutsPerWinner: [0.125, 0.0625, 0.0625, 0.0375],
payoutsPerWinnerAsPercentage: [12.5, 6.25, 6.25, 3.75],
endRanks: [2, 5, 10, 20],
startRanks: [1, 2, 5, 10, 20],
});
});
});

View File

@ -1,184 +0,0 @@
import type { RankTable } from '@vegaprotocol/types';
import { formatNumber } from '@vegaprotocol/utils';
import { useT } from '../../lib/use-t';
export const RankPayoutTable = ({
rankTable,
}: {
rankTable: (RankTable | null)[] | null;
}) => {
const t = useT();
const { payoutsPerWinnerAsPercentage, numPayouts, endRanks } =
usePayoutPerRank(rankTable);
let isOpenFinalTier = false;
return (
rankTable &&
rankTable.length > 0 && (
<>
<table className="min-w-full divide-y divide-gray-200">
<thead className="">
<tr className="text-right text-xs divide-x">
<th scope="col">
<span className="flex p-1 w-full justify-end">
{t('Rank tier')}
</span>
</th>
<th scope="col">
<span className="flex p-1 w-full justify-end">
{t('Start rank')}
</span>
</th>
<th scope="col">
<span className="flex p-1 w-full justify-end">
{t('End rank')}
</span>
</th>
<th scope="col">
<span className="flex p-1 w-full justify-end">
{t('Places paid')}
</span>
</th>
<th scope="col">
<span className="flex p-1 w-full justify-end">
{t('Payout')}
</span>
</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-500 text-xs">
{rankTable?.map((rank: RankTable | null, tier: number) => {
const endRank = endRanks?.[tier];
const placesPaid = numPayouts?.[tier];
const isFinalTier = tier === rankTable.length - 1;
isOpenFinalTier =
isFinalTier && rank ? rank.shareRatio > 0 : false;
if (isFinalTier && rank?.shareRatio === 0) {
return null;
}
return (
rank && (
<tr
key={`rank-table-row-${tier}`}
className="whitespace-nowrap text-right divide-x p-4"
>
<td>
<span className="flex p-1 justify-end">{tier + 1}</span>
</td>
<td>
<span className="flex p-1 justify-end">
{rank.startRank}
</span>
</td>
<td>
<span className="flex p-1 justify-end">
{endRank || 'TBC*'}
</span>
</td>
<td>
<span className="flex p-1 justify-end">
{placesPaid || 'TBC*'}
</span>
</td>
<td>
<span className="flex p-1 justify-end">
{payoutsPerWinnerAsPercentage?.[tier]
? `${formatNumber(
payoutsPerWinnerAsPercentage[tier],
2
)} %`
: 'TBC*'}
</span>
</td>
</tr>
)
);
})}
</tbody>
</table>
<p>
{isOpenFinalTier &&
t(
'*Note: Final tier will payout to all game participants, therefore all payout estimates will lower depending on how many participants there are.'
)}
</p>
</>
)
);
};
// Use rank table to calculate payouts per rank
// as per https://docs.google.com/spreadsheets/d/1RpWKnGEf4eYMxjI-feauRa9vWz3pNGdP05ejQrwWatg/
export const usePayoutPerRank = (
rankTable?: (RankTable | null)[] | null
): {
numPayouts?: number[];
startRanks?: number[];
endRanks?: number[];
ratioShares?: number[];
payoutsPerTier?: number[];
payoutsPerWinner?: number[];
payoutsPerWinnerAsPercentage?: number[];
} => {
if (!rankTable) return {};
const numPayouts: number[] = [],
ratioShares: number[] = [],
startRanks: number[] = [],
endRanks: number[] = [],
payoutsPerTier: number[] = [],
payoutsPerWinner: number[] = [],
payoutsPerWinnerAsPercentage: number[] = [];
let totalRatio = 0;
// We have to work out how many ppl in each bucket to get the total for the ratio
rankTable.forEach((rank, tier) => {
const startRank = rank?.startRank;
startRank && startRanks.push(startRank);
const endRank =
tier < rankTable.length - 1 ? rankTable[tier + 1]?.startRank : undefined;
endRank && endRanks.push(endRank);
const numPayout = endRank && startRank ? endRank - startRank : 0;
numPayouts.push(numPayout);
const shareRatio = rank?.shareRatio;
const ratioShare = shareRatio ? shareRatio * numPayout : 0;
ratioShares.push(ratioShare);
totalRatio += ratioShare;
});
rankTable.forEach((_rank, tier) => {
const ratioShare = ratioShares[tier];
// Then we multiply back out to get the total payout per tier
const payoutPerTierValue = totalRatio ? ratioShare / totalRatio : 0;
payoutsPerTier.push(payoutPerTierValue);
const numPayout = numPayouts[tier];
// And then divide by the payouts to get each individual winner payout
const payoutPerWinnerValue =
numPayout && payoutPerTierValue
? payoutPerTierValue / numPayout
: undefined;
payoutPerWinnerValue && payoutsPerWinner.push(payoutPerWinnerValue);
payoutPerWinnerValue &&
payoutsPerWinnerAsPercentage.push(payoutPerWinnerValue * 100);
});
return {
numPayouts,
ratioShares,
startRanks,
endRanks,
payoutsPerTier,
payoutsPerWinner,
payoutsPerWinnerAsPercentage,
};
};

File diff suppressed because it is too large Load Diff

View File

@ -246,19 +246,6 @@ export const RewardsContainer = () => {
})}
</div>
<div className="grid auto-rows-min grid-cols-6 gap-3">
<Card
title={t('Rewards history')}
className="lg:col-span-full hidden md:block"
loading={rewardsLoading}
noBackgroundOnMobile={true}
highlight={true}
>
<RewardsHistoryContainer
epoch={Number(epochData?.epoch.id)}
pubKey={pubKey}
assets={assetMap}
/>
</Card>
{pubKey && activityStreakBenefitTiers.tiers?.length > 0 && (
<Card
title={t('Activity Streak')}
@ -300,12 +287,24 @@ export const RewardsContainer = () => {
</Card>
)}
<ActiveRewards currentEpoch={Number(epochData?.epoch.id)} />
<Card
title={t('Rewards history')}
className="lg:col-span-full hidden md:block"
loading={rewardsLoading}
noBackgroundOnMobile={true}
>
<RewardsHistoryContainer
epoch={Number(epochData?.epoch.id)}
pubKey={pubKey}
assets={assetMap}
/>
</Card>
</div>
</div>
);
};
export type VestingBalances = NonNullable<
type VestingBalances = NonNullable<
RewardsPageQuery['party']
>['vestingBalancesSummary'];

View File

@ -96,7 +96,6 @@ export const VegaWalletConnectButton = ({
pubKeys={pubKeys}
activeKey={activeKey?.publicKey}
onSelect={selectPubKey}
isReadOnly={isReadOnly}
/>
<TradingDropdownSeparator />
{!isReadOnly && (
@ -142,13 +141,11 @@ const KeypairRadioGroup = ({
pubKeys,
activeKey,
onSelect,
isReadOnly,
}: {
pubKey: string | undefined;
pubKeys: Key[];
activeKey: string | undefined;
onSelect: (pubKey: string) => void;
isReadOnly: boolean;
}) => {
const { data } = usePartyProfilesQuery({
variables: { partyIds: pubKeys.map((pk) => pk.publicKey) },
@ -168,7 +165,6 @@ const KeypairRadioGroup = ({
pk={pk}
isActive={activeKey === pk.publicKey}
alias={profile?.node.alias}
isReadOnly={isReadOnly}
/>
);
})}
@ -180,12 +176,10 @@ const KeypairItem = ({
pk,
isActive,
alias,
isReadOnly,
}: {
pk: Key;
alias: string | undefined;
isActive: boolean;
isReadOnly: boolean;
}) => {
const t = useT();
const [copied, setCopied] = useCopyTimeout();
@ -216,18 +210,16 @@ const KeypairItem = ({
className={classNames('flex-1 mr-2 text-secondary text-sm')}
data-testid={`key-${pk.publicKey}`}
>
{!isReadOnly && (
<Tooltip description={t('Public facing key alias. Click to edit')}>
<button
data-testid="alias"
onClick={() => setOpen(pk.publicKey)}
className="flex items-center gap-1"
>
{alias ? alias : t('No alias')}
{isActive && <VegaIcon name={VegaIconNames.EDIT} />}
</button>
</Tooltip>
)}
<Tooltip description={t('Public facing key alias. Click to edit')}>
<button
data-testid="alias"
onClick={() => setOpen(pk.publicKey)}
className="flex items-center gap-1"
>
{alias ? alias : t('No alias')}
{isActive && <VegaIcon name={VegaIconNames.EDIT} />}
</button>
</Tooltip>
</div>
</div>
<TradingDropdownItemIndicator />

View File

@ -1,4 +1,3 @@
CONSOLE_IMAGE_NAME=vegaprotocol/trading:latest
VEGA_VERSION=v0.75.5
VEGA_VERSION=v0.75.0-preview.2
LOCAL_SERVER=false
VEGA_ENV=STAGNET1

View File

@ -1,4 +1,3 @@
CONSOLE_IMAGE_NAME=vegaprotocol/trading:develop
VEGA_VERSION=v0.75.5
VEGA_VERSION=v0.74.6
LOCAL_SERVER=false
VEGA_ENV=STAGNET1

View File

@ -1,4 +1,3 @@
CONSOLE_IMAGE_NAME=vegaprotocol/trading:main
VEGA_VERSION=v0.74.10
LOCAL_SERVER=false
VEGA_ENV=MAINNET
VEGA_VERSION=v0.73.13
LOCAL_SERVER=false

View File

@ -92,7 +92,7 @@ def init_vega(request=None):
"store_transactions": True,
"transactions_per_block": 1000,
"seconds_per_block": seconds_per_block,
"genesis_time": datetime.now() - timedelta(hours=1),
"genesis_time": datetime.now() - timedelta(days=1),
}
if port_config is not None:
@ -153,13 +153,10 @@ def init_page(vega: VegaServiceNull, browser: Browser, request: pytest.FixtureRe
raise e
# Set window._env_ so built app uses datanode from vega market sim
load_dotenv()
vega_env = os.getenv('VEGA_ENV')
env = json.dumps(
{
"VEGA_URL": f"http://localhost:{vega.data_node_rest_port}/graphql",
"VEGA_WALLET_URL": f"http://localhost:{vega.wallet_port}",
"VEGA_ENV": vega_env,
}
)
window_env = f"window._env_ = Object.assign({{}}, window._env_, {env})"

View File

@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
[[package]]
name = "certifi"
@ -253,13 +253,13 @@ testing = ["hatch", "pre-commit", "pytest", "tox"]
[[package]]
name = "googleapis-common-protos"
version = "1.63.0"
version = "1.62.0"
description = "Common protobufs used in Google APIs"
optional = false
python-versions = ">=3.7"
files = [
{file = "googleapis-common-protos-1.63.0.tar.gz", hash = "sha256:17ad01b11d5f1d0171c06d3ba5c04c54474e883b66b949722b4938ee2694ef4e"},
{file = "googleapis_common_protos-1.63.0-py2.py3-none-any.whl", hash = "sha256:ae45f75702f7c08b541f750854a678bd8f534a1a6bace6afe975f1d0a82d6632"},
{file = "googleapis-common-protos-1.62.0.tar.gz", hash = "sha256:83f0ece9f94e5672cced82f592d2a5edf527a96ed1794f0bab36d5735c996277"},
{file = "googleapis_common_protos-1.62.0-py2.py3-none-any.whl", hash = "sha256:4750113612205514f9f6aa4cb00d523a94f3e8c06c5ad2fee466387dc4875f07"},
]
[package.dependencies]
@ -341,135 +341,135 @@ test = ["objgraph", "psutil"]
[[package]]
name = "grpcio"
version = "1.62.1"
version = "1.62.0"
description = "HTTP/2-based RPC framework"
optional = false
python-versions = ">=3.7"
files = [
{file = "grpcio-1.62.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:179bee6f5ed7b5f618844f760b6acf7e910988de77a4f75b95bbfaa8106f3c1e"},
{file = "grpcio-1.62.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:48611e4fa010e823ba2de8fd3f77c1322dd60cb0d180dc6630a7e157b205f7ea"},
{file = "grpcio-1.62.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:b2a0e71b0a2158aa4bce48be9f8f9eb45cbd17c78c7443616d00abbe2a509f6d"},
{file = "grpcio-1.62.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fbe80577c7880911d3ad65e5ecc997416c98f354efeba2f8d0f9112a67ed65a5"},
{file = "grpcio-1.62.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58f6c693d446964e3292425e1d16e21a97a48ba9172f2d0df9d7b640acb99243"},
{file = "grpcio-1.62.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:77c339403db5a20ef4fed02e4d1a9a3d9866bf9c0afc77a42234677313ea22f3"},
{file = "grpcio-1.62.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b5a4ea906db7dec694098435d84bf2854fe158eb3cd51e1107e571246d4d1d70"},
{file = "grpcio-1.62.1-cp310-cp310-win32.whl", hash = "sha256:4187201a53f8561c015bc745b81a1b2d278967b8de35f3399b84b0695e281d5f"},
{file = "grpcio-1.62.1-cp310-cp310-win_amd64.whl", hash = "sha256:844d1f3fb11bd1ed362d3fdc495d0770cfab75761836193af166fee113421d66"},
{file = "grpcio-1.62.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:833379943d1728a005e44103f17ecd73d058d37d95783eb8f0b28ddc1f54d7b2"},
{file = "grpcio-1.62.1-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:c7fcc6a32e7b7b58f5a7d27530669337a5d587d4066060bcb9dee7a8c833dfb7"},
{file = "grpcio-1.62.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:fa7d28eb4d50b7cbe75bb8b45ed0da9a1dc5b219a0af59449676a29c2eed9698"},
{file = "grpcio-1.62.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:48f7135c3de2f298b833be8b4ae20cafe37091634e91f61f5a7eb3d61ec6f660"},
{file = "grpcio-1.62.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:71f11fd63365ade276c9d4a7b7df5c136f9030e3457107e1791b3737a9b9ed6a"},
{file = "grpcio-1.62.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4b49fd8fe9f9ac23b78437da94c54aa7e9996fbb220bac024a67469ce5d0825f"},
{file = "grpcio-1.62.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:482ae2ae78679ba9ed5752099b32e5fe580443b4f798e1b71df412abf43375db"},
{file = "grpcio-1.62.1-cp311-cp311-win32.whl", hash = "sha256:1faa02530b6c7426404372515fe5ddf66e199c2ee613f88f025c6f3bd816450c"},
{file = "grpcio-1.62.1-cp311-cp311-win_amd64.whl", hash = "sha256:5bd90b8c395f39bc82a5fb32a0173e220e3f401ff697840f4003e15b96d1befc"},
{file = "grpcio-1.62.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:b134d5d71b4e0837fff574c00e49176051a1c532d26c052a1e43231f252d813b"},
{file = "grpcio-1.62.1-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:d1f6c96573dc09d50dbcbd91dbf71d5cf97640c9427c32584010fbbd4c0e0037"},
{file = "grpcio-1.62.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:359f821d4578f80f41909b9ee9b76fb249a21035a061a327f91c953493782c31"},
{file = "grpcio-1.62.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a485f0c2010c696be269184bdb5ae72781344cb4e60db976c59d84dd6354fac9"},
{file = "grpcio-1.62.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b50b09b4dc01767163d67e1532f948264167cd27f49e9377e3556c3cba1268e1"},
{file = "grpcio-1.62.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3227c667dccbe38f2c4d943238b887bac588d97c104815aecc62d2fd976e014b"},
{file = "grpcio-1.62.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:3952b581eb121324853ce2b191dae08badb75cd493cb4e0243368aa9e61cfd41"},
{file = "grpcio-1.62.1-cp312-cp312-win32.whl", hash = "sha256:83a17b303425104d6329c10eb34bba186ffa67161e63fa6cdae7776ff76df73f"},
{file = "grpcio-1.62.1-cp312-cp312-win_amd64.whl", hash = "sha256:6696ffe440333a19d8d128e88d440f91fb92c75a80ce4b44d55800e656a3ef1d"},
{file = "grpcio-1.62.1-cp37-cp37m-linux_armv7l.whl", hash = "sha256:e3393b0823f938253370ebef033c9fd23d27f3eae8eb9a8f6264900c7ea3fb5a"},
{file = "grpcio-1.62.1-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:83e7ccb85a74beaeae2634f10eb858a0ed1a63081172649ff4261f929bacfd22"},
{file = "grpcio-1.62.1-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:882020c87999d54667a284c7ddf065b359bd00251fcd70279ac486776dbf84ec"},
{file = "grpcio-1.62.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a10383035e864f386fe096fed5c47d27a2bf7173c56a6e26cffaaa5a361addb1"},
{file = "grpcio-1.62.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:960edebedc6b9ada1ef58e1c71156f28689978188cd8cff3b646b57288a927d9"},
{file = "grpcio-1.62.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:23e2e04b83f347d0aadde0c9b616f4726c3d76db04b438fd3904b289a725267f"},
{file = "grpcio-1.62.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:978121758711916d34fe57c1f75b79cdfc73952f1481bb9583399331682d36f7"},
{file = "grpcio-1.62.1-cp37-cp37m-win_amd64.whl", hash = "sha256:9084086190cc6d628f282e5615f987288b95457292e969b9205e45b442276407"},
{file = "grpcio-1.62.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:22bccdd7b23c420a27fd28540fb5dcbc97dc6be105f7698cb0e7d7a420d0e362"},
{file = "grpcio-1.62.1-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:8999bf1b57172dbc7c3e4bb3c732658e918f5c333b2942243f10d0d653953ba9"},
{file = "grpcio-1.62.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:d9e52558b8b8c2f4ac05ac86344a7417ccdd2b460a59616de49eb6933b07a0bd"},
{file = "grpcio-1.62.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1714e7bc935780bc3de1b3fcbc7674209adf5208ff825799d579ffd6cd0bd505"},
{file = "grpcio-1.62.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8842ccbd8c0e253c1f189088228f9b433f7a93b7196b9e5b6f87dba393f5d5d"},
{file = "grpcio-1.62.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1f1e7b36bdff50103af95a80923bf1853f6823dd62f2d2a2524b66ed74103e49"},
{file = "grpcio-1.62.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:bba97b8e8883a8038606480d6b6772289f4c907f6ba780fa1f7b7da7dfd76f06"},
{file = "grpcio-1.62.1-cp38-cp38-win32.whl", hash = "sha256:a7f615270fe534548112a74e790cd9d4f5509d744dd718cd442bf016626c22e4"},
{file = "grpcio-1.62.1-cp38-cp38-win_amd64.whl", hash = "sha256:e6c8c8693df718c5ecbc7babb12c69a4e3677fd11de8886f05ab22d4e6b1c43b"},
{file = "grpcio-1.62.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:73db2dc1b201d20ab7083e7041946910bb991e7e9761a0394bbc3c2632326483"},
{file = "grpcio-1.62.1-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:407b26b7f7bbd4f4751dbc9767a1f0716f9fe72d3d7e96bb3ccfc4aace07c8de"},
{file = "grpcio-1.62.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:f8de7c8cef9261a2d0a62edf2ccea3d741a523c6b8a6477a340a1f2e417658de"},
{file = "grpcio-1.62.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd5c8a1af40ec305d001c60236308a67e25419003e9bb3ebfab5695a8d0b369"},
{file = "grpcio-1.62.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be0477cb31da67846a33b1a75c611f88bfbcd427fe17701b6317aefceee1b96f"},
{file = "grpcio-1.62.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:60dcd824df166ba266ee0cfaf35a31406cd16ef602b49f5d4dfb21f014b0dedd"},
{file = "grpcio-1.62.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:973c49086cabab773525f6077f95e5a993bfc03ba8fc32e32f2c279497780585"},
{file = "grpcio-1.62.1-cp39-cp39-win32.whl", hash = "sha256:12859468e8918d3bd243d213cd6fd6ab07208195dc140763c00dfe901ce1e1b4"},
{file = "grpcio-1.62.1-cp39-cp39-win_amd64.whl", hash = "sha256:b7209117bbeebdfa5d898205cc55153a51285757902dd73c47de498ad4d11332"},
{file = "grpcio-1.62.1.tar.gz", hash = "sha256:6c455e008fa86d9e9a9d85bb76da4277c0d7d9668a3bfa70dbe86e9f3c759947"},
{file = "grpcio-1.62.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:136ffd79791b1eddda8d827b607a6285474ff8a1a5735c4947b58c481e5e4271"},
{file = "grpcio-1.62.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:d6a56ba703be6b6267bf19423d888600c3f574ac7c2cc5e6220af90662a4d6b0"},
{file = "grpcio-1.62.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:4cd356211579043fce9f52acc861e519316fff93980a212c8109cca8f47366b6"},
{file = "grpcio-1.62.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e803e9b58d8f9b4ff0ea991611a8d51b31c68d2e24572cd1fe85e99e8cc1b4f8"},
{file = "grpcio-1.62.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f4c04fe33039b35b97c02d2901a164bbbb2f21fb9c4e2a45a959f0b044c3512c"},
{file = "grpcio-1.62.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:95370c71b8c9062f9ea033a0867c4c73d6f0ff35113ebd2618171ec1f1e903e0"},
{file = "grpcio-1.62.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c912688acc05e4ff012c8891803659d6a8a8b5106f0f66e0aed3fb7e77898fa6"},
{file = "grpcio-1.62.0-cp310-cp310-win32.whl", hash = "sha256:821a44bd63d0f04e33cf4ddf33c14cae176346486b0df08b41a6132b976de5fc"},
{file = "grpcio-1.62.0-cp310-cp310-win_amd64.whl", hash = "sha256:81531632f93fece32b2762247c4c169021177e58e725494f9a746ca62c83acaa"},
{file = "grpcio-1.62.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:3fa15850a6aba230eed06b236287c50d65a98f05054a0f01ccedf8e1cc89d57f"},
{file = "grpcio-1.62.0-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:36df33080cd7897623feff57831eb83c98b84640b016ce443305977fac7566fb"},
{file = "grpcio-1.62.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:7a195531828b46ea9c4623c47e1dc45650fc7206f8a71825898dd4c9004b0928"},
{file = "grpcio-1.62.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ab140a3542bbcea37162bdfc12ce0d47a3cda3f2d91b752a124cc9fe6776a9e2"},
{file = "grpcio-1.62.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f9d6c3223914abb51ac564dc9c3782d23ca445d2864321b9059d62d47144021"},
{file = "grpcio-1.62.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fbe0c20ce9a1cff75cfb828b21f08d0a1ca527b67f2443174af6626798a754a4"},
{file = "grpcio-1.62.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:38f69de9c28c1e7a8fd24e4af4264726637b72f27c2099eaea6e513e7142b47e"},
{file = "grpcio-1.62.0-cp311-cp311-win32.whl", hash = "sha256:ce1aafdf8d3f58cb67664f42a617af0e34555fe955450d42c19e4a6ad41c84bd"},
{file = "grpcio-1.62.0-cp311-cp311-win_amd64.whl", hash = "sha256:eef1d16ac26c5325e7d39f5452ea98d6988c700c427c52cbc7ce3201e6d93334"},
{file = "grpcio-1.62.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:8aab8f90b2a41208c0a071ec39a6e5dbba16fd827455aaa070fec241624ccef8"},
{file = "grpcio-1.62.0-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:62aa1659d8b6aad7329ede5d5b077e3d71bf488d85795db517118c390358d5f6"},
{file = "grpcio-1.62.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:0d7ae7fc7dbbf2d78d6323641ded767d9ec6d121aaf931ec4a5c50797b886532"},
{file = "grpcio-1.62.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f359d635ee9428f0294bea062bb60c478a8ddc44b0b6f8e1f42997e5dc12e2ee"},
{file = "grpcio-1.62.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:77d48e5b1f8f4204889f1acf30bb57c30378e17c8d20df5acbe8029e985f735c"},
{file = "grpcio-1.62.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:662d3df5314ecde3184cf87ddd2c3a66095b3acbb2d57a8cada571747af03873"},
{file = "grpcio-1.62.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:92cdb616be44c8ac23a57cce0243af0137a10aa82234f23cd46e69e115071388"},
{file = "grpcio-1.62.0-cp312-cp312-win32.whl", hash = "sha256:0b9179478b09ee22f4a36b40ca87ad43376acdccc816ce7c2193a9061bf35701"},
{file = "grpcio-1.62.0-cp312-cp312-win_amd64.whl", hash = "sha256:614c3ed234208e76991992342bab725f379cc81c7dd5035ee1de2f7e3f7a9842"},
{file = "grpcio-1.62.0-cp37-cp37m-linux_armv7l.whl", hash = "sha256:7e1f51e2a460b7394670fdb615e26d31d3260015154ea4f1501a45047abe06c9"},
{file = "grpcio-1.62.0-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:bcff647e7fe25495e7719f779cc219bbb90b9e79fbd1ce5bda6aae2567f469f2"},
{file = "grpcio-1.62.0-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:56ca7ba0b51ed0de1646f1735154143dcbdf9ec2dbe8cc6645def299bb527ca1"},
{file = "grpcio-1.62.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2e84bfb2a734e4a234b116be208d6f0214e68dcf7804306f97962f93c22a1839"},
{file = "grpcio-1.62.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c1488b31a521fbba50ae86423f5306668d6f3a46d124f7819c603979fc538c4"},
{file = "grpcio-1.62.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:98d8f4eb91f1ce0735bf0b67c3b2a4fea68b52b2fd13dc4318583181f9219b4b"},
{file = "grpcio-1.62.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:b3d3d755cfa331d6090e13aac276d4a3fb828bf935449dc16c3d554bf366136b"},
{file = "grpcio-1.62.0-cp37-cp37m-win_amd64.whl", hash = "sha256:a33f2bfd8a58a02aab93f94f6c61279be0f48f99fcca20ebaee67576cd57307b"},
{file = "grpcio-1.62.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:5e709f7c8028ce0443bddc290fb9c967c1e0e9159ef7a030e8c21cac1feabd35"},
{file = "grpcio-1.62.0-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:2f3d9a4d0abb57e5f49ed5039d3ed375826c2635751ab89dcc25932ff683bbb6"},
{file = "grpcio-1.62.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:62ccb92f594d3d9fcd00064b149a0187c246b11e46ff1b7935191f169227f04c"},
{file = "grpcio-1.62.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:921148f57c2e4b076af59a815467d399b7447f6e0ee10ef6d2601eb1e9c7f402"},
{file = "grpcio-1.62.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f897b16190b46bc4d4aaf0a32a4b819d559a37a756d7c6b571e9562c360eed72"},
{file = "grpcio-1.62.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:1bc8449084fe395575ed24809752e1dc4592bb70900a03ca42bf236ed5bf008f"},
{file = "grpcio-1.62.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:81d444e5e182be4c7856cd33a610154fe9ea1726bd071d07e7ba13fafd202e38"},
{file = "grpcio-1.62.0-cp38-cp38-win32.whl", hash = "sha256:88f41f33da3840b4a9bbec68079096d4caf629e2c6ed3a72112159d570d98ebe"},
{file = "grpcio-1.62.0-cp38-cp38-win_amd64.whl", hash = "sha256:fc2836cb829895ee190813446dce63df67e6ed7b9bf76060262c55fcd097d270"},
{file = "grpcio-1.62.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:fcc98cff4084467839d0a20d16abc2a76005f3d1b38062464d088c07f500d170"},
{file = "grpcio-1.62.0-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:0d3dee701e48ee76b7d6fbbba18ba8bc142e5b231ef7d3d97065204702224e0e"},
{file = "grpcio-1.62.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:b7a6be562dd18e5d5bec146ae9537f20ae1253beb971c0164f1e8a2f5a27e829"},
{file = "grpcio-1.62.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29cb592c4ce64a023712875368bcae13938c7f03e99f080407e20ffe0a9aa33b"},
{file = "grpcio-1.62.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1eda79574aec8ec4d00768dcb07daba60ed08ef32583b62b90bbf274b3c279f7"},
{file = "grpcio-1.62.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7eea57444a354ee217fda23f4b479a4cdfea35fb918ca0d8a0e73c271e52c09c"},
{file = "grpcio-1.62.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0e97f37a3b7c89f9125b92d22e9c8323f4e76e7993ba7049b9f4ccbe8bae958a"},
{file = "grpcio-1.62.0-cp39-cp39-win32.whl", hash = "sha256:39cd45bd82a2e510e591ca2ddbe22352e8413378852ae814549c162cf3992a93"},
{file = "grpcio-1.62.0-cp39-cp39-win_amd64.whl", hash = "sha256:b71c65427bf0ec6a8b48c68c17356cb9fbfc96b1130d20a07cb462f4e4dcdcd5"},
{file = "grpcio-1.62.0.tar.gz", hash = "sha256:748496af9238ac78dcd98cce65421f1adce28c3979393e3609683fcd7f3880d7"},
]
[package.extras]
protobuf = ["grpcio-tools (>=1.62.1)"]
protobuf = ["grpcio-tools (>=1.62.0)"]
[[package]]
name = "grpcio-tools"
version = "1.62.1"
version = "1.62.0"
description = "Protobuf code generator for gRPC"
optional = false
python-versions = ">=3.7"
files = [
{file = "grpcio-tools-1.62.1.tar.gz", hash = "sha256:a4991e5ee8a97ab791296d3bf7e8700b1445635cc1828cc98df945ca1802d7f2"},
{file = "grpcio_tools-1.62.1-cp310-cp310-linux_armv7l.whl", hash = "sha256:f2b404bcae7e2ef9b0b9803b2a95119eb7507e6dc80ea4a64a78be052c30cebc"},
{file = "grpcio_tools-1.62.1-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:fdd987a580b4474769adfd40144486f54bcc73838d5ec5d3647a17883ea78e76"},
{file = "grpcio_tools-1.62.1-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:07af1a6442e2313cff22af93c2c4dd37ae32b5239b38e0d99e2cbf93de65429f"},
{file = "grpcio_tools-1.62.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:41384c9ee18e61ef20cad2774ef71bd8854b63efce263b5177aa06fccb84df1f"},
{file = "grpcio_tools-1.62.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5c38006f7702d2ff52122e4c77a47348709374050c76216e84b30a9f06e45afa"},
{file = "grpcio_tools-1.62.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:08fecc3c5b4e6dd3278f2b9d12837e423c7dcff551ca1e587018b4a0fc5f8019"},
{file = "grpcio_tools-1.62.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a01e8dcd0f041f6fa6d815c54a2017d032950e310c41d514a8bc041e872c4d12"},
{file = "grpcio_tools-1.62.1-cp310-cp310-win32.whl", hash = "sha256:dd933b8e0b3c13fe3543d58f849a6a5e0d7987688cb6801834278378c724f695"},
{file = "grpcio_tools-1.62.1-cp310-cp310-win_amd64.whl", hash = "sha256:2b04844a9382f1bde4b4174e476e654ab3976168d2469cb4b29e352f4f35a5aa"},
{file = "grpcio_tools-1.62.1-cp311-cp311-linux_armv7l.whl", hash = "sha256:024380536ba71a96cdf736f0954f6ad03f5da609c09edbcc2ca02fdd639e0eed"},
{file = "grpcio_tools-1.62.1-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:21f14b99e0cd38ad56754cc0b62b2bf3cf75f9f7fc40647da54669e0da0726fe"},
{file = "grpcio_tools-1.62.1-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:975ac5fb482c23f3608c16e06a43c8bab4d79c2e2564cdbc25cf753c6e998775"},
{file = "grpcio_tools-1.62.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50739aaab0c8076ad5957204e71f2e0c9876e11fd8338f7f09de12c2d75163c5"},
{file = "grpcio_tools-1.62.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598c54318f0326cf5020aa43fc95a15e933aba4a71943d3bff2677d2d21ddfa1"},
{file = "grpcio_tools-1.62.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:f309bdb33a61f8e049480d41498ee2e525cfb5e959958b326abfdf552bf9b9cb"},
{file = "grpcio_tools-1.62.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f358effd3c11d66c150e0227f983d54a5cd30e14038566dadcf25f9f6844e6e8"},
{file = "grpcio_tools-1.62.1-cp311-cp311-win32.whl", hash = "sha256:b76aead9b73f1650a091870fe4e9ed15ac4d8ed136f962042367255199c23594"},
{file = "grpcio_tools-1.62.1-cp311-cp311-win_amd64.whl", hash = "sha256:d66a5d47eaa427039752fa0a83a425ff2a487b6a0ac30556fd3be2f3a27a0130"},
{file = "grpcio_tools-1.62.1-cp312-cp312-linux_armv7l.whl", hash = "sha256:575535d039b97d63e6a9abee626d6c7cd47bd8cb73dd00a5c84a98254a2164a4"},
{file = "grpcio_tools-1.62.1-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:22644c90e43d1a888477899af917979e17364fdd6e9bbb92679cd6a54c4d36c3"},
{file = "grpcio_tools-1.62.1-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:156d3e1b227c16e903003a56881dbe60e40f2b4bd66f0bc3b27c53e466e6384d"},
{file = "grpcio_tools-1.62.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5ad7c5691625a85327e5b683443baf73ae790fd5afc938252041ed5cd665e377"},
{file = "grpcio_tools-1.62.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e140bbc08eea8abf51c0274f45fb1e8350220e64758998d7f3c7f985a0b2496"},
{file = "grpcio_tools-1.62.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:7444fcab861911525470d398e5638b70d5cbea3b4674a3de92b5c58c5c515d4d"},
{file = "grpcio_tools-1.62.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e643cd14a5d1e59865cba68a5a6f0175d987f36c5f4cb0db80dee9ed60b4c174"},
{file = "grpcio_tools-1.62.1-cp312-cp312-win32.whl", hash = "sha256:1344a773d2caa9bb7fbea7e879b84f33740c808c34a5bd2a2768e526117a6b44"},
{file = "grpcio_tools-1.62.1-cp312-cp312-win_amd64.whl", hash = "sha256:2eea1db3748b2f37b4dce84d8e0c15d9bc811094807cabafe7b0ea47f424dfd5"},
{file = "grpcio_tools-1.62.1-cp37-cp37m-linux_armv7l.whl", hash = "sha256:45d2e6cf04d27286b6f73e6e20ba3f0a1f6d8f5535e5dcb1356200419bb457f4"},
{file = "grpcio_tools-1.62.1-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:46ae58e6926773e7315e9005f0f17aacedbc0895a8752bec087d24efa2f1fb21"},
{file = "grpcio_tools-1.62.1-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:4c28086df31478023a36f45e50767872ab3aed2419afff09814cb61c88b77db4"},
{file = "grpcio_tools-1.62.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a4fba5b339f4797548591036c9481e6895bf920fab7d3dc664d2697f8fb7c0bf"},
{file = "grpcio_tools-1.62.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23eb3d47f78f509fcd201749b1f1e44b76f447913f7fbb3b8bae20f109086295"},
{file = "grpcio_tools-1.62.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:fd5d47707bd6bc2b707ece765c362d2a1d2e8f6cd92b04c99fab49a929f3610c"},
{file = "grpcio_tools-1.62.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d1924a6a943df7c73b9ef0048302327c75962b567451479710da729ead241228"},
{file = "grpcio_tools-1.62.1-cp37-cp37m-win_amd64.whl", hash = "sha256:fe71ca30aabe42591e84ecb9694c0297dc699cc20c5b24d2cb267fb0fc01f947"},
{file = "grpcio_tools-1.62.1-cp38-cp38-linux_armv7l.whl", hash = "sha256:1819fd055c1ae672d1d725ec75eefd1f700c18acba0ed9332202be31d69c401d"},
{file = "grpcio_tools-1.62.1-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:5dbe1f7481dd14b6d477b4bace96d275090bc7636b9883975a08b802c94e7b78"},
{file = "grpcio_tools-1.62.1-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:771c051c5ece27ad03e4f2e33624a925f0ad636c01757ab7dbb04a37964af4ba"},
{file = "grpcio_tools-1.62.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:98209c438b38b6f1276dbc27b1c04e346a75bfaafe72a25a548f2dc5ce71d226"},
{file = "grpcio_tools-1.62.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2152308e5321cb90fb45aaa84d03d6dedb19735a8779aaf36c624f97b831842d"},
{file = "grpcio_tools-1.62.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ed1f27dc2b2262c8b8d9036276619c1bb18791311c16ccbf1f31b660f2aad7cf"},
{file = "grpcio_tools-1.62.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2744947b6c5e907af21133431809ccca535a037356864e32c122efed8cb9de1f"},
{file = "grpcio_tools-1.62.1-cp38-cp38-win32.whl", hash = "sha256:13b20e269d14ad629ff9a2c9a2450f3dbb119d5948de63b27ffe624fa7aea85a"},
{file = "grpcio_tools-1.62.1-cp38-cp38-win_amd64.whl", hash = "sha256:999823758e9eacd0095863d06cd6d388be769f80c9abb65cdb11c4f2cfce3fea"},
{file = "grpcio_tools-1.62.1-cp39-cp39-linux_armv7l.whl", hash = "sha256:941f8a5c31986053e75fa466bcfa743c2bf1b513b7978cf1f4ab4e96a8219d27"},
{file = "grpcio_tools-1.62.1-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:b9c02c88c77ef6057c6cbeea8922d7c2424aabf46bfc40ddf42a32765ba91061"},
{file = "grpcio_tools-1.62.1-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:6abd4eb3ccb444383a40156139acc3aaa73745d395139cb6bc8e2a3429e1e627"},
{file = "grpcio_tools-1.62.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:449503213d142f8470b331a1c2f346f8457f16c7fe20f531bc2500e271f7c14c"},
{file = "grpcio_tools-1.62.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a11bcf609d00cfc9baed77ab308223cabc1f0b22a05774a26dd4c94c0c80f1f"},
{file = "grpcio_tools-1.62.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:5d7bdea33354b55acf40bb4dd3ba7324d6f1ef6b4a1a4da0807591f8c7e87b9a"},
{file = "grpcio_tools-1.62.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d03b645852d605f43003020e78fe6d573cae6ee6b944193e36b8b317e7549a20"},
{file = "grpcio_tools-1.62.1-cp39-cp39-win32.whl", hash = "sha256:52b185dfc3bf32e70929310367dbc66185afba60492a6a75a9b1141d407e160c"},
{file = "grpcio_tools-1.62.1-cp39-cp39-win_amd64.whl", hash = "sha256:63a273b70896d3640b7a883eb4a080c3c263d91662d870a2e9c84b7bbd978e7b"},
{file = "grpcio-tools-1.62.0.tar.gz", hash = "sha256:7fca6ecfbbf0549058bb29dcc6e435d885b878d07701e77ac58e1e1f591736dc"},
{file = "grpcio_tools-1.62.0-cp310-cp310-linux_armv7l.whl", hash = "sha256:465c51ebaa184ee3bb619cd5bfaf562bbdde166f2822a6935461e6a741f5ac19"},
{file = "grpcio_tools-1.62.0-cp310-cp310-macosx_12_0_universal2.whl", hash = "sha256:0d9c9a4832f52c4597d6dc12d9ab3109c3bd0ee1686b8bf6d64f9eab4145e3cb"},
{file = "grpcio_tools-1.62.0-cp310-cp310-manylinux_2_17_aarch64.whl", hash = "sha256:5a482d9625209023481e631c29a6df1392bfc49f9accfa880dabbacff642559a"},
{file = "grpcio_tools-1.62.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:74196beed18383d53ff3e2412a6c1eefa3ff109e987be240368496bc3dcabc8b"},
{file = "grpcio_tools-1.62.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75aca28cbeb605c59b5689a7e000fbc2bd659d2f322c58461f3912f00069f6da"},
{file = "grpcio_tools-1.62.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:523adf731fa4c5af0bf7ee2edb65e8c7ef4d9df9951461d6a18fe096688efd2d"},
{file = "grpcio_tools-1.62.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:791aa220f8f1936e65bc079e9eb954fa0202a1f16e28b83956e59d17dface127"},
{file = "grpcio_tools-1.62.0-cp310-cp310-win32.whl", hash = "sha256:5dacc691b18d2c294ea971720ff980a1e2d68a3f7ddcd2f0670b3204e81c4b18"},
{file = "grpcio_tools-1.62.0-cp310-cp310-win_amd64.whl", hash = "sha256:6999a4e705b03aacad46e625feb7610e47ec88dbd51220c2282b6334f90721fc"},
{file = "grpcio_tools-1.62.0-cp311-cp311-linux_armv7l.whl", hash = "sha256:19b74e141937c885c9e56b6a7dfa190ca7d583bd48bce9171dd65bbf108b9271"},
{file = "grpcio_tools-1.62.0-cp311-cp311-macosx_10_10_universal2.whl", hash = "sha256:17c16e9a89c0b9f4ff2b143f232c5256383453ce7b55fe981598f9517adc8252"},
{file = "grpcio_tools-1.62.0-cp311-cp311-manylinux_2_17_aarch64.whl", hash = "sha256:3730b1cd998a0cffc817602cc55e51f268fa97b3e38fa4bee578e3741474547a"},
{file = "grpcio_tools-1.62.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:14201950513636f515dd455a06890e3a21d115b943cf6a8f5af67ad1413cfa1f"},
{file = "grpcio_tools-1.62.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f74e0053360e0eadd75193c0c379b6d7f51d074ebbff856bd41780e1a028b38d"},
{file = "grpcio_tools-1.62.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:d5959e3df126931d28cd94dd5f0a708b7dd96019de80ab715fb922fd0c8a838d"},
{file = "grpcio_tools-1.62.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1927934dfba4658a97c2dab267e53ed239264d40fdd5b295fc317693543db85b"},
{file = "grpcio_tools-1.62.0-cp311-cp311-win32.whl", hash = "sha256:2f5bd22203e64e1732e149bfdd3083716d038abca294e4e2852159b3d893f9ec"},
{file = "grpcio_tools-1.62.0-cp311-cp311-win_amd64.whl", hash = "sha256:cd1f4caeca614b04db803566473f7db0971e7a88268f95e4a529b0ace699b949"},
{file = "grpcio_tools-1.62.0-cp312-cp312-linux_armv7l.whl", hash = "sha256:f0884eaf6a2bbd7b03fea456e808909ee48dd4f7f455519d67defda791116368"},
{file = "grpcio_tools-1.62.0-cp312-cp312-macosx_10_10_universal2.whl", hash = "sha256:6b900ae319b6f9ac1be0ca572dfb41c23a7ff6fcbf36e3be6d3054e1e4c60de6"},
{file = "grpcio_tools-1.62.0-cp312-cp312-manylinux_2_17_aarch64.whl", hash = "sha256:3bbe79b134dfb7c98cf60e4962e31039bef824834cc7034bdf1886a2ed1097f9"},
{file = "grpcio_tools-1.62.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:77196c7ac8741d4a2aebb023bcc2964ac65ca44180fd791640889ab2afed3e47"},
{file = "grpcio_tools-1.62.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b65288ebe12e38dd3650fea65d82fcce0d35df1ae4a770b525c10119ee71962f"},
{file = "grpcio_tools-1.62.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:52b216c458458f6c292e12428916e80974c5113abc505a61e7b0b9f8932a785d"},
{file = "grpcio_tools-1.62.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:88aa62303278aec45bbb26bf679269c7890346c37140ae30e39da1070c341e11"},
{file = "grpcio_tools-1.62.0-cp312-cp312-win32.whl", hash = "sha256:bb6802d63e42734d2baf02e1343377fe18590ed6a1f5ffbdebbbe0f8331f176b"},
{file = "grpcio_tools-1.62.0-cp312-cp312-win_amd64.whl", hash = "sha256:d5652d3a52a2e8e1d9bdf28fbd15e21b166e31b968cd7c8c604bf31611c0bb5b"},
{file = "grpcio_tools-1.62.0-cp37-cp37m-linux_armv7l.whl", hash = "sha256:84e27206bd884be83a7fdcef8be3c90eb1591341c0ba9b0d25ec9db1043ba2f2"},
{file = "grpcio_tools-1.62.0-cp37-cp37m-macosx_10_10_universal2.whl", hash = "sha256:5eb63d9207b02a0fa30216907e1e7705cc2670f933e77236c6e0eb966ad3b4bf"},
{file = "grpcio_tools-1.62.0-cp37-cp37m-manylinux_2_17_aarch64.whl", hash = "sha256:95e49839d49e79187c43cd63af5c206dc5743a01d7d3d2f039772fa743cbb30c"},
{file = "grpcio_tools-1.62.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9ae5cd2f89e33a529790bf8aa59a459484edb05e4f58d4cf78836b9dfa1fab43"},
{file = "grpcio_tools-1.62.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e1fd7301d762bf5984b7e7fb62fce82cff864d75f0a57e15cfd07ae1bd79133"},
{file = "grpcio_tools-1.62.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:e38d5800151e6804d500e329f7ddfb615c50eee0c1607593e3147a4b21037e40"},
{file = "grpcio_tools-1.62.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:563a75924109e75809b2919e68d7e6ae7872e63d20258aae7899b14f6ff9e18b"},
{file = "grpcio_tools-1.62.0-cp37-cp37m-win_amd64.whl", hash = "sha256:5f8934715577c9cc0c792b8a77f7d0dd2bb60e951161b10c5f46b60856673240"},
{file = "grpcio_tools-1.62.0-cp38-cp38-linux_armv7l.whl", hash = "sha256:ed6cf7ff4a10c46f85340f9c68982f9efb29f51ee4b66828310fcdf3c2d7ffd1"},
{file = "grpcio_tools-1.62.0-cp38-cp38-macosx_10_10_universal2.whl", hash = "sha256:1faa5006fe9e7b9e65c47bc23f7cd333fdcdd4ba35d44080303848266db5ab05"},
{file = "grpcio_tools-1.62.0-cp38-cp38-manylinux_2_17_aarch64.whl", hash = "sha256:3b526dc5566161a3a17599753838b9cfbdd4cb15b6ad419aae8a5d12053fa8ae"},
{file = "grpcio_tools-1.62.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a09db3688efd3499ce3c0b02c0bac0656abdab4cb99716f81ad879c08b92c56e"},
{file = "grpcio_tools-1.62.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:006ea0cc16e8bf8f307326e0556e1384f24abb402cc4e6a720aa1dfe8f268647"},
{file = "grpcio_tools-1.62.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:b46ba0b6552b4375ede65e0c89491af532635347f78d52a72f8a027529e713ed"},
{file = "grpcio_tools-1.62.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:ec6f561c86fe13cff3be16f297cc05e1aa1274294524743a4cf91d971866fbb0"},
{file = "grpcio_tools-1.62.0-cp38-cp38-win32.whl", hash = "sha256:c85391e06620d6e16a56341caae5007d0c6219beba065e1e288f2523fba6a335"},
{file = "grpcio_tools-1.62.0-cp38-cp38-win_amd64.whl", hash = "sha256:679cf2507090e010da73e5001665c76de2a5927b2e2110e459222b1c81cb10c2"},
{file = "grpcio_tools-1.62.0-cp39-cp39-linux_armv7l.whl", hash = "sha256:0e87f105f1d152934759f8975ed002d5ce057b3cdf1cc6cb63fe6008671a27b9"},
{file = "grpcio_tools-1.62.0-cp39-cp39-macosx_10_10_universal2.whl", hash = "sha256:bf9f281f528e0220558d57e09b4518dec148dcb250d78bd9cbb27e09edabb3f9"},
{file = "grpcio_tools-1.62.0-cp39-cp39-manylinux_2_17_aarch64.whl", hash = "sha256:711314cb4c6c8b3d51bafaee380ffa5012bd0567ed68f1b0b1fc07492b27acab"},
{file = "grpcio_tools-1.62.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:54bb570bd963905de3bda596b35e06026552705edebbb2cb737b57aa5252b9e5"},
{file = "grpcio_tools-1.62.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dce5f04676cf94e6e2d13d7f91ac2de79097d86675bc4d404a3c24dcc0332c88"},
{file = "grpcio_tools-1.62.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:98ddf871c614cc0ed331c7159ebbbf5040be562279677d3bb97c2e6083539f72"},
{file = "grpcio_tools-1.62.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:f3aaf3b20c0f7063856b2432335af8f76cf580f898e04085548cde28332d6833"},
{file = "grpcio_tools-1.62.0-cp39-cp39-win32.whl", hash = "sha256:3dee3be61d9032f777a9b4e2696ea3d0748a582cb99c672b5d41ca66821e8c87"},
{file = "grpcio_tools-1.62.0-cp39-cp39-win_amd64.whl", hash = "sha256:f54b5181784464bd3573ae7dbcf053da18a4b7a75fe19960791f383be3d035ca"},
]
[package.dependencies]
grpcio = ">=1.62.1"
grpcio = ">=1.62.0"
protobuf = ">=4.21.6,<5.0dev"
setuptools = "*"
@ -553,13 +553,13 @@ files = [
[[package]]
name = "packaging"
version = "24.0"
version = "23.2"
description = "Core utilities for Python packages"
optional = false
python-versions = ">=3.7"
files = [
{file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"},
{file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"},
{file = "packaging-23.2-py3-none-any.whl", hash = "sha256:8c491190033a9af7e1d931d0b5dacc2ef47509b34dd0de67ed209b5203fc88c7"},
{file = "packaging-23.2.tar.gz", hash = "sha256:048fb0e9405036518eaaf48a55953c750c11e1a1b68e0dd1a9d62ed0c092cfc5"},
]
[[package]]
@ -633,18 +633,18 @@ xml = ["lxml (>=4.9.2)"]
[[package]]
name = "playwright"
version = "1.42.0"
version = "1.41.2"
description = "A high-level API to automate web browsers"
optional = false
python-versions = ">=3.8"
files = [
{file = "playwright-1.42.0-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:e2b293f077efeaa45253fde31cea4bc6b0ae8be6b5e65e8ce8b4aa3b9f0d55b6"},
{file = "playwright-1.42.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:283887f0bdd0039c3d720e32fbc73a045c24fa800599a6ad60fb199c29580534"},
{file = "playwright-1.42.0-py3-none-macosx_11_0_universal2.whl", hash = "sha256:4e1fc1c049a0af64626ddd50814d14a01f316bcbb4d1aa83c3416fe420add558"},
{file = "playwright-1.42.0-py3-none-manylinux1_x86_64.whl", hash = "sha256:313f2551a772f57c9ccca017c4dd4661f2277166f9e1d84bbf5a2e316f0f892c"},
{file = "playwright-1.42.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2a46a24641e5d468046cde567c98fdb8d85e32df901630b14dfb288cbd1ed4f"},
{file = "playwright-1.42.0-py3-none-win32.whl", hash = "sha256:dbf473496808d4c2c816902c1dee2aabc029648e56ce8514b643f5a1a6fc8e22"},
{file = "playwright-1.42.0-py3-none-win_amd64.whl", hash = "sha256:e092c6cfbf797bff03fbdfc53c3e6a9e29fbcf6b82f9e43113d37494aee0561b"},
{file = "playwright-1.41.2-py3-none-macosx_10_13_x86_64.whl", hash = "sha256:cf68335a5dfa4038fa797a4ba0105faee0094ebbb372547d7a27feec5b23c672"},
{file = "playwright-1.41.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:431e3a05f8c99147995e2b3e8475d07818745294fd99f1510b61756e73bdcf68"},
{file = "playwright-1.41.2-py3-none-macosx_11_0_universal2.whl", hash = "sha256:0608717cbf291a625ba6f751061af0fc0cc9bdace217e69d87b1eb1383b03406"},
{file = "playwright-1.41.2-py3-none-manylinux1_x86_64.whl", hash = "sha256:4bf214d812092cf5b9b9648ba84611aa35e28685519911342a7da3a3031f9ed6"},
{file = "playwright-1.41.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaa17ab44622c447de26ed8f7d99912719568d8dbc3a9db0e07f0ae1487709d9"},
{file = "playwright-1.41.2-py3-none-win32.whl", hash = "sha256:edb210a015e70bb0d328bf1c9b65fa3a08361f33e4d7c4ddd1ad2adb6d9b4479"},
{file = "playwright-1.41.2-py3-none-win_amd64.whl", hash = "sha256:71ead0f33e00f5a8533c037c647938b99f219436a1b27d4ba4de4e6bf0567278"},
]
[package.dependencies]
@ -653,13 +653,13 @@ pyee = "11.0.1"
[[package]]
name = "plotly"
version = "5.20.0"
version = "5.19.0"
description = "An open-source, interactive data visualization library for Python"
optional = false
python-versions = ">=3.8"
files = [
{file = "plotly-5.20.0-py3-none-any.whl", hash = "sha256:837a9c8aa90f2c0a2f0d747b82544d014dc2a2bdde967b5bb1da25b53932d1a9"},
{file = "plotly-5.20.0.tar.gz", hash = "sha256:bf901c805d22032cfa534b2ff7c5aa6b0659e037f19ec1e0cca7f585918b5c89"},
{file = "plotly-5.19.0-py3-none-any.whl", hash = "sha256:906abcc5f15945765328c5d47edaa884bc99f5985fbc61e8cd4dc361f4ff8f5a"},
{file = "plotly-5.19.0.tar.gz", hash = "sha256:5ea91a56571292ade3e3bc9bf712eba0b95a1fb0a941375d978cc79432e055f4"},
]
[package.dependencies]
@ -800,13 +800,13 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"]
[[package]]
name = "pytest"
version = "8.1.1"
version = "8.0.2"
description = "pytest: simple powerful testing with Python"
optional = false
python-versions = ">=3.8"
files = [
{file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"},
{file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"},
{file = "pytest-8.0.2-py3-none-any.whl", hash = "sha256:edfaaef32ce5172d5466b5127b42e0d6d35ebbe4453f0e3505d96afd93f6b096"},
{file = "pytest-8.0.2.tar.gz", hash = "sha256:d4051d623a2e0b7e51960ba963193b09ce6daeb9759a451844a21e4ddedfc1bd"},
]
[package.dependencies]
@ -814,11 +814,11 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""}
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
iniconfig = "*"
packaging = "*"
pluggy = ">=1.4,<2.0"
tomli = {version = ">=1", markers = "python_version < \"3.11\""}
pluggy = ">=1.3.0,<2.0"
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
[package.extras]
testing = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
[[package]]
name = "pytest-base-url"
@ -1019,18 +1019,18 @@ test = ["asv", "gmpy2", "hypothesis", "mpmath", "pooch", "pytest", "pytest-cov",
[[package]]
name = "setuptools"
version = "69.2.0"
version = "69.1.1"
description = "Easily download, build, install, upgrade, and uninstall Python packages"
optional = false
python-versions = ">=3.8"
files = [
{file = "setuptools-69.2.0-py3-none-any.whl", hash = "sha256:c21c49fb1042386df081cb5d86759792ab89efca84cf114889191cd09aacc80c"},
{file = "setuptools-69.2.0.tar.gz", hash = "sha256:0ff4183f8f42cd8fa3acea16c45205521a4ef28f73c6391d8a25e92893134f2e"},
{file = "setuptools-69.1.1-py3-none-any.whl", hash = "sha256:02fa291a0471b3a18b2b2481ed902af520c69e8ae0919c13da936542754b4c56"},
{file = "setuptools-69.1.1.tar.gz", hash = "sha256:5c0806c7d9af348e6dd3777b4f4dbb42c7ad85b190104837488eab9a7c945cf8"},
]
[package.extras]
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pip (>=19.1)", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
[[package]]
@ -1165,8 +1165,8 @@ profile = ["pytest-profiling", "snakeviz"]
[package.source]
type = "git"
url = "https://github.com/vegaprotocol/vega-market-sim.git/"
reference = "pre-release/vega-v0.75.5"
resolved_reference = "b2a3437fc13ced2b7ecd582ca4778bbc4b0fe3a6"
reference = "HEAD"
resolved_reference = "53eed8942acb670783105cb1115bab76710a46dc"
[[package]]
name = "websocket-client"
@ -1347,4 +1347,4 @@ files = [
[metadata]
lock-version = "2.0"
python-versions = ">=3.9,<3.11"
content-hash = "80e87cbde486e7bb150fce0b1c974de38501bc16732952b455d43cb843426623"
content-hash = "39ce8400de7bf060857447281ef27bd78c9b1d9639da063b051e3ae6e7887a67"

View File

@ -1,29 +0,0 @@
[tool.poetry]
name = "trading market-sim e2e"
version = "0.1.0"
description = ""
authors = ["Matthew Russell <mattrussell36@gmail.com>"]
readme = "README.md"
packages = [{include = "trading market-sim e2e"}]
[tool.poetry.dependencies]
python = ">=3.9,<3.11"
psutil = "^5.9.5"
pytest-playwright = "^0.4.2"
docker = "^6.1.3"
pytest-xdist = "^3.3.1"
python-dotenv = "^1.0.0"
vega-sim = { git = "https://github.com/vegaprotocol/vega-market-sim.git/", branch = "pre-release/vega-v0.75.5"}
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.pytest.ini_options]
log_cli = true
log_cli_format = "%(asctime)s - %(name)s - %(levelname)s: %(message)s"
log_cli_date_format = "%Y-%m-%d %H:%M:%S"
log_cli_level = "INFO"
log_file_format = "%(asctime)s - %(name)s - %(levelname)s: %(message)s"
log_file_date_format = "%Y-%m-%d %H:%M:%S"
log_file_level = "INFO"

View File

@ -1,29 +0,0 @@
[tool.poetry]
name = "trading market-sim e2e"
version = "0.1.0"
description = ""
authors = ["Matthew Russell <mattrussell36@gmail.com>"]
readme = "README.md"
packages = [{include = "trading market-sim e2e"}]
[tool.poetry.dependencies]
python = ">=3.9,<3.11"
psutil = "^5.9.5"
pytest-playwright = "^0.4.2"
docker = "^6.1.3"
pytest-xdist = "^3.3.1"
python-dotenv = "^1.0.0"
vega-sim = { git = "https://github.com/vegaprotocol/vega-market-sim.git/", branch = "release/vega-v0.74.10" }
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.pytest.ini_options]
log_cli = true
log_cli_format = "%(asctime)s - %(name)s - %(levelname)s: %(message)s"
log_cli_date_format = "%Y-%m-%d %H:%M:%S"
log_cli_level = "INFO"
log_file_format = "%(asctime)s - %(name)s - %(levelname)s: %(message)s"
log_file_date_format = "%Y-%m-%d %H:%M:%S"
log_file_level = "INFO"

View File

@ -9,11 +9,11 @@ packages = [{include = "trading market-sim e2e"}]
[tool.poetry.dependencies]
python = ">=3.9,<3.11"
psutil = "^5.9.5"
vega-sim = {git = "https://github.com/vegaprotocol/vega-market-sim.git/"}
pytest-playwright = "^0.4.2"
docker = "^6.1.3"
pytest-xdist = "^3.3.1"
python-dotenv = "^1.0.0"
vega-sim = { git = "https://github.com/vegaprotocol/vega-market-sim.git/", branch = "pre-release/vega-v0.75.5"}
[build-system]
requires = ["poetry-core"]
@ -26,4 +26,4 @@ log_cli_date_format = "%Y-%m-%d %H:%M:%S"
log_cli_level = "INFO"
log_file_format = "%(asctime)s - %(name)s - %(levelname)s: %(message)s"
log_file_date_format = "%Y-%m-%d %H:%M:%S"
log_file_level = "INFO"
log_file_level = "INFO"

Some files were not shown because too many files have changed in this diff Show More