Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
69ddba288a |
@@ -205,7 +205,7 @@ jobs:
|
||||
# run tests
|
||||
#----------------------------------------------
|
||||
- name: Run tests
|
||||
run: CONSOLE_IMAGE_NAME=ci/trading:local poetry run pytest -v --numprocesses 4 --dist loadfile --durations=45
|
||||
run: CONSOLE_IMAGE_NAME=ci/trading:local poetry run pytest -v --numprocesses 1 --dist loadfile --durations=45
|
||||
working-directory: apps/trading/e2e
|
||||
#----------------------------------------------
|
||||
# upload traces
|
||||
|
||||
@@ -24,6 +24,10 @@ context('Proposal page', { tags: '@smoke' }, function () {
|
||||
cy.get_element_by_col_id('title').should('have.text', proposalTitle);
|
||||
cy.get_element_by_col_id('type').should('have.text', 'NewMarket');
|
||||
cy.get_element_by_col_id('state').should('have.text', 'Enacted');
|
||||
cy.getByTestId('vote-progress').should('be.visible');
|
||||
cy.getByTestId('vote-progress-bar-for')
|
||||
.invoke('attr', 'style')
|
||||
.should('eq', 'width: 100%;');
|
||||
cy.get('[col-id="cDate"]')
|
||||
.invoke('text')
|
||||
.should('match', dateTimeRegex);
|
||||
@@ -69,6 +73,10 @@ context('Proposal page', { tags: '@smoke' }, function () {
|
||||
'have.text',
|
||||
'Waiting for Node Vote'
|
||||
);
|
||||
cy.getByTestId('vote-progress').should('be.visible');
|
||||
cy.getByTestId('vote-progress-bar-against')
|
||||
.invoke('attr', 'style')
|
||||
.should('eq', 'width: 100%;');
|
||||
cy.get('[col-id="cDate"]')
|
||||
.invoke('text')
|
||||
.should('match', dateTimeRegex);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { type ProposalListFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { VoteProgress } from '@vegaprotocol/proposals';
|
||||
import { type AgGridReact } from 'ag-grid-react';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGrid } from '@vegaprotocol/datagrid';
|
||||
@@ -11,7 +12,12 @@ import { type ColDef } from 'ag-grid-community';
|
||||
import type { RowClickedEvent } from 'ag-grid-community';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
NetworkParams,
|
||||
useNetworkParams,
|
||||
} from '@vegaprotocol/network-parameters';
|
||||
import { ProposalStateMapping } from '@vegaprotocol/types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import { DApp, TOKEN_PROPOSAL, useLinks } from '@vegaprotocol/environment';
|
||||
import { BREAKPOINT_MD } from '../../config/breakpoints';
|
||||
import { JsonViewerDialog } from '../dialogs/json-viewer-dialog';
|
||||
@@ -25,7 +31,15 @@ type ProposalsTableProps = {
|
||||
data: ProposalListFieldsFragment[] | null;
|
||||
};
|
||||
export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
||||
const { params } = useNetworkParams([
|
||||
NetworkParams.governance_proposal_market_requiredMajority,
|
||||
]);
|
||||
const tokenLink = useLinks(DApp.Governance);
|
||||
const requiredMajorityPercentage = useMemo(() => {
|
||||
const requiredMajority =
|
||||
params?.governance_proposal_market_requiredMajority ?? 1;
|
||||
return new BigNumber(requiredMajority).times(100);
|
||||
}, [params?.governance_proposal_market_requiredMajority]);
|
||||
|
||||
const gridRef = useRef<AgGridReact>(null);
|
||||
useLayoutEffect(() => {
|
||||
@@ -76,6 +90,33 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
||||
return value ? ProposalStateMapping[value] : '-';
|
||||
},
|
||||
},
|
||||
{
|
||||
colId: 'voting',
|
||||
maxWidth: 100,
|
||||
hide: window.innerWidth <= BREAKPOINT_MD,
|
||||
headerName: t('Voting'),
|
||||
cellRenderer: ({
|
||||
data,
|
||||
}: VegaICellRendererParams<ProposalListFieldsFragment>) => {
|
||||
if (data) {
|
||||
const yesTokens = new BigNumber(data.votes.yes.totalTokens);
|
||||
const noTokens = new BigNumber(data.votes.no.totalTokens);
|
||||
const totalTokensVoted = yesTokens.plus(noTokens);
|
||||
const yesPercentage = totalTokensVoted.isZero()
|
||||
? new BigNumber(0)
|
||||
: yesTokens.multipliedBy(100).dividedBy(totalTokensVoted);
|
||||
return (
|
||||
<div className="flex h-full items-center justify-center pt-2 uppercase">
|
||||
<VoteProgress
|
||||
threshold={requiredMajorityPercentage}
|
||||
progress={yesPercentage}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return '-';
|
||||
},
|
||||
},
|
||||
{
|
||||
colId: 'cDate',
|
||||
maxWidth: 150,
|
||||
@@ -143,7 +184,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
|
||||
},
|
||||
},
|
||||
],
|
||||
[tokenLink]
|
||||
[requiredMajorityPercentage, tokenLink]
|
||||
);
|
||||
return (
|
||||
<>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"short_name": "Explorer VEGA",
|
||||
"name": "Vega Protocol - Explorer",
|
||||
"short_name": "Mainnet Stats",
|
||||
"name": "Vega Mainnet statistics",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"short_name": "Governance VEGA",
|
||||
"name": "Vega Protocol - Governance",
|
||||
"short_name": "Mainnet Stats",
|
||||
"name": "Vega Mainnet statistics",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
<title>Vega Protocol static assets</title>
|
||||
<title>Vega Protocol static asseets</title>
|
||||
<link rel="stylesheet" href="fonts.css" />
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
</head>
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
{
|
||||
"name": "Vega Protocol - Trading",
|
||||
"short_name": "Console",
|
||||
"description": "Vega Protocol - Trading dApp",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"orientation": "portrait",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff",
|
||||
"short_name": "Mainnet Stats",
|
||||
"name": "Vega Mainnet statistics",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
@@ -18,5 +12,9 @@
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
}
|
||||
]
|
||||
],
|
||||
"start_url": ".",
|
||||
"display": "standalone",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { Intent, TradingAnchorButton } from '@vegaprotocol/ui-toolkit';
|
||||
import { Link, useSearchParams } from 'react-router-dom';
|
||||
import {
|
||||
Intent,
|
||||
TradingAnchorButton,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
|
||||
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
|
||||
import { useT } from '../../lib/use-t';
|
||||
@@ -30,6 +35,19 @@ export const CompetitionsCreateTeam = () => {
|
||||
<LayoutWithGradient>
|
||||
<div className="mx-auto md:w-2/3 max-w-xl">
|
||||
<Box className="flex flex-col gap-4">
|
||||
<Link
|
||||
to={Links.COMPETITIONS()}
|
||||
className="text-xs inline-flex items-center gap-1 group"
|
||||
>
|
||||
<VegaIcon
|
||||
name={VegaIconNames.CHEVRON_LEFT}
|
||||
size={12}
|
||||
className="text-vega-clight-100 dark:text-vega-cdark-100"
|
||||
/>{' '}
|
||||
<span className="group-hover:underline">
|
||||
{t('Go back to the competitions')}
|
||||
</span>
|
||||
</Link>
|
||||
<h1 className="calt text-2xl lg:text-3xl xl:text-4xl">
|
||||
{isSolo ? t('Create solo team') : t('Create a team')}
|
||||
</h1>
|
||||
@@ -78,15 +96,17 @@ const CreateTeamFormContainer = ({ isSolo }: { isSolo: boolean }) => {
|
||||
<p className="text-sm">{t('Team creation transaction successful')}</p>
|
||||
{code && (
|
||||
<>
|
||||
<p className="text-sm">
|
||||
Your team ID is:{' '}
|
||||
<span
|
||||
className="font-mono break-all"
|
||||
data-testid="team-id-display"
|
||||
>
|
||||
{code}
|
||||
</span>
|
||||
</p>
|
||||
<dl>
|
||||
<dt className="text-sm">{t('Your team ID:')}</dt>
|
||||
<dl>
|
||||
<span
|
||||
className="font-mono break-all bg-rainbow bg-clip-text text-transparent text-2xl"
|
||||
data-testid="team-id-display"
|
||||
>
|
||||
{code}
|
||||
</span>
|
||||
</dl>
|
||||
</dl>
|
||||
<TradingAnchorButton
|
||||
href={Links.COMPETITIONS_TEAM(code)}
|
||||
intent={Intent.Info}
|
||||
|
||||
@@ -3,7 +3,14 @@ import { usePageTitle } from '../../lib/hooks/use-page-title';
|
||||
import { Box } from '../../components/competitions/box';
|
||||
import { useT } from '../../lib/use-t';
|
||||
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
|
||||
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
Intent,
|
||||
Loader,
|
||||
Splash,
|
||||
TradingAnchorButton,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { RainbowButton } from '../../components/rainbow-button';
|
||||
import { Link, Navigate, useParams } from 'react-router-dom';
|
||||
import { Links } from '../../lib/links';
|
||||
@@ -11,6 +18,7 @@ import { useReferralSetTransaction } from '../../lib/hooks/use-referral-set-tran
|
||||
import { type FormFields, TeamForm, TransactionType } from './team-form';
|
||||
import { useTeam } from '../../lib/hooks/use-team';
|
||||
import { LayoutWithGradient } from '../../components/layouts-inner';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export const CompetitionsUpdateTeam = () => {
|
||||
const t = useT();
|
||||
@@ -29,6 +37,19 @@ export const CompetitionsUpdateTeam = () => {
|
||||
<LayoutWithGradient>
|
||||
<div className="mx-auto md:w-2/3 max-w-xl">
|
||||
<Box className="flex flex-col gap-4">
|
||||
<Link
|
||||
to={Links.COMPETITIONS_TEAM(teamId)}
|
||||
className="text-xs inline-flex items-center gap-1 group"
|
||||
>
|
||||
<VegaIcon
|
||||
name={VegaIconNames.CHEVRON_LEFT}
|
||||
size={12}
|
||||
className="text-vega-clight-100 dark:text-vega-cdark-100"
|
||||
/>{' '}
|
||||
<span className="group-hover:underline">
|
||||
{t('Go back to the team profile')}
|
||||
</span>
|
||||
</Link>
|
||||
<h1 className="calt text-2xl lg:text-3xl xl:text-5xl">
|
||||
{t('Update a team')}
|
||||
</h1>
|
||||
@@ -57,7 +78,8 @@ const UpdateTeamFormContainer = ({
|
||||
pubKey: string;
|
||||
}) => {
|
||||
const t = useT();
|
||||
const { team, loading, error } = useTeam(teamId, pubKey);
|
||||
const [refetching, setRefetching] = useState<boolean>(false);
|
||||
const { team, loading, error, refetch } = useTeam(teamId, pubKey);
|
||||
|
||||
const { err, status, onSubmit } = useReferralSetTransaction({
|
||||
onSuccess: () => {
|
||||
@@ -65,7 +87,15 @@ const UpdateTeamFormContainer = ({
|
||||
},
|
||||
});
|
||||
|
||||
if (loading) {
|
||||
// refetch when saved
|
||||
useEffect(() => {
|
||||
if (refetch && status === 'confirmed') {
|
||||
refetch();
|
||||
setRefetching(true);
|
||||
}
|
||||
}, [refetch, status]);
|
||||
|
||||
if (loading && !refetching) {
|
||||
return <Loader size="small" />;
|
||||
}
|
||||
if (error) {
|
||||
@@ -84,6 +114,33 @@ const UpdateTeamFormContainer = ({
|
||||
return <Navigate to={Links.COMPETITIONS_TEAM(teamId)} />;
|
||||
}
|
||||
|
||||
if (status === 'confirmed') {
|
||||
return (
|
||||
<div
|
||||
className="flex flex-col items-start gap-2"
|
||||
data-testid="team-creation-success-message"
|
||||
>
|
||||
<p className="text-sm">
|
||||
<VegaIcon
|
||||
name={VegaIconNames.TICK}
|
||||
size={18}
|
||||
className="text-vega-green-500"
|
||||
/>{' '}
|
||||
{t('Changes successfully saved to your team.')}
|
||||
</p>
|
||||
|
||||
<TradingAnchorButton
|
||||
href={Links.COMPETITIONS_TEAM(teamId)}
|
||||
intent={Intent.Info}
|
||||
size="small"
|
||||
data-testid="view-team-button"
|
||||
>
|
||||
{t('View team')}
|
||||
</TradingAnchorButton>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const defaultValues: FormFields = {
|
||||
id: team.teamId,
|
||||
name: team.name,
|
||||
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
useFundingRate,
|
||||
useMarketTradingMode,
|
||||
useExternalTwap,
|
||||
getQuoteName,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { MarketState as State } from '@vegaprotocol/types';
|
||||
import { HeaderStat } from '../../components/header';
|
||||
@@ -42,7 +41,6 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
|
||||
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
|
||||
|
||||
const asset = getAsset(market);
|
||||
const quoteUnit = getQuoteName(market);
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -56,15 +54,12 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
|
||||
<Last24hPriceChange
|
||||
marketId={market.id}
|
||||
decimalPlaces={market.decimalPlaces}
|
||||
fallback={<span>-</span>}
|
||||
/>
|
||||
</HeaderStat>
|
||||
<HeaderStat heading={t('Volume (24h)')} testId="market-volume">
|
||||
<Last24hVolume
|
||||
marketId={market.id}
|
||||
positionDecimalPlaces={market.positionDecimalPlaces}
|
||||
marketDecimals={market.decimalPlaces}
|
||||
quoteUnit={quoteUnit}
|
||||
/>
|
||||
</HeaderStat>
|
||||
<HeaderStatMarketTradingMode
|
||||
@@ -113,7 +108,7 @@ export const MarketHeaderStats = ({ market }: MarketHeaderStatsProps) => {
|
||||
heading={`${t('Funding Rate')} / ${t('Countdown')}`}
|
||||
testId="market-funding"
|
||||
>
|
||||
<div className="flex gap-2">
|
||||
<div className="flex justify-between gap-2">
|
||||
<FundingRate marketId={market.id} />
|
||||
<FundingCountdown marketId={market.id} />
|
||||
</div>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { type Market } from '@vegaprotocol/markets';
|
||||
// TODO: handle oracle banner
|
||||
// import { OracleBanner } from '@vegaprotocol/markets';
|
||||
import { useState } from 'react';
|
||||
import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
import classNames from 'classnames';
|
||||
import {
|
||||
Popover,
|
||||
@@ -11,21 +12,21 @@ import {
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { useT } from '../../lib/use-t';
|
||||
import { MarketBanner } from '../../components/market-banner';
|
||||
import { ErrorBoundary } from '../../components/error-boundary';
|
||||
import { type TradingView } from './trade-views';
|
||||
import { TradingViews } from './trade-views';
|
||||
|
||||
interface TradePanelsProps {
|
||||
market: Market;
|
||||
pinnedAsset?: PinnedAsset;
|
||||
}
|
||||
|
||||
export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
|
||||
const [topView, setTopView] = useState<TradingView>('chart');
|
||||
const topViewCfg = TradingViews[topView];
|
||||
const [bottomView, setBottomView] = useState<TradingView>('positions');
|
||||
const bottomViewCfg = TradingViews[bottomView];
|
||||
const [view, setView] = useState<TradingView>('chart');
|
||||
const viewCfg = TradingViews[view];
|
||||
|
||||
const renderView = (view: TradingView) => {
|
||||
const renderView = () => {
|
||||
const Component = TradingViews[view].component;
|
||||
|
||||
if (!Component) {
|
||||
@@ -38,13 +39,12 @@ export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
|
||||
// so watch out for clashes in props
|
||||
return (
|
||||
<ErrorBoundary feature={view}>
|
||||
<Component marketId={market?.id} pinnedAsset={pinnedAsset} />
|
||||
<Component marketId={market?.id} pinnedAsset={pinnedAsset} />;
|
||||
</ErrorBoundary>
|
||||
);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const renderMenu = (viewCfg: any) => {
|
||||
const renderMenu = () => {
|
||||
if ('menu' in viewCfg || 'settings' in viewCfg) {
|
||||
return (
|
||||
<div className="flex items-center justify-end gap-1 p-1 bg-vega-clight-800 dark:bg-vega-cdark-800 border-b border-default">
|
||||
@@ -69,80 +69,55 @@ export const TradePanels = ({ market, pinnedAsset }: TradePanelsProps) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col lg:grid grid-rows-[min-content_min-content_1fr_min-content]">
|
||||
<div className="flex flex-col w-full overflow-hidden">
|
||||
<div className="flex flex-nowrap overflow-x-auto max-w-full border-t border-default">
|
||||
{['chart', 'orderbook', 'trades', 'liquidity', 'fundingPayments']
|
||||
// filter to control available views for the current market
|
||||
// e.g. only perpetuals should get the funding views
|
||||
.filter((_key) => {
|
||||
const key = _key as TradingView;
|
||||
const perpOnlyViews = ['funding', 'fundingPayments'];
|
||||
|
||||
if (
|
||||
market?.tradableInstrument.instrument.product.__typename ===
|
||||
'Perpetual'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (perpOnlyViews.includes(key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.map((_key) => {
|
||||
const key = _key as TradingView;
|
||||
const isActive = topView === key;
|
||||
return (
|
||||
<ViewButton
|
||||
key={key}
|
||||
view={key}
|
||||
isActive={isActive}
|
||||
onClick={() => {
|
||||
setTopView(key);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="h-[50vh] lg:h-full relative">
|
||||
<div>{renderMenu(topViewCfg)}</div>
|
||||
<div className="overflow-auto h-full">{renderView(topView)}</div>
|
||||
</div>
|
||||
<div className="h-full grid grid-rows-[min-content_min-content_1fr_min-content]">
|
||||
<div>
|
||||
<MarketBanner market={market} />
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col w-full grow">
|
||||
<div className="flex flex-nowrap overflow-x-auto max-w-full border-t border-default">
|
||||
{[
|
||||
'positions',
|
||||
'activeOrders',
|
||||
'closedOrders',
|
||||
'rejectedOrders',
|
||||
'orders',
|
||||
'stopOrders',
|
||||
'collateral',
|
||||
'fills',
|
||||
].map((_key) => {
|
||||
<div>{renderMenu()}</div>
|
||||
<div className="h-full relative">
|
||||
<AutoSizer>
|
||||
{({ width, height }) => (
|
||||
<div style={{ width, height }} className="overflow-auto">
|
||||
{renderView()}
|
||||
</div>
|
||||
)}
|
||||
</AutoSizer>
|
||||
</div>
|
||||
<div className="flex flex-nowrap overflow-x-auto max-w-full border-t border-default">
|
||||
{Object.keys(TradingViews)
|
||||
// filter to control available views for the current market
|
||||
// eg only perps should get the funding views
|
||||
.filter((_key) => {
|
||||
const key = _key as TradingView;
|
||||
const isActive = bottomView === key;
|
||||
const perpOnlyViews = ['funding', 'fundingPayments'];
|
||||
|
||||
if (
|
||||
market?.tradableInstrument.instrument.product.__typename ===
|
||||
'Perpetual'
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (perpOnlyViews.includes(key)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
})
|
||||
.map((_key) => {
|
||||
const key = _key as TradingView;
|
||||
const isActive = view === key;
|
||||
return (
|
||||
<ViewButton
|
||||
key={key}
|
||||
view={key}
|
||||
isActive={isActive}
|
||||
onClick={() => {
|
||||
setBottomView(key);
|
||||
setView(key);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="relative grow">
|
||||
<div className="flex flex-col">{renderMenu(bottomViewCfg)}</div>
|
||||
<div className="overflow-auto h-full">{renderView(bottomView)}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
@@ -182,7 +157,7 @@ const useViewLabel = (view: TradingView) => {
|
||||
depth: t('Depth'),
|
||||
liquidity: t('Liquidity'),
|
||||
funding: t('Funding'),
|
||||
fundingPayments: t('Funding'),
|
||||
fundingPayments: t('Funding Payments'),
|
||||
orderbook: t('Orderbook'),
|
||||
trades: t('Trades'),
|
||||
positions: t('Positions'),
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
useDataGridEvents,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import type { MarketMaybeWithData } from '@vegaprotocol/markets';
|
||||
import { useMarketsColumnDefs } from './use-column-defs';
|
||||
import { useColumnDefs } from './use-column-defs';
|
||||
import type { DataGridStore } from '../../stores/datagrid-store-slice';
|
||||
import { type StateCreator, create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
@@ -50,7 +50,7 @@ export const useMarketsStore = create<DataGridSlice>()(
|
||||
);
|
||||
|
||||
export const MarketListTable = (props: Props) => {
|
||||
const columnDefs = useMarketsColumnDefs();
|
||||
const columnDefs = useColumnDefs();
|
||||
const gridStore = useMarketsStore((store) => store.gridStore);
|
||||
const updateGridStore = useMarketsStore((store) => store.updateGridStore);
|
||||
|
||||
|
||||
@@ -7,31 +7,21 @@ import type {
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { COL_DEFS, SetFilter } from '@vegaprotocol/datagrid';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
formatNumber,
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { addDecimalsFormatNumber, toBigNum } from '@vegaprotocol/utils';
|
||||
import { ButtonLink, Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import type {
|
||||
MarketFieldsFragment,
|
||||
MarketMaybeWithData,
|
||||
MarketMaybeWithDataAndCandles,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { MarketActionsDropdown } from './market-table-actions';
|
||||
import {
|
||||
calcCandleVolume,
|
||||
calcCandleVolumePrice,
|
||||
getAsset,
|
||||
getQuoteName,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { calcCandleVolume, getAsset } from '@vegaprotocol/markets';
|
||||
import { MarketCodeCell } from './market-code-cell';
|
||||
import { useT } from '../../lib/use-t';
|
||||
|
||||
const { MarketTradingMode, AuctionTrigger } = Schema;
|
||||
|
||||
export const useMarketsColumnDefs = () => {
|
||||
export const useColumnDefs = () => {
|
||||
const t = useT();
|
||||
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
|
||||
return useMemo<ColDef[]>(
|
||||
@@ -168,25 +158,11 @@ export const useMarketsColumnDefs = () => {
|
||||
}: ValueFormatterParams<MarketMaybeWithDataAndCandles, 'candles'>) => {
|
||||
const candles = data?.candles;
|
||||
const vol = candles ? calcCandleVolume(candles) : '0';
|
||||
const quoteName = getQuoteName(data as MarketFieldsFragment);
|
||||
const volPrice =
|
||||
candles &&
|
||||
calcCandleVolumePrice(
|
||||
candles,
|
||||
data.decimalPlaces,
|
||||
data.positionDecimalPlaces
|
||||
);
|
||||
|
||||
const volume =
|
||||
data && vol && vol !== '0'
|
||||
? addDecimalsFormatNumber(vol, data.positionDecimalPlaces)
|
||||
: '0.00';
|
||||
const volumePrice =
|
||||
volPrice && formatNumber(volPrice, data?.decimalPlaces);
|
||||
|
||||
return volumePrice
|
||||
? `${volume} (${volumePrice} ${quoteName})`
|
||||
: volume;
|
||||
return volume;
|
||||
},
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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,7 +44,7 @@ export const TeamAvatar = ({
|
||||
alt?: string;
|
||||
size?: 'large' | 'small';
|
||||
}) => {
|
||||
const img = imgUrl && imgUrl.length > 0 ? imgUrl : getFallbackAvatar(teamId);
|
||||
const img = useAvatar(teamId, imgUrl);
|
||||
return (
|
||||
// eslint-disable-next-line @next/next/no-img-element
|
||||
<img
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Outlet } from 'react-router-dom';
|
||||
import { Sidebar, SidebarContent, useSidebar } from '../sidebar';
|
||||
import classNames from 'classnames';
|
||||
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
|
||||
|
||||
export const LayoutWithSidebar = ({
|
||||
header,
|
||||
sidebar,
|
||||
@@ -26,13 +27,10 @@ export const LayoutWithSidebar = ({
|
||||
<div className={gridClasses}>
|
||||
<div className="col-span-full">{header}</div>
|
||||
<main
|
||||
className={classNames(
|
||||
'col-start-1 col-end-1 overflow-hidden lg:overflow-y-auto grow lg:grow-0',
|
||||
{
|
||||
'lg:col-end-3': !sidebarOpen,
|
||||
'hidden lg:block lg:col-end-2': sidebarOpen,
|
||||
}
|
||||
)}
|
||||
className={classNames('col-start-1 col-end-1 overflow-y-auto', {
|
||||
'lg:col-end-3': !sidebarOpen,
|
||||
'hidden lg:block lg:col-end-2': sidebarOpen,
|
||||
})}
|
||||
>
|
||||
<Outlet />
|
||||
</main>
|
||||
|
||||
@@ -1,2 +1 @@
|
||||
export * from './market-header';
|
||||
export * from './mobile-market-header';
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||
import { MarketSelector } from '../market-selector';
|
||||
import {
|
||||
Last24hPriceChange,
|
||||
useMarket,
|
||||
useMarketList,
|
||||
} from '@vegaprotocol/markets';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
||||
import { useState } from 'react';
|
||||
import { useT } from '../../lib/use-t';
|
||||
import classNames from 'classnames';
|
||||
import { MarketHeaderStats } from '../../client-pages/market/market-header-stats';
|
||||
import { MarketMarkPrice } from '../market-mark-price';
|
||||
/**
|
||||
* This is only rendered for the mobile navigation
|
||||
*/
|
||||
export const MobileMarketHeader = () => {
|
||||
const t = useT();
|
||||
const { marketId } = useParams();
|
||||
const { data } = useMarket(marketId);
|
||||
const [openMarket, setOpenMarket] = useState(false);
|
||||
const [openPrice, setOpenPrice] = useState(false);
|
||||
|
||||
// Ensure that markets are kept cached so opening the list
|
||||
// shows all markets instantly
|
||||
useMarketList();
|
||||
|
||||
if (!marketId) return null;
|
||||
|
||||
return (
|
||||
<div className="pl-3 pr-2 flex justify-between gap-2 h-10 bg-vega-clight-700 dark:bg-vega-cdark-700">
|
||||
<FullScreenPopover
|
||||
open={openMarket}
|
||||
onOpenChange={(x) => {
|
||||
setOpenMarket(x);
|
||||
}}
|
||||
trigger={
|
||||
<h1 className="flex gap-1 sm:gap-2 md:gap-4 items-center text-base leading-3 md:text-lg whitespace-nowrap">
|
||||
{data
|
||||
? data.tradableInstrument.instrument.code
|
||||
: t('Select market')}
|
||||
<span
|
||||
className={classNames(
|
||||
'transition-transform ease-in-out duration-300 flex',
|
||||
{
|
||||
'rotate-180': openMarket,
|
||||
}
|
||||
)}
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.CHEVRON_DOWN} size={16} />
|
||||
</span>
|
||||
</h1>
|
||||
}
|
||||
>
|
||||
<MarketSelector
|
||||
currentMarketId={marketId}
|
||||
onSelect={() => setOpenMarket(false)}
|
||||
/>
|
||||
</FullScreenPopover>
|
||||
<FullScreenPopover
|
||||
open={openPrice}
|
||||
onOpenChange={(x) => {
|
||||
setOpenPrice(x);
|
||||
}}
|
||||
trigger={
|
||||
<span className="flex gap-2 items-end md:text-md whitespace-nowrap leading-3">
|
||||
{data && (
|
||||
<>
|
||||
<span className="text-xs">
|
||||
<Last24hPriceChange
|
||||
marketId={data.id}
|
||||
decimalPlaces={data.decimalPlaces}
|
||||
/>
|
||||
</span>
|
||||
<span className="flex items-center gap-1">
|
||||
<MarketMarkPrice
|
||||
marketId={data.id}
|
||||
decimalPlaces={data.decimalPlaces}
|
||||
/>
|
||||
<VegaIcon
|
||||
name={VegaIconNames.CHEVRON_DOWN}
|
||||
size={16}
|
||||
className={classNames(
|
||||
'transition-transform ease-in-out duration-300',
|
||||
{
|
||||
'rotate-180': openPrice,
|
||||
}
|
||||
)}
|
||||
/>
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
}
|
||||
>
|
||||
{data && (
|
||||
<div className="px-3 py-6 text-sm grid grid-cols-2 items-center gap-x-4 gap-y-6">
|
||||
<MarketHeaderStats market={data} />
|
||||
</div>
|
||||
)}
|
||||
</FullScreenPopover>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export interface PopoverProps extends PopoverPrimitive.PopoverProps {
|
||||
trigger: React.ReactNode | string;
|
||||
}
|
||||
|
||||
export const FullScreenPopover = ({
|
||||
trigger,
|
||||
children,
|
||||
open,
|
||||
onOpenChange,
|
||||
}: PopoverProps) => {
|
||||
return (
|
||||
<PopoverPrimitive.Root open={open} onOpenChange={onOpenChange}>
|
||||
<PopoverPrimitive.Trigger data-testid="popover-trigger">
|
||||
{trigger}
|
||||
</PopoverPrimitive.Trigger>
|
||||
<PopoverPrimitive.Portal>
|
||||
<PopoverPrimitive.Content
|
||||
data-testid="popover-content"
|
||||
className="w-screen bg-vega-clight-800 dark:bg-vega-cdark-800 border-y border-default"
|
||||
sideOffset={0}
|
||||
>
|
||||
{children}
|
||||
</PopoverPrimitive.Content>
|
||||
</PopoverPrimitive.Portal>
|
||||
</PopoverPrimitive.Root>
|
||||
);
|
||||
};
|
||||
@@ -1 +1,2 @@
|
||||
export * from './navbar';
|
||||
export * from './nav-header';
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
import { VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||
import { MarketSelector } from '../market-selector';
|
||||
import { useMarket, useMarketList } from '@vegaprotocol/markets';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
||||
import { useState } from 'react';
|
||||
import { useT } from '../../lib/use-t';
|
||||
import classNames from 'classnames';
|
||||
|
||||
/**
|
||||
* This is only rendered for the mobile navigation
|
||||
*/
|
||||
export const NavHeader = () => {
|
||||
const t = useT();
|
||||
const { marketId } = useParams();
|
||||
const { data } = useMarket(marketId);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
// Ensure that markets are kept cached so opening the list
|
||||
// shows all markets instantly
|
||||
useMarketList();
|
||||
|
||||
if (!marketId) return null;
|
||||
|
||||
return (
|
||||
<FullScreenPopover
|
||||
open={open}
|
||||
onOpenChange={(x) => {
|
||||
setOpen(x);
|
||||
}}
|
||||
trigger={
|
||||
<h1 className="flex gap-1 sm:gap-2 md:gap-4 items-center text-default text-lg whitespace-nowrap xl:pr-4 xl:border-r border-default">
|
||||
{data ? data.tradableInstrument.instrument.code : t('Select market')}
|
||||
<span
|
||||
className={classNames(
|
||||
'transition-transform ease-in-out duration-300',
|
||||
{
|
||||
'rotate-180': open,
|
||||
}
|
||||
)}
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.CHEVRON_DOWN} size={20} />
|
||||
</span>
|
||||
</h1>
|
||||
}
|
||||
>
|
||||
<MarketSelector
|
||||
currentMarketId={marketId}
|
||||
onSelect={() => setOpen(false)}
|
||||
/>
|
||||
</FullScreenPopover>
|
||||
);
|
||||
};
|
||||
|
||||
export interface PopoverProps extends PopoverPrimitive.PopoverProps {
|
||||
trigger: React.ReactNode | string;
|
||||
}
|
||||
|
||||
export const FullScreenPopover = ({
|
||||
trigger,
|
||||
children,
|
||||
open,
|
||||
onOpenChange,
|
||||
}: PopoverProps) => {
|
||||
return (
|
||||
<PopoverPrimitive.Root open={open} onOpenChange={onOpenChange}>
|
||||
<PopoverPrimitive.Trigger data-testid="popover-trigger">
|
||||
{trigger}
|
||||
</PopoverPrimitive.Trigger>
|
||||
<PopoverPrimitive.Portal>
|
||||
<PopoverPrimitive.Content
|
||||
data-testid="popover-content"
|
||||
className="w-screen bg-vega-clight-800 dark:bg-vega-cdark-800 text-default border border-default"
|
||||
sideOffset={5}
|
||||
>
|
||||
{children}
|
||||
</PopoverPrimitive.Content>
|
||||
</PopoverPrimitive.Portal>
|
||||
</PopoverPrimitive.Root>
|
||||
);
|
||||
};
|
||||
@@ -34,7 +34,13 @@ import { supportedLngs } from '../../lib/i18n';
|
||||
type MenuState = 'wallet' | 'nav' | null;
|
||||
type Theme = 'system' | 'yellow';
|
||||
|
||||
export const Navbar = ({ theme = 'system' }: { theme?: Theme }) => {
|
||||
export const Navbar = ({
|
||||
children,
|
||||
theme = 'system',
|
||||
}: {
|
||||
children?: ReactNode;
|
||||
theme?: Theme;
|
||||
}) => {
|
||||
const i18n = useI18n();
|
||||
const t = useT();
|
||||
// menu state for small screens
|
||||
@@ -69,6 +75,8 @@ export const Navbar = ({ theme = 'system' }: { theme?: Theme }) => {
|
||||
>
|
||||
<VLogo className="w-4" />
|
||||
</NavLink>
|
||||
{/* Left section */}
|
||||
<div className="flex items-center lg:hidden">{children}</div>
|
||||
{/* Used to show header in nav on mobile */}
|
||||
<div className="hidden lg:block">
|
||||
<NavbarMenu onClick={() => setMenu(null)} />
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
CONSOLE_IMAGE_NAME=vegaprotocol/trading:latest
|
||||
VEGA_VERSION=v0.74.0-preview.10
|
||||
VEGA_VERSION=v0.74.0-preview.8
|
||||
LOCAL_SERVER=false
|
||||
|
||||
@@ -111,7 +111,6 @@ def init_vega(request=None):
|
||||
f"Container {container.id} started",
|
||||
extra={"worker_id": os.environ.get("PYTEST_XDIST_WORKER")},
|
||||
)
|
||||
vega.container = container
|
||||
yield vega
|
||||
except APIError as e:
|
||||
logger.info(f"Container creation failed.")
|
||||
@@ -178,34 +177,10 @@ def init_page(vega: VegaServiceNull, browser: Browser, request: pytest.FixtureRe
|
||||
|
||||
@pytest.fixture
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance))
|
||||
yield vega_instance
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
|
||||
def cleanup_container(vega_instance):
|
||||
try:
|
||||
# Attempt to stop the container if it's still running
|
||||
if vega_instance.container.status == 'running':
|
||||
print(f"Stopping container {vega_instance.container.id}")
|
||||
vega_instance.container.stop()
|
||||
else:
|
||||
print(f"Container {vega_instance.container.id} is not running.")
|
||||
except docker.errors.NotFound:
|
||||
print(f"Container {vega_instance.container.id} not found, may have been stopped and removed.")
|
||||
except Exception as e:
|
||||
print(f"Error during cleanup: {str(e)}")
|
||||
|
||||
try:
|
||||
# Attempt to remove the container
|
||||
vega_instance.container.remove()
|
||||
print(f"Container {vega_instance.container.id} removed.")
|
||||
except docker.errors.NotFound:
|
||||
print(f"Container {vega_instance.container.id} not found, may have been removed.")
|
||||
except Exception as e:
|
||||
print(f"Error during container removal: {str(e)}")
|
||||
|
||||
@pytest.fixture
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page_instance:
|
||||
|
||||
@@ -2,7 +2,7 @@ import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from datetime import datetime, timedelta
|
||||
from conftest import init_vega, cleanup_container
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import wait_for_toast_confirmation
|
||||
|
||||
@@ -17,10 +17,8 @@ expire = "expire"
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
||||
@@ -3,7 +3,7 @@ from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from datetime import datetime, timedelta
|
||||
from conftest import init_vega, cleanup_container
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
stop_order_btn = "order-type-Stop"
|
||||
@@ -259,10 +259,9 @@ def test_submit_stop_limit_order_cancel(
|
||||
|
||||
class TestStopOcoValidation:
|
||||
@pytest.fixture(scope="class")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
def vega(self, request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def continuous_market(self, vega):
|
||||
|
||||
@@ -2,7 +2,7 @@ import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.utils import change_keys
|
||||
from conftest import init_vega, cleanup_container
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
order_size = "order-size"
|
||||
@@ -14,9 +14,8 @@ deal_ticket_deposit_dialog_button = "deal-ticket-deposit-dialog-button"
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
||||
@@ -4,7 +4,7 @@ from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET
|
||||
from conftest import init_vega, init_page, auth_setup, cleanup_container
|
||||
from conftest import init_vega, init_page, auth_setup
|
||||
from actions.utils import next_epoch, change_keys, forward_time
|
||||
from fixtures.market import market_exists, setup_continuous_market
|
||||
|
||||
@@ -82,36 +82,31 @@ def market_ids():
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_volume_discount_tier_1(request):
|
||||
with init_vega(request) as vega_volume_discount_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_volume_discount_tier_1)) # Register the cleanup function
|
||||
yield vega_volume_discount_tier_1
|
||||
yield vega_volume_discount_tier_1
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_volume_discount_tier_2(request):
|
||||
with init_vega(request) as vega_volume_discount_tier_2:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_volume_discount_tier_2)) # Register the cleanup function
|
||||
yield vega_volume_discount_tier_2
|
||||
yield vega_volume_discount_tier_2
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_referral_discount_tier_1(request):
|
||||
with init_vega(request) as vega_referral_discount_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_referral_discount_tier_1)) # Register the cleanup function
|
||||
yield vega_referral_discount_tier_1
|
||||
yield vega_referral_discount_tier_1
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_referral_discount_tier_2(request):
|
||||
with init_vega(request) as vega_referral_discount_tier_2:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_referral_discount_tier_2)) # Register the cleanup function
|
||||
yield vega_referral_discount_tier_2
|
||||
yield vega_referral_discount_tier_2
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_referral_and_volume_discount(request):
|
||||
with init_vega(request) as vega_referral_and_volume_discount:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_referral_and_volume_discount)) # Register the cleanup function
|
||||
yield vega_referral_and_volume_discount
|
||||
yield vega_referral_and_volume_discount
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
|
||||
@@ -3,7 +3,7 @@ from playwright.sync_api import expect, Page
|
||||
import json
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from fixtures.market import setup_simple_market
|
||||
from conftest import init_vega, cleanup_container
|
||||
from conftest import init_vega
|
||||
from actions.vega import submit_order
|
||||
from wallet_config import MM_WALLET, TERMINATE_WALLET, wallets
|
||||
import logging
|
||||
@@ -12,10 +12,9 @@ logger = logging.getLogger()
|
||||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
|
||||
@@ -2,6 +2,8 @@ import pytest
|
||||
from playwright.sync_api import expect, Page
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market
|
||||
from wallet_config import MM_WALLET2
|
||||
|
||||
def hover_and_assert_tooltip(page: Page, element_text):
|
||||
@@ -9,30 +11,39 @@ def hover_and_assert_tooltip(page: Page, element_text):
|
||||
element.hover()
|
||||
expect(page.get_by_role("tooltip")).to_be_visible()
|
||||
|
||||
class TestIcebergOrdersValidations:
|
||||
@pytest.fixture(scope="class")
|
||||
def vega(self, request):
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_iceberg_submit(continuous_market, vega: VegaServiceNull, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id("iceberg").click()
|
||||
page.get_by_test_id("order-peak-size").type("2")
|
||||
page.get_by_test_id("order-minimum-size").type("1")
|
||||
page.get_by_test_id("order-size").type("3")
|
||||
page.get_by_test_id("order-price").type("107")
|
||||
page.get_by_test_id("place-order").click()
|
||||
@pytest.fixture(scope="class")
|
||||
def continuous_market(self, vega):
|
||||
return setup_continuous_market(vega)
|
||||
|
||||
expect(page.get_by_test_id("toast-content")).to_have_text(
|
||||
"Awaiting confirmationPlease wait for your transaction to be confirmedView in block explorer"
|
||||
)
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_iceberg_submit(self, continuous_market, vega: VegaServiceNull, page: Page):
|
||||
page.goto(f"/#/markets/{continuous_market}")
|
||||
page.get_by_test_id("iceberg").click()
|
||||
page.get_by_test_id("order-peak-size").type("2")
|
||||
page.get_by_test_id("order-minimum-size").type("1")
|
||||
page.get_by_test_id("order-size").type("3")
|
||||
page.get_by_test_id("order-price").type("107")
|
||||
page.get_by_test_id("place-order").click()
|
||||
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
expect(page.get_by_test_id("toast-content")).to_have_text(
|
||||
"Order filledYour transaction has been confirmedView in block explorerSubmit order - filledBTC:DAI_2023+3 @ 107.00 tDAI"
|
||||
)
|
||||
page.get_by_test_id("All").click()
|
||||
expect(
|
||||
(page.get_by_role("row").locator('[col-id="type"]')).nth(1)
|
||||
).to_have_text("Limit (Iceberg)")
|
||||
expect(page.get_by_test_id("toast-content")).to_have_text(
|
||||
"Awaiting confirmationPlease wait for your transaction to be confirmedView in block explorer"
|
||||
)
|
||||
|
||||
vega.wait_fn(1)
|
||||
vega.wait_for_total_catchup()
|
||||
expect(page.get_by_test_id("toast-content")).to_have_text(
|
||||
"Order filledYour transaction has been confirmedView in block explorerSubmit order - filledBTC:DAI_2023+3 @ 107.00 tDAI"
|
||||
)
|
||||
page.get_by_test_id("All").click()
|
||||
expect(
|
||||
(page.get_by_role("row").locator('[col-id="type"]')).nth(1)
|
||||
).to_have_text("Limit (Iceberg)")
|
||||
|
||||
@pytest.mark.usefixtures("auth", "risk_accepted")
|
||||
def test_iceberg_open_order(continuous_market, vega: VegaServiceNull, page: Page):
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from conftest import init_vega, cleanup_container
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import next_epoch, truncate_middle, change_keys
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
||||
@@ -4,15 +4,14 @@ import vega_sim.api.governance as governance
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from playwright.sync_api import Page, expect
|
||||
from fixtures.market import setup_continuous_market
|
||||
from conftest import init_vega, cleanup_container
|
||||
from conftest import init_vega
|
||||
from actions.utils import next_epoch
|
||||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="class")
|
||||
|
||||
@@ -3,16 +3,15 @@ import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from fixtures.market import setup_continuous_market
|
||||
from conftest import init_page, init_vega, risk_accepted_setup, cleanup_container
|
||||
from conftest import init_page, init_vega, risk_accepted_setup
|
||||
|
||||
market_title_test_id = "accordion-title"
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
||||
@@ -3,7 +3,7 @@ import vega_sim.api.governance as governance
|
||||
import re
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from conftest import init_vega, cleanup_container
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_simple_market
|
||||
from wallet_config import MM_WALLET
|
||||
|
||||
@@ -13,10 +13,8 @@ col_market_id = '[col-id="market"] [data-testid="stack-cell-primary"]'
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
||||
@@ -3,7 +3,7 @@ from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from actions.vega import submit_order
|
||||
from fixtures.market import setup_simple_market
|
||||
from conftest import init_vega, cleanup_container
|
||||
from conftest import init_vega
|
||||
from actions.utils import wait_for_toast_confirmation, change_keys
|
||||
from wallet_config import MM_WALLET, MM_WALLET2
|
||||
|
||||
@@ -15,10 +15,8 @@ COL_ID_FEE = ".ag-center-cols-container [col-id='fee'] .ag-cell-value"
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
||||
@@ -37,7 +37,7 @@ def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
|
||||
# 6002-MDET-004
|
||||
expect(page.get_by_test_id("market-change")).to_have_text("Change (24h)0.00%0.00")
|
||||
# 6002-MDET-005
|
||||
expect(page.get_by_test_id("market-volume")).to_have_text("Volume (24h)- (- BTC)")
|
||||
expect(page.get_by_test_id("market-volume")).to_have_text("Volume (24h)-")
|
||||
# 6002-MDET-008
|
||||
expect(page.get_by_test_id("market-settlement-asset")).to_have_text(
|
||||
"Settlement assettDAI"
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect, Locator
|
||||
|
||||
from conftest import init_page, init_vega, cleanup_container
|
||||
from conftest import init_page, init_vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
# we can reuse single page instance in all tests
|
||||
|
||||
@@ -2,7 +2,7 @@ import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.service import PeggedOrder
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from conftest import auth_setup, init_page, init_vega, risk_accepted_setup, cleanup_container
|
||||
from conftest import auth_setup, init_page, init_vega, risk_accepted_setup
|
||||
from fixtures.market import setup_continuous_market, setup_simple_market
|
||||
from actions.utils import wait_for_toast_confirmation
|
||||
|
||||
@@ -11,9 +11,8 @@ order_tab = "tab-orders"
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
|
||||
@@ -2,16 +2,15 @@ import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from typing import List
|
||||
from actions.vega import submit_order, submit_liquidity, submit_multiple_orders
|
||||
from conftest import init_vega, cleanup_container
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_simple_market
|
||||
from wallet_config import MM_WALLET, MM_WALLET2
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page, expect
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from conftest import init_vega, cleanup_container
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market
|
||||
|
||||
TOOLTIP_LABEL = "margin-health-tooltip-label"
|
||||
@@ -11,10 +11,8 @@ COL_ID_USED = ".ag-center-cols-container [col-id='used'] .ag-cell-value"
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
from playwright.sync_api import Page
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from conftest import init_vega, cleanup_container
|
||||
from conftest import init_vega
|
||||
from fixtures.market import setup_continuous_market, setup_simple_market
|
||||
from actions.utils import change_keys, create_and_faucet_wallet, forward_time, selector_contains_text
|
||||
from actions.vega import submit_order, submit_liquidity
|
||||
@@ -14,10 +14,8 @@ BUY_ORDERS = [[1, 106], [1, 107], [1, 108]]
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
||||
@@ -2,7 +2,7 @@ import pytest
|
||||
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup, cleanup_container
|
||||
from conftest import init_vega, init_page, auth_setup
|
||||
from fixtures.market import setup_continuous_market, market_exists
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from wallet_config import MM_WALLET, PARTY_A, PARTY_B, PARTY_C, PARTY_D
|
||||
@@ -46,42 +46,36 @@ def market_ids():
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_activity_tier_0(request):
|
||||
with init_vega(request) as vega_activity_tier_0:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_activity_tier_0)) # Register the cleanup function
|
||||
yield vega_activity_tier_0
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_hoarder_tier_0(request):
|
||||
with init_vega(request) as vega_hoarder_tier_0:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_hoarder_tier_0)) # Register the cleanup function
|
||||
yield vega_hoarder_tier_0
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_combo_tier_0(request):
|
||||
with init_vega(request) as vega_combo_tier_0:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_combo_tier_0)) # Register the cleanup function
|
||||
yield vega_combo_tier_0
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_activity_tier_1(request):
|
||||
with init_vega(request) as vega_activity_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_activity_tier_1)) # Register the cleanup function
|
||||
yield vega_activity_tier_1
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_hoarder_tier_1(request):
|
||||
with init_vega(request) as vega_hoarder_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_hoarder_tier_1)) # Register the cleanup function
|
||||
yield vega_hoarder_tier_1
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega_combo_tier_1(request):
|
||||
with init_vega(request) as vega_combo_tier_1:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_combo_tier_1)) # Register the cleanup function
|
||||
yield vega_combo_tier_1
|
||||
|
||||
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
import pytest
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from playwright.sync_api import Page, expect
|
||||
from conftest import init_vega, init_page, auth_setup, risk_accepted_setup, cleanup_container
|
||||
from fixtures.market import setup_continuous_market
|
||||
from actions.utils import next_epoch, change_keys, create_and_faucet_wallet
|
||||
from wallet_config import MM_WALLET, WalletConfig
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
|
||||
# region Constants
|
||||
ACTIVITY = "activity"
|
||||
HOARDER = "hoarder"
|
||||
COMBO = "combo"
|
||||
|
||||
REWARDS_URL = "/#/rewards"
|
||||
|
||||
# test IDs
|
||||
COMBINED_MULTIPLIERS = "combined-multipliers"
|
||||
TOTAL_REWARDS = "total-rewards"
|
||||
PRICE_TAKING_COL_ID = '[col-id="priceTaking"]'
|
||||
TOTAL_COL_ID = '[col-id="total"]'
|
||||
ROW = "row"
|
||||
STREAK_REWARD_MULTIPLIER_VALUE = "streak-reward-multiplier-value"
|
||||
HOARDER_REWARD_MULTIPLIER_VALUE = "hoarder-reward-multiplier-value"
|
||||
HOARDER_BONUS_TOTAL_HOARDED = "hoarder-bonus-total-hoarded"
|
||||
EARNED_BY_ME_BUTTON = "earned-by-me-button"
|
||||
TRANSFER_AMOUNT = "transfer-amount"
|
||||
EPOCH_STREAK = "epoch-streak"
|
||||
|
||||
# endregion
|
||||
|
||||
# Keys
|
||||
PARTY_A = "PARTY_A"
|
||||
PARTY_B = "PARTY_B"
|
||||
PARTY_C = "PARTY_C"
|
||||
PARTY_D = "PARTY_D"
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def page(vega, browser, request):
|
||||
with init_page(vega, browser, request) as page:
|
||||
risk_accepted_setup(page)
|
||||
auth_setup(vega, page)
|
||||
page.goto(REWARDS_URL)
|
||||
change_keys(page, vega, PARTY_B)
|
||||
yield page
|
||||
|
||||
|
||||
@pytest.fixture(scope="module", autouse=True)
|
||||
def setup_market_with_reward_program(vega: VegaServiceNull):
|
||||
tDAI_market = setup_continuous_market(vega)
|
||||
PARTY_A, PARTY_B, PARTY_C, PARTY_D = keys(vega)
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_C.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
|
||||
vega.mint(key_name=PARTY_D.name, asset=tDAI_asset_id, amount=100000)
|
||||
next_epoch(vega=vega)
|
||||
|
||||
vega.update_network_parameter(
|
||||
proposal_key=MM_WALLET.name,
|
||||
parameter="rewards.activityStreak.benefitTiers",
|
||||
new_value=ACTIVITY_STREAKS,
|
||||
)
|
||||
print("update_network_parameter activity done")
|
||||
next_epoch(vega=vega)
|
||||
|
||||
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
|
||||
vega.update_network_parameter(
|
||||
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
|
||||
)
|
||||
|
||||
next_epoch(vega=vega)
|
||||
vega.recurring_transfer(
|
||||
from_key_name=PARTY_A.name,
|
||||
from_account_type=vega_protos.vega.ACCOUNT_TYPE_GENERAL,
|
||||
to_account_type=vega_protos.vega.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
|
||||
asset=tDAI_asset_id,
|
||||
reference="reward",
|
||||
asset_for_metric=tDAI_asset_id,
|
||||
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
|
||||
amount=100,
|
||||
factor=1.0,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_B.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
vega.submit_order(
|
||||
trading_key=PARTY_A.name,
|
||||
market_id=tDAI_market,
|
||||
order_type="TYPE_MARKET",
|
||||
time_in_force="TIME_IN_FORCE_IOC",
|
||||
side="SIDE_BUY",
|
||||
volume=1,
|
||||
)
|
||||
|
||||
vega.wait_for_total_catchup()
|
||||
|
||||
next_epoch(vega=vega)
|
||||
return tDAI_market, tDAI_asset_id
|
||||
|
||||
|
||||
ACTIVITY_STREAKS = """
|
||||
{
|
||||
"tiers": [
|
||||
{
|
||||
"minimum_activity_streak": 2,
|
||||
"reward_multiplier": "2.0",
|
||||
"vesting_multiplier": "1.1"
|
||||
}
|
||||
]
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
def keys(vega):
|
||||
PARTY_A = WalletConfig("PARTY_A", "PARTY_A")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_A)
|
||||
PARTY_B = WalletConfig("PARTY_B", "PARTY_B")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_B)
|
||||
PARTY_C = WalletConfig("PARTY_C", "PARTY_C")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_C)
|
||||
PARTY_D = WalletConfig("PARTY_D", "PARTY_D")
|
||||
create_and_faucet_wallet(vega=vega, wallet=PARTY_D)
|
||||
return PARTY_A, PARTY_B, PARTY_C, PARTY_D
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_0")
|
||||
def test_network_reward_pot(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text("50.00 tDAI")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_0")
|
||||
def test_reward_multiplier(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text("1x")
|
||||
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text("1x")
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_0")
|
||||
def test_activity_streak(
|
||||
page: Page,
|
||||
):
|
||||
expect(page.get_by_test_id(EPOCH_STREAK)).to_have_text(
|
||||
"Active trader: 1 epochs so far "
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.xdist_group(name="test_rewards_activity_tier_0")
|
||||
def test_reward_history(
|
||||
page: Page,
|
||||
):
|
||||
page.locator('[name="fromEpoch"]').fill("1")
|
||||
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
|
||||
"100.00100.00%"
|
||||
)
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("100.00")
|
||||
page.get_by_test_id(EARNED_BY_ME_BUTTON).click()
|
||||
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text("50.00")
|
||||
@@ -1,13 +1,12 @@
|
||||
import pytest
|
||||
from playwright.sync_api import expect, Page
|
||||
from conftest import init_vega, cleanup_container
|
||||
from conftest import init_vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
def vega():
|
||||
with init_vega() as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("risk_accepted")
|
||||
|
||||
@@ -2,17 +2,17 @@ import pytest
|
||||
from playwright.sync_api import expect, Page
|
||||
import vega_sim.proto.vega as vega_protos
|
||||
from vega_sim.null_service import VegaServiceNull
|
||||
from conftest import init_vega, cleanup_container
|
||||
from conftest import init_vega
|
||||
from actions.utils import next_epoch, change_keys
|
||||
from fixtures.market import setup_continuous_market
|
||||
from conftest import auth_setup, init_page, init_vega, risk_accepted_setup
|
||||
from wallet_config import PARTY_A, PARTY_B, PARTY_C, PARTY_D, MM_WALLET
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vega(request):
|
||||
with init_vega(request) as vega_instance:
|
||||
request.addfinalizer(lambda: cleanup_container(vega_instance)) # Register the cleanup function
|
||||
yield vega_instance
|
||||
with init_vega(request) as vega:
|
||||
yield vega
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
@@ -237,12 +237,12 @@ def test_team_page_headline(team_page: Page, setup_teams_and_games):
|
||||
expect(team_page.get_by_test_id("team-name")).to_have_text(team_name)
|
||||
expect(team_page.get_by_test_id("members-count-stat")).to_have_text("4")
|
||||
|
||||
expect(team_page.get_by_test_id("total-games-stat")).to_have_text("1")
|
||||
expect(team_page.get_by_test_id("total-games-stat")).to_have_text("2")
|
||||
|
||||
# TODO this still seems wrong as its always 0
|
||||
expect(team_page.get_by_test_id("total-volume-stat")).to_have_text("0")
|
||||
|
||||
expect(team_page.get_by_test_id("rewards-paid-stat")).to_have_text("78")
|
||||
expect(team_page.get_by_test_id("rewards-paid-stat")).to_have_text("214")
|
||||
|
||||
|
||||
def test_switch_teams(team_page: Page, vega: VegaServiceNull):
|
||||
@@ -271,7 +271,7 @@ def test_leaderboard(competitions_page: Page, setup_teams_and_games):
|
||||
|
||||
# FIXME: the numbers are different we need to clarify this with the backend
|
||||
# expect(competitions_page.get_by_test_id("earned-1")).to_have_text("160")
|
||||
expect(competitions_page.get_by_test_id("games-1")).to_have_text("1")
|
||||
expect(competitions_page.get_by_test_id("games-1")).to_have_text("2")
|
||||
|
||||
# TODO still odd that this is 0
|
||||
expect(competitions_page.get_by_test_id("volume-0")).to_have_text("-")
|
||||
|
||||
@@ -14,7 +14,7 @@ import './styles.css';
|
||||
import { usePageTitleStore } from '../stores';
|
||||
import DialogsContainer from './dialogs-container';
|
||||
import ToastsManager from './toasts-manager';
|
||||
import { HashRouter, useLocation } from 'react-router-dom';
|
||||
import { HashRouter, useLocation, Route, Routes } from 'react-router-dom';
|
||||
import { Bootstrapper } from '../components/bootstrapper';
|
||||
import { AnnouncementBanner } from '../components/banner';
|
||||
import { Navbar } from '../components/navbar';
|
||||
@@ -25,7 +25,9 @@ import {
|
||||
ProtocolUpgradeProposalNotification,
|
||||
} from '@vegaprotocol/proposals';
|
||||
import { ViewingBanner } from '../components/viewing-banner';
|
||||
import { NavHeader } from '../components/navbar/nav-header';
|
||||
import { Telemetry } from '../components/telemetry';
|
||||
import { Routes as AppRoutes } from '../lib/links';
|
||||
import { SSRLoader } from './ssr-loader';
|
||||
import { PartyActiveOrdersHandler } from './party-active-orders-handler';
|
||||
import { MaybeConnectEagerly } from './maybe-connect-eagerly';
|
||||
@@ -71,7 +73,16 @@ function AppBody({ Component }: AppProps) {
|
||||
<Title />
|
||||
<div className={gridClasses}>
|
||||
<AnnouncementBanner />
|
||||
<Navbar theme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'system'} />
|
||||
<Navbar theme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'system'}>
|
||||
<Routes>
|
||||
<Route
|
||||
path={AppRoutes.MARKETS}
|
||||
// render nothing for markets/all, otherwise markets/:marketId will match with markets/all
|
||||
element={null}
|
||||
/>
|
||||
<Route path={AppRoutes.MARKET} element={<NavHeader />} />
|
||||
</Routes>
|
||||
</Navbar>
|
||||
<div data-testid="banners">
|
||||
<ProtocolUpgradeProposalNotification
|
||||
mode={ProtocolUpgradeCountdownMode.IN_ESTIMATED_TIME_REMAINING}
|
||||
|
||||
@@ -24,14 +24,11 @@ export default function Document() {
|
||||
|
||||
{/* scripts */}
|
||||
<script src="/theme-setter.js" type="text/javascript" async />
|
||||
|
||||
{/* manifest */}
|
||||
<link rel="manifest" href="/apps/trading/public/manifest.json" />
|
||||
</Head>
|
||||
<Html>
|
||||
<body
|
||||
// Next.js will set body to display none until js runs. Because the entire app is client rendered
|
||||
// and delivered via IPFS we override this to show a server side render loading animation until the
|
||||
// Nextjs will set body to display none until js runs. Because the entire app is client rendered
|
||||
// and delivered via ipfs we override this to show a server side render loading animation until the
|
||||
// js is downloaded and react takes over rendering
|
||||
style={{ display: 'block' }}
|
||||
className="bg-white dark:bg-vega-cdark-900 text-default font-alpha"
|
||||
|
||||
@@ -23,7 +23,7 @@ import { NotFound as ReferralNotFound } from '../client-pages/referrals/error-bo
|
||||
import { compact } from 'lodash';
|
||||
import { useFeatureFlags } from '@vegaprotocol/environment';
|
||||
import { LiquidityHeader } from '../components/liquidity-header';
|
||||
import { MarketHeader, MobileMarketHeader } from '../components/market-header';
|
||||
import { MarketHeader } from '../components/market-header';
|
||||
import { PortfolioSidebar } from '../client-pages/portfolio/portfolio-sidebar';
|
||||
import { LiquiditySidebar } from '../client-pages/liquidity/liquidity-sidebar';
|
||||
import { MarketsSidebar } from '../client-pages/markets/markets-sidebar';
|
||||
@@ -33,7 +33,6 @@ import { CompetitionsTeams } from '../client-pages/competitions/competitions-tea
|
||||
import { CompetitionsTeam } from '../client-pages/competitions/competitions-team';
|
||||
import { CompetitionsCreateTeam } from '../client-pages/competitions/competitions-create-team';
|
||||
import { CompetitionsUpdateTeam } from '../client-pages/competitions/competitions-update-team';
|
||||
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
|
||||
|
||||
// These must remain dynamically imported as pennant cannot be compiled by nextjs due to ESM
|
||||
// Using dynamic imports is a workaround for this until pennant is published as ESM
|
||||
@@ -51,9 +50,6 @@ const NotFound = () => {
|
||||
|
||||
export const useRouterConfig = (): RouteObject[] => {
|
||||
const featureFlags = useFeatureFlags((state) => state.flags);
|
||||
const { screenSize } = useScreenDimensions();
|
||||
const largeScreen = ['lg', 'xl', 'xxl', 'xxxl'].includes(screenSize);
|
||||
const marketHeader = largeScreen ? <MarketHeader /> : <MobileMarketHeader />;
|
||||
const routeConfig = compact([
|
||||
{
|
||||
index: true,
|
||||
@@ -155,7 +151,10 @@ export const useRouterConfig = (): RouteObject[] => {
|
||||
{
|
||||
path: 'markets/*',
|
||||
element: (
|
||||
<LayoutWithSidebar header={marketHeader} sidebar={<MarketsSidebar />} />
|
||||
<LayoutWithSidebar
|
||||
header={<MarketHeader />}
|
||||
sidebar={<MarketsSidebar />}
|
||||
/>
|
||||
),
|
||||
children: [
|
||||
{
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"name": "Vega Protocol - Trading",
|
||||
"short_name": "Console",
|
||||
"description": "Vega Protocol - Trading dApp",
|
||||
"start_url": "/",
|
||||
"display": "standalone",
|
||||
"orientation": "portrait",
|
||||
"theme_color": "#000000",
|
||||
"background_color": "#ffffff",
|
||||
"icons": [
|
||||
{
|
||||
"src": "favicon.ico",
|
||||
"sizes": "64x64 32x32 24x24 16x16",
|
||||
"type": "image/x-icon"
|
||||
},
|
||||
{
|
||||
"src": "cover.png",
|
||||
"type": "image/png",
|
||||
"sizes": "192x192"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -446,5 +446,9 @@
|
||||
"Choose a team": "Choose a team",
|
||||
"Join a team": "Join a team",
|
||||
"Solo team / lone wolf": "Solo team / lone wolf",
|
||||
"Choose a team to get involved": "Choose a team to get involved"
|
||||
"Choose a team to get involved": "Choose a team to get involved",
|
||||
"Go back to the team's profile": "Go back to the team's profile",
|
||||
"Go back to the competitions": "Go back to the competitions",
|
||||
"Your team ID:": "Your team ID:",
|
||||
"Changes successfully saved to your team.": "Changes successfully saved to your team."
|
||||
}
|
||||
|
||||
@@ -18,15 +18,12 @@ interface Props {
|
||||
initialValue?: string[];
|
||||
isHeader?: boolean;
|
||||
noUpdate?: boolean;
|
||||
// render prop for no price change
|
||||
fallback?: React.ReactNode;
|
||||
}
|
||||
|
||||
export const Last24hPriceChange = ({
|
||||
marketId,
|
||||
decimalPlaces,
|
||||
initialValue,
|
||||
fallback,
|
||||
}: Props) => {
|
||||
const t = useT();
|
||||
const { oneDayCandles, error, fiveDaysCandles } = useCandles({
|
||||
@@ -51,13 +48,13 @@ export const Last24hPriceChange = ({
|
||||
</span>
|
||||
}
|
||||
>
|
||||
<span>{fallback}</span>
|
||||
<span>-</span>
|
||||
</Tooltip>
|
||||
);
|
||||
}
|
||||
|
||||
if (error || !isNumeric(decimalPlaces)) {
|
||||
return <span>{fallback}</span>;
|
||||
return <span>-</span>;
|
||||
}
|
||||
|
||||
const candles = oneDayCandles?.map((c) => c.close) || initialValue || [];
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
import { calcCandleVolume, calcCandleVolumePrice } from '../../market-utils';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
formatNumber,
|
||||
isNumeric,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { calcCandleVolume } from '../../market-utils';
|
||||
import { addDecimalsFormatNumber, isNumeric } from '@vegaprotocol/utils';
|
||||
import { Tooltip } from '@vegaprotocol/ui-toolkit';
|
||||
import { useCandles } from '../../hooks';
|
||||
import { useT } from '../../use-t';
|
||||
@@ -13,17 +9,13 @@ interface Props {
|
||||
positionDecimalPlaces?: number;
|
||||
formatDecimals?: number;
|
||||
initialValue?: string;
|
||||
marketDecimals?: number;
|
||||
quoteUnit?: string;
|
||||
}
|
||||
|
||||
export const Last24hVolume = ({
|
||||
marketId,
|
||||
marketDecimals,
|
||||
positionDecimalPlaces,
|
||||
formatDecimals,
|
||||
initialValue,
|
||||
quoteUnit,
|
||||
}: Props) => {
|
||||
const t = useT();
|
||||
const { oneDayCandles, fiveDaysCandles } = useCandles({
|
||||
@@ -36,11 +28,6 @@ export const Last24hVolume = ({
|
||||
(!oneDayCandles || oneDayCandles?.length === 0)
|
||||
) {
|
||||
const candleVolume = calcCandleVolume(fiveDaysCandles);
|
||||
const candleVolumePrice = calcCandleVolumePrice(
|
||||
fiveDaysCandles,
|
||||
marketDecimals,
|
||||
positionDecimalPlaces
|
||||
);
|
||||
const candleVolumeValue =
|
||||
candleVolume && isNumeric(positionDecimalPlaces)
|
||||
? addDecimalsFormatNumber(
|
||||
@@ -55,8 +42,8 @@ export const Last24hVolume = ({
|
||||
<div>
|
||||
<span className="flex flex-col">
|
||||
{t(
|
||||
'24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}} ({{candleVolumePrice}} {{quoteUnit}})',
|
||||
{ candleVolumeValue, candleVolumePrice, quoteUnit }
|
||||
'24 hour change is unavailable at this time. The volume change in the last 120 hours is {{candleVolumeValue}}',
|
||||
{ candleVolumeValue }
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
@@ -70,18 +57,10 @@ export const Last24hVolume = ({
|
||||
? calcCandleVolume(oneDayCandles)
|
||||
: initialValue;
|
||||
|
||||
const candleVolumePrice = oneDayCandles
|
||||
? calcCandleVolumePrice(
|
||||
oneDayCandles,
|
||||
marketDecimals,
|
||||
positionDecimalPlaces
|
||||
)
|
||||
: initialValue;
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
description={t(
|
||||
'The total number of contracts traded in the last 24 hours. (Total value of contracts traded in the last 24 hours)'
|
||||
'The total number of contracts traded in the last 24 hours.'
|
||||
)}
|
||||
>
|
||||
<span>
|
||||
@@ -91,12 +70,7 @@ export const Last24hVolume = ({
|
||||
positionDecimalPlaces,
|
||||
formatDecimals
|
||||
)
|
||||
: '-'}{' '}
|
||||
(
|
||||
{candleVolumePrice && isNumeric(positionDecimalPlaces)
|
||||
? formatNumber(candleVolumePrice, formatDecimals)
|
||||
: '-'}{' '}
|
||||
{quoteUnit})
|
||||
: '-'}
|
||||
</span>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
@@ -155,7 +155,6 @@ export const MarketVolumeInfoPanel = ({ market }: MarketInfoProps) => {
|
||||
<Last24hVolume
|
||||
marketId={market.id}
|
||||
positionDecimalPlaces={market.positionDecimalPlaces}
|
||||
marketDecimals={market.decimalPlaces}
|
||||
/>
|
||||
),
|
||||
openInterest: dash(data?.openInterest),
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import type { Market, MarketMaybeWithDataAndCandles } from './markets-provider';
|
||||
import {
|
||||
calcCandleVolumePrice,
|
||||
calcTradedFactor,
|
||||
filterAndSortMarkets,
|
||||
sumFeesFactors,
|
||||
@@ -146,31 +145,3 @@ describe('sumFeesFactors', () => {
|
||||
).toEqual(0.6);
|
||||
});
|
||||
});
|
||||
|
||||
describe('calcCandleVolumePrice', () => {
|
||||
it('calculates the volume price', () => {
|
||||
const candles = [
|
||||
{
|
||||
volume: '1000',
|
||||
high: '100',
|
||||
low: '10',
|
||||
open: '15',
|
||||
close: '90',
|
||||
periodStart: '2022-05-18T13:08:27.693537312Z',
|
||||
},
|
||||
{
|
||||
volume: '1000',
|
||||
high: '100',
|
||||
low: '10',
|
||||
open: '15',
|
||||
close: '90',
|
||||
periodStart: '2022-05-18T14:08:27.693537312Z',
|
||||
},
|
||||
];
|
||||
const marketDecimals = 3;
|
||||
const positionDecimalPlaces = 2;
|
||||
expect(
|
||||
calcCandleVolumePrice(candles, marketDecimals, positionDecimalPlaces)
|
||||
).toEqual('2');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
import {
|
||||
addDecimal,
|
||||
formatNumberPercentage,
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { formatNumberPercentage, toBigNum } from '@vegaprotocol/utils';
|
||||
import { MarketState, MarketTradingMode } from '@vegaprotocol/types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import orderBy from 'lodash/orderBy';
|
||||
@@ -151,51 +147,10 @@ export const calcCandleHigh = (candles: Candle[]): string | undefined => {
|
||||
.toString();
|
||||
};
|
||||
|
||||
/**
|
||||
* The total number of contracts traded in the last 24 hours.
|
||||
*
|
||||
* @param candles
|
||||
* @returns the volume of a given set of candles
|
||||
*/
|
||||
export const calcCandleVolume = (candles: Candle[]): string | undefined =>
|
||||
candles &&
|
||||
candles.reduce((acc, c) => new BigNumber(acc).plus(c.volume).toString(), '0');
|
||||
|
||||
/**
|
||||
* The total number of contracts traded in the last 24 hours. (Total value of contracts traded in the last 24 hours)
|
||||
* The volume is calculated as the sum of the product of the volume and the high price of each candle.
|
||||
* The result is formatted using positionDecimalPlaces to account for the position size.
|
||||
* The result is formatted using marketDecimals to account for the market precision.
|
||||
*
|
||||
* @param candles
|
||||
* @param marketDecimals
|
||||
* @param positionDecimalPlaces
|
||||
* @returns the volume (in quote price) of a given set of candles
|
||||
*/
|
||||
export const calcCandleVolumePrice = (
|
||||
candles: Candle[],
|
||||
marketDecimals: number = 1,
|
||||
positionDecimalPlaces: number = 1
|
||||
): string | undefined =>
|
||||
candles &&
|
||||
candles.reduce(
|
||||
(acc, c) =>
|
||||
new BigNumber(acc)
|
||||
.plus(
|
||||
BigNumber(addDecimal(c.volume, positionDecimalPlaces)).times(
|
||||
addDecimal(c.high, marketDecimals)
|
||||
)
|
||||
)
|
||||
.toString(),
|
||||
'0'
|
||||
);
|
||||
|
||||
/**
|
||||
* Calculates the traded factor of a given market.
|
||||
*
|
||||
* @param m
|
||||
* @returns
|
||||
*/
|
||||
export const calcTradedFactor = (m: MarketMaybeWithDataAndCandles) => {
|
||||
const volume = Number(calcCandleVolume(m.candles || []) || 0);
|
||||
const price = m.data?.markPrice ? Number(m.data.markPrice) : 0;
|
||||
|
||||
Reference in New Issue
Block a user