Compare commits

...
Author SHA1 Message Date
sam-keen 0530019633 feat(3835) avoid showing untitled proposals 2023-05-19 14:52:41 +01:00
dexturr 22a43249ea chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-19 12:08:42 +00:00
m.ray b40ee0caf5 fix(markets): remove queries for internal data sources (#3829) 2023-05-19 12:53:00 +01:00
Edd 95aca70434 fix(explorer): prevent render of signature component on some proposals (#3840) 2023-05-19 12:09:48 +01:00
Sam Keen 5e13266250 feat(governance): change url of upgrade proposals (#3841) 2023-05-19 12:09:40 +01:00
Edd 5c0588887c fix(explorer): fix footer links (#3825) 2023-05-19 10:37:59 +01:00
daro-maj 089a7daac7 test(trading): e2e test for select network and nodes - 0006-NETW (#3828) 2023-05-19 10:37:44 +01:00
Mikołaj Młodzikowski 02b6251b1a feat(ci): support mainnet branching strategy (#3832) 2023-05-19 10:38:36 +02:00
Bartłomiej Głownia 9ce8907861 feat(trading): do not show oracle banner when data is loading (#3821) 2023-05-19 10:01:22 +02:00
dexturr 3be9126906 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-19 06:10:00 +00:00
dexturr 77316092d1 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-19 00:15:57 +00:00
Dexter Edwards fca229e62a feat(governance): use rest to expose proposal data (#3827) 2023-05-18 22:43:32 +01:00
dexturr 162b167860 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-18 18:07:36 +00:00
Art a4149cc55e feat(web3): withdrawal details (#3701) 2023-05-18 16:50:15 +02:00
Mikołaj Młodzikowski 4161a74eaf feat(ci): fix release body (#3822) 2023-05-18 14:59:46 +01:00
Mikołaj Młodzikowski 5008e57a56 feat(ci): adjust variables during release pipeline to cover actual tag_name 2023-05-18 15:12:12 +02:00
Mikołaj Młodzikowski 89031bf826 feat(ci): append ipfs related information to release body (#3818) 2023-05-18 14:51:53 +02:00
dexturr 61501d4d14 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-18 12:10:20 +00:00
Madalina Raicu f8f3ce7df9 fix: no oracle for this market banner 2023-05-18 13:00:17 +01:00
Maciek f7aab5a78a feat(ui-toolkit,trading): allow toast box configuration (#3811) 2023-05-18 12:53:36 +01:00
Bartłomiej Głownia 2904975fd3 feat(trading): highlight negative oracle statuses in market lists (#3816) 2023-05-18 13:22:54 +02:00
Mikołaj Młodzikowski 4f55c946f0 feat(ci): add pipeline for rollback console deployments (#3817) 2023-05-18 10:11:41 +00:00
Matthew Russell de637fee13 chore(trading): show markets in opening auction in market selector (#3814) 2023-05-18 09:49:44 +01:00
dexturr 69c6db8ec2 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-18 06:09:07 +00:00
Matthew Russell 8dc465c1d1 feat(trading): additional row actions for tables (#3600) 2023-05-17 21:05:53 -07:00
dexturr 0be934edca chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-18 00:16:39 +00:00
Matthew Russell 653688c1dd fix(governance): clear wallet state if user changes to a non existent party (#3813) 2023-05-17 19:25:14 +00:00
dexturr 34400be18a chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-17 18:09:58 +00:00
Sam Keen d4a0a4a42c fix(governance): updated page titles (#3810) 2023-05-17 16:16:19 +00:00
Joe Tsang fabf643ce7 chore(ci): fix nightly test runner (#3804) 2023-05-17 16:21:10 +01:00
309 changed files with 5976 additions and 2766 deletions
@@ -0,0 +1,74 @@
name: After Release
on:
release:
types: [published]
jobs:
after-release:
runs-on: ubuntu-22.04
timeout-minutes: 30
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to the Container registry (ghcr)
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to the Container registry (docker hub)
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: resolve ipfs hashes for release
run: |
echo "Tag name: ${{ github.event.release.tag_name }}"
echo "Name: ${{ github.event.release.name }}"
echo "Description: ${{ github.event.release.body }}"
until docker pull vegaprotocol/trading:${{ github.event.release.tag_name }}; do
echo "Image not pushed yet, waiting 60 seconds"
sleep 60
done
docker run --rm vegaprotocol/trading:${{ github.event.release.tag_name }} cat /ipfs-hash > ipfs-hash
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
echo IPFS_V0=$(cat ipfs-hash) >> $GITHUB_ENV
echo IPFS_V1=$(ipfs cid format -v 1 -b base32 $(cat ipfs-hash)) >> $GITHUB_ENV
- name: Edit Release
uses: irongut/EditRelease@v1.2.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
id: ${{ github.event.release.id }}
body: |
---
# Deployments
* https://explorer.vega.xyz
* https://governance.vega.xyz
# IPFS releases
Tye IPFS hash of this release of the Trading app is:
CIDv0: ${{ env.IPFS_V0 }}
CIDv1: ${{ env.IPFS_V1 }}
You can always access the latest IPFS release by visiting [vega.trading](https://vega.trading).
You can also access Trading directly from an IPFS gateway.
BEWARE: The Trading interface uses [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to remember your settings, such as which tokens you have imported. You should always use an IPFS gateway that enforces [origin separation](https://ipfs.github.io/public-gateway-checker/).
Your settings are not remembered across different URLs.
IPFS gateways:
https://${{ env.IPFS_V1 }}.ipfs.dweb.link/
https://${{ env.IPFS_V1 }}.ipfs.cf-ipfs.com/
ipfs://${{ env.IPFS_V0 }}/
+2 -2
View File
@@ -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
+6 -10
View File
@@ -62,17 +62,19 @@ jobs:
- name: Define variables
run: |
envName=''
domain="vega.rocks"
if [[ "${{ github.event_name }}" = "push" ]]; then
domain="vega.rocks"
if [[ "${{ github.ref }}" =~ .*release/.* ]]; then
envName="$(echo ${{ github.ref }} | rev | cut -d '/' -f 1 | rev)"
if [[ "${{ github.ref }}" =~ .*mainnet.* ]]; then
domain="vega.community"
fi
elif [[ "${{ github.ref }}" =~ .*develop$ ]]; then
envName="stagnet1"
elif [[ "${{ matrix.app}}" = "trading" ]] && [[ ${{ startsWith(github.ref, 'refs/tags/v') && 'true' || 'false' }} = "true" ]]; then
envName="mainnet"
elif [[ "${{ github.ref }}" =~ .*main$ ]]; then
envName="mainnet"
fi
if [[ "${envName}" = "mainnet" ]]; then
domain="vega.xyz"
fi
bucketName="${{ matrix.app }}.${envName}.${domain}"
echo BUCKET_NAME=${bucketName} >> $GITHUB_ENV
@@ -170,12 +172,6 @@ jobs:
labels: ${{ matrix.app }}-preview
number: ${{ github.event.number }}
- name: Add ipfs hash to release
uses: softprops/action-gh-release@v1
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
with:
files: ${{ matrix.app }}-ipfs-hash
- name: Trigger fleek deployment
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
run: |
+77
View File
@@ -0,0 +1,77 @@
name: 'Rollback console'
on:
workflow_dispatch:
inputs:
version:
description: 'Version that should be set on rollback'
required: true
type: string
jobs:
rollback:
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to the Container registry (docker hub)
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Retag mainnet
run: |
docker pull vegaprotocol/trading:${{ inputs.version }}
docker tag vegaprotocol/trading:${{ inputs.version }} vegaprotocol/trading:mainnet
docker push vegaprotocol/trading:mainnet
docker run --rm vegaprotocol/trading:mainnet cat /ipfs-hash > ipfs-hash
- name: Trigger fleek deployment
run: |
# display info about app
curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
-H "Content-Type: application/json" \
-d '{"query": "query{getSiteById(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id latestDeploy{id status}}}"}' \
https://api.fleek.co/graphql
# trigger new deployment as base image is always set to vegaprotocol/trading:mainnet
curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
-H "Content-Type: application/json" \
-d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \
https://api.fleek.co/graphql
- name: Update vega.trading DNS to redirect to the new console
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 ipfs-hash)
new_cid=$(ipfs cid format -v 1 -b base32 $new_hash)
# 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
View File
@@ -49,4 +49,4 @@ cypress.env.json
.next
#cypress
/apps/trading-e2e/cypress/reports/
/apps/**/cypress/reports/
+2 -1
View File
@@ -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;
},
+1
View File
@@ -15,5 +15,6 @@
import '@vegaprotocol/cypress';
import './common.functions.js';
import 'cypress-mochawesome-reporter/register';
import registerCypressGrep from '@cypress/grep';
registerCypressGrep();
+1
View File
@@ -14,6 +14,7 @@ NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/m
NX_VEGA_GOVERNANCE_URL=https://stagnet1.governance.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.jsoo
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
# App flags
NX_EXPLORER_ASSETS=1
@@ -48,11 +48,13 @@ export const Footer = () => {
</Link>
</div>
<div className="flex pl-2 content-center">
<ExternalLink href={ENV.addresses.feedback}>
{showFullFeedbackLabel ? t('Share your feedback') : t('Feedback')}
</ExternalLink>
</div>
{ENV.addresses.feedback ? (
<div className="flex pl-2 content-center">
<ExternalLink href={ENV.addresses.feedback}>
{showFullFeedbackLabel ? t('Share your feedback') : t('Feedback')}
</ExternalLink>
</div>
) : null}
</div>
</footer>
);
@@ -62,9 +64,5 @@ const NodeUrl = ({ url }: { url: string }) => {
// get base url from api url, api sub domain
const urlObj = new URL(url);
const nodeUrl = urlObj.origin.replace(/^[^.]+\./g, '');
return (
<Link href={'https://' + nodeUrl} target="_blank">
{nodeUrl}
</Link>
);
return <span className="cursor-default">{nodeUrl}</span>;
};
@@ -1,8 +1,8 @@
import { t } from '@vegaprotocol/i18n';
import type { MarketInfoWithData } from '@vegaprotocol/market-info';
import { LiquidityInfoPanel } from '@vegaprotocol/market-info';
import { LiquidityMonitoringParametersInfoPanel } from '@vegaprotocol/market-info';
import type { MarketInfoWithData } from '@vegaprotocol/markets';
import {
LiquidityInfoPanel,
LiquidityMonitoringParametersInfoPanel,
InstrumentInfoPanel,
KeyDetailsInfoPanel,
LiquidityPriceRangeInfoPanel,
@@ -12,20 +12,18 @@ import {
RiskModelInfoPanel,
RiskParametersInfoPanel,
SettlementAssetInfoPanel,
} from '@vegaprotocol/market-info';
import { MarketInfoTable } from '@vegaprotocol/market-info';
} from '@vegaprotocol/markets';
import { MarketInfoTable } from '@vegaprotocol/markets';
import type { DataSourceDefinition } from '@vegaprotocol/types';
import isEqual from 'lodash/isEqual';
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
if (!market) return null;
const settlementData =
market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData
.data;
const terminationData =
market.tradableInstrument.instrument.product
.dataSourceSpecForTradingTermination.data;
const settlementData = market.tradableInstrument.instrument.product
.dataSourceSpecForSettlementData.data as DataSourceDefinition;
const terminationData = market.tradableInstrument.instrument.product
.dataSourceSpecForTradingTermination.data as DataSourceDefinition;
const getSigners = (data: DataSourceDefinition) => {
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
@@ -1,4 +1,4 @@
import type { MarketFieldsFragment } from '@vegaprotocol/market-list';
import type { MarketFieldsFragment } from '@vegaprotocol/markets';
import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
@@ -0,0 +1,56 @@
import type { Proposal } from './tx-proposal';
import { proposalRequiresSignatureBundle } from './tx-proposal';
describe('proposalRequiresSignatureBundle', () => {
it('should return false for freeform proposals, which do not require a signature bundle to enact', () => {
const mock = {
terms: {
newFreeform: {},
},
};
expect(proposalRequiresSignatureBundle(mock)).toEqual(false);
});
it('should return false for newMarket proposals, which do not require a signature bundle to enact', () => {
const mock = {
terms: {
newMarket: {},
},
};
expect(proposalRequiresSignatureBundle(mock)).toEqual(false);
});
it('should return true for newAsset proposals, which do require a signature bundle to enact', () => {
const mock = {
terms: {
newAsset: {},
},
};
expect(proposalRequiresSignatureBundle(mock)).toEqual(true);
});
it('should return true for updateAsset proposals, which do require a signature bundle to enact', () => {
const mock = {
terms: {
updateAsset: {},
},
};
expect(proposalRequiresSignatureBundle(mock)).toEqual(true);
});
it('should return false when bad data is supplied', () => {
expect(
proposalRequiresSignatureBundle(false as unknown as Proposal)
).toEqual(false);
expect(
proposalRequiresSignatureBundle(undefined as unknown as Proposal)
).toEqual(false);
expect(
proposalRequiresSignatureBundle({ test: false } as unknown as Proposal)
).toEqual(false);
});
});
@@ -28,11 +28,16 @@ interface TxProposalProps {
* @returns boolean True if a signature bundle is required. Used to fetch a signature bundle
*/
export function proposalRequiresSignatureBundle(proposal?: Proposal): boolean {
const proposalsThatRequireBundles = ['newAsset', 'updateAsset'];
if (!proposal?.terms) {
return false;
}
return !!['newAsset', 'updateAsset'].filter((requiredIfExists) =>
has(proposal.terms, requiredIfExists)
return (
proposalsThatRequireBundles.filter((requiredIfExists) =>
has(proposal.terms, requiredIfExists)
).length > 0
);
}
@@ -81,6 +86,7 @@ export const TxProposal = ({ txData, pubKey, blockData }: TxProposalProps) => {
const tx = proposal.terms?.newAsset || proposal.terms?.updateAsset;
// This component is not rendered if no bundle is required
const SignatureBundleComponent = proposal.terms?.newAsset
? ProposalSignatureBundleNewAsset
: ProposalSignatureBundleUpdateAsset;
@@ -8,7 +8,7 @@ import { useScrollToLocation } from '../../hooks/scroll-to-location';
import { useDocumentTitle } from '../../hooks/use-document-title';
import compact from 'lodash/compact';
import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog';
import { marketInfoWithDataProvider } from '@vegaprotocol/market-info';
import { marketInfoWithDataProvider } from '@vegaprotocol/markets';
import { PageTitle } from '../../components/page-helpers/page-title';
export const MarketPage = () => {
@@ -1,6 +1,6 @@
import { useScrollToLocation } from '../../hooks/scroll-to-location';
import { useDocumentTitle } from '../../hooks/use-document-title';
import { marketsProvider } from '@vegaprotocol/market-list';
import { marketsProvider } from '@vegaprotocol/markets';
import { RouteTitle } from '../../components/route-title';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
+3 -5
View File
@@ -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
View File
@@ -17,6 +17,7 @@ NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
#Test configuration variables
CYPRESS_FAIRGROUND=false
+2 -1
View File
@@ -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;
},
+1
View File
@@ -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';
+1
View File
@@ -15,6 +15,7 @@ NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
#Test configuration variables
CYPRESS_FAIRGROUND=false
+1
View File
@@ -17,6 +17,7 @@ NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
#Test configuration variables
CYPRESS_FAIRGROUND=false
+1
View File
@@ -11,3 +11,4 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-devnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_REST_URL=https://api.n00.devnet1.vega.xyz/api/v2/
+1
View File
@@ -12,3 +12,4 @@ NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_REST_URL=https://api.vega.community/api/v2/
+1
View File
@@ -8,3 +8,4 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
+1
View File
@@ -12,3 +12,4 @@ NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-testnet-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_REST_URL=https://api.n07.testnet.vega.xyz/api/v2/
+1
View File
@@ -9,3 +9,4 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_REST_URL=https://api-validators-testnet.vega.rocks/api/v2/
+7 -5
View File
@@ -16,6 +16,7 @@ import { AppStateProvider } from './contexts/app-state/app-state-provider';
import { ContractsProvider } from './contexts/contracts/contracts-provider';
import { AppRouter } from './routes';
import type { EthereumConfig } from '@vegaprotocol/web3';
import { WithdrawalApprovalDialogContainer } from '@vegaprotocol/web3';
import {
createConnectors,
useEthTransactionManager,
@@ -43,7 +44,7 @@ import {
} from '@vegaprotocol/environment';
import { ENV } from './config';
import type { InMemoryCacheConfig } from '@apollo/client';
import { WithdrawalDialog } from '@vegaprotocol/withdraws';
import { CreateWithdrawalDialog } from '@vegaprotocol/withdraws';
import { SplashLoader } from './components/splash-loader';
import { ToastsManager } from './toasts-manager';
import {
@@ -52,6 +53,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: {
@@ -157,7 +159,8 @@ const Web3Container = ({
<InitializeHandlers />
<VegaWalletDialogs />
<TransactionModal />
<WithdrawalDialog />
<CreateWithdrawalDialog />
<WithdrawalApprovalDialogContainer />
<TelemetryDialog />
</>
</BalanceManager>
@@ -219,9 +222,8 @@ const AppContainer = () => {
const transaction = event.transaction;
if (
(errorIsString && error.includes('failed to get party ID')) ||
(errorIsObject &&
error?.message?.includes('failed to get party ID'))
(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.
@@ -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
+1
View File
@@ -62,6 +62,7 @@ export const ENV = {
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
delegationsPagination: windowOrDefault('NX_DELEGATIONS_PAGINATION'),
rest: windowOrDefault('NX_VEGA_REST_URL'),
flags: {
NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')),
MOCK: TRUTHY.includes(windowOrDefault('NX_MOCKED')),
+8
View File
@@ -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;
};
@@ -124,7 +124,7 @@ describe('Proposal header', () => {
})
);
expect(screen.getByTestId('proposal-title')).toHaveTextContent(
'Unknown proposal'
'New asset proposal'
);
expect(screen.getByTestId('proposal-type')).toHaveTextContent('New asset');
expect(screen.getByTestId('proposal-details')).toHaveTextContent(
@@ -21,6 +21,7 @@ export const ProposalHeader = ({
let details: ReactNode;
let proposalType = '';
let fallbackTitle = '';
const title = proposal?.rationale.title.trim();
@@ -29,6 +30,7 @@ export const ProposalHeader = ({
switch (change?.__typename) {
case 'NewMarket': {
proposalType = 'NewMarket';
fallbackTitle = t('NewMarketProposal');
details = (
<>
<span>
@@ -50,6 +52,7 @@ export const ProposalHeader = ({
}
case 'UpdateMarket': {
proposalType = 'UpdateMarket';
fallbackTitle = t('UpdateMarketProposal');
details = (
<>
<span>{t('Market change')}:</span>{' '}
@@ -60,6 +63,7 @@ export const ProposalHeader = ({
}
case 'NewAsset': {
proposalType = 'NewAsset';
fallbackTitle = t('NewAssetProposal');
details = (
<>
<span>{t('Symbol')}:</span> <Lozenge>{change.symbol}.</Lozenge>{' '}
@@ -81,6 +85,7 @@ export const ProposalHeader = ({
}
case 'UpdateNetworkParameter': {
proposalType = 'NetworkParameter';
fallbackTitle = t('NetworkParameterProposal');
details = (
<>
<span>{t('Change')}:</span>{' '}
@@ -95,11 +100,13 @@ export const ProposalHeader = ({
}
case 'NewFreeform': {
proposalType = 'Freeform';
fallbackTitle = t('FreeformProposal');
details = <span />;
break;
}
case 'UpdateAsset': {
proposalType = 'UpdateAsset';
fallbackTitle = t('UpdateAssetProposal');
details = (
<>
<span>{t('AssetID')}:</span>{' '}
@@ -115,10 +122,14 @@ export const ProposalHeader = ({
<div data-testid="proposal-title">
{isListItem ? (
<header>
<SubHeading title={titleContent || t('Unknown proposal')} />
<SubHeading
title={titleContent || fallbackTitle || t('Unknown proposal')}
/>
</header>
) : (
<Heading title={titleContent || t('Unknown proposal')} />
<Heading
title={titleContent || fallbackTitle || t('Unknown proposal')}
/>
)}
</div>
@@ -43,13 +43,17 @@ jest.mock('../list-asset', () => ({
it('Renders with data-testid', async () => {
const proposal = generateProposal();
render(<Proposal proposal={proposal as ProposalQuery['proposal']} />);
render(
<Proposal restData={{}} proposal={proposal as ProposalQuery['proposal']} />
);
expect(await screen.findByTestId('proposal')).toBeInTheDocument();
});
it('renders each section', async () => {
const proposal = generateProposal();
render(<Proposal proposal={proposal as ProposalQuery['proposal']} />);
render(
<Proposal restData={{}} proposal={proposal as ProposalQuery['proposal']} />
);
expect(await screen.findByTestId('proposal-header')).toBeInTheDocument();
expect(screen.getByTestId('proposal-change-table')).toBeInTheDocument();
expect(screen.getByTestId('proposal-json')).toBeInTheDocument();
@@ -76,6 +80,8 @@ it('renders whitelist section if proposal is new asset and source is erc20', asy
},
},
});
render(<Proposal proposal={proposal as ProposalQuery['proposal']} />);
render(
<Proposal restData={{}} proposal={proposal as ProposalQuery['proposal']} />
);
expect(screen.getByTestId('proposal-list-asset')).toBeInTheDocument();
});
@@ -24,9 +24,11 @@ export enum ProposalType {
}
export interface ProposalProps {
proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
restData: any;
}
export const Proposal = ({ proposal }: ProposalProps) => {
export const Proposal = ({ proposal, restData }: ProposalProps) => {
const { params, loading, error } = useNetworkParams([
NetworkParams.governance_proposal_market_minVoterBalance,
NetworkParams.governance_proposal_updateMarket_minVoterBalance,
@@ -104,7 +106,7 @@ export const Proposal = ({ proposal }: ProposalProps) => {
</div>
<div className="mb-6">
<ProposalJson proposal={proposal} />
<ProposalJson proposal={restData?.data?.proposal} />
</div>
<div className="mb-10">
@@ -107,7 +107,7 @@ export const ProtocolUpgradeProposalsListItem = ({
<div className="grid grid-cols-1 mt-3">
<div className="justify-self-end">
<Link
to={`${Routes.PROPOSALS}/protocol-upgrade/${stripFullStops(
to={`${Routes.PROTOCOL_UPGRADES}/${stripFullStops(
proposal.vegaReleaseTag
)}`}
>
@@ -5,9 +5,15 @@ import { useParams } from 'react-router-dom';
import { Proposal } from '../components/proposal';
import { ProposalNotFound } from '../components/proposal-not-found';
import { useProposalQuery } from './__generated__/Proposal';
import { useFetch } from '@vegaprotocol/react-helpers';
import { ENV } from '../../../config';
export const ProposalContainer = () => {
const params = useParams<{ proposalId: string }>();
const {
state: { loading: restLoading, error: restError, data: restData },
} = useFetch(`${ENV.rest}governance?proposalId=${params.proposalId}`);
console.log(restLoading, restError, restData);
const { data, loading, error, refetch } = useProposalQuery({
fetchPolicy: 'network-only',
errorPolicy: 'ignore',
@@ -23,7 +29,7 @@ export const ProposalContainer = () => {
return (
<AsyncRenderer loading={loading} error={error} data={data}>
{data?.proposal ? (
<Proposal proposal={data.proposal} />
<Proposal proposal={data.proposal} restData={restData} />
) : (
<ProposalNotFound />
)}
@@ -49,6 +49,7 @@ export const ProposeFreeform = () => {
formState: { errors },
setValue,
watch,
trigger,
} = useForm<FreeformProposalFormFields>();
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
@@ -85,7 +86,13 @@ export const ProposeFreeform = () => {
await submit(assembleProposal(fields));
};
const viewJson = () => {
const viewJson = async () => {
const isValid = await trigger();
if (!isValid) {
return;
}
const formData = watch();
downloadJson(
JSON.stringify(assembleProposal(formData)),
@@ -89,6 +89,7 @@ export const ProposeNetworkParameter = () => {
formState: { errors },
setValue,
watch,
trigger,
} = useForm<NetworkParameterProposalFormFields>();
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
@@ -148,7 +149,13 @@ export const ProposeNetworkParameter = () => {
await submit(assembleProposal(fields));
};
const viewJson = () => {
const viewJson = async () => {
const isValid = await trigger();
if (!isValid) {
return;
}
const formData = watch();
downloadJson(
JSON.stringify(assembleProposal(formData)),
@@ -61,6 +61,7 @@ export const ProposeNewAsset = () => {
formState: { errors },
setValue,
watch,
trigger,
} = useForm<NewAssetProposalFormFields>();
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
@@ -117,7 +118,13 @@ export const ProposeNewAsset = () => {
await submit(assembleProposal(fields));
};
const viewJson = () => {
const viewJson = async () => {
const isValid = await trigger();
if (!isValid) {
return;
}
const formData = watch();
downloadJson(
JSON.stringify(assembleProposal(formData)),
@@ -59,6 +59,7 @@ export const ProposeNewMarket = () => {
formState: { errors },
setValue,
watch,
trigger,
} = useForm<NewMarketProposalFormFields>();
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
@@ -107,7 +108,13 @@ export const ProposeNewMarket = () => {
await submit(assembleProposal(fields));
};
const viewJson = () => {
const viewJson = async () => {
const isValid = await trigger();
if (!isValid) {
return;
}
const formData = watch();
downloadJson(
JSON.stringify(assembleProposal(formData)),
@@ -59,6 +59,7 @@ export const ProposeUpdateAsset = () => {
formState: { errors },
setValue,
watch,
trigger,
} = useForm<UpdateAssetProposalFormFields>();
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
@@ -107,7 +108,13 @@ export const ProposeUpdateAsset = () => {
await submit(assembleProposal(fields));
};
const viewJson = () => {
const viewJson = async () => {
const isValid = await trigger();
if (!isValid) {
return;
}
const formData = watch();
downloadJson(
JSON.stringify(assembleProposal(formData)),
@@ -106,6 +106,7 @@ export const ProposeUpdateMarket = () => {
formState: { errors },
setValue,
watch,
trigger,
} = useForm<UpdateMarketProposalFormFields>();
const { finalizedProposal, submit, Dialog } = useProposalSubmit();
@@ -157,7 +158,13 @@ export const ProposeUpdateMarket = () => {
await submit(assembleProposal(fields));
};
const viewJson = () => {
const viewJson = async () => {
const isValid = await trigger();
if (!isValid) {
return;
}
const formData = watch();
downloadJson(
JSON.stringify(assembleProposal(formData)),
+15 -8
View File
@@ -224,12 +224,16 @@ const redirects = [
path: '/vesting',
element: <Navigate to={Routes.REDEEM} replace />,
},
{
path: Routes.PROTOCOL_UPGRADES,
element: <Navigate to={Routes.PROPOSALS} replace />,
},
];
const routerConfig = [
{
path: Routes.HOME,
element: <LazyHome name="Token" />,
element: <LazyHome name="Home" />,
},
{
path: Routes.PROPOSALS,
@@ -264,13 +268,13 @@ const routerConfig = [
},
{ path: 'proposals', element: <LazyProposalsList /> },
{ path: ':proposalId', element: <LazyProposal /> },
{
path: 'protocol-upgrade/:proposalReleaseTag',
element: <LazyProtocolUpgradeProposal />,
},
{ path: 'rejected', element: <LazyRejectedProposalsList /> },
],
},
{
path: `${Routes.PROTOCOL_UPGRADES}/:proposalReleaseTag`,
element: <LazyProtocolUpgradeProposal />,
},
{
path: Routes.VALIDATORS,
element: <LazyStaking name="Staking" />,
@@ -291,7 +295,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 +329,11 @@ const routerConfig = [
},
],
},
{ path: 'associate', element: <LazyStakingAssociate /> },
{ path: 'disassociate', element: <LazyStakingDisassociate /> },
{ path: 'associate', element: <LazyStakingAssociate name="Associate" /> },
{
path: 'disassociate',
element: <LazyStakingDisassociate name="Disassociate" />,
},
],
},
{
+1
View File
@@ -5,6 +5,7 @@ const Routes = {
REWARDS: '/rewards',
PROPOSALS: '/proposals',
PROPOSALS_REJECTED: '/proposals/rejected',
PROTOCOL_UPGRADES: '/protocol-upgrades',
NOT_PERMITTED: '/not-permitted',
NOT_FOUND: '/not-found',
CONTRACTS: '/contracts',
@@ -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();
@@ -9,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.
@@ -50,7 +51,7 @@ export const NodeContainer = ({
useRefreshAfterEpoch(data?.epoch.timestamps.expiry, refetch);
if (error && !error.message.includes('failed to get party for ID')) {
if (error && !isPartyNotFoundError(error)) {
return (
<Callout intent={Intent.Danger} title={t('Something went wrong')}>
<pre>
+3 -4
View File
@@ -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 {
@@ -10,8 +10,8 @@ import {
displayChange,
} from '@vegaprotocol/liquidity';
import type { Candle } from '@vegaprotocol/market-list';
import { marketCandlesProvider } from '@vegaprotocol/market-list';
import type { Candle } from '@vegaprotocol/markets';
import { marketCandlesProvider } from '@vegaprotocol/markets';
const THROTTLE_UPDATE_TIME = 500;
File diff suppressed because it is too large Load Diff
@@ -194,6 +194,7 @@ describe('capsule', { tags: '@slow', testIsolation: true }, () => {
});
it('shows node health', function () {
// 0006-NETW-010
const market = this.market;
cy.visit(`/#/markets/${market.id}`);
cy.getByTestId('node-health')
@@ -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');
});
});
@@ -0,0 +1,111 @@
import { closeWelcomeDialog } from '../support/helpers';
const dialogContent = 'dialog-content';
const nodeHealth = 'node-health';
describe('home', { tags: '@regression' }, () => {
before(() => {
cy.clearLocalStorage();
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/');
});
describe('footer', () => {
it('shows current block height', () => {
closeWelcomeDialog();
// 0006-NETW-004
// 0006-NETW-005
// 0006-NETW-008
// 0006-NETW-009
// 0006-NETW-011
cy.intercept('POST', 'http://localhost:3008/graphql', (req) => {
req.on('response', (res) => {
res.setDelay(3000);
});
});
cy.getByTestId(nodeHealth)
.children()
.first()
.should('contain.text', 'Warning delay ( >3 sec)');
cy.intercept('POST', 'http://localhost:3008/graphql', (req) => {
req.on('response', (res) => {
res.setDelay(1);
});
});
cy.getByTestId(nodeHealth)
.children()
.first()
.should('contain.text', 'Operational', { timeout: 10000 })
.next()
.should('contain.text', new URL(Cypress.env('VEGA_URL')).origin)
.next()
.should('contain.text', '100'); // all mocked queries have x-block-height header set to 100
});
it('shows node switcher details', () => {
// 0006-NETW-012
// 0006-NETW-013
// 0006-NETW-014
// 0006-NETW-015
// 0006-NETW-016
cy.getByTestId(nodeHealth).click();
cy.getByTestId(dialogContent).should('contain.text', 'Connected node');
cy.getByTestId(dialogContent).should(
'contain.text',
'This app will only work on CUSTOM. Select a node to connect to.'
);
cy.getByTestId('node')
.first()
.should('contain.text', new URL(Cypress.env('VEGA_URL')).origin)
.next()
.should('contain.text', 'Response time')
.next()
.should('contain.text', 'Block')
.next()
.should('contain.text', 'Subscription');
cy.getByTestId('custom-row').should('contain.text', 'Other');
cy.getByTestId('dialog-close').click();
});
it('switch to other node', () => {
// 0006-NETW-017
// 0006-NETW-018
// 0006-NETW-019
// 0006-NETW-020
cy.getByTestId(nodeHealth).click();
cy.getByTestId('connect').should('be.disabled');
cy.getByTestId('node-url-custom').click();
cy.getByTestId('connect').should('be.disabled');
cy.get("input[placeholder='https://']")
.focus()
.type(new URL(Cypress.env('VEGA_URL')).origin + '/graphql');
cy.getByTestId('connect').click();
cy.getByTestId(nodeHealth)
.children()
.first()
.should('contain.text', 'Operational');
});
});
describe('Network switcher', () => {
before(() => {
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/');
});
// 0006-NETW-002
// 0006-NETW-003
it('switch to fairground network', () => {
cy.getByTestId('network-switcher').click();
cy.getByTestId('network-item').contains('Fairground testnet').click();
cy.get('[aria-haspopup="menu"]').should('contain.text', 'Fairground');
});
});
});
+3 -24
View File
@@ -4,6 +4,7 @@ import { marketsDataQuery } from '@vegaprotocol/mock';
import * as Schema from '@vegaprotocol/types';
const selectMarketOverlay = 'select-market-list';
const dialogContent = 'dialog-content';
const generateProposal = (code: string): ProposalListFieldsFragment => ({
__typename: 'Proposal',
@@ -81,20 +82,12 @@ const generateProposal = (code: string): ProposalListFieldsFragment => ({
__typename: 'DataSourceDefinition',
sourceType: {
__typename: 'DataSourceDefinitionInternal',
sourceType: {
__typename: 'DataSourceSpecConfigurationTime',
conditions: [],
},
},
},
dataSourceSpecForTradingTermination: {
__typename: 'DataSourceDefinition',
sourceType: {
__typename: 'DataSourceDefinitionInternal',
sourceType: {
__typename: 'DataSourceSpecConfigurationTime',
conditions: [],
},
},
},
},
@@ -288,7 +281,7 @@ describe('home', { tags: '@regression' }, () => {
cy.visit('/');
cy.wait('@Markets');
cy.location('hash').should('equal', '#/markets/market-1');
cy.getByTestId('dialog-content').should('not.exist');
cy.getByTestId(dialogContent).should('not.exist');
});
});
@@ -301,22 +294,8 @@ describe('home', { tags: '@regression' }, () => {
cy.visit('/');
cy.wait('@Markets');
cy.location('hash').should('equal', '#/markets/market-not-existing');
cy.getByTestId('dialog-content').should('not.exist');
cy.getByTestId(dialogContent).should('not.exist');
});
});
});
describe('footer', () => {
it('shows current block height', () => {
cy.visit('/');
cy.getByTestId('node-health')
.children()
.first()
.should('contain.text', 'Operational')
.next()
.should('contain.text', new URL(Cypress.env('VEGA_URL')).origin)
.next()
.should('contain.text', '100'); // all mocked queries have x-block-height header set to 100
});
});
});
@@ -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)
+2 -2
View File
@@ -1,7 +1,7 @@
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import * as Schema from '@vegaprotocol/types';
import type { CyHttpMessages } from 'cypress/types/net-stubbing';
import type { Provider, Status } from '@vegaprotocol/market-info';
import type { Provider, Status } from '@vegaprotocol/markets';
import {
accountsQuery,
assetQuery,
@@ -32,7 +32,7 @@ import {
blockStatisticsQuery,
} from '@vegaprotocol/mock';
import type { PartialDeep } from 'type-fest';
import type { MarketDataQuery, MarketsQuery } from '@vegaprotocol/market-list';
import type { MarketDataQuery, MarketsQuery } from '@vegaprotocol/markets';
type MarketPageMockData = {
state: Schema.MarketState;
+1 -1
View File
@@ -1,6 +1,6 @@
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { marketsWithDataProvider } from '@vegaprotocol/market-list';
import { marketsWithDataProvider } from '@vegaprotocol/markets';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { Links, Routes } from '../../pages/client-router';
@@ -5,7 +5,7 @@ import {
lpAggregatedDataProvider,
useCheckLiquidityStatus,
} from '@vegaprotocol/liquidity';
import { tooltipMapping } from '@vegaprotocol/market-info';
import { tooltipMapping } from '@vegaprotocol/markets';
import {
addDecimalsFormatNumber,
formatNumberPercentage,
@@ -37,7 +37,7 @@ import type { LiquidityProvisionData, Filter } from '@vegaprotocol/liquidity';
import { Link, useParams } from 'react-router-dom';
import { Links, Routes } from '../../pages/client-router';
import { useMarket, useStaticMarketData } from '@vegaprotocol/market-list';
import { useMarket, useStaticMarketData } from '@vegaprotocol/markets';
import { DocsLinks } from '@vegaprotocol/environment';
const enum LiquidityTabs {
@@ -2,12 +2,12 @@ import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import { useEnvironment } from '@vegaprotocol/environment';
import { ButtonLink, Link } from '@vegaprotocol/ui-toolkit';
import { MarketProposalNotification } from '@vegaprotocol/proposals';
import type { Market } from '@vegaprotocol/market-list';
import type { Market } from '@vegaprotocol/markets';
import { getExpiryDate, getMarketExpiryDate } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import { HeaderStat } from '../../components/header';
import { MarketMarkPrice } from '../../components/market-mark-price';
import { Last24hPriceChange, Last24hVolume } from '@vegaprotocol/market-info';
import { Last24hPriceChange, Last24hVolume } from '@vegaprotocol/markets';
import { MarketState } from '../../components/market-state';
import { HeaderStatMarketTradingMode } from '../../components/market-trading-mode';
import { MarketLiquiditySupplied } from '../../components/liquidity-supplied';
@@ -8,8 +8,8 @@ import { MockedProvider } from '@apollo/client/testing';
import type {
MarketDataUpdateFieldsFragment,
MarketDataUpdateSubscription,
} from '@vegaprotocol/market-list';
import { MarketDataUpdateDocument } from '@vegaprotocol/market-list';
} from '@vegaprotocol/markets';
import { MarketDataUpdateDocument } from '@vegaprotocol/markets';
import {
AuctionTrigger,
MarketState,
@@ -6,8 +6,8 @@ import {
formatNumber,
priceChangePercentage,
} from '@vegaprotocol/utils';
import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/market-list';
import { useMarketDataUpdateSubscription } from '@vegaprotocol/market-list';
import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/markets';
import { useMarketDataUpdateSubscription } from '@vegaprotocol/markets';
import { Sparkline } from '@vegaprotocol/ui-toolkit';
export const MarketSelectorItem = ({
@@ -1,7 +1,7 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { MarketSelector } from './market-selector';
import { useMarketList } from '@vegaprotocol/market-list';
import { useMarketList } from '@vegaprotocol/markets';
import { createMarketFragment } from '@vegaprotocol/mock';
import { MarketState } from '@vegaprotocol/types';
import { MemoryRouter } from 'react-router-dom';
@@ -10,8 +10,9 @@ import type { SortType } from './sort-dropdown';
import { SortTypeMapping } from './sort-dropdown';
import { Sort } from './sort-dropdown';
import { subDays } from 'date-fns';
import { isMarketActive } from './use-market-selector-list';
jest.mock('@vegaprotocol/market-list');
jest.mock('@vegaprotocol/markets');
const mockUseMarketList = useMarketList as jest.Mock;
// mock market list items to avoid subscriptions starting
@@ -126,9 +127,7 @@ describe('MarketSelector', () => {
}),
];
const activeMarkets = markets.filter((m) =>
[MarketState.STATE_ACTIVE, MarketState.STATE_SUSPENDED].includes(m.state)
);
const activeMarkets = markets.filter((m) => isMarketActive(m.state));
mockUseMarketList.mockReturnValue({
data: markets,
loading: false,
@@ -1,6 +1,6 @@
import { t } from '@vegaprotocol/i18n';
import uniqBy from 'lodash/uniqBy';
import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/market-list';
import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/markets';
import {
Input,
TinyScroll,
+1 -1
View File
@@ -7,7 +7,7 @@ import {
useThrottledDataProvider,
} from '@vegaprotocol/data-provider';
import { AsyncRenderer, ExternalLink, Splash } from '@vegaprotocol/ui-toolkit';
import { marketProvider, marketDataProvider } from '@vegaprotocol/market-list';
import { marketProvider, marketDataProvider } from '@vegaprotocol/markets';
import { useGlobalStore, usePageTitleStore } from '../../stores';
import { TradeGrid } from './trade-grid';
import { TradePanels } from './trade-panels';
@@ -6,8 +6,8 @@ import classNames from 'classnames';
import AutoSizer from 'react-virtualized-auto-sizer';
import type { PinnedAsset } from '@vegaprotocol/accounts';
import { t } from '@vegaprotocol/i18n';
import { OracleBanner } from '@vegaprotocol/market-info';
import type { Market } from '@vegaprotocol/market-list';
import { OracleBanner } from '@vegaprotocol/markets';
import type { Market } from '@vegaprotocol/markets';
import { Filter } from '@vegaprotocol/orders';
import {
usePaneLayout,
@@ -1,6 +1,6 @@
import type { PinnedAsset } from '@vegaprotocol/accounts';
import type { Market } from '@vegaprotocol/market-list';
import { OracleBanner } from '@vegaprotocol/market-info';
import type { Market } from '@vegaprotocol/markets';
import { OracleBanner } from '@vegaprotocol/markets';
import {
useMarketClickHandler,
useMarketLiquidityClickHandler,
@@ -1,5 +1,5 @@
import { DealTicketContainer } from '@vegaprotocol/deal-ticket';
import { MarketInfoAccordionContainer } from '@vegaprotocol/market-info';
import { MarketInfoAccordionContainer } from '@vegaprotocol/markets';
import { OrderbookContainer } from '@vegaprotocol/market-depth';
import { OrderListContainer, Filter } from '@vegaprotocol/orders';
import type { OrderListContainerProps } from '@vegaprotocol/orders';
@@ -1,15 +1,18 @@
import merge from 'lodash/merge';
import { renderHook } from '@testing-library/react';
import { useMarketSelectorList } from './use-market-selector-list';
import {
isMarketActive,
useMarketSelectorList,
} from './use-market-selector-list';
import { Product } from './product-selector';
import { Sort } from './sort-dropdown';
import { createMarketFragment } from '@vegaprotocol/mock';
import { MarketState } from '@vegaprotocol/types';
import { useMarketList } from '@vegaprotocol/market-list';
import { useMarketList } from '@vegaprotocol/markets';
import type { Filter } from './market-selector';
import { subDays } from 'date-fns';
jest.mock('@vegaprotocol/market-list');
jest.mock('@vegaprotocol/markets');
const mockUseMarketList = useMarketList as jest.Mock;
describe('useMarketSelectorList', () => {
@@ -38,6 +41,10 @@ describe('useMarketSelectorList', () => {
}),
createMarketFragment({
id: 'market-3',
state: MarketState.STATE_CLOSED,
}),
createMarketFragment({
id: 'market-4',
state: MarketState.STATE_PENDING,
}),
];
@@ -48,7 +55,7 @@ describe('useMarketSelectorList', () => {
});
const { result } = setup();
const expectedFilteredMarkets = markets.filter((m) =>
[MarketState.STATE_ACTIVE, MarketState.STATE_SUSPENDED].includes(m.state)
isMarketActive(m.state)
);
expect(result.current).toEqual({
data: markets,
@@ -1,7 +1,7 @@
import { useMemo } from 'react';
import orderBy from 'lodash/orderBy';
import { MarketState } from '@vegaprotocol/types';
import { useMarketList } from '@vegaprotocol/market-list';
import { useMarketList } from '@vegaprotocol/markets';
import { priceChangePercentage } from '@vegaprotocol/utils';
import type { Filter } from './market-selector';
import { Sort } from './sort-dropdown';
@@ -18,11 +18,7 @@ export const useMarketSelectorList = ({
if (!data?.length) return [];
const markets = data
// only active
.filter((m) => {
return [MarketState.STATE_ACTIVE, MarketState.STATE_SUSPENDED].includes(
m.state
);
})
.filter((m) => isMarketActive(m.state))
// only selected product type
.filter((m) => {
if (m.tradableInstrument.instrument.product.__typename === product) {
@@ -80,3 +76,11 @@ export const useMarketSelectorList = ({
return { markets, data, loading, error };
};
export const isMarketActive = (state: MarketState) => {
return [
MarketState.STATE_ACTIVE,
MarketState.STATE_SUSPENDED,
MarketState.STATE_PENDING,
].includes(state);
};
@@ -6,8 +6,16 @@ import { MarketState } from '@vegaprotocol/types';
import { subDays } from 'date-fns';
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
import type { OracleSpecDataConnectionQuery } from '@vegaprotocol/market-info';
import { OracleSpecDataConnectionDocument } from '@vegaprotocol/market-info';
import type {
OracleSpecDataConnectionQuery,
MarketsDataQuery,
MarketsQuery,
} from '@vegaprotocol/markets';
import {
OracleSpecDataConnectionDocument,
MarketsDataDocument,
MarketsDocument,
} from '@vegaprotocol/markets';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { VegaWalletContext } from '@vegaprotocol/wallet';
import type {
@@ -16,9 +24,6 @@ import type {
} from '@vegaprotocol/positions';
import { PositionsDocument } from '@vegaprotocol/positions';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import type { MarketsDataQuery, MarketsQuery } from '@vegaprotocol/market-list';
import { MarketsDataDocument } from '@vegaprotocol/market-list';
import { MarketsDocument } from '@vegaprotocol/market-list';
import {
createMarketFragment,
marketsQuery,
@@ -214,7 +219,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 +241,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 +333,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));
});
});
+27 -6
View File
@@ -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';
@@ -13,8 +13,11 @@ import {
getMarketExpiryDate,
} from '@vegaprotocol/utils';
import { usePositionsQuery } from '@vegaprotocol/positions';
import type { MarketMaybeWithData } from '@vegaprotocol/market-list';
import { closedMarketsWithDataProvider } from '@vegaprotocol/market-list';
import type { MarketMaybeWithData } from '@vegaprotocol/markets';
import {
MarketTableActions,
closedMarketsWithDataProvider,
} from '@vegaprotocol/markets';
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;
@@ -1,4 +1,4 @@
import { MarketsContainer } from '@vegaprotocol/market-list';
import { MarketsContainer } from '@vegaprotocol/markets';
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
export const Markets = () => {
@@ -2,8 +2,8 @@ import { render, screen } from '@testing-library/react';
import type { Property } from '@vegaprotocol/types';
import type { MockedResponse } from '@apollo/client/testing';
import { MockedProvider } from '@apollo/client/testing';
import type { OracleSpecDataConnectionQuery } from '@vegaprotocol/market-info';
import { OracleSpecDataConnectionDocument } from '@vegaprotocol/market-info';
import type { OracleSpecDataConnectionQuery } from '@vegaprotocol/markets';
import { OracleSpecDataConnectionDocument } from '@vegaprotocol/markets';
import type { SettlementPriceCellProps } from './settlement-price-cell';
import { SettlementPriceCell } from './settlement-price-cell';
@@ -1,6 +1,6 @@
import { DApp, EXPLORER_ORACLE, useLinks } from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n';
import { useOracleSpecBindingData } from '@vegaprotocol/market-info';
import { useOracleSpecBindingData } from '@vegaprotocol/markets';
import { Link } from '@vegaprotocol/ui-toolkit';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
@@ -26,7 +26,7 @@ import type { Account } from '@vegaprotocol/accounts';
import { accountsDataProvider } from '@vegaprotocol/accounts';
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
import { useDataProvider } from '@vegaprotocol/data-provider';
import type { Market } from '@vegaprotocol/market-list';
import type { Market } from '@vegaprotocol/markets';
const DateRange = {
RANGE_1D: '1D',
@@ -5,6 +5,7 @@ import {
RoundedWrapper,
Switch,
ThemeSwitcher,
ToastPositionSetter,
} from '@vegaprotocol/ui-toolkit';
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
@@ -41,6 +42,8 @@ export const Settings = () => {
'Help identify bugs and improve the service by sharing anonymous usage data.'
)}
/>
<Divider />
<ToastPositionSetter />
</RoundedWrapper>
</div>
</div>
@@ -4,8 +4,8 @@ import {
useNetworkParams,
} from '@vegaprotocol/network-parameters';
import { useDataProvider } from '@vegaprotocol/data-provider';
import type { MarketData } from '@vegaprotocol/market-list';
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
import type { MarketData } from '@vegaprotocol/markets';
import { marketDataProvider, marketProvider } from '@vegaprotocol/markets';
import { HeaderStat } from '../header';
import {
ExternalLink,
@@ -3,7 +3,7 @@ import { useInView } from 'react-intersection-observer';
import { addDecimalsFormatNumber, isNumeric } from '@vegaprotocol/utils';
import { useThrottledDataProvider } from '@vegaprotocol/data-provider';
import { PriceCell } from '@vegaprotocol/datagrid';
import { marketDataProvider } from '@vegaprotocol/market-list';
import { marketDataProvider } from '@vegaprotocol/markets';
import { THROTTLE_UPDATE_TIME } from '../constants';
interface Props {
@@ -1,6 +1,6 @@
import throttle from 'lodash/throttle';
import type { MarketData, Market } from '@vegaprotocol/market-list';
import { marketDataProvider } from '@vegaprotocol/market-list';
import type { MarketData, Market } from '@vegaprotocol/markets';
import { marketDataProvider } from '@vegaprotocol/markets';
import { t } from '@vegaprotocol/i18n';
import { useDataProvider } from '@vegaprotocol/data-provider';
import * as Schema from '@vegaprotocol/types';
@@ -5,7 +5,7 @@ import { useInView } from 'react-intersection-observer';
import * as Schema from '@vegaprotocol/types';
import { HeaderStat } from '../header';
import { Tooltip } from '@vegaprotocol/ui-toolkit';
import { useStaticMarketData } from '@vegaprotocol/market-list';
import { useStaticMarketData } from '@vegaprotocol/markets';
const getTradingModeLabel = (
marketTradingMode?: Schema.MarketTradingMode,
@@ -3,8 +3,8 @@ import throttle from 'lodash/throttle';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import { useDataProvider } from '@vegaprotocol/data-provider';
import type { MarketData } from '@vegaprotocol/market-list';
import { marketDataProvider, marketProvider } from '@vegaprotocol/market-list';
import type { MarketData } from '@vegaprotocol/markets';
import { marketDataProvider, marketProvider } from '@vegaprotocol/markets';
import { HeaderStat } from '../header';
import * as constants from '../constants';
@@ -1,20 +1,21 @@
import type { RefObject, MouseEvent } from 'react';
import { FeesCell } from '@vegaprotocol/market-info';
import {
FeesCell,
calcCandleHigh,
calcCandleLow,
calcCandleVolume,
} from '@vegaprotocol/market-list';
Last24hPriceChange,
Last24hVolume,
} from '@vegaprotocol/markets';
import { addDecimalsFormatNumber } from '@vegaprotocol/utils';
import { t } from '@vegaprotocol/i18n';
import { PriceCell } from '@vegaprotocol/datagrid';
import { Link as UILink, Sparkline, Tooltip } from '@vegaprotocol/ui-toolkit';
import isNil from 'lodash/isNil';
import type { CandleClose } from '@vegaprotocol/types';
import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/market-list';
import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/markets';
import { Link } from 'react-router-dom';
import { MarketMarkPrice } from '../market-mark-price';
import { Last24hPriceChange, Last24hVolume } from '@vegaprotocol/market-info';
import { MarketTradingMode } from '../market-trading-mode';
import { Links, Routes } from '../../pages/client-router';
@@ -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}>
@@ -4,7 +4,7 @@ import { Dialog } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
import { useLocalStorage } from '@vegaprotocol/react-helpers';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { activeMarketsProvider } from '@vegaprotocol/market-list';
import { activeMarketsProvider } from '@vegaprotocol/markets';
import * as constants from '../constants';
import { RiskNoticeDialog } from './risk-notice-dialog';
import { WelcomeNoticeDialog } from './welcome-notice-dialog';
@@ -6,7 +6,7 @@ import type {
MarketMaybeWithCandles,
MarketMaybeWithData,
MarketData,
} from '@vegaprotocol/market-list';
} from '@vegaprotocol/markets';
import { SelectMarketLandingTable } from './welcome-landing-dialog';
const mockMarketClickHandler = jest.fn();
jest.mock('../../lib/hooks/use-market-click-handler', () => ({
@@ -43,10 +43,28 @@ const MARKET_A: PartialMarket = {
dataSourceSpecForTradingTermination: {
__typename: 'DataSourceSpec',
id: 'oracleId',
data: {
__typename: 'DataSourceDefinition',
sourceType: {
__typename: 'DataSourceDefinitionExternal',
sourceType: {
__typename: 'DataSourceSpecConfiguration',
},
},
},
},
dataSourceSpecForSettlementData: {
__typename: 'DataSourceSpec',
id: 'oracleId',
data: {
__typename: 'DataSourceDefinition',
sourceType: {
__typename: 'DataSourceDefinitionExternal',
sourceType: {
__typename: 'DataSourceSpecConfiguration',
},
},
},
},
dataSourceSpecBinding: {
__typename: 'DataSourceSpecToFutureBinding',
@@ -129,10 +147,28 @@ const MARKET_B: PartialMarket = {
dataSourceSpecForTradingTermination: {
__typename: 'DataSourceSpec',
id: 'oracleId',
data: {
__typename: 'DataSourceDefinition',
sourceType: {
__typename: 'DataSourceDefinitionExternal',
sourceType: {
__typename: 'DataSourceSpecConfiguration',
},
},
},
},
dataSourceSpecForSettlementData: {
__typename: 'DataSourceSpec',
id: 'oracleId',
data: {
__typename: 'DataSourceDefinition',
sourceType: {
__typename: 'DataSourceDefinitionExternal',
sourceType: {
__typename: 'DataSourceSpecConfiguration',
},
},
},
},
dataSourceSpecBinding: {
__typename: 'DataSourceSpecToFutureBinding',
@@ -1,10 +1,10 @@
import React, { useCallback } from 'react';
import { useMarketList } from '@vegaprotocol/market-list';
import { useMarketList } from '@vegaprotocol/markets';
import { t } from '@vegaprotocol/i18n';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import { Link as UILink, TinyScroll } from '@vegaprotocol/ui-toolkit';
import type { OnCellClickHandler } from '../select-market';
import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/market-list';
import type { MarketMaybeWithDataAndCandles } from '@vegaprotocol/markets';
import {
ColumnKind,
columns,
+5 -1
View File
@@ -6,7 +6,10 @@ import { VegaConnectDialog } from '@vegaprotocol/wallet';
import { Connectors } from '../lib/vega-connectors';
import { CreateWithdrawalDialog } from '@vegaprotocol/withdraws';
import { DepositDialog } from '@vegaprotocol/deposits';
import { Web3ConnectUncontrolledDialog } from '@vegaprotocol/web3';
import {
Web3ConnectUncontrolledDialog,
WithdrawalApprovalDialogContainer,
} from '@vegaprotocol/web3';
import { WelcomeDialog } from '../components/welcome-dialog';
import { TransferDialog } from '@vegaprotocol/accounts';
@@ -27,6 +30,7 @@ const DialogsContainer = () => {
<Web3ConnectUncontrolledDialog />
<CreateWithdrawalDialog />
<TransferDialog />
<WithdrawalApprovalDialogContainer />
</>
);
};
+3 -5
View File
@@ -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,
+6
View File
@@ -0,0 +1,6 @@
function ReactMarkdown({ children }) {
// eslint-disable-next-line react/jsx-no-useless-fragment
return <>{children}</>;
}
export default ReactMarkdown;
@@ -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>
);
};
@@ -1,5 +1,5 @@
import { assetsProvider } from '@vegaprotocol/assets';
import { marketsProvider } from '@vegaprotocol/market-list';
import { marketsProvider } from '@vegaprotocol/markets';
import { removePaginationWrapper } from '@vegaprotocol/utils';
import {
makeDataProvider,
@@ -20,7 +20,7 @@ import type {
AccountEventsSubscription,
AccountsQueryVariables,
} from './__generated__/Accounts';
import type { Market } from '@vegaprotocol/market-list';
import type { Market } from '@vegaprotocol/markets';
import type { Asset } from '@vegaprotocol/assets';
const AccountType = Schema.AccountType;
+58 -100
View File
@@ -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
+2 -1
View File
@@ -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}
/>
+7 -5
View File
@@ -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>
);
};
+7 -1
View File
@@ -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');
+7 -7
View File
@@ -12,13 +12,13 @@ export * from '../fills/src/lib/fills.mock';
export * from '../proposals/src/lib/proposals-data-provider/proposals.mock';
export * from '../ledger/src/lib/ledger-entries.mock';
export * from '../market-depth/src/lib/market-depth.mock';
export * from '../market-info/src/lib/components/market-info/market-info.mock';
export * from '../market-list/src/lib/market-candles.mock';
export * from '../market-list/src/lib/market-data.mock';
export * from '../market-list/src/lib/markets-candles.mock';
export * from '../market-list/src/lib/markets-data.mock';
export * from '../market-list/src/lib/markets.mock';
export * from '../market-info/src/lib/oracle-spec-data-connection.mock';
export * from '../markets/src/lib/components/market-info/market-info.mock';
export * from '../markets/src/lib/market-candles.mock';
export * from '../markets/src/lib/market-data.mock';
export * from '../markets/src/lib/markets-candles.mock';
export * from '../markets/src/lib/markets-data.mock';
export * from '../markets/src/lib/markets.mock';
export * from '../markets/src/lib/oracle-spec-data-connection.mock';
export * from '../orders/src/lib/components/order-data-provider/orders.mock';
export * from '../positions/src/lib/positions.mock';
export * from '../network-parameters/src/network-params.mock';
+2
View File
@@ -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';

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