Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
33931da667 | ||
|
|
92d9e7b457 | ||
|
|
f48018d1bb | ||
|
|
6851f42624 | ||
|
|
28e18af970 | ||
|
|
47342e9ee9 |
@@ -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=
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/capsule-network.json
|
||||
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet1-network.json
|
||||
|
||||
@@ -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://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mirror-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
|
||||
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_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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet1-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
|
||||
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,12 +1,12 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_ENV=VALIDATOR_TESTNET
|
||||
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.rocks/
|
||||
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_REST=https://api.validators-testnet.vega.xyz/
|
||||
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
|
||||
NX_VEGA_GOVERNANCE_URL=https://validator-testnet.governance.vega.xyz
|
||||
NX_TENDERMINT_URL=https://tm-be.validators-testnet.vega.rocks
|
||||
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/
|
||||
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.xyz
|
||||
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.xyz/rest
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
|
||||
|
||||
@@ -48,7 +48,7 @@ const MainnetSimAd = () => {
|
||||
<Icon name="cross" className="w-6 h-6" ariaLabel="dismiss" />
|
||||
</button>
|
||||
<div>
|
||||
<span className="pr-4">Mainnet sim 3 is live!</span>
|
||||
<span className="pr-4">Mainnet sim 3 is coming soon!</span>
|
||||
<ExternalLink href="https://fairground.wtf/">Learn more</ExternalLink>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -10,7 +10,7 @@ export const Footer = () => {
|
||||
const [nodeSwitcherOpen, setNodeSwitcherOpen] = useState(false);
|
||||
const { screenSize } = useScreenDimensions();
|
||||
const showFullFeedbackLabel = useMemo(
|
||||
() => ['lg', 'xl', 'xxl', 'xxxl'].includes(screenSize),
|
||||
() => ['lg', 'xl'].includes(screenSize),
|
||||
[screenSize]
|
||||
);
|
||||
|
||||
|
||||
@@ -1,52 +1,143 @@
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
formatNumberPercentage,
|
||||
getMarketExpiryDateFormatted,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type { MarketInfoWithData } from '@vegaprotocol/market-info';
|
||||
import { LiquidityInfoPanel } from '@vegaprotocol/market-info';
|
||||
import { LiquidityMonitoringParametersInfoPanel } from '@vegaprotocol/market-info';
|
||||
import {
|
||||
InstrumentInfoPanel,
|
||||
KeyDetailsInfoPanel,
|
||||
LiquidityPriceRangeInfoPanel,
|
||||
MetadataInfoPanel,
|
||||
OracleInfoPanel,
|
||||
RiskFactorsInfoPanel,
|
||||
RiskModelInfoPanel,
|
||||
RiskParametersInfoPanel,
|
||||
SettlementAssetInfoPanel,
|
||||
} from '@vegaprotocol/market-info';
|
||||
import { MarketInfoTable } 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';
|
||||
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: <KeyDetailsInfoPanel noBorder={false} market={market} />,
|
||||
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,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t('Instrument'),
|
||||
content: <InstrumentInfoPanel noBorder={false} market={market} />,
|
||||
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,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t('Settlement asset'),
|
||||
content: <SettlementAssetInfoPanel market={market} noBorder={false} />,
|
||||
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>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t('Metadata'),
|
||||
content: <MetadataInfoPanel noBorder={false} market={market} />,
|
||||
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 }), {}),
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t('Risk model'),
|
||||
content: <RiskModelInfoPanel noBorder={false} market={market} />,
|
||||
content: (
|
||||
<MarketInfoTable
|
||||
noBorder={false}
|
||||
data={market.tradableInstrument.riskModel}
|
||||
unformatted={true}
|
||||
omits={[]}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t('Risk parameters'),
|
||||
content: <RiskParametersInfoPanel noBorder={false} market={market} />,
|
||||
content: (
|
||||
<MarketInfoTable
|
||||
noBorder={false}
|
||||
data={market.tradableInstrument.riskModel.params}
|
||||
unformatted={true}
|
||||
omits={[]}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t('Risk factors'),
|
||||
content: <RiskFactorsInfoPanel noBorder={false} market={market} />,
|
||||
content: (
|
||||
<MarketInfoTable
|
||||
noBorder={false}
|
||||
data={market.riskFactors}
|
||||
unformatted={true}
|
||||
omits={['market', '__typename']}
|
||||
/>
|
||||
),
|
||||
},
|
||||
...(market.priceMonitoringSettings?.parameters?.triggers || []).map(
|
||||
(trigger, i) => ({
|
||||
@@ -67,10 +158,7 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
<MarketInfoTable
|
||||
noBorder={false}
|
||||
data={{ referencePrice: trigger.referencePrice }}
|
||||
decimalPlaces={
|
||||
market.tradableInstrument.instrument.product.settlementAsset
|
||||
.decimals
|
||||
}
|
||||
decimalPlaces={assetDecimals}
|
||||
/>
|
||||
</>
|
||||
),
|
||||
@@ -78,26 +166,64 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
{
|
||||
title: t('Liquidity monitoring parameters'),
|
||||
content: (
|
||||
<LiquidityMonitoringParametersInfoPanel
|
||||
<MarketInfoTable
|
||||
noBorder={false}
|
||||
market={market}
|
||||
data={{
|
||||
triggeringRatio:
|
||||
market.liquidityMonitoringParameters.triggeringRatio,
|
||||
...market.liquidityMonitoringParameters.targetStakeParameters,
|
||||
}}
|
||||
/>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t('Liquidity'),
|
||||
content: <LiquidityInfoPanel market={market} noBorder={false} />,
|
||||
},
|
||||
{
|
||||
title: t('Liquidity price range'),
|
||||
content: (
|
||||
<LiquidityPriceRangeInfoPanel market={market} noBorder={false} />
|
||||
<>
|
||||
<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>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: t('Oracle'),
|
||||
content: (
|
||||
<OracleInfoPanel noBorder={false} market={market}>
|
||||
<MarketInfoTable
|
||||
noBorder={false}
|
||||
data={
|
||||
market.tradableInstrument.instrument.product.dataSourceSpecBinding
|
||||
}
|
||||
>
|
||||
<Link
|
||||
className="text-xs hover:underline"
|
||||
to={`/oracles#${market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData.id}`}
|
||||
@@ -110,7 +236,7 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
>
|
||||
{t('View termination oracle specification')}
|
||||
</Link>
|
||||
</OracleInfoPanel>
|
||||
</MarketInfoTable>
|
||||
),
|
||||
},
|
||||
];
|
||||
@@ -118,7 +244,7 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
|
||||
return (
|
||||
<>
|
||||
{panels.map((p) => (
|
||||
<div key={p.title} className="mb-3">
|
||||
<div className="mb-3">
|
||||
<h2 className="font-alpha calt text-xl">{p.title}</h2>
|
||||
{p.content}
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
||||
import { StatusMessage } from '../status-message';
|
||||
|
||||
interface RenderFetchedProps {
|
||||
@@ -8,7 +7,6 @@ interface RenderFetchedProps {
|
||||
loading: boolean | undefined;
|
||||
className?: string;
|
||||
errorMessage?: string;
|
||||
refetch?: () => void;
|
||||
}
|
||||
|
||||
export const RenderFetched = ({
|
||||
@@ -17,7 +15,6 @@ export const RenderFetched = ({
|
||||
children,
|
||||
className,
|
||||
errorMessage = t('Error retrieving data'),
|
||||
refetch,
|
||||
}: RenderFetchedProps) => {
|
||||
if (loading) {
|
||||
return (
|
||||
@@ -26,20 +23,7 @@ export const RenderFetched = ({
|
||||
}
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
<>
|
||||
<StatusMessage className={className}>{errorMessage}</StatusMessage>
|
||||
{refetch && (
|
||||
<Button
|
||||
onClick={() => {
|
||||
refetch();
|
||||
}}
|
||||
>
|
||||
{t('Try again')}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
return <StatusMessage className={className}>{errorMessage}</StatusMessage>;
|
||||
}
|
||||
|
||||
return children;
|
||||
|
||||
@@ -5,6 +5,7 @@ import type { components } from '../../../../../types/explorer';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { TxDetailsChainMultisigSigner } from './tx-multisig-signer';
|
||||
import { getBlockTime } from './lib/get-block-time';
|
||||
|
||||
type Added = components['schemas']['vegaERC20SignerAdded'];
|
||||
type Removed = components['schemas']['vegaERC20SignerRemoved'];
|
||||
@@ -60,7 +61,10 @@ describe('Chain Event: multisig signer change', () => {
|
||||
expect(screen.getByText(t('Add signer'))).toBeInTheDocument();
|
||||
expect(screen.getByText(`${addedMock.newSigner}`)).toBeInTheDocument();
|
||||
|
||||
const expectedDate = getBlockTime(mockBlockTime);
|
||||
|
||||
expect(screen.getByText(t('Signer change at'))).toBeInTheDocument();
|
||||
expect(screen.getByText(expectedDate)).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Renders TableRows if all data is provided', () => {
|
||||
@@ -89,6 +93,9 @@ describe('Chain Event: multisig signer change', () => {
|
||||
expect(screen.getByText(t('Remove signer'))).toBeInTheDocument();
|
||||
expect(screen.getByText(`${removedMock.oldSigner}`)).toBeInTheDocument();
|
||||
|
||||
const expectedDate = getBlockTime(mockBlockTime);
|
||||
|
||||
expect(screen.getByText(t('Signer change at'))).toBeInTheDocument();
|
||||
expect(screen.getByText(expectedDate)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
+4
@@ -6,6 +6,7 @@ import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import { TxDetailsChainMultisigThreshold } from './tx-multisig-threshold';
|
||||
import omit from 'lodash/omit';
|
||||
import { getBlockTime } from './lib/get-block-time';
|
||||
|
||||
type Threshold =
|
||||
components['schemas']['vegaERC20MultiSigEvent']['thresholdSet'];
|
||||
@@ -73,6 +74,9 @@ describe('Chain Event: multisig threshold change', () => {
|
||||
expect(screen.getByText(t('Threshold'))).toBeInTheDocument();
|
||||
expect(screen.getByText(`66.7%`)).toBeInTheDocument();
|
||||
|
||||
const expectedDate = getBlockTime(mockBlockTime);
|
||||
|
||||
expect(screen.getByText(t('Threshold change date'))).toBeInTheDocument();
|
||||
expect(screen.getByText(expectedDate)).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -5,11 +5,6 @@ query ExplorerNewAssetSignatureBundle($id: ID!) {
|
||||
}
|
||||
asset(id: $id) {
|
||||
status
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +15,5 @@ query ExplorerUpdateAssetSignatureBundle($id: ID!) {
|
||||
}
|
||||
asset(id: $id) {
|
||||
status
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
-12
@@ -8,14 +8,14 @@ export type ExplorerNewAssetSignatureBundleQueryVariables = Types.Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerNewAssetSignatureBundleQuery = { __typename?: 'Query', erc20ListAssetBundle?: { __typename?: 'Erc20ListAssetBundle', signatures: string, nonce: string } | null, asset?: { __typename?: 'Asset', status: Types.AssetStatus, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } | null };
|
||||
export type ExplorerNewAssetSignatureBundleQuery = { __typename?: 'Query', erc20ListAssetBundle?: { __typename?: 'Erc20ListAssetBundle', signatures: string, nonce: string } | null, asset?: { __typename?: 'Asset', status: Types.AssetStatus } | null };
|
||||
|
||||
export type ExplorerUpdateAssetSignatureBundleQueryVariables = Types.Exact<{
|
||||
id: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ExplorerUpdateAssetSignatureBundleQuery = { __typename?: 'Query', erc20SetAssetLimitsBundle: { __typename?: 'ERC20SetAssetLimitsBundle', signatures: string, nonce: string }, asset?: { __typename?: 'Asset', status: Types.AssetStatus, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } | null };
|
||||
export type ExplorerUpdateAssetSignatureBundleQuery = { __typename?: 'Query', erc20SetAssetLimitsBundle: { __typename?: 'ERC20SetAssetLimitsBundle', signatures: string, nonce: string }, asset?: { __typename?: 'Asset', status: Types.AssetStatus } | null };
|
||||
|
||||
|
||||
export const ExplorerNewAssetSignatureBundleDocument = gql`
|
||||
@@ -26,11 +26,6 @@ export const ExplorerNewAssetSignatureBundleDocument = gql`
|
||||
}
|
||||
asset(id: $id) {
|
||||
status
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -70,11 +65,6 @@ export const ExplorerUpdateAssetSignatureBundleDocument = gql`
|
||||
}
|
||||
asset(id: $id) {
|
||||
status
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -110,9 +110,7 @@ export const ProposalStatusIcon = ({ id }: ProposalStatusIconProps) => {
|
||||
return (
|
||||
<div className="float-left mr-3">
|
||||
<Tooltip description={<p>{label}</p>}>
|
||||
<div>
|
||||
<Icon name={icon} />
|
||||
</div>
|
||||
<Icon name={icon} />
|
||||
</Tooltip>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
import { Loader } from '@vegaprotocol/ui-toolkit';
|
||||
import type { ProposalTerms } from '../tx-proposal';
|
||||
import { BundleError } from './signature-bundle/bundle-error';
|
||||
import { BundleExists } from './signature-bundle/bundle-exists';
|
||||
import { useExplorerNewAssetSignatureBundleQuery } from './__generated__/SignatureBundle';
|
||||
|
||||
export interface ProposalSignatureBundleByTypeProps {
|
||||
id: string;
|
||||
tx?: ProposalTerms['newAsset'] | ProposalTerms['updateAsset'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -18,7 +16,6 @@ export interface ProposalSignatureBundleByTypeProps {
|
||||
*/
|
||||
export const ProposalSignatureBundleNewAsset = ({
|
||||
id,
|
||||
tx,
|
||||
}: ProposalSignatureBundleByTypeProps) => {
|
||||
const { data, error, loading } = useExplorerNewAssetSignatureBundleQuery({
|
||||
variables: {
|
||||
@@ -27,20 +24,7 @@ export const ProposalSignatureBundleNewAsset = ({
|
||||
});
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="w-auto max-w-lg p-5 mt-5">
|
||||
<Loader />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
if (
|
||||
!tx?.changes?.erc20 ||
|
||||
!tx?.changes?.erc20 ||
|
||||
!('contractAddress' in tx.changes.erc20) ||
|
||||
tx.changes.erc20.contractAddress === undefined
|
||||
) {
|
||||
return null;
|
||||
return <Loader />;
|
||||
}
|
||||
|
||||
if (data?.erc20ListAssetBundle?.signatures) {
|
||||
@@ -48,10 +32,8 @@ export const ProposalSignatureBundleNewAsset = ({
|
||||
<BundleExists
|
||||
signatures={data.erc20ListAssetBundle.signatures}
|
||||
nonce={data.erc20ListAssetBundle.nonce}
|
||||
assetAddress={tx.changes.erc20.contractAddress}
|
||||
status={data.asset?.status}
|
||||
proposalId={id}
|
||||
tx={tx}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
|
||||
@@ -13,7 +13,6 @@ import { useExplorerUpdateAssetSignatureBundleQuery } from './__generated__/Sign
|
||||
*/
|
||||
export const ProposalSignatureBundleUpdateAsset = ({
|
||||
id,
|
||||
tx,
|
||||
}: ProposalSignatureBundleByTypeProps) => {
|
||||
const { data, error, loading } = useExplorerUpdateAssetSignatureBundleQuery({
|
||||
variables: {
|
||||
@@ -25,16 +24,11 @@ export const ProposalSignatureBundleUpdateAsset = ({
|
||||
return <Loader />;
|
||||
}
|
||||
|
||||
if (data?.asset?.source?.__typename !== 'ERC20') {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (data?.erc20SetAssetLimitsBundle?.signatures) {
|
||||
return (
|
||||
<BundleExists
|
||||
signatures={data.erc20SetAssetLimitsBundle.signatures}
|
||||
nonce={data.erc20SetAssetLimitsBundle.nonce}
|
||||
assetAddress={data.asset.source.contractAddress}
|
||||
status={data.asset?.status}
|
||||
proposalId={id}
|
||||
/>
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import { ProposalSignatureBundleNewAsset } from './signature-bundle-new';
|
||||
import { ProposalSignatureBundleUpdateAsset } from './signature-bundle-update';
|
||||
|
||||
export function format(date: string | undefined, def: string) {
|
||||
if (!date) {
|
||||
return def;
|
||||
}
|
||||
|
||||
return new Date().toLocaleDateString() || def;
|
||||
}
|
||||
|
||||
interface ProposalSignatureBundleProps {
|
||||
id: string;
|
||||
type: 'NewAsset' | 'UpdateAsset';
|
||||
}
|
||||
|
||||
/**
|
||||
* Some proposals, if enacted, generate a signature bundle.
|
||||
* The queries have to be split due to the way the API returns
|
||||
* errors, hence this slightly redundant feeling switcher.
|
||||
*/
|
||||
export const ProposalSignatureBundle = ({
|
||||
id,
|
||||
type,
|
||||
}: ProposalSignatureBundleProps) => {
|
||||
return type === 'NewAsset' ? (
|
||||
<ProposalSignatureBundleNewAsset id={id} />
|
||||
) : (
|
||||
<ProposalSignatureBundleUpdateAsset id={id} />
|
||||
);
|
||||
};
|
||||
-17
@@ -1,17 +0,0 @@
|
||||
query ExplorerBundleSigners {
|
||||
networkParameter(key: "blockchains.ethereumConfig") {
|
||||
value
|
||||
}
|
||||
nodesConnection(pagination: { first: 25 }) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
status
|
||||
ethereumAddress
|
||||
pubkey
|
||||
tmPubkey
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
import * as Types from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type ExplorerBundleSignersQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type ExplorerBundleSignersQuery = { __typename?: 'Query', networkParameter?: { __typename?: 'NetworkParameter', value: string } | null, nodesConnection: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, name: string, status: Types.NodeStatus, ethereumAddress: string, pubkey: string, tmPubkey: string } } | null> | null } };
|
||||
|
||||
|
||||
export const ExplorerBundleSignersDocument = gql`
|
||||
query ExplorerBundleSigners {
|
||||
networkParameter(key: "blockchains.ethereumConfig") {
|
||||
value
|
||||
}
|
||||
nodesConnection(pagination: {first: 25}) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
status
|
||||
ethereumAddress
|
||||
pubkey
|
||||
tmPubkey
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useExplorerBundleSignersQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useExplorerBundleSignersQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useExplorerBundleSignersQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useExplorerBundleSignersQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useExplorerBundleSignersQuery(baseOptions?: Apollo.QueryHookOptions<ExplorerBundleSignersQuery, ExplorerBundleSignersQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<ExplorerBundleSignersQuery, ExplorerBundleSignersQueryVariables>(ExplorerBundleSignersDocument, options);
|
||||
}
|
||||
export function useExplorerBundleSignersLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ExplorerBundleSignersQuery, ExplorerBundleSignersQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<ExplorerBundleSignersQuery, ExplorerBundleSignersQueryVariables>(ExplorerBundleSignersDocument, options);
|
||||
}
|
||||
export type ExplorerBundleSignersQueryHookResult = ReturnType<typeof useExplorerBundleSignersQuery>;
|
||||
export type ExplorerBundleSignersLazyQueryHookResult = ReturnType<typeof useExplorerBundleSignersLazyQuery>;
|
||||
export type ExplorerBundleSignersQueryResult = Apollo.QueryResult<ExplorerBundleSignersQuery, ExplorerBundleSignersQueryVariables>;
|
||||
+3
-22
@@ -8,33 +8,14 @@ import { BundleError } from './bundle-error';
|
||||
describe('Bundle Error', () => {
|
||||
const NON_ENABLED_STATUS: AssetStatus[] = [
|
||||
AssetStatus.STATUS_PENDING_LISTING,
|
||||
];
|
||||
|
||||
const NOT_SHOWN_STATUS: AssetStatus[] = [
|
||||
AssetStatus.STATUS_PROPOSED,
|
||||
AssetStatus.STATUS_REJECTED,
|
||||
];
|
||||
|
||||
const ENABLED_STATUS: AssetStatus[] = [AssetStatus.STATUS_ENABLED];
|
||||
it.each(NOT_SHOWN_STATUS)(
|
||||
'does not render for proposed or rejected bundles',
|
||||
(status) => {
|
||||
const screen = render(
|
||||
<MemoryRouter>
|
||||
<MockedProvider>
|
||||
<BundleError
|
||||
error={{ message: 'test-error-message' } as ApolloError}
|
||||
status={status}
|
||||
/>
|
||||
</MockedProvider>
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
expect(screen.container).toBeEmptyDOMElement();
|
||||
}
|
||||
);
|
||||
it.each(NON_ENABLED_STATUS)(
|
||||
'shows the apollo error in a syntax highlighter if not enabled and a message is provided',
|
||||
'shows the apollo error if not enabled and a message is provided',
|
||||
(status) => {
|
||||
const screen = render(
|
||||
<MemoryRouter>
|
||||
@@ -47,7 +28,7 @@ describe('Bundle Error', () => {
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
expect(screen.getByText('No signature bundle')).toBeInTheDocument();
|
||||
expect(screen.getByText('test-error-message')).toBeInTheDocument();
|
||||
}
|
||||
);
|
||||
|
||||
@@ -62,7 +43,7 @@ describe('Bundle Error', () => {
|
||||
</MemoryRouter>
|
||||
);
|
||||
|
||||
expect(screen.getByText('No signature bundle')).toBeInTheDocument();
|
||||
expect(screen.getByText('No bundle for proposal ID')).toBeInTheDocument();
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
+5
-20
@@ -2,8 +2,8 @@ import type { ApolloError } from '@apollo/client';
|
||||
import type { AssetStatus } from '@vegaprotocol/types';
|
||||
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import Hash from '../../../../links/hash';
|
||||
import { IconForBundleStatus } from './bundle-icon';
|
||||
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
export interface BundleErrorProps {
|
||||
status?: AssetStatus;
|
||||
@@ -17,33 +17,18 @@ export interface BundleErrorProps {
|
||||
* the status - if it's already enabled, pretend this isn't an error
|
||||
*/
|
||||
export const BundleError = ({ status, error }: BundleErrorProps) => {
|
||||
if (!status || status === 'STATUS_PROPOSED' || status === 'STATUS_REJECTED') {
|
||||
// If there is no status, there is no asset and no bundle - ProposalDetails will make it clear why.
|
||||
// If the asset exists but is just proposed, or rejected, there won't be a signature bundle yet
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div className="w-auto max-w-lg border-2 border-solid border-vega-light-100 dark:border-vega-dark-200 p-5 mt-5">
|
||||
<IconForBundleStatus status={status} />
|
||||
<h1 className="text-xl pb-1">{t('No signature bundle')}</h1>
|
||||
<h1 className="text-xl pb-1">{t('No signature bundle found')}</h1>
|
||||
|
||||
<p className="my-4">
|
||||
{t(
|
||||
'No signature bundle was generated as a result of this proposal, or the signature bundle could not be found.'
|
||||
)}
|
||||
</p>
|
||||
|
||||
<div>
|
||||
<p>
|
||||
{status === 'STATUS_ENABLED' ? (
|
||||
t('Asset already enabled')
|
||||
) : (
|
||||
<details>
|
||||
<summary>{t('Show server error message')}</summary>
|
||||
|
||||
<SyntaxHighlighter data={error} size="smaller" />
|
||||
</details>
|
||||
<Hash text={error ? error.message : t('No bundle for proposal ID')} />
|
||||
)}
|
||||
</div>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
-2
@@ -32,7 +32,6 @@ describe('Bundle Exists', () => {
|
||||
nonce={MOCK_NONCE}
|
||||
proposalId={MOCK_PROPOSAL_ID}
|
||||
signatures={MOCK_SIGNATURES}
|
||||
assetAddress={'0x123413423'}
|
||||
status={status}
|
||||
/>
|
||||
</MockedProvider>
|
||||
@@ -53,7 +52,6 @@ describe('Bundle Exists', () => {
|
||||
nonce={MOCK_NONCE}
|
||||
proposalId={MOCK_PROPOSAL_ID}
|
||||
signatures={MOCK_SIGNATURES}
|
||||
assetAddress={'0x123413423'}
|
||||
status={status}
|
||||
/>
|
||||
</MockedProvider>
|
||||
|
||||
+3
-45
@@ -1,17 +1,14 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type { AssetStatus } from '@vegaprotocol/types';
|
||||
import ProposalLink from '../../../../links/proposal-link/proposal-link';
|
||||
import { IconForBundleStatus } from './bundle-icon';
|
||||
import type { AssetStatus } from '@vegaprotocol/types';
|
||||
import type { ProposalTerms } from '../../tx-proposal';
|
||||
import { BundleSigners } from './bundle-signers';
|
||||
import { ProposalSignatureBundleDetails } from './details';
|
||||
|
||||
export interface BundleExistsProps {
|
||||
signatures: string;
|
||||
nonce: string;
|
||||
status?: AssetStatus;
|
||||
assetAddress: string;
|
||||
proposalId: string;
|
||||
tx?: ProposalTerms['newAsset'] | ProposalTerms['updateAsset'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -24,11 +21,7 @@ export const BundleExists = ({
|
||||
nonce,
|
||||
status,
|
||||
proposalId,
|
||||
assetAddress,
|
||||
tx,
|
||||
}: BundleExistsProps) => {
|
||||
// Note if this is wrong, the wrong decoder will be used which will give incorrect data
|
||||
|
||||
return (
|
||||
<div className="w-auto max-w-lg border-2 border-solid border-vega-light-100 dark:border-vega-dark-200 p-5 mt-5">
|
||||
<IconForBundleStatus status={status} />
|
||||
@@ -38,42 +31,7 @@ export const BundleExists = ({
|
||||
: t('Signature bundle generated')}
|
||||
</h1>
|
||||
|
||||
<details className="mt-5">
|
||||
<summary>{t('Signature bundle details')}</summary>
|
||||
|
||||
<div className="ml-4">
|
||||
<h2 className="text-lg mt-2 mb-2">{t('Signatures')}</h2>
|
||||
<p>
|
||||
<textarea
|
||||
className="font-mono bg-neutral-300 text-[11px] leading-3 text-gray-900 w-full p-2 max-w-[615px]"
|
||||
readOnly={true}
|
||||
rows={12}
|
||||
cols={120}
|
||||
value={signatures}
|
||||
/>
|
||||
</p>
|
||||
|
||||
<h2 className="text-lg mt-5 mb-2">{t('Nonce')}</h2>
|
||||
|
||||
<p>
|
||||
<textarea
|
||||
className="font-mono bg-neutral-300 text-[11px] leading-3 text-gray-900 w-full p-2 max-w-[615px]"
|
||||
readOnly={true}
|
||||
rows={2}
|
||||
cols={120}
|
||||
value={nonce}
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<BundleSigners
|
||||
signatures={signatures}
|
||||
nonce={nonce}
|
||||
tx={tx}
|
||||
id={proposalId}
|
||||
assetAddress={assetAddress}
|
||||
/>
|
||||
<ProposalSignatureBundleDetails signatures={signatures} nonce={nonce} />
|
||||
|
||||
{status !== 'STATUS_ENABLED' ? (
|
||||
<p className="mt-5">
|
||||
|
||||
+11
-12
@@ -1,34 +1,33 @@
|
||||
import { render } from '@testing-library/react';
|
||||
import { AssetStatus } from '@vegaprotocol/types';
|
||||
import { getIcon } from './bundle-icon';
|
||||
import { IconForBundleStatus } from './bundle-icon';
|
||||
|
||||
describe('Bundle status icon', () => {
|
||||
const NON_ENABLED_STATUS: AssetStatus[] = [
|
||||
AssetStatus.STATUS_PENDING_LISTING,
|
||||
AssetStatus.STATUS_PROPOSED,
|
||||
AssetStatus.STATUS_REJECTED,
|
||||
];
|
||||
|
||||
const ERROR_STATUS: AssetStatus[] = [AssetStatus.STATUS_REJECTED];
|
||||
|
||||
const ENABLED_STATUS: AssetStatus[] = [AssetStatus.STATUS_ENABLED];
|
||||
|
||||
it.each(NON_ENABLED_STATUS)(
|
||||
'show a sparkle icon if the bundle is unused',
|
||||
(status) => {
|
||||
expect(getIcon(status)).toEqual('clean');
|
||||
}
|
||||
);
|
||||
|
||||
it.each(ERROR_STATUS)(
|
||||
'show an error icon if the bundle is unavailable',
|
||||
(status) => {
|
||||
expect(getIcon(status)).toEqual('disable');
|
||||
const screen = render(<IconForBundleStatus status={status} />);
|
||||
const i = screen.getByRole('img');
|
||||
expect(i).toHaveAttribute('aria-label');
|
||||
expect(i.getAttribute('aria-label')).toMatch(/clean/);
|
||||
}
|
||||
);
|
||||
|
||||
it.each(ENABLED_STATUS)(
|
||||
'shows a tick if the bundle is already used',
|
||||
(status) => {
|
||||
expect(getIcon(status)).toEqual('tick-circle');
|
||||
const screen = render(<IconForBundleStatus status={status} />);
|
||||
const i = screen.getByRole('img');
|
||||
expect(i).toHaveAttribute('aria-label');
|
||||
expect(i.getAttribute('aria-label')).toMatch(/tick-circle/);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
+2
-22
@@ -12,26 +12,6 @@ export interface IconForBundleStatusProps {
|
||||
* asset should not exist
|
||||
*/
|
||||
export const IconForBundleStatus = ({ status }: IconForBundleStatusProps) => {
|
||||
const i = getIcon(status);
|
||||
|
||||
return (
|
||||
<Icon
|
||||
className="float-left mt-2 mr-3"
|
||||
name={i}
|
||||
data-testid={i}
|
||||
ariaLabel={status}
|
||||
/>
|
||||
);
|
||||
const i: IconName = status === 'STATUS_ENABLED' ? 'tick-circle' : 'clean';
|
||||
return <Icon className="float-left mt-2 mr-3" name={i} />;
|
||||
};
|
||||
|
||||
export function getIcon(status?: AssetStatus): IconName {
|
||||
switch (status) {
|
||||
case 'STATUS_ENABLED':
|
||||
return 'tick-circle';
|
||||
case undefined:
|
||||
case 'STATUS_REJECTED':
|
||||
return 'disable';
|
||||
default:
|
||||
return 'clean';
|
||||
}
|
||||
}
|
||||
|
||||
-94
@@ -1,94 +0,0 @@
|
||||
import type { EncodeListAssetParameters } from '../../../../../lib/encoders/abis/list-asset';
|
||||
import type { BridgeFunction } from './bundle-signers';
|
||||
import {
|
||||
getBridgeAddressFromNetworkParameter,
|
||||
getSigners,
|
||||
} from './bundle-signers';
|
||||
|
||||
describe('Bundle Signers helpers', () => {
|
||||
it('getBridgeAddressFromNetworkParameter handles invalid json', () => {
|
||||
expect(getBridgeAddressFromNetworkParameter('hi')).toEqual(null);
|
||||
expect(getBridgeAddressFromNetworkParameter('{hi]')).toEqual(null);
|
||||
expect(getBridgeAddressFromNetworkParameter('{"hi"}')).toEqual(null);
|
||||
expect(
|
||||
getBridgeAddressFromNetworkParameter(false as unknown as string)
|
||||
).toEqual(null);
|
||||
});
|
||||
|
||||
it('getBridgeAddressFromNetworkParameter returns null if bridge adderss is not in expected place', () => {
|
||||
expect(
|
||||
getBridgeAddressFromNetworkParameter(`{
|
||||
"NetworkParamter": false
|
||||
}`)
|
||||
).toEqual(null);
|
||||
|
||||
expect(
|
||||
getBridgeAddressFromNetworkParameter(`{
|
||||
"network_id": "11155111",
|
||||
"chain_id": "11155111",
|
||||
"confirmations": 3,
|
||||
"staking_bridge_contract": {
|
||||
"address": "0xFFb0A0d4806502ceF491aF1141f66669A1Bd0D03",
|
||||
"deployment_block_height": 2011705
|
||||
},
|
||||
"token_vesting_contract": {
|
||||
"address": "0x680fF88252FA7071CAce7398e77872d54D781d0B",
|
||||
"deployment_block_height": 2011709
|
||||
},
|
||||
"multisig_control_contract": {
|
||||
"address": "0x6eBc32d66277D94DB8FF2ccF86E36f37F29a52D3",
|
||||
"deployment_block_height": 2011699
|
||||
}
|
||||
}`)
|
||||
).toEqual(null);
|
||||
});
|
||||
|
||||
it('getBridgeAddressFromNetworkParameter returns address if the collateral_bridge_contract has an address', () => {
|
||||
expect(
|
||||
getBridgeAddressFromNetworkParameter(`{
|
||||
"network_id": "11155111",
|
||||
"chain_id": "11155111",
|
||||
"confirmations": 3,
|
||||
"collateral_bridge_contract": {
|
||||
"address": "0x7fe27d970bc8Afc3B11Cc8d9737bfB66B1efd799"
|
||||
},
|
||||
"staking_bridge_contract": {
|
||||
"address": "0xFFb0A0d4806502ceF491aF1141f66669A1Bd0D03",
|
||||
"deployment_block_height": 2011705
|
||||
},
|
||||
"token_vesting_contract": {
|
||||
"address": "0x680fF88252FA7071CAce7398e77872d54D781d0B",
|
||||
"deployment_block_height": 2011709
|
||||
},
|
||||
"multisig_control_contract": {
|
||||
"address": "0x6eBc32d66277D94DB8FF2ccF86E36f37F29a52D3",
|
||||
"deployment_block_height": 2011699
|
||||
}
|
||||
}`)
|
||||
).toEqual('0x7fe27d970bc8Afc3B11Cc8d9737bfB66B1efd799');
|
||||
});
|
||||
|
||||
it('getSigners to return [] in the case of bad inputs', () => {
|
||||
expect(
|
||||
getSigners('list_asset', '123', '', {
|
||||
assetERC20: '123',
|
||||
assetId: '456',
|
||||
limit: 'bad',
|
||||
threshold: 'data',
|
||||
nonce: 'here',
|
||||
})
|
||||
).toEqual([]);
|
||||
|
||||
expect(
|
||||
getSigners('nothing' as unknown as BridgeFunction, '123', '', {
|
||||
nonce: 'here',
|
||||
} as unknown as EncodeListAssetParameters)
|
||||
).toEqual([]);
|
||||
|
||||
expect(
|
||||
getSigners('set_asset_limits', '0x123', '0x456', {
|
||||
nonce: 'here',
|
||||
} as unknown as EncodeListAssetParameters)
|
||||
).toEqual([]);
|
||||
});
|
||||
});
|
||||
-197
@@ -1,197 +0,0 @@
|
||||
import { encodeListAssetBridgeTx } from '../../../../../lib/encoders/abis/list-asset';
|
||||
import { recoverAddress } from 'ethers/lib/utils';
|
||||
import { useExplorerBundleSignersQuery } from './__generated__/BundleSigners';
|
||||
import type { ProposalTerms } from '../../tx-proposal';
|
||||
import { DApp, TOKEN_VALIDATOR, useLinks } from '@vegaprotocol/environment';
|
||||
import { ExternalLink, Icon } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { IconNames } from '@blueprintjs/icons';
|
||||
import { encodeUpdateAssetBridgeTx } from '../../../../../lib/encoders/abis/update-asset';
|
||||
import { prepend0x } from '@vegaprotocol/smart-contracts';
|
||||
import type { EncodeListAssetParameters } from '../../../../../lib/encoders/abis/list-asset';
|
||||
|
||||
import omit from 'lodash/omit';
|
||||
|
||||
export type BridgeFunction = 'list_asset' | 'set_asset_limits';
|
||||
|
||||
export interface BundleSignersProps {
|
||||
signatures: string;
|
||||
assetAddress: string;
|
||||
nonce: string;
|
||||
tx?: ProposalTerms['updateAsset'] | ProposalTerms['newAsset'];
|
||||
id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* A logic-heavy component that takes in a signature bundle and returns
|
||||
* the list of validators that signed the bundle. To do this it requires
|
||||
* data from quite a few places - a network parameter, the signature bundle,
|
||||
* the asset that has been modified
|
||||
*/
|
||||
export const BundleSigners = ({
|
||||
signatures,
|
||||
nonce,
|
||||
assetAddress,
|
||||
tx,
|
||||
id,
|
||||
}: BundleSignersProps) => {
|
||||
const tokenLink = useLinks(DApp.Token);
|
||||
|
||||
const bridgeFunction: BridgeFunction =
|
||||
tx?.changes?.erc20 && 'contractAddress' in tx.changes.erc20
|
||||
? 'list_asset'
|
||||
: 'set_asset_limits';
|
||||
|
||||
const { data } = useExplorerBundleSignersQuery();
|
||||
|
||||
const bridgeAddress = getBridgeAddressFromNetworkParameter(
|
||||
data?.networkParameter?.value
|
||||
);
|
||||
|
||||
const allEthereumKeys =
|
||||
data?.nodesConnection?.edges
|
||||
?.filter((n) => n?.node.status === 'NODE_STATUS_VALIDATOR')
|
||||
.map((s) => s?.node) || [];
|
||||
|
||||
if (!tx || !tx.changes?.erc20) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { lifetimeLimit, withdrawThreshold } = tx.changes.erc20;
|
||||
|
||||
if (
|
||||
!id ||
|
||||
allEthereumKeys.length === 0 ||
|
||||
!bridgeAddress ||
|
||||
!lifetimeLimit ||
|
||||
!withdrawThreshold
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const signersLowerCase = getSigners(
|
||||
bridgeFunction,
|
||||
bridgeAddress,
|
||||
signatures,
|
||||
{
|
||||
assetERC20: assetAddress,
|
||||
assetId: prepend0x(id),
|
||||
limit: lifetimeLimit,
|
||||
threshold: withdrawThreshold,
|
||||
nonce,
|
||||
}
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<h2 className="mt-4 mb-2 text-lg">{t('Signed by validators')}</h2>
|
||||
<ul>
|
||||
{allEthereumKeys?.map((n) => {
|
||||
if (!n) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const validatorPage = tokenLink(TOKEN_VALIDATOR.replace(':id', n.id));
|
||||
return signersLowerCase?.indexOf(
|
||||
n?.ethereumAddress.toLowerCase() || '??'
|
||||
) !== -1 ? (
|
||||
<li key={n?.pubkey}>
|
||||
<ExternalLink href={validatorPage}>
|
||||
<Icon name={IconNames.ENDORSED} className="ml-1 mr-2" />
|
||||
{n?.name}
|
||||
<Icon size={3} name={IconNames.SHARE} className="ml-2" />
|
||||
</ExternalLink>
|
||||
</li>
|
||||
) : (
|
||||
<li>
|
||||
<ExternalLink href={validatorPage}>
|
||||
<Icon name={IconNames.MINUS} className="ml-1 mr-2" />
|
||||
{n?.name}
|
||||
<Icon size={3} name={IconNames.SHARE} className="ml-2" />
|
||||
</ExternalLink>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Given all of the collated information, this function creates an equivalent unsigned bundle
|
||||
* and recovers the signers from it, In the case of an error, it returns an empty array.
|
||||
*
|
||||
* @param bridgeFunction Decides which data goes in to the digest
|
||||
* @param bridgeAddress ERC20 bridge address
|
||||
* @param signatures Long string of signatures
|
||||
* @param params The object containing all data that the bridge requires for New or Updating assets
|
||||
* @returns String[] Empty if there was an error or no signers were recovered, otherwise lowercased ETH addresses
|
||||
*/
|
||||
export function getSigners(
|
||||
bridgeFunction: BridgeFunction,
|
||||
bridgeAddress: string,
|
||||
signatures: string,
|
||||
params: EncodeListAssetParameters
|
||||
): string[] {
|
||||
try {
|
||||
if (bridgeFunction === 'list_asset') {
|
||||
const digest = encodeListAssetBridgeTx(params, bridgeAddress);
|
||||
|
||||
// Recover Address from digest can return null, which is handled as an empty array
|
||||
return recoverAddressesFromDigest(digest, signatures) || [];
|
||||
} else {
|
||||
// The params bundles are so similar, rather than force the component to make two different
|
||||
// styles, just delete the one different property
|
||||
const p = omit(params, 'assetId');
|
||||
const digest = encodeUpdateAssetBridgeTx(p, bridgeAddress);
|
||||
return recoverAddressesFromDigest(digest, signatures) || [];
|
||||
}
|
||||
} catch (e) {
|
||||
// In the worst case, no signing addresses are recovered. This means that all nodes will
|
||||
// be rendered as if they had not signed the bundle.
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Querying for the network parameter value gets us all of the contract details for this network
|
||||
* encoded as a JSON object. This function pulls out the address for the bridge, or returns null
|
||||
* in any of the many cases where it may fail
|
||||
*
|
||||
* @param networkParameterAsString the stringified JSON object
|
||||
* @returns null or bridge address as a string
|
||||
*/
|
||||
export function getBridgeAddressFromNetworkParameter(
|
||||
networkParameterAsString: string | undefined
|
||||
): string | null {
|
||||
if (!networkParameterAsString) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
const networkParameter = JSON.parse(networkParameterAsString);
|
||||
return networkParameter.collateral_bridge_contract.address;
|
||||
} catch (e) {
|
||||
// There is no good recovery state so return null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export function recoverAddressesFromDigest(
|
||||
digest: string,
|
||||
unprefixedBundle: string
|
||||
) {
|
||||
// Remove 0x from bundle, then split it in to signatures
|
||||
const sigs = unprefixedBundle.substring(2).match(/.{1,130}/g);
|
||||
|
||||
// Convert each of the signatures from hex to a string
|
||||
const hexSigs = sigs?.map((s) => `0x${s.toString()}`);
|
||||
|
||||
if (!hexSigs) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// toLowerCase is a hack - something somewhere is lowercasing some
|
||||
// pubkeys
|
||||
return hexSigs.map((h) => recoverAddress(digest, h).toLowerCase());
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
export interface ProposalSignatureBundleDetailsProps {
|
||||
signatures: string;
|
||||
nonce: string;
|
||||
}
|
||||
|
||||
export const ProposalSignatureBundleDetails = ({
|
||||
signatures,
|
||||
nonce,
|
||||
}: ProposalSignatureBundleDetailsProps) => {
|
||||
return (
|
||||
<details className="mt-5">
|
||||
<summary>{t('Signature bundle details')}</summary>
|
||||
|
||||
<div className="ml-4">
|
||||
<h2 className="text-lg mt-2 mb-2">{t('Signatures')}</h2>
|
||||
<p>
|
||||
<textarea
|
||||
className="font-mono bg-neutral-300 text-[11px] leading-3 text-gray-900 w-full p-2 max-w-[615px]"
|
||||
readOnly={true}
|
||||
rows={12}
|
||||
cols={120}
|
||||
value={signatures}
|
||||
/>
|
||||
</p>
|
||||
|
||||
<h2 className="text-lg mt-5 mb-2">{t('Nonce')}</h2>
|
||||
<p>
|
||||
<textarea
|
||||
className="font-mono bg-neutral-300 text-[11px] leading-3 text-gray-900 w-full p-2 max-w-[615px]"
|
||||
readOnly={true}
|
||||
rows={2}
|
||||
cols={120}
|
||||
value={nonce}
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</details>
|
||||
);
|
||||
};
|
||||
@@ -61,7 +61,7 @@ export const ProposalSummary = ({
|
||||
{id && <ProposalStatusIcon id={id} />}
|
||||
{rationale?.title && <h1 className="text-xl pb-1">{rationale.title}</h1>}
|
||||
{rationale?.description && (
|
||||
<div className="pt-2 text-sm leading-tight">
|
||||
<p className="pt-2 text-sm leading-tight">
|
||||
<ReactMarkdown
|
||||
className="react-markdown-container"
|
||||
skipHtml={true}
|
||||
@@ -70,15 +70,15 @@ export const ProposalSummary = ({
|
||||
>
|
||||
{md}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</p>
|
||||
)}
|
||||
<div className="pt-5">
|
||||
<p className="pt-5">
|
||||
<button className="underline max-md:hidden mr-5" onClick={openDialog}>
|
||||
{t('View terms')}
|
||||
</button>{' '}
|
||||
<ProposalLink id={id} text={t('Full details')} />
|
||||
{terms && <ProposalDate terms={terms} id={id} />}
|
||||
</div>
|
||||
</p>
|
||||
<JsonViewerDialog
|
||||
open={dialog.open}
|
||||
onChange={(isOpen) => setDialog({ ...dialog, open: isOpen })}
|
||||
|
||||
@@ -7,9 +7,8 @@ import { txSignatureToDeterministicId } from '../lib/deterministic-ids';
|
||||
import has from 'lodash/has';
|
||||
import { ProposalSummary } from './proposal/summary';
|
||||
import Hash from '../../links/hash';
|
||||
import { ProposalSignatureBundle } from './proposal/signature-bundle';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { ProposalSignatureBundleNewAsset } from './proposal/signature-bundle-new';
|
||||
import { ProposalSignatureBundleUpdateAsset } from './proposal/signature-bundle-update';
|
||||
|
||||
export type Proposal = components['schemas']['v1ProposalSubmission'];
|
||||
export type ProposalTerms = components['schemas']['vegaProposalTerms'];
|
||||
@@ -79,12 +78,6 @@ export const TxProposal = ({ txData, pubKey, blockData }: TxProposalProps) => {
|
||||
deterministicId = txSignatureToDeterministicId(sig);
|
||||
}
|
||||
|
||||
const tx = proposal.terms?.newAsset || proposal.terms?.updateAsset;
|
||||
|
||||
const SignatureBundleComponent = proposal.terms?.newAsset
|
||||
? ProposalSignatureBundleNewAsset
|
||||
: ProposalSignatureBundleUpdateAsset;
|
||||
|
||||
return (
|
||||
<>
|
||||
<TableWithTbody className="mb-8" allowWrap={true}>
|
||||
@@ -112,7 +105,10 @@ export const TxProposal = ({ txData, pubKey, blockData }: TxProposalProps) => {
|
||||
terms={proposal?.terms}
|
||||
/>
|
||||
{proposalRequiresSignatureBundle(proposal) && (
|
||||
<SignatureBundleComponent id={deterministicId} tx={tx} />
|
||||
<ProposalSignatureBundle
|
||||
id={deterministicId}
|
||||
type={proposal.terms?.newAsset ? 'NewAsset' : 'UpdateAsset'}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
// The subset of ABI types that we use in relevant types
|
||||
export type AbiType = 'address' | 'bytes' | 'bytes32' | 'uint256' | 'string';
|
||||
@@ -1,31 +0,0 @@
|
||||
import { keccak256, defaultAbiCoder, isAddress } from 'ethers/lib/utils';
|
||||
import type { AbiType } from './abi-types';
|
||||
|
||||
export const BRIDGE_COMMAND: AbiType[] = [
|
||||
// The abi encoded bytes of the message
|
||||
'bytes',
|
||||
// The address of the bridge
|
||||
'address',
|
||||
];
|
||||
|
||||
/**
|
||||
* ABI encode values for a bridge call, getting back its digest
|
||||
*
|
||||
* @param bytes The packed bytes of the command for the bridge
|
||||
* @param address the Ethereum address of the ERC20 bridge
|
||||
* @param raw defaults to false. If set, does not keccak256 the output
|
||||
*/
|
||||
export function encodeBridgeCommand(
|
||||
bytes: string,
|
||||
address: string,
|
||||
raw = false
|
||||
) {
|
||||
if (!isAddress(address)) {
|
||||
throw new Error('Bridge address must be a hex value');
|
||||
}
|
||||
|
||||
const values = [bytes, address];
|
||||
|
||||
const value = defaultAbiCoder.encode(BRIDGE_COMMAND, values);
|
||||
return raw === true ? value : keccak256(value);
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import { encodeBridgeCommand } from './bridge-command';
|
||||
|
||||
describe('Bridge command encoder', () => {
|
||||
const VALID_BYTES =
|
||||
'0x000000000000000000000000b063f5504610ba4b8db230d9f884bfadc1e31da00b87ac58d4af7fc11c8b417153fcb62631cfd9643835ef28db3f5a1caef0b3790000000000000000000000000000000000000000000000487a9a30453944000000000000000000000000000000000000000000000000000000000000000000010b87ac58d4af7fc11c8b417153fcb62631cfd9643835ef28db3f5a1caef0b37900000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000a6c6973745f617373657400000000000000000000000000000000000000000000';
|
||||
const VALID_ADDRESS = '0x7fe27d970bc8Afc3B11Cc8d9737bfB66B1efd799';
|
||||
|
||||
it('rejects non valid bridge addresses', () => {
|
||||
expect(() => {
|
||||
encodeBridgeCommand(VALID_BYTES, '456789');
|
||||
}).toThrowError('Bridge address must be a hex value');
|
||||
});
|
||||
|
||||
it('throws if the bytes are not bytes-like', () => {
|
||||
expect(() => {
|
||||
encodeBridgeCommand('hello', VALID_ADDRESS);
|
||||
}).toThrowError(/invalid/);
|
||||
});
|
||||
|
||||
it('keccac256s the value by default', () => {
|
||||
const res = encodeBridgeCommand(VALID_BYTES, VALID_ADDRESS);
|
||||
// Magic number: Known output, including 0x
|
||||
expect(res.length).toEqual(66);
|
||||
});
|
||||
|
||||
it('Does not keccac256 the value if third param is set', () => {
|
||||
const res = encodeBridgeCommand(VALID_BYTES, VALID_ADDRESS, true);
|
||||
// Magic number: Known output
|
||||
expect(res.length).toEqual(706);
|
||||
});
|
||||
});
|
||||
@@ -1,76 +0,0 @@
|
||||
import { encodeListAsset, encodeListAssetBridgeTx } from './list-asset';
|
||||
|
||||
describe('List Asset ABI encoder', () => {
|
||||
it('throws if asset erc20 address is invalid', () => {
|
||||
expect(() => {
|
||||
encodeListAsset({
|
||||
assetERC20: '123',
|
||||
assetId: '0x456',
|
||||
limit: '1',
|
||||
threshold: '1',
|
||||
nonce: '1',
|
||||
});
|
||||
}).toThrowError('Asset ERC20 and assetID must be hex values');
|
||||
});
|
||||
|
||||
it('throws if assetId is not hex encoded', () => {
|
||||
expect(() => {
|
||||
encodeListAsset({
|
||||
assetERC20: '0x123',
|
||||
assetId: '456',
|
||||
limit: '1',
|
||||
threshold: '1',
|
||||
nonce: '1',
|
||||
});
|
||||
}).toThrowError('Asset ERC20 and assetID must be hex values');
|
||||
});
|
||||
|
||||
it('throws if values to not match expected format', () => {
|
||||
expect(() => {
|
||||
encodeListAsset({
|
||||
assetERC20: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
|
||||
assetId: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
|
||||
limit: 'not a valid number',
|
||||
threshold: '1',
|
||||
nonce: '1',
|
||||
});
|
||||
}).toThrowError(/incorrect data length/);
|
||||
});
|
||||
|
||||
it('returns an ABI encoded value if inputs are valid', () => {
|
||||
const EXPECTED_OUTPUT =
|
||||
'0x000000000000000000000000b063f5504610ba4b8db230d9f884bfadc1e31da00b87ac58d4af7fc11c8b417153fcb62631cfd9643835ef28db3f5a1caef0b37900000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000a6c6973745f617373657400000000000000000000000000000000000000000000';
|
||||
|
||||
const res = encodeListAsset({
|
||||
assetERC20: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
|
||||
assetId:
|
||||
'0x0b87ac58d4af7fc11c8b417153fcb62631cfd9643835ef28db3f5a1caef0b379',
|
||||
limit: '1',
|
||||
threshold: '1',
|
||||
nonce: '1',
|
||||
});
|
||||
|
||||
expect(res).toEqual(EXPECTED_OUTPUT);
|
||||
});
|
||||
|
||||
it('encodeListAssetBridge returns a keccak256 hash of the bridge tx', () => {
|
||||
const EXPECTED_OUTPUT =
|
||||
'0xe0e62b27fe4490025d312bb2e37486f56935a3d9442dc34c2b918b2a28a386f2';
|
||||
|
||||
const res = encodeListAssetBridgeTx(
|
||||
{
|
||||
assetERC20: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
|
||||
assetId:
|
||||
'0x0b87ac58d4af7fc11c8b417153fcb62631cfd9643835ef28db3f5a1caef0b379',
|
||||
limit: '1',
|
||||
threshold: '1',
|
||||
nonce: '1',
|
||||
},
|
||||
'0xb063f5504610ba4b8db230d9f884bfadc1e31da0'
|
||||
);
|
||||
|
||||
// Magic number: keccak256 hash length + '0x'
|
||||
expect(res.length).toEqual(66);
|
||||
expect(res).toEqual(EXPECTED_OUTPUT);
|
||||
});
|
||||
});
|
||||
@@ -1,76 +0,0 @@
|
||||
import { defaultAbiCoder, isAddress, isHexString } from 'ethers/lib/utils';
|
||||
import { encodeBridgeCommand } from './bridge-command';
|
||||
import type { AbiType } from './abi-types';
|
||||
|
||||
export const METHOD_NAME = 'list_asset';
|
||||
|
||||
export const LIST_ASSET_ABI: AbiType[] = [
|
||||
// Asset address
|
||||
'address',
|
||||
// Asset ID on Vega
|
||||
'bytes32',
|
||||
// Lifetime limit
|
||||
'uint256',
|
||||
// Withdraw threshold
|
||||
'uint256',
|
||||
// Nonce
|
||||
'uint256',
|
||||
// Contract method name
|
||||
'string',
|
||||
];
|
||||
|
||||
export interface EncodeListAssetParameters {
|
||||
// The ETH address of the ERC20 asset
|
||||
assetERC20: string;
|
||||
// The Vega ID of the asset, 0x prefixed
|
||||
assetId: string;
|
||||
// The number as a string of the asset
|
||||
limit: string;
|
||||
// THe number-as-a-string of the withdraw threshold
|
||||
threshold: string;
|
||||
// The n-once supplied to the contract
|
||||
nonce: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an ABI encoded function call to list an asset. This is
|
||||
* used in the Signature Bundle view on some proposals to recover
|
||||
* which validators signed a multisig bundle. It does this by recovering
|
||||
* the ERC20 addresses of the signers, then comparing those to the list
|
||||
* of signers on the bundle. In order to do this, we recreate the signed
|
||||
* data from the values we know from the transaction. That last part
|
||||
* is what this function does.
|
||||
*
|
||||
* @param EncodeListAssetParameters The arguments for the ABI call
|
||||
* @returns string encoded message
|
||||
*/
|
||||
export function encodeListAsset({
|
||||
assetERC20,
|
||||
assetId,
|
||||
limit,
|
||||
threshold,
|
||||
nonce,
|
||||
}: EncodeListAssetParameters) {
|
||||
if (!isAddress(assetERC20) || !isHexString(assetId)) {
|
||||
throw new Error('Asset ERC20 and assetID must be hex values');
|
||||
}
|
||||
|
||||
const values = [assetERC20, assetId, limit, threshold, nonce, METHOD_NAME];
|
||||
|
||||
return defaultAbiCoder.encode(LIST_ASSET_ABI, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function that encodes and packs the message as it is encoded by the
|
||||
* validators in a multisig bundle
|
||||
*
|
||||
* @param params Parameters for the List Asset call
|
||||
* @param bridgeAddress Bridge address for the appropiate network
|
||||
* @returns keccak256 encoded message digest
|
||||
*/
|
||||
export function encodeListAssetBridgeTx(
|
||||
params: EncodeListAssetParameters,
|
||||
bridgeAddress: string
|
||||
) {
|
||||
return encodeBridgeCommand(encodeListAsset(params), bridgeAddress);
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
import { encodeUpdateAsset, encodeUpdateAssetBridgeTx } from './update-asset';
|
||||
|
||||
describe('Update Asset ABI encoder', () => {
|
||||
it('throws if asset erc20 address is invalid', () => {
|
||||
expect(() => {
|
||||
encodeUpdateAsset({
|
||||
assetERC20: '123',
|
||||
limit: '1',
|
||||
threshold: '1',
|
||||
nonce: '1',
|
||||
});
|
||||
}).toThrowError('Asset ERC20 must be a valid address');
|
||||
});
|
||||
|
||||
it('throws if an input is invalid', () => {
|
||||
expect(() => {
|
||||
encodeUpdateAsset({
|
||||
assetERC20: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
|
||||
limit: 'hello',
|
||||
threshold: '1',
|
||||
nonce: '1',
|
||||
});
|
||||
}).toThrowError(/invalid BigNumber/);
|
||||
});
|
||||
|
||||
it('returns an ABI encoded value if inputs are valid', () => {
|
||||
const EXPECTED_OUTPUT =
|
||||
'0x000000000000000000000000b063f5504610ba4b8db230d9f884bfadc1e31da000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000107365745f61737365745f6c696d69747300000000000000000000000000000000';
|
||||
|
||||
const res = encodeUpdateAsset({
|
||||
assetERC20: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
|
||||
limit: '1',
|
||||
threshold: '1',
|
||||
nonce: '1',
|
||||
});
|
||||
|
||||
expect(res).toEqual(EXPECTED_OUTPUT);
|
||||
});
|
||||
|
||||
it('encodeUpdateAssetBridge returns a keccak256 hash of the bridge tx', () => {
|
||||
const EXPECTED_OUTPUT =
|
||||
'0xeb240131c4558aebfab3da0ddbea1ac0447b9f5670899af2d78795867631d877';
|
||||
|
||||
const res = encodeUpdateAssetBridgeTx(
|
||||
{
|
||||
assetERC20: '0xb063f5504610ba4b8db230d9f884bfadc1e31da0',
|
||||
limit: '1',
|
||||
threshold: '1',
|
||||
nonce: '1',
|
||||
},
|
||||
'0xb063f5504610ba4b8db230d9f884bfadc1e31da0'
|
||||
);
|
||||
|
||||
// Magic number: keccak256 hash length + '0x'
|
||||
expect(res.length).toEqual(66);
|
||||
expect(res).toEqual(EXPECTED_OUTPUT);
|
||||
});
|
||||
});
|
||||
@@ -1,65 +0,0 @@
|
||||
import { defaultAbiCoder, isAddress } from 'ethers/lib/utils';
|
||||
import { encodeBridgeCommand } from './bridge-command';
|
||||
import type { AbiType } from './abi-types';
|
||||
|
||||
export const METHOD_NAME = 'set_asset_limits';
|
||||
|
||||
export const LIST_ASSET_ABI: AbiType[] = [
|
||||
// Asset address
|
||||
'address',
|
||||
// Lifetime limit
|
||||
'uint256',
|
||||
// Withdraw threshold
|
||||
'uint256',
|
||||
// Nonce
|
||||
'uint256',
|
||||
// Contract method name
|
||||
'string',
|
||||
];
|
||||
|
||||
export interface EncodeUpdateAssetParameters {
|
||||
// The ETH address of the ERC20 asset
|
||||
assetERC20: string;
|
||||
// The number as a string of the asset
|
||||
limit: string;
|
||||
// THe number-as-a-string of the withdraw threshold
|
||||
threshold: string;
|
||||
// The n-once supplied to the contract
|
||||
nonce: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates an ABI encoded function call to list an asset
|
||||
*
|
||||
* @param EncodeListAssetParameters The arguments for the ABI call
|
||||
* @returns string encoded message
|
||||
*/
|
||||
export function encodeUpdateAsset({
|
||||
assetERC20,
|
||||
limit,
|
||||
threshold,
|
||||
nonce,
|
||||
}: EncodeUpdateAssetParameters) {
|
||||
if (!isAddress(assetERC20)) {
|
||||
throw new Error('Asset ERC20 must be a valid address');
|
||||
}
|
||||
|
||||
const values = [assetERC20, limit, threshold, nonce, METHOD_NAME];
|
||||
|
||||
return defaultAbiCoder.encode(LIST_ASSET_ABI, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function that encodes and packs the message as it is encoded by the
|
||||
* validators in a multisig bundle
|
||||
*
|
||||
* @param params Parameters for the List Asset call
|
||||
* @param bridgeAddress Bridge address for the appropiate network
|
||||
* @returns keccak256 encoded message digest
|
||||
*/
|
||||
export function encodeUpdateAssetBridgeTx(
|
||||
params: EncodeUpdateAssetParameters,
|
||||
bridgeAddress: string
|
||||
) {
|
||||
return encodeBridgeCommand(encodeUpdateAsset(params), bridgeAddress);
|
||||
}
|
||||
@@ -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 { marketInfoWithDataProvider } from '@vegaprotocol/market-info';
|
||||
import { marketInfoProvider } 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: marketInfoWithDataProvider,
|
||||
dataProvider: marketInfoProvider,
|
||||
skipUpdates: true,
|
||||
variables: {
|
||||
marketId: marketId || '',
|
||||
|
||||
@@ -22,7 +22,6 @@ const Tx = () => {
|
||||
|
||||
const {
|
||||
state: { data, loading, error },
|
||||
refetch,
|
||||
} = useFetch<BlockExplorerTransaction>(
|
||||
`${DATA_SOURCES.blockExplorerUrl}/transactions/${toNonHex(hash)}`
|
||||
);
|
||||
@@ -57,7 +56,6 @@ 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 {
|
||||
EtherscanLink,
|
||||
ContractAddressLink,
|
||||
DApp,
|
||||
TOKEN_VALIDATOR,
|
||||
useLinks,
|
||||
@@ -176,14 +176,25 @@ export const ValidatorsPage = () => {
|
||||
const validatorName =
|
||||
v.name && v.name.length > 0 ? v.name : truncateMiddle(v.id);
|
||||
return (
|
||||
<li className="mb-5 relative" key={v.id}>
|
||||
<li className="mb-5" key={v.id}>
|
||||
<div
|
||||
data-testid="validator-tile"
|
||||
validator-id={v.id}
|
||||
className="border border-vega-light-200 dark:border-vega-dark-200 rounded p-2 overflow-hidden"
|
||||
className="border border-vega-light-200 dark:border-vega-dark-200 rounded p-2 overflow-hidden relative flex gap-2 items-start justify-between"
|
||||
>
|
||||
{v.avatarUrl && (
|
||||
<div className="w-20">
|
||||
<ExternalLink href={validatorPage}>
|
||||
<img
|
||||
className="w-full"
|
||||
src={v.avatarUrl}
|
||||
alt={validatorName}
|
||||
/>
|
||||
</ExternalLink>
|
||||
</div>
|
||||
)}
|
||||
<div className="w-full">
|
||||
<h2 className="font-alpha text-2xl leading-[60px]">
|
||||
<h2 className="font-alpha text-2xl">
|
||||
<ExternalLink href={validatorPage}>
|
||||
{validatorName}
|
||||
</ExternalLink>
|
||||
@@ -224,7 +235,7 @@ export const ValidatorsPage = () => {
|
||||
<KeyValueTableRow>
|
||||
<div>{t('Ethereum address')}</div>
|
||||
<div className="break-all text-xs">
|
||||
<EtherscanLink address={v.ethereumAddress} />{' '}
|
||||
<ContractAddressLink address={v.ethereumAddress} />{' '}
|
||||
<CopyWithTooltip text={v.ethereumAddress}>
|
||||
<button title={t('Copy address to clipboard')}>
|
||||
<Icon size={3} name="duplicate" />
|
||||
@@ -304,23 +315,6 @@ export const ValidatorsPage = () => {
|
||||
</div>
|
||||
</div>
|
||||
</KeyValueTableRow>
|
||||
{v.avatarUrl && (
|
||||
<KeyValueTableRow>
|
||||
<div>{t('Avatar')}</div>
|
||||
<div>
|
||||
<ExternalLink
|
||||
href={validatorPage}
|
||||
className="mx-auto"
|
||||
>
|
||||
<img
|
||||
className="max-w-[75px] md:max-w-[200px] max-h-[80px]"
|
||||
src={v.avatarUrl}
|
||||
alt={validatorName}
|
||||
/>
|
||||
</ExternalLink>
|
||||
</div>
|
||||
</KeyValueTableRow>
|
||||
)}
|
||||
</KeyValueTable>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
"changes": {
|
||||
"decimalPlaces": "5",
|
||||
"positionDecimalPlaces": "5",
|
||||
"linearSlippageFactor": "0.001",
|
||||
"quadraticSlippageFactor": "0",
|
||||
"lpPriceRange": "10",
|
||||
"instrument": {
|
||||
"name": "Token test market",
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{
|
||||
"lpPriceRange": "10",
|
||||
"linearSlippageFactor": "0.001",
|
||||
"quadraticSlippageFactor": "0",
|
||||
"instrument": {
|
||||
"code": "TEST.24h",
|
||||
"future": {
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
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, '100000000000000000000');
|
||||
cy.deposit_asset(usdcEthAddress);
|
||||
});
|
||||
|
||||
beforeEach('Navigate to withdrawal page', function () {
|
||||
|
||||
@@ -73,7 +73,7 @@ context(
|
||||
.should('be.visible')
|
||||
.and(
|
||||
'have.text',
|
||||
'Rewards are credited less than a minute after the epoch ends.This delay is set by a network parameter'
|
||||
'Rewards are credited 5 minutes after the epoch ends.This delay is set by a network parameter'
|
||||
);
|
||||
});
|
||||
it('should have toggle for seeing total vs individual rewards', () => {
|
||||
|
||||
@@ -83,7 +83,6 @@ 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: '[data-testid="navigation"]',
|
||||
section: 'nav',
|
||||
vesting: '[href="/token/redeem"]',
|
||||
validators: '[href="/validators"]',
|
||||
rewards: '[href="/rewards"]',
|
||||
|
||||
@@ -47,14 +47,13 @@ beforeEach(function () {
|
||||
cy.wrap(this.vestingContract).as('vestingContract');
|
||||
});
|
||||
|
||||
Cypress.Commands.add('deposit_asset', function (assetEthAddress, amount) {
|
||||
cy.highlight('Depositing asset into vegawallet');
|
||||
Cypress.Commands.add('deposit_asset', function (assetEthAddress) {
|
||||
cy.get('@signer', { log: false }).then((signer) => {
|
||||
// Approve asset
|
||||
cy.wrap(
|
||||
new TokenFaucetable(assetEthAddress, signer).approve(
|
||||
Erc20BridgeAddress,
|
||||
amount + '0'.repeat(19)
|
||||
'10000000000'
|
||||
)
|
||||
)
|
||||
.then((tx) => {
|
||||
@@ -68,7 +67,7 @@ Cypress.Commands.add('deposit_asset', function (assetEthAddress, amount) {
|
||||
cy.wrap(
|
||||
bridge.deposit_asset(
|
||||
assetEthAddress,
|
||||
amount + '0'.repeat(18),
|
||||
'1000000000',
|
||||
'0x' + vegaWalletPubKey
|
||||
),
|
||||
{ timeout: transactionTimeout, log: false }
|
||||
@@ -110,9 +109,10 @@ Cypress.Commands.add('vega_wallet_teardown', function () {
|
||||
}
|
||||
});
|
||||
cy.get(vegaWalletContainer).within(() => {
|
||||
cy.get('[data-testid="vega-wallet-balance-unstaked"]', {
|
||||
timeout: 30000,
|
||||
}).should('contain.text', '0.00');
|
||||
cy.get('[data-testid="associated-amount"]', { timeout: 30000 }).should(
|
||||
'contain.text',
|
||||
'0.00'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mirror-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
|
||||
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_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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet1-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
|
||||
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,8 +1,8 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_ENV=VALIDATOR_TESTNET
|
||||
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.rocks/
|
||||
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_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
|
||||
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
|
||||
|
||||
@@ -21,7 +21,7 @@ export function TemplateSidebar({ children, sidebar }: TemplateSidebarProps) {
|
||||
<>
|
||||
<AnnouncementBanner>
|
||||
<div className="font-alpha calt uppercase text-center text-lg text-white">
|
||||
<span className="pr-4">Mainnet sim 3 is live!</span>
|
||||
<span className="pr-4">Mainnet sim 3 is coming soon!</span>
|
||||
<ExternalLink href="https://fairground.wtf/">
|
||||
Come help stress test the network
|
||||
</ExternalLink>
|
||||
|
||||
+121
-51
@@ -3,66 +3,115 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type WalletDelegationFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } };
|
||||
export type WalletDelegationFieldsFragment = {
|
||||
__typename?: 'Delegation';
|
||||
amount: string;
|
||||
epoch: number;
|
||||
node: { __typename?: 'Node'; id: string; name: string };
|
||||
};
|
||||
|
||||
export type DelegationsQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
|
||||
}>;
|
||||
|
||||
|
||||
export type DelegationsQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string }, party?: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string, name: string } } } | null> | null } | null, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, accountsConnection?: { __typename?: 'AccountsConnection', edges?: Array<{ __typename?: 'AccountEdge', node: { __typename?: 'AccountBalance', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', name: string, id: string, decimals: number, symbol: string, source: { __typename: 'BuiltinAsset' } | { __typename: 'ERC20', contractAddress: string } } } } | null> | null } | null } | null };
|
||||
export type DelegationsQuery = {
|
||||
__typename?: 'Query';
|
||||
epoch: { __typename?: 'Epoch'; id: string };
|
||||
party?: {
|
||||
__typename?: 'Party';
|
||||
id: string;
|
||||
delegationsConnection?: {
|
||||
__typename?: 'DelegationsConnection';
|
||||
edges?: Array<{
|
||||
__typename?: 'DelegationEdge';
|
||||
node: {
|
||||
__typename?: 'Delegation';
|
||||
amount: string;
|
||||
epoch: number;
|
||||
node: { __typename?: 'Node'; id: string; name: string };
|
||||
};
|
||||
} | null> | null;
|
||||
} | null;
|
||||
stakingSummary: {
|
||||
__typename?: 'StakingSummary';
|
||||
currentStakeAvailable: string;
|
||||
};
|
||||
accountsConnection?: {
|
||||
__typename?: 'AccountsConnection';
|
||||
edges?: Array<{
|
||||
__typename?: 'AccountEdge';
|
||||
node: {
|
||||
__typename?: 'AccountBalance';
|
||||
type: Types.AccountType;
|
||||
balance: string;
|
||||
asset: {
|
||||
__typename?: 'Asset';
|
||||
name: string;
|
||||
id: string;
|
||||
decimals: number;
|
||||
symbol: string;
|
||||
source:
|
||||
| { __typename: 'BuiltinAsset' }
|
||||
| { __typename: 'ERC20'; contractAddress: string };
|
||||
};
|
||||
};
|
||||
} | null> | null;
|
||||
} | null;
|
||||
} | null;
|
||||
};
|
||||
|
||||
export const WalletDelegationFieldsFragmentDoc = gql`
|
||||
fragment WalletDelegationFields on Delegation {
|
||||
amount
|
||||
node {
|
||||
id
|
||||
name
|
||||
fragment WalletDelegationFields on Delegation {
|
||||
amount
|
||||
node {
|
||||
id
|
||||
name
|
||||
}
|
||||
epoch
|
||||
}
|
||||
epoch
|
||||
}
|
||||
`;
|
||||
`;
|
||||
export const DelegationsDocument = gql`
|
||||
query Delegations($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
epoch {
|
||||
id
|
||||
}
|
||||
party(id: $partyId) {
|
||||
id
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
edges {
|
||||
node {
|
||||
...WalletDelegationFields
|
||||
query Delegations($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
epoch {
|
||||
id
|
||||
}
|
||||
party(id: $partyId) {
|
||||
id
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
edges {
|
||||
node {
|
||||
...WalletDelegationFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
stakingSummary {
|
||||
currentStakeAvailable
|
||||
}
|
||||
accountsConnection {
|
||||
edges {
|
||||
node {
|
||||
asset {
|
||||
name
|
||||
id
|
||||
decimals
|
||||
symbol
|
||||
source {
|
||||
__typename
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
stakingSummary {
|
||||
currentStakeAvailable
|
||||
}
|
||||
accountsConnection {
|
||||
edges {
|
||||
node {
|
||||
asset {
|
||||
name
|
||||
id
|
||||
decimals
|
||||
symbol
|
||||
source {
|
||||
__typename
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
type
|
||||
balance
|
||||
}
|
||||
type
|
||||
balance
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${WalletDelegationFieldsFragmentDoc}`;
|
||||
${WalletDelegationFieldsFragmentDoc}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useDelegationsQuery__
|
||||
@@ -81,14 +130,35 @@ export const DelegationsDocument = gql`
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useDelegationsQuery(baseOptions: Apollo.QueryHookOptions<DelegationsQuery, DelegationsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<DelegationsQuery, DelegationsQueryVariables>(DelegationsDocument, options);
|
||||
}
|
||||
export function useDelegationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DelegationsQuery, DelegationsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<DelegationsQuery, DelegationsQueryVariables>(DelegationsDocument, options);
|
||||
}
|
||||
export function useDelegationsQuery(
|
||||
baseOptions: Apollo.QueryHookOptions<
|
||||
DelegationsQuery,
|
||||
DelegationsQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useQuery<DelegationsQuery, DelegationsQueryVariables>(
|
||||
DelegationsDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export function useDelegationsLazyQuery(
|
||||
baseOptions?: Apollo.LazyQueryHookOptions<
|
||||
DelegationsQuery,
|
||||
DelegationsQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useLazyQuery<DelegationsQuery, DelegationsQueryVariables>(
|
||||
DelegationsDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export type DelegationsQueryHookResult = ReturnType<typeof useDelegationsQuery>;
|
||||
export type DelegationsLazyQueryHookResult = ReturnType<typeof useDelegationsLazyQuery>;
|
||||
export type DelegationsQueryResult = Apollo.QueryResult<DelegationsQuery, DelegationsQueryVariables>;
|
||||
export type DelegationsLazyQueryHookResult = ReturnType<
|
||||
typeof useDelegationsLazyQuery
|
||||
>;
|
||||
export type DelegationsQueryResult = Apollo.QueryResult<
|
||||
DelegationsQuery,
|
||||
DelegationsQueryVariables
|
||||
>;
|
||||
|
||||
+105
-44
@@ -7,29 +7,44 @@ export type ProposalAssetQueryVariables = Types.Exact<{
|
||||
assetId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ProposalAssetQuery = { __typename?: 'Query', asset?: { __typename?: 'Asset', status: Types.AssetStatus, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } | null };
|
||||
export type ProposalAssetQuery = {
|
||||
__typename?: 'Query';
|
||||
asset?: {
|
||||
__typename?: 'Asset';
|
||||
status: Types.AssetStatus;
|
||||
source:
|
||||
| { __typename?: 'BuiltinAsset' }
|
||||
| { __typename?: 'ERC20'; contractAddress: string };
|
||||
} | null;
|
||||
};
|
||||
|
||||
export type AssetListBundleQueryVariables = Types.Exact<{
|
||||
assetId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type AssetListBundleQuery = { __typename?: 'Query', erc20ListAssetBundle?: { __typename?: 'Erc20ListAssetBundle', assetSource: string, vegaAssetId: string, nonce: string, signatures: string } | null };
|
||||
|
||||
export type AssetListBundleQuery = {
|
||||
__typename?: 'Query';
|
||||
erc20ListAssetBundle?: {
|
||||
__typename?: 'Erc20ListAssetBundle';
|
||||
assetSource: string;
|
||||
vegaAssetId: string;
|
||||
nonce: string;
|
||||
signatures: string;
|
||||
} | null;
|
||||
};
|
||||
|
||||
export const ProposalAssetDocument = gql`
|
||||
query ProposalAsset($assetId: ID!) {
|
||||
asset(id: $assetId) {
|
||||
status
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
query ProposalAsset($assetId: ID!) {
|
||||
asset(id: $assetId) {
|
||||
status
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useProposalAssetQuery__
|
||||
@@ -47,27 +62,50 @@ export const ProposalAssetDocument = gql`
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useProposalAssetQuery(baseOptions: Apollo.QueryHookOptions<ProposalAssetQuery, ProposalAssetQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<ProposalAssetQuery, ProposalAssetQueryVariables>(ProposalAssetDocument, options);
|
||||
}
|
||||
export function useProposalAssetLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ProposalAssetQuery, ProposalAssetQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<ProposalAssetQuery, ProposalAssetQueryVariables>(ProposalAssetDocument, options);
|
||||
}
|
||||
export type ProposalAssetQueryHookResult = ReturnType<typeof useProposalAssetQuery>;
|
||||
export type ProposalAssetLazyQueryHookResult = ReturnType<typeof useProposalAssetLazyQuery>;
|
||||
export type ProposalAssetQueryResult = Apollo.QueryResult<ProposalAssetQuery, ProposalAssetQueryVariables>;
|
||||
export const AssetListBundleDocument = gql`
|
||||
query AssetListBundle($assetId: ID!) {
|
||||
erc20ListAssetBundle(assetId: $assetId) {
|
||||
assetSource
|
||||
vegaAssetId
|
||||
nonce
|
||||
signatures
|
||||
}
|
||||
export function useProposalAssetQuery(
|
||||
baseOptions: Apollo.QueryHookOptions<
|
||||
ProposalAssetQuery,
|
||||
ProposalAssetQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useQuery<ProposalAssetQuery, ProposalAssetQueryVariables>(
|
||||
ProposalAssetDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
`;
|
||||
export function useProposalAssetLazyQuery(
|
||||
baseOptions?: Apollo.LazyQueryHookOptions<
|
||||
ProposalAssetQuery,
|
||||
ProposalAssetQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useLazyQuery<ProposalAssetQuery, ProposalAssetQueryVariables>(
|
||||
ProposalAssetDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export type ProposalAssetQueryHookResult = ReturnType<
|
||||
typeof useProposalAssetQuery
|
||||
>;
|
||||
export type ProposalAssetLazyQueryHookResult = ReturnType<
|
||||
typeof useProposalAssetLazyQuery
|
||||
>;
|
||||
export type ProposalAssetQueryResult = Apollo.QueryResult<
|
||||
ProposalAssetQuery,
|
||||
ProposalAssetQueryVariables
|
||||
>;
|
||||
export const AssetListBundleDocument = gql`
|
||||
query AssetListBundle($assetId: ID!) {
|
||||
erc20ListAssetBundle(assetId: $assetId) {
|
||||
assetSource
|
||||
vegaAssetId
|
||||
nonce
|
||||
signatures
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useAssetListBundleQuery__
|
||||
@@ -85,14 +123,37 @@ export const AssetListBundleDocument = gql`
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useAssetListBundleQuery(baseOptions: Apollo.QueryHookOptions<AssetListBundleQuery, AssetListBundleQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<AssetListBundleQuery, AssetListBundleQueryVariables>(AssetListBundleDocument, options);
|
||||
}
|
||||
export function useAssetListBundleLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<AssetListBundleQuery, AssetListBundleQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<AssetListBundleQuery, AssetListBundleQueryVariables>(AssetListBundleDocument, options);
|
||||
}
|
||||
export type AssetListBundleQueryHookResult = ReturnType<typeof useAssetListBundleQuery>;
|
||||
export type AssetListBundleLazyQueryHookResult = ReturnType<typeof useAssetListBundleLazyQuery>;
|
||||
export type AssetListBundleQueryResult = Apollo.QueryResult<AssetListBundleQuery, AssetListBundleQueryVariables>;
|
||||
export function useAssetListBundleQuery(
|
||||
baseOptions: Apollo.QueryHookOptions<
|
||||
AssetListBundleQuery,
|
||||
AssetListBundleQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useQuery<AssetListBundleQuery, AssetListBundleQueryVariables>(
|
||||
AssetListBundleDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export function useAssetListBundleLazyQuery(
|
||||
baseOptions?: Apollo.LazyQueryHookOptions<
|
||||
AssetListBundleQuery,
|
||||
AssetListBundleQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useLazyQuery<
|
||||
AssetListBundleQuery,
|
||||
AssetListBundleQueryVariables
|
||||
>(AssetListBundleDocument, options);
|
||||
}
|
||||
export type AssetListBundleQueryHookResult = ReturnType<
|
||||
typeof useAssetListBundleQuery
|
||||
>;
|
||||
export type AssetListBundleLazyQueryHookResult = ReturnType<
|
||||
typeof useAssetListBundleLazyQuery
|
||||
>;
|
||||
export type AssetListBundleQueryResult = Apollo.QueryResult<
|
||||
AssetListBundleQuery,
|
||||
AssetListBundleQueryVariables
|
||||
>;
|
||||
|
||||
+49
-20
@@ -7,20 +7,28 @@ export type VoteButtonsQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type VoteButtonsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string } } | null };
|
||||
|
||||
export type VoteButtonsQuery = {
|
||||
__typename?: 'Query';
|
||||
party?: {
|
||||
__typename?: 'Party';
|
||||
id: string;
|
||||
stakingSummary: {
|
||||
__typename?: 'StakingSummary';
|
||||
currentStakeAvailable: string;
|
||||
};
|
||||
} | null;
|
||||
};
|
||||
|
||||
export const VoteButtonsDocument = gql`
|
||||
query VoteButtons($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
stakingSummary {
|
||||
currentStakeAvailable
|
||||
query VoteButtons($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
stakingSummary {
|
||||
currentStakeAvailable
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useVoteButtonsQuery__
|
||||
@@ -38,14 +46,35 @@ export const VoteButtonsDocument = gql`
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useVoteButtonsQuery(baseOptions: Apollo.QueryHookOptions<VoteButtonsQuery, VoteButtonsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<VoteButtonsQuery, VoteButtonsQueryVariables>(VoteButtonsDocument, options);
|
||||
}
|
||||
export function useVoteButtonsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<VoteButtonsQuery, VoteButtonsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<VoteButtonsQuery, VoteButtonsQueryVariables>(VoteButtonsDocument, options);
|
||||
}
|
||||
export function useVoteButtonsQuery(
|
||||
baseOptions: Apollo.QueryHookOptions<
|
||||
VoteButtonsQuery,
|
||||
VoteButtonsQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useQuery<VoteButtonsQuery, VoteButtonsQueryVariables>(
|
||||
VoteButtonsDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export function useVoteButtonsLazyQuery(
|
||||
baseOptions?: Apollo.LazyQueryHookOptions<
|
||||
VoteButtonsQuery,
|
||||
VoteButtonsQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useLazyQuery<VoteButtonsQuery, VoteButtonsQueryVariables>(
|
||||
VoteButtonsDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export type VoteButtonsQueryHookResult = ReturnType<typeof useVoteButtonsQuery>;
|
||||
export type VoteButtonsLazyQueryHookResult = ReturnType<typeof useVoteButtonsLazyQuery>;
|
||||
export type VoteButtonsQueryResult = Apollo.QueryResult<VoteButtonsQuery, VoteButtonsQueryVariables>;
|
||||
export type VoteButtonsLazyQueryHookResult = ReturnType<
|
||||
typeof useVoteButtonsLazyQuery
|
||||
>;
|
||||
export type VoteButtonsQueryResult = Apollo.QueryResult<
|
||||
VoteButtonsQuery,
|
||||
VoteButtonsQueryVariables
|
||||
>;
|
||||
|
||||
+56
-24
@@ -7,27 +7,41 @@ export type UserVoteQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type UserVoteQuery = { __typename?: 'Query', party?: { __typename?: 'Party', votesConnection?: { __typename?: 'ProposalVoteConnection', edges?: Array<{ __typename?: 'ProposalVoteEdge', node: { __typename?: 'ProposalVote', proposalId: string, vote: { __typename?: 'Vote', value: Types.VoteValue, datetime: any } } }> | null } | null } | null };
|
||||
|
||||
export type UserVoteQuery = {
|
||||
__typename?: 'Query';
|
||||
party?: {
|
||||
__typename?: 'Party';
|
||||
votesConnection?: {
|
||||
__typename?: 'ProposalVoteConnection';
|
||||
edges?: Array<{
|
||||
__typename?: 'ProposalVoteEdge';
|
||||
node: {
|
||||
__typename?: 'ProposalVote';
|
||||
proposalId: string;
|
||||
vote: { __typename?: 'Vote'; value: Types.VoteValue; datetime: any };
|
||||
};
|
||||
}> | null;
|
||||
} | null;
|
||||
} | null;
|
||||
};
|
||||
|
||||
export const UserVoteDocument = gql`
|
||||
query UserVote($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
votesConnection {
|
||||
edges {
|
||||
node {
|
||||
proposalId
|
||||
vote {
|
||||
value
|
||||
datetime
|
||||
query UserVote($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
votesConnection {
|
||||
edges {
|
||||
node {
|
||||
proposalId
|
||||
vote {
|
||||
value
|
||||
datetime
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useUserVoteQuery__
|
||||
@@ -45,14 +59,32 @@ export const UserVoteDocument = gql`
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useUserVoteQuery(baseOptions: Apollo.QueryHookOptions<UserVoteQuery, UserVoteQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<UserVoteQuery, UserVoteQueryVariables>(UserVoteDocument, options);
|
||||
}
|
||||
export function useUserVoteLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<UserVoteQuery, UserVoteQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<UserVoteQuery, UserVoteQueryVariables>(UserVoteDocument, options);
|
||||
}
|
||||
export function useUserVoteQuery(
|
||||
baseOptions: Apollo.QueryHookOptions<UserVoteQuery, UserVoteQueryVariables>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useQuery<UserVoteQuery, UserVoteQueryVariables>(
|
||||
UserVoteDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export function useUserVoteLazyQuery(
|
||||
baseOptions?: Apollo.LazyQueryHookOptions<
|
||||
UserVoteQuery,
|
||||
UserVoteQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useLazyQuery<UserVoteQuery, UserVoteQueryVariables>(
|
||||
UserVoteDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export type UserVoteQueryHookResult = ReturnType<typeof useUserVoteQuery>;
|
||||
export type UserVoteLazyQueryHookResult = ReturnType<typeof useUserVoteLazyQuery>;
|
||||
export type UserVoteQueryResult = Apollo.QueryResult<UserVoteQuery, UserVoteQueryVariables>;
|
||||
export type UserVoteLazyQueryHookResult = ReturnType<
|
||||
typeof useUserVoteLazyQuery
|
||||
>;
|
||||
export type UserVoteQueryResult = Apollo.QueryResult<
|
||||
UserVoteQuery,
|
||||
UserVoteQueryVariables
|
||||
>;
|
||||
|
||||
+619
-222
File diff suppressed because one or more lines are too long
+283
-92
@@ -3,106 +3,279 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type ProposalFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } };
|
||||
export type ProposalFieldsFragment = {
|
||||
__typename?: 'Proposal';
|
||||
id?: string | null;
|
||||
reference: string;
|
||||
state: Types.ProposalState;
|
||||
datetime: any;
|
||||
rejectionReason?: Types.ProposalRejectionReason | null;
|
||||
errorDetails?: string | null;
|
||||
rationale: {
|
||||
__typename?: 'ProposalRationale';
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
party: { __typename?: 'Party'; id: string };
|
||||
terms: {
|
||||
__typename?: 'ProposalTerms';
|
||||
closingDatetime: any;
|
||||
enactmentDatetime?: any | null;
|
||||
change:
|
||||
| {
|
||||
__typename: 'NewAsset';
|
||||
name: string;
|
||||
symbol: string;
|
||||
decimals: number;
|
||||
quantum: string;
|
||||
source:
|
||||
| { __typename?: 'BuiltinAsset'; maxFaucetAmountMint: string }
|
||||
| {
|
||||
__typename?: 'ERC20';
|
||||
contractAddress: string;
|
||||
withdrawThreshold: string;
|
||||
lifetimeLimit: string;
|
||||
};
|
||||
}
|
||||
| { __typename?: 'NewFreeform' }
|
||||
| {
|
||||
__typename?: 'NewMarket';
|
||||
instrument: {
|
||||
__typename?: 'InstrumentConfiguration';
|
||||
name: string;
|
||||
code: string;
|
||||
futureProduct?: {
|
||||
__typename?: 'FutureProduct';
|
||||
settlementAsset: { __typename?: 'Asset'; symbol: string };
|
||||
} | null;
|
||||
};
|
||||
}
|
||||
| {
|
||||
__typename?: 'UpdateAsset';
|
||||
quantum: string;
|
||||
assetId: string;
|
||||
source: {
|
||||
__typename?: 'UpdateERC20';
|
||||
lifetimeLimit: string;
|
||||
withdrawThreshold: string;
|
||||
};
|
||||
}
|
||||
| { __typename?: 'UpdateMarket'; marketId: string }
|
||||
| {
|
||||
__typename?: 'UpdateNetworkParameter';
|
||||
networkParameter: {
|
||||
__typename?: 'NetworkParameter';
|
||||
key: string;
|
||||
value: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
votes: {
|
||||
__typename?: 'ProposalVotes';
|
||||
yes: {
|
||||
__typename?: 'ProposalVoteSide';
|
||||
totalTokens: string;
|
||||
totalNumber: string;
|
||||
totalEquityLikeShareWeight: string;
|
||||
};
|
||||
no: {
|
||||
__typename?: 'ProposalVoteSide';
|
||||
totalTokens: string;
|
||||
totalNumber: string;
|
||||
totalEquityLikeShareWeight: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
export type ProposalsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
export type ProposalsQueryVariables = Types.Exact<{ [key: string]: never }>;
|
||||
|
||||
|
||||
export type ProposalsQuery = { __typename?: 'Query', proposalsConnection?: { __typename?: 'ProposalsConnection', edges?: Array<{ __typename?: 'ProposalEdge', node: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: any, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, rationale: { __typename?: 'ProposalRationale', title: string, description: string }, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: any, enactmentDatetime?: any | null, change: { __typename: 'NewAsset', name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename?: 'ERC20', contractAddress: string, withdrawThreshold: string, lifetimeLimit: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'UpdateAsset', quantum: string, assetId: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, totalEquityLikeShareWeight: string } } } } | null> | null } | null };
|
||||
export type ProposalsQuery = {
|
||||
__typename?: 'Query';
|
||||
proposalsConnection?: {
|
||||
__typename?: 'ProposalsConnection';
|
||||
edges?: Array<{
|
||||
__typename?: 'ProposalEdge';
|
||||
node: {
|
||||
__typename?: 'Proposal';
|
||||
id?: string | null;
|
||||
reference: string;
|
||||
state: Types.ProposalState;
|
||||
datetime: any;
|
||||
rejectionReason?: Types.ProposalRejectionReason | null;
|
||||
errorDetails?: string | null;
|
||||
rationale: {
|
||||
__typename?: 'ProposalRationale';
|
||||
title: string;
|
||||
description: string;
|
||||
};
|
||||
party: { __typename?: 'Party'; id: string };
|
||||
terms: {
|
||||
__typename?: 'ProposalTerms';
|
||||
closingDatetime: any;
|
||||
enactmentDatetime?: any | null;
|
||||
change:
|
||||
| {
|
||||
__typename: 'NewAsset';
|
||||
name: string;
|
||||
symbol: string;
|
||||
decimals: number;
|
||||
quantum: string;
|
||||
source:
|
||||
| { __typename?: 'BuiltinAsset'; maxFaucetAmountMint: string }
|
||||
| {
|
||||
__typename?: 'ERC20';
|
||||
contractAddress: string;
|
||||
withdrawThreshold: string;
|
||||
lifetimeLimit: string;
|
||||
};
|
||||
}
|
||||
| { __typename?: 'NewFreeform' }
|
||||
| {
|
||||
__typename?: 'NewMarket';
|
||||
instrument: {
|
||||
__typename?: 'InstrumentConfiguration';
|
||||
name: string;
|
||||
code: string;
|
||||
futureProduct?: {
|
||||
__typename?: 'FutureProduct';
|
||||
settlementAsset: { __typename?: 'Asset'; symbol: string };
|
||||
} | null;
|
||||
};
|
||||
}
|
||||
| {
|
||||
__typename?: 'UpdateAsset';
|
||||
quantum: string;
|
||||
assetId: string;
|
||||
source: {
|
||||
__typename?: 'UpdateERC20';
|
||||
lifetimeLimit: string;
|
||||
withdrawThreshold: string;
|
||||
};
|
||||
}
|
||||
| { __typename?: 'UpdateMarket'; marketId: string }
|
||||
| {
|
||||
__typename?: 'UpdateNetworkParameter';
|
||||
networkParameter: {
|
||||
__typename?: 'NetworkParameter';
|
||||
key: string;
|
||||
value: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
votes: {
|
||||
__typename?: 'ProposalVotes';
|
||||
yes: {
|
||||
__typename?: 'ProposalVoteSide';
|
||||
totalTokens: string;
|
||||
totalNumber: string;
|
||||
totalEquityLikeShareWeight: string;
|
||||
};
|
||||
no: {
|
||||
__typename?: 'ProposalVoteSide';
|
||||
totalTokens: string;
|
||||
totalNumber: string;
|
||||
totalEquityLikeShareWeight: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
} | null> | null;
|
||||
} | null;
|
||||
};
|
||||
|
||||
export const ProposalFieldsFragmentDoc = gql`
|
||||
fragment ProposalFields on Proposal {
|
||||
id
|
||||
rationale {
|
||||
title
|
||||
description
|
||||
}
|
||||
reference
|
||||
state
|
||||
datetime
|
||||
rejectionReason
|
||||
party {
|
||||
fragment ProposalFields on Proposal {
|
||||
id
|
||||
}
|
||||
errorDetails
|
||||
terms {
|
||||
closingDatetime
|
||||
enactmentDatetime
|
||||
change {
|
||||
... on NewMarket {
|
||||
instrument {
|
||||
rationale {
|
||||
title
|
||||
description
|
||||
}
|
||||
reference
|
||||
state
|
||||
datetime
|
||||
rejectionReason
|
||||
party {
|
||||
id
|
||||
}
|
||||
errorDetails
|
||||
terms {
|
||||
closingDatetime
|
||||
enactmentDatetime
|
||||
change {
|
||||
... on NewMarket {
|
||||
instrument {
|
||||
name
|
||||
code
|
||||
futureProduct {
|
||||
settlementAsset {
|
||||
symbol
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on UpdateMarket {
|
||||
marketId
|
||||
}
|
||||
... on NewAsset {
|
||||
__typename
|
||||
name
|
||||
code
|
||||
futureProduct {
|
||||
settlementAsset {
|
||||
symbol
|
||||
symbol
|
||||
decimals
|
||||
quantum
|
||||
source {
|
||||
... on BuiltinAsset {
|
||||
maxFaucetAmountMint
|
||||
}
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
withdrawThreshold
|
||||
lifetimeLimit
|
||||
}
|
||||
}
|
||||
}
|
||||
... on UpdateNetworkParameter {
|
||||
networkParameter {
|
||||
key
|
||||
value
|
||||
}
|
||||
}
|
||||
... on UpdateAsset {
|
||||
quantum
|
||||
assetId
|
||||
source {
|
||||
... on UpdateERC20 {
|
||||
lifetimeLimit
|
||||
withdrawThreshold
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
... on UpdateMarket {
|
||||
marketId
|
||||
}
|
||||
votes {
|
||||
yes {
|
||||
totalTokens
|
||||
totalNumber
|
||||
totalEquityLikeShareWeight
|
||||
}
|
||||
... on NewAsset {
|
||||
__typename
|
||||
name
|
||||
symbol
|
||||
decimals
|
||||
quantum
|
||||
source {
|
||||
... on BuiltinAsset {
|
||||
maxFaucetAmountMint
|
||||
}
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
withdrawThreshold
|
||||
lifetimeLimit
|
||||
}
|
||||
}
|
||||
}
|
||||
... on UpdateNetworkParameter {
|
||||
networkParameter {
|
||||
key
|
||||
value
|
||||
}
|
||||
}
|
||||
... on UpdateAsset {
|
||||
quantum
|
||||
assetId
|
||||
source {
|
||||
... on UpdateERC20 {
|
||||
lifetimeLimit
|
||||
withdrawThreshold
|
||||
}
|
||||
}
|
||||
no {
|
||||
totalTokens
|
||||
totalNumber
|
||||
totalEquityLikeShareWeight
|
||||
}
|
||||
}
|
||||
}
|
||||
votes {
|
||||
yes {
|
||||
totalTokens
|
||||
totalNumber
|
||||
totalEquityLikeShareWeight
|
||||
}
|
||||
no {
|
||||
totalTokens
|
||||
totalNumber
|
||||
totalEquityLikeShareWeight
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
`;
|
||||
export const ProposalsDocument = gql`
|
||||
query Proposals {
|
||||
proposalsConnection {
|
||||
edges {
|
||||
node {
|
||||
...ProposalFields
|
||||
query Proposals {
|
||||
proposalsConnection {
|
||||
edges {
|
||||
node {
|
||||
...ProposalFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${ProposalFieldsFragmentDoc}`;
|
||||
${ProposalFieldsFragmentDoc}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useProposalsQuery__
|
||||
@@ -119,14 +292,32 @@ export const ProposalsDocument = gql`
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useProposalsQuery(baseOptions?: Apollo.QueryHookOptions<ProposalsQuery, ProposalsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<ProposalsQuery, ProposalsQueryVariables>(ProposalsDocument, options);
|
||||
}
|
||||
export function useProposalsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ProposalsQuery, ProposalsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<ProposalsQuery, ProposalsQueryVariables>(ProposalsDocument, options);
|
||||
}
|
||||
export function useProposalsQuery(
|
||||
baseOptions?: Apollo.QueryHookOptions<ProposalsQuery, ProposalsQueryVariables>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useQuery<ProposalsQuery, ProposalsQueryVariables>(
|
||||
ProposalsDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export function useProposalsLazyQuery(
|
||||
baseOptions?: Apollo.LazyQueryHookOptions<
|
||||
ProposalsQuery,
|
||||
ProposalsQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useLazyQuery<ProposalsQuery, ProposalsQueryVariables>(
|
||||
ProposalsDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export type ProposalsQueryHookResult = ReturnType<typeof useProposalsQuery>;
|
||||
export type ProposalsLazyQueryHookResult = ReturnType<typeof useProposalsLazyQuery>;
|
||||
export type ProposalsQueryResult = Apollo.QueryResult<ProposalsQuery, ProposalsQueryVariables>;
|
||||
export type ProposalsLazyQueryHookResult = ReturnType<
|
||||
typeof useProposalsLazyQuery
|
||||
>;
|
||||
export type ProposalsQueryResult = Apollo.QueryResult<
|
||||
ProposalsQuery,
|
||||
ProposalsQueryVariables
|
||||
>;
|
||||
|
||||
+65
-26
@@ -3,29 +3,45 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type ProposalMarketsQueryQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type ProposalMarketsQueryQuery = { __typename?: 'Query', marketsConnection?: { __typename?: 'MarketConnection', edges: Array<{ __typename?: 'MarketEdge', node: { __typename?: 'Market', id: string, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', name: string, code: string } } } }> } | null };
|
||||
export type ProposalMarketsQueryQueryVariables = Types.Exact<{
|
||||
[key: string]: never;
|
||||
}>;
|
||||
|
||||
export type ProposalMarketsQueryQuery = {
|
||||
__typename?: 'Query';
|
||||
marketsConnection?: {
|
||||
__typename?: 'MarketConnection';
|
||||
edges: Array<{
|
||||
__typename?: 'MarketEdge';
|
||||
node: {
|
||||
__typename?: 'Market';
|
||||
id: string;
|
||||
tradableInstrument: {
|
||||
__typename?: 'TradableInstrument';
|
||||
instrument: { __typename?: 'Instrument'; name: string; code: string };
|
||||
};
|
||||
};
|
||||
}>;
|
||||
} | null;
|
||||
};
|
||||
|
||||
export const ProposalMarketsQueryDocument = gql`
|
||||
query ProposalMarketsQuery {
|
||||
marketsConnection {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
code
|
||||
query ProposalMarketsQuery {
|
||||
marketsConnection {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
tradableInstrument {
|
||||
instrument {
|
||||
name
|
||||
code
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useProposalMarketsQueryQuery__
|
||||
@@ -42,14 +58,37 @@ export const ProposalMarketsQueryDocument = gql`
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useProposalMarketsQueryQuery(baseOptions?: Apollo.QueryHookOptions<ProposalMarketsQueryQuery, ProposalMarketsQueryQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<ProposalMarketsQueryQuery, ProposalMarketsQueryQueryVariables>(ProposalMarketsQueryDocument, options);
|
||||
}
|
||||
export function useProposalMarketsQueryLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ProposalMarketsQueryQuery, ProposalMarketsQueryQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<ProposalMarketsQueryQuery, ProposalMarketsQueryQueryVariables>(ProposalMarketsQueryDocument, options);
|
||||
}
|
||||
export type ProposalMarketsQueryQueryHookResult = ReturnType<typeof useProposalMarketsQueryQuery>;
|
||||
export type ProposalMarketsQueryLazyQueryHookResult = ReturnType<typeof useProposalMarketsQueryLazyQuery>;
|
||||
export type ProposalMarketsQueryQueryResult = Apollo.QueryResult<ProposalMarketsQueryQuery, ProposalMarketsQueryQueryVariables>;
|
||||
export function useProposalMarketsQueryQuery(
|
||||
baseOptions?: Apollo.QueryHookOptions<
|
||||
ProposalMarketsQueryQuery,
|
||||
ProposalMarketsQueryQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useQuery<
|
||||
ProposalMarketsQueryQuery,
|
||||
ProposalMarketsQueryQueryVariables
|
||||
>(ProposalMarketsQueryDocument, options);
|
||||
}
|
||||
export function useProposalMarketsQueryLazyQuery(
|
||||
baseOptions?: Apollo.LazyQueryHookOptions<
|
||||
ProposalMarketsQueryQuery,
|
||||
ProposalMarketsQueryQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useLazyQuery<
|
||||
ProposalMarketsQueryQuery,
|
||||
ProposalMarketsQueryQueryVariables
|
||||
>(ProposalMarketsQueryDocument, options);
|
||||
}
|
||||
export type ProposalMarketsQueryQueryHookResult = ReturnType<
|
||||
typeof useProposalMarketsQueryQuery
|
||||
>;
|
||||
export type ProposalMarketsQueryLazyQueryHookResult = ReturnType<
|
||||
typeof useProposalMarketsQueryLazyQuery
|
||||
>;
|
||||
export type ProposalMarketsQueryQueryResult = Apollo.QueryResult<
|
||||
ProposalMarketsQueryQuery,
|
||||
ProposalMarketsQueryQueryVariables
|
||||
>;
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ export const EpochIndividualRewards = () => {
|
||||
data={data}
|
||||
render={() => (
|
||||
<div>
|
||||
<p data-testid="connected-vega-key" className="mb-10">
|
||||
<p className="mb-10">
|
||||
{t('Connected Vega key')}:{' '}
|
||||
<span className="text-white">{pubKey}</span>
|
||||
</p>
|
||||
|
||||
+73
-28
@@ -7,30 +7,52 @@ export type PreviousEpochQueryVariables = Types.Exact<{
|
||||
epochId?: Types.InputMaybe<Types.Scalars['ID']>;
|
||||
}>;
|
||||
|
||||
|
||||
export type PreviousEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, validatorsConnection?: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string } | null, rankingScore: { __typename?: 'RankingScore', performanceScore: string } } } | null> | null } | null } };
|
||||
|
||||
export type PreviousEpochQuery = {
|
||||
__typename?: 'Query';
|
||||
epoch: {
|
||||
__typename?: 'Epoch';
|
||||
id: string;
|
||||
validatorsConnection?: {
|
||||
__typename?: 'NodesConnection';
|
||||
edges?: Array<{
|
||||
__typename?: 'NodeEdge';
|
||||
node: {
|
||||
__typename?: 'Node';
|
||||
id: string;
|
||||
rewardScore?: {
|
||||
__typename?: 'RewardScore';
|
||||
rawValidatorScore: string;
|
||||
} | null;
|
||||
rankingScore: {
|
||||
__typename?: 'RankingScore';
|
||||
performanceScore: string;
|
||||
};
|
||||
};
|
||||
} | null> | null;
|
||||
} | null;
|
||||
};
|
||||
};
|
||||
|
||||
export const PreviousEpochDocument = gql`
|
||||
query PreviousEpoch($epochId: ID) {
|
||||
epoch(id: $epochId) {
|
||||
id
|
||||
validatorsConnection {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
rewardScore {
|
||||
rawValidatorScore
|
||||
}
|
||||
rankingScore {
|
||||
performanceScore
|
||||
query PreviousEpoch($epochId: ID) {
|
||||
epoch(id: $epochId) {
|
||||
id
|
||||
validatorsConnection {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
rewardScore {
|
||||
rawValidatorScore
|
||||
}
|
||||
rankingScore {
|
||||
performanceScore
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
`;
|
||||
|
||||
/**
|
||||
* __usePreviousEpochQuery__
|
||||
@@ -48,14 +70,37 @@ export const PreviousEpochDocument = gql`
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function usePreviousEpochQuery(baseOptions?: Apollo.QueryHookOptions<PreviousEpochQuery, PreviousEpochQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<PreviousEpochQuery, PreviousEpochQueryVariables>(PreviousEpochDocument, options);
|
||||
}
|
||||
export function usePreviousEpochLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PreviousEpochQuery, PreviousEpochQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<PreviousEpochQuery, PreviousEpochQueryVariables>(PreviousEpochDocument, options);
|
||||
}
|
||||
export type PreviousEpochQueryHookResult = ReturnType<typeof usePreviousEpochQuery>;
|
||||
export type PreviousEpochLazyQueryHookResult = ReturnType<typeof usePreviousEpochLazyQuery>;
|
||||
export type PreviousEpochQueryResult = Apollo.QueryResult<PreviousEpochQuery, PreviousEpochQueryVariables>;
|
||||
export function usePreviousEpochQuery(
|
||||
baseOptions?: Apollo.QueryHookOptions<
|
||||
PreviousEpochQuery,
|
||||
PreviousEpochQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useQuery<PreviousEpochQuery, PreviousEpochQueryVariables>(
|
||||
PreviousEpochDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export function usePreviousEpochLazyQuery(
|
||||
baseOptions?: Apollo.LazyQueryHookOptions<
|
||||
PreviousEpochQuery,
|
||||
PreviousEpochQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useLazyQuery<PreviousEpochQuery, PreviousEpochQueryVariables>(
|
||||
PreviousEpochDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export type PreviousEpochQueryHookResult = ReturnType<
|
||||
typeof usePreviousEpochQuery
|
||||
>;
|
||||
export type PreviousEpochLazyQueryHookResult = ReturnType<
|
||||
typeof usePreviousEpochLazyQuery
|
||||
>;
|
||||
export type PreviousEpochQueryResult = Apollo.QueryResult<
|
||||
PreviousEpochQuery,
|
||||
PreviousEpochQueryVariables
|
||||
>;
|
||||
|
||||
+79
-30
@@ -3,38 +3,64 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type LinkingsFieldsFragment = { __typename?: 'StakeLinking', id: string, txHash: string, status: Types.StakeLinkingStatus };
|
||||
export type LinkingsFieldsFragment = {
|
||||
__typename?: 'StakeLinking';
|
||||
id: string;
|
||||
txHash: string;
|
||||
status: Types.StakeLinkingStatus;
|
||||
};
|
||||
|
||||
export type PartyStakeLinkingsQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type PartyStakeLinkingsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, stakingSummary: { __typename?: 'StakingSummary', linkings: { __typename?: 'StakesConnection', edges?: Array<{ __typename?: 'StakeLinkingEdge', node: { __typename?: 'StakeLinking', id: string, txHash: string, status: Types.StakeLinkingStatus } } | null> | null } } } | null };
|
||||
export type PartyStakeLinkingsQuery = {
|
||||
__typename?: 'Query';
|
||||
party?: {
|
||||
__typename?: 'Party';
|
||||
id: string;
|
||||
stakingSummary: {
|
||||
__typename?: 'StakingSummary';
|
||||
linkings: {
|
||||
__typename?: 'StakesConnection';
|
||||
edges?: Array<{
|
||||
__typename?: 'StakeLinkingEdge';
|
||||
node: {
|
||||
__typename?: 'StakeLinking';
|
||||
id: string;
|
||||
txHash: string;
|
||||
status: Types.StakeLinkingStatus;
|
||||
};
|
||||
} | null> | null;
|
||||
};
|
||||
};
|
||||
} | null;
|
||||
};
|
||||
|
||||
export const LinkingsFieldsFragmentDoc = gql`
|
||||
fragment LinkingsFields on StakeLinking {
|
||||
id
|
||||
txHash
|
||||
status
|
||||
}
|
||||
`;
|
||||
export const PartyStakeLinkingsDocument = gql`
|
||||
query PartyStakeLinkings($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
fragment LinkingsFields on StakeLinking {
|
||||
id
|
||||
stakingSummary {
|
||||
linkings {
|
||||
edges {
|
||||
node {
|
||||
...LinkingsFields
|
||||
txHash
|
||||
status
|
||||
}
|
||||
`;
|
||||
export const PartyStakeLinkingsDocument = gql`
|
||||
query PartyStakeLinkings($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
stakingSummary {
|
||||
linkings {
|
||||
edges {
|
||||
node {
|
||||
...LinkingsFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${LinkingsFieldsFragmentDoc}`;
|
||||
${LinkingsFieldsFragmentDoc}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __usePartyStakeLinkingsQuery__
|
||||
@@ -52,14 +78,37 @@ export const PartyStakeLinkingsDocument = gql`
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function usePartyStakeLinkingsQuery(baseOptions: Apollo.QueryHookOptions<PartyStakeLinkingsQuery, PartyStakeLinkingsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<PartyStakeLinkingsQuery, PartyStakeLinkingsQueryVariables>(PartyStakeLinkingsDocument, options);
|
||||
}
|
||||
export function usePartyStakeLinkingsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PartyStakeLinkingsQuery, PartyStakeLinkingsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<PartyStakeLinkingsQuery, PartyStakeLinkingsQueryVariables>(PartyStakeLinkingsDocument, options);
|
||||
}
|
||||
export type PartyStakeLinkingsQueryHookResult = ReturnType<typeof usePartyStakeLinkingsQuery>;
|
||||
export type PartyStakeLinkingsLazyQueryHookResult = ReturnType<typeof usePartyStakeLinkingsLazyQuery>;
|
||||
export type PartyStakeLinkingsQueryResult = Apollo.QueryResult<PartyStakeLinkingsQuery, PartyStakeLinkingsQueryVariables>;
|
||||
export function usePartyStakeLinkingsQuery(
|
||||
baseOptions: Apollo.QueryHookOptions<
|
||||
PartyStakeLinkingsQuery,
|
||||
PartyStakeLinkingsQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useQuery<
|
||||
PartyStakeLinkingsQuery,
|
||||
PartyStakeLinkingsQueryVariables
|
||||
>(PartyStakeLinkingsDocument, options);
|
||||
}
|
||||
export function usePartyStakeLinkingsLazyQuery(
|
||||
baseOptions?: Apollo.LazyQueryHookOptions<
|
||||
PartyStakeLinkingsQuery,
|
||||
PartyStakeLinkingsQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useLazyQuery<
|
||||
PartyStakeLinkingsQuery,
|
||||
PartyStakeLinkingsQueryVariables
|
||||
>(PartyStakeLinkingsDocument, options);
|
||||
}
|
||||
export type PartyStakeLinkingsQueryHookResult = ReturnType<
|
||||
typeof usePartyStakeLinkingsQuery
|
||||
>;
|
||||
export type PartyStakeLinkingsLazyQueryHookResult = ReturnType<
|
||||
typeof usePartyStakeLinkingsLazyQuery
|
||||
>;
|
||||
export type PartyStakeLinkingsQueryResult = Apollo.QueryResult<
|
||||
PartyStakeLinkingsQuery,
|
||||
PartyStakeLinkingsQueryVariables
|
||||
>;
|
||||
|
||||
+116
-47
@@ -3,54 +3,110 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type NodesFragmentFragment = { __typename?: 'Node', avatarUrl?: string | null, id: string, name: string, pubkey: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } };
|
||||
export type NodesFragmentFragment = {
|
||||
__typename?: 'Node';
|
||||
avatarUrl?: string | null;
|
||||
id: string;
|
||||
name: string;
|
||||
pubkey: string;
|
||||
stakedByOperator: string;
|
||||
stakedByDelegates: string;
|
||||
stakedTotal: string;
|
||||
pendingStake: string;
|
||||
rankingScore: {
|
||||
__typename?: 'RankingScore';
|
||||
rankingScore: string;
|
||||
stakeScore: string;
|
||||
performanceScore: string;
|
||||
votingPower: string;
|
||||
status: Types.ValidatorStatus;
|
||||
};
|
||||
};
|
||||
|
||||
export type NodesQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
export type NodesQueryVariables = Types.Exact<{ [key: string]: never }>;
|
||||
|
||||
|
||||
export type NodesQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, expiry?: any | null } }, nodesConnection: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', avatarUrl?: string | null, id: string, name: string, pubkey: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } } } | null> | null }, nodeData?: { __typename?: 'NodeData', stakedTotal: string } | null };
|
||||
export type NodesQuery = {
|
||||
__typename?: 'Query';
|
||||
epoch: {
|
||||
__typename?: 'Epoch';
|
||||
id: string;
|
||||
timestamps: {
|
||||
__typename?: 'EpochTimestamps';
|
||||
start?: any | null;
|
||||
end?: any | null;
|
||||
expiry?: any | null;
|
||||
};
|
||||
};
|
||||
nodesConnection: {
|
||||
__typename?: 'NodesConnection';
|
||||
edges?: Array<{
|
||||
__typename?: 'NodeEdge';
|
||||
node: {
|
||||
__typename?: 'Node';
|
||||
avatarUrl?: string | null;
|
||||
id: string;
|
||||
name: string;
|
||||
pubkey: string;
|
||||
stakedByOperator: string;
|
||||
stakedByDelegates: string;
|
||||
stakedTotal: string;
|
||||
pendingStake: string;
|
||||
rankingScore: {
|
||||
__typename?: 'RankingScore';
|
||||
rankingScore: string;
|
||||
stakeScore: string;
|
||||
performanceScore: string;
|
||||
votingPower: string;
|
||||
status: Types.ValidatorStatus;
|
||||
};
|
||||
};
|
||||
} | null> | null;
|
||||
};
|
||||
nodeData?: { __typename?: 'NodeData'; stakedTotal: string } | null;
|
||||
};
|
||||
|
||||
export const NodesFragmentFragmentDoc = gql`
|
||||
fragment NodesFragment on Node {
|
||||
avatarUrl
|
||||
id
|
||||
name
|
||||
pubkey
|
||||
stakedByOperator
|
||||
stakedByDelegates
|
||||
stakedTotal
|
||||
pendingStake
|
||||
rankingScore {
|
||||
rankingScore
|
||||
stakeScore
|
||||
performanceScore
|
||||
votingPower
|
||||
status
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const NodesDocument = gql`
|
||||
query Nodes {
|
||||
epoch {
|
||||
fragment NodesFragment on Node {
|
||||
avatarUrl
|
||||
id
|
||||
timestamps {
|
||||
start
|
||||
end
|
||||
expiry
|
||||
name
|
||||
pubkey
|
||||
stakedByOperator
|
||||
stakedByDelegates
|
||||
stakedTotal
|
||||
pendingStake
|
||||
rankingScore {
|
||||
rankingScore
|
||||
stakeScore
|
||||
performanceScore
|
||||
votingPower
|
||||
status
|
||||
}
|
||||
}
|
||||
nodesConnection {
|
||||
edges {
|
||||
node {
|
||||
...NodesFragment
|
||||
`;
|
||||
export const NodesDocument = gql`
|
||||
query Nodes {
|
||||
epoch {
|
||||
id
|
||||
timestamps {
|
||||
start
|
||||
end
|
||||
expiry
|
||||
}
|
||||
}
|
||||
nodesConnection {
|
||||
edges {
|
||||
node {
|
||||
...NodesFragment
|
||||
}
|
||||
}
|
||||
}
|
||||
nodeData {
|
||||
stakedTotal
|
||||
}
|
||||
}
|
||||
nodeData {
|
||||
stakedTotal
|
||||
}
|
||||
}
|
||||
${NodesFragmentFragmentDoc}`;
|
||||
${NodesFragmentFragmentDoc}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useNodesQuery__
|
||||
@@ -67,14 +123,27 @@ export const NodesDocument = gql`
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useNodesQuery(baseOptions?: Apollo.QueryHookOptions<NodesQuery, NodesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<NodesQuery, NodesQueryVariables>(NodesDocument, options);
|
||||
}
|
||||
export function useNodesLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<NodesQuery, NodesQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<NodesQuery, NodesQueryVariables>(NodesDocument, options);
|
||||
}
|
||||
export function useNodesQuery(
|
||||
baseOptions?: Apollo.QueryHookOptions<NodesQuery, NodesQueryVariables>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useQuery<NodesQuery, NodesQueryVariables>(
|
||||
NodesDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export function useNodesLazyQuery(
|
||||
baseOptions?: Apollo.LazyQueryHookOptions<NodesQuery, NodesQueryVariables>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useLazyQuery<NodesQuery, NodesQueryVariables>(
|
||||
NodesDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export type NodesQueryHookResult = ReturnType<typeof useNodesQuery>;
|
||||
export type NodesLazyQueryHookResult = ReturnType<typeof useNodesLazyQuery>;
|
||||
export type NodesQueryResult = Apollo.QueryResult<NodesQuery, NodesQueryVariables>;
|
||||
export type NodesQueryResult = Apollo.QueryResult<
|
||||
NodesQuery,
|
||||
NodesQueryVariables
|
||||
>;
|
||||
|
||||
+20
-18
@@ -2,7 +2,7 @@ import type { Dispatch, SetStateAction } from 'react';
|
||||
import { forwardRef, useMemo, useRef, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { Button, Icon } from '@vegaprotocol/ui-toolkit';
|
||||
import { Button } from '@vegaprotocol/ui-toolkit';
|
||||
import { AgGridDynamic as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { useAppState } from '../../../../contexts/app-state/app-state-context';
|
||||
import { BigNumber } from '../../../../lib/bignumber';
|
||||
@@ -87,12 +87,7 @@ const TopThirdCellRenderer = (
|
||||
<div className="mb-4">
|
||||
<Button
|
||||
data-testid="show-all-validators"
|
||||
rightIcon={
|
||||
<Icon
|
||||
name="arrow-right"
|
||||
className="fill-current mr-2 align-text-top"
|
||||
/>
|
||||
}
|
||||
rightIcon="arrow-right"
|
||||
className="inline-flex items-center"
|
||||
>
|
||||
{t('Reveal top validators')}
|
||||
@@ -171,7 +166,10 @@ export const ConsensusValidatorsTable = ({
|
||||
avatarUrl,
|
||||
name,
|
||||
},
|
||||
[ValidatorFields.STAKE]: stakedTotal,
|
||||
[ValidatorFields.STAKE]: formatNumber(
|
||||
toBigNum(stakedTotal, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.NORMALISED_VOTING_POWER]:
|
||||
getNormalisedVotingPower(votingPower),
|
||||
[ValidatorFields.UNNORMALISED_VOTING_POWER]:
|
||||
@@ -200,8 +198,10 @@ export const ConsensusValidatorsTable = ({
|
||||
stakedTotal,
|
||||
totalStake
|
||||
),
|
||||
[ValidatorFields.PENDING_STAKE]: pendingStake,
|
||||
decimals,
|
||||
[ValidatorFields.PENDING_STAKE]: formatNumber(
|
||||
toBigNum(pendingStake, decimals),
|
||||
2
|
||||
),
|
||||
};
|
||||
}
|
||||
);
|
||||
@@ -256,18 +256,22 @@ export const ConsensusValidatorsTable = ({
|
||||
|
||||
return {
|
||||
...acc,
|
||||
[ValidatorFields.STAKE]: toBigNum(accStake, decimals)
|
||||
.plus(toBigNum(stake, decimals))
|
||||
.toString(),
|
||||
[ValidatorFields.STAKE]: formatNumber(
|
||||
toBigNum(accStake, decimals).plus(toBigNum(stake, decimals)),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.STAKE_SHARE]: formatNumberPercentage(
|
||||
new BigNumber(parseFloat(accStakeShare)).plus(
|
||||
new BigNumber(parseFloat(stakeShare))
|
||||
),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PENDING_STAKE]: toBigNum(accPendingStake, decimals)
|
||||
.plus(toBigNum(pendingStake, decimals))
|
||||
.toString(),
|
||||
[ValidatorFields.PENDING_STAKE]: formatNumber(
|
||||
toBigNum(accPendingStake, decimals).plus(
|
||||
toBigNum(pendingStake, decimals)
|
||||
),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.NORMALISED_VOTING_POWER]: formatNumberPercentage(
|
||||
new BigNumber(parseFloat(accNormalisedVotingPower)).plus(
|
||||
new BigNumber(parseFloat(normalisedVotingPower))
|
||||
@@ -345,8 +349,6 @@ 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,7 +12,6 @@ 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',
|
||||
@@ -149,11 +148,6 @@ interface TotalStakeRendererProps {
|
||||
|
||||
export const TotalStakeRenderer = ({ data }: TotalStakeRendererProps) => {
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
appState: { decimals },
|
||||
} = useAppState();
|
||||
|
||||
const formattedStake = formatNumber(toBigNum(data.stake, decimals), 2);
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
@@ -166,13 +160,12 @@ export const TotalStakeRenderer = ({ data }: TotalStakeRendererProps) => {
|
||||
{t('stakedByDelegates')}: {data.stakedByDelegates.toString()}
|
||||
</div>
|
||||
<div data-testid="total-staked-tooltip">
|
||||
{t('totalStake')}:{' '}
|
||||
<span className="font-bold">{formattedStake}</span>
|
||||
{t('totalStake')}: <span className="font-bold">{data.stake}</span>
|
||||
</div>
|
||||
</>
|
||||
}
|
||||
>
|
||||
<span>{formattedStake}</span>
|
||||
<span>{data.stake}</span>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
+8
-4
@@ -122,7 +122,10 @@ export const StandbyPendingValidatorsTable = ({
|
||||
avatarUrl,
|
||||
name,
|
||||
},
|
||||
[ValidatorFields.STAKE]: stakedTotal,
|
||||
[ValidatorFields.STAKE]: formatNumber(
|
||||
toBigNum(stakedTotal, decimals),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.STAKE_NEEDED_FOR_PROMOTION]:
|
||||
individualStakeNeededForPromotion || null,
|
||||
[ValidatorFields.STAKE_NEEDED_FOR_PROMOTION_DESCRIPTION]:
|
||||
@@ -151,7 +154,10 @@ export const StandbyPendingValidatorsTable = ({
|
||||
stakedTotal,
|
||||
totalStake
|
||||
),
|
||||
[ValidatorFields.PENDING_STAKE]: pendingStake,
|
||||
[ValidatorFields.PENDING_STAKE]: formatNumber(
|
||||
toBigNum(pendingStake, decimals),
|
||||
2
|
||||
),
|
||||
};
|
||||
}
|
||||
);
|
||||
@@ -216,8 +222,6 @@ 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,
|
||||
},
|
||||
],
|
||||
|
||||
+80
-33
@@ -3,42 +3,66 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type StakingDelegationsFieldsFragment = { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } };
|
||||
export type StakingDelegationsFieldsFragment = {
|
||||
__typename?: 'Delegation';
|
||||
amount: string;
|
||||
epoch: number;
|
||||
node: { __typename?: 'Node'; id: string };
|
||||
};
|
||||
|
||||
export type PartyDelegationsQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
|
||||
}>;
|
||||
|
||||
|
||||
export type PartyDelegationsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string } };
|
||||
export type PartyDelegationsQuery = {
|
||||
__typename?: 'Query';
|
||||
party?: {
|
||||
__typename?: 'Party';
|
||||
id: string;
|
||||
delegationsConnection?: {
|
||||
__typename?: 'DelegationsConnection';
|
||||
edges?: Array<{
|
||||
__typename?: 'DelegationEdge';
|
||||
node: {
|
||||
__typename?: 'Delegation';
|
||||
amount: string;
|
||||
epoch: number;
|
||||
node: { __typename?: 'Node'; id: string };
|
||||
};
|
||||
} | null> | null;
|
||||
} | null;
|
||||
} | null;
|
||||
epoch: { __typename?: 'Epoch'; id: string };
|
||||
};
|
||||
|
||||
export const StakingDelegationsFieldsFragmentDoc = gql`
|
||||
fragment StakingDelegationsFields on Delegation {
|
||||
amount
|
||||
node {
|
||||
id
|
||||
fragment StakingDelegationsFields on Delegation {
|
||||
amount
|
||||
node {
|
||||
id
|
||||
}
|
||||
epoch
|
||||
}
|
||||
epoch
|
||||
}
|
||||
`;
|
||||
`;
|
||||
export const PartyDelegationsDocument = gql`
|
||||
query PartyDelegations($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
edges {
|
||||
node {
|
||||
...StakingDelegationsFields
|
||||
query PartyDelegations($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
edges {
|
||||
node {
|
||||
...StakingDelegationsFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
epoch {
|
||||
id
|
||||
}
|
||||
}
|
||||
epoch {
|
||||
id
|
||||
}
|
||||
}
|
||||
${StakingDelegationsFieldsFragmentDoc}`;
|
||||
${StakingDelegationsFieldsFragmentDoc}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __usePartyDelegationsQuery__
|
||||
@@ -57,14 +81,37 @@ export const PartyDelegationsDocument = gql`
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function usePartyDelegationsQuery(baseOptions: Apollo.QueryHookOptions<PartyDelegationsQuery, PartyDelegationsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<PartyDelegationsQuery, PartyDelegationsQueryVariables>(PartyDelegationsDocument, options);
|
||||
}
|
||||
export function usePartyDelegationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<PartyDelegationsQuery, PartyDelegationsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<PartyDelegationsQuery, PartyDelegationsQueryVariables>(PartyDelegationsDocument, options);
|
||||
}
|
||||
export type PartyDelegationsQueryHookResult = ReturnType<typeof usePartyDelegationsQuery>;
|
||||
export type PartyDelegationsLazyQueryHookResult = ReturnType<typeof usePartyDelegationsLazyQuery>;
|
||||
export type PartyDelegationsQueryResult = Apollo.QueryResult<PartyDelegationsQuery, PartyDelegationsQueryVariables>;
|
||||
export function usePartyDelegationsQuery(
|
||||
baseOptions: Apollo.QueryHookOptions<
|
||||
PartyDelegationsQuery,
|
||||
PartyDelegationsQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useQuery<PartyDelegationsQuery, PartyDelegationsQueryVariables>(
|
||||
PartyDelegationsDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export function usePartyDelegationsLazyQuery(
|
||||
baseOptions?: Apollo.LazyQueryHookOptions<
|
||||
PartyDelegationsQuery,
|
||||
PartyDelegationsQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useLazyQuery<
|
||||
PartyDelegationsQuery,
|
||||
PartyDelegationsQueryVariables
|
||||
>(PartyDelegationsDocument, options);
|
||||
}
|
||||
export type PartyDelegationsQueryHookResult = ReturnType<
|
||||
typeof usePartyDelegationsQuery
|
||||
>;
|
||||
export type PartyDelegationsLazyQueryHookResult = ReturnType<
|
||||
typeof usePartyDelegationsLazyQuery
|
||||
>;
|
||||
export type PartyDelegationsQueryResult = Apollo.QueryResult<
|
||||
PartyDelegationsQuery,
|
||||
PartyDelegationsQueryVariables
|
||||
>;
|
||||
|
||||
+180
-69
@@ -3,84 +3,182 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type StakingNodeFieldsFragment = { __typename?: 'Node', id: string, name: string, pubkey: string, infoUrl: string, location: string, ethereumAddress: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, epochData?: { __typename?: 'EpochData', total: number, offline: number, online: number } | null, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } };
|
||||
export type StakingNodeFieldsFragment = {
|
||||
__typename?: 'Node';
|
||||
id: string;
|
||||
name: string;
|
||||
pubkey: string;
|
||||
infoUrl: string;
|
||||
location: string;
|
||||
ethereumAddress: string;
|
||||
stakedByOperator: string;
|
||||
stakedByDelegates: string;
|
||||
stakedTotal: string;
|
||||
pendingStake: string;
|
||||
epochData?: {
|
||||
__typename?: 'EpochData';
|
||||
total: number;
|
||||
offline: number;
|
||||
online: number;
|
||||
} | null;
|
||||
rankingScore: {
|
||||
__typename?: 'RankingScore';
|
||||
rankingScore: string;
|
||||
stakeScore: string;
|
||||
performanceScore: string;
|
||||
votingPower: string;
|
||||
status: Types.ValidatorStatus;
|
||||
};
|
||||
};
|
||||
|
||||
export type StakingQueryVariables = Types.Exact<{
|
||||
partyId: Types.Scalars['ID'];
|
||||
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
|
||||
}>;
|
||||
|
||||
|
||||
export type StakingQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, stakingSummary: { __typename?: 'StakingSummary', currentStakeAvailable: string }, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number, node: { __typename?: 'Node', id: string } } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, expiry?: any | null } }, nodesConnection: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, name: string, pubkey: string, infoUrl: string, location: string, ethereumAddress: string, stakedByOperator: string, stakedByDelegates: string, stakedTotal: string, pendingStake: string, epochData?: { __typename?: 'EpochData', total: number, offline: number, online: number } | null, rankingScore: { __typename?: 'RankingScore', rankingScore: string, stakeScore: string, performanceScore: string, votingPower: string, status: Types.ValidatorStatus } } } | null> | null }, nodeData?: { __typename?: 'NodeData', stakedTotal: string, totalNodes: number, inactiveNodes: number, uptime: number } | null };
|
||||
export type StakingQuery = {
|
||||
__typename?: 'Query';
|
||||
party?: {
|
||||
__typename?: 'Party';
|
||||
id: string;
|
||||
stakingSummary: {
|
||||
__typename?: 'StakingSummary';
|
||||
currentStakeAvailable: string;
|
||||
};
|
||||
delegationsConnection?: {
|
||||
__typename?: 'DelegationsConnection';
|
||||
edges?: Array<{
|
||||
__typename?: 'DelegationEdge';
|
||||
node: {
|
||||
__typename?: 'Delegation';
|
||||
amount: string;
|
||||
epoch: number;
|
||||
node: { __typename?: 'Node'; id: string };
|
||||
};
|
||||
} | null> | null;
|
||||
} | null;
|
||||
} | null;
|
||||
epoch: {
|
||||
__typename?: 'Epoch';
|
||||
id: string;
|
||||
timestamps: {
|
||||
__typename?: 'EpochTimestamps';
|
||||
start?: any | null;
|
||||
end?: any | null;
|
||||
expiry?: any | null;
|
||||
};
|
||||
};
|
||||
nodesConnection: {
|
||||
__typename?: 'NodesConnection';
|
||||
edges?: Array<{
|
||||
__typename?: 'NodeEdge';
|
||||
node: {
|
||||
__typename?: 'Node';
|
||||
id: string;
|
||||
name: string;
|
||||
pubkey: string;
|
||||
infoUrl: string;
|
||||
location: string;
|
||||
ethereumAddress: string;
|
||||
stakedByOperator: string;
|
||||
stakedByDelegates: string;
|
||||
stakedTotal: string;
|
||||
pendingStake: string;
|
||||
epochData?: {
|
||||
__typename?: 'EpochData';
|
||||
total: number;
|
||||
offline: number;
|
||||
online: number;
|
||||
} | null;
|
||||
rankingScore: {
|
||||
__typename?: 'RankingScore';
|
||||
rankingScore: string;
|
||||
stakeScore: string;
|
||||
performanceScore: string;
|
||||
votingPower: string;
|
||||
status: Types.ValidatorStatus;
|
||||
};
|
||||
};
|
||||
} | null> | null;
|
||||
};
|
||||
nodeData?: {
|
||||
__typename?: 'NodeData';
|
||||
stakedTotal: string;
|
||||
totalNodes: number;
|
||||
inactiveNodes: number;
|
||||
uptime: number;
|
||||
} | null;
|
||||
};
|
||||
|
||||
export const StakingNodeFieldsFragmentDoc = gql`
|
||||
fragment StakingNodeFields on Node {
|
||||
id
|
||||
name
|
||||
pubkey
|
||||
infoUrl
|
||||
location
|
||||
ethereumAddress
|
||||
stakedByOperator
|
||||
stakedByDelegates
|
||||
stakedTotal
|
||||
pendingStake
|
||||
epochData {
|
||||
total
|
||||
offline
|
||||
online
|
||||
}
|
||||
rankingScore {
|
||||
rankingScore
|
||||
stakeScore
|
||||
performanceScore
|
||||
votingPower
|
||||
status
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const StakingDocument = gql`
|
||||
query Staking($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
party(id: $partyId) {
|
||||
fragment StakingNodeFields on Node {
|
||||
id
|
||||
stakingSummary {
|
||||
currentStakeAvailable
|
||||
name
|
||||
pubkey
|
||||
infoUrl
|
||||
location
|
||||
ethereumAddress
|
||||
stakedByOperator
|
||||
stakedByDelegates
|
||||
stakedTotal
|
||||
pendingStake
|
||||
epochData {
|
||||
total
|
||||
offline
|
||||
online
|
||||
}
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
edges {
|
||||
node {
|
||||
amount
|
||||
epoch
|
||||
rankingScore {
|
||||
rankingScore
|
||||
stakeScore
|
||||
performanceScore
|
||||
votingPower
|
||||
status
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const StakingDocument = gql`
|
||||
query Staking($partyId: ID!, $delegationsPagination: Pagination) {
|
||||
party(id: $partyId) {
|
||||
id
|
||||
stakingSummary {
|
||||
currentStakeAvailable
|
||||
}
|
||||
delegationsConnection(pagination: $delegationsPagination) {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
amount
|
||||
epoch
|
||||
node {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
epoch {
|
||||
id
|
||||
timestamps {
|
||||
start
|
||||
end
|
||||
expiry
|
||||
}
|
||||
}
|
||||
nodesConnection {
|
||||
edges {
|
||||
node {
|
||||
...StakingNodeFields
|
||||
epoch {
|
||||
id
|
||||
timestamps {
|
||||
start
|
||||
end
|
||||
expiry
|
||||
}
|
||||
}
|
||||
nodesConnection {
|
||||
edges {
|
||||
node {
|
||||
...StakingNodeFields
|
||||
}
|
||||
}
|
||||
}
|
||||
nodeData {
|
||||
stakedTotal
|
||||
totalNodes
|
||||
inactiveNodes
|
||||
uptime
|
||||
}
|
||||
}
|
||||
nodeData {
|
||||
stakedTotal
|
||||
totalNodes
|
||||
inactiveNodes
|
||||
uptime
|
||||
}
|
||||
}
|
||||
${StakingNodeFieldsFragmentDoc}`;
|
||||
${StakingNodeFieldsFragmentDoc}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useStakingQuery__
|
||||
@@ -99,14 +197,27 @@ export const StakingDocument = gql`
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useStakingQuery(baseOptions: Apollo.QueryHookOptions<StakingQuery, StakingQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<StakingQuery, StakingQueryVariables>(StakingDocument, options);
|
||||
}
|
||||
export function useStakingLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<StakingQuery, StakingQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<StakingQuery, StakingQueryVariables>(StakingDocument, options);
|
||||
}
|
||||
export function useStakingQuery(
|
||||
baseOptions: Apollo.QueryHookOptions<StakingQuery, StakingQueryVariables>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useQuery<StakingQuery, StakingQueryVariables>(
|
||||
StakingDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export function useStakingLazyQuery(
|
||||
baseOptions?: Apollo.LazyQueryHookOptions<StakingQuery, StakingQueryVariables>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useLazyQuery<StakingQuery, StakingQueryVariables>(
|
||||
StakingDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export type StakingQueryHookResult = ReturnType<typeof useStakingQuery>;
|
||||
export type StakingLazyQueryHookResult = ReturnType<typeof useStakingLazyQuery>;
|
||||
export type StakingQueryResult = Apollo.QueryResult<StakingQuery, StakingQueryVariables>;
|
||||
export type StakingQueryResult = Apollo.QueryResult<
|
||||
StakingQuery,
|
||||
StakingQueryVariables
|
||||
>;
|
||||
|
||||
+38
-19
@@ -3,19 +3,20 @@ import * as Types from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type NodeDataQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type NodeDataQuery = { __typename?: 'Query', nodeData?: { __typename?: 'NodeData', stakedTotal: string } | null };
|
||||
export type NodeDataQueryVariables = Types.Exact<{ [key: string]: never }>;
|
||||
|
||||
export type NodeDataQuery = {
|
||||
__typename?: 'Query';
|
||||
nodeData?: { __typename?: 'NodeData'; stakedTotal: string } | null;
|
||||
};
|
||||
|
||||
export const NodeDataDocument = gql`
|
||||
query NodeData {
|
||||
nodeData {
|
||||
stakedTotal
|
||||
query NodeData {
|
||||
nodeData {
|
||||
stakedTotal
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useNodeDataQuery__
|
||||
@@ -32,14 +33,32 @@ export const NodeDataDocument = gql`
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useNodeDataQuery(baseOptions?: Apollo.QueryHookOptions<NodeDataQuery, NodeDataQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<NodeDataQuery, NodeDataQueryVariables>(NodeDataDocument, options);
|
||||
}
|
||||
export function useNodeDataLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<NodeDataQuery, NodeDataQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<NodeDataQuery, NodeDataQueryVariables>(NodeDataDocument, options);
|
||||
}
|
||||
export function useNodeDataQuery(
|
||||
baseOptions?: Apollo.QueryHookOptions<NodeDataQuery, NodeDataQueryVariables>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useQuery<NodeDataQuery, NodeDataQueryVariables>(
|
||||
NodeDataDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export function useNodeDataLazyQuery(
|
||||
baseOptions?: Apollo.LazyQueryHookOptions<
|
||||
NodeDataQuery,
|
||||
NodeDataQueryVariables
|
||||
>
|
||||
) {
|
||||
const options = { ...defaultOptions, ...baseOptions };
|
||||
return Apollo.useLazyQuery<NodeDataQuery, NodeDataQueryVariables>(
|
||||
NodeDataDocument,
|
||||
options
|
||||
);
|
||||
}
|
||||
export type NodeDataQueryHookResult = ReturnType<typeof useNodeDataQuery>;
|
||||
export type NodeDataLazyQueryHookResult = ReturnType<typeof useNodeDataLazyQuery>;
|
||||
export type NodeDataQueryResult = Apollo.QueryResult<NodeDataQuery, NodeDataQueryVariables>;
|
||||
export type NodeDataLazyQueryHookResult = ReturnType<
|
||||
typeof useNodeDataLazyQuery
|
||||
>;
|
||||
export type NodeDataQueryResult = Apollo.QueryResult<
|
||||
NodeDataQuery,
|
||||
NodeDataQueryVariables
|
||||
>;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {
|
||||
KeyValueTable,
|
||||
KeyValueTableRow,
|
||||
Link,
|
||||
RoundedWrapper,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
@@ -10,7 +11,7 @@ import { useParams } from 'react-router';
|
||||
import { Navigate } from 'react-router-dom';
|
||||
import { formatNumber } from '@vegaprotocol/utils';
|
||||
|
||||
import { EtherscanLink } from '@vegaprotocol/environment';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { TrancheItem } from '../redemption/tranche-item';
|
||||
import Routes from '../routes';
|
||||
import { TrancheLabel } from './tranche-label';
|
||||
@@ -18,6 +19,7 @@ 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();
|
||||
@@ -57,15 +59,25 @@ export const Tranche = () => {
|
||||
</KeyValueTableRow>
|
||||
{tranche.users.map((user) => (
|
||||
<KeyValueTableRow key={user}>
|
||||
<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>
|
||||
{
|
||||
<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>
|
||||
}
|
||||
</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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
|
||||
NX_VEGA_CONFIG_URL="https://static.vega.xyz/assets/testnet-network.json"
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet1-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/sandbox-network.json
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
# App configuration variables
|
||||
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
|
||||
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://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.tom
|
||||
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
|
||||
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_NETWORKS='{"TESTNET":"https://multisig-signer.fairground.wtf","MAINNET":"https://multisig-signer.vega.xyz"}'
|
||||
NX_VEGA_ENV=VALIDATOR_TESTNET
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"hosts": ["https://api-n04.d.vega.rocks/graphql"]
|
||||
"hosts": ["https://api.n04.d.vega.xyz/graphql"]
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"hosts": ["https://api-n00.mainnet-mirror.vega.rocks/graphql"]
|
||||
"hosts": ["https://api.n00.mainnet-mirror.vega.xyz/graphql"]
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"hosts": ["https://api-n01.sandbox.vega.rocks/graphql"]
|
||||
"hosts": ["https://api.n01.sandbox.vega.xyz/graphql"]
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"hosts": ["https://api-n00.stagnet1.vega.rocks/graphql"]
|
||||
"hosts": ["https://api.n00.stagnet1.vega.xyz/graphql"]
|
||||
}
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"hosts": ["https://api-stagnet3.vega.rocks/graphql"]
|
||||
"hosts": ["https://api.stagnet3.vega.xyz/graphql"]
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user