Compare commits
42
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
72cb5b9764 | ||
|
|
8f8e509c9e | ||
|
|
d7bf9f887f | ||
|
|
5fab1e738c | ||
|
|
fd6a459ac3 | ||
|
|
4260c0508f | ||
|
|
93fa5c77e8 | ||
|
|
d220574d02 | ||
|
|
414483dc1f | ||
|
|
6ff0358b87 | ||
|
|
f997ca5480 | ||
|
|
6e3e44742f | ||
|
|
fb3505b995 | ||
|
|
01c32ffd0a | ||
|
|
5312a7e0e7 | ||
|
|
d4e2ace760 | ||
|
|
cba5cd317d | ||
|
|
34dbe5cb27 | ||
|
|
79c255c740 | ||
|
|
71bd1a097d | ||
|
|
09d4a01b2e | ||
|
|
ae31339a61 | ||
|
|
f327ccd361 | ||
|
|
1a66518ea5 | ||
|
|
6d0d163aca | ||
|
|
34fb65ecf0 | ||
|
|
8021872a30 | ||
|
|
0ac588edba | ||
|
|
0be934edca | ||
|
|
653688c1dd | ||
|
|
34400be18a | ||
|
|
d4a0a4a42c | ||
|
|
fabf643ce7 | ||
|
|
45e210092c | ||
|
|
1dc3b3fd05 | ||
|
|
0a80e3e39d | ||
|
|
7b8d9dc94b | ||
|
|
c0320c2468 | ||
|
|
11173d6614 | ||
|
|
e3324331e2 | ||
|
|
0a6e3cb6f5 | ||
|
|
68ede90609 |
@@ -20,7 +20,7 @@ jobs:
|
||||
project: ${{ fromJSON(inputs.projects) }}
|
||||
name: ${{ matrix.project }}
|
||||
runs-on: self-hosted-runner
|
||||
timeout-minutes: 40
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
# Checks if skip cache was requested
|
||||
- name: Set skip-nx-cache flag
|
||||
@@ -98,4 +98,4 @@ jobs:
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: test-report-${{ matrix.project }}
|
||||
path: frontend-monorepo/apps/trading-e2e/cypress/reports
|
||||
path: frontend-monorepo/apps/${{ matrix.project }}/cypress/reports
|
||||
|
||||
@@ -191,37 +191,36 @@ jobs:
|
||||
-d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \
|
||||
https://api.fleek.co/graphql
|
||||
|
||||
- name: Checkout vega.xyz
|
||||
- name: Update vega.trading DNS to redirect to the new console
|
||||
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
repository: vegaprotocol/vega.xyz
|
||||
path: './vega-xyz'
|
||||
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||
|
||||
- name: Update hash on interstitial page
|
||||
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
|
||||
run: |
|
||||
curl -L https://dist.ipfs.tech/kubo/v0.20.0/kubo_v0.20.0_linux-amd64.tar.gz -o kubo.tgz
|
||||
tar -xzf kubo.tgz
|
||||
export PATH="$PATH:$PWD/kubo"
|
||||
which ipfs
|
||||
new_hash=$(cat ${{ matrix.app }}-ipfs-hash)
|
||||
cd vega-xyz
|
||||
./interstital-allow-update.sh ${new_hash}
|
||||
git config --global user.email "vega-ci-bot@vega.xyz"
|
||||
git config --global user.name "vega-ci-bot"
|
||||
git add interstitial-allow.json netlify.toml
|
||||
commit_msg="feat(ci): Update CID for console release @ ${{ github.ref }}"
|
||||
git commit -m "${commit_msg}"
|
||||
git push origin main
|
||||
new_cid=$(ipfs cid format -v 1 -b base32 $new_hash)
|
||||
|
||||
# branch_name=${{ github.ref_name }}-hash-update
|
||||
# git checkout -b "${branch_name}"
|
||||
# git add interstitial-allow.json netlify.toml
|
||||
# git push -u origin "${branch_name}"
|
||||
# pr_url="$(gh pr create --title "${commit_msg}" --body 'update ipfs hash for console @ ${{ github.ref }}')"
|
||||
# echo $pr_url
|
||||
# gh pr merge --admin --auto $pr_url
|
||||
# Generate console URL
|
||||
new_console_url_type=ipfs
|
||||
# new_console_url_type=ipns
|
||||
new_console_url_domain=cf-ipfs.com
|
||||
# new_console_url_domain=dweb.link
|
||||
new_console_url="https://${new_cid}.${new_console_url_type}.${new_console_url_domain}/"
|
||||
echo "new_console_url=${new_console_url}"
|
||||
|
||||
# Update record in DNSimple
|
||||
# docs: https://developer.dnsimple.com/v2/zones/records/#updateZoneRecord
|
||||
dnsimple_account_id=84895
|
||||
dnsimple_zone_name=vega.trading
|
||||
dnsimple_record_id=44409591
|
||||
# see: https://dnsimple.com/a/84895/domains/vega.trading/records/44409591/edit
|
||||
|
||||
curl -H 'Authorization: Bearer ${{ secrets.DNSIMPLE_API_TOKEN }}' \
|
||||
-H 'Accept: application/json' \
|
||||
-H 'Content-Type: application/json' \
|
||||
-X PATCH \
|
||||
-d "{
|
||||
\"content\": \"${new_console_url}\"
|
||||
}" \
|
||||
https://api.dnsimple.com/v2/${dnsimple_account_id}/zones/${dnsimple_zone_name}/records/${dnsimple_record_id}
|
||||
|
||||
+1
-1
@@ -49,4 +49,4 @@ cypress.env.json
|
||||
.next
|
||||
|
||||
#cypress
|
||||
/apps/trading-e2e/cypress/reports/
|
||||
/apps/**/cypress/reports/
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
const { defineConfig } = require('cypress');
|
||||
|
||||
module.exports = defineConfig({
|
||||
projectId: 'et4snf',
|
||||
reporter: '../../node_modules/cypress-mochawesome-reporter',
|
||||
|
||||
e2e: {
|
||||
setupNodeEvents(on, config) {
|
||||
require('cypress-mochawesome-reporter/plugin')(on);
|
||||
require('@cypress/grep/src/plugin')(config);
|
||||
return config;
|
||||
},
|
||||
|
||||
@@ -15,5 +15,6 @@
|
||||
|
||||
import '@vegaprotocol/cypress';
|
||||
import './common.functions.js';
|
||||
import 'cypress-mochawesome-reporter/register';
|
||||
import registerCypressGrep from '@cypress/grep';
|
||||
registerCypressGrep();
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Header } from './header';
|
||||
import { MemoryRouter } from 'react-router-dom';
|
||||
|
||||
jest.mock('@vegaprotocol/environment', () => ({
|
||||
...jest.requireActual('@vegaprotocol/environment'),
|
||||
NetworkSwitcher: () => (
|
||||
<div data-testid="network-switcher">NetworkSwitcher</div>
|
||||
),
|
||||
|
||||
@@ -32,9 +32,9 @@
|
||||
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
|
||||
}
|
||||
|
||||
.vega-ag-grid .ag-row {
|
||||
border-width: 1px 0;
|
||||
border-bottom: 1px solid transparent;
|
||||
.vega-ag-grid .ag-row,
|
||||
.vega-ag-grid .ag-cell {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
/* Light variables */
|
||||
@@ -46,7 +46,6 @@
|
||||
--ag-header-column-separator-color: theme(colors.neutral[300]);
|
||||
--ag-row-border-color: theme(colors.white);
|
||||
--ag-row-hover-color: theme(colors.neutral[100]);
|
||||
--ag-font-size: 12px;
|
||||
}
|
||||
|
||||
/* Dark variables */
|
||||
@@ -58,7 +57,6 @@
|
||||
--ag-header-column-separator-color: theme(colors.neutral[600]);
|
||||
--ag-row-border-color: theme(colors.black);
|
||||
--ag-row-hover-color: theme(colors.neutral[800]);
|
||||
--ag-font-size: 12px;
|
||||
}
|
||||
|
||||
.voteicon svg {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
const { defineConfig } = require('cypress');
|
||||
|
||||
module.exports = defineConfig({
|
||||
projectId: 'et4snf',
|
||||
reporter: '../../node_modules/cypress-mochawesome-reporter',
|
||||
|
||||
e2e: {
|
||||
setupNodeEvents(on, config) {
|
||||
require('cypress-mochawesome-reporter/plugin')(on);
|
||||
require('@cypress/grep/src/plugin')(config);
|
||||
return config;
|
||||
},
|
||||
|
||||
@@ -63,7 +63,6 @@ context(
|
||||
});
|
||||
|
||||
it('should have option to go to last and newest page', function () {
|
||||
waitForBeginningOfEpoch();
|
||||
cy.getByTestId('goto-last-page').click();
|
||||
cy.getByTestId('epoch-total-rewards-table')
|
||||
.last()
|
||||
|
||||
@@ -8,6 +8,7 @@ import './wallet-eth.functions.ts';
|
||||
import './wallet-teardown.functions.ts';
|
||||
import './wallet-vega.functions.ts';
|
||||
import './proposal.functions.ts';
|
||||
import 'cypress-mochawesome-reporter/register';
|
||||
import registerCypressGrep from '@cypress/grep';
|
||||
import { aliasGQLQuery } from '@vegaprotocol/cypress';
|
||||
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
|
||||
|
||||
@@ -52,6 +52,7 @@ import {
|
||||
} from './components/telemetry-dialog/telemetry-dialog';
|
||||
import { useLocalStorage } from '@vegaprotocol/react-helpers';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { isPartyNotFoundError } from './lib/party';
|
||||
|
||||
const cache: InMemoryCacheConfig = {
|
||||
typePolicies: {
|
||||
@@ -211,24 +212,36 @@ const AppContainer = () => {
|
||||
enabled: true,
|
||||
environment: VEGA_ENV,
|
||||
release: GIT_COMMIT_HASH,
|
||||
beforeSend(event) {
|
||||
beforeSend(event, hint) {
|
||||
const error = hint?.originalException;
|
||||
const errorIsString = typeof error === 'string';
|
||||
const errorIsObject = error instanceof Error;
|
||||
const requestUrl = event.request?.url;
|
||||
const transaction = event.transaction;
|
||||
|
||||
if (
|
||||
(errorIsString && isPartyNotFoundError({ message: error })) ||
|
||||
(errorIsObject && isPartyNotFoundError(error))
|
||||
) {
|
||||
// This error is caused by a pubkey making an API request before
|
||||
// it has interacted with the chain. This isn't needed in Sentry.
|
||||
return null;
|
||||
}
|
||||
|
||||
const updatedRequest =
|
||||
requestUrl && requestUrl.includes('/test?')
|
||||
requestUrl && requestUrl.includes('/claim?')
|
||||
? { ...event.request, url: removeQueryParams(requestUrl) }
|
||||
: event.request;
|
||||
|
||||
const updatedTransaction =
|
||||
transaction && transaction.includes('/test?')
|
||||
transaction && transaction.includes('/claim?')
|
||||
? removeQueryParams(transaction)
|
||||
: transaction;
|
||||
|
||||
const updatedBreadcrumbs = event.breadcrumbs?.map((breadcrumb) => {
|
||||
if (
|
||||
breadcrumb.type === 'navigation' &&
|
||||
breadcrumb.data?.to?.includes('/test?')
|
||||
breadcrumb.data?.to?.includes('/claim?')
|
||||
) {
|
||||
return {
|
||||
...breadcrumb,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Link } from '@vegaprotocol/ui-toolkit';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ExternalLinks } from '@vegaprotocol/utils';
|
||||
import { ExternalLinks } from '@vegaprotocol/environment';
|
||||
|
||||
export const DownloadWalletPrompt = () => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -26,6 +26,7 @@ import type {
|
||||
WalletDelegationFieldsFragment,
|
||||
} from './__generated__/Delegations';
|
||||
import { DelegationsDocument } from './__generated__/Delegations';
|
||||
import { isPartyNotFoundError } from '../../lib/party';
|
||||
|
||||
export const usePollForDelegations = () => {
|
||||
const { token: vegaToken } = useContracts();
|
||||
@@ -75,6 +76,7 @@ export const usePollForDelegations = () => {
|
||||
})
|
||||
.then((res) => {
|
||||
if (!mounted) return;
|
||||
|
||||
const canonisedDelegations = removePaginationWrapper(
|
||||
res.data.party?.delegationsConnection?.edges
|
||||
);
|
||||
@@ -203,6 +205,15 @@ export const usePollForDelegations = () => {
|
||||
setDelegatedNodes(delegatedAmounts);
|
||||
})
|
||||
.catch((err: Error) => {
|
||||
// if party isn't found, dont log to Sentry, just clear state as, user
|
||||
// will not have any delagations or accounts
|
||||
if (isPartyNotFoundError(err)) {
|
||||
setDelegations([]);
|
||||
setAccounts([]);
|
||||
setDelegatedNodes([]);
|
||||
setCurrentStakeAvailable(new BigNumber(0));
|
||||
return;
|
||||
}
|
||||
Sentry.captureException(err);
|
||||
// If query fails stop interval. Its almost certain that the query
|
||||
// will just continue to fail
|
||||
|
||||
@@ -594,7 +594,9 @@
|
||||
"numberOfAgainstVotes": "Number of votes against",
|
||||
"yesPercentage": "Yes percentage",
|
||||
"noPercentage": "No percentage",
|
||||
"proposalTerms": "Proposal terms",
|
||||
"proposalJson": "Full proposal JSON",
|
||||
"proposalDetails": "Proposal details",
|
||||
"proposalDescription": "Description",
|
||||
"currentlySetTo": "Currently expected to ",
|
||||
"currently": "currently",
|
||||
"finalOutcomeMayDiffer": "Final outcome may differ",
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export const PARTY_NOT_FOUND = 'failed to get party for ID';
|
||||
|
||||
export const isPartyNotFoundError = (error: { message: string }) => {
|
||||
if (error.message.includes(PARTY_NOT_FOUND)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
@@ -12,7 +12,8 @@ import { useRefreshAfterEpoch } from '../../hooks/use-refresh-after-epoch';
|
||||
import { ProposalsListItem } from '../proposals/components/proposals-list-item';
|
||||
import { ProtocolUpgradeProposalsListItem } from '../proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item';
|
||||
import Routes from '../routes';
|
||||
import { ExternalLinks, removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import { ExternalLinks } from '@vegaprotocol/environment';
|
||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import { useNodesQuery } from '../staking/home/__generated__/Nodes';
|
||||
import { useProposalsQuery } from '../proposals/proposals/__generated__/Proposals';
|
||||
import {
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { ProposalDescription } from './proposal-description';
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import classnames from 'classnames';
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Icon, RoundedWrapper } from '@vegaprotocol/ui-toolkit';
|
||||
import { SubHeading } from '../../../../components/heading';
|
||||
|
||||
export const ProposalDescription = ({
|
||||
description,
|
||||
}: {
|
||||
description: string;
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [showDescription, setShowDescription] = useState(false);
|
||||
const showDescriptionIconClasses = classnames('mb-4', {
|
||||
'rotate-180': showDescription,
|
||||
});
|
||||
|
||||
return (
|
||||
<section data-testid="proposal-description">
|
||||
<button
|
||||
onClick={() => setShowDescription(!showDescription)}
|
||||
data-testid="proposal-description-toggle"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<SubHeading title={t('proposalDescription')} />
|
||||
<div className={showDescriptionIconClasses}>
|
||||
<Icon name="chevron-down" size={8} />
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{showDescription && (
|
||||
<RoundedWrapper paddingBottom={true} marginBottomLarge={true}>
|
||||
<div className="p-2">
|
||||
<ReactMarkdown
|
||||
className="react-markdown-container"
|
||||
/* Prevents HTML embedded in the description from rendering */
|
||||
skipHtml={true}
|
||||
/* Stops users embedding images which could be used for tracking */
|
||||
disallowedElements={['img']}
|
||||
linkTarget="_blank"
|
||||
>
|
||||
{description}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
</RoundedWrapper>
|
||||
)}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
-22
@@ -206,28 +206,6 @@ describe('Proposal header', () => {
|
||||
).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('Renders Freeform proposal - long rationale (105 chars) - details', () => {
|
||||
renderComponent(
|
||||
generateProposal({
|
||||
id: 'long',
|
||||
rationale: {
|
||||
title: '0x0',
|
||||
description:
|
||||
'Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean dolor.',
|
||||
},
|
||||
terms: {
|
||||
change: {
|
||||
__typename: 'NewFreeform',
|
||||
},
|
||||
},
|
||||
}),
|
||||
false
|
||||
);
|
||||
expect(screen.getByTestId('proposal-description')).toHaveTextContent(
|
||||
/Class aptent/
|
||||
);
|
||||
});
|
||||
|
||||
// Remove once proposals have rationale and re-enable above tests
|
||||
it('Renders Freeform proposal - id for title', () => {
|
||||
renderComponent(
|
||||
|
||||
+1
-24
@@ -5,7 +5,6 @@ import { Heading, SubHeading } from '../../../../components/heading';
|
||||
import type { ReactNode } from 'react';
|
||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import { truncateMiddle } from '../../../../lib/truncate-middle';
|
||||
import { CurrentProposalState } from '../current-proposal-state';
|
||||
import { ProposalInfoLabel } from '../proposal-info-label';
|
||||
@@ -23,12 +22,7 @@ export const ProposalHeader = ({
|
||||
let details: ReactNode;
|
||||
let proposalType = '';
|
||||
|
||||
let title = proposal?.rationale.title.trim();
|
||||
let description = proposal?.rationale.description.trim();
|
||||
if (title?.length === 0 && description && description.length > 0) {
|
||||
title = description;
|
||||
description = '';
|
||||
}
|
||||
const title = proposal?.rationale.title.trim();
|
||||
|
||||
const titleContent = shorten(title ?? '', 100);
|
||||
|
||||
@@ -145,23 +139,6 @@ export const ProposalHeader = ({
|
||||
{details}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{description && !isListItem && (
|
||||
<div data-testid="proposal-description">
|
||||
{/*<div className="uppercase mr-2">{t('ProposalDescription')}:</div>*/}
|
||||
<SubHeading title={t('ProposalDescription')} />
|
||||
<ReactMarkdown
|
||||
className="react-markdown-container"
|
||||
/* Prevents HTML embedded in the description from rendering */
|
||||
skipHtml={true}
|
||||
/* Stops users embedding images which could be used for tracking */
|
||||
disallowedElements={['img']}
|
||||
linkTarget="_blank"
|
||||
>
|
||||
{description}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export { ProposalJson } from './proposal-json';
|
||||
+11
-11
@@ -1,15 +1,15 @@
|
||||
import classnames from 'classnames';
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Icon, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
|
||||
import { SubHeading } from '../../../../components/heading';
|
||||
import type { PartialDeep } from 'type-fest';
|
||||
import type * as Schema from '@vegaprotocol/types';
|
||||
import { useState } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
|
||||
export const ProposalTermsJson = ({
|
||||
terms,
|
||||
export const ProposalJson = ({
|
||||
proposal,
|
||||
}: {
|
||||
terms: PartialDeep<Schema.ProposalTerms>;
|
||||
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const [showDetails, setShowDetails] = useState(false);
|
||||
@@ -18,20 +18,20 @@ export const ProposalTermsJson = ({
|
||||
});
|
||||
|
||||
return (
|
||||
<section>
|
||||
<section data-testid="proposal-json">
|
||||
<button
|
||||
onClick={() => setShowDetails(!showDetails)}
|
||||
data-testid="proposal-terms-toggle"
|
||||
data-testid="proposal-json-toggle"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<SubHeading title={t('proposalTerms')} />
|
||||
<SubHeading title={t('proposalJson')} />
|
||||
<div className={showDetailsIconClasses}>
|
||||
<Icon name="chevron-down" size={8} />
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{showDetails && <SyntaxHighlighter data={terms} />}
|
||||
{showDetails && <SyntaxHighlighter data={proposal} />}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export { ProposalTermsJson } from './proposal-terms-json';
|
||||
@@ -0,0 +1 @@
|
||||
export { ProposalTerms } from './proposal-terms';
|
||||
@@ -0,0 +1,142 @@
|
||||
import {
|
||||
RoundedWrapper,
|
||||
KeyValueTable,
|
||||
KeyValueTableRow,
|
||||
Icon,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { BigNumber } from '../../../../lib/bignumber';
|
||||
import { SubHeading } from '../../../../components/heading';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useState } from 'react';
|
||||
import classnames from 'classnames';
|
||||
|
||||
interface ProposalTermsProps {
|
||||
data: Record<string, unknown>;
|
||||
}
|
||||
|
||||
const getParsedValue = (value: unknown) => {
|
||||
if (typeof value === 'string') {
|
||||
try {
|
||||
// Check if value is a number string - if so use bignumber to maintain precision
|
||||
if (/^\d+(\.\d+)?$/.test(value)) {
|
||||
return new BigNumber(value).toString();
|
||||
} else {
|
||||
// This would convert, for example, a JSON object ('{"key":"value"}')
|
||||
// into an actual JS object ({key: "value"})
|
||||
return JSON.parse(value);
|
||||
}
|
||||
} catch (error) {
|
||||
return value;
|
||||
}
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
const RenderKeyValue = ({
|
||||
title,
|
||||
value,
|
||||
}: {
|
||||
title: string;
|
||||
value: string | number;
|
||||
}) => (
|
||||
<KeyValueTable>
|
||||
<KeyValueTableRow>
|
||||
{title}
|
||||
{value}
|
||||
</KeyValueTableRow>
|
||||
</KeyValueTable>
|
||||
);
|
||||
|
||||
const RenderArray = ({ title, array }: { title: string; array: unknown[] }) => {
|
||||
if (array.every((item) => typeof item === 'string')) {
|
||||
return <RenderKeyValue title={title} value={array.join(', ')} />;
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
<div className="mb-2">{title}</div>
|
||||
{array.map((item, index) => (
|
||||
<div key={index}>
|
||||
<ProposalTermsRenderer data={item as Record<string, unknown>} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Working with 'unknown' type as a proposal's terms can be in many shapes
|
||||
const RenderTerm = ({ title, value }: { title: string; value: unknown }) => {
|
||||
const parsedValue = getParsedValue(value);
|
||||
|
||||
if (parsedValue === null || typeof parsedValue === 'boolean') {
|
||||
return <RenderKeyValue title={title} value={String(parsedValue)} />;
|
||||
} else if (
|
||||
typeof parsedValue === 'string' ||
|
||||
typeof parsedValue === 'number'
|
||||
) {
|
||||
return <RenderKeyValue title={title} value={parsedValue} />;
|
||||
} else if (typeof parsedValue === 'object') {
|
||||
if (Array.isArray(parsedValue)) {
|
||||
return <RenderArray title={title} array={parsedValue} />;
|
||||
} else {
|
||||
return (
|
||||
<div>
|
||||
<div className="my-2">{title}</div>
|
||||
<ProposalTermsRenderer
|
||||
data={parsedValue as Record<string, unknown>}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
} else if (parsedValue === undefined) {
|
||||
return <span>{'undefined'}</span>;
|
||||
} else {
|
||||
return <span>{String(parsedValue)}</span>;
|
||||
}
|
||||
};
|
||||
|
||||
const ProposalTermsRenderer = ({ data }: ProposalTermsProps) => {
|
||||
return (
|
||||
<RoundedWrapper paddingBottom={true}>
|
||||
{Object.keys(data)
|
||||
.filter(
|
||||
(key) =>
|
||||
!['__typename', 'closingDatetime', 'enactmentDatetime'].includes(
|
||||
key
|
||||
)
|
||||
)
|
||||
.map((key, index) => (
|
||||
<div key={index}>
|
||||
<RenderTerm title={key} value={data[key]} />
|
||||
</div>
|
||||
))}
|
||||
</RoundedWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
export const ProposalTerms = ({ data }: ProposalTermsProps) => {
|
||||
const { t } = useTranslation();
|
||||
const [showTerms, setShowTerms] = useState(false);
|
||||
const showTermsIconClasses = classnames('mb-4', {
|
||||
'rotate-180': showTerms,
|
||||
});
|
||||
|
||||
return (
|
||||
<section data-testid="proposal-terms">
|
||||
<button
|
||||
onClick={() => setShowTerms(!showTerms)}
|
||||
data-testid="proposal-terms-toggle"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<SubHeading title={t('proposalDetails')} />
|
||||
<div className={showTermsIconClasses}>
|
||||
<Icon name="chevron-down" size={8} />
|
||||
</div>
|
||||
</div>
|
||||
</button>
|
||||
|
||||
{showTerms && <ProposalTermsRenderer data={data} />}
|
||||
</section>
|
||||
);
|
||||
};
|
||||
@@ -25,8 +25,11 @@ jest.mock('../proposal-detail-header/proposal-header', () => ({
|
||||
jest.mock('../proposal-change-table', () => ({
|
||||
ProposalChangeTable: () => <div data-testid="proposal-change-table"></div>,
|
||||
}));
|
||||
jest.mock('../proposal-terms-json', () => ({
|
||||
ProposalTermsJson: () => <div data-testid="proposal-terms-json"></div>,
|
||||
jest.mock('../proposal-json', () => ({
|
||||
ProposalJson: () => <div data-testid="proposal-json"></div>,
|
||||
}));
|
||||
jest.mock('../proposal-terms/proposal-terms', () => ({
|
||||
ProposalTerms: () => <div data-testid="proposal-terms"></div>,
|
||||
}));
|
||||
jest.mock('../proposal-votes-table', () => ({
|
||||
ProposalVotesTable: () => <div data-testid="proposal-votes-table"></div>,
|
||||
@@ -49,7 +52,8 @@ it('renders each section', async () => {
|
||||
render(<Proposal proposal={proposal as ProposalQuery['proposal']} />);
|
||||
expect(await screen.findByTestId('proposal-header')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('proposal-change-table')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('proposal-terms-json')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('proposal-json')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('proposal-terms')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('proposal-votes-table')).toBeInTheDocument();
|
||||
expect(screen.getByTestId('proposal-vote-details')).toBeInTheDocument();
|
||||
expect(screen.queryByTestId('proposal-list-asset')).not.toBeInTheDocument();
|
||||
|
||||
@@ -6,8 +6,10 @@ import { AsyncRenderer, RoundedWrapper } from '@vegaprotocol/ui-toolkit';
|
||||
import { ProposalHeader } from '../proposal-detail-header/proposal-header';
|
||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
import { ProposalDescription } from '../proposal-description';
|
||||
import { ProposalChangeTable } from '../proposal-change-table';
|
||||
import { ProposalTermsJson } from '../proposal-terms-json';
|
||||
import { ProposalJson } from '../proposal-json';
|
||||
import { ProposalTerms } from '../proposal-terms';
|
||||
import { ProposalVotesTable } from '../proposal-votes-table';
|
||||
import { VoteDetails } from '../vote-details';
|
||||
import { ListAsset } from '../list-asset';
|
||||
@@ -20,7 +22,7 @@ export enum ProposalType {
|
||||
PROPOSAL_NETWORK_PARAMETER = 'PROPOSAL_NETWORK_PARAMETER',
|
||||
PROPOSAL_FREEFORM = 'PROPOSAL_FREEFORM',
|
||||
}
|
||||
interface ProposalProps {
|
||||
export interface ProposalProps {
|
||||
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
|
||||
}
|
||||
|
||||
@@ -78,9 +80,11 @@ export const Proposal = ({ proposal }: ProposalProps) => {
|
||||
<AsyncRenderer data={params} loading={loading} error={error}>
|
||||
<section data-testid="proposal">
|
||||
<ProposalHeader proposal={proposal} isListItem={false} />
|
||||
|
||||
<div className="my-10">
|
||||
<ProposalChangeTable proposal={proposal} />
|
||||
</div>
|
||||
|
||||
{proposal.terms.change.__typename === 'NewAsset' &&
|
||||
proposal.terms.change.source.__typename === 'ERC20' &&
|
||||
proposal.id ? (
|
||||
@@ -90,7 +94,20 @@ export const Proposal = ({ proposal }: ProposalProps) => {
|
||||
lifetimeLimit={proposal.terms.change.source.lifetimeLimit}
|
||||
/>
|
||||
) : null}
|
||||
<div className="mb-12">
|
||||
|
||||
<div className="mb-4">
|
||||
<ProposalDescription description={proposal.rationale.description} />
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<ProposalTerms data={proposal.terms} />
|
||||
</div>
|
||||
|
||||
<div className="mb-6">
|
||||
<ProposalJson proposal={proposal} />
|
||||
</div>
|
||||
|
||||
<div className="mb-10">
|
||||
<RoundedWrapper paddingBottom={true}>
|
||||
<VoteDetails
|
||||
proposal={proposal}
|
||||
@@ -102,10 +119,10 @@ export const Proposal = ({ proposal }: ProposalProps) => {
|
||||
/>
|
||||
</RoundedWrapper>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<ProposalVotesTable proposal={proposal} proposalType={proposalType} />
|
||||
</div>
|
||||
<ProposalTermsJson terms={proposal.terms} />
|
||||
</section>
|
||||
</AsyncRenderer>
|
||||
);
|
||||
|
||||
@@ -8,12 +8,11 @@ import { ProposalsListFilter } from '../proposals-list-filter';
|
||||
import Routes from '../../../routes';
|
||||
import { Button, VegaIcon, VegaIconNames } from '@vegaprotocol/ui-toolkit';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { createDocsLinks, ExternalLinks } from '@vegaprotocol/utils';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
|
||||
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
|
||||
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { DocsLinks, ExternalLinks } from '@vegaprotocol/environment';
|
||||
|
||||
interface ProposalsListProps {
|
||||
proposals: Array<ProposalFieldsFragment | ProposalQuery['proposal']>;
|
||||
@@ -36,7 +35,6 @@ export const ProposalsList = ({
|
||||
protocolUpgradeProposals,
|
||||
lastBlockHeight,
|
||||
}: ProposalsListProps) => {
|
||||
const { VEGA_DOCS_URL } = useEnvironment();
|
||||
const { t } = useTranslation();
|
||||
const [filterString, setFilterString] = useState('');
|
||||
const sortedProposals = proposals.reduce(
|
||||
@@ -83,9 +81,9 @@ export const ProposalsList = ({
|
||||
marginBottom={false}
|
||||
title={t('pageTitleProposals')}
|
||||
/>
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<div className="xs:justify-self-end" data-testid="new-proposal-link">
|
||||
<ExternalLink href={createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE}>
|
||||
<ExternalLink href={DocsLinks.PROPOSALS_GUIDE}>
|
||||
<Button variant="primary" size="sm">
|
||||
<div className="flex items-center gap-1">
|
||||
{t('NewProposal')}
|
||||
|
||||
+4
-3
@@ -2,9 +2,10 @@ import { render, screen } from '@testing-library/react';
|
||||
import { ProposalFormTerms } from './proposal-form-terms';
|
||||
|
||||
jest.mock('@vegaprotocol/environment', () => ({
|
||||
useEnvironment: () => ({
|
||||
VEGA_DOCS_URL: 'https://docs.vega.xyz',
|
||||
}),
|
||||
...jest.requireActual('@vegaprotocol/environment'),
|
||||
DocsLinks: {
|
||||
PROPOSALS_GUIDE: 'https://docs.vega.xyz/tutorials/proposals',
|
||||
},
|
||||
}));
|
||||
|
||||
const renderComponent = () => {
|
||||
|
||||
@@ -5,8 +5,7 @@ import {
|
||||
ExternalLink,
|
||||
TextArea,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { createDocsLinks } from '@vegaprotocol/utils';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { DocsLinks } from '@vegaprotocol/environment';
|
||||
import type { UseFormRegisterReturn } from 'react-hook-form';
|
||||
|
||||
interface ProposalFormTermsProps {
|
||||
@@ -22,23 +21,20 @@ export const ProposalFormTerms = ({
|
||||
labelOverride,
|
||||
docsLink,
|
||||
}: ProposalFormTermsProps) => {
|
||||
const { VEGA_DOCS_URL } = useEnvironment();
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
<FormGroup
|
||||
label={labelOverride || t('ProposalTerms')}
|
||||
labelFor="proposal-terms"
|
||||
>
|
||||
{docsLink && VEGA_DOCS_URL && (
|
||||
{docsLink && DocsLinks && (
|
||||
<div className="mt-[-4px] mb-2 text-sm font-light">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<ExternalLink
|
||||
href={`${
|
||||
createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE
|
||||
}${docsLink}`}
|
||||
href={`${DocsLinks.PROPOSALS_GUIDE}${docsLink}`}
|
||||
target="_blank"
|
||||
>
|
||||
{`${createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE}${docsLink}`}
|
||||
{`${DocsLinks.PROPOSALS_GUIDE}${docsLink}`}
|
||||
</ExternalLink>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -10,9 +10,10 @@ import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { NetworkParamsDocument } from '@vegaprotocol/network-parameters';
|
||||
|
||||
jest.mock('@vegaprotocol/environment', () => ({
|
||||
useEnvironment: () => ({
|
||||
VEGA_DOCS_URL: 'https://docs.vega.xyz',
|
||||
}),
|
||||
...jest.requireActual('@vegaprotocol/environment'),
|
||||
DocsLinks: {
|
||||
PROPOSALS_GUIDE: 'https://docs.vega.xyz/tutorials/proposals',
|
||||
},
|
||||
}));
|
||||
|
||||
const updateMarketNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
|
||||
|
||||
@@ -5,7 +5,7 @@ import {
|
||||
useProposalSubmit,
|
||||
deadlineToRoundedHours,
|
||||
} from '@vegaprotocol/proposals';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
|
||||
import {
|
||||
ProposalFormDescription,
|
||||
ProposalFormSubheader,
|
||||
@@ -17,7 +17,6 @@ import {
|
||||
import { ProposalMinRequirements } from '../../components/shared';
|
||||
import { AsyncRenderer, ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { Heading } from '../../../../components/heading';
|
||||
import { createDocsLinks } from '@vegaprotocol/utils';
|
||||
import {
|
||||
NetworkParams,
|
||||
useNetworkParams,
|
||||
@@ -42,7 +41,7 @@ export const ProposeFreeform = () => {
|
||||
NetworkParams.governance_proposal_freeform_minProposerBalance,
|
||||
NetworkParams.spam_protection_proposal_min_tokens,
|
||||
]);
|
||||
const { VEGA_DOCS_URL, VEGA_EXPLORER_URL } = useEnvironment();
|
||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
register,
|
||||
@@ -111,17 +110,13 @@ export const ProposeFreeform = () => {
|
||||
userAction={ProposalUserAction.CREATE}
|
||||
/>
|
||||
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<ExternalLink
|
||||
href={`${
|
||||
createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE
|
||||
}${DOCS_LINK}`}
|
||||
href={`${DocsLinks.PROPOSALS_GUIDE}${DOCS_LINK}`}
|
||||
target="_blank"
|
||||
>{`${
|
||||
createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE
|
||||
}${DOCS_LINK}`}</ExternalLink>
|
||||
>{`${DocsLinks.PROPOSALS_GUIDE}${DOCS_LINK}`}</ExternalLink>
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
+4
-3
@@ -10,9 +10,10 @@ import { NetworkParamsDocument } from '@vegaprotocol/network-parameters';
|
||||
import type { MockedResponse } from '@apollo/client/testing';
|
||||
|
||||
jest.mock('@vegaprotocol/environment', () => ({
|
||||
useEnvironment: () => ({
|
||||
VEGA_DOCS_URL: 'https://docs.vega.xyz',
|
||||
}),
|
||||
...jest.requireActual('@vegaprotocol/environment'),
|
||||
DocsLinks: {
|
||||
PROPOSALS_GUIDE: 'https://docs.vega.xyz/tutorials/proposals',
|
||||
},
|
||||
}));
|
||||
|
||||
const updateMarketNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
|
||||
|
||||
+6
-13
@@ -1,10 +1,7 @@
|
||||
import { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import {
|
||||
createDocsLinks,
|
||||
suitableForSyntaxHighlighter,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { suitableForSyntaxHighlighter } from '@vegaprotocol/utils';
|
||||
import { useNetworkParams } from '@vegaprotocol/network-parameters';
|
||||
import {
|
||||
getClosingTimestamp,
|
||||
@@ -12,7 +9,7 @@ import {
|
||||
useProposalSubmit,
|
||||
doesValueEquateToParam,
|
||||
} from '@vegaprotocol/proposals';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
|
||||
import {
|
||||
ProposalFormDescription,
|
||||
ProposalFormSubheader,
|
||||
@@ -84,7 +81,7 @@ export const ProposeNetworkParameter = () => {
|
||||
loading: networkParamsLoading,
|
||||
error: networkParamsError,
|
||||
} = useNetworkParams();
|
||||
const { VEGA_EXPLORER_URL, VEGA_DOCS_URL } = useEnvironment();
|
||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
register,
|
||||
@@ -175,17 +172,13 @@ export const ProposeNetworkParameter = () => {
|
||||
userAction={ProposalUserAction.CREATE}
|
||||
/>
|
||||
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<ExternalLink
|
||||
href={`${
|
||||
createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE
|
||||
}${DOCS_LINK}`}
|
||||
href={`${DocsLinks.PROPOSALS_GUIDE}${DOCS_LINK}`}
|
||||
target="_blank"
|
||||
>{`${
|
||||
createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE
|
||||
}${DOCS_LINK}`}</ExternalLink>
|
||||
>{`${DocsLinks.PROPOSALS_GUIDE}${DOCS_LINK}`}</ExternalLink>
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
@@ -10,9 +10,10 @@ import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { NetworkParamsDocument } from '@vegaprotocol/network-parameters';
|
||||
|
||||
jest.mock('@vegaprotocol/environment', () => ({
|
||||
useEnvironment: () => ({
|
||||
VEGA_DOCS_URL: 'https://docs.vega.xyz',
|
||||
}),
|
||||
...jest.requireActual('@vegaprotocol/environment'),
|
||||
DocsLinks: {
|
||||
PROPOSALS_GUIDE: 'https://docs.vega.xyz/tutorials/proposals',
|
||||
},
|
||||
}));
|
||||
|
||||
const newAssetNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
useProposalSubmit,
|
||||
doesValueEquateToParam,
|
||||
} from '@vegaprotocol/proposals';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { createDocsLinks, validateJson } from '@vegaprotocol/utils';
|
||||
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
|
||||
import { validateJson } from '@vegaprotocol/utils';
|
||||
import {
|
||||
NetworkParams,
|
||||
useNetworkParams,
|
||||
@@ -53,7 +53,7 @@ export const ProposeNewAsset = () => {
|
||||
NetworkParams.governance_proposal_asset_minProposerBalance,
|
||||
NetworkParams.spam_protection_proposal_min_tokens,
|
||||
]);
|
||||
const { VEGA_EXPLORER_URL, VEGA_DOCS_URL } = useEnvironment();
|
||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
register,
|
||||
@@ -142,17 +142,13 @@ export const ProposeNewAsset = () => {
|
||||
userAction={ProposalUserAction.CREATE}
|
||||
/>
|
||||
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<ExternalLink
|
||||
href={`${
|
||||
createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE
|
||||
}${DOCS_LINK}`}
|
||||
href={`${DocsLinks.PROPOSALS_GUIDE}${DOCS_LINK}`}
|
||||
target="_blank"
|
||||
>{`${
|
||||
createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE
|
||||
}${DOCS_LINK}`}</ExternalLink>
|
||||
>{`${DocsLinks.PROPOSALS_GUIDE}${DOCS_LINK}`}</ExternalLink>
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
@@ -10,9 +10,10 @@ import type { NetworkParamsQuery } from '@vegaprotocol/network-parameters';
|
||||
import { NetworkParamsDocument } from '@vegaprotocol/network-parameters';
|
||||
|
||||
jest.mock('@vegaprotocol/environment', () => ({
|
||||
useEnvironment: () => ({
|
||||
VEGA_DOCS_URL: 'https://docs.vega.xyz',
|
||||
}),
|
||||
...jest.requireActual('@vegaprotocol/environment'),
|
||||
DocsLinks: {
|
||||
PROPOSALS_GUIDE: 'https://docs.vega.xyz/tutorials/proposals',
|
||||
},
|
||||
}));
|
||||
|
||||
const newMarketNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
useProposalSubmit,
|
||||
doesValueEquateToParam,
|
||||
} from '@vegaprotocol/proposals';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { createDocsLinks, validateJson } from '@vegaprotocol/utils';
|
||||
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
|
||||
import { validateJson } from '@vegaprotocol/utils';
|
||||
import {
|
||||
NetworkParams,
|
||||
useNetworkParams,
|
||||
@@ -51,7 +51,7 @@ export const ProposeNewMarket = () => {
|
||||
NetworkParams.governance_proposal_market_minProposerBalance,
|
||||
NetworkParams.spam_protection_proposal_min_tokens,
|
||||
]);
|
||||
const { VEGA_EXPLORER_URL, VEGA_DOCS_URL } = useEnvironment();
|
||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
register,
|
||||
@@ -132,17 +132,13 @@ export const ProposeNewMarket = () => {
|
||||
userAction={ProposalUserAction.CREATE}
|
||||
/>
|
||||
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<ExternalLink
|
||||
href={`${
|
||||
createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE
|
||||
}${DOCS_LINK}`}
|
||||
href={`${DocsLinks.PROPOSALS_GUIDE}${DOCS_LINK}`}
|
||||
target="_blank"
|
||||
>{`${
|
||||
createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE
|
||||
}${DOCS_LINK}`}</ExternalLink>
|
||||
>{`${DocsLinks.PROPOSALS_GUIDE}${DOCS_LINK}`}</ExternalLink>
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
@@ -2,12 +2,11 @@ import Routes from '../../routes';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
|
||||
import { Heading } from '../../../components/heading';
|
||||
import { createDocsLinks } from '@vegaprotocol/utils';
|
||||
|
||||
export const Propose = () => {
|
||||
const { VEGA_DOCS_URL, VEGA_EXPLORER_URL } = useEnvironment();
|
||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
@@ -15,14 +14,11 @@ export const Propose = () => {
|
||||
<section className="pb-6">
|
||||
<Heading title={t('NewProposal')} />
|
||||
<div className="text-sm">
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<p>
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<ExternalLink
|
||||
href={createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE}
|
||||
target="_blank"
|
||||
>
|
||||
{createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE}
|
||||
<ExternalLink href={DocsLinks.PROPOSALS_GUIDE} target="_blank">
|
||||
{DocsLinks.PROPOSALS_GUIDE}
|
||||
</ExternalLink>
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
|
||||
import { Heading } from '../../../../components/heading';
|
||||
import {
|
||||
AsyncRenderer,
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
InputError,
|
||||
TextArea,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { createDocsLinks, validateJson } from '@vegaprotocol/utils';
|
||||
import { validateJson } from '@vegaprotocol/utils';
|
||||
import {
|
||||
NetworkParams,
|
||||
useNetworkParams,
|
||||
@@ -39,7 +39,7 @@ export const ProposeRaw = () => {
|
||||
NetworkParams.governance_proposal_freeform_minProposerBalance,
|
||||
NetworkParams.spam_protection_proposal_min_tokens,
|
||||
]);
|
||||
const { VEGA_EXPLORER_URL, VEGA_DOCS_URL } = useEnvironment();
|
||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
register,
|
||||
@@ -79,14 +79,11 @@ export const ProposeRaw = () => {
|
||||
spamProtectionMin={params.spam_protection_proposal_min_tokens}
|
||||
/>
|
||||
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<ExternalLink
|
||||
href={createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE}
|
||||
target="_blank"
|
||||
>
|
||||
{createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE}
|
||||
<ExternalLink href={DocsLinks.PROPOSALS_GUIDE} target="_blank">
|
||||
{DocsLinks.PROPOSALS_GUIDE}
|
||||
</ExternalLink>
|
||||
</p>
|
||||
)}
|
||||
|
||||
+4
-3
@@ -10,9 +10,10 @@ import type { MockedResponse } from '@apollo/client/testing';
|
||||
import { NetworkParamsDocument } from '@vegaprotocol/network-parameters';
|
||||
|
||||
jest.mock('@vegaprotocol/environment', () => ({
|
||||
useEnvironment: () => ({
|
||||
VEGA_DOCS_URL: 'https://docs.vega.xyz',
|
||||
}),
|
||||
...jest.requireActual('@vegaprotocol/environment'),
|
||||
DocsLinks: {
|
||||
PROPOSALS_GUIDE: 'https://docs.vega.xyz/tutorials/proposals',
|
||||
},
|
||||
}));
|
||||
|
||||
const updateAssetNetworkParamsQueryMock: MockedResponse<NetworkParamsQuery> = {
|
||||
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
useProposalSubmit,
|
||||
doesValueEquateToParam,
|
||||
} from '@vegaprotocol/proposals';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { createDocsLinks, validateJson } from '@vegaprotocol/utils';
|
||||
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
|
||||
import { validateJson } from '@vegaprotocol/utils';
|
||||
import {
|
||||
NetworkParams,
|
||||
useNetworkParams,
|
||||
@@ -51,7 +51,7 @@ export const ProposeUpdateAsset = () => {
|
||||
NetworkParams.governance_proposal_updateAsset_minProposerBalance,
|
||||
NetworkParams.spam_protection_proposal_min_tokens,
|
||||
]);
|
||||
const { VEGA_EXPLORER_URL, VEGA_DOCS_URL } = useEnvironment();
|
||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
register,
|
||||
@@ -132,17 +132,13 @@ export const ProposeUpdateAsset = () => {
|
||||
userAction={ProposalUserAction.CREATE}
|
||||
/>
|
||||
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<ExternalLink
|
||||
href={`${
|
||||
createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE
|
||||
}${DOCS_LINK}`}
|
||||
href={`${DocsLinks.PROPOSALS_GUIDE}${DOCS_LINK}`}
|
||||
target="_blank"
|
||||
>{`${
|
||||
createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE
|
||||
}${DOCS_LINK}`}</ExternalLink>
|
||||
>{`${DocsLinks.PROPOSALS_GUIDE}${DOCS_LINK}`}</ExternalLink>
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
+6
-10
@@ -7,8 +7,8 @@ import {
|
||||
getEnactmentTimestamp,
|
||||
useProposalSubmit,
|
||||
} from '@vegaprotocol/proposals';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { createDocsLinks, validateJson } from '@vegaprotocol/utils';
|
||||
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
|
||||
import { validateJson } from '@vegaprotocol/utils';
|
||||
import {
|
||||
NetworkParams,
|
||||
useNetworkParams,
|
||||
@@ -98,7 +98,7 @@ export const ProposeUpdateMarket = () => {
|
||||
const [selectedMarket, setSelectedMarket] = useState<string | undefined>(
|
||||
undefined
|
||||
);
|
||||
const { VEGA_EXPLORER_URL, VEGA_DOCS_URL } = useEnvironment();
|
||||
const { VEGA_EXPLORER_URL } = useEnvironment();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
register,
|
||||
@@ -181,17 +181,13 @@ export const ProposeUpdateMarket = () => {
|
||||
userAction={ProposalUserAction.CREATE}
|
||||
/>
|
||||
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<p className="text-sm" data-testid="proposal-docs-link">
|
||||
<span className="mr-1">{t('ProposalTermsText')}</span>
|
||||
<ExternalLink
|
||||
href={`${
|
||||
createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE
|
||||
}${DOCS_LINK}`}
|
||||
href={`${DocsLinks.PROPOSALS_GUIDE}${DOCS_LINK}`}
|
||||
target="_blank"
|
||||
>{`${
|
||||
createDocsLinks(VEGA_DOCS_URL).PROPOSALS_GUIDE
|
||||
}${DOCS_LINK}`}</ExternalLink>
|
||||
>{`${DocsLinks.PROPOSALS_GUIDE}${DOCS_LINK}`}</ExternalLink>
|
||||
</p>
|
||||
)}
|
||||
|
||||
|
||||
+4
-2
@@ -25,7 +25,7 @@ const mockData = {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
ACCOUNT_TYPE_FEES_LIQUIDITY: {
|
||||
ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES: {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
@@ -55,7 +55,9 @@ describe('EpochIndividualRewardsTable', () => {
|
||||
expect(
|
||||
getByTestId('ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES')
|
||||
).toBeInTheDocument();
|
||||
expect(getByTestId('ACCOUNT_TYPE_FEES_LIQUIDITY')).toBeInTheDocument();
|
||||
expect(
|
||||
getByTestId('ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByTestId('ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS')
|
||||
).toBeInTheDocument();
|
||||
|
||||
+11
-11
@@ -24,7 +24,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
};
|
||||
|
||||
const reward3: RewardFieldsFragment = {
|
||||
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
rewardType: AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
amount: '200',
|
||||
percentageOfTotal: '0.2',
|
||||
receivedAt: new Date(),
|
||||
@@ -34,7 +34,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
};
|
||||
|
||||
const reward4: RewardFieldsFragment = {
|
||||
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
rewardType: AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
amount: '100',
|
||||
percentageOfTotal: '0.1',
|
||||
receivedAt: new Date(),
|
||||
@@ -44,7 +44,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
};
|
||||
|
||||
const reward5: RewardFieldsFragment = {
|
||||
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
rewardType: AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
amount: '150',
|
||||
percentageOfTotal: '0.15',
|
||||
receivedAt: new Date(),
|
||||
@@ -105,7 +105,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY]: {
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
@@ -172,7 +172,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY]: {
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
amount: '200',
|
||||
percentageOfTotal: '0.2',
|
||||
},
|
||||
@@ -202,7 +202,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY]: {
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
@@ -237,7 +237,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY]: {
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
amount: '100',
|
||||
percentageOfTotal: '0.1',
|
||||
},
|
||||
@@ -285,7 +285,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY]: {
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
amount: '150',
|
||||
percentageOfTotal: '0.15',
|
||||
},
|
||||
@@ -320,7 +320,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY]: {
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
amount: '200',
|
||||
percentageOfTotal: '0.2',
|
||||
},
|
||||
@@ -350,7 +350,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY]: {
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
@@ -395,7 +395,7 @@ describe('generateEpochIndividualRewardsList', () => {
|
||||
amount: '0',
|
||||
percentageOfTotal: '0',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY]: {
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
amount: '100',
|
||||
percentageOfTotal: '0.1',
|
||||
},
|
||||
|
||||
+4
-2
@@ -29,7 +29,7 @@ const rewardsList = [
|
||||
amount: '0',
|
||||
},
|
||||
{
|
||||
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
rewardType: AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
amount: '0',
|
||||
},
|
||||
{
|
||||
@@ -78,7 +78,9 @@ describe('EpochTotalRewardsTable', () => {
|
||||
expect(
|
||||
getByTestId('ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES')
|
||||
).toBeInTheDocument();
|
||||
expect(getByTestId('ACCOUNT_TYPE_FEES_LIQUIDITY')).toBeInTheDocument();
|
||||
expect(
|
||||
getByTestId('ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES')
|
||||
).toBeInTheDocument();
|
||||
expect(
|
||||
getByTestId('ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS')
|
||||
).toBeInTheDocument();
|
||||
|
||||
+21
-15
@@ -162,9 +162,10 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
},
|
||||
],
|
||||
[
|
||||
AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
{
|
||||
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
rewardType:
|
||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
amount: '0',
|
||||
},
|
||||
],
|
||||
@@ -227,7 +228,7 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
node: {
|
||||
epoch: 2,
|
||||
assetId: '1',
|
||||
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
rewardType: AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
amount: '5',
|
||||
},
|
||||
},
|
||||
@@ -287,9 +288,10 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
},
|
||||
],
|
||||
[
|
||||
AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
{
|
||||
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
rewardType:
|
||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
amount: '0',
|
||||
},
|
||||
],
|
||||
@@ -351,9 +353,10 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
},
|
||||
],
|
||||
[
|
||||
AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
{
|
||||
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
rewardType:
|
||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
amount: '5',
|
||||
},
|
||||
],
|
||||
@@ -416,7 +419,7 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
node: {
|
||||
epoch: 2,
|
||||
assetId: '1',
|
||||
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
rewardType: AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
amount: '6',
|
||||
},
|
||||
},
|
||||
@@ -424,7 +427,7 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
node: {
|
||||
epoch: 2,
|
||||
assetId: '1',
|
||||
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
rewardType: AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
amount: '27',
|
||||
},
|
||||
},
|
||||
@@ -497,9 +500,10 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
},
|
||||
],
|
||||
[
|
||||
AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
{
|
||||
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
rewardType:
|
||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
amount: '33',
|
||||
},
|
||||
],
|
||||
@@ -561,9 +565,10 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
},
|
||||
],
|
||||
[
|
||||
AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
{
|
||||
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
rewardType:
|
||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
amount: '0',
|
||||
},
|
||||
],
|
||||
@@ -637,9 +642,10 @@ describe('generateEpochAssetRewardsList', () => {
|
||||
},
|
||||
],
|
||||
[
|
||||
AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
{
|
||||
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
|
||||
rewardType:
|
||||
AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES,
|
||||
amount: '0',
|
||||
},
|
||||
],
|
||||
|
||||
@@ -11,7 +11,6 @@ import {
|
||||
ExternalLink,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { createDocsLinks } from '@vegaprotocol/utils';
|
||||
import {
|
||||
useNetworkParams,
|
||||
NetworkParams,
|
||||
@@ -21,7 +20,7 @@ import { EpochCountdown } from '../../../components/epoch-countdown';
|
||||
import { Heading, SubHeading } from '../../../components/heading';
|
||||
import { EpochIndividualRewards } from '../epoch-individual-rewards/epoch-individual-rewards';
|
||||
import { useRefreshAfterEpoch } from '../../../hooks/use-refresh-after-epoch';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { DocsLinks } from '@vegaprotocol/environment';
|
||||
import { ConnectToSeeRewards } from '../connect-to-see-rewards';
|
||||
import { EpochTotalRewards } from '../epoch-total-rewards/epoch-total-rewards';
|
||||
|
||||
@@ -29,7 +28,6 @@ type RewardsView = 'total' | 'individual';
|
||||
|
||||
export const RewardsPage = () => {
|
||||
const { t } = useTranslation();
|
||||
const { VEGA_DOCS_URL } = useEnvironment();
|
||||
const { pubKey, pubKeys } = useVegaWallet();
|
||||
const [toggleRewardsView, setToggleRewardsView] =
|
||||
useState<RewardsView>('total');
|
||||
@@ -68,9 +66,9 @@ export const RewardsPage = () => {
|
||||
<Heading title={t('pageTitleRewards')} />
|
||||
<p className="mb-12">
|
||||
{t('rewardsIntro')}{' '}
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<ExternalLink
|
||||
href={createDocsLinks(VEGA_DOCS_URL).REWARDS_GUIDE}
|
||||
href={DocsLinks.REWARDS_GUIDE}
|
||||
target="_blank"
|
||||
data-testid="rewards-guide-link"
|
||||
className="text-white"
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ export const RowAccountTypes = {
|
||||
columnTitle: 'rewardsColPriceMakingHeader',
|
||||
description: 'rewardsColPriceMakingTooltip',
|
||||
},
|
||||
[AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY]: {
|
||||
[AccountType.ACCOUNT_TYPE_REWARD_LP_RECEIVED_FEES]: {
|
||||
columnTitle: 'rewardsColLiquidityProvisionHeader',
|
||||
description: 'rewardsColLiquidityProvisionTooltip',
|
||||
},
|
||||
|
||||
@@ -229,7 +229,7 @@ const redirects = [
|
||||
const routerConfig = [
|
||||
{
|
||||
path: Routes.HOME,
|
||||
element: <LazyHome name="Token" />,
|
||||
element: <LazyHome name="Home" />,
|
||||
},
|
||||
{
|
||||
path: Routes.PROPOSALS,
|
||||
@@ -291,7 +291,7 @@ const routerConfig = [
|
||||
// Not lazy as loaded when a user first hits the site
|
||||
children: [
|
||||
{
|
||||
element: <Home name="Home" />,
|
||||
element: <Home name="Token" />,
|
||||
index: true,
|
||||
},
|
||||
{
|
||||
@@ -325,8 +325,11 @@ const routerConfig = [
|
||||
},
|
||||
],
|
||||
},
|
||||
{ path: 'associate', element: <LazyStakingAssociate /> },
|
||||
{ path: 'disassociate', element: <LazyStakingDisassociate /> },
|
||||
{ path: 'associate', element: <LazyStakingAssociate name="Associate" /> },
|
||||
{
|
||||
path: 'disassociate',
|
||||
element: <LazyStakingDisassociate name="Disassociate" />,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
import { useEthereumConfig } from '@vegaprotocol/web3';
|
||||
import { StakingWalletsContainer } from './components/staking-wallets-container/staking-wallets-container';
|
||||
import { StakingWalletsContainer } from './components/staking-wallets-container';
|
||||
import { AssociatePage } from './associate-page';
|
||||
import { AssociatePageNoVega } from './associate-page-no-vega';
|
||||
import { Heading } from '../../../components/heading';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||
import type { RouteChildProps } from '../../index';
|
||||
|
||||
export const AssociateContainer = () => {
|
||||
export const AssociateContainer = ({ name }: RouteChildProps) => {
|
||||
useDocumentTitle(name);
|
||||
const { t } = useTranslation();
|
||||
const { config } = useEthereumConfig();
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ jest.mock('@vegaprotocol/wallet', () => ({
|
||||
}));
|
||||
|
||||
const renderComponent = () => {
|
||||
return render(<Disassociate />);
|
||||
return render(<Disassociate name="Disassociate" />);
|
||||
};
|
||||
|
||||
describe('Disassociate', () => {
|
||||
|
||||
@@ -3,10 +3,12 @@ import { useWeb3React } from '@web3-react/core';
|
||||
import { EthConnectPrompt } from '../../../components/eth-connect-prompt';
|
||||
import { DisassociatePage } from './components/disassociate-page';
|
||||
import { Heading } from '../../../components/heading';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDocumentTitle } from '../../../hooks/use-document-title';
|
||||
import type { RouteChildProps } from '../../index';
|
||||
|
||||
export const DisassociateContainer = () => {
|
||||
export const DisassociateContainer = ({ name }: RouteChildProps) => {
|
||||
useDocumentTitle(name);
|
||||
const { t } = useTranslation();
|
||||
const { account } = useWeb3React();
|
||||
const { pubKey } = useVegaWallet();
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { EpochData } from './epoch-data';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { DocsLinks } from '@vegaprotocol/environment';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { createDocsLinks } from '@vegaprotocol/utils';
|
||||
import { Heading } from '../../../components/heading';
|
||||
import React from 'react';
|
||||
|
||||
export const Staking = () => {
|
||||
const { t } = useTranslation();
|
||||
const { VEGA_DOCS_URL } = useEnvironment();
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -16,9 +14,9 @@ export const Staking = () => {
|
||||
<section>
|
||||
<p className="mb-12">
|
||||
{t('stakingIntro')}{' '}
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<ExternalLink
|
||||
href={createDocsLinks(VEGA_DOCS_URL).STAKING_GUIDE}
|
||||
href={DocsLinks.STAKING_GUIDE}
|
||||
target="_blank"
|
||||
data-testid="staking-guide-link"
|
||||
className="text-white"
|
||||
|
||||
+69
-58
@@ -131,20 +131,25 @@ export const ConsensusValidatorsTable = ({
|
||||
|
||||
const gridRef = useRef<AgGridReact | null>(null);
|
||||
|
||||
const thirdOfTotalStake = useMemo(
|
||||
() => new BigNumber(totalStake).dividedBy(3),
|
||||
[totalStake]
|
||||
);
|
||||
|
||||
const nodes = useMemo(() => {
|
||||
if (!data) return [];
|
||||
let canonisedNodes = data
|
||||
.sort((a, b) => {
|
||||
const aVotingPower = new BigNumber(a.rankingScore.votingPower);
|
||||
const bVotingPower = new BigNumber(b.rankingScore.votingPower);
|
||||
return bVotingPower.minus(aVotingPower).toNumber();
|
||||
const aStakedTotal = new BigNumber(a.stakedTotal);
|
||||
const bStakedTotal = new BigNumber(b.stakedTotal);
|
||||
return bStakedTotal.minus(aStakedTotal).toNumber();
|
||||
})
|
||||
.map((node, index) => {
|
||||
const votingPowerRanking = index + 1;
|
||||
const stakedTotalRanking = index + 1;
|
||||
|
||||
return {
|
||||
...node,
|
||||
votingPowerRanking,
|
||||
stakedTotalRanking,
|
||||
};
|
||||
})
|
||||
.map(
|
||||
@@ -157,7 +162,7 @@ export const ConsensusValidatorsTable = ({
|
||||
stakedTotal,
|
||||
rankingScore: { stakeScore, votingPower },
|
||||
pendingStake,
|
||||
votingPowerRanking,
|
||||
stakedTotalRanking,
|
||||
stakedByUser,
|
||||
pendingUserStake,
|
||||
userStakeShare,
|
||||
@@ -175,7 +180,7 @@ export const ConsensusValidatorsTable = ({
|
||||
|
||||
return {
|
||||
id,
|
||||
[ValidatorFields.RANKING_INDEX]: votingPowerRanking,
|
||||
[ValidatorFields.RANKING_INDEX]: stakedTotalRanking,
|
||||
[ValidatorFields.VALIDATOR]: {
|
||||
avatarUrl: logo,
|
||||
name,
|
||||
@@ -236,16 +241,12 @@ export const ConsensusValidatorsTable = ({
|
||||
return canonisedNodes;
|
||||
}
|
||||
|
||||
// The point of identifying and hiding the group that could halt the network
|
||||
// is that we assume the top 1/3 of stake is held by considerably less than
|
||||
// 1/3 of the validators and we really want people not to stake any more to
|
||||
// that group, because we want to make it require as many difference
|
||||
// validators to collude as possible to halt the network, so we hide them.
|
||||
const { topThird, remaining } = canonisedNodes.reduce(
|
||||
(acc, node) => {
|
||||
if (acc.cumulativeScore < 100 / 3) {
|
||||
acc.cumulativeScore += parseFloat(
|
||||
node[ValidatorFields.NORMALISED_VOTING_POWER]
|
||||
if (acc.cumulativeScore.isLessThan(thirdOfTotalStake)) {
|
||||
const prev = acc.cumulativeScore;
|
||||
acc.cumulativeScore = prev.plus(
|
||||
new BigNumber(node[ValidatorFields.STAKE])
|
||||
);
|
||||
acc.topThird.push(node);
|
||||
return acc;
|
||||
@@ -253,61 +254,70 @@ export const ConsensusValidatorsTable = ({
|
||||
acc.remaining.push(node);
|
||||
return acc;
|
||||
},
|
||||
{ topThird: [], remaining: [], cumulativeScore: 0 } as {
|
||||
{ topThird: [], remaining: [], cumulativeScore: new BigNumber(0) } as {
|
||||
topThird: CanonisedConsensusNodeProps[];
|
||||
remaining: CanonisedConsensusNodeProps[];
|
||||
cumulativeScore: number;
|
||||
cumulativeScore: BigNumber;
|
||||
}
|
||||
);
|
||||
|
||||
// We need to combine the top third of validators into a single node, this
|
||||
// way the combined values can be passed to AG grid so that the combined cell's
|
||||
// values are correct for ordering.
|
||||
const combinedTopThird = topThird.reduce((acc, node) => {
|
||||
const {
|
||||
[ValidatorFields.STAKE]: stake,
|
||||
[ValidatorFields.STAKE_SHARE]: stakeShare,
|
||||
[ValidatorFields.PENDING_STAKE]: pendingStake,
|
||||
[ValidatorFields.NORMALISED_VOTING_POWER]: normalisedVotingPower,
|
||||
[ValidatorFields.TOTAL_PENALTIES]: totalPenalties,
|
||||
} = node;
|
||||
const combinedTopThird = topThird.reduce(
|
||||
(acc, node) => {
|
||||
const {
|
||||
[ValidatorFields.STAKE]: stake,
|
||||
[ValidatorFields.STAKE_SHARE]: stakeShare,
|
||||
[ValidatorFields.PENDING_STAKE]: pendingStake,
|
||||
[ValidatorFields.NORMALISED_VOTING_POWER]: normalisedVotingPower,
|
||||
[ValidatorFields.TOTAL_PENALTIES]: totalPenalties,
|
||||
} = node;
|
||||
|
||||
const {
|
||||
[ValidatorFields.STAKE]: accStake,
|
||||
[ValidatorFields.STAKE_SHARE]: accStakeShare,
|
||||
[ValidatorFields.PENDING_STAKE]: accPendingStake,
|
||||
[ValidatorFields.NORMALISED_VOTING_POWER]: accNormalisedVotingPower,
|
||||
[ValidatorFields.TOTAL_PENALTIES]: accTotalPenalties,
|
||||
} = acc;
|
||||
const {
|
||||
[ValidatorFields.STAKE]: accStake,
|
||||
[ValidatorFields.STAKE_SHARE]: accStakeShare,
|
||||
[ValidatorFields.PENDING_STAKE]: accPendingStake,
|
||||
[ValidatorFields.NORMALISED_VOTING_POWER]: accNormalisedVotingPower,
|
||||
[ValidatorFields.TOTAL_PENALTIES]: accTotalPenalties,
|
||||
} = acc;
|
||||
|
||||
return {
|
||||
...acc,
|
||||
[ValidatorFields.STAKE]: toBigNum(accStake, decimals)
|
||||
.plus(toBigNum(stake, decimals))
|
||||
.toString(),
|
||||
[ValidatorFields.STAKE_SHARE]: formatNumberPercentage(
|
||||
new BigNumber(parseFloat(accStakeShare)).plus(
|
||||
new BigNumber(parseFloat(stakeShare))
|
||||
return {
|
||||
...acc,
|
||||
[ValidatorFields.STAKE]: new BigNumber(accStake)
|
||||
.plus(new BigNumber(stake))
|
||||
.toString(),
|
||||
[ValidatorFields.STAKE_SHARE]: formatNumberPercentage(
|
||||
new BigNumber(parseFloat(accStakeShare)).plus(
|
||||
new BigNumber(parseFloat(stakeShare))
|
||||
),
|
||||
2
|
||||
),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.PENDING_STAKE]: toBigNum(accPendingStake, decimals)
|
||||
.plus(toBigNum(pendingStake, decimals))
|
||||
.toString(),
|
||||
[ValidatorFields.NORMALISED_VOTING_POWER]: formatNumberPercentage(
|
||||
new BigNumber(parseFloat(accNormalisedVotingPower)).plus(
|
||||
new BigNumber(parseFloat(normalisedVotingPower))
|
||||
[ValidatorFields.PENDING_STAKE]: toBigNum(accPendingStake, decimals)
|
||||
.plus(toBigNum(pendingStake, decimals))
|
||||
.toString(),
|
||||
[ValidatorFields.NORMALISED_VOTING_POWER]: formatNumberPercentage(
|
||||
new BigNumber(parseFloat(accNormalisedVotingPower)).plus(
|
||||
new BigNumber(parseFloat(normalisedVotingPower))
|
||||
),
|
||||
2
|
||||
),
|
||||
2
|
||||
),
|
||||
[ValidatorFields.TOTAL_PENALTIES]: formatNumberPercentage(
|
||||
new BigNumber(parseFloat(accTotalPenalties)).plus(
|
||||
new BigNumber(parseFloat(totalPenalties))
|
||||
[ValidatorFields.TOTAL_PENALTIES]: formatNumberPercentage(
|
||||
new BigNumber(parseFloat(accTotalPenalties)).plus(
|
||||
new BigNumber(parseFloat(totalPenalties))
|
||||
),
|
||||
2
|
||||
),
|
||||
2
|
||||
),
|
||||
};
|
||||
});
|
||||
};
|
||||
},
|
||||
{
|
||||
[ValidatorFields.STAKE]: '0',
|
||||
[ValidatorFields.STAKE_SHARE]: '0',
|
||||
[ValidatorFields.PENDING_STAKE]: '0',
|
||||
[ValidatorFields.NORMALISED_VOTING_POWER]: '0',
|
||||
[ValidatorFields.TOTAL_PENALTIES]: '0',
|
||||
}
|
||||
);
|
||||
|
||||
return [
|
||||
{
|
||||
@@ -322,6 +332,7 @@ export const ConsensusValidatorsTable = ({
|
||||
decimals,
|
||||
hideTopThird,
|
||||
previousEpochData,
|
||||
thirdOfTotalStake,
|
||||
totalStake,
|
||||
validatorsView,
|
||||
]);
|
||||
@@ -352,6 +363,7 @@ export const ConsensusValidatorsTable = ({
|
||||
headerTooltip: t('StakeDescription').toString(),
|
||||
cellRenderer: TotalStakeRenderer,
|
||||
width: 120,
|
||||
sort: 'desc',
|
||||
},
|
||||
{
|
||||
field: ValidatorFields.PENDING_STAKE,
|
||||
@@ -373,7 +385,6 @@ export const ConsensusValidatorsTable = ({
|
||||
headerTooltip: t('NormalisedVotingPowerDescription').toString(),
|
||||
cellRenderer: VotingPowerRenderer,
|
||||
width: 200,
|
||||
sort: 'desc',
|
||||
},
|
||||
{
|
||||
field: ValidatorFields.TOTAL_PENALTIES,
|
||||
|
||||
+9
-9
@@ -57,16 +57,16 @@ export const StandbyPendingValidatorsTable = ({
|
||||
|
||||
return data
|
||||
.sort((a, b) => {
|
||||
const aVotingPower = new BigNumber(a.rankingScore.votingPower);
|
||||
const bVotingPower = new BigNumber(b.rankingScore.votingPower);
|
||||
return bVotingPower.minus(aVotingPower).toNumber();
|
||||
const aStakedTotal = new BigNumber(a.stakedTotal);
|
||||
const bStakedTotal = new BigNumber(b.stakedTotal);
|
||||
return bStakedTotal.minus(aStakedTotal).toNumber();
|
||||
})
|
||||
.map((node, index) => {
|
||||
const votingPowerRanking = index + 1;
|
||||
const stakedTotalRanking = index + 1;
|
||||
|
||||
return {
|
||||
...node,
|
||||
votingPowerRanking,
|
||||
stakedTotalRanking,
|
||||
};
|
||||
})
|
||||
.map(
|
||||
@@ -79,7 +79,7 @@ export const StandbyPendingValidatorsTable = ({
|
||||
stakedTotal,
|
||||
rankingScore: { stakeScore },
|
||||
pendingStake,
|
||||
votingPowerRanking,
|
||||
stakedTotalRanking,
|
||||
stakedByUser,
|
||||
pendingUserStake,
|
||||
userStakeShare,
|
||||
@@ -125,7 +125,7 @@ export const StandbyPendingValidatorsTable = ({
|
||||
|
||||
return {
|
||||
id,
|
||||
[ValidatorFields.RANKING_INDEX]: votingPowerRanking,
|
||||
[ValidatorFields.RANKING_INDEX]: stakedTotalRanking,
|
||||
[ValidatorFields.VALIDATOR]: {
|
||||
avatarUrl,
|
||||
name,
|
||||
@@ -166,7 +166,7 @@ export const StandbyPendingValidatorsTable = ({
|
||||
: undefined,
|
||||
[ValidatorFields.PENDING_USER_STAKE]: pendingUserStake,
|
||||
[ValidatorFields.USER_STAKE_SHARE]: userStakeShare
|
||||
? formatNumberPercentage(new BigNumber(userStakeShare))
|
||||
? formatNumberPercentage(new BigNumber(userStakeShare), 2)
|
||||
: undefined,
|
||||
};
|
||||
}
|
||||
@@ -210,6 +210,7 @@ export const StandbyPendingValidatorsTable = ({
|
||||
headerTooltip: t('StakeDescription').toString(),
|
||||
cellRenderer: TotalStakeRenderer,
|
||||
width: 120,
|
||||
sort: 'desc',
|
||||
},
|
||||
{
|
||||
field: ValidatorFields.PENDING_STAKE,
|
||||
@@ -233,7 +234,6 @@ export const StandbyPendingValidatorsTable = ({
|
||||
}),
|
||||
cellRenderer: StakeNeededForPromotionRenderer,
|
||||
width: 210,
|
||||
sort: 'asc',
|
||||
},
|
||||
{
|
||||
field: ValidatorFields.TOTAL_PENALTIES,
|
||||
|
||||
@@ -2,12 +2,8 @@ import { useMemo, useState } from 'react';
|
||||
import { Trans, useTranslation } from 'react-i18next';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import {
|
||||
createDocsLinks,
|
||||
removePaginationWrapper,
|
||||
toBigNum,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { removePaginationWrapper, toBigNum } from '@vegaprotocol/utils';
|
||||
import { DocsLinks } from '@vegaprotocol/environment';
|
||||
import { Link as UTLink, Toggle } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
import { formatNumber } from '../../../../lib/format-number';
|
||||
@@ -42,7 +38,6 @@ export const ValidatorTables = ({
|
||||
previousEpochData,
|
||||
}: ValidatorsTableProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { VEGA_DOCS_URL } = useEnvironment();
|
||||
const {
|
||||
appState: { decimals },
|
||||
} = useAppState();
|
||||
@@ -213,12 +208,12 @@ export const ValidatorTables = ({
|
||||
<>
|
||||
<SubHeading title={t('status-pending')} />
|
||||
<p>
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<>
|
||||
<span>{t('pendingDescription1')} </span>
|
||||
<span>
|
||||
<UTLink
|
||||
href={createDocsLinks(VEGA_DOCS_URL).STAKING_GUIDE}
|
||||
href={DocsLinks.STAKING_GUIDE}
|
||||
target="_blank"
|
||||
data-testid="validator-forum-link"
|
||||
>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { ENV } from '../../../config';
|
||||
import { Callout, Intent, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
@@ -10,6 +9,7 @@ import { usePreviousEpochQuery } from '../__generated__/PreviousEpoch';
|
||||
import type { ReactElement } from 'react';
|
||||
import type { StakingQuery } from '../__generated__/Staking';
|
||||
import type { PreviousEpochQuery } from '../__generated__/PreviousEpoch';
|
||||
import { isPartyNotFoundError } from '../../../lib/party';
|
||||
|
||||
// TODO should only request a single node. When migrating from deprecated APIs we should address this.
|
||||
|
||||
@@ -39,21 +39,9 @@ export const NodeContainer = ({
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
errorPolicy: 'all',
|
||||
});
|
||||
|
||||
const [isRefetching, setIsRefetching] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (error && error.message.includes('failed to get party for ID')) {
|
||||
setIsRefetching(true);
|
||||
// The API errors if there is a pubkey, but it hasn't interacted with the
|
||||
// chain before. In that case, retry the query with empty pubKey
|
||||
refetch({
|
||||
partyId: '',
|
||||
}).finally(() => setIsRefetching(false));
|
||||
}
|
||||
}, [error, refetch, delegationsPagination]);
|
||||
|
||||
const { data: previousEpochData } = usePreviousEpochQuery({
|
||||
variables: {
|
||||
epochId: (Number(data?.epoch.id) - 1).toString(),
|
||||
@@ -63,7 +51,7 @@ export const NodeContainer = ({
|
||||
|
||||
useRefreshAfterEpoch(data?.epoch.timestamps.expiry, refetch);
|
||||
|
||||
if (error && !isRefetching) {
|
||||
if (error && !isPartyNotFoundError(error)) {
|
||||
return (
|
||||
<Callout intent={Intent.Danger} title={t('Something went wrong')}>
|
||||
<pre>
|
||||
@@ -75,7 +63,7 @@ export const NodeContainer = ({
|
||||
);
|
||||
}
|
||||
|
||||
if (loading || isRefetching) {
|
||||
if (loading) {
|
||||
return (
|
||||
<Splash>
|
||||
<SplashLoader />
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
import React, { useMemo } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { createDocsLinks, ExternalLinks, toBigNum } from '@vegaprotocol/utils';
|
||||
import {
|
||||
useEnvironment,
|
||||
DocsLinks,
|
||||
ExternalLinks,
|
||||
} from '@vegaprotocol/environment';
|
||||
import { toBigNum } from '@vegaprotocol/utils';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import {
|
||||
Link as UTLink,
|
||||
@@ -64,7 +68,7 @@ export const ValidatorTable = ({
|
||||
stakedTotal,
|
||||
previousEpochData,
|
||||
}: ValidatorTableProps) => {
|
||||
const { ETHERSCAN_URL, VEGA_DOCS_URL } = useEnvironment();
|
||||
const { ETHERSCAN_URL } = useEnvironment();
|
||||
const { t } = useTranslation();
|
||||
const {
|
||||
appState: { decimals },
|
||||
@@ -90,9 +94,9 @@ export const ValidatorTable = ({
|
||||
<>
|
||||
<p className="mb-12">
|
||||
{t('validatorFormIntro')}{' '}
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<ExternalLink
|
||||
href={createDocsLinks(VEGA_DOCS_URL).STAKING_GUIDE}
|
||||
href={DocsLinks.STAKING_GUIDE}
|
||||
target="_blank"
|
||||
data-testid="validator-table-staking-guide-link"
|
||||
className="text-white"
|
||||
|
||||
@@ -60,9 +60,14 @@ export const getOverstakingPenalty = (
|
||||
}
|
||||
|
||||
return formatNumberPercentage(
|
||||
new BigNumber(1)
|
||||
.minus(new BigNumber(validatorScore).dividedBy(new BigNumber(stakeScore)))
|
||||
.times(100),
|
||||
BigNumber.max(
|
||||
new BigNumber(1)
|
||||
.minus(
|
||||
new BigNumber(validatorScore).dividedBy(new BigNumber(stakeScore))
|
||||
)
|
||||
.times(100),
|
||||
new BigNumber(0)
|
||||
),
|
||||
2
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,7 +3,8 @@ import { Trans, useTranslation } from 'react-i18next';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
import { Heading, SubHeading } from '../../components/heading';
|
||||
import { ExternalLinks, toBigNum } from '@vegaprotocol/utils';
|
||||
import { ExternalLinks } from '@vegaprotocol/environment';
|
||||
import { toBigNum } from '@vegaprotocol/utils';
|
||||
import { useAppState } from '../../contexts/app-state/app-state-context';
|
||||
import { useDocumentTitle } from '../../hooks/use-document-title';
|
||||
import type { RouteChildProps } from '..';
|
||||
|
||||
@@ -40,9 +40,9 @@
|
||||
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
|
||||
}
|
||||
|
||||
.vega-ag-grid .ag-row {
|
||||
border-width: 1px 0;
|
||||
border-bottom: 1px solid transparent;
|
||||
.vega-ag-grid .ag-row,
|
||||
.vega-ag-grid .ag-cell {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
/* Dark variables */
|
||||
@@ -54,7 +54,6 @@
|
||||
--ag-header-column-separator-color: theme(colors.neutral[600]);
|
||||
--ag-row-border-color: theme(colors.black);
|
||||
--ag-row-hover-color: theme(colors.neutral[800]);
|
||||
--ag-font-size: 12px;
|
||||
}
|
||||
|
||||
.validators-table .ag-theme-balham-dark .ag-body-horizontal-scroll {
|
||||
|
||||
@@ -36,12 +36,54 @@
|
||||
"tranche_id": 58,
|
||||
"tranche_start": "2023-05-11T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-11T00:00:00.000Z",
|
||||
"total_added": "0",
|
||||
"total_added": "11570",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "0",
|
||||
"deposits": [],
|
||||
"locked_amount": "8953.108251194743961",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "11447",
|
||||
"user": "0x73F1955867a9b19ADFEa2cc3f425839607126ec7",
|
||||
"tx": "0xd31ed81d798f6690586935dbc6e722b3d2a3b6a049be4565dc7a4894084f0a05"
|
||||
},
|
||||
{
|
||||
"amount": "123",
|
||||
"user": "0x6A228Fffda4D1B3C773b9ce38DA43592581b36FC",
|
||||
"tx": "0xd6e8129942a80bb2a611c07347ed0f0917690e67cbd99cba1922b5c4aed2f179"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"users": []
|
||||
"users": [
|
||||
{
|
||||
"address": "0x73F1955867a9b19ADFEa2cc3f425839607126ec7",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "11447",
|
||||
"user": "0x73F1955867a9b19ADFEa2cc3f425839607126ec7",
|
||||
"tranche_id": 58,
|
||||
"tx": "0xd31ed81d798f6690586935dbc6e722b3d2a3b6a049be4565dc7a4894084f0a05"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "11447",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "11447"
|
||||
},
|
||||
{
|
||||
"address": "0x6A228Fffda4D1B3C773b9ce38DA43592581b36FC",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "123",
|
||||
"user": "0x6A228Fffda4D1B3C773b9ce38DA43592581b36FC",
|
||||
"tranche_id": 58,
|
||||
"tx": "0xd6e8129942a80bb2a611c07347ed0f0917690e67cbd99cba1922b5c4aed2f179"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "123",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "123"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"tranche_id": 57,
|
||||
@@ -80,10 +122,15 @@
|
||||
"tranche_id": 56,
|
||||
"tranche_start": "2023-04-20T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-20T00:00:00.000Z",
|
||||
"total_added": "19242.125",
|
||||
"total_added": "20139.125",
|
||||
"total_removed": "2667.900599530005",
|
||||
"locked_amount": "1760.572777247300418465",
|
||||
"locked_amount": "1334.85414863040152049375",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "897",
|
||||
"user": "0xfaa18BFeb7bfe6AF79Ec6dA193A8737C06163AFd",
|
||||
"tx": "0x0e321b8af82bbdc845f5b6c6d3cccd68f14d23cd5d3c33c3df17ba3a4885b0bc"
|
||||
},
|
||||
{
|
||||
"amount": "188",
|
||||
"user": "0x90Cf7B9958C3BbBCddAb52Ecc408535D4f3C4241",
|
||||
@@ -318,6 +365,21 @@
|
||||
}
|
||||
],
|
||||
"users": [
|
||||
{
|
||||
"address": "0xfaa18BFeb7bfe6AF79Ec6dA193A8737C06163AFd",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "897",
|
||||
"user": "0xfaa18BFeb7bfe6AF79Ec6dA193A8737C06163AFd",
|
||||
"tranche_id": 56,
|
||||
"tx": "0x0e321b8af82bbdc845f5b6c6d3cccd68f14d23cd5d3c33c3df17ba3a4885b0bc"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "897",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "897"
|
||||
},
|
||||
{
|
||||
"address": "0x90Cf7B9958C3BbBCddAb52Ecc408535D4f3C4241",
|
||||
"deposits": [
|
||||
@@ -964,8 +1026,8 @@
|
||||
"tranche_id": 54,
|
||||
"tranche_start": "2023-04-06T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-06T00:00:00.000Z",
|
||||
"total_added": "14610",
|
||||
"total_removed": "7227.45090157707",
|
||||
"total_added": "14658",
|
||||
"total_removed": "7275.45090157707",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
@@ -973,6 +1035,11 @@
|
||||
"user": "0x05659B08a8079E003eE37F26c29e52532728c034",
|
||||
"tx": "0x83cb92910e0725b82b3459e025260c448f931224f7cb00a376351dbd75ae2733"
|
||||
},
|
||||
{
|
||||
"amount": "48",
|
||||
"user": "0x2a65Ae527C6Ff4665e048B0E0883c486A7BA4DBc",
|
||||
"tx": "0x6d708d9b252c3ef0eb41c1bb5f412ae4a644ba3483bbdb329d403728c8257794"
|
||||
},
|
||||
{
|
||||
"amount": "111",
|
||||
"user": "0x90Cf7B9958C3BbBCddAb52Ecc408535D4f3C4241",
|
||||
@@ -1190,6 +1257,11 @@
|
||||
"user": "0xf9c6C5F942B94Db9dedC550956865cf99D743959",
|
||||
"tx": "0x4fa5d02d920d90835694cbab1e41a66d317b2bc35860d07a5ccd70d12182116b"
|
||||
},
|
||||
{
|
||||
"amount": "48",
|
||||
"user": "0x2a65Ae527C6Ff4665e048B0E0883c486A7BA4DBc",
|
||||
"tx": "0x54ac8f0ed6570e6ce5fc437f15744be4be5c716c08fa7cf58d23ed93ca29dc84"
|
||||
},
|
||||
{
|
||||
"amount": "106.53500000286",
|
||||
"user": "0x6F32AA5A6198329c16e438512F992a0548C856f9",
|
||||
@@ -1259,6 +1331,28 @@
|
||||
"withdrawn_tokens": "90",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x2a65Ae527C6Ff4665e048B0E0883c486A7BA4DBc",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "48",
|
||||
"user": "0x2a65Ae527C6Ff4665e048B0E0883c486A7BA4DBc",
|
||||
"tranche_id": 54,
|
||||
"tx": "0x6d708d9b252c3ef0eb41c1bb5f412ae4a644ba3483bbdb329d403728c8257794"
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "48",
|
||||
"user": "0x2a65Ae527C6Ff4665e048B0E0883c486A7BA4DBc",
|
||||
"tranche_id": 54,
|
||||
"tx": "0x54ac8f0ed6570e6ce5fc437f15744be4be5c716c08fa7cf58d23ed93ca29dc84"
|
||||
}
|
||||
],
|
||||
"total_tokens": "48",
|
||||
"withdrawn_tokens": "48",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x90Cf7B9958C3BbBCddAb52Ecc408535D4f3C4241",
|
||||
"deposits": [
|
||||
@@ -5045,7 +5139,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "86666.297",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "47902.6878201683513969045",
|
||||
"locked_amount": "47723.0811534878766318718",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "86666.297",
|
||||
@@ -5111,7 +5205,7 @@
|
||||
"tranche_end": "2023-06-01T00:00:00.000Z",
|
||||
"total_added": "2500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "202.53945996133505",
|
||||
"locked_amount": "192.14902574277575",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "2500",
|
||||
@@ -5144,7 +5238,7 @@
|
||||
"tranche_end": "2023-11-01T00:00:00.000Z",
|
||||
"total_added": "15000.000000000000015",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "13674.853751509662013674853751509662",
|
||||
"locked_amount": "13613.188783212561013613188783212561",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1.5e-14",
|
||||
@@ -5252,7 +5346,7 @@
|
||||
"tranche_end": "2023-09-01T00:00:00.000Z",
|
||||
"total_added": "17500",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "10152.36560864532825",
|
||||
"locked_amount": "10080.42314563204725",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "12500",
|
||||
@@ -5518,8 +5612,8 @@
|
||||
"tranche_start": "2023-02-01T00:00:00.000Z",
|
||||
"tranche_end": "2023-08-01T00:00:00.000Z",
|
||||
"total_added": "37500",
|
||||
"total_removed": "18500.56159815",
|
||||
"locked_amount": "15692.99848449969375",
|
||||
"total_removed": "18592.291570575",
|
||||
"locked_amount": "15536.280885512584875",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "7500",
|
||||
@@ -5543,6 +5637,11 @@
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xc25a025176872981def8433ef0982ba306737aaf2cf0867f2259fd19492af2b5"
|
||||
},
|
||||
{
|
||||
"amount": "91.729972425",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xd0166245f3cf9223b3bd9291215dfb0dda92cc5554380d0ec767077c33729cf5"
|
||||
},
|
||||
{
|
||||
"amount": "164.727209925",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -5733,6 +5832,12 @@
|
||||
"tranche_id": 34,
|
||||
"tx": "0xc25a025176872981def8433ef0982ba306737aaf2cf0867f2259fd19492af2b5"
|
||||
},
|
||||
{
|
||||
"amount": "91.729972425",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 34,
|
||||
"tx": "0xd0166245f3cf9223b3bd9291215dfb0dda92cc5554380d0ec767077c33729cf5"
|
||||
},
|
||||
{
|
||||
"amount": "164.727209925",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -5915,8 +6020,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "7500",
|
||||
"withdrawn_tokens": "4290.80292735",
|
||||
"remaining_tokens": "3209.19707265"
|
||||
"withdrawn_tokens": "4382.532899775",
|
||||
"remaining_tokens": "3117.467100225"
|
||||
},
|
||||
{
|
||||
"address": "0x0B4e6fcE839B01ef43DA6F890FAC7B1Afb004600",
|
||||
@@ -5960,7 +6065,7 @@
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "129999.45",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "47858.982644879740029465",
|
||||
"locked_amount": "47679.539846683643054142",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "129999.45",
|
||||
@@ -5993,7 +6098,7 @@
|
||||
"tranche_end": "2024-04-01T00:00:00.000Z",
|
||||
"total_added": "54144.7663",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "47301.94373541695517923511",
|
||||
"locked_amount": "47190.04105878467927027815",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "54144.7663",
|
||||
@@ -6026,7 +6131,7 @@
|
||||
"tranche_end": "2023-09-03T00:00:00.000Z",
|
||||
"total_added": "62600",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "18650.49049340436032",
|
||||
"locked_amount": "18520.75866311516918",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "10000",
|
||||
@@ -6219,7 +6324,7 @@
|
||||
"tranche_end": "2023-09-17T00:00:00.000Z",
|
||||
"total_added": "5000",
|
||||
"total_removed": "0",
|
||||
"locked_amount": "1681.4366121258245",
|
||||
"locked_amount": "1671.07464485033",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "5000",
|
||||
@@ -7288,7 +7393,7 @@
|
||||
"tranche_end": "2023-06-02T00:00:00.000Z",
|
||||
"total_added": "1939928.38",
|
||||
"total_removed": "1709370.7872515768348",
|
||||
"locked_amount": "83681.9872917193018111752",
|
||||
"locked_amount": "79661.6924136466705951094",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1852091.69",
|
||||
@@ -12809,10 +12914,15 @@
|
||||
"tranche_id": 11,
|
||||
"tranche_start": "2021-09-03T00:00:00.000Z",
|
||||
"tranche_end": "2022-09-03T00:00:00.000Z",
|
||||
"total_added": "57278.000000000000000003",
|
||||
"total_added": "57398.000000000000000003",
|
||||
"total_removed": "50196.35141572991",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "120",
|
||||
"user": "0x05783022615f76de7E887aed81307aE39206Aa95",
|
||||
"tx": "0x388bd7537d91f3a919522ae885ce8dd9ddf415e3df3d5de687c1d5653790fcfd"
|
||||
},
|
||||
{
|
||||
"amount": "10",
|
||||
"user": "0xfb269c54dC4b43Fe98EdacE28Ce0a36A03B375D8",
|
||||
@@ -24512,6 +24622,21 @@
|
||||
}
|
||||
],
|
||||
"users": [
|
||||
{
|
||||
"address": "0x05783022615f76de7E887aed81307aE39206Aa95",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "120",
|
||||
"user": "0x05783022615f76de7E887aed81307aE39206Aa95",
|
||||
"tranche_id": 11,
|
||||
"tx": "0x388bd7537d91f3a919522ae885ce8dd9ddf415e3df3d5de687c1d5653790fcfd"
|
||||
}
|
||||
],
|
||||
"withdrawals": [],
|
||||
"total_tokens": "120",
|
||||
"withdrawn_tokens": "0",
|
||||
"remaining_tokens": "120"
|
||||
},
|
||||
{
|
||||
"address": "0xfb269c54dC4b43Fe98EdacE28Ce0a36A03B375D8",
|
||||
"deposits": [
|
||||
@@ -41160,7 +41285,7 @@
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "3732368.4671",
|
||||
"total_removed": "715655.108029600523393",
|
||||
"locked_amount": "153091.4042231713229007715616",
|
||||
"locked_amount": "146913.610713584637088982725",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "1998.95815",
|
||||
@@ -42552,8 +42677,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-12-05T00:00:00.000Z",
|
||||
"total_added": "15870102.715470999700000001",
|
||||
"total_removed": "885240.49984321970795352",
|
||||
"locked_amount": "5842539.8756085922637222718130454678926737",
|
||||
"total_removed": "887801.96986137105506852",
|
||||
"locked_amount": "5820633.81647585290817427255075677483590156",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "16249.93",
|
||||
@@ -43092,6 +43217,21 @@
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0xb048cb2dcdfc30508770a3a112ddbacd63210f740cc887559660522bd506612c"
|
||||
},
|
||||
{
|
||||
"amount": "1007.907542",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
"tx": "0x6a0d503d78cb1fd2291064c2d876cb8d2d91ad87c23ea6ff0b87b6443f8b434e"
|
||||
},
|
||||
{
|
||||
"amount": "502.98404323406874",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
"tx": "0x34f5294e12b0fcbfe0be234ce712cfbc52d4d75b159ca4e55610eb75efe43286"
|
||||
},
|
||||
{
|
||||
"amount": "1050.578432917278375",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tx": "0x817fbcc3b4739be85ab9781a9a28eca24711a398f9e27b13403b0756fed908d0"
|
||||
},
|
||||
{
|
||||
"amount": "10150.87581603206683",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
@@ -45284,6 +45424,12 @@
|
||||
"tranche_id": 2,
|
||||
"tx": "0xb048cb2dcdfc30508770a3a112ddbacd63210f740cc887559660522bd506612c"
|
||||
},
|
||||
{
|
||||
"amount": "1050.578432917278375",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x817fbcc3b4739be85ab9781a9a28eca24711a398f9e27b13403b0756fed908d0"
|
||||
},
|
||||
{
|
||||
"amount": "913.910324501590625",
|
||||
"user": "0x20CD77B9FC2f1fEDfb6F184E25f7127BFE991C8b",
|
||||
@@ -46840,8 +46986,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "259998.8875",
|
||||
"withdrawn_tokens": "163472.318146307289625",
|
||||
"remaining_tokens": "96526.569353692710375"
|
||||
"withdrawn_tokens": "164522.896579224568",
|
||||
"remaining_tokens": "95475.990920775432"
|
||||
},
|
||||
{
|
||||
"address": "0x89051CAb67Bc7F8CC44F7e270c6EDaf1EC57676c",
|
||||
@@ -47080,6 +47226,12 @@
|
||||
"tranche_id": 2,
|
||||
"tx": "0xc8835acd2e148eeaacde2a0df0ecad19c22717c7c51b207fdeac9a1af3f98c88"
|
||||
},
|
||||
{
|
||||
"amount": "502.98404323406874",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x34f5294e12b0fcbfe0be234ce712cfbc52d4d75b159ca4e55610eb75efe43286"
|
||||
},
|
||||
{
|
||||
"amount": "10150.87581603206683",
|
||||
"user": "0xe3eB4CF43C072658401996b71D43eE26E573562D",
|
||||
@@ -47370,8 +47522,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "150551.801",
|
||||
"withdrawn_tokens": "94629.10697606348661",
|
||||
"remaining_tokens": "55922.69402393651339"
|
||||
"withdrawn_tokens": "95132.09101929755535",
|
||||
"remaining_tokens": "55419.70998070244465"
|
||||
},
|
||||
{
|
||||
"address": "0x4d982Ab0823fD2f48e934a7be2bb0a5374a26148",
|
||||
@@ -47597,6 +47749,12 @@
|
||||
"tranche_id": 2,
|
||||
"tx": "0xdedcbf90e8f19c2a732ba2da663f59b5a19ad94800ddca6a3575019f19e9ca20"
|
||||
},
|
||||
{
|
||||
"amount": "1007.907542",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
"tranche_id": 2,
|
||||
"tx": "0x6a0d503d78cb1fd2291064c2d876cb8d2d91ad87c23ea6ff0b87b6443f8b434e"
|
||||
},
|
||||
{
|
||||
"amount": "1784.722222",
|
||||
"user": "0xF4c75FdbAe821C6B5DBB9f001bB23cBA58D1bA37",
|
||||
@@ -47857,8 +48015,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "200000",
|
||||
"withdrawn_tokens": "125368.96374",
|
||||
"remaining_tokens": "74631.03626"
|
||||
"withdrawn_tokens": "126376.871282",
|
||||
"remaining_tokens": "73623.128718"
|
||||
},
|
||||
{
|
||||
"address": "0x1b956E6c00E238194B331eddEFF72Cb5f28A8d01",
|
||||
@@ -49240,7 +49398,7 @@
|
||||
"tranche_start": "2021-11-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-05-05T00:00:00.000Z",
|
||||
"total_added": "14597706.0446472999",
|
||||
"total_removed": "6246751.954791069035514289",
|
||||
"total_removed": "6411995.942894415700913537",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
@@ -49455,6 +49613,36 @@
|
||||
"user": "0xfc3b2D0b548d3edBb512CeE0Bb79Fb7FaD50AaF3",
|
||||
"tx": "0x5c4a7a8fbab9c7c5899835a06397ea9f9dfbc434376dd0515482b8ba83944d67"
|
||||
},
|
||||
{
|
||||
"amount": "52738.10729529675679353",
|
||||
"user": "0x91715128a71c9C734CDC20E5EdEEeA02E72e428E",
|
||||
"tx": "0x6e58fe35d24a3b99b2dbf1b967952645c6025c4bf40cece1fb80f5c323d1b16e"
|
||||
},
|
||||
{
|
||||
"amount": "60704.453275555138884",
|
||||
"user": "0x47FbE34Fd93416c63d35544dEE6c6f442Db8513d",
|
||||
"tx": "0x21a962bdd6ba4dd4fc1229d2cf4801c0c8a7b54bb3be80881a15e2b3acdbf148"
|
||||
},
|
||||
{
|
||||
"amount": "15176.2482394768129956",
|
||||
"user": "0xcc2cf726A84e71301f9079FC177BA946aa98A694",
|
||||
"tx": "0xacccd728b8095f4a66cd6b5126f589270f32f643086d7f3e6191eab13444e69f"
|
||||
},
|
||||
{
|
||||
"amount": "12208.093275125918557286",
|
||||
"user": "0x85E14d90C63f70421a098AC26a5aCaB3854a1ee8",
|
||||
"tx": "0xcc751c50c669ee8908fb382e3712f6a3df7832acb43c8f8707351214cdc23892"
|
||||
},
|
||||
{
|
||||
"amount": "12208.430575675159834467",
|
||||
"user": "0x534200f54E753D998F9C2984B5971e4DB490e56F",
|
||||
"tx": "0x24c682a7c0ee0f12ce81e921c0b2dfe8dd5e5a7d8ddbe5a7e5ebf61a908ca58b"
|
||||
},
|
||||
{
|
||||
"amount": "12208.655442216878334365",
|
||||
"user": "0x35022e6c85B50F4904C7BC7e692A9F3bbEE8D2CE",
|
||||
"tx": "0xa4ff302beb1dbc78161fcfd4bc457af7a75d5c759d88c4067b961d3cc48db4f3"
|
||||
},
|
||||
{
|
||||
"amount": "1257.7360413991436375",
|
||||
"user": "0x4Aa3c35F6CC2d507E5C18205ee57099A4C80B19b",
|
||||
@@ -55836,6 +56024,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "12208.093275125918557286",
|
||||
"user": "0x85E14d90C63f70421a098AC26a5aCaB3854a1ee8",
|
||||
"tranche_id": 3,
|
||||
"tx": "0xcc751c50c669ee8908fb382e3712f6a3df7832acb43c8f8707351214cdc23892"
|
||||
},
|
||||
{
|
||||
"amount": "61458.259458207381442714",
|
||||
"user": "0x85E14d90C63f70421a098AC26a5aCaB3854a1ee8",
|
||||
@@ -55844,8 +56038,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "73666.3527333333",
|
||||
"withdrawn_tokens": "61458.259458207381442714",
|
||||
"remaining_tokens": "12208.093275125918557286"
|
||||
"withdrawn_tokens": "73666.3527333333",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xcc2cf726A84e71301f9079FC177BA946aa98A694",
|
||||
@@ -55858,6 +56052,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "15176.2482394768129956",
|
||||
"user": "0xcc2cf726A84e71301f9079FC177BA946aa98A694",
|
||||
"tranche_id": 3,
|
||||
"tx": "0xacccd728b8095f4a66cd6b5126f589270f32f643086d7f3e6191eab13444e69f"
|
||||
},
|
||||
{
|
||||
"amount": "3671.528996246291985",
|
||||
"user": "0xcc2cf726A84e71301f9079FC177BA946aa98A694",
|
||||
@@ -55908,8 +56108,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "66299.71746",
|
||||
"withdrawn_tokens": "51123.4692205231870044",
|
||||
"remaining_tokens": "15176.2482394768129956"
|
||||
"withdrawn_tokens": "66299.71746",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x66827bCD635f2bB1779d68c46aEB16541bCA6ba8",
|
||||
@@ -56430,6 +56630,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "60704.453275555138884",
|
||||
"user": "0x47FbE34Fd93416c63d35544dEE6c6f442Db8513d",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x21a962bdd6ba4dd4fc1229d2cf4801c0c8a7b54bb3be80881a15e2b3acdbf148"
|
||||
},
|
||||
{
|
||||
"amount": "14686.9255071873432384",
|
||||
"user": "0x47FbE34Fd93416c63d35544dEE6c6f442Db8513d",
|
||||
@@ -56480,8 +56686,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "265198.86984",
|
||||
"withdrawn_tokens": "204494.416564444861116",
|
||||
"remaining_tokens": "60704.453275555138884"
|
||||
"withdrawn_tokens": "265198.86984",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x35022e6c85B50F4904C7BC7e692A9F3bbEE8D2CE",
|
||||
@@ -56494,6 +56700,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "12208.655442216878334365",
|
||||
"user": "0x35022e6c85B50F4904C7BC7e692A9F3bbEE8D2CE",
|
||||
"tranche_id": 3,
|
||||
"tx": "0xa4ff302beb1dbc78161fcfd4bc457af7a75d5c759d88c4067b961d3cc48db4f3"
|
||||
},
|
||||
{
|
||||
"amount": "61457.697291116421665635",
|
||||
"user": "0x35022e6c85B50F4904C7BC7e692A9F3bbEE8D2CE",
|
||||
@@ -56502,8 +56714,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "73666.3527333333",
|
||||
"withdrawn_tokens": "61457.697291116421665635",
|
||||
"remaining_tokens": "12208.655442216878334365"
|
||||
"withdrawn_tokens": "73666.3527333333",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xC62BC272187e0Fd48ed126B99ABD6e7943707E64",
|
||||
@@ -56598,6 +56810,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "12208.430575675159834467",
|
||||
"user": "0x534200f54E753D998F9C2984B5971e4DB490e56F",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x24c682a7c0ee0f12ce81e921c0b2dfe8dd5e5a7d8ddbe5a7e5ebf61a908ca58b"
|
||||
},
|
||||
{
|
||||
"amount": "61457.922157658140165533",
|
||||
"user": "0x534200f54E753D998F9C2984B5971e4DB490e56F",
|
||||
@@ -56606,8 +56824,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "73666.3527333333",
|
||||
"withdrawn_tokens": "61457.922157658140165533",
|
||||
"remaining_tokens": "12208.430575675159834467"
|
||||
"withdrawn_tokens": "73666.3527333333",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x4020DC404D9470E0F08D2E7A8d6eBc54035CF42C",
|
||||
@@ -56703,6 +56921,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "52738.10729529675679353",
|
||||
"user": "0x91715128a71c9C734CDC20E5EdEEeA02E72e428E",
|
||||
"tranche_id": 3,
|
||||
"tx": "0x6e58fe35d24a3b99b2dbf1b967952645c6025c4bf40cece1fb80f5c323d1b16e"
|
||||
},
|
||||
{
|
||||
"amount": "12758.73908063512839093",
|
||||
"user": "0x91715128a71c9C734CDC20E5EdEEeA02E72e428E",
|
||||
@@ -56747,8 +56971,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "230391.5181735",
|
||||
"withdrawn_tokens": "177653.41087820324320647",
|
||||
"remaining_tokens": "52738.10729529675679353"
|
||||
"withdrawn_tokens": "230391.5181735",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0xC6b2864fbCD2A8dEC8DEfD1D421bC1E450C370AD",
|
||||
@@ -57167,7 +57391,7 @@
|
||||
"tranche_start": "2021-10-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-04-05T00:00:00.000Z",
|
||||
"total_added": "5778205.3912159303",
|
||||
"total_removed": "3492469.400132244009296769",
|
||||
"total_removed": "3521250.583356139543129269",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
@@ -57317,6 +57541,11 @@
|
||||
"user": "0x759C9ABABA492500c4c730bEB568B5b851Dec2c7",
|
||||
"tx": "0xd4191eb657ad26e08faddde326514247ae4a88e8aefcc7592590f368010c4046"
|
||||
},
|
||||
{
|
||||
"amount": "28781.1832238955338325",
|
||||
"user": "0x91715128a71c9C734CDC20E5EdEEeA02E72e428E",
|
||||
"tx": "0xf8179ed797f62e95dccb30c6efcbfa272d1e52efbcb94d04bfeb33312744755c"
|
||||
},
|
||||
{
|
||||
"amount": "58898.87608135458795",
|
||||
"user": "0x83b1a48376E045D26420200345414e6b93066396",
|
||||
@@ -58186,6 +58415,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "28781.1832238955338325",
|
||||
"user": "0x91715128a71c9C734CDC20E5EdEEeA02E72e428E",
|
||||
"tranche_id": 4,
|
||||
"tx": "0xf8179ed797f62e95dccb30c6efcbfa272d1e52efbcb94d04bfeb33312744755c"
|
||||
},
|
||||
{
|
||||
"amount": "9162.0421945609117395",
|
||||
"user": "0x91715128a71c9C734CDC20E5EdEEeA02E72e428E",
|
||||
@@ -58230,8 +58465,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "165749.29365",
|
||||
"withdrawn_tokens": "136968.1104261044661675",
|
||||
"remaining_tokens": "28781.1832238955338325"
|
||||
"withdrawn_tokens": "165749.29365",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x72e7BB93E73b2885a22CA29c34759361399a5C0e",
|
||||
@@ -59383,8 +59618,8 @@
|
||||
"tranche_start": "2022-06-05T00:00:00.000Z",
|
||||
"tranche_end": "2023-06-05T00:00:00.000Z",
|
||||
"total_added": "472355.6199999996",
|
||||
"total_removed": "45345.4733895423416",
|
||||
"locked_amount": "24258.2081069361612058598496600864",
|
||||
"total_removed": "45451.7934047643416",
|
||||
"locked_amount": "23279.30141156897471279865169965",
|
||||
"deposits": [
|
||||
{
|
||||
"amount": "3000",
|
||||
@@ -66048,6 +66283,16 @@
|
||||
"user": "0xf0d681c15447dCfaa6002f17078944FCe75B5e26",
|
||||
"tx": "0xca745232557385fff568386375d868633bd9542981dd07a6c471b4633dd5c9b8"
|
||||
},
|
||||
{
|
||||
"amount": "69.499619482",
|
||||
"user": "0x8c951C54F9cd08Cf81F770248e835D7A4F491a46",
|
||||
"tx": "0xfee87c40eeb3d6681eaa844b65ddb52756356c3612e2c2c8606b96f4965bc195"
|
||||
},
|
||||
{
|
||||
"amount": "36.82039574",
|
||||
"user": "0x4eD2b3c68BB4fda084ce1591a210F4aC8b71234A",
|
||||
"tx": "0xebbec73307d5d44428f791ad28622e6a075fa9a02d627f028db45a1042af473a"
|
||||
},
|
||||
{
|
||||
"amount": "182.662252664",
|
||||
"user": "0xb1169C6daAc76bAcaf0D8f87641Fc38fbabe569F",
|
||||
@@ -80149,6 +80394,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "36.82039574",
|
||||
"user": "0x4eD2b3c68BB4fda084ce1591a210F4aC8b71234A",
|
||||
"tranche_id": 5,
|
||||
"tx": "0xebbec73307d5d44428f791ad28622e6a075fa9a02d627f028db45a1042af473a"
|
||||
},
|
||||
{
|
||||
"amount": "26.662404872",
|
||||
"user": "0x4eD2b3c68BB4fda084ce1591a210F4aC8b71234A",
|
||||
@@ -80253,8 +80504,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "400",
|
||||
"withdrawn_tokens": "342.891159308",
|
||||
"remaining_tokens": "57.108840692"
|
||||
"withdrawn_tokens": "379.711555048",
|
||||
"remaining_tokens": "20.288444952"
|
||||
},
|
||||
{
|
||||
"address": "0x5c90765F50629570738fEe7b7FA82ae118f81Ed1",
|
||||
@@ -86702,6 +86953,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "69.499619482",
|
||||
"user": "0x8c951C54F9cd08Cf81F770248e835D7A4F491a46",
|
||||
"tranche_id": 5,
|
||||
"tx": "0xfee87c40eeb3d6681eaa844b65ddb52756356c3612e2c2c8606b96f4965bc195"
|
||||
},
|
||||
{
|
||||
"amount": "26.330974124",
|
||||
"user": "0x8c951C54F9cd08Cf81F770248e835D7A4F491a46",
|
||||
@@ -86722,8 +86979,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "200",
|
||||
"withdrawn_tokens": "120.251972348",
|
||||
"remaining_tokens": "79.748027652"
|
||||
"withdrawn_tokens": "189.75159183",
|
||||
"remaining_tokens": "10.24840817"
|
||||
},
|
||||
{
|
||||
"address": "0x3437f6ED844013852650851D769ae7939B5e0aec",
|
||||
@@ -89264,7 +89521,7 @@
|
||||
"tranche_start": "2021-12-05T00:00:00.000Z",
|
||||
"tranche_end": "2022-06-05T00:00:00.000Z",
|
||||
"total_added": "171288.42",
|
||||
"total_removed": "71890.5995794947989",
|
||||
"total_removed": "72069.2365096947989",
|
||||
"locked_amount": "0",
|
||||
"deposits": [
|
||||
{
|
||||
@@ -93524,6 +93781,11 @@
|
||||
"user": "0x2A6Ea2aBEf3D7d7A76CBeF3c297eE0eF9a86BBA8",
|
||||
"tx": "0x163b699e8a25073ad1ad45c8a8f9b1348eb0b648d3f4bc6f3f64648e0ad726bf"
|
||||
},
|
||||
{
|
||||
"amount": "178.6369302",
|
||||
"user": "0xC3d15bD936DDCb45b87BFF3Ff13445284a6c9d43",
|
||||
"tx": "0x7381b77de572d356ae185a760ff839dbdc85cb97bf408b110f7779bb095ea293"
|
||||
},
|
||||
{
|
||||
"amount": "250",
|
||||
"user": "0x0E3407C9A94effa675471afe7A9D37e687C32141",
|
||||
@@ -110020,6 +110282,12 @@
|
||||
}
|
||||
],
|
||||
"withdrawals": [
|
||||
{
|
||||
"amount": "178.6369302",
|
||||
"user": "0xC3d15bD936DDCb45b87BFF3Ff13445284a6c9d43",
|
||||
"tranche_id": 6,
|
||||
"tx": "0x7381b77de572d356ae185a760ff839dbdc85cb97bf408b110f7779bb095ea293"
|
||||
},
|
||||
{
|
||||
"amount": "71.3630698",
|
||||
"user": "0xC3d15bD936DDCb45b87BFF3Ff13445284a6c9d43",
|
||||
@@ -110028,8 +110296,8 @@
|
||||
}
|
||||
],
|
||||
"total_tokens": "250",
|
||||
"withdrawn_tokens": "71.3630698",
|
||||
"remaining_tokens": "178.6369302"
|
||||
"withdrawn_tokens": "250",
|
||||
"remaining_tokens": "0"
|
||||
},
|
||||
{
|
||||
"address": "0x4A13d4dC5e06ACdA81C011D55a7DaAc332bC5Dbf",
|
||||
|
||||
@@ -318,10 +318,11 @@ describe('Closed markets', { tags: '@smoke' }, () => {
|
||||
.should('have.text', product.settlementAsset.symbol);
|
||||
|
||||
// 6001-MARK-020
|
||||
cy.get(rowSelector)
|
||||
cy.get('.ag-pinned-right-cols-container')
|
||||
.find('[col-id="market-actions"]')
|
||||
.first()
|
||||
.find('[col-id="id"]')
|
||||
.should('have.text', settledMarket.id);
|
||||
.find('button svg')
|
||||
.should('exist');
|
||||
});
|
||||
|
||||
// test market list for market in terminated state
|
||||
@@ -373,5 +374,33 @@ describe('Closed markets', { tags: '@smoke' }, () => {
|
||||
'have.text',
|
||||
`Asset details - ${settlementAsset.symbol}`
|
||||
);
|
||||
|
||||
cy.get('[data-testid="dialog-close"]').click();
|
||||
});
|
||||
|
||||
it('can open row actions', () => {
|
||||
cy.get('.ag-pinned-right-cols-container')
|
||||
.find('[col-id="market-actions"]')
|
||||
.first()
|
||||
.find('button')
|
||||
.click();
|
||||
|
||||
const dropdownContent = '[data-testid="market-actions-content"]';
|
||||
const dropdownContentItem = '[role="menuitem"]';
|
||||
cy.get(dropdownContent)
|
||||
.find(dropdownContentItem)
|
||||
.eq(0)
|
||||
// Cannot click the copy button as it falls back to window.prompt, blocking the test.
|
||||
.should('have.text', 'Copy Market ID');
|
||||
|
||||
cy.get(dropdownContent)
|
||||
.find(dropdownContentItem)
|
||||
.eq(1)
|
||||
.find('a')
|
||||
.then(($el) => {
|
||||
const href = $el.attr('href');
|
||||
expect(/\/markets\/0/.test(href || '')).to.equal(true);
|
||||
})
|
||||
.should('have.text', 'View on Explorer');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -108,10 +108,9 @@ describe('deposit actions', { tags: '@smoke' }, () => {
|
||||
|
||||
it('Deposit to trade is visble', () => {
|
||||
cy.getByTestId('Collateral').click();
|
||||
cy.contains('[data-testid="deposit"]', 'Deposit to trade').should(
|
||||
'be.visible'
|
||||
);
|
||||
cy.contains('[data-testid="deposit"]', 'Deposit to trade').click();
|
||||
cy.contains('[data-testid="deposit"]', 'Deposit')
|
||||
.should('be.visible')
|
||||
.click();
|
||||
cy.getByTestId('deposit-submit').should('be.visible');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -48,7 +48,7 @@ describe('accounts', { tags: '@smoke' }, () => {
|
||||
cy.getByTestId('tab-accounts')
|
||||
.get(tradingAccountRowId)
|
||||
.find('[col-id="accounts-actions"]')
|
||||
.should('have.text', ' ');
|
||||
.should('have.text', '');
|
||||
|
||||
cy.getByTestId('tab-accounts')
|
||||
.get(tradingAccountRowId)
|
||||
|
||||
@@ -8,7 +8,6 @@ import {
|
||||
import { tooltipMapping } from '@vegaprotocol/market-info';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
createDocsLinks,
|
||||
formatNumberPercentage,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
@@ -39,7 +38,7 @@ import { Link, useParams } from 'react-router-dom';
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
|
||||
import { useMarket, useStaticMarketData } from '@vegaprotocol/market-list';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { DocsLinks } from '@vegaprotocol/environment';
|
||||
|
||||
const enum LiquidityTabs {
|
||||
Active = 'active',
|
||||
@@ -147,7 +146,6 @@ const LiquidityViewHeader = memo(({ marketId }: { marketId?: string }) => {
|
||||
market?.tradableInstrument.instrument.product.settlementAsset.decimals || 0;
|
||||
const symbol =
|
||||
market?.tradableInstrument.instrument.product.settlementAsset.symbol;
|
||||
const { VEGA_DOCS_URL } = useEnvironment();
|
||||
|
||||
const { params } = useNetworkParams([
|
||||
NetworkParams.market_liquidity_stakeToCcyVolume,
|
||||
@@ -216,10 +214,12 @@ const LiquidityViewHeader = memo(({ marketId }: { marketId?: string }) => {
|
||||
<div className="break-word">{marketId}</div>
|
||||
</HeaderStat>
|
||||
<HeaderStat heading={t('Learn more')}>
|
||||
{VEGA_DOCS_URL && (
|
||||
<ExternalLink href={createDocsLinks(VEGA_DOCS_URL).LIQUIDITY}>
|
||||
{DocsLinks ? (
|
||||
<ExternalLink href={DocsLinks.LIQUIDITY}>
|
||||
{t('Providing liquidity')}
|
||||
</ExternalLink>
|
||||
) : (
|
||||
(null as React.ReactNode)
|
||||
)}
|
||||
</HeaderStat>
|
||||
</Header>
|
||||
|
||||
@@ -214,7 +214,7 @@ describe('Closed', () => {
|
||||
'Settlement price',
|
||||
'Realised PNL',
|
||||
'Settlement asset',
|
||||
'Market ID',
|
||||
'', // actions row
|
||||
];
|
||||
expect(headers).toHaveLength(expectedHeaders.length);
|
||||
expect(headers.map((h) => h.textContent?.trim())).toEqual(expectedHeaders);
|
||||
@@ -236,7 +236,7 @@ describe('Closed', () => {
|
||||
addDecimalsFormatNumber(property.value, market.decimalPlaces),
|
||||
addDecimalsFormatNumber(position.realisedPNL, market.decimalPlaces),
|
||||
market.tradableInstrument.instrument.product.settlementAsset.symbol,
|
||||
market.id,
|
||||
'', // actions row
|
||||
];
|
||||
cells.forEach((cell, i) => {
|
||||
expect(cell).toHaveTextContent(expectedValues[i]);
|
||||
@@ -328,8 +328,13 @@ describe('Closed', () => {
|
||||
// check that only included ids are shown
|
||||
const cells = screen
|
||||
.getAllByRole('gridcell')
|
||||
.filter((cell) => cell.getAttribute('col-id') === 'id')
|
||||
.map((cell) => cell.textContent?.trim());
|
||||
.filter((cell) => cell.getAttribute('col-id') === 'code')
|
||||
.map((cell) => {
|
||||
const marketId = within(cell)
|
||||
.getByTestId('market-code')
|
||||
.getAttribute('data-market-id');
|
||||
return marketId;
|
||||
});
|
||||
expect(cells).toEqual(expectedRows.map((m) => m.node.id));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -4,7 +4,7 @@ import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
|
||||
import { AgGridLazy as AgGrid, COL_DEFS } from '@vegaprotocol/datagrid';
|
||||
import { useMemo } from 'react';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { MarketState, MarketStateMapping } from '@vegaprotocol/types';
|
||||
@@ -14,7 +14,10 @@ import {
|
||||
} from '@vegaprotocol/utils';
|
||||
import { usePositionsQuery } from '@vegaprotocol/positions';
|
||||
import type { MarketMaybeWithData } from '@vegaprotocol/market-list';
|
||||
import { closedMarketsWithDataProvider } from '@vegaprotocol/market-list';
|
||||
import {
|
||||
MarketTableActions,
|
||||
closedMarketsWithDataProvider,
|
||||
} from '@vegaprotocol/market-list';
|
||||
import { useVegaWallet } from '@vegaprotocol/wallet';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import type { ColDef } from 'ag-grid-community';
|
||||
@@ -121,6 +124,16 @@ const ClosedMarketsDataGrid = ({ rowData }: { rowData: Row[] }) => {
|
||||
{
|
||||
headerName: t('Market'),
|
||||
field: 'code',
|
||||
cellRenderer: ({
|
||||
value,
|
||||
data,
|
||||
}: VegaICellRendererParams<Row, 'code'>) => {
|
||||
return (
|
||||
<span data-testid="market-code" data-market-id={data?.id}>
|
||||
{value}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
headerName: t('Description'),
|
||||
@@ -262,9 +275,17 @@ const ClosedMarketsDataGrid = ({ rowData }: { rowData: Row[] }) => {
|
||||
),
|
||||
},
|
||||
{
|
||||
headerName: t('Market ID'),
|
||||
field: 'id',
|
||||
flex: 1,
|
||||
colId: 'market-actions',
|
||||
...COL_DEFS.actions,
|
||||
cellRenderer: ({ data }: VegaICellRendererParams<Row>) => {
|
||||
if (!data) return null;
|
||||
return (
|
||||
<MarketTableActions
|
||||
marketId={data.id}
|
||||
assetId={data.settlementAsset.id}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
return cols;
|
||||
|
||||
@@ -19,11 +19,10 @@ import { useCheckLiquidityStatus } from '@vegaprotocol/liquidity';
|
||||
import { AuctionTrigger, MarketTradingMode } from '@vegaprotocol/types';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
createDocsLinks,
|
||||
formatNumberPercentage,
|
||||
} from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { DocsLinks } from '@vegaprotocol/environment';
|
||||
|
||||
interface Props {
|
||||
marketId?: string;
|
||||
@@ -47,8 +46,6 @@ export const MarketLiquiditySupplied = ({
|
||||
params.market_liquidity_targetstake_triggering_ratio
|
||||
);
|
||||
|
||||
const { VEGA_DOCS_URL } = useEnvironment();
|
||||
|
||||
const variables = useMemo(
|
||||
() => ({
|
||||
marketId: marketId || '',
|
||||
@@ -131,11 +128,8 @@ export const MarketLiquiditySupplied = ({
|
||||
<Link href={`/#/liquidity/${marketId}`} data-testid="view-liquidity-link">
|
||||
{t('View liquidity provision table')}
|
||||
</Link>
|
||||
{VEGA_DOCS_URL && (
|
||||
<ExternalLink
|
||||
href={createDocsLinks(VEGA_DOCS_URL).LIQUIDITY}
|
||||
className="mt-2"
|
||||
>
|
||||
{DocsLinks && (
|
||||
<ExternalLink href={DocsLinks.LIQUIDITY} className="mt-2">
|
||||
{t('Learn about providing liquidity')}
|
||||
</ExternalLink>
|
||||
)}
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
TOKEN_GOVERNANCE,
|
||||
useEnvironment,
|
||||
useLinks,
|
||||
DocsLinks,
|
||||
} from '@vegaprotocol/environment';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useGlobalStore } from '../../stores';
|
||||
@@ -22,7 +23,6 @@ import {
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
import { Links, Routes } from '../../pages/client-router';
|
||||
import { createDocsLinks } from '@vegaprotocol/utils';
|
||||
import { SettingsButton } from '../../client-pages/settings';
|
||||
import {
|
||||
ProtocolUpgradeCountdown,
|
||||
@@ -34,7 +34,7 @@ export const Navbar = ({
|
||||
}: {
|
||||
theme: ComponentProps<typeof Navigation>['theme'];
|
||||
}) => {
|
||||
const { VEGA_DOCS_URL, GITHUB_FEEDBACK_URL } = useEnvironment();
|
||||
const { GITHUB_FEEDBACK_URL } = useEnvironment();
|
||||
const tokenLink = useLinks(DApp.Token);
|
||||
const { marketId } = useGlobalStore((store) => ({
|
||||
marketId: store.marketId,
|
||||
@@ -92,15 +92,13 @@ export const Navbar = ({
|
||||
{t('Governance')}
|
||||
</NavExternalLink>
|
||||
</NavigationItem>
|
||||
{VEGA_DOCS_URL && GITHUB_FEEDBACK_URL && (
|
||||
{DocsLinks?.NEW_TO_VEGA && GITHUB_FEEDBACK_URL && (
|
||||
<NavigationItem>
|
||||
<NavigationTrigger>{t('Resources')}</NavigationTrigger>
|
||||
<NavigationContent>
|
||||
<NavigationList>
|
||||
<NavigationItem>
|
||||
<NavExternalLink
|
||||
href={createDocsLinks(VEGA_DOCS_URL).NEW_TO_VEGA}
|
||||
>
|
||||
<NavExternalLink href={DocsLinks.NEW_TO_VEGA}>
|
||||
{t('Docs')}
|
||||
</NavExternalLink>
|
||||
</NavigationItem>
|
||||
|
||||
@@ -21,6 +21,7 @@ import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
|
||||
import { Networks, useEnvironment } from '@vegaprotocol/environment';
|
||||
import { WalletIcon } from '../icons/wallet';
|
||||
import { useTransferDialog } from '@vegaprotocol/accounts';
|
||||
import { useCopyTimeout } from '@vegaprotocol/react-helpers';
|
||||
|
||||
const MobileWalletButton = ({
|
||||
isConnected,
|
||||
@@ -237,21 +238,7 @@ export const VegaWalletConnectButton = () => {
|
||||
};
|
||||
|
||||
const KeypairItem = ({ pk }: { pk: PubKey }) => {
|
||||
const [copied, setCopied] = useState(false);
|
||||
useEffect(() => {
|
||||
// eslint-disable-next-line
|
||||
let timeout: any;
|
||||
|
||||
if (copied) {
|
||||
timeout = setTimeout(() => {
|
||||
setCopied(false);
|
||||
}, 800);
|
||||
}
|
||||
|
||||
return () => {
|
||||
clearTimeout(timeout);
|
||||
};
|
||||
}, [copied]);
|
||||
const [copied, setCopied] = useCopyTimeout();
|
||||
|
||||
return (
|
||||
<DropdownMenuRadioItem value={pk.publicKey}>
|
||||
|
||||
@@ -8,11 +8,10 @@ import {
|
||||
import { RISK_ACCEPTED_KEY } from '../constants';
|
||||
import { TelemetryApproval } from './telemetry-approval';
|
||||
import {
|
||||
DOCS_VEGA_WALLET,
|
||||
GET_VEGA_WALLET_URL,
|
||||
Networks,
|
||||
useDocsLink,
|
||||
useEnvironment,
|
||||
DocsLinks,
|
||||
ExternalLinks,
|
||||
} from '@vegaprotocol/environment';
|
||||
import { useLocalStorage } from '@vegaprotocol/react-helpers';
|
||||
|
||||
@@ -53,8 +52,6 @@ export const RiskNoticeDialog = ({ onClose, network }: Props) => {
|
||||
|
||||
const TestnetContent = ({ network }: { network: Networks }) => {
|
||||
const { GITHUB_FEEDBACK_URL } = useEnvironment();
|
||||
const docsLink = useDocsLink();
|
||||
|
||||
return (
|
||||
<>
|
||||
<p className="mb-4">
|
||||
@@ -69,16 +66,16 @@ const TestnetContent = ({ network }: { network: Networks }) => {
|
||||
[network]
|
||||
)}
|
||||
</p>
|
||||
{GITHUB_FEEDBACK_URL && GET_VEGA_WALLET_URL && docsLink && (
|
||||
{GITHUB_FEEDBACK_URL && DocsLinks && (
|
||||
<ul className="list-disc pl-4">
|
||||
<li className="mb-1">
|
||||
<Link href={GET_VEGA_WALLET_URL} target="_blank">
|
||||
<Link href={ExternalLinks.VEGA_WALLET_URL} target="_blank">
|
||||
<span className="underline">{t('Get a Vega Wallet')}</span>{' '}
|
||||
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} />
|
||||
</Link>
|
||||
</li>
|
||||
<li className="mb-1">
|
||||
<Link href={docsLink(DOCS_VEGA_WALLET)} target="_blank">
|
||||
<Link href={DocsLinks.VEGA_WALLET_TOOLS_URL} target="_blank">
|
||||
<span className="underline">{t('Learn about Vega Wallet')}</span>{' '}
|
||||
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} />
|
||||
</Link>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
BLOG,
|
||||
DApp,
|
||||
Networks,
|
||||
TOKEN_NEW_MARKET_PROPOSAL,
|
||||
TOKEN_PROPOSALS,
|
||||
useEnvironment,
|
||||
useLinks,
|
||||
ExternalLinks,
|
||||
} from '@vegaprotocol/environment';
|
||||
import { ProposedMarkets } from './proposed-markets';
|
||||
|
||||
@@ -52,7 +52,7 @@ export const WelcomeNoticeDialog = () => {
|
||||
</ExternalLink>
|
||||
</li>
|
||||
<li>
|
||||
<ExternalLink target="_blank" href={BLOG}>
|
||||
<ExternalLink target="_blank" href={ExternalLinks.BLOG}>
|
||||
{t('Read about the mainnet launch')}
|
||||
</ExternalLink>
|
||||
</li>
|
||||
|
||||
@@ -93,9 +93,9 @@ html [data-theme='light'] {
|
||||
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
|
||||
}
|
||||
|
||||
.vega-ag-grid .ag-row {
|
||||
border-width: 1px 0;
|
||||
border-bottom: 1px solid transparent;
|
||||
.vega-ag-grid .ag-row,
|
||||
.vega-ag-grid .ag-cell {
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
/* Light variables */
|
||||
@@ -107,7 +107,6 @@ html [data-theme='light'] {
|
||||
--ag-header-column-separator-color: theme(colors.neutral[300]);
|
||||
--ag-row-border-color: theme(colors.white);
|
||||
--ag-row-hover-color: theme(colors.neutral[100]);
|
||||
--ag-font-size: 12px;
|
||||
}
|
||||
|
||||
/* Dark variables */
|
||||
@@ -119,7 +118,6 @@ html [data-theme='light'] {
|
||||
--ag-header-column-separator-color: theme(colors.neutral[600]);
|
||||
--ag-row-border-color: theme(colors.black);
|
||||
--ag-row-hover-color: theme(colors.neutral[800]);
|
||||
--ag-font-size: 12px;
|
||||
}
|
||||
.ag-theme-balham-dark .ag-row.no-hover,
|
||||
.ag-theme-balham-dark .ag-row.no-hover:hover,
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
import { ETHERSCAN_ADDRESS, useEtherscanLink } from '@vegaprotocol/environment';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuCopyItem,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
Link,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { useTransferDialog } from './transfer-dialog';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
|
||||
export const AccountsActionsDropdown = ({
|
||||
assetId,
|
||||
assetContractAddress,
|
||||
onClickDeposit,
|
||||
onClickWithdraw,
|
||||
onClickBreakdown,
|
||||
}: {
|
||||
assetId: string;
|
||||
assetContractAddress?: string;
|
||||
onClickDeposit: () => void;
|
||||
onClickWithdraw: () => void;
|
||||
onClickBreakdown: () => void;
|
||||
}) => {
|
||||
const etherscanLink = useEtherscanLink();
|
||||
const openTransferDialog = useTransferDialog((store) => store.open);
|
||||
const openAssetDialog = useAssetDetailsDialogStore((store) => store.open);
|
||||
return (
|
||||
<DropdownMenu
|
||||
trigger={
|
||||
<DropdownMenuTrigger
|
||||
className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full"
|
||||
data-testid="dropdown-menu"
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.KEBAB} />
|
||||
</DropdownMenuTrigger>
|
||||
}
|
||||
>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem
|
||||
key={'deposit'}
|
||||
data-testid="deposit"
|
||||
onClick={onClickDeposit}
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.DEPOSIT} size={16} />
|
||||
{t('Deposit')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
key={'withdraw'}
|
||||
data-testid="withdraw"
|
||||
onClick={onClickWithdraw}
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.WITHDRAW} size={16} />
|
||||
{t('Withdraw')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
key={'transfer'}
|
||||
data-testid="transfer"
|
||||
onClick={() => openTransferDialog(true, assetId)}
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.TRANSFER} size={16} />
|
||||
{t('Transfer')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
key={'breakdown'}
|
||||
data-testid="breakdown"
|
||||
onClick={onClickBreakdown}
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.BREAKDOWN} size={16} />
|
||||
{t('Breakdown')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={(e) => {
|
||||
openAssetDialog(assetId, e.target as HTMLElement);
|
||||
}}
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.BREAKDOWN} size={16} />
|
||||
{t('View asset')}
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuCopyItem value={assetId} text={t('Copy asset ID')} />
|
||||
{assetContractAddress && (
|
||||
<DropdownMenuItem>
|
||||
<Link
|
||||
href={etherscanLink(
|
||||
ETHERSCAN_ADDRESS.replace(':hash', assetContractAddress)
|
||||
)}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="flex gap-2">
|
||||
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} />
|
||||
{t('View on Etherscan')}
|
||||
</span>
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
)}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
};
|
||||
@@ -9,14 +9,11 @@ import type {
|
||||
VegaICellRendererParams,
|
||||
VegaValueFormatterParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { COL_DEFS } from '@vegaprotocol/datagrid';
|
||||
import {
|
||||
Button,
|
||||
ButtonLink,
|
||||
Dialog,
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
@@ -38,6 +35,7 @@ import type { AccountFields } from './accounts-data-provider';
|
||||
import type { Asset } from '@vegaprotocol/types';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import classNames from 'classnames';
|
||||
import { AccountsActionsDropdown } from './accounts-actions-dropdown';
|
||||
|
||||
const colorClass = (percentageUsed: number, neutral = false) => {
|
||||
return classNames({
|
||||
@@ -109,7 +107,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
||||
const [row, setRow] = useState<AccountFields>();
|
||||
const pinnedAssetId = props.pinnedAsset?.id;
|
||||
|
||||
const pinnedAssetRow = useMemo(() => {
|
||||
const pinnedAsset = useMemo(() => {
|
||||
const currentPinnedAssetRow = props.rowData?.find(
|
||||
(row) => row.asset.id === pinnedAssetId
|
||||
);
|
||||
@@ -143,6 +141,13 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
||||
[pinnedAssetId, getRowHeight]
|
||||
);
|
||||
|
||||
const accountForPinnedAsset = props?.rowData?.find(
|
||||
(a) => a.asset.id === pinnedAssetId
|
||||
);
|
||||
const showDepositButton = accountForPinnedAsset
|
||||
? new BigNumber(accountForPinnedAsset.total).isLessThanOrEqualTo(0)
|
||||
: true;
|
||||
|
||||
return (
|
||||
<>
|
||||
<AgGrid
|
||||
@@ -162,7 +167,7 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
||||
comparator: accountValuesComparator,
|
||||
}}
|
||||
getRowHeight={getPinnedAssetRowHeight}
|
||||
pinnedTopRowData={pinnedAssetRow ? [pinnedAssetRow] : undefined}
|
||||
pinnedTopRowData={pinnedAsset ? [pinnedAsset] : undefined}
|
||||
>
|
||||
<AgGridColumn
|
||||
headerName={t('Asset')}
|
||||
@@ -266,104 +271,57 @@ export const AccountTable = forwardRef<AgGridReact, AccountTableProps>(
|
||||
formatWithAssetDecimals(data, data?.total)
|
||||
}
|
||||
/>
|
||||
{
|
||||
<AgGridColumn
|
||||
colId="accounts-actions"
|
||||
headerName=""
|
||||
sortable={false}
|
||||
maxWidth={200}
|
||||
type="rightAligned"
|
||||
cellRenderer={({
|
||||
data,
|
||||
}: VegaICellRendererParams<AccountFields>) => {
|
||||
if (!data) return null;
|
||||
else {
|
||||
if (
|
||||
data.asset.id === pinnedAssetId &&
|
||||
new BigNumber(data.total).isLessThanOrEqualTo(0)
|
||||
) {
|
||||
return (
|
||||
<CenteredGridCellWrapper className="h-[30px] justify-end py-1">
|
||||
<Button
|
||||
size="xs"
|
||||
variant="primary"
|
||||
data-testid="deposit"
|
||||
onClick={() => {
|
||||
onClickDeposit && onClickDeposit(data.asset.id);
|
||||
}}
|
||||
>
|
||||
{t('Deposit to trade')}
|
||||
</Button>
|
||||
</CenteredGridCellWrapper>
|
||||
);
|
||||
}
|
||||
<AgGridColumn
|
||||
colId="accounts-actions"
|
||||
{...COL_DEFS.actions}
|
||||
minWidth={showDepositButton ? 130 : COL_DEFS.actions.minWidth}
|
||||
maxWidth={showDepositButton ? 130 : COL_DEFS.actions.maxWidth}
|
||||
cellRenderer={({
|
||||
data,
|
||||
}: VegaICellRendererParams<AccountFields>) => {
|
||||
if (!data) return null;
|
||||
else {
|
||||
if (showDepositButton && data.asset.id === pinnedAssetId) {
|
||||
return (
|
||||
!props.isReadOnly && (
|
||||
<DropdownMenu
|
||||
trigger={
|
||||
<DropdownMenuTrigger
|
||||
iconName="more"
|
||||
className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full"
|
||||
data-testid="dropdown-menu"
|
||||
></DropdownMenuTrigger>
|
||||
}
|
||||
<CenteredGridCellWrapper className="h-[30px] justify-end py-1">
|
||||
<Button
|
||||
size="xs"
|
||||
variant="primary"
|
||||
data-testid="deposit"
|
||||
onClick={() => {
|
||||
onClickDeposit && onClickDeposit(data.asset.id);
|
||||
}}
|
||||
>
|
||||
<DropdownMenuContent>
|
||||
<DropdownMenuItem
|
||||
key={'deposit'}
|
||||
data-testid="deposit"
|
||||
onClick={() => {
|
||||
onClickDeposit && onClickDeposit(data.asset.id);
|
||||
}}
|
||||
>
|
||||
<span className="flex gap-2">
|
||||
<VegaIcon
|
||||
name={VegaIconNames.DEPOSIT}
|
||||
size={16}
|
||||
/>
|
||||
{t('Deposit')}
|
||||
</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
key={'withdraw'}
|
||||
data-testid="withdraw"
|
||||
onClick={() =>
|
||||
onClickWithdraw && onClickWithdraw(data.asset.id)
|
||||
}
|
||||
>
|
||||
<span className="flex gap-2">
|
||||
<VegaIcon
|
||||
name={VegaIconNames.WITHDRAW}
|
||||
size={16}
|
||||
/>
|
||||
{t('Withdraw')}
|
||||
</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
key={'breakdown'}
|
||||
data-testid="breakdown"
|
||||
onClick={() => {
|
||||
setOpenBreakdown(!openBreakdown);
|
||||
setRow(data);
|
||||
}}
|
||||
>
|
||||
<span className="flex gap-2">
|
||||
<VegaIcon
|
||||
name={VegaIconNames.BREAKDOWN}
|
||||
size={16}
|
||||
/>
|
||||
{t('Breakdown')}
|
||||
</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
)
|
||||
<VegaIcon name={VegaIconNames.DEPOSIT} /> {t('Deposit')}
|
||||
</Button>
|
||||
</CenteredGridCellWrapper>
|
||||
);
|
||||
}
|
||||
}}
|
||||
flex={1}
|
||||
/>
|
||||
}
|
||||
return (
|
||||
!props.isReadOnly && (
|
||||
<AccountsActionsDropdown
|
||||
assetId={data.asset.id}
|
||||
assetContractAddress={
|
||||
data.asset.source?.__typename === 'ERC20'
|
||||
? data.asset.source.contractAddress
|
||||
: undefined
|
||||
}
|
||||
onClickDeposit={() => {
|
||||
onClickDeposit && onClickDeposit(data.asset.id);
|
||||
}}
|
||||
onClickWithdraw={() => {
|
||||
onClickWithdraw && onClickWithdraw(data.asset.id);
|
||||
}}
|
||||
onClickBreakdown={() => {
|
||||
setOpenBreakdown(!openBreakdown);
|
||||
setRow(data);
|
||||
}}
|
||||
/>
|
||||
)
|
||||
);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</AgGrid>
|
||||
<Dialog size="medium" open={openBreakdown} onChange={setOpenBreakdown}>
|
||||
<div
|
||||
|
||||
@@ -14,7 +14,7 @@ import { TransferForm } from './transfer-form';
|
||||
import { useTransferDialog } from './transfer-dialog';
|
||||
import { Lozenge } from '@vegaprotocol/ui-toolkit';
|
||||
|
||||
export const TransferContainer = () => {
|
||||
export const TransferContainer = ({ assetId }: { assetId?: string }) => {
|
||||
const { pubKey, pubKeys } = useVegaWallet();
|
||||
const open = useTransferDialog((store) => store.open);
|
||||
const { param } = useNetworkParam(NetworkParams.transfer_fee_factor);
|
||||
@@ -59,6 +59,7 @@ export const TransferContainer = () => {
|
||||
pubKey={pubKey}
|
||||
pubKeys={pubKeys ? pubKeys?.map((pk) => pk.publicKey) : null}
|
||||
assets={assets}
|
||||
assetId={assetId}
|
||||
feeFactor={param}
|
||||
submitTransfer={transfer}
|
||||
/>
|
||||
|
||||
@@ -5,24 +5,26 @@ import { TransferContainer } from './transfer-container';
|
||||
|
||||
interface State {
|
||||
isOpen: boolean;
|
||||
assetId: string | undefined;
|
||||
}
|
||||
|
||||
interface Actions {
|
||||
open: (open?: boolean) => void;
|
||||
open: (open?: boolean, assetId?: string) => void;
|
||||
}
|
||||
|
||||
export const useTransferDialog = create<State & Actions>()((set) => ({
|
||||
isOpen: false,
|
||||
open: (open = true) => {
|
||||
set(() => ({ isOpen: open }));
|
||||
assetId: undefined,
|
||||
open: (open = true, assetId) => {
|
||||
set(() => ({ isOpen: open, assetId }));
|
||||
},
|
||||
}));
|
||||
|
||||
export const TransferDialog = () => {
|
||||
const { isOpen, open } = useTransferDialog();
|
||||
const { isOpen, open, assetId } = useTransferDialog();
|
||||
return (
|
||||
<Dialog title={t('Transfer')} open={isOpen} onChange={open} size="small">
|
||||
<TransferContainer />
|
||||
<TransferContainer assetId={assetId} />
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -41,6 +41,7 @@ interface TransferFormProps {
|
||||
decimals: number;
|
||||
balance: string;
|
||||
}>;
|
||||
assetId?: string;
|
||||
feeFactor: string | null;
|
||||
submitTransfer: (transfer: Transfer) => void;
|
||||
}
|
||||
@@ -49,6 +50,7 @@ export const TransferForm = ({
|
||||
pubKey,
|
||||
pubKeys,
|
||||
assets,
|
||||
assetId: initialAssetId,
|
||||
feeFactor,
|
||||
submitTransfer,
|
||||
}: TransferFormProps) => {
|
||||
@@ -59,7 +61,11 @@ export const TransferForm = ({
|
||||
handleSubmit,
|
||||
setValue,
|
||||
formState: { errors },
|
||||
} = useForm<FormFields>();
|
||||
} = useForm<FormFields>({
|
||||
defaultValues: {
|
||||
asset: initialAssetId,
|
||||
},
|
||||
});
|
||||
|
||||
const amount = watch('amount');
|
||||
const assetId = watch('asset');
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
export * from './lib/ag-grid/ag-grid-lazy';
|
||||
export * from './lib/ag-grid/use-column-sizes';
|
||||
|
||||
export * from './lib/column-definitions';
|
||||
|
||||
export * from './lib/cells/cumulative-vol-cell';
|
||||
export * from './lib/cells/flash-cell';
|
||||
export * from './lib/cells/numeric-cell';
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
export const COL_DEFS = {
|
||||
actions: {
|
||||
headerName: '',
|
||||
sortable: false,
|
||||
resizable: false,
|
||||
filter: false,
|
||||
minWidth: 45,
|
||||
maxWidth: 45,
|
||||
type: 'rightAligned',
|
||||
pinned: 'right',
|
||||
},
|
||||
};
|
||||
@@ -2,8 +2,8 @@ import { useMemo } from 'react';
|
||||
import { parseISO, isValid, isAfter } from 'date-fns';
|
||||
import classNames from 'classnames';
|
||||
import { useProposalOfMarketQuery } from '@vegaprotocol/proposals';
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { createDocsLinks, getDateTimeFormat } from '@vegaprotocol/utils';
|
||||
import { DocsLinks } from '@vegaprotocol/environment';
|
||||
import { getDateTimeFormat } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import { ExternalLink, SimpleGrid } from '@vegaprotocol/ui-toolkit';
|
||||
@@ -23,7 +23,6 @@ export const TradingModeTooltip = ({
|
||||
skip,
|
||||
skipGrid,
|
||||
}: TradingModeTooltipProps) => {
|
||||
const { VEGA_DOCS_URL } = useEnvironment();
|
||||
const { data: market } = useMarket(marketId);
|
||||
const { data: marketData } = useStaticMarketData(marketId, skip);
|
||||
const { marketTradingMode, trigger } = marketData || {};
|
||||
@@ -102,9 +101,9 @@ export const TradingModeTooltip = ({
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<ExternalLink
|
||||
href={createDocsLinks(VEGA_DOCS_URL).AUCTION_TYPE_OPENING}
|
||||
href={DocsLinks.AUCTION_TYPE_OPENING}
|
||||
className="ml-1"
|
||||
>
|
||||
{t('Find out more')}
|
||||
@@ -126,12 +125,9 @@ export const TradingModeTooltip = ({
|
||||
'This market is in auction until it reaches sufficient liquidity.'
|
||||
)}
|
||||
</span>
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<ExternalLink
|
||||
href={
|
||||
createDocsLinks(VEGA_DOCS_URL)
|
||||
.AUCTION_TYPE_LIQUIDITY_MONITORING
|
||||
}
|
||||
href={DocsLinks.AUCTION_TYPE_LIQUIDITY_MONITORING}
|
||||
className="ml-1"
|
||||
>
|
||||
{t('Find out more')}
|
||||
@@ -151,12 +147,9 @@ export const TradingModeTooltip = ({
|
||||
'This market may have sufficient liquidity but there are not enough priced limit orders in the order book, which are required to deploy liquidity commitment pegged orders.'
|
||||
)}
|
||||
</span>
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<ExternalLink
|
||||
href={
|
||||
createDocsLinks(VEGA_DOCS_URL)
|
||||
.AUCTION_TYPE_LIQUIDITY_MONITORING
|
||||
}
|
||||
href={DocsLinks.AUCTION_TYPE_LIQUIDITY_MONITORING}
|
||||
className="ml-1"
|
||||
>
|
||||
{t('Find out more')}
|
||||
@@ -174,12 +167,9 @@ export const TradingModeTooltip = ({
|
||||
<span>
|
||||
{t('This market is in auction due to high price volatility.')}
|
||||
</span>{' '}
|
||||
{VEGA_DOCS_URL && (
|
||||
{DocsLinks && (
|
||||
<ExternalLink
|
||||
href={
|
||||
createDocsLinks(VEGA_DOCS_URL)
|
||||
.AUCTION_TYPE_PRICE_MONITORING
|
||||
}
|
||||
href={DocsLinks.AUCTION_TYPE_PRICE_MONITORING}
|
||||
className="ml-1"
|
||||
>
|
||||
{t('Find out more')}
|
||||
|
||||
@@ -154,19 +154,21 @@ export const NetworkSwitcher = ({
|
||||
<>
|
||||
{advancedNetworkKeys.map((key) => (
|
||||
<DropdownMenuItem key={key} data-testid="network-item-advanced">
|
||||
<div className="mr-4">
|
||||
<Link href={VEGA_NETWORKS[key]}>{envNameMapping[key]}</Link>
|
||||
<NetworkLabel
|
||||
isCurrent={current === key}
|
||||
isAvailable={!!VEGA_NETWORKS[key]}
|
||||
/>
|
||||
<div className="w-full flex justify-between gap-2">
|
||||
<div>
|
||||
<Link href={VEGA_NETWORKS[key]}>{envNameMapping[key]}</Link>
|
||||
<NetworkLabel
|
||||
isCurrent={current === key}
|
||||
isAvailable={!!VEGA_NETWORKS[key]}
|
||||
/>
|
||||
</div>
|
||||
<span
|
||||
className="hidden md:inline"
|
||||
data-testid="network-item-description"
|
||||
>
|
||||
{envDescriptionMapping[key]}
|
||||
</span>
|
||||
</div>
|
||||
<span
|
||||
className="hidden md:inline"
|
||||
data-testid="network-item-description"
|
||||
>
|
||||
{envDescriptionMapping[key]}
|
||||
</span>
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</>
|
||||
|
||||
@@ -4,6 +4,8 @@ import { Networks } from '../types';
|
||||
import { useEnvironment } from './use-environment';
|
||||
import { stripFullStops } from '@vegaprotocol/utils';
|
||||
|
||||
const VEGA_DOCS_URL = process.env['NX_VEGA_DOCS_URL'] || '';
|
||||
|
||||
type Net = Exclude<Networks, 'CUSTOM'>;
|
||||
export enum DApp {
|
||||
Explorer = 'Explorer',
|
||||
@@ -50,6 +52,25 @@ const Links: { [k in DApp]: DAppLinks } = {
|
||||
[DApp.Token]: TokenLinks,
|
||||
};
|
||||
|
||||
export const DocsLinks = VEGA_DOCS_URL
|
||||
? {
|
||||
NEW_TO_VEGA: `${VEGA_DOCS_URL}/concepts/new-to-vega`,
|
||||
AUCTION_TYPE_OPENING: `${VEGA_DOCS_URL}/concepts/trading-on-vega/trading-modes#auction-type-opening`,
|
||||
AUCTION_TYPE_LIQUIDITY_MONITORING: `${VEGA_DOCS_URL}/concepts/trading-on-vega/trading-modes#auction-type-liquidity-monitoring`,
|
||||
AUCTION_TYPE_PRICE_MONITORING: `${VEGA_DOCS_URL}/concepts/trading-on-vega/trading-modes#auction-type-price-monitoring`,
|
||||
AUCTION_TYPE_CLOSING: `${VEGA_DOCS_URL}/concepts/trading-on-vega/trading-modes#auction-type-closing`,
|
||||
STAKING_GUIDE: `${VEGA_DOCS_URL}/concepts/vega-chain/#staking-on-vega`,
|
||||
REWARDS_GUIDE: `${VEGA_DOCS_URL}/concepts/trading-on-vega/fees-rewards#trading-rewards`,
|
||||
VEGA_WALLET_CONCEPTS_URL: `${VEGA_DOCS_URL}/concepts/vega-wallet`,
|
||||
VEGA_WALLET_TOOLS_URL: `${VEGA_DOCS_URL}/tools/vega-wallet`,
|
||||
PROPOSALS_GUIDE: `${VEGA_DOCS_URL}/tutorials/proposals`,
|
||||
NODE_OPERATORS: `${VEGA_DOCS_URL}/node-operators`,
|
||||
LOSS_SOCIALIZATION: `${VEGA_DOCS_URL}/concepts/trading-on-vega/market-protections#loss-socialisation`,
|
||||
POSITION_RESOLUTION: `${VEGA_DOCS_URL}/concepts/trading-on-vega/market-protections#position-resolution`,
|
||||
LIQUIDITY: `${VEGA_DOCS_URL}/concepts/liquidity/provision`,
|
||||
}
|
||||
: undefined;
|
||||
|
||||
export const useLinks = (dapp: DApp, network?: Net) => {
|
||||
const { VEGA_ENV, VEGA_EXPLORER_URL, VEGA_TOKEN_URL } = useEnvironment();
|
||||
const fallback = {
|
||||
@@ -84,19 +105,6 @@ export const useEtherscanLink = () => {
|
||||
return link;
|
||||
};
|
||||
|
||||
export const useDocsLink = () => {
|
||||
const { VEGA_DOCS_URL } = useEnvironment();
|
||||
const baseUrl = trim(VEGA_DOCS_URL, '/');
|
||||
const link = useCallback(
|
||||
(url?: string) => `${baseUrl}/${trim(url, '/') || ''}`,
|
||||
[baseUrl]
|
||||
);
|
||||
return link;
|
||||
};
|
||||
|
||||
// Vega blog
|
||||
export const BLOG = 'https://blog.vega.xyz/';
|
||||
|
||||
// Governance pages
|
||||
export const TOKEN_NEW_MARKET_PROPOSAL = '/proposals/propose/new-market';
|
||||
export const TOKEN_NEW_NETWORK_PARAM_PROPOSAL =
|
||||
@@ -125,19 +133,26 @@ export const useProtocolUpgradeProposalLink = () => {
|
||||
// Explorer pages
|
||||
export const EXPLORER_TX = '/txs/:hash';
|
||||
export const EXPLORER_ORACLE = '/oracles/:id';
|
||||
export const EXPLORER_MARKET = '/markets/:id';
|
||||
|
||||
// Etherscan pages
|
||||
export const ETHERSCAN_ADDRESS = '/address/:hash';
|
||||
export const ETHERSCAN_TX = '/tx/:hash';
|
||||
|
||||
// Console pages
|
||||
export const CONSOLE_MARKET = '/markets/:marketId';
|
||||
export const CONSOLE_MARKETS = '/markets/all';
|
||||
export const CONSOLE_PORTFOLIO = '/portfolio';
|
||||
export const CONSOLE_LIQUIDITY = 'liquidity/:marketId';
|
||||
export const ExternalLinks = {
|
||||
FEEDBACK: 'https://github.com/vegaprotocol/feedback/discussions',
|
||||
GITHUB: 'https://github.com/vegaprotocol/token-frontend',
|
||||
DISCORD: 'https://vega.xyz/discord',
|
||||
GOVERNANCE_PAGE: 'https://vega.xyz/governance',
|
||||
VALIDATOR_FORUM: 'https://community.vega.xyz/c/mainnet-validator-candidates',
|
||||
MARGIN_CREDIT_RISK:
|
||||
'https://vega.xyz/papers/margins-and-credit-risk.pdf#page=7',
|
||||
VEGA_WALLET_URL: 'https://vega.xyz/wallet',
|
||||
VEGA_WALLET_HOSTED_URL: 'https://vega-hosted-wallet.on.fleek.co/',
|
||||
BLOG: 'https://blog.vega.xyz/',
|
||||
};
|
||||
|
||||
// Vega XYZ
|
||||
export const GET_VEGA_WALLET_URL = 'https://vega.xyz/wallet/';
|
||||
|
||||
// Docs
|
||||
export const DOCS_VEGA_WALLET = '/tools/vega-wallet';
|
||||
export const TokenStaticLinks = {
|
||||
PROPOSAL_PAGE: ':tokenUrl/proposals/:proposalId',
|
||||
UPDATE_PROPOSAL_PAGE: ':tokenUrl/proposals/propose/update-market',
|
||||
};
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuCopyItem,
|
||||
DropdownMenuTrigger,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
export const FillActionsDropdown = ({
|
||||
tradeId,
|
||||
buyOrderId,
|
||||
sellOrderId,
|
||||
}: {
|
||||
tradeId: string;
|
||||
buyOrderId: string;
|
||||
sellOrderId: string;
|
||||
}) => {
|
||||
return (
|
||||
<DropdownMenu
|
||||
trigger={
|
||||
<DropdownMenuTrigger
|
||||
className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full"
|
||||
data-testid="dropdown-menu"
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.KEBAB} />
|
||||
</DropdownMenuTrigger>
|
||||
}
|
||||
>
|
||||
<DropdownMenuContent data-testid="market-actions-content">
|
||||
<DropdownMenuCopyItem value={tradeId} text={t('Copy trade ID')} />
|
||||
<DropdownMenuCopyItem
|
||||
value={buyOrderId}
|
||||
text={t('Copy buy order ID')}
|
||||
/>
|
||||
<DropdownMenuCopyItem
|
||||
value={sellOrderId}
|
||||
text={t('Copy sell order ID')}
|
||||
/>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
};
|
||||
@@ -48,6 +48,7 @@ describe('FillsTable', () => {
|
||||
'Role',
|
||||
'Fee',
|
||||
'Date',
|
||||
'', // action column
|
||||
];
|
||||
expect(headers).toHaveLength(expectedHeaders.length);
|
||||
expect(headers.map((h) => h.textContent?.trim())).toEqual(expectedHeaders);
|
||||
@@ -77,6 +78,7 @@ describe('FillsTable', () => {
|
||||
'Maker',
|
||||
'2.00 BTC',
|
||||
getDateTimeFormat().format(new Date(buyerFill.createdAt)),
|
||||
'', // action column
|
||||
];
|
||||
cells.forEach((cell, i) => {
|
||||
expect(cell).toHaveTextContent(expectedValues[i]);
|
||||
@@ -111,6 +113,7 @@ describe('FillsTable', () => {
|
||||
'Taker',
|
||||
'0.03 BTC',
|
||||
getDateTimeFormat().format(new Date(buyerFill.createdAt)),
|
||||
'', // action column
|
||||
];
|
||||
cells.forEach((cell, i) => {
|
||||
expect(cell).toHaveTextContent(expectedValues[i]);
|
||||
@@ -145,6 +148,7 @@ describe('FillsTable', () => {
|
||||
'-',
|
||||
'0.03 BTC',
|
||||
getDateTimeFormat().format(new Date(buyerFill.createdAt)),
|
||||
'', // action column
|
||||
];
|
||||
cells.forEach((cell, i) => {
|
||||
expect(cell).toHaveTextContent(expectedValues[i]);
|
||||
|
||||
@@ -19,12 +19,17 @@ import {
|
||||
positiveClassNames,
|
||||
negativeClassNames,
|
||||
MarketNameCell,
|
||||
COL_DEFS,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import type {
|
||||
VegaValueFormatterParams,
|
||||
VegaICellRendererParams,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import type { VegaValueFormatterParams } from '@vegaprotocol/datagrid';
|
||||
import { forwardRef } from 'react';
|
||||
import BigNumber from 'bignumber.js';
|
||||
import type { Trade } from './fills-data-provider';
|
||||
import type { FillFieldsFragment } from './__generated__/Fills';
|
||||
import { FillActionsDropdown } from './fill-actions-dropdown';
|
||||
|
||||
const TAKER = 'Taker';
|
||||
const MAKER = 'Maker';
|
||||
@@ -108,6 +113,20 @@ export const FillsTable = forwardRef<AgGridReact, Props>(
|
||||
return value ? getDateTimeFormat().format(new Date(value)) : '';
|
||||
}}
|
||||
/>
|
||||
<AgGridColumn
|
||||
colId="fill-actions"
|
||||
{...COL_DEFS.actions}
|
||||
cellRenderer={({ data }: VegaICellRendererParams<Trade, 'id'>) => {
|
||||
if (!data) return null;
|
||||
return (
|
||||
<FillActionsDropdown
|
||||
buyOrderId={data.buyOrder}
|
||||
sellOrderId={data.sellOrder}
|
||||
tradeId={data.id}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</AgGrid>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "@vegaprotocol/i18n",
|
||||
"version": "0.0.2",
|
||||
"version": "0.0.3",
|
||||
"type": "commonjs"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useEnvironment } from '@vegaprotocol/environment';
|
||||
import { removePaginationWrapper, TokenLinks } from '@vegaprotocol/utils';
|
||||
import { TokenStaticLinks, useEnvironment } from '@vegaprotocol/environment';
|
||||
import { removePaginationWrapper } from '@vegaprotocol/utils';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import { useDataProvider } from '@vegaprotocol/data-provider';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
@@ -236,7 +236,7 @@ export const MarketInfoAccordion = ({
|
||||
{VEGA_TOKEN_URL && (
|
||||
<ExternalLink
|
||||
className="mb-2 w-full"
|
||||
href={generatePath(TokenLinks.PROPOSAL_PAGE, {
|
||||
href={generatePath(TokenStaticLinks.PROPOSAL_PAGE, {
|
||||
tokenUrl: VEGA_TOKEN_URL,
|
||||
proposalId: market.proposal?.id || '',
|
||||
})}
|
||||
@@ -252,7 +252,7 @@ export const MarketInfoAccordion = ({
|
||||
{VEGA_TOKEN_URL && (
|
||||
<ExternalLink
|
||||
className="w-full"
|
||||
href={generatePath(TokenLinks.UPDATE_PROPOSAL_PAGE, {
|
||||
href={generatePath(TokenStaticLinks.UPDATE_PROPOSAL_PAGE, {
|
||||
tokenUrl: VEGA_TOKEN_URL,
|
||||
})}
|
||||
title={
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ExternalLinks } from '@vegaprotocol/utils';
|
||||
import { ExternalLinks } from '@vegaprotocol/environment';
|
||||
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import type { ReactNode } from 'react';
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export * from './markets-container';
|
||||
export * from './market-table-actions';
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from './market-table-actions';
|
||||
@@ -0,0 +1,59 @@
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
DropdownMenuCopyItem,
|
||||
Link,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { DApp, EXPLORER_MARKET, useLinks } from '@vegaprotocol/environment';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
|
||||
export const MarketTableActions = ({
|
||||
marketId,
|
||||
assetId,
|
||||
}: {
|
||||
marketId: string;
|
||||
assetId: string;
|
||||
}) => {
|
||||
const open = useAssetDetailsDialogStore((store) => store.open);
|
||||
const linkCreator = useLinks(DApp.Explorer);
|
||||
return (
|
||||
<DropdownMenu
|
||||
trigger={
|
||||
<DropdownMenuTrigger
|
||||
className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full"
|
||||
data-testid="dropdown-menu"
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.KEBAB} />
|
||||
</DropdownMenuTrigger>
|
||||
}
|
||||
>
|
||||
<DropdownMenuContent data-testid="market-actions-content">
|
||||
<DropdownMenuCopyItem value={marketId} text={t('Copy Market ID')} />
|
||||
<DropdownMenuItem>
|
||||
<Link
|
||||
href={linkCreator(EXPLORER_MARKET.replace(':id', marketId))}
|
||||
target="_blank"
|
||||
>
|
||||
<span className="flex gap-2">
|
||||
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} />
|
||||
{t('View on Explorer')}
|
||||
</span>
|
||||
</Link>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem
|
||||
onClick={(e) => {
|
||||
open(assetId, e.target as HTMLElement);
|
||||
}}
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={16} />
|
||||
{t('View asset')}
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
};
|
||||
@@ -7,6 +7,7 @@ import type {
|
||||
VegaICellRendererParams,
|
||||
TypedDataAgGrid,
|
||||
} from '@vegaprotocol/datagrid';
|
||||
import { COL_DEFS } from '@vegaprotocol/datagrid';
|
||||
import {
|
||||
AgGridLazy as AgGrid,
|
||||
PriceFlashCell,
|
||||
@@ -18,6 +19,7 @@ import { AgGridColumn } from 'ag-grid-react';
|
||||
import type { AgGridReact } from 'ag-grid-react';
|
||||
import * as Schema from '@vegaprotocol/types';
|
||||
import type { MarketMaybeWithData } from '../../';
|
||||
import { MarketTableActions } from '../../';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
|
||||
const { MarketTradingMode, AuctionTrigger } = Schema;
|
||||
@@ -176,15 +178,13 @@ export const MarketListTable = forwardRef<
|
||||
/>
|
||||
<AgGridColumn
|
||||
headerName={t('Settlement asset')}
|
||||
field="tradableInstrument.instrument.product.settlementAsset.symbol"
|
||||
field="tradableInstrument.instrument.product.settlementAsset"
|
||||
cellRenderer={({
|
||||
data,
|
||||
value,
|
||||
}: VegaICellRendererParams<
|
||||
MarketMaybeWithData,
|
||||
'tradableInstrument.instrument.product.settlementAsset.symbol'
|
||||
'tradableInstrument.instrument.product.settlementAsset'
|
||||
>) => {
|
||||
const value =
|
||||
data?.tradableInstrument.instrument.product.settlementAsset;
|
||||
return value ? (
|
||||
<ButtonLink
|
||||
onClick={(e) => {
|
||||
@@ -198,7 +198,23 @@ export const MarketListTable = forwardRef<
|
||||
);
|
||||
}}
|
||||
/>
|
||||
<AgGridColumn headerName={t('Market ID')} field="id" flex={1} />
|
||||
<AgGridColumn
|
||||
colId="market-actions"
|
||||
{...COL_DEFS.actions}
|
||||
cellRenderer={({
|
||||
data,
|
||||
}: VegaICellRendererParams<MarketMaybeWithData>) => {
|
||||
if (!data) return null;
|
||||
return (
|
||||
<MarketTableActions
|
||||
marketId={data.id}
|
||||
assetId={
|
||||
data.tradableInstrument.instrument.product.settlementAsset.id
|
||||
}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
</AgGrid>
|
||||
);
|
||||
});
|
||||
|
||||
@@ -36,9 +36,12 @@ export const MarketsContainer = ({ onSelect }: MarketsContainerProps) => {
|
||||
suppressNoRowsOverlay
|
||||
onCellClicked={(cellEvent: CellClickedEvent) => {
|
||||
const { data, column, event } = cellEvent;
|
||||
// prevent navigating to the market page if any of the below cells are clicked
|
||||
// event.preventDefault or event.stopPropagation dont seem to apply for aggird
|
||||
const colId = column.getColId();
|
||||
if (
|
||||
[
|
||||
'id',
|
||||
'tradableInstrument.instrument.code',
|
||||
'tradableInstrument.instrument.product.settlementAsset',
|
||||
].includes(colId)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
export * from './order-actions-dropdown';
|
||||
@@ -0,0 +1,28 @@
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuCopyItem,
|
||||
DropdownMenuTrigger,
|
||||
VegaIcon,
|
||||
VegaIconNames,
|
||||
} from '@vegaprotocol/ui-toolkit';
|
||||
import { t } from '@vegaprotocol/i18n';
|
||||
|
||||
export const OrderActionsDropdown = ({ id }: { id: string }) => {
|
||||
return (
|
||||
<DropdownMenu
|
||||
trigger={
|
||||
<DropdownMenuTrigger
|
||||
className="hover:bg-vega-light-200 dark:hover:bg-vega-dark-200 p-0.5 focus:rounded-full hover:rounded-full"
|
||||
data-testid="dropdown-menu"
|
||||
>
|
||||
<VegaIcon name={VegaIconNames.KEBAB} />
|
||||
</DropdownMenuTrigger>
|
||||
}
|
||||
>
|
||||
<DropdownMenuContent data-testid="market-actions-content">
|
||||
<DropdownMenuCopyItem value={id} text={t('Copy order ID')} />
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
);
|
||||
};
|
||||
@@ -145,7 +145,7 @@ export const OrderListManager = ({
|
||||
<OrderListTable
|
||||
rowData={data as Order[]}
|
||||
ref={gridRef}
|
||||
readonlyStatusFilter={filter !== undefined}
|
||||
filter={filter}
|
||||
onGridReady={onGridReady}
|
||||
cancel={cancel}
|
||||
setEditOrder={setEditOrder}
|
||||
|
||||
@@ -160,7 +160,6 @@ describe('OrderListTable', () => {
|
||||
);
|
||||
});
|
||||
const amendCell = getAmendCell();
|
||||
expect(amendCell.getAllByRole('button')).toHaveLength(2);
|
||||
await userEvent.click(amendCell.getByTestId('edit'));
|
||||
expect(mockEdit).toHaveBeenCalledWith(order);
|
||||
await userEvent.click(amendCell.getByTestId('cancel'));
|
||||
@@ -187,7 +186,8 @@ describe('OrderListTable', () => {
|
||||
);
|
||||
});
|
||||
const amendCell = getAmendCell();
|
||||
expect(amendCell.queryAllByRole('button')).toHaveLength(0);
|
||||
expect(amendCell.queryByTestId('edit')).not.toBeInTheDocument();
|
||||
expect(amendCell.queryByTestId('cancel')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows if an order is a liquidity provision order and does not show order actions', async () => {
|
||||
@@ -204,7 +204,8 @@ describe('OrderListTable', () => {
|
||||
const amendCell = getAmendCell();
|
||||
const typeCell = screen.getAllByRole('gridcell')[2];
|
||||
expect(typeCell).toHaveTextContent('Liquidity provision');
|
||||
expect(amendCell.queryAllByRole('button')).toHaveLength(0);
|
||||
expect(amendCell.queryByTestId('edit')).not.toBeInTheDocument();
|
||||
expect(amendCell.queryByTestId('cancel')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('shows if an order is a pegged order and does not show order actions', async () => {
|
||||
@@ -225,7 +226,8 @@ describe('OrderListTable', () => {
|
||||
const amendCell = getAmendCell();
|
||||
const typeCell = screen.getAllByRole('gridcell')[2];
|
||||
expect(typeCell).toHaveTextContent('Mid - 10.0 Peg limit');
|
||||
expect(amendCell.queryAllByRole('button')).toHaveLength(0);
|
||||
expect(amendCell.queryByTestId('edit')).not.toBeInTheDocument();
|
||||
expect(amendCell.queryByTestId('cancel')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it.each([
|
||||
@@ -242,7 +244,7 @@ describe('OrderListTable', () => {
|
||||
});
|
||||
|
||||
const amendCell = getAmendCell();
|
||||
expect(amendCell.getAllByRole('button')).toHaveLength(2);
|
||||
expect(amendCell.getAllByRole('button')).toHaveLength(3);
|
||||
});
|
||||
|
||||
it.each([
|
||||
@@ -251,19 +253,23 @@ describe('OrderListTable', () => {
|
||||
Schema.OrderStatus.STATUS_FILLED,
|
||||
Schema.OrderStatus.STATUS_REJECTED,
|
||||
Schema.OrderStatus.STATUS_STOPPED,
|
||||
])('does not show buttons for %s orders', async (status) => {
|
||||
const order = generateOrder({
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
status,
|
||||
});
|
||||
])(
|
||||
'does not show edit and cancel buttons for %s orders',
|
||||
async (status) => {
|
||||
const order = generateOrder({
|
||||
type: Schema.OrderType.TYPE_LIMIT,
|
||||
status,
|
||||
});
|
||||
|
||||
await act(async () => {
|
||||
render(generateJsx({ rowData: [order] }));
|
||||
});
|
||||
await act(async () => {
|
||||
render(generateJsx({ rowData: [order] }));
|
||||
});
|
||||
|
||||
const amendCell = getAmendCell();
|
||||
expect(amendCell.queryAllByRole('button')).toHaveLength(0);
|
||||
});
|
||||
const amendCell = getAmendCell();
|
||||
expect(amendCell.queryByTestId('edit')).not.toBeInTheDocument();
|
||||
expect(amendCell.queryByTestId('cancel')).not.toBeInTheDocument();
|
||||
}
|
||||
);
|
||||
|
||||
const getAmendCell = () => {
|
||||
const cells = screen.getAllByRole('gridcell');
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user