Compare commits
30
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8ec793b65 | ||
|
|
927fe2cb4a | ||
|
|
e205c9df8b | ||
|
|
2c2251e953 | ||
|
|
d73080965b | ||
|
|
67e602ebb1 | ||
|
|
f407110e95 | ||
|
|
66a85cce2a | ||
|
|
93f8450ecb | ||
|
|
0447a6cf5d | ||
|
|
498be838c7 | ||
|
|
fc3b1bd9ab | ||
|
|
090d850647 | ||
|
|
95280f5b26 | ||
|
|
101ae00a57 | ||
|
|
613cce3683 | ||
|
|
41fa18ed45 | ||
|
|
c941893cdd | ||
|
|
d049b471d8 | ||
|
|
010ffc0f46 | ||
|
|
dd56e4083b | ||
|
|
09d1ba68ba | ||
|
|
3959daa2b7 | ||
|
|
c599b02c89 | ||
|
|
e5ebaf02d2 | ||
|
|
ae54616c1f | ||
|
|
8f3cf390c5 | ||
|
|
64cf0c90a7 | ||
|
|
3edd91eadb | ||
|
|
676aeb07a4 |
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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,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,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,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,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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,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
|
||||
|
||||
@@ -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,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,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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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>
|
||||
|
||||
+11
-18
@@ -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>
|
||||
);
|
||||
};
|
||||
|
||||
+4
-8
@@ -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,
|
||||
},
|
||||
],
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,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,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,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
|
||||
|
||||
@@ -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,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,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
|
||||
|
||||
@@ -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,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');
|
||||
});
|
||||
});
|
||||
+19
-39
@@ -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
@@ -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,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,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,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,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,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,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,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,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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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,
|
||||
}))
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -60,7 +60,8 @@ export const AccountManager = ({
|
||||
onClickDeposit={onClickDeposit}
|
||||
onClickWithdraw={onClickWithdraw}
|
||||
isReadOnly={isReadOnly}
|
||||
noRowsOverlayComponent={() => null}
|
||||
suppressLoadingOverlay
|
||||
suppressNoRowsOverlay
|
||||
pinnedAsset={pinnedAsset}
|
||||
getRowHeight={getRowHeight}
|
||||
{...bottomPlaceholderProps}
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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',
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
@@ -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
Reference in New Issue
Block a user