Compare commits

..
Author SHA1 Message Date
Madalina Raicu 08e77935ce feat(trading): show gray bar is user is not active 2024-01-05 11:22:39 +02:00
Madalina Raicu fe0e43ba1b feat(trading): tier as of last epoch copy change 2024-01-05 11:18:23 +02:00
Madalina Raicu 268b4d308a feat(trading): move to node guard 2024-01-04 14:53:38 +02:00
Madalina Raicu 42dfc217d7 chore(trading): load assets and markets on startup 2024-01-03 16:30:16 +02:00
Madalina Raicu 185c2e9b41 feat(trading): remove fill and show rewards history when pubkey is not connected 2024-01-03 16:13:01 +02:00
Madalina Raicu 7479478192 feat(trading): fix lint issues on active-rewards.spec 2024-01-03 12:26:31 +02:00
Madalina Raicu f3f049d21b Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/activity-streaks 2024-01-03 12:11:00 +02:00
Madalina Raicu 900ff07493 Merge branch 'feat/activity-streaks' of github.com:vegaprotocol/frontend-monorepo into feat/activity-streaks 2024-01-03 12:02:52 +02:00
bwallacee 7a984aa798 feat(trading): test ids 2024-01-03 09:59:29 +00:00
Madalina Raicu 45242de622 feat(trading): add search by asset and market 2023-12-29 19:25:21 +02:00
Madalina Raicu c13842a0c6 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/activity-streaks 2023-12-29 14:39:01 +02:00
Madalina Raicu 4b3fddb8ad chore(trading): update tests 2023-12-29 13:41:42 +02:00
Madalina Raicu a5c844b70c chore(trading): use flex instead of grid in container 2023-12-29 13:30:59 +02:00
Madalina Raicu ed10862122 feat(trading): refactor streaks 2023-12-29 13:26:58 +02:00
Madalina Raicu fc2cf01305 feat(trading): use h3 2023-12-29 12:51:20 +02:00
Madalina Raicu 7c0b362efe Merge branch 'feat/activity-streaks' of github.com:vegaprotocol/frontend-monorepo into feat/activity-streaks 2023-12-29 12:14:20 +02:00
bwallacee acbcced3c0 feat(trading): add market-sim tests for local dev 2023-12-28 16:21:31 +00:00
Madalina Raicu 5d05b9c264 chore(trading): remove xmlns from icons 2023-12-28 14:40:26 +02:00
Madalina Raicu f926067315 fix(trading): tier number fix 2023-12-28 13:12:02 +02:00
Madalina Raicu e058937072 feat(trading): use i18n pluralisation 2023-12-27 18:45:39 +02:00
Madalina Raicu 011c5591f5 feat(trading): enrich rewards page query 2023-12-27 17:55:19 +02:00
Madalina Raicu bb98000c11 feat(trading): search by entity scope 2023-12-27 14:36:33 +02:00
Madalina Raicu afceb010da fix(trading): add tiers check length 2023-12-27 12:42:42 +02:00
Madalina Raicu 61ae417561 fix(trading): fix tiers color 2023-12-27 11:27:12 +02:00
Madalina Raicu 1c7ffd8298 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/activity-streaks 2023-12-27 10:36:02 +02:00
Madalina Raicu 1d258532b8 chore(trading): add active reward card tests 2023-12-22 20:17:56 +02:00
Madalina Raicu fb96fef15a feat(trading): active cards show dispatch asset if no market 2023-12-22 19:07:17 +02:00
Madalina Raicu 69070bbb61 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/activity-streaks 2023-12-22 16:34:56 +02:00
Madalina Raicu e8f1bb6b6b feat(trading): render empty tears if no streak 2023-12-22 16:06:34 +02:00
Madalina Raicu 255aab2189 feat(trading): render empty tears if no streak 2023-12-22 15:58:37 +02:00
Madalina Raicu bac852c4b5 feat(trading): render empty tears if no streak 2023-12-22 15:55:14 +02:00
Madalina Raicu 156bde18c2 feat(trading): show tier next to steak and fix maximum tier 2023-12-22 15:51:34 +02:00
Madalina Raicu d440abfdaf feat(trading): apply cards reward filter 2023-12-22 15:29:43 +02:00
Madalina Raicu 0f1a2f4041 feat(trading): overflow cards & remove reference 2023-12-22 13:27:03 +02:00
Madalina Raicu 5ac6977a64 fix(trading): streak render gray fix 2023-12-21 08:42:08 +00:00
Madalina Raicu c91f67e828 fix(trading): streak render gray fix 2023-12-21 08:40:42 +00:00
Madalina Raicu 50118721aa Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/activity-streaks 2023-12-20 16:26:28 +00:00
Madalina Raicu 20553bd113 fix(trading): fix activity streaks test 2023-12-20 13:15:19 +00:00
Madalina Raicu 8f103df254 fix(trading): update font glitch and copy 2023-12-20 13:14:11 +00:00
Madalina Raicu c4dd62bab6 chore: add extra check for safe prog 2023-12-20 10:46:58 +00:00
Madalina Raicu 9aa9136067 chore(trading): add streaks tests 2023-12-20 10:40:44 +00:00
Madalina Raicu 41f8bcabaf fix(trading): fix icons attributes 2023-12-19 22:50:48 +00:00
Madalina Raicu 6a2f13a7a1 feat(trading): update tier index function 2023-12-19 22:37:09 +00:00
Madalina Raicu 748d8748c5 feat(trading): add font alpha calt 2023-12-19 19:25:27 +00:00
Madalina Raicu a74349648f feat(trading): update colors 2023-12-19 18:31:38 +00:00
Madalina Raicu 77f6e0a5c2 Merge branch 'fix/alpha-lyrae' of github.com:vegaprotocol/frontend-monorepo into feat/activity-streaks 2023-12-19 12:42:12 +00:00
Madalina Raicu 9ac654524c feat(trading): center point on streaks 2023-12-19 12:38:57 +00:00
Matthew Russell 6593ce3d7e fix: alpha lyrae font not working in woff2 2023-12-19 12:33:03 +00:00
Madalina Raicu 21fffba2cb feat: update responsiveness 2023-12-18 19:57:46 +00:00
Madalina Raicu c75a620d69 feat: update grid cols streaks 2023-12-18 19:45:56 +00:00
Madalina Raicu 7d122f0902 feat: update user tier index for reward hoarder bonus 2023-12-18 19:33:40 +00:00
Madalina Raicu 8505e2b930 Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/activity-streaks 2023-12-18 19:28:26 +00:00
Madalina Raicu 750fd921fd feat: add translation 2023-12-18 19:27:22 +00:00
Madalina Raicu 3a3d46ff63 feat: extract market name for active reward cards 2023-12-18 19:18:33 +00:00
Madalina Raicu fd7374668f feat: add activity streak and reward hoarder bonus 2023-12-17 18:33:04 +00:00
Madalina Raicu 42130c17e4 fix: update dispatch metric description 2023-12-15 09:24:53 +00:00
Madalina Raicu 5793144f27 feat: refactor activity streak component 2023-12-14 17:07:09 +00:00
Madalina Raicu acbe4ac16b Merge branch 'develop' of github.com:vegaprotocol/frontend-monorepo into feat/activity-streaks 2023-12-14 17:05:39 +00:00
Madalina Raicu 7accad6739 Merge branch 'feat/activity-streaks' of github.com:vegaprotocol/frontend-monorepo into feat/activity-streaks 2023-12-14 17:05:28 +00:00
m.rayandcandida-d f9b13817fe Update libs/types/src/global-types-mappings.ts
Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>
2023-12-14 17:05:14 +00:00
Madalina Raicu 17fa1505e9 Merge branch 'feat/activity-streaks' of github.com:vegaprotocol/frontend-monorepo into feat/activity-streaks 2023-12-14 17:05:04 +00:00
m.rayandcandida-d 1c34685d4f Update libs/types/src/global-types-mappings.ts
Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>
2023-12-14 16:13:57 +00:00
m.rayandcandida-d 864b7a4367 Update libs/types/src/global-types-mappings.ts
Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>
2023-12-14 16:13:51 +00:00
m.rayandcandida-d 37cf62ba97 Update libs/types/src/global-types-mappings.ts
Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>
2023-12-14 16:13:44 +00:00
m.rayandcandida-d b0b602e068 Update libs/types/src/global-types-mappings.ts
Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>
2023-12-14 16:13:38 +00:00
m.rayandcandida-d ead2deb8ea Update libs/types/src/global-types-mappings.ts
Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>
2023-12-14 16:13:31 +00:00
Madalina Raicu 68429a31a8 fix: revert env file 2023-12-12 13:14:41 +00:00
Madalina Raicu 31d1fc21c6 feat: refactor components 2023-12-12 13:13:29 +00:00
Madalina Raicu 942132e478 feat(trading): activity streaks and active rewards 2023-12-12 00:01:14 +00:00
116 changed files with 1640 additions and 1695 deletions
+3 -46
View File
@@ -19,7 +19,7 @@ jobs:
create-docker-image:
name: Create docker image for console-test
runs-on: ubuntu-22.04
timeout-minutes: 90
timeout-minutes: 20
steps:
#----------------------------------------------
# check-out frontend-monorepo
@@ -138,7 +138,7 @@ jobs:
name: run-tests
runs-on: 8-cores
needs: [create-docker-image, console-test-branch]
timeout-minutes: 90
timeout-minutes: 20
steps:
#----------------------------------------------
# load docker image
@@ -205,7 +205,7 @@ jobs:
# run tests
#----------------------------------------------
- name: Run tests
run: CONSOLE_IMAGE_NAME=ci/trading:local poetry run pytest -v -s --numprocesses 2 --dist loadfile --durations=90
run: CONSOLE_IMAGE_NAME=ci/trading:local poetry run pytest -v -s --numprocesses 4 --dist loadfile --durations=15
working-directory: apps/trading/e2e
#----------------------------------------------
# upload traces
@@ -227,46 +227,3 @@ jobs:
name: worker-logs
path: ./logs/
retention-days: 15
#----------------------------------------------
# ----- upload market-sim logs -----
#----------------------------------------------
- name: Prepare and Zip market-sim-logs
if: always()
run: |
parent_dir="/tmp/market-sim-logs"
echo "Creating parent directory at $parent_dir"
mkdir -p "$parent_dir"
echo "Waiting for vega-sim-* folders to be created..."
sleep 10 # Waits 10 seconds to ensure all folders are created
echo "Before searching for vega-sim-* folders in /tmp..."
folders=$(find /tmp -mindepth 1 -type d -name 'vega-sim-*' -print) || echo "Find command failed with exit code $?"
echo "After searching for vega-sim-* folders in /tmp..."
if [ -z "$folders" ]; then
echo "No vega-sim-* folders found."
exit 0
fi
echo "Moving vega-sim-* folders to $parent_dir"
echo "$folders" | xargs -I {} mv {} "$parent_dir/"
echo "Checking if $parent_dir is not empty..."
if [ "$(ls -A $parent_dir)" ]; then
echo "Zipping the parent directory..."
zip -r market-sim-logs.zip "$parent_dir" && echo "Zip file created successfully."
else
echo "$parent_dir is empty. No zip file created."
exit 0
fi
shell: /usr/bin/bash -e {0}
- name: Upload market-sim-logs
uses: actions/upload-artifact@v3
if: always()
with:
name: market-sim-logs
path: market-sim-logs.zip
retention-days: 15
@@ -44,7 +44,7 @@ context('Proposal page', { tags: '@smoke' }, function () {
cy.getByTestId('icon-cross').click();
});
it('Proposal page displayed on mobile', function () {
it.skip('Proposal page displayed on mobile', function () {
const proposalTitle = 'Add Lorem Ipsum market';
cy.common_switch_to_mobile_and_click_toggle();
@@ -55,7 +55,7 @@ context('Proposal page', { tags: '@smoke' }, function () {
});
});
it.skip('Able to view new asset proposal', function () {
it('Able to view new asset proposal', function () {
const proposalTitle = 'Test new asset proposal';
const newAssetProposalBody = getNewAssetTxBody();
cy.VegaWalletSubmitProposal(newAssetProposalBody);
@@ -60,7 +60,7 @@ const PartyLink = ({ id, truncate = false, ...props }: PartyLinkProps) => {
}
return (
<span>
<span className="whitespace-nowrap">
{useName && <Icon size={4} name="cube" className="mr-2" />}
<Link
className="underline font-mono"
@@ -60,7 +60,7 @@ const DeterministicOrderDetails = ({
const o = data.orderByID;
return (
<div className={wrapperClasses}>
<div className="mb-0">
<div className="mb-12 lg:mb-0">
<div className="relative block px-3 py-6 md:px-6 lg:-mr-7">
<h2 className="text-3xl font-bold mb-4 display-5">
<abbr title={tifFull[o.timeInForce]} className="bb-dotted mr-2">
@@ -89,9 +89,9 @@ const DeterministicOrderDetails = ({
<span>{t('Reference')}</span>: {o.reference}
</p>
) : null}
<div className="grid grid-cols-2 md:grid-cols-5 gap-x-6 mt-4">
<div className="mb-6 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-0 md:mb-4">
<div className="grid md:grid-cols-5 gap-x-6 mt-4">
<div className="mb-12 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-4">
{t('Status')}
</h2>
<h5 className="text-lg font-medium text-gray-500 mb-0 capitalize">
@@ -99,17 +99,15 @@ const DeterministicOrderDetails = ({
</h5>
</div>
<div className="mb-6 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-0 md:mb-4">
{t('Size')}
</h2>
<div className="mb-12 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-4">{t('Size')}</h2>
<h5 className="text-lg font-medium text-gray-500 mb-0">
<SizeInMarket size={o.size} marketId={o.market.id} />
</h5>
</div>
<div className="mb-6 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-0 md:mb-4">
<div className="">
<h2 className="text-2xl font-bold text-dark mb-4">
{t('Version')}
</h2>
<h5 className="text-lg font-medium text-gray-500 mb-0">
@@ -117,8 +115,8 @@ const DeterministicOrderDetails = ({
</h5>
</div>
{o.type ? (
<div className="mb-6 md:mb-0">
<h2 className="text-2xl font-bold text-dark mb-0 md:mb-4">
<div className="">
<h2 className="text-2xl font-bold text-dark mb-4">
{t('Type')}
</h2>
<h5 className="text-lg font-medium text-gray-500 mb-0">
@@ -30,12 +30,12 @@ export const Signature = ({ signature }: SignatureProps) => {
return (
<div className="inline-flex border rounded signature-component relative pr-[20px]">
<div
<span
className="bg-gray-100 px-2.5 py-0.5 text-xs text-gray-500 select-none cursor-default"
title={`${signature.algo}`}
title={`Version ${signature.version}`}
>
<span>v{signature.version}</span>
</div>
{signature.algo}
</span>
<div
className={
isOpen
+1 -1
View File
@@ -73,7 +73,7 @@ export const Layout = () => {
<ProtocolUpgradeInProgressNotification />
</div>
<div className={fixedWidthClasses}>
<main className="md:p-4">
<main className="p-4">
{!isHome && <BreadcrumbsContainer className="mb-4" />}
<Outlet />
</main>
@@ -55,10 +55,7 @@ context('View functionality with public key', { tags: '@smoke' }, function () {
cy.getByTestId('dialog-content')
.first()
.within(() => {
cy.getByTestId('dialog-title').should(
'have.text',
'Transaction failed'
);
cy.get('h1').should('have.text', 'Transaction failed');
cy.getByTestId('Error').should('have.text', expectedErrorTxt);
});
});
@@ -112,7 +112,6 @@ export function createNewMarketProposalTxBody(): ProposalSubmissionBody {
performanceHysteresisEpochs: 2,
slaCompetitionFactor: '0.1',
},
// FIXME: workaround because of https://github.com/vegaprotocol/vega/issues/10343
quadraticSlippageFactor: '0',
instrument: {
name: 'Token test market',
@@ -197,7 +196,6 @@ export function createNewMarketProposalTxBody(): ProposalSubmissionBody {
timeWindow: '3600',
scalingFactor: 10,
},
// FIXME: workaround because of https://github.com/vegaprotocol/vega/issues/10343
triggeringRatio: '0.7',
auctionExtension: '1',
},
@@ -242,7 +240,6 @@ export function createSuccessorMarketProposalTxBody(
decimalPlaces: '5',
positionDecimalPlaces: '5',
linearSlippageFactor: '0.001',
// FIXME: workaround because of https://github.com/vegaprotocol/vega/issues/10343
quadraticSlippageFactor: '0',
liquiditySlaParameters: {
priceRange: '0.5',
@@ -337,7 +334,6 @@ export function createSuccessorMarketProposalTxBody(
timeWindow: '3600',
scalingFactor: 10,
},
// FIXME: workaround because of https://github.com/vegaprotocol/vega/issues/10343
triggeringRatio: '0.7',
auctionExtension: '1',
},
@@ -205,6 +205,7 @@ query Proposal(
}
}
liquidityMonitoringParameters {
triggeringRatio
targetStakeParameters {
timeWindow
scalingFactor
@@ -212,6 +213,7 @@ query Proposal(
}
positionDecimalPlaces
linearSlippageFactor
quadraticSlippageFactor
}
... on UpdateMarket {
marketId
@@ -364,6 +366,7 @@ query Proposal(
}
}
liquidityMonitoringParameters {
triggeringRatio
targetStakeParameters {
timeWindow
scalingFactor
File diff suppressed because one or more lines are too long
+2 -7
View File
@@ -22,12 +22,7 @@ NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_SUCCESSOR_MARKETS=true
NX_STOP_ORDERS=true
NX_ICEBERG_ORDERS=true
# NX_PRODUCT_PERPETUALS
NX_METAMASK_SNAPS=true
NX_REFERRALS=true
# NX_DISABLE_CLOSE_POSITION=false
NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
NX_CHARTING_LIBRARY_PATH=https://assets.vega.community/trading-view-bundle/v0.0.1/
NX_CHARTING_LIBRARY_HASH=PDjWaqPFndDp+LCvqbKvntWriaqNzNpZ5i9R/BULzCg=
NX_TEAM_COMPETITION=true
-3
View File
@@ -28,6 +28,3 @@ NX_REFERRALS=true
NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
NX_CHARTING_LIBRARY_PATH=https://assets.vega.community/trading-view-bundle/v0.0.1/
NX_CHARTING_LIBRARY_HASH=PDjWaqPFndDp+LCvqbKvntWriaqNzNpZ5i9R/BULzCg=
-2
View File
@@ -54,5 +54,3 @@ To run the UI automation tests with a mocked API, run:
```bash
yarn nx run trading-e2e:e2e
```
To run tests with market sim please read [the readme](e2e/README.md).
@@ -314,7 +314,7 @@ describe('Closed', () => {
});
it('display market actions', async () => {
// Use market with a successor Id as the actions dropdown will optionally
// Use market with a succcessor Id as the actions dropdown will optionally
// show a link to the successor market
const marketsWithSuccessorAndParent = [
{
@@ -137,8 +137,6 @@ const ClosedMarketsDataGrid = ({
headerName: t('Market'),
field: 'code',
cellRenderer: 'MarketCodeCell',
width: 150,
resizable: true,
},
{
headerName: t('Status'),
@@ -282,7 +280,6 @@ const ClosedMarketsDataGrid = ({
return (
<AgGrid
rowData={rowData}
defaultColDef={COL_DEFS.default}
columnDefs={colDefs}
getRowId={({ data }) => data.id}
overlayNoRowsTemplate={error ? error.message : t('No markets')}
@@ -17,7 +17,6 @@ const defaultColDef = {
filter: true,
resizable: true,
filterParams: { buttons: ['reset'] },
minWidth: 120,
};
const components = {
@@ -53,7 +53,6 @@ export const MarketsPage = () => {
size="extra-small"
data-testid="propose-new-market"
href={externalLink}
target="_blank"
>
{t('Propose a new market')}
</TradingAnchorButton>
@@ -29,7 +29,6 @@ export const useColumnDefs = () => {
{
headerName: t('Market'),
field: 'tradableInstrument.instrument.code',
pinned: true,
cellRenderer: ({
value,
data,
@@ -4,7 +4,6 @@ import { useT } from '../../lib/use-t';
import { RewardsContainer } from '../../components/rewards-container';
import { usePageTitleStore } from '../../stores';
import { ErrorBoundary } from '../../components/error-boundary';
import { TinyScroll } from '@vegaprotocol/ui-toolkit';
export const Rewards = () => {
const t = useT();
@@ -17,10 +16,10 @@ export const Rewards = () => {
}, [updateTitle, title]);
return (
<ErrorBoundary feature="rewards">
<TinyScroll className="p-4 max-h-full overflow-auto">
<div className="container mx-auto p-4">
<h1 className="px-4 pb-4 text-2xl">{title}</h1>
<RewardsContainer />
</TinyScroll>
</div>
</ErrorBoundary>
);
};
@@ -38,11 +38,7 @@ export const FeesContainer = () => {
const { data: markets, loading: marketsLoading } = useMarketList();
const { data: programData, loading: programLoading } =
useDiscountProgramsQuery({
errorPolicy: 'ignore',
fetchPolicy: 'cache-and-network',
pollInterval: 15000,
});
useDiscountProgramsQuery({ errorPolicy: 'ignore' });
const volumeDiscountWindowLength =
programData?.currentVolumeDiscountProgram?.windowLength || 1;
@@ -53,8 +49,6 @@ export const FeesContainer = () => {
partyId: pubKey || '',
},
skip: !pubKey,
fetchPolicy: 'cache-and-network',
pollInterval: 15000,
});
const previousEpoch = (Number(feesData?.epoch.id) || 0) - 1;
@@ -1,5 +1,4 @@
import type { DiscountProgramsQuery, FeesQuery } from './__generated__/Fees';
export const useReferralStats = (
previousEpoch?: number,
referralStats?: NonNullable<
@@ -42,9 +42,13 @@ export const LiquidityHeader = () => {
const assetDecimalPlaces = asset?.decimals || 0;
const symbol = asset?.symbol;
const triggeringRatio =
market?.liquidityMonitoringParameters.triggeringRatio || '1';
const { percentage, status } = useCheckLiquidityStatus({
suppliedStake: suppliedStake || 0,
targetStake: targetStake || 0,
triggeringRatio,
});
const feesObject = feesPaidRes?.paidLiquidityFees?.edges?.find(
@@ -47,6 +47,9 @@ export const MarketLiquiditySupplied = ({
]);
const stakeToCcyVolume = params.market_liquidity_stakeToCcyVolume;
const triggeringRatio = Number(
params.market_liquidity_targetstake_triggering_ratio
);
const variables = useMemo(
() => ({
@@ -91,6 +94,7 @@ export const MarketLiquiditySupplied = ({
const { percentage, status } = useCheckLiquidityStatus({
suppliedStake: market?.suppliedStake || 0,
targetStake: market?.targetStake || 0,
triggeringRatio,
});
const showMessage =
@@ -97,9 +97,9 @@ const MarketData = ({
return (
<>
<div className="w-2/6" role="gridcell">
<div className="w-2/5" role="gridcell">
<h3 className="flex items-baseline">
<span className="overflow-hidden text-xs md:text-sm lg:text-base text-ellipsis whitespace-nowrap">
<span className="overflow-hidden text-sm lg:text-base text-ellipsis whitespace-nowrap">
{market.tradableInstrument.instrument.code}
</span>
{allProducts && productType && (
@@ -113,7 +113,7 @@ const MarketData = ({
)}
</div>
<div
className="w-2/6 overflow-hidden text-xs lg:text-sm whitespace-nowrap text-ellipsis text-right"
className="w-1/5 overflow-hidden text-xs lg:text-sm whitespace-nowrap text-ellipsis"
title={symbol}
data-testid="market-selector-price"
role="gridcell"
@@ -121,14 +121,14 @@ const MarketData = ({
{price} {symbol}
</div>
<div
className="w-2/6 sm:w-1/6 overflow-hidden text-xs lg:text-sm whitespace-nowrap text-ellipsis text-right"
className="w-1/5 overflow-hidden text-xs text-right lg:text-sm whitespace-nowrap text-ellipsis"
title={t('24h vol')}
data-testid="market-selector-volume"
role="gridcell"
>
{volume}
</div>
<div className="hidden sm:w-1/6 sm:flex justify-end" role="gridcell">
<div className="flex justify-end w-1/5" role="gridcell">
{oneDayCandles && (
<Sparkline
width={64}
@@ -64,7 +64,7 @@ export const MarketSelector = ({
setFilter((curr) => ({ ...curr, product }));
}}
/>
<div className="text-sm flex sm:grid grid-cols-[2fr_1fr_1fr] gap-1 ">
<div className="text-sm grid grid-cols-[2fr_1fr_1fr] gap-1 ">
<div className="flex-1">
<TradingInput
onChange={(e) =>
@@ -182,16 +182,16 @@ const MarketList = ({
'p-2 mx-2 border-b border-default text-xs text-secondary'
)}
>
<div className="w-2/6" role="columnheader">
<div className="w-2/5" role="columnheader">
{t('Name')}
</div>
<div className="w-2/6 text-right pr-4" role="columnheader">
<div className="w-1/5" role="columnheader">
{t('Price')}
</div>
<div className="w-2/6 sm:w-1/6 text-right" role="columnheader">
<div className="w-1/5 text-right" role="columnheader">
{t('24h volume')}
</div>
<div className="hidden sm:w-1/6" role="columnheader" />
<div className="w-1/5" role="columnheader" />
</div>
<div ref={listRef}>
<List
+1 -11
View File
@@ -5,7 +5,6 @@ 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
@@ -31,16 +30,7 @@ export const NavHeader = () => {
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>
<VegaIcon name={VegaIconNames.CHEVRON_DOWN} size={20} />
</h1>
}
>
@@ -14,7 +14,6 @@ import {
VegaIconNames,
type VegaIconSize,
TradingInput,
TinyScroll,
} from '@vegaprotocol/ui-toolkit';
import { IconNames } from '@blueprintjs/icons';
import {
@@ -150,45 +149,47 @@ export const ActiveRewards = ({ currentEpoch }: { currentEpoch: number }) => {
return (
<Card title={t('Active rewards')} className="lg:col-span-full">
{transfers.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"
prependElement={<VegaIcon name={VegaIconNames.SEARCH} />}
/>
)}
<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">
{transfers
.filter((n) => applyFilter(n, filter))
.map((node, i) => {
const { transfer } = node;
if (
transfer.kind.__typename !== 'RecurringTransfer' ||
!transfer.kind.dispatchStrategy?.dispatchMetric
) {
return null;
<div className="">
{transfers.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"
prependElement={<VegaIcon name={VegaIconNames.SEARCH} />}
/>
)}
<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(343px,_1fr))] max-h-[40rem] overflow-auto">
{transfers
.filter((n) => applyFilter(n, filter))
.map((node, i) => {
const { transfer } = node;
if (
transfer.kind.__typename !== 'RecurringTransfer' ||
!transfer.kind.dispatchStrategy?.dispatchMetric
) {
return null;
}
return (
node && (
<ActiveRewardCard
key={i}
transferNode={node}
kind={transfer.kind}
currentEpoch={currentEpoch}
/>
)
);
})}
</TinyScroll>
return (
node && (
<ActiveRewardCard
key={i}
transferNode={node}
kind={transfer.kind}
currentEpoch={currentEpoch}
/>
)
);
})}
</div>
</div>
</Card>
);
};
+1 -1
View File
@@ -1,3 +1,3 @@
CONSOLE_IMAGE_NAME=vegaprotocol/trading:latest
VEGA_VERSION=v0.74.0-preview.2
VEGA_VERSION=v0.73.9
LOCAL_SERVER=false
+1 -2
View File
@@ -1,3 +1,2 @@
CONSOLE_IMAGE_NAME=vegaprotocol/trading:develop
VEGA_VERSION=v0.74.0-preview.2
LOCAL_SERVER=false
VEGA_VERSION=v0.73.9
+1 -1
View File
@@ -1,3 +1,3 @@
CONSOLE_IMAGE_NAME=vegaprotocol/trading:main
VEGA_VERSION=v0.73.10
VEGA_VERSION=v0.73.8
LOCAL_SERVER=false
+1 -16
View File
@@ -8,7 +8,7 @@ import docker
import http.server
import sys
from dotenv import load_dotenv
from playwright.sync_api import Error as PlaywrightError
from docker.models.containers import Container
from docker.errors import APIError
from contextlib import contextmanager
@@ -274,18 +274,3 @@ def perps_market(vega, request):
if hasattr(request, "param"):
kwargs.update(request.param)
return setup_perps_market(vega, **kwargs)
@pytest.fixture(autouse=True)
def retry_on_http_error(request):
retry_count = 3
for i in range(retry_count):
try:
yield
return
except requests.exceptions.HTTPError:
if i < retry_count - 1:
print(f"Retrying due to HTTPError (attempt {i+1}/{retry_count})")
else:
raise
+18 -56
View File
@@ -18,14 +18,14 @@ def setup_simple_market(
custom_market_name=market_name,
custom_asset_name="tDAI",
custom_asset_symbol="tDAI",
custom_quantum=1,
custom_quantum=1
):
for wallet in wallets:
vega.create_key(wallet.name)
vega.mint(
MM_WALLET.name,
asset=vega.find_asset_id(symbol="VOTE", enabled=True),
asset="VOTE",
amount=mint_amount,
)
@@ -117,30 +117,18 @@ def setup_simple_successor_market(
return market_id
def setup_opening_auction_market(
vega: VegaService,
market_id: str = None,
buy_orders=default_buy_orders,
sell_orders=default_sell_orders,
add_liquidity=True,
custom_market_name="BTC:DAI_2023",
custom_asset_name="tDAI",
custom_asset_symbol="tDAI",
**kwargs,
):
def setup_opening_auction_market(vega: VegaService, market_id: str = None, buy_orders=default_buy_orders, sell_orders=default_sell_orders, add_liquidity=True, **kwargs):
if not market_exists(vega, market_id):
market_id = setup_simple_market(
vega,
custom_market_name=custom_market_name,
custom_asset_name=custom_asset_name,
custom_asset_symbol=custom_asset_symbol,
**kwargs,
)
market_id = setup_simple_market(vega, **kwargs)
if add_liquidity:
submit_liquidity(vega, MM_WALLET.name, market_id)
submit_multiple_orders(vega, MM_WALLET.name, market_id, "SIDE_SELL", sell_orders)
submit_multiple_orders(vega, MM_WALLET2.name, market_id, "SIDE_BUY", buy_orders)
submit_multiple_orders(
vega, MM_WALLET.name, market_id, "SIDE_SELL", sell_orders
)
submit_multiple_orders(
vega, MM_WALLET2.name, market_id, "SIDE_BUY", buy_orders
)
vega.forward("10s")
vega.wait_fn(1)
@@ -158,37 +146,13 @@ def market_exists(vega: VegaService, market_id: str):
# Add sell orders and buy orders to put on the book
def setup_continuous_market(
vega: VegaService,
market_id: str = None,
buy_orders=default_buy_orders,
sell_orders=default_sell_orders,
add_liquidity=True,
custom_market_name="BTC:DAI_2023",
custom_asset_name="tDAI",
custom_asset_symbol="tDAI",
**kwargs,
):
if (
not market_exists(vega, market_id)
or buy_orders != default_buy_orders
or sell_orders != default_sell_orders
):
def setup_continuous_market(vega: VegaService, market_id: str = None, buy_orders=default_buy_orders, sell_orders=default_sell_orders, add_liquidity=True, **kwargs):
if not market_exists(vega, market_id) or buy_orders != default_buy_orders or sell_orders != default_sell_orders:
market_id = setup_opening_auction_market(
vega,
market_id,
buy_orders,
sell_orders,
add_liquidity,
custom_market_name=custom_market_name,
custom_asset_name=custom_asset_name,
custom_asset_symbol=custom_asset_symbol,
**kwargs,
)
vega, market_id, buy_orders, sell_orders, add_liquidity, **kwargs)
submit_order(
vega, "Key 1", market_id, "SIDE_BUY", sell_orders[0][0], sell_orders[0][1]
)
submit_order(vega, "Key 1", market_id, "SIDE_BUY",
sell_orders[0][0], sell_orders[0][1])
vega.forward("10s")
vega.wait_fn(1)
@@ -207,7 +171,7 @@ def setup_perps_market(
vega.mint(
MM_WALLET.name,
asset=vega.find_asset_id(symbol="VOTE", enabled=True),
asset="VOTE",
amount=mint_amount,
)
@@ -286,8 +250,6 @@ def setup_perps_market(
def market_exists(vega: VegaService, market_id: str):
if market_id is None:
return False
all_markets = vega.all_markets()
all_markets = vega.all_markets()
market_ids = [market.id for market in all_markets]
print("Checking for market ID:", market_id)
print("Available market IDs:", market_ids)
return market_id in market_ids
return market_id in market_ids
+4 -4
View File
@@ -1,4 +1,4 @@
# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
[[package]]
name = "certifi"
@@ -1160,8 +1160,8 @@ profile = ["pytest-profiling", "snakeviz"]
[package.source]
type = "git"
url = "https://github.com/vegaprotocol/vega-market-sim.git/"
reference = "HEAD"
resolved_reference = "2aed8c94b25d8fa2e376d3b63ca1f9193d28cdfd"
reference = "fix/genesis_panic"
resolved_reference = "de30d2d4c7a1b81a830527ca76473e23ef59de12"
[[package]]
name = "websocket-client"
@@ -1342,4 +1342,4 @@ files = [
[metadata]
lock-version = "2.0"
python-versions = ">=3.9,<3.11"
content-hash = "39ce8400de7bf060857447281ef27bd78c9b1d9639da063b051e3ae6e7887a67"
content-hash = "68ed0de55290a3b929d47eb7f7b031fb7e172261c7bbeb4f554b7c27a4462754"
+1 -1
View File
@@ -9,7 +9,7 @@ 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/"}
vega-sim = {git = "https://github.com/vegaprotocol/vega-market-sim.git/", branch = "fix/genesis_panic"}
pytest-playwright = "^0.4.2"
docker = "^6.1.3"
pytest-xdist = "^3.3.1"
@@ -14,18 +14,15 @@ market_order = "order-type-Market"
tif = "order-tif"
expire = "expire"
@pytest.fixture(scope="module")
def vega(request):
with init_vega(request) as vega:
yield vega
@pytest.fixture(scope="module")
def continuous_market(vega):
return setup_continuous_market(vega)
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_limit_buy_order_GTT(continuous_market, vega: VegaServiceNull, page: Page):
page.goto(f"/#/markets/{continuous_market}")
@@ -45,26 +42,31 @@ def test_limit_buy_order_GTT(continuous_market, vega: VegaServiceNull, page: Pag
)
page.get_by_test_id(place_order).click()
wait_for_toast_confirmation(page)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
page.get_by_test_id("All").click()
# 7002-SORD-017
expect(page.get_by_role("row").nth(5)).to_contain_text("10+10LimitFilled120.00GTT:")
expect(page.get_by_role("row").nth(2)).to_contain_text(
"BTC:DAI_2023Futr10+10LimitFilled120.00GTT:"
)
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_limit_buy_order(continuous_market, vega: VegaServiceNull, page: Page):
page.goto(f"/#/markets/{continuous_market}")
page.get_by_test_id(order_size).fill("10")
page.get_by_test_id(order_price).fill("120")
page.get_by_test_id(place_order).click()
wait_for_toast_confirmation(page)
vega.wait_fn(2)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
page.get_by_test_id("All").click()
# 7002-SORD-017
expect(page.get_by_role("row").nth(6)).to_contain_text("10+10LimitFilled120.00GTC")
expect(page.get_by_role("row").nth(2)).to_contain_text(
"BTC:DAI_2023Futr10+10LimitFilled120.00GTC"
)
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_limit_sell_order(continuous_market, vega: VegaServiceNull, page: Page):
@@ -82,11 +84,13 @@ def test_limit_sell_order(continuous_market, vega: VegaServiceNull, page: Page):
)
page.get_by_test_id(place_order).click()
wait_for_toast_confirmation(page)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
page.get_by_test_id("All").click()
expect(page.get_by_role("row").nth(7)).to_contain_text("10-10LimitFilled100.00GFN")
expect(page.get_by_role("row").nth(2)).to_contain_text(
"BTC:DAI_2023Futr10-10LimitFilled100.00GFN"
)
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_market_sell_order(continuous_market, vega: VegaServiceNull, page: Page):
@@ -103,12 +107,14 @@ def test_market_sell_order(continuous_market, vega: VegaServiceNull, page: Page)
)
page.get_by_test_id(place_order).click()
wait_for_toast_confirmation(page)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
page.get_by_test_id("All").click()
expect(page.get_by_role("row").nth(8)).to_contain_text("10-10MarketFilled-IOC")
expect(page.get_by_role("row").nth(2)).to_contain_text(
"BTC:DAI_2023Futr10-10MarketFilled-IOC"
)
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_market_buy_order(continuous_market, vega: VegaServiceNull, page: Page):
@@ -118,32 +124,13 @@ def test_market_buy_order(continuous_market, vega: VegaServiceNull, page: Page):
page.get_by_test_id(tif).select_option("Fill or Kill (FOK)")
page.get_by_test_id(place_order).click()
wait_for_toast_confirmation(page)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
page.get_by_test_id("All").click()
# 7002-SORD-010
# 0003-WTXN-012
# 0003-WTXN-003
expect(page.get_by_role("row").nth(9)).to_contain_text("10+10MarketFilled-FOK")
@pytest.mark.usefixtures("risk_accepted")
def test_sidebar_should_be_open_after_reload(continuous_market, page: Page):
page.goto(f"/#/markets/{continuous_market}")
expect(page.get_by_test_id("deal-ticket-form")).to_be_visible()
page.get_by_test_id("Order").click()
expect(page.get_by_test_id("deal-ticket-form")).not_to_be_visible()
page.reload()
expect(page.get_by_test_id("deal-ticket-form")).to_be_visible()
@pytest.mark.skip("We currently can't approve wallet connection through Sim")
@pytest.mark.usefixtures("risk_accepted")
def test_connect_vega_wallet(continuous_market, page: Page):
page.goto(f"/#/markets/{continuous_market}")
page.get_by_test_id("order-price").fill("101")
page.get_by_test_id("order-connect-wallet").click()
expect(page.locator('[role="dialog"]')).to_be_visible()
page.get_by_test_id("connector-jsonRpc").click()
expect(page.get_by_test_id("wallet-dialog-title")).to_be_visible()
# TODO: accept wallet connection and assert wallet is connected.
expect(page.get_by_test_id("order-type-Limit")).to_be_checked()
expect(page.get_by_test_id("order-price")).to_have_value("101")
expect(page.get_by_role("row").nth(2)).to_contain_text(
"BTC:DAI_2023Futr10+10MarketFilled-FOK"
)
@@ -0,0 +1,35 @@
import pytest
from playwright.sync_api import Page, expect
from conftest import init_vega
from fixtures.market import setup_continuous_market
@pytest.fixture(scope="module")
def vega(request):
with init_vega(request) as vega:
yield vega
@pytest.fixture(scope="module")
def continuous_market(vega):
return setup_continuous_market(vega)
@pytest.mark.skip("We currently can't approve wallet connection through Sim")
@pytest.mark.usefixtures("risk_accepted")
def test_connect_vega_wallet(continuous_market, page: Page):
page.goto(f"/#/markets/{continuous_market}")
page.get_by_test_id("order-price").fill("101")
page.get_by_test_id("order-connect-wallet").click()
expect(page.locator('[role="dialog"]')).to_be_visible()
page.get_by_test_id("connector-jsonRpc").click()
expect(page.get_by_test_id("wallet-dialog-title")).to_be_visible()
# TODO: accept wallet connection and assert wallet is connected.
expect(page.get_by_test_id("order-type-Limit")).to_be_checked()
expect(page.get_by_test_id("order-price")).to_have_value("101")
@pytest.mark.usefixtures("risk_accepted")
def test_sidebar_should_be_open_after_reload(continuous_market, page: Page):
page.goto(f"/#/markets/{continuous_market}")
expect(page.get_by_test_id("deal-ticket-form")).to_be_visible()
page.get_by_test_id("Order").click()
expect(page.get_by_test_id("deal-ticket-form")).not_to_be_visible()
page.reload()
expect(page.get_by_test_id("deal-ticket-form")).to_be_visible()
@@ -27,7 +27,7 @@ submit_stop_order = "place-order"
stop_orders_tab = "Stop orders"
row_table = "row"
cancel = "cancel"
market_name_col = '[data-testid="market-code"]'
market_name_col = '[col-id="market.tradableInstrument.instrument.code"]'
trigger_col = '[col-id="trigger"]'
expiresAt_col = '[col-id="expiresAt"]'
size_col = '[col-id="submission.size"]'
@@ -41,6 +41,7 @@ close_toast = "toast-close"
def create_position(vega: VegaServiceNull, market_id):
submit_order(vega, "Key 1", market_id, "SIDE_SELL", 100, 110)
submit_order(vega, "Key 1", market_id, "SIDE_BUY", 100, 110)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup
@@ -77,6 +78,7 @@ def test_submit_stop_order_rejected(continuous_market, vega: VegaServiceNull, pa
page.get_by_test_id(trigger_price).fill("103")
page.get_by_test_id(order_size).fill("3")
page.get_by_test_id(submit_stop_order).click()
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
page.get_by_test_id(close_toast).click()
@@ -267,6 +269,82 @@ class TestStopOcoValidation:
def continuous_market(self, vega):
return setup_continuous_market(vega)
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_stop_market_order_form_validation(self, continuous_market, page: Page):
# 7002-SORD-052
# 7002-SORD-055
# 7002-SORD-056
# 7002-SORD-057
# 7002-SORD-058
# 7002-SORD-064
# 7002-SORD-065
page.goto(f"/#/markets/{continuous_market}")
page.get_by_test_id(stop_order_btn).click()
page.get_by_test_id(stop_market_order_btn).is_visible()
page.get_by_test_id(stop_market_order_btn).click()
expect(
page.get_by_test_id("sidebar-content").get_by_text("Trigger").first
).to_be_visible()
expect(page.locator('[for="triggerDirection-risesAbove"]')).to_have_text(
"Rises above"
)
expect(page.locator('[for="triggerDirection-fallsBelow"]')).to_have_text(
"Falls below"
)
page.get_by_test_id(trigger_price).click()
expect(page.get_by_test_id(trigger_price)).to_be_empty
expect(page.locator('[for="triggerType-price"]')).to_have_text("Price")
expect(page.locator('[for="triggerType-trailingPercentOffset"]')).to_have_text(
"Trailing Percent Offset"
)
expect(page.locator('[for="order-size"]')).to_have_text("Size")
page.get_by_test_id(order_size).click()
expect(page.get_by_test_id(order_size)).to_be_empty
expect(page.get_by_test_id(order_price)).not_to_be_visible()
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_stop_limit_order_form_validation(self, continuous_market, page: Page):
# 7002-SORD-020
# 7002-SORD-021
# 7002-SORD-022
# 7002-SORD-033
# 7002-SORD-034
# 7002-SORD-035
# 7002-SORD-036
# 7002-SORD-037
# 7002-SORD-038
# 7002-SORD-049
# 7002-SORD-050
# 7002-SORD-051
page.goto(f"/#/markets/{continuous_market}")
page.get_by_test_id(stop_order_btn).click()
page.get_by_test_id(stop_limit_order_btn).is_visible()
page.get_by_test_id(stop_limit_order_btn).click()
expect(
page.get_by_test_id("sidebar-content").get_by_text("Trigger").first
).to_be_visible()
expect(page.locator('[for="triggerDirection-risesAbove"]')).to_have_text(
"Rises above"
)
expect(page.locator('[for="triggerDirection-risesAbove"]')).to_be_checked
expect(page.locator('[for="triggerDirection-fallsBelow"]')).to_have_text(
"Falls below"
)
page.get_by_test_id(trigger_price).click()
expect(page.get_by_test_id(trigger_price)).to_be_empty
expect(page.locator('[for="triggerType-price"]')).to_have_text("Price")
expect(page.locator('[for="triggerType-price"]')).to_be_checked
expect(page.locator('[for="triggerType-trailingPercentOffset"]')).to_have_text(
"Trailing Percent Offset"
)
expect(page.locator('[for="order-size"]').first).to_have_text("Size")
expect(page.locator('[for="order-price"]').last).to_have_text("Price")
page.get_by_test_id(order_size).click()
expect(page.get_by_test_id(order_size)).to_be_empty
page.get_by_test_id(order_price).click()
expect(page.get_by_test_id(order_price)).to_be_empty()
@pytest.mark.skip("core issue")
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_maximum_number_of_active_stop_orders(
+3 -1
View File
@@ -53,7 +53,7 @@ FEE_BREAKDOWN_TOOLTIP = "fee-breakdown-tooltip"
PINNED_ROW_LOCATOR = ".ag-pinned-left-cols-container .ag-row"
ROW_LOCATOR = ".ag-center-cols-container .ag-row"
# Col-Ids:
COL_INSTRUMENT_CODE = '[data-testid="market-code"]'
COL_INSTRUMENT_CODE = '[col-id="market.tradableInstrument.instrument.code"]'
COL_CODE = '[col-id="code"]'
COL_SIZE = '[col-id="size"]'
COL_PRICE = '[col-id="price"]'
@@ -563,6 +563,7 @@ def test_fills_taker_discount_program(
page.goto(f"/#/markets/{market_id}")
page.get_by_test_id(FILLS).click()
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
expect(row.locator(COL_INSTRUMENT_CODE)).to_have_text("BTC:DAI_2023Futr")
expect(row.locator(COL_SIZE)).to_have_text(size)
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
expect(row.locator(COL_PRICE_1)).to_have_text(price_1)
@@ -604,6 +605,7 @@ def test_fills_maker_discount_program(
change_keys(page, vega_instance, MM_WALLET.name)
page.get_by_test_id(FILLS).click()
row = page.get_by_test_id(TAB_FILLS).locator(ROW_LOCATOR).first
expect(row.locator(COL_INSTRUMENT_CODE)).to_have_text("BTC:DAI_2023Futr")
expect(row.locator(COL_SIZE)).to_have_text(size)
expect(row.locator(COL_PRICE)).to_have_text("103.50 tDAI")
expect(row.locator(COL_PRICE_1)).to_have_text(price_1)
@@ -77,7 +77,7 @@ class TestGetStarted:
vega.mint(
MM_WALLET.name,
asset=vega.find_asset_id(symbol="VOTE", enabled=True),
asset="VOTE",
amount=mint_amount,
)
@@ -105,8 +105,6 @@ class TestGetStarted:
vega.wait_fn(1)
vega.wait_for_total_catchup()
page.reload()
# Assert step 2 complete
expect(page.get_by_test_id("icon-tick")).to_have_count(2)
@@ -35,6 +35,7 @@ class TestIcebergOrdersValidations:
"Awaiting confirmationPlease wait for your transaction to be confirmedView in block explorer"
)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
expect(page.get_by_test_id("toast-content")).to_have_text(
@@ -50,6 +51,7 @@ def test_iceberg_open_order(continuous_market, vega: VegaServiceNull, page: Page
page.goto(f"/#/markets/{continuous_market}")
submit_order(vega, "Key 1", continuous_market, "SIDE_SELL", 102, 101, 2, 1)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
@@ -68,6 +70,7 @@ def test_iceberg_open_order(continuous_market, vega: VegaServiceNull, page: Page
expect(
page.locator(".ag-center-cols-container .ag-row [col-id='size']").first
).to_have_text("-102")
page.pause()
expect(
page.locator(".ag-center-cols-container .ag-row [col-id='type'] ").first
).to_have_text("Limit (Iceberg)")
@@ -82,6 +85,7 @@ def test_iceberg_open_order(continuous_market, vega: VegaServiceNull, page: Page
submit_order(vega, MM_WALLET2.name, continuous_market, "SIDE_BUY", 103, 101)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
expect(
@@ -16,6 +16,7 @@ def vega(request):
def continuous_market(vega):
return setup_continuous_market(vega)
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_liquidity_provision_amendment(continuous_market, vega: VegaServiceNull, page: Page):
# TODO Refactor asserting the grid
@@ -5,7 +5,6 @@ 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
from actions.utils import next_epoch
@pytest.fixture(scope="class")
@@ -22,7 +21,9 @@ def create_settled_market(vega: VegaServiceNull):
settlement_price=110,
market_id=market_id,
)
next_epoch(vega=vega)
vega.forward("10s")
vega.wait_fn(10)
vega.wait_for_total_catchup()
class TestSettledMarket:
@@ -122,7 +123,9 @@ def test_terminated_market_no_settlement_date(page: Page, vega: VegaServiceNull)
payload={"trading.terminated": "true"},
key_name="FJMKnwfZdd48C8NqvYrG",
)
next_epoch(vega=vega)
vega.forward("60s")
vega.wait_fn(10)
vega.wait_for_total_catchup()
page.goto(f"/#/markets/all")
page.get_by_test_id("Closed markets").click()
row_selector = page.locator(
@@ -15,13 +15,72 @@ def test_market_selector(continuous_market, page: Page):
# 6001-MARK-025
btc_market = page.locator('[data-testid="market-selector-list"] a')
expect(btc_market.locator("h3")).to_have_text("BTC:DAI_2023Futr")
# tbd - 5465
# expect(btc_market.locator('[data-testid="market-selector-volume"]')).to_have_text(
# "1"
# )
expect(btc_market.locator('[data-testid="market-selector-volume"]')).to_have_text(
"0.00"
)
expect(btc_market.locator('[data-testid="market-selector-price"]')).to_have_text(
"107.50 tDAI"
)
expect(btc_market.locator("span.rounded-md.leading-none")).to_be_visible()
expect(btc_market.locator("span.rounded-md.leading-none")).to_have_text("Futr")
expect(btc_market.locator('[data-testid="sparkline-svg"]')).not_to_be_visible
@pytest.mark.usefixtures("simple_market", "auth", "risk_accepted")
@pytest.mark.parametrize(
"simple_market",
[
{
"custom_market_name": "APPL.MF21",
"custom_asset_name": "tUSDC",
"custom_asset_symbol": "tUSDC",
}
],
indirect=True,
)
def test_market_selector_filter(continuous_market, page: Page):
page.goto(f"/#/markets/{continuous_market}")
page.get_by_test_id("header-title").click()
# 6001-MARK-027
page.get_by_test_id("product-Spot").click()
expect(page.get_by_test_id("market-selector-list")).to_contain_text(
"Spot markets coming soon."
)
page.get_by_test_id("product-Perpetual").click()
expect(page.get_by_test_id("market-selector-list")).to_contain_text(
"No perpetual markets."
)
page.get_by_test_id("product-Future").click()
expect(page.locator('[data-testid="market-selector-list"] a')).to_have_count(2)
# 6001-MARK-029
page.get_by_test_id("search-term").fill("btc")
expect(page.locator('[data-testid="market-selector-list"] a')).to_have_count(1)
expect(page.locator('[data-testid="market-selector-list"] a').nth(0)).to_have_text(
"BTC:DAI_2023107.50 tDAI0.00"
)
page.get_by_test_id("search-term").clear()
expect(page.locator('[data-testid="market-selector-list"] a')).to_have_count(2)
# 6001-MARK-030
# 6001-MARK-031
# 6001-MARK-032
# 6001-MARK-033
page.get_by_test_id("sort-trigger").click()
expect(page.get_by_test_id("sort-item-Gained")).to_have_text("Top gaining")
expect(page.get_by_test_id("sort-item-Gained")).to_be_visible()
expect(page.get_by_test_id("sort-item-Lost")).to_have_text("Top losing")
expect(page.get_by_test_id("sort-item-Lost")).to_be_visible()
expect(page.get_by_test_id("sort-item-New")).to_have_text("New markets")
expect(page.get_by_test_id("sort-item-New")).to_be_visible()
# 6001-MARK-028
page.get_by_test_id("sort-trigger").click(force=True)
page.get_by_test_id("asset-trigger").click()
page.get_by_role("menuitemcheckbox").nth(0).get_by_text("tDAI").click()
expect(page.locator('[data-testid="market-selector-list"] a')).to_have_count(1)
expect(page.locator('[data-testid="market-selector-list"] a').nth(0)).to_have_text(
"BTC:DAI_2023107.50 tDAI0.00"
)
@@ -0,0 +1,35 @@
import pytest
from playwright.sync_api import Page, expect
from conftest import init_page, init_vega, risk_accepted_setup
@pytest.fixture(scope="module")
def vega(request):
with init_vega(request) as vega:
yield vega
@pytest.fixture(scope="module")
def page(vega, browser, request):
with init_page(vega, browser, request) as page:
risk_accepted_setup(page)
page.goto("/#/markets/all")
yield page
def test_no_open_markets(page: Page):
# 6001-MARK-034
page.get_by_test_id("Open markets").click()
expect(page.locator(".ag-overlay-wrapper")).to_have_text("No markets")
def test_no_closed_markets(page: Page):
page.get_by_test_id("Closed markets").click()
expect(page.locator(".ag-overlay-wrapper")).to_have_text("No markets")
def test_no_proposed_markets(page: Page):
# 6001-MARK-061
page.get_by_test_id("Proposed markets").click()
expect(page.locator(".ag-overlay-wrapper")).to_have_text("No proposed markets")
@@ -56,6 +56,9 @@ def test_renders_markets_correctly(proposed_market, page: Page):
page.goto(f"/#/markets/all")
page.click('[data-testid="Proposed markets"]')
row = page.locator(row_selector)
# 6001-MARK-049
expect(row.locator(col_market_id)).to_have_text("BTC:DAI_2023")
# 6001-MARK-051
expect(row.locator('[col-id="asset"]')).to_have_text("tDAI")
@@ -64,16 +64,18 @@ def setup_market_monitoring_auction(vega: VegaServiceNull, simple_market):
submit_order(vega, MM_WALLET.name, simple_market, "SIDE_SELL", 1, 1 + 0.1 / 2)
submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_SELL", 1, 1)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
# add orders that change the price so that it goes beyond the limits of price monitoring
submit_order(vega, MM_WALLET.name, simple_market, "SIDE_SELL", 100, 300)
submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_BUY", 100, 290)
submit_order(vega, MM_WALLET.name, simple_market, "SIDE_SELL", 100, 305)
submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_BUY", 100, 295)
submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_BUY", 1, 305)
submit_order(vega, MM_WALLET.name, simple_market, "SIDE_SELL", 100, 110)
submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_BUY", 100, 90)
submit_order(vega, MM_WALLET.name, simple_market, "SIDE_SELL", 100, 105)
submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_BUY", 100, 95)
submit_order(vega, MM_WALLET2.name, simple_market, "SIDE_BUY", 1, 105)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
@@ -89,6 +91,7 @@ def test_market_monitoring_auction_price_volatility_limit_order(
page.get_by_test_id("order-price").type("110")
page.get_by_test_id("order-tif").select_option("Fill or Kill (FOK)")
page.get_by_test_id("place-order").click()
expect(page.get_by_test_id("deal-ticket-error-message-tif")).to_have_text(
"This market is in auction due to high price volatility. Until the auction ends, you can only place GFA, GTT, or GTC limit orders."
)
@@ -106,11 +109,12 @@ def test_market_monitoring_auction_price_volatility_limit_order(
page.get_by_test_id("place-order").click()
wait_for_toast_confirmation(page)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
page.get_by_test_id("All").click()
expect(page.get_by_role("row").nth(4)).to_contain_text(
"0+1LimitActive110.00GTC"
expect(page.get_by_role("row").nth(2)).to_contain_text(
"BTC:DAI_2023Futr0+1LimitActive110.00GTC"
)
@@ -124,6 +128,7 @@ def test_market_monitoring_auction_price_volatility_market_order(
page.get_by_test_id("order-size").type("1")
# 7002-SORD-060
page.get_by_test_id("place-order").click()
expect(page.get_by_test_id("deal-ticket-error-message-tif")).to_have_text(
"This market is in auction due to high price volatility. Until the auction ends, you can only place GFA, GTT, or GTC limit orders."
)
@@ -73,6 +73,9 @@ def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
)
# "wait" for market to be approved and enacted
vega.forward("60s")
vega.wait_fn(10)
vega.wait_for_total_catchup()
next_epoch(vega=vega)
# check that market is in pending state
expect(trading_mode).to_have_text("Opening auction")
@@ -115,7 +118,8 @@ def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
submit_order(vega, MM_WALLET.name, market_id, "SIDE_SELL", 1, 100)
submit_order(vega, MM_WALLET2.name, market_id, "SIDE_BUY", 1, 100)
vega.wait_fn(2)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
# check market state is now active and trading mode is continuous
@@ -135,7 +139,9 @@ def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
.get_by_test_id(f"update-state-banner-{market_id}")
).to_be_visible()
next_epoch(vega=vega)
vega.forward("60s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
expect(
page.get_by_test_id("market-banner")
@@ -149,7 +155,9 @@ def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
forward_time_to_enactment = False
)
next_epoch(vega=vega)
vega.forward("60s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
expect(page.get_by_test_id("market-banner")).not_to_be_visible()
@@ -162,9 +170,11 @@ def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
payload={"trading.terminated": "true"},
key_name=GOVERNANCE_WALLET.name,
)
next_epoch(vega=vega)
vega.forward("60s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
# market state should be changed to "No trading" because of the invalid oracle
# market state should be changed to "Trading Terminated" because of the invalid oracle
expect(trading_mode).to_have_text("No trading")
expect(market_state).to_have_text("Trading Terminated")
@@ -174,7 +184,9 @@ def test_market_lifecycle(proposed_market, vega: VegaServiceNull, page: Page):
settlement_price=100,
market_id=market_id,
)
next_epoch(vega=vega)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
# check market state is now settled
expect(trading_mode).to_have_text("No trading")
@@ -44,7 +44,7 @@ def verify_order_value(
actual_text = element.text_content()
if actual_text is None:
raise Exception(f"no text found for test_id {test_id}")
raise Exception(f"no text found for test_id {test_id}")
assert re.match(
expected_text, actual_text
@@ -65,6 +65,7 @@ def test_limit_order_trade_open_order(
expect(orderbook_trade).to_be_visible()
expected_open_order = [
"BTC:DAI_2023",
"+1",
"Limit",
"Active",
@@ -86,6 +87,9 @@ def test_limit_order_trade_open_position(continuous_market, page: Page):
secondary_id = "stack-cell-secondary"
position = {
"market_code": "BTC:DAI_2023",
"settlement_asset": "tDAI",
"product_type": "Futr",
"size": "+1",
"notional": "107.50",
"average_entry_price": "107.50",
@@ -103,6 +107,12 @@ def test_limit_order_trade_open_position(continuous_market, page: Page):
# 7004-POSI-001
# 7004-POSI-002
market = table.locator("[col-id='marketCode']")
expect(market.get_by_test_id(primary_id)).to_have_text(position["market_code"])
expect(market.get_by_test_id(secondary_id)).to_have_text(
position["settlement_asset"] + position["product_type"]
)
size_and_notional = table.locator("[col-id='openVolume']")
expect(size_and_notional.get_by_test_id(primary_id)).to_have_text(position["size"])
expect(size_and_notional.get_by_test_id(secondary_id)).to_have_text(
@@ -144,4 +154,5 @@ def test_limit_order_trade_order_trade_away(continuous_market, page: Page):
page.get_by_test_id("Orderbook").click()
price_element = page.get_by_test_id("price-11000000").nth(1)
# 6003-ORDB-010
print(price_element)
expect(price_element).to_be_hidden()
@@ -257,63 +257,46 @@ def test_order_sorted(page: Page):
def test_order_status_active(page: Page):
# 7002-SORD-041
expect(page.locator('[row-index="2"]').first).to_contain_text(
"market-2Futr"
)
expect(page.locator('[row-index="2"]').nth(1)).to_contain_text(
"0" + "-10" + "Limit" + "Active" + "150.00" + "GTC"
expect(page.get_by_test_id(order_tab)).to_contain_text(
"market-2Futr" + "0" + "-10" + "Limit" + "Active" + "150.00" + "GTC"
)
def test_status_expired(page: Page):
# 7002-SORD-042
expect(page.locator('[row-index="7"]').first).to_contain_text(
"market-3Futr"
)
expect(page.locator('[row-index="7"]').nth(1)).to_contain_text(
"0" + "-10" + "Limit" + "Expired" + "120.00" + "GTT:"
expect(page.get_by_test_id(order_tab)).to_contain_text(
"market-3Futr" + "0" + "-10" + "Limit" + "Expired" + "120.00" + "GTT:"
)
def test_order_status_Stopped(page: Page):
# 7002-SORD-044
expect(page.locator('[row-index="12"]').first).to_contain_text(
"market-1Futr"
)
expect(page.locator('[row-index="12"]').nth(1)).to_contain_text(
"0" + "-100" + "Limit" + "Stopped" + "130.00" + "IOC"
expect(page.get_by_test_id(order_tab)).to_contain_text(
"market-1Futr" + "0" + "-100" + "Limit" + "Stopped" + "130.00" + "IOC"
)
def test_order_status_partially_filled(page: Page):
# 7002-SORD-045
expect(page.locator('[row-index="8"]').first).to_contain_text(
"market-2Futr"
)
expect(page.locator('[row-index="8"]').nth(1)).to_contain_text(
"99" + "+100" + "Limit" + "Partially Filled" + "104.00" + "IOC"
expect(page.get_by_test_id(order_tab)).to_contain_text(
"market-2Futr" + "99" + "+100" + "Limit" + "Partially Filled" + "104.00" + "IOC"
)
def test_order_status_filled(page: Page):
# 7002-SORD-046
# 7003-MORD-020
expect(page.locator('[row-index="11"]').first).to_contain_text(
"market-1Futr"
)
expect(page.locator('[row-index="11"]').nth(1)).to_contain_text(
"100" + "-100" + "Limit" + "Filled" + "88.00" + "GTC"
expect(page.get_by_test_id(order_tab)).to_contain_text(
"market-1Futr" + "100" + "-100" + "Limit" + "Filled" + "88.00" + "GTC"
)
def test_order_status_rejected(page: Page):
# 7002-SORD-047
# 7003-MORD-018
expect(page.locator('[row-index="9"]').first).to_contain_text(
expect(page.get_by_test_id(order_tab)).to_contain_text(
"market-1Futr"
)
expect(page.locator('[row-index="9"]').nth(1)).to_contain_text(
"0"
+ "0"
+ "-10,000,000,000"
+ "Limit"
+ "Rejected: Margin check failed"
@@ -325,11 +308,9 @@ def test_order_status_rejected(page: Page):
def test_order_status_parked(page: Page):
# 7002-SORD-048
# 7003-MORD-016
expect(page.locator('[row-index="3"]').first).to_contain_text(
expect(page.get_by_test_id(order_tab)).to_contain_text(
"market-5Futr"
)
expect(page.locator('[row-index="3"]').nth(1)).to_contain_text(
"0"
+ "0"
+ "-60"
+ "Ask + 15.00 Peg limit"
+ "Parked"
@@ -340,11 +321,9 @@ def test_order_status_parked(page: Page):
def test_order_status_pegged_ask(page: Page):
# 7003-MORD-016
expect(page.locator('[row-index="4"]').first).to_contain_text(
expect(page.get_by_test_id(order_tab)).to_contain_text(
"market-4Futr"
)
expect(page.locator('[row-index="4"]').nth(1)).to_contain_text(
"0"
+ "0"
+ "-60"
+ "Ask + 15.00 Peg limit"
+ "Active"
@@ -355,11 +334,9 @@ def test_order_status_pegged_ask(page: Page):
def test_order_status_pegged_bid(page: Page):
# 7003-MORD-016
expect(page.locator('[row-index="5"]').first).to_contain_text(
expect(page.get_by_test_id(order_tab)).to_contain_text(
"market-4Futr"
)
expect(page.locator('[row-index="5"]').nth(1)).to_contain_text(
"0"
+ "0"
+ "+40"
+ "Bid - 10.00 Peg limit"
+ "Active"
@@ -370,11 +347,9 @@ def test_order_status_pegged_bid(page: Page):
def test_order_status_pegged_mid(page: Page):
# 7003-MORD-016
expect(page.locator('[row-index="6"]').first).to_contain_text(
expect(page.get_by_test_id(order_tab)).to_contain_text(
"market-4Futr"
)
expect(page.locator('[row-index="6"]').nth(1)).to_contain_text(
"0"
+ "0"
+ "+20"
+ "Mid - 5.00 Peg limit"
+ "Active"
@@ -397,11 +372,9 @@ def test_order_amend_order(vega: VegaServiceNull, page: Page):
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
expect(page.locator('[row-index="1"]').first).to_contain_text(
"market-2Futr"
)
expect(page.locator('[row-index="1"]').nth(1)).to_contain_text(
"0" + "-15" + "Limit" + "Active" + "170.00" + "GTC"
expect(page.get_by_test_id(order_tab)).to_contain_text(
"market-2Futr" + "0" + "-15" + "Limit" + "Active" + "170.00" + "GTC"
)
@@ -416,11 +389,9 @@ def test_order_cancel_single_order(vega: VegaServiceNull, page: Page):
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
expect(page.locator('[row-index="0"]').first).to_contain_text(
"market-3Futr"
)
expect(page.locator('[row-index="0"]').nth(1)).to_contain_text(
"0" + "+10" + "Limit" + "Cancelled" + "60.00" + "GTC"
expect(page.get_by_test_id(order_tab)).to_contain_text(
"market-3Futr" + "0" + "+10" + "Limit" + "Cancelled" + "60.00" + "GTC"
)
@@ -106,6 +106,7 @@ def test_orderbook_grid_content(setup_market, page: Page):
matching_order[1],
)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
@@ -232,6 +233,7 @@ def test_orderbook_price_movement(setup_market, page: Page):
matching_order_1[1],
)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
@@ -252,6 +254,7 @@ def test_orderbook_price_movement(setup_market, page: Page):
matching_order_2[1],
)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
@@ -34,6 +34,7 @@ class TestPerpetuals:
settlement_price=110,
market_id=perps_market,
)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
submit_multiple_orders(
@@ -47,7 +48,8 @@ class TestPerpetuals:
settlement_price=110,
market_id=perps_market,
)
vega.wait_fn(10)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
return perps_market
@@ -108,6 +110,7 @@ def test_perps_market_termination_proposed(page: Page, vega: VegaServiceNull):
forward_time_to_enactment=False,
)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
banner_text = page.get_by_test_id(
@@ -132,6 +135,7 @@ def test_perps_market_terminated(page: Page, vega: VegaServiceNull):
approve_proposal=True,
forward_time_to_enactment=True,
)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
+1 -1
View File
@@ -11,7 +11,7 @@ def check_pnl_color_value(element, expected_color, expected_value):
assert color == expected_color, f"Unexpected color: {color}"
assert value == expected_value, f"Unexpected value: {value}"
#TODO move this test to jest
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_pnl(continuous_market, vega: VegaServiceNull, page: Page):
page.set_viewport_size({"width": 1748, "height": 977})
@@ -0,0 +1,32 @@
import os
import pytest
from playwright.sync_api import Page, expect
#TODO migrate to jest
@pytest.mark.usefixtures("auth", "risk_accepted", "continuous_market")
def test_ledger_entries_downloads(page: Page):
page.goto("/#/portfolio")
page.get_by_test_id("Ledger entries").click()
expect(page.get_by_test_id("ledger-download-button")).to_be_enabled()
# 7007-LEEN-001
page.get_by_test_id("ledger-download-button").click()
# 7007-LEEN-009
expect(page.get_by_test_id("toast-content")).to_contain_text(("Your file is ready"))
# Get the user's Downloads directory
downloads_directory = os.path.expanduser("~") + "/Downloads/"
# Start waiting for the download
with page.expect_download() as download_info:
# Perform the action that initiates download
page.get_by_role("link", name="Get file here").click()
download = download_info.value
# Wait for the download process to complete and save the downloaded file in the Downloads directory
download.save_as(os.path.join(downloads_directory, download.suggested_filename))
# Verify the download by asserting that the file exists
downloaded_file_path = os.path.join(
downloads_directory, download.suggested_filename
)
assert os.path.exists(
downloaded_file_path
), f"Download failed! File not found at: {downloaded_file_path}"
@@ -15,13 +15,14 @@ def test_closed_market_position(vega: VegaServiceNull, page: Page):
settlement_price=110,
market_id=market_id,
)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
page.goto(f"/#/markets/{market_id}")
expect(page.locator(".ag-overlay-panel")).to_have_text("No positions")
page.get_by_test_id("open-transfer").click()
tab = page.get_by_test_id("tab-positions")
table = tab.locator('[class="ag-body ag-layout-normal"]')
table = tab.locator(".ag-center-cols-container")
market = table.locator("[col-id='marketCode']")
expect(market.get_by_test_id("stack-cell-primary")).to_have_text("BTC:DAI_2023")
page.get_by_test_id("open-transfer").click()
+208 -282
View File
@@ -1,34 +1,13 @@
import pytest
import logging
import vega_sim.proto.vega as vega_protos
from typing import Tuple, Any
from playwright.sync_api import Page, expect
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
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
from vega_sim.service import VegaService
@pytest.fixture(scope="module")
@@ -45,19 +24,19 @@ def market_ids():
@pytest.fixture(scope="module")
def vega_activity_tier_0(request):
with init_vega(request) as vega_activity_tier_0:
# with init_vega(request) as vega_activity_tier_0:
yield vega_activity_tier_0
@pytest.fixture(scope="module")
def vega_hoarder_tier_0(request):
with init_vega(request) as vega_hoarder_tier_0:
# with init_vega(request) as vega_hoarder_tier_0:
yield vega_hoarder_tier_0
@pytest.fixture(scope="module")
def vega_combo_tier_0(request):
with init_vega(request) as vega_combo_tier_0:
# with init_vega(request) as vega_combo_tier_0:
yield vega_combo_tier_0
@@ -69,48 +48,79 @@ def vega_activity_tier_1(request):
@pytest.fixture(scope="module")
def vega_hoarder_tier_1(request):
with init_vega(request) as vega_hoarder_tier_1:
#with init_vega(request) as vega_hoarder_tier_1:
yield vega_hoarder_tier_1
@pytest.fixture(scope="module")
def vega_combo_tier_1(request):
with init_vega(request) as vega_combo_tier_1:
# with init_vega(request) as vega_combo_tier_1:
yield vega_combo_tier_1
@pytest.fixture
def auth(vega_instance, page):
return auth_setup(vega_instance, page)
vega, _, _ = vega_instance
return auth_setup(vega, page)
@pytest.fixture
def page(vega_instance, browser, request):
with init_page(vega_instance, browser, request) as page_instance:
vega, _, _ = vega_instance
with init_page(vega, browser, request) as page_instance:
yield page_instance
@pytest.fixture
def vega_instance(
reward_program,
vega_activity_tier_0,
vega_hoarder_tier_0,
vega_combo_tier_0,
vega_activity_tier_1,
vega_hoarder_tier_1,
vega_combo_tier_1,
tier,
):
if reward_program == "activity":
return vega_activity_tier_0 if tier == 1 else vega_activity_tier_1
elif reward_program == "hoarder":
return vega_hoarder_tier_0 if tier == 1 else vega_hoarder_tier_1
elif reward_program == "combo":
return vega_combo_tier_0 if tier == 1 else vega_combo_tier_1
reward_program: str,
vega_activity_tier_0: Any,
vega_hoarder_tier_0: Any,
vega_combo_tier_0: Any,
vega_activity_tier_1: Any,
vega_hoarder_tier_1: Any,
vega_combo_tier_1: Any,
market_ids: list,
tier: int,
) -> Tuple[Any, Any, Any]:
"""
Create a Vega instance based on the reward program and tier.
:param reward_program: The reward program type.
:param vega_activity_tier_0: The Vega instance for activity tier 0.
:param vega_hoarder_tier_0: The Vega instance for hoarder tier 0.
:param vega_combo_tier_0: The Vega instance for combo tier 0.
:param vega_activity_tier_1: The Vega instance for activity tier 1.
:param vega_hoarder_tier_1: The Vega instance for hoarder tier 1.
:param vega_combo_tier_1: The Vega instance for combo tier 1.
:param market_ids: List of market IDs.
:param tier: The tier level.
:return: Tuple containing the Vega instance, market ID, and tDAI asset ID.
"""
vega_tiers = {
"activity": (vega_activity_tier_0, vega_activity_tier_1),
"hoarder": (vega_hoarder_tier_0, vega_hoarder_tier_1),
"combo": (vega_combo_tier_0, vega_combo_tier_1),
}
if reward_program not in vega_tiers or tier not in (0, 1):
logging.error(f"Invalid reward_program '{reward_program}' or tier '{tier}'")
raise ValueError(f"Invalid reward_program '{reward_program}' or tier '{tier}'")
vega = vega_tiers[reward_program][tier]
# Set up market with the reward program
logging.info("Setting up Vega Instance")
market_id, tDAI_asset_id = set_market_reward_program(
vega, reward_program, market_ids, tier
)
return vega, market_id, tDAI_asset_id
def setup_market_with_reward_program(vega: VegaServiceNull, reward_programs, tier):
print(f"Started setup_market_with_{reward_programs}_{tier}")
def setup_market_with_reward_program(vega: VegaService, reward_programs, tier):
print("Started setup_market_with_reward_program")
tDAI_market = setup_continuous_market(vega)
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
@@ -118,7 +128,7 @@ def setup_market_with_reward_program(vega: VegaServiceNull, reward_programs, tie
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)
if ACTIVITY in reward_programs:
if "activity" in reward_programs:
vega.update_network_parameter(
proposal_key=MM_WALLET.name,
parameter="rewards.activityStreak.benefitTiers",
@@ -127,7 +137,7 @@ def setup_market_with_reward_program(vega: VegaServiceNull, reward_programs, tie
print("update_network_parameter activity done")
next_epoch(vega=vega)
if HOARDER in reward_programs:
if "hoarder" in reward_programs:
vega.update_network_parameter(
proposal_key=MM_WALLET.name,
parameter="rewards.vesting.benefitTiers",
@@ -150,7 +160,6 @@ def setup_market_with_reward_program(vega: VegaServiceNull, reward_programs, tie
asset_for_metric=tDAI_asset_id,
metric=vega_protos.vega.DISPATCH_METRIC_MAKER_FEES_PAID,
# lock_period= 5,
# TODO test lock period
amount=100,
factor=1.0,
)
@@ -172,17 +181,7 @@ def setup_market_with_reward_program(vega: VegaServiceNull, reward_programs, tie
)
vega.wait_for_total_catchup()
if tier == 1:
next_epoch(vega=vega)
vega.submit_order(
trading_key=PARTY_B.name,
market_id=tDAI_market,
order_type="TYPE_LIMIT",
time_in_force="TIME_IN_FORCE_GTC",
side="SIDE_BUY",
price=1,
volume=1,
)
""" if tier == 1:
next_epoch(vega=vega)
vega.submit_order(
trading_key=PARTY_B.name,
@@ -200,62 +199,46 @@ def setup_market_with_reward_program(vega: VegaServiceNull, reward_programs, tie
side="SIDE_BUY",
volume=1,
)
vega.wait_for_total_catchup()
next_epoch(vega=vega)
next_epoch(vega=vega)
if HOARDER in reward_programs:
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_D.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)
next_epoch(vega=vega)
next_epoch(vega=vega)
vega.wait_for_total_catchup() """
#next_epoch(vega=vega)
return tDAI_market, tDAI_asset_id
def set_market_reward_program(vega, reward_program, market_ids, tier):
market_id_key = f"vega_{reward_program}_tier_{tier}"
if reward_program == COMBO:
market_id_key = COMBO
market_id_key = f"vega_{reward_program}"
if reward_program == "combo":
market_id_key = "combo"
market_id = market_ids.get(market_id_key, "default_id")
print(f"Checking if market exists: {market_id}")
if not market_exists(vega, market_id):
print(
f"Market doesn't exist for {reward_program} {tier}. Setting up new market."
)
print(f"Market doesn't exist for {reward_program}. Setting up new market.")
reward_programs = [reward_program]
if reward_program == COMBO:
reward_programs = [ACTIVITY, HOARDER]
if reward_program == "combo":
reward_programs = ["activity", "hoarder"]
market_id, _ = setup_market_with_reward_program(vega, reward_programs, tier)
market_id = setup_market_with_reward_program(vega, reward_programs, tier)
market_ids[market_id_key] = market_id
return market_id, market_ids
print(f"Using market ID: {market_id}")
return market_id
ACTIVITY_STREAKS = """
{
"tiers": [
{
"minimum_activity_streak": 2,
"minimum_activity_streak": 1,
"reward_multiplier": "2.0",
"vesting_multiplier": "1.1"
},
{
"minimum_activity_streak": 5,
"reward_multiplier": "3.0",
"vesting_multiplier": "1.2"
}
]
}
@@ -264,8 +247,12 @@ VESTING = """
{
"tiers": [
{
"minimum_quantum_balance": "10000000",
"minimum_quantum_balance": "5000000",
"reward_multiplier": "2"
},
{
"minimum_quantum_balance": "11666668",
"reward_multiplier": "3"
}
]
}
@@ -275,195 +262,134 @@ VESTING = """
@pytest.mark.parametrize(
"reward_program, tier, total_rewards",
[
(ACTIVITY, 0, "50.00 tDAI"),
(HOARDER, 0, "50.00 tDAI"),
(COMBO, 0, "50.00 tDAI"),
(ACTIVITY, 1, "116.66666 tDAI"),
(HOARDER, 1, "166.66666 tDAI "),
(COMBO, 1, "183.33333 tDAI"),
#("activity", 0, "50.00 tDAI"),
#("hoarder", 0, "50.00 tDAI"),
#("combo", 0, "50.00 tDAI"),
("activity", 1, "110.00 tDAI"),
#("hoarder", 1, "116.66666 tDAI"),
#("combo", 1, "125.00 tDAI"),
],
)
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
@pytest.mark.skip("tbd")
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_network_reward_pot(
reward_program,
vega_instance: VegaServiceNull,
page: Page,
total_rewards,
tier,
market_ids,
reward_program, vega_instance: VegaService, page: Page, total_rewards, tier
):
print("reward program: " + reward_program, " tier:", tier)
market_id, market_ids = set_market_reward_program(
vega_instance, reward_program, market_ids, tier
)
page.goto(REWARDS_URL)
change_keys(page, vega_instance, PARTY_B.name)
expect(page.get_by_test_id(TOTAL_REWARDS)).to_have_text(total_rewards)
@pytest.mark.parametrize(
"reward_program, tier, reward_multiplier, streak_multiplier, hoarder_multiplier",
[
(ACTIVITY, 0, "1x", "1x", "1x"),
(HOARDER, 0, "1x", "1x", "1x"),
(COMBO, 0, "1x", "1x", "1x"),
(ACTIVITY, 1, "2x", "2x", "1x"),
(HOARDER, 1, "2x", "1x", "2x"),
(COMBO, 1, "4x", "2x", "2x"),
],
)
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
def test_reward_multiplier(
reward_program,
vega_instance: VegaServiceNull,
page: Page,
reward_multiplier,
streak_multiplier,
hoarder_multiplier,
tier,
market_ids,
):
print("reward program: " + reward_program, " tier:", tier)
market_id, market_ids = set_market_reward_program(
vega_instance, reward_program, market_ids, tier
)
page.goto(REWARDS_URL)
change_keys(page, vega_instance, PARTY_B.name)
expect(page.get_by_test_id(COMBINED_MULTIPLIERS)).to_have_text(reward_multiplier)
expect(page.get_by_test_id(STREAK_REWARD_MULTIPLIER_VALUE)).to_have_text(
streak_multiplier
)
expect(page.get_by_test_id(HOARDER_REWARD_MULTIPLIER_VALUE)).to_have_text(
hoarder_multiplier
)
@pytest.mark.parametrize(
"reward_program, tier, epoch_streak",
[
(ACTIVITY, 0, "1"),
(ACTIVITY, 1, "7"),
],
)
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
def test_activity_streak(
reward_program,
vega_instance: VegaServiceNull,
page: Page,
epoch_streak,
tier,
market_ids,
):
print("reward program: " + reward_program, " tier:", tier)
market_id, market_ids = set_market_reward_program(
vega_instance, reward_program, market_ids, tier
)
page.goto(REWARDS_URL)
change_keys(page, vega_instance, PARTY_B.name)
vega, market_id, tDAI_asset_id = vega_instance
next_epoch(vega=vega)
page.goto(f"/#/rewards")
if tier == 1:
expect(page.get_by_test_id(EPOCH_STREAK)).to_have_text(
"Active trader: " + epoch_streak + " epochs so far (Tier 1 as of last epoch)"
page.pause()
next_epoch(vega=vega)
next_epoch(vega=vega)
vega.submit_order(
trading_key=PARTY_B.name,
market_id=market_id,
order_type="TYPE_MARKET",
time_in_force="TIME_IN_FORCE_IOC",
side="SIDE_BUY",
volume=1,
)
else:
expect(page.get_by_test_id(EPOCH_STREAK)).to_have_text(
"Active trader: " + epoch_streak + " epochs so far "
vega.submit_order(
trading_key=PARTY_D.name,
market_id=market_id,
order_type="TYPE_MARKET",
time_in_force="TIME_IN_FORCE_IOC",
side="SIDE_BUY",
volume=1,
)
@pytest.mark.parametrize(
"reward_program, tier, rewards_hoarded",
[
(HOARDER, 0, "5,000,000"),
(HOARDER, 1, "16,666,666"),
],
)
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
def test_hoarder_bonus(
reward_program,
vega_instance: VegaServiceNull,
page: Page,
rewards_hoarded,
tier,
market_ids,
):
print("reward program: " + reward_program, " tier:", tier)
market_id, market_ids = set_market_reward_program(
vega_instance, reward_program, market_ids, tier
)
page.goto(REWARDS_URL)
change_keys(page, vega_instance, PARTY_B.name)
expect(page.get_by_test_id(HOARDER_BONUS_TOTAL_HOARDED)).to_contain_text(
rewards_hoarded
)
@pytest.mark.parametrize(
"reward_program, tier, price_taking, total, earned_by_me",
[
(ACTIVITY, 0, "100.00100.00%", "100.00", "50.00"),
(HOARDER, 0, "100.00100.00%", "100.00", "50.00"),
(COMBO, 0, "100.00100.00%", "100.00", "50.00"),
(ACTIVITY, 1, "300.00100.00%", "300.00", "116.66666"),
(HOARDER, 1, "299.99999100.00%", "299.99999", "166.66666"),
(COMBO, 1, "299.99999100.00%", "299.99999", "183.33333"),
],
)
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
def test_reward_history(
reward_program,
vega_instance: VegaServiceNull,
page: Page,
price_taking,
total,
earned_by_me,
tier,
market_ids,
):
print("reward program: " + reward_program, " tier:", tier)
market_id, market_ids = set_market_reward_program(
vega_instance, reward_program, market_ids, tier
)
page.goto(REWARDS_URL)
change_keys(page, vega_instance, PARTY_B.name)
page.locator('[name="fromEpoch"]').fill("1")
expect((page.get_by_role(ROW).locator(PRICE_TAKING_COL_ID)).nth(1)).to_have_text(
price_taking
)
expect((page.get_by_role(ROW).locator(TOTAL_COL_ID)).nth(1)).to_have_text(total)
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(
earned_by_me
)
@pytest.mark.parametrize(
"reward_program, tier",
[
(ACTIVITY, 1),
],
)
@pytest.mark.usefixtures("auth", "risk_accepted", "market_ids")
def test_redeem(
reward_program, vega_instance: VegaServiceNull, page: Page, tier, market_ids
):
print("reward program: " + reward_program, " tier:", tier)
market_id, market_ids = set_market_reward_program(
vega_instance, reward_program, market_ids, tier
)
page.goto(REWARDS_URL)
change_keys(page, vega_instance, PARTY_B.name)
page.get_by_test_id("redeem-rewards-button").click()
available_to_withdraw = page.get_by_test_id(
"available-to-withdraw-value"
).text_content()
option_value = page.locator(
'[data-testid="transfer-form"] [name="fromAccount"] option[value^="ACCOUNT_TYPE_VESTED_REWARDS"]'
).first.get_attribute("value")
page.select_option(
'[data-testid="transfer-form"] [name="fromAccount"]', option_value
)
vega.wait_for_total_catchup()
page.pause()
next_epoch(vega=vega)
page.pause()
next_epoch(vega=vega)
change_keys(page, vega, PARTY_B.name)
page.pause()
page.get_by_test_id("use-max-button").first.click()
expect(page.get_by_test_id(TRANSFER_AMOUNT)).to_have_text(available_to_withdraw)
expect(page.get_by_test_id("total-rewards")).to_have_text(total_rewards)
# TODO Add test ID and Assert for locked,
""" @pytest.mark.parametrize(
"reward_program",
[
("activity"),
# ("hoarder"),
# ("combo"),
],
)
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_vesting(vega_setup, vega: VegaService, page: Page):
expect() """
@pytest.mark.skip("tbd")
@pytest.mark.parametrize(
"reward_program, tier, reward_multiplier",
[
("activity", 0, "1x"),
("hoarder", 0, "1x"),
("combo", 0, "1x"),
("activity", 1, "2x"),
("hoarder", 1, "2x"),
("combo", 1, "4x"),
],
)
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_reward_multiplier(reward_program, vega_instance: VegaService, page: Page, reward_multiplier, tier):
vega, market_id, tDAI_asset_id = vega_instance
page.goto(f"/#/rewards")
change_keys(page, vega, PARTY_B.name)
expect(page.get_by_test_id("combined-multipliers")).to_have_text(reward_multiplier)
#TODO add test ids and assert for individual multipliers
"""
@pytest.mark.parametrize(
"reward_program",
[
("activity"),
# ("hoarder"),
# ("combo"),
],
)
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_activity_streak(vega_setup, vega: VegaService, page: Page):
expect()
@pytest.mark.parametrize(
"reward_program",
[
("activity"),
# ("hoarder"),
# ("combo"),
],
)
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_hoarder_Bonus(vega_setup, vega: VegaService, page: Page):
expect()
@pytest.mark.parametrize(
"reward_program",
[
("activity"),
# ("hoarder"),
# ("combo"),
],
)
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_Rewards_history(vega_setup, vega: VegaService, page: Page):
expect()
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_redeem(vega_setup, vega: VegaService, page: Page):
expect()
@pytest.mark.usefixtures("auth", "risk_accepted")
def test_redeem(vega_setup, vega: VegaService, page: Page):
expect()
"""
@@ -1,65 +0,0 @@
import pytest
import vega_sim.proto.vega as vega_protos
from playwright.sync_api import Page, expect
from vega_sim.null_service import VegaServiceNull
from actions.utils import next_epoch, change_keys
from wallet_config import MM_WALLET, PARTY_A, PARTY_B
@pytest.mark.usefixtures("risk_accepted", "auth")
def test_vesting(continuous_market, vega: VegaServiceNull, page: Page):
tDAI_asset_id = vega.find_asset_id(symbol="tDAI")
vega.update_network_parameter(
MM_WALLET.name, parameter="reward.asset", new_value=tDAI_asset_id
)
vega.mint(key_name=PARTY_B.name, asset=tDAI_asset_id, amount=100000)
vega.mint(key_name=PARTY_A.name, asset=tDAI_asset_id, amount=100000)
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,
lock_period=5,
amount=100,
factor=1.0,
)
vega.submit_order(
trading_key=PARTY_B.name,
market_id=continuous_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=continuous_market,
order_type="TYPE_MARKET",
time_in_force="TIME_IN_FORCE_IOC",
side="SIDE_BUY",
volume=1,
)
vega.wait_for_total_catchup()
page.goto("/#/rewards")
change_keys(page, vega, PARTY_B.name)
next_epoch(vega=vega)
page.reload()
expect(page.get_by_test_id("locked-value")).to_have_text("50.00")
# Proceed through the 5 epoch lock period
next_epoch(vega=vega)
next_epoch(vega=vega)
next_epoch(vega=vega)
next_epoch(vega=vega)
next_epoch(vega=vega)
page.reload()
expect(page.get_by_test_id("locked-value")).to_have_text("0.00")
expect(page.get_by_test_id("vesting-value")).to_have_text("37.50")
expect(page.get_by_test_id("available-to-withdraw-value")).to_have_text("12.50")
@@ -149,5 +149,7 @@ def provide_successor_liquidity(
)
submit_order(vega, "Key 1", market_id, "SIDE_BUY", 1, 110)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
@@ -73,6 +73,6 @@ def test_limit_order_new_trade_top_of_list(
def test_price_copied_to_deal_ticket(continuous_market, page: Page):
page.goto(f"/#/markets/{continuous_market}")
page.get_by_test_id("Trades").click()
page.locator("[col-id=price]").nth(1).click()
page.locator("[col-id=price]").last.click()
# 6005-THIS-007
expect(page.get_by_test_id("order-price")).to_have_value("107.50000")
@@ -22,6 +22,8 @@ def test_trade_match_table(opening_auction_market: str, vega: VegaServiceNull, p
price=10e15,
wait=False,
)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
@@ -32,6 +34,7 @@ def test_trade_match_table(opening_auction_market: str, vega: VegaServiceNull, p
"SIDE_BUY",
[[5, 110], [5, 105], [1, 50]],
)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
@@ -42,6 +45,7 @@ def test_trade_match_table(opening_auction_market: str, vega: VegaServiceNull, p
"SIDE_SELL",
[[5, 90], [5, 95], [1, 150]],
)
vega.forward("60s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
@@ -50,6 +50,7 @@ def test_transfer_submit(continuous_market, vega: VegaServiceNull, page: Page):
page.locator('[data-testid=transfer-form] [type="submit"]').click()
wait_for_toast_confirmation(page)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
expected_confirmation_text = re.compile(
@@ -141,12 +142,14 @@ def test_transfer_vesting_below_minimum(
asset=asset_id,
amount=24.999999,
)
vega.forward("10s")
vega.wait_fn(10)
vega.wait_for_total_catchup()
page.get_by_test_id("use-max-button").first.click()
page.get_by_text("Use max").first.click()
page.locator('[data-testid=transfer-form] [type="submit"]').click()
wait_for_toast_confirmation(page)
vega.forward("10s")
vega.wait_fn(1)
vega.wait_for_total_catchup()
expected_confirmation_text = re.compile(
+1 -1
View File
@@ -116,7 +116,7 @@ def test_wallet_transaction_rejected(continuous_market, page: Page):
page.get_by_test_id(order_price).fill("120")
page.route("**/*", handle_route_connection_rejected)
page.get_by_test_id(place_order).click()
expect(page.get_by_test_id("toast-content").nth(0)).to_have_text(
expect(page.get_by_test_id("toast-content")).to_have_text(
"Error occurredthe user rejected the wallet connection"
)
+2 -5
View File
@@ -67,7 +67,6 @@ const defaultColDef = {
sortable: true,
tooltipComponent: TooltipCellComponent,
comparator: accountValuesComparator,
minWidth: 150,
};
export interface GetRowsParams extends Omit<IGetRowsParams, 'successCallback'> {
successCallback(rowsThisBlock: AccountFields[], lastRow?: number): void;
@@ -140,8 +139,6 @@ export const AccountTable = ({
{
headerName: t('Asset'),
field: 'asset.symbol',
pinned: true,
minWidth: 75,
headerTooltip: t(
'Asset is the collateral that is deposited into the Vega protocol.'
),
@@ -256,8 +253,8 @@ export const AccountTable = ({
colId: 'accounts-actions',
field: 'asset.id',
...COL_DEFS.actions,
minWidth: showDepositButton ? 110 : COL_DEFS.actions.minWidth,
maxWidth: showDepositButton ? 110 : COL_DEFS.actions.maxWidth,
minWidth: showDepositButton ? 105 : COL_DEFS.actions.minWidth,
maxWidth: showDepositButton ? 105 : COL_DEFS.actions.maxWidth,
cellRenderer: ({
value: assetId,
node,
+3 -6
View File
@@ -23,9 +23,7 @@ import { AccountType } from '@vegaprotocol/types';
const defaultColDef = {
resizable: true,
sortable: true,
minWidth: 100,
};
interface BreakdownTableProps extends AgGridReactProps {
data: AccountFields[] | null;
onMarketClick?: (marketId: string, metaKey?: boolean) => void;
@@ -34,13 +32,12 @@ interface BreakdownTableProps extends AgGridReactProps {
const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
({ data }, ref) => {
const t = useT();
const colDefs = useMemo(() => {
const coldefs = useMemo(() => {
const defs: ColDef[] = [
{
headerName: t('Market'),
field: 'market.tradableInstrument.instrument.code',
width: 90,
pinned: true,
minWidth: 200,
sort: 'desc',
cellRenderer: ({
value,
@@ -144,7 +141,7 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
components={{ PriceCell, ProgressBarCell }}
tooltipShowDelay={500}
defaultColDef={defaultColDef}
columnDefs={colDefs}
columnDefs={coldefs}
domLayout="autoHeight"
/>
);
-1
View File
@@ -438,7 +438,6 @@ export const TransferForm = ({
shouldValidate: true,
})
}
data-testid="use-max-button"
>
{t('Use max')}
</button>
@@ -15,6 +15,7 @@ export async function proposeMarket(publicKey: string) {
log('sending proposal tx');
const proposalTx = createNewMarketProposal();
const result = await sendVegaTx(publicKey, proposalTx);
return result.result;
}
@@ -118,7 +119,6 @@ function createNewMarketProposal(): ProposalSubmissionBody {
timeWindow: '3600',
scalingFactor: 10,
},
// FIXME: workaround because of https://github.com/vegaprotocol/vega/issues/10343
triggeringRatio: '0.7',
auctionExtension: '1',
},
@@ -9,7 +9,4 @@ export const COL_DEFS = {
type: 'rightAligned',
pinned: 'right' as const,
},
default: {
minWidth: 100,
},
};
@@ -329,9 +329,8 @@ export const DealTicket = ({
const marketTradingModeError = validateMarketTradingMode(
marketTradingMode,
t('No trading')
t('Trading terminated')
);
if (marketTradingModeError !== true) {
return {
message: marketTradingModeError,
+4
View File
@@ -11,6 +11,9 @@ export function generateMarket(override?: PartialDeep<Market>): Market {
positionDecimalPlaces: 1,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_CONTINUOUS,
state: Schema.MarketState.STATE_ACTIVE,
liquidityMonitoringParameters: {
triggeringRatio: '1',
},
marketTimestamps: {
__typename: 'MarketTimestamps',
close: '',
@@ -72,6 +75,7 @@ export function generateMarket(override?: PartialDeep<Market>): Market {
__typename: 'Instrument',
},
},
fees: {
factors: {
makerFee: '0.001',
+37 -43
View File
@@ -1,4 +1,10 @@
import { waitFor, fireEvent, render, screen } from '@testing-library/react';
import {
waitFor,
fireEvent,
render,
screen,
act,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import BigNumber from 'bignumber.js';
import type { DepositFormProps } from './deposit-form';
@@ -83,10 +89,7 @@ describe('Deposit form', () => {
render(<DepositForm {...props} />);
// Assert default values (including) from/to provided by useVegaWallet and useWeb3React
// Wait for first value to show as form is rendered conditionally based on chainId
expect(
await screen.findByText('From (Ethereum address)')
).toBeInTheDocument();
expect(screen.getByText('From (Ethereum address)')).toBeInTheDocument();
expect(screen.getByTestId('ethereum-address')).toHaveTextContent(
truncateMiddle(MOCK_ETH_ADDRESS)
);
@@ -316,40 +319,34 @@ describe('Deposit form', () => {
it('shows "View asset details" button when an asset is selected', async () => {
render(<DepositForm {...props} selectedAsset={asset} />);
expect(await screen.findByTestId('view-asset-details')).toBeInTheDocument();
expect(await screen.getByTestId('view-asset-details')).toBeInTheDocument();
});
it('does not shows "View asset details" button when no asset is selected', async () => {
render(<DepositForm {...props} />);
await waitFor(() => {
expect(screen.queryAllByTestId('view-asset-details')).toHaveLength(0);
});
expect(await screen.queryAllByTestId('view-asset-details')).toHaveLength(0);
});
it('renders a connect button if Ethereum wallet is not connected', async () => {
it('renders a connect button if Ethereum wallet is not connected', () => {
(useWeb3React as jest.Mock).mockReturnValue({
isActive: false,
account: '',
});
render(<DepositForm {...props} />);
expect(
await screen.findByRole('button', { name: 'Connect' })
).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Connect' })).toBeInTheDocument();
expect(
screen.queryByLabelText('From (Ethereum address)')
).not.toBeInTheDocument();
});
it('renders a disabled input if Ethereum wallet is connected', async () => {
it('renders a disabled input if Ethereum wallet is connected', () => {
(useWeb3React as jest.Mock).mockReturnValue({
isActive: true,
account: MOCK_ETH_ADDRESS,
});
render(<DepositForm {...props} />);
expect(await screen.findByTestId('deposit-form')).toBeInTheDocument();
expect(
screen.queryByRole('button', { name: 'Connect' })
).not.toBeInTheDocument();
@@ -359,56 +356,53 @@ describe('Deposit form', () => {
);
});
it('prevents submission if you are on the wrong chain', async () => {
// Make mocks return a chain id mismatch
it('prevents submission if you are on the wrong chain', () => {
(useWeb3React as jest.Mock).mockReturnValue({
isActive: true,
account: MOCK_ETH_ADDRESS,
chainId: 1,
});
(useWeb3ConnectStore as unknown as jest.Mock).mockImplementationOnce(
(useWeb3ConnectStore as unknown as jest.Mock).mockImplementation(
// eslint-disable-next-line
(selector: (result: ReturnType<typeof useWeb3ConnectStore>) => any) => {
return selector({
desiredChainId: 11155111,
open: jest.fn(),
foo: 'asdf',
});
}
);
render(<DepositForm {...props} />);
expect(await screen.findByTestId('chain-error')).toHaveTextContent(
expect(screen.getByTestId('chain-error')).toHaveTextContent(
/this app only works on/i
);
expect(screen.queryByTestId('deposit-form')).not.toBeInTheDocument();
});
it('Remaining deposit allowance tooltip should be rendered', async () => {
render(<DepositForm {...props} selectedAsset={asset} />);
expect(await screen.findByTestId('deposit-form')).toBeInTheDocument();
await userEvent.hover(screen.getByText('Remaining deposit allowance'));
expect(
await screen.findByRole('tooltip', {
name: /VEGA has a lifetime deposit limit of 20 asset-symbol per address/,
})
).toBeInTheDocument();
await act(async () => {
await userEvent.hover(screen.getByText('Remaining deposit allowance'));
});
await waitFor(async () => {
await expect(
screen.getByRole('tooltip', {
name: /VEGA has a lifetime deposit limit of 20 asset-symbol per address/,
})
).toBeInTheDocument();
});
});
it('Ethereum deposit cap tooltip should be rendered', async () => {
render(<DepositForm {...props} selectedAsset={asset} />);
expect(await screen.findByTestId('deposit-form')).toBeInTheDocument();
await userEvent.hover(screen.getByText('Ethereum deposit cap'));
expect(
await screen.findByRole('tooltip', {
name: /The deposit cap is set when you approve an asset for use with this app/,
})
).toBeInTheDocument();
await act(async () => {
await userEvent.hover(screen.getByText('Ethereum deposit cap'));
});
await waitFor(async () => {
await expect(
screen.getByRole('tooltip', {
name: /The deposit cap is set when you approve an asset for use with this app/,
})
).toBeInTheDocument();
});
});
});
+28 -33
View File
@@ -92,9 +92,7 @@ export const DepositForm = ({
const maxSafe = useMaxSafe();
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
const openDialog = useWeb3ConnectStore((store) => store.open);
const { isActive, account, chainId } = useWeb3React();
const desiredChainId = useWeb3ConnectStore((store) => store.desiredChainId);
const invalidChain = isActive && chainId !== desiredChainId;
const { isActive, account } = useWeb3React();
const { pubKey, pubKeys: _pubKeys } = useVegaWallet();
const [approveNotificationIntent, setApproveNotificationIntent] =
useState<Intent>(Intent.Warning);
@@ -154,20 +152,7 @@ export const DepositForm = ({
const approved =
balances && balances.allowance.isGreaterThan(0) ? true : false;
return invalidChain ? (
<div className="mb-2">
<Notification
intent={Intent.Danger}
testId="chain-error"
message={t(
'This app only works on {{chainId}}. Switch your Ethereum wallet to the correct network.',
{
chainId: getChainName(desiredChainId),
}
)}
/>
</div>
) : (
return (
<form
onSubmit={handleSubmit(onSubmit)}
noValidate={true}
@@ -432,11 +417,7 @@ export const DepositForm = ({
intent={approveNotificationIntent}
amount={amount}
/>
<FormButton
approved={approved}
isActive={isActive}
selectedAsset={selectedAsset}
/>
<FormButton approved={approved} selectedAsset={selectedAsset} />
</form>
);
};
@@ -444,21 +425,35 @@ export const DepositForm = ({
interface FormButtonProps {
approved: boolean;
selectedAsset: AssetFieldsFragment | undefined;
isActive: boolean;
}
const FormButton = ({ approved, selectedAsset, isActive }: FormButtonProps) => {
const FormButton = ({ approved, selectedAsset }: FormButtonProps) => {
const t = useT();
const { isActive, chainId } = useWeb3React();
const desiredChainId = useWeb3ConnectStore((store) => store.desiredChainId);
const invalidChain = isActive && chainId !== desiredChainId;
return (
<TradingButton
type="submit"
data-testid="deposit-submit"
fill
disabled={!isActive}
>
{t('Deposit')}
</TradingButton>
<>
{invalidChain && (
<div className="mb-2">
<Notification
intent={Intent.Danger}
testId="chain-error"
message={t('This app only works on {{chainId}}.', {
chainId: getChainName(desiredChainId),
})}
/>
</div>
)}
<TradingButton
type="submit"
data-testid="deposit-submit"
fill
disabled={!isActive || invalidChain}
>
{t('Deposit')}
</TradingButton>
</>
);
};
+3 -9
View File
@@ -6,7 +6,7 @@ import {
isNumeric,
} from '@vegaprotocol/utils';
import { type ColDef } from 'ag-grid-community';
import { AgGrid, COL_DEFS } from '@vegaprotocol/datagrid';
import { AgGrid } from '@vegaprotocol/datagrid';
import {
type VegaICellRendererParams,
type VegaValueFormatterParams,
@@ -21,7 +21,7 @@ export const DepositsTable = (
) => {
const columnDefs = useMemo<ColDef[]>(
() => [
{ headerName: 'Asset', field: 'asset.symbol', pinned: true },
{ headerName: 'Asset', field: 'asset.symbol' },
{
headerName: 'Amount',
field: 'amount',
@@ -74,11 +74,5 @@ export const DepositsTable = (
],
[]
);
return (
<AgGrid
columnDefs={columnDefs}
defaultColDef={COL_DEFS.default}
{...props}
/>
);
return <AgGrid columnDefs={columnDefs} {...props} />;
};
-2
View File
@@ -48,7 +48,6 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
field: 'market.tradableInstrument.instrument.code',
cellRenderer: 'MarketNameCell',
cellRendererParams: { idPath: 'market.id', onMarketClick },
pinned: true,
},
{
headerName: t('Size'),
@@ -144,7 +143,6 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
<AgGrid
ref={ref}
columnDefs={columnDefs}
defaultColDef={COL_DEFS.default}
overlayNoRowsTemplate={t('No fills')}
getRowId={({ data }) => data?.id}
tooltipShowDelay={0}
+3
View File
@@ -54,6 +54,9 @@ export const generateFill = (override?: PartialDeep<Trade>) => {
decimalPlaces: 5,
state: MarketState.STATE_ACTIVE,
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
liquidityMonitoringParameters: {
triggeringRatio: '1',
},
fees: {
__typename: 'Fees',
factors: {
@@ -22,7 +22,9 @@ export const generateFundingPayment = (
decimalPlaces: 5,
state: MarketState.STATE_ACTIVE,
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
liquidityMonitoringParameters: {
triggeringRatio: '1',
},
fees: {
__typename: 'Fees',
factors: {
+1 -1
View File
@@ -116,7 +116,7 @@
"Total fees": "Total fees",
"Total margin available": "Total margin available",
"TOTAL_MARGIN_AVAILABLE": "Total margin available = general {{assetSymbol}} balance ({{generalAccountBalance}} {{assetSymbol}}) + margin balance ({{marginAccountBalance}} {{assetSymbol}}) - maintenance level ({{marginMaintenance}} {{assetSymbol}}).",
"No trading": "No trading",
"Trading terminated": "Trading terminated",
"Trailing percent offset cannot be higher than 99.9": "Trailing percent offset cannot be higher than 99.9",
"Trailing percent offset cannot be lower than {{trailingPercentOffsetStep}}": "Trailing percent offset cannot be lower than {{trailingPercentOffsetStep}}",
"Trailing percentage offset": "Trailing percentage offset",
+1 -1
View File
@@ -27,7 +27,7 @@
"The {{symbol}} faucet is not available at this time": "The {{symbol}} faucet is not available at this time",
"The deposit cap is set when you approve an asset for use with this app. To increase this cap, approve {{assetSymbol}} again and choose a higher cap. Check the documentation for your Ethereum wallet app for details.": "The deposit cap is set when you approve an asset for use with this app. To increase this cap, approve {{assetSymbol}} again and choose a higher cap. Check the documentation for your Ethereum wallet app for details.",
"The faucet transaction was rejected by the connected Ethereum wallet": "The faucet transaction was rejected by the connected Ethereum wallet",
"This app only works on {{chainId}}. Switch your Ethereum wallet to the correct network.": "This app only works on {{chainId}}. Switch your Ethereum wallet to the correct network.",
"This app only works on {{chainId}}.": "This app only works on {{chainId}}.",
"To (Vega key)": "To (Vega key)",
"To date, {{currentDeposit}} {{assetSymbol}} has been deposited from this Ethereum address, so you can deposit up to {{remainingDeposit}} {{assetSymbol}} more.": "To date, {{currentDeposit}} {{assetSymbol}} has been deposited from this Ethereum address, so you can deposit up to {{remainingDeposit}} {{assetSymbol}} more.",
"Use maximum": "Use maximum",
+1 -1
View File
@@ -383,7 +383,7 @@
"MoreMarketsInfo": "To see Explorer data on existing markets visit",
"MoreNetParamsInfo": "To see Explorer data on network params visit",
"MoreProposalsInfo": "To see Explorer data on proposals visit",
"multisigContractIncorrect": "was incorrectly configured as at the end of the last epoch so rewards were penalised. Validator and delegator rewards will continue to be penalised until this is resolved.",
"multisigContractIncorrect": "is incorrectly configured. Validator and delegator rewards will be penalised until this is resolved.",
"multisigContractLink": "Ethereum Multisig Contract",
"multisigPenalty": "Multisig penalty",
"myPendingStake": "My pending stake",
-1
View File
@@ -30,7 +30,6 @@
"How often the quality of liquidity supplied by each liquidity provider is evaluated and the fees arising from that period are earmarked for specific providers. This is a market parameter. ": "How often the quality of liquidity supplied by each liquidity provider is evaluated and the fees arising from that period are earmarked for specific providers. This is a market parameter. ",
"Instrument": "Instrument",
"Insurance pool": "Insurance pool",
"Insurance Pool Balance": "Insurance Pool Balance",
"Internal conditions": "Internal conditions",
"Invalid data source": "Invalid data source",
"involvedInMarkets_one": "Involved in {{count}} market",
+81 -81
View File
@@ -1,24 +1,25 @@
{
"(Combined set volume {{runningVolume}} over last {{epochs}} epochs)": "(Combined set volume {{runningVolume}} over last {{epochs}} epochs)",
"(Created at: {{createdAt}})": "(Created at: {{createdAt}})",
"(Tier {{tier}} as of last epoch)": "(Tier {{tier}} as of last epoch)",
"{{amount}} $VEGA staked": "{{amount}} $VEGA staked",
"{{assetSymbol}} Reward pot": "{{assetSymbol}} Reward pot",
"{{checkedAssets}} Assets": "{{checkedAssets}} Assets",
"{{distance}} ago": "{{distance}} ago",
"{{instrumentCode}} liquidity provision": "{{instrumentCode}} liquidity provision",
"<0>No running Desktop App/CLI detected. Open your app now to connect or enter a</0> <1>custom wallet location</1>": "<0>No running Desktop App/CLI detected. Open your app now to connect or enter a</0> <1>custom wallet location</1>",
"24h vol": "24h vol",
"24h volume": "24h volume",
"<0>No running Desktop App/CLI detected. Open your app now to connect or enter a</0> <1>custom wallet location</1>": "<0>No running Desktop App/CLI detected. Open your app now to connect or enter a</0> <1>custom wallet location</1>",
"A percentage of commission earned by the referrer": "A percentage of commission earned by the referrer",
"A successor to this market has been proposed": "A successor to this market has been proposed",
"About the referral program": "About the referral program",
"Active": "Active",
"Activity Streak": "Activity Streak",
"All": "All",
"An unknown error occurred.": "An unknown error occurred.",
"Anonymous": "Anonymous",
"Anyone with the referral link can apply it to their key(s) of choice via an on chain transaction": "Anyone with the referral link can apply it to their key(s) of choice via an on chain transaction",
"Assessed over": "Assessed over",
"Asset (1)": "Asset (1)",
"Assets": "Assets",
"Available to withdraw this epoch": "Available to withdraw this epoch",
"Average position": "Average position",
"Base commission rate": "Base commission rate",
"Base rate": "Base rate",
"Best bid": "Best bid",
@@ -29,6 +30,9 @@
"Changes have been proposed for this market. <0>View proposals</0>": "Changes have been proposed for this market. <0>View proposals</0>",
"Chart": "Chart",
"Chart by <0>TradingView</0>": "Chart by <0>TradingView</0>",
"checkOutProposalsAndVote": "Check out the terms of the proposals and vote:",
"checkOutProposalsAndVote_one": "Check out the terms of the proposal and vote:",
"checkOutProposalsAndVote_other": "Check out the terms of the proposals and vote:",
"Close": "Close",
"Close menu": "Close menu",
"Closed": "Closed",
@@ -51,13 +55,6 @@
"Countdown": "Countdown",
"Create a referral code": "Create a referral code",
"Current tier": "Current tier",
"DISCLAIMER_P1": "Vega is a decentralised peer-to-peer protocol that can be used to trade derivatives with cryptoassets. The Vega Protocol is an implementation layer (layer one) protocol made of free, public, open-source or source-available software. Use of the Vega Protocol involves various risks, including but not limited to, losses while digital assets are supplied to the Vega Protocol and losses due to the fluctuation of prices of assets.",
"DISCLAIMER_P2": "Before using the Vega Protocol, review the relevant documentation at docs.vega.xyz to make sure that you understand how it works. Conduct your own due diligence and consult your financial advisor before making any investment decisions.",
"DISCLAIMER_P3": "As described in the Vega Protocol core license, the Vega Protocol is provided “as is”, at your own risk, and without warranties of any kind. Although Gobalsky Labs Limited developed much of the initial code for the Vega Protocol, it does not provide or control the Vega Protocol, which is run by third parties deploying it on a bespoke blockchain. Upgrades and modifications to the Vega Protocol are managed in a community-driven way by holders of the VEGA governance token.",
"DISCLAIMER_P4": "No developer or entity involved in creating the Vega Protocol will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the Vega Protocol, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or legal costs, or loss of profits, cryptoassets, tokens or anything else of value.",
"DISCLAIMER_P5": "This website is hosted on a decentralised network, the Interplanetary File System (“IPFS”). The IPFS decentralised web is made up of all the computers (nodes) connected to it. Data is therefore stored on many different computers.",
"DISCLAIMER_P6": "The information provided on this website does not constitute investment advice, financial advice, trading advice, or any other sort of advice and you should not treat any of the website's content as such. No party recommends that any cryptoasset should be bought, sold, or held by you via this website. No party ensures the accuracy of information listed on this website or holds any responsibility for any missing or wrong information. You understand that you are using any and all information available here at your own risk.",
"DISCLAIMER_P7": "Additionally, just as you can access email protocols such as SMTP through multiple email clients, you can potentially access the Vega Protocol through many web or mobile interfaces. You are responsible for doing your own diligence on those interfaces to understand the associated risks and any fees.",
"Dark mode": "Dark mode",
"Date Joined": "Date Joined",
"Depending on data node retention you may not be able see the full 30 days": "Depending on data node retention you may not be able see the full 30 days",
@@ -67,6 +64,13 @@
"Depth": "Depth",
"Description": "Description",
"Disclaimer": "Disclaimer",
"DISCLAIMER_P1": "Vega is a decentralised peer-to-peer protocol that can be used to trade derivatives with cryptoassets. The Vega Protocol is an implementation layer (layer one) protocol made of free, public, open-source or source-available software. Use of the Vega Protocol involves various risks, including but not limited to, losses while digital assets are supplied to the Vega Protocol and losses due to the fluctuation of prices of assets.",
"DISCLAIMER_P2": "Before using the Vega Protocol, review the relevant documentation at docs.vega.xyz to make sure that you understand how it works. Conduct your own due diligence and consult your financial advisor before making any investment decisions.",
"DISCLAIMER_P3": "As described in the Vega Protocol core license, the Vega Protocol is provided “as is”, at your own risk, and without warranties of any kind. Although Gobalsky Labs Limited developed much of the initial code for the Vega Protocol, it does not provide or control the Vega Protocol, which is run by third parties deploying it on a bespoke blockchain. Upgrades and modifications to the Vega Protocol are managed in a community-driven way by holders of the VEGA governance token.",
"DISCLAIMER_P4": "No developer or entity involved in creating the Vega Protocol will be liable for any claims or damages whatsoever associated with your use, inability to use, or your interaction with other users of the Vega Protocol, including any direct, indirect, incidental, special, exemplary, punitive or consequential damages, or legal costs, or loss of profits, cryptoassets, tokens or anything else of value.",
"DISCLAIMER_P5": "This website is hosted on a decentralised network, the Interplanetary File System (“IPFS”). The IPFS decentralised web is made up of all the computers (nodes) connected to it. Data is therefore stored on many different computers.",
"DISCLAIMER_P6": "The information provided on this website does not constitute investment advice, financial advice, trading advice, or any other sort of advice and you should not treat any of the website's content as such. No party recommends that any cryptoasset should be bought, sold, or held by you via this website. No party ensures the accuracy of information listed on this website or holds any responsibility for any missing or wrong information. You understand that you are using any and all information available here at your own risk.",
"DISCLAIMER_P7": "Additionally, just as you can access email protocols such as SMTP through multiple email clients, you can potentially access the Vega Protocol through many web or mobile interfaces. You are responsible for doing your own diligence on those interfaces to understand the associated risks and any fees.",
"Disconnect": "Disconnect",
"Discount": "Discount",
"Discounts are applied automatically during trading based on the key(s) used": "Discounts are applied automatically during trading based on the key(s) used",
@@ -74,13 +78,12 @@
"Earn commission & stake rewards": "Earn commission & stake rewards",
"Earned by me": "Earned by me",
"Enactment date reached and usual auction exit checks pass": "Enactment date reached and usual auction exit checks pass",
"Ends in": "Ends in",
"Entity scope": "Entity scope",
"Environment not configured": "Environment not configured",
"epochs in referral set": "epochs in referral set",
"Epochs in set": "Epochs in set",
"Epochs to next tier": "Epochs to next tier",
"Expected in {{distance}}": "Expected in {{distance}}",
"Expected {{distance}} ago": "Expected {{distance}} ago",
"Expected in {{distance}}": "Expected in {{distance}}",
"Experiment for free with virtual assets on <0>Fairground Testnet</0>": "Experiment for free with virtual assets on <0>Fairground Testnet</0>",
"Expiry": "Expiry",
"Explore": "Explore",
@@ -94,15 +97,14 @@
"From epoch": "From epoch",
"Fully decentralised high performance peer-to-network trading.": "Fully decentralised high performance peer-to-network trading.",
"Funding": "Funding",
"Funding Payments": "Funding Payments",
"Funding Rate": "Funding Rate",
"Funding history": "Funding history",
"Funding Payments": "Funding Payments",
"Funding payments": "Funding payments",
"Funding Rate": "Funding Rate",
"Funding rate": "Funding rate",
"Futures": "Futures",
"Generate a referral code to share with your friends and start earning commission.": "Generate a referral code to share with your friends and start earning commission.",
"Generate code": "Generate code",
"Get rewards for providing liquidity. Get rewards for providing liquidity.": "Get rewards for providing liquidity. Get rewards for providing liquidity.",
"Get started": "Get started",
"Give Feedback": "Give Feedback",
"Go back and try again": "Go back and try again",
@@ -117,19 +119,18 @@
"Hoarder reward multiplier": "Hoarder reward multiplier",
"How it works": "How it works",
"I want a code": "I want a code",
"INTERVAL_I15M": "15m",
"INTERVAL_I1D": "1D",
"INTERVAL_I1H": "1H",
"INTERVAL_I1M": "1m",
"INTERVAL_I5M": "5m",
"INTERVAL_I6H": "6H",
"Improve vega console": "Improve vega console",
"Inactive": "Inactive",
"Index Price": "Index Price",
"Indicators": "Indicators",
"Individual": "Individual",
"Infrastructure": "Infrastructure",
"Interval: {{interval}}": "Interval: {{interval}}",
"INTERVAL_I1M": "1m",
"INTERVAL_I5M": "5m",
"INTERVAL_I15M": "15m",
"INTERVAL_I1H": "1H",
"INTERVAL_I6H": "6H",
"INTERVAL_I1D": "1D",
"Invite friends and earn rewards from the trading fees they pay. Stake those rewards to earn multipliers on future rewards.": "Invite friends and earn rewards from the trading fees they pay. Stake those rewards to earn multipliers on future rewards.",
"Learn about providing liquidity": "Learn about providing liquidity",
"Learn more": "Learn more",
@@ -153,11 +154,16 @@
"Metamask Snap <0>quick start</0>": "Metamask Snap <0>quick start</0>",
"Min. epochs": "Min. epochs",
"Min. trading volume": "Min. trading volume",
"minTradingVolume": "Min. trading volume (last {{count}} epochs)",
"minTradingVolume_one": "Min. trading volume (last {{count}} epoch)",
"minTradingVolume_other": "Min. trading volume (last {{count}} epochs)",
"My current volume": "My current volume",
"My liquidity provision": "My liquidity provision",
"My trading fees": "My trading fees",
"myVolume": "My volume (last {{count}} epochs)",
"myVolume_one": "My volume (last {{count}} epoch)",
"myVolume_other": "My volume (last {{count}} epochs)",
"Name": "Name",
"No MetaMask version that supports snaps detected. Learn more about <0>MetaMask Snaps</0>": "No MetaMask version that supports snaps detected. Learn more about <0>MetaMask Snaps</0>",
"No closed orders": "No closed orders",
"No data": "No data",
"No deposits": "No deposits",
@@ -167,6 +173,7 @@
"No market": "No market",
"No markets": "No markets",
"No markets.": "No markets.",
"No MetaMask version that supports snaps detected. Learn more about <0>MetaMask Snaps</0>": "No MetaMask version that supports snaps detected. Learn more about <0>MetaMask Snaps</0>",
"No open orders": "No open orders",
"No orders": "No orders",
"No party accepts any liability for any losses whatsoever.": "No party accepts any liability for any losses whatsoever.",
@@ -174,7 +181,6 @@
"No referral program active": "No referral program active",
"No rejected orders": "No rejected orders",
"No rewards": "No rewards",
"No rows": "No rows",
"No thanks": "No thanks",
"No third party has access to your funds.": "No third party has access to your funds.",
"No volume discount program active": "No volume discount program active",
@@ -183,7 +189,6 @@
"Non-custodial and pseudonymous": "Non-custodial and pseudonymous",
"None": "None",
"Not connected": "Not connected",
"Number of epochs after distribution to delay vesting of rewards by": "Number of epochs after distribution to delay vesting of rewards by",
"Number of traders": "Number of traders",
"Open": "Open",
"Open a position": "Open a position",
@@ -192,9 +197,11 @@
"Order": "Order",
"Orderbook": "Orderbook",
"Orders": "Orders",
"PRNT": "PRNT",
"Page not found": "Page not found",
"Parent of a market": "Parent of a market",
"pastEpochs": "Past {{count}} epochs",
"pastEpochs_one": "Past {{count}} epoch",
"pastEpochs_other": "Past {{count}} epochs",
"Pennant": "Pennant",
"Perpetuals": "Perpetuals",
"Please choose another market from the <0>market list</0>": "Please choose another market from the <0>market list</0>",
@@ -202,12 +209,15 @@
"Portfolio": "Portfolio",
"Positions": "Positions",
"Price": "Price",
"PRNT": "PRNT",
"Program ends:": "Program ends:",
"Propose a new market": "Propose a new market",
"Proposed final price is {{price}} {{assetSymbol}}.": "Proposed final price is {{price}} {{assetSymbol}}.",
"Proposed markets": "Proposed markets",
"Providing liquidity": "Providing liquidity",
"Purpose built proof of stake blockchain": "Purpose built proof of stake blockchain",
"qUSD": "qUSD",
"qUSD provides a rough USD equivalent of balances across all assets using the value of \"Quantum\" for that asset": "qUSD provides a rough USD equivalent of balances across all assets using the value of \"Quantum\" for that asset",
"Read the terms": "Read the terms",
"Ready to trade": "Ready to trade",
"Ready to trade with real funds? <0>Switch to Mainnet</0>": "Ready to trade with real funds? <0>Switch to Mainnet</0>",
@@ -215,6 +225,9 @@
"Referral benefits": "Referral benefits",
"Referral discount": "Referral discount",
"Referrals": "Referrals",
"referralStatisticsCommission": "Commission earned in <0>qUSD</0> (<1>last {{count}} epochs</1>)",
"referralStatisticsCommission_one": "Commission earned in <0>qUSD</0> (<1>last {{count}} epoch</1>)",
"referralStatisticsCommission_other": "Commission earned in <0>qUSD</0> (<1>last {{count}} epochs</1>)",
"Referrer commission": "Referrer commission",
"Referrer trading discount": "Referrer trading discount",
"Referrers earn commission based on a percentage of the taker fees their referees pay": "Referrers earn commission based on a percentage of the taker fees their referees pay",
@@ -224,12 +237,12 @@
"Required for next tier": "Required for next tier",
"Reset Columns": "Reset Columns",
"Resources": "Resources",
"Reward bonus": "Reward bonus",
"Reward {{reward}}x": "Reward {{reward}}x",
"Rewards": "Rewards",
"Rewards funded using the pro-rata strategy should be distributed pro-rata by each entity's reward metric scaled by any active multipliers that party has": " Rewards funded using the pro-rata strategy should be distributed pro-rata by each entity's reward metric scaled by any active multipliers that party has",
"Rewards history": "Rewards history",
"Rewards multipliers": "Rewards multipliers",
"runningNotionalOverEpochs": "Combined running notional over the {{count}} epochs",
"runningNotionalOverEpochs_one": "Combined running notional over the {{count}} epoch",
"runningNotionalOverEpochs_other": "Combined running notional over the {{count}} epochs",
"SCCR": "SCCR",
"Search": "Search",
"See all markets": "See all markets",
@@ -248,7 +261,6 @@
"Spread": "Spread",
"Stake a minimum of {{minimumStakedTokens}} $VEGA tokens": "Stake a minimum of {{minimumStakedTokens}} $VEGA tokens",
"Stake some $VEGA now": "Stake some $VEGA now",
"Staked VEGA": "Staked VEGA",
"Staking multiplier": "Staking multiplier",
"Start trading": "Start trading",
"Start trading on the worlds most advanced decentralised exchange.": "Start trading on the worlds most advanced decentralised exchange.",
@@ -261,7 +273,6 @@
"Supplied stake": "Supplied stake",
"Suspended due to price or liquidity monitoring trigger": "Suspended due to price or liquidity monitoring trigger",
"Target stake": "Target stake",
"Team": "Team",
"The amount of fees paid to liquidity providers across the whole market during the last epoch {{epoch}}.": "The amount of fees paid to liquidity providers across the whole market during the last epoch {{epoch}}.",
"The commission is taken from the infrastructure fee, maker fee, and liquidity provider fee, not from the referee": "The commission is taken from the infrastructure fee, maker fee, and liquidity provider fee, not from the referee",
"The external time weighted average price (TWAP) received from the data source defined in the data sourcing specification.": "The external time weighted average price (TWAP) received from the data source defined in the data sourcing specification.",
@@ -271,41 +282,42 @@
"The successor market <0>{{instrumentName}}</0> has a 24h trading volume of {{successorVolume}}": "The successor market <0>{{instrumentName}}</0> has a 24h trading volume of {{successorVolume}}",
"The successor market is <0>{{instrumentName}}</0>": "The successor market is <0>{{instrumentName}}</0>",
"The transaction could not be sent": "The transaction could not be sent",
"This market URL is not available any more.": "This market URL is not available any more.",
"This market expires in {{duration}}.": "This market expires in {{duration}}.",
"This market expires when triggered by its oracle, not on a set date.": "This market expires when triggered by its oracle, not on a set date.",
"This market has been settled": "This market has been settled",
"This market has been succeeded": "This market has been succeeded",
"This market has been suspended via a governance vote and can be resumed or terminated by further votes.": "This market has been suspended via a governance vote and can be resumed or terminated by further votes.",
"This market URL is not available any more.": "This market URL is not available any more.",
"This timestamp is user curated metadata and does not drive any on-chain functionality.": "This timestamp is user curated metadata and does not drive any on-chain functionality.",
"Tier": "Tier",
"Tier {{tier}}": "Tier {{tier}}",
"Tier {{userTier}}": "Tier {{userTier}}",
"to": "to",
"To protect the network from spam, you must have at least {{requiredFunds}} qUSD of any asset on the network to proceed.": "To protect the network from spam, you must have at least {{requiredFunds}} qUSD of any asset on the network to proceed.",
"Toast location": "Toast location",
"Total discount": "Total discount",
"Total distributed": "Total distributed",
"Total fee after discount": "Total fee after discount",
"Total fee before discount": "Total fee before discount",
"totalCommission": "Total commission (<0>last {{count}} epochs</0>)",
"totalCommission_one": "Total commission (<0>last {{count}} epoch</0>)",
"totalCommission_other": "Total commission (<0>last {{count}} epochs</0>)",
"Trader": "Trader",
"Trades": "Trades",
"Trading": "Trading",
"TradingView": "TradingView",
"Trading has been terminated as a result of the product definition": "Trading has been terminated as a result of the product definition",
"Trading mode": "Trading mode",
"Trading on market {{name}} may stop on {{date}}. There is an open proposal to close this market.": "Trading on market {{name}} may stop on {{date}}. There is an open proposal to close this market.",
"Trading on market {{name}} may stop. There are open proposals to close this market": "Trading on market {{name}} may stop. There are open proposals to close this market",
"Trading on market {{name}} will stop on {{date}}": "Trading on market {{name}} will stop on {{date}}",
"TradingView": "TradingView",
"Transfer": "Transfer",
"Unknown": "Unknown",
"Unknown settlement date": "Unknown settlement date",
"Vega chart": "Vega chart",
"Vega Reward pot": "Vega Reward pot",
"Vega Wallet <0>full featured<0>": "Vega Wallet <0>full featured<0>",
"Vega chart": "Vega chart",
"Vesting": "Vesting",
"Vesting multiplier": "Vesting multiplier",
"Vesting {{assetSymbol}}": "Vesting {{assetSymbol}}",
"Vesting {{vesting}}x": "Vesting {{vesting}}x",
"Vesting multiplier": "Vesting multiplier",
"View as party": "View as party",
"View liquidity provision table": "View liquidity provision table",
"View on Explorer": "View on Explorer",
@@ -318,6 +330,9 @@
"Volume (24h)": "Volume (24h)",
"Volume discount": "Volume discount",
"Volume to next tier": "Volume to next tier",
"volumeLastEpochs": "Volume (last {{count}} epochs)",
"volumeLastEpochs_one": "Volume (last {{count}} epoch)",
"volumeLastEpochs_other": "Volume (last {{count}} epochs)",
"Wallet": "Wallet",
"We're sorry but we don't have an active referral programme currently running. You can propose a new programme <0>here</0>.": "We're sorry but we don't have an active referral programme currently running. You can propose a new programme <0>here</0>.",
"Welcome to Vega trading!": "Welcome to Vega trading!",
@@ -329,51 +344,36 @@
"You need a <0>Vega wallet</0> to start trading in this market.": "You need a <0>Vega wallet</0> to start trading in this market.",
"You need at least {{requiredStake}} VEGA staked to generate a referral code and participate in the referral program.": "You need at least {{requiredStake}} VEGA staked to generate a referral code and participate in the referral program.",
"You will no longer be able to hold a position on this market when it closes in {{duration}}.": "You will no longer be able to hold a position on this market when it closes in {{duration}}.",
"youAreJoiningTheGroup": "You are joining the group shown, but will not have access to benefits until you have completed at least {{count}} epochs.",
"youAreJoiningTheGroup_one": "You are joining the group shown, but will not have access to benefits until you have completed at least {{count}} epoch.",
"youAreJoiningTheGroup_other": "You are joining the group shown, but will not have access to benefits until you have completed at least {{count}} epochs.",
"Your code has been rejected": "Your code has been rejected",
"Your identity is always anonymous on Vega": "Your identity is always anonymous on Vega",
"Your referral code": "Your referral code",
"Your tier": "Your tier",
"checkOutProposalsAndVote": "Check out the terms of the proposals and vote:",
"checkOutProposalsAndVote_one": "Check out the terms of the proposal and vote:",
"checkOutProposalsAndVote_other": "Check out the terms of the proposals and vote:",
"epochStreak_one": "{{count}} epoch streak",
"epochs in referral set": "epochs in referral set",
"epochsStreak": "{{count}} epochs streak",
"minTradingVolume": "Min. trading volume (last {{count}} epochs)",
"minTradingVolume_one": "Min. trading volume (last {{count}} epoch)",
"minTradingVolume_other": "Min. trading volume (last {{count}} epochs)",
"myVolume": "My volume (last {{count}} epochs)",
"myVolume_one": "My volume (last {{count}} epoch)",
"myVolume_other": "My volume (last {{count}} epochs)",
"Number of epochs after distribution to delay vesting of rewards by": "Number of epochs after distribution to delay vesting of rewards by",
"numberEpochs": "{{count}} epochs",
"numberEpochs_one": "{{count}} epoch",
"numberEpochs_other": "{{count}} epochs",
"pastEpochs": "Past {{count}} epochs",
"pastEpochs_one": "Past {{count}} epoch",
"pastEpochs_other": "Past {{count}} epochs",
"qUSD": "qUSD",
"qUSD provides a rough USD equivalent of balances across all assets using the value of \"Quantum\" for that asset": "qUSD provides a rough USD equivalent of balances across all assets using the value of \"Quantum\" for that asset",
"referralStatisticsCommission": "Commission earned in <0>qUSD</0> (<1>last {{count}} epochs</1>)",
"referralStatisticsCommission_one": "Commission earned in <0>qUSD</0> (<1>last {{count}} epoch</1>)",
"referralStatisticsCommission_other": "Commission earned in <0>qUSD</0> (<1>last {{count}} epochs</1>)",
"runningNotionalOverEpochs": "Combined running notional over the {{count}} epochs",
"runningNotionalOverEpochs_one": "Combined running notional over the {{count}} epoch",
"runningNotionalOverEpochs_other": "Combined running notional over the {{count}} epochs",
"to": "to",
"totalCommission": "Total commission (<0>last {{count}} epochs</0>)",
"totalCommission_one": "Total commission (<0>last {{count}} epoch</0>)",
"totalCommission_other": "Total commission (<0>last {{count}} epochs</0>)",
"numberEpochs_one": "{{count}} epoch",
"epochsStreak": "{{count}} epochs streak",
"epochStreak_one": "{{count}} epoch streak",
"Get rewards for providing liquidity. Get rewards for providing liquidity.": "Get rewards for providing liquidity. Get rewards for providing liquidity.",
"Entity scope": "Entity scope",
"Staked VEGA": "Staked VEGA",
"Average position": "Average position",
"Individual": "Individual",
"Rewards funded using the pro-rata strategy should be distributed pro-rata by each entity's reward metric scaled by any active multipliers that party has": " Rewards funded using the pro-rata strategy should be distributed pro-rata by each entity's reward metric scaled by any active multipliers that party has",
"Tier {{tier}}": "Tier {{tier}}",
"Reward {{reward}}x": "Reward {{reward}}x",
"Vesting {{vesting}}x": "Vesting {{vesting}}x",
"Tier {{userTier}}": "Tier {{userTier}}",
"{{reward}}x": "{{reward}}x",
"Reward bonus": "Reward bonus",
"Activity Streak": "Activity Streak",
"userActive": "{{active}} trader: {{count}} epochs so far",
"volumeLastEpochs": "Volume (last {{count}} epochs)",
"volumeLastEpochs_one": "Volume (last {{count}} epoch)",
"volumeLastEpochs_other": "Volume (last {{count}} epochs)",
"youAreJoiningTheGroup": "You are joining the group shown, but will not have access to benefits until you have completed at least {{count}} epochs.",
"youAreJoiningTheGroup_one": "You are joining the group shown, but will not have access to benefits until you have completed at least {{count}} epoch.",
"youAreJoiningTheGroup_other": "You are joining the group shown, but will not have access to benefits until you have completed at least {{count}} epochs.",
"{{amount}} $VEGA staked": "{{amount}} $VEGA staked",
"{{assetSymbol}} Reward pot": "{{assetSymbol}} Reward pot",
"{{checkedAssets}} Assets": "{{checkedAssets}} Assets",
"{{distance}} ago": "{{distance}} ago",
"{{instrumentCode}} liquidity provision": "{{instrumentCode}} liquidity provision",
"{{reward}}x": "{{reward}}x"
"(Tier {{tier}} as of last epoch)": "(Tier {{tier}} as of last epoch)",
"Team": "Team",
"Ends in": "Ends in",
"Assessed over": "Assessed over",
"No rows": "No rows"
}
@@ -83,6 +83,11 @@ describe('LiquidityTable', () => {
h.querySelector('[ref="eText"]')?.textContent?.trim()
);
const expectedHeaders = [
undefined,
undefined,
undefined,
undefined,
undefined,
'Party',
'Status',
'Commitment ()',
+311 -279
View File
@@ -18,7 +18,7 @@ import {
truncateMiddle,
} from '@vegaprotocol/ui-toolkit';
import type {
ColDef,
ColGroupDef,
ITooltipParams,
ValueFormatterParams,
} from 'ag-grid-community';
@@ -60,11 +60,10 @@ const dateValueFormatter = ({ value }: { value?: string | null }) => {
return getDateTimeFormat().format(new Date(value));
};
const defaultColDef: ColDef = {
const defaultColDef = {
resizable: true,
sortable: true,
tooltipComponent: TooltipCellComponent,
minWidth: 120,
};
export interface LiquidityTableProps
@@ -169,300 +168,333 @@ export const LiquidityTable = ({
)}`;
};
const defs: ColDef[] = [
const defs: ColGroupDef[] = [
{
headerName: t('Party'),
field: 'partyId',
headerTooltip: t('The public key of the party making this commitment.'),
cellRenderer: copyCellRenderer,
pinned: 'left',
headerName: '',
children: [
{
headerName: t('Party'),
field: 'partyId',
headerTooltip: t(
'The public key of the party making this commitment.'
),
cellRenderer: copyCellRenderer,
},
],
},
{
headerName: t('Status'),
headerTooltip: t('The current status of this liquidity provision.'),
field: 'status',
cellRenderer: ({
data,
value,
}: VegaICellRendererParams<LiquidityProvisionData, 'status'>) => {
if (!value) return value;
if (
data?.status === LiquidityProvisionStatus.STATUS_PENDING &&
(data?.currentCommitmentAmount || data?.currentFee)
) {
return (
<span className="text-warning">{t('Updating next epoch')}</span>
);
}
return (
<span>
{
LiquidityProvisionStatusMapping[
value as LiquidityProvisionStatus
]
headerName: t('Commitment details'),
marryChildren: true,
children: [
{
headerName: t('Status'),
headerTooltip: t('The current status of this liquidity provision.'),
field: 'status',
cellRenderer: ({
data,
value,
}: VegaICellRendererParams<LiquidityProvisionData, 'status'>) => {
if (!value) return value;
if (
data?.status === LiquidityProvisionStatus.STATUS_PENDING &&
(data?.currentCommitmentAmount || data?.currentFee)
) {
return (
<span className="text-warning">
{t('Updating next epoch')}
</span>
);
}
</span>
);
},
},
{
headerName: t(`Commitment ({{symbol}})`, { symbol }),
field: 'commitmentAmount',
type: 'rightAligned',
headerTooltip: t(
'The amount committed to the market by this liquidity provider.'
),
cellRenderer: ({
data,
value,
}: VegaICellRendererParams<
LiquidityProvisionData,
'commitmentAmount'
>) => {
if (!value) return '-';
const currentCommitmentAmount = data?.currentCommitmentAmount;
const pendingCommitmentAmount = value;
const formattedPendingCommitmentAmount =
addDecimalsFormatNumberQuantum(
pendingCommitmentAmount,
assetDecimalPlaces ?? 0,
quantum ?? 0
);
if (
currentCommitmentAmount &&
currentCommitmentAmount !== pendingCommitmentAmount
) {
const formattedCurrentCommitmentAmount =
addDecimalsFormatNumberQuantum(
currentCommitmentAmount,
assetDecimalPlaces ?? 0,
quantum ?? 0
);
return (
<>
<span>{formattedCurrentCommitmentAmount}</span> (
<span className="text-warning">
{formattedPendingCommitmentAmount}
return (
<span>
{
LiquidityProvisionStatusMapping[
value as LiquidityProvisionStatus
]
}
</span>
)
</>
);
} else {
return formattedPendingCommitmentAmount;
}
},
tooltipValueGetter: assetDecimalsFormatter,
},
{
headerName: t('Obligation'),
field: 'commitmentAmount',
type: 'rightAligned',
headerTooltip: t(
`The liquidity provider's obligation to the market, calculated as the liquidity commitment amount multiplied by the value of the stake_to_ccy_volume network parameter to convert into units of liquidity volume.`
),
cellRenderer: ({
data,
value,
}: VegaICellRendererParams<
LiquidityProvisionData,
'commitmentAmount'
>) => {
if (!value) return '-';
);
},
},
{
headerName: t(`Commitment ({{symbol}})`, { symbol }),
field: 'commitmentAmount',
type: 'rightAligned',
headerTooltip: t(
'The amount committed to the market by this liquidity provider.'
),
cellRenderer: ({
data,
value,
}: VegaICellRendererParams<
LiquidityProvisionData,
'commitmentAmount'
>) => {
if (!value) return '-';
const currentCommitmentAmount = data?.currentCommitmentAmount;
const pendingCommitmentAmount = value;
const currentCommitmentAmount = data?.currentCommitmentAmount
? new BigNumber(data?.currentCommitmentAmount)
const formattedPendingCommitmentAmount =
addDecimalsFormatNumberQuantum(
pendingCommitmentAmount,
assetDecimalPlaces ?? 0,
quantum ?? 0
);
if (
currentCommitmentAmount &&
currentCommitmentAmount !== pendingCommitmentAmount
) {
const formattedCurrentCommitmentAmount =
addDecimalsFormatNumberQuantum(
currentCommitmentAmount,
assetDecimalPlaces ?? 0,
quantum ?? 0
);
return (
<>
<span>{formattedCurrentCommitmentAmount}</span> (
<span className="text-warning">
{formattedPendingCommitmentAmount}
</span>
)
</>
);
} else {
return formattedPendingCommitmentAmount;
}
},
tooltipValueGetter: assetDecimalsFormatter,
},
{
headerName: t('Obligation'),
field: 'commitmentAmount',
type: 'rightAligned',
headerTooltip: t(
`The liquidity provider's obligation to the market, calculated as the liquidity commitment amount multiplied by the value of the stake_to_ccy_volume network parameter to convert into units of liquidity volume.`
),
cellRenderer: ({
data,
value,
}: VegaICellRendererParams<
LiquidityProvisionData,
'commitmentAmount'
>) => {
if (!value) return '-';
const currentCommitmentAmount = data?.currentCommitmentAmount
? new BigNumber(data?.currentCommitmentAmount)
.times(Number(stakeToCcyVolume) || 1)
.toString()
: undefined;
const pendingCommitmentAmount = new BigNumber(value)
.times(Number(stakeToCcyVolume) || 1)
.toString()
: undefined;
.toString();
const pendingCommitmentAmount = new BigNumber(value)
.times(Number(stakeToCcyVolume) || 1)
.toString();
const formattedPendingCommitmentAmount =
addDecimalsFormatNumberQuantum(
pendingCommitmentAmount,
assetDecimalPlaces ?? 0,
quantum ?? 0
);
const formattedPendingCommitmentAmount =
addDecimalsFormatNumberQuantum(
pendingCommitmentAmount,
assetDecimalPlaces ?? 0,
quantum ?? 0
);
if (
currentCommitmentAmount &&
currentCommitmentAmount !== pendingCommitmentAmount
) {
const formattedCurrentCommitmentAmount =
addDecimalsFormatNumberQuantum(
currentCommitmentAmount,
assetDecimalPlaces ?? 0,
quantum ?? 0
);
if (
currentCommitmentAmount &&
currentCommitmentAmount !== pendingCommitmentAmount
) {
const formattedCurrentCommitmentAmount =
addDecimalsFormatNumberQuantum(
currentCommitmentAmount,
assetDecimalPlaces ?? 0,
quantum ?? 0
);
return (
<>
<span>{formattedCurrentCommitmentAmount}</span> (
<span className="text-warning">
{formattedPendingCommitmentAmount}
</span>
)
</>
);
} else {
return formattedPendingCommitmentAmount;
}
},
tooltipValueGetter: stakeToCcyVolumeFormatter,
},
{
headerName: t('Fee'),
headerTooltip: t(
'The fee percentage (per trade) proposed by each liquidity provider.'
),
field: 'fee',
type: 'rightAligned',
cellRenderer: ({
data,
value,
}: VegaICellRendererParams<LiquidityProvisionData, 'fee'>) => {
if (!value) return '-';
const formattedPendingFee =
formatNumberPercentage(new BigNumber(value).times(100), 2) || '-';
if (data?.currentFee && data?.currentFee !== value) {
const formattedCurrentFee = formatNumberPercentage(
new BigNumber(data.currentFee).times(100),
2
);
return (
<>
<span>{formattedCurrentFee}</span> (
<span className="text-warning">{formattedPendingFee}</span>)
</>
);
}
return formattedPendingFee;
},
},
{
headerName: t('Adjusted stake'),
field: 'feeShare.virtualStake',
type: 'rightAligned',
headerTooltip: t(
'The effective stake of the liquidity provider, adjusted for length of commitment and impact on equity like share.'
),
valueFormatter: assetDecimalsQuantumFormatter,
tooltipValueGetter: assetDecimalsFormatter,
},
{
headerName: t(`Share`),
field: 'feeShare.equityLikeShare',
type: 'rightAligned',
headerTooltip: t(
'The equity-like share of liquidity of the market used to determine allocation of LP fees. Calculated based on share of total liquidity, with a premium added for length of commitment.'
),
valueFormatter: percentageFormatter,
},
{
headerName: t('Live supplied liquidity'),
field: 'balance',
type: 'rightAligned',
headerTooltip: t(
`The amount of liquidity volume supplied by the LP order in order to meet the obligation. If the obligation is already met in full by other limit orders from the same Vega key the LP order is not required and this value will be zero. Also note if the target stake for the market is less than the obligation the full value of the obligation may not be required.`
),
valueFormatter: stakeToCcyVolumeQuantumFormatter,
tooltipValueGetter: stakeToCcyVolumeFormatter,
},
{
headerName: t('Fees accrued this epoch'),
field: 'earmarkedFees',
type: 'rightAligned',
headerTooltip: t(
`The liquidity fees accrued by each provider, which will be distributed at the end of the epoch after applying any penalties.`
),
valueFormatter: assetDecimalsQuantumFormatter,
tooltipValueGetter: feesAccruedTooltip,
cellClassRules: {
'text-warning': ({ data }: { data: LiquidityProvisionData }) => {
if (!data.sla) return false;
return (
new BigNumber(
data.sla.currentEpochFractionOfTimeOnBook
).isLessThan(1) &&
new BigNumber(
data.sla.currentEpochFractionOfTimeOnBook
).isGreaterThan(data.commitmentMinTimeFraction)
);
return (
<>
<span>{formattedCurrentCommitmentAmount}</span> (
<span className="text-warning">
{formattedPendingCommitmentAmount}
</span>
)
</>
);
} else {
return formattedPendingCommitmentAmount;
}
},
tooltipValueGetter: stakeToCcyVolumeFormatter,
},
'text-red-500': ({ data }: { data: LiquidityProvisionData }) => {
if (!data.sla) return false;
return new BigNumber(
data.sla.currentEpochFractionOfTimeOnBook
).isLessThan(data.commitmentMinTimeFraction);
{
headerName: t('Fee'),
headerTooltip: t(
'The fee percentage (per trade) proposed by each liquidity provider.'
),
field: 'fee',
type: 'rightAligned',
cellRenderer: ({
data,
value,
}: VegaICellRendererParams<LiquidityProvisionData, 'fee'>) => {
if (!value) return '-';
const formattedPendingFee =
formatNumberPercentage(new BigNumber(value).times(100), 2) ||
'-';
if (data?.currentFee && data?.currentFee !== value) {
const formattedCurrentFee = formatNumberPercentage(
new BigNumber(data.currentFee).times(100),
2
);
return (
<>
<span>{formattedCurrentFee}</span> (
<span className="text-warning">{formattedPendingFee}</span>)
</>
);
}
return formattedPendingFee;
},
},
},
{
headerName: t('Adjusted stake'),
field: 'feeShare.virtualStake',
type: 'rightAligned',
headerTooltip: t(
'The effective stake of the liquidity provider, adjusted for length of commitment and impact on equity like share.'
),
valueFormatter: assetDecimalsQuantumFormatter,
tooltipValueGetter: assetDecimalsFormatter,
},
{
headerName: t(`Share`),
field: 'feeShare.equityLikeShare',
type: 'rightAligned',
headerTooltip: t(
'The equity-like share of liquidity of the market used to determine allocation of LP fees. Calculated based on share of total liquidity, with a premium added for length of commitment.'
),
valueFormatter: percentageFormatter,
},
],
},
{
headerName: t(`Live time on book`),
field: 'sla.currentEpochFractionOfTimeOnBook',
type: 'rightAligned',
headerTooltip: t('Current epoch fraction of time on the book.'),
valueFormatter: percentageFormatter,
headerName: t('Live liquidity data'),
marryChildren: true,
children: [
{
headerName: t('Live supplied liquidity'),
field: 'balance',
type: 'rightAligned',
headerTooltip: t(
`The amount of liquidity volume supplied by the LP order in order to meet the obligation. If the obligation is already met in full by other limit orders from the same Vega key the LP order is not required and this value will be zero. Also note if the target stake for the market is less than the obligation the full value of the obligation may not be required.`
),
valueFormatter: stakeToCcyVolumeQuantumFormatter,
tooltipValueGetter: stakeToCcyVolumeFormatter,
},
{
headerName: t('Fees accrued this epoch'),
field: 'earmarkedFees',
type: 'rightAligned',
headerTooltip: t(
`The liquidity fees accrued by each provider, which will be distributed at the end of the epoch after applying any penalties.`
),
valueFormatter: assetDecimalsQuantumFormatter,
tooltipValueGetter: feesAccruedTooltip,
cellClassRules: {
'text-warning': ({ data }: { data: LiquidityProvisionData }) => {
if (!data.sla) return false;
return (
new BigNumber(
data.sla.currentEpochFractionOfTimeOnBook
).isLessThan(1) &&
new BigNumber(
data.sla.currentEpochFractionOfTimeOnBook
).isGreaterThan(data.commitmentMinTimeFraction)
);
},
'text-red-500': ({ data }: { data: LiquidityProvisionData }) => {
if (!data.sla) return false;
return new BigNumber(
data.sla.currentEpochFractionOfTimeOnBook
).isLessThan(data.commitmentMinTimeFraction);
},
},
},
{
headerName: t(`Live time on book`),
field: 'sla.currentEpochFractionOfTimeOnBook',
type: 'rightAligned',
headerTooltip: t('Current epoch fraction of time on the book.'),
valueFormatter: percentageFormatter,
},
{
headerName: t('Live liquidity score (%)'),
field: 'feeShare.averageScore',
type: 'rightAligned',
headerTooltip: t(
'The liquidity score of the provider, used to determine allocation of fees to the best performing LPs. Posting volume closer to the mid on both sides of the book will improve this score.'
),
valueFormatter: percentageFormatter,
},
],
},
{
headerName: t('Live liquidity score (%)'),
field: 'feeShare.averageScore',
type: 'rightAligned',
headerTooltip: t(
'The liquidity score of the provider, used to determine allocation of fees to the best performing LPs. Posting volume closer to the mid on both sides of the book will improve this score.'
),
valueFormatter: percentageFormatter,
headerName: t('Last epoch SLA details'),
marryChildren: true,
children: [
{
headerName: t(`Last time on book`),
field: 'sla.lastEpochFractionOfTimeOnBook',
type: 'rightAligned',
headerTooltip: t(
'Fraction of time on the book at the end of the last epoch.'
),
valueFormatter: percentageFormatter,
},
{
headerName: t(`Last fee penalty`),
field: 'sla.lastEpochFeePenalty',
type: 'rightAligned',
headerTooltip: t(
'Penalty applied on the fees a liquidity provider collected in the last epoch. This percentage increased if an LP did not meet the SLA, or if they met it but other LPs outscored them in the previous epoch.'
),
valueFormatter: percentageFormatter,
},
{
headerName: t(`Last bond penalty`),
field: 'sla.lastEpochBondPenalty',
type: 'rightAligned',
headerTooltip: t(
`Penalty applied on a provider's bond penalty at the end of the last epoch. This percentage increased if an LP: had a shortfall and their bond needed to be used to cover it, did not meet the SLA, and/or reduced their commitment to the point that the market was below its target stake.`
),
valueFormatter: percentageFormatter,
},
],
},
{
headerName: t(`Last time on book`),
field: 'sla.lastEpochFractionOfTimeOnBook',
type: 'rightAligned',
headerTooltip: t(
'Fraction of time on the book at the end of the last epoch.'
),
valueFormatter: percentageFormatter,
},
{
headerName: t(`Last fee penalty`),
field: 'sla.lastEpochFeePenalty',
type: 'rightAligned',
headerTooltip: t(
'Penalty applied on the fees a liquidity provider collected in the last epoch. This percentage increased if an LP did not meet the SLA, or if they met it but other LPs outscored them in the previous epoch.'
),
valueFormatter: percentageFormatter,
},
{
headerName: t(`Last bond penalty`),
field: 'sla.lastEpochBondPenalty',
type: 'rightAligned',
headerTooltip: t(
`Penalty applied on a provider's bond penalty at the end of the last epoch. This percentage increased if an LP: had a shortfall and their bond needed to be used to cover it, did not meet the SLA, and/or reduced their commitment to the point that the market was below its target stake.`
),
valueFormatter: percentageFormatter,
},
{
headerName: t('Created'),
headerTooltip: t(
'The date and time this liquidity provision was created.'
),
field: 'createdAt',
type: 'rightAligned',
valueFormatter: dateValueFormatter,
},
{
headerName: t('Updated'),
headerTooltip: t(
'The date and time this liquidity provision was last updated.'
),
field: 'updatedAt',
type: 'rightAligned',
valueFormatter: dateValueFormatter,
headerName: '',
marryChildren: true,
children: [
{
headerName: t('Created'),
headerTooltip: t(
'The date and time this liquidity provision was created.'
),
field: 'createdAt',
type: 'rightAligned',
valueFormatter: dateValueFormatter,
},
{
headerName: t('Updated'),
headerTooltip: t(
'The date and time this liquidity provision was last updated.'
),
field: 'updatedAt',
type: 'rightAligned',
valueFormatter: dateValueFormatter,
},
],
},
];
return defs;
@@ -124,11 +124,27 @@ describe('getChange', () => {
});
describe('useCheckLiquidityStatus', () => {
it('should return amber if liquidity is enough', () => {
const { result } = renderHook(() =>
useCheckLiquidityStatus({
suppliedStake: '60',
targetStake: '100',
triggeringRatio: '0.5',
})
);
expect(result.current).toEqual({
status: Intent.Warning,
percentage: new BigNumber('60'),
});
});
it('should return red if liquidity is not enough', () => {
const { result } = renderHook(() =>
useCheckLiquidityStatus({
suppliedStake: '60',
targetStake: '100',
triggeringRatio: '1',
})
);
@@ -143,6 +159,7 @@ describe('useCheckLiquidityStatus', () => {
useCheckLiquidityStatus({
suppliedStake: '101',
targetStake: '100',
triggeringRatio: '1',
})
);
@@ -121,9 +121,11 @@ export const getTargetStake = (
export const useCheckLiquidityStatus = ({
suppliedStake,
targetStake,
triggeringRatio,
}: {
suppliedStake: string | number;
targetStake: string | number;
triggeringRatio: string | number;
}): {
status: Intent;
percentage: BigNumber;
@@ -140,12 +142,23 @@ export const useCheckLiquidityStatus = ({
percentage,
};
}
if (new BigNumber(suppliedStake).gte(targetStake)) {
if (new BigNumber(suppliedStake).gte(new BigNumber(targetStake))) {
// show a green status, e.g. "🟢 $13,666,999 liquidity supplied"
return {
status: Intent.Success,
percentage,
};
// ELSE IF supplied_stake > NETPARAM[market.liquidity.targetstake.triggering.ratio] * target_stake THEN
} else if (
new BigNumber(suppliedStake).gte(
new BigNumber(targetStake).multipliedBy(triggeringRatio)
)
) {
// show an amber status, e.g. "🟠 $3,456,123 liquidity supplied"
return {
status: Intent.Warning,
percentage,
};
// ELSE show a red status, e.g. "🔴 $600,002 liquidity supplied"
} else {
return {
File diff suppressed because one or more lines are too long
@@ -139,6 +139,7 @@ query MarketInfo($marketId: ID!) {
state
tradingMode
linearSlippageFactor
quadraticSlippageFactor
proposal {
id
rationale {
@@ -187,6 +188,7 @@ query MarketInfo($marketId: ID!) {
long
}
liquidityMonitoringParameters {
triggeringRatio
targetStakeParameters {
timeWindow
scalingFactor
File diff suppressed because one or more lines are too long
@@ -262,7 +262,6 @@ export const MarketInfoAccordion = ({
<PriceMonitoringBoundsInfoPanel
market={market}
triggerIndex={triggerIndex}
key={id}
/>
}
/>
@@ -177,7 +177,7 @@ export const InsurancePoolInfoPanel = ({
return (
<MarketInfoTable
data={{
insurancePoolBalance: account.balance,
balance: account.balance,
}}
assetSymbol={asset.symbol}
decimalPlaces={asset.decimals}
@@ -551,6 +551,7 @@ export const MarginScalingFactorsPanel = ({
}: MarketInfoProps) => {
const data = {
linearSlippageFactor: market.linearSlippageFactor,
quadraticSlippageFactor: market.quadraticSlippageFactor,
searchLevel:
market.tradableInstrument.marginCalculator?.scalingFactors.searchLevel,
initialMargin:
@@ -563,6 +564,7 @@ export const MarginScalingFactorsPanel = ({
const parentData = parentMarket
? {
linearSlippageFactor: parentMarket?.linearSlippageFactor,
quadraticSlippageFactor: parentMarket?.quadraticSlippageFactor,
searchLevel:
parentMarket?.tradableInstrument.marginCalculator?.scalingFactors
.searchLevel,
@@ -696,13 +698,17 @@ export const PriceMonitoringBoundsInfoPanel = ({
const quoteUnit = getQuoteName(market);
const trigger =
market.priceMonitoringSettings?.parameters?.triggers?.[triggerIndex];
const bounds = data?.priceMonitoringBounds?.[triggerIndex];
const trigger = bounds?.trigger;
if (!trigger) {
console.error(
`Could not find data for trigger ${triggerIndex} (market id: ${market.id})`
);
return null;
}
return (
<>
<div className="mb-2 grid grid-cols-2 text-sm">
@@ -743,6 +749,7 @@ export const LiquidityMonitoringParametersInfoPanel = ({
parentMarket,
}: MarketInfoProps) => {
const marketData = {
triggeringRatio: market.liquidityMonitoringParameters.triggeringRatio,
timeWindow:
market.liquidityMonitoringParameters.targetStakeParameters.timeWindow,
scalingFactor:
@@ -751,6 +758,8 @@ export const LiquidityMonitoringParametersInfoPanel = ({
const parentMarketData = parentMarket
? {
triggeringRatio:
parentMarket.liquidityMonitoringParameters.triggeringRatio,
timeWindow:
parentMarket.liquidityMonitoringParameters.targetStakeParameters
.timeWindow,
@@ -24,6 +24,7 @@ export const marketInfoQuery = (
},
},
linearSlippageFactor: '0.01',
quadraticSlippageFactor: '0.0001',
marketTimestamps: {
__typename: 'MarketTimestamps',
open: '2022-11-15T02:15:24.543614154Z',
@@ -94,6 +95,7 @@ export const marketInfoQuery = (
long: '0.008508132993273576',
},
liquidityMonitoringParameters: {
triggeringRatio: '0.7',
targetStakeParameters: {
timeWindow: 3600,
scalingFactor: 10,
@@ -101,6 +101,8 @@ export const useTooltipMapping: () => Record<string, ReactNode> = () => {
auctionExtensionSecs: t(
'Auction extension duration in seconds, should the price breach its theoretical level over the specified horizon at the specified probability level.'
),
triggeringRatio: t('The triggering ratio for entering liquidity auction.'),
timeWindow: t('The length of time over which open interest is measured.'),
scalingFactor: t(
'The scaling between the liquidity demand estimate, based on open interest and target stake.'
+3
View File
@@ -35,6 +35,9 @@ fragment MarketFields on Market {
open
close
}
liquidityMonitoringParameters {
triggeringRatio
}
}
query Markets {
+3
View File
@@ -53,6 +53,9 @@ export const createMarketFragment = (
liquidityFee: '',
},
},
liquidityMonitoringParameters: {
triggeringRatio: '1',
},
tradableInstrument: {
instrument: {
id: '',
@@ -20,6 +20,9 @@ export const generateOrder = (partialOrder?: PartialDeep<Order>) => {
makerFee: '0.1',
},
},
liquidityMonitoringParameters: {
triggeringRatio: '1',
},
marketTimestamps: {
__typename: 'MarketTimestamps',
close: '',
@@ -21,6 +21,9 @@ export const generateStopOrder = (
__typename: 'Market',
id: 'market-id',
decimalPlaces: 1,
liquidityMonitoringParameters: {
triggeringRatio: '0.7',
},
fees: {
__typename: 'Fees',
factors: {
@@ -39,7 +39,6 @@ const defaultColDef = {
resizable: true,
sortable: true,
filterParams: { buttons: ['reset'] },
minWidth: 100,
};
export type OrderListTableProps = TypedDataAgGrid<Order> & {
@@ -83,9 +82,6 @@ export const OrderListTable = memo<
field: 'market.tradableInstrument.instrument.code',
cellRenderer: 'MarketNameCell',
cellRendererParams: { idPath: 'market.id', onMarketClick },
pinned: true,
width: 130,
resizable: true,
},
{
headerName: t('Filled'),
@@ -31,6 +31,9 @@ describe('OrderViewDialog', () => {
liquidityFee: '0.001',
},
},
liquidityMonitoringParameters: {
triggeringRatio: '1',
},
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
@@ -40,7 +40,6 @@ const defaultColDef = {
resizable: true,
sortable: true,
filterParams: { buttons: ['reset'] },
minWidth: 100,
};
export type StopOrdersTableProps = TypedDataAgGrid<StopOrder> & {
@@ -62,7 +61,6 @@ export const StopOrdersTable = memo(
field: 'market.tradableInstrument.instrument.code',
cellRenderer: 'MarketNameCell',
cellRendererParams: { idPath: 'market.id', onMarketClick },
pinned: true,
},
{
headerName: t('Trigger'),
+343 -326
View File
@@ -71,7 +71,6 @@ const defaultColDef = {
filterParams: { buttons: ['reset'] },
tooltipComponent: TooltipCellComponent,
resizable: true,
minWidth: 110,
};
export const PositionsTable = ({
@@ -84,330 +83,6 @@ export const PositionsTable = ({
...props
}: Props) => {
const t = useT();
const colDefs = useMemo<ColDef[]>(() => {
const columnDefs: (ColDef | null)[] = [
multipleKeys
? {
headerName: t('Vega key'),
field: 'partyId',
valueGetter: ({ data }: VegaValueGetterParams<Position>) =>
(data?.partyId &&
pubKeys &&
pubKeys.find((key) => key.publicKey === data.partyId)?.name) ||
data?.partyId,
}
: null,
{
headerName: t('Market'),
field: 'marketCode',
resizable: true,
onCellClicked: ({ data }) => {
if (!onMarketClick) return;
onMarketClick(data.marketId);
},
pinned: true,
cellRenderer: ({
value,
data,
}: VegaICellRendererParams<Position, 'marketCode'>) => {
if (!data || !value) return '-';
return (
<StackedCell
primary={value}
secondary={
<>
{data?.assetSymbol}
<MarketProductPill productType={data.productType} />
</>
}
/>
);
},
},
{
headerName: t('Size / Notional'),
field: 'openVolume',
type: 'rightAligned',
cellClass: 'font-mono text-right',
cellClassRules: signedNumberCssClassRules,
filter: 'agNumberColumnFilter',
valueGetter: ({ data }: { data: Position }) => {
return data?.openVolume === undefined
? undefined
: toBigNum(data?.openVolume, data.positionDecimalPlaces).toNumber();
},
valueFormatter: ({
data,
}: VegaValueFormatterParams<Position, 'openVolume'>): string => {
if (!data?.openVolume) return '-';
const vol = volumePrefix(
addDecimalsFormatNumber(data.openVolume, data.positionDecimalPlaces)
);
return vol;
},
cellRenderer: OpenVolumeCell,
},
{
headerName: t('Entry / Mark'),
field: 'markPrice',
type: 'rightAligned',
cellClass: 'font-mono text-right',
cellRenderer: ({
data,
}: VegaICellRendererParams<Position, 'markPrice'>) => {
if (
!data?.averageEntryPrice ||
!data?.markPrice ||
!data?.marketDecimalPlaces
) {
return <>-</>;
}
if (
data.marketTradingMode ===
MarketTradingMode.TRADING_MODE_OPENING_AUCTION
) {
return <>-</>;
}
const entry = addDecimalsFormatNumber(
data.averageEntryPrice,
data.marketDecimalPlaces
);
const mark = addDecimalsFormatNumber(
data.markPrice,
data.marketDecimalPlaces
);
return (
<StackedCell
primary={entry}
secondary={
<PriceFlashCell
value={Number(data.markPrice)}
valueFormatted={mark}
/>
}
/>
);
},
filter: 'agNumberColumnFilter',
valueGetter: ({ data }: VegaValueGetterParams<Position>) => {
return !data ||
!data.markPrice ||
data.marketTradingMode ===
MarketTradingMode.TRADING_MODE_OPENING_AUCTION
? undefined
: toBigNum(data.markPrice, data.marketDecimalPlaces).toNumber();
},
},
{
headerName: t('Margin / Leverage'),
colId: 'margin',
type: 'rightAligned',
cellClass: 'font-mono text-right',
filter: 'agNumberColumnFilter',
valueGetter: ({ data }: VegaValueGetterParams<Position>) => {
return !data
? undefined
: toBigNum(
data.marginAccountBalance,
data.assetDecimals
).toNumber();
},
cellRenderer: ({ data }: VegaICellRendererParams<Position>) => {
if (
!data ||
!data.marginAccountBalance ||
!data.marketDecimalPlaces
) {
return null;
}
const margin = addDecimalsFormatNumberQuantum(
data.marginAccountBalance,
data.assetDecimals,
data.quantum
);
const lev = data?.currentLeverage ? data.currentLeverage : 1;
const leverage = formatNumber(Math.max(1, lev), 1);
return <StackedCell primary={margin} secondary={leverage + 'x'} />;
},
},
{
colId: 'liquidationPrice',
headerName: 'Liquidation',
headerTooltip: t('Worst case liquidation price'),
cellClass: 'font-mono text-right',
type: 'rightAligned',
// Cannot be sortable as data is fetched within the cell
sortable: false,
filter: false,
cellRenderer: ({ data }: VegaICellRendererParams<Position>) => {
if (!data) {
return '-';
}
return (
<div className="flex h-[45px] items-center">
<LiquidationPrice
className="block text-right grow"
marketId={data.marketId}
openVolume={data.openVolume}
collateralAvailable={data.totalBalance}
decimalPlaces={data.marketDecimalPlaces}
/>
</div>
);
},
},
{
headerName: t('Realised PNL'),
field: 'realisedPNL',
type: 'rightAligned',
cellClassRules: signedNumberCssClassRules,
cellClass: 'font-mono text-right',
filter: 'agNumberColumnFilter',
valueGetter: realisedPNLValueGetter,
cellRenderer: (
args: VegaICellRendererParams<Position, 'realisedPNL'>
) => {
const LOSS_SOCIALIZATION_LINK = DocsLinks?.LOSS_SOCIALIZATION ?? '';
if (!args.data || args.value === undefined) {
return null;
}
const losses = parseInt(args.data?.lossSocializationAmount ?? '0');
if (losses <= 0) {
// eslint-disable-next-line react/jsx-no-useless-fragment
return (
<Tooltip description={args.valueFormatted} align="end">
<div>
<PNLCell {...args} />
</div>
</Tooltip>
);
}
const lossesFormatted = addDecimalsFormatNumber(
args.data.lossSocializationAmount,
args.data.assetDecimals
);
return (
<Tooltip
align="end"
description={
<>
<p className="mb-2">
{t('Realised PNL: {{value}}', {
nsSeparator: '*',
replace: { value: args.value },
})}
</p>
<p className="mb-2">
{t('Lifetime loss socialisation deductions: {{losses}}', {
nsSeparator: '*',
replace: {
losses: lossesFormatted,
},
})}
</p>
<p className="mb-2">
{t(
`You received less {{assetSymbol}} in gains that you should have when the market moved in your favour. This occurred because one or more other trader(s) were closed out and did not have enough funds to cover their losses, and the market's insurance pool was empty.`,
{ assetSymbol: args.data.assetSymbol }
)}
</p>
{LOSS_SOCIALIZATION_LINK && (
<ExternalLink href={LOSS_SOCIALIZATION_LINK}>
{t('Read more about loss socialisation')}
</ExternalLink>
)}
</>
}
>
<div>
<PNLCell {...args} />
</div>
</Tooltip>
);
},
valueFormatter: ({
data,
}: VegaValueFormatterParams<Position, 'realisedPNL'>) => {
return !data
? ''
: addDecimalsFormatNumberQuantum(
data.realisedPNL,
data.assetDecimals,
data.quantum
);
},
headerTooltip: t(
'Profit or loss is realised whenever your position is reduced to zero and the margin is released back to your collateral balance. P&L excludes any fees paid.'
),
},
{
headerName: t('Unrealised PNL'),
field: 'unrealisedPNL',
type: 'rightAligned',
cellClassRules: signedNumberCssClassRules,
cellClass: 'font-mono text-right',
filter: 'agNumberColumnFilter',
valueGetter: unrealisedPNLValueGetter,
// @ts-ignore no type overlap but function can be identical
tooltipValueGetter: unrealisedPNLValueGetter,
valueFormatter: ({
data,
}: VegaValueFormatterParams<Position, 'unrealisedPNL'>) =>
!data
? ''
: addDecimalsFormatNumberQuantum(
data.unrealisedPNL,
data.assetDecimals,
data.quantum
),
headerTooltip: t(
'Unrealised profit is the current profit on your open position. Margin is still allocated to your position.'
),
},
onClose && !isReadOnly
? {
...COL_DEFS.actions,
cellRenderer: ({ data }: VegaICellRendererParams<Position>) => {
return (
<div className="flex items-center justify-end gap-2">
{data?.openVolume &&
data?.openVolume !== '0' &&
data.partyId === pubKey ? (
<ButtonLink
data-testid="close-position"
onClick={() => data && onClose(data)}
title={t('Close position')}
>
<VegaIcon name={VegaIconNames.CROSS} size={16} />
</ButtonLink>
) : null}
{data?.assetId && (
<PositionActionsDropdown assetId={data?.assetId} />
)}
</div>
);
},
minWidth: 55,
maxWidth: 55,
}
: null,
];
return columnDefs.filter<ColDef>(
(colDef: ColDef | null): colDef is ColDef => colDef !== null
);
}, [isReadOnly, multipleKeys, onClose, onMarketClick, pubKey, pubKeys, t]);
return (
<AgGrid
overlayNoRowsTemplate={t('No positions')}
@@ -420,7 +95,349 @@ export const PositionsTable = ({
MarketNameCell,
}}
rowHeight={45}
columnDefs={colDefs}
columnDefs={useMemo<ColDef[]>(() => {
const columnDefs: (ColDef | null)[] = [
multipleKeys
? {
headerName: t('Vega key'),
field: 'partyId',
valueGetter: ({ data }: VegaValueGetterParams<Position>) =>
(data?.partyId &&
pubKeys &&
pubKeys.find((key) => key.publicKey === data.partyId)
?.name) ||
data?.partyId,
}
: null,
{
headerName: t('Market'),
field: 'marketCode',
onCellClicked: ({ data }) => {
if (!onMarketClick) return;
onMarketClick(data.marketId);
},
cellRenderer: ({
value,
data,
}: VegaICellRendererParams<Position, 'marketCode'>) => {
if (!data || !value) return '-';
return (
<StackedCell
primary={value}
secondary={
<>
{data?.assetSymbol}
<MarketProductPill productType={data.productType} />
</>
}
/>
);
},
},
{
headerName: t('Size / Notional'),
field: 'openVolume',
type: 'rightAligned',
cellClass: 'font-mono text-right',
cellClassRules: signedNumberCssClassRules,
filter: 'agNumberColumnFilter',
valueGetter: ({ data }: { data: Position }) => {
return data?.openVolume === undefined
? undefined
: toBigNum(
data?.openVolume,
data.positionDecimalPlaces
).toNumber();
},
valueFormatter: ({
data,
}: VegaValueFormatterParams<Position, 'openVolume'>): string => {
if (!data?.openVolume) return '-';
const vol = volumePrefix(
addDecimalsFormatNumber(
data.openVolume,
data.positionDecimalPlaces
)
);
return vol;
},
cellRenderer: OpenVolumeCell,
},
{
headerName: t('Entry / Mark'),
field: 'markPrice',
type: 'rightAligned',
cellClass: 'font-mono text-right',
cellRenderer: ({
data,
}: VegaICellRendererParams<Position, 'markPrice'>) => {
if (
!data?.averageEntryPrice ||
!data?.markPrice ||
!data?.marketDecimalPlaces
) {
return <>-</>;
}
if (
data.marketTradingMode ===
MarketTradingMode.TRADING_MODE_OPENING_AUCTION
) {
return <>-</>;
}
const entry = addDecimalsFormatNumber(
data.averageEntryPrice,
data.marketDecimalPlaces
);
const mark = addDecimalsFormatNumber(
data.markPrice,
data.marketDecimalPlaces
);
return (
<StackedCell
primary={entry}
secondary={
<PriceFlashCell
value={Number(data.markPrice)}
valueFormatted={mark}
/>
}
/>
);
},
filter: 'agNumberColumnFilter',
valueGetter: ({ data }: VegaValueGetterParams<Position>) => {
return !data ||
!data.markPrice ||
data.marketTradingMode ===
MarketTradingMode.TRADING_MODE_OPENING_AUCTION
? undefined
: toBigNum(data.markPrice, data.marketDecimalPlaces).toNumber();
},
},
{
headerName: t('Margin / Leverage'),
colId: 'margin',
type: 'rightAligned',
cellClass: 'font-mono text-right',
filter: 'agNumberColumnFilter',
valueGetter: ({ data }: VegaValueGetterParams<Position>) => {
return !data
? undefined
: toBigNum(
data.marginAccountBalance,
data.assetDecimals
).toNumber();
},
cellRenderer: ({ data }: VegaICellRendererParams<Position>) => {
if (
!data ||
!data.marginAccountBalance ||
!data.marketDecimalPlaces
) {
return null;
}
const margin = addDecimalsFormatNumberQuantum(
data.marginAccountBalance,
data.assetDecimals,
data.quantum
);
const lev = data?.currentLeverage ? data.currentLeverage : 1;
const leverage = formatNumber(Math.max(1, lev), 1);
return (
<StackedCell primary={margin} secondary={leverage + 'x'} />
);
},
},
{
colId: 'liquidationPrice',
headerName: 'Liquidation',
headerTooltip: t('Worst case liquidation price'),
cellClass: 'font-mono text-right',
type: 'rightAligned',
// Cannot be sortable as data is fetched within the cell
sortable: false,
filter: false,
cellRenderer: ({ data }: VegaICellRendererParams<Position>) => {
if (!data) {
return '-';
}
return (
<div className="flex h-[45px] items-center">
<LiquidationPrice
className="block text-right grow"
marketId={data.marketId}
openVolume={data.openVolume}
collateralAvailable={data.totalBalance}
decimalPlaces={data.marketDecimalPlaces}
/>
</div>
);
},
},
{
headerName: t('Realised PNL'),
field: 'realisedPNL',
type: 'rightAligned',
cellClassRules: signedNumberCssClassRules,
cellClass: 'font-mono text-right',
filter: 'agNumberColumnFilter',
valueGetter: realisedPNLValueGetter,
cellRenderer: (
args: VegaICellRendererParams<Position, 'realisedPNL'>
) => {
const LOSS_SOCIALIZATION_LINK =
DocsLinks?.LOSS_SOCIALIZATION ?? '';
if (!args.data || args.value === undefined) {
return null;
}
const losses = parseInt(
args.data?.lossSocializationAmount ?? '0'
);
if (losses <= 0) {
// eslint-disable-next-line react/jsx-no-useless-fragment
return (
<Tooltip description={args.valueFormatted} align="end">
<div>
<PNLCell {...args} />
</div>
</Tooltip>
);
}
const lossesFormatted = addDecimalsFormatNumber(
args.data.lossSocializationAmount,
args.data.assetDecimals
);
return (
<Tooltip
align="end"
description={
<>
<p className="mb-2">
{t('Realised PNL: {{value}}', {
nsSeparator: '*',
replace: { value: args.value },
})}
</p>
<p className="mb-2">
{t(
'Lifetime loss socialisation deductions: {{losses}}',
{
nsSeparator: '*',
replace: {
losses: lossesFormatted,
},
}
)}
</p>
<p className="mb-2">
{t(
`You received less {{assetSymbol}} in gains that you should have when the market moved in your favour. This occurred because one or more other trader(s) were closed out and did not have enough funds to cover their losses, and the market's insurance pool was empty.`,
{ assetSymbol: args.data.assetSymbol }
)}
</p>
{LOSS_SOCIALIZATION_LINK && (
<ExternalLink href={LOSS_SOCIALIZATION_LINK}>
{t('Read more about loss socialisation')}
</ExternalLink>
)}
</>
}
>
<div>
<PNLCell {...args} />
</div>
</Tooltip>
);
},
valueFormatter: ({
data,
}: VegaValueFormatterParams<Position, 'realisedPNL'>) => {
return !data
? ''
: addDecimalsFormatNumberQuantum(
data.realisedPNL,
data.assetDecimals,
data.quantum
);
},
headerTooltip: t(
'Profit or loss is realised whenever your position is reduced to zero and the margin is released back to your collateral balance. P&L excludes any fees paid.'
),
},
{
headerName: t('Unrealised PNL'),
field: 'unrealisedPNL',
type: 'rightAligned',
cellClassRules: signedNumberCssClassRules,
cellClass: 'font-mono text-right',
filter: 'agNumberColumnFilter',
valueGetter: unrealisedPNLValueGetter,
// @ts-ignore no type overlap but function can be identical
tooltipValueGetter: unrealisedPNLValueGetter,
valueFormatter: ({
data,
}: VegaValueFormatterParams<Position, 'unrealisedPNL'>) =>
!data
? ''
: addDecimalsFormatNumberQuantum(
data.unrealisedPNL,
data.assetDecimals,
data.quantum
),
headerTooltip: t(
'Unrealised profit is the current profit on your open position. Margin is still allocated to your position.'
),
},
onClose && !isReadOnly
? {
...COL_DEFS.actions,
cellRenderer: ({ data }: VegaICellRendererParams<Position>) => {
return (
<div className="flex items-center justify-end gap-2">
{data?.openVolume &&
data?.openVolume !== '0' &&
data.partyId === pubKey ? (
<ButtonLink
data-testid="close-position"
onClick={() => data && onClose(data)}
title={t('Close position')}
>
<VegaIcon name={VegaIconNames.CROSS} size={16} />
</ButtonLink>
) : null}
{data?.assetId && (
<PositionActionsDropdown assetId={data?.assetId} />
)}
</div>
);
},
minWidth: 55,
maxWidth: 55,
}
: null,
];
return columnDefs.filter<ColDef>(
(colDef: ColDef | null): colDef is ColDef => colDef !== null
);
}, [
isReadOnly,
multipleKeys,
onClose,
onMarketClick,
pubKey,
pubKeys,
t,
])}
{...props}
/>
);
@@ -29,7 +29,6 @@ export const useColumnDefs = () => {
colId: 'market',
headerName: t('Market'),
field: 'terms.change.instrument.code',
pinned: true,
cellStyle: { lineHeight: '14px' },
cellRenderer: ({
value,

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