Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
+3 |
9eee4ff8c4 |
@@ -32,14 +32,14 @@ runs:
|
||||
- name: Import fairground network
|
||||
shell: bash
|
||||
if: ${{ inputs.capsule==false }}
|
||||
run: vegawallet network import --from-url="https://raw.githubusercontent.com/vegaprotocol/networks/master/fairground/fairground.toml" --force --home ~/.vegacapsule/testnet/wallet
|
||||
run: vegawallet network import --from-url="https://raw.githubusercontent.com/vegaprotocol/networks-internal/master/fairground/vegawallet-fairground.toml" --force --home ~/.vegacapsule/testnet/wallet
|
||||
|
||||
- name: Start service using fairground network
|
||||
shell: bash
|
||||
if: ${{ inputs.capsule==false }}
|
||||
run: vegawallet service run --network fairground --automatic-consent --home ~/.vegacapsule/testnet/wallet &
|
||||
run: vegawallet service run --network fairground --automatic-consent --no-version-check --home ~/.vegacapsule/testnet/wallet &
|
||||
|
||||
- name: Start service using capsule network
|
||||
shell: bash
|
||||
if: ${{ inputs.capsule }}
|
||||
if: ${{ inputs.capsule==true }}
|
||||
run: vegawallet service run --network DV --automatic-consent --home ~/.vegacapsule/testnet/wallet &
|
||||
|
||||
@@ -296,11 +296,7 @@ describe('Market trade', { tags: '@smoke' }, () => {
|
||||
|
||||
cy.get('#step-3-panel').find('dd').eq(4).should('have.text', ' - ');
|
||||
|
||||
cy.getByTestId('place-order').click();
|
||||
cy.getByTestId('dialog-title').should(
|
||||
'have.text',
|
||||
'Awaiting network confirmation'
|
||||
);
|
||||
cy.getByTestId('place-order').should('be.enabled').click();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -8,10 +8,8 @@ import {
|
||||
emptyPositions,
|
||||
generateMargins,
|
||||
} from '../support/mocks/generate-positions';
|
||||
import {
|
||||
generateAccounts,
|
||||
generateAssets,
|
||||
} from '../support/mocks/generate-accounts';
|
||||
import { generateAccounts } from '../support/mocks/generate-accounts';
|
||||
import { generateAssets } from '../support/mocks/generate-assets';
|
||||
import { generateOrders } from '../support/mocks/generate-orders';
|
||||
import { generateFills } from '../support/mocks/generate-fills';
|
||||
import {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { AccountsQuery, AssetsQuery } from '@vegaprotocol/accounts';
|
||||
import { AccountType, Schema as Types } from '@vegaprotocol/types';
|
||||
import type { AccountsQuery } from '@vegaprotocol/accounts';
|
||||
import { AccountType } from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateAccounts = (
|
||||
@@ -75,43 +75,3 @@ export const generateAccounts = (
|
||||
};
|
||||
return merge(defaultAccounts, override);
|
||||
};
|
||||
|
||||
export const generateAssets = (override?: PartialDeep<AssetsQuery>) => {
|
||||
const defaultAssets: AssetsQuery = {
|
||||
assetsConnection: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
id: 'asset-id',
|
||||
symbol: 'tEURO',
|
||||
decimals: 5,
|
||||
name: 'Euro',
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-id-2',
|
||||
symbol: 'tDAI',
|
||||
decimals: 5,
|
||||
name: 'DAI',
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-0',
|
||||
symbol: 'AST0',
|
||||
decimals: 5,
|
||||
name: 'Asto',
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
return merge(defaultAssets, override);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { AssetsQuery } from '@vegaprotocol/assets';
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateAssets = (override?: PartialDeep<AssetsQuery>) => {
|
||||
const defaultAssets: AssetsQuery = {
|
||||
assetsConnection: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
id: 'asset-id',
|
||||
symbol: 'tEURO',
|
||||
decimals: 5,
|
||||
name: 'Euro',
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x0158031158Bb4dF2AD02eAA31e8963E84EA978a4',
|
||||
},
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-id-2',
|
||||
symbol: 'tDAI',
|
||||
decimals: 5,
|
||||
name: 'DAI',
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x0158031158Bb4dF2AD02eAA31e8963E84EA978a4',
|
||||
},
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-0',
|
||||
symbol: 'AST0',
|
||||
decimals: 5,
|
||||
name: 'Asto',
|
||||
source: {
|
||||
__typename: 'BuiltinAsset',
|
||||
},
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
return merge(defaultAssets, override);
|
||||
};
|
||||
@@ -1,14 +1,15 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type {
|
||||
Positions,
|
||||
Positions_party_positionsConnection_edges_node,
|
||||
PositionsQuery,
|
||||
PositionFieldsFragment,
|
||||
MarginsQuery,
|
||||
} from '@vegaprotocol/positions';
|
||||
|
||||
export const generatePositions = (
|
||||
override?: PartialDeep<Positions>
|
||||
): Positions => {
|
||||
const nodes: Positions_party_positionsConnection_edges_node[] = [
|
||||
override?: PartialDeep<PositionsQuery>
|
||||
): PositionsQuery => {
|
||||
const nodes: PositionFieldsFragment[] = [
|
||||
{
|
||||
__typename: 'Position',
|
||||
realisedPNL: '0',
|
||||
@@ -47,7 +48,7 @@ export const generatePositions = (
|
||||
},
|
||||
];
|
||||
|
||||
const defaultResult: Positions = {
|
||||
const defaultResult: PositionsQuery = {
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
@@ -66,7 +67,7 @@ export const generatePositions = (
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
|
||||
export const emptyPositions = () => {
|
||||
export const emptyPositions = (): PositionsQuery => {
|
||||
return {
|
||||
party: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
@@ -76,7 +77,7 @@ export const emptyPositions = () => {
|
||||
};
|
||||
};
|
||||
|
||||
export const generateMargins = () => {
|
||||
export const generateMargins = (): MarginsQuery => {
|
||||
return {
|
||||
party: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
@@ -119,7 +120,7 @@ export const generateMargins = () => {
|
||||
},
|
||||
{
|
||||
node: {
|
||||
m_typename: 'MarginLevels',
|
||||
__typename: 'MarginLevels',
|
||||
maintenanceLevel: '0',
|
||||
searchLevel: '0',
|
||||
initialLevel: '0',
|
||||
|
||||
@@ -1,32 +1,12 @@
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import { useMemo } from 'react';
|
||||
import { DepositManager } from '@vegaprotocol/deposits';
|
||||
import { getEnabledAssets, t } from '@vegaprotocol/react-helpers';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { enabledAssetsProvider } from '@vegaprotocol/assets';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { Networks, useEnvironment } from '@vegaprotocol/environment';
|
||||
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { Web3Container } from '@vegaprotocol/web3';
|
||||
import type { DepositAssets } from './__generated__/DepositAssets';
|
||||
|
||||
const DEPOSITS_QUERY = gql`
|
||||
query DepositAssets {
|
||||
assetsConnection {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
symbol
|
||||
decimals
|
||||
status
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Fetches data required for the Deposit page
|
||||
@@ -34,20 +14,19 @@ const DEPOSITS_QUERY = gql`
|
||||
export const DepositContainer = () => {
|
||||
const { VEGA_ENV } = useEnvironment();
|
||||
const { pubKey } = useVegaWallet();
|
||||
|
||||
const { data, loading, error } = useQuery<DepositAssets>(DEPOSITS_QUERY, {
|
||||
variables: { partyId: pubKey },
|
||||
const variables = useMemo(() => ({ partyId: pubKey }), [pubKey]);
|
||||
const { data, loading, error } = useDataProvider({
|
||||
dataProvider: enabledAssetsProvider,
|
||||
variables,
|
||||
skip: !pubKey,
|
||||
});
|
||||
|
||||
const assets = getEnabledAssets(data);
|
||||
|
||||
return (
|
||||
<AsyncRenderer<DepositAssets> data={data} loading={loading} error={error}>
|
||||
{assets.length ? (
|
||||
<AsyncRenderer data={data} loading={loading} error={error}>
|
||||
{data && data.length ? (
|
||||
<Web3Container>
|
||||
<DepositManager
|
||||
assets={assets}
|
||||
assets={data}
|
||||
isFaucetable={VEGA_ENV !== Networks.MAINNET}
|
||||
/>
|
||||
</Web3Container>
|
||||
|
||||
@@ -4,6 +4,7 @@ import type { AgGridReact } from 'ag-grid-react';
|
||||
import {
|
||||
useScreenDimensions,
|
||||
useDataProvider,
|
||||
useYesterday,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import type { MarketState } from '@vegaprotocol/types';
|
||||
@@ -33,13 +34,13 @@ const SimpleMarketList = () => {
|
||||
const statusesRef = useRef<Record<string, MarketState | ''>>({});
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
|
||||
const yesterday = useYesterday();
|
||||
const variables = useMemo(() => {
|
||||
const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
|
||||
return {
|
||||
since: new Date(yesterday * 1000).toISOString(),
|
||||
since: new Date(yesterday).toISOString(),
|
||||
interval: Interval.INTERVAL_I1H,
|
||||
};
|
||||
}, []);
|
||||
}, [yesterday]);
|
||||
const { data, error, loading } = useDataProvider({
|
||||
dataProvider: marketsWithCandlesProvider,
|
||||
variables,
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { InView } from 'react-intersection-observer';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { useDataProvider, useYesterday } from '@vegaprotocol/react-helpers';
|
||||
import type { Candle } from '@vegaprotocol/market-list';
|
||||
import { marketCandlesProvider } from '@vegaprotocol/market-list';
|
||||
import { Interval } from '@vegaprotocol/types';
|
||||
@@ -68,13 +68,13 @@ const SimpleMarketPercentChangeWrapper = (props: Props) => {
|
||||
};
|
||||
|
||||
const SimpleMarketPercentChange = ({ candles, marketId, setValue }: Props) => {
|
||||
const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
|
||||
const yesterday = useYesterday();
|
||||
const { data } = useDataProvider({
|
||||
dataProvider: marketCandlesProvider,
|
||||
variables: {
|
||||
marketId,
|
||||
interval: Interval.INTERVAL_I1D,
|
||||
since: new Date(yesterday * 1000).toISOString(),
|
||||
since: new Date(yesterday).toISOString(),
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ module.exports = defineConfig({
|
||||
},
|
||||
baseUrl: 'http://localhost:3000',
|
||||
fileServerFolder: '.',
|
||||
fixturesFolder: false,
|
||||
fixturesFolder: './src/fixtures',
|
||||
specPattern: '**/*.cy.{js,jsx,ts,tsx}',
|
||||
modifyObstructiveCode: false,
|
||||
supportFile: './src/support/index.js',
|
||||
|
||||
@@ -0,0 +1,121 @@
|
||||
{
|
||||
"eighteenDecimal": [
|
||||
"governance.proposal.asset.minProposerBalance",
|
||||
"governance.proposal.asset.minVoterBalance",
|
||||
"governance.proposal.freeform.minProposerBalance",
|
||||
"governance.proposal.freeform.minVoterBalance",
|
||||
"governance.proposal.market.minProposerBalance",
|
||||
"governance.proposal.market.minVoterBalance",
|
||||
"governance.proposal.updateMarket.minProposerBalance",
|
||||
"governance.proposal.updateMarket.minVoterBalance",
|
||||
"governance.proposal.updateNetParam.minProposerBalance",
|
||||
"governance.proposal.updateNetParam.minVoterBalance",
|
||||
"reward.staking.delegation.maxPayoutPerEpoch",
|
||||
"reward.staking.delegation.maxPayoutPerParticipant",
|
||||
"reward.staking.delegation.minimumValidatorStake",
|
||||
"spam.protection.delegation.min.tokens",
|
||||
"spam.protection.proposal.min.tokens",
|
||||
"spam.protection.voting.min.tokens",
|
||||
"validators.delegation.minAmount"
|
||||
],
|
||||
"fiveDecimal": [
|
||||
"governance.proposal.updateAsset.minProposerBalance",
|
||||
"governance.proposal.updateAsset.minVoterBalance",
|
||||
"governance.proposal.updateAsset.requiredParticipation",
|
||||
"governance.proposal.updateMarket.minProposerEquityLikeShare",
|
||||
"market.fee.factors.infrastructureFee",
|
||||
"market.fee.factors.makerFee",
|
||||
"market.liquidity.bondPenaltyParameter",
|
||||
"market.liquidity.maximumLiquidityFeeFactorLevel",
|
||||
"market.liquidity.minimum.probabilityOfTrading.lpOrders",
|
||||
"market.liquidity.probabilityOfTrading.tau.scaling",
|
||||
"market.liquidity.stakeToCcySiskas",
|
||||
"market.liquidity.targetstake.triggering.ratio",
|
||||
"market.liquidityProvision.minLpStakeQuantumMultiple",
|
||||
"market.liquidityProvision.shapes.maxSize",
|
||||
"market.stake.target.scalingFactor",
|
||||
"network.validators.ersatz.multipleOfTendermintValidators",
|
||||
"network.validators.ersatz.rewardFactor",
|
||||
"network.validators.incumbentBonus",
|
||||
"network.validators.minimumEthereumEventsForNewValidator",
|
||||
"network.validators.multisig.numberOfSigners",
|
||||
"network.validators.tendermint.number",
|
||||
"reward.staking.delegation.competitionLevel",
|
||||
"reward.staking.delegation.delegatorShare",
|
||||
"reward.staking.delegation.minValidators",
|
||||
"reward.staking.delegation.optimalStakeMultiplier",
|
||||
"reward.staking.delegation.payoutFraction",
|
||||
"rewards.marketCreationQuantumMultiple",
|
||||
"spam.pow.difficulty",
|
||||
"spam.pow.increaseDifficulty",
|
||||
"spam.pow.numberOfPastBlocks",
|
||||
"spam.pow.numberOfTxPerBlock",
|
||||
"spam.protection.max.batchSize",
|
||||
"spam.protection.max.delegations",
|
||||
"spam.protection.max.proposals",
|
||||
"spam.protection.max.votes",
|
||||
"spam.protection.maxUserTransfersPerEpoch",
|
||||
"transfer.fee.factor",
|
||||
"transfer.minTransferQuantumMultiple",
|
||||
"snapshot.interval.length"
|
||||
],
|
||||
"json": [
|
||||
"blockchains.ethereumConfig",
|
||||
"market.margin.scalingFactors",
|
||||
"market.monitor.price.defaultParameters"
|
||||
],
|
||||
"percentage": [
|
||||
"governance.proposal.asset.requiredMajority",
|
||||
"governance.proposal.asset.requiredParticipation",
|
||||
"governance.proposal.freeform.requiredMajority",
|
||||
"governance.proposal.freeform.requiredParticipation",
|
||||
"governance.proposal.market.requiredMajority",
|
||||
"governance.proposal.market.requiredParticipation",
|
||||
"governance.proposal.updateMarket.requiredMajority",
|
||||
"governance.proposal.updateMarket.requiredMajorityLP",
|
||||
"governance.proposal.updateMarket.requiredParticipation",
|
||||
"governance.proposal.updateMarket.requiredParticipationLP",
|
||||
"governance.proposal.updateNetParam.requiredMajority",
|
||||
"governance.proposal.updateNetParam.requiredParticipation",
|
||||
"validators.vote.required"
|
||||
],
|
||||
"duration": [
|
||||
"governance.proposal.asset.maxClose",
|
||||
"governance.proposal.asset.maxEnact",
|
||||
"governance.proposal.asset.minClose",
|
||||
"governance.proposal.asset.minEnact",
|
||||
"governance.proposal.freeform.maxClose",
|
||||
"governance.proposal.freeform.minClose",
|
||||
"governance.proposal.market.maxClose",
|
||||
"governance.proposal.market.maxEnact",
|
||||
"governance.proposal.market.minClose",
|
||||
"governance.proposal.market.minEnact",
|
||||
"governance.proposal.updateAsset.maxClose",
|
||||
"governance.proposal.updateAsset.maxEnact",
|
||||
"governance.proposal.updateAsset.minClose",
|
||||
"governance.proposal.updateAsset.minEnact",
|
||||
"governance.proposal.updateMarket.maxClose",
|
||||
"governance.proposal.updateMarket.maxEnact",
|
||||
"governance.proposal.updateMarket.minClose",
|
||||
"governance.proposal.updateMarket.minEnact",
|
||||
"governance.proposal.updateNetParam.maxClose",
|
||||
"governance.proposal.updateNetParam.maxEnact",
|
||||
"governance.proposal.updateNetParam.minClose",
|
||||
"governance.proposal.updateNetParam.minEnact",
|
||||
"market.auction.maximumDuration",
|
||||
"market.auction.minimumDuration",
|
||||
"market.liquidity.providers.fee.distributionTimeStep",
|
||||
"market.stake.target.timeWindow",
|
||||
"market.value.windowLength",
|
||||
"network.checkpoint.timeElapsedBetweenCheckpoints",
|
||||
"network.floatingPointUpdates.delay",
|
||||
"reward.staking.delegation.payoutDelay",
|
||||
"spam.pow.hashFunction",
|
||||
"validators.epoch.length"
|
||||
],
|
||||
"date": [
|
||||
"limits.assets.proposeEnabledFrom",
|
||||
"limits.markets.proposeEnabledFrom"
|
||||
],
|
||||
"id": ["reward.asset"]
|
||||
}
|
||||
@@ -1,33 +1,257 @@
|
||||
context('Network parameters page', { tags: '@smoke' }, function () {
|
||||
before('visit token home page', function () {
|
||||
cy.visit('/');
|
||||
before('navigate to network parameter page', function () {
|
||||
cy.fixture('net_parameter_format_lookup').as('networkParameterFormat');
|
||||
});
|
||||
|
||||
describe('Verify elements on page', function () {
|
||||
const networkParametersNavigation = 'a[href="/network-parameters"]';
|
||||
const networkParametersHeader = '[data-testid="network-param-header"]';
|
||||
const tableRows = '[data-testid="key-value-table-row"]';
|
||||
|
||||
beforeEach('Navigate to network parameter page', function () {
|
||||
before('navigate to network parameter page', function () {
|
||||
cy.visit('/');
|
||||
cy.get(networkParametersNavigation).click();
|
||||
});
|
||||
|
||||
it('Network paremeter page is displayed', function () {
|
||||
verifyNetworkParametersPageDisplayed();
|
||||
it('should show network parameter heading at top of page', function () {
|
||||
cy.get(networkParametersHeader)
|
||||
.should('have.text', 'Network Parameters')
|
||||
.and('be.visible');
|
||||
});
|
||||
|
||||
it('Network parameter page displayed on mobile', function () {
|
||||
it('should list each of the network parameters available', function () {
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
const numberOfNetworkParametersInSystem =
|
||||
Object.keys(network_parameters).length;
|
||||
cy.get(tableRows).should(
|
||||
'have.length',
|
||||
numberOfNetworkParametersInSystem
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should list each network parameter displayed with json - in the correct format', function () {
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
network_parameters = Object.entries(network_parameters);
|
||||
network_parameters.forEach((network_parameter) => {
|
||||
const parameterName = network_parameter[0];
|
||||
const parameterValue = network_parameter[1];
|
||||
if (this.networkParameterFormat.json.includes(parameterName)) {
|
||||
cy.get(tableRows)
|
||||
.contains(parameterName)
|
||||
.should('be.visible')
|
||||
.next()
|
||||
.invoke('text')
|
||||
.convert_string_json_to_js_object()
|
||||
.then((jsonOnPage) => {
|
||||
cy.wrap(parameterValue, { log: false })
|
||||
.convert_string_json_to_js_object()
|
||||
.then((jsonInSystem) =>
|
||||
assert.deepEqual(
|
||||
jsonOnPage,
|
||||
jsonInSystem,
|
||||
`Checking ${parameterName} has the correct value of ${jsonInSystem}`
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should list each network parameter displayed as a percentage - in the correct format', function () {
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
network_parameters = Object.entries(network_parameters);
|
||||
network_parameters.forEach((network_parameter) => {
|
||||
const parameterName = network_parameter[0];
|
||||
const parameterValue = network_parameter[1];
|
||||
if (this.networkParameterFormat.percentage.includes(parameterName)) {
|
||||
const formattedPercentageParameter =
|
||||
(parseFloat(parameterValue) * 100).toFixed(0) + '%';
|
||||
cy.get(tableRows)
|
||||
.contains(parameterName)
|
||||
.should('be.visible')
|
||||
.next()
|
||||
.invoke('text')
|
||||
.then((parameterValueOnPage) => {
|
||||
assert.equal(
|
||||
parameterValueOnPage,
|
||||
formattedPercentageParameter,
|
||||
`Checking ${parameterName} has the correct value of ${formattedPercentageParameter}`
|
||||
);
|
||||
cy.contains(parameterValueOnPage).should('be.visible');
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should list each network parameter displayed as an id - in the correct format', function () {
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
network_parameters = Object.entries(network_parameters);
|
||||
network_parameters.forEach((network_parameter) => {
|
||||
const parameterName = network_parameter[0];
|
||||
const parameterValue = network_parameter[1];
|
||||
if (this.networkParameterFormat.id.includes(parameterName)) {
|
||||
cy.get(tableRows)
|
||||
.contains(parameterName)
|
||||
.should('be.visible')
|
||||
.next()
|
||||
.should('contain', parameterValue)
|
||||
.and('be.visible')
|
||||
.invoke('text');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should list each network parameter displayed as a date - in the correct format', function () {
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
network_parameters = Object.entries(network_parameters);
|
||||
network_parameters.forEach((network_parameter) => {
|
||||
const parameterName = network_parameter[0];
|
||||
const parameterValue = network_parameter[1];
|
||||
if (this.networkParameterFormat.date.includes(parameterName)) {
|
||||
cy.get(tableRows)
|
||||
.contains(parameterName)
|
||||
.should('be.visible')
|
||||
.next()
|
||||
.should('contain', parameterValue)
|
||||
.and('be.visible');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should list each network parameter displayed as a duration - in the correct format', function () {
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
network_parameters = Object.entries(network_parameters);
|
||||
network_parameters.forEach((network_parameter) => {
|
||||
const parameterName = network_parameter[0];
|
||||
const parameterValue = network_parameter[1];
|
||||
if (this.networkParameterFormat.duration.includes(parameterName)) {
|
||||
cy.get(tableRows)
|
||||
.contains(parameterName)
|
||||
.should('be.visible')
|
||||
.next()
|
||||
.should('contain', parameterValue)
|
||||
.and('be.visible');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should list each network parameter displayed as a currency value with four decimals - in the correct format', function () {
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
network_parameters = Object.entries(network_parameters);
|
||||
network_parameters.forEach((network_parameter) => {
|
||||
const parameterName = network_parameter[0];
|
||||
const parameterValue = network_parameter[1];
|
||||
if (this.networkParameterFormat.fiveDecimal.includes(parameterName)) {
|
||||
cy.convert_number_to_four_decimal(parameterValue)
|
||||
.add_commas_to_number_if_large_enough()
|
||||
.then((parameterValueFormatted) => {
|
||||
cy.get(tableRows)
|
||||
.contains(parameterName)
|
||||
.should('be.visible')
|
||||
.next()
|
||||
.invoke('text')
|
||||
.then((parameterValueOnPage) => {
|
||||
assert.equal(
|
||||
parameterValueOnPage,
|
||||
parameterValueFormatted,
|
||||
`Checking ${parameterName} has the correct value of ${parameterValueFormatted}`
|
||||
);
|
||||
cy.contains(parameterValueOnPage).should('be.visible');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should list each network parameter displayed as a currency value with eighteen decimals - in the correct format', function () {
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
network_parameters = Object.entries(network_parameters);
|
||||
network_parameters.forEach((network_parameter) => {
|
||||
const parameterName = network_parameter[0];
|
||||
const parameterValue = network_parameter[1];
|
||||
if (
|
||||
this.networkParameterFormat.eighteenDecimal.includes(parameterName)
|
||||
) {
|
||||
cy.convert_number_to_eighteen_decimal(parameterValue)
|
||||
.add_commas_to_number_if_large_enough()
|
||||
.then((parameterValueFormatted) => {
|
||||
cy.get(tableRows)
|
||||
.contains(parameterName)
|
||||
.should('be.visible')
|
||||
.next()
|
||||
.invoke('text')
|
||||
.then((parameterValueOnPage) => {
|
||||
assert.equal(
|
||||
parameterValueOnPage,
|
||||
parameterValueFormatted,
|
||||
`Checking ${parameterName} has the correct value of ${parameterValueFormatted}`
|
||||
);
|
||||
cy.contains(parameterValueOnPage).should('be.visible');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it.skip('should be able to switch network parameter page - between light and dark mode', function () {
|
||||
const whiteThemeSelectedMenuOptionColor = 'rgb(255, 7, 127)';
|
||||
const whiteThemeJsonFieldBackColor = 'rgb(255, 255, 255)';
|
||||
const whiteThemeSideMenuBackgroundColor = 'rgb(255, 255, 255)';
|
||||
const blackThemeSelectedMenuOptionColor = 'rgb(223, 255, 11)';
|
||||
const blackThemeJsonFieldBackColor = 'rgb(38, 38, 38)';
|
||||
const blackThemeSideMenuBackgroundColor = 'rgb(0, 0, 0)';
|
||||
const themeSwitcher = '[data-testid="theme-switcher"]';
|
||||
const jsonFields = '.hljs';
|
||||
const sideMenuBackground = '.absolute';
|
||||
|
||||
// White Mode
|
||||
cy.get(themeSwitcher).click();
|
||||
cy.get(networkParametersNavigation)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', whiteThemeSelectedMenuOptionColor);
|
||||
cy.get(jsonFields)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', whiteThemeJsonFieldBackColor);
|
||||
cy.get(sideMenuBackground)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', whiteThemeSideMenuBackgroundColor);
|
||||
|
||||
// Dark Mode
|
||||
cy.get(themeSwitcher).click();
|
||||
cy.get(networkParametersNavigation)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', blackThemeSelectedMenuOptionColor);
|
||||
cy.get(jsonFields)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', blackThemeJsonFieldBackColor);
|
||||
cy.get(sideMenuBackground)
|
||||
.should('have.css', 'background-color')
|
||||
.and('include', blackThemeSideMenuBackgroundColor);
|
||||
});
|
||||
|
||||
it('should be able to see network parameters - on mobile', function () {
|
||||
cy.common_switch_to_mobile_and_click_toggle();
|
||||
cy.get(networkParametersNavigation).click();
|
||||
verifyNetworkParametersPageDisplayed();
|
||||
cy.get_network_parameters().then((network_parameters) => {
|
||||
network_parameters = Object.entries(network_parameters);
|
||||
network_parameters.forEach((network_parameter) => {
|
||||
const parameterName = network_parameter[0];
|
||||
cy.get(tableRows)
|
||||
.contains(parameterName)
|
||||
.should('be.visible')
|
||||
.next()
|
||||
.should('not.be.empty')
|
||||
.and('be.visible');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function verifyNetworkParametersPageDisplayed() {
|
||||
cy.get('[data-testid="network-param-header"]').should(
|
||||
'have.text',
|
||||
'Network Parameters'
|
||||
);
|
||||
cy.common_verify_json_parameters(18);
|
||||
cy.common_verify_json_string_values(6);
|
||||
cy.common_verify_json_int_values(7);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { BigNumber } from 'bignumber.js';
|
||||
|
||||
Cypress.Commands.add(
|
||||
'common_validate_blocks_data_displayed',
|
||||
function (headerTestId) {
|
||||
@@ -25,33 +27,6 @@ Cypress.Commands.add('common_switch_to_mobile_and_click_toggle', function () {
|
||||
cy.get('[data-testid="open-menu"]').click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('common_verify_json_parameters', function (expectedNum) {
|
||||
cy.get('.hljs-attr')
|
||||
.should('have.length.at.least', expectedNum)
|
||||
.each(($paramName) => {
|
||||
cy.wrap($paramName).should('not.be.empty');
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add(
|
||||
'common_verify_json_string_values',
|
||||
function (expectedNum) {
|
||||
cy.get('.hljs-string')
|
||||
.should('have.length.at.least', expectedNum)
|
||||
.each(($paramValue) => {
|
||||
cy.wrap($paramValue).should('not.be.empty');
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add('common_verify_json_int_values', function (expectedNum) {
|
||||
cy.get('.hljs-number')
|
||||
.should('have.length.at.least', expectedNum)
|
||||
.each(($paramValue) => {
|
||||
cy.wrap($paramValue).should('not.be.empty');
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('monitor_clipboard', () => {
|
||||
cy.window().then((win) => {
|
||||
return cy.stub(win, 'prompt').returns(win.prompt);
|
||||
@@ -72,6 +47,33 @@ Cypress.Commands.add(
|
||||
'convert_string_json_to_js_object',
|
||||
{ prevSubject: true },
|
||||
(jsonBlobString) => {
|
||||
// Note: this is a chaining function
|
||||
return JSON.parse(jsonBlobString);
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add(
|
||||
'add_commas_to_number_if_large_enough',
|
||||
{ prevSubject: true },
|
||||
(number) => {
|
||||
// This will turn 10000000.0000 into 10,000,000.000
|
||||
// Note: this is a chaining function
|
||||
const beforeDecimal = number.split('.')[0];
|
||||
const afterDecimal = number.split('.')[1];
|
||||
const beforeDecimalWithCommas = beforeDecimal
|
||||
.toString()
|
||||
.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
||||
const formattedValue = beforeDecimalWithCommas + '.' + afterDecimal;
|
||||
return formattedValue;
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add('convert_number_to_eighteen_decimal', (number) => {
|
||||
// this will take a number like this : 700000000000000000000
|
||||
// and convert it to a number like this: 700.000000000000000000
|
||||
return BigNumber((number / 1000000000000000000).toString()).toFixed(18);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('convert_number_to_four_decimal', (number) => {
|
||||
return parseFloat(number).toFixed(4);
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https:
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
|
||||
NX_BLOCK_EXPLORER=
|
||||
|
||||
# App flags
|
||||
NX_EXPLORER_ASSETS=1
|
||||
|
||||
@@ -7,3 +7,4 @@ NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
|
||||
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
|
||||
NX_VEGA_ENV=DEVNET
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_BLOCK_EXPLORER=
|
||||
|
||||
@@ -7,3 +7,4 @@ NX_VEGA_URL=https://api.vega.xyz/query
|
||||
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
|
||||
NX_VEGA_ENV=MAINNET
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_BLOCK_EXPLORER=
|
||||
|
||||
@@ -7,3 +7,4 @@ NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
|
||||
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
|
||||
NX_VEGA_ENV=STAGNET3
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_BLOCK_EXPLORER=
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# App configuration variables
|
||||
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
|
||||
NX_TENDERMINT_URL=https://tm.n07.testnet.vega.xyz
|
||||
NX_BLOCK_EXPLORER=https://n13.testnet.vega.xyz/rest
|
||||
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n07.testnet.vega.xyz/websocket
|
||||
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
|
||||
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
|
||||
|
||||
@@ -5,3 +5,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26607/websocket
|
||||
NX_VEGA_URL=http://localhost:3003/query
|
||||
NX_VEGA_ENV=CUSTOM
|
||||
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
|
||||
NX_BLOCK_EXPLORER=
|
||||
|
||||
@@ -1,92 +1,90 @@
|
||||
import { TxsInfiniteListItem } from './txs-infinite-list-item';
|
||||
import { render, screen, fireEvent, act } from '@testing-library/react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
describe('Txs infinite list item', () => {
|
||||
it('should display "missing vital data" if "Type" data missing', () => {
|
||||
it('should display "missing vital data" if "type" data missing', () => {
|
||||
render(
|
||||
<TxsInfiniteListItem
|
||||
// @ts-ignore testing deliberate failure
|
||||
Type={undefined}
|
||||
Command={'test'}
|
||||
Sig={'test'}
|
||||
PubKey={'test'}
|
||||
Nonce={1}
|
||||
TxHash={'test'}
|
||||
type={undefined}
|
||||
submitter="test"
|
||||
hash=""
|
||||
index={0}
|
||||
block="1"
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Missing vital data')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display "missing vital data" if "Command" data missing', () => {
|
||||
it('should display "missing vital data" if "hash" data missing', () => {
|
||||
render(
|
||||
<TxsInfiniteListItem
|
||||
Type={'test'}
|
||||
// @ts-ignore testing deliberate failure
|
||||
Command={undefined}
|
||||
Sig={'test'}
|
||||
PubKey={'test'}
|
||||
Nonce={1}
|
||||
TxHash={'test'}
|
||||
type="test"
|
||||
submitter="test"
|
||||
hash={undefined}
|
||||
index={0}
|
||||
block="1"
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Missing vital data')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display "missing vital data" if "Pubkey" data missing', () => {
|
||||
it('should display "missing vital data" if "submitter" data missing', () => {
|
||||
render(
|
||||
<TxsInfiniteListItem
|
||||
Type={'test'}
|
||||
Command={'test'}
|
||||
Sig={'test'}
|
||||
// @ts-ignore testing deliberate failure
|
||||
PubKey={undefined}
|
||||
Nonce={1}
|
||||
TxHash={'test'}
|
||||
type="test"
|
||||
submitter={undefined}
|
||||
hash="test"
|
||||
index={0}
|
||||
block="1"
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Missing vital data')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display "missing vital data" if "TxHash" data missing', () => {
|
||||
it('should display "missing vital data" if "block" data missing', () => {
|
||||
render(
|
||||
<TxsInfiniteListItem
|
||||
Type={'test'}
|
||||
Command={'test'}
|
||||
Sig={'test'}
|
||||
PubKey={'test'}
|
||||
Nonce={1}
|
||||
// @ts-ignore testing deliberate failure
|
||||
TxHash={undefined}
|
||||
type="test"
|
||||
submitter="test"
|
||||
hash="test"
|
||||
index={0}
|
||||
block={undefined}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Missing vital data')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should display "missing vital data" if "index" data missing', () => {
|
||||
render(
|
||||
<TxsInfiniteListItem
|
||||
type="test"
|
||||
submitter="test"
|
||||
hash="test"
|
||||
index={undefined}
|
||||
block="1"
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Missing vital data')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders data correctly', () => {
|
||||
const testCommandData = JSON.stringify({
|
||||
test: 'test of command data',
|
||||
});
|
||||
|
||||
render(
|
||||
<MemoryRouter>
|
||||
<TxsInfiniteListItem
|
||||
Type={'testType'}
|
||||
Command={testCommandData}
|
||||
Sig={'testSig'}
|
||||
PubKey={'testPubKey'}
|
||||
Nonce={1}
|
||||
TxHash={'testTxHash'}
|
||||
type="testType"
|
||||
submitter="testPubKey"
|
||||
hash="testTxHash"
|
||||
index={1}
|
||||
block="1"
|
||||
/>
|
||||
</MemoryRouter>
|
||||
);
|
||||
expect(screen.getByTestId('tx-hash')).toHaveTextContent('testTxHash');
|
||||
expect(screen.getByTestId('pub-key')).toHaveTextContent('testPubKey');
|
||||
expect(screen.getByTestId('type')).toHaveTextContent('testType');
|
||||
const button = screen.getByTestId('command-details');
|
||||
act(() => {
|
||||
fireEvent.click(button);
|
||||
});
|
||||
expect(screen.getByText('"test of command data"')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('tx-type')).toHaveTextContent('testType');
|
||||
expect(screen.getByTestId('tx-block')).toHaveTextContent(
|
||||
'Block 1 (index 1)'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,69 +1,60 @@
|
||||
import React, { useState } from 'react';
|
||||
import {
|
||||
Dialog,
|
||||
Icon,
|
||||
Intent,
|
||||
SyntaxHighlighter,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import React from 'react';
|
||||
import { TruncatedLink } from '../truncate/truncated-link';
|
||||
import { Routes } from '../../routes/route-names';
|
||||
import { TxOrderType } from './tx-order-type';
|
||||
import type { ChainExplorerTxResponse } from '../../routes/types/chain-explorer-response';
|
||||
import type { BlockExplorerTransaction } from '../../routes/types/block-explorer-response';
|
||||
import { toHex } from '../search/detect-search';
|
||||
|
||||
const TRUNCATE_LENGTH = 14;
|
||||
|
||||
export const TxsInfiniteListItem = ({
|
||||
TxHash,
|
||||
PubKey,
|
||||
Type,
|
||||
Command,
|
||||
}: ChainExplorerTxResponse) => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
if (!TxHash || !PubKey || !Type || !Command) {
|
||||
hash,
|
||||
submitter,
|
||||
type,
|
||||
block,
|
||||
index,
|
||||
}: Partial<BlockExplorerTransaction>) => {
|
||||
if (
|
||||
!hash ||
|
||||
!submitter ||
|
||||
!type ||
|
||||
block === undefined ||
|
||||
index === undefined
|
||||
) {
|
||||
return <div>Missing vital data</div>;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
data-testid="transaction-row"
|
||||
className="grid grid-cols-[repeat(2,_1fr)_240px] gap-12 w-full border-t border-neutral-600 dark:border-neutral-800 py-8 txs-infinite-list-item"
|
||||
className="grid grid-flow-col auto-cols-auto border-t border-neutral-600 dark:border-neutral-800 py-2 txs-infinite-list-item"
|
||||
>
|
||||
<div className="whitespace-nowrap overflow-scroll" data-testid="tx-hash">
|
||||
<div className="whitespace-nowrap" data-testid="tx-type">
|
||||
<TxOrderType orderType={type} />
|
||||
</div>
|
||||
<div className="whitespace-nowrap" data-testid="pub-key">
|
||||
<TruncatedLink
|
||||
to={`/${Routes.TX}/${TxHash}`}
|
||||
text={TxHash}
|
||||
to={`/${Routes.PARTIES}/${submitter}`}
|
||||
text={submitter}
|
||||
startChars={TRUNCATE_LENGTH}
|
||||
endChars={TRUNCATE_LENGTH}
|
||||
/>
|
||||
</div>
|
||||
<div className="whitespace-nowrap overflow-scroll" data-testid="pub-key">
|
||||
<div className="whitespace-nowrap" data-testid="tx-hash">
|
||||
<TruncatedLink
|
||||
to={`/${Routes.PARTIES}/${PubKey}`}
|
||||
text={PubKey}
|
||||
to={`/${Routes.TX}/${toHex(hash)}`}
|
||||
text={hash}
|
||||
startChars={TRUNCATE_LENGTH}
|
||||
endChars={TRUNCATE_LENGTH}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="flex justify-between whitespace-nowrap overflow-scroll"
|
||||
data-testid="type"
|
||||
>
|
||||
<TxOrderType orderType={Type} />
|
||||
<button
|
||||
title="More details"
|
||||
onClick={() => setOpen(true)}
|
||||
data-testid="command-details"
|
||||
>
|
||||
<Icon name="search-template" />
|
||||
</button>
|
||||
<Dialog
|
||||
open={open}
|
||||
onChange={(isOpen) => setOpen(false)}
|
||||
intent={Intent.None}
|
||||
>
|
||||
<SyntaxHighlighter data={JSON.parse(Command)} />
|
||||
</Dialog>
|
||||
<div className="whitespace-nowrap" data-testid="tx-block">
|
||||
<TruncatedLink
|
||||
to={`/${Routes.BLOCKS}/${block}`}
|
||||
text={`Block ${block} (index ${index})`}
|
||||
startChars={TRUNCATE_LENGTH}
|
||||
endChars={TRUNCATE_LENGTH}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -1,18 +1,34 @@
|
||||
import { TxsInfiniteList } from './txs-infinite-list';
|
||||
import { render, screen, fireEvent, act } from '@testing-library/react';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
import type { BlockExplorerTransaction } from '../../routes/types/block-explorer-response';
|
||||
|
||||
const generateTxs = (number: number) => {
|
||||
const generateTxs = (number: number): BlockExplorerTransaction[] => {
|
||||
return Array.from(Array(number)).map((_) => ({
|
||||
Type: 'ChainEvent',
|
||||
Command:
|
||||
'{"txId":"0xc8941ac4ea989988cb8f72e8fdab2e2009376fd17619491439d36b519d27bc93","nonce":"1494","stakingEvent":{"index":"263","block":"14805346","stakeDeposited":{"ethereumAddress":"0x2e5fe63e5d49c26998cf4bfa9b64de1cf9ae7ef2","vegaPublicKey":"657c2a8a5867c43c831e24820b7544e2fdcc1cf610cfe0ece940fe78137400fd","amount":"38471116086510047870875","blockTime":"1652968806"}}}',
|
||||
Sig: 'fe7624ab742c492cf1e667e79de4777992aca8e093c8707e1f22685c3125c6082cd21b85cd966a61ad4ca0cca2f8bed3082565caa5915bc3b2f78c1ae35cac0b',
|
||||
PubKey:
|
||||
'0x7d69327393cdfaaae50e5e215feca65273eafabfb38f32b8124e66298af346d5',
|
||||
Nonce: 18296387398179254000,
|
||||
TxHash:
|
||||
'0x9C753FA6325F7A40D9C4FA5C25E24476C54613E12B1FA2DD841E3BB00D088B77',
|
||||
block: '87901',
|
||||
index: 2,
|
||||
hash: '0F8B98DA0923A50786B852D9CA11E051CACC4C733E1DB93D535C7D81DBD10F6F',
|
||||
submitter:
|
||||
'4b782482f587d291e8614219eb9a5ee9280fa2c58982dee71d976782a9be1964',
|
||||
type: 'Submit Order',
|
||||
code: 0,
|
||||
cursor: '87901.2',
|
||||
command: {
|
||||
nonce: '4214037379192575529',
|
||||
blockHeight: '87898',
|
||||
orderSubmission: {
|
||||
marketId:
|
||||
'b4d0a070f5cc73a7d53b23d6f63f8cb52e937ed65d2469a3af4cc1e80e155fcf',
|
||||
price: '14525946',
|
||||
size: '54',
|
||||
side: 'SIDE_SELL',
|
||||
timeInForce: 'TIME_IN_FORCE_GTT',
|
||||
expiresAt: '1664966445481288736',
|
||||
type: 'TYPE_LIMIT',
|
||||
reference: 'traderbot',
|
||||
peggedOrder: null,
|
||||
},
|
||||
},
|
||||
}));
|
||||
};
|
||||
|
||||
@@ -41,7 +57,9 @@ describe('Txs infinite list', () => {
|
||||
error={Error('test error!')}
|
||||
/>
|
||||
);
|
||||
expect(screen.getByText('Error: test error!')).toBeInTheDocument();
|
||||
expect(
|
||||
screen.getByText('Cannot fetch transaction: Error: test error!')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('item renders data of n length into list of n length', () => {
|
||||
|
||||
@@ -3,19 +3,19 @@ import { FixedSizeList as List } from 'react-window';
|
||||
import InfiniteLoader from 'react-window-infinite-loader';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { TxsInfiniteListItem } from './txs-infinite-list-item';
|
||||
import type { ChainExplorerTxResponse } from '../../routes/types/chain-explorer-response';
|
||||
import type { BlockExplorerTransaction } from '../../routes/types/block-explorer-response';
|
||||
|
||||
interface TxsInfiniteListProps {
|
||||
hasMoreTxs: boolean;
|
||||
areTxsLoading: boolean | undefined;
|
||||
txs: ChainExplorerTxResponse[] | undefined;
|
||||
txs: BlockExplorerTransaction[] | undefined;
|
||||
loadMoreTxs: () => void;
|
||||
error: Error | undefined;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
interface ItemProps {
|
||||
index: ChainExplorerTxResponse;
|
||||
index: BlockExplorerTransaction;
|
||||
style: React.CSSProperties;
|
||||
isLoading: boolean;
|
||||
error: Error | undefined;
|
||||
@@ -27,19 +27,19 @@ const NOOP = () => {};
|
||||
const Item = ({ index, style, isLoading, error }: ItemProps) => {
|
||||
let content;
|
||||
if (error) {
|
||||
content = t(`${error}`);
|
||||
content = t(`Cannot fetch transaction: ${error}`);
|
||||
} else if (isLoading) {
|
||||
content = t('Loading...');
|
||||
} else {
|
||||
const { TxHash, PubKey, Type, Command, Sig, Nonce } = index;
|
||||
const { hash, submitter, type, command, block, index: blockIndex } = index;
|
||||
content = (
|
||||
<TxsInfiniteListItem
|
||||
Type={Type}
|
||||
Command={Command}
|
||||
Sig={Sig}
|
||||
PubKey={PubKey}
|
||||
Nonce={Nonce}
|
||||
TxHash={TxHash}
|
||||
type={type}
|
||||
command={command}
|
||||
submitter={submitter}
|
||||
hash={hash}
|
||||
block={block}
|
||||
index={blockIndex}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -71,10 +71,11 @@ export const TxsInfiniteList = ({
|
||||
|
||||
return (
|
||||
<div className={className} data-testid="transactions-list">
|
||||
<div className="grid grid-cols-[repeat(2,_1fr)_240px] gap-12 w-full mb-8">
|
||||
<div className="text-lg font-bold">Txn hash</div>
|
||||
<div className="text-lg font-bold">Party</div>
|
||||
<div className="grid grid-flow-col auto-cols-auto w-full mb-8">
|
||||
<div className="text-lg font-bold pl-2">Type</div>
|
||||
<div className="text-lg font-bold">Submitted By</div>
|
||||
<div className="text-lg font-bold">Transaction ID</div>
|
||||
<div className="text-lg font-bold">Block</div>
|
||||
</div>
|
||||
<div data-testid="infinite-scroll-wrapper">
|
||||
<InfiniteLoader
|
||||
|
||||
@@ -13,6 +13,7 @@ export const ENV = {
|
||||
dsn: windowOrDefault('NX_EXPLORER_SENTRY_DSN'),
|
||||
dataSources: {
|
||||
chainExplorerUrl: windowOrDefault('NX_CHAIN_EXPLORER_URL'),
|
||||
blockExplorerUrl: windowOrDefault('NX_BLOCK_EXPLORER'),
|
||||
tendermintUrl: windowOrDefault('NX_TENDERMINT_URL'),
|
||||
tendermintWebsocketUrl: windowOrDefault('NX_TENDERMINT_WEBSOCKET_URL'),
|
||||
},
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import { getAssets, t } from '@vegaprotocol/react-helpers';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import React from 'react';
|
||||
import { RouteTitle } from '../../components/route-title';
|
||||
import { SubHeading } from '../../components/sub-heading';
|
||||
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import type { AssetsQuery } from './__generated__/AssetsQuery';
|
||||
import type {
|
||||
AssetsQuery,
|
||||
AssetsQuery_assetsConnection_edges_node,
|
||||
} from './__generated__/AssetsQuery';
|
||||
|
||||
export const ASSETS_QUERY = gql`
|
||||
query AssetsQuery {
|
||||
@@ -39,7 +42,10 @@ export const ASSETS_QUERY = gql`
|
||||
const Assets = () => {
|
||||
const { data } = useQuery<AssetsQuery>(ASSETS_QUERY);
|
||||
|
||||
const assets = getAssets(data);
|
||||
const assets =
|
||||
data?.assetsConnection?.edges
|
||||
?.filter((e) => e && e?.node)
|
||||
.map((e) => e?.node as AssetsQuery_assetsConnection_edges_node) || [];
|
||||
|
||||
return (
|
||||
<section>
|
||||
|
||||
@@ -13,7 +13,7 @@ import Genesis from './genesis';
|
||||
import { Block } from './blocks/id';
|
||||
import { Blocks } from './blocks/home';
|
||||
import { Tx } from './txs/id';
|
||||
import { TxsHome, TxsHomeFallback } from './txs/home';
|
||||
import { TxsList } from './txs/home';
|
||||
import { PendingTxs } from './pending';
|
||||
import flags from '../config/flags';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
@@ -141,7 +141,7 @@ const routerConfig = [
|
||||
},
|
||||
{
|
||||
index: true,
|
||||
element: flags.txsList ? <TxsHome /> : <TxsHomeFallback />,
|
||||
element: <TxsList />,
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,86 +1,73 @@
|
||||
import { DATA_SOURCES } from '../../../config';
|
||||
import { useCallback, useState, useMemo } from 'react';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { t, useFetch } from '@vegaprotocol/react-helpers';
|
||||
import { RouteTitle } from '../../../components/route-title';
|
||||
import { BlocksRefetch } from '../../../components/blocks';
|
||||
import { JumpToBlock } from '../../../components/jump-to-block';
|
||||
import { TxsInfiniteList } from '../../../components/txs';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import type { ChainExplorerTxResponse } from '../../types/chain-explorer-response';
|
||||
import type { TendermintBlockchainResponse } from '../../blocks/tendermint-blockchain-response';
|
||||
|
||||
interface TxsProps {
|
||||
latestBlockHeight: string;
|
||||
}
|
||||
import type {
|
||||
BlockExplorerTransaction,
|
||||
BlockExplorerTransactions,
|
||||
} from '../../../routes/types/block-explorer-response';
|
||||
|
||||
interface TxsStateProps {
|
||||
txsData: ChainExplorerTxResponse[];
|
||||
txsData: BlockExplorerTransaction[];
|
||||
hasMoreTxs: boolean;
|
||||
nextPage: number;
|
||||
lastCursor: string;
|
||||
}
|
||||
|
||||
const Txs = ({ latestBlockHeight }: TxsProps) => {
|
||||
const [{ txsData, hasMoreTxs, nextPage }, setTxsState] =
|
||||
const BE_TXS_PER_REQUEST = 100;
|
||||
|
||||
export const TxsList = () => {
|
||||
const [{ txsData, hasMoreTxs, lastCursor }, setTxsState] =
|
||||
useState<TxsStateProps>({
|
||||
txsData: [],
|
||||
hasMoreTxs: true,
|
||||
nextPage: 1,
|
||||
lastCursor: '',
|
||||
});
|
||||
|
||||
const reusedBodyParams = useMemo(
|
||||
() => ({
|
||||
node_url: DATA_SOURCES.tendermintUrl,
|
||||
transaction_height: parseInt(latestBlockHeight),
|
||||
page_size: 30,
|
||||
}),
|
||||
[latestBlockHeight]
|
||||
);
|
||||
|
||||
const {
|
||||
state: { error, loading },
|
||||
state: { data, error, loading },
|
||||
refetch,
|
||||
} = useFetch(
|
||||
DATA_SOURCES.chainExplorerUrl,
|
||||
{
|
||||
method: 'POST',
|
||||
body: JSON.stringify(reusedBodyParams),
|
||||
},
|
||||
} = useFetch<BlockExplorerTransactions>(
|
||||
`${DATA_SOURCES.blockExplorerUrl}/transactions?` +
|
||||
new URLSearchParams({
|
||||
limit: BE_TXS_PER_REQUEST.toString(10),
|
||||
}),
|
||||
{},
|
||||
false
|
||||
);
|
||||
|
||||
const loadTxs = useCallback(async () => {
|
||||
const data = await refetch(
|
||||
undefined,
|
||||
JSON.stringify({
|
||||
...reusedBodyParams,
|
||||
page_number: nextPage,
|
||||
})
|
||||
);
|
||||
|
||||
if (data) {
|
||||
useEffect(() => {
|
||||
if (data?.transactions?.length) {
|
||||
setTxsState((prev) => ({
|
||||
...prev,
|
||||
nextPage: prev.nextPage + 1,
|
||||
txsData: [...prev.txsData, ...data.transactions],
|
||||
hasMoreTxs: true,
|
||||
txsData: [...prev.txsData, ...(data as ChainExplorerTxResponse[])],
|
||||
lastCursor:
|
||||
data.transactions[data.transactions.length - 1].cursor || '',
|
||||
}));
|
||||
}
|
||||
}, [nextPage, refetch, reusedBodyParams]);
|
||||
}, [data?.transactions]);
|
||||
|
||||
const loadTxs = useCallback(() => {
|
||||
return refetch({
|
||||
limit: BE_TXS_PER_REQUEST,
|
||||
before: lastCursor,
|
||||
});
|
||||
}, [lastCursor, refetch]);
|
||||
|
||||
const refreshTxs = useCallback(async () => {
|
||||
setTxsState((prev) => ({
|
||||
...prev,
|
||||
lastCursor: '',
|
||||
hasMoreTxs: true,
|
||||
txsData: [],
|
||||
}));
|
||||
}, [setTxsState]);
|
||||
|
||||
return (
|
||||
<section>
|
||||
<RouteTitle>{t('Transactions')}</RouteTitle>
|
||||
<BlocksRefetch
|
||||
refetch={() =>
|
||||
refetch(
|
||||
undefined,
|
||||
JSON.stringify({
|
||||
...reusedBodyParams,
|
||||
page_number: 1,
|
||||
})
|
||||
)
|
||||
}
|
||||
/>
|
||||
<BlocksRefetch refetch={refreshTxs} />
|
||||
<TxsInfiniteList
|
||||
hasMoreTxs={hasMoreTxs}
|
||||
areTxsLoading={loading}
|
||||
@@ -89,42 +76,6 @@ const Txs = ({ latestBlockHeight }: TxsProps) => {
|
||||
error={error}
|
||||
className="mb-28"
|
||||
/>
|
||||
<JumpToBlock />
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export const TxsHome = () => {
|
||||
const {
|
||||
state: { data, error, loading },
|
||||
} = useFetch<TendermintBlockchainResponse>(
|
||||
`${DATA_SOURCES.tendermintUrl}/blockchain`
|
||||
);
|
||||
|
||||
return (
|
||||
<AsyncRenderer
|
||||
loading={!!loading}
|
||||
loadingMessage={t('Getting latest block height...')}
|
||||
error={error}
|
||||
data={data}
|
||||
noDataMessage={t('Could not get latest block height')}
|
||||
render={(data) => (
|
||||
<Txs
|
||||
latestBlockHeight={
|
||||
data?.result?.block_metas?.[0]?.header?.height || ''
|
||||
}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export const TxsHomeFallback = () => (
|
||||
<>
|
||||
<RouteTitle>{t('Transactions')}</RouteTitle>
|
||||
<div>
|
||||
The transactions list is currently disabled. Please use the search bar to
|
||||
discover transaction data
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
export interface BlockExplorerTransaction {
|
||||
block: string;
|
||||
index: number;
|
||||
hash: string;
|
||||
submitter: string;
|
||||
type: string;
|
||||
code: number;
|
||||
cursor: string;
|
||||
command: Record<string, unknown>;
|
||||
}
|
||||
|
||||
export interface BlockExplorerTransactions {
|
||||
transactions: BlockExplorerTransaction[];
|
||||
}
|
||||
@@ -232,7 +232,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "129999.45",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "101055.803023481857846155",
|
||||
"locked_amount": "99808.964557038223180575",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129999.45",
|
||||
@@ -298,7 +298,7 @@
|
||||
"tranche_end": "2023-09-03T00:00:00.000Z",
|
||||
"total_added": "52600",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "47987.1788178589567",
|
||||
"locked_amount": "47229.74949264333032",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2600",
|
||||
@@ -471,7 +471,7 @@
|
||||
"tranche_end": "2023-09-17T00:00:00.000Z",
|
||||
"total_added": "5000",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "4753.299720953831",
|
||||
"locked_amount": "4681.3007356671745",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "5000",
|
||||
@@ -682,7 +682,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "97499.58",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "42348.530615082211097964",
|
||||
"locked_amount": "41125.4982277578856557894",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "97499.58",
|
||||
@@ -715,7 +715,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "135173.4239508",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "57883.13018201161087005483132",
|
||||
"locked_amount": "56211.456056272351055479479",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "135173.4239508",
|
||||
@@ -748,7 +748,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "32499.86",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "17815.295509758479255574",
|
||||
"locked_amount": "17300.786905050761868906",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "32499.86",
|
||||
@@ -781,7 +781,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "10833.29",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "5798.705812890794772696",
|
||||
"locked_amount": "5631.238254731752483847",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10833.29",
|
||||
@@ -814,7 +814,7 @@
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "22749.93",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "21676.857446138743511523",
|
||||
"locked_amount": "21050.826310536649083198",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "6500",
|
||||
@@ -889,7 +889,7 @@
|
||||
"tranche_end": "2022-11-01T00:00:00.000Z",
|
||||
"total_added": "30000",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "4400.6868961352664",
|
||||
"locked_amount": "3543.74245169082",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -1006,7 +1006,7 @@
|
||||
"tranche_end": "2023-06-02T00:00:00.000Z",
|
||||
"total_added": "1939928.38",
|
||||
"total_removed": "626880.6921411330574",
|
||||
"locked_amount": "1275520.872149814893848934",
|
||||
"locked_amount": "1247586.29717205741791664",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1852091.69",
|
||||
@@ -1303,7 +1303,7 @@
|
||||
"tranche_end": "2023-02-01T00:00:00.000Z",
|
||||
"total_added": "42500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "27484.30643619162825",
|
||||
"locked_amount": "26270.30180656199925",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "12500",
|
||||
@@ -2181,7 +2181,7 @@
|
||||
"tranche_start": "2021-09-05T00:00:00.000Z",
|
||||
"tranche_end": "2022-09-30T00:00:00.000Z",
|
||||
"total_added": "60916.66666633337",
|
||||
"total_removed": "22679.59090768217556896",
|
||||
"total_removed": "22920.80703869967556896",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
@@ -2281,6 +2281,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "241.2161310175",
|
||||
"user": "0x1887D97F9C875108Aa6bE109B282f87A666472f2",
|
||||
"tx": "0xeb4604db9ecd236bfe8a3481989577fd57b942e9900342c23497dedfdf85a0ef"
|
||||
},
|
||||
{
|
||||
"amount": "1983.33333333333",
|
||||
"user": "0xED5847639328EDd38E7CE934442FF4eE8e714f7C",
|
||||
@@ -2989,6 +2994,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "241.2161310175",
|
||||
"user": "0x1887D97F9C875108Aa6bE109B282f87A666472f2",
|
||||
"tranche_id": 13,
|
||||
"tx": "0xeb4604db9ecd236bfe8a3481989577fd57b942e9900342c23497dedfdf85a0ef"
|
||||
},
|
||||
{
|
||||
"amount": "339.9854953025",
|
||||
"user": "0x1887D97F9C875108Aa6bE109B282f87A666472f2",
|
||||
@@ -3075,8 +3086,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "4250",
|
||||
"withdrawn_tokens": "4008.7838689825",
|
||||
"remaining_tokens": "241.2161310175"
|
||||
"withdrawn_tokens": "4250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x9fd50776F133751E8Ae6abE1Be124638Bb917E05",
|
||||
@@ -5940,7 +5951,7 @@
|
||||
"tranche_start": "2021-09-03T00:00:00.000Z",
|
||||
"tranche_end": "2022-09-03T00:00:00.000Z",
|
||||
"total_added": "39600.000000000000000003",
|
||||
"total_removed": "23868.97808024224",
|
||||
"total_removed": "23872.84141180056",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
@@ -12560,6 +12571,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "3.86333155832",
|
||||
"user": "0xC6D7208DaDEe4F431bd0f3f11E7d4c91fF51bfb2",
|
||||
"tx": "0x068081c78445c62a22f68a81cbfd73d1c906b35c31882e5dcbd95b158485b227"
|
||||
},
|
||||
{
|
||||
"amount": "505",
|
||||
"user": "0x2f28F3Be9315cD7F2475F6500020262bd8505fA1",
|
||||
@@ -19110,6 +19126,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "3.86333155832",
|
||||
"user": "0xC6D7208DaDEe4F431bd0f3f11E7d4c91fF51bfb2",
|
||||
"tranche_id": 11,
|
||||
"tx": "0x068081c78445c62a22f68a81cbfd73d1c906b35c31882e5dcbd95b158485b227"
|
||||
},
|
||||
{
|
||||
"amount": "41.64068004762",
|
||||
"user": "0xC6D7208DaDEe4F431bd0f3f11E7d4c91fF51bfb2",
|
||||
@@ -19124,8 +19146,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "104",
|
||||
"withdrawn_tokens": "100.13666844168",
|
||||
"remaining_tokens": "3.86333155832"
|
||||
"withdrawn_tokens": "104",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xd996efF75E43357F04E3f37D61EF6A6851A0b8f1",
|
||||
@@ -24352,8 +24374,8 @@
|
||||
"tranche_start": "2022-03-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "3732368.4671",
|
||||
"total_removed": "212048.9552173080602",
|
||||
"locked_amount": "1984532.81602302279885050992",
|
||||
"total_removed": "216488.8190253099792",
|
||||
"locked_amount": "1941607.10006823176798276368",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1998.95815",
|
||||
@@ -24522,6 +24544,11 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "4439.863808001919",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
"tx": "0x0036b66c9129b9c96b3e456e7958216ed7a9d4e9f2ad548bb8b4e8a036bd70d6"
|
||||
},
|
||||
{
|
||||
"amount": "3087.2670009465625",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
@@ -24696,6 +24723,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "4439.863808001919",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
"tranche_id": 1,
|
||||
"tx": "0x0036b66c9129b9c96b3e456e7958216ed7a9d4e9f2ad548bb8b4e8a036bd70d6"
|
||||
},
|
||||
{
|
||||
"amount": "3087.2670009465625",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
@@ -24782,8 +24815,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "187637.95",
|
||||
"withdrawn_tokens": "84806.4863872416465",
|
||||
"remaining_tokens": "102831.4636127583535"
|
||||
"withdrawn_tokens": "89246.3501952435655",
|
||||
"remaining_tokens": "98391.5998047564345"
|
||||
},
|
||||
{
|
||||
"address": "0x1A71e3ED1996CAbB91bB043f880CE963D601707e",
|
||||
@@ -25264,8 +25297,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "15870102.715470999700000001",
|
||||
"total_removed": "222408.2894258465985744",
|
||||
"locked_amount": "12336713.5320731118005870614596262497620979",
|
||||
"total_removed": "224997.4571492768169494",
|
||||
"locked_amount": "12184501.6993918133532141480489084640578535",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "16249.93",
|
||||
@@ -25769,6 +25802,21 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "243.932422174205",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
"tx": "0x9962e848bcc9ec1ee7db91bafe00948c766bf7184d20f39bfe08539928844213"
|
||||
},
|
||||
{
|
||||
"amount": "981.32183505687375",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xdc3bc277d041e6dff7fb11e0be0a500fadda69ab829b0c6d5caa196031062f40"
|
||||
},
|
||||
{
|
||||
"amount": "432.7384147709755",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xa3998f6f73372f3841256fc23cb4e182545252515cd8d25d5d228d13636b435c"
|
||||
},
|
||||
{
|
||||
"amount": "668.448073601292875",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -25839,6 +25887,16 @@
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x9cf6b1e7e12f0786a9aff09f0379ba8162ea88a8357a8e28c562b618093d0f5f"
|
||||
},
|
||||
{
|
||||
"amount": "501.731430959210375",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x1e91d12aef9afe631095ded8bd5ff6e0a40e5aa87271f46078b3175f41f4ee39"
|
||||
},
|
||||
{
|
||||
"amount": "429.44362046895375",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x10f121ed91c0f605893d86d1eed2ccca505b86c73c89c30e0dfb90edcff637b0"
|
||||
},
|
||||
{
|
||||
"amount": "504.652814859004625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -26512,6 +26570,18 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "981.32183505687375",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0xdc3bc277d041e6dff7fb11e0be0a500fadda69ab829b0c6d5caa196031062f40"
|
||||
},
|
||||
{
|
||||
"amount": "432.7384147709755",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0xa3998f6f73372f3841256fc23cb4e182545252515cd8d25d5d228d13636b435c"
|
||||
},
|
||||
{
|
||||
"amount": "668.448073601292875",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -26572,6 +26642,18 @@
|
||||
"tranche_id": 2,
|
||||
"tx": "0x9cf6b1e7e12f0786a9aff09f0379ba8162ea88a8357a8e28c562b618093d0f5f"
|
||||
},
|
||||
{
|
||||
"amount": "501.731430959210375",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x1e91d12aef9afe631095ded8bd5ff6e0a40e5aa87271f46078b3175f41f4ee39"
|
||||
},
|
||||
{
|
||||
"amount": "429.44362046895375",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x10f121ed91c0f605893d86d1eed2ccca505b86c73c89c30e0dfb90edcff637b0"
|
||||
},
|
||||
{
|
||||
"amount": "504.652814859004625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -27150,8 +27232,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "259998.8875",
|
||||
"withdrawn_tokens": "57731.002552864795",
|
||||
"remaining_tokens": "202267.884947135205"
|
||||
"withdrawn_tokens": "60076.237854120808375",
|
||||
"remaining_tokens": "199922.649645879191625"
|
||||
},
|
||||
{
|
||||
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
|
||||
@@ -28045,6 +28127,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "243.932422174205",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x9962e848bcc9ec1ee7db91bafe00948c766bf7184d20f39bfe08539928844213"
|
||||
},
|
||||
{
|
||||
"amount": "169.6116120463555",
|
||||
"user": "0xE6CacAE56Cca8dFdB7910b5A13578719D4E57DA0",
|
||||
@@ -28119,8 +28207,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "12362.05",
|
||||
"withdrawn_tokens": "2584.0836409459565",
|
||||
"remaining_tokens": "9777.9663590540435"
|
||||
"withdrawn_tokens": "2828.0160631201615",
|
||||
"remaining_tokens": "9534.0339368798385"
|
||||
},
|
||||
{
|
||||
"address": "0xb091D456d0dFCB94dcba6f355379056C5bb995fC",
|
||||
@@ -28744,8 +28832,8 @@
|
||||
"tranche_start": "2021-11-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-05T00:00:00.000Z",
|
||||
"total_added": "14597706.0446472999",
|
||||
"total_removed": "2923085.955595204497185312",
|
||||
"locked_amount": "5667729.935859967841691532439599905",
|
||||
"total_removed": "2926333.340895590665080812",
|
||||
"locked_amount": "5527208.943810320731141048979540034",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129284.449",
|
||||
@@ -28954,6 +29042,16 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "1360.2331260920135955",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x8c5fe9e7c9b1ff5e11cd044869b4d43b06512d8a8037c945315e44b2829b49d8"
|
||||
},
|
||||
{
|
||||
"amount": "598.630467392367358",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0xfccb647f645ad7c56c3f73a6b92b19dcad5100cf5dbbaf8a885793d353053f08"
|
||||
},
|
||||
{
|
||||
"amount": "927.5894688774561055",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@@ -29024,6 +29122,16 @@
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0xb45a95262772c307dd2f75b2cba4d5e7d12968b5a04a7ca6c59f5c99ab54815a"
|
||||
},
|
||||
{
|
||||
"amount": "690.53070553304891625",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x16096cd1bc7539778177c7db0fcda97d0085a63b13ebd3a751648337b698d8aa"
|
||||
},
|
||||
{
|
||||
"amount": "597.99100136873802575",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tx": "0x6fdfd3c077574cd9b9ede40db9488759ceac7d430e6ad09fdbd5a64bd87ce8b3"
|
||||
},
|
||||
{
|
||||
"amount": "700.967684681521309",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@@ -31195,6 +31303,18 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "1360.2331260920135955",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x8c5fe9e7c9b1ff5e11cd044869b4d43b06512d8a8037c945315e44b2829b49d8"
|
||||
},
|
||||
{
|
||||
"amount": "598.630467392367358",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0xfccb647f645ad7c56c3f73a6b92b19dcad5100cf5dbbaf8a885793d353053f08"
|
||||
},
|
||||
{
|
||||
"amount": "927.5894688774561055",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@@ -31255,6 +31375,18 @@
|
||||
"tranche_id": 3,
|
||||
"tx": "0xb45a95262772c307dd2f75b2cba4d5e7d12968b5a04a7ca6c59f5c99ab54815a"
|
||||
},
|
||||
{
|
||||
"amount": "690.53070553304891625",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x16096cd1bc7539778177c7db0fcda97d0085a63b13ebd3a751648337b698d8aa"
|
||||
},
|
||||
{
|
||||
"amount": "597.99100136873802575",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x6fdfd3c077574cd9b9ede40db9488759ceac7d430e6ad09fdbd5a64bd87ce8b3"
|
||||
},
|
||||
{
|
||||
"amount": "700.967684681521309",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@@ -33111,8 +33243,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "359123.469575",
|
||||
"withdrawn_tokens": "219475.84527111689429425",
|
||||
"remaining_tokens": "139647.62430388310570575"
|
||||
"withdrawn_tokens": "222723.23057150306218975",
|
||||
"remaining_tokens": "136400.23900349693781025"
|
||||
},
|
||||
{
|
||||
"address": "0xBdd412797c1B78535Afc5F71503b91fAbD0160fB",
|
||||
@@ -34223,8 +34355,8 @@
|
||||
"tranche_start": "2021-10-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "5778205.3912159303",
|
||||
"total_removed": "1859061.122194459692887301",
|
||||
"locked_amount": "1922450.97226335538560662121602032",
|
||||
"total_removed": "1873909.449655528970703801",
|
||||
"locked_amount": "1866930.278440655586530334992507438",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "552496.6455",
|
||||
@@ -34368,6 +34500,16 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "14848.19419062596735675",
|
||||
"user": "0x9058e12e2F32cB1cD4D3123359963D77786477FC",
|
||||
"tx": "0x51d2a4b9c2db0dc6c34ee296e468d44d074a1debd4271d66cb1eeb1cc449860f"
|
||||
},
|
||||
{
|
||||
"amount": "0.13327044331045975",
|
||||
"user": "0x9058e12e2F32cB1cD4D3123359963D77786477FC",
|
||||
"tx": "0x31bcddc1d9f267c2337fba36d44e2282388183e2608a7781fedeaa7abb002482"
|
||||
},
|
||||
{
|
||||
"amount": "4240.023826533383217",
|
||||
"user": "0xafa64cCa337eFEE0AD827F6C2684e69275226e90",
|
||||
@@ -35030,6 +35172,18 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "14848.19419062596735675",
|
||||
"user": "0x9058e12e2F32cB1cD4D3123359963D77786477FC",
|
||||
"tranche_id": 4,
|
||||
"tx": "0x51d2a4b9c2db0dc6c34ee296e468d44d074a1debd4271d66cb1eeb1cc449860f"
|
||||
},
|
||||
{
|
||||
"amount": "0.13327044331045975",
|
||||
"user": "0x9058e12e2F32cB1cD4D3123359963D77786477FC",
|
||||
"tranche_id": 4,
|
||||
"tx": "0x31bcddc1d9f267c2337fba36d44e2282388183e2608a7781fedeaa7abb002482"
|
||||
},
|
||||
{
|
||||
"amount": "2155.49461457390087475",
|
||||
"user": "0x9058e12e2F32cB1cD4D3123359963D77786477FC",
|
||||
@@ -35044,8 +35198,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "27624.882275",
|
||||
"withdrawn_tokens": "3835.43954817344395075",
|
||||
"remaining_tokens": "23789.44272682655604925"
|
||||
"withdrawn_tokens": "18683.76700924272176725",
|
||||
"remaining_tokens": "8941.11526575727823275"
|
||||
},
|
||||
{
|
||||
"address": "0xBc934494675a6ceB639B9EfEe5b9C0f017D35a75",
|
||||
@@ -35753,8 +35907,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "472355.6199999996",
|
||||
"total_removed": "4160.13945227826",
|
||||
"locked_amount": "314460.5687720519725132450634196",
|
||||
"total_removed": "4675.66485244886",
|
||||
"locked_amount": "307658.74370516207651625788635212",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "3000",
|
||||
@@ -42373,6 +42527,16 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "95.248756976",
|
||||
"user": "0xA17b91BdDcE741528fDDF8E5738A767B3053ac18",
|
||||
"tx": "0xad37bdd4cbd855be571f4fd5157688a34b1e9f9f90f93f9460e5123ca221a319"
|
||||
},
|
||||
{
|
||||
"amount": "48.7169590306",
|
||||
"user": "0xB168ce7397Dc52ed13B4eD8119f309ec30DDa2c9",
|
||||
"tx": "0xdca459e274a6629dbb7e9a0874f254b1c8970d73e46ceb42432a70e1690e4227"
|
||||
},
|
||||
{
|
||||
"amount": "65.770370368",
|
||||
"user": "0x7708B79e2bc3b7ab816E66aF33A8c9385f0FcA4b",
|
||||
@@ -42408,6 +42572,31 @@
|
||||
"user": "0xA0beaa6EC671f4cC8B6D6cA52C46D6c252F525a8",
|
||||
"tx": "0x026f716e8e3cc425aaa9a78b34a685f788d52a14d843dc2ed2430a400194b1ac"
|
||||
},
|
||||
{
|
||||
"amount": "24.760013952",
|
||||
"user": "0x4d4AA3f302cbA998AAFC03F9d73484434ed9Fd53",
|
||||
"tx": "0x6137b5d86d1038fbad53e50bb0d1f76dbd67a4fef4c2bf9176608c4d1e15ebbe"
|
||||
},
|
||||
{
|
||||
"amount": "13.344748856",
|
||||
"user": "0x4eD2b3c68BB4fda084ce1591a210F4aC8b71234A",
|
||||
"tx": "0x1ce993074ad983b356da0559cd03cde2632665ec9cddaf20ba384fc325cbde60"
|
||||
},
|
||||
{
|
||||
"amount": "135.474264332",
|
||||
"user": "0xe28dBf57Ad23cc0c32b6769556CD3c64873b4330",
|
||||
"tx": "0xc706b9ab1e410b4de90f3969faeec3b7bd71de1c3d1de4eb9ccda0b8be02d1a9"
|
||||
},
|
||||
{
|
||||
"amount": "61.83652968",
|
||||
"user": "0x7345AaA0D0e4C4A46d921fA9323973956F2b7392",
|
||||
"tx": "0xc79c54283a3bdd5944f0098641f9537a62c433718a4c391f01684255155ef9d2"
|
||||
},
|
||||
{
|
||||
"amount": "136.144127344",
|
||||
"user": "0xb1EAD214506D0cD73785Dd09B3EfC2307133bf69",
|
||||
"tx": "0xe563eb4f77cb43e4eeb099bf3d7134e54f2a2d046d77785570afa2869bc0f997"
|
||||
},
|
||||
{
|
||||
"amount": "52.731139014",
|
||||
"user": "0x28FC83947F02f59Cb36b40f97f2D32BBC5D00585",
|
||||
@@ -49885,6 +50074,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "95.248756976",
|
||||
"user": "0xA17b91BdDcE741528fDDF8E5738A767B3053ac18",
|
||||
"tranche_id": 5,
|
||||
"tx": "0xad37bdd4cbd855be571f4fd5157688a34b1e9f9f90f93f9460e5123ca221a319"
|
||||
},
|
||||
{
|
||||
"amount": "42.526268388",
|
||||
"user": "0xA17b91BdDcE741528fDDF8E5738A767B3053ac18",
|
||||
@@ -49893,8 +50088,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "42.526268388",
|
||||
"remaining_tokens": "357.473731612"
|
||||
"withdrawn_tokens": "137.775025364",
|
||||
"remaining_tokens": "262.224974636"
|
||||
},
|
||||
{
|
||||
"address": "0x8CF85d1ecC6eDd70000c57E31ff8FC18633F7328",
|
||||
@@ -50888,10 +51083,17 @@
|
||||
"tx": "0x96a22c369645e8945b4047374a05332f4054b50a492c43092e8bb8e974a006b9"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "48.7169590306",
|
||||
"user": "0xB168ce7397Dc52ed13B4eD8119f309ec30DDa2c9",
|
||||
"tranche_id": 5,
|
||||
"tx": "0xdca459e274a6629dbb7e9a0874f254b1c8970d73e46ceb42432a70e1690e4227"
|
||||
}
|
||||
],
|
||||
"total_tokens": "140",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "140"
|
||||
"withdrawn_tokens": "48.7169590306",
|
||||
"remaining_tokens": "91.2830409694"
|
||||
},
|
||||
{
|
||||
"address": "0xdD37b0ff9aE7e2EDbABdc291e8d44431084dA4c2",
|
||||
@@ -54673,6 +54875,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "13.344748856",
|
||||
"user": "0x4eD2b3c68BB4fda084ce1591a210F4aC8b71234A",
|
||||
"tranche_id": 5,
|
||||
"tx": "0x1ce993074ad983b356da0559cd03cde2632665ec9cddaf20ba384fc325cbde60"
|
||||
},
|
||||
{
|
||||
"amount": "26.406887368",
|
||||
"user": "0x4eD2b3c68BB4fda084ce1591a210F4aC8b71234A",
|
||||
@@ -54705,8 +54913,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "121.366349568",
|
||||
"remaining_tokens": "278.633650432"
|
||||
"withdrawn_tokens": "134.711098424",
|
||||
"remaining_tokens": "265.288901576"
|
||||
},
|
||||
{
|
||||
"address": "0x5c90765F50629570738fEe7b7FA82ae118f81Ed1",
|
||||
@@ -56226,10 +56434,17 @@
|
||||
"tx": "0xe32a466fc780a0fb3fd84a804f622931ebfaf3f428bff0dc6d141270410e75f8"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "136.144127344",
|
||||
"user": "0xb1EAD214506D0cD73785Dd09B3EfC2307133bf69",
|
||||
"tranche_id": 5,
|
||||
"tx": "0xe563eb4f77cb43e4eeb099bf3d7134e54f2a2d046d77785570afa2869bc0f997"
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "400"
|
||||
"withdrawn_tokens": "136.144127344",
|
||||
"remaining_tokens": "263.855872656"
|
||||
},
|
||||
{
|
||||
"address": "0xDcD1000CB62FAE013aEd379d9F1287D828bcEaA3",
|
||||
@@ -56725,10 +56940,17 @@
|
||||
"tx": "0xb1425d9b0d5f10c5b06236d6f9d61ebddd21c4027e0f41deb5ec227a1753c715"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "135.474264332",
|
||||
"user": "0xe28dBf57Ad23cc0c32b6769556CD3c64873b4330",
|
||||
"tranche_id": 5,
|
||||
"tx": "0xc706b9ab1e410b4de90f3969faeec3b7bd71de1c3d1de4eb9ccda0b8be02d1a9"
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "400"
|
||||
"withdrawn_tokens": "135.474264332",
|
||||
"remaining_tokens": "264.525735668"
|
||||
},
|
||||
{
|
||||
"address": "0xff2D0F83b812bfbFe5aafca081140C59f67d5fd3",
|
||||
@@ -58600,6 +58822,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "61.83652968",
|
||||
"user": "0x7345AaA0D0e4C4A46d921fA9323973956F2b7392",
|
||||
"tranche_id": 5,
|
||||
"tx": "0xc79c54283a3bdd5944f0098641f9537a62c433718a4c391f01684255155ef9d2"
|
||||
},
|
||||
{
|
||||
"amount": "201.207077628",
|
||||
"user": "0x7345AaA0D0e4C4A46d921fA9323973956F2b7392",
|
||||
@@ -58614,8 +58842,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "1200",
|
||||
"withdrawn_tokens": "344.995395732",
|
||||
"remaining_tokens": "855.004604268"
|
||||
"withdrawn_tokens": "406.831925412",
|
||||
"remaining_tokens": "793.168074588"
|
||||
},
|
||||
{
|
||||
"address": "0x47181cf36aDFb0b5dB7EfDB123f403D890607841",
|
||||
@@ -61660,6 +61888,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "24.760013952",
|
||||
"user": "0x4d4AA3f302cbA998AAFC03F9d73484434ed9Fd53",
|
||||
"tranche_id": 5,
|
||||
"tx": "0x6137b5d86d1038fbad53e50bb0d1f76dbd67a4fef4c2bf9176608c4d1e15ebbe"
|
||||
},
|
||||
{
|
||||
"amount": "14.663413242",
|
||||
"user": "0x4d4AA3f302cbA998AAFC03F9d73484434ed9Fd53",
|
||||
@@ -61674,8 +61908,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "200",
|
||||
"withdrawn_tokens": "42.270268898",
|
||||
"remaining_tokens": "157.729731102"
|
||||
"withdrawn_tokens": "67.03028285",
|
||||
"remaining_tokens": "132.96971715"
|
||||
},
|
||||
{
|
||||
"address": "0xd9390b46a1749DEe5325A490490491db9a826D1F",
|
||||
|
||||
@@ -40,6 +40,9 @@ module.exports = defineConfig({
|
||||
vegaWalletPublicKey:
|
||||
'02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65',
|
||||
vegaWalletPublicKeyShort: '02ecea…2f65',
|
||||
vegaWalletPublicKey2:
|
||||
'7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535',
|
||||
vegaWalletPublicKey2Short: '7f9cf0…5535',
|
||||
vegaTokenContractAddress: '0xF41bD86d462D36b997C0bbb4D97a0a3382f205B7',
|
||||
vegaTokenAddress: '0x67175Da1D5e966e40D11c4B2519392B2058373de',
|
||||
txTimeout: { timeout: 70000 },
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"changes": {
|
||||
"name": "USDT Coin",
|
||||
"symbol": "USDT",
|
||||
"decimals": "18",
|
||||
"quantum": "1",
|
||||
"erc20": {
|
||||
"contractAddress": "0xb404c51bbc10dcbe948077f18a4b8e553d160084",
|
||||
"withdrawThreshold": "10",
|
||||
"lifetimeLimit": "10"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
{
|
||||
"changes": {
|
||||
"decimalPlaces": "5",
|
||||
"positionDecimalPlaces": "5",
|
||||
"instrument": {
|
||||
"name": "Oranges Daily",
|
||||
"code": "ORANGES.24h",
|
||||
"future": {
|
||||
"settlementAsset": "8b52d4a3a4b0ffe733cddbc2b67be273816cfeb6ca4c8b339bac03ffba08e4e4",
|
||||
"quoteName": "tEuro",
|
||||
"settlementDataDecimals": 5,
|
||||
"oracleSpecForSettlementPrice": {
|
||||
"pubKeys": ["0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC"],
|
||||
"filters": [
|
||||
{
|
||||
"key": {
|
||||
"name": "prices.BTC.value",
|
||||
"type": "TYPE_INTEGER"
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"operator": "OPERATOR_GREATER_THAN",
|
||||
"value": "0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"oracleSpecForTradingTermination": {
|
||||
"pubKeys": ["0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC"],
|
||||
"filters": [
|
||||
{
|
||||
"key": {
|
||||
"name": "vegaprotocol.builtin.timestamp",
|
||||
"type": "TYPE_TIMESTAMP"
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"operator": "OPERATOR_GREATER_THAN_OR_EQUAL",
|
||||
"value": "1648684800000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"oracleSpecBinding": {
|
||||
"settlementPriceProperty": "prices.BTC.value",
|
||||
"tradingTerminationProperty": "vegaprotocol.builtin.timestamp"
|
||||
}
|
||||
}
|
||||
},
|
||||
"metadata": ["sector:food", "sector:materials", "source:docs.vega.xyz"],
|
||||
"priceMonitoringParameters": {
|
||||
"triggers": [
|
||||
{
|
||||
"horizon": "43200",
|
||||
"probability": "0.9999999",
|
||||
"auctionExtension": "600"
|
||||
}
|
||||
]
|
||||
},
|
||||
"liquidityMonitoringParameters": {
|
||||
"targetStakeParameters": {
|
||||
"timeWindow": "3600",
|
||||
"scalingFactor": 10
|
||||
},
|
||||
"triggeringRatio": 0.7,
|
||||
"auctionExtension": "1"
|
||||
},
|
||||
"logNormal": {
|
||||
"tau": 0.0001140771161,
|
||||
"riskAversionParameter": 0.001,
|
||||
"params": {
|
||||
"mu": 0,
|
||||
"r": 0.016,
|
||||
"sigma": 0.8
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"rationale": {
|
||||
"title": "An example freeform proposal with unique number of: ",
|
||||
"title": "An example raw proposal with unique number of: ",
|
||||
"description": "I propose that everyone evaluate the following IPFS document and vote Yes if they agree. [bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si](https://dweb.link/ipfs/bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si)"
|
||||
},
|
||||
"terms": {
|
||||
@@ -0,0 +1,69 @@
|
||||
{
|
||||
"marketId": "315a8e48db0a292c92b617264728048c82c20efc922c75fd292fc54e5c727c81",
|
||||
"changes": {
|
||||
"instrument": {
|
||||
"code": "ORANGES.24h",
|
||||
"future": {
|
||||
"quoteName": "tEuro",
|
||||
"settlementDataDecimals": 5,
|
||||
"oracleSpecForSettlementPrice": {
|
||||
"pubKeys": ["0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC"],
|
||||
"filters": [
|
||||
{
|
||||
"key": {
|
||||
"name": "prices.BTC.value",
|
||||
"type": "TYPE_INTEGER"
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"operator": "OPERATOR_GREATER_THAN",
|
||||
"value": "0"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"oracleSpecForTradingTermination": {
|
||||
"pubKeys": ["0xfCEAdAFab14d46e20144F48824d0C09B1a03F2BC"],
|
||||
"filters": [
|
||||
{
|
||||
"key": {
|
||||
"name": "vegaprotocol.builtin.timestamp",
|
||||
"type": "TYPE_TIMESTAMP"
|
||||
},
|
||||
"conditions": [
|
||||
{
|
||||
"operator": "OPERATOR_GREATER_THAN_OR_EQUAL",
|
||||
"value": "1648684800000000000"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"oracleSpecBinding": {
|
||||
"settlementPriceProperty": "prices.BTC.value",
|
||||
"tradingTerminationProperty": "vegaprotocol.builtin.timestamp"
|
||||
}
|
||||
}
|
||||
},
|
||||
"metadata": ["sector:energy", "sector:food", "source:docs.vega.xyz"],
|
||||
"priceMonitoringParameters": {
|
||||
"triggers": [
|
||||
{
|
||||
"horizon": "43200",
|
||||
"probability": "0.9999999",
|
||||
"auctionExtension": "600"
|
||||
}
|
||||
]
|
||||
},
|
||||
"logNormal": {
|
||||
"tau": 0.0001140771161,
|
||||
"riskAversionParameter": 0.001,
|
||||
"params": {
|
||||
"mu": 0,
|
||||
"r": 0.016,
|
||||
"sigma": 0.3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
/// <reference types="cypress" />
|
||||
|
||||
const vegaWalletUnstakedBalance =
|
||||
'[data-testid="vega-wallet-balance-unstaked"]';
|
||||
const vegaWalletStakedBalances =
|
||||
@@ -28,16 +27,20 @@ const changeVoteButton = '[data-testid="change-vote-button"]';
|
||||
const proposalDetailsTitle = '[data-testid="proposal-title"]';
|
||||
const proposalDetailsDescription = '[data-testid="proposal-description"]';
|
||||
const proposalVoteDeadline = '[data-testid="proposal-vote-deadline"]';
|
||||
const minVoteButton = '[data-testid="min-vote"]';
|
||||
const maxVoteButton = '[data-testid="max-vote"]';
|
||||
const voteButtons = '[data-testid="vote-buttons"]';
|
||||
const votingDate = '[data-testid="voting-date"]';
|
||||
const voteTwoMinExtraNote = '[data-testid="voting-2-mins-extra"]';
|
||||
const voteStatus = '[data-testid="vote-status"]';
|
||||
const rejectProposalsLink = '[href="/governance/rejected"]';
|
||||
const feedbackError = '[data-testid="Error"]';
|
||||
const txTimeout = Cypress.env('txTimeout');
|
||||
const epochTimeout = Cypress.env('epochTimeout');
|
||||
const proposalTimeout = { timeout: 14000 };
|
||||
const restConnectorForm = '[data-testid="rest-connector-form"]';
|
||||
const noOpenProposals = '[data-testid="no-open-proposals"]';
|
||||
const noClosedProposals = '[data-testid="no-closed-proposals"]';
|
||||
const txTimeout = Cypress.env('txTimeout');
|
||||
const epochTimeout = Cypress.env('epochTimeout');
|
||||
const proposalTimeout = { timeout: 14000 };
|
||||
|
||||
const governanceProposalType = {
|
||||
NETWORK_PARAMETER: 'Network parameter',
|
||||
@@ -45,6 +48,7 @@ const governanceProposalType = {
|
||||
UPDATE_MARKET: 'Update market',
|
||||
NEW_ASSET: 'New asset',
|
||||
FREEFORM: 'Freeform',
|
||||
RAW: 'raw proposal',
|
||||
};
|
||||
|
||||
context(
|
||||
@@ -142,7 +146,7 @@ context(
|
||||
});
|
||||
});
|
||||
|
||||
it('should be able to see that no proposals exist', function () {
|
||||
it('Should be able to see that no proposals exist', function () {
|
||||
// 1004-VOTE-003
|
||||
cy.get(noOpenProposals)
|
||||
.should('be.visible')
|
||||
@@ -152,13 +156,17 @@ context(
|
||||
.and('have.text', 'There are no enacted or rejected proposals');
|
||||
});
|
||||
|
||||
// 1005-PROP-002
|
||||
// 1005-PROP-003
|
||||
it('Submit a proposal form - shows how many vega tokens are required to make a proposal', function () {
|
||||
// 1005-PROP-005
|
||||
cy.go_to_make_new_proposal(governanceProposalType.NEW_MARKET);
|
||||
cy.contains(
|
||||
`You must have at least ${this.minProposerBalance} VEGA associated to make a proposal`
|
||||
).should('be.visible');
|
||||
});
|
||||
|
||||
// 1005-PROP-011
|
||||
it(
|
||||
'Able to submit a valid freeform proposal - with minimum required tokens associated',
|
||||
{ tags: '@smoke' },
|
||||
@@ -166,20 +174,19 @@ context(
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.get(minVoteButton).should('be.visible'); // 1005-PROP-008
|
||||
cy.get(maxVoteButton).should('be.visible');
|
||||
cy.get(votingDate).should('not.be.empty');
|
||||
cy.get(voteTwoMinExtraNote).should(
|
||||
'contain.text',
|
||||
'we add 2 minutes of extra time'
|
||||
);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Confirm transaction in wallet', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.get(dialogCloseButton).click();
|
||||
// 1005-PROP-012
|
||||
// 1005-PROP-016
|
||||
cy.wait_for_proposal_submitted();
|
||||
}
|
||||
);
|
||||
|
||||
@@ -190,8 +197,7 @@ context(
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
|
||||
'contain',
|
||||
this.minProposerBalance,
|
||||
txTimeout
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to('staking');
|
||||
cy.wait_for_spinner();
|
||||
@@ -200,63 +206,19 @@ context(
|
||||
|
||||
cy.get(vegaWalletStakedBalances, txTimeout).should(
|
||||
'contain',
|
||||
this.minProposerBalance,
|
||||
txTimeout
|
||||
);
|
||||
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
});
|
||||
|
||||
it('Newly created freeform proposals list - able to filter by proposalID to show it in list', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
cy.wait('@proposalSubmissionCompletion')
|
||||
.its(proposalResponseProposalIdPath)
|
||||
.then((proposalId) => {
|
||||
cy.get('[data-testid="set-proposals-filter-visible"]').click();
|
||||
cy.get('[data-testid="filter-input"]').type(proposalId);
|
||||
cy.get(`#${proposalId}`).should('contain', proposalId);
|
||||
});
|
||||
cy.wait_for_proposal_submitted();
|
||||
});
|
||||
|
||||
it('Newly created freeform proposals list - able to filter by proposerID to show it in list', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
it('Newly created proposals list - able to filter by proposerID to show it in list', function () {
|
||||
createFreeformProposal(this.minProposerBalance);
|
||||
cy.wait('@proposalSubmissionCompletion').then((proposal) => {
|
||||
let proposerId = proposal.request.body.variables.partyId;
|
||||
let proposalId = proposal.response.body.data.busEvents[0].event.id;
|
||||
@@ -266,36 +228,22 @@ context(
|
||||
});
|
||||
});
|
||||
|
||||
it('Newly created freeform proposals list - shows title and portion of summary', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50').as('freeformProposal');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
it('Newly created proposals list - shows title and portion of summary', function () {
|
||||
createRawProposal(this.minProposerBalance);
|
||||
cy.wait('@proposalSubmissionCompletion')
|
||||
.its(proposalResponseProposalIdPath)
|
||||
.then((proposalId) => {
|
||||
cy.get(openProposals).within(() => {
|
||||
cy.get('@freeformProposal').then((freeformProposal) => {
|
||||
cy.get('@rawProposal').then((rawProposal) => {
|
||||
// 1004-VOTE-008
|
||||
// 1004-VOTE-034
|
||||
cy.get(`#${proposalId}`)
|
||||
.should('contain', freeformProposal.rationale.title)
|
||||
.should('contain', rawProposal.rationale.title)
|
||||
.and('be.visible');
|
||||
cy.get(`#${proposalId}`)
|
||||
.should(
|
||||
'contain',
|
||||
freeformProposal.rationale.description.substring(0, 59)
|
||||
rawProposal.rationale.description.substring(0, 59)
|
||||
)
|
||||
.and('be.visible');
|
||||
});
|
||||
@@ -303,70 +251,63 @@ context(
|
||||
});
|
||||
});
|
||||
|
||||
it('Newly created freeform proposals list - shows open proposals in an open state', function () {
|
||||
it('Newly created proposals list - shows open proposals in an open state', function () {
|
||||
// 1004-VOTE-004
|
||||
// 1004-VOTE-035
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
createRawProposal(this.minProposerBalance);
|
||||
cy.wait('@proposalSubmissionCompletion')
|
||||
.its(proposalResponseProposalIdPath)
|
||||
.then((proposalId) => {
|
||||
cy.get(openProposals).within(() => {
|
||||
// 1004-VOTE-035
|
||||
cy.get(`#${proposalId}`)
|
||||
.should('contain', proposalId)
|
||||
.and('contain', 'Open')
|
||||
.and('be.visible');
|
||||
cy.get(`#${proposalId}`).within(() => {
|
||||
cy.get(viewProposalButton).should('be.visible').click();
|
||||
});
|
||||
});
|
||||
cy.get_proposal_information_from_table('ID')
|
||||
.contains(proposalId)
|
||||
.and('be.visible');
|
||||
cy.get_proposal_information_from_table('State')
|
||||
.contains('STATE_OPEN')
|
||||
.and('be.visible');
|
||||
cy.get_proposal_information_from_table('Type')
|
||||
.contains('NewFreeform')
|
||||
.and('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
it('Newly created freeform proposals list - proposals closest to closing date appear higher in list', function () {
|
||||
it('Newly created proposals list - proposals closest to closing date appear higher in list', function () {
|
||||
// 1004-VOTE-005
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
).then(() => {
|
||||
let proposalHours = [
|
||||
(Number(this.minCloseHours) + 1).toString(),
|
||||
this.maxCloseHours,
|
||||
(Number(this.minCloseHours) + 3).toString(),
|
||||
(Number(this.minCloseHours) + 2).toString(),
|
||||
];
|
||||
for (var index = 0; index < proposalHours.length; index++) {
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body(proposalHours[index]);
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
}
|
||||
});
|
||||
// Ensuring that proposals are not posted in same order as sort order
|
||||
);
|
||||
let proposalDays = [
|
||||
this.minCloseDays + 1,
|
||||
this.maxCloseDays,
|
||||
this.minCloseDays + 3,
|
||||
this.minCloseDays + 2,
|
||||
];
|
||||
for (var index = 0; index < proposalDays.length; index++) {
|
||||
cy.go_to_make_new_proposal(governanceProposalType.RAW);
|
||||
cy.create_ten_digit_unix_timestamp_for_specified_days(
|
||||
proposalDays[index]
|
||||
).then((closingDateTimestamp) => {
|
||||
cy.enter_raw_proposal_body(closingDateTimestamp);
|
||||
});
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
}
|
||||
|
||||
let arrayOfProposals = [];
|
||||
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
|
||||
cy.get(proposalDetailsTitle)
|
||||
.each((proposalTitleElement) => {
|
||||
arrayOfProposals.push(proposalTitleElement.text());
|
||||
@@ -380,22 +321,8 @@ context(
|
||||
});
|
||||
|
||||
// Skipping test due to bug: #1320
|
||||
it.skip('Newly created freeform proposals list - shows proposal parcipitation - both met and not', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
it.skip('Newly created freeform proposals list - shows proposal participation - both met and not', function () {
|
||||
createFreeformProposal(this.minProposerBalance);
|
||||
cy.get_submitted_proposal_from_proposal_list()
|
||||
.as('submittedProposal')
|
||||
.within(() => {
|
||||
@@ -430,20 +357,7 @@ context(
|
||||
|
||||
// Skipping test due to bug - should be solved when #1223 released
|
||||
it.skip('Newly created freeform proposal details - shows proposal title and full description', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50').as('freeformProposal');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
createRawProposal(this.minProposerBalance);
|
||||
cy.wait('@proposalSubmissionCompletion')
|
||||
.its(proposalResponseProposalIdPath)
|
||||
.then((proposalId) => {
|
||||
@@ -452,7 +366,7 @@ context(
|
||||
cy.get(viewProposalButton).should('be.visible').click();
|
||||
});
|
||||
});
|
||||
cy.get('@freeformProposal').then((freeformProposal) => {
|
||||
cy.get('@rawProposal').then((freeformProposal) => {
|
||||
// 1004-VOTE-054
|
||||
cy.get(proposalDetailsTitle)
|
||||
.should('contain', freeformProposal.rationale.title)
|
||||
@@ -464,23 +378,10 @@ context(
|
||||
});
|
||||
});
|
||||
|
||||
// 1005-todo-PROP-019
|
||||
// Skipping test due to bug - should be solved when #1223 released
|
||||
it.skip('Newly created freeform proposal details - shows full link included in description', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50').as('freeformProposal');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
it.skip('Newly created raw proposal details - shows full link included in description', function () {
|
||||
createRawProposal(this.minProposerBalance);
|
||||
cy.wait('@proposalSubmissionCompletion')
|
||||
.its(proposalResponseProposalIdPath)
|
||||
.then((proposalId) => {
|
||||
@@ -489,7 +390,7 @@ context(
|
||||
cy.get(viewProposalButton).should('be.visible').click();
|
||||
});
|
||||
});
|
||||
cy.get('@freeformProposal').then(() => {
|
||||
cy.get('@rawProposal').then(() => {
|
||||
// 1004-VOTE-055
|
||||
cy.get(proposalDetailsDescription)
|
||||
.should('have.attr', 'href')
|
||||
@@ -502,61 +403,18 @@ context(
|
||||
});
|
||||
});
|
||||
|
||||
it('Newly created freeform proposal details - shows open proposal in an open state', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
cy.wait('@proposalSubmissionCompletion')
|
||||
.its(proposalResponseProposalIdPath)
|
||||
.then((proposalId) => {
|
||||
cy.get(openProposals).within(() => {
|
||||
cy.get(`#${proposalId}`).within(() => {
|
||||
cy.get(viewProposalButton).should('be.visible').click();
|
||||
});
|
||||
});
|
||||
cy.get_proposal_information_from_table('ID')
|
||||
.contains(proposalId)
|
||||
.and('be.visible');
|
||||
cy.get_proposal_information_from_table('State')
|
||||
.contains('STATE_OPEN')
|
||||
.and('be.visible');
|
||||
cy.get_proposal_information_from_table('Type')
|
||||
.contains('NewFreeform')
|
||||
.and('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
it('Newly created freeform proposal details - shows proposed and closing dates', function () {
|
||||
const closingVoteHrs = '72';
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.create_ten_digit_unix_timestamp_for_specified_days('3').then(
|
||||
(closingDateTimestamp) => {
|
||||
cy.enter_unique_freeform_proposal_body(closingVoteHrs);
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_submitted();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
@@ -583,24 +441,10 @@ context(
|
||||
cy.contains('3 days left to vote').should('be.visible');
|
||||
});
|
||||
|
||||
it('Newly created freeform proposal details - shows default status set to fail', function () {
|
||||
it('Newly created proposal details - shows default status set to fail', function () {
|
||||
// 1004-VOTE-037
|
||||
// 1004-VOTE-040
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
createRawProposal(this.minProposerBalance);
|
||||
cy.get_submitted_proposal_from_proposal_list().within(() =>
|
||||
cy.get(viewProposalButton).click()
|
||||
);
|
||||
@@ -621,22 +465,8 @@ context(
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
it('Newly created freeform proposal details - ability to vote for proposal - with minimum required tokens associated', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () {
|
||||
createRawProposal(this.minProposerBalance);
|
||||
cy.get_submitted_proposal_from_proposal_list()
|
||||
.as('submittedProposal')
|
||||
.within(() => cy.get(viewProposalButton).click());
|
||||
@@ -686,191 +516,28 @@ context(
|
||||
cy.get_proposal_information_from_table('Number of voting parties')
|
||||
.should('have.text', '1')
|
||||
.and('be.visible');
|
||||
});
|
||||
|
||||
it('Newly created freeform proposal details - ability to vote against proposal - with minimum required tokens associated', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
cy.get_submitted_proposal_from_proposal_list()
|
||||
.as('submittedProposal')
|
||||
.within(() => cy.get(viewProposalButton).click());
|
||||
cy.vote_for_proposal('against');
|
||||
cy.get_governance_proposal_date_format_for_specified_days(
|
||||
'0',
|
||||
'shortMonth'
|
||||
).then((votedDate) => {
|
||||
// 1004-VOTE-051
|
||||
cy.contains('You voted:')
|
||||
.siblings()
|
||||
.contains('Against')
|
||||
.siblings()
|
||||
.contains(votedDate)
|
||||
.should('be.visible');
|
||||
});
|
||||
cy.get(proposalVoteProgressForPercentage)
|
||||
.contains('0.00%')
|
||||
.and('be.visible');
|
||||
cy.get(proposalVoteProgressAgainstPercentage)
|
||||
.contains('100.00%')
|
||||
.and('be.visible');
|
||||
cy.get(proposalVoteProgressForTokens)
|
||||
.contains('0.00')
|
||||
.and('be.visible');
|
||||
cy.get(proposalVoteProgressAgainstTokens)
|
||||
.contains('1.00')
|
||||
.and('be.visible');
|
||||
cy.get_proposal_information_from_table('Tokens for proposal')
|
||||
.should('have.text', '0.00')
|
||||
.and('be.visible');
|
||||
cy.get_proposal_information_from_table('Tokens against proposal')
|
||||
.should('have.text', parseFloat(this.minProposerBalance).toFixed(2))
|
||||
.and('be.visible');
|
||||
cy.get_proposal_information_from_table('Participation required')
|
||||
.contains(`${this.requiredParticipation}%`)
|
||||
.should('be.visible');
|
||||
cy.get_proposal_information_from_table('Majority Required')
|
||||
.contains(`${parseFloat(this.requiredMajority).toFixed(2)}%`)
|
||||
.should('be.visible');
|
||||
cy.get_proposal_information_from_table('Number of voting parties')
|
||||
.should('have.text', '1')
|
||||
.and('be.visible');
|
||||
});
|
||||
|
||||
it('Newly created freeform proposal details - ability to change vote from against to for - with minimum required tokens associated', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
cy.get_submitted_proposal_from_proposal_list()
|
||||
.as('submittedProposal')
|
||||
.within(() => cy.get(viewProposalButton).click());
|
||||
cy.vote_for_proposal('against');
|
||||
// 1004-VOTE-090
|
||||
cy.get(changeVoteButton).should('be.visible').click();
|
||||
cy.wait_for_spinner();
|
||||
cy.vote_for_proposal('for');
|
||||
cy.get(proposalVoteProgressForPercentage)
|
||||
.contains('100.00%')
|
||||
.and('be.visible');
|
||||
cy.get(proposalVoteProgressAgainstPercentage)
|
||||
.contains('0.00%')
|
||||
.and('be.visible');
|
||||
cy.get(proposalVoteProgressForTokens)
|
||||
.contains('1.00')
|
||||
.and('be.visible');
|
||||
cy.get(proposalVoteProgressAgainstTokens)
|
||||
.contains('0.00')
|
||||
.and('be.visible');
|
||||
// 1004-VOTE-064
|
||||
cy.get_proposal_information_from_table('Tokens for proposal')
|
||||
.should('have.text', parseFloat(this.minProposerBalance).toFixed(2))
|
||||
.and('be.visible');
|
||||
cy.get_proposal_information_from_table('Tokens against proposal')
|
||||
.should('have.text', '0.00')
|
||||
.and('be.visible');
|
||||
cy.get_proposal_information_from_table('Participation required')
|
||||
.contains(`${this.requiredParticipation}%`)
|
||||
.should('be.visible');
|
||||
cy.get_proposal_information_from_table('Majority Required')
|
||||
.contains(`${parseFloat(this.requiredMajority).toFixed(2)}%`)
|
||||
.should('be.visible');
|
||||
cy.get_proposal_information_from_table('Number of voting parties')
|
||||
.should('have.text', '1')
|
||||
.and('be.visible');
|
||||
});
|
||||
|
||||
it('Newly created freeform proposal details - ability to change vote from for to against - with minimum required tokens associated', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
cy.get_submitted_proposal_from_proposal_list()
|
||||
.as('submittedProposal')
|
||||
.within(() => cy.get(viewProposalButton).click());
|
||||
cy.vote_for_proposal('for');
|
||||
cy.get(changeVoteButton).should('be.visible').click();
|
||||
cy.wait_for_spinner();
|
||||
cy.vote_for_proposal('against');
|
||||
cy.get(proposalVoteProgressForPercentage)
|
||||
.contains('0.00%')
|
||||
.and('be.visible');
|
||||
cy.get(proposalVoteProgressAgainstPercentage)
|
||||
.contains('100.00%')
|
||||
.and('be.visible');
|
||||
cy.get(proposalVoteProgressForTokens)
|
||||
.contains('0.00')
|
||||
.and('be.visible');
|
||||
cy.get(proposalVoteProgressAgainstTokens)
|
||||
.contains('1.00')
|
||||
.and('be.visible');
|
||||
cy.get_proposal_information_from_table('Tokens for proposal')
|
||||
.should('have.text', '0.00')
|
||||
.and('be.visible');
|
||||
cy.get_proposal_information_from_table('Tokens against proposal')
|
||||
.should('have.text', parseFloat(this.minProposerBalance).toFixed(2))
|
||||
.and('be.visible');
|
||||
cy.get_proposal_information_from_table('Participation required')
|
||||
.contains(`${this.requiredParticipation}%`)
|
||||
.should('be.visible');
|
||||
cy.get_proposal_information_from_table('Majority Required')
|
||||
.contains(`${parseFloat(this.requiredMajority).toFixed(2)}%`)
|
||||
.should('be.visible');
|
||||
cy.get_proposal_information_from_table('Number of voting parties')
|
||||
.should('have.text', '1')
|
||||
.and('be.visible');
|
||||
});
|
||||
|
||||
it('Newly created freeform proposal details - ability to increase associated tokens - so that vote sways result', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
it('Newly created proposal details - ability to increase associated tokens - so that vote sways result', function () {
|
||||
createRawProposal(this.minProposerBalance);
|
||||
cy.get_submitted_proposal_from_proposal_list()
|
||||
.as('submittedProposal')
|
||||
.within(() => cy.get(viewProposalButton).click());
|
||||
@@ -935,7 +602,6 @@ context(
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('40');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
@@ -948,7 +614,6 @@ context(
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('100000');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
@@ -962,7 +627,6 @@ context(
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('500000000');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
@@ -991,15 +655,14 @@ context(
|
||||
.and('be.visible');
|
||||
});
|
||||
|
||||
it('Unable to create a freeform proposal - when no tokens are associated', function () {
|
||||
it('Unable to create a proposal - when no tokens are associated', function () {
|
||||
cy.vega_wallet_teardown();
|
||||
cy.get(vegaWalletAssociatedBalance, txTimeout).contains(
|
||||
'0.000000000000000000',
|
||||
txTimeout
|
||||
);
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('49');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.go_to_make_new_proposal(governanceProposalType.RAW);
|
||||
createRawProposal();
|
||||
|
||||
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
|
||||
cy.get(feedbackError)
|
||||
@@ -1009,14 +672,12 @@ context(
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
it('Unable to create a freeform proposal - when some but not enough tokens are associated', function () {
|
||||
it('Unable to create a proposal - when some but not enough tokens are associated', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance - 0.000001
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('49');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.go_to_make_new_proposal(governanceProposalType.RAW);
|
||||
createRawProposal(this.minProposerBalance);
|
||||
|
||||
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
|
||||
cy.get(feedbackError)
|
||||
@@ -1032,13 +693,12 @@ context(
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.create_ten_digit_unix_timestamp_for_specified_days('1').then(
|
||||
(closingDateTimestamp) => {
|
||||
cy.fixture('/proposals/freeform.json').then((freeformProposal) => {
|
||||
freeformProposal.terms.closingTimestamp = closingDateTimestamp;
|
||||
freeformProposal.unexpectfield = `i shouldn't be here`;
|
||||
freeformProposal.unexpected = `i shouldn't be here`;
|
||||
let proposalPayload = JSON.stringify(freeformProposal);
|
||||
|
||||
cy.get(proposalDetailsTitle).type(
|
||||
@@ -1056,7 +716,7 @@ context(
|
||||
|
||||
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
|
||||
cy.get(feedbackError)
|
||||
.contains('Unknown field unexpectfield in vega proposal terms')
|
||||
.contains('Unknown field unexpected in vega proposal terms')
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
@@ -1066,18 +726,15 @@ context(
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.go_to_make_new_proposal(governanceProposalType.RAW);
|
||||
cy.create_ten_digit_unix_timestamp_for_specified_days('1').then(
|
||||
(closingDateTimestamp) => {
|
||||
cy.fixture('/proposals/freeform.json').then((freeformProposal) => {
|
||||
freeformProposal.terms.closingTimestamp = closingDateTimestamp;
|
||||
freeformProposal.terms.unexpectedField = `i shouldn't be here`;
|
||||
let proposalPayload = JSON.stringify(freeformProposal);
|
||||
cy.fixture('/proposals/raw.json').then((rawProposal) => {
|
||||
rawProposal.terms.closingTimestamp = closingDateTimestamp;
|
||||
rawProposal.terms.unexpectedField = `i shouldn't be here`;
|
||||
let proposalPayload = JSON.stringify(rawProposal);
|
||||
|
||||
cy.get(proposalDetailsTitle).type(
|
||||
freeformProposal.rationale.title
|
||||
);
|
||||
cy.get(proposalDetailsTitle).type(rawProposal.rationale.title);
|
||||
cy.get(proposalDetailsDescription).type(proposalPayload, {
|
||||
parseSpecialCharSequences: false,
|
||||
delay: 2,
|
||||
@@ -1090,24 +747,20 @@ context(
|
||||
|
||||
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
|
||||
cy.get(feedbackError)
|
||||
.contains('Unknown field unexpectfield in vega proposal terms')
|
||||
.contains('Unknown field unexpected in vega proposal terms')
|
||||
.should('be.visible');
|
||||
});
|
||||
|
||||
// Have to skip because #1326 bug doesn't handle below scenario
|
||||
// 1005-todo-PROP-009
|
||||
it.skip('Unable to vote on a freeform proposal - when some but not enough vega associated', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_submitted();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.staking_page_disassociate_tokens('0.0001');
|
||||
cy.get(vegaWallet).within(() => {
|
||||
@@ -1126,21 +779,8 @@ context(
|
||||
cy.get(voteButtons).contains('against').should('not.exist');
|
||||
});
|
||||
|
||||
it('Unable to vote on a freeform proposal - when vega wallet disconnected - option to connect from within', function () {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(
|
||||
this.minProposerBalance
|
||||
);
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
it('Unable to vote on a proposal - when vega wallet disconnected - option to connect from within', function () {
|
||||
createRawProposal(this.minProposerBalance);
|
||||
cy.wait_for_spinner();
|
||||
cy.get('[data-testid="manage-vega-wallet"]').click();
|
||||
cy.get('[data-testid="disconnect"]').click();
|
||||
@@ -1171,6 +811,33 @@ context(
|
||||
cy.contains('You voted: Against').should('be.visible');
|
||||
});
|
||||
|
||||
function createRawProposal(proposerBalance) {
|
||||
if (proposerBalance)
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(proposerBalance);
|
||||
cy.go_to_make_new_proposal('raw proposal');
|
||||
cy.create_ten_digit_unix_timestamp_for_specified_days('8').then(
|
||||
(closingDateTimestamp) => {
|
||||
cy.enter_raw_proposal_body(closingDateTimestamp).as('rawProposal');
|
||||
}
|
||||
);
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.wait_for_proposal_submitted();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
}
|
||||
|
||||
function createFreeformProposal(proposerBalance) {
|
||||
cy.ensure_specified_unstaked_tokens_are_associated(proposerBalance);
|
||||
cy.go_to_make_new_proposal(governanceProposalType.FREEFORM);
|
||||
cy.enter_unique_freeform_proposal_body('50');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.wait_for_proposal_submitted();
|
||||
cy.wait_for_proposal_sync();
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
}
|
||||
|
||||
after(
|
||||
'teardown environment to prevent test data bleeding into other tests',
|
||||
function () {
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
const newProposalSubmitButton = '[data-testid="proposal-submit"]';
|
||||
const proposalVoteDeadline = '[data-testid="proposal-vote-deadline"]';
|
||||
const proposalValidationDeadline =
|
||||
'[data-testid="proposal-validation-deadline"]';
|
||||
const proposalParameterSelect = '[data-testid="proposal-parameter-select"]';
|
||||
const proposalMarketSelect = '[data-testid="proposal-market-select"]';
|
||||
const newProposalTitle = '[data-testid="proposal-title"]';
|
||||
const newProposalDescription = '[data-testid="proposal-description"]';
|
||||
const newProposalTerms = '[data-testid="proposal-terms"]';
|
||||
const currentParameterValue =
|
||||
'[data-testid="selected-proposal-param-current-value"]';
|
||||
const newProposedParameterValue =
|
||||
'[data-testid="selected-proposal-param-new-value"]';
|
||||
const dialogCloseButton = '[data-testid="dialog-close"]';
|
||||
const inputError = '[data-testid="input-error-text"]';
|
||||
const epochTimeout = Cypress.env('epochTimeout');
|
||||
const proposalTimeout = { timeout: 14000 };
|
||||
|
||||
const governanceProposalType = {
|
||||
NETWORK_PARAMETER: 'Network parameter',
|
||||
NEW_MARKET: 'New market',
|
||||
UPDATE_MARKET: 'Update market',
|
||||
NEW_ASSET: 'New asset',
|
||||
FREEFORM: 'Freeform',
|
||||
RAW: 'raw proposal',
|
||||
};
|
||||
|
||||
context(
|
||||
'Governance flow - form validations for different governance proposals',
|
||||
{ tags: '@slow' },
|
||||
function () {
|
||||
before('connect wallets and set approval limit', function () {
|
||||
cy.vega_wallet_import();
|
||||
cy.visit('/');
|
||||
cy.verify_page_header('The $VEGA token');
|
||||
cy.vega_wallet_connect();
|
||||
cy.vega_wallet_set_specified_approval_amount('1000');
|
||||
cy.reload();
|
||||
cy.wait_for_spinner();
|
||||
cy.verify_page_header('The $VEGA token');
|
||||
cy.ethereum_wallet_connect();
|
||||
});
|
||||
|
||||
beforeEach('visit governance tab', function () {
|
||||
cy.navigate_to('governance');
|
||||
cy.wait_for_spinner();
|
||||
cy.intercept('POST', '/query', (req) => {
|
||||
if (req.body.operationName === 'ProposalEvent') {
|
||||
req.alias = 'proposalSubmissionCompletion';
|
||||
}
|
||||
});
|
||||
cy.ensure_specified_unstaked_tokens_are_associated('1');
|
||||
});
|
||||
|
||||
it('Able to submit valid update network parameter proposal', function () {
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.NETWORK_PARAMETER);
|
||||
// 1005-PROP-006
|
||||
cy.get(newProposalTitle).type('Test update network parameter proposal');
|
||||
// 1005-PROP-007
|
||||
cy.get(newProposalDescription).type('E2E test for proposals');
|
||||
|
||||
cy.get(proposalParameterSelect).find('option').should('have.length', 109);
|
||||
cy.get(proposalParameterSelect).select(
|
||||
'governance_proposal_asset_minEnact'
|
||||
);
|
||||
cy.get(currentParameterValue).should('have.value', '2s');
|
||||
cy.get(newProposedParameterValue).type('5s');
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.wait_for_proposal_submitted();
|
||||
});
|
||||
|
||||
it('Unable to submit network parameter with missing/invalid fields', function () {
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.go_to_make_new_proposal(governanceProposalType.NETWORK_PARAMETER);
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.get(inputError).should('have.length', 3);
|
||||
cy.get(newProposalTitle).type(
|
||||
'Invalid update network parameter proposal'
|
||||
);
|
||||
cy.get(newProposalDescription).type('E2E invalid test for proposals');
|
||||
cy.get(proposalParameterSelect).select(
|
||||
'spam_protection_proposal_min_tokens'
|
||||
);
|
||||
cy.get(newProposedParameterValue).type('0');
|
||||
cy.get(proposalVoteDeadline).clear().type('0');
|
||||
cy.get(newProposalSubmitButton).click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'not.exist'
|
||||
);
|
||||
cy.get(proposalVoteDeadline).clear().type('9000');
|
||||
cy.get(newProposalSubmitButton).click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'not.exist'
|
||||
);
|
||||
});
|
||||
|
||||
it('Able to submit valid new market proposal', function () {
|
||||
cy.go_to_make_new_proposal(governanceProposalType.NEW_MARKET);
|
||||
cy.get(newProposalTitle).type('Test new market proposal');
|
||||
cy.get(newProposalDescription).type('E2E test for proposals');
|
||||
cy.fixture('/proposals/new-market').then((newMarketProposal) => {
|
||||
let newMarketPayload = JSON.stringify(newMarketProposal);
|
||||
cy.get(newProposalTerms).type(newMarketPayload, {
|
||||
parseSpecialCharSequences: false,
|
||||
delay: 2,
|
||||
});
|
||||
});
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.wait_for_proposal_submitted();
|
||||
});
|
||||
|
||||
it('Unable to submit new market proposal with missing/invalid fields', function () {
|
||||
cy.go_to_make_new_proposal(governanceProposalType.NEW_MARKET);
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.get(inputError).should('have.length', 3);
|
||||
});
|
||||
|
||||
// skipped because of bug #1605
|
||||
it.skip('Able to submit update market proposal', function () {
|
||||
const marketId =
|
||||
'315a8e48db0a292c92b617264728048c82c20efc922c75fd292fc54e5c727c81';
|
||||
cy.go_to_make_new_proposal(governanceProposalType.UPDATE_MARKET);
|
||||
cy.get(newProposalTitle).type('Test update asset proposal');
|
||||
cy.get(newProposalDescription).type('E2E test for proposals');
|
||||
cy.get(proposalMarketSelect).select(marketId);
|
||||
cy.get('[data-testid="update-market-details"]').within(() => {
|
||||
cy.get('dd').eq(0).should('have.text', 'Oranges Daily');
|
||||
cy.get('dd').eq(1).should('have.text', 'ORANGES.24h');
|
||||
cy.get('dd').eq(2).should('have.text', marketId);
|
||||
});
|
||||
cy.fixture('/proposals/update-market').then((updateMarketProposal) => {
|
||||
let newUpdateMarketProposal = JSON.stringify(updateMarketProposal);
|
||||
cy.get(newProposalTerms).type(newUpdateMarketProposal, {
|
||||
parseSpecialCharSequences: false,
|
||||
delay: 2,
|
||||
});
|
||||
});
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.wait_for_proposal_submitted();
|
||||
});
|
||||
|
||||
it('Able to submit new asset proposal', function () {
|
||||
cy.go_to_make_new_proposal(governanceProposalType.NEW_ASSET);
|
||||
cy.get(newProposalTitle).type('Test new asset proposal');
|
||||
cy.get(newProposalDescription).type('E2E test for proposals');
|
||||
cy.fixture('/proposals/new-asset').then((newAssetProposal) => {
|
||||
let newAssetPayload = JSON.stringify(newAssetProposal);
|
||||
cy.get(newProposalTerms).type(newAssetPayload, {
|
||||
parseSpecialCharSequences: false,
|
||||
delay: 2,
|
||||
});
|
||||
});
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal waiting for node vote', proposalTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.get(dialogCloseButton).click();
|
||||
});
|
||||
|
||||
it('Unable to submit new asset proposal with missing/invalid fields', function () {
|
||||
cy.go_to_make_new_proposal(governanceProposalType.NEW_ASSET);
|
||||
cy.get(newProposalSubmitButton).should('be.visible').click();
|
||||
cy.get(inputError).should('have.length', 3);
|
||||
cy.get(newProposalTitle).type('Invalid new asset proposal');
|
||||
cy.get(newProposalDescription).type('Invalid E2E test for proposals');
|
||||
cy.get(proposalValidationDeadline).clear().type('2');
|
||||
cy.get(newProposalSubmitButton).click();
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'not.exist'
|
||||
);
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -14,9 +14,11 @@ const tokenSubmitButton = '[data-testid="token-input-submit-button"]';
|
||||
const ethWalletDissociateButton = '[href="/staking/disassociate"]';
|
||||
const vestingContractSection = '[data-testid="vega-in-vesting-contract"]';
|
||||
const vegaInWalletSection = '[data-testid="vega-in-wallet"]';
|
||||
const connectedVegaKey = '[data-testid="connected-vega-key"]';
|
||||
const associatedKey = '[data-test-id="associated-key"]';
|
||||
const associatedAmount = '[data-test-id="associated-amount"]';
|
||||
const disassocitiationWarning = '[data-testid="disassociation-warning"]';
|
||||
const associateCompleteText = '[data-testid="transaction-complete-body"]';
|
||||
const disassociationWarning = '[data-testid="disassociation-warning"]';
|
||||
const vegaWallet = '[data-testid="vega-wallet"]';
|
||||
|
||||
context(
|
||||
@@ -47,7 +49,8 @@ context(
|
||||
);
|
||||
|
||||
it('Able to associate tokens - from wallet', function () {
|
||||
//1004-ASSO-008
|
||||
//1004-ASSO-003
|
||||
//1004-ASSO-005
|
||||
//1004-ASSO-009
|
||||
//1004-ASSO-030
|
||||
//1004-ASSO-012
|
||||
@@ -162,7 +165,7 @@ context(
|
||||
cy.get('button').contains('Select a validator to nominate').click();
|
||||
|
||||
cy.get(ethWalletDissociateButton).click();
|
||||
cy.get(disassocitiationWarning).should('contain', warningText);
|
||||
cy.get(disassociationWarning).should('contain', warningText);
|
||||
|
||||
cy.staking_page_disassociate_all_tokens();
|
||||
|
||||
@@ -185,6 +188,8 @@ context(
|
||||
|
||||
it('Able to associate and disassociate vesting contract tokens', function () {
|
||||
// 1004-ASSO-006
|
||||
// 1004-ASSO-007
|
||||
// 1004-ASSO-018
|
||||
// 1004-ASSO-024
|
||||
// 1004-ASSO-023
|
||||
|
||||
@@ -268,15 +273,44 @@ context(
|
||||
});
|
||||
|
||||
it('Not able to associate more tokens than owned', function () {
|
||||
// 1004-ASSO-008
|
||||
// 1004-ASSO-010
|
||||
// No warning visible as described in AC, but the button is disabled
|
||||
|
||||
cy.get(ethWalletAssociateButton).first().click();
|
||||
cy.get(associateWalletRadioButton, { timeout: 30000 }).click();
|
||||
cy.get(tokenSubmitButton, txTimeout).should('be.disabled'); // button disabled with no input
|
||||
cy.get(tokenAmountInputBox, { timeout: 10000 }).type(6500000);
|
||||
cy.get(tokenSubmitButton, txTimeout).should('be.disabled');
|
||||
});
|
||||
|
||||
// 1004-ASSO-004
|
||||
it('Able to associate tokens to different public key of connected vega wallet', function () {
|
||||
cy.get(ethWalletAssociateButton).first().click();
|
||||
cy.get(associateWalletRadioButton).click();
|
||||
cy.get(connectedVegaKey).should(
|
||||
'have.text',
|
||||
Cypress.env('vegaWalletPublicKey')
|
||||
);
|
||||
|
||||
cy.get('[data-testid="manage-vega-wallet"]').click();
|
||||
cy.get('[data-testid="select-keypair-button"]').click();
|
||||
cy.get(connectedVegaKey).should(
|
||||
'have.text',
|
||||
Cypress.env('vegaWalletPublicKey2')
|
||||
);
|
||||
cy.staking_page_associate_tokens('2');
|
||||
cy.get(vegaWallet).within(() => {
|
||||
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
|
||||
});
|
||||
cy.get(associateCompleteText).should(
|
||||
'have.text',
|
||||
`Vega key ${Cypress.env(
|
||||
'vegaWalletPublicKey2Short'
|
||||
)} can now participate in governance and nominate a validator with your associated $VEGA.`
|
||||
);
|
||||
});
|
||||
|
||||
after(
|
||||
'teardown environment to prevent test data bleeding into other tests',
|
||||
function () {
|
||||
|
||||
@@ -29,6 +29,7 @@ context(
|
||||
.and('have.attr', 'href')
|
||||
.and('equal', governanceDocsUrl);
|
||||
|
||||
// 1005-PROP-001
|
||||
cy.request(governanceDocsUrl)
|
||||
.its('body')
|
||||
.then((body) => {
|
||||
|
||||
@@ -2,11 +2,15 @@ const newProposalButton = '[data-testid="new-proposal-link"]';
|
||||
const proposalInformationTableRows = '[data-testid="key-value-table-row"]';
|
||||
const newProposalTitle = '[data-testid="proposal-title"]';
|
||||
const newProposalDescription = '[data-testid="proposal-description"]';
|
||||
const rawProposalData = '[data-testid="proposal-data"]';
|
||||
const proposalResponseProposalIdPath =
|
||||
'response.body.data.busEvents.0.event.id';
|
||||
const voteButtons = '[data-testid="vote-buttons"]';
|
||||
const txTimeout = Cypress.env('txTimeout');
|
||||
const proposalVoteDeadline = '[data-testid="proposal-vote-deadline"]';
|
||||
const dialogCloseButton = '[data-testid="dialog-close"]';
|
||||
const epochTimeout = Cypress.env('epochTimeout');
|
||||
const proposalTimeout = { timeout: 14000 };
|
||||
|
||||
Cypress.Commands.add(
|
||||
'convert_unix_timestamp_to_governance_data_table_date_format',
|
||||
@@ -47,44 +51,26 @@ Cypress.Commands.add(
|
||||
}
|
||||
);
|
||||
|
||||
Cypress.Commands.add('enter_unique_freeform_proposal_body', (timestamp) => {
|
||||
cy.fixture('/proposals/freeform.json').then((freeformProposal) => {
|
||||
freeformProposal.terms.closingTimestamp = timestamp;
|
||||
freeformProposal.rationale.title += timestamp;
|
||||
let proposalPayload = JSON.stringify(freeformProposal);
|
||||
Cypress.Commands.add('enter_raw_proposal_body', (timestamp) => {
|
||||
cy.fixture('/proposals/raw.json').then((rawProposal) => {
|
||||
rawProposal.terms.closingTimestamp = timestamp;
|
||||
rawProposal.rationale.title += timestamp;
|
||||
let proposalPayload = JSON.stringify(rawProposal);
|
||||
|
||||
cy.get(newProposalTitle).type(freeformProposal.rationale.title);
|
||||
|
||||
cy.get(newProposalDescription).type(proposalPayload, {
|
||||
cy.get(rawProposalData).type(proposalPayload, {
|
||||
parseSpecialCharSequences: false,
|
||||
delay: 2,
|
||||
});
|
||||
|
||||
cy.get(proposalVoteDeadline).clear().click().type(timestamp);
|
||||
|
||||
cy.wrap(freeformProposal);
|
||||
cy.wrap(rawProposal);
|
||||
});
|
||||
});
|
||||
|
||||
Cypress.Commands.add('get_network_parameters', () => {
|
||||
let mutation = '{networkParameters {key value}}';
|
||||
cy.request({
|
||||
method: 'POST',
|
||||
url: `http://localhost:3028/query`,
|
||||
body: {
|
||||
query: mutation,
|
||||
},
|
||||
headers: { 'content-type': 'application/json' },
|
||||
})
|
||||
.its(`body.data.networkParameters`)
|
||||
.then(function (response) {
|
||||
let object = response.reduce(function (r, e) {
|
||||
r[e.key] = e.value;
|
||||
return r;
|
||||
}, {});
|
||||
|
||||
return object;
|
||||
});
|
||||
Cypress.Commands.add('enter_unique_freeform_proposal_body', (timestamp) => {
|
||||
cy.get(newProposalTitle).type(`${timestamp} test freeform proposal`);
|
||||
cy.get(newProposalDescription).type(
|
||||
'this is a e2e freeform proposal description'
|
||||
);
|
||||
cy.get(proposalVoteDeadline).clear().click().type(timestamp);
|
||||
});
|
||||
|
||||
Cypress.Commands.add('get_submitted_proposal_from_proposal_list', () => {
|
||||
@@ -165,6 +151,15 @@ Cypress.Commands.add('get_sort_order_of_supplied_array', (suppliedArray) => {
|
||||
});
|
||||
|
||||
Cypress.Commands.add('go_to_make_new_proposal', (proposalType) => {
|
||||
cy.navigate_to_page_if_not_already_loaded('governance');
|
||||
cy.get(newProposalButton).should('be.visible').click();
|
||||
cy.get('li').contains(proposalType).click();
|
||||
});
|
||||
|
||||
Cypress.Commands.add('wait_for_proposal_submitted', () => {
|
||||
cy.contains('Awaiting network confirmation', epochTimeout).should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
|
||||
cy.get(dialogCloseButton).click();
|
||||
});
|
||||
|
||||
@@ -20,7 +20,7 @@ const vegaKeySelector = '#vega-key-selector';
|
||||
const txTimeout = Cypress.env('txTimeout');
|
||||
const epochTimeout = Cypress.env('epochTimeout');
|
||||
|
||||
Cypress.Commands.add('wait_for_begining_of_epoch', () => {
|
||||
Cypress.Commands.add('wait_for_beginning_of_epoch', () => {
|
||||
cy.contains('Waiting for next epoch to start', epochTimeout).should(
|
||||
'not.exist'
|
||||
);
|
||||
@@ -34,7 +34,7 @@ Cypress.Commands.add('staking_validator_page_add_stake', (stake) => {
|
||||
cy.wait_for_spinner();
|
||||
cy.get(addStakeRadioButton, epochTimeout).click({ force: true });
|
||||
cy.get(tokenAmountInputBox).type(stake);
|
||||
cy.wait_for_begining_of_epoch();
|
||||
cy.wait_for_beginning_of_epoch();
|
||||
cy.get(tokenSubmitButton, epochTimeout)
|
||||
.should('be.enabled')
|
||||
.and('contain', `Add ${stake} $VEGA tokens`)
|
||||
@@ -47,7 +47,7 @@ Cypress.Commands.add('staking_validator_page_remove_stake', (stake) => {
|
||||
cy.wait_for_spinner();
|
||||
cy.get(removeStakeRadioButton, epochTimeout).click();
|
||||
cy.get(tokenAmountInputBox).type(stake);
|
||||
cy.wait_for_begining_of_epoch();
|
||||
cy.wait_for_beginning_of_epoch();
|
||||
cy.get(tokenSubmitButton)
|
||||
.should('be.enabled', epochTimeout)
|
||||
.and('contain', `Remove ${stake} $VEGA tokens at the end of epoch`)
|
||||
@@ -151,7 +151,7 @@ Cypress.Commands.add(
|
||||
cy.wait_for_spinner();
|
||||
cy.contains('Loading...', epochTimeout).should('not.exist');
|
||||
cy.contains('Total stake this epoch').should('be.visible');
|
||||
cy.wait_for_begining_of_epoch();
|
||||
cy.wait_for_beginning_of_epoch();
|
||||
// below is to ensure validator list is shown
|
||||
cy.get(stakeValidatorListName, { timeout: 10000 }).should('exist');
|
||||
cy.get(stakeValidatorListPendingStake, txTimeout).should(
|
||||
@@ -180,7 +180,7 @@ Cypress.Commands.add(
|
||||
cy.wait_for_spinner();
|
||||
cy.contains('Loading...', epochTimeout).should('not.exist');
|
||||
cy.contains('Total stake this epoch').should('be.visible');
|
||||
cy.wait_for_begining_of_epoch();
|
||||
cy.wait_for_beginning_of_epoch();
|
||||
cy.get(`[row-id="${positionOnList}"]`).within(() => {
|
||||
cy.get(stakeValidatorListName).should('have.text', expectedValidatorName);
|
||||
cy.get(stakeValidatorListTotalStake, epochTimeout).should(
|
||||
|
||||
@@ -17,7 +17,7 @@ import type {
|
||||
} from './__generated__/Delegations';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { useContracts } from '../../contexts/contracts/contracts-context';
|
||||
import { isAssetTypeERC20 } from '@vegaprotocol/react-helpers';
|
||||
import { isAssetTypeERC20 } from '@vegaprotocol/assets';
|
||||
import { AccountType } from '@vegaprotocol/types';
|
||||
|
||||
const DELEGATIONS_QUERY = gql`
|
||||
|
||||
@@ -636,6 +636,7 @@
|
||||
"NewMarketProposal": "New market proposal",
|
||||
"UpdateMarketProposal": "Update market proposal",
|
||||
"NewAssetProposal": "New asset proposal",
|
||||
"UpdateAssetProposal": "Update asset proposal",
|
||||
"NewFreeformProposal": "New freeform proposal",
|
||||
"NewRawProposal": "New raw proposal",
|
||||
"MinProposalRequirements": "You must have at least {{value}} VEGA associated to make a proposal",
|
||||
@@ -647,6 +648,7 @@
|
||||
"NewMarket": "New market",
|
||||
"UpdateMarket": "Update market",
|
||||
"NewAsset": "New asset",
|
||||
"UpdateAsset": "Update asset",
|
||||
"Freeform": "Freeform",
|
||||
"RawProposal": "Let me choose (raw proposal)",
|
||||
"UseMin": "Use minimum",
|
||||
|
||||
+3
-3
@@ -26,7 +26,7 @@ import {
|
||||
lastWeek,
|
||||
nextWeek,
|
||||
} from '../../test-helpers/mocks';
|
||||
import type { ProposalsConnection_proposalsConnection_edges_node as ProposalNode } from '@vegaprotocol/governance';
|
||||
import type { Proposals_proposalsConnection_edges_node as ProposalNode } from '../../proposals/__generated__/Proposals';
|
||||
|
||||
const renderComponent = (
|
||||
proposal: ProposalNode,
|
||||
@@ -172,7 +172,7 @@ describe('Proposals list item details', () => {
|
||||
datetime: lastWeek.toString(),
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
id: mockPubkey,
|
||||
id: mockPubkey.publicKey,
|
||||
stakingSummary: {
|
||||
__typename: 'StakingSummary',
|
||||
currentStakeAvailable: '1000',
|
||||
@@ -210,7 +210,7 @@ describe('Proposals list item details', () => {
|
||||
datetime: lastWeek.toString(),
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
id: mockPubkey,
|
||||
id: mockPubkey.publicKey,
|
||||
stakingSummary: {
|
||||
__typename: 'StakingSummary',
|
||||
currentStakeAvailable: '1000',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { ProposeFreeform } from './propose-freeform';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { mockWalletContext } from '../../test-helpers/mocks';
|
||||
@@ -81,16 +81,14 @@ describe('Propose Freeform', () => {
|
||||
|
||||
it('should render the title', async () => {
|
||||
renderComponent();
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText('New freeform proposal')).toBeInTheDocument()
|
||||
);
|
||||
expect(
|
||||
await screen.findByText('New freeform proposal')
|
||||
).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('should render the form components', async () => {
|
||||
renderComponent();
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId('freeform-proposal-form')).toBeTruthy()
|
||||
);
|
||||
expect(await screen.findByTestId('freeform-proposal-form')).toBeTruthy();
|
||||
expect(screen.getByTestId('min-proposal-requirements')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-docs-link')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-title')).toBeTruthy();
|
||||
|
||||
@@ -27,7 +27,7 @@ export interface FreeformProposalFormFields {
|
||||
proposalReference: string;
|
||||
}
|
||||
|
||||
const docsLink = 'freeform-proposal';
|
||||
const DOCS_LINK = 'freeform-proposal';
|
||||
|
||||
export const ProposeFreeform = () => {
|
||||
const { params, loading, error } = useNetworkParams([
|
||||
@@ -76,9 +76,9 @@ export const ProposeFreeform = () => {
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<Link
|
||||
href={`${VEGA_DOCS_URL}/tutorials/proposals/${docsLink}`}
|
||||
href={`${VEGA_DOCS_URL}/tutorials/proposals/${DOCS_LINK}`}
|
||||
target="_blank"
|
||||
>{`${VEGA_DOCS_URL}/tutorials/proposals/${docsLink}`}</Link>
|
||||
>{`${VEGA_DOCS_URL}/tutorials/proposals/${DOCS_LINK}`}</Link>
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
+11
-11
@@ -1,4 +1,4 @@
|
||||
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
|
||||
import { fireEvent, render, screen } from '@testing-library/react';
|
||||
import { ProposeNetworkParameter } from './propose-network-parameter';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { mockWalletContext } from '../../test-helpers/mocks';
|
||||
@@ -81,16 +81,16 @@ describe('Propose Network Parameter', () => {
|
||||
|
||||
it('should render the correct title', async () => {
|
||||
renderComponent();
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText('Update network parameter proposal')).toBeTruthy()
|
||||
);
|
||||
expect(
|
||||
await screen.findByText('Update network parameter proposal')
|
||||
).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render the form components', async () => {
|
||||
renderComponent();
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId('network-parameter-proposal-form')).toBeTruthy()
|
||||
);
|
||||
expect(
|
||||
await screen.findByTestId('network-parameter-proposal-form')
|
||||
).toBeTruthy();
|
||||
expect(screen.getByTestId('min-proposal-requirements')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-docs-link')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-title')).toBeTruthy();
|
||||
@@ -103,15 +103,15 @@ describe('Propose Network Parameter', () => {
|
||||
|
||||
it('should render the network param select element with no initial value', async () => {
|
||||
renderComponent();
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId('proposal-parameter-select')).toHaveValue('')
|
||||
expect(await screen.findByTestId('proposal-parameter-select')).toHaveValue(
|
||||
''
|
||||
);
|
||||
});
|
||||
|
||||
it('should render the current param value and a new value input when the network param select element is changed', async () => {
|
||||
renderComponent();
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId('proposal-parameter-select')).toHaveValue('')
|
||||
expect(await screen.findByTestId('proposal-parameter-select')).toHaveValue(
|
||||
''
|
||||
);
|
||||
|
||||
fireEvent.change(screen.getByTestId('proposal-parameter-select'), {
|
||||
|
||||
+3
-3
@@ -69,7 +69,7 @@ export interface NetworkParameterProposalFormFields {
|
||||
proposalReference: string;
|
||||
}
|
||||
|
||||
const docsLink = '/network-parameter-proposal';
|
||||
const DOCS_LINK = '/network-parameter-proposal';
|
||||
|
||||
export const ProposeNetworkParameter = () => {
|
||||
const [selectedNetworkParam, setSelectedNetworkParam] = useState<
|
||||
@@ -141,9 +141,9 @@ export const ProposeNetworkParameter = () => {
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<Link
|
||||
href={`${VEGA_DOCS_URL}/tutorials/proposals${docsLink}`}
|
||||
href={`${VEGA_DOCS_URL}/tutorials/proposals${DOCS_LINK}`}
|
||||
target="_blank"
|
||||
>{`${VEGA_DOCS_URL}/tutorials/proposals${docsLink}`}</Link>
|
||||
>{`${VEGA_DOCS_URL}/tutorials/proposals${DOCS_LINK}`}</Link>
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MemoryRouter as Router } from 'react-router-dom';
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { VegaWalletContext } from '@vegaprotocol/wallet';
|
||||
import { AppStateProvider } from '../../../../contexts/app-state/app-state-provider';
|
||||
import { mockWalletContext } from '../../test-helpers/mocks';
|
||||
@@ -81,16 +81,12 @@ describe('Propose New Asset', () => {
|
||||
|
||||
it('should render the title', async () => {
|
||||
renderComponent();
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText('New asset proposal')).toBeTruthy()
|
||||
);
|
||||
expect(await screen.findByText('New asset proposal')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render the form components', async () => {
|
||||
renderComponent();
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId('new-asset-proposal-form')).toBeTruthy()
|
||||
);
|
||||
expect(await screen.findByTestId('new-asset-proposal-form')).toBeTruthy();
|
||||
expect(screen.getByTestId('min-proposal-requirements')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-docs-link')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-title')).toBeTruthy();
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
getValidationTimestamp,
|
||||
} from '@vegaprotocol/governance';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { validateJson } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
ProposalFormMinRequirements,
|
||||
ProposalFormTitle,
|
||||
@@ -32,7 +33,7 @@ export interface NewAssetProposalFormFields {
|
||||
proposalReference: string;
|
||||
}
|
||||
|
||||
const docsLink = '/new-asset-proposal';
|
||||
const DOCS_LINK = '/new-asset-proposal';
|
||||
|
||||
export const ProposeNewAsset = () => {
|
||||
const {
|
||||
@@ -100,9 +101,9 @@ export const ProposeNewAsset = () => {
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<Link
|
||||
href={`${VEGA_DOCS_URL}/tutorials/proposals${docsLink}`}
|
||||
href={`${VEGA_DOCS_URL}/tutorials/proposals${DOCS_LINK}`}
|
||||
target="_blank"
|
||||
>{`${VEGA_DOCS_URL}/tutorials/proposals${docsLink}`}</Link>
|
||||
>{`${VEGA_DOCS_URL}/tutorials/proposals${DOCS_LINK}`}</Link>
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -141,20 +142,11 @@ export const ProposeNewAsset = () => {
|
||||
<ProposalFormTerms
|
||||
registerField={register('proposalTerms', {
|
||||
required: t('Required'),
|
||||
validate: {
|
||||
validateJson: (value) => {
|
||||
try {
|
||||
JSON.parse(value);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return t('Must be valid JSON');
|
||||
}
|
||||
},
|
||||
},
|
||||
validate: (value) => validateJson(value),
|
||||
})}
|
||||
labelOverride={'Terms.newAsset (JSON format)'}
|
||||
errorMessage={errors?.proposalTerms?.message}
|
||||
customDocLink={docsLink}
|
||||
customDocLink={DOCS_LINK}
|
||||
/>
|
||||
|
||||
<ProposalFormVoteAndEnactmentDeadline
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { render, screen, waitFor } from '@testing-library/react';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { ProposeNewMarket } from './propose-new-market';
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { mockWalletContext } from '../../test-helpers/mocks';
|
||||
@@ -81,9 +81,7 @@ describe('Propose New Market', () => {
|
||||
|
||||
it('should render the form components', async () => {
|
||||
renderComponent();
|
||||
await waitFor(() =>
|
||||
expect(screen.getByTestId('new-market-proposal-form')).toBeTruthy()
|
||||
);
|
||||
expect(await screen.findByTestId('new-market-proposal-form')).toBeTruthy();
|
||||
expect(screen.getByTestId('min-proposal-requirements')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-docs-link')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-title')).toBeTruthy();
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
getEnactmentTimestamp,
|
||||
} from '@vegaprotocol/governance';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { validateJson } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
ProposalFormMinRequirements,
|
||||
ProposalFormTitle,
|
||||
@@ -30,7 +31,7 @@ export interface NewMarketProposalFormFields {
|
||||
proposalReference: string;
|
||||
}
|
||||
|
||||
const docsLink = '/new-market-proposal';
|
||||
const DOCS_LINK = '/new-market-proposal';
|
||||
|
||||
export const ProposeNewMarket = () => {
|
||||
const {
|
||||
@@ -95,9 +96,9 @@ export const ProposeNewMarket = () => {
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<Link
|
||||
href={`${VEGA_DOCS_URL}/tutorials/proposals/${docsLink}`}
|
||||
href={`${VEGA_DOCS_URL}/tutorials/proposals${DOCS_LINK}`}
|
||||
target="_blank"
|
||||
>{`${VEGA_DOCS_URL}/tutorials/proposals/${docsLink}`}</Link>
|
||||
>{`${VEGA_DOCS_URL}/tutorials/proposals${DOCS_LINK}`}</Link>
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -136,20 +137,11 @@ export const ProposeNewMarket = () => {
|
||||
<ProposalFormTerms
|
||||
registerField={register('proposalTerms', {
|
||||
required: t('Required'),
|
||||
validate: {
|
||||
validateJson: (value) => {
|
||||
try {
|
||||
JSON.parse(value);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return t('Must be valid JSON');
|
||||
}
|
||||
},
|
||||
},
|
||||
validate: (value) => validateJson(value),
|
||||
})}
|
||||
labelOverride={'Terms.newMarket (JSON format)'}
|
||||
errorMessage={errors?.proposalTerms?.message}
|
||||
customDocLink={docsLink}
|
||||
customDocLink={DOCS_LINK}
|
||||
/>
|
||||
|
||||
<ProposalFormVoteAndEnactmentDeadline
|
||||
|
||||
@@ -24,6 +24,7 @@ describe('Propose', () => {
|
||||
expect(screen.getByText('New market')).toBeTruthy();
|
||||
expect(screen.getByText('Update market')).toBeTruthy();
|
||||
expect(screen.getByText('New asset')).toBeTruthy();
|
||||
expect(screen.getByText('Update asset')).toBeTruthy();
|
||||
expect(screen.getByText('Freeform')).toBeTruthy();
|
||||
expect(screen.getByText('Let me choose (raw proposal)')).toBeTruthy();
|
||||
});
|
||||
|
||||
@@ -79,6 +79,16 @@ export const Propose = () => {
|
||||
</Link>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<Link
|
||||
className="underline"
|
||||
to={`${Routes.GOVERNANCE}/propose/update-asset`}
|
||||
>
|
||||
{t('UpdateAsset')}
|
||||
</Link>
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<p>
|
||||
<Link
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
Link,
|
||||
TextArea,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { validateJson } from '@vegaprotocol/react-helpers';
|
||||
import { useProposalSubmit } from '@vegaprotocol/governance';
|
||||
import {
|
||||
ProposalFormSubmit,
|
||||
@@ -74,16 +75,7 @@ export const ProposeRaw = () => {
|
||||
data-testid="proposal-data"
|
||||
{...register('rawProposalData', {
|
||||
required: t('Required'),
|
||||
validate: {
|
||||
validateJson: (value) => {
|
||||
try {
|
||||
JSON.parse(value);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return t('Must be valid JSON');
|
||||
}
|
||||
},
|
||||
},
|
||||
validate: (value) => validateJson(value),
|
||||
})}
|
||||
/>
|
||||
{errors.rawProposalData?.message && (
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
export {
|
||||
ProposeUpdateAsset,
|
||||
ProposeUpdateAsset as default,
|
||||
} from './propose-update-asset';
|
||||
@@ -0,0 +1,102 @@
|
||||
import { MockedProvider } from '@apollo/client/testing';
|
||||
import { MemoryRouter as Router } from 'react-router-dom';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { VegaWalletContext } from '@vegaprotocol/wallet';
|
||||
import { AppStateProvider } from '../../../../contexts/app-state/app-state-provider';
|
||||
import { mockWalletContext } from '../../test-helpers/mocks';
|
||||
import { ProposeUpdateAsset } from './propose-update-asset';
|
||||
import type { NetworkParamsQuery } from '@vegaprotocol/web3';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { NETWORK_PARAMETERS_QUERY } from '@vegaprotocol/react-helpers';
|
||||
|
||||
jest.mock('@vegaprotocol/environment', () => ({
|
||||
useEnvironment: () => ({
|
||||
VEGA_DOCS_URL: 'https://docs.vega.xyz',
|
||||
}),
|
||||
}));
|
||||
|
||||
const updateAssetNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
|
||||
request: {
|
||||
query: NETWORK_PARAMETERS_QUERY,
|
||||
},
|
||||
result: {
|
||||
data: {
|
||||
networkParameters: [
|
||||
{
|
||||
__typename: 'NetworkParameter',
|
||||
key: 'governance.proposal.updateAsset.maxClose',
|
||||
value: '8760h0m0s',
|
||||
},
|
||||
{
|
||||
__typename: 'NetworkParameter',
|
||||
key: 'governance.proposal.updateAsset.maxEnact',
|
||||
value: '8760h0m0s',
|
||||
},
|
||||
{
|
||||
__typename: 'NetworkParameter',
|
||||
key: 'governance.proposal.updateAsset.minClose',
|
||||
value: '1h0m0s',
|
||||
},
|
||||
{
|
||||
__typename: 'NetworkParameter',
|
||||
key: 'governance.proposal.updateAsset.minEnact',
|
||||
value: '2h0m0s',
|
||||
},
|
||||
{
|
||||
__typename: 'NetworkParameter',
|
||||
key: 'governance.proposal.updateAsset.minProposerBalance',
|
||||
value: '1',
|
||||
},
|
||||
{
|
||||
__typename: 'NetworkParameter',
|
||||
key: 'spam.protection.proposal.min.tokens',
|
||||
value: '1000000000000000000',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const renderComponent = () =>
|
||||
render(
|
||||
<Router>
|
||||
<MockedProvider mocks={[updateAssetNetworkParamsQueryMock]}>
|
||||
<AppStateProvider>
|
||||
<VegaWalletContext.Provider value={mockWalletContext}>
|
||||
<ProposeUpdateAsset />
|
||||
</VegaWalletContext.Provider>
|
||||
</AppStateProvider>
|
||||
</MockedProvider>
|
||||
</Router>
|
||||
);
|
||||
|
||||
// Note: form submission is tested in propose-raw.spec.tsx. Reusable form
|
||||
// components are tested in their own directory.
|
||||
|
||||
describe('Propose Update Asset', () => {
|
||||
it('should render successfully', async () => {
|
||||
const { baseElement } = renderComponent();
|
||||
await expect(baseElement).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render the title', async () => {
|
||||
renderComponent();
|
||||
expect(await screen.findByText('Update asset proposal')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render the form components', async () => {
|
||||
renderComponent();
|
||||
expect(
|
||||
await screen.findByTestId('update-asset-proposal-form')
|
||||
).toBeTruthy();
|
||||
expect(screen.getByTestId('min-proposal-requirements')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-docs-link')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-title')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-description')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-terms')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-vote-deadline')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-enactment-deadline')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-submit')).toBeTruthy();
|
||||
expect(screen.getByTestId('proposal-transaction-dialog')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,182 @@
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import {
|
||||
useProposalSubmit,
|
||||
getClosingTimestamp,
|
||||
getEnactmentTimestamp,
|
||||
} from '@vegaprotocol/governance';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { validateJson } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
ProposalFormMinRequirements,
|
||||
ProposalFormTitle,
|
||||
ProposalFormDescription,
|
||||
ProposalFormTerms,
|
||||
ProposalFormSubmit,
|
||||
ProposalFormTransactionDialog,
|
||||
ProposalFormSubheader,
|
||||
ProposalFormVoteAndEnactmentDeadline,
|
||||
} from '../../components/propose';
|
||||
import { AsyncRenderer, Link } from '@vegaprotocol/ui-toolkit';
|
||||
import { Heading } from '../../../../components/heading';
|
||||
import { VegaWalletContainer } from '../../../../components/vega-wallet-container';
|
||||
import { NetworkParams, useNetworkParams } from '@vegaprotocol/react-helpers';
|
||||
|
||||
export interface UpdateAssetProposalFormFields {
|
||||
proposalVoteDeadline: string;
|
||||
proposalEnactmentDeadline: string;
|
||||
proposalTitle: string;
|
||||
proposalDescription: string;
|
||||
proposalTerms: string;
|
||||
proposalReference: string;
|
||||
}
|
||||
|
||||
const DOCS_LINK = '/update-asset-proposal';
|
||||
|
||||
export const ProposeUpdateAsset = () => {
|
||||
const {
|
||||
params,
|
||||
loading: networkParamsLoading,
|
||||
error: networkParamsError,
|
||||
} = useNetworkParams([
|
||||
NetworkParams.governance_proposal_updateAsset_minClose,
|
||||
NetworkParams.governance_proposal_updateAsset_maxClose,
|
||||
NetworkParams.governance_proposal_updateAsset_minEnact,
|
||||
NetworkParams.governance_proposal_updateAsset_maxEnact,
|
||||
NetworkParams.governance_proposal_updateAsset_minProposerBalance,
|
||||
NetworkParams.spam_protection_proposal_min_tokens,
|
||||
]);
|
||||
|
||||
const { VEGA_EXPLORER_URL, VEGA_DOCS_URL } = useEnvironment();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
register,
|
||||
handleSubmit,
|
||||
formState: { isSubmitting, errors },
|
||||
} = useForm<UpdateAssetProposalFormFields>();
|
||||
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
|
||||
|
||||
const onSubmit = async (fields: UpdateAssetProposalFormFields) => {
|
||||
await submit({
|
||||
rationale: {
|
||||
title: fields.proposalTitle,
|
||||
description: fields.proposalDescription,
|
||||
},
|
||||
terms: {
|
||||
updateAsset: {
|
||||
...JSON.parse(fields.proposalTerms),
|
||||
},
|
||||
closingTimestamp: getClosingTimestamp(fields.proposalVoteDeadline),
|
||||
enactmentTimestamp: getEnactmentTimestamp(
|
||||
fields.proposalVoteDeadline,
|
||||
fields.proposalEnactmentDeadline
|
||||
),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<AsyncRenderer
|
||||
loading={networkParamsLoading}
|
||||
error={networkParamsError}
|
||||
data={params}
|
||||
>
|
||||
<Heading title={t('UpdateAssetProposal')} />
|
||||
<VegaWalletContainer>
|
||||
{() => (
|
||||
<>
|
||||
<ProposalFormMinRequirements
|
||||
minProposerBalance={
|
||||
params.governance_proposal_updateAsset_minProposerBalance
|
||||
}
|
||||
spamProtectionMin={params.spam_protection_proposal_min_tokens}
|
||||
/>
|
||||
|
||||
{VEGA_DOCS_URL && (
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<Link
|
||||
href={`${VEGA_DOCS_URL}/tutorials/proposals${DOCS_LINK}`}
|
||||
target="_blank"
|
||||
>{`${VEGA_DOCS_URL}/tutorials/proposals${DOCS_LINK}`}</Link>
|
||||
</p>
|
||||
)}
|
||||
|
||||
{VEGA_EXPLORER_URL && (
|
||||
<p className="text-sm">
|
||||
{t('MoreAssetsInfo')}{' '}
|
||||
<Link
|
||||
href={`${VEGA_EXPLORER_URL}/assets`}
|
||||
target="_blank"
|
||||
>{`${VEGA_EXPLORER_URL}/assets`}</Link>
|
||||
</p>
|
||||
)}
|
||||
|
||||
<div data-testid="update-asset-proposal-form">
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<ProposalFormSubheader>
|
||||
{t('ProposalRationale')}
|
||||
</ProposalFormSubheader>
|
||||
|
||||
<ProposalFormTitle
|
||||
registerField={register('proposalTitle', {
|
||||
required: t('Required'),
|
||||
})}
|
||||
errorMessage={errors?.proposalTitle?.message}
|
||||
/>
|
||||
|
||||
<ProposalFormDescription
|
||||
registerField={register('proposalDescription', {
|
||||
required: t('Required'),
|
||||
})}
|
||||
errorMessage={errors?.proposalDescription?.message}
|
||||
/>
|
||||
|
||||
<ProposalFormSubheader>
|
||||
{t('UpdateAsset')}
|
||||
</ProposalFormSubheader>
|
||||
|
||||
<ProposalFormTerms
|
||||
registerField={register('proposalTerms', {
|
||||
required: t('Required'),
|
||||
validate: (value) => validateJson(value),
|
||||
})}
|
||||
labelOverride={'Terms.updateAsset (JSON format)'}
|
||||
errorMessage={errors?.proposalTerms?.message}
|
||||
customDocLink={DOCS_LINK}
|
||||
/>
|
||||
|
||||
<ProposalFormVoteAndEnactmentDeadline
|
||||
voteRegister={register('proposalVoteDeadline', {
|
||||
required: t('Required'),
|
||||
})}
|
||||
voteErrorMessage={errors?.proposalVoteDeadline?.message}
|
||||
voteMinClose={params.governance_proposal_updateAsset_minClose}
|
||||
voteMaxClose={params.governance_proposal_updateAsset_maxClose}
|
||||
enactmentRegister={register('proposalEnactmentDeadline', {
|
||||
required: t('Required'),
|
||||
})}
|
||||
enactmentErrorMessage={
|
||||
errors?.proposalEnactmentDeadline?.message
|
||||
}
|
||||
enactmentMinClose={
|
||||
params.governance_proposal_updateAsset_minEnact
|
||||
}
|
||||
enactmentMaxClose={
|
||||
params.governance_proposal_updateAsset_maxEnact
|
||||
}
|
||||
/>
|
||||
|
||||
<ProposalFormSubmit isSubmitting={isSubmitting} />
|
||||
<ProposalFormTransactionDialog
|
||||
finalizedProposal={finalizedProposal}
|
||||
TransactionDialog={Dialog}
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</VegaWalletContainer>
|
||||
</AsyncRenderer>
|
||||
);
|
||||
};
|
||||
+6
-6
@@ -178,17 +178,17 @@ describe('Propose Update Market', () => {
|
||||
|
||||
it('should render the select element with no initial value', async () => {
|
||||
renderComponent();
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText('Update market proposal')).toBeInTheDocument()
|
||||
);
|
||||
expect(
|
||||
await screen.findByText('Update market proposal')
|
||||
).toBeInTheDocument();
|
||||
expect(screen.getByTestId('proposal-market-select')).toHaveValue('');
|
||||
});
|
||||
|
||||
it('should render the correct market details when the market select is used', async () => {
|
||||
renderComponent();
|
||||
await waitFor(() =>
|
||||
expect(screen.getByText('Update market proposal')).toBeInTheDocument()
|
||||
);
|
||||
expect(
|
||||
await screen.findByText('Update market proposal')
|
||||
).toBeInTheDocument();
|
||||
fireEvent.change(screen.getByTestId('proposal-market-select'), {
|
||||
target: {
|
||||
value:
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
getEnactmentTimestamp,
|
||||
} from '@vegaprotocol/governance';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { validateJson } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
ProposalFormSubheader,
|
||||
ProposalFormMinRequirements,
|
||||
@@ -60,7 +61,7 @@ export interface UpdateMarketProposalFormFields {
|
||||
proposalReference: string;
|
||||
}
|
||||
|
||||
const docsLink = '/update-market-proposal';
|
||||
const DOCS_LINK = '/update-market-proposal';
|
||||
|
||||
export const ProposeUpdateMarket = () => {
|
||||
const {
|
||||
@@ -158,9 +159,9 @@ export const ProposeUpdateMarket = () => {
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<Link
|
||||
href={`${VEGA_DOCS_URL}/tutorials/proposals${docsLink}`}
|
||||
href={`${VEGA_DOCS_URL}/tutorials/proposals${DOCS_LINK}`}
|
||||
target="_blank"
|
||||
>{`${VEGA_DOCS_URL}/tutorials/proposals${docsLink}`}</Link>
|
||||
>{`${VEGA_DOCS_URL}/tutorials/proposals${DOCS_LINK}`}</Link>
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -255,20 +256,11 @@ export const ProposeUpdateMarket = () => {
|
||||
<ProposalFormTerms
|
||||
registerField={register('proposalTerms', {
|
||||
required: t('Required'),
|
||||
validate: {
|
||||
validateJson: (value) => {
|
||||
try {
|
||||
JSON.parse(value);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return t('Must be valid JSON');
|
||||
}
|
||||
},
|
||||
},
|
||||
validate: (value) => validateJson(value),
|
||||
})}
|
||||
labelOverride={t('ProposeUpdateMarketTerms')}
|
||||
errorMessage={errors?.proposalTerms?.message}
|
||||
customDocLink={docsLink}
|
||||
customDocLink={DOCS_LINK}
|
||||
/>
|
||||
|
||||
<ProposalFormVoteAndEnactmentDeadline
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { NETWORK_PARAMS_QUERY } from '@vegaprotocol/web3';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
import type { NetworkParamsQuery } from '@vegaprotocol/web3';
|
||||
import type { PubKey } from '@vegaprotocol/wallet';
|
||||
|
||||
export const mockPubkey = '0x123';
|
||||
export const mockPubkey: PubKey = {
|
||||
publicKey: '0x123',
|
||||
name: 'test key 1',
|
||||
};
|
||||
|
||||
export const mockWalletContext = {
|
||||
pubKey: mockPubkey,
|
||||
pubKey: mockPubkey.publicKey,
|
||||
pubKeys: [mockPubkey],
|
||||
sendTx: jest.fn().mockReturnValue(Promise.resolve(null)),
|
||||
connect: jest.fn(),
|
||||
|
||||
@@ -158,6 +158,13 @@ const LazyGovernanceProposeNewAsset = React.lazy(
|
||||
)
|
||||
);
|
||||
|
||||
const LazyGovernanceProposeUpdateAsset = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
/* webpackChunkName: "route-governance-propose-update-asset", webpackPrefetch: true */ './governance/propose/update-asset'
|
||||
)
|
||||
);
|
||||
|
||||
const LazyGovernanceProposeFreeform = React.lazy(
|
||||
() =>
|
||||
import(
|
||||
@@ -273,6 +280,10 @@ const routerConfig = [
|
||||
element: <LazyGovernanceProposeUpdateMarket />,
|
||||
},
|
||||
{ path: 'new-asset', element: <LazyGovernanceProposeNewAsset /> },
|
||||
{
|
||||
path: 'update-asset',
|
||||
element: <LazyGovernanceProposeUpdateAsset />,
|
||||
},
|
||||
{ path: 'freeform', element: <LazyGovernanceProposeFreeform /> },
|
||||
{ path: 'raw', element: <LazyGovernanceProposeRaw /> },
|
||||
],
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Heading } from '../../components/heading';
|
||||
import { SplashLoader } from '../../components/splash-loader';
|
||||
import { VegaWalletContainer } from '../../components/vega-wallet-container';
|
||||
import {
|
||||
PendingWithdrawalsTable,
|
||||
useWithdrawals,
|
||||
WithdrawalDialogs,
|
||||
WithdrawalsTable,
|
||||
@@ -30,7 +31,7 @@ const Withdrawals = ({ name }: RouteChildProps) => {
|
||||
const WithdrawPendingContainer = () => {
|
||||
const [withdrawDialog, setWithdrawDialog] = useState(false);
|
||||
const { t } = useTranslation();
|
||||
const { withdrawals, loading, error } = useWithdrawals();
|
||||
const { pending, completed, loading, error } = useWithdrawals();
|
||||
|
||||
if (error) {
|
||||
return (
|
||||
@@ -58,7 +59,11 @@ const WithdrawPendingContainer = () => {
|
||||
<p>{t('withdrawalsText')}</p>
|
||||
<p className="mb-8">{t('withdrawalsPreparedWarningText')}</p>
|
||||
<div className="w-full h-[500px]">
|
||||
<WithdrawalsTable withdrawals={withdrawals} />
|
||||
{pending && pending.length > 0 && (
|
||||
<PendingWithdrawalsTable rowData={pending} />
|
||||
)}
|
||||
<h4 className="pt-3 pb-1">{t('Withdrawal history')}</h4>
|
||||
<WithdrawalsTable rowData={completed} />
|
||||
</div>
|
||||
<WithdrawalDialogs
|
||||
withdrawDialog={withdrawDialog}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import { generateDepositPage } from '../support/mocks/generate-deposit-page';
|
||||
import { generateAssets } from '../support/mocks/generate-assets';
|
||||
import { generateNetworkParameters } from '../support/mocks/generate-network-parameters';
|
||||
|
||||
const connectEthWalletBtn = 'connect-eth-wallet-btn';
|
||||
@@ -14,7 +14,7 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
|
||||
cy.mockGQLSubscription();
|
||||
cy.mockGQL((req) => {
|
||||
aliasQuery(req, 'NetworkParamsQuery', generateNetworkParameters());
|
||||
aliasQuery(req, 'DepositPage', generateDepositPage());
|
||||
aliasQuery(req, 'Assets', generateAssets());
|
||||
});
|
||||
cy.visit('/portfolio/deposit');
|
||||
|
||||
@@ -22,7 +22,7 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
|
||||
cy.getByTestId(connectEthWalletBtn).click();
|
||||
cy.getByTestId('web3-connector-MetaMask').click();
|
||||
|
||||
cy.wait('@DepositPage');
|
||||
cy.wait('@Assets');
|
||||
});
|
||||
|
||||
it('handles empty fields', () => {
|
||||
@@ -41,7 +41,7 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
|
||||
|
||||
// Deposit amount smaller than minimum viable for selected asset
|
||||
// Select an amount so that we have a known decimal places value to work with
|
||||
cy.get(assetSelectField).select('Asset 0');
|
||||
cy.get(assetSelectField).select('Euro');
|
||||
cy.get(amountField)
|
||||
.clear()
|
||||
.type('0.00000000000000000000000000000000001')
|
||||
|
||||
@@ -115,7 +115,7 @@ describe('markets table', { tags: '@regression' }, () => {
|
||||
.should('have.attr', 'href')
|
||||
.and(
|
||||
'include',
|
||||
'https://docs.fairground.vega.xyz/docs/trading-questions/#auctions-what-is-a-liquidity-monitoring-auction'
|
||||
'https://docs.vega.xyz/docs/testnet/concepts/trading-on-vega/trading-modes#auction-type-liquidity-monitoring'
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -42,7 +42,6 @@ describe('orders', { tags: '@smoke' }, () => {
|
||||
|
||||
it('renders orders', () => {
|
||||
cy.getByTestId('tab-orders').should('be.visible');
|
||||
expect(subscriptionMocks.OrderSub).to.be.calledOnce;
|
||||
|
||||
cy.getByTestId('tab-orders').within(() => {
|
||||
cy.get(`[col-id='${orderSymbol}']`).each(($symbol) => {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import { connectEthereumWallet } from '../support/ethereum-wallet';
|
||||
import { generateAccounts } from '../support/mocks/generate-accounts';
|
||||
import { generateChainId } from '../support/mocks/generate-chain-id';
|
||||
import { generateAccounts } from '../support/mocks/generate-accounts';
|
||||
import { generateAssets } from '../support/mocks/generate-assets';
|
||||
import { generateNetworkParameters } from '../support/mocks/generate-network-parameters';
|
||||
import { generateWithdrawFormQuery } from '../support/mocks/generate-withdraw-page-query';
|
||||
import { generateWithdrawals } from '../support/mocks/generate-withdrawals';
|
||||
import { connectVegaWallet } from '../support/vega-wallet';
|
||||
|
||||
@@ -24,7 +24,7 @@ describe('withdraw', { tags: '@smoke' }, () => {
|
||||
aliasQuery(req, 'ChainId', generateChainId());
|
||||
aliasQuery(req, 'Withdrawals', generateWithdrawals());
|
||||
aliasQuery(req, 'NetworkParamsQuery', generateNetworkParameters());
|
||||
aliasQuery(req, 'WithdrawFormQuery', generateWithdrawFormQuery());
|
||||
aliasQuery(req, 'Assets', generateAssets());
|
||||
aliasQuery(req, 'Accounts', generateAccounts());
|
||||
});
|
||||
cy.mockGQLSubscription();
|
||||
@@ -39,7 +39,8 @@ describe('withdraw', { tags: '@smoke' }, () => {
|
||||
connectEthereumWallet();
|
||||
|
||||
cy.getByTestId('withdraw-dialog-button').click();
|
||||
cy.wait('@WithdrawFormQuery');
|
||||
cy.wait('@Accounts');
|
||||
cy.wait('@Assets');
|
||||
});
|
||||
|
||||
it('form validation', () => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { AccountsQuery, AssetsQuery } from '@vegaprotocol/accounts';
|
||||
import { AccountType, Schema as Types } from '@vegaprotocol/types';
|
||||
import type { AccountsQuery } from '@vegaprotocol/accounts';
|
||||
import { AccountType } from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateAccounts = (
|
||||
@@ -70,48 +70,19 @@ export const generateAccounts = (
|
||||
id: 'asset-0',
|
||||
},
|
||||
},
|
||||
// account to withdraw Sepolia tBTC
|
||||
{
|
||||
__typename: 'Account',
|
||||
type: AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
balance: '100000000',
|
||||
market: null,
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: 'cee709223217281d7893b650850ae8ee8a18b7539b5658f9b4cc24de95dd18ad',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
return merge(defaultAccounts, override);
|
||||
};
|
||||
|
||||
export const generateAssets = (override?: PartialDeep<AssetsQuery>) => {
|
||||
const defaultAssets: AssetsQuery = {
|
||||
assetsConnection: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
id: 'asset-id',
|
||||
symbol: 'tEURO',
|
||||
decimals: 5,
|
||||
name: 'Euro',
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-id-2',
|
||||
symbol: 'tDAI',
|
||||
decimals: 5,
|
||||
name: 'DAI',
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-0',
|
||||
symbol: 'AST0',
|
||||
decimals: 5,
|
||||
name: 'Asto',
|
||||
quantum: '',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
return merge(defaultAssets, override);
|
||||
};
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { AssetsQuery } from '@vegaprotocol/assets';
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateAssets = (override?: PartialDeep<AssetsQuery>) => {
|
||||
const defaultAssets: AssetsQuery = {
|
||||
assetsConnection: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
id: 'asset-id',
|
||||
symbol: 'tEURO',
|
||||
decimals: 5,
|
||||
name: 'Euro',
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x0158031158Bb4dF2AD02eAA31e8963E84EA978a4',
|
||||
},
|
||||
quantum: '1',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-id-2',
|
||||
symbol: 'tDAI',
|
||||
decimals: 5,
|
||||
name: 'DAI',
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x26223f9C67871CFcEa329975f7BC0C9cB8FBDb9b',
|
||||
},
|
||||
quantum: '1',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-0',
|
||||
symbol: 'AST0',
|
||||
decimals: 5,
|
||||
name: 'Asto',
|
||||
source: {
|
||||
__typename: 'BuiltinAsset',
|
||||
},
|
||||
quantum: '1',
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
},
|
||||
},
|
||||
// NOTE: These assets ids and contract addresses are real assets on Sepolia, this is needed
|
||||
// because we don't currently mock our seplia infura provider. If we change network these will
|
||||
// need to be updated
|
||||
{
|
||||
node: {
|
||||
id: 'cee709223217281d7893b650850ae8ee8a18b7539b5658f9b4cc24de95dd18ad',
|
||||
symbol: 'tBTC',
|
||||
name: 'Sepolia tBTC',
|
||||
decimals: 5,
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x1d525fB145Af5c51766a89706C09fE07E6058D1D',
|
||||
},
|
||||
quantum: '1',
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'AssetEdge',
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'c9fe6fc24fce121b2cc72680543a886055abb560043fda394ba5376203b7527d',
|
||||
symbol: 'tUSDC',
|
||||
name: 'Sepolia tUSDC',
|
||||
decimals: 5,
|
||||
status: Types.AssetStatus.STATUS_ENABLED,
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x444b9aDA947130Fc320a144cd22bC1641e5c9d81',
|
||||
},
|
||||
quantum: '1',
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'AssetEdge',
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
return merge(defaultAssets, override);
|
||||
};
|
||||
@@ -1,93 +0,0 @@
|
||||
import { AssetStatus } from '@vegaprotocol/types';
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateDepositPage = (
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
override?: PartialDeep<any>
|
||||
) => {
|
||||
const defaultResult = {
|
||||
assetsConnection: {
|
||||
edges: [
|
||||
{
|
||||
node: {
|
||||
id: 'asset-0',
|
||||
symbol: 'AST0',
|
||||
name: 'Asset 0',
|
||||
decimals: 5,
|
||||
status: AssetStatus.STATUS_ENABLED,
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x5E4b9aDA947130Fc320a144cd22bC1641e5c9d81',
|
||||
},
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'AssetEdge',
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-1',
|
||||
symbol: 'AST1',
|
||||
name: 'Asset 1',
|
||||
decimals: 5,
|
||||
status: AssetStatus.STATUS_ENABLED,
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x444b9aDA947130Fc320a144cd22bC1641e5c9d81',
|
||||
},
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'AssetEdge',
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-2',
|
||||
symbol: 'AST2',
|
||||
name: 'Asset 2',
|
||||
decimals: 5,
|
||||
status: AssetStatus.STATUS_PENDING_LISTING,
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x444b9aDA947130Fc320a144cd22bC1641e5c9d82',
|
||||
},
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'AssetEdge',
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-3',
|
||||
symbol: 'AST3',
|
||||
name: 'Asset 3',
|
||||
decimals: 5,
|
||||
status: AssetStatus.STATUS_PROPOSED,
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x444b9aDA947130Fc320a144cd22bC1641e5c9d83',
|
||||
},
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'AssetEdge',
|
||||
},
|
||||
{
|
||||
node: {
|
||||
id: 'asset-4',
|
||||
symbol: 'AST4',
|
||||
name: 'Asset 4',
|
||||
decimals: 5,
|
||||
status: AssetStatus.STATUS_REJECTED,
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x444b9aDA947130Fc320a144cd22bC1641e5c9d84',
|
||||
},
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'AssetEdge',
|
||||
},
|
||||
],
|
||||
__typename: 'AssetsConnection',
|
||||
},
|
||||
};
|
||||
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
@@ -1,15 +1,15 @@
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type {
|
||||
Positions,
|
||||
Positions_party_positionsConnection_edges_node,
|
||||
Margins,
|
||||
PositionsQuery,
|
||||
PositionFieldsFragment,
|
||||
MarginsQuery,
|
||||
} from '@vegaprotocol/positions';
|
||||
|
||||
export const generatePositions = (
|
||||
override?: PartialDeep<Positions>
|
||||
): Positions => {
|
||||
const nodes: Positions_party_positionsConnection_edges_node[] = [
|
||||
override?: PartialDeep<PositionsQuery>
|
||||
): PositionsQuery => {
|
||||
const nodes: PositionFieldsFragment[] = [
|
||||
{
|
||||
__typename: 'Position',
|
||||
realisedPNL: '0',
|
||||
@@ -48,7 +48,7 @@ export const generatePositions = (
|
||||
},
|
||||
];
|
||||
|
||||
const defaultResult: Positions = {
|
||||
const defaultResult: PositionsQuery = {
|
||||
party: {
|
||||
__typename: 'Party',
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
@@ -67,7 +67,7 @@ export const generatePositions = (
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
|
||||
export const generateMargins = (): Margins => {
|
||||
export const generateMargins = (): MarginsQuery => {
|
||||
return {
|
||||
party: {
|
||||
id: Cypress.env('VEGA_PUBLIC_KEY'),
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
import { AccountType, AssetStatus } from '@vegaprotocol/types';
|
||||
import type {
|
||||
WithdrawFormQuery,
|
||||
WithdrawFormQuery_assetsConnection_edges,
|
||||
WithdrawFormQuery_party_accounts,
|
||||
WithdrawFormQuery_party_withdrawals,
|
||||
} from '@vegaprotocol/withdraws';
|
||||
import merge from 'lodash/merge';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
|
||||
export const generateWithdrawFormQuery = (
|
||||
override?: PartialDeep<WithdrawFormQuery>
|
||||
): WithdrawFormQuery => {
|
||||
const withdrawal: WithdrawFormQuery_party_withdrawals = {
|
||||
id: 'withdrawal-0',
|
||||
txHash: null,
|
||||
__typename: 'Withdrawal',
|
||||
};
|
||||
|
||||
// NOTE: These assets ids and contract addresses are real assets on Sepolia, this is needed
|
||||
// because we don't currently mock our seplia infura provider. If we change network these will
|
||||
// need to be updated
|
||||
const assetEdge1: WithdrawFormQuery_assetsConnection_edges = {
|
||||
node: {
|
||||
id: 'cee709223217281d7893b650850ae8ee8a18b7539b5658f9b4cc24de95dd18ad',
|
||||
symbol: 'tBTC',
|
||||
name: 'Sepolia tBTC',
|
||||
decimals: 5,
|
||||
status: AssetStatus.STATUS_ENABLED,
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x1d525fB145Af5c51766a89706C09fE07E6058D1D',
|
||||
},
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'AssetEdge',
|
||||
};
|
||||
const assetEdge2: WithdrawFormQuery_assetsConnection_edges = {
|
||||
node: {
|
||||
id: 'c9fe6fc24fce121b2cc72680543a886055abb560043fda394ba5376203b7527d',
|
||||
symbol: 'tUSDC',
|
||||
name: 'Sepolia tUSDC',
|
||||
decimals: 5,
|
||||
status: AssetStatus.STATUS_ENABLED,
|
||||
source: {
|
||||
__typename: 'ERC20',
|
||||
contractAddress: '0x444b9aDA947130Fc320a144cd22bC1641e5c9d81',
|
||||
},
|
||||
__typename: 'Asset',
|
||||
},
|
||||
__typename: 'AssetEdge',
|
||||
};
|
||||
const account: WithdrawFormQuery_party_accounts = {
|
||||
type: AccountType.ACCOUNT_TYPE_GENERAL,
|
||||
balance: '100000000',
|
||||
asset: {
|
||||
__typename: 'Asset',
|
||||
id: assetEdge1.node.id,
|
||||
symbol: 'AST0',
|
||||
},
|
||||
__typename: 'Account',
|
||||
};
|
||||
|
||||
const defaultResult = {
|
||||
party: {
|
||||
id: 'party-0',
|
||||
withdrawals: [withdrawal],
|
||||
accounts: [account],
|
||||
__typename: 'Party',
|
||||
},
|
||||
assetsConnection: {
|
||||
__typename: 'AssetsConnection',
|
||||
edges: [assetEdge1, assetEdge2],
|
||||
},
|
||||
};
|
||||
return merge(defaultResult, override);
|
||||
};
|
||||
@@ -1,7 +1,8 @@
|
||||
import { aliasQuery } from '@vegaprotocol/cypress';
|
||||
import type { MarketState } from '@vegaprotocol/types';
|
||||
import type { CyHttpMessages } from 'cypress/types/net-stubbing';
|
||||
import { generateAccounts, generateAssets } from './mocks/generate-accounts';
|
||||
import { generateAccounts } from './mocks/generate-accounts';
|
||||
import { generateAssets } from './mocks/generate-assets';
|
||||
import { generateCandles } from './mocks/generate-candles';
|
||||
import { generateChart } from './mocks/generate-chart';
|
||||
import { generateDealTicketQuery } from './mocks/generate-deal-ticket-query';
|
||||
|
||||
@@ -15,7 +15,7 @@ import type {
|
||||
MarketWithData,
|
||||
} from '@vegaprotocol/market-list';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import type { Positions_party_positionsConnection_edges_node } from '@vegaprotocol/positions';
|
||||
import type { PositionFieldsFragment } from '@vegaprotocol/positions';
|
||||
import { positionsDataProvider } from '@vegaprotocol/positions';
|
||||
import {
|
||||
SelectMarketTableHeader,
|
||||
@@ -79,7 +79,7 @@ export const SelectAllMarketsTableBody = ({
|
||||
tableColumns = (market) => columns(market, onSelect, onCellClick),
|
||||
}: {
|
||||
markets?: Market[] | null;
|
||||
positions?: Positions_party_positionsConnection_edges_node[];
|
||||
positions?: PositionFieldsFragment[];
|
||||
title?: string;
|
||||
onSelect: (id: string) => void;
|
||||
onCellClick: OnCellClickHandler;
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const ASSET_FRAGMENT = gql`
|
||||
fragment AssetFields on Asset {
|
||||
id
|
||||
symbol
|
||||
name
|
||||
decimals
|
||||
status
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -4,6 +4,7 @@ import {
|
||||
addDecimalsFormatNumber,
|
||||
t,
|
||||
titlefy,
|
||||
useYesterday,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { Interval } from '@vegaprotocol/types';
|
||||
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
@@ -113,12 +114,12 @@ const MarketPage = ({ id }: { id?: string }) => {
|
||||
}
|
||||
};
|
||||
|
||||
const yesterday = useYesterday();
|
||||
// Cache timestamp for yesterday to prevent full unmount of market page when
|
||||
// a rerender occurs
|
||||
const yTimestamp = useMemo(() => {
|
||||
const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
|
||||
return new Date(yesterday * 1000).toISOString();
|
||||
}, []);
|
||||
return new Date(yesterday).toISOString();
|
||||
}, [yesterday]);
|
||||
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
query DepositPage {
|
||||
assetsConnection {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
symbol
|
||||
name
|
||||
decimals
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @generated
|
||||
// This file was automatically generated and should not be edited.
|
||||
|
||||
import { AssetStatus } from "@vegaprotocol/types";
|
||||
|
||||
// ====================================================
|
||||
// GraphQL query operation: DepositPage
|
||||
// ====================================================
|
||||
|
||||
export interface DepositPage_assetsConnection_edges_node_source_BuiltinAsset {
|
||||
__typename: "BuiltinAsset";
|
||||
}
|
||||
|
||||
export interface DepositPage_assetsConnection_edges_node_source_ERC20 {
|
||||
__typename: "ERC20";
|
||||
/**
|
||||
* The address of the ERC20 contract
|
||||
*/
|
||||
contractAddress: string;
|
||||
}
|
||||
|
||||
export type DepositPage_assetsConnection_edges_node_source = DepositPage_assetsConnection_edges_node_source_BuiltinAsset | DepositPage_assetsConnection_edges_node_source_ERC20;
|
||||
|
||||
export interface DepositPage_assetsConnection_edges_node {
|
||||
__typename: "Asset";
|
||||
/**
|
||||
* The ID of the asset
|
||||
*/
|
||||
id: string;
|
||||
/**
|
||||
* The symbol of the asset (e.g: GBP)
|
||||
*/
|
||||
symbol: string;
|
||||
/**
|
||||
* The full name of the asset (e.g: Great British Pound)
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* The precision of the asset. Should match the decimal precision of the asset on its native chain, e.g: for ERC20 assets, it is often 18
|
||||
*/
|
||||
decimals: number;
|
||||
/**
|
||||
* The status of the asset in the Vega network
|
||||
*/
|
||||
status: AssetStatus;
|
||||
/**
|
||||
* The origin source of the asset (e.g: an ERC20 asset)
|
||||
*/
|
||||
source: DepositPage_assetsConnection_edges_node_source;
|
||||
}
|
||||
|
||||
export interface DepositPage_assetsConnection_edges {
|
||||
__typename: "AssetEdge";
|
||||
/**
|
||||
* The asset information
|
||||
*/
|
||||
node: DepositPage_assetsConnection_edges_node;
|
||||
}
|
||||
|
||||
export interface DepositPage_assetsConnection {
|
||||
__typename: "AssetsConnection";
|
||||
/**
|
||||
* The assets
|
||||
*/
|
||||
edges: (DepositPage_assetsConnection_edges | null)[] | null;
|
||||
}
|
||||
|
||||
export interface DepositPage {
|
||||
/**
|
||||
* The list of all assets in use in the Vega network or the specified asset if ID is provided
|
||||
*/
|
||||
assetsConnection: DepositPage_assetsConnection | null;
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type DepositPageQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type DepositPageQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, symbol: string, name: string, decimals: number, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } } | null> | null } | null };
|
||||
|
||||
|
||||
export const DepositPageDocument = gql`
|
||||
query DepositPage {
|
||||
assetsConnection {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
symbol
|
||||
name
|
||||
decimals
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useDepositPageQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useDepositPageQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useDepositPageQuery` 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 } = useDepositPageQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useDepositPageQuery(baseOptions?: Apollo.QueryHookOptions<DepositPageQuery, DepositPageQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<DepositPageQuery, DepositPageQueryVariables>(DepositPageDocument, options);
|
||||
}
|
||||
export function useDepositPageLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DepositPageQuery, DepositPageQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<DepositPageQuery, DepositPageQueryVariables>(DepositPageDocument, options);
|
||||
}
|
||||
export type DepositPageQueryHookResult = ReturnType<typeof useDepositPageQuery>;
|
||||
export type DepositPageLazyQueryHookResult = ReturnType<typeof useDepositPageLazyQuery>;
|
||||
export type DepositPageQueryResult = Apollo.QueryResult<DepositPageQuery, DepositPageQueryVariables>;
|
||||
@@ -1,37 +1,24 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { PageQueryContainer } from '../../../components/page-query-container';
|
||||
import type { DepositPage } from './__generated__/DepositPage';
|
||||
import { DepositManager } from '@vegaprotocol/deposits';
|
||||
import { getEnabledAssets, t } from '@vegaprotocol/react-helpers';
|
||||
import { useDataProvider, t } from '@vegaprotocol/react-helpers';
|
||||
import { enabledAssetsProvider } from '@vegaprotocol/assets';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { ASSET_FRAGMENT } from '../../../lib/query-fragments';
|
||||
|
||||
const DEPOSIT_PAGE_QUERY = gql`
|
||||
${ASSET_FRAGMENT}
|
||||
query DepositPage {
|
||||
assetsConnection {
|
||||
edges {
|
||||
node {
|
||||
...AssetFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
/**
|
||||
* Fetches data required for the Deposit page
|
||||
*/
|
||||
export const DepositContainer = () => {
|
||||
const { VEGA_ENV } = useEnvironment();
|
||||
|
||||
const { data, error, loading } = useDataProvider({
|
||||
dataProvider: enabledAssetsProvider,
|
||||
});
|
||||
return (
|
||||
<PageQueryContainer<DepositPage>
|
||||
query={DEPOSIT_PAGE_QUERY}
|
||||
render={(data) => {
|
||||
const assets = getEnabledAssets(data);
|
||||
if (!assets.length) {
|
||||
<AsyncRenderer
|
||||
data={data}
|
||||
error={error}
|
||||
loading={loading}
|
||||
render={(assets) => {
|
||||
if (!assets || !assets.length) {
|
||||
return (
|
||||
<Splash>
|
||||
<p>{t('No assets on this network')}</p>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { AsyncRenderer, Button } from '@vegaprotocol/ui-toolkit';
|
||||
import {
|
||||
PendingWithdrawalsTable,
|
||||
useWithdrawals,
|
||||
WithdrawalDialogs,
|
||||
WithdrawalsTable,
|
||||
@@ -10,7 +11,7 @@ import { VegaWalletContainer } from '../../components/vega-wallet-container';
|
||||
import { Web3Container } from '@vegaprotocol/web3';
|
||||
|
||||
export const WithdrawalsContainer = () => {
|
||||
const { withdrawals, loading, error } = useWithdrawals();
|
||||
const { pending, completed, loading, error } = useWithdrawals();
|
||||
const [withdrawDialog, setWithdrawDialog] = useState(false);
|
||||
|
||||
return (
|
||||
@@ -25,17 +26,27 @@ export const WithdrawalsContainer = () => {
|
||||
onClick={() => setWithdrawDialog(true)}
|
||||
data-testid="withdraw-dialog-button"
|
||||
>
|
||||
{t('Withdraw')}
|
||||
{t('Make withdrawal')}
|
||||
</Button>
|
||||
</header>
|
||||
<div>
|
||||
<div className="h-full px-4">
|
||||
<AsyncRenderer
|
||||
data={withdrawals}
|
||||
data={{ pending, completed }}
|
||||
loading={loading}
|
||||
error={error}
|
||||
render={(data) => {
|
||||
return <WithdrawalsTable withdrawals={data} />;
|
||||
}}
|
||||
render={({ pending, completed }) => (
|
||||
<>
|
||||
{pending && pending.length > 0 && (
|
||||
<>
|
||||
<h4 className="pt-3 pb-1">{t('Pending withdrawals')}</h4>
|
||||
<PendingWithdrawalsTable rowData={pending} />
|
||||
</>
|
||||
)}
|
||||
|
||||
<h4 className="pt-3 pb-1">{t('Withdrawal history')}</h4>
|
||||
<WithdrawalsTable rowData={completed} />
|
||||
</>
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -26,22 +26,3 @@ subscription AccountEvents($partyId: ID!) {
|
||||
marketId
|
||||
}
|
||||
}
|
||||
|
||||
fragment AssetsFields on Asset {
|
||||
id
|
||||
name
|
||||
symbol
|
||||
decimals
|
||||
quantum
|
||||
status
|
||||
}
|
||||
|
||||
query Assets {
|
||||
assetsConnection {
|
||||
edges {
|
||||
node {
|
||||
...AssetsFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,6 @@ export type AccountEventsSubscriptionVariables = Types.Exact<{
|
||||
|
||||
export type AccountEventsSubscription = { __typename?: 'Subscription', accounts: Array<{ __typename?: 'AccountUpdate', type: Types.AccountType, balance: string, assetId: string, marketId?: string | null }> };
|
||||
|
||||
export type AssetsFieldsFragment = { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, quantum: string, status: Types.AssetStatus };
|
||||
|
||||
export type AssetsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type AssetsQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, quantum: string, status: Types.AssetStatus } } | null> | null } | null };
|
||||
|
||||
export const AccountFieldsFragmentDoc = gql`
|
||||
fragment AccountFields on Account {
|
||||
type
|
||||
@@ -38,16 +31,6 @@ export const AccountFieldsFragmentDoc = gql`
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const AssetsFieldsFragmentDoc = gql`
|
||||
fragment AssetsFields on Asset {
|
||||
id
|
||||
name
|
||||
symbol
|
||||
decimals
|
||||
quantum
|
||||
status
|
||||
}
|
||||
`;
|
||||
export const AccountsDocument = gql`
|
||||
query Accounts($partyId: ID!) {
|
||||
party(id: $partyId) {
|
||||
@@ -118,42 +101,4 @@ export function useAccountEventsSubscription(baseOptions: Apollo.SubscriptionHoo
|
||||
return Apollo.useSubscription<AccountEventsSubscription, AccountEventsSubscriptionVariables>(AccountEventsDocument, options);
|
||||
}
|
||||
export type AccountEventsSubscriptionHookResult = ReturnType<typeof useAccountEventsSubscription>;
|
||||
export type AccountEventsSubscriptionResult = Apollo.SubscriptionResult<AccountEventsSubscription>;
|
||||
export const AssetsDocument = gql`
|
||||
query Assets {
|
||||
assetsConnection {
|
||||
edges {
|
||||
node {
|
||||
...AssetsFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${AssetsFieldsFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __useAssetsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useAssetsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useAssetsQuery` 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 } = useAssetsQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useAssetsQuery(baseOptions?: Apollo.QueryHookOptions<AssetsQuery, AssetsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<AssetsQuery, AssetsQueryVariables>(AssetsDocument, options);
|
||||
}
|
||||
export function useAssetsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<AssetsQuery, AssetsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<AssetsQuery, AssetsQueryVariables>(AssetsDocument, options);
|
||||
}
|
||||
export type AssetsQueryHookResult = ReturnType<typeof useAssetsQuery>;
|
||||
export type AssetsLazyQueryHookResult = ReturnType<typeof useAssetsLazyQuery>;
|
||||
export type AssetsQueryResult = Apollo.QueryResult<AssetsQuery, AssetsQueryVariables>;
|
||||
export type AccountEventsSubscriptionResult = Apollo.SubscriptionResult<AccountEventsSubscription>;
|
||||
@@ -8,7 +8,6 @@ import type {
|
||||
AccountFieldsFragment,
|
||||
AccountsQuery,
|
||||
AccountEventsSubscription,
|
||||
AssetsFieldsFragment,
|
||||
} from './__generated___/Accounts';
|
||||
import {
|
||||
makeDataProvider,
|
||||
@@ -17,7 +16,8 @@ import {
|
||||
import { AccountType } from '@vegaprotocol/types';
|
||||
import type { Market } from '@vegaprotocol/market-list';
|
||||
import { marketsProvider } from '@vegaprotocol/market-list';
|
||||
import { assetProvider } from './asset-data-provider';
|
||||
import type { AssetsFieldsFragment } from '@vegaprotocol/assets';
|
||||
import { assetsProvider } from '@vegaprotocol/assets';
|
||||
|
||||
function isAccount(
|
||||
account:
|
||||
@@ -77,7 +77,7 @@ const getDelta = (
|
||||
subscriptionData: AccountEventsSubscription
|
||||
): AccountEventsSubscription['accounts'] => subscriptionData.accounts;
|
||||
|
||||
export const accountsBasedDataProvider = makeDataProvider<
|
||||
export const accountsOnlyDataProvider = makeDataProvider<
|
||||
AccountsQuery,
|
||||
AccountFieldsFragment[],
|
||||
AccountEventsSubscription,
|
||||
@@ -114,10 +114,12 @@ const getTotalBalance = (accounts: AccountFieldsFragment[]) =>
|
||||
accounts.reduce((acc, a) => acc + BigInt(a.balance), BigInt(0));
|
||||
|
||||
export const getAccountData = (data: Account[]): AccountFields[] => {
|
||||
return getAssetIds(data).map((assetId) => {
|
||||
const accounts = data.filter((a) => a.asset.id === assetId);
|
||||
return accounts && getAssetAccountAggregation(accounts, assetId);
|
||||
});
|
||||
return getAssetIds(data)
|
||||
.map((assetId) => {
|
||||
const accounts = data.filter((a) => a.asset.id === assetId);
|
||||
return accounts && getAssetAccountAggregation(accounts, assetId);
|
||||
})
|
||||
.filter((a) => a.deposited !== '0'); // filter empty accounts
|
||||
};
|
||||
|
||||
const getAssetAccountAggregation = (
|
||||
@@ -150,12 +152,13 @@ const getAssetAccountAggregation = (
|
||||
deposited: balanceAccount.deposited,
|
||||
available: balanceAccount.available,
|
||||
used: a.balance,
|
||||
}));
|
||||
}))
|
||||
.filter((a) => a.used !== '0');
|
||||
return { ...balanceAccount, breakdown };
|
||||
};
|
||||
|
||||
export const accountsDataProvider = makeDerivedDataProvider<Account[], never>(
|
||||
[accountsBasedDataProvider, marketsProvider, assetProvider],
|
||||
[accountsOnlyDataProvider, marketsProvider, assetsProvider],
|
||||
([accounts, markets, assets]): Account[] | null => {
|
||||
return accounts
|
||||
? accounts
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Asset } from '@vegaprotocol/react-helpers';
|
||||
import type { Asset } from '@vegaprotocol/assets';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
|
||||
@@ -38,7 +38,7 @@ describe('AccountsTable', () => {
|
||||
<AccountTable rowData={singleRowData} onClickAsset={() => null} />
|
||||
);
|
||||
});
|
||||
const expectedHeaders = ['Asset', 'Deposited', 'Used', '', ''];
|
||||
const expectedHeaders = ['Asset', 'Total', 'Used', '', ''];
|
||||
const headers = await screen.findAllByRole('columnheader');
|
||||
expect(headers).toHaveLength(expectedHeaders.length);
|
||||
expect(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { forwardRef, useState } from 'react';
|
||||
import type { ValueFormatterParams } from 'ag-grid-community';
|
||||
import type { Asset } from '@vegaprotocol/react-helpers';
|
||||
import type { Asset } from '@vegaprotocol/assets';
|
||||
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
|
||||
import type {
|
||||
ValueProps,
|
||||
@@ -109,8 +109,11 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
||||
maxWidth={300}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Deposited')}
|
||||
headerName={t('Total')}
|
||||
field="deposited"
|
||||
headerTooltip={t(
|
||||
'This is the total amount of collateral used plus the amount available in your general account.'
|
||||
)}
|
||||
valueFormatter={({
|
||||
value,
|
||||
data,
|
||||
@@ -125,6 +128,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
||||
headerName={t('Used')}
|
||||
field="used"
|
||||
flex={2}
|
||||
minWidth={150}
|
||||
maxWidth={500}
|
||||
headerComponentParams={progressBarHeaderComponentParams}
|
||||
cellRendererSelector={progressBarCellRendererSelector}
|
||||
@@ -133,7 +137,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
||||
<AgGridColumn
|
||||
headerName=""
|
||||
field="breakdown"
|
||||
maxWidth={150}
|
||||
minWidth={150}
|
||||
cellRenderer={({
|
||||
value,
|
||||
}: VegaICellRendererParams<AccountFields, 'breakdown'>) => {
|
||||
@@ -154,6 +158,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
||||
colId="transact"
|
||||
headerName=""
|
||||
sortable={false}
|
||||
minWidth={250}
|
||||
cellRenderer={({
|
||||
data,
|
||||
}: VegaICellRendererParams<AccountFields>) => {
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
import { makeDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { AssetsDocument } from './__generated___/Accounts';
|
||||
import type {
|
||||
AssetsQuery,
|
||||
AssetsFieldsFragment,
|
||||
} from './__generated___/Accounts';
|
||||
|
||||
const getData = (responseData: AssetsQuery) =>
|
||||
responseData.assetsConnection?.edges
|
||||
?.filter((e) => Boolean(e?.node))
|
||||
.map((e) => e?.node as AssetsFieldsFragment) ?? null;
|
||||
|
||||
export const assetProvider = makeDataProvider<
|
||||
AssetsQuery,
|
||||
AssetsFieldsFragment[] | null,
|
||||
never,
|
||||
never
|
||||
>({
|
||||
query: AssetsDocument,
|
||||
getData,
|
||||
});
|
||||
@@ -37,10 +37,10 @@ describe('BreakdownTable', () => {
|
||||
render(<BreakdownTable data={singleRowData} />);
|
||||
});
|
||||
const headers = await screen.findAllByRole('columnheader');
|
||||
expect(headers).toHaveLength(5);
|
||||
expect(headers).toHaveLength(4);
|
||||
expect(
|
||||
headers.map((h) => h.querySelector('[ref="eText"]')?.textContent?.trim())
|
||||
).toEqual(['Account type', 'Market', 'Used', 'Deposited', 'Balance']);
|
||||
).toEqual(['Account type', 'Market', 'Used', 'Balance']);
|
||||
});
|
||||
|
||||
it('should apply correct formatting', async () => {
|
||||
|
||||
@@ -74,21 +74,6 @@ const BreakdownTable = forwardRef<AgGridReact, BreakdownTableProps>(
|
||||
cellRendererSelector={progressBarCellRendererSelector}
|
||||
valueFormatter={progressBarValueFormatter}
|
||||
/>
|
||||
|
||||
<AgGridColumn
|
||||
headerName={t('Deposited')}
|
||||
field="deposited"
|
||||
valueFormatter={({
|
||||
value,
|
||||
data,
|
||||
}: VegaValueFormatterParams<AccountFields, 'deposited'>) => {
|
||||
if (data && data.asset) {
|
||||
return addDecimalsFormatNumber(value, data.asset.decimals);
|
||||
}
|
||||
return '-';
|
||||
}}
|
||||
maxWidth={300}
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Balance')}
|
||||
field="balance"
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
query Asset($assetId: ID!) {
|
||||
asset(id: $assetId) {
|
||||
id
|
||||
name
|
||||
symbol
|
||||
decimals
|
||||
quantum
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
lifetimeLimit
|
||||
withdrawThreshold
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,22 @@
|
||||
query AssetsConnection {
|
||||
fragment AssetsFields on Asset {
|
||||
id
|
||||
name
|
||||
symbol
|
||||
decimals
|
||||
quantum
|
||||
status
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
query Assets {
|
||||
assetsConnection {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
symbol
|
||||
decimals
|
||||
quantum
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
lifetimeLimit
|
||||
withdrawThreshold
|
||||
}
|
||||
}
|
||||
...AssetsFields
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
import { Schema as Types } from '@vegaprotocol/types';
|
||||
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type AssetQueryVariables = Types.Exact<{
|
||||
assetId: Types.Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type AssetQuery = { __typename?: 'Query', asset?: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string, lifetimeLimit: string, withdrawThreshold: string } } | null };
|
||||
|
||||
|
||||
export const AssetDocument = gql`
|
||||
query Asset($assetId: ID!) {
|
||||
asset(id: $assetId) {
|
||||
id
|
||||
name
|
||||
symbol
|
||||
decimals
|
||||
quantum
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
lifetimeLimit
|
||||
withdrawThreshold
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useAssetQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useAssetQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useAssetQuery` 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 } = useAssetQuery({
|
||||
* variables: {
|
||||
* assetId: // value for 'assetId'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useAssetQuery(baseOptions: Apollo.QueryHookOptions<AssetQuery, AssetQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<AssetQuery, AssetQueryVariables>(AssetDocument, options);
|
||||
}
|
||||
export function useAssetLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<AssetQuery, AssetQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<AssetQuery, AssetQueryVariables>(AssetDocument, options);
|
||||
}
|
||||
export type AssetQueryHookResult = ReturnType<typeof useAssetQuery>;
|
||||
export type AssetLazyQueryHookResult = ReturnType<typeof useAssetLazyQuery>;
|
||||
export type AssetQueryResult = Apollo.QueryResult<AssetQuery, AssetQueryVariables>;
|
||||
@@ -3,58 +3,63 @@ import { Schema as Types } from '@vegaprotocol/types';
|
||||
import { gql } from '@apollo/client';
|
||||
import * as Apollo from '@apollo/client';
|
||||
const defaultOptions = {} as const;
|
||||
export type AssetsConnectionQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
export type AssetsFieldsFragment = { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, quantum: string, status: Types.AssetStatus, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } };
|
||||
|
||||
export type AssetsQueryVariables = Types.Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type AssetsConnectionQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, quantum: string, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string, lifetimeLimit: string, withdrawThreshold: string } } } | null> | null } | null };
|
||||
export type AssetsQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, quantum: string, status: Types.AssetStatus, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } } | null> | null } | null };
|
||||
|
||||
|
||||
export const AssetsConnectionDocument = gql`
|
||||
query AssetsConnection {
|
||||
assetsConnection {
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
symbol
|
||||
decimals
|
||||
quantum
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
lifetimeLimit
|
||||
withdrawThreshold
|
||||
}
|
||||
}
|
||||
}
|
||||
export const AssetsFieldsFragmentDoc = gql`
|
||||
fragment AssetsFields on Asset {
|
||||
id
|
||||
name
|
||||
symbol
|
||||
decimals
|
||||
quantum
|
||||
status
|
||||
source {
|
||||
... on ERC20 {
|
||||
contractAddress
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export const AssetsDocument = gql`
|
||||
query Assets {
|
||||
assetsConnection {
|
||||
edges {
|
||||
node {
|
||||
...AssetsFields
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${AssetsFieldsFragmentDoc}`;
|
||||
|
||||
/**
|
||||
* __useAssetsConnectionQuery__
|
||||
* __useAssetsQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useAssetsConnectionQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useAssetsConnectionQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* To run a query within a React component, call `useAssetsQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useAssetsQuery` 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 } = useAssetsConnectionQuery({
|
||||
* const { data, loading, error } = useAssetsQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useAssetsConnectionQuery(baseOptions?: Apollo.QueryHookOptions<AssetsConnectionQuery, AssetsConnectionQueryVariables>) {
|
||||
export function useAssetsQuery(baseOptions?: Apollo.QueryHookOptions<AssetsQuery, AssetsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<AssetsConnectionQuery, AssetsConnectionQueryVariables>(AssetsConnectionDocument, options);
|
||||
return Apollo.useQuery<AssetsQuery, AssetsQueryVariables>(AssetsDocument, options);
|
||||
}
|
||||
export function useAssetsConnectionLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<AssetsConnectionQuery, AssetsConnectionQueryVariables>) {
|
||||
export function useAssetsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<AssetsQuery, AssetsQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<AssetsConnectionQuery, AssetsConnectionQueryVariables>(AssetsConnectionDocument, options);
|
||||
return Apollo.useLazyQuery<AssetsQuery, AssetsQueryVariables>(AssetsDocument, options);
|
||||
}
|
||||
export type AssetsConnectionQueryHookResult = ReturnType<typeof useAssetsConnectionQuery>;
|
||||
export type AssetsConnectionLazyQueryHookResult = ReturnType<typeof useAssetsConnectionLazyQuery>;
|
||||
export type AssetsConnectionQueryResult = Apollo.QueryResult<AssetsConnectionQuery, AssetsConnectionQueryVariables>;
|
||||
export type AssetsQueryHookResult = ReturnType<typeof useAssetsQuery>;
|
||||
export type AssetsLazyQueryHookResult = ReturnType<typeof useAssetsLazyQuery>;
|
||||
export type AssetsQueryResult = Apollo.QueryResult<AssetsQuery, AssetsQueryVariables>;
|
||||
@@ -1,7 +1,7 @@
|
||||
import { MockedProvider } from '@apollo/react-testing';
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import { AssetDetailsDialog } from './asset-details-dialog';
|
||||
import { AssetsConnectionDocument } from './__generated___/Assets';
|
||||
import { AssetsDocument } from './__generated___/Assets';
|
||||
|
||||
const mockedData = {
|
||||
data: {
|
||||
@@ -273,7 +273,7 @@ const mockedData = {
|
||||
const mocks = [
|
||||
{
|
||||
request: {
|
||||
query: AssetsConnectionDocument,
|
||||
query: AssetsDocument,
|
||||
variables: {},
|
||||
},
|
||||
result: mockedData,
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
|
||||
import type { Asset } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
t,
|
||||
useDataProvider,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import type { Asset } from './assets-data-provider';
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
@@ -9,7 +13,7 @@ import {
|
||||
Splash,
|
||||
Tooltip,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { useAssetsConnectionQuery } from './__generated___/Assets';
|
||||
import { assetsProvider } from './assets-data-provider';
|
||||
import type { Schema } from '@vegaprotocol/types';
|
||||
import create from 'zustand';
|
||||
|
||||
@@ -59,12 +63,10 @@ export const AssetDetailsDialog = ({
|
||||
open,
|
||||
onChange,
|
||||
}: AssetDetailsDialogProps) => {
|
||||
const { data } = useAssetsConnectionQuery();
|
||||
const { data } = useDataProvider({ dataProvider: assetsProvider });
|
||||
const symbol =
|
||||
typeof assetSymbol === 'string' ? assetSymbol : assetSymbol.symbol;
|
||||
const asset = data?.assetsConnection?.edges?.find(
|
||||
(e) => e?.node.symbol === symbol
|
||||
);
|
||||
const asset = data?.find((a) => a?.symbol === symbol);
|
||||
|
||||
let details: AssetDetails = [];
|
||||
if (asset != null) {
|
||||
@@ -72,31 +74,31 @@ export const AssetDetailsDialog = ({
|
||||
{
|
||||
key: 'name',
|
||||
label: t('Name'),
|
||||
value: asset.node.name,
|
||||
value: asset.name,
|
||||
tooltip: '', // t('Name of the asset (e.g: Great British Pound)')
|
||||
},
|
||||
{
|
||||
key: 'symbol',
|
||||
label: t('Symbol'),
|
||||
value: asset.node.symbol,
|
||||
value: asset.symbol,
|
||||
tooltip: '', // t('Symbol of the asset (e.g: GBP)')
|
||||
},
|
||||
{
|
||||
key: 'decimals',
|
||||
label: t('Decimals'),
|
||||
value: asset.node.decimals.toString(),
|
||||
value: asset.decimals.toString(),
|
||||
tooltip: t('Number of decimal / precision handled by this asset'),
|
||||
},
|
||||
{
|
||||
key: 'quantum',
|
||||
label: t('Quantum'),
|
||||
value: asset.node.quantum,
|
||||
value: asset.quantum,
|
||||
tooltip: t('The minimum economically meaningful amount in the asset'),
|
||||
},
|
||||
{
|
||||
key: 'contractaddress',
|
||||
label: t('Contract address'),
|
||||
value: (asset.node.source as Schema.ERC20).contractAddress,
|
||||
value: (asset.source as Schema.ERC20).contractAddress,
|
||||
tooltip: t(
|
||||
'The address of the contract for the token, on the ethereum network'
|
||||
),
|
||||
@@ -105,8 +107,8 @@ export const AssetDetailsDialog = ({
|
||||
key: 'withdrawalthreshold',
|
||||
label: t('Withdrawal threshold'),
|
||||
value: addDecimalsFormatNumber(
|
||||
(asset.node.source as Schema.ERC20).withdrawThreshold,
|
||||
asset.node.decimals
|
||||
(asset.source as Schema.ERC20).withdrawThreshold,
|
||||
asset.decimals
|
||||
),
|
||||
tooltip: t(
|
||||
'The maximum allowed per withdraw note: this is a temporary measure for restricted mainnet'
|
||||
@@ -116,8 +118,8 @@ export const AssetDetailsDialog = ({
|
||||
key: 'lifetimelimit',
|
||||
label: t('Lifetime limit'),
|
||||
value: addDecimalsFormatNumber(
|
||||
(asset.node.source as Schema.ERC20).lifetimeLimit,
|
||||
asset.node.decimals
|
||||
(asset.source as Schema.ERC20).lifetimeLimit,
|
||||
asset.decimals
|
||||
),
|
||||
tooltip: t(
|
||||
'The lifetime limits deposit per address note: this is a temporary measure for restricted mainnet'
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import {
|
||||
makeDataProvider,
|
||||
makeDerivedDataProvider,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { AssetsDocument } from './__generated___/Assets';
|
||||
import { AssetStatus } from '@vegaprotocol/types';
|
||||
import type {
|
||||
AssetsQuery,
|
||||
AssetsFieldsFragment,
|
||||
} from './__generated___/Assets';
|
||||
|
||||
export type Asset = AssetsFieldsFragment;
|
||||
|
||||
export interface ERC20AssetSource {
|
||||
__typename: 'ERC20';
|
||||
contractAddress: string;
|
||||
}
|
||||
|
||||
export interface BuiltinAssetSource {
|
||||
__typename: 'BuiltinAsset';
|
||||
}
|
||||
|
||||
export type ERC20Asset = Omit<Asset, 'source'> & {
|
||||
source: ERC20AssetSource;
|
||||
};
|
||||
|
||||
export type BuiltinAsset = Omit<Asset, 'source'> & {
|
||||
source: BuiltinAssetSource;
|
||||
};
|
||||
|
||||
export const isAssetTypeERC20 = (
|
||||
asset?: Pick<Asset, 'source'>
|
||||
): asset is ERC20Asset => {
|
||||
if (!asset?.source) return false;
|
||||
return asset.source.__typename === 'ERC20';
|
||||
};
|
||||
|
||||
const getData = (responseData: AssetsQuery) =>
|
||||
responseData.assetsConnection?.edges
|
||||
?.filter((e) => Boolean(e?.node))
|
||||
.map((e) => e?.node as Asset) ?? [];
|
||||
|
||||
export const assetsProvider = makeDataProvider<
|
||||
AssetsQuery,
|
||||
Asset[] | null,
|
||||
never,
|
||||
never
|
||||
>({
|
||||
query: AssetsDocument,
|
||||
getData,
|
||||
});
|
||||
|
||||
export const enabledAssetsProvider = makeDerivedDataProvider<
|
||||
ReturnType<typeof getData>,
|
||||
never
|
||||
>([assetsProvider], ([assets]) =>
|
||||
(assets as ReturnType<typeof getData>).filter(
|
||||
(a) => a.status === AssetStatus.STATUS_ENABLED
|
||||
)
|
||||
);
|
||||
@@ -1,2 +1,3 @@
|
||||
export * from './__generated___/Assets';
|
||||
export * from './assets-data-provider';
|
||||
export * from './asset-details-dialog';
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
"types": ["jest", "node", "@testing-library/jest-dom"]
|
||||
},
|
||||
"include": [
|
||||
"**/*.test.ts",
|
||||
|
||||
@@ -12,6 +12,7 @@ import { addVegaWalletReceiveFaucetedAsset } from './lib/commands/vega-wallet-re
|
||||
import { addVegaWalletImport } from './lib/commands/vega-wallet-import';
|
||||
import { addContainsExactly } from './lib/commands/contains-exactly';
|
||||
import { addRestartVegacapsuleNetwork } from './lib/commands/restart-vegacapsule-network';
|
||||
import { addGetNetworkParameters } from './lib/commands/get-network-parameters';
|
||||
|
||||
addGetTestIdcommand();
|
||||
addSlackCommand();
|
||||
@@ -25,6 +26,7 @@ addGetAssetInformation();
|
||||
addVegaWalletImport();
|
||||
addContainsExactly();
|
||||
addRestartVegacapsuleNetwork();
|
||||
addGetNetworkParameters();
|
||||
|
||||
export * from './lib/graphql-test-utils';
|
||||
export type { onMessage } from './lib/commands/mock-gql';
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/no-namespace
|
||||
namespace Cypress {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
interface Chainable<Subject> {
|
||||
get_network_parameters(): void;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function addGetNetworkParameters() {
|
||||
// @ts-ignore - ignoring Cypress type error which gets resolved when Cypress uses the command
|
||||
Cypress.Commands.add('get_network_parameters', () => {
|
||||
const mutation = '{networkParameters {key value}}';
|
||||
cy.request({
|
||||
method: 'POST',
|
||||
url: `http://localhost:3028/query`,
|
||||
body: {
|
||||
query: mutation,
|
||||
},
|
||||
headers: { 'content-type': 'application/json' },
|
||||
})
|
||||
.its('body.data.networkParameters')
|
||||
.then(function (response) {
|
||||
// @ts-ignore - ignoring Cypress type error which gets resolved when Cypress uses the command
|
||||
const object = response.reduce(function (r, e) {
|
||||
r[e.key] = e.value;
|
||||
return r;
|
||||
}, {});
|
||||
return object;
|
||||
});
|
||||
});
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user