Compare commits

...
Author SHA1 Message Date
maciek e2e2b8c455 Merge remote-tracking branch 'origin/main' into chore/4792-aggrid-autosize-selected-columns-main 2023-09-28 08:24:06 +02:00
Radosław Szpiech 7ac3a68ac9 chore(trading): add possibility to manualy trigger console-test (#4899) 2023-09-27 15:18:32 +02:00
Radosław Szpiech 2640ccb20a chore(trading): change runner for mainnet compatible vega version (#4907) 2023-09-27 14:42:12 +02:00
Maciek d78de10855 chore(trading): remove underlines on tooltips (#4884) 2023-09-26 13:45:33 -04:00
Matthew Russell bb402c02f6 chore(trading): make volume bars color match candle color (#4881) 2023-09-26 12:08:12 -04:00
Bartłomiej Głownia 8a9b1c7874 feat(deal-ticket): amend fee estimates for postOnly orders and when market is in auction (#4843) 2023-09-26 11:57:47 -04:00
Matthew Russell a7e8b0eb01 fix(market-depth): ensure scroll bar doesn't show on orderbook (#4882) 2023-09-26 11:54:42 -04:00
Bartłomiej Głownia 89b3c06107 feat(deal-ticket): show worst case instead of ranges in estimated values (#4870) 2023-09-26 11:53:45 -04:00
maciek 54430b7d64 chore: add handle of autosizing selected columns - add also on positions table 2023-09-26 15:43:02 +02:00
maciek 9a21bad81f Merge remote-tracking branch 'origin/main' into chore/4792-aggrid-autosize-selected-columns-main 2023-09-26 12:06:35 +02:00
Radosław Szpiech cd5c73d3fd chore(trading): temporary disable console-test to unblock CI queue (#4885) 2023-09-26 10:45:27 +01:00
maciek 917e5c2773 chore: add handle of autosizing selected columns - fix failing cypress tests 2023-09-26 11:45:09 +02:00
Joe Tsang b3a5ab022d chore(ci): update genesis file (#4887) 2023-09-26 10:44:55 +01:00
maciek 192dd749cc chore: add handle of autosizing selected columns - add unit test 2023-09-26 11:44:18 +02:00
maciek 5aa3f238a9 chore: add handle of autosizing selected columns 2023-09-26 11:37:31 +02:00
Mikołaj Młodzikowski 496d1f5c68 feat(ci): parse if there are any changes 2023-09-25 18:10:01 -04:00
Mikołaj Młodzikowski e914e7bb70 fix(ci): provide proper ipfs process 2023-09-25 18:09:31 -04:00
Matthew Russell 71a36c2382 fix(trading): remove upgrade banner [main] (#4877) 2023-09-25 17:27:01 -04:00
Matthew Russell 1c6a307bcd fix(wallet): reduce time to check for wallet running [main] (#4876) 2023-09-25 17:26:40 -04:00
Matthew Russell ef4a740b91 fix(trading): allotment breaking [main] (#4875) 2023-09-25 17:26:06 -04:00
Sam Keen 2d4be5fcb3 fix(governance): mainnet rewards query looping (#4865) 2023-09-25 09:59:38 +00:00
m.rayandMatthew Russell 835f2b793f chore(trading): remove static assets console coming from vega.xyz (#4825)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-09-19 23:54:07 -07:00
Matthew Russell d50b988b4a Merge branch 'release/mainnet-trading' of github.com:vegaprotocol/frontend-monorepo into release/mainnet-trading 2023-09-18 09:03:44 -07:00
Madalina Raicu a6aec899c8 chore: update tag metamask snaps to true 2023-09-18 15:08:46 +01:00
Mikołaj Młodzikowski 8b19572dc9 feat(ci): proper run 2023-09-15 13:07:55 -07:00
Mikołaj Młodzikowski 80399d04f7 feat(ci): patch releasing to ipfs 2023-09-15 17:03:50 +02:00
m.ray 8322fc7edd chore: bump version (#4805) 2023-09-15 15:46:02 +01:00
46752816ec chore(trading): get started section for deposit (#4783)
Co-authored-by: maciek <maciek@vegaprotocol.io>
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2023-09-15 15:10:38 +01:00
Sam Keen f99f78780c fix(markets): market info for liquidity is showing "added" tags (#4796) 2023-09-15 13:54:17 +01:00
Maciek f7037bca80 chore(deal-ticket): 4743 preserve estimate position cache in deal ticket (#4770) 2023-09-15 13:53:24 +01:00
Matthew RussellandMadalina Raicu ba39720f05 fix(trading,web3): prevent deposit toasts reappearing (#4797)
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2023-09-15 13:51:28 +01:00
MaciekandMadalina Raicu 6d35f2b39d chore(trading): 4764 remember closed sidebar (#4799)
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2023-09-15 13:36:08 +01:00
Matthew Russell 78afecc2e5 chore(trading): layout adjustments to accomodate default 13 inch screens (#4798) 2023-09-15 13:24:47 +01:00
Bartłomiej Głownia 3de5b07495 fix(trading): add overflow hidden to candles tab container (#4803) 2023-09-15 13:13:05 +01:00
Matthew Russell e944d3e37c fix(trading): correct link for get started prompt (#4782) 2023-09-15 13:12:39 +01:00
Joe Tsang 5596392835 chore(governance): fix failing staking test (#4801) 2023-09-15 13:04:42 +01:00
Ben 5c57106c04 chore(trading): delete market info tests (#4804) 2023-09-15 14:45:52 +03:00
Ben 2fc688f477 chore(trading): fix wallet test (#4802) 2023-09-15 14:45:15 +03:00
Mikołaj Młodzikowski 9ea8c839db feat(ci): use ipfs daemon in dockerfiles (#4786) 2023-09-15 08:48:25 +02:00
Matthew Russell d7e2da7a54 fix(trading): missing styles for tooltip in positions table (#4780) 2023-09-14 14:00:59 -07:00
m.ray b29c268257 chore(trading): add oracle proofs url to all envs (#4793) 2023-09-14 13:57:28 -07:00
m.rayandMatthew Russell 01ca05a313 chore(trading): update governance variables (#4766)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-09-14 13:57:15 -07:00
Matthew Russell e3c6dd41c9 fix(trading): simplify onboarding and explore button to use top traded (#4781) 2023-09-14 12:10:33 -07:00
Bartłomiej GłowniaandMatthew Russell fbd01dc1bd fix(trading): use asset decimals to format liquidation price in posions table (#4787)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-09-14 11:18:58 -07:00
m.rayandMatthew Russell af6719cc9d chore(trading): add governance link to top level nav (#4765)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-09-13 14:25:31 -07:00
158 changed files with 1255 additions and 1053 deletions
+8 -8
View File
@@ -175,14 +175,14 @@ jobs:
preview_explorer: ${{ env.PREVIEW_EXPLORER }}
preview_tools: ${{ env.PREVIEW_TOOLS }}
console-e2e:
needs: build-sources
name: '(CI) console python'
uses: ./.github/workflows/console-test-run.yml
secrets: inherit
if: ${{ contains(fromJSON(needs.build-sources.outputs.projects), 'trading') && github.event_name == 'pull_request' }}
with:
github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
# console-e2e:
# needs: build-sources
# name: '(CI) console python'
# uses: ./.github/workflows/console-test-run.yml
# secrets: inherit
# if: ${{ contains(fromJSON(needs.build-sources.outputs.projects), 'trading') && github.event_name == 'pull_request' }}
# with:
# github-sha: ${{ github.event.pull_request.head.sha || github.sha }}
cypress:
needs: build-sources
+35 -7
View File
@@ -6,20 +6,28 @@ on:
github-sha:
required: true
type: string
workflow_dispatch:
inputs:
console-test-branch:
type: choice
description: 'main: v0.72.14, develop: v0.73.0-preview7'
options:
- main
- develop
jobs:
run-tests:
name: run-tests
runs-on: console-test
runs-on: 8-cores
timeout-minutes: 20
steps:
#----------------------------------------------
# check-out frontend-monorepo
#----------------------------------------------
- name: Checkout console test repo
- name: Checkout frontend-monorepo
uses: actions/checkout@v3
with:
ref: ${{ inputs.github-sha }}
ref: ${{ inputs.github-sha || github.sha }}
#----------------------------------------------
# cache node modules
#----------------------------------------------
@@ -65,32 +73,42 @@ jobs:
uses: actions/checkout@v3
with:
repository: vegaprotocol/console-test
ref: ${{ inputs.console-test-branch }}
path: './console-test'
- name: Load console test envs
id: console-test-env
uses: falti/dotenv-action@v1.0.4
with:
path: './console-test/.env.${{ inputs.console-test-branch }}'
export-variables: true
keys-case: upper
log-variables: true
#----------------------------------------------
# install dependencies if cache does not exist
#----------------------------------------------
- name: Install dependencies
working-directory: ./console-test
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
run: poetry install --no-interaction --no-root
#----------------------------------------------
# install vega binaries
#----------------------------------------------
- name: Install vega binaries
working-directory: ./console-test
run: poetry run python -m vega_sim.tools.load_binaries --force
run: poetry run python -m vega_sim.tools.load_binaries --force --version ${{ env.VEGA_VERSION }}
#----------------------------------------------
# install playwright
#----------------------------------------------
- name: install playwright
run: poetry run playwright install
run: poetry run playwright install --with-deps chromium
working-directory: ./console-test
#----------------------------------------------
# run tests
#----------------------------------------------
- name: Run tests
working-directory: ./console-test
run: poetry run pytest -v -s --numprocesses 2 --dist loadfile --durations=20
run: poetry run pytest -v -s --numprocesses 4 --dist loadfile --durations=15
- name: Check files
run: |
ls -al .
@@ -105,3 +123,13 @@ jobs:
name: playwright-trace
path: ./traces/
retention-days: 15
#----------------------------------------------
# ----- upload logs -----
#----------------------------------------------
- name: Upload worker logs
uses: actions/upload-artifact@v3
if: always()
with:
name: worker-logs
path: ./logs/
retention-days: 15
+1 -1
View File
@@ -19,7 +19,7 @@ jobs:
matrix:
project: ${{ fromJSON(inputs.projects) }}
name: ${{ matrix.project }}
runs-on: self-hosted-runner
runs-on: mainnet-compatible-runner
timeout-minutes: 120
steps:
# Checks if skip cache was requested
+8 -6
View File
@@ -155,10 +155,10 @@ jobs:
- name: Sanity check docker image
run: |
echo "Check ipfs-hash"
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash > ${{ matrix.app }}-ipfs-hash
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local /bin/sh -c 'cat /ipfs-hash'
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local /bin/sh -c 'cat /ipfs-hash' > ${{ matrix.app }}-ipfs-hash
echo "List html directory"
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local sh -c 'apk add --update tree; tree /usr/share/nginx/html'
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local /bin/sh -c 'apk add --update tree; tree /usr/share/nginx/html'
- name: Publish dist as docker image (ghcr)
uses: docker/build-push-action@v3
@@ -329,7 +329,9 @@ jobs:
fi
# create commit
commit_msg="Automated hash update from ${{ github.ref }}"
git commit -m "$commit_msg"
git push -u origin "main"
if ! git diff --cached --exit-code; then
commit_msg="Automated hash update from ${{ github.ref }}"
git commit -m "$commit_msg"
git push -u origin "main"
fi
)
+15 -1
View File
@@ -113,6 +113,20 @@ In order to run a container on port 3000:
docker run -p 3000:80 [TAG]
```
On top of that there are two possible scenarios for running docker image - using nginx server (default) of ipfs daemon.
to run ipfs on port 3000:
```bash
docker run -p 3000:80 [TAG] /run-ipfs.sh
```
to run nginx on port 3000:
```bash
docker run -p 3000:80 [TAG]
```
## Build instructions
The [`docker`](./docker) subfolder has some docker configurations for easily setting up your own hosted version of Console either for the web, or ready for pinning on IPFS.
@@ -150,7 +164,7 @@ As a prerequisite you need to perform build of `dist` directory and move its con
You can build any of the containers locally with the following command:
```bash
docker build --dockerfile docker/node-outside-docker.Dockerfile . --tag=[TAG]
docker build -f docker/node-outside-docker.Dockerfile . --tag=[TAG]
```
### Verifying ipfs-hash of existing current application version
+2
View File
@@ -4,6 +4,8 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://n04.d.vega.xyz/tm/websocket
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
NX_VEGA_ENV=DEVNET
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
# App flags
NX_EXPLORER_ASSETS=1
+1
View File
@@ -4,6 +4,7 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://mainnet-observer-proxy01.ops.vega.xyz/websocke
NX_VEGA_URL=https://api.vega.community/graphql
NX_VEGA_ENV=MAINNET
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
# App flags
NX_EXPLORER_ASSETS=1
+1
View File
@@ -4,6 +4,7 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_VEGA_ENV=TESTNET
NX_BLOCK_EXPLORER=https://be.testnet.vega.xyz/rest
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
# App flags
NX_EXPLORER_ASSETS=1
+1
View File
@@ -3,6 +3,7 @@ NX_VEGA_ENV=CUSTOM
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_VEGA_EXPLORER_URL=/
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
# App flags
NX_EXPLORER_TXS_LIST=0
+1
View File
@@ -8,6 +8,7 @@ NX_VEGA_URL=https://api.devnet1.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_EXPLORER_URL=/
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
+1
View File
@@ -9,6 +9,7 @@ NX_VEGA_GOVERNANCE_URL=https://governance.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz/
NX_VEGA_CONSOLE_URL=https://console.vega.xyz
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
+1
View File
@@ -9,6 +9,7 @@ NX_VEGA_GOVERNANCE_URL=https://governance.mainnet-mirror.vega.rocks
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.mainnet-mirror.vega.rocks/
NX_VEGA_CONSOLE_URL=https://console.mainnet-mirror.vega.rocks
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
+1
View File
@@ -1,2 +1,3 @@
# .env is stagnet1, so there are no overrides required
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz","STAGNET1":"https://stagnet1.explorer.vega.xyz"}'
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
+1
View File
@@ -9,6 +9,7 @@ NX_VEGA_GOVERNANCE_URL=https://governance.fairground.wtf
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
+1
View File
@@ -11,6 +11,7 @@ NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/rest
NX_VEGA_GOVERNANCE_URL=https://governance.validators-testnet.vega.rocks
NX_VEGA_EXPLORER_URL=https://explorer.validators-testnet.vega.rocks/
NX_VEGA_CONSOLE_URL=https://trading.validators-testnet.vega.rocks/
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_TENDERMINT_URL=https://tm.be.validators-testnet.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
+2 -1
View File
@@ -5,4 +5,5 @@ NX_VEGA_ENV=CUSTOM
NX_BLOCK_EXPLORER=
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_VEGA_EXPLORER_URL=/
NX_VEGA_EXPLORER_URL=/
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
@@ -4,7 +4,7 @@ import { AssetTypeMapping, AssetStatusMapping } from '@vegaprotocol/assets';
import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { AgGrid } from '@vegaprotocol/datagrid';
import type { VegaICellRendererParams } from '@vegaprotocol/datagrid';
import { useRef, useLayoutEffect } from 'react';
import { BREAKPOINT_MD } from '../../config/breakpoints';
@@ -4,7 +4,7 @@ import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
import type { ColDef } from 'ag-grid-community';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { AgGrid } from '@vegaprotocol/datagrid';
import type {
VegaICellRendererParams,
VegaValueGetterParams,
@@ -2,7 +2,7 @@ import type { ProposalListFieldsFragment } from '@vegaprotocol/proposals';
import { VoteProgress } from '@vegaprotocol/proposals';
import type { AgGridReact } from 'ag-grid-react';
import { ExternalLink } from '@vegaprotocol/ui-toolkit';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { AgGrid } from '@vegaprotocol/datagrid';
import type {
VegaICellRendererParams,
VegaValueFormatterParams,
@@ -33,7 +33,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
const { params } = useNetworkParams([
NetworkParams.governance_proposal_market_requiredMajority,
]);
const tokenLink = useLinks(DApp.Token);
const tokenLink = useLinks(DApp.Governance);
const requiredMajorityPercentage = useMemo(() => {
const requiredMajority =
params?.governance_proposal_market_requiredMajority ?? 1;
@@ -105,7 +105,7 @@ export const ProposalsTable = ({ data }: ProposalsTableProps) => {
? new BigNumber(0)
: yesTokens.multipliedBy(100).dividedBy(totalTokensVoted);
return (
<div className="uppercase flex h-full items-center justify-center pt-2">
<div className="flex items-center justify-center h-full pt-2 uppercase">
<VoteProgress
threshold={requiredMajorityPercentage}
progress={yesPercentage}
@@ -35,7 +35,7 @@ export const BundleSigners = ({
tx,
id,
}: BundleSignersProps) => {
const tokenLink = useLinks(DApp.Token);
const tokenLink = useLinks(DApp.Governance);
const bridgeFunction: BridgeFunction =
tx?.changes?.erc20 && 'contractAddress' in tx.changes.erc20
@@ -139,7 +139,7 @@ export const ValidatorsPage = () => {
const [vegaDialog, setVegaDialog] = useState<boolean>(false);
const [tmDialog, setTmDialog] = useState<boolean>(false);
const tokenLink = useLinks(DApp.Token);
const tokenLink = useLinks(DApp.Governance);
return (
<>
+2
View File
@@ -14,6 +14,8 @@ NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
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
+1
View File
@@ -3,3 +3,4 @@ NX_VEGA_ENV=DEVNET
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
+1
View File
@@ -3,3 +3,4 @@ NX_VEGA_ENV=MAINNET
NX_VEGA_URL=https://api.vega.community/graphql
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://etherscan.io
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
+1
View File
@@ -3,3 +3,4 @@ NX_VEGA_ENV=TESTNET
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
@@ -212,7 +212,7 @@ context(
closeStakingDialog();
navigateTo(navigation.validators);
cy.get(`[row-id="${0}"]`)
.eq(1)
.first()
.within(() => {
cy.getByTestId(stakeValidatorListTotalStake)
.should('have.text', '3,002.00')
@@ -222,7 +222,7 @@ context(
.and('be.visible');
});
cy.get(`[row-id="${1}"]`)
.eq(1)
.first()
.within(() => {
cy.getByTestId(stakeValidatorListTotalStake)
.scrollIntoView()
+2
View File
@@ -22,6 +22,8 @@ NX_VEGA_REST_URL=http://localhost:3008/api/v2/
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
+2
View File
@@ -19,6 +19,8 @@ NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fa
NX_TENDERMINT_URL=https://tm.be.devnet1.vega.xyz/
NX_TENDERMINT_WEBSOCKET_URL=wss://be.devnet1.vega.xyz/websocket
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
+1
View File
@@ -16,6 +16,7 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
NX_VEGA_REST_URL=https://api.vega.community/api/v2/
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-mainnet
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
+1
View File
@@ -15,6 +15,7 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
NX_VEGA_REST_URL=https://api.mainnet-mirror.vega.rocks/api/v2/
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-mainnet
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_TENDERMINT_URL=https://be.mainnet-mirror.vega.rocks
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.rocks/websocket
+1
View File
@@ -9,6 +9,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/fairground/announcements.json
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
+1
View File
@@ -14,6 +14,7 @@ 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/
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
+1
View File
@@ -11,6 +11,7 @@ NX_VEGA_EXPLORER_URL=https://explorer.validators-testnet.vega.rocks/
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/
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
@@ -1,4 +1,4 @@
import { useMemo, useEffect, useState, useCallback } from 'react';
import { useMemo, useEffect, useState, useCallback, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { AsyncRenderer, Pagination } from '@vegaprotocol/ui-toolkit';
import { removePaginationWrapper } from '@vegaprotocol/utils';
@@ -86,12 +86,18 @@ export const EpochIndividualRewards = ({
[epochId, page, refetch, delegationsPagination, pubKey]
);
const prevEpochIdRef = useRef<number | null>(null);
useEffect(() => {
// when the epoch changes, we want to refetch the data to update the current page
if (data) {
if (prevEpochIdRef.current === null) {
prevEpochIdRef.current = epochId;
} else if (epochId !== prevEpochIdRef.current) {
// When the epoch changes, we want to refetch the data to update the current page
refetchData();
}
}, [epochId, data, refetchData]);
prevEpochIdRef.current = epochId;
}, [epochId, refetchData]);
return (
<AsyncRenderer
@@ -3,7 +3,7 @@ import { forwardRef, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { Button, Icon } from '@vegaprotocol/ui-toolkit';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { AgGrid } from '@vegaprotocol/datagrid';
import { useAppState } from '../../../../contexts/app-state/app-state-context';
import { BigNumber } from '../../../../lib/bignumber';
import {
@@ -85,17 +85,17 @@ const TopThirdCellRenderer = (
}}
className="grid grid-cols-[60px_1fr] w-full h-full py-4 px-0 text-sm text-white text-center overflow-scroll"
>
<div className="text-xs text-left px-3">
<div className="px-3 text-xs text-left">
{params?.data?.rankingDisplay}
</div>
<div className="whitespace-normal px-3">
<div className="px-3 whitespace-normal">
<div className="mb-4">
<Button
data-testid="show-all-validators"
rightIcon={
<Icon
name="arrow-right"
className="fill-current mr-2 align-text-top"
className="mr-2 align-text-top fill-current"
/>
}
className="inline-flex items-center"
@@ -103,7 +103,7 @@ const TopThirdCellRenderer = (
{t('Reveal top validators')}
</Button>
</div>
<p className="font-semibold text-white mb-0">
<p className="mb-0 font-semibold text-white">
{t(
'Validators with too great a stake share will have the staking rewards for their delegators penalised.'
)}
@@ -1,7 +1,7 @@
import { forwardRef, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router-dom';
import { AgGridLazy as AgGrid } from '@vegaprotocol/datagrid';
import { AgGrid } from '@vegaprotocol/datagrid';
import { useAppState } from '../../../../contexts/app-state/app-state-context';
import { BigNumber } from '../../../../lib/bignumber';
import {
+2
View File
@@ -15,6 +15,8 @@ NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_SENTRY_DSN=https://dummy@o999999.ingest.sentry.io/9999999
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
# Expose some env vars to cypress environment for market setup
CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
+2
View File
@@ -12,6 +12,8 @@ NX_VEGA_URL=http://localhost:3008/graphql
NX_VEGA_WALLET_URL=http://localhost:1789
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
# Expose some env vars to cypress environment for market setup
CYPRESS_ETH_WALLET_MNEMONIC=ozone access unlock valid olympic save include omit supply green clown session
@@ -104,7 +104,7 @@ describe('deposit actions', { tags: '@smoke' }, () => {
cy.visit('/#/markets/market-1');
});
it('Deposit to trade is visible', () => {
it.skip('Deposit to trade is visible', () => {
cy.getByTestId('Collateral').click();
cy.get('[row-id="asset-id"]').contains('tEURO').should('be.visible');
cy.contains('[data-testid="deposit"]', 'Deposit').should('be.visible');
@@ -1,256 +0,0 @@
import { MarketTradingModeMapping } from '@vegaprotocol/types';
import { MarketState } from '@vegaprotocol/types';
import compact from 'lodash/compact';
const accordionContent = 'accordion-content';
const blockExplorerLink = 'block-explorer-link';
const dialogClose = 'dialog-close';
const dialogContent = 'dialog-content';
const externalLink = 'external-link';
const githubLink = 'github-link';
const liquidityLink = 'view-liquidity-link';
const marketInfoBtn = 'Info';
const marketTitle = 'accordion-title';
const providerName = 'provider-name';
const row = 'key-value-table-row';
const verifiedProofs = 'verified-proofs';
describe('market info is displayed', { tags: '@smoke' }, () => {
beforeEach(() => {
cy.mockTradingPage();
});
before(() => {
cy.setOnBoardingViewed();
cy.mockTradingPage(MarketState.STATE_ACTIVE);
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
cy.getByTestId(marketInfoBtn).click();
cy.wait('@MarketInfo');
});
it('current fees displayed', () => {
// 6002-MDET-101
cy.getByTestId(marketTitle).contains('Current fees').click();
validateMarketDataRow(0, 'Maker Fee', '0.02%');
validateMarketDataRow(1, 'Infrastructure Fee', '0.05%');
validateMarketDataRow(2, 'Liquidity Fee', '1.00%');
validateMarketDataRow(3, 'Total Fees', '1.07%');
});
it('market price', () => {
// 6002-MDET-102
cy.getByTestId(marketTitle).contains('Market price').click();
validateMarketDataRow(0, 'Mark Price', '46,126.90058');
validateMarketDataRow(1, 'Best Bid Price', '44,126.90058 ');
validateMarketDataRow(2, 'Best Offer Price', '48,126.90058 ');
validateMarketDataRow(3, 'Quote Unit', 'BTC');
});
it('market volume displayed', () => {
// 6002-MDET-103
cy.getByTestId(marketTitle).contains('Market volume').click();
validateMarketDataRow(1, 'Open Interest', '-');
validateMarketDataRow(2, 'Best Bid Volume', '1');
validateMarketDataRow(3, 'Best Offer Volume', '3');
validateMarketDataRow(4, 'Best Static Bid Volume', '2');
validateMarketDataRow(5, 'Best Static Offer Volume', '4');
});
it('insurance pool displayed', () => {
// 6002-MDET-104
cy.getByTestId(marketTitle).contains('Insurance pool').click();
validateMarketDataRow(0, 'Balance', '0');
});
it('key details displayed', () => {
// 6002-MDET-201
cy.getByTestId(marketTitle).contains('Key details').click();
const rows: [string, string][] = compact([
['Name', 'BTCUSD Monthly (30 Jun 2022)'],
['Market ID', 'market-0'],
Cypress.env('NX_SUCCESSOR_MARKETS') && ['Parent Market ID', 'PARENT-A'],
Cypress.env('NX_SUCCESSOR_MARKETS') && [
'Insurance Pool Fraction',
'0.75',
],
['Trading Mode', MarketTradingModeMapping.TRADING_MODE_CONTINUOUS],
['Market Decimal Places', '5'],
['Position Decimal Places', '0'],
['Settlement Asset Decimal Places', '5'],
]);
for (const rowNumber in rows) {
const [name, value] = rows[rowNumber];
validateMarketDataRow(Number(rowNumber), name, value);
}
});
it('instrument displayed', () => {
// 6002-MDET-202
cy.getByTestId(marketTitle).contains('Instrument').click();
validateMarketDataRow(0, 'Market Name', 'BTCUSD Monthly (30 Jun 2022)');
validateMarketDataRow(1, 'Code', 'BTCUSD.MF21');
validateMarketDataRow(2, 'Product Type', 'Future');
validateMarketDataRow(3, 'Quote Name', 'BTC');
});
it('oracle displayed', () => {
// 6002-MDET-203
cy.getByTestId(marketTitle).contains('Oracle').click();
cy.getByTestId(accordionContent)
.getByTestId(providerName)
.and('contain', 'Another oracle');
cy.getByTestId(providerName).should('be.visible').click();
cy.getByTestId(dialogContent)
.eq(1)
.within(() => {
cy.getByTestId(blockExplorerLink).contains('Block explorer');
cy.getByTestId(githubLink).contains('Oracle repository');
});
cy.getByTestId(dialogClose).click();
cy.getByTestId(accordionContent)
.getByTestId(verifiedProofs)
.and('contain', '1');
});
it('settlement asset displayed', () => {
// 6002-MDET-206
cy.getByTestId(marketTitle).contains('Settlement asset').click();
cy.window().then((win) => {
cy.stub(win, 'prompt').returns('DISABLED WINDOW PROMPT');
});
validateMarketDataRow(0, 'ID', 'asset-id');
validateMarketDataRow(1, 'Type', 'ERC20');
validateMarketDataRow(2, 'Name', 'Euro');
validateMarketDataRow(3, 'Symbol', 'tEURO');
validateMarketDataRow(4, 'Decimals', '5');
validateMarketDataRow(5, 'Quantum', '1');
validateMarketDataRow(6, 'Status', 'Enabled');
validateMarketDataRow(7, 'Contract address', '0x0158…78a4');
validateMarketDataRow(8, 'Withdrawal threshold', '0.0005');
validateMarketDataRow(9, 'Lifetime limit', '1,230');
validateMarketDataRow(10, 'Infrastructure fee account balance', '0.00001');
validateMarketDataRow(11, 'Global reward pool account balance', '0.00002');
});
it('metadata displayed', () => {
// 6002-MDET-207
cy.getByTestId(marketTitle).contains('Metadata').click();
validateMarketDataRow(0, 'Formerly', '076BB86A5AA41E3E');
validateMarketDataRow(1, 'Base', 'BTC');
validateMarketDataRow(2, 'Quote', 'USD');
validateMarketDataRow(3, 'Class', 'fx/crypto');
validateMarketDataRow(4, 'Sector', 'crypto');
});
it('risk model displayed', () => {
// 6002-MDET-208
cy.getByTestId(marketTitle).contains('Risk model').click();
validateMarketDataRow(0, 'Tau', '0.0001140771161');
validateMarketDataRow(1, 'Risk Aversion Parameter', '0.01');
});
it('risk parameters displayed', () => {
// 6002-MDET-209
cy.getByTestId(marketTitle).contains('Risk parameters').click();
validateMarketDataRow(0, 'R', '0.016');
validateMarketDataRow(1, 'Sigma', '0.3');
});
it('risk factors displayed', () => {
// 6002-MDET-210
cy.getByTestId(marketTitle).contains('Risk factors').click();
validateMarketDataRow(0, 'Short', '0.008571790367285281');
validateMarketDataRow(1, 'Long', '0.008508132993273576');
});
it('price monitoring bounds displayed', () => {
// 6002-MDET-211
cy.getByTestId(marketTitle).contains('Price monitoring bounds 1').click();
cy.get('p.col-span-1').contains('99.99999% probability price bounds');
cy.get('p.col-span-1').contains('Within 43,200 seconds');
validateMarketDataRow(0, 'Highest Price', '7.97323 ');
validateMarketDataRow(1, 'Lowest Price', '6.54701 ');
});
it('liquidity monitoring parameters displayed', () => {
// 6002-MDET-212
cy.getByTestId(marketTitle)
.contains('Liquidity monitoring parameters')
.click();
validateMarketDataRow(0, 'Triggering Ratio', '0.7');
validateMarketDataRow(1, 'Time Window', '3,600');
validateMarketDataRow(2, 'Scaling Factor', '10');
});
it('liquidity displayed', () => {
// 6002-MDET-213
cy.getByTestId(marketTitle)
.contains(/Liquidity(?! m)/)
.click();
validateMarketDataRow(0, 'Target Stake', '10.00 tBTC');
validateMarketDataRow(1, 'Supplied Stake', '0.01 tBTC');
validateMarketDataRow(2, 'Market Value Proxy', '20.00 tBTC');
cy.getByTestId(liquidityLink).should(
'have.text',
'View liquidity provision table'
);
});
it('liquidity price range displayed', () => {
// 6002-MDET-214
cy.getByTestId(marketTitle).contains('Liquidity price range').click();
validateMarketDataRow(0, 'Liquidity Price Range', '2.00% of mid price');
validateMarketDataRow(1, 'Lowest Price', '45,204.362 BTC');
validateMarketDataRow(2, 'Highest Price', '47,049.438 BTC');
});
it('proposal displayed', () => {
// 6002-MDET-301
cy.getByTestId(marketTitle).contains('Proposal').click();
cy.getByTestId(accordionContent)
.find(`[data-testid="${externalLink}"]`)
.first()
.should('have.text', 'View governance proposal')
.and('have.attr', 'href')
.and('contain', '/proposals/market-0');
cy.getByTestId(accordionContent)
.find(`[data-testid="${externalLink}"]`)
.eq(1)
.should('have.text', 'Propose a change to market')
.and('have.attr', 'href')
.and('contain', '/proposals/propose/update-market');
});
afterEach('close toggle', () => {
cy.get('[data-state="open"]').then((tab) => {
if (tab) tab.find('button').trigger('click');
});
});
function validateMarketDataRow(
rowNumber: number,
name: string,
value: string
) {
cy.getByTestId(row)
.eq(rowNumber)
.within(() => {
cy.get('dt').should('contain.text', name);
cy.get('dd').should('contain.text', value);
});
}
});
@@ -24,9 +24,7 @@ describe('deal ticker order validation', { tags: '@smoke' }, () => {
beforeEach(() => {
cy.mockTradingPage();
cy.getByTestId('deal-ticket-fee-margin-required').within(() => {
cy.get('button').click();
});
cy.getByTestId('deal-ticket-fee-margin-required').click();
});
describe('limit order', () => {
@@ -111,6 +109,7 @@ describe('deal ticker order validation', { tags: '@smoke' }, () => {
'Total margin available100.01 tDAI'
);
});
cy.getByTestId('deal-ticket-fee-margin-required').click();
});
it('must have current margin allocation', () => {
@@ -120,6 +119,7 @@ describe('deal ticker order validation', { tags: '@smoke' }, () => {
'Current margin allocation'
);
});
cy.getByTestId('deal-ticket-fee-margin-required').click();
});
it('should open usage breakdown dialog when clicked on current margin allocation', () => {
@@ -128,6 +128,7 @@ describe('deal ticker order validation', { tags: '@smoke' }, () => {
});
cy.getByTestId('usage-breakdown').should('exist');
cy.getByTestId('dialog-close').click();
cy.getByTestId('deal-ticket-fee-margin-required').click();
});
});
});
@@ -9,7 +9,7 @@ import {
testOrderAmendment,
} from '../support/order-validation';
const orderSymbol = 'market.tradableInstrument.instrument.code';
const orderSymbol = 'instrument-code';
const orderSize = 'size';
const orderType = 'type';
const orderStatus = 'status';
@@ -229,10 +229,7 @@ describe('subscribe orders', { tags: '@smoke' }, () => {
status: Schema.OrderStatus.STATUS_FILLED,
});
cy.getByTestId(`order-status-${orderId}`).should('have.text', 'Filled');
cy.get('[col-id="market.tradableInstrument.instrument.code"]').contains(
'[title="Future"]',
'Futr'
);
cy.get(`[col-id="${orderSymbol}"]`).contains('[title="Future"]', 'Futr');
});
it('must see a rejected order', () => {
@@ -86,8 +86,8 @@ describe('trades', { tags: '@smoke' }, () => {
});
it('copy price to deal ticket form', () => {
cy.getByTestId('Order').click();
// 6005-THIS-007
cy.getByTestId('order-type-Limit').click();
cy.get(colIdPrice).last().should('be.visible').click();
cy.getByTestId('order-price').should('have.value', '171.16898');
});
@@ -10,10 +10,10 @@ const dialogContent = 'dialog-content';
describe('connect vega wallet', { tags: '@smoke', testIsolation: true }, () => {
beforeEach(() => {
// Using portfolio page as it requires vega wallet connection
cy.visit('/#/portfolio');
cy.mockTradingPage();
cy.mockSubscription();
cy.setOnBoardingViewed();
cy.visit('/#/portfolio');
cy.get('[data-testid="pathname-/portfolio"]').should('exist');
});
+2 -1
View File
@@ -16,13 +16,14 @@ NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
NX_STOP_ORDERS=true
NX_ICEBERG_ORDERS=true
# NX_PRODUCT_PERPETUALS
NX_METAMASK_SNAPS=false
NX_METAMASK_SNAPS=true
NX_TENDERMINT_URL=https://tm.be.testnet.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.testnet.vega.xyz/websocket
+1 -2
View File
@@ -15,8 +15,7 @@ NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
NX_VEGA_CONSOLE_URL=https://console.vega.xyz
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-mainnet/codfcglpplgmmlokgilfkpcjnmkbfiel
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-mainnet
# TAG name of the current app version - TODO: bump to the latest upon release
NX_APP_VERSION=v0.21.1-core-0.72.14
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
+2
View File
@@ -15,6 +15,8 @@ NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/annou
NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
+1
View File
@@ -16,6 +16,7 @@ NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
+1
View File
@@ -17,6 +17,7 @@ NX_VEGA_CONSOLE_URL=https://trading.validators-testnet.vega.rocks
NX_CHROME_EXTENSION_URL=https://chrome.google.com/webstore/detail/vega-wallet-fairground/nmmjkiafpmphlikhefgjbblebfgclikn
NX_MOZILLA_EXTENSION_URL=https://addons.mozilla.org/firefox/addon/vega-wallet-fairground
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
# Cosmic elevator flags
NX_SUCCESSOR_MARKETS=true
+50 -10
View File
@@ -1,18 +1,58 @@
import { DepositContainer } from '@vegaprotocol/deposits';
import { GetStarted } from '../../components/welcome-dialog';
import { t } from '@vegaprotocol/i18n';
import { Intent, TradingAnchorButton } from '@vegaprotocol/ui-toolkit';
import { GetStartedCheckList } from '../../components/welcome-dialog';
import {
useGetOnboardingStep,
useOnboardingStore,
OnboardingStep,
} from '../../components/welcome-dialog/use-get-onboarding-step';
import { Links, Routes } from '../../pages/client-router';
import classNames from 'classnames';
export const Deposit = () => {
return (
<div className="py-16 px-8 flex w-full justify-center">
<div className="lg:min-w-[700px] min-w-[300px] max-w-[700px]">
<h1 className="text-4xl xl:text-5xl uppercase font-alpha calt">
{t('Deposit')}
</h1>
<div className="mt-10">
<DepositContainer />
<GetStarted />
</div>
<div className="max-w-[600px] px-4 py-8 mx-auto lg:px-8">
<h1 className="mb-6 text-4xl uppercase xl:text-5xl font-alpha calt">
{t('Deposit')}
</h1>
<div className="flex flex-col gap-6">
<DepositContainer />
<DepositGetStarted />
</div>
</div>
);
};
const DepositGetStarted = () => {
const onboardingDismissed = useOnboardingStore((store) => store.dismissed);
const dismiss = useOnboardingStore((store) => store.dismiss);
const step = useGetOnboardingStep();
const wrapperClasses = classNames(
'flex flex-col py-4 px-6 gap-4 rounded',
'bg-vega-blue-300 dark:bg-vega-blue-700',
'border border-vega-blue-350 dark:border-vega-blue-650'
);
// Dont show unless still onboarding
if (onboardingDismissed) {
return null;
}
return (
<div className="pt-6 border-t border-default">
<div className={wrapperClasses}>
<h3 className="text-lg">{t('Get started')}</h3>
<GetStartedCheckList />
{step > OnboardingStep.ONBOARDING_DEPOSIT_STEP && (
<TradingAnchorButton
href={Links[Routes.HOME]()}
onClick={() => dismiss()}
intent={Intent.Info}
>
{t('Start trading')}
</TradingAnchorButton>
)}
</div>
</div>
);
+10 -15
View File
@@ -1,20 +1,16 @@
import { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import { marketsWithDataProvider } from '@vegaprotocol/markets';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
import { Links, Routes } from '../../pages/client-router';
import { useGlobalStore } from '../../stores';
import { useTopTradedMarkets } from '../../lib/hooks/use-top-traded-markets';
// The home pages only purpose is to redirect to the users last market,
// the top traded if they are new, or fall back to the list of markets.
// Thats why we just render a loader here
export const Home = () => {
const navigate = useNavigate();
// The default market selected in the platform behind the overlay
// should be the oldest market that is currently trading in continuous mode(i.e. not in auction).
const { data, error, loading } = useDataProvider({
dataProvider: marketsWithDataProvider,
variables: undefined,
});
const update = useGlobalStore((store) => store.update);
const { data } = useTopTradedMarkets();
const marketId = useGlobalStore((store) => store.marketId);
useEffect(() => {
@@ -32,12 +28,11 @@ export const Home = () => {
navigate(Links[Routes.MARKETS]());
}
}
}, [marketId, data, navigate, update]);
}, [marketId, data, navigate]);
return (
<AsyncRenderer data={data} loading={loading} error={error}>
{/* Render a loading and error state but we will redirect if markets are found */}
{null}
</AsyncRenderer>
<Splash>
<Loader />
</Splash>
);
};
+9 -7
View File
@@ -11,6 +11,7 @@ import { TradePanels } from './trade-panels';
import { useNavigate, useParams } from 'react-router-dom';
import { Links, Routes } from '../../pages/client-router';
import { ViewType, useSidebar } from '../../components/sidebar';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
const calculatePrice = (markPrice?: string, decimalPlaces?: number) => {
return markPrice && decimalPlaces
@@ -58,7 +59,9 @@ const TitleUpdater = ({
export const MarketPage = () => {
const { marketId } = useParams();
const navigate = useNavigate();
const { init, view, setView } = useSidebar();
const currentRouteId = useGetCurrentRouteId();
const { setViews, getView } = useSidebar();
const view = getView(currentRouteId);
const { screenSize } = useScreenDimensions();
const largeScreen = ['lg', 'xl', 'xxl', 'xxxl'].includes(screenSize);
const update = useGlobalStore((store) => store.update);
@@ -69,15 +72,14 @@ export const MarketPage = () => {
useEffect(() => {
if (data?.id && data.id !== lastMarketId) {
update({ marketId: data.id });
// make sidebar open on market id change
setView({ type: ViewType.Order });
}
}, [update, lastMarketId, data?.id]);
// make sidebar open on deal ticket by default
if (view === null) {
setView({ type: ViewType.Order });
useEffect(() => {
if (largeScreen && view === undefined) {
setViews({ type: ViewType.Order }, currentRouteId);
}
}, [update, lastMarketId, data?.id, setView, init, view]);
}, [setViews, view, currentRouteId, largeScreen]);
const tradeView = useMemo(() => {
if (largeScreen) {
@@ -56,6 +56,7 @@ const MainGrid = memo(
<Tabs storageKey="console-trade-grid-main-left">
<Tab
id="chart"
overflowHidden
name={t('Chart')}
menu={<TradingViews.candles.menu />}
>
@@ -72,7 +73,7 @@ const MainGrid = memo(
</ResizableGridPanel>
<ResizableGridPanel
minSize={200}
preferredSize={sizesMiddle[1] || 300}
preferredSize={sizesMiddle[1] || 275}
>
<TradeGridChild>
<Tabs storageKey="console-trade-grid-main-right">
@@ -180,7 +181,7 @@ const TradeGridChild = ({ children }: TradeGridChildProps) => {
{({ width, height }) => (
<div
style={{ width, height }}
className="border border-default rounded-sm"
className="border rounded-sm border-default"
>
{children}
</div>
+1 -1
View File
@@ -4,7 +4,7 @@ import type {
VegaICellRendererParams,
VegaValueFormatterParams,
} from '@vegaprotocol/datagrid';
import { AgGridLazy as AgGrid, COL_DEFS } from '@vegaprotocol/datagrid';
import { AgGrid, COL_DEFS } from '@vegaprotocol/datagrid';
import { useMemo } from 'react';
import { t } from '@vegaprotocol/i18n';
import type { ProductType } from '@vegaprotocol/types';
@@ -1,5 +1,5 @@
import type { TypedDataAgGrid } from '@vegaprotocol/datagrid';
import { AgGridLazy as AgGrid, PriceFlashCell } from '@vegaprotocol/datagrid';
import { AgGrid, PriceFlashCell } from '@vegaprotocol/datagrid';
import type { MarketMaybeWithData } from '@vegaprotocol/markets';
import { useColumnDefs } from './use-column-defs';
@@ -21,8 +21,8 @@ export const MarketsPage = () => {
updateTitle: store.updateTitle,
}));
const tokenLink = useLinks(DApp.Token);
const externalLink = tokenLink(TOKEN_NEW_MARKET_PROPOSAL);
const governanceLink = useLinks(DApp.Governance);
const externalLink = governanceLink(TOKEN_NEW_MARKET_PROPOSAL);
useEffect(() => {
updateTitle(titlefy(['Markets']));
@@ -23,6 +23,7 @@ import { ViewType, useSidebar } from '../../components/sidebar';
import { AccountsMenu } from '../../components/accounts-menu';
import { DepositsMenu } from '../../components/deposits-menu';
import { WithdrawalsMenu } from '../../components/withdrawals-menu';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
const WithdrawalsIndicator = () => {
const { ready } = useIncompleteWithdrawals();
@@ -37,7 +38,10 @@ const WithdrawalsIndicator = () => {
};
export const Portfolio = () => {
const { init, view, setView } = useSidebar();
const currentRouteId = useGetCurrentRouteId();
const { getView, setViews } = useSidebar();
const view = getView(currentRouteId);
const { updateTitle } = usePageTitleStore((store) => ({
updateTitle: store.updateTitle,
}));
@@ -48,10 +52,10 @@ export const Portfolio = () => {
// Make transfer sidebar open by default
useEffect(() => {
if (init && view === null) {
setView({ type: ViewType.Transfer });
if (view === undefined) {
setViews({ type: ViewType.Transfer }, currentRouteId);
}
}, [init, view, setView]);
}, [view, setViews, currentRouteId]);
const [sizes, handleOnLayoutChange] = usePaneLayout({ id: 'portfolio' });
const wrapperClasses = 'p-0.5 h-full max-h-full flex flex-col';
@@ -12,6 +12,7 @@ import type { DataGridSlice } from '../../stores/datagrid-store-slice';
import { createDataGridSlice } from '../../stores/datagrid-store-slice';
import { ViewType, useSidebar } from '../sidebar';
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
export const AccountsContainer = ({
pinnedAsset,
@@ -21,7 +22,8 @@ export const AccountsContainer = ({
const onMarketClick = useMarketClickHandler(true);
const { pubKey, isReadOnly } = useVegaWallet();
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
const setView = useSidebar((store) => store.setView);
const currentRouteId = useGetCurrentRouteId();
const setViews = useSidebar((store) => store.setViews);
const gridStore = useAccountStore((store) => store.gridStore);
const updateGridStore = useAccountStore((store) => store.updateGridStore);
@@ -49,13 +51,13 @@ export const AccountsContainer = ({
partyId={pubKey}
onClickAsset={onClickAsset}
onClickWithdraw={(assetId) => {
setView({ type: ViewType.Withdraw, assetId });
setViews({ type: ViewType.Withdraw, assetId }, currentRouteId);
}}
onClickDeposit={(assetId) => {
setView({ type: ViewType.Deposit, assetId });
setViews({ type: ViewType.Deposit, assetId }, currentRouteId);
}}
onClickTransfer={(assetId) => {
setView({ type: ViewType.Transfer, assetId });
setViews({ type: ViewType.Transfer, assetId }, currentRouteId);
}}
onMarketClick={onMarketClick}
isReadOnly={isReadOnly}
@@ -1,22 +1,24 @@
import { t } from '@vegaprotocol/i18n';
import { TradingButton } from '@vegaprotocol/ui-toolkit';
import { ViewType, useSidebar } from '../sidebar';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
export const AccountsMenu = () => {
const setView = useSidebar((store) => store.setView);
const currentRouteId = useGetCurrentRouteId();
const setViews = useSidebar((store) => store.setViews);
return (
<>
<TradingButton
size="extra-small"
data-testid="open-transfer"
onClick={() => setView({ type: ViewType.Transfer })}
onClick={() => setViews({ type: ViewType.Transfer }, currentRouteId)}
>
{t('Transfer')}
</TradingButton>
<TradingButton
size="extra-small"
onClick={() => setView({ type: ViewType.Deposit })}
onClick={() => setViews({ type: ViewType.Deposit }, currentRouteId)}
>
{t('Deposit')}
</TradingButton>
@@ -9,5 +9,11 @@ export const AnnouncementBanner = () => {
return null;
}
return <Banner app="console" configUrl={ANNOUNCEMENTS_CONFIG_URL} />;
return (
<Banner
app="console"
configUrl={ANNOUNCEMENTS_CONFIG_URL}
background="url('/banner-bg.jpg')"
/>
);
};
-1
View File
@@ -1,2 +1 @@
export * from './announcement-banner';
export * from './upgrade-banner';
@@ -1,84 +0,0 @@
import { useMemo, useState } from 'react';
import { gt, prerelease } from 'semver';
import {
ReleasesFeed,
useEnvironment,
useReleases,
Networks,
} from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n';
import {
CopyWithTooltip,
ExternalLink,
Intent,
NotificationBanner,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
// v0.20.12-core-0.71.4 -> v0.20.12
// we need to strip the "core" suffix in order to determine whether a release
// is a pre-release (candidate); example: v.0.21.0-beta.1-core-0.71.4
const parseTagName = (tagName: string) => tagName.replace(/-core-[\d.]+$/i, '');
type UpgradeBannerProps = {
showVersionChange: boolean;
};
export const UpgradeBanner = ({ showVersionChange }: UpgradeBannerProps) => {
const [visible, setVisible] = useState(true);
const { data } = useReleases(ReleasesFeed.FrontEnd);
const { APP_VERSION, VEGA_ENV, VEGA_NETWORKS } = useEnvironment();
const CANONICAL_URL = VEGA_NETWORKS[VEGA_ENV] || 'https://console.vega.xyz';
const newest = useMemo(() => {
if (!APP_VERSION || !data) return undefined;
const newer = data.filter((r) => gt(r.tagName, APP_VERSION));
const valid =
// filter pre-releases on mainnet
VEGA_ENV === Networks.MAINNET
? newer?.filter((r) => !prerelease(parseTagName(r.tagName)))
: newer;
return valid.sort((a, b) => (gt(a.tagName, b.tagName) ? -1 : 1))[0];
}, [APP_VERSION, VEGA_ENV, data]);
if (!visible || !newest) {
return null;
}
return (
<NotificationBanner
intent={Intent.Warning}
onClose={() => {
setVisible(false);
}}
>
<div className="uppercase mb-1">
<ExternalLink href={CANONICAL_URL}>
{t('Upgrade to the latest version of Console')}
</ExternalLink>
</div>
<div data-testid="bookmark-message">
<a
className="underline"
href={newest.htmlUrl}
rel="noreferrer nofollow noopener"
target="_blank"
>
{t("View what's changed")}
</a>{' '}
{t(' or bookmark')}{' '}
<a className="underline" href={CANONICAL_URL}>
{t('console.vega.xyz')}
</a>{' '}
<CopyWithTooltip text={CANONICAL_URL}>
<button title={t('Copy %s', CANONICAL_URL)}>
<span className="sr-only">{t('Copy %s', CANONICAL_URL)}</span>
<VegaIcon size={14} name={VegaIconNames.COPY} />
</button>
</CopyWithTooltip>{' '}
{'to always see the latest version.'}
</div>
</NotificationBanner>
);
};
-1
View File
@@ -1,2 +1 @@
export const THROTTLE_UPDATE_TIME = 500;
export const ONBOARDING_VIEWED_KEY = 'vega_onboarding_viewed';
@@ -1,14 +1,16 @@
import { t } from '@vegaprotocol/i18n';
import { TradingButton } from '@vegaprotocol/ui-toolkit';
import { ViewType, useSidebar } from '../sidebar';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
export const DepositsMenu = () => {
const setView = useSidebar((store) => store.setView);
const currentRouteId = useGetCurrentRouteId();
const setViews = useSidebar((store) => store.setViews);
return (
<TradingButton
size="extra-small"
onClick={() => setView({ type: ViewType.Deposit })}
onClick={() => setViews({ type: ViewType.Deposit }, currentRouteId)}
data-testid="deposit-button"
>
{t('Deposit')}
+1 -1
View File
@@ -53,7 +53,7 @@ export const HeaderStat = ({
<div data-testid="item-header" id={id}>
{heading}
</div>
<Tooltip description={description}>
<Tooltip description={description} underline>
<div
data-testid="item-value"
aria-labelledby={id}
@@ -4,16 +4,19 @@ import classNames from 'classnames';
import { Routes as AppRoutes } from '../../pages/client-router';
import { MarketHeader } from '../market-header';
import { LiquidityHeader } from '../liquidity-header';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
export const LayoutWithSidebar = () => {
const sidebarView = useSidebar((store) => store.view);
const currentRouteId = useGetCurrentRouteId();
const views = useSidebar((store) => store.views);
const sidebarView = views[currentRouteId] || null;
const sidebarOpen = sidebarView !== null;
const gridClasses = classNames(
'h-full relative z-0 grid',
'grid-rows-[min-content_1fr_40px]',
'lg:grid-rows-[min-content_1fr]',
'lg:grid-cols-[1fr_350px_40px]'
'lg:grid-cols-[1fr_280px_40px]',
'xxxl:grid-cols-[1fr_320px_40px]'
);
return (
@@ -29,7 +29,7 @@ export const MarketSuccessorProposalBanner = ({
?.successorConfiguration?.parentMarketId === marketId
) ?? [];
const [visible, setVisible] = useState(true);
const tokenLink = useLinks(DApp.Token);
const tokenLink = useLinks(DApp.Governance);
if (visible && successors.length) {
return (
<NotificationBanner
@@ -57,6 +57,7 @@ describe('Navbar', () => {
['/markets/all', 'Markets'],
[`/markets/${marketId}`, 'Trading'],
['/portfolio', 'Portfolio'],
[expect.stringContaining('governance'), 'Governance'],
];
const links = screen.getAllByRole('link');
@@ -88,6 +89,7 @@ describe('Navbar', () => {
['/markets/all', 'Markets'],
[`/markets/${marketId}`, 'Trading'],
['/portfolio', 'Portfolio'],
[expect.stringContaining('governance'), 'Governance'],
];
const links = menu.getAllByRole('link');
links.forEach((link, i) => {
+20 -9
View File
@@ -1,6 +1,12 @@
import type { ButtonHTMLAttributes, LiHTMLAttributes, ReactNode } from 'react';
import { useState } from 'react';
import { useEnvironment, DocsLinks, Networks } from '@vegaprotocol/environment';
import {
useEnvironment,
DocsLinks,
Networks,
DApp,
useLinks,
} from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n';
import { useGlobalStore } from '../../stores';
import { VegaWalletConnectButton } from '../vega-wallet-connect-button';
@@ -59,14 +65,14 @@ export const Navbar = ({
<VLogo className="w-4" />
</NavLink>
{/* Left section */}
<div className="lg:hidden flex items-center">{children}</div>
<div className="flex items-center lg:hidden">{children}</div>
{/* Used to show header in nav on mobile */}
<div className="hidden lg:block">
<NavbarMenu onClick={() => setMenu(null)} />
</div>
{/* Right section */}
<div className="ml-auto flex justify-end items-center gap-2">
<div className="flex items-center justify-end ml-auto gap-2">
<ProtocolUpgradeCountdown />
<NavbarMobileButton
onClick={() => {
@@ -100,7 +106,7 @@ export const Navbar = ({
onOpenChange={(open) => setMenu((x) => (open ? x : null))}
>
<D.Overlay
className="lg:hidden fixed inset-0 dark:bg-black/80 bg-black/50 z-20"
className="fixed inset-0 z-20 lg:hidden dark:bg-black/80 bg-black/50"
data-testid="navbar-menu-overlay"
/>
<D.Content
@@ -111,7 +117,7 @@ export const Navbar = ({
)}
data-testid="navbar-menu-content"
>
<div className="flex justify-end items-center h-10 p-1">
<div className="flex items-center justify-end h-10 p-1">
<NavbarMobileButton onClick={() => setMenu(null)}>
<span className="sr-only">{t('Close menu')}</span>
<VegaIcon name={VegaIconNames.CROSS} size={24} />
@@ -179,6 +185,11 @@ const NavbarMenu = ({ onClick }: { onClick: () => void }) => {
{t('Portfolio')}
</NavbarLink>
</NavbarItem>
<NavbarItem>
<NavbarLinkExternal to={useLinks(DApp.Governance)()}>
{t('Governance')}
</NavbarLinkExternal>
</NavbarItem>
<NavbarItem>
<NavbarTrigger>{t('Resources')}</NavbarTrigger>
<NavbarContent data-testid="navbar-content-resources">
@@ -336,7 +347,7 @@ const NavbarLinkExternal = ({
<NavLink
to={to}
className={classNames(
'flex lg:inline-flex gap-2 justify-between items-center relative',
'flex gap-2 lg:h-full items-center',
'px-6 py-2 lg:p-0 text-lg lg:text-sm',
'hover:text-vega-clight-100 dark:hover:text-vega-cdark-100'
)}
@@ -344,7 +355,7 @@ const NavbarLinkExternal = ({
target="_blank"
>
<span>{children}</span>
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} />
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} size={14} />
</NavLink>
</N.Link>
);
@@ -364,8 +375,8 @@ const BurgerIcon = () => (
const NavbarListDivider = () => {
return (
<div className="py-2 px-6 lg:px-0" role="separator">
<div className="h-px lg:h-full w-full lg:w-px bg-vega-clight-500 dark:bg-vega-cdark-500" />
<div className="px-6 py-2 lg:px-0" role="separator">
<div className="w-full h-px lg:h-full lg:w-px bg-vega-clight-500 dark:bg-vega-cdark-500" />
</div>
);
};
@@ -1,16 +1,18 @@
import { OrderbookManager } from '@vegaprotocol/market-depth';
import { ViewType, useSidebar } from '../sidebar';
import { useDealTicketFormValues } from '@vegaprotocol/deal-ticket';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
export const OrderbookContainer = ({ marketId }: { marketId: string }) => {
const currentRouteId = useGetCurrentRouteId();
const update = useDealTicketFormValues((state) => state.updateAll);
const setView = useSidebar((store) => store.setView);
const setViews = useSidebar((store) => store.setViews);
return (
<OrderbookManager
marketId={marketId}
onClick={(values) => {
update(marketId, values);
setView({ type: ViewType.Order });
setViews({ type: ViewType.Order }, currentRouteId);
}}
/>
);
@@ -28,14 +28,20 @@ export interface OrderContainerProps {
filter?: Filter;
}
const AUTO_SIZE_COLUMNS = ['instrument-code'];
export const OrdersContainer = ({ filter }: OrderContainerProps) => {
const { pubKey, isReadOnly } = useVegaWallet();
const onMarketClick = useMarketClickHandler(true);
const onOrderTypeClick = useMarketLiquidityClickHandler();
const { gridState, updateGridState } = useOrderListGridState(filter);
const gridStoreCallbacks = useDataGridEvents(gridState, (newState) => {
updateGridState(filter, newState);
});
const gridStoreCallbacks = useDataGridEvents(
gridState,
(newState) => {
updateGridState(filter, newState);
},
AUTO_SIZE_COLUMNS
);
if (!pubKey) {
return <Splash>{t('Please connect Vega wallet')}</Splash>;
@@ -10,6 +10,8 @@ import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { useMarketClickHandler } from '../../lib/hooks/use-market-click-handler';
const AUTO_SIZE_COLUMNS = ['marketCode'];
export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => {
const onMarketClick = useMarketClickHandler(true);
const { pubKey, pubKeys, isReadOnly } = useVegaWallet();
@@ -17,7 +19,11 @@ export const PositionsContainer = ({ allKeys }: { allKeys?: boolean }) => {
const showClosed = usePositionsStore((store) => store.showClosedMarkets);
const gridStore = usePositionsStore((store) => store.gridStore);
const updateGridStore = usePositionsStore((store) => store.updateGridStore);
const gridStoreCallbacks = useDataGridEvents(gridStore, updateGridStore);
const gridStoreCallbacks = useDataGridEvents(
gridStore,
updateGridStore,
AUTO_SIZE_COLUMNS
);
if (!pubKey) {
return (
@@ -11,6 +11,7 @@ import { MemoryRouter, Route, Routes } from 'react-router-dom';
import { VegaIconNames } from '@vegaprotocol/ui-toolkit';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { VegaWalletContext } from '@vegaprotocol/wallet';
import { Routes as AppRoutes } from '../../pages/client-router';
jest.mock('../node-health', () => ({
NodeHealthContainer: () => <span data-testid="node-health" />,
@@ -115,7 +116,11 @@ describe('SidebarContent', () => {
<VegaWalletContext.Provider value={walletContext}>
<MemoryRouter initialEntries={['/markets/ABC']}>
<Routes>
<Route path="/markets/:marketId" element={<SidebarContent />} />
<Route
path="/markets/:marketId"
id={AppRoutes.MARKET}
element={<SidebarContent />}
/>
</Routes>
</MemoryRouter>
</VegaWalletContext.Provider>
@@ -124,13 +129,17 @@ describe('SidebarContent', () => {
expect(container).toBeEmptyDOMElement();
act(() => {
useSidebar.setState({ view: { type: ViewType.Transfer } });
useSidebar.setState({
views: { [AppRoutes.MARKET]: { type: ViewType.Transfer } },
});
});
expect(screen.getByTestId('transfer')).toBeInTheDocument();
act(() => {
useSidebar.setState({ view: { type: ViewType.Deposit } });
useSidebar.setState({
views: { [AppRoutes.MARKET]: { type: ViewType.Deposit } },
});
});
expect(screen.getByTestId('deposit')).toBeInTheDocument();
@@ -141,26 +150,36 @@ describe('SidebarContent', () => {
<VegaWalletContext.Provider value={walletContext}>
<MemoryRouter initialEntries={['/portfolio']}>
<Routes>
<Route path="/portfolio" element={<SidebarContent />} />
<Route
path="/portfolio"
id={AppRoutes.PORTFOLIO}
element={<SidebarContent />}
/>
</Routes>
</MemoryRouter>
</VegaWalletContext.Provider>
);
act(() => {
useSidebar.setState({ view: { type: ViewType.Order } });
useSidebar.setState({
views: { [AppRoutes.PORTFOLIO]: { type: ViewType.Order } },
});
});
expect(container).toBeEmptyDOMElement();
act(() => {
useSidebar.setState({ view: { type: ViewType.Settings } });
useSidebar.setState({
views: { [AppRoutes.PORTFOLIO]: { type: ViewType.Settings } },
});
});
expect(screen.getByTestId('settings')).toBeInTheDocument();
act(() => {
useSidebar.setState({ view: { type: ViewType.Info } });
useSidebar.setState({
views: { [AppRoutes.PORTFOLIO]: { type: ViewType.Info } },
});
});
expect(container).toBeEmptyDOMElement();
@@ -178,6 +197,7 @@ describe('SidebarButton', () => {
tooltip="INFO"
onClick={onClick}
view={view}
routeId="current-route-id"
/>
);
+37 -32
View File
@@ -14,8 +14,9 @@ import { Settings } from '../settings';
import { Tooltip } from '../../components/tooltip';
import { WithdrawContainer } from '../withdraw-container';
import { Routes as AppRoutes } from '../../pages/client-router';
import { GetStarted } from '../welcome-dialog';
import { useVegaWallet, useViewAsDialog } from '@vegaprotocol/wallet';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
import { GetStarted } from '../welcome-dialog';
export enum ViewType {
Order = 'Order',
@@ -51,27 +52,31 @@ type SidebarView =
};
export const Sidebar = () => {
const currentRouteId = useGetCurrentRouteId();
const navClasses = 'flex lg:flex-col items-center gap-2 lg:gap-4 p-1';
const setViewAsDialogOpen = useViewAsDialog((state) => state.setOpen);
const { pubKeys } = useVegaWallet();
return (
<div className="flex lg:flex-col gap-2 h-full p-1" data-testid="sidebar">
<div className="flex h-full p-1 lg:flex-col gap-2" data-testid="sidebar">
<nav className={navClasses}>
{/* sidebar options that always show */}
<SidebarButton
view={ViewType.Deposit}
icon={VegaIconNames.DEPOSIT}
tooltip={t('Deposit')}
routeId={currentRouteId}
/>
<SidebarButton
view={ViewType.Withdraw}
icon={VegaIconNames.WITHDRAW}
tooltip={t('Withdraw')}
routeId={currentRouteId}
/>
<SidebarButton
view={ViewType.Transfer}
icon={VegaIconNames.TRANSFER}
tooltip={t('Transfer')}
routeId={currentRouteId}
/>
{/* buttons for specific routes */}
<Routes>
@@ -94,11 +99,13 @@ export const Sidebar = () => {
view={ViewType.Order}
icon={VegaIconNames.TICKET}
tooltip={t('Order')}
routeId={currentRouteId}
/>
<SidebarButton
view={ViewType.Info}
icon={VegaIconNames.BREAKDOWN}
tooltip={t('Market specification')}
routeId={currentRouteId}
/>
</>
}
@@ -114,12 +121,13 @@ export const Sidebar = () => {
icon={VegaIconNames.EYE}
tooltip={t('View as party')}
disabled={Boolean(pubKeys)}
routeId={currentRouteId}
/>
<SidebarButton
view={ViewType.Settings}
icon={VegaIconNames.COG}
tooltip={t('Settings')}
routeId={currentRouteId}
/>
<NodeHealthContainer />
</nav>
@@ -133,23 +141,25 @@ export const SidebarButton = ({
tooltip,
disabled = false,
onClick,
routeId,
}: {
view?: ViewType;
icon: VegaIconNames;
tooltip: string;
disabled?: boolean;
onClick?: () => void;
routeId: string;
}) => {
const { currView, setView } = useSidebar((store) => ({
currView: store.view,
setView: store.setView,
const { setViews, getView } = useSidebar((store) => ({
setViews: store.setViews,
getView: store.getView,
}));
const currView = getView(routeId);
const onSelect = (view: SidebarView['type']) => {
if (view === currView?.type) {
setView(null);
setViews(null, routeId);
} else {
setView({ type: view });
setViews({ type: view }, routeId);
}
};
@@ -187,7 +197,7 @@ export const SidebarButton = ({
const SidebarDivider = () => {
return (
<div
className="bg-vega-clight-600 dark:bg-vega-cdark-600 w-px h-4 lg:w-4 lg:h-px"
className="w-px h-4 bg-vega-clight-600 dark:bg-vega-cdark-600 lg:w-4 lg:h-px"
role="separator"
/>
);
@@ -195,8 +205,10 @@ const SidebarDivider = () => {
export const SidebarContent = () => {
const params = useParams();
const { view, setView } = useSidebar();
const currentRouteId = useGetCurrentRouteId();
const { setViews, getView } = useSidebar();
const view = getView(currentRouteId);
if (!view) return null;
if (view.type === ViewType.Order) {
@@ -206,7 +218,7 @@ export const SidebarContent = () => {
<DealTicketContainer
marketId={params.marketId}
onDeposit={(assetId) =>
setView({ type: ViewType.Deposit, assetId })
setViews({ type: ViewType.Deposit, assetId }, currentRouteId)
}
/>
<GetStarted />
@@ -233,7 +245,6 @@ export const SidebarContent = () => {
return (
<ContentWrapper title={t('Deposit')}>
<DepositContainer assetId={view.assetId} />
<GetStarted />
</ContentWrapper>
);
}
@@ -242,7 +253,6 @@ export const SidebarContent = () => {
return (
<ContentWrapper title={t('Withdraw')}>
<WithdrawContainer assetId={view.assetId} />
<GetStarted />
</ContentWrapper>
);
}
@@ -251,7 +261,6 @@ export const SidebarContent = () => {
return (
<ContentWrapper title={t('Transfer')}>
<TransferContainer assetId={view.assetId} />
<GetStarted />
</ContentWrapper>
);
}
@@ -276,7 +285,7 @@ const ContentWrapper = ({
}) => {
return (
<TinyScroll
className="h-full overflow-auto py-4 pl-3 pr-4"
className="h-full py-4 pl-3 pr-4 overflow-auto"
// panes have p-1, since sidebar is on the right make pl less to account for additional pane space
data-testid="sidebar-content"
>
@@ -288,25 +297,21 @@ const ContentWrapper = ({
/** If rendered will close sidebar */
const CloseSidebar = () => {
const setView = useSidebar((store) => store.setView);
const currentRouteId = useGetCurrentRouteId();
const setViews = useSidebar((store) => store.setViews);
useEffect(() => {
setView(null);
}, [setView]);
setViews(null, currentRouteId);
}, [setViews, currentRouteId]);
return null;
};
export const useSidebar = create<{
init: boolean;
view: SidebarView | null;
setView: (view: SidebarView | null) => void;
}>()((set) => ({
init: true,
view: null,
setView: (x) =>
set(() => {
if (x == null) {
return { view: null, init: false };
}
return { view: x, init: false };
}),
views: { [key: string]: SidebarView | null };
setViews: (view: SidebarView | null, routeId: string) => void;
getView: (routeId: string) => SidebarView | null | undefined;
}>()((set, get) => ({
views: {},
setViews: (x, routeId) =>
set(({ views }) => ({ views: { ...views, [routeId]: x } })),
getView: (routeId) => get().views[routeId],
}));
@@ -0,0 +1 @@
export { Telemetry } from './telemetry';
@@ -0,0 +1,69 @@
import type { Toast } from '@vegaprotocol/ui-toolkit';
import { Intent, useToasts } from '@vegaprotocol/ui-toolkit';
import { useTelemetryApproval } from '../../lib/hooks/use-telemetry-approval';
import { useCallback, useEffect } from 'react';
import { TelemetryApproval } from './telemetry-approval';
import { t } from '@vegaprotocol/i18n';
import { useOnboardingStore } from '../welcome-dialog/use-get-onboarding-step';
const TELEMETRY_APPROVAL_TOAST_ID = 'telemetry_tost_id';
export const Telemetry = () => {
const onboardingDissmissed = useOnboardingStore((store) => store.dismissed);
const [telemetryValue, setTelemetryValue, isTelemetryNeeded, closeTelemetry] =
useTelemetryApproval();
const [setToast, hasToast, removeToast] = useToasts((store) => [
store.setToast,
store.hasToast,
store.remove,
]);
const onApprovalClose = useCallback(() => {
closeTelemetry();
removeToast(TELEMETRY_APPROVAL_TOAST_ID);
}, [closeTelemetry, removeToast]);
const setTelemetryApprovalAndClose = useCallback(
(value: string) => {
setTelemetryValue(value);
onApprovalClose();
},
[onApprovalClose, setTelemetryValue]
);
useEffect(() => {
if (isTelemetryNeeded && onboardingDissmissed) {
const toast: Toast = {
id: TELEMETRY_APPROVAL_TOAST_ID,
intent: Intent.Primary,
content: (
<>
<h3 className="mb-1 text-sm uppercase">
{t('Improve vega console')}
</h3>
<TelemetryApproval
telemetryValue={telemetryValue}
setTelemetryValue={setTelemetryApprovalAndClose}
/>
</>
),
onClose: onApprovalClose,
};
if (!hasToast(TELEMETRY_APPROVAL_TOAST_ID)) {
setToast(toast);
}
return;
}
}, [
telemetryValue,
isTelemetryNeeded,
onboardingDissmissed,
setToast,
hasToast,
onApprovalClose,
setTelemetryApprovalAndClose,
]);
return null;
};
@@ -11,6 +11,10 @@ jest.mock('@vegaprotocol/wallet', () => ({
useVegaWalletDialogStore: () => mockUpdateDialogOpen,
}));
jest.mock('../../lib/hooks/use-get-current-route-id', () => ({
useGetCurrentRouteId: jest.fn().mockReturnValue('current-route-id'),
}));
beforeEach(() => {
jest.clearAllMocks();
});
@@ -22,13 +22,15 @@ import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { useCopyTimeout } from '@vegaprotocol/react-helpers';
import { ViewType, useSidebar } from '../sidebar';
import classNames from 'classnames';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
export const VegaWalletConnectButton = () => {
const [dropdownOpen, setDropdownOpen] = useState(false);
const openVegaWalletDialog = useVegaWalletDialogStore(
(store) => store.openVegaWalletDialog
);
const setView = useSidebar((store) => store.setView);
const currentRouteId = useGetCurrentRouteId();
const setViews = useSidebar((store) => store.setViews);
const {
pubKey,
pubKeys,
@@ -95,7 +97,7 @@ export const VegaWalletConnectButton = () => {
<TradingDropdownItem
data-testid="wallet-transfer"
onClick={() => {
setView({ type: ViewType.Transfer });
setViews({ type: ViewType.Transfer }, currentRouteId);
setDropdownOpen(false);
}}
>
@@ -10,6 +10,7 @@ import { useVegaWallet, type PubKey } from '@vegaprotocol/wallet';
import { useCallback, useMemo } from 'react';
import CopyToClipboard from 'react-copy-to-clipboard';
import { ViewType, useSidebar } from '../sidebar';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
export const VegaWalletMenu = ({
setMenu,
@@ -17,7 +18,8 @@ export const VegaWalletMenu = ({
setMenu: (open: 'nav' | 'wallet' | null) => void;
}) => {
const { pubKey, pubKeys, selectPubKey, disconnect } = useVegaWallet();
const setView = useSidebar((store) => store.setView);
const currentRouteId = useGetCurrentRouteId();
const setViews = useSidebar((store) => store.setViews);
const activeKey = useMemo(() => {
return pubKeys?.find((pk) => pk.publicKey === pubKey);
@@ -46,7 +48,7 @@ export const VegaWalletMenu = ({
<div className="flex flex-col gap-2 m-4">
<Button
onClick={() => {
setView({ type: ViewType.Transfer });
setViews({ type: ViewType.Transfer }, currentRouteId);
setMenu(null);
}}
>
@@ -2,7 +2,8 @@ import { MemoryRouter } from 'react-router-dom';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { VegaWalletContext } from '@vegaprotocol/wallet';
import { GetStarted } from './get-started';
import { render, screen } from '@testing-library/react';
import { render, screen, fireEvent } from '@testing-library/react';
import { useOnboardingStore } from './use-get-onboarding-step';
let mockStep = 1;
jest.mock('./use-get-onboarding-step', () => ({
@@ -44,13 +45,15 @@ describe('GetStarted', () => {
globalThis.window.vega = undefined as unknown as Vega;
});
it('renders nothing if connected', () => {
it('renders nothing if dismissed', () => {
useOnboardingStore.setState({ dismissed: true });
mockStep = 0;
const { container } = renderComponent({ pubKey: 'my-pubkey' });
expect(container).toBeEmptyDOMElement();
});
it('steps should be ticked', () => {
useOnboardingStore.setState({ dismissed: false });
const navigatorGetter: jest.SpyInstance = jest.spyOn(
window.navigator,
'userAgent',
@@ -72,7 +75,7 @@ describe('GetStarted', () => {
</MemoryRouter>
);
checkTicks(screen.getAllByRole('listitem'));
expect(screen.getByRole('button', { name: 'Deposit' })).toBeInTheDocument();
expect(screen.getByRole('link', { name: 'Deposit' })).toBeInTheDocument();
mockStep = 4;
rerender(
@@ -84,9 +87,11 @@ describe('GetStarted', () => {
);
checkTicks(screen.getAllByRole('listitem'));
expect(
screen.getByRole('button', { name: 'Ready to trade' })
screen.getByRole('link', { name: 'Ready to trade' })
).toBeInTheDocument();
fireEvent.click(screen.getByRole('link', { name: 'Ready to trade' }));
mockStep = 5;
rerender(
<MemoryRouter>
@@ -3,89 +3,113 @@ import { t } from '@vegaprotocol/i18n';
import {
ExternalLink,
Intent,
TradingAnchorButton,
TradingButton,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { Networks, useEnvironment } from '@vegaprotocol/environment';
import { useLocalStorage } from '@vegaprotocol/react-helpers';
import { useNavigate } from 'react-router-dom';
import {
OnboardingStep,
useGetOnboardingStep,
useOnboardingStore,
} from './use-get-onboarding-step';
import { Links, Routes } from '../../pages/client-router';
import { useGlobalStore } from '../../stores';
import { useSidebar, ViewType } from '../sidebar';
import * as constants from '../constants';
import { useOnboardingStore } from './welcome-dialog';
interface Props {
lead?: string;
}
const GetStartedButton = ({ step }: { step: OnboardingStep }) => {
const navigate = useNavigate();
const [, setOnboardingViewed] = useLocalStorage(
constants.ONBOARDING_VIEWED_KEY
);
const dismiss = useOnboardingStore((store) => store.dismiss);
const setDialogOpen = useOnboardingStore((store) => store.setDialogOpen);
const marketId = useGlobalStore((store) => store.marketId);
const link = marketId ? Links[Routes.MARKET](marketId) : Links[Routes.HOME]();
const openVegaWalletDialog = useVegaWalletDialogStore(
(store) => store.openVegaWalletDialog
);
const setView = useSidebar((store) => store.setView);
let buttonText = t('Get started');
let onClickHandle = () => {
openVegaWalletDialog();
const setViews = useSidebar((store) => store.setViews);
const buttonProps = {
size: 'small' as const,
'data-testid': 'get-started-button',
intent: Intent.Info,
};
if (step <= OnboardingStep.ONBOARDING_CONNECT_STEP) {
buttonText = t('Connect');
return (
<TradingButton {...buttonProps} onClick={() => openVegaWalletDialog()}>
{t('Connect')}
</TradingButton>
);
} else if (step === OnboardingStep.ONBOARDING_DEPOSIT_STEP) {
buttonText = t('Deposit');
onClickHandle = () => {
navigate(link);
setView({ type: ViewType.Deposit });
dismiss();
};
} else if (step === OnboardingStep.ONBOARDING_ORDER_STEP) {
buttonText = t('Ready to trade');
onClickHandle = () => {
navigate(link);
setView({ type: ViewType.Order });
setOnboardingViewed('true');
};
return (
<TradingAnchorButton
{...buttonProps}
href={Links[Routes.DEPOSIT]()}
onClick={() => setDialogOpen(false)}
>
{t('Deposit')}
</TradingAnchorButton>
);
} else if (step >= OnboardingStep.ONBOARDING_ORDER_STEP) {
return (
<TradingAnchorButton
{...buttonProps}
href={marketId ? Links[Routes.MARKET](marketId) : Links[Routes.HOME]()}
onClick={() => {
setViews({ type: ViewType.Order }, Routes.MARKET);
dismiss();
}}
>
{t('Ready to trade')}
</TradingAnchorButton>
);
}
return (
<TradingButton
onClick={onClickHandle}
size="small"
data-testid="get-started-button"
intent={Intent.Info}
>
{buttonText}
<TradingButton {...buttonProps} onClick={() => openVegaWalletDialog()}>
{t('Get started')}
</TradingButton>
);
};
export const GetStartedCheckList = () => {
const { pubKey } = useVegaWallet();
const currentStep = useGetOnboardingStep();
return (
<ul className="list-none">
<Step
step={1}
text={t('Connect')}
complete={Boolean(
currentStep > OnboardingStep.ONBOARDING_CONNECT_STEP || pubKey
)}
/>
<Step
step={2}
text={t('Deposit funds')}
complete={currentStep > OnboardingStep.ONBOARDING_DEPOSIT_STEP}
/>
<Step
step={3}
text={t('Open a position')}
complete={currentStep > OnboardingStep.ONBOARDING_ORDER_STEP}
/>
</ul>
);
};
export const GetStarted = ({ lead }: Props) => {
const { pubKey } = useVegaWallet();
const { VEGA_ENV, VEGA_NETWORKS } = useEnvironment();
const CANONICAL_URL = VEGA_NETWORKS[VEGA_ENV] || 'https://console.vega.xyz';
const [onBoardingViewed] = useLocalStorage(constants.ONBOARDING_VIEWED_KEY);
const currentStep = useGetOnboardingStep();
const openVegaWalletDialog = useVegaWalletDialogStore(
(store) => store.openVegaWalletDialog
);
const getStartedNeeded =
onBoardingViewed !== 'true' &&
currentStep &&
currentStep < OnboardingStep.ONBOARDING_COMPLETE_STEP;
const currentStep = useGetOnboardingStep();
const dismissed = useOnboardingStore((store) => store.dismissed);
const wrapperClasses = classNames(
'flex flex-col py-4 px-6 gap-4 rounded',
@@ -94,31 +118,13 @@ export const GetStarted = ({ lead }: Props) => {
{ 'mt-8': !lead }
);
if (getStartedNeeded) {
if (!dismissed) {
return (
<div className={wrapperClasses} data-testid="get-started-banner">
{lead && <h2>{lead}</h2>}
<h3 className="text-lg">{t('Get started')}</h3>
<div>
<ul className="list-none">
<Step
step={1}
text={t('Connect')}
complete={Boolean(
currentStep > OnboardingStep.ONBOARDING_CONNECT_STEP || pubKey
)}
/>
<Step
step={2}
text={t('Deposit funds')}
complete={currentStep > OnboardingStep.ONBOARDING_DEPOSIT_STEP}
/>
<Step
step={3}
text={t('Open a position')}
complete={currentStep > OnboardingStep.ONBOARDING_ORDER_STEP}
/>
</ul>
<GetStartedCheckList />
</div>
<div>
<GetStartedButton step={currentStep} />
@@ -126,7 +132,7 @@ export const GetStarted = ({ lead }: Props) => {
{VEGA_ENV === Networks.MAINNET && (
<p className="text-sm">
{t('Experiment for free with virtual assets on')}{' '}
<ExternalLink href={CANONICAL_URL}>
<ExternalLink href={VEGA_NETWORKS.TESTNET}>
{t('Fairground Testnet')}
</ExternalLink>
</p>
@@ -134,7 +140,7 @@ export const GetStarted = ({ lead }: Props) => {
{VEGA_ENV === Networks.TESTNET && (
<p className="text-sm">
{t('Ready to trade with real funds?')}{' '}
<ExternalLink href={CANONICAL_URL}>
<ExternalLink href={VEGA_NETWORKS.MAINNET}>
{t('Switch to Mainnet')}
</ExternalLink>
</p>
@@ -41,7 +41,7 @@ export const ProposedMarkets = () => {
proposal.terms.change.instrument.code,
}));
const tokenLink = useLinks(DApp.Token);
const tokenLink = useLinks(DApp.Governance);
return useMemo(
() => (
<div className="mt-7 pt-8 border-t border-default">
@@ -1,3 +1,5 @@
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { depositsProvider } from '@vegaprotocol/deposits';
import { useDataProvider } from '@vegaprotocol/data-provider';
@@ -7,6 +9,29 @@ import { aggregatedAccountsDataProvider } from '@vegaprotocol/accounts';
import { positionsDataProvider } from '@vegaprotocol/positions';
import { useGlobalStore } from '../../stores';
const ONBOARDING_STORAGE_KEY = 'vega_onboarding';
export const useOnboardingStore = create<{
dialogOpen: boolean;
dismissed: boolean;
dismiss: () => void;
setDialogOpen: (isOpen: boolean) => void;
}>()(
persist(
(set) => ({
dialogOpen: true,
dismissed: false,
dismiss: () => set({ dismissed: true }),
setDialogOpen: (isOpen) => set({ dialogOpen: isOpen }),
}),
{
name: ONBOARDING_STORAGE_KEY,
partialize: (state) => ({
dismissed: state.dismissed,
}),
}
)
);
export enum OnboardingStep {
ONBOARDING_UNKNOWN_STEP,
ONBOARDING_WALLET_STEP,
@@ -1,40 +1,24 @@
import { t } from '@vegaprotocol/i18n';
import { GetStarted } from './get-started';
import { TradingButton } from '@vegaprotocol/ui-toolkit';
import { useNavigate } from 'react-router-dom';
import { TradingAnchorButton } from '@vegaprotocol/ui-toolkit';
import { Links, Routes } from '../../pages/client-router';
import { Networks, useEnvironment } from '@vegaprotocol/environment';
import type { ReactNode } from 'react';
import { useOnboardingStore } from './welcome-dialog';
import { useMarketList } from '@vegaprotocol/markets';
import { isMarketActive } from '../../lib/utils';
import orderBy from 'lodash/orderBy';
import { priceChangePercentage } from '@vegaprotocol/utils';
import { useTopTradedMarkets } from '../../lib/hooks/use-top-traded-markets';
import { useOnboardingStore } from './use-get-onboarding-step';
export const WelcomeDialogContent = () => {
const { VEGA_ENV } = useEnvironment();
const dismiss = useOnboardingStore((store) => store.dismiss);
const navigate = useNavigate();
const { data } = useMarketList();
const markets = orderBy(
data?.filter((m) => isMarketActive(m.state)) || [],
[
(m) => {
if (!m.candles?.length) return 0;
return Number(priceChangePercentage(m.candles.map((c) => c.close)));
},
],
['desc']
const setOnboardingDialog = useOnboardingStore(
(store) => store.setDialogOpen
);
const explore = () => {
const marketId = markets?.[0].id ?? '';
const link = marketId
? Links[Routes.MARKET](marketId)
: Links[Routes.MARKETS]();
navigate(link);
dismiss();
};
const { data } = useTopTradedMarkets();
const marketId = data && data[0]?.id;
const link = marketId
? Links[Routes.MARKET](marketId)
: Links[Routes.MARKETS]();
const lead =
VEGA_ENV === Networks.MAINNET
? t('Start trading on the worlds most advanced decentralised exchange.')
@@ -43,7 +27,7 @@ export const WelcomeDialogContent = () => {
);
return (
<div className="flex flex-col sm:flex-row gap-8">
<div className="sm:w-1/2 flex flex-col justify-between pt-3">
<div className="flex flex-col justify-between pt-3 sm:w-1/2">
<ul className="ml-0">
<ListItemContent
icon={<NonCustodialIcon />}
@@ -65,15 +49,16 @@ export const WelcomeDialogContent = () => {
)}
/>
</ul>
<TradingButton
onClick={explore}
<TradingAnchorButton
href={link}
onClick={() => setOnboardingDialog(false)}
className="block w-full"
data-testid="browse-markets-button"
>
{t('Explore')}
</TradingButton>
</TradingAnchorButton>
</div>
<div className="sm:w-1/2 flex grow">
<div className="flex sm:w-1/2 grow">
<GetStarted lead={lead} />
</div>
</div>
@@ -90,10 +75,10 @@ const ListItemContent = ({
text: string;
}) => {
return (
<li className="my-4 flex gap-3">
<div className="shrink-0 pt-1">{icon}</div>
<li className="flex my-4 gap-3">
<div className="pt-1 shrink-0">{icon}</div>
<div>
<h3 className="text-lg leading-snug mb-2">{title}</h3>
<h3 className="mb-2 text-lg leading-snug">{title}</h3>
<p className="text-sm text-secondary">{text}</p>
</div>
</li>
@@ -1,133 +1,32 @@
import { useNavigate } from 'react-router-dom';
import type { Toast } from '@vegaprotocol/ui-toolkit';
import { Dialog, Intent, useToasts } from '@vegaprotocol/ui-toolkit';
import { Dialog, Intent } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
import { useEnvironment } from '@vegaprotocol/environment';
import { useLocalStorage } from '@vegaprotocol/react-helpers';
import { WelcomeDialogContent } from './welcome-dialog-content';
import { Links, Routes } from '../../pages/client-router';
import { useGlobalStore } from '../../stores';
import {
useGetOnboardingStep,
OnboardingStep,
} from './use-get-onboarding-step';
import * as constants from '../constants';
import { TelemetryApproval } from './telemetry-approval';
import { useTelemetryApproval } from '../../lib/hooks/use-telemetry-approval';
import { useCallback } from 'react';
import { useOnboardingStore } from './use-get-onboarding-step';
const ONBOARDING_STORAGE_KEY = 'vega_onboarding_dismiss_store';
export const useOnboardingStore = create<{
dismissed: boolean;
dismiss: () => void;
}>()(
persist(
(set) => ({
dismissed: false,
dismiss: () => set(() => ({ dismissed: true })),
}),
{
name: ONBOARDING_STORAGE_KEY,
}
)
);
const TELEMETRY_APPROVAL_TOAST_ID = 'telemetry_tost_id';
export const WelcomeDialog = () => {
const { VEGA_ENV } = useEnvironment();
const navigate = useNavigate();
const [telemetryValue, setTelemetryValue, isTelemetryNeeded, closeTelemetry] =
useTelemetryApproval();
const [onBoardingViewed] = useLocalStorage(constants.ONBOARDING_VIEWED_KEY);
const dismiss = useOnboardingStore((store) => store.dismiss);
const dismissed = useOnboardingStore((store) => store.dismissed);
const currentStep = useGetOnboardingStep();
const isTelemetryPopupNeeded =
isTelemetryNeeded &&
(onBoardingViewed === 'true' ||
currentStep > OnboardingStep.ONBOARDING_ORDER_STEP);
const dialogOpen = useOnboardingStore((store) => store.dialogOpen);
const dismiss = useOnboardingStore((store) => store.dismiss);
const isOnboardingDialogNeeded =
onBoardingViewed !== 'true' &&
currentStep &&
currentStep < OnboardingStep.ONBOARDING_COMPLETE_STEP &&
!dismissed;
const marketId = useGlobalStore((store) => store.marketId);
const onClose = () => {
if (isTelemetryPopupNeeded) {
closeTelemetry();
} else {
const link = marketId
? Links[Routes.MARKET](marketId)
: Links[Routes.HOME]();
navigate(link);
dismiss();
}
};
const [setToast, hasToast, removeToast] = useToasts((store) => [
store.setToast,
store.hasToast,
store.remove,
]);
const onApprovalClose = useCallback(() => {
closeTelemetry();
removeToast(TELEMETRY_APPROVAL_TOAST_ID);
}, [removeToast, closeTelemetry]);
const setTelemetryApprovalAndClose = useCallback(
(value: string) => {
setTelemetryValue(value);
onApprovalClose();
},
[setTelemetryValue, onApprovalClose]
);
if (isTelemetryPopupNeeded) {
const toast: Toast = {
id: TELEMETRY_APPROVAL_TOAST_ID,
intent: Intent.Primary,
content: (
<>
<h3 className="mb-1 text-sm uppercase">
{t('Improve vega console')}
</h3>
<TelemetryApproval
telemetryValue={telemetryValue}
setTelemetryValue={setTelemetryApprovalAndClose}
/>
</>
),
onClose: onApprovalClose,
};
if (!hasToast(TELEMETRY_APPROVAL_TOAST_ID)) {
setToast(toast);
}
return;
}
const title = (
<span className="font-alpha calt" data-testid="welcome-title">
{t('Console')}{' '}
<span className="text-vega-clight-100 dark:text-vega-cdark-100">
{VEGA_ENV}
</span>
</span>
);
return isOnboardingDialogNeeded ? (
return (
<Dialog
open
title={title}
open={dismissed ? false : dialogOpen}
title={
<span className="font-alpha calt" data-testid="welcome-title">
{t('Console')}{' '}
<span className="text-vega-clight-100 dark:text-vega-cdark-100">
{VEGA_ENV}
</span>
</span>
}
size="medium"
onChange={onClose}
onChange={() => dismiss()}
intent={Intent.None}
dataTestId="welcome-dialog"
>
<WelcomeDialogContent />
</Dialog>
) : null;
);
};
@@ -1,14 +1,15 @@
import { t } from '@vegaprotocol/i18n';
import { TradingButton } from '@vegaprotocol/ui-toolkit';
import { ViewType, useSidebar } from '../sidebar';
import { useGetCurrentRouteId } from '../../lib/hooks/use-get-current-route-id';
export const WithdrawalsMenu = () => {
const setView = useSidebar((store) => store.setView);
const setViews = useSidebar((store) => store.setViews);
const currentRouteId = useGetCurrentRouteId();
return (
<TradingButton
size="extra-small"
onClick={() => setView({ type: ViewType.Withdraw })}
onClick={() => setViews({ type: ViewType.Withdraw }, currentRouteId)}
data-testid="withdraw-dialog-button"
>
{t('Make withdrawal')}
@@ -0,0 +1,15 @@
import { routerConfig } from '../../pages/client-router';
import { matchRoutes, useLocation } from 'react-router-dom';
export const useGetCurrentRouteId = () => {
const location = useLocation();
const currentRoute = matchRoutes(routerConfig, location);
const lastRoute = currentRoute?.pop();
if (lastRoute) {
const {
route: { id },
} = lastRoute;
return id || '';
}
return '';
};
@@ -0,0 +1,13 @@
import orderBy from 'lodash/orderBy';
import { calcTradedFactor, useMarketList } from '@vegaprotocol/markets';
import { isMarketActive } from '../utils';
export const useTopTradedMarkets = () => {
const { data, loading, error } = useMarketList();
const activeMarkets = data?.filter((m) => isMarketActive(m.state));
const marketsByTopTraded = data
? orderBy(activeMarkets, (m) => calcTradedFactor(m), 'desc')
: undefined;
return { data: marketsByTopTraded, loading, error };
};
+3 -2
View File
@@ -38,7 +38,7 @@ import { AppLoader, DynamicLoader } from '../components/app-loader';
import { useDataProvider } from '@vegaprotocol/data-provider';
import { activeOrdersProvider } from '@vegaprotocol/orders';
import { useTelemetryApproval } from '../lib/hooks/use-telemetry-approval';
import { AnnouncementBanner, UpgradeBanner } from '../components/banner';
import { AnnouncementBanner } from '../components/banner';
import { Navbar } from '../components/navbar';
import classNames from 'classnames';
import {
@@ -49,6 +49,7 @@ import {
import { ViewingBanner } from '../components/viewing-banner';
import { NavHeader } from '../components/navbar/nav-header';
import { Routes as AppRoutes } from './client-router';
import { Telemetry } from '../components/telemetry';
const DEFAULT_TITLE = t('Welcome to Vega trading!');
@@ -114,7 +115,6 @@ function AppBody({ Component }: AppProps) {
/>
<ProtocolUpgradeInProgressNotification />
<ViewingBanner />
<UpgradeBanner showVersionChange={true} />
</div>
<div data-testid={`pathname-${location.pathname}`}>
<Component />
@@ -125,6 +125,7 @@ function AppBody({ Component }: AppProps) {
<InitializeHandlers />
<MaybeConnectEagerly />
<PartyData />
<Telemetry />
</div>
);
}
+8 -17
View File
@@ -4,33 +4,24 @@ export default function Document() {
return (
<>
<Head>
{/*
{/*
meta tags
- next advised against using _document for this, so they exist in our
- next advised against using _document for this, so they exist in our
- single page index.page.tsx
*/}
{/* icons */}
<link
rel="icon"
type="image/x-icon"
href="https://static.vega.xyz/favicon.ico"
/>
<link
rel="apple-touch-icon"
content="https://static.vega.xyz/favicon.ico"
/>
{/* fonts */}
{/* preload fonts */}
<link
rel="preload"
href="https://static.vega.xyz/AlphaLyrae-Medium.woff2"
href="/AlphaLyrae-Medium.woff2"
as="font"
type="font/woff2"
/>
{/* styles */}
<link rel="stylesheet" href="https://static.vega.xyz/fonts.css" />
{/* icons */}
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<link rel="apple-touch-icon" content="/favicon.ico" />
{/* eslint-disable-next-line @next/next/no-css-tags */}
<link rel="stylesheet" href="/preloader.css" media="all" />
+6 -1
View File
@@ -59,7 +59,7 @@ export const Links: ConsoleLinks = {
[Routes.DEPOSIT]: () => Routes.DEPOSIT,
};
const routerConfig: RouteObject[] = [
export const routerConfig: RouteObject[] = [
{
path: '/*',
element: <LayoutWithSidebar />,
@@ -68,6 +68,7 @@ const routerConfig: RouteObject[] = [
{
index: true,
element: <LazyHome />,
id: Routes.HOME,
},
{
path: 'markets',
@@ -76,16 +77,19 @@ const routerConfig: RouteObject[] = [
{
path: 'all',
element: <LazyMarkets />,
id: Routes.MARKETS,
},
{
path: ':marketId',
element: <LazyMarket />,
id: Routes.MARKET,
},
],
},
{
path: 'portfolio',
element: <LazyPortfolio />,
id: Routes.PORTFOLIO,
},
{
path: 'liquidity',
@@ -94,6 +98,7 @@ const routerConfig: RouteObject[] = [
{
path: ':marketId',
element: <LazyLiquidity />,
id: Routes.LIQUIDITY,
},
],
},
+3 -9
View File
@@ -19,17 +19,11 @@ export default function Index() {
<meta name="og:url" content="https://console.vega.xyz/" />
<meta name="og:title" content="Vega Protocol - Console" />
<meta name="og:site_name" content="Vega Protocol - Console" />
<meta name="og:image" content="https://static.vega.xyz/favicon.ico" />
<meta
name="twitter:card"
content="https://static.vega.xyz/favicon.ico"
/>
<meta name="og:image" content="./favicon.ico" />
<meta name="twitter:card" content="./favicon.ico" />
<meta name="twitter:title" content="Vega Protocol - Console" />
<meta name="twitter:description" content="Vega Protocol - Console" />
<meta
name="twitter:image"
content="https://static.vega.xyz/favicon.ico"
/>
<meta name="twitter:image" content="./favicon.ico" />
<meta name="twitter:image:alt" content="VEGA logo" />
<meta name="twitter:site" content="@vegaprotocol" />
</Head>
+26 -11
View File
@@ -1,6 +1,13 @@
@import 'ag-grid-community/styles/ag-grid.css';
@import 'ag-grid-community/styles/ag-theme-balham.css';
/** Load AlphaLyrae font */
@font-face {
font-family: AlphaLyrae;
src: url('/AlphaLyrae-Medium.woff2') format('woff2'),
url('/AlphaLyrae-Medium.woff') format('woff');
}
@tailwind base;
@tailwind components;
@tailwind utilities;
@@ -83,8 +90,7 @@ html [data-theme='light'] {
--pennant-color-volume-sell: theme(colors.market.red.DEFAULT);
/* reduce space between candles */
--pennant-candlestick-inner-padding: 0.175;
--pennant-candlestick-stroke-width: 0.5;
--pennant-candlestick-inner-padding: 0.25;
}
html [data-theme='light'] {
@@ -104,8 +110,8 @@ html [data-theme='light'] {
--pennant-color-depth-sell-fill: theme(colors.market.red.DEFAULT);
--pennant-color-depth-sell-stroke: theme(colors.market.red.650);
--pennant-color-volume-buy: theme(colors.market.green.300);
--pennant-color-volume-sell: theme(colors.market.red.300);
--pennant-color-volume-buy: theme(colors.market.green.DEFAULT);
--pennant-color-volume-sell: theme(colors.market.red.DEFAULT);
}
html [data-theme='dark'] {
@@ -126,7 +132,7 @@ html [data-theme='dark'] {
--pennant-color-depth-sell-stroke: theme(colors.market.red.DEFAULT);
--pennant-color-volume-buy: theme(colors.market.green.600);
--pennant-color-volume-sell: theme(colors.market.red.650);
--pennant-color-volume-sell: theme(colors.market.red.DEFAULT);
}
/**
@@ -162,11 +168,22 @@ html [data-theme='dark'] {
@apply font-normal font-alpha;
}
/* Light variables */
.ag-theme-balham {
.ag-theme-balham,
.ag-theme-balham-dark {
--ag-grid-size: 2px; /* Used for compactness */
--ag-row-height: 36px;
--ag-header-height: 36px;
--ag-header-height: 28px;
}
@media (min-width: theme(screens.xxl)) {
.ag-theme-balham,
.ag-theme-balham-dark {
--ag-header-height: 36px;
}
}
/* Light variables */
.ag-theme-balham {
--ag-background-color: theme(colors.white);
--ag-border-color: theme(colors.vega.clight.600);
--ag-header-background-color: theme(colors.vega.clight.700);
@@ -179,9 +196,6 @@ html [data-theme='dark'] {
/* Dark variables */
.ag-theme-balham-dark {
--ag-grid-size: 2px; /* Used for compactness */
--ag-row-height: 36px;
--ag-header-height: 36px;
--ag-background-color: theme(colors.vega.cdark.900);
--ag-border-color: theme(colors.vega.cdark.600);
--ag-header-background-color: theme(colors.vega.cdark.700);
@@ -191,6 +205,7 @@ html [data-theme='dark'] {
--ag-row-hover-color: theme(colors.vega.cdark.800);
--ag-modal-overlay-background-color: rgb(9 11 16 / 50%);
}
.ag-theme-balham-dark .ag-row.no-hover,
.ag-theme-balham-dark .ag-row.no-hover:hover,
.ag-theme-balham .ag-row.no-hover,
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

+1
View File
@@ -20,6 +20,7 @@ RUN sh docker/docker-build.sh
FROM --platform=amd64 nginx:1.23-alpine@sha256:6318314189b40e73145a48060bff4783a116c34cc7241532d0d94198fb2c9629
# configuration of system
EXPOSE 80
COPY docker/run-ipfs.sh /run-ipfs.sh
# Copy dist
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
RUN rm -rf /usr/share/nginx/html/*
+1
View File
@@ -1,5 +1,6 @@
FROM --platform=amd64 nginx:1.23-alpine@sha256:6318314189b40e73145a48060bff4783a116c34cc7241532d0d94198fb2c9629
EXPOSE 80
COPY docker/run-ipfs.sh /run-ipfs.sh
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
RUN rm -rf /usr/share/nginx/html/*
COPY ./dist-result/ /usr/share/nginx/html/

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