Compare commits

..
Author SHA1 Message Date
Maciek c8ec793b65 chore(trading): make loading masks in tabs consistent along the app (#3155) 2023-03-15 16:15:37 +01:00
Dariusz Majcherczyk 927fe2cb4a test: skip test 2023-03-15 16:11:52 +01:00
dexturr e205c9df8b chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-15 16:11:52 +01:00
Maciek 2c2251e953 chore(trading): display latency in block height progressing as warn or error (#3169) 2023-03-15 16:11:52 +01:00
Dariusz Majcherczyk d73080965b test: increase coverage for AC: Connect Ethereum wallet 2023-03-15 11:56:53 +01:00
Art 67e602ebb1 feat(explorer): try again for tx details (#3195) 2023-03-15 08:24:42 +00:00
Art f407110e95 chore(environment): etherscan link (#3193) 2023-03-15 08:24:20 +00:00
Art 66a85cce2a chore(explorer): market info shared panels (#3192) 2023-03-15 08:21:12 +00:00
Art 93f8450ecb fix(utils): missing flags (#3194) 2023-03-15 08:20:41 +00:00
dexturr 0447a6cf5d chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-15 06:09:39 +00:00
dexturr 498be838c7 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-15 00:17:07 +00:00
dexturr fc3b1bd9ab chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-14 18:09:59 +00:00
Joe Tsang 090d850647 test(governance): e2e rewards (#3190) 2023-03-14 16:10:58 +00:00
Maciek 95280f5b26 chore(environment): fetch networks configuration from repo (#3145) 2023-03-14 16:02:43 +01:00
m.ray 101ae00a57 fix(trading): hide transfer button in view as mode (#3189) 2023-03-14 15:39:47 +01:00
Bartłomiej Głownia 613cce3683 feat(orders): use default filters in orders list (#3143) 2023-03-14 13:53:51 +01:00
dexturr 41fa18ed45 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-14 12:10:12 +00:00
Sam Keen c941893cdd fix(governance): ensure validators tables sorting on develop (#3176) 2023-03-14 09:16:12 +00:00
m.ray d049b471d8 chore(trading): mainnet sim 3 live banners (#3184) 2023-03-14 09:04:19 +00:00
m.ray 010ffc0f46 fix(trading): dropdown fix from testnet and validator-testnet (#3185) 2023-03-14 08:55:45 +00:00
dexturr dd56e4083b chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-14 06:08:23 +00:00
dexturr 09d1ba68ba chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-14 00:16:43 +00:00
Matthew Russell 3959daa2b7 chore(trading,explorer,governance): update validator testnet nodes (#3182) 2023-03-13 16:17:10 -07:00
Matthew Russell c599b02c89 fix(trading): add missing block explorer link for complete transfer (#3181) 2023-03-13 18:00:51 -04:00
m.ray e5ebaf02d2 fix(trading): ledger entries table formatting (#3180) 2023-03-13 19:40:08 +00:00
Matthew Russell ae54616c1f chore(trading): move banner above nav (#3161) 2023-03-13 18:38:16 +00:00
m.ray 8f3cf390c5 fix(trading): remove liquidation from positions & format price bounds with market dp (#3173) 2023-03-13 18:17:00 +00:00
m.ray 64cf0c90a7 feat(trading): clarify collateral and breakdown tables (#3113) 2023-03-13 18:15:53 +00:00
dexturr 3edd91eadb chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-13 18:06:59 +00:00
m.ray 676aeb07a4 fix(trading): deal ticket validation on zero account balance and margin warnings (#3177) 2023-03-13 17:58:51 +00:00
127 changed files with 3664 additions and 1715 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_ENV=CUSTOM
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/capsule-network.json
NX_VEGA_CONFIG_URL=
CYPRESS_VEGA_TENDERMINT_URL=http://localhost:26617
+1 -1
View File
@@ -1,6 +1,6 @@
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n00.stagnet3.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_NETWORKS='{"SANDBOX":"https://sandbox.explorer.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz", "STAGNET3":"https://stagnet3.explorer.vega.xyz","VALIDATOR_TESTNET":"https://validator-testnet.fairground.wtf","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_ENV=STAGNET3
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
+2 -2
View File
@@ -1,10 +1,10 @@
# App configuration variables
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_VEGA_ENV=DEVNET
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://dev.token.vega.xyz
NX_VEGA_URL=https://api.devnet1.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet1-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
+2 -2
View File
@@ -1,8 +1,8 @@
# App configuration variables
NX_TENDERMINT_URL=https://be.explorer.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.explorer.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
NX_VEGA_ENV=MAINNET
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest/
NX_ETHERSCAN_URL=https://etherscan.io
NX_VEGA_GOVERNANCE_URL=https://token.vega.xyz
NX_VEGA_GOVERNANCE_URL=https://token.vega.xyz
+1 -1
View File
@@ -1,7 +1,7 @@
# App configuration variables
NX_TENDERMINT_URL=https://tm.be.mainnet-mirror.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mirror-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
NX_VEGA_ENV=MIRROR
NX_BLOCK_EXPLORER=https://be.mainnet-mirror.vega.xyz/rest/
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+1 -1
View File
@@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_ENV=SANDBOX
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
+1 -1
View File
@@ -1,7 +1,7 @@
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/stagnet1-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_ENV=STAGNET1
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_TOKEN_URL=https://stagnet1.token.vega.xyz
+1 -1
View File
@@ -1,6 +1,6 @@
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.stagnet3.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_ENV=STAGNET3
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
NX_VEGA_GOVERNANCE_URL=https://stagnet3.token.vega.xyz
+2 -2
View File
@@ -2,9 +2,9 @@
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_ENV=TESTNET
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://token.fairground.wtf
NX_VEGA_GOVERNANCE_URL=https://token.fairground.wtf
+2 -2
View File
@@ -1,7 +1,7 @@
# App configuration variables
NX_VEGA_ENV=VALIDATOR_TESTNET
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/validator-testnet-network.json
NX_VEGA_URL=https://api.validators-testnet.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.toml
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
NX_VEGA_REST=https://api.validators-testnet.vega.xyz/
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
@@ -1,143 +1,52 @@
import {
addDecimalsFormatNumber,
formatNumberPercentage,
getMarketExpiryDateFormatted,
} from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import type { MarketInfoWithData } from '@vegaprotocol/market-info';
import { MarketInfoTable } from '@vegaprotocol/market-info';
import { LiquidityInfoPanel } from '@vegaprotocol/market-info';
import { LiquidityMonitoringParametersInfoPanel } from '@vegaprotocol/market-info';
import {
MarketStateMapping,
MarketTradingModeMapping,
} from '@vegaprotocol/types';
import { AssetDetailsTable, useAssetDataProvider } from '@vegaprotocol/assets';
import { Splash } from '@vegaprotocol/ui-toolkit';
import BigNumber from 'bignumber.js';
import { useMemo } from 'react';
InstrumentInfoPanel,
KeyDetailsInfoPanel,
LiquidityPriceRangeInfoPanel,
MetadataInfoPanel,
OracleInfoPanel,
RiskFactorsInfoPanel,
RiskModelInfoPanel,
RiskParametersInfoPanel,
SettlementAssetInfoPanel,
} from '@vegaprotocol/market-info';
import { MarketInfoTable } from '@vegaprotocol/market-info';
import { Link } from 'react-router-dom';
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
const quoteUnit = market?.tradableInstrument.instrument.product.quoteName;
const assetId = useMemo(
() => market?.tradableInstrument.instrument.product?.settlementAsset.id,
[market]
);
const { data: asset } = useAssetDataProvider(assetId ?? '');
if (!market) return null;
const keyDetails = {
decimalPlaces: market.decimalPlaces,
positionDecimalPlaces: market.positionDecimalPlaces,
tradingMode: market.tradingMode,
state: MarketStateMapping[market.state],
};
const assetDecimals =
market.tradableInstrument.instrument.product.settlementAsset.decimals;
const liquidityPriceRange = formatNumberPercentage(
new BigNumber(market.lpPriceRange).times(100)
);
const panels = [
{
title: t('Key details'),
content: (
<MarketInfoTable
noBorder={false}
data={{
name: market.tradableInstrument.instrument.name,
marketID: market.id,
tradingMode:
keyDetails.tradingMode &&
MarketTradingModeMapping[keyDetails.tradingMode],
marketDecimalPlaces: market.decimalPlaces,
positionDecimalPlaces: market.positionDecimalPlaces,
settlementAssetDecimalPlaces: assetDecimals,
}}
/>
),
content: <KeyDetailsInfoPanel noBorder={false} market={market} />,
},
{
title: t('Instrument'),
content: (
<MarketInfoTable
noBorder={false}
data={{
marketName: market.tradableInstrument.instrument.name,
code: market.tradableInstrument.instrument.code,
productType:
market.tradableInstrument.instrument.product.__typename,
...market.tradableInstrument.instrument.product,
}}
/>
),
content: <InstrumentInfoPanel noBorder={false} market={market} />,
},
{
title: t('Settlement asset'),
content: asset ? (
<AssetDetailsTable
asset={asset}
inline={true}
noBorder={false}
dtClassName="text-black dark:text-white text-ui !px-0 !font-normal"
ddClassName="text-black dark:text-white text-ui !px-0 !font-normal max-w-full"
/>
) : (
<Splash>{t('No data')}</Splash>
),
content: <SettlementAssetInfoPanel market={market} noBorder={false} />,
},
{
title: t('Metadata'),
content: (
<MarketInfoTable
noBorder={false}
data={{
expiryDate: getMarketExpiryDateFormatted(
market.tradableInstrument.instrument.metadata.tags
),
...market.tradableInstrument.instrument.metadata.tags
?.map((tag) => {
const [key, value] = tag.split(':');
return { [key]: value };
})
.reduce((acc, curr) => ({ ...acc, ...curr }), {}),
}}
/>
),
content: <MetadataInfoPanel noBorder={false} market={market} />,
},
{
title: t('Risk model'),
content: (
<MarketInfoTable
noBorder={false}
data={market.tradableInstrument.riskModel}
unformatted={true}
omits={[]}
/>
),
content: <RiskModelInfoPanel noBorder={false} market={market} />,
},
{
title: t('Risk parameters'),
content: (
<MarketInfoTable
noBorder={false}
data={market.tradableInstrument.riskModel.params}
unformatted={true}
omits={[]}
/>
),
content: <RiskParametersInfoPanel noBorder={false} market={market} />,
},
{
title: t('Risk factors'),
content: (
<MarketInfoTable
noBorder={false}
data={market.riskFactors}
unformatted={true}
omits={['market', '__typename']}
/>
),
content: <RiskFactorsInfoPanel noBorder={false} market={market} />,
},
...(market.priceMonitoringSettings?.parameters?.triggers || []).map(
(trigger, i) => ({
@@ -158,7 +67,10 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
<MarketInfoTable
noBorder={false}
data={{ referencePrice: trigger.referencePrice }}
decimalPlaces={assetDecimals}
decimalPlaces={
market.tradableInstrument.instrument.product.settlementAsset
.decimals
}
/>
</>
),
@@ -166,64 +78,26 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
{
title: t('Liquidity monitoring parameters'),
content: (
<MarketInfoTable
<LiquidityMonitoringParametersInfoPanel
noBorder={false}
data={{
triggeringRatio:
market.liquidityMonitoringParameters.triggeringRatio,
...market.liquidityMonitoringParameters.targetStakeParameters,
}}
market={market}
/>
),
},
{
title: t('Liquidity'),
content: <LiquidityInfoPanel market={market} noBorder={false} />,
},
{
title: t('Liquidity price range'),
content: (
<>
<p className="text-xs mb-4">
{`For liquidity orders to count towards a commitment, they must be
within the liquidity monitoring bounds.`}
</p>
<p className="text-xs mb-4">
{`The liquidity price range is a ${liquidityPriceRange} difference from the mid
price.`}
</p>
<MarketInfoTable
noBorder={false}
data={{
liquidityPriceRange: `${liquidityPriceRange} of mid price`,
lowestPrice:
market.data?.midPrice &&
`${addDecimalsFormatNumber(
new BigNumber(1)
.minus(market.lpPriceRange)
.times(market.data.midPrice)
.toString(),
market.decimalPlaces
)} ${quoteUnit}`,
highestPrice:
market.data?.midPrice &&
`${addDecimalsFormatNumber(
new BigNumber(1)
.plus(market.lpPriceRange)
.times(market.data.midPrice)
.toString(),
market.decimalPlaces
)} ${quoteUnit}`,
}}
></MarketInfoTable>
</>
<LiquidityPriceRangeInfoPanel market={market} noBorder={false} />
),
},
{
title: t('Oracle'),
content: (
<MarketInfoTable
noBorder={false}
data={
market.tradableInstrument.instrument.product.dataSourceSpecBinding
}
>
<OracleInfoPanel noBorder={false} market={market}>
<Link
className="text-xs hover:underline"
to={`/oracles#${market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData.id}`}
@@ -236,7 +110,7 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
>
{t('View termination oracle specification')}
</Link>
</MarketInfoTable>
</OracleInfoPanel>
),
},
];
@@ -244,7 +118,7 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
return (
<>
{panels.map((p) => (
<div className="mb-3">
<div key={p.title} className="mb-3">
<h2 className="font-alpha calt text-xl">{p.title}</h2>
{p.content}
</div>
@@ -1,4 +1,5 @@
import { t } from '@vegaprotocol/i18n';
import { Button } from '@vegaprotocol/ui-toolkit';
import { StatusMessage } from '../status-message';
interface RenderFetchedProps {
@@ -7,6 +8,7 @@ interface RenderFetchedProps {
loading: boolean | undefined;
className?: string;
errorMessage?: string;
refetch?: () => void;
}
export const RenderFetched = ({
@@ -15,6 +17,7 @@ export const RenderFetched = ({
children,
className,
errorMessage = t('Error retrieving data'),
refetch,
}: RenderFetchedProps) => {
if (loading) {
return (
@@ -23,7 +26,20 @@ export const RenderFetched = ({
}
if (error) {
return <StatusMessage className={className}>{errorMessage}</StatusMessage>;
return (
<>
<StatusMessage className={className}>{errorMessage}</StatusMessage>
{refetch && (
<Button
onClick={() => {
refetch();
}}
>
{t('Try again')}
</Button>
)}
</>
);
}
return children;
@@ -8,7 +8,7 @@ import { useScrollToLocation } from '../../hooks/scroll-to-location';
import { useDocumentTitle } from '../../hooks/use-document-title';
import compact from 'lodash/compact';
import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog';
import { marketInfoProvider } from '@vegaprotocol/market-info';
import { marketInfoWithDataProvider } from '@vegaprotocol/market-info';
import { PageTitle } from '../../components/page-helpers/page-title';
export const MarketPage = () => {
@@ -17,7 +17,7 @@ export const MarketPage = () => {
const { marketId } = useParams<{ marketId: string }>();
const { data, loading, error } = useDataProvider({
dataProvider: marketInfoProvider,
dataProvider: marketInfoWithDataProvider,
skipUpdates: true,
variables: {
marketId: marketId || '',
@@ -22,6 +22,7 @@ const Tx = () => {
const {
state: { data, loading, error },
refetch,
} = useFetch<BlockExplorerTransaction>(
`${DATA_SOURCES.blockExplorerUrl}/transactions/${toNonHex(hash)}`
);
@@ -56,6 +57,7 @@ const Tx = () => {
error={error}
loading={loading}
errorMessage={errorMessage}
refetch={refetch}
>
<TxDetails
className="mb-28"
@@ -21,7 +21,7 @@ import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog';
import { PageTitle } from '../../components/page-helpers/page-title';
import BigNumber from 'bignumber.js';
import {
ContractAddressLink,
EtherscanLink,
DApp,
TOKEN_VALIDATOR,
useLinks,
@@ -224,7 +224,7 @@ export const ValidatorsPage = () => {
<KeyValueTableRow>
<div>{t('Ethereum address')}</div>
<div className="break-all text-xs">
<ContractAddressLink address={v.ethereumAddress} />{' '}
<EtherscanLink address={v.ethereumAddress} />{' '}
<CopyWithTooltip text={v.ethereumAddress}>
<button title={t('Copy address to clipboard')}>
<Icon size={3} name="duplicate" />
@@ -0,0 +1,103 @@
const vegaAssetAddress = '0x67175Da1D5e966e40D11c4B2519392B2058373de';
const vegaWalletUnstakedBalance =
'[data-testid="vega-wallet-balance-unstaked"]';
const rewardsTable = 'epoch-total-rewards-table';
const txTimeout = Cypress.env('txTimeout');
const rewardsTimeOut = { timeout: 60000 };
context('rewards - flow', { tags: '@slow' }, function () {
before('set up environment to allow rewards', function () {
cy.visit('/');
cy.wait_for_spinner();
cy.deposit_asset(vegaAssetAddress, '1000');
cy.validatorsSelfDelegate();
cy.ethereum_wallet_connect();
cy.connectVegaWallet();
topUpRewardsPool();
cy.navigate_to('validators');
cy.vega_wallet_teardown();
cy.staking_page_associate_tokens('6000');
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
'6,000.0',
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
cy.click_on_validator_from_list(0);
cy.staking_validator_page_add_stake('3000');
cy.close_staking_dialog();
cy.navigate_to('validators');
cy.click_on_validator_from_list(1);
cy.staking_validator_page_add_stake('3000');
cy.close_staking_dialog();
cy.navigate_to('rewards');
});
it('Should display rewards per epoch', function () {
cy.getByTestId(rewardsTable, rewardsTimeOut).should('exist');
cy.getByTestId(rewardsTable)
.first()
.within(() => {
cy.getByTestId('asset').should('have.text', 'Vega');
cy.getByTestId('ACCOUNT_TYPE_GLOBAL_REWARD').should('have.text', '1');
cy.getByTestId('ACCOUNT_TYPE_FEES_INFRASTRUCTURE').should(
'have.text',
'0'
);
cy.getByTestId('total').should('have.text', '1');
});
});
it('Should update when epoch starts', function () {
cy.getByTestId(rewardsTable)
.first()
.within(() => {
cy.get('h2').first().invoke('text').as('epochNumber');
});
cy.wait_for_beginning_of_epoch();
cy.get('@epochNumber').then((epochNumber) => {
cy.getByTestId(rewardsTable)
.first()
.within(() => {
cy.get('h2').first().invoke('text').should('not.equal', epochNumber);
});
});
});
// 2002-SINC-009 2002-SINC-010 2002-SINC-011 2002-SINC-012
it('Should display table of rewards earned by connected vega wallet', function () {
cy.getByTestId('epoch-reward-view-toggle-individual').click();
cy.getByTestId('connected-vega-key')
.find('span')
.should('have.text', Cypress.env('vegaWalletPublicKey'));
cy.getByTestId('epoch-individual-rewards-table')
.first()
.within(() => {
cy.get('h2').first().should('contain.text', 'EPOCH');
cy.getByTestId('individual-rewards-asset').should('have.text', 'Vega');
cy.getByTestId('ACCOUNT_TYPE_GLOBAL_REWARD')
.should('contain.text', '0.4415')
.and('contain.text', '(44.15%)');
cy.getByTestId('ACCOUNT_TYPE_FEES_INFRASTRUCTURE')
.should('contain.text', '0.0004')
.and('contain.text', '(44.15%)');
cy.getByTestId('total').should('have.text', '0.4419');
});
});
function topUpRewardsPool() {
// Must ensure that test wallet contains assets already and that the tests are within the start and end epochs
cy.exec(
`vega wallet transaction send --wallet ${Cypress.env(
'vegaWalletName'
)} --pubkey ${Cypress.env(
'vegaWalletPublicKey'
)} -p "./src/fixtures/wallet/passphrase" --network DV '{"transfer":{"fromAccountType":4,"toAccountType":12,"to":"0000000000000000000000000000000000000000000000000000000000000000","asset":"b4f2726571fbe8e33b442dc92ed2d7f0d810e21835b7371a7915a365f07ccd9b","amount":"1000000000000000000","recurring":{"startEpoch":30, "endEpoch": 200, "factor":"1"}}}' --home ${Cypress.env(
'vegaWalletLocation'
)}`,
{ failOnNonZeroExit: false }
)
.its('stderr')
.should('contain', '');
}
});
@@ -27,7 +27,7 @@ context(
function () {
before('visit withdrawals and connect vega wallet', function () {
cy.updateCapsuleMultiSig(); // When running tests locally, will fail if run without restarting capsule
cy.deposit_asset(usdcEthAddress);
cy.deposit_asset(usdcEthAddress, '100000000000000000000');
});
beforeEach('Navigate to withdrawal page', function () {
@@ -73,7 +73,7 @@ context(
.should('be.visible')
.and(
'have.text',
'Rewards are credited 5 minutes after the epoch ends.This delay is set by a network parameter'
'Rewards are credited less than a minute after the epoch ends.This delay is set by a network parameter'
);
});
it('should have toggle for seeing total vs individual rewards', () => {
@@ -83,6 +83,7 @@ context('Staking Page - verify elements on page', function () {
.should('contain', 'Normalised voting power: 0.10%');
});
// 2002-SINC-018
it('Should be able to see validator total penalties', function () {
cy.get('[col-id="totalPenalties"] > div > span > span')
.should('have.length.at.least', 1)
@@ -10,7 +10,7 @@ Cypress.Commands.add(
);
const navigation = {
section: 'nav',
section: '[data-testid="navigation"]',
vesting: '[href="/token/redeem"]',
validators: '[href="/validators"]',
rewards: '[href="/rewards"]',
@@ -47,13 +47,14 @@ beforeEach(function () {
cy.wrap(this.vestingContract).as('vestingContract');
});
Cypress.Commands.add('deposit_asset', function (assetEthAddress) {
Cypress.Commands.add('deposit_asset', function (assetEthAddress, amount) {
cy.highlight('Depositing asset into vegawallet');
cy.get('@signer', { log: false }).then((signer) => {
// Approve asset
cy.wrap(
new TokenFaucetable(assetEthAddress, signer).approve(
Erc20BridgeAddress,
'10000000000'
amount + '0'.repeat(19)
)
)
.then((tx) => {
@@ -67,7 +68,7 @@ Cypress.Commands.add('deposit_asset', function (assetEthAddress) {
cy.wrap(
bridge.deposit_asset(
assetEthAddress,
'1000000000',
amount + '0'.repeat(18),
'0x' + vegaWalletPubKey
),
{ timeout: transactionTimeout, log: false }
+1 -1
View File
@@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_ENV=STAGNET3
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
+2 -2
View File
@@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_ENV=DEVNET
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_VEGA_URL=https://api.n00.devnet1.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
@@ -9,4 +9,4 @@ NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-devnet1-k8s.ops.vega.xyz
NX_TRANCHES_SERVICE_URL=https://tranches-devnet1-k8s.ops.vega.xyz
+2 -2
View File
@@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_ENV=MAINNET
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
NX_VEGA_URL=https://api.vega.xyz/query
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://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
@@ -10,4 +10,4 @@ NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-k8s.ops.vega.xyz
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-k8s.ops.vega.xyz
+1 -1
View File
@@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_ENV=MIRROR
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mirror-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
NX_VEGA_URL=https://api.n00.mainnet-mirror.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
+1 -1
View File
@@ -2,7 +2,7 @@
NX_VEGA_URL=https://api.sandbox.vega.xyz/graphql
NX_VEGA_ENV=SANDBOX
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
+2 -2
View File
@@ -2,8 +2,8 @@
NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql
NX_VEGA_ENV=STAGNET1
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet1-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
+2 -2
View File
@@ -2,9 +2,9 @@
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
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_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
+2 -2
View File
@@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_ENV=TESTNET
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_URL=https://api.n08.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
@@ -10,4 +10,4 @@ NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-testnet-k8s.ops.vega.xyz
NX_TRANCHES_SERVICE_URL=https://tranches-testnet-k8s.ops.vega.xyz
+2 -2
View File
@@ -1,7 +1,7 @@
# App configuration variables
NX_VEGA_ENV=VALIDATOR_TESTNET
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/validator-testnet-network.json
NX_VEGA_URL=https://api.validators-testnet.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.toml
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
NX_VEGA_REST=https://api.validators-testnet.vega.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_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
@@ -43,7 +43,7 @@ export const EpochIndividualRewards = () => {
data={data}
render={() => (
<div>
<p className="mb-10">
<p data-testid="connected-vega-key" className="mb-10">
{t('Connected Vega key')}:{' '}
<span className="text-white">{pubKey}</span>
</p>
@@ -166,10 +166,7 @@ export const ConsensusValidatorsTable = ({
avatarUrl,
name,
},
[ValidatorFields.STAKE]: formatNumber(
toBigNum(stakedTotal, decimals),
2
),
[ValidatorFields.STAKE]: stakedTotal,
[ValidatorFields.NORMALISED_VOTING_POWER]:
getNormalisedVotingPower(votingPower),
[ValidatorFields.UNNORMALISED_VOTING_POWER]:
@@ -198,10 +195,8 @@ export const ConsensusValidatorsTable = ({
stakedTotal,
totalStake
),
[ValidatorFields.PENDING_STAKE]: formatNumber(
toBigNum(pendingStake, decimals),
2
),
[ValidatorFields.PENDING_STAKE]: pendingStake,
decimals,
};
}
);
@@ -256,22 +251,18 @@ export const ConsensusValidatorsTable = ({
return {
...acc,
[ValidatorFields.STAKE]: formatNumber(
toBigNum(accStake, decimals).plus(toBigNum(stake, decimals)),
2
),
[ValidatorFields.STAKE]: toBigNum(accStake, decimals)
.plus(toBigNum(stake, decimals))
.toString(),
[ValidatorFields.STAKE_SHARE]: formatNumberPercentage(
new BigNumber(parseFloat(accStakeShare)).plus(
new BigNumber(parseFloat(stakeShare))
),
2
),
[ValidatorFields.PENDING_STAKE]: formatNumber(
toBigNum(accPendingStake, decimals).plus(
toBigNum(pendingStake, decimals)
),
2
),
[ValidatorFields.PENDING_STAKE]: toBigNum(accPendingStake, decimals)
.plus(toBigNum(pendingStake, decimals))
.toString(),
[ValidatorFields.NORMALISED_VOTING_POWER]: formatNumberPercentage(
new BigNumber(parseFloat(accNormalisedVotingPower)).plus(
new BigNumber(parseFloat(normalisedVotingPower))
@@ -349,6 +340,8 @@ export const ConsensusValidatorsTable = ({
field: ValidatorFields.PENDING_STAKE,
headerName: t(ValidatorFields.PENDING_STAKE).toString(),
headerTooltip: t('PendingStakeDescription').toString(),
valueFormatter: ({ value }) =>
formatNumber(toBigNum(value, decimals), 2),
width: 110,
},
],
@@ -12,6 +12,7 @@ import {
} from '@vegaprotocol/ui-toolkit';
import type { NodesFragmentFragment } from '../__generated___/Nodes';
import type { PreviousEpochQuery } from '../../__generated___/PreviousEpoch';
import { useAppState } from '../../../../contexts/app-state/app-state-context';
export enum ValidatorFields {
RANKING_INDEX = 'rankingIndex',
@@ -148,6 +149,11 @@ interface TotalStakeRendererProps {
export const TotalStakeRenderer = ({ data }: TotalStakeRendererProps) => {
const { t } = useTranslation();
const {
appState: { decimals },
} = useAppState();
const formattedStake = formatNumber(toBigNum(data.stake, decimals), 2);
return (
<Tooltip
@@ -160,12 +166,13 @@ export const TotalStakeRenderer = ({ data }: TotalStakeRendererProps) => {
{t('stakedByDelegates')}: {data.stakedByDelegates.toString()}
</div>
<div data-testid="total-staked-tooltip">
{t('totalStake')}: <span className="font-bold">{data.stake}</span>
{t('totalStake')}:{' '}
<span className="font-bold">{formattedStake}</span>
</div>
</>
}
>
<span>{data.stake}</span>
<span>{formattedStake}</span>
</Tooltip>
);
};
@@ -122,10 +122,7 @@ export const StandbyPendingValidatorsTable = ({
avatarUrl,
name,
},
[ValidatorFields.STAKE]: formatNumber(
toBigNum(stakedTotal, decimals),
2
),
[ValidatorFields.STAKE]: stakedTotal,
[ValidatorFields.STAKE_NEEDED_FOR_PROMOTION]:
individualStakeNeededForPromotion || null,
[ValidatorFields.STAKE_NEEDED_FOR_PROMOTION_DESCRIPTION]:
@@ -154,10 +151,7 @@ export const StandbyPendingValidatorsTable = ({
stakedTotal,
totalStake
),
[ValidatorFields.PENDING_STAKE]: formatNumber(
toBigNum(pendingStake, decimals),
2
),
[ValidatorFields.PENDING_STAKE]: pendingStake,
};
}
);
@@ -222,6 +216,8 @@ export const StandbyPendingValidatorsTable = ({
field: ValidatorFields.PENDING_STAKE,
headerName: t(ValidatorFields.PENDING_STAKE).toString(),
headerTooltip: t('PendingStakeDescription').toString(),
valueFormatter: ({ value }) =>
formatNumber(toBigNum(value, decimals), 2),
width: 110,
},
],
+10 -22
View File
@@ -1,7 +1,6 @@
import {
KeyValueTable,
KeyValueTableRow,
Link,
RoundedWrapper,
} from '@vegaprotocol/ui-toolkit';
import { Link as RouterLink } from 'react-router-dom';
@@ -11,7 +10,7 @@ import { useParams } from 'react-router';
import { Navigate } from 'react-router-dom';
import { formatNumber } from '@vegaprotocol/utils';
import { useEnvironment } from '@vegaprotocol/environment';
import { EtherscanLink } from '@vegaprotocol/environment';
import { TrancheItem } from '../redemption/tranche-item';
import Routes from '../routes';
import { TrancheLabel } from './tranche-label';
@@ -19,7 +18,6 @@ import { useTranches } from '../../lib/tranches/tranches-store';
export const Tranche = () => {
const tranches = useTranches((state) => state.tranches);
const { ETHERSCAN_URL } = useEnvironment();
const { t } = useTranslation();
const { trancheId } = useParams<{ trancheId: string; address: string }>();
const { chainId } = useWeb3React();
@@ -59,25 +57,15 @@ export const Tranche = () => {
</KeyValueTableRow>
{tranche.users.map((user) => (
<KeyValueTableRow key={user}>
{
<Link
title={t('View on Etherscan (opens in a new tab)')}
href={`${ETHERSCAN_URL}/address/${user}`}
target="_blank"
>
{user}
</Link>
}
{
<RouterLink
className="underline"
title={t('View vesting information')}
to={`${Routes.REDEEM}/${user}`}
data-testid="redeem-link"
>
{t('View vesting information')}
</RouterLink>
}
<EtherscanLink address={user} data-testid="link" />
<RouterLink
className="underline"
title={t('View vesting information')}
to={`${Routes.REDEEM}/${user}`}
data-testid="redeem-link"
>
{t('View vesting information')}
</RouterLink>
</KeyValueTableRow>
))}
</KeyValueTable>
+1 -1
View File
@@ -17,7 +17,7 @@ NX_INCOMING_HOOK_BODY=$INCOMING_HOOK_BODY
NX_URL=$URL
NX_DEPLOY_URL=$DEPLOY_URL
NX_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
NX_VEGA_CONFIG_URL="https://static.vega.xyz/assets/testnet-network.json"
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_ENV = 'TESTNET'
NX_VEGA_URL="https://api.n11.testnet.vega.xyz/graphql"
NX_VEGA_WALLET_URL=http://localhost:1789
@@ -1,8 +1,8 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
NX_VEGA_ENV=DEVNET
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
NX_VEGA_URL=https://api.vega.xyz/query
NX_VEGA_ENV=MAINNET
NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\",\"TESTNET\":\"https://console.fairground.wtf\"}
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet1-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql
NX_VEGA_ENV=STAGNET1
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
@@ -1,8 +1,8 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_EXPLORER_URL=https://staging2.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_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql
NX_VEGA_ENV=TESTNET
NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\",\"TESTNET\":\"https://console.fairground.wtf\"}
+1 -1
View File
@@ -1,5 +1,5 @@
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=STAGNET3
+1 -1
View File
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=DEVNET
+1 -1
View File
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
NX_VEGA_URL=https://api.vega.xyz/query
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=MAINNET
+2 -2
View File
@@ -1,5 +1,5 @@
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
NX_VEGA_URL=https://api.sandbox.vega.xyz/graphql
NX_VEGA_ENV=SANDBOX
NX_VEGA_NETWORKS={\"DEVNET\":\"https://dev.token.vega.xyz\",\"STAGNET3\":\"https://stagnet3.token.vega.xyz\",\"STAGNET1\":\"https://stagnet1.token.vega.xyz\",\"TESTNET\":\"https://token.fairground.wtf\",\"MAINNET\":\"https://token.vega.xyz\"}
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
+1 -1
View File
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_URL=https://api.stagnet3.vega.xyz/graphql
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=STAGNET3
+1 -1
View File
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_URL=https://api.n09.testnet.vega.xyz/graphql
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=TESTNET
+2 -2
View File
@@ -1,5 +1,5 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/validator-testnet-network.json
NX_VEGA_URL=https://api.validators-testnet.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.tom
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
NX_VEGA_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
NX_VEGA_ENV=VALIDATOR_TESTNET
File diff suppressed because it is too large Load Diff
@@ -1,3 +1,6 @@
{
"hosts": ["https://api.validators-testnet.vega.xyz/graphql"]
"hosts": [
"https://api-validators-testnet.vega.rocks/graphql",
"https://vega-testnet.anyvalid.com/query"
]
}
+1 -1
View File
@@ -1,7 +1,7 @@
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/stagnet3-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_ENV=STAGNET3
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
@@ -71,7 +71,8 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
validateMarketDataRow(3, 'Quote Name', 'BTC');
});
it('settlement asset displayed', () => {
// need to check why data are not visible
it.skip('settlement asset displayed', () => {
cy.getByTestId(marketTitle).contains('Settlement asset').click();
cy.window().then((win) => {
cy.stub(win, 'prompt').returns('DISABLED WINDOW PROMPT');
@@ -131,7 +132,6 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
cy.get('p.col-span-1').contains('Within 43,200 seconds');
validateMarketDataRow(0, 'Highest Price', '7.97323 ');
validateMarketDataRow(1, 'Lowest Price', '6.54701 ');
validateMarketDataRow(2, 'Reference Price', '7.22625 ');
});
it('liquidity monitoring parameters displayed', () => {
@@ -22,24 +22,25 @@ describe('accounts', { tags: '@smoke' }, () => {
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="breakdown"] [data-testid="breakdown"]')
.should('have.text', 'Breakdown');
.find('[col-id="accounts-actions"]')
.should('have.text', 'DepositWithdraw');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="breakdown"] [data-testid="deposit"]')
.find('[data-testid="deposit"]')
.should('have.text', 'Deposit');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="breakdown"] [data-testid="withdraw"]')
.find('[col-id="accounts-actions"] [data-testid="withdraw"]')
.should('have.text', 'Withdraw');
cy.getByTestId('tab-accounts')
.get(tradingAccountRowId)
.find('[col-id="deposited"]')
.find('[col-id="total"]')
.should('have.text', '100,001.01');
});
describe('sorting by ag-grid columns should work well', () => {
it('sorting by asset', () => {
cy.getByTestId('Collateral').click();
@@ -78,7 +79,7 @@ describe('accounts', { tags: '@smoke' }, () => {
'1,000.00',
];
checkSorting(
'deposited',
'total',
marketsSortedDefault,
marketsSortedAsc,
marketsSortedDesc
@@ -87,9 +88,27 @@ describe('accounts', { tags: '@smoke' }, () => {
it('sorting by used', () => {
cy.getByTestId('Collateral').click();
const marketsSortedDefault = ['0.00', '1.01', '0.01', '0.00', '0.00'];
const marketsSortedAsc = ['0.00', '0.00', '0.00', '0.01', '1.01'];
const marketsSortedDesc = ['1.01', '0.01', '0.00', '0.00', '0.00'];
const marketsSortedDefault = [
'0.000.00%',
'1.010.00%',
'0.010.00%',
'0.000.00%',
'0.000.00%',
];
const marketsSortedAsc = [
'0.000.00%',
'0.000.00%',
'0.000.00%',
'0.010.00%',
'1.010.00%',
];
const marketsSortedDesc = [
'1.010.00%',
'0.010.00%',
'0.000.00%',
'0.000.00%',
'0.000.00%',
];
checkSorting(
'used',
marketsSortedDefault,
@@ -98,32 +117,32 @@ describe('accounts', { tags: '@smoke' }, () => {
);
});
it('sorting by available', () => {
it('sorting by total', () => {
cy.getByTestId('Collateral').click();
const marketsSortedDefault = [
'1,000.00002',
'100,000.00',
'1,000.00',
'100,001.01',
'1,000.01',
'1,000.00',
'1,000.00001',
];
const marketsSortedAsc = [
'1,000.00',
'1,000.00',
'1,000.00001',
'1,000.00002',
'100,000.00',
'1,000.01',
'100,001.01',
];
const marketsSortedDesc = [
'100,000.00',
'100,001.01',
'1,000.01',
'1,000.00002',
'1,000.00001',
'1,000.00',
'1,000.00',
];
checkSorting(
'available',
'total',
marketsSortedDefault,
marketsSortedAsc,
marketsSortedDesc
@@ -30,9 +30,6 @@ describe('orders list', { tags: '@smoke' }, () => {
cy.setVegaWallet();
cy.visit('/#/markets/market-0');
cy.getByTestId('Orders').click();
cy.wait('@Orders').then(() => {
expect(subscriptionMocks.OrdersUpdate).to.be.calledThrice;
});
cy.wait('@Markets');
});
@@ -135,14 +132,19 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
cy.setVegaWallet();
cy.visit('/#/markets/market-0');
cy.getByTestId('Orders').click();
cy.wait('@Orders').then(() => {
expect(subscriptionMocks.OrdersUpdate).to.be.calledThrice;
cy.getByTestId('tab-orders').within(() => {
cy.get('[col-id="status"][role="columnheader"]')
.focus()
.find('.ag-header-cell-menu-button')
.click();
cy.get('.ag-filter-apply-panel-button').click();
});
});
const orderId = '1234567890';
// 7002-SORD-053
// 7002-SORD-040
// 7003-MORD-001
it('must see an active order', () => {
// 7002-SORD-041
updateOrder({
@@ -151,6 +153,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
});
cy.getByTestId(`order-status-${orderId}`).should('have.text', 'Active');
});
it('must see an expired order', () => {
// 7002-SORD-042
updateOrder({
@@ -353,8 +356,12 @@ describe('amend and cancel order', { tags: '@smoke' }, () => {
cy.setVegaWallet();
cy.visit('/#/markets/market-0');
cy.getByTestId('Orders').click();
cy.wait('@Orders').then(() => {
expect(subscriptionMocks.OrdersUpdate).to.be.calledThrice;
cy.getByTestId('tab-orders').within(() => {
cy.get('[col-id="status"][role="columnheader"]')
.focus()
.find('.ag-header-cell-menu-button')
.click();
cy.get('.ag-filter-apply-panel-button').click();
});
cy.mockVegaWalletTransaction();
});
@@ -50,7 +50,6 @@ describe('positions', { tags: '@smoke' }, () => {
const emptyCells = [
'notional',
'markPrice',
'liquidationPrice',
'currentLeverage',
'averageEntryPrice',
];
@@ -162,8 +161,6 @@ describe('positions', { tags: '@smoke' }, () => {
cy.wrap($prices).invoke('text').should('not.be.empty');
});
cy.get('[col-id="liquidationPrice"]').should('contain.text', '0'); // liquidation price
cy.get('[col-id="currentLeverage"]').should('contain.text', '2.846.1');
cy.get('[col-id="marginAccountBalance"]') // margin allocated
@@ -0,0 +1,58 @@
import { connectEthereumWallet } from '../support/ethereum-wallet';
const connectEthWalletBtn = 'connect-eth-wallet-btn';
describe('ethereum wallet', { tags: '@smoke' }, () => {
beforeEach(() => {
cy.mockWeb3Provider();
// Using portfolio withdrawals tab is it requires Ethereum wallet connection
cy.mockTradingPage();
cy.mockSubscription();
cy.setVegaWallet();
cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist');
cy.getByTestId('Withdrawals').click();
});
it('can connect', () => {
// 0004-EWAL-001
cy.wait('@NetworkParams');
cy.getByTestId('Deposits').click();
cy.getByTestId('deposit-button').click();
cy.getByTestId('connect-eth-wallet-btn').click();
cy.getByTestId('web3-connector-list').should('exist');
cy.getByTestId('web3-connector-MetaMask').click();
cy.getByTestId('web3-connector-list').should('not.exist');
cy.getByTestId('tab-deposits').should('not.be.empty');
});
it('should see an option to cancel the attempted connection', () => {
// 0004-EWAL-003
cy.wait('@NetworkParams');
cy.getByTestId('Deposits').click();
cy.getByTestId('deposit-button').click();
cy.getByTestId('connect-eth-wallet-btn').click();
cy.getByTestId('web3-connector-list').should('exist');
cy.getByTestId('web3-connector-WalletConnect').click();
cy.get('#walletconnect-qrcode-text').should('exist');
cy.get('#walletconnect-qrcode-close').click();
});
it('able to disconnect eth wallet', () => {
// 0004-EWAL-004
// 0004-EWAL-005
// 0004-EWAL-006
const ethWalletAddress = Cypress.env('ETHEREUM_WALLET_ADDRESS');
cy.getByTestId('Deposits').click();
cy.getByTestId('deposit-button').click();
connectEthereumWallet('MetaMask');
cy.getByTestId('ethereum-address').should('have.text', ethWalletAddress);
cy.getByTestId('disconnect-ethereum-wallet')
.should('have.text', 'Disconnect')
.click();
cy.getByTestId(connectEthWalletBtn).should('exist');
});
});
@@ -1,7 +1,8 @@
import { mockConnectWallet } from '@vegaprotocol/cypress';
import { connectEthereumWallet } from '../support/ethereum-wallet';
import {
mockConnectWallet,
mockConnectWalletWithUserError,
} from '@vegaprotocol/cypress';
const connectEthWalletBtn = 'connect-eth-wallet-btn';
const connectVegaBtn = 'connect-vega-wallet';
const manageVegaBtn = 'manage-vega-wallet';
const form = 'rest-connector-form';
@@ -127,6 +128,21 @@ describe('connect vega wallet', { tags: '@smoke' }, () => {
cy.getByTestId(manageVegaBtn).should('exist');
});
it.only('can not connect', () => {
// 0002-WCON-002
// 0002-WCON-005
// 0002-WCON-007
mockConnectWalletWithUserError();
cy.getByTestId(connectVegaBtn).click();
cy.getByTestId('connectors-list')
.find('[data-testid="connector-jsonRpc"]')
.click();
cy.getByTestId('dialog-content')
.should('contain.text', 'User error')
.and('contain.text', 'the user rejected the wallet connection');
});
it('can change selected public key and disconnect', () => {
// 0002-WCON-022
// 0002-WCON-023
@@ -164,39 +180,3 @@ describe('connect vega wallet', { tags: '@smoke' }, () => {
);
});
});
describe('ethereum wallet', { tags: '@smoke' }, () => {
beforeEach(() => {
cy.mockWeb3Provider();
// Using portfolio withdrawals tab is it requires Ethereum wallet connection
cy.mockTradingPage();
cy.mockSubscription();
cy.setVegaWallet();
cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist');
cy.getByTestId('Withdrawals').click();
});
it('can connect', () => {
cy.wait('@NetworkParams');
cy.getByTestId('Deposits').click();
cy.getByTestId('deposit-button').click();
cy.getByTestId('connect-eth-wallet-btn').click();
cy.getByTestId('web3-connector-list').should('exist');
cy.getByTestId('web3-connector-MetaMask').click();
cy.getByTestId('web3-connector-list').should('not.exist');
cy.getByTestId('tab-deposits').should('not.be.empty');
});
it('able to disconnect eth wallet', () => {
const ethWalletAddress = Cypress.env('ETHEREUM_WALLET_ADDRESS');
cy.getByTestId('Deposits').click();
cy.getByTestId('deposit-button').click();
connectEthereumWallet('MetaMask');
cy.getByTestId('ethereum-address').should('have.text', ethWalletAddress);
cy.getByTestId('disconnect-ethereum-wallet')
.should('have.text', 'Disconnect')
.click();
cy.getByTestId(connectEthWalletBtn).should('exist');
});
});
+1 -1
View File
@@ -1,7 +1,7 @@
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/stagnet3-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_ENV=STAGNET3
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
+1 -1
View File
@@ -1,7 +1,7 @@
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/devnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_VEGA_ENV=DEVNET
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
+1 -1
View File
@@ -1,6 +1,6 @@
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://etherscan.io
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
NX_VEGA_ENV=MAINNET
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\",\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
+1 -1
View File
@@ -1,7 +1,7 @@
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/mirror-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
NX_VEGA_ENV=MIRROR
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\"}
+1 -2
View File
@@ -1,10 +1,9 @@
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.sandbox.vega.xyz
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
NX_VEGA_ENV=SANDBOX
NX_VEGA_NETWORKS={\"DEVNET\":\"https://dev.token.vega.xyz\",\"STAGNET3\":\"https://stagnet3.token.vega.xyz\",\"STAGNET1\":\"https://stagnet1.token.vega.xyz\",\"TESTNET\":\"https://token.fairground.wtf\",\"MAINNET\":\"https://token.vega.xyz\"}
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 -1
View File
@@ -1,7 +1,7 @@
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/stagnet1-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_ENV=STAGNET1
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
+1 -1
View File
@@ -1,7 +1,7 @@
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/stagnet3-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_ENV=STAGNET3
NX_VEGA_EXPLORER_URL=https://stagnet3.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
+1 -1
View File
@@ -1,7 +1,7 @@
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/testnet-network.json
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_ENV=TESTNET
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
+1 -1
View File
@@ -1,7 +1,7 @@
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_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.toml
NX_VEGA_ENV=VALIDATOR_TESTNET
NX_VEGA_EXPLORER_URL=https://validator-testnet.explorer.vega.xyz
NX_VEGA_NETWORKS={\"STAGNET3\":\"https://stagnet3.console.vega.xyz\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"TESTNET\":\"https://console.fairground.wtf\"}
@@ -25,7 +25,8 @@ export const DepositsContainer = () => {
<div className="h-full relative">
<DepositsTable
rowData={data || []}
noRowsOverlayComponent={() => null}
suppressLoadingOverlay
suppressNoRowsOverlay
ref={gridRef}
{...bottomPlaceholderProps}
/>
@@ -24,7 +24,8 @@ export const WithdrawalsContainer = () => {
<WithdrawalsTable
data-testid="withdrawals-history"
rowData={data}
noRowsOverlayComponent={() => null}
suppressLoadingOverlay
suppressNoRowsOverlay
/>
<div className="pointer-events-none absolute inset-0">
<AsyncRenderer
+33 -15
View File
@@ -1,20 +1,30 @@
import { render, screen } from '@testing-library/react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { NodeHealth, NodeUrl, HealthIndicator } from './footer';
import { MockedProvider } from '@apollo/client/testing';
import { Intent } from '@vegaprotocol/ui-toolkit';
jest.mock('@vegaprotocol/environment', () => ({
...jest.requireActual('@vegaprotocol/environment'),
useEnvironment: jest
.fn()
.mockImplementation(() => ({ VEGA_URL: 'https://vega-url.wtf' })),
}));
const mockSetNodeSwitcher = jest.fn();
jest.mock('../../stores', () => ({
...jest.requireActual('../../stores'),
useGlobalStore: () => mockSetNodeSwitcher,
}));
describe('NodeHealth', () => {
it('controls the node switcher dialog', async () => {
const mockOnClick = jest.fn();
render(
<NodeHealth
onClick={mockOnClick}
url={'https://api.n99.somenetwork.vega.xyz'}
blockHeight={100}
blockDiff={0}
/>
);
render(<NodeHealth />, { wrapper: MockedProvider });
await waitFor(() => {
expect(screen.getByRole('button')).toBeInTheDocument();
});
await userEvent.click(screen.getByRole('button'));
expect(mockOnClick).toHaveBeenCalled();
expect(mockSetNodeSwitcher).toHaveBeenCalled();
});
});
@@ -31,14 +41,22 @@ describe('NodeUrl', () => {
describe('HealthIndicator', () => {
const cases = [
{ diff: 0, classname: 'bg-vega-green-550', text: 'Operational' },
{ diff: 5, classname: 'bg-warning', text: '5 Blocks behind' },
{ diff: null, classname: 'bg-danger', text: 'Non operational' },
{
intent: Intent.Success,
text: 'Operational',
classname: 'bg-vega-green-550',
},
{
intent: Intent.Warning,
text: '5 Blocks behind',
classname: 'bg-warning',
},
{ intent: Intent.Danger, text: 'Non operational', classname: 'bg-danger' },
];
it.each(cases)(
'renders correct text and indicator color for $diff block difference',
(elem) => {
render(<HealthIndicator blockDiff={elem.diff} />);
render(<HealthIndicator text={elem.text} intent={elem.intent} />);
expect(screen.getByTestId('indicator')).toHaveClass(elem.classname);
expect(screen.getByText(elem.text)).toBeInTheDocument();
}
+21 -56
View File
@@ -1,60 +1,45 @@
import { useCallback } from 'react';
import { useEnvironment, useNodeHealth } from '@vegaprotocol/environment';
import { useNavigatorOnline } from '@vegaprotocol/react-helpers';
import { t } from '@vegaprotocol/i18n';
import { Indicator, Intent } from '@vegaprotocol/ui-toolkit';
import type { Intent } from '@vegaprotocol/ui-toolkit';
import { Indicator } from '@vegaprotocol/ui-toolkit';
import classNames from 'classnames';
import type { ButtonHTMLAttributes, ReactNode } from 'react';
import { useGlobalStore } from '../../stores';
export const Footer = () => {
const { VEGA_URL } = useEnvironment();
const setNodeSwitcher = useGlobalStore(
(store) => (open: boolean) => store.update({ nodeSwitcherDialog: open })
);
const { blockDiff, datanodeBlockHeight } = useNodeHealth();
return (
<footer className="px-4 py-1 text-xs border-t border-default text-vega-light-300 dark:text-vega-dark-300 lg:fixed bottom-0 left-0 border-r bg-white dark:bg-black">
{/* Pull left to align with top nav, due to button padding */}
<div className="-ml-2">
{VEGA_URL && (
<NodeHealth
url={VEGA_URL}
blockHeight={datanodeBlockHeight}
blockDiff={blockDiff}
onClick={() => setNodeSwitcher(true)}
/>
)}
<NodeHealth />
</div>
</footer>
);
};
interface NodeHealthProps {
url: string;
blockHeight: number | undefined;
blockDiff: number | null;
onClick: () => void;
}
export const NodeHealth = ({
url,
blockHeight,
blockDiff,
onClick,
}: NodeHealthProps) => {
return (
export const NodeHealth = () => {
const { VEGA_URL } = useEnvironment();
const setNodeSwitcher = useGlobalStore(
(store) => (open: boolean) => store.update({ nodeSwitcherDialog: open })
);
const { datanodeBlockHeight, text, intent } = useNodeHealth();
const onClick = useCallback(() => {
setNodeSwitcher(true);
}, [setNodeSwitcher]);
return VEGA_URL ? (
<FooterButton onClick={onClick} data-testid="node-health">
<FooterButtonPart>
<HealthIndicator blockDiff={blockDiff} />
<HealthIndicator text={text} intent={intent} />
</FooterButtonPart>
<FooterButtonPart>
<NodeUrl url={url} />
<NodeUrl url={VEGA_URL} />
</FooterButtonPart>
<FooterButtonPart>
<span title={t('Block height')}>{blockHeight}</span>
<span title={t('Block height')}>{datanodeBlockHeight}</span>
</FooterButtonPart>
</FooterButton>
);
) : null;
};
interface NodeUrlProps {
@@ -69,31 +54,11 @@ export const NodeUrl = ({ url }: NodeUrlProps) => {
};
interface HealthIndicatorProps {
blockDiff: number | null;
text: string;
intent: Intent;
}
// How many blocks behind the most advanced block that is
// deemed acceptable for "Good" status
const BLOCK_THRESHOLD = 3;
export const HealthIndicator = ({ blockDiff }: HealthIndicatorProps) => {
const online = useNavigatorOnline();
let intent = Intent.Success;
let text = 'Operational';
if (!online) {
text = t('Offline');
intent = Intent.Danger;
} else if (blockDiff === null) {
// Block height query failed and null was returned
text = t('Non operational');
intent = Intent.Danger;
} else if (blockDiff >= BLOCK_THRESHOLD) {
text = t(`${blockDiff} Blocks behind`);
intent = Intent.Warning;
}
export const HealthIndicator = ({ text, intent }: HealthIndicatorProps) => {
return (
<span title={t('Node health')}>
<Indicator variant={intent} />
@@ -145,7 +145,8 @@ export const VegaWalletConnectButton = () => {
(store) => store.openVegaWalletDialog
);
const openTransferDialog = useTransferDialog((store) => store.open);
const { pubKey, pubKeys, selectPubKey, disconnect } = useVegaWallet();
const { pubKey, pubKeys, selectPubKey, disconnect, isReadOnly } =
useVegaWallet();
const isConnected = pubKey !== null;
const activeKey = useMemo(() => {
@@ -186,12 +187,14 @@ export const VegaWalletConnectButton = () => {
))}
</DropdownMenuRadioGroup>
<DropdownMenuSeparator />
<DropdownMenuItem
data-testid="wallet-transfer"
onClick={() => openTransferDialog(true)}
>
{t('Transfer')}
</DropdownMenuItem>
{!isReadOnly && (
<DropdownMenuItem
data-testid="wallet-transfer"
onClick={() => openTransferDialog(true)}
>
{t('Transfer')}
</DropdownMenuItem>
)}
<DropdownMenuItem data-testid="disconnect" onClick={disconnect}>
{t('Disconnect')}
</DropdownMenuItem>
@@ -1,6 +1,6 @@
import type { ReactNode } from 'react';
import { useAssetsDataProvider } from '@vegaprotocol/assets';
import { ETHERSCAN_TX, useEtherscanLink } from '@vegaprotocol/environment';
import { EtherscanLink } from '@vegaprotocol/environment';
import { formatNumber, toBigNum } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import type { Toast, ToastContent } from '@vegaprotocol/ui-toolkit';
@@ -8,7 +8,7 @@ import { ToastHeading } from '@vegaprotocol/ui-toolkit';
import { Panel } from '@vegaprotocol/ui-toolkit';
import { CLOSE_AFTER } from '@vegaprotocol/ui-toolkit';
import { useToasts } from '@vegaprotocol/ui-toolkit';
import { ExternalLink, Intent, ProgressBar } from '@vegaprotocol/ui-toolkit';
import { Intent, ProgressBar } from '@vegaprotocol/ui-toolkit';
import { useCallback } from 'react';
import compact from 'lodash/compact';
import type { EthStoredTxState } from '@vegaprotocol/web3';
@@ -103,7 +103,7 @@ const EthTxPendingToastContent = ({ tx }: EthTxToastContentProps) => {
<>
<ToastHeading>{t('Awaiting confirmation')}</ToastHeading>
<p>{t('Please wait for your transaction to be confirmed.')}</p>
<EtherscanLink tx={tx} />
{tx.txHash && <EtherscanLink tx={tx.txHash} />}
<EthTransactionDetails tx={tx} />
</>
);
@@ -126,26 +126,12 @@ const EthTxErrorToastContent = ({ tx }: EthTxToastContentProps) => {
);
};
const EtherscanLink = ({ tx }: EthTxToastContentProps) => {
const etherscanLink = useEtherscanLink();
return tx.txHash ? (
<p className="break-all">
<ExternalLink
href={etherscanLink(ETHERSCAN_TX.replace(':hash', tx.txHash))}
rel="noreferrer"
>
{t('View on Etherscan')}
</ExternalLink>
</p>
) : null;
};
const EthTxConfirmedToastContent = ({ tx }: EthTxToastContentProps) => {
return (
<>
<ToastHeading>{t('Transaction confirmed')}</ToastHeading>
<p>{t('Your transaction has been confirmed.')}</p>
<EtherscanLink tx={tx} />
{tx.txHash && <EtherscanLink tx={tx.txHash} />}
<EthTransactionDetails tx={tx} />
</>
);
@@ -162,7 +148,7 @@ const EthTxCompletedToastContent = ({ tx }: EthTxToastContentProps) => {
{t('Your transaction has been completed.')}{' '}
{isDeposit && t('Waiting for deposit confirmation.')}
</p>
<EtherscanLink tx={tx} />
{tx.txHash && <EtherscanLink tx={tx.txHash} />}
<EthTransactionDetails tx={tx} />
</>
);
@@ -523,6 +523,16 @@ const VegaTxCompleteToastsContent = ({ tx }: VegaTxToastContentProps) => {
<div>
<h3 className="font-bold">{t('Transfer complete')}</h3>
<p>{t('Your transaction has been confirmed ')}</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>
);
+1 -1
View File
@@ -83,8 +83,8 @@ function AppBody({ Component }: AppProps) {
</Head>
<Title />
<div className={gridClasses}>
<Navbar theme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'system'} />
<Banner />
<Navbar theme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'system'} />
<ViewingBanner />
<main data-testid={location.pathname}>
<Component />
@@ -159,38 +159,50 @@ const accountResult = [
{
asset: {
__typename: 'Asset',
decimals: 5,
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
symbol: 'tBTC',
decimals: 5,
},
available: '4000000000000001006031',
balance: '4000000000000001006031',
breakdown: [],
deposited: '4000000000000001006031',
type: AccountType.ACCOUNT_TYPE_GENERAL,
type: 'ACCOUNT_TYPE_GENERAL',
available: '4000000000000001006031',
used: '0',
total: '4000000000000001006031',
breakdown: [
{
__typename: 'AccountBalance',
type: 'ACCOUNT_TYPE_GENERAL',
balance: '4000000000000001006031',
market: null,
asset: {
__typename: 'Asset',
id: '5cfa87844724df6069b94e4c8a6f03af21907d7bc251593d08e4251043ee9f7c',
symbol: 'tBTC',
decimals: 5,
},
total: '4000000000000001006031',
available: '4000000000000001006031',
used: '4000000000000001006031',
},
],
},
{
asset: {
__typename: 'Asset',
decimals: 5,
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
decimals: 5,
},
available: '5000593078',
balance: '5000593078',
type: 'ACCOUNT_TYPE_GENERAL',
available: '5000593078',
used: '406922',
total: '5001000000',
breakdown: [
{
__typename: 'AccountBalance',
asset: {
__typename: 'Asset',
decimals: 5,
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
},
available: '5000593078',
type: 'ACCOUNT_TYPE_MARGIN',
balance: '406922',
deposited: '5001000000',
market: {
__typename: 'Market',
id: '9c1ee71959e566c484fcea796513137f8a02219cca2e973b7ae72dc29d099581',
@@ -202,35 +214,50 @@ const accountResult = [
},
},
},
type: AccountType.ACCOUNT_TYPE_MARGIN,
asset: {
__typename: 'Asset',
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
decimals: 5,
},
total: '5001000000',
available: '5000593078',
used: '406922',
},
{
__typename: 'AccountBalance',
type: 'ACCOUNT_TYPE_GENERAL',
balance: '5000593078',
market: null,
asset: {
__typename: 'Asset',
id: '6d9d35f657589e40ddfb448b7ad4a7463b66efb307527fedd2aa7df1bbd5ea61',
symbol: 'tDAI',
decimals: 5,
},
total: '5001000000',
available: '5000593078',
used: '5000593078',
},
],
deposited: '5001000000',
type: AccountType.ACCOUNT_TYPE_GENERAL,
used: '406922',
},
{
asset: {
__typename: 'Asset',
decimals: 5,
id: '8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4',
symbol: 'tEURO',
decimals: 5,
},
available: '2996218603',
balance: '2996218603',
type: 'ACCOUNT_TYPE_GENERAL',
available: '2996218603',
used: '2781397',
total: '2999000000',
breakdown: [
{
__typename: 'AccountBalance',
asset: {
__typename: 'Asset',
decimals: 5,
id: '8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4',
symbol: 'tEURO',
},
available: '2996218603',
type: 'ACCOUNT_TYPE_MARGIN',
balance: '2781397',
deposited: '2999000000',
market: {
__typename: 'Market',
id: 'd90fd7c746286625504d7a3f5f420a280875acd3cd611676d9e70acc675f4540',
@@ -242,40 +269,91 @@ const accountResult = [
},
},
},
type: AccountType.ACCOUNT_TYPE_MARGIN,
asset: {
__typename: 'Asset',
id: '8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4',
symbol: 'tEURO',
decimals: 5,
},
total: '2999000000',
available: '2996218603',
used: '2781397',
},
{
__typename: 'AccountBalance',
type: 'ACCOUNT_TYPE_GENERAL',
balance: '2996218603',
market: null,
asset: {
__typename: 'Asset',
id: '8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4',
symbol: 'tEURO',
decimals: 5,
},
total: '2999000000',
available: '2996218603',
used: '2996218603',
},
],
deposited: '2999000000',
type: AccountType.ACCOUNT_TYPE_GENERAL,
used: '2781397',
},
{
asset: {
__typename: 'Asset',
decimals: 5,
id: '993ed98f4f770d91a796faab1738551193ba45c62341d20597df70fea6704ede',
symbol: 'tUSDC',
decimals: 5,
},
available: '1990351587',
balance: '1990351587',
breakdown: [],
deposited: '1990351587',
type: AccountType.ACCOUNT_TYPE_GENERAL,
type: 'ACCOUNT_TYPE_GENERAL',
available: '1990351587',
used: '0',
total: '1990351587',
breakdown: [
{
__typename: 'AccountBalance',
type: 'ACCOUNT_TYPE_GENERAL',
balance: '1990351587',
market: null,
asset: {
__typename: 'Asset',
id: '993ed98f4f770d91a796faab1738551193ba45c62341d20597df70fea6704ede',
symbol: 'tUSDC',
decimals: 5,
},
total: '1990351587',
available: '1990351587',
used: '1990351587',
},
],
},
{
asset: {
__typename: 'Asset',
decimals: 5,
id: 'XYZalpha',
symbol: 'XYZalpha',
decimals: 5,
},
available: '10001000000',
balance: '10001000000',
breakdown: [],
deposited: '10001000000',
type: AccountType.ACCOUNT_TYPE_GENERAL,
type: 'ACCOUNT_TYPE_GENERAL',
available: '10001000000',
used: '0',
total: '10001000000',
breakdown: [
{
__typename: 'AccountBalance',
type: 'ACCOUNT_TYPE_GENERAL',
balance: '10001000000',
market: null,
asset: {
__typename: 'Asset',
id: 'XYZalpha',
symbol: 'XYZalpha',
decimals: 5,
},
total: '10001000000',
available: '10001000000',
used: '10001000000',
},
],
},
] as AccountFields[];
@@ -99,7 +99,7 @@ export const accountsOnlyDataProvider = makeDataProvider<
export interface AccountFields extends Account {
available: string;
used: string;
deposited: string;
total: string;
balance: string;
breakdown?: AccountFields[];
}
@@ -145,15 +145,17 @@ const getAssetAccountAggregation = (
type: AccountType.ACCOUNT_TYPE_GENERAL,
available: available.toString(),
used: used.toString(),
deposited: (available + used).toString(),
total: (available + used).toString(),
};
const breakdown = accounts
.filter((a) => USE_ACCOUNT_TYPES.includes(a.type))
.filter((a) =>
[...USE_ACCOUNT_TYPES, AccountType.ACCOUNT_TYPE_GENERAL].includes(a.type)
)
.map((a) => ({
...a,
asset: accounts[0].asset,
deposited: balanceAccount.deposited,
total: balanceAccount.total,
available: balanceAccount.available,
used: a.balance,
}))
+87 -51
View File
@@ -15,51 +15,29 @@ jest.mock('@vegaprotocol/react-helpers', () => ({
}));
describe('AccountManager', () => {
beforeEach(() => {
mockedUseDataProvider
.mockImplementationOnce((args) => {
return {
data: [],
};
})
.mockImplementationOnce((args) => {
return {
data: [
{ asset: { id: 'a1' }, party: { id: 't1' } },
{ asset: { id: 'a2' }, party: { id: 't2' } },
],
};
});
});
it('change partyId should reload data provider', async () => {
const { rerender } = render(
<AccountManager
partyId="partyOne"
onClickAsset={jest.fn}
isReadOnly={false}
/>
);
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}
/>
);
describe('when rerender', () => {
beforeEach(() => {
mockedUseDataProvider
.mockImplementationOnce((args) => {
return {
data: [],
};
})
.mockImplementationOnce((args) => {
return {
data: [
{ asset: { id: 'a1' }, party: { id: 't1' } },
{ asset: { id: 'a2' }, party: { id: 't2' } },
],
};
});
});
expect(
(helpers.useDataProvider as jest.Mock).mock.calls[1][0].variables.partyId
).toEqual('partyTwo');
});
it('update method should return proper result', async () => {
let rerenderer: (ui: React.ReactElement) => void;
await act(() => {
afterEach(() => {
jest.clearAllMocks();
});
it('change partyId should reload data provider', async () => {
const { rerender } = render(
<AccountManager
partyId="partyOne"
@@ -67,13 +45,67 @@ describe('AccountManager', () => {
isReadOnly={false}
/>
);
rerenderer = rerender;
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}
/>
);
});
expect(
(helpers.useDataProvider as jest.Mock).mock.calls[1][0].variables
.partyId
).toEqual('partyTwo');
});
await waitFor(() => {
expect(screen.getByText('No accounts')).toBeInTheDocument();
it('update method should return proper result', async () => {
let rerenderer: (ui: React.ReactElement) => void;
await act(() => {
const { rerender } = render(
<AccountManager
partyId="partyOne"
onClickAsset={jest.fn}
isReadOnly={false}
/>
);
rerenderer = rerender;
});
await waitFor(() => {
expect(screen.getByText('No accounts')).toBeInTheDocument();
});
await act(() => {
rerenderer(
<AccountManager
partyId="partyOne"
onClickAsset={jest.fn}
isReadOnly={false}
/>
);
});
const container = document.querySelector('.ag-center-cols-container');
await waitFor(() => {
expect(container).toBeInTheDocument();
});
expect(getAllByRole(container as HTMLDivElement, 'row')).toHaveLength(2);
});
});
it('splash loading should be displayed', async () => {
mockedUseDataProvider.mockImplementation((args) => {
return {
loading: true,
data: null,
};
});
await act(() => {
rerenderer(
render(
<AccountManager
partyId="partyOne"
onClickAsset={jest.fn}
@@ -81,11 +113,15 @@ describe('AccountManager', () => {
/>
);
});
const container = document.querySelector('.ag-center-cols-container');
await waitFor(() => {
expect(container).toBeInTheDocument();
expect(
screen.getByText(
(content, element) =>
Boolean(
element?.className.endsWith('flex items-center justify-center')
) && content.startsWith('Loading')
)
).toBeInTheDocument();
});
expect(getAllByRole(container as HTMLDivElement, 'row')).toHaveLength(2);
});
});
+2 -1
View File
@@ -60,7 +60,8 @@ export const AccountManager = ({
onClickDeposit={onClickDeposit}
onClickWithdraw={onClickWithdraw}
isReadOnly={isReadOnly}
noRowsOverlayComponent={() => null}
suppressLoadingOverlay
suppressNoRowsOverlay
pinnedAsset={pinnedAsset}
getRowHeight={getRowHeight}
{...bottomPlaceholderProps}
+7 -13
View File
@@ -27,7 +27,7 @@ const singleRow = {
},
available: '125600000',
used: '125600000',
deposited: '125600000',
total: '251200000',
} as AccountFields;
const singleRowData = [singleRow];
@@ -42,7 +42,7 @@ describe('AccountsTable', () => {
/>
);
});
const expectedHeaders = ['Asset', 'Total', 'Used', 'Available', ''];
const expectedHeaders = ['Asset', 'Used', 'Available', 'Total', ''];
const headers = await screen.findAllByRole('columnheader');
expect(headers).toHaveLength(expectedHeaders.length);
expect(
@@ -65,8 +65,7 @@ describe('AccountsTable', () => {
'tBTC',
'1,256.00',
'1,256.00',
'1,256.00',
'Breakdown',
'2,512.00',
'Deposit',
'Withdraw',
];
@@ -88,13 +87,8 @@ describe('AccountsTable', () => {
);
});
const cells = await screen.findAllByRole('gridcell');
const expectedValues = [
'tBTC',
'1,256.00',
'1,256.00',
'1,256.00',
'Breakdown',
];
const expectedValues = ['tBTC', '1,256.00', '1,256.00', '2,512.00', ''];
expect(cells.length).toBe(expectedValues.length);
cells.forEach((cell, i) => {
expect(cell).toHaveTextContent(expectedValues[i]);
});
@@ -145,7 +139,7 @@ describe('AccountsTable', () => {
},
available: '0',
balance: '125600000',
deposited: '125600000',
total: '125600000',
market: {
__typename: 'Market',
id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35',
@@ -161,7 +155,7 @@ describe('AccountsTable', () => {
used: '125600000',
},
],
deposited: '125600000',
total: '125600000',
type: 'ACCOUNT_TYPE_GENERAL',
used: '125600000',
},
+182 -166
View File
@@ -8,7 +8,6 @@ import { t } from '@vegaprotocol/i18n';
import type {
VegaICellRendererParams,
VegaValueFormatterParams,
VegaValueGetterParams,
} from '@vegaprotocol/datagrid';
import { Button, ButtonLink, Dialog } from '@vegaprotocol/ui-toolkit';
import { TooltipCellComponent } from '@vegaprotocol/ui-toolkit';
@@ -17,12 +16,56 @@ import {
CenteredGridCellWrapper,
} from '@vegaprotocol/datagrid';
import { AgGridColumn } from 'ag-grid-react';
import type { IDatasource, IGetRowsParams } from 'ag-grid-community';
import type { IDatasource, IGetRowsParams, RowNode } from 'ag-grid-community';
import type { AgGridReact, AgGridReactProps } from 'ag-grid-react';
import BreakdownTable from './breakdown-table';
import type { AccountFields } from './accounts-data-provider';
import type { Asset } from '@vegaprotocol/types';
import BigNumber from 'bignumber.js';
import classNames from 'classnames';
const colorClass = (percentageUsed: number, neutral = false) => {
return classNames({
'text-neutral-500 dark:text-neutral-400': percentageUsed < 75 && !neutral,
'text-vega-orange': percentageUsed >= 75 && percentageUsed < 90,
'text-vega-pink': percentageUsed >= 90,
});
};
export const percentageValue = (part?: string, total?: string) =>
new BigNumber(part || 0)
.dividedBy(total || 1)
.multipliedBy(100)
.toNumber();
const formatWithAssetDecimals = (
data: AccountFields | undefined,
value: string | undefined
) => {
return (
data &&
data.asset &&
isNumeric(value) &&
addDecimalsFormatNumber(value, data.asset.decimals)
);
};
export const accountValuesComparator = (
valueA: string,
valueB: string,
nodeA: RowNode,
nodeB: RowNode
) => {
if (isNumeric(valueA) && isNumeric(valueB)) {
const a = toBigNum(valueA, nodeA.data.asset?.decimals);
const b = toBigNum(valueB, nodeB.data.asset?.decimals);
if (a.isEqualTo(b)) return 0;
return a.isGreaterThan(b) ? 1 : -1;
}
if (valueA === valueB) return 0;
return valueA > valueB ? 1 : -1;
};
export interface GetRowsParams extends Omit<IGetRowsParams, 'successCallback'> {
successCallback(rowsThisBlock: AccountFields[], lastRow?: number): void;
@@ -47,7 +90,7 @@ export interface AccountTableProps extends AgGridReactProps {
export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
({ onClickAsset, onClickWithdraw, onClickDeposit, ...props }, ref) => {
const [openBreakdown, setOpenBreakdown] = useState(false);
const [breakdown, setBreakdown] = useState<AccountFields[] | null>(null);
const [row, setRow] = useState<AccountFields>();
const pinnedAssetId = props.pinnedAsset?.id;
const pinnedAssetRow = useMemo(() => {
@@ -60,7 +103,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
asset: props.pinnedAsset,
available: '0',
used: '0',
deposited: '0',
total: '0',
balance: '0',
};
}
@@ -81,6 +124,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
resizable: true,
tooltipComponent: TooltipCellComponent,
sortable: true,
comparator: accountValuesComparator,
}}
{...props}
pinnedTopRowData={pinnedAssetRow ? [pinnedAssetRow] : undefined}
@@ -94,90 +138,64 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
cellRenderer={({
value,
data,
node,
}: VegaICellRendererParams<AccountFields, 'asset.symbol'>) => {
return value ? (
<CenteredGridCellWrapper
className={node.rowPinned ? 'h-[30px]' : undefined}
return (
<ButtonLink
data-testid="asset"
onClick={() => {
if (data) {
onClickAsset(data.asset.id);
}
}}
>
<ButtonLink
data-testid="asset"
onClick={() => {
if (data) {
onClickAsset(data.asset.id);
}
}}
>
{value}
</ButtonLink>
</CenteredGridCellWrapper>
) : null;
}}
maxWidth={300}
/>
<AgGridColumn
headerName={t('Total')}
type="rightAligned"
field="deposited"
headerTooltip={t(
'This is the total amount of collateral used plus the amount available in your general account.'
)}
valueGetter={({
data,
}: VegaValueGetterParams<AccountFields, 'deposited'>) => {
return !data?.deposited
? undefined
: toBigNum(data.deposited, data.asset.decimals).toNumber();
}}
maxWidth={300}
cellRenderer={({
data,
node,
}: VegaICellRendererParams<AccountFields, 'deposited'>) => {
const valueFormatted =
data &&
data.asset &&
isNumeric(data.deposited) &&
addDecimalsFormatNumber(data.deposited, data.asset.decimals);
return node.rowPinned ? (
<CenteredGridCellWrapper className="h-[30px] justify-end">
{valueFormatted}
</CenteredGridCellWrapper>
) : (
valueFormatted
{value}
</ButtonLink>
);
}}
maxWidth={300}
/>
<AgGridColumn
headerName={t('Used')}
type="rightAligned"
field="used"
headerTooltip={t(
'This is the amount of collateral used from your general account.'
'Currently allocated to a market as margin or bond. Check the breakdown for details.'
)}
valueGetter={({
data,
}: VegaValueGetterParams<AccountFields, 'used'>) => {
return !data?.used
? undefined
: toBigNum(data.used, data.asset.decimals).toNumber();
}}
maxWidth={300}
cellRenderer={({
data,
node,
value,
}: VegaICellRendererParams<AccountFields, 'used'>) => {
const valueFormatted =
data &&
data.asset &&
isNumeric(data.used) &&
addDecimalsFormatNumber(data.used, data.asset.decimals);
return node.rowPinned ? (
<CenteredGridCellWrapper className="h-[30px] justify-end">
{valueFormatted}
</CenteredGridCellWrapper>
if (!data) return null;
const percentageUsed = percentageValue(value, data.total);
const valueFormatted = formatWithAssetDecimals(data, value);
return data.breakdown ? (
<>
<ButtonLink
data-testid="breakdown"
onClick={() => {
setOpenBreakdown(!openBreakdown);
setRow(data);
}}
>
<span>{valueFormatted}</span>
</ButtonLink>
<span
className={classNames(
colorClass(percentageUsed),
'ml-2 inline-block w-14'
)}
>
{percentageUsed.toFixed(2)}%
</span>
</>
) : (
valueFormatted
<>
<span>{valueFormatted}</span>
<span className="ml-2 inline-block w-14 text-neutral-500 dark:text-neutral-400">
0.00%
</span>
</>
);
}}
/>
@@ -186,115 +204,113 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
field="available"
type="rightAligned"
headerTooltip={t(
'This is the amount of collateral available in your general account.'
'Deposited on the network, but not allocated to a market. Free to use for placing orders or providing liquidity.'
)}
valueGetter={({
data,
}: VegaValueGetterParams<AccountFields, 'available'>) => {
return !data?.available
? undefined
: toBigNum(data.available, data.asset.decimals).toNumber();
}}
valueFormatter={({
data,
}: VegaValueFormatterParams<AccountFields, 'available'>) =>
data &&
data.asset &&
isNumeric(data.available) &&
addDecimalsFormatNumber(data.available, data.asset.decimals)
}
maxWidth={300}
cellRenderer={({
value,
data,
node,
}: VegaICellRendererParams<AccountFields, 'available'>) => {
const valueFormatted =
data &&
data.asset &&
isNumeric(data.available) &&
addDecimalsFormatNumber(data.available, data.asset.decimals);
return node.rowPinned ? (
<CenteredGridCellWrapper className="h-[30px] justify-end">
{valueFormatted}
</CenteredGridCellWrapper>
) : (
valueFormatted
const percentageUsed = percentageValue(data?.used, data?.total);
return (
<span className={colorClass(percentageUsed, true)}>
{formatWithAssetDecimals(data, value)}
</span>
);
}}
/>
<AgGridColumn
colId="breakdown"
headerName=""
sortable={false}
minWidth={200}
headerName={t('Total')}
type="rightAligned"
cellRenderer={({
field="total"
headerTooltip={t(
'The total amount of each asset on this key. Includes used and available collateral.'
)}
valueFormatter={({
data,
}: VegaICellRendererParams<AccountFields>) => {
if (!data) return null;
else {
if (
data.asset.id === pinnedAssetId &&
new BigNumber(data.deposited).isLessThanOrEqualTo(0)
) {
}: VegaValueFormatterParams<AccountFields, 'total'>) =>
formatWithAssetDecimals(data, data?.total)
}
/>
{
<AgGridColumn
colId="accounts-actions"
headerName=""
sortable={false}
minWidth={200}
type="rightAligned"
cellRenderer={({
data,
}: VegaICellRendererParams<AccountFields>) => {
if (!data) return null;
else {
if (
data.asset.id === pinnedAssetId &&
new BigNumber(data.total).isLessThanOrEqualTo(0)
) {
return (
<CenteredGridCellWrapper className="h-[30px] justify-end py-1">
<Button
size="xs"
variant="primary"
data-testid="deposit"
onClick={() => {
onClickDeposit && onClickDeposit(data.asset.id);
}}
>
{t('Deposit to trade')}
</Button>
</CenteredGridCellWrapper>
);
}
return (
<CenteredGridCellWrapper className="h-[30px] justify-end py-1">
<Button
size="xs"
variant="primary"
data-testid="deposit"
onClick={() => {
onClickDeposit && onClickDeposit(data.asset.id);
}}
>
{t('Deposit to trade')}
</Button>
</CenteredGridCellWrapper>
<>
<span className="mx-1" />
{!props.isReadOnly && (
<ButtonLink
data-testid="deposit"
onClick={() => {
onClickDeposit && onClickDeposit(data.asset.id);
}}
>
{t('Deposit')}
</ButtonLink>
)}
<span className="mx-1" />
{!props.isReadOnly && (
<ButtonLink
data-testid="withdraw"
onClick={() =>
onClickWithdraw && onClickWithdraw(data.asset.id)
}
>
{t('Withdraw')}
</ButtonLink>
)}
</>
);
}
return (
<>
<ButtonLink
data-testid="breakdown"
onClick={() => {
setOpenBreakdown(!openBreakdown);
setBreakdown(data.breakdown || null);
}}
>
{t('Breakdown')}
</ButtonLink>
<span className="mx-1" />
{!props.isReadOnly && (
<ButtonLink
data-testid="deposit"
onClick={() => {
onClickDeposit && onClickDeposit(data.asset.id);
}}
>
{t('Deposit')}
</ButtonLink>
)}
<span className="mx-1" />
{!props.isReadOnly && (
<ButtonLink
data-testid="withdraw"
onClick={() =>
onClickWithdraw && onClickWithdraw(data.asset.id)
}
>
{t('Withdraw')}
</ButtonLink>
)}
</>
);
}
}}
/>
}}
/>
}
</AgGrid>
<Dialog size="medium" open={openBreakdown} onChange={setOpenBreakdown}>
<div className="h-[35vh] w-full m-auto flex flex-col">
<h1 className="text-xl mb-4">{t('Collateral breakdown')}</h1>
<BreakdownTable data={breakdown} domLayout="autoHeight" />
<h1 className="text-xl mb-4">
{row?.asset?.symbol} {t('usage breakdown')}
</h1>
{row && (
<p className="mb-2 text-sm">
{t('You have %s %s in total.', [
addDecimalsFormatNumber(row.total, row.asset.decimals),
row.asset.symbol,
])}
</p>
)}
<BreakdownTable
data={row?.breakdown || null}
domLayout="autoHeight"
/>
</div>
</Dialog>
</>
@@ -27,7 +27,7 @@ const singleRow = {
},
available: '125600000',
used: '125600000',
deposited: '125600000',
total: '251200000',
} as AccountFields;
const singleRowData = [singleRow];
@@ -37,10 +37,10 @@ describe('BreakdownTable', () => {
render(<BreakdownTable data={singleRowData} />);
});
const headers = await screen.findAllByRole('columnheader');
expect(headers).toHaveLength(4);
expect(headers).toHaveLength(3);
expect(
headers.map((h) => h.querySelector('[ref="eText"]')?.textContent?.trim())
).toEqual(['Account type', 'Market', 'Used', 'Balance']);
).toEqual(['Market', 'Account type', 'Balance']);
});
it('should apply correct formatting', async () => {
@@ -49,9 +49,9 @@ describe('BreakdownTable', () => {
});
const cells = await screen.findAllByRole('gridcell');
const expectedValues = [
'Margin',
'BTCUSD Monthly (30 Jun 2022)',
'1,256.001,256.00',
'Margin',
'1,256.00 (50%)',
'1,256.00',
'1,256.00',
];
@@ -83,7 +83,7 @@ describe('BreakdownTable', () => {
},
available: '0',
balance: '125600000',
deposited: '125600000',
total: '125600000',
market: {
__typename: 'Market',
id: '10cd0a793ad2887b340940337fa6d97a212e0e517fe8e9eab2b5ef3a38633f35',
@@ -99,7 +99,7 @@ describe('BreakdownTable', () => {
used: '125600000',
},
],
deposited: '125600000',
total: '125600000',
type: 'ACCOUNT_TYPE_GENERAL',
used: '125600000',
},
+23 -42
View File
@@ -1,5 +1,5 @@
import { forwardRef } from 'react';
import { addDecimalsFormatNumber, isNumeric } from '@vegaprotocol/utils';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import {
Intent,
@@ -13,6 +13,7 @@ import type { ValueProps } from '@vegaprotocol/ui-toolkit';
import type { VegaValueFormatterParams } from '@vegaprotocol/datagrid';
import { AgGridDynamic as AgGrid, PriceCell } from '@vegaprotocol/datagrid';
import type { ValueFormatterParams } from 'ag-grid-community';
import { accountValuesComparator } from './accounts-table';
export const progressBarValueFormatter = ({
data,
@@ -23,24 +24,16 @@ export const progressBarValueFormatter = ({
}
const min = BigInt(data.used);
const mid = BigInt(data.available);
const max = BigInt(data.deposited);
const max = BigInt(data.total);
const range = max > min ? max : min;
return {
low: addDecimalsFormatNumber(min.toString(), data.asset.decimals, 4),
high: addDecimalsFormatNumber(mid.toString(), data.asset.decimals, 4),
low: addDecimalsFormatNumber(min.toString(), data.asset.decimals),
high: addDecimalsFormatNumber(mid.toString(), data.asset.decimals),
value: range ? Number((min * BigInt(100)) / range) : 0,
intent: Intent.Warning,
};
};
export const progressBarHeaderComponentParams = {
template:
'<div class="ag-cell-label-container" role="presentation">' +
` <span>${t('Available')}</span>` +
' <span ref="eText" class="ag-header-cell-text"></span>' +
'</div>',
};
interface BreakdownTableProps extends AgGridReactProps {
data: AccountFields[] | null;
}
@@ -62,8 +55,23 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
defaultColDef={{
flex: 1,
resizable: true,
sortable: true,
}}
>
<AgGridColumn
headerName={t('Market')}
field="market.tradableInstrument.instrument.name"
valueFormatter={({
value,
}: VegaValueFormatterParams<
AccountFields,
'market.tradableInstrument.instrument.name'
>) => {
if (!value) return 'None';
return value;
}}
minWidth={200}
/>
<AgGridColumn
headerName={t('Account type')}
field="type"
@@ -76,42 +84,15 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
: ''
}
/>
<AgGridColumn
headerName={t('Market')}
field="market.tradableInstrument.instrument.name"
valueFormatter={({
value,
}: VegaValueFormatterParams<
AccountFields,
'market.tradableInstrument.instrument.name'
>) => {
if (!value) return '-';
return value;
}}
minWidth={200}
/>
<AgGridColumn
headerName={t('Used')}
headerName={t('Balance')}
field="used"
flex={2}
maxWidth={500}
headerComponentParams={progressBarHeaderComponentParams}
cellRendererSelector={progressBarCellRendererSelector}
valueFormatter={progressBarValueFormatter}
/>
<AgGridColumn
headerName={t('Balance')}
field="balance"
valueFormatter={({
value,
data,
}: VegaValueFormatterParams<AccountFields, 'balance'>) => {
if (data && data.asset && isNumeric(value)) {
return addDecimalsFormatNumber(value, data.asset.decimals);
}
return '-';
}}
maxWidth={300}
comparator={accountValuesComparator}
/>
</AgGrid>
);
+13 -7
View File
@@ -59,13 +59,19 @@ export function createClient({
const timestamp = r?.headers.get('x-block-timestamp');
if (blockHeight && timestamp) {
const state = useHeaderStore.getState();
useHeaderStore.setState({
...state,
[r.url]: {
blockHeight: Number(blockHeight),
timestamp: new Date(Number(timestamp.slice(0, -6))),
},
});
const urlState = state[r.url];
if (
!urlState?.blockHeight ||
urlState.blockHeight !== blockHeight
) {
useHeaderStore.setState({
...state,
[r.url]: {
blockHeight: Number(blockHeight),
timestamp: new Date(Number(timestamp.slice(0, -6))),
},
});
}
}
return response;
});
+2 -2
View File
@@ -1,4 +1,4 @@
import { ContractAddressLink } from '@vegaprotocol/environment';
import { EtherscanLink } from '@vegaprotocol/environment';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import type * as Schema from '@vegaprotocol/types';
@@ -108,7 +108,7 @@ export const rows: Rows = [
return (
<>
<ContractAddressLink address={asset.source.contractAddress} />{' '}
<EtherscanLink address={asset.source.contractAddress} />{' '}
<CopyWithTooltip text={asset.source.contractAddress}>
<button title={t('Copy address to clipboard')}>
<Icon size={3} name="duplicate" />
+8 -1
View File
@@ -17,9 +17,11 @@ import {
import { addMockTransactionResponse } from './lib/commands/mock-transaction-response';
import { addCreateMarket } from './lib/commands/create-market';
import { addConnectPublicKey } from './lib/commands/add-connect-public-key';
import { addValidatorsSelfDelegate } from './lib/commands/validators-self-delegate';
import { addVegaWalletSubmitProposal } from './lib/commands/vega-wallet-submit-proposal';
import { addGetNodes } from './lib/commands/get-nodes';
import { addVegaWalletSubmitLiquidityProvision } from './lib/commands/vega-wallet-submit-liquidity-provision';
import { addImportNodeWallets } from './lib/commands/import-node-wallets';
addGetTestIdcommand();
addSlackCommand();
@@ -39,10 +41,15 @@ addSetVegaWallet();
addMockTransactionResponse();
addCreateMarket();
addConnectPublicKey();
addValidatorsSelfDelegate();
addVegaWalletSubmitProposal();
addVegaWalletSubmitLiquidityProvision();
addImportNodeWallets();
export { mockConnectWallet } from './lib/commands/vega-wallet-connect';
export {
mockConnectWallet,
mockConnectWalletWithUserError,
} from './lib/commands/vega-wallet-connect';
export type { onMessage } from './lib/mock-ws';
export { aliasGQLQuery } from './lib/mock-gql';
export { aliasWalletQuery } from './lib/mock-rest';
@@ -44,7 +44,7 @@ export async function createMarket(cfg: {
// To participate in governance (in this case proposing and voting in a market)
// you need to have staked (associated) some Vega with a Vega public key
await stakeForVegaPublicKey(cfg.vegaPubKey);
await stakeForVegaPublicKey(cfg.vegaPubKey, '10000');
// Send some of the asset for the market to be proposed to the test pubkey
const result = await faucetAsset(
@@ -8,7 +8,10 @@ import { wallet } from './ethereum-wallet';
const log = createLog('ethereum-setup');
export async function stakeForVegaPublicKey(vegaPublicKey: string) {
export async function stakeForVegaPublicKey(
vegaPublicKey: string,
amount: string
) {
if (!wallet) {
throw new Error('ethereum wallet not initialized');
}
@@ -29,7 +32,7 @@ export async function stakeForVegaPublicKey(vegaPublicKey: string) {
const approveTx = await promiseWithTimeout(
tokenContract.approve(
ethereumConfig.staking_bridge_contract.address,
'100000' + '0'.repeat(18)
amount + '0'.repeat(19)
),
1000,
'approve staking tx'
@@ -47,12 +50,12 @@ export async function stakeForVegaPublicKey(vegaPublicKey: string) {
wallet
);
const amount = '10000' + '0'.repeat(18);
log(`sending stake tx of ${amount} to ${vegaPublicKey}`);
const realAmount = amount + '0'.repeat(18);
log(`sending stake tx of ${realAmount} to ${vegaPublicKey}`);
const stakeTx = await promiseWithTimeout(
stakingContract.stake(amount, vegaPublicKey),
stakingContract.stake(realAmount, vegaPublicKey),
14000,
'stakingContract.stake(amount, vegaPublicKey)'
'stakingContract.stake(realAmount, vegaPublicKey)'
);
await promiseWithTimeout(
stakeTx.wait(3),
@@ -0,0 +1,37 @@
import { setGraphQLEndpoint } from './request';
import { stakeForVegaPublicKey } from './ethereum-setup';
import { createWalletClient, sendVegaTx } from './wallet-client';
import { createEthereumWallet } from './ethereum-wallet';
export async function selfDelegate(
cfg: {
ethWalletMnemonic: string;
ethereumProviderUrl: string;
vegaWalletUrl: string;
vegaUrl: string;
faucetUrl: string;
},
vegaWalletPubKey: string,
apiToken: string,
nodeId: string
) {
// setup wallet client and graphql clients
setGraphQLEndpoint(cfg.vegaUrl);
createWalletClient(cfg.vegaWalletUrl, apiToken);
createEthereumWallet(cfg.ethWalletMnemonic, cfg.ethereumProviderUrl);
// Associate tokens to validator wallet
await stakeForVegaPublicKey(vegaWalletPubKey, '3000');
// Stake on validator
// By default 3000 vega is minimum amount of stake required for self-delegation
const stakeTx = {
delegateSubmission: {
nodeId: nodeId,
amount: '3000' + '0'.repeat(18),
},
};
const result = await sendVegaTx(vegaWalletPubKey, stakeTx);
return result;
}
@@ -0,0 +1,84 @@
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> {
importNodeWallets(): void;
}
}
}
export const addImportNodeWallets = () => {
Cypress.Commands.add('importNodeWallets', () => {
// Get node wallet recovery phrases
cy.exec('vegacapsule nodes ls --home-path ~/.vegacapsule/testnet/')
.its('stdout')
.then((result) => {
const obj = JSON.parse(result);
console.log(obj);
cy.writeFile(
'./src/fixtures/wallet/node0RecoveryPhrase',
obj['testnet-nodeset-validators-0-validator'].Vega.NodeWalletInfo
.VegaWalletRecoveryPhrase
);
cy.writeFile(
'./src/fixtures/wallet/node1RecoveryPhrase',
obj['testnet-nodeset-validators-1-validator'].Vega.NodeWalletInfo
.VegaWalletRecoveryPhrase
);
cy.wrap(
obj['testnet-nodeset-validators-0-validator'].Vega.NodeWalletInfo
.VegaWalletPublicKey
).as('node0PubKey');
cy.wrap(
obj['testnet-nodeset-validators-1-validator'].Vega.NodeWalletInfo
.VegaWalletPublicKey
).as('node1PubKey');
cy.wrap(
obj['testnet-nodeset-validators-0-validator'].Vega.NodeWalletInfo
.VegaWalletID
).as('node0Id');
cy.wrap(
obj['testnet-nodeset-validators-1-validator'].Vega.NodeWalletInfo
.VegaWalletID
).as('node1Id');
});
// Import node wallets
cy.exec(
'vega wallet import -w node0_wallet --recovery-phrase-file ./src/fixtures/wallet/node0RecoveryPhrase -p ./src/fixtures/wallet/passphrase --home ~/.vegacapsule/testnet/wallet'
);
cy.exec(
'vega wallet import -w node1_wallet --recovery-phrase-file ./src/fixtures/wallet/node1RecoveryPhrase -p ./src/fixtures/wallet/passphrase --home ~/.vegacapsule/testnet/wallet'
);
// Initialise api token
cy.exec(
'vega wallet api-token init --home ~/.vegacapsule/testnet/wallet --passphrase-file ./src/fixtures/wallet/passphrase'
);
// Generate api tokens for wallets
cy.exec(
'vega wallet api-token generate --wallet-name node0_wallet --tokens-passphrase-file ./src/fixtures/wallet/passphrase --wallet-passphrase-file ./src/fixtures/wallet/passphrase --home ~/.vegacapsule/testnet/wallet'
)
.its('stdout')
.then((result) => {
const apiToken = result.match('[a-zA-Z0-9]{64}');
if (apiToken) {
cy.wrap(apiToken[0]).as('node0ApiToken');
}
});
cy.exec(
'vega wallet api-token generate --wallet-name node1_wallet --tokens-passphrase-file ./src/fixtures/wallet/passphrase --wallet-passphrase-file ./src/fixtures/wallet/passphrase --home ~/.vegacapsule/testnet/wallet'
)
.its('stdout')
.then((result) => {
const apiToken = result.match('[a-zA-Z0-9]{64}');
if (apiToken) {
cy.wrap(apiToken[0]).as('node1ApiToken');
}
});
});
};
@@ -0,0 +1,130 @@
import { selfDelegate } from '../capsule/self-delegate';
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Cypress {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
interface Chainable<Subject> {
validatorsSelfDelegate(): void;
}
}
}
export const addValidatorsSelfDelegate = () => {
Cypress.Commands.add('validatorsSelfDelegate', () => {
const config = {
ethWalletMnemonic: Cypress.env('ETH_WALLET_MNEMONIC'),
ethereumProviderUrl: Cypress.env('ETHEREUM_PROVIDER_URL'),
vegaWalletUrl: Cypress.env('VEGA_WALLET_URL'),
vegaUrl: Cypress.env('VEGA_URL'),
faucetUrl: Cypress.env('FAUCET_URL'),
};
// Get node wallet recovery phrases
cy.exec('vegacapsule nodes ls --home-path ~/.vegacapsule/testnet/')
.its('stdout')
.then((result) => {
const obj = JSON.parse(result);
console.log(obj);
cy.writeFile(
'./src/fixtures/wallet/node0RecoveryPhrase',
obj['testnet-nodeset-validators-0-validator'].Vega.NodeWalletInfo
.VegaWalletRecoveryPhrase
);
cy.writeFile(
'./src/fixtures/wallet/node1RecoveryPhrase',
obj['testnet-nodeset-validators-1-validator'].Vega.NodeWalletInfo
.VegaWalletRecoveryPhrase
);
cy.wrap(
obj['testnet-nodeset-validators-0-validator'].Vega.NodeWalletInfo
.VegaWalletPublicKey
).as('node0PubKey');
cy.wrap(
obj['testnet-nodeset-validators-1-validator'].Vega.NodeWalletInfo
.VegaWalletPublicKey
).as('node1PubKey');
cy.wrap(
obj['testnet-nodeset-validators-0-validator'].Vega.NodeWalletInfo
.VegaWalletID
).as('node0Id');
cy.wrap(
obj['testnet-nodeset-validators-1-validator'].Vega.NodeWalletInfo
.VegaWalletID
).as('node1Id');
});
// Import node wallets
cy.exec(
'vega wallet import -w node0_wallet --recovery-phrase-file ./src/fixtures/wallet/node0RecoveryPhrase -p ./src/fixtures/wallet/passphrase --home ~/.vegacapsule/testnet/wallet'
);
cy.exec(
'vega wallet import -w node1_wallet --recovery-phrase-file ./src/fixtures/wallet/node1RecoveryPhrase -p ./src/fixtures/wallet/passphrase --home ~/.vegacapsule/testnet/wallet'
);
// Initialise api token
cy.exec(
'vega wallet api-token init --home ~/.vegacapsule/testnet/wallet --passphrase-file ./src/fixtures/wallet/passphrase'
);
// Generate api tokens for wallets
cy.exec(
'vega wallet api-token generate --wallet-name node0_wallet --tokens-passphrase-file ./src/fixtures/wallet/passphrase --wallet-passphrase-file ./src/fixtures/wallet/passphrase --home ~/.vegacapsule/testnet/wallet'
)
.its('stdout')
.then((result) => {
const apiToken = result.match('[a-zA-Z0-9]{64}');
if (apiToken) {
cy.wrap(apiToken[0]).as('node0ApiToken');
}
});
cy.exec(
'vega wallet api-token generate --wallet-name node1_wallet --tokens-passphrase-file ./src/fixtures/wallet/passphrase --wallet-passphrase-file ./src/fixtures/wallet/passphrase --home ~/.vegacapsule/testnet/wallet'
)
.its('stdout')
.then((result) => {
const apiToken = result.match('[a-zA-Z0-9]{64}');
if (apiToken) {
cy.wrap(apiToken[0]).as('node1ApiToken');
}
});
cy.updateCapsuleMultiSig();
cy.highlight('Validators self-delegating');
// Self delegating Node 0 wallet
cy.get('@node0PubKey').then((node0PubKey) => {
cy.get('@node0ApiToken').then((node0ApiToken) => {
cy.get('@node0Id').then((node0Id) => {
cy.wrap(
selfDelegate(
config,
String(node0PubKey),
String(node0ApiToken),
String(node0Id)
),
{ timeout: 60000 }
);
// Self delegating Node 1 wallet
cy.get('@node1PubKey').then((node1PubKey) => {
cy.get('@node1ApiToken').then((node1ApiToken) => {
cy.get('@node1Id').then((node1Id) => {
cy.wrap(
selfDelegate(
config,
String(node1PubKey),
String(node1ApiToken),
String(node1Id)
),
{ timeout: 60000 }
);
});
});
});
});
});
});
});
};
@@ -1,4 +1,7 @@
import { aliasWalletConnectQuery } from '../mock-rest';
import {
aliasWalletConnectQuery,
aliasWalletConnectWithUserError,
} from '../mock-rest';
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
@@ -20,6 +23,12 @@ export const mockConnectWallet = () => {
});
};
export const mockConnectWalletWithUserError = () => {
cy.mockWallet((req) => {
aliasWalletConnectWithUserError(req, Cypress.env('VEGA_WALLET_API_TOKEN'));
});
};
export function addVegaWalletConnect() {
Cypress.Commands.add('connectVegaWallet', (isMobile) => {
mockConnectWallet();
+21
View File
@@ -63,3 +63,24 @@ export const aliasWalletConnectQuery = (
});
}
};
export const aliasWalletConnectWithUserError = (
req: CyHttpMessages.IncomingHttpRequest,
token: string
) => {
if (hasMethod(req, 'client.connect_wallet')) {
req.alias = 'client.connect_wallet';
req.reply({
statusCode: 400,
body: {
jsonrpc: '2.0',
error: {
code: 3001,
data: 'the user rejected the wallet connection',
message: 'User error',
},
id: '0',
},
});
}
};
+1
View File
@@ -53,6 +53,7 @@ export const checkSorting = (
});
checkSortChange(orderTabDesc, column);
};
const checkSortChange = (tabsArr: string[], column: string) => {
cy.get('.ag-center-cols-container').within(() => {
tabsArr.forEach((entry, i) => {
@@ -116,7 +116,7 @@ export const DealTicket = ({
return;
}
const hasNoBalance = generalAccountBalance === '0';
const hasNoBalance = !BigInt(generalAccountBalance);
if (hasNoBalance) {
setError('summary', {
message: SummaryValidationType.NoCollateral,
@@ -141,7 +141,6 @@ export const DealTicket = ({
pubKey,
setError,
clearErrors,
errors.summary,
]);
const onSubmit = useCallback(
@@ -386,8 +385,12 @@ const SummaryMessage = memo(
// If there is no blocking error but user doesn't have enough
// balance render the margin warning, but still allow submission
if (BigInt(balance) < BigInt(margin)) {
return <MarginWarning balance={balance} margin={margin} asset={asset} />;
if (BigInt(balance) < BigInt(margin) && BigInt(balance) > BigInt(0)) {
return (
<div className="mb-2">
<MarginWarning balance={balance} margin={margin} asset={asset} />
</div>
);
}
// Show auction mode warning
if (
@@ -1,7 +1,7 @@
import type { Asset } from '@vegaprotocol/assets';
import { useEnvironment } from '@vegaprotocol/environment';
import { EtherscanLink } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n';
import { ExternalLink, Intent, Notification } from '@vegaprotocol/ui-toolkit';
import { Intent, Notification } from '@vegaprotocol/ui-toolkit';
import { formatNumber } from '@vegaprotocol/utils';
import type { EthStoredTxState } from '@vegaprotocol/web3';
import { EthTxStatus, useEthTransactionStore } from '@vegaprotocol/web3';
@@ -126,14 +126,10 @@ const ApprovalTxFeedback = ({
selectedAsset: Asset;
allowance?: BigNumber;
}) => {
const { ETHERSCAN_URL } = useEnvironment();
if (!tx) return null;
const txLink = tx.txHash && (
<ExternalLink href={`${ETHERSCAN_URL}/tx/${tx.txHash}`}>
{t('View on Etherscan')}
</ExternalLink>
<EtherscanLink tx={tx.txHash}>{t('View on Etherscan')}</EtherscanLink>
);
if (tx.status === EthTxStatus.Error) {
+3 -10
View File
@@ -8,7 +8,6 @@ import {
} from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import type { AgGridReact } from 'ag-grid-react';
import { Link } from '@vegaprotocol/ui-toolkit';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
import type {
VegaICellRendererParams,
@@ -16,14 +15,13 @@ import type {
TypedDataAgGrid,
} from '@vegaprotocol/datagrid';
import type { DepositFieldsFragment } from './__generated__/Deposit';
import { useEnvironment } from '@vegaprotocol/environment';
import { EtherscanLink } from '@vegaprotocol/environment';
import { DepositStatusMapping } from '@vegaprotocol/types';
export const DepositsTable = forwardRef<
AgGridReact,
TypedDataAgGrid<DepositFieldsFragment>
>((props, ref) => {
const { ETHERSCAN_URL } = useEnvironment();
return (
<AgGrid
ref={ref}
@@ -77,14 +75,9 @@ export const DepositsTable = forwardRef<
if (!data) return null;
if (!value) return '-';
return (
<Link
title={t('View transaction on Etherscan')}
href={`${ETHERSCAN_URL}/tx/${value}`}
data-testid="etherscan-link"
target="_blank"
>
<EtherscanLink tx={value} data-testid="etherscan-link">
{truncateByChars(value)}
</Link>
</EtherscanLink>
);
}}
/>
@@ -1,7 +1,7 @@
import type { Asset } from '@vegaprotocol/assets';
import { useEnvironment } from '@vegaprotocol/environment';
import { EtherscanLink } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n';
import { ExternalLink, Intent, Notification } from '@vegaprotocol/ui-toolkit';
import { Intent, Notification } from '@vegaprotocol/ui-toolkit';
import { EthTxStatus, useEthTransactionStore } from '@vegaprotocol/web3';
import { getFaucetError } from './get-faucet-error';
@@ -19,7 +19,6 @@ export const FaucetNotification = ({
selectedAsset,
faucetTxId,
}: FaucetNotificationProps) => {
const { ETHERSCAN_URL } = useEnvironment();
const tx = useEthTransactionStore((state) => {
return state.transactions.find((t) => t?.id === faucetTxId);
});
@@ -79,9 +78,9 @@ export const FaucetNotification = ({
</p>
{tx.txHash && (
<p>
<ExternalLink href={`${ETHERSCAN_URL}/tx/${tx.txHash}`}>
<EtherscanLink tx={tx.txHash}>
{t('View on Etherscan')}
</ExternalLink>
</EtherscanLink>
</p>
)}
</>
@@ -107,9 +106,9 @@ export const FaucetNotification = ({
</p>
{tx.txHash && (
<p>
<ExternalLink href={`${ETHERSCAN_URL}/tx/${tx.txHash}`}>
<EtherscanLink tx={tx.txHash}>
{t('View on Etherscan')}
</ExternalLink>
</EtherscanLink>
</p>
)}
</>
@@ -1,13 +0,0 @@
import { t } from '@vegaprotocol/i18n';
import { Link } from '@vegaprotocol/ui-toolkit';
import { useEtherscanLink } from '../hooks';
export const ContractAddressLink = ({ address }: { address: string }) => {
const etherscanLink = useEtherscanLink();
const href = etherscanLink(`/address/${address}`);
return (
<Link href={href} target="_blank" title={t('View on etherscan')}>
{address}
</Link>
);
};
@@ -0,0 +1,38 @@
import { t } from '@vegaprotocol/i18n';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import type { ComponentProps } from 'react';
import { ETHERSCAN_ADDRESS, ETHERSCAN_TX, useEtherscanLink } from '../hooks';
export const EtherscanLink = ({
address,
tx,
children,
...props
}: {
address?: string;
tx?: string;
} & ComponentProps<typeof ExternalLink>) => {
const etherscanLink = useEtherscanLink();
let href = '';
if ((!address && !tx) || (address && tx)) {
return null;
}
if (address) {
href = etherscanLink(ETHERSCAN_ADDRESS.replace(':hash', address));
}
if (tx) {
href = etherscanLink(ETHERSCAN_TX.replace(':hash', tx));
}
return (
<ExternalLink
href={href}
title={t('View on Etherscan (opens in a new tab)')}
{...props}
>
{children || address || tx}
</ExternalLink>
);
};
+1 -1
View File
@@ -2,4 +2,4 @@ export * from './network-loader';
export * from './network-switcher';
export * from './node-guard';
export * from './node-switcher';
export * from './contract-address-link';
export * from './etherscan-link';

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