Compare commits

..
182 changed files with 1934 additions and 3963 deletions
+2 -1
View File
@@ -64,11 +64,12 @@ jobs:
######
- name: Run Cypress tests
run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome --env.grepTags="${{ inputs.tags }}"
run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome
working-directory: frontend-monorepo
env:
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
CYPRESS_VEGA_WALLET_API_TOKEN: ${{ steps.setup-vega.outputs.token }}
CYPRESS_grepTags: ${{ inputs.tags }}
######
## Upload logs
+5 -7
View File
@@ -8,16 +8,14 @@ jobs:
lint_pr:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Use Node.js 16
id: Node
uses: actions/setup-node@v2
with:
node-version: 16.14.0
- name: Install root dependencies
run: yarn install
- name: Install commitlint cli and config
run: npm install @commitlint/cli @commitlint/config-conventional
- name: Create config
run: echo "module.exports = {extends:['@commitlint/config-conventional']};" > commitlint.config.js
- name: Check PR title
run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js
run: echo "${{ github.event.pull_request.title }}" | npx commitlint
-1
View File
@@ -6,4 +6,3 @@ NX_VEGA_ENV=STAGNET3
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
NX_VEGA_GOVERNANCE_URL=https://stagnet3.token.vega.xyz
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega-dev-releases/releases/
-10
View File
@@ -8,7 +8,6 @@ import { Main } from './components/main';
import { TendermintWebsocketProvider } from './contexts/websocket/tendermint-websocket-provider';
import type { InMemoryCacheConfig } from '@apollo/client';
import { Footer } from './components/footer/footer';
import { AnnouncementBanner, ExternalLink } from '@vegaprotocol/ui-toolkit';
function App() {
const [menuOpen, setMenuOpen] = useState(false);
@@ -41,15 +40,6 @@ function App() {
return (
<TendermintWebsocketProvider>
<NetworkLoader cache={cacheConfig}>
<AnnouncementBanner>
<div className="font-alpha calt uppercase text-center text-lg text-white">
<span className="pr-4">The Mainnet sims are live!</span>
<ExternalLink href="https://fairground.wtf/">
Come help stress test the network
</ExternalLink>
</div>
</AnnouncementBanner>
<div className={layoutClasses}>
<Header menuOpen={menuOpen} setMenuOpen={setMenuOpen} />
<Nav menuOpen={menuOpen} />
@@ -117,7 +117,7 @@ const NestedDataListItem = ({
)}
</h4>
{!hasChildren && (
<code className="text-vega-light-100 mb-2 last:mb-0 dark:text-vega-dark-100 break-all">
<code className="text-vega-light-400 mb-2 last:mb-0 dark:text-vega-dark-400 break-all">
{JSON.stringify(value, null, ' ')}
</code>
)}
@@ -1,4 +1,5 @@
import { t } from '@vegaprotocol/react-helpers';
import React from 'react';
import { StatusMessage } from '../status-message';
interface RenderFetchedProps {
@@ -1,62 +0,0 @@
import { t } from '@vegaprotocol/react-helpers';
import { TxDetailsShared } from './shared/tx-details-shared';
import { TableCell, TableRow, TableWithTbody } from '../../table';
import { BlockLink } from '../../links';
import { StatusMessage } from '../../status-message';
import { ENV } from '../../../config/env';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import type { components } from '../../../../types/explorer';
interface TxDetailsProtocolUpgradeProps {
txData: BlockExplorerTransactionResult | undefined;
pubKey: string | undefined;
blockData: TendermintBlocksResponse | undefined;
}
/**
* Validator event: Protocol Upgrade proposal
*/
export const TxDetailsProtocolUpgrade = ({
txData,
pubKey,
blockData,
}: TxDetailsProtocolUpgradeProps) => {
if (!txData) {
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const upgrade: components['schemas']['v1ProtocolUpgradeProposal'] =
txData.command.protocolUpgradeProposal;
if (!upgrade || !upgrade.upgradeBlockHeight || !upgrade.vegaReleaseTag) {
return (
<StatusMessage>{t('Invalid upgrade proposal format')}</StatusMessage>
);
}
const urlBase = ENV.dataSources.vegaRepoUrl;
const release = upgrade.vegaReleaseTag;
return (
<TableWithTbody className="mb-8">
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
<TableRow modifier="bordered">
<TableCell>{t('Upgrade at block')}</TableCell>
<TableCell>
<BlockLink height={upgrade.upgradeBlockHeight} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Upgrade to')}</TableCell>
<TableCell>
<ExternalLink href={`${urlBase}${release}`}>
{upgrade.vegaReleaseTag}
</ExternalLink>
</TableCell>
</TableRow>
</TableWithTbody>
);
};
@@ -19,7 +19,6 @@ import { TxDetailsLiquidityAmendment } from './tx-liquidity-amend';
import { TxDetailsLiquidityCancellation } from './tx-liquidity-cancel';
import { TxDetailsDataSubmission } from './tx-data-submission';
import { TxProposalVote } from './tx-proposal-vote';
import { TxDetailsProtocolUpgrade } from './tx-details-protocol-upgrade';
interface TxDetailsWrapperProps {
txData: BlockExplorerTransactionResult | undefined;
@@ -71,8 +70,6 @@ function getTransactionComponent(txData?: BlockExplorerTransactionResult) {
return TxDetailsOrder;
case 'Submit Oracle Data':
return TxDetailsDataSubmission;
case 'Protocol Upgrade':
return TxDetailsProtocolUpgrade;
case 'Cancel Order':
return TxDetailsOrderCancel;
case 'Amend Order':
@@ -1,11 +1,10 @@
import { t } from '@vegaprotocol/react-helpers';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
import { MarketLink } from '../../links';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import { TxDetailsShared } from './shared/tx-details-shared';
import { TableCell, TableRow, TableWithTbody } from '../../table';
import type { components } from '../../../../types/explorer';
import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint-blocks-response';
import type { BlockExplorerTransactionResult } from '../../../routes/types/block-explorer-response';
export type LiquidityCancellation =
components['schemas']['v1LiquidityProvisionCancellation'];
@@ -63,7 +63,7 @@ export const TxDataView = ({ txData, blockData }: TxDataViewProps) => {
<Select
placeholder="View as..."
onChange={(v) => setShowTxData(v.target.value as ShowTxDataType)}
value={showTxData}
value={'JSON'}
>
<option value={'JSON'}>JSON</option>
<option value={'base64'}>Base64</option>
-2
View File
@@ -10,7 +10,6 @@ const truthy = ['1', 'true'];
export const ENV = {
// Data sources
// Environment
env: windowOrDefault('NX_VEGA_ENV'),
dsn: windowOrDefault('NX_EXPLORER_SENTRY_DSN'),
dataSources: {
blockExplorerUrl: windowOrDefault('NX_BLOCK_EXPLORER'),
@@ -18,7 +17,6 @@ export const ENV = {
tendermintWebsocketUrl: windowOrDefault('NX_TENDERMINT_WEBSOCKET_URL'),
ethExplorerUrl: windowOrDefault('NX_ETHERSCAN_URL'),
governanceUrl: windowOrDefault('NX_VEGA_GOVERNANCE_URL'),
vegaRepoUrl: windowOrDefault('NX_VEGA_REPO_URL'),
},
flags: {
assets: truthy.includes(windowOrDefault('NX_EXPLORER_ASSETS')),
+4 -5
View File
@@ -5,7 +5,6 @@ import type {
BlockExplorerTransactions,
} from '../routes/types/block-explorer-response';
import { DATA_SOURCES } from '../config';
import isNumber from 'lodash/isNumber';
export interface TxsStateProps {
txsData: BlockExplorerTransactionResult[];
@@ -55,15 +54,15 @@ export const useTxsData = ({ limit, filters }: IUseTxsData) => {
} = useFetch<BlockExplorerTransactions>(url, {}, false);
useEffect(() => {
if (data && isNumber(data?.transactions?.length)) {
if (data?.transactions?.length) {
setTxsState((prev) => ({
txsData: [...prev.txsData, ...data.transactions],
hasMoreTxs: data.transactions.length > 0,
hasMoreTxs: true,
lastCursor:
data.transactions[data.transactions.length - 1]?.cursor || '',
data.transactions[data.transactions.length - 1].cursor || '',
}));
}
}, [setTxsState, data]);
}, [setTxsState, data?.transactions]);
const loadTxs = useCallback(() => {
return refetch({
@@ -10,7 +10,7 @@ export type ExplorerOracleDataConnectionFragment = { __typename?: 'OracleSpec',
export type ExplorerOracleSpecsQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type ExplorerOracleSpecsQuery = { __typename?: 'Query', oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } } } } | null> | null } | null };
export type ExplorerOracleSpecsQuery = { __typename?: 'Query', oracleSpecsConnection?: { __typename?: 'OracleSpecsConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleSpecEdge', node: { __typename?: 'OracleSpec', dataSourceSpec: { __typename?: 'ExternalDataSourceSpec', spec: { __typename?: 'DataSourceSpec', id: string, createdAt: any, updatedAt?: any | null, status: Types.DataSourceSpecStatus, data: { __typename?: 'DataSourceDefinition', sourceType: { __typename?: 'DataSourceDefinitionExternal', sourceType: { __typename?: 'DataSourceSpecConfiguration', signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, filters?: Array<{ __typename?: 'Filter', key: { __typename?: 'PropertyKey', name?: string | null, type: Types.PropertyKeyType }, conditions?: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator }> | null }> | null } } | { __typename?: 'DataSourceDefinitionInternal', sourceType: { __typename?: 'DataSourceSpecConfigurationTime', conditions: Array<{ __typename?: 'Condition', value?: string | null, operator: Types.ConditionOperator } | null> } } } } }, dataConnection: { __typename?: 'OracleDataConnection', pageInfo: { __typename?: 'PageInfo', hasNextPage: boolean }, edges?: Array<{ __typename?: 'OracleDataEdge', node: { __typename?: 'OracleData', externalData: { __typename?: 'ExternalData', data: { __typename?: 'Data', matchedSpecIds?: Array<string> | null, broadcastAt: any, signers?: Array<{ __typename?: 'Signer', signer: { __typename?: 'ETHAddress', address?: string | null } | { __typename?: 'PubKey', key?: string | null } }> | null, data?: Array<{ __typename?: 'Property', name: string, value: string }> | null } } } } | null> | null } } } | null> | null } | null };
export type ExplorerOracleSpecByIdQueryVariables = Types.Exact<{
id: Types.Scalars['ID'];
@@ -73,7 +73,7 @@ export const ExplorerOracleDataSourceFragmentDoc = gql`
`;
export const ExplorerOracleDataConnectionFragmentDoc = gql`
fragment ExplorerOracleDataConnection on OracleSpec {
dataConnection {
dataConnection(pagination: {first: 1}) {
pageInfo {
hasNextPage
}
@@ -113,11 +113,13 @@ export const ExplorerOracleSpecsDocument = gql`
edges {
node {
...ExplorerOracleDataSource
...ExplorerOracleDataConnection
}
}
}
}
${ExplorerOracleDataSourceFragmentDoc}`;
${ExplorerOracleDataSourceFragmentDoc}
${ExplorerOracleDataConnectionFragmentDoc}`;
/**
* __useExplorerOracleSpecsQuery__
@@ -22,7 +22,7 @@ export type SourceType =
interface OracleDetailsProps {
id: string;
dataSource: ExplorerOracleDataSourceFragment;
dataConnection?: ExplorerOracleDataConnectionFragment;
dataConnection: ExplorerOracleDataConnectionFragment;
// Defaults to false. Hides the count of 'broadcasts' this oracle has seen
showBroadcasts?: boolean;
}
@@ -41,8 +41,7 @@ export const OracleDetails = ({
showBroadcasts = false,
}: OracleDetailsProps) => {
const sourceType = dataSource.dataSourceSpec.spec.data.sourceType;
const reportsCount: number =
dataConnection?.dataConnection.edges?.length || 0;
const reportsCount: number = dataConnection.dataConnection.edges?.length || 0;
return (
<div>
@@ -64,9 +63,7 @@ export const OracleDetails = ({
</TableRow>
</TableWithTbody>
<OracleFilter data={dataSource} />
{showBroadcasts && dataConnection ? (
<OracleData data={dataConnection} />
) : null}
{showBroadcasts ? <OracleData data={dataConnection} /> : null}
</div>
);
};
@@ -28,7 +28,7 @@ const Oracles = () => {
<OracleDetails
id={id}
dataSource={o?.node}
showBroadcasts={false}
dataConnection={o?.node}
/>
<details>
<summary className="pointer">JSON</summary>
@@ -38,7 +38,7 @@ const Tx = () => {
to={`/${Routes.TX}`}
>
<Icon
className="text-vega-light-150 dark:text-vega-light-150"
className="text-vega-light-300 dark:text-vega-light-300"
name={IconNames.CHEVRON_LEFT}
/>
All Transactions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

File diff suppressed because it is too large Load Diff
-12
View File
@@ -16,16 +16,4 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
#Test configuration variables
CYPRESS_FAIRGROUND=false
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
CYPRESS_ETHEREUM_PROVIDER_URL=http://localhost:8545
CYPRESS_EXPLORER_URL=https://explorer.fairground.wtf
CYPRESS_FAUCET_URL=http://localhost:1790/api/v1/mint
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY=02ecea…342f65
CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY2=7f9cf0…c25535
CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf
CYPRESS_VEGA_URL=http://localhost:3028/query
CYPRESS_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_WALLET_API_TOKEN=
@@ -2,59 +2,56 @@
"changes": {
"decimalPlaces": "5",
"positionDecimalPlaces": "5",
"lpPriceRange": "10",
"instrument": {
"name": "Token test market",
"code": "Token.24h",
"name": "Oranges Daily",
"code": "ORANGES.24h",
"future": {
"settlementAsset": "fBTC",
"quoteName": "fBTC",
"settlementAsset": "8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4",
"quoteName": "tEuro",
"settlementDataDecimals": 5,
"dataSourceSpecForSettlementData": {
"external": {
"oracle": {
"signers": [
{
"pubKey": {
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
}
}
],
"filters": [
{
"key": {
"name": "prices.ETH.value",
"type": "TYPE_INTEGER",
"numberDecimalPlaces": "0"
},
"conditions": [
{
"operator": "OPERATOR_GREATER_THAN",
"value": "0"
}
]
}
]
}
}
},
"dataSourceSpecForTradingTermination": {
"signers": [
{
"pubKey": {
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
"signer": {
"__typename": "ETHAddress",
"address": "0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC"
}
}
],
"filters": [
{
"key": {
"name": "trading.terminated.ETH5",
"type": "TYPE_BOOLEAN"
"name": "prices.BTC.value",
"type": "TYPE_INTEGER"
},
"conditions": [
{
"operator": "OPERATOR_EQUALS",
"value": "true"
"operator": "OPERATOR_GREATER_THAN",
"value": "0"
}
]
}
]
},
"dataSourceSpecForTradingTermination": {
"signers": [
{
"signer": {
"__typename": "ETHAddress",
"address": "0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC"
}
}
],
"filters": [
{
"key": {
"name": "vegaprotocol.builtin.timestamp",
"type": "TYPE_TIMESTAMP"
},
"conditions": [
{
"operator": "OPERATOR_GREATER_THAN_OR_EQUAL",
"value": "1648684800000000000"
}
]
}
@@ -62,7 +59,7 @@
},
"dataSourceSpecBinding": {
"settlementPriceProperty": "prices.BTC.value",
"tradingTerminationProperty": "trading.terminated.ETH5"
"tradingTerminationProperty": "vegaprotocol.builtin.timestamp"
}
}
},
@@ -1,78 +1,83 @@
{
"instrument": {
"code": "TEST.24h",
"future": {
"quoteName": "fUSDC",
"settlementDataDecimals": 5,
"dataSourceSpecForSettlementData": {
"signers": [
{
"pubKey": {
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
}
}
],
"filters": [
{
"key": {
"name": "prices.ETH.value",
"type": "TYPE_INTEGER"
},
"conditions": [
{
"operator": "OPERATOR_GREATER_THAN",
"value": "0"
"marketId": "315a8e48db0a292c92b617264728048c82c20efc922c75fd292fc54e5c727c81",
"changes": {
"instrument": {
"code": "ORANGES.24h",
"future": {
"quoteName": "tEuro",
"settlementDataDecimals": 5,
"dataSourceSpecForSettlementData": {
"signers": [
{
"signer": {
"__typename": "ETHAddress",
"address": "0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC"
}
]
}
]
},
"dataSourceSpecForTradingTermination": {
"signers": [
{
"pubKey": {
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
}
}
],
"filters": [
{
"key": {
"name": "trading.terminated.ETH5",
"type": "TYPE_BOOLEAN"
},
"conditions": [
{
"operator": "OPERATOR_GREATER_THAN_OR_EQUAL",
"value": "1648684800000000000"
],
"filters": [
{
"key": {
"name": "prices.BTC.value",
"type": "TYPE_INTEGER"
},
"conditions": [
{
"operator": "OPERATOR_GREATER_THAN",
"value": "0"
}
]
}
]
},
"dataSourceSpecForTradingTermination": {
"signers": [
{
"signer": {
"__typename": "ETHAddress",
"address": "0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC"
}
]
}
]
},
"dataSourceSpecBinding": {
"settlementPriceProperty": "prices.ETH.value",
"tradingTerminationProperty": "trading.terminated.ETH5"
}
],
"filters": [
{
"key": {
"name": "vegaprotocol.builtin.timestamp",
"type": "TYPE_TIMESTAMP"
},
"conditions": [
{
"operator": "OPERATOR_GREATER_THAN_OR_EQUAL",
"value": "1648684800000000000"
}
]
}
]
},
"dataSourceSpecBinding": {
"settlementPriceProperty": "prices.BTC.value",
"tradingTerminationProperty": "vegaprotocol.builtin.timestamp"
}
}
}
},
"metadata": ["sector:energy", "sector:food", "source:docs.vega.xyz"],
"priceMonitoringParameters": {
"triggers": [
{
"horizon": "43200",
"probability": "0.9999999",
"auctionExtension": "600"
},
"metadata": ["sector:energy", "sector:food", "source:docs.vega.xyz"],
"priceMonitoringParameters": {
"triggers": [
{
"horizon": "43200",
"probability": "0.9999999",
"auctionExtension": "600"
}
]
},
"logNormal": {
"tau": 0.0001140771161,
"riskAversionParameter": 0.001,
"params": {
"mu": 0,
"r": 0.016,
"sigma": 0.3
}
]
},
"logNormal": {
"tau": 0.0001140771161,
"riskAversionParameter": 0.001,
"params": {
"mu": 0,
"r": 0.016,
"sigma": 0.3
}
}
}
@@ -1 +1 @@
0123245
123
@@ -11,7 +11,6 @@ const newProposalSubmitButton = '[data-testid="proposal-submit"]';
const dialogCloseButton = '[data-testid="dialog-close"]';
const viewProposalButton = '[data-testid="view-proposal-btn"]';
const openProposals = '[data-testid="open-proposals"]';
const closedProposals = '[data-testid="closed-proposals"]';
const proposalVoteProgressForPercentage =
'[data-testid="vote-progress-indicator-percentage-for"]';
const proposalVoteProgressAgainstPercentage =
@@ -23,9 +22,7 @@ const proposalVoteProgressAgainstTokens =
const changeVoteButton = '[data-testid="change-vote-button"]';
const proposalDetailsTitle = '[data-testid="proposal-title"]';
const proposalDetailsDescription = '[data-testid="proposal-description"]';
const proposalStatus = '[data-testid="proposal-status"]';
const rawProposalData = '[data-testid="proposal-data"]';
const votesTable = '[data-testid="votes-table"]';
const minVoteButton = '[data-testid="min-vote"]';
const maxVoteButton = '[data-testid="max-vote"]';
const voteButtons = '[data-testid="vote-buttons"]';
@@ -40,10 +37,6 @@ const txTimeout = Cypress.env('txTimeout');
const epochTimeout = Cypress.env('epochTimeout');
const proposalTimeout = { timeout: 14000 };
const minCloseDays = 2;
const maxCloseDays = 3;
const requiredParticipation = 0.001;
const governanceProposalType = {
NETWORK_PARAMETER: 'Network parameter',
NEW_MARKET: 'New market',
@@ -72,6 +65,21 @@ context(
network_parameters['governance.proposal.freeform.requiredMajority'] *
100
).as('requiredMajority');
cy.wrap(
network_parameters[
'governance.proposal.freeform.requiredParticipation'
] * 100
).as('requiredParticipation');
cy.wrap(
network_parameters['governance.proposal.freeform.minClose'].split(
'h'
)[0] / 24
).as('minCloseDays');
cy.wrap(
network_parameters['governance.proposal.freeform.maxClose'].split(
'h'
)[0] / 24
).as('maxCloseDays');
cy.wrap(
network_parameters['governance.proposal.freeform.minClose'].split(
'h'
@@ -100,6 +108,21 @@ context(
0.00001,
'Asserting that value is at least 0.00001 for network parameter minVoterBalance'
);
assert.isAtLeast(
parseFloat(this.requiredParticipation),
0.00001,
'Asserting that value is at least 0.00001 for network parameter requiredParticipation'
);
assert.isAtLeast(
parseInt(this.minCloseDays),
1,
'Asserting that value is at least 1 for network parameter minCloseDays'
);
assert.isAtLeast(
parseInt(this.maxCloseDays),
parseInt(this.minCloseDays + 1),
'Asserting that network parameter maxCloseDays is at least 1 day higher than minCloseDays'
);
// workaround for first eth tx hanging
associateTokenStartOfTests();
}
@@ -159,10 +182,10 @@ context(
this.minProposerBalance
);
let proposalDays = [
minCloseDays + 1,
maxCloseDays,
minCloseDays + 3,
minCloseDays + 2,
this.minCloseDays + 1,
this.maxCloseDays,
this.minCloseDays + 3,
this.minCloseDays + 2,
];
for (var index = 0; index < proposalDays.length; index++) {
cy.go_to_make_new_proposal(governanceProposalType.RAW);
@@ -204,7 +227,6 @@ context(
cy.navigate_to('validators');
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('2');
cy.close_staking_dialog();
cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2');
@@ -275,12 +297,10 @@ context(
});
});
// 3001-VOTE-071
it('Newly created freeform proposals list - shows proposal participation - both met and not', function () {
const proposalTitle = generateProposalTitle();
createFreeformProposal(this.minProposerBalance, proposalTitle);
cy.get_submitted_proposal_from_proposal_list(proposalTitle)
// Skipping test due to bug: #1320
it.skip('Newly created freeform proposals list - shows proposal participation - both met and not', function () {
createFreeformProposal(this.minProposerBalance);
cy.get_submitted_proposal_from_proposal_list()
.as('submittedProposal')
.within(() => {
// 3001-VOTE-039
@@ -292,7 +312,7 @@ context(
.invoke('text')
.then((totalSupply) => {
let tokensRequiredToAchieveResult = parseFloat(
(totalSupply.replace(/,/g, '') * requiredParticipation) / 100
(totalSupply.replace(/,/g, '') * this.requiredParticipation) / 100
).toFixed(2);
cy.ensure_specified_unstaked_tokens_are_associated(
tokensRequiredToAchieveResult
@@ -301,17 +321,16 @@ context(
cy.get('@submittedProposal').within(() =>
cy.get(viewProposalButton).click()
);
cy.get_proposal_information_from_table('Token participation met')
cy.get_proposal_information_from_table('Participation met')
.contains('👍')
.should('be.visible');
cy.navigate_to('proposals');
cy.get('@submittedProposal').within(() =>
cy.get(voteStatus).should('have.text', 'Set to pass')
cy.get(voteStatus).should('have.text', 'Participation met')
);
});
});
// 3001-VOTE-055
it('Newly created raw proposal details - shows proposal title and full description', function () {
createRawProposal(this.minProposerBalance);
cy.get('@rawProposal').then((rawProposal) => {
@@ -338,7 +357,6 @@ context(
});
});
// 3001-VOTE-043
it('Newly created freeform proposal details - shows proposed and closing dates', function () {
const closingVoteHrs = '72';
const proposalTitle = generateProposalTitle();
@@ -381,7 +399,6 @@ context(
it('Newly created proposal details - shows default status set to fail', function () {
// 3001-VOTE-037
// 3001-VOTE-040
// 3001-VOTE-067
createRawProposal(this.minProposerBalance);
cy.get('@rawProposal').then((rawProposal) => {
cy.get_submitted_proposal_from_proposal_list(
@@ -396,17 +413,15 @@ context(
.should('be.visible');
// 3001-VOTE-062
// 3001-VOTE-040
// 3001-VOTE-070
cy.get_proposal_information_from_table('Token majority met')
.contains('👎')
.should('be.visible');
// 3001-VOTE-068
cy.get_proposal_information_from_table('Token participation met')
.contains('👎')
.should('be.visible');
});
// 3001-VOTE-080 3001-VOTE-090 3001-VOTE-069 3001-VOTE-072 3001-VOTE-073
// 3001-VOTE-080 3001-VOTE-090
it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () {
createRawProposal(this.minProposerBalance);
cy.get('@rawProposal').then((rawProposal) => {
@@ -431,7 +446,7 @@ context(
.contains(votedDate)
.should('be.visible');
});
cy.get(proposalVoteProgressForPercentage) // 3001-VOTE-072
cy.get(proposalVoteProgressForPercentage)
.contains('100.00%')
.and('be.visible');
cy.get(proposalVoteProgressAgainstPercentage)
@@ -451,10 +466,10 @@ context(
.and('be.visible');
// 3001-VOTE-061
cy.get_proposal_information_from_table('Participation required')
.contains(`${requiredParticipation}%`)
.contains(`${this.requiredParticipation}%`)
.should('be.visible');
// 3001-VOTE-066
cy.get_proposal_information_from_table('Majority Required') // 3001-VOTE-073
cy.get_proposal_information_from_table('Majority Required')
.contains(`${parseFloat(this.requiredMajority).toFixed(2)}%`)
.should('be.visible');
cy.get_proposal_information_from_table('Number of voting parties')
@@ -497,7 +512,7 @@ context(
.invoke('text')
.then((totalSupply) => {
let tokensRequiredToAchieveResult = parseFloat(
(totalSupply.replace(/,/g, '') * requiredParticipation) / 100
(totalSupply.replace(/,/g, '') * this.requiredParticipation) / 100
).toFixed(2);
cy.ensure_specified_unstaked_tokens_are_associated(
tokensRequiredToAchieveResult
@@ -521,11 +536,6 @@ context(
cy.get(proposalVoteProgressAgainstTokens)
.contains('0.00')
.and('be.visible');
cy.get_proposal_information_from_table(
'Total tokens voted percentage'
)
.should('have.text', '0.00%')
.and('be.visible');
cy.get_proposal_information_from_table('Tokens for proposal')
.should('have.text', tokensRequiredToAchieveResult)
.and('be.visible');
@@ -578,7 +588,6 @@ context(
);
});
// 3001-VOTE-006
it('Creating a proposal - proposal rejected - able to access rejected proposals', function () {
cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance
@@ -640,7 +649,6 @@ context(
cy.get(dialogCloseButton).click();
});
// 3002-PROP-009
it('Unable to create a proposal - when some but not enough tokens are associated', function () {
cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance - 0.000001
@@ -661,7 +669,7 @@ context(
});
it('Unable to create a freeform proposal - when json parent section contains unexpected field', function () {
// 3001-VOTE-038 3002-PROP-013 3002-PROP-014
// 3001-VOTE-038
cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance
);
@@ -687,9 +695,6 @@ context(
'Invalid params: the transaction is malformed'
);
cy.get(dialogCloseButton).click();
cy.get(rawProposalData)
.invoke('val')
.should('contain', "i shouldn't be here");
});
it('Unable to create a freeform proposal - when json terms section contains unexpected field', function () {
@@ -787,107 +792,6 @@ context(
cy.contains('You voted: Against').should('be.visible');
});
// 3001-VOTE-006
it('Able to view enacted proposal', function () {
cy.createMarket();
cy.reload();
cy.wait_for_spinner();
cy.get(closedProposals).within(() => {
cy.get(proposalDetailsTitle).should(
'have.text',
'Add Lorem Ipsum market'
);
cy.get(proposalStatus).should('have.text', 'Enacted ');
cy.get(viewProposalButton).click();
});
cy.getByTestId('proposal-type').should('have.text', 'New market');
cy.get_proposal_information_from_table('State')
.contains('Enacted')
.and('be.visible');
cy.get(votesTable).within(() => {
cy.contains('Vote passed.').should('be.visible');
cy.contains('Voting has ended.').should('be.visible');
});
});
// 3001-VOTE-047
it('Able to enact freeform proposal', function () {
const proposalTitle = 'Add New free form proposal with short enactment';
cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance
);
cy.sendWalletTxFreeFormProposal();
cy.navigate_to('proposals');
cy.reload();
cy.wait_for_spinner();
cy.contains(proposalTitle)
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click());
cy.get_proposal_information_from_table('State')
.contains('Open')
.and('be.visible');
cy.vote_for_proposal('for');
cy.get_proposal_information_from_table('State')
.contains('Enacted', epochTimeout)
.and('be.visible');
});
// 3001-VOTE-046 3001-VOTE-044 3001-VOTE-074 3001-VOTE-074
it('Able to enact proposal by voting', function () {
const proposalTitle = 'Add New proposal with short enactment';
cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance
);
cy.sendWalletTxUpdateNetworkProposal();
cy.navigate_to('proposals');
cy.reload();
cy.wait_for_spinner();
cy.contains(proposalTitle)
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click());
cy.get_proposal_information_from_table('State')
.contains('Open')
.and('be.visible');
cy.vote_for_proposal('for');
cy.get_proposal_information_from_table('State') // 3001-VOTE-047
.contains('Passed', txTimeout)
.and('be.visible');
cy.get_proposal_information_from_table('State')
.contains('Enacted', epochTimeout)
.and('be.visible');
cy.get(votesTable).within(() => {
cy.contains('Vote passed.').should('be.visible');
cy.contains('Voting has ended.').should('be.visible');
});
cy.get(proposalVoteProgressForPercentage)
.contains('100.00%')
.and('be.visible');
});
// 3001-VOTE-048 3001-VOTE-049
it('Able to fail proposal due to lack of participation', function () {
const proposalTitle = 'Add New free form proposal with short enactment';
cy.ensure_specified_unstaked_tokens_are_associated(
this.minProposerBalance
);
cy.sendWalletTxFreeFormProposal();
cy.navigate_to('proposals');
cy.reload();
cy.wait_for_spinner();
cy.contains(proposalTitle)
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click());
cy.get_proposal_information_from_table('State')
.contains('Open')
.and('be.visible');
cy.get_proposal_information_from_table('State') // 3001-VOTE-047
.contains('Declined', txTimeout)
.and('be.visible');
cy.get_proposal_information_from_table('Rejection reason')
.contains('PROPOSAL_ERROR_PARTICIPATION_THRESHOLD_NOT_REACHED')
.and('be.visible');
});
function createRawProposal(proposerBalance) {
if (proposerBalance)
cy.ensure_specified_unstaked_tokens_are_associated(proposerBalance);
@@ -1,7 +1,3 @@
const proposalListItem = '[data-testid="proposals-list-item"]';
const openProposals = '[data-testid="open-proposals"]';
const proposalType = '[data-testid="proposal-type"]';
const proposalDetails = '[data-testid="proposal-details"]';
const newProposalSubmitButton = '[data-testid="proposal-submit"]';
const proposalVoteDeadline = '[data-testid="proposal-vote-deadline"]';
const proposalValidationDeadline =
@@ -213,15 +209,18 @@ context(
);
});
// skipped because no markets available to select in capsule
it.skip('Able to submit update market proposal', function () {
const marketId =
'315a8e48db0a292c92b617264728048c82c20efc922c75fd292fc54e5c727c81';
cy.go_to_make_new_proposal(governanceProposalType.UPDATE_MARKET);
cy.get(newProposalTitle).type('Test update market proposal');
cy.get(newProposalTitle).type('Test update asset proposal');
cy.get(newProposalDescription).type('E2E test for proposals');
cy.get(proposalMarketSelect).select('Test market 1');
cy.get(proposalMarketSelect).select(marketId);
cy.get('[data-testid="update-market-details"]').within(() => {
cy.get('dd').eq(0).should('have.text', 'Test market 1');
cy.get('dd').eq(1).should('have.text', 'TEST.24h');
cy.get('dd').eq(2).should('not.be.empty');
cy.get('dd').eq(0).should('have.text', 'Oranges Daily');
cy.get('dd').eq(1).should('have.text', 'ORANGES.24h');
cy.get('dd').eq(2).should('have.text', marketId);
});
cy.fixture('/proposals/update-market').then((updateMarketProposal) => {
let newUpdateMarketProposal = JSON.stringify(updateMarketProposal);
@@ -282,28 +281,12 @@ context(
});
it('Able to submit update asset proposal using min deadline', function () {
const assetId =
'ebcd94151ae1f0d39a4bde3b21a9c7ae81a80ea4352fb075a92e07608d9c953d';
cy.go_to_make_new_proposal(governanceProposalType.UPDATE_ASSET);
enterUpdateAssetProposalDetails();
cy.get(minVoteDeadline).click();
cy.get(minEnactDeadline).click();
cy.get(newProposalSubmitButton).should('be.visible').click();
cy.wait_for_proposal_submitted();
cy.navigate_to('proposals');
cy.get(openProposals).within(() => {
cy.get(proposalType)
.contains('Update asset')
.parentsUntil(proposalListItem)
.within(() => {
cy.get(proposalDetails).should('contain.text', assetId); // 3001-VOTE-029
cy.getByTestId('view-proposal-btn').click();
});
});
cy.get_proposal_information_from_table('Proposed enactment') // 3001-VOTE-044
.invoke('text')
.should('not.be.empty');
});
it('Able to submit update asset proposal using max deadline', function () {
@@ -37,8 +37,8 @@ context(
function () {
cy.reload();
cy.wait_for_spinner();
cy.ethereum_wallet_connect();
cy.connectVegaWallet();
cy.ethereum_wallet_connect();
cy.vega_wallet_teardown();
cy.navigate_to('validators');
}
@@ -57,16 +57,7 @@ context(
//0005-ETXN-006
//0005-ETXN-003
//0005-ETXN-005
cy.staking_page_associate_tokens('2', { skipConfirmation: true });
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
);
cy.validate_wallet_currency('Associated', '0.00');
cy.validate_wallet_currency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '2.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.staking_page_associate_tokens('2');
// 0005-ETXN-002
cy.get(ethWalletAssociatedBalances, txTimeout)
@@ -107,15 +98,6 @@ context(
cy.staking_page_disassociate_tokens('2');
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
);
cy.validate_wallet_currency('Associated', '2.00');
cy.validate_wallet_currency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '0.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.get(ethWalletAssociatedBalances, txTimeout).should('not.exist');
cy.get(ethWalletTotalAssociatedBalance, txTimeout)
@@ -212,19 +194,7 @@ context(
// 1004-ASSO-024
// 1004-ASSO-023
cy.staking_page_associate_tokens('2', {
type: 'contract',
skipConfirmation: true,
});
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
);
cy.validate_wallet_currency('Associated', '0.00');
cy.validate_wallet_currency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '2.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.staking_page_associate_tokens('2', { type: 'contract' });
cy.get(ethWalletAssociatedBalances, txTimeout)
.contains(vegaWalletPublicKeyShort)
@@ -240,19 +210,7 @@ context(
});
cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', 2.0);
cy.staking_page_disassociate_tokens('1', {
type: 'contract',
skipConfirmation: true,
});
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
);
cy.validate_wallet_currency('Associated', '2.00');
cy.validate_wallet_currency('Pending association', '1.00');
cy.validate_wallet_currency('Total associated after pending', '1.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.staking_page_disassociate_tokens('1', { type: 'contract' });
cy.get(ethWalletAssociatedBalances, txTimeout)
.contains(vegaWalletPublicKeyShort)
@@ -328,35 +286,6 @@ context(
});
// 1004-ASSO-004
it('Pending association outside of app is shown', function () {
cy.vega_wallet_associate('2');
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
);
cy.validate_wallet_currency('Associated', '0.00');
cy.validate_wallet_currency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '2.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.validate_wallet_currency('Associated', '2.00');
});
it('Disassociation outside of app is shown', function () {
cy.staking_page_associate_tokens('2');
cy.validate_wallet_currency('Associated', '2.00');
cy.vega_wallet_disassociate('2');
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
);
cy.validate_wallet_currency('Associated', '2.00');
cy.validate_wallet_currency('Pending association', '2.00');
cy.validate_wallet_currency('Total associated after pending', '0.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.validate_wallet_currency('Associated', '0.00');
});
it('Able to associate tokens to different public key of connected vega wallet', function () {
cy.get(ethWalletAssociateButton).first().click();
cy.get(associateWalletRadioButton).click();
@@ -381,7 +310,6 @@ context(
'vegaWalletPublicKey2Short'
)} can now participate in governance and nominate a validator with your associated $VEGA.`
);
cy.staking_page_disassociate_all_tokens();
});
});
}
@@ -20,10 +20,7 @@ context('View functionality with public key', { tags: '@smoke' }, function () {
it('Able to connect public key via wallet', function () {
verifyConnectedToPubKey();
cy.getByTestId('currency-title', Cypress.env('epochTimeout')).should(
'contain.text',
'USDC (fake)'
);
cy.getByTestId('currency-title').should('contain.text', 'USDC (fake)');
});
it('Able to connect public key using url', function () {
@@ -321,8 +321,6 @@ context(
'200000',
vegaWalletPublicKey
);
cy.reload();
cy.wait_for_spinner();
cy.connectVegaWallet();
cy.ethereum_wallet_connect();
});
@@ -46,6 +46,6 @@ Cypress.Commands.add('verify_page_header', (text) => {
});
Cypress.Commands.add('wait_for_spinner', () => {
cy.get(navigation.pageSpinner, Cypress.env('epochTimeout')).should('exist');
cy.get(navigation.pageSpinner).should('exist');
cy.get(navigation.pageSpinner, { timeout: 20000 }).should('not.exist');
});
-1
View File
@@ -6,7 +6,6 @@ import './governance.functions.js';
import './wallet-eth.functions.js';
import './wallet-teardown.functions.js';
import './wallet-vega.functions.js';
import './proposal.functions.js';
import registerCypressGrep from '@cypress/grep';
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
@@ -1,103 +0,0 @@
import { addSeconds, millisecondsToSeconds } from 'date-fns';
const walletName = Cypress.env('vegaWalletName');
const walletPubKey = Cypress.env('vegaWalletPublicKey');
const walletLocation = Cypress.env('vegaWalletLocation');
const walletPassphraseFile = './src/fixtures/wallet/passphrase';
Cypress.Commands.add('sendWalletTxUpdateNetworkProposal', () => {
const MIN_CLOSE_SEC = 8;
const MIN_ENACT_SEC = 5;
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
const enactmentDate = addSeconds(closingDate, MIN_ENACT_SEC);
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime());
cy.exec(
`vegawallet transaction send --wallet ${walletName} --pubkey ${walletPubKey} -p ${walletPassphraseFile} --network DV '{
"proposalSubmission": {
"rationale": {
"title": "Add New proposal with short enactment",
"description": "E2E enactment test"
},
"terms": {
"updateNetworkParameter": {
"changes": {
"key": "governance.proposal.updateNetParam.minProposerBalance",
"value": "2"
}
},
"closingTimestamp": ${closingTimestamp},
"enactmentTimestamp": ${enactmentTimestamp}
}
}
}' --home ${walletLocation}`,
{ failOnNonZeroExit: false }
)
.its('stderr')
.should('contain', '');
});
Cypress.Commands.add('sendWalletTxUpdateAssetProposal', () => {
const MIN_CLOSE_SEC = 8;
const MIN_ENACT_SEC = 5;
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
const enactmentDate = addSeconds(closingDate, MIN_ENACT_SEC);
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime());
cy.exec(
`vegawallet transaction send --wallet ${walletName} --pubkey ${walletPubKey} -p ${walletPassphraseFile} --network DV '{
"proposalSubmission": {
"rationale": {
"title": "Update Asset set to fail",
"description": "E2E fail test"
},
"terms": {
"updateAsset": {
"assetId": "ebcd94151ae1f0d39a4bde3b21a9c7ae81a80ea4352fb075a92e07608d9c953d",
"changes": {
"quantum": "1",
"erc20": {
"withdrawThreshold": "10",
"lifetimeLimit": "10"
}
}
},
"closingTimestamp": ${closingTimestamp},
"enactmentTimestamp": ${enactmentTimestamp}
}
}
}' --home ${walletLocation}`,
{ failOnNonZeroExit: false }
)
.its('stderr')
.should('contain', '');
});
Cypress.Commands.add('sendWalletTxFreeFormProposal', () => {
const MIN_CLOSE_SEC = 5;
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
cy.exec(
`vegawallet transaction send --wallet ${walletName} --pubkey ${walletPubKey} -p ${walletPassphraseFile} --network DV '{
"proposalSubmission": {
"rationale": {
"title": "Add New free form proposal with short enactment",
"description": "E2E enactment test"
},
"terms": {
"newFreeform": {},
"closingTimestamp": ${closingTimestamp}
}
}
}' --home ${walletLocation}`,
{ failOnNonZeroExit: false }
)
.its('stderr')
.should('contain', '');
});
+10 -31
View File
@@ -58,8 +58,6 @@ Cypress.Commands.add('staking_validator_page_remove_stake', (stake) => {
Cypress.Commands.add('staking_page_associate_tokens', (amount, options) => {
let approve = options && options.approve ? options.approve : false;
let type = options && options.type ? options.type : 'wallet';
let skipConfirmation =
options && options.skipConfirmation ? options.skipConfirmation : false;
cy.highlight(`Associating ${amount} tokens from ${type}`);
cy.get(ethWalletAssociateButton).first().click();
@@ -81,19 +79,16 @@ Cypress.Commands.add('staking_page_associate_tokens', (amount, options) => {
);
}
cy.get(tokenSubmitButton, txTimeout).should('be.enabled').click();
if (!skipConfirmation) {
cy.contains(
`Associating with Vega key. Waiting for ${Cypress.env(
'blockConfirmations'
)} more confirmations..`,
txTimeout
).should('be.visible');
cy.contains(
'can now participate in governance and nominate a validator',
txTimeout
).should('be.visible');
}
cy.contains(
`Associating with Vega key. Waiting for ${Cypress.env(
'blockConfirmations'
)} more confirmations..`,
txTimeout
).should('be.visible');
cy.contains(
'can now participate in governance and nominate a validator',
txTimeout
).should('be.visible');
});
Cypress.Commands.add('staking_page_disassociate_tokens', (amount, options) => {
@@ -221,19 +216,3 @@ Cypress.Commands.add('close_staking_dialog', () => {
cy.get('a').should('have.text', 'Back to Staking').click();
});
});
Cypress.Commands.add(
'validate_wallet_currency',
(currencyTitle, expectedAmount) => {
cy.get("[data-testid='currency-title']")
.contains(currencyTitle)
.parent()
.parent()
.within(() => {
cy.getByTestId('currency-value', txTimeout).should(
'have.text',
expectedAmount
);
});
}
);
@@ -8,6 +8,7 @@ import {
import { ethers, Wallet } from 'ethers';
const vegaWalletContainer = '[data-testid="vega-wallet"]';
const vegaWalletAssociatedBalance = '[data-testid="currency-value"]';
const vegaWalletMnemonic = Cypress.env('vegaWalletMnemonic');
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey');
const vegaTokenContractAddress = Cypress.env('vegaTokenContractAddress');
@@ -42,11 +43,6 @@ before('Vega wallet teardown prep', function () {
});
});
beforeEach(function () {
cy.wrap(this.stakingBridgeContract).as('stakingBridgeContract');
cy.wrap(this.vestingContract).as('vestingContract');
});
Cypress.Commands.add('deposit_asset', function (assetEthAddress) {
cy.get('@signer', { log: false }).then((signer) => {
// Approve asset
@@ -95,18 +91,29 @@ Cypress.Commands.add('faucet_asset', function (assetEthAddress) {
});
Cypress.Commands.add('vega_wallet_teardown', function () {
cy.get('body').then(($body) => {
if ($body.find('[data-testid="eth-wallet-associated-balances"]').length) {
cy.vega_wallet_teardown_vesting(this.vestingContract);
cy.vega_wallet_teardown_staking(this.stakingBridgeContract);
}
});
cy.get(vegaWalletContainer).within(() => {
cy.get(vegaWalletAssociatedBalance)
.first()
.invoke('text')
.then((balance) => {
if (balance != '0.00') {
cy.vega_wallet_teardown_vesting(this.vestingContract);
cy.vega_wallet_teardown_staking(this.stakingBridgeContract);
}
});
cy.get('[data-testid="associated-amount"]', { timeout: 30000 }).should(
'contain.text',
'0.00'
);
});
cy.get(vegaWalletContainer).within(() => {
cy.get(vegaWalletAssociatedBalance, { timeout: transactionTimeout }).should(
'contain',
'0.00',
{ timeout: transactionTimeout }
);
});
});
Cypress.Commands.add(
@@ -169,22 +176,6 @@ Cypress.Commands.add('vega_wallet_teardown_vesting', (vestingContract) => {
});
});
Cypress.Commands.add('vega_wallet_associate', (amount) => {
amount = amount + '0'.repeat(18);
cy.highlight('Associating tokens');
cy.get('@stakingBridgeContract').then((stakingBridgeContract) => {
stakingBridgeContract.stake(amount, vegaWalletPubKey);
});
});
Cypress.Commands.add('vega_wallet_disassociate', (amount) => {
amount = amount + '0'.repeat(18);
cy.highlight('Disassociating tokens');
cy.get('@stakingBridgeContract').then((stakingBridgeContract) => {
stakingBridgeContract.remove_stake(amount, vegaWalletPubKey);
});
});
Cypress.Commands.add('wait_for_transaction', (tx) => {
cy.wrap(tx.wait(1).catch(cy.log), { timeout: transactionTimeout });
});
+1 -1
View File
@@ -1,7 +1,7 @@
# App configuration variables
NX_VEGA_ENV=TESTNET
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
NX_VEGA_URL=https://api.n08.testnet.vega.xyz/graphql
NX_VEGA_URL=https://api.n10.testnet.vega.xyz/graphql
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+1 -6
View File
@@ -12,10 +12,5 @@ export default {
moduleNameMapper: {
'^d3-(.*)$': `d3-$1/dist/d3-$1`,
},
collectCoverageFrom: [
'**/*.{ts,tsx}',
'!**/node_modules/**',
'!**/__generated__/**',
'!**/__generated___/**',
],
collectCoverageFrom: ['**/*.{ts,tsx}', '!**/node_modules/**'],
};
+2 -3
View File
@@ -8,7 +8,6 @@ import { AppLoader } from './app-loader';
import { NetworkInfo } from '@vegaprotocol/network-info';
import { BalanceManager } from './components/balance-manager';
import { EthWallet } from './components/eth-wallet';
import { AppLayout } from './components/page-templates/app-layout';
import { TemplateSidebar } from './components/page-templates/template-sidebar';
import { TransactionModal } from './components/transactions-modal';
import { VegaWallet } from './components/vega-wallet';
@@ -89,14 +88,14 @@ const Web3Container = ({
<AppLoader>
<BalanceManager>
<>
<AppLayout>
<div className="app w-full max-w-[1500px] mx-auto grid grid-rows-[min-content_min-content_1fr_min-content] min-h-full border-neutral-700 lg:border-l lg:border-r lg:text-body-large">
<TemplateSidebar sidebar={sideBar}>
<AppRouter />
</TemplateSidebar>
<footer className="p-4 border-t border-neutral-700">
<NetworkInfo />
</footer>
</AppLayout>
</div>
<VegaWalletDialogs />
<TransactionModal />
<WithdrawalDialog />
@@ -2,24 +2,20 @@ import * as Sentry from '@sentry/react';
import { toBigNum } from '@vegaprotocol/react-helpers';
import { useEthereumConfig } from '@vegaprotocol/web3';
import { useWeb3React } from '@web3-react/core';
import { useEffect } from 'react';
import React from 'react';
import { useAppState } from '../../contexts/app-state/app-state-context';
import { useContracts } from '../../contexts/contracts/contracts-context';
import { useGetAssociationBreakdown } from '../../hooks/use-get-association-breakdown';
import { useGetUserTrancheBalances } from '../../hooks/use-get-user-tranche-balances';
import { useBalances } from '../../lib/balances/balances-store';
import type { ReactElement } from 'react';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useListenForStakingEvents as useListenForAssociationEvents } from '../../hooks/use-listen-for-staking-events';
interface BalanceManagerProps {
children: ReactElement;
children: React.ReactElement;
}
export const BalanceManager = ({ children }: BalanceManagerProps) => {
const contracts = useContracts();
const { pubKey } = useVegaWallet();
const { account } = useWeb3React();
const {
appState: { decimals },
@@ -27,20 +23,6 @@ export const BalanceManager = ({ children }: BalanceManagerProps) => {
const { updateBalances: updateStoreBalances } = useBalances();
const { config } = useEthereumConfig();
const numberOfConfirmations = config?.confirmations || 0;
useListenForAssociationEvents(
contracts?.staking.contract,
pubKey,
numberOfConfirmations
);
useListenForAssociationEvents(
contracts?.vesting.contract,
pubKey,
numberOfConfirmations
);
const getUserTrancheBalances = useGetUserTrancheBalances(
account || '',
contracts?.vesting
@@ -52,7 +34,7 @@ export const BalanceManager = ({ children }: BalanceManagerProps) => {
);
// update balances on connect to Ethereum
useEffect(() => {
React.useEffect(() => {
const updateBalances = async () => {
if (!account || !config) return;
try {
@@ -93,13 +75,13 @@ export const BalanceManager = ({ children }: BalanceManagerProps) => {
]);
// This use effect hook is very expensive and is kept separate to prevent expensive reloading of data.
useEffect(() => {
React.useEffect(() => {
if (account) {
getUserTrancheBalances();
}
}, [account, getUserTrancheBalances]);
useEffect(() => {
React.useEffect(() => {
if (account) {
getAssociationBreakdown();
}
@@ -72,8 +72,8 @@ export const LockedProgress = ({
unlocked,
leftLabel,
rightLabel,
leftColor = Colors.vega.pink.DEFAULT,
rightColor = Colors.vega.green.DEFAULT,
leftColor = Colors.vega.pink,
rightColor = Colors.vega.green,
decimals = 2,
}: LockedProgressProps) => {
const lockedPercentage = React.useMemo(() => {
@@ -18,7 +18,7 @@ export const NavDropDown = ({ navbarTheme }: { navbarTheme: NavbarTheme }) => {
<AppNavLink
name={
<NavDropdownMenuTrigger
className="w-auto flex items-center"
className="w-auto text-capMenu"
data-testid="state-trigger"
onClick={() => setOpen(!isOpen)}
>
@@ -38,7 +38,6 @@ export const NavDropDown = ({ navbarTheme }: { navbarTheme: NavbarTheme }) => {
name={t(r.name)}
path={r.path}
navbarTheme={'inherit'}
subNav={true}
end={true}
fullWidth={true}
/>
+7 -12
View File
@@ -13,7 +13,6 @@ interface AppNavLinkProps {
target?: HTMLAttributeAnchorTarget;
end?: boolean;
fullWidth?: boolean;
subNav?: boolean;
}
export const AppNavLink = ({
@@ -24,32 +23,28 @@ export const AppNavLink = ({
testId,
end = false,
fullWidth = false,
subNav = false,
}: AppNavLinkProps) => {
const borderClasses = classNames(
'absolute h-0.5 w-full bottom-[-1px] left-0',
{
'bg-black dark:bg-vega-yellow': navbarTheme !== 'yellow',
'bg-black': navbarTheme === 'yellow',
}
);
const borderClasses = classNames('absolute h-1 w-full bottom-[-1px] left-0', {
'bg-black dark:bg-vega-yellow': navbarTheme !== 'yellow',
'bg-black': navbarTheme === 'yellow',
});
return (
<NavLink
key={path}
data-testid={testId}
to={{ pathname: path }}
className={getNavLinkClassNames(navbarTheme, fullWidth, subNav)}
className={getNavLinkClassNames(navbarTheme, fullWidth)}
target={target}
end={end}
>
{({ isActive }) => {
return (
<div className={subNav ? 'inline-block relative pb-1' : undefined}>
<>
{name}
{isActive && (
<span data-testid="link-active" className={borderClasses} />
)}
</div>
</>
);
}}
</NavLink>
+2 -1
View File
@@ -22,8 +22,9 @@ const renderComponent = (initialEntries?: string[]) => {
};
describe('nav', () => {
it('Renders logo with link to home', () => {
it('Renders title and logo with link to home', () => {
renderComponent();
expect(screen.getByText('Governance')).toBeInTheDocument();
expect(screen.getByTestId('logo-link')).toHaveProperty(
'href',
'http://localhost/'
+4 -10
View File
@@ -3,8 +3,7 @@ import { NetworkSwitcher } from '@vegaprotocol/environment';
import { useEffect, useState } from 'react';
import { TOP_LEVEL_ROUTES } from '../../routes/routes';
import { useTranslation } from 'react-i18next';
import logoWhiteText from '../../images/logo-white-text.png';
import logoBlackText from '../../images/logo-black-text.png';
import vegaWhite from '../../images/vega_white.png';
import debounce from 'lodash/debounce';
import { NavDrawer } from './nav-draw';
import { Nav as ToolkitNav } from '@vegaprotocol/ui-toolkit';
@@ -47,19 +46,14 @@ export const Nav = ({ navbarTheme = 'inherit' }: NavbarProps) => {
navbarTheme={navbarTheme}
icon={
<Link to="/" data-testid="logo-link">
<img
alt="Vega"
src={navbarTheme === 'yellow' ? logoBlackText : logoWhiteText}
height={30}
width={250}
/>
<img alt="Vega" src={vegaWhite} height={30} width={30} />
</Link>
}
title={undefined}
title={t('Governance')}
titleContent={<NetworkSwitcher />}
>
{isDesktop ? (
<nav className="flex items-center flex-1 px-4">
<nav className="flex items-center flex-1 px-2">
{TOP_LEVEL_ROUTES.map((r) => (
<AppNavLink
key={r.path}
@@ -1,21 +0,0 @@
import classNames from 'classnames';
import { useVegaWallet } from '@vegaprotocol/wallet';
import type { ReactNode } from 'react';
interface AppLayoutProps {
children: ReactNode;
}
export const AppLayout = ({ children }: AppLayoutProps) => {
const { isReadOnly } = useVegaWallet();
const AppLayoutClasses = classNames(
'app w-full max-w-[1500px] mx-auto grid min-h-full',
'border-neutral-700 lg:border-l lg:border-r',
'lg:text-body-large',
{
'grid-rows-[repeat(2,min-content)_1fr_min-content]': !isReadOnly,
'grid-rows-[repeat(3,min-content)_1fr_min-content]': isReadOnly,
}
);
return <div className={AppLayoutClasses}>{children}</div>;
};
@@ -1,9 +1,5 @@
import { Networks, useEnvironment } from '@vegaprotocol/environment';
import {
ViewingAsBanner,
AnnouncementBanner,
ExternalLink,
} from '@vegaprotocol/ui-toolkit';
import { ViewingAsBanner } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import React from 'react';
@@ -19,18 +15,12 @@ export function TemplateSidebar({ children, sidebar }: TemplateSidebarProps) {
const { isReadOnly, pubKey, disconnect } = useVegaWallet();
return (
<>
<AnnouncementBanner>
<div className="font-alpha calt uppercase text-center text-lg text-white">
<span className="pr-4">The Mainnet sims are live!</span>
<ExternalLink href="https://fairground.wtf/">
Come help stress test the network
</ExternalLink>
</div>
</AnnouncementBanner>
<Nav navbarTheme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'dark'} />
{isReadOnly ? (
<ViewingAsBanner pubKey={pubKey} disconnect={disconnect} />
) : null}
) : (
<div />
)}
<div className="w-full border-b border-neutral-700 lg:grid lg:grid-rows-[1fr] lg:grid-cols-[1fr_450px]">
<main className="col-start-1 p-4">{children}</main>
<aside className="col-start-2 row-start-1 row-span-2 hidden lg:block p-4 bg-banner bg-contain border-l border-neutral-700">
@@ -25,8 +25,6 @@ import { usePollForDelegations } from './hooks';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { Button, ButtonLink } from '@vegaprotocol/ui-toolkit';
import { toBigNum } from '@vegaprotocol/react-helpers';
import { usePendingBalancesStore } from '../../hooks/use-pending-balances-manager';
import { StakingEventType } from '../../hooks/use-get-association-breakdown';
export const VegaWallet = () => {
const { t } = useTranslation();
@@ -121,10 +119,6 @@ interface VegaWalletConnectedProps {
}
const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
const pendingBalances = usePendingBalancesStore(
(state) => state.pendingBalances
);
const { t } = useTranslation();
const {
appDispatch,
@@ -132,27 +126,6 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
} = useAppState();
const { delegations, currentStakeAvailable, delegatedNodes, accounts } =
usePollForDelegations();
const amountRemoved = BigNumber.sum.apply(null, [
new BigNumber(0),
...pendingBalances
.filter(({ event }) => event === StakingEventType.Stake_Removed)
.map(({ args }) => toBigNum(args?.[1].toString(), decimals)),
]);
const amountAdded = BigNumber.sum.apply(null, [
new BigNumber(0),
...pendingBalances
.filter(({ event }) => event === StakingEventType.Stake_Deposited)
.map(({ args }) => toBigNum(args?.[1].toString(), decimals)),
]);
const totalPending = React.useMemo(
() => amountRemoved.plus(amountAdded),
[amountAdded, amountRemoved]
);
const pendingStakeAmount = React.useMemo(
() => currentStakeAvailable.plus(amountAdded).minus(amountRemoved),
[amountAdded, amountRemoved, currentStakeAvailable]
);
const unstaked = React.useMemo(() => {
const totalDelegated = delegations.reduce<BigNumber>(
@@ -188,26 +161,6 @@ const VegaWalletConnected = ({ vegaKeys }: VegaWalletConnectedProps) => {
symbol="VEGA"
balance={currentStakeAvailable}
/>
{totalPending.eq(0) ? null : (
<>
<WalletCardAsset
image={vegaWhite}
decimals={decimals}
name="VEGA"
subheading={t('Pending association')}
symbol="VEGA"
balance={totalPending}
/>
<WalletCardAsset
image={vegaWhite}
decimals={decimals}
name="VEGA"
subheading={t('Total associated after pending')}
symbol="VEGA"
balance={pendingStakeAmount}
/>
</>
)}
<div data-testid="vega-wallet-balance-unstaked">
<WalletCardRow label={t('unstaked')} value={unstaked} />
</div>
+4 -7
View File
@@ -30,12 +30,9 @@ export function useAnimateValue(
) {
elRef.current?.animate(
[
{ backgroundColor: customColors.vega.pink, color: colors.white },
{
backgroundColor: customColors.vega.pink.DEFAULT,
color: colors.white,
},
{
backgroundColor: customColors.vega.pink.DEFAULT,
backgroundColor: customColors.vega.pink,
color: colors.white,
offset: 0.8,
},
@@ -56,11 +53,11 @@ export function useAnimateValue(
elRef.current?.animate(
[
{
backgroundColor: customColors.vega.green.DEFAULT,
backgroundColor: customColors.vega.green,
color: colors.white,
},
{
backgroundColor: customColors.vega.green.DEFAULT,
backgroundColor: customColors.vega.green,
color: colors.white,
offset: 0.8,
},
@@ -11,11 +11,6 @@ import { useAppState } from '../contexts/app-state/app-state-context';
import BigNumber from 'bignumber.js';
import { useBalances } from '../lib/balances/balances-store';
export enum StakingEventType {
Stake_Removed = 'Stake_Removed',
Stake_Deposited = 'Stake_Deposited',
}
export function useGetAssociationBreakdown(
ethAddress: string,
staking: StakingBridge,
@@ -68,8 +63,8 @@ function combineStakeEventsByVegaKey(
const res = events.reduce((obj, e) => {
const vegaKey = e.args?.vega_public_key;
const amount = parseEventAmount(e, decimals);
const isDeposit = e.event === StakingEventType.Stake_Deposited;
const isRemove = e.event === StakingEventType.Stake_Removed;
const isDeposit = e.event === 'Stake_Deposited';
const isRemove = e.event === 'Stake_Removed';
if (!isDeposit && !isRemove) return obj;
@@ -1,102 +0,0 @@
import { useListenForPendingEthEvents } from './use-listen-for-pending-eth-events';
import { renderHook, cleanup, waitFor } from '@testing-library/react';
import type { Contract, EventFilter, Event } from 'ethers';
let contract: Contract;
let filter: EventFilter;
let addPendingTxs: (event: Event[]) => void;
let removePendingTx: (event: Event) => void;
let resetPendingTxs: () => void;
beforeEach(() => {
contract = {
on: jest.fn(),
off: jest.fn(),
queryFilter: jest.fn().mockResolvedValue([]),
} as unknown as Contract;
filter = {} as EventFilter;
addPendingTxs = jest.fn();
removePendingTx = jest.fn();
resetPendingTxs = jest.fn();
});
jest.mock('@web3-react/core', () => ({
useWeb3React: () => ({
provider: {
getBlockNumber: jest.fn().mockResolvedValue(1),
},
}),
}));
describe('useListenForPendingEthEvents', () => {
it('listens for events on contract', async () => {
renderHook(() =>
useListenForPendingEthEvents(
1,
contract,
filter,
addPendingTxs,
removePendingTx,
resetPendingTxs
)
);
expect(contract.on).toHaveBeenCalledWith(filter, expect.any(Function));
cleanup();
expect(contract.off).toHaveBeenCalledWith(filter, expect.any(Function));
});
it('waits for correct number of confirmations before removing tx from pending txs', async () => {
renderHook(() => {
useListenForPendingEthEvents(
2,
contract,
filter,
addPendingTxs,
removePendingTx,
resetPendingTxs
);
});
const listener = (contract.on as jest.Mock).mock.calls[0][1];
const event = {
getTransaction: jest.fn().mockResolvedValue({
wait: jest.fn().mockResolvedValue({}),
}),
} as unknown as Event;
listener(null, null, null, event);
expect(addPendingTxs).toHaveBeenCalledWith([event]);
expect(removePendingTx).not.toHaveBeenCalled();
await waitFor(() => {
expect(removePendingTx).toHaveBeenCalledWith(event);
});
});
it('gets existing transactions', async () => {
const event = {
getTransaction: jest.fn().mockResolvedValue({
wait: jest.fn().mockResolvedValue(null),
}),
} as unknown as Event;
contract.queryFilter = jest.fn().mockResolvedValue([event]);
renderHook(() => {
useListenForPendingEthEvents(
2,
contract,
filter,
addPendingTxs,
removePendingTx,
resetPendingTxs
);
});
await waitFor(() => {
expect(contract.queryFilter).toHaveBeenCalledWith(filter, -1);
expect(addPendingTxs).toHaveBeenCalledWith([event]);
});
});
});
@@ -1,103 +0,0 @@
import { useWeb3React } from '@web3-react/core';
import { useCallback, useEffect } from 'react';
import * as Sentry from '@sentry/react';
import type { Contract, Event, EventFilter } from 'ethers';
export const useListenForPendingEthEvents = (
numberOfConfirmations: number,
contract: Contract | undefined,
filter: EventFilter | null,
addPendingTxs: (event: Event[]) => void,
removePendingTx: (event: Event) => void,
resetPendingTxs: () => void
) => {
const { provider } = useWeb3React();
/**
* Add listener for the ethereum events on the contract passed in for the filter passed in.
* Push the event into the store and wait for the correct number of confirmations before removing it.
*/
useEffect(() => {
if (!contract || !filter) {
return;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const listener = async (...args: any[]) => {
try {
const event = args[3] as Event;
addPendingTxs([event]);
const tx = await event.getTransaction();
await tx.wait(numberOfConfirmations);
removePendingTx(event);
} catch (e) {
Sentry.captureException(`Error listening for pending eth events ${e}`);
}
};
contract.on(filter, listener);
return () => {
contract.off(filter, listener);
};
}, [addPendingTxs, contract, filter, numberOfConfirmations, removePendingTx]);
/**
* Get all transactions that exist on the blockchain but have yet to reach the number of confirmations
*/
const getExistingTransactions = useCallback(async () => {
const blockNumber = (await provider?.getBlockNumber()) || 0;
if (!filter || !contract) {
return [];
}
try {
return await contract.queryFilter(
filter,
blockNumber - numberOfConfirmations
);
} catch (e) {
Sentry.captureException(`Error getting existing transactions ${e}`);
return [];
}
}, [contract, filter, numberOfConfirmations, provider]);
const waitForExistingTransactions = useCallback(
(events: Event[], numberOfConfirmations: number) => {
events.map(async (event) => {
try {
const tx = await event.getTransaction();
await tx.wait(Math.max(numberOfConfirmations, 0));
removePendingTx(event);
} catch (e) {
Sentry.captureException(
`Error waiting for existing transactions ${e}`
);
}
});
},
[removePendingTx]
);
useEffect(() => {
let cancelled = false;
resetPendingTxs();
getExistingTransactions().then((events) => {
if (!cancelled) {
addPendingTxs([...events]);
waitForExistingTransactions([...events], numberOfConfirmations);
}
});
return () => {
cancelled = true;
};
}, [
addPendingTxs,
getExistingTransactions,
numberOfConfirmations,
resetPendingTxs,
waitForExistingTransactions,
]);
};
@@ -1,56 +0,0 @@
import { useMemo } from 'react';
import { usePendingBalancesStore } from './use-pending-balances-manager';
import type { Contract } from 'ethers';
import { useListenForPendingEthEvents } from './use-listen-for-pending-eth-events';
import { prepend0x } from '@vegaprotocol/smart-contracts';
export const useListenForStakingEvents = (
contract: Contract | undefined,
vegaPublicKey: string | null,
numberOfConfirmations: number
) => {
const { addPendingTxs, removePendingTx, resetPendingTxs } =
usePendingBalancesStore((state) => ({
addPendingTxs: state.addPendingTxs,
removePendingTx: state.removePendingTx,
resetPendingTxs: state.resetPendingTxs,
}));
const addFilter = useMemo(
() =>
vegaPublicKey && contract
? contract.filters.Stake_Deposited(null, null, prepend0x(vegaPublicKey))
: null,
[contract, vegaPublicKey]
);
const removeFilter = useMemo(
() =>
vegaPublicKey && contract
? contract.filters.Stake_Removed(null, null, prepend0x(vegaPublicKey))
: null,
[contract, vegaPublicKey]
);
/**
* Listen for all add stake events
*/
useListenForPendingEthEvents(
numberOfConfirmations,
contract,
addFilter,
addPendingTxs,
removePendingTx,
resetPendingTxs
);
/**
* Listen for all remove stake events
*/
useListenForPendingEthEvents(
numberOfConfirmations,
contract,
removeFilter,
addPendingTxs,
removePendingTx,
resetPendingTxs
);
};
@@ -1,76 +0,0 @@
import { act } from '@testing-library/react-hooks';
import { usePendingBalancesStore } from './use-pending-balances-manager';
import type { Event } from 'ethers';
afterEach(() => {
usePendingBalancesStore.setState((state) => ({
...state,
pendingBalances: [],
}));
});
const event1 = { transactionHash: 'tx1' } as Event;
const event2 = { transactionHash: 'tx2' } as Event;
describe('usePendingBalancesStore', () => {
it('should add new events to the pendingBalances state and remove duplicates', () => {
const { addPendingTxs } = usePendingBalancesStore.getState();
const duplicateEvent = { transactionHash: 'tx1' } as Event;
act(() => {
addPendingTxs([event1, duplicateEvent]);
});
expect(usePendingBalancesStore.getState().pendingBalances).toEqual([
event1,
]);
act(() => {
addPendingTxs([event2]);
});
expect(usePendingBalancesStore.getState().pendingBalances).toEqual([
event1,
event2,
]);
});
it('should remove a specific event from the pendingBalances state', () => {
const { addPendingTxs, removePendingTx } =
usePendingBalancesStore.getState();
const eventToRemove = { transactionHash: 'tx1' } as Event;
act(() => {
addPendingTxs([eventToRemove, event2]);
});
expect(usePendingBalancesStore.getState().pendingBalances).toEqual([
eventToRemove,
event2,
]);
act(() => {
removePendingTx(eventToRemove);
});
expect(usePendingBalancesStore.getState().pendingBalances).toEqual([
event2,
]);
});
it('should reset the pendingBalances state', () => {
const { addPendingTxs, resetPendingTxs } =
usePendingBalancesStore.getState();
act(() => {
addPendingTxs([event1, event2]);
});
expect(usePendingBalancesStore.getState().pendingBalances).toEqual([
event1,
event2,
]);
act(() => {
resetPendingTxs();
});
expect(usePendingBalancesStore.getState().pendingBalances).toEqual([]);
});
});
@@ -1,35 +0,0 @@
import type { Event } from 'ethers';
import uniqBy from 'lodash/uniqBy';
import create from 'zustand';
export type PendingTxsStore = {
pendingBalances: Event[];
addPendingTxs: (event: Event[]) => void;
removePendingTx: (event: Event) => void;
resetPendingTxs: () => void;
};
export const usePendingBalancesStore = create<PendingTxsStore>((set, get) => ({
pendingBalances: [],
addPendingTxs: (event: Event[]) => {
set({
pendingBalances: uniqBy(
[...get().pendingBalances, ...event],
'transactionHash'
),
});
},
removePendingTx: (event: Event) => {
set({
pendingBalances: [
...get().pendingBalances.filter(
({ transactionHash }) => transactionHash !== event.transactionHash
),
],
});
},
resetPendingTxs: () => {
set({ pendingBalances: [] });
},
}));
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

@@ -102,7 +102,7 @@ export const VoteDetails = ({
</table>
</section>
)}
<section data-testid="votes-table">
<section>
<SubHeading title={t('tokenVotes')} />
<p>
<span>
@@ -177,7 +177,7 @@ interface TotalPenaltiesRendererProps {
performanceScore: string;
performancePenalty: string;
overstakedAmount: string;
overstakingPenalty: string;
overstakedPenalty: string;
totalPenalties: string;
};
}
@@ -192,10 +192,20 @@ export const TotalPenaltiesRenderer = ({
description={
<>
<div>
{t('performancePenalty')}: {data.performancePenalty}
<span>
{t('performancePenalty')}: {data.performancePenalty}
</span>
<span className="pl-2">
({t('score')} {data.performanceScore})
</span>
</div>
<div>
{t('overstakedPenalty')}: {data.overstakingPenalty}
<span>
{t('overstakedPenalty')}: {data.overstakedPenalty}
</span>
<span className="pl-2">
({t('overstaked')} {data.overstakedAmount})
</span>
</div>
<div>
{t('totalPenalties')}:{' '}
@@ -1,6 +1,6 @@
import { Dialog, Icon, Intent } from '@vegaprotocol/ui-toolkit';
import { useTranslation } from 'react-i18next';
import { Link, useNavigate } from 'react-router-dom';
import { Link } from 'react-router-dom';
import Routes from '../../routes';
import type { StakeAction } from './staking-form';
import { Actions, RemoveType } from './staking-form';
@@ -23,7 +23,6 @@ export const StakeSuccess = ({
toggleDialog,
}: StakeSuccessProps) => {
const { t } = useTranslation();
const navigate = useNavigate();
const isAdd = action === Actions.Add;
const title = isAdd
? t('stakeAddSuccessTitle', { amount })
@@ -45,15 +44,7 @@ export const StakeSuccess = ({
<div>
<p>{message}</p>
<p>
<Link
className="underline"
to={Routes.VALIDATORS}
onClick={(event) => {
event.preventDefault();
toggleDialog();
setTimeout(() => navigate(Routes.VALIDATORS), 0);
}}
>
<Link className="underline" to={Routes.VALIDATORS}>
{t('backToStaking')}
</Link>
</p>
@@ -29,7 +29,7 @@ export const TrancheProgress = ({
<span className="tranches__progress-title">{t('Locked')}</span>
<ProgressBar
width={220}
color={Colors.vega.pink.DEFAULT}
color={Colors.vega.pink}
percentage={lockedPercentage}
/>
<span className="tranches__progress-numbers">
@@ -40,7 +40,7 @@ export const TrancheProgress = ({
<span className="tranches__progress-title">{t('Redeemed')}</span>
<ProgressBar
width={220}
color={Colors.vega.green.DEFAULT}
color={Colors.vega.green}
percentage={removedPercentage}
/>
<span className="tranches__progress-numbers">
@@ -34,10 +34,10 @@ export const VestingChart = () => {
<AreaChart data={data}>
<defs>
{[
['pink', Colors.vega.pink.DEFAULT],
['green', Colors.vega.green.DEFAULT],
['pink', Colors.vega.pink],
['green', Colors.vega.green],
['orange', Colors.warning],
['yellow', Colors.vega.yellow.DEFAULT],
['yellow', Colors.vega.yellow],
].map(([key, color]) => (
<linearGradient key={key} id={key} x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor={color} stopOpacity={0.85} />
@@ -97,7 +97,7 @@ export const VestingChart = () => {
dot={false}
type="linear"
dataKey="team"
stroke={Colors.vega.pink.DEFAULT}
stroke={Colors.vega.pink}
fill="url(#pink)"
yAxisId={0}
strokeWidth={2}
@@ -109,7 +109,7 @@ export const VestingChart = () => {
dot={false}
type="monotone"
dataKey="earlyInvestors"
stroke={Colors.vega.green.DEFAULT}
stroke={Colors.vega.green}
fill="url(#green)"
yAxisId={0}
strokeWidth={2}
@@ -121,7 +121,7 @@ export const VestingChart = () => {
dot={false}
type="monotone"
dataKey="publicSale"
stroke={Colors.vega.yellow.DEFAULT}
stroke={Colors.vega.yellow}
fill="url(#yellow)"
yAxisId={0}
strokeWidth={2}
-6
View File
@@ -13,9 +13,3 @@
@apply mb-2 text-neutral-400;
}
}
@layer components {
.border-default {
@apply border-vega-dark-200;
}
}
+63 -186
View File
@@ -24,10 +24,7 @@ const txTimeout = Cypress.env('txTimeout');
const sepoliaUrl = Cypress.env('ETHERSCAN_URL');
const btcName =
'BTC (local)5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c - tBTC';
const vegaName =
'Vegab4f2726571fbe8e33b442dc92ed2d7f0d810e21835b7371a7915a365f07ccd9b - VEGA';
const btcSymbol = 'tBTC';
const vegaSymbol = 'VEGA';
const usdcSymbol = 'fUSDC';
const toastContent = 'toast-content';
const ordersTab = 'Orders';
@@ -36,112 +33,9 @@ const toastCloseBtn = 'toast-close';
const price = '390';
const size = '0.0005';
const newPrice = '200';
const completeWithdrawalBtn = 'complete-withdrawal';
// TODO: ensure this test runs only if capsule is running via workflow
// Because the tests are run on a live network to optimize time, the tests are interdependent and must be run in the given order.
describe('capsule - without MultiSign', { tags: '@slow' }, () => {
before(() => {
cy.createMarket();
cy.get('@markets').then((markets) => {
cy.wrap(markets[0]).as('market');
});
});
beforeEach(() => {
cy.setVegaWallet();
});
it('can deposit', function () {
cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist');
// 1001-DEPO-001
// 1001-DEPO-002
// 1001-DEPO-003
// 1001-DEPO-005
// 1001-DEPO-006
// 1001-DEPO-007
// 1001-DEPO-008
// 1001-DEPO-009
// 1001-DEPO-010
cy.getByTestId(depositsTab).click();
cy.getByTestId('deposit-button').click();
connectEthereumWallet('Unknown');
cy.get(assetSelectField, txTimeout).select(btcName, { force: true });
cy.getByTestId('deposit-approve-submit').click();
cy.getByTestId('dialog-title').should('contain.text', 'Approve complete');
cy.get('[data-testid="Return to deposit"]').click();
cy.get(amountField).clear().type('10');
cy.getByTestId('deposit-submit').click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
`Transaction confirmedYour transaction has been confirmed.View on EtherscanDeposit 10.00 ${btcSymbol}`,
{ matchCase: false }
);
cy.getByTestId(toastCloseBtn).click();
cy.getByTestId('Collateral').click();
cy.highlight('deposit verification');
cy.getByTestId('asset', txTimeout).should('contain.text', btcSymbol);
cy.getByTestId(depositsTab).click();
cy.get('.ag-cell-value', txTimeout).should('contain.text', btcSymbol);
cy.get('[col-id="status"]').should('not.have.text', 'Open', txTimeout);
cy.get('[col-id="txHash"]')
.should('have.length.above', 2)
.eq(1)
.parent()
.within(() => {
cy.get('[col-id="asset.symbol"]').should('have.text', btcSymbol);
cy.get('[col-id="amount"]').should('have.text', '10.00');
cy.get('[col-id="createdTimestamp"]').should('not.be.empty');
cy.get('[col-id="status"]').should('have.text', 'Finalized');
cy.get('[col-id="txHash"]')
.find('a')
.should('have.attr', 'href')
.and('contain', `${sepoliaUrl}/tx/0x`);
});
});
it('can not withdrawal because of no MultiSign', function () {
// 1002-WITH-022
// 1002-WITH-023
cy.getByTestId('Withdrawals').click();
cy.getByTestId('withdraw-dialog-button').click();
cy.get(assetSelectField, txTimeout).select(btcName, { force: true });
cy.get(amountField).clear().type('1');
cy.getByTestId('submit-withdrawal').click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
'Funds unlocked'
);
cy.getByTestId('tab-withdrawals').within(() => {
cy.get('.ag-center-cols-container')
.children()
.first()
.within(() => {
cy.get('[col-id="status"]').should('contain.text', 'Pending');
});
});
cy.highlight('withdrawals verification');
cy.getByTestId('toast-complete-withdrawal').click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
'Error occurredprocessing response error'
);
cy.getByTestId(completeWithdrawalBtn).should(
'contain.text',
'Complete withdrawal'
);
});
});
describe('capsule', { tags: '@slow' }, () => {
before(() => {
cy.createMarket();
@@ -234,15 +128,13 @@ describe('capsule', { tags: '@slow' }, () => {
cy.getByTestId('dialog-title').should('contain.text', 'Edit order');
cy.get('#limitPrice').focus().clear().type(newPrice);
cy.getByTestId('edit-order').find('[type="submit"]').click();
cy.getByTestId(toastContent).should(
'contain.text',
`ConfirmedYour transaction has been confirmed View in block explorerEdit order - activeTEST.24h+${size} @ ${price}.00 ${usdcSymbol}+${size} @ ${newPrice}.00 ${usdcSymbol}`,
{ matchCase: false }
);
cy.getByTestId(toastCloseBtn).click({ multiple: true });
cy.getByTestId(ordersTab).click();
cy.getByTestId(toastCloseBtn).click({ multiple: true });
cy.get('.ag-center-cols-container')
.children()
.first()
@@ -272,8 +164,62 @@ describe('capsule', { tags: '@slow' }, () => {
.should('contain.text', OrderStatusMapping.STATUS_CANCELLED);
});
it('can deposit', function () {
cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist');
// 1001-DEPO-001
// 1001-DEPO-002
// 1001-DEPO-003
// 1001-DEPO-005
// 1001-DEPO-006
// 1001-DEPO-007
// 1001-DEPO-008
// 1001-DEPO-009
// 1001-DEPO-010
cy.getByTestId(depositsTab).click();
cy.getByTestId('deposit-button').click();
connectEthereumWallet('Unknown');
cy.get(assetSelectField, txTimeout).select(btcName, { force: true });
cy.getByTestId('deposit-approve-submit').click();
cy.getByTestId('dialog-title').should('contain.text', 'Approve complete');
cy.get('[data-testid="Return to deposit"]').click();
cy.get(amountField).clear().type('1');
cy.getByTestId('deposit-submit').click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
`Transaction confirmedYour transaction has been confirmed.View on EtherscanDeposit 1.00 ${btcSymbol}`,
{ matchCase: false }
);
cy.getByTestId(toastCloseBtn).click();
cy.getByTestId('Collateral').click();
cy.highlight('deposit verification');
cy.getByTestId('asset', txTimeout).should('contain.text', btcSymbol);
cy.getByTestId(depositsTab).click();
cy.get('.ag-cell-value', txTimeout).should('contain.text', btcSymbol);
cy.get('[col-id="status"]').should('not.have.text', 'Open', txTimeout);
cy.get('[col-id="txHash"]')
.should('have.length.above', 2)
.eq(1)
.parent()
.within(() => {
cy.get('[col-id="asset.symbol"]').should('have.text', btcSymbol);
cy.get('[col-id="amount"]').should('have.text', '1.00');
cy.get('[col-id="createdTimestamp"]').should('not.be.empty');
cy.get('[col-id="status"]').should('have.text', 'Finalized');
cy.get('[col-id="txHash"]')
.find('a')
.should('have.attr', 'href')
.and('contain', `${sepoliaUrl}/tx/0x`);
});
});
it('can withdrawal', function () {
// 1002-WITH-0014
// 1002-WITH-001
// 1002-WITH-006
// 1002-WITH-009
// 1002-WITH-011
@@ -283,18 +229,14 @@ describe('capsule', { tags: '@slow' }, () => {
// 1002-WITH-014
// 1002-WITH-015
// 1002-WITH-016
// 1002-WITH-017
// 1002-WITH-019
// 1002-WITH-020
// 1002-WITH-021
cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist');
cy.getByTestId('Withdrawals').click();
cy.getByTestId('withdraw-dialog-button').click();
connectEthereumWallet('Unknown');
cy.get(assetSelectField, txTimeout).select(btcName, { force: true });
cy.get(assetSelectField, txTimeout).select(
'BTC (local)5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c - tBTC',
{ force: true }
);
cy.get(amountField).clear().type('1');
cy.getByTestId('submit-withdrawal').click();
cy.getByTestId(toastContent, txTimeout).should(
@@ -313,13 +255,12 @@ describe('capsule', { tags: '@slow' }, () => {
cy.highlight('withdrawals verification');
cy.getByTestId('toast-complete-withdrawal').click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
'Transaction confirmed'
);
cy.getByTestId(completeWithdrawalBtn).eq(0, txTimeout).should('not.exist');
cy.getByTestId('complete-withdrawal', txTimeout).should('not.exist');
cy.get('[col-id="txHash"]', txTimeout)
.should('have.length.above', 1)
@@ -340,12 +281,9 @@ describe('capsule', { tags: '@slow' }, () => {
.should('have.attr', 'href')
.and('contain', `${sepoliaUrl}/tx/0x`);
});
// comment because of bug #2819
// cy.getByTestId('withdraw-dialog-button').click();
// cy.getByTestId('BALANCE_AVAILABLE_value').should('have.text', '0')
});
it('approved amount is less than deposit', function () {
it('deposit - if approved amount is less than deposit: must see that an approval is needed and be prompted to approve more', function () {
// 1001-DEPO-006
cy.getByTestId(depositsTab).click();
@@ -354,67 +292,6 @@ describe('capsule', { tags: '@slow' }, () => {
cy.get(amountField).clear().type('20000000');
cy.getByTestId('deposit-approve-submit').should('be.visible');
});
it('withdraw - delay verification', function () {
// 1001-DEPO-007
// 1001-DEPO-024
cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist');
cy.getByTestId(depositsTab).click();
cy.getByTestId('deposit-button').click();
connectEthereumWallet('Unknown');
cy.get(assetSelectField, txTimeout).select(vegaName, { force: true });
cy.getByTestId('deposit-approve-submit').click();
cy.getByTestId('dialog-title').should('contain.text', 'Approve complete');
cy.get('[data-testid="Return to deposit"]').click();
cy.get(amountField).clear().type('10000');
cy.getByTestId('deposit-submit').click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
`Your transaction has been confirmed.`,
{ matchCase: false }
);
cy.getByTestId(toastCloseBtn).click();
cy.getByTestId('Collateral').click();
cy.highlight('deposit verification');
cy.getByTestId('asset', txTimeout).should('contain.text', vegaSymbol);
cy.getByTestId(depositsTab).click();
cy.get('.ag-cell-value', txTimeout).should('contain.text', vegaSymbol);
cy.get('[col-id="status"]').should('not.have.text', 'Open', txTimeout);
cy.get('[col-id="txHash"]')
.should('have.length.above', 2)
.eq(1)
.parent()
.within(() => {
cy.get('[col-id="asset.symbol"]').should('have.text', vegaSymbol);
cy.get('[col-id="amount"]').should('have.text', '10,000.00');
cy.get('[col-id="createdTimestamp"]').should('not.be.empty');
cy.get('[col-id="status"]').should('have.text', 'Finalized');
cy.get('[col-id="txHash"]')
.find('a')
.should('have.attr', 'href')
.and('contain', `${sepoliaUrl}/tx/0x`);
});
cy.getByTestId('Withdrawals').click();
cy.getByTestId('withdraw-dialog-button').click();
cy.get(assetSelectField, txTimeout).select(vegaName, { force: true });
cy.get(amountField).clear().type('10000');
cy.getByTestId('DELAY_TIME_value').should('have.text', '5 days');
cy.getByTestId('submit-withdrawal').click();
cy.getByTestId(toastContent, txTimeout).should(
'contain.text',
'Your funds have been unlocked'
);
cy.getByTestId(toastCloseBtn).click();
cy.getByTestId(completeWithdrawalBtn).first().should('be.visible').click();
cy.getByTestId(toastContent, txTimeout).should('contain.text', 'Delayed');
});
});
function checkIfDataAndTimeOfCreationAndUpdateIsEqual(date: string) {
@@ -4,7 +4,6 @@ const marketInfoBtn = 'Info';
const row = 'key-value-table-row';
const marketTitle = 'accordion-title';
const externalLink = 'external-link';
const accordionContent = 'accordion-content';
describe('market info is displayed', { tags: '@smoke' }, () => {
before(() => {
@@ -180,8 +179,7 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
'termination.BTC.value'
);
cy.getByTestId(accordionContent)
.find(`[data-testid="${externalLink}"]`)
cy.getByTestId(externalLink)
.should('have.attr', 'href')
.and('contain', '/oracles');
});
@@ -189,14 +187,12 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
it('proposal displayed', () => {
cy.getByTestId(marketTitle).contains('Proposal').click();
cy.getByTestId(accordionContent)
.find(`[data-testid="${externalLink}"]`)
cy.getByTestId(externalLink)
.first()
.should('have.text', 'View governance proposal')
.and('have.attr', 'href')
.and('contain', '/proposals/market-0');
cy.getByTestId(accordionContent)
.find(`[data-testid="${externalLink}"]`)
cy.getByTestId(externalLink)
.eq(1)
.should('have.text', 'Propose a change to market')
.and('have.attr', 'href')
+1 -52
View File
@@ -1,7 +1,4 @@
import * as Schema from '@vegaprotocol/types';
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { marketQuery } from '@vegaprotocol/mock';
import { getDateTimeFormat } from '@vegaprotocol/react-helpers';
describe('markets table', { tags: '@smoke' }, () => {
beforeEach(() => {
@@ -104,8 +101,7 @@ describe('markets table', { tags: '@smoke' }, () => {
'have.length',
10
);
cy.getByTestId('tab-proposed-markets')
.find('[data-testid="external-link"]')
cy.getByTestId('external-link')
.should('have.length', 11)
.last()
.should('have.text', 'Propose a new market')
@@ -115,53 +111,6 @@ describe('markets table', { tags: '@smoke' }, () => {
`${Cypress.env('VEGA_TOKEN_URL')}/proposals/propose/new-market`
);
});
it('opening auction subsets should be properly displayed', () => {
cy.mockTradingPage(
Schema.MarketState.STATE_ACTIVE,
Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION
);
cy.mockGQL((req) => {
const override = {
market: {
tradableInstrument: {
instrument: {
name: `opening auction MARKET`,
},
},
state: Schema.MarketState.STATE_ACTIVE,
tradingMode: Schema.MarketTradingMode.TRADING_MODE_OPENING_AUCTION,
},
};
const market = marketQuery(override);
aliasGQLQuery(req, 'Market', market);
aliasGQLQuery(req, 'ProposalOfMarket', {
proposal: { terms: { enactmentDatetime: '2023-01-31 12:00:01' } },
});
});
cy.visit('/');
cy.visit('#/markets/market-0');
cy.getByTestId('item-value').contains('Opening auction').realHover();
cy.getByTestId('opening-auction-sub-status').should(
'contain.text',
'Opening auction: Not enough liquidity to open'
);
const now = new Date(Date.parse('2023-01-30 12:00:01')).getTime();
cy.clock(now, ['Date']); // Set "now" to BEFORE reservation
cy.visit('/');
cy.visit('#/markets/market-0');
cy.getByTestId('item-value').contains('Opening auction').realHover();
cy.getByTestId('opening-auction-sub-status').should(
'contain.text',
`Opening auction: Closing on ${getDateTimeFormat().format(
new Date('2023-01-31 12:00:01')
)}`
);
cy.clock().then((clock) => {
clock.restore();
});
});
});
function openMarketDropDown() {
@@ -452,7 +452,7 @@ describe('limit order validations', { tags: '@smoke' }, () => {
//7002-SORD-018
cy.getByTestId(orderPriceField)
.siblings('label')
.should('have.text', 'Price (BTC)');
.should('have.text', 'Price (tBTC)');
});
it('must see warning when placing an order with expiry date in past', () => {
@@ -41,7 +41,6 @@ describe('withdraw form validation', { tags: '@smoke' }, () => {
cy.get(toAddressField).should('have.value', ethAddressValue);
});
it('min amount', () => {
// 1002-WITH-010
selectAsset(ASSET_SEPOLIA_TBTC);
cy.get(amountField).clear().type('0');
cy.getByTestId(submitWithdrawBtn).click();
@@ -51,8 +50,6 @@ describe('withdraw form validation', { tags: '@smoke' }, () => {
);
});
it('max amount', () => {
// 1002-WITH-005
// 1002-WITH-008
selectAsset(ASSET_EURO); // Will be above maximum because the vega wallet doesn't have any collateral
cy.get(amountField).clear().type('1001', { delay: 100 });
cy.getByTestId(submitWithdrawBtn).click();
@@ -63,7 +60,6 @@ describe('withdraw form validation', { tags: '@smoke' }, () => {
});
it('can set amount using use maximum button', () => {
// 1002-WITH-004
selectAsset(ASSET_SEPOLIA_TBTC);
cy.getByTestId(useMaximumAmount).click();
cy.get(amountField).should('have.value', '1000.00000');
@@ -72,9 +68,6 @@ describe('withdraw form validation', { tags: '@smoke' }, () => {
describe('withdraw actions', { tags: '@regression' }, () => {
// this is extremely ugly hack, but setting it properly in contract is too much effort for such simple validation
// 1002-WITH-018
const withdrawalThreshold =
Cypress.env('VEGA_ENV') === 'CUSTOM' ? '0.00' : '100.00';
before(() => {
@@ -95,8 +88,6 @@ describe('withdraw actions', { tags: '@regression' }, () => {
});
it('triggers transaction when submitted', () => {
// 1002-WITH-002
// 1002-WITH-003
selectAsset(ASSET_SEPOLIA_TBTC);
cy.getByTestId('BALANCE_AVAILABLE_label').should(
'contain.text',
@@ -117,4 +108,7 @@ describe('withdraw actions', { tags: '@regression' }, () => {
cy.getByTestId(submitWithdrawBtn).click();
cy.getByTestId('toast').should('contain.text', 'Awaiting confirmation');
});
it.skip('creates a withdrawal on submit'); // Needs capsule
it.skip('creates a withdrawal on submit and prompts to complete withdrawal'); // Needs capsule
});
-1
View File
@@ -8,4 +8,3 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
-1
View File
@@ -9,7 +9,6 @@ NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
-1
View File
@@ -8,4 +8,3 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega-dev-releases/releases
-1
View File
@@ -7,4 +7,3 @@ NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\",\"TESTNET\":\"h
NX_VEGA_TOKEN_URL=https://token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
+1 -2
View File
@@ -7,5 +7,4 @@ NX_VEGA_EXPLORER_URL=https://mainnet-mirror.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://mainnet-mirror.token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
-1
View File
@@ -7,4 +7,3 @@ NX_VEGA_NETWORKS={\"DEVNET\":\"https://dev.token.vega.xyz\",\"STAGNET3\":\"https
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
-1
View File
@@ -8,4 +8,3 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://stagnet1.token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
-1
View File
@@ -8,4 +8,3 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega-dev-releases/releases
-1
View File
@@ -8,4 +8,3 @@ NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
-13
View File
@@ -1,13 +0,0 @@
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/validator-testnet-network.json
NX_VEGA_ENV=VALIDATOR_TESTNET
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
@@ -5,7 +5,7 @@ import { t, useDataProvider } from '@vegaprotocol/react-helpers';
import { useVegaWallet } from '@vegaprotocol/wallet';
export const DepositsContainer = () => {
const { pubKey, isReadOnly } = useVegaWallet();
const { pubKey } = useVegaWallet();
const { data, loading, error } = useDataProvider({
dataProvider: depositsProvider,
variables: { partyId: pubKey || '' },
@@ -30,17 +30,15 @@ export const DepositsContainer = () => {
/>
</div>
</div>
{!isReadOnly && (
<div className="w-full dark:bg-black bg-white absolute bottom-0 h-auto flex justify-end px-[11px] py-2">
<Button
size="sm"
onClick={() => openDepositDialog()}
data-testid="deposit-button"
>
{t('Deposit')}
</Button>
</div>
)}
<div className="w-full dark:bg-black bg-white absolute bottom-0 h-auto flex justify-end px-[11px] py-2">
<Button
size="sm"
onClick={() => openDepositDialog()}
data-testid="deposit-button"
>
{t('Deposit')}
</Button>
</div>
</div>
);
};
@@ -9,7 +9,7 @@ import { t, useDataProvider } from '@vegaprotocol/react-helpers';
import { VegaWalletContainer } from '../../components/vega-wallet-container';
export const WithdrawalsContainer = () => {
const { pubKey, isReadOnly } = useVegaWallet();
const { pubKey } = useVegaWallet();
const { data, loading, error } = useDataProvider({
dataProvider: withdrawalProvider,
variables: { partyId: pubKey || '' },
@@ -36,17 +36,15 @@ export const WithdrawalsContainer = () => {
/>
</div>
</div>
{!isReadOnly && (
<div className="w-full dark:bg-black bg-white absolute bottom-0 h-auto flex justify-end px-[11px] py-2">
<Button
size="sm"
onClick={() => openWithdrawDialog()}
data-testid="withdraw-dialog-button"
>
{t('Make withdrawal')}
</Button>
</div>
)}
<div className="w-full dark:bg-black bg-white absolute bottom-0 h-auto flex justify-end px-[11px] py-2">
<Button
size="sm"
onClick={() => openWithdrawDialog()}
data-testid="withdraw-dialog-button"
>
{t('Make withdrawal')}
</Button>
</div>
</div>
</VegaWalletContainer>
);
@@ -9,7 +9,7 @@ import { AccountManager } from '@vegaprotocol/accounts';
import { useDepositDialog } from '@vegaprotocol/deposits';
export const AccountsContainer = () => {
const { pubKey, isReadOnly } = useVegaWallet();
const { pubKey } = useVegaWallet();
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
const openWithdrawalDialog = useWithdrawalDialog((store) => store.open);
const openDepositDialog = useDepositDialog((store) => store.open);
@@ -37,16 +37,13 @@ export const AccountsContainer = () => {
onClickAsset={onClickAsset}
onClickWithdraw={openWithdrawalDialog}
onClickDeposit={openDepositDialog}
isReadOnly={isReadOnly}
/>
</div>
{!isReadOnly && (
<div className="flex justify-end p-2 px-[11px]">
<Button size="sm" onClick={() => openDepositDialog()}>
{t('Deposit')}
</Button>
</div>
)}
<div className="flex justify-end p-2 px-[11px]">
<Button size="sm" onClick={() => openDepositDialog()}>
{t('Deposit')}
</Button>
</div>
</div>
);
};
-39
View File
@@ -1,39 +0,0 @@
import {
AnnouncementBanner,
ExternalLink,
Icon,
} from '@vegaprotocol/ui-toolkit';
import { useGlobalStore } from '../../stores';
export const Banner = () => {
const { update, shouldDisplayAnnouncementBanner } = useGlobalStore(
(store) => ({
update: store.update,
shouldDisplayAnnouncementBanner: store.shouldDisplayAnnouncementBanner,
})
);
// Return an empty div so that the grid layout in _app.page.ts
// renders correctly
if (!shouldDisplayAnnouncementBanner) {
return <div />;
}
return (
<AnnouncementBanner>
<div className="grid grid-cols-[auto_1fr] gap-4 font-alpha calt uppercase text-center text-lg text-white">
<button
onClick={() => update({ shouldDisplayAnnouncementBanner: false })}
>
<Icon name="cross" className="w-6 h-6" ariaLabel="dismiss" />
</button>
<div>
<span className="pr-4">The Mainnet sims are live!</span>
<ExternalLink href="https://fairground.wtf/">
Come help stress test the network
</ExternalLink>
</div>
</div>
</AnnouncementBanner>
);
};
-1
View File
@@ -1 +0,0 @@
export * from './banner';
@@ -49,6 +49,7 @@ describe('NodeHealth', () => {
it.each(cases)(
'renders correct text and indicator color for $diff block difference',
(elem) => {
console.log(elem);
render(<NodeHealth blockDiff={elem.diff} openNodeSwitcher={jest.fn()} />);
expect(screen.getByTestId('indicator')).toHaveClass(elem.classname);
expect(screen.getByText(elem.text)).toBeInTheDocument();
+1 -1
View File
@@ -15,7 +15,7 @@ export const Header = ({ title, children }: TradeMarketHeaderProps) => {
<div className="px-4 xl:px-0 pb-2 xl:pb-3">{title}</div>
<div
data-testid="header-summary"
className="flex flex-nowrap items-end xl:flex-1 w-full overflow-x-auto text-xs"
className="flex flex-nowrap items-start xl:flex-1 w-full overflow-x-auto text-xs"
>
{Children.map(children, (child, index) => {
if (!child) return null;
@@ -1,25 +1,11 @@
import type { RefObject } from 'react';
import { useMemo } from 'react';
import { t, useDataProvider } from '@vegaprotocol/react-helpers';
import { t } from '@vegaprotocol/react-helpers';
import { TradingModeTooltip } from '@vegaprotocol/deal-ticket';
import { useInView } from 'react-intersection-observer';
import * as Schema from '@vegaprotocol/types';
import { useStaticMarketData } from '@vegaprotocol/market-list';
import { HeaderStat } from '../header';
import { Tooltip } from '@vegaprotocol/ui-toolkit';
import { marketDataProvider } from '@vegaprotocol/market-list';
// This will cause often re-rendering
// Here it may not be a problem because the component is not very complex
// In general, we should avoid using this marketData hook without any throttling
const useMarketData = (marketId?: string, skip?: boolean) => {
const variables = useMemo(() => ({ marketId }), [marketId]);
const { data } = useDataProvider({
dataProvider: marketDataProvider,
variables,
skip: skip || !marketId,
});
return data;
};
const getTradingModeLabel = (
tradingMode?: Schema.MarketTradingMode,
@@ -49,7 +35,7 @@ export const HeaderStatMarketTradingMode = ({
initialTradingMode,
initialTrigger,
}: HeaderStatMarketTradingModeProps) => {
const data = useMarketData(marketId);
const data = useStaticMarketData(marketId);
const tradingMode = data?.marketTradingMode ?? initialTradingMode;
const trigger = data?.trigger ?? initialTrigger;
@@ -75,7 +61,7 @@ export const MarketTradingMode = ({
inViewRoot?: RefObject<Element>;
}) => {
const [ref, inView] = useInView({ root: inViewRoot?.current });
const data = useMarketData(marketId, !inView);
const data = useStaticMarketData(marketId, !inView);
return (
<Tooltip
+2 -2
View File
@@ -8,7 +8,7 @@ import {
useLinks,
} from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/react-helpers';
import { useGlobalStore } from '../../stores';
import { useGlobalStore } from '../../stores/global';
import { VegaWalletConnectButton } from '../vega-wallet-connect-button';
import {
Drawer,
@@ -165,7 +165,7 @@ export const Navbar = ({ navbarTheme = 'inherit' }: NavbarProps) => {
</Link>
}
>
<LinkList className="hidden md:flex md:px-2" navbarTheme={navbarTheme} />
<LinkList className="hidden md:flex" navbarTheme={navbarTheme} />
<div className="flex items-center gap-2 ml-auto overflow-hidden">
<VegaWalletConnectButton />
<ThemeSwitcher className="hidden md:block" />
@@ -151,8 +151,6 @@ const MARKET_B: PartialMarket = {
};
describe('SelectMarket', () => {
const table = document.createElement('table');
it('should render the SelectAllMarketsTableBody', () => {
const onSelect = jest.fn();
const onCellClick = jest.fn();
@@ -164,7 +162,7 @@ describe('SelectMarket', () => {
onSelect={onSelect}
/>
</MemoryRouter>,
{ wrapper: MockedProvider, container: document.body.appendChild(table) }
{ wrapper: MockedProvider }
);
expect(screen.getByText('ABCDEF')).toBeTruthy(); // name
expect(screen.getByText('25.00%')).toBeTruthy(); // price change
@@ -0,0 +1 @@
export { VegaTransaction } from './vega-transaction';
@@ -0,0 +1,57 @@
import { WithdrawalFeedback } from '@vegaprotocol/withdraws';
import { OrderFeedback } from '@vegaprotocol/orders';
import {
VegaDialog,
VegaTxStatus,
isWithdrawTransaction,
isOrderCancellationTransaction,
isOrderSubmissionTransaction,
isOrderAmendmentTransaction,
} from '@vegaprotocol/wallet';
import type { VegaStoredTxState } from '@vegaprotocol/wallet';
import { useEthWithdrawApprovalsStore } from '@vegaprotocol/web3';
export const VegaTransaction = ({
transaction,
}: {
transaction: VegaStoredTxState;
}) => {
const createEthWithdrawalApproval = useEthWithdrawApprovalsStore(
(state) => state.create
);
if (isWithdrawTransaction(transaction.body)) {
if (
transaction.status === VegaTxStatus.Complete &&
transaction.withdrawal
) {
return (
<WithdrawalFeedback
transaction={transaction}
withdrawal={transaction.withdrawal}
availableTimestamp={null}
submitWithdraw={() => {
if (!transaction?.withdrawal) {
return;
}
createEthWithdrawalApproval(
transaction.withdrawal,
transaction.withdrawalApproval
);
}}
/>
);
}
} else if (
(isOrderCancellationTransaction(transaction.body) ||
isOrderSubmissionTransaction(transaction.body) ||
isOrderAmendmentTransaction(transaction.body)) &&
transaction.status === VegaTxStatus.Complete &&
transaction.order
) {
return (
<OrderFeedback transaction={transaction} order={transaction.order} />
);
}
return <VegaDialog transaction={transaction} />;
};
@@ -134,7 +134,23 @@ const submitOrder: VegaStoredTxState = {
type: OrderType.TYPE_MARKET,
price: '1234',
createdAt: new Date(),
marketId: 'market-1',
market: {
id: 'market-1',
decimalPlaces: 2,
positionDecimalPlaces: 2,
tradableInstrument: {
instrument: {
code: 'M1',
name: 'M1',
product: {
settlementAsset: {
decimals: 2,
symbol: '$A',
},
},
},
},
},
status: OrderStatus.STATUS_ACTIVE,
},
};
@@ -165,7 +181,23 @@ const editOrder: VegaStoredTxState = {
type: OrderType.TYPE_MARKET,
price: '1234',
createdAt: new Date(),
marketId: 'market-1',
market: {
id: 'market-1',
decimalPlaces: 2,
positionDecimalPlaces: 2,
tradableInstrument: {
instrument: {
code: 'M1',
name: 'M1',
product: {
settlementAsset: {
decimals: 2,
symbol: '$A',
},
},
},
},
},
status: OrderStatus.STATUS_ACTIVE,
},
};
@@ -4,7 +4,7 @@ import compact from 'lodash/compact';
import type {
BatchMarketInstructionSubmissionBody,
OrderAmendment,
OrderTxUpdateFieldsFragment,
OrderBusEventFieldsFragment,
OrderCancellationBody,
OrderSubmission,
VegaStoredTxState,
@@ -50,15 +50,6 @@ const intentMap: { [s in VegaTxStatus]: Intent } = {
Complete: Intent.Success,
};
const getIntent = (tx: VegaStoredTxState) => {
// Transaction can be successful
// But the order can be rejected by the network
if (tx.order?.rejectionReason) {
return Intent.Danger;
}
return intentMap[tx.status];
};
const isClosePositionTransaction = (tx: VegaStoredTxState) => {
if (isBatchMarketInstructionsTransaction(tx.body)) {
const amendments =
@@ -139,10 +130,12 @@ const SubmitOrderDetails = ({
order,
}: {
data: OrderSubmission;
order?: OrderTxUpdateFieldsFragment;
order?: OrderBusEventFieldsFragment;
}) => {
const { data: markets } = useMarketList();
const market = markets?.find((m) => m.id === order?.marketId);
const market = order
? order.market
: markets?.find((m) => m.id === data.marketId);
if (!market) return null;
const price = order ? order.price : data.price;
@@ -185,7 +178,7 @@ const EditOrderDetails = ({
order,
}: {
data: OrderAmendment;
order?: OrderTxUpdateFieldsFragment;
order?: OrderBusEventFieldsFragment;
}) => {
const { data: orderById } = useOrderByIdQuery({
variables: { orderId: data.orderId },
@@ -249,7 +242,7 @@ const CancelOrderDetails = ({
order,
}: {
orderId: string;
order?: OrderTxUpdateFieldsFragment;
order?: OrderBusEventFieldsFragment;
}) => {
const { data: orderById } = useOrderByIdQuery({
variables: { orderId },
@@ -470,26 +463,6 @@ const VegaTxCompleteToastsContent = ({ tx }: VegaTxToastContentProps) => {
);
}
if (isOrderSubmissionTransaction(tx.body) && tx.order?.rejectionReason) {
return (
<div>
<h3 className="font-bold">{t('Order rejected')}</h3>
<p>{t('Your order was rejected.')}</p>
{tx.txHash && (
<p className="break-all">
<ExternalLink
href={explorerLink(EXPLORER_TX.replace(':hash', tx.txHash))}
rel="noreferrer"
>
{t('View in block explorer')}
</ExternalLink>
</p>
)}
<VegaTransactionDetails tx={tx} />
</div>
);
}
return (
<div>
<h3 className="font-bold">{t('Confirmed')}</h3>
@@ -574,7 +547,7 @@ export const useVegaTransactionToasts = () => {
}
return {
id: `vega-${tx.id}`,
intent: getIntent(tx),
intent: intentMap[tx.status],
onClose: () => dismissVegaTransaction(tx.id),
loader: tx.status === VegaTxStatus.Pending,
content,
+5 -13
View File
@@ -33,8 +33,6 @@ import ToastsManager from './toasts-manager';
import { HashRouter, useLocation, useSearchParams } from 'react-router-dom';
import { Connectors } from '../lib/vega-connectors';
import { ViewingBanner } from '../components/viewing-banner';
import { Banner } from '../components/banner';
import classNames from 'classnames';
const DEFAULT_TITLE = t('Welcome to Vega trading!');
@@ -72,11 +70,6 @@ function AppBody({ Component }: AppProps) {
const location = useLocation();
const { VEGA_ENV } = useEnvironment();
const gridClasses = classNames(
'h-full relative z-0 grid',
'grid-rows-[repeat(3,min-content),1fr,min-content]'
);
return (
<div className="h-full dark:bg-black dark:text-white">
<Head>
@@ -87,21 +80,20 @@ function AppBody({ Component }: AppProps) {
<VegaWalletProvider>
<AppLoader>
<Web3Provider>
<div className={gridClasses}>
<div className="h-full relative z-0 grid grid-rows-[min-content,min-content,1fr,min-content]">
<Navbar
navbarTheme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'dark'}
/>
<Banner />
<ViewingBanner />
<main data-testid={location.pathname}>
<Component />
</main>
<Footer />
<DialogsContainer />
<ToastsManager />
<TransactionsHandler />
<MaybeConnectEagerly />
</div>
<DialogsContainer />
<ToastsManager />
<TransactionsHandler />
<MaybeConnectEagerly />
</Web3Provider>
</AppLoader>
</VegaWalletProvider>
+1 -1
View File
@@ -22,7 +22,7 @@ export default function Document() {
<script src="/assets/env-config.js" type="text/javascript" />
) : null}
</Head>
<body className="font-alpha liga-0-calt-0">
<body>
<Main />
<NextScript />
</body>
+22 -22
View File
@@ -10,49 +10,49 @@ body,
/* Styles for allotment */
html {
--focus-border: theme('colors.vega.pink.500');
--separator-border: theme('colors.vega.light.200');
--pennant-color-danger: theme('colors.vega.pink.500');
--focus-border: theme('colors.vega.pink');
--separator-border: theme('colors.neutral.300');
--pennant-color-danger: theme('colors.vega.pink');
}
html.dark {
--focus-border: theme('colors.vega.yellow.500');
--separator-border: theme('colors.vega.dark.200');
--focus-border: theme('colors.vega.yellow');
--separator-border: theme('colors.neutral.600');
}
.border-default {
@apply border-vega-light-200 dark:border-vega-dark-200;
@apply border-neutral-300 dark:border-neutral-600;
}
/* Styles for charts */
html [data-theme='dark'] {
--pennant-color-danger: theme('colors.vega.pink.DEFAULT');
--pennant-color-danger: theme('colors.vega.pink');
/* candles */
--pennant-color-buy-fill: theme('colors.vega.green.650');
--pennant-color-buy-stroke: theme('colors.vega.green.500');
--pennant-color-buy-fill: theme('colors.vega.green-data-dark');
--pennant-color-buy-stroke: theme('colors.vega.green');
/* sell candles only use stroke as the candle is solid (without border) */
--pennant-color-sell-stroke: theme('colors.vega.pink.500');
--pennant-color-sell-stroke: theme('colors.vega.pink');
/* depth chart */
--pennant-color-depth-buy-fill: theme('colors.vega.green.650');
--pennant-color-depth-buy-stroke: theme('colors.vega.green.500');
--pennant-color-depth-sell-fill: theme('colors.vega.pink.650');
--pennant-color-depth-sell-stroke: theme('colors.vega.pink.500');
--pennant-color-depth-buy-fill: theme('colors.vega.green-data-dark');
--pennant-color-depth-buy-stroke: theme('colors.vega.green');
--pennant-color-depth-sell-fill: theme('colors.vega.pink-data-dark');
--pennant-color-depth-sell-stroke: theme('colors.vega.pink');
}
html [data-theme='light'] {
--pennant-color-danger: theme('colors.vega.pink.500');
--pennant-color-danger: theme('colors.vega.pink');
/* candles */
--pennant-color-buy-fill: theme('colors.vega.green.400');
--pennant-color-buy-stroke: theme('colors.vega.green.550');
--pennant-color-buy-fill: theme('colors.vega.green-data-light');
--pennant-color-buy-stroke: theme('colors.vega.green-dark');
/* sell candles only use stroke as the candle is solid (without border) */
--pennant-color-sell-stroke: theme('colors.vega.pink.400');
--pennant-color-sell-stroke: theme('colors.vega.pink-data-light');
/* depth chart */
--pennant-color-depth-buy-fill: theme('colors.vega.green.400');
--pennant-color-depth-buy-stroke: theme('colors.vega.green.550');
--pennant-color-depth-sell-fill: theme('colors.vega.pink.400');
--pennant-color-depth-sell-stroke: theme('colors.vega.pink.550');
--pennant-color-depth-buy-fill: theme('colors.vega.green-data-light');
--pennant-color-depth-buy-stroke: theme('colors.vega.green-dark');
--pennant-color-depth-sell-fill: theme('colors.vega.pink-data-light');
--pennant-color-depth-sell-stroke: theme('colors.vega.pink-dark');
}
-2
View File
@@ -7,7 +7,6 @@ interface GlobalStore {
marketId: string | null;
update: (store: Partial<Omit<GlobalStore, 'update'>>) => void;
shouldDisplayWelcomeDialog: boolean;
shouldDisplayAnnouncementBanner: boolean;
}
interface PageTitleStore {
@@ -19,7 +18,6 @@ export const useGlobalStore = create<GlobalStore>((set) => ({
networkSwitcherDialog: false,
marketId: LocalStorage.getItem('marketId') || null,
shouldDisplayWelcomeDialog: false,
shouldDisplayAnnouncementBanner: true,
update: (newState) => {
set(
produce((state: GlobalStore) => {
-13
View File
@@ -1,13 +0,0 @@
const { utils } = require('@commitlint/config-nx-scopes');
module.exports = {
extends: ['@commitlint/config-conventional', '@commitlint/config-nx-scopes'],
rules: {
'scope-empty': [2, 'never'],
'scope-enum': async (ctx) => [
2,
'always',
['ci', 'docs', ...(await utils.getProjects(ctx))],
],
},
};
+12 -31
View File
@@ -23,23 +23,13 @@ jest.mock('@vegaprotocol/react-helpers', () => ({
describe('AccountManager', () => {
it('change partyId should reload data provider', async () => {
const { rerender } = render(
<AccountManager
partyId="partyOne"
onClickAsset={jest.fn}
isReadOnly={false}
/>
<AccountManager partyId="partyOne" onClickAsset={jest.fn} />
);
expect(
(helpers.useDataProvider as jest.Mock).mock.calls[0][0].variables.partyId
).toEqual('partyOne');
await act(() => {
rerender(
<AccountManager
partyId="partyTwo"
onClickAsset={jest.fn}
isReadOnly={false}
/>
);
rerender(<AccountManager partyId="partyTwo" onClickAsset={jest.fn} />);
});
expect(
(helpers.useDataProvider as jest.Mock).mock.calls[1][0].variables.partyId
@@ -48,28 +38,19 @@ describe('AccountManager', () => {
it('update method should return proper result', async () => {
await act(() => {
render(
<AccountManager
partyId="partyOne"
onClickAsset={jest.fn}
isReadOnly={false}
/>
);
render(<AccountManager partyId="partyOne" onClickAsset={jest.fn} />);
});
await waitFor(() => {
expect(screen.getByText('No accounts')).toBeInTheDocument();
});
await act(() => {
expect(mockedUpdate({ data: [] })).toEqual(true);
expect(
mockedUpdate({ data: [{ party: { id: 't1' } }] as AccountFields[] })
).toEqual(false);
expect(
mockedUpdate({ data: [{ party: { id: 't2' } }] as AccountFields[] })
).toEqual(true);
expect(mockedUpdate({ data: [] })).toEqual(false);
expect(mockedUpdate({ data: [] })).toEqual(true);
});
expect(mockedUpdate({ data: [] })).toEqual(true);
expect(
mockedUpdate({ data: [{ party: { id: 't1' } }] as AccountFields[] })
).toEqual(false);
expect(
mockedUpdate({ data: [{ party: { id: 't2' } }] as AccountFields[] })
).toEqual(true);
expect(mockedUpdate({ data: [] })).toEqual(false);
expect(mockedUpdate({ data: [] })).toEqual(true);
});
});
@@ -16,7 +16,6 @@ interface AccountManagerProps {
onClickAsset: (assetId: string) => void;
onClickWithdraw?: (assetId?: string) => void;
onClickDeposit?: (assetId?: string) => void;
isReadOnly: boolean;
}
export const AccountManager = ({
@@ -24,7 +23,6 @@ export const AccountManager = ({
onClickWithdraw,
onClickDeposit,
partyId,
isReadOnly,
}: AccountManagerProps) => {
const gridRef = useRef<AgGridReact | null>(null);
const dataRef = useRef<AccountFields[] | null>(null);
@@ -60,7 +58,6 @@ export const AccountManager = ({
onClickAsset={onClickAsset}
onClickDeposit={onClickDeposit}
onClickWithdraw={onClickWithdraw}
isReadOnly={isReadOnly}
/>
<div className="pointer-events-none absolute inset-0">
<AsyncRenderer
+2 -10
View File
@@ -35,11 +35,7 @@ describe('AccountsTable', () => {
it('should render correct columns', async () => {
await act(async () => {
render(
<AccountTable
rowData={singleRowData}
onClickAsset={() => null}
isReadOnly={false}
/>
<AccountTable rowData={singleRowData} onClickAsset={() => null} />
);
});
const expectedHeaders = ['Asset', 'Total', 'Used', 'Available', ''];
@@ -53,11 +49,7 @@ describe('AccountsTable', () => {
it('should apply correct formatting', async () => {
await act(async () => {
render(
<AccountTable
rowData={singleRowData}
onClickAsset={() => null}
isReadOnly={false}
/>
<AccountTable rowData={singleRowData} onClickAsset={() => null} />
);
});
const cells = await screen.findAllByRole('gridcell');
+42 -45
View File
@@ -29,7 +29,6 @@ export interface AccountTableProps extends AgGridReactProps {
onClickAsset: (assetId: string) => void;
onClickWithdraw?: (assetId: string) => void;
onClickDeposit?: (assetId: string) => void;
isReadOnly: boolean;
}
export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
@@ -128,50 +127,48 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
}
maxWidth={300}
/>
{!props.isReadOnly && (
<AgGridColumn
colId="breakdown"
headerName=""
sortable={false}
minWidth={200}
type="rightAligned"
cellRenderer={({
data,
}: VegaICellRendererParams<AccountFields>) => {
return data ? (
<>
<ButtonLink
data-testid="breakdown"
onClick={() => {
setOpenBreakdown(!openBreakdown);
setBreakdown(data.breakdown || null);
}}
>
{t('Breakdown')}
</ButtonLink>
<span className="mx-1" />
<ButtonLink
data-testid="deposit"
onClick={() => {
onClickDeposit && onClickDeposit(data.asset.id);
}}
>
{t('Deposit')}
</ButtonLink>
<span className="mx-1" />
<ButtonLink
data-testid="withdraw"
onClick={() =>
onClickWithdraw && onClickWithdraw(data.asset.id)
}
>
{t('Withdraw')}
</ButtonLink>
</>
) : null;
}}
/>
)}
<AgGridColumn
colId="breakdown"
headerName=""
sortable={false}
minWidth={200}
type="rightAligned"
cellRenderer={({
data,
}: VegaICellRendererParams<AccountFields>) => {
return data ? (
<>
<ButtonLink
data-testid="breakdown"
onClick={() => {
setOpenBreakdown(!openBreakdown);
setBreakdown(data.breakdown || null);
}}
>
{t('Breakdown')}
</ButtonLink>
<span className="mx-1" />
<ButtonLink
data-testid="deposit"
onClick={() => {
onClickDeposit && onClickDeposit(data.asset.id);
}}
>
{t('Deposit')}
</ButtonLink>
<span className="mx-1" />
<ButtonLink
data-testid="withdraw"
onClick={() =>
onClickWithdraw && onClickWithdraw(data.asset.id)
}
>
{t('Withdraw')}
</ButtonLink>
</>
) : null;
}}
/>
</AgGrid>
<Dialog size="medium" open={openBreakdown} onChange={setOpenBreakdown}>
<div className="h-[35vh] w-full m-auto flex flex-col">
-15
View File
@@ -1,15 +0,0 @@
import { Option } from '@vegaprotocol/ui-toolkit';
import type { AssetFieldsFragment } from './__generated__/Asset';
export const AssetOption = ({ asset }: { asset: AssetFieldsFragment }) => {
return (
<Option key={asset.id} value={asset.id}>
<div className="flex flex-col items-start">
<span>{asset.name}</span>
<div className="text-[10px] font-mono w-full text-left break-all">
<span className="text-gray-500">{asset.id} -</span> {asset.symbol}
</div>
</div>
</Option>
);
};
-1
View File
@@ -4,4 +4,3 @@ export * from './asset-data-provider';
export * from './assets-data-provider';
export * from './asset-details-dialog';
export * from './asset-details-table';
export * from './asset-option';
+1 -5
View File
@@ -1,4 +1,5 @@
import 'pennant/dist/style.css';
import {
Chart,
ChartType,
@@ -167,11 +168,6 @@ export const CandlesChartContainer = ({
chartType: chartType,
overlays: overlays,
studies: studies,
notEnoughDataText: (
<span className="text-xs text-center text-neutral-800 dark:text-neutral-200">
{t('No data')}
</span>
),
}}
interval={interval}
theme={theme}

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