Compare commits

...
Author SHA1 Message Date
Matthew Russell 917c452116 refactor: use zustand for theme store 2022-09-28 15:54:14 -07:00
Matthew Russell 166c9b6fb9 fix: hydration error due to theme switcher 2022-09-28 15:53:22 -07:00
Bartłomiej GłowniaandRado 8dd63d7cac chore: fix mocks and hydration error (#1520)
* chore: fix DealTicket mock

* chore: fix React Hydration Error

* test: change tag

Co-authored-by: Rado <szpiechrados@gmail.com>
2022-09-28 14:40:21 -07:00
Matthew Russell 8bffc05be2 fix: ensure sub is cancelled if dialog is closed (#1472)
* fix: ensure sub is cancelled if dialog is closed

* fix: pass transaction object in use proposal hooks
2022-09-28 12:34:49 -07:00
Matthew Russell 26e3596c5a fix: align market dropdown cells for both my markets and all markets (#1492) 2022-09-28 12:15:09 -07:00
mattrussell36 6ad68f87cc chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-28 18:08:30 +00:00
Radosław Szpiech 86fdd75d6c fix: disabled test (#1525) 2022-09-28 18:56:45 +02:00
Dexter Edwards f688b28b29 fix: vote not seen being incorrectly reported (#1508) 2022-09-28 14:55:25 +01:00
Radosław Szpiech 6ddceaf6bd chore: update vega binaries to v0.57.0 (#1514) 2022-09-28 15:31:35 +02:00
AndyWhiteVega a9e8b6915e Test/using chrome headless (#1516)
* test: change night run to use headless chrome to address memory issues

* test: update manual for non-smoke

* test: remove headless flag since depreciated

* test: update browser for cypress
2022-09-28 14:26:22 +01:00
Dexter Edwards 9318dab698 Chore/support update asset (#1473)
* chore: generate types

* chore: add update asset type

* feat: display asset change proposals in list

* chore: generate types
2022-09-28 13:46:41 +01:00
mattrussell36 ae0424e21a chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-28 12:06:11 +00:00
mattrussell36 5e484dfab0 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-28 06:26:05 +00:00
mattrussell36 e5b1390302 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-28 00:16:31 +00:00
m.ray 6a6779ee72 feat: 1506 add risk parameters (#1510)
* feat: #1506 add risk parameters

* fix: integration test

* fix: integration test
2022-09-27 23:49:34 +01:00
Bartłomiej Głownia 414b8ced13 chore: fix positions data provider restarts (#1509) 2022-09-27 15:02:48 -07:00
Bartłomiej Głownia e310f04034 chore: set default fetchPolicy, handle subscription errors like query errors, timeout unsubscribe (#1482)
* chore: set default fetchPolicy, handle subscription errors like query errors,add unsubscribe timeout

* chore: improve no data handling in fills, ordes and trades

* chore: make reset delay optional, fix pagination and useOrderListData spec
2022-09-27 11:48:53 -07:00
mattrussell36 adf6059701 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-27 18:07:13 +00:00
m.ray 5dda58334e fix: 1425 add link on select market table row (#1493)
* fix: #1425 add link on select market table row

* fix: #1425 use only on select

* fix: #1425 revert withdraw manager spec
2022-09-27 14:03:58 +01:00
Dexter Edwards 3b03b16938 Chore/vote progress color (#1504)
* chore: fix vote progress color

* chore: sort out double full stops
2022-09-27 14:00:11 +01:00
Dexter Edwards 0d8c052ec6 fix: hide enacted on proposal details page for freeform proposals (#1503) 2022-09-27 13:59:09 +01:00
mattrussell36 9836f29e15 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-27 12:04:37 +00:00
AndyWhiteVega 4d69dceaa7 Test/faucet fake assets into vegawallet - then check displayed correctly in TFE (#1485)
* test: initial

* test: update

* test: lint

* test: faucet asset checks

* test: lint

* test: tweaks

* test: tweaks

* test: lint

* test: tweaks

* test: lint

* test: re-arrange into views

* test: lint
2022-09-27 11:22:44 +01:00
Radosław Szpiech 6af189150b test: vega in vegacapsule version changed to 0.56.0 (#1499) 2022-09-27 12:10:39 +02:00
Elmar 6f20c9125d fix(explorer): theme dark nav (#1498) 2022-09-27 10:24:42 +01:00
Dexter Edwards 7c6b14f73a fix: full reload when moving to propose child routes (#1496)
* fix: full reload when moving to propose child routes

* chore: replace outlet
2022-09-27 10:06:31 +01:00
mattrussell36 0fa1f47ad5 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-27 06:21:37 +00:00
Matthew Russell c4468d507b fix: classname mismatch warning by setting dark class for nav (#1465)
* fix: classname mismatch warning, tidy unnecessary classes to accomodate dark nav

* chore: lint

* fix: lp test console error and fix

* fix: remove fixed bg from console-lite theme switcher
2022-09-26 23:18:41 -07:00
191e73335e chore: fixes for 0.56 release (#1487)
* chore: use new GQL candle fields

* Revert "chore: downgrade to 0.55 (#1406)"

This reverts commit cc7a4f2ddd.

* chore: update queries to be compatible with 0.56

* fix: update positions data provider to use only marketId field, omit new position insertion for now

* fix: regen types after merging candles query update

* chore: remove unused generated files

* chore: check for null markets connection

* fix: import errors

* chore: export types from market-list, disable unrelated failing tests

Co-authored-by: johnwalley <john@walley.org.uk>
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2022-09-26 17:40:08 -07:00
mattrussell36 dae8949b46 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-27 00:17:06 +00:00
Matthew Russell 3aca9207ed fix: network params query name clash which was blocking type generation (#1490) 2022-09-26 15:04:40 -07:00
mattrussell36 69db3fdecb chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-26 18:04:40 +00:00
Dexter Edwardsandcandida-d d9a747102d Feat/1076 proposal not found (#1432)
* feat: add not found page

* test: add tests for not found

* Update apps/token/src/i18n/translations/dev.json

Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>

* test: fix test for new updated copy

Co-authored-by: candida-d <62548908+candida-d@users.noreply.github.com>
2022-09-26 14:35:53 +01:00
Bartłomiej Głownia 3f6bd066f1 Feat/asset balance decimals fix (#1474)
* feat: positions tab asset balance decimals

* feat: positions tab asset balance decimals
2022-09-26 14:33:01 +01:00
Joe TsangandRado 195e234f16 Chore/separate cypress install in workflow (#1481)
* chore: add step that makes sure that Cypress bins are installed correctly

* chore: missing working directory

* chore: update remaining flows

Co-authored-by: Rado <szpiechrados@gmail.com>
2022-09-26 14:56:53 +02:00
mattrussell36 b505a0598d chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-26 12:05:44 +00:00
Joe Tsang f87fd676f6 chore: revert hosted runner (#1480) 2022-09-26 13:42:43 +02:00
Joe Tsang b885696659 Chore/use self hosted runners (#1475)
* chore: edit manual flow

* chore: install yarn in flow

* chore: change runner for remaining flows

* chore: add yarn install to other flows
2022-09-26 12:15:05 +01:00
Radosław Szpiech 5d553271a5 test: fixed public key 2 issue in trading test (#1477) 2022-09-26 13:07:11 +02:00
botond 87f7efd960 Chore/migrate to new types (#1439)
* fix: candle type paths

* chore: migrate deal-ticket

* chore: migrate deposits

* fix: format

* chore: migrate environment

* fix: format

* chore: migrate fills

* fix: format

* chore: fix build errors

* fix: format

* fix: lint

* fix: env tests

* fix: add missing query variable

* fix: format

* fix: change vega_url because n11 is down

* fix: deal ticket query name

* chore: extend event type

* fix: incorrect e2e test
2022-09-26 11:35:45 +01:00
Elmar d9e3b9de99 Feat/1334 replace json (#1459)
* feat(explorer): add panel component

* feat(explorer): add info panel component

* feat(explorer): change layout styles

* feat(explorer): render json data in component for parties

* feat(explorer): change testnet env

* feat(explorer): change eslint json

* feat(explorer): render staking json in info panel component

* fix(explorer): pr comments
2022-09-26 10:10:33 +01:00
macqbatandmaciek b5e2513d53 chore: [console-lite] - portfolio - use more advanced react router (#1467)
* chore: [console-lite] - portfolio use mora advanced react router

* chore: [console-lite] - portfolio - fix container dimms

Co-authored-by: maciek <maciek@vegaprotocol.io>
2022-09-26 09:59:52 +02:00
mattrussell36 ba27f9e738 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-26 06:26:10 +00:00
mattrussell36 22787bd4c4 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-26 00:10:51 +00:00
mattrussell36 c5eeead356 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-25 18:04:17 +00:00
mattrussell36 612b906cb4 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-25 12:04:32 +00:00
mattrussell36 94a2de859f chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-25 06:06:21 +00:00
mattrussell36 f287dced18 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-25 00:12:57 +00:00
mattrussell36 3beb43a719 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-24 18:04:13 +00:00
mattrussell36 da807c883d chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-24 12:05:10 +00:00
mattrussell36 5a842c9be9 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-24 00:11:49 +00:00
mattrussell36 3bec65ac67 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-23 18:04:47 +00:00
Radosław Szpiech f124275ce5 chore: remove unnecessary if (#1468) 2022-09-23 16:49:38 +02:00
Art d271f28b82 feat: page title (660) (#1437)
* feat: page title (660)

* fix: trading-e2e home tests
2022-09-23 16:29:35 +02:00
Radosław Szpiech 483cf05050 fix: need to yarn install before nx usage (#1466) 2022-09-23 16:23:54 +02:00
Radosław Szpiechandasiaznik a452a6e831 Chore/use cache in GitHub jobs (#1461)
* chore: use cache v3

* chore: just cache whole node modules

* chore: download binaries instead of building them

* chore: missing directory flag

* chore: remove directory

* chore: aaah gobin

* chore: apply all improvements to other workflows

* chore: cache cypress

* fix: added mock for one failing test, removed console.log

* fix: removed increased timeout - not needed

* chore: change name back

Co-authored-by: asiaznik <artur@vegaprotocol.io>
2022-09-23 15:56:47 +02:00
ArtandMatthew Russell ebf2bfc7a9 feat: added asset details dialog to market select (1226) (#1260)
* feat: added asset details dialog to market select (1226)

* Update libs/ui-toolkit/src/components/dialog/dialog.tsx

Co-authored-by: Matthew Russell <mattrussell36@gmail.com>

* removed focus complexity from popover, refactored

* chore: after rebase fixes

* fix: fixed console-lite asset details dialog func - after rebase

* fix: added mock for one failing test, removed console.log

* fix: removed increased timeout - not needed

Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2022-09-23 15:14:52 +02:00
mattrussell36 d60cf3e5e6 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-23 12:05:44 +00:00
Radosław Szpiech 2650329a31 chore: update trading testnet config (#1415) 2022-09-23 12:36:29 +02:00
4ef8218267 Feat/800 better proposal ux round 1 (#1223)
* Feat/800: Configured routes for different proposal types

* Feat/800: Refactored propose.tsx to be a hub for the new proposal routes

* Feat/800: Link style tweak for proposals guide

* Feat/927: Hydrating the new proposal forms

* chore: fix typings for shared components

* Feat/927: Proposal forms built with reusable components

* Feat/800: Updated network params, added new method to get param keys as well as values, updated generated types

* Feat/800: Updated and built more reusable proposal form components

* Feat/800: Removed old catchall file of reusable proposal form components

* Feat/800: Added utils for vote deadline and enactment timestamps

* Feat/800: Readded necessary 'color-scheme-dark' class for dark-theme date and datetime inputs

* Feat/800: Tweak to icon positioning on the dialog component

* Feat/800: Regenerated types for network params

* Feat/800: Added iso8601-duration package for working with API vote deadline and enactment data

* Feat/800: Reworked the proposal forms

* Feat/800: Couple of translation additions

* Feat/800: Another translation addition

* Feat/800: Raw proposal test (tests as per old proposal form test)

* Feat/800: Some basic proposal form tests

* Feat/800: Fixing small types error in test

* Feat/800: Updating simple proposal form tests

* Feat/800: Set up env-specific proposal docs links

* Feat/800: Deadlines to the bottom of proposal forms

* Feat/800: Another type error from API changes fixed

* Feat/800: Added the spam protection min tokens network param to proposal forms requests, and the min requirements now displays the larger value of spam protection or min proposer balance

* Feat/800: Network param value change now a textarea

* Feat/800: Improved way to pass docs url

* Feat/800: Added useful explorer links to proposal forms

* Feat/800: Show current value of selected network param in proposal form

* Feat/800: Removed wallet-confirmation buffer, suspect it is not necessary

* Feat/800: Condense vote and enactment ui into single component for simpler state management, memoised some stuff

* Feat/800: Set a default select option for the market selector

* Feat/800: For network params that aren't JSON, display the network param current value in a readonly text input rather than the syntax highlighter

* Feat/800: Corrected network param form network params

* Feat/800: Timestamp functions for closing, enactment and validation, with tests

* Feat/800: More translations

* Feat/800: Added validation options to proposal-form-vote-and-enactment-deadline.tsx, generally improved the component and added tests

* Feat/800: Improved workings of proposal-form-min-requirements.tsx and wrote tests

* Feat/800: Tests for the other reusable form components

* Feat/800: Improved tests for the proposal forms

* Feat/800: Corrected mistake in get-enactment-timestamp.ts

* Feat/800: Fixed type issues that were preventing spotting an error

* Feat/800: Added some extra docs links

* Feat/800: Using renamed Dialog passed in from useProposalSubmit

* refactor: network params to return an object

* fix: update net param form, remove old net params obj

* fix: check for params before rendering

* Feat/800: Rename and simplify isJson based off PR comment

* Feat/800: Small tweaks to timestamp helpers based on PR comments

* Feat/800: Removed proposal-docs-link.tsx

* Feat/800: Used bignumber for min-requirements calculation

* Feat/800: Update tests to work with merged network params branch

* Feat/800: Removed unnecessary translations splitting

* Feat/800: Removed unwanted test

* Feat/800: Removed unwanted tests

* Feat/800: Consistent arrow functions

* Feat/800: Sorted links

* Feat/800: Removed unnecessary typecasting

* Feat/800: Refactored routing

* Feat/800: Refactored mocking of proposal forms to use MockedProvider

* Feat/800: Correct response from the raw proposal submission test

* Feat/800: Removed console.logs added for debugging

* Feat/800: Result of running 'nx format:write'

* Feat/800: Cleaning up lint warnings

* Update apps/token/.env.stagnet3

Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com>

* Feat/800: Added extra test for docs link in the proposal-form-terms component

* Feat/800: Removed stray console.log

* Feat/800: Added basic render test for proposal-form-terms and cleaned up a bit

* Feat/800: Added tests for the correct form components for the different forms

* Feat/800: Split up the proposal-form-vote-and-enactment-deadline components inside the file to make things a bit more readable

* Feat/800: router config webpack chunk name tweak

* Feat/800: Lint issue fixed

* Feat/800: Fixed timing issue with get-[deadline]-timestamp tests

* Feat/800: Setting a system time in proposal-form-vote-and-enactment-deadline.spec.tsx that doesn't get affected by British Summer Time

* Feat/800: Skipping a cypress test as the newProposalButton no longer takes a user directly to a proposal form. Leaving it in the codebase as the test is very likely to be updated.

* Feat/800: Adding comment on why I've skipped a cypress test

Co-authored-by: Dexter <dexter@vega.xyz>
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
Co-authored-by: Dexter Edwards <dexter.edwards93@gmail.com>
2022-09-23 11:10:13 +01:00
m.ray e3254564ae fix: view liquidity provision anchor (#1443)
* fix: view liquidity provision anchor

* fix: remove router push and use external links in tooltips

* fix:  remove unused push router

* fix:  remove unused push router
2022-09-23 09:18:59 +01:00
Bartłomiej Głownia 7effa0791c chore: add example of gql subscription mock usage (#1440) 2022-09-23 09:20:22 +02:00
mattrussell36 93108c5b48 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-23 06:20:36 +00:00
macqbatandmaciek 06a2fc4d12 fix: [console-lite] - empty portfolio views (#1433)
* fix: [console-lite] - empty protfolio views

* fix: [console-lite] - empty portfolio views - fix linters

Co-authored-by: maciek <maciek@vegaprotocol.io>
2022-09-23 07:51:18 +02:00
mattrussell36 c274a4694a chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-23 00:10:49 +00:00
352 changed files with 7858 additions and 4522 deletions
@@ -24,10 +24,10 @@ on:
jobs:
manual:
name: Run capsule tests -- manual trigger
runs-on: ubuntu-latest
runs-on: self-hosted
env:
GO111MODULE: 'on'
GOPROXY: ${{ secrets.GO_PROXY }}
VEGA_VERSION: 'v0.57.0'
steps:
#######
## Setup langs
@@ -43,6 +43,12 @@ jobs:
with:
node-version: 16
#######
## Install Yarn
#######
- name: Setup yarn
run: npm install -g yarn
#######
## Checkout repos
#######
@@ -70,18 +76,18 @@ jobs:
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
path: './capsule'
# Checkout vega
- name: Checkout Vega
uses: actions/checkout@v2
# Restore node_modules from cache if possible
- name: Restore node_modules from cache
uses: actions/cache@v3
with:
repository: vegaprotocol/vega
ref: v0.54.0
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
path: './vega'
path: |
frontend-monorepo/node_modules
/home/runner/.cache/Cypress
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
# Install frontend dependencies
- name: Install root dependencies
run: yarn install
run: yarn install --frozen-lockfile
working-directory: frontend-monorepo
#######
@@ -97,17 +103,20 @@ jobs:
- name: Install Vega binaries
if: ${{ env.RUN_CAPSULE }}
run: go install -v ./cmd/vega
working-directory: vega
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vega-linux-amd64.zip'
unzip vega-linux-amd64.zip -d ${{ env.GOBIN }}
- name: Install date-node binaries
if: ${{ env.RUN_CAPSULE }}
run: go install ./cmd/data-node
working-directory: vega
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/data-node-linux-amd64.zip'
unzip data-node-linux-amd64.zip -d ${{ env.GOBIN }}
- name: Install Vega wallet binaries
run: go install ./cmd/vegawallet
working-directory: vega
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vegawallet-linux-amd64.zip'
unzip vegawallet-linux-amd64.zip -d ${{ env.GOBIN }}
######
## Start capsule
@@ -149,20 +158,21 @@ jobs:
run: vegawallet service run --network fairground --automatic-consent --home ~/.vegacapsule/testnet/wallet &
- name: Start service using capsule network
if: ${{ env.RUN_CAPSULE==true }}
if: ${{ env.RUN_CAPSULE }}
run: vegawallet service run --network DV --automatic-consent --home ~/.vegacapsule/testnet/wallet &
######
## Run some tests
######
- name: Install root dependencies
run: yarn install
# To make sure that all Cypress binaries are installed properly
- name: Install cypress bins
run: yarn cypress install
working-directory: frontend-monorepo
- name: Run smoke Cypress tests
if: ${{ github.event.inputs.runAlltests == 'true' }}
run: yarn nx run ${{ github.event.inputs.project }}:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --env.grepTags='@smoke'
run: yarn nx run ${{ github.event.inputs.project }}:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --env.grepTags='@smoke' --browser chrome
working-directory: frontend-monorepo
env:
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
@@ -172,7 +182,7 @@ jobs:
- name: Run Cypress tests
if: ${{ github.event.inputs.runAlltests == 'false' }}
run: yarn nx run ${{ github.event.inputs.project }}:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }}
run: yarn nx run ${{ github.event.inputs.project }}:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome
working-directory: frontend-monorepo
env:
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
@@ -185,11 +195,11 @@ jobs:
######
- name: Logs
if: ${{ env.RUN_CAPSULE==true }}
if: ${{ env.RUN_CAPSULE }}
run: vegacapsule network logs > vega-capsule-logs.txt
- uses: actions/upload-artifact@v2
if: ${{ env.RUN_CAPSULE==true }}
if: ${{ env.RUN_CAPSULE }}
with:
name: logs
path: ./vega-capsule-logs.txt
+38 -22
View File
@@ -9,9 +9,10 @@ on:
jobs:
nightly:
name: Run capsule tests -- nightly
runs-on: ubuntu-latest
runs-on: self-hosted
env:
GO111MODULE: 'on'
VEGA_VERSION: 'v0.57.0'
steps:
#######
## Setup langs
@@ -28,7 +29,13 @@ jobs:
node-version: 16
#######
## Checkout capsule
## Install Yarn
#######
- name: Setup yarn
run: npm install -g yarn
#######
## Checkout repos
#######
# Checkout front ends
@@ -48,6 +55,20 @@ jobs:
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
path: './capsule'
# Restore node_modules from cache if possible
- name: Restore node_modules from cache
uses: actions/cache@v3
with:
path: |
frontend-monorepo/node_modules
/home/runner/.cache/Cypress
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
# Install frontend dependencies
- name: Install root dependencies
run: yarn install --frozen-lockfile
working-directory: frontend-monorepo
#######
## Build binaries
#######
@@ -58,25 +79,20 @@ jobs:
- name: Set GOBIN
run: echo GOBIN=$(go env GOPATH)/bin >> $GITHUB_ENV
- name: Checkout Vega
uses: actions/checkout@v2
with:
repository: vegaprotocol/vega
ref: v0.55.0
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
path: './vega'
- name: Install Vega binaries
run: go install -v ./cmd/vega
working-directory: vega
- name: Install Vega wallet binaries
run: go install ./cmd/vegawallet
working-directory: vega
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vega-linux-amd64.zip'
unzip vega-linux-amd64.zip -d ${{ env.GOBIN }}
- name: Install date-node binaries
run: go install ./cmd/data-node
working-directory: vega
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/data-node-linux-amd64.zip'
unzip data-node-linux-amd64.zip -d ${{ env.GOBIN }}
- name: Install Vega wallet binaries
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vegawallet-linux-amd64.zip'
unzip vegawallet-linux-amd64.zip -d ${{ env.GOBIN }}
######
## Start capsule
@@ -112,12 +128,13 @@ jobs:
## Run some tests
######
- name: Install root dependencies
run: yarn install
# To make sure that all Cypress binaries are installed properly
- name: Install cypress bins
run: yarn cypress install
working-directory: frontend-monorepo
- name: Run Cypress tests
run: yarn nx run-many --target=e2e --all --record --key ${{ secrets.CYPRESS_RECORD_KEY }}
run: yarn nx run-many --target=e2e --all --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome
working-directory: frontend-monorepo
env:
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
@@ -131,7 +148,6 @@ jobs:
######
- name: Logs
if: ${{ always() }}
run: vegacapsule network logs > vega-capsule-logs.txt
- uses: actions/upload-artifact@v2
+43 -28
View File
@@ -3,8 +3,8 @@ name: Capsule tests
on:
push:
branches:
- master
- develop
- main
pull_request:
types:
- opened
@@ -15,10 +15,10 @@ on:
jobs:
pr:
name: Run capsule tests - PR
runs-on: ubuntu-latest
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.draft == false }}
runs-on: self-hosted
env:
GO111MODULE: 'on'
VEGA_VERSION: 'v0.57.0'
steps:
#######
## Setup langs
@@ -34,6 +34,12 @@ jobs:
with:
node-version: 16
#######
## Install Yarn
#######
- name: Setup yarn
run: npm install -g yarn
#######
## Checkout repos
#######
@@ -46,27 +52,18 @@ jobs:
fetch-depth: 0
path: './frontend-monorepo'
# Checkout capsule to build local network
- name: Checkout capsule
uses: actions/checkout@v2
# Restore node_modules from cache if possible
- name: Restore node_modules from cache
uses: actions/cache@v3
with:
repository: vegaprotocol/vegacapsule
ref: main
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
path: './capsule'
# Checkout vega
- name: Checkout Vega
uses: actions/checkout@v2
with:
repository: vegaprotocol/vega
ref: v0.54.0
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
path: './vega'
path: |
frontend-monorepo/node_modules
/home/runner/.cache/Cypress
key: node_modules_cypress-${{ hashFiles('frontend-monorepo/yarn.lock') }}
# Install frontend dependencies
- name: Install root dependencies
run: yarn install
run: yarn install --frozen-lockfile
working-directory: frontend-monorepo
# See affected apps to see if building all binaries is necessary
@@ -78,6 +75,16 @@ jobs:
if: ${{ contains(env.AFFECTED, 'token') || contains(env.AFFECTED, 'token-e2e') || contains(env.AFFECTED, 'explorer') || contains(env.AFFECTED, 'explorer-e2e') }}
run: echo RUN_CAPSULE=true >> $GITHUB_ENV
# Checkout capsule to build local network
- name: Checkout capsule
if: ${{ env.RUN_CAPSULE }}
uses: actions/checkout@v2
with:
repository: vegaprotocol/vegacapsule
ref: main
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
path: './capsule'
#######
## Build binaries
#######
@@ -91,17 +98,20 @@ jobs:
- name: Install Vega binaries
if: ${{ env.RUN_CAPSULE }}
run: go install -v ./cmd/vega
working-directory: vega
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vega-linux-amd64.zip'
unzip vega-linux-amd64.zip -d ${{ env.GOBIN }}
- name: Install date-node binaries
if: ${{ env.RUN_CAPSULE }}
run: go install ./cmd/data-node
working-directory: vega
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/data-node-linux-amd64.zip'
unzip data-node-linux-amd64.zip -d ${{ env.GOBIN }}
- name: Install Vega wallet binaries
run: go install ./cmd/vegawallet
working-directory: vega
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vegawallet-linux-amd64.zip'
unzip vegawallet-linux-amd64.zip -d ${{ env.GOBIN }}
######
## Start capsule
@@ -143,7 +153,7 @@ jobs:
run: vegawallet service run --network fairground --automatic-consent --home ~/.vegacapsule/testnet/wallet &
- name: Start service using capsule network
if: ${{ env.RUN_CAPSULE==true }}
if: ${{ env.RUN_CAPSULE }}
run: vegawallet service run --network DV --automatic-consent --home ~/.vegacapsule/testnet/wallet &
######
@@ -156,8 +166,13 @@ jobs:
working-directory: frontend-monorepo
main-branch-name: ${{github.base_ref}}
# To make sure that all Cypress binaries are installed properly
- name: Install cypress bins
run: yarn cypress install
working-directory: frontend-monorepo
- name: Run Cypress tests
run: npx nx affected:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --env.grepTags='@smoke'
run: npx nx affected:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --env.grepTags='@smoke' --browser chrome
working-directory: frontend-monorepo
env:
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
+8 -37
View File
@@ -3,50 +3,16 @@ name: Unit tests & build
on:
push:
branches:
- master
- develop
- main
pull_request:
jobs:
master:
name: Test and lint - main
runs-on: ubuntu-latest
permissions:
contents: 'read'
actions: 'read'
if: ${{ github.event_name != 'pull_request' }}
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.ref }}
fetch-depth: 0
- name: Derive appropriate SHAs for base and head for `nx affected` commands
uses: nrwl/nx-set-shas@v2
with:
main-branch-name: master
- name: Use Node.js 16
id: Node
uses: actions/setup-node@v3
with:
node-version: 16.14.0
- name: Install root dependencies
run: yarn install
- name: Check formatting
run: yarn nx format:check
- name: Lint affected
run: yarn nx affected:lint --max-warnings=0
- name: Test affected
run: yarn nx affected:test
- name: Build affected
run: yarn nx affected:build
pr:
name: Test and lint - PR
runs-on: ubuntu-latest
permissions:
contents: 'read'
actions: 'read'
if: ${{ github.event_name == 'pull_request' }}
steps:
- name: Checkout
uses: actions/checkout@v3
@@ -55,14 +21,19 @@ jobs:
- name: Derive appropriate SHAs for base and head for `nx affected` commands
uses: nrwl/nx-set-shas@v2
with:
main-branch-name: develop
main-branch-name: ${{ github.base_ref }}
- name: Use Node.js 16
id: Node
uses: actions/setup-node@v3
with:
node-version: 16.14.0
- name: Restore node_modules from cache
uses: actions/cache@v3
with:
path: '**/node_modules'
key: node_modules-${{ hashFiles('**/yarn.lock') }}
- name: Install root dependencies
run: yarn install
run: yarn install --frozen-lockfile
- name: Check formatting
run: yarn nx format:check
- name: Lint affected
@@ -23,7 +23,7 @@ describe('market selector', { tags: '@smoke' }, () => {
aliasQuery(req, 'Markets', generateSimpleMarkets());
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
aliasQuery(req, 'DealTicketQuery', generateDealTicket());
aliasQuery(req, 'DealTicket', generateDealTicket());
aliasQuery(req, 'MarketTags', generateMarketTags());
aliasQuery(req, 'MarketPositions', generateMarketPositions());
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
@@ -23,7 +23,7 @@ describe('Market trade', { tags: '@smoke' }, () => {
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
aliasQuery(req, 'DealTicketQuery', generateDealTicket());
aliasQuery(req, 'DealTicket', generateDealTicket());
aliasQuery(req, 'MarketTags', generateMarketTags());
aliasQuery(req, 'MarketPositions', generateMarketPositions());
aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
@@ -3,7 +3,10 @@ import {
disconnectVegaWallet,
} from '../support/connect-wallet';
import { aliasQuery } from '@vegaprotocol/cypress';
import { generatePositions } from '../support/mocks/generate-positions';
import {
generatePositions,
emptyPositions,
} from '../support/mocks/generate-positions';
import { generateAccounts } from '../support/mocks/generate-accounts';
import { generateOrders } from '../support/mocks/generate-orders';
import { generateFills } from '../support/mocks/generate-fills';
@@ -112,4 +115,42 @@ describe('Portfolio page', { tags: '@smoke' }, () => {
cy.get('.ag-center-cols-container .ag-row').should('have.length', 4);
});
});
describe('Empty views', () => {
beforeEach(() => {
cy.mockGQL((req) => {
aliasQuery(req, 'Positions', emptyPositions());
aliasQuery(req, 'Accounts', { party: null });
aliasQuery(req, 'Orders', { party: null });
aliasQuery(req, 'Fills', { party: null });
aliasQuery(req, 'Markets', {
marketsConnection: { edges: [], __typename: 'MarketConnection' },
});
});
cy.visit('/portfolio');
connectVegaWallet();
});
it('"No data to display" should be always displayed', () => {
cy.getByTestId('assets').click();
cy.get('div.flex.items-center.justify-center').contains(
'No data to display'
);
cy.getByTestId('positions').click();
cy.get('div.flex.items-center.justify-center').contains(
'No data to display'
);
cy.getByTestId('orders').click();
cy.get('div.flex.items-center.justify-center').contains(
'No data to display'
);
cy.getByTestId('fills').click();
cy.get('div.flex.items-center.justify-center').contains(
'No data to display'
);
});
});
});
@@ -1,13 +1,12 @@
import type {
Fills,
Fills_party_tradesConnection_edges_node,
} from '@vegaprotocol/fills';
import type { FillsQuery, FillFieldsFragment } from '@vegaprotocol/fills';
import { Side } from '@vegaprotocol/types';
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
export const generateFills = (override?: PartialDeep<Fills>): Fills => {
const fills: Fills_party_tradesConnection_edges_node[] = [
export const generateFills = (
override?: PartialDeep<FillsQuery>
): FillsQuery => {
const fills: FillFieldsFragment[] = [
generateFill({
buyer: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
@@ -45,7 +44,7 @@ export const generateFills = (override?: PartialDeep<Fills>): Fills => {
}),
];
const defaultResult: Fills = {
const defaultResult: FillsQuery = {
party: {
id: 'buyer-id',
tradesConnection: {
@@ -72,10 +71,8 @@ export const generateFills = (override?: PartialDeep<Fills>): Fills => {
return merge(defaultResult, override);
};
export const generateFill = (
override?: PartialDeep<Fills_party_tradesConnection_edges_node>
) => {
const defaultFill: Fills_party_tradesConnection_edges_node = {
export const generateFill = (override?: PartialDeep<FillFieldsFragment>) => {
const defaultFill: FillFieldsFragment = {
__typename: 'Trade',
id: '0',
createdAt: new Date().toISOString(),
@@ -189,3 +189,13 @@ export const generatePositions = (
return merge(defaultResult, override);
};
export const emptyPositions = () => {
return {
party: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
positionsConnection: { edges: null, __typename: 'PositionConnection' },
__typename: 'Party',
},
};
};
+1 -1
View File
@@ -1,6 +1,6 @@
# App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql
NX_VEGA_URL=https://api.n12.testnet.vega.xyz/graphql
NX_VEGA_ENV=TESTNET
NX_VEGA_NETWORKS='{\"MAINNET\":\"https://alpha.console.vega.xyz\"}'
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
+22 -27
View File
@@ -1,8 +1,6 @@
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { createClient } from './lib/apollo-client';
import { ThemeContext } from '@vegaprotocol/react-helpers';
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
import { EnvironmentProvider, NetworkLoader } from '@vegaprotocol/environment';
import {
VegaConnectDialog,
@@ -18,8 +16,7 @@ import LocalContext from './context/local-context';
import useLocalValues from './hooks/use-local-values';
function App() {
const [theme, toggleTheme] = useThemeSwitcher();
const localValues = useLocalValues(theme, toggleTheme);
const localValues = useLocalValues();
const {
vegaWalletDialog,
menu: { setMenuOpen },
@@ -32,29 +29,27 @@ function App() {
return (
<EnvironmentProvider>
<ThemeContext.Provider value={theme}>
<NetworkLoader createClient={createClient}>
<VegaWalletProvider>
<LocalContext.Provider value={localValues}>
<AppLoader>
<div className="max-h-full min-h-full dark:bg-lite-black dark:text-neutral-200 bg-white text-neutral-800 grid grid-rows-[min-content,1fr]">
<Header />
<Main />
<VegaConnectDialog
connectors={Connectors}
dialogOpen={vegaWalletDialog.connect}
setDialogOpen={vegaWalletDialog.setConnect}
/>
<VegaManageDialog
dialogOpen={vegaWalletDialog.manage}
setDialogOpen={vegaWalletDialog.setManage}
/>
</div>
</AppLoader>
</LocalContext.Provider>
</VegaWalletProvider>
</NetworkLoader>
</ThemeContext.Provider>
<NetworkLoader createClient={createClient}>
<VegaWalletProvider>
<LocalContext.Provider value={localValues}>
<AppLoader>
<div className="max-h-full min-h-full dark:bg-lite-black dark:text-neutral-200 bg-white text-neutral-800 grid grid-rows-[min-content,1fr]">
<Header />
<Main />
<VegaConnectDialog
connectors={Connectors}
dialogOpen={vegaWalletDialog.connect}
setDialogOpen={vegaWalletDialog.setConnect}
/>
<VegaManageDialog
dialogOpen={vegaWalletDialog.manage}
setDialogOpen={vegaWalletDialog.setManage}
/>
</div>
</AppLoader>
</LocalContext.Provider>
</VegaWalletProvider>
</NetworkLoader>
</EnvironmentProvider>
);
}
@@ -1,41 +1,43 @@
import React, {
forwardRef,
useCallback,
useContext,
useMemo,
useRef,
} from 'react';
import React, { forwardRef, useCallback, useMemo, useRef } from 'react';
import classNames from 'classnames';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
import {
t,
ThemeContext,
useScreenDimensions,
} from '@vegaprotocol/react-helpers';
import { useScreenDimensions, useTheme } from '@vegaprotocol/react-helpers';
import type {
GridOptions,
GetRowIdParams,
TabToNextCellParams,
CellKeyDownEvent,
FullWidthCellKeyDownEvent,
IGetRowsParams,
IDatasource,
} from 'ag-grid-community';
import { NO_DATA_MESSAGE } from '../../constants';
import * as constants from '../simple-market-list/constants';
export interface GetRowsParams<T>
extends Omit<IGetRowsParams, 'successCallback'> {
successCallback(rowsThisBlock: T[], lastRow?: number): void;
}
export interface Datasource<T> extends IDatasource {
getRows(params: GetRowsParams<T>): void;
}
interface Props<T> extends GridOptions {
data?: T[];
rowData?: T[];
datasource?: Datasource<T>;
handleRowClicked?: (event: { data: T }) => void;
components?: Record<string, unknown>;
classNamesParam?: string | string[];
}
const ConsoleLiteGrid = <T extends { id?: string }>(
{ data, handleRowClicked, getRowId, classNamesParam, ...props }: Props<T>,
{ handleRowClicked, getRowId, classNamesParam, ...props }: Props<T>,
ref?: React.Ref<AgGridReact>
) => {
const { isMobile, screenSize } = useScreenDimensions();
const gridRef = useRef<AgGridReact | null>(null);
const theme = useContext(ThemeContext);
const { theme } = useTheme();
const handleOnGridReady = useCallback(() => {
(
(ref as React.RefObject<AgGridReact>) || gridRef
@@ -73,7 +75,6 @@ const ConsoleLiteGrid = <T extends { id?: string }>(
return (
<AgGrid
className={classNames(classNamesParam)}
rowData={data}
rowHeight={60}
customThemeParams={
theme === 'dark'
@@ -85,7 +86,7 @@ const ConsoleLiteGrid = <T extends { id?: string }>(
rowClass={isMobile ? 'mobile' : ''}
rowClassRules={constants.ROW_CLASS_RULES}
ref={ref || gridRef}
overlayNoRowsTemplate={t('No data to display')}
overlayNoRowsTemplate={NO_DATA_MESSAGE}
suppressContextMenu
getRowId={getRowId || getRowIdLocal}
suppressMovableColumns
@@ -1,13 +1,13 @@
import * as React from 'react';
import classNames from 'classnames';
import type { DealTicketQuery_market_tradableInstrument_instrument_product_settlementAsset } from '@vegaprotocol/deal-ticket';
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import type { PartyBalanceQuery_party_accounts } from './__generated__/PartyBalanceQuery';
import { useSettlementAccount } from '../../hooks/use-settlement-account';
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
import { AccountType } from '@vegaprotocol/types';
interface DealTicketBalanceProps {
settlementAsset: DealTicketQuery_market_tradableInstrument_instrument_product_settlementAsset;
settlementAsset: DealTicketMarketFragment['tradableInstrument']['instrument']['product']['settlementAsset'];
accounts: PartyBalanceQuery_party_accounts[];
isWalletConnected: boolean;
className?: string;
@@ -52,6 +52,10 @@ export const DealTicketContainer = () => {
const container = marketId ? (
<Container marketId={marketId}>
{(data) => {
if (!data.market) {
return null as unknown as JSX.Element;
}
const balance = (
<DealTicketBalance
className="mb-4"
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { useForm, Controller } from 'react-hook-form';
import { Stepper } from '../stepper';
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket';
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import { InputError } from '@vegaprotocol/ui-toolkit';
import { BigNumber } from 'bignumber.js';
import { MarketSelector } from '@vegaprotocol/deal-ticket';
@@ -37,7 +37,7 @@ import { Side, OrderType } from '@vegaprotocol/types';
import { DealTicketSlippage } from './deal-ticket-slippage';
interface DealTicketMarketProps {
market: DealTicketQuery_market;
market: DealTicketMarketFragment;
partyData?: PartyBalanceQuery;
}
@@ -6,7 +6,7 @@ import {
} from '@vegaprotocol/ui-toolkit';
import * as React from 'react';
import classNames from 'classnames';
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket';
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import type { Order } from '@vegaprotocol/orders';
import { SIDE_NAMES } from './side-selector';
import SimpleMarketExpires from '../simple-market-list/simple-market-expires';
@@ -33,7 +33,7 @@ export const MARKET_TAGS_QUERY = gql`
`;
interface Props {
market: DealTicketQuery_market;
market: DealTicketMarketFragment;
isDisabled: boolean;
transactionStatus?: string;
order: Order;
@@ -1,4 +1,4 @@
query Deposits {
query DepositAssets {
assetsConnection {
edges {
node {
@@ -6,14 +6,14 @@
import { AssetStatus } from "@vegaprotocol/types";
// ====================================================
// GraphQL query operation: Deposits
// GraphQL query operation: DepositAssets
// ====================================================
export interface Deposits_assetsConnection_edges_node_source_BuiltinAsset {
export interface DepositAssets_assetsConnection_edges_node_source_BuiltinAsset {
__typename: "BuiltinAsset";
}
export interface Deposits_assetsConnection_edges_node_source_ERC20 {
export interface DepositAssets_assetsConnection_edges_node_source_ERC20 {
__typename: "ERC20";
/**
* The address of the ERC20 contract
@@ -21,9 +21,9 @@ export interface Deposits_assetsConnection_edges_node_source_ERC20 {
contractAddress: string;
}
export type Deposits_assetsConnection_edges_node_source = Deposits_assetsConnection_edges_node_source_BuiltinAsset | Deposits_assetsConnection_edges_node_source_ERC20;
export type DepositAssets_assetsConnection_edges_node_source = DepositAssets_assetsConnection_edges_node_source_BuiltinAsset | DepositAssets_assetsConnection_edges_node_source_ERC20;
export interface Deposits_assetsConnection_edges_node {
export interface DepositAssets_assetsConnection_edges_node {
__typename: "Asset";
/**
* The ID of the asset
@@ -48,25 +48,28 @@ export interface Deposits_assetsConnection_edges_node {
/**
* The origin source of the asset (e.g: an ERC20 asset)
*/
source: Deposits_assetsConnection_edges_node_source;
source: DepositAssets_assetsConnection_edges_node_source;
}
export interface Deposits_assetsConnection_edges {
export interface DepositAssets_assetsConnection_edges {
__typename: "AssetEdge";
node: Deposits_assetsConnection_edges_node;
/**
* The asset information
*/
node: DepositAssets_assetsConnection_edges_node;
}
export interface Deposits_assetsConnection {
export interface DepositAssets_assetsConnection {
__typename: "AssetsConnection";
/**
* The assets
*/
edges: (Deposits_assetsConnection_edges | null)[] | null;
edges: (DepositAssets_assetsConnection_edges | null)[] | null;
}
export interface Deposits {
export interface DepositAssets {
/**
* The list of all assets in use in the Vega network or the specified asset if ID is provided
*/
assetsConnection: Deposits_assetsConnection | null;
assetsConnection: DepositAssets_assetsConnection | null;
}
@@ -3,14 +3,14 @@ import { Schema as Types } from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type DepositsQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type DepositAssetsQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type DepositsQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } } | null> | null } | null };
export type DepositAssetsQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string, symbol: string, decimals: number, source: { __typename?: 'BuiltinAsset' } | { __typename?: 'ERC20', contractAddress: string } } } | null> | null } | null };
export const DepositsDocument = gql`
query Deposits {
export const DepositAssetsDocument = gql`
query DepositAssets {
assetsConnection {
edges {
node {
@@ -30,28 +30,28 @@ export const DepositsDocument = gql`
`;
/**
* __useDepositsQuery__
* __useDepositAssetsQuery__
*
* To run a query within a React component, call `useDepositsQuery` and pass it any options that fit your needs.
* When your component renders, `useDepositsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* To run a query within a React component, call `useDepositAssetsQuery` and pass it any options that fit your needs.
* When your component renders, `useDepositAssetsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useDepositsQuery({
* const { data, loading, error } = useDepositAssetsQuery({
* variables: {
* },
* });
*/
export function useDepositsQuery(baseOptions?: Apollo.QueryHookOptions<DepositsQuery, DepositsQueryVariables>) {
export function useDepositAssetsQuery(baseOptions?: Apollo.QueryHookOptions<DepositAssetsQuery, DepositAssetsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<DepositsQuery, DepositsQueryVariables>(DepositsDocument, options);
return Apollo.useQuery<DepositAssetsQuery, DepositAssetsQueryVariables>(DepositAssetsDocument, options);
}
export function useDepositsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DepositsQuery, DepositsQueryVariables>) {
export function useDepositAssetsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<DepositAssetsQuery, DepositAssetsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<DepositsQuery, DepositsQueryVariables>(DepositsDocument, options);
return Apollo.useLazyQuery<DepositAssetsQuery, DepositAssetsQueryVariables>(DepositAssetsDocument, options);
}
export type DepositsQueryHookResult = ReturnType<typeof useDepositsQuery>;
export type DepositsLazyQueryHookResult = ReturnType<typeof useDepositsLazyQuery>;
export type DepositsQueryResult = Apollo.QueryResult<DepositsQuery, DepositsQueryVariables>;
export type DepositAssetsQueryHookResult = ReturnType<typeof useDepositAssetsQuery>;
export type DepositAssetsLazyQueryHookResult = ReturnType<typeof useDepositAssetsLazyQuery>;
export type DepositAssetsQueryResult = Apollo.QueryResult<DepositAssetsQuery, DepositAssetsQueryVariables>;
@@ -5,10 +5,10 @@ import { Networks, useEnvironment } from '@vegaprotocol/environment';
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { Web3Container } from '@vegaprotocol/web3';
import type { Deposits } from './__generated__/Deposits';
import type { DepositAssets } from './__generated__/DepositAssets';
const DEPOSITS_QUERY = gql`
query Deposits {
query DepositAssets {
assetsConnection {
edges {
node {
@@ -35,7 +35,7 @@ export const DepositContainer = () => {
const { VEGA_ENV } = useEnvironment();
const { keypair } = useVegaWallet();
const { data, loading, error } = useQuery<Deposits>(DEPOSITS_QUERY, {
const { data, loading, error } = useQuery<DepositAssets>(DEPOSITS_QUERY, {
variables: { partyId: keypair?.pub },
skip: !keypair?.pub,
});
@@ -43,7 +43,7 @@ export const DepositContainer = () => {
const assets = getEnabledAssets(data);
return (
<AsyncRenderer<Deposits> data={data} loading={loading} error={error}>
<AsyncRenderer<DepositAssets> data={data} loading={loading} error={error}>
{assets.length ? (
<Web3Container>
<DepositManager
@@ -12,7 +12,7 @@ const Header = () => {
} = useContext(LocalContext);
return (
<div
className="flex items-stretch pr-6 py-6 bg-black text-neutral-400"
className="dark flex items-stretch pr-6 py-6 bg-black text-neutral-400"
data-testid="header"
>
<Logo />
@@ -21,12 +21,7 @@ const Header = () => {
setConnectDialog={setConnect}
setManageDialog={setManage}
/>
<ThemeSwitcher
theme={theme}
onToggle={toggleTheme}
className="-my-4"
fixedBg="dark"
/>
<ThemeSwitcher theme={theme} onToggle={toggleTheme} className="-my-4" />
</div>
</div>
);
@@ -1,4 +1,5 @@
import { useMemo, useRef } from 'react';
import { useOutletContext } from 'react-router-dom';
import type { AgGridReact } from 'ag-grid-react';
import { PriceCell, useDataProvider } from '@vegaprotocol/react-helpers';
import type {
@@ -15,6 +16,7 @@ import {
AssetDetailsDialog,
useAssetDetailsDialogStore,
} from '@vegaprotocol/assets';
import { NO_DATA_MESSAGE } from '../../../constants';
import { ConsoleLiteGrid } from '../../console-lite-grid';
import { useAccountColumnDefinitions } from '.';
@@ -22,19 +24,12 @@ interface AccountObj extends AccountFieldsFragment {
id: string;
}
interface Props {
partyId: string;
}
const AccountsManager = ({ partyId }: Props) => {
const {
isAssetDetailsDialogOpen,
assetDetailsDialogSymbol,
setAssetDetailsDialogOpen,
} = useAssetDetailsDialogStore();
const AccountsManager = () => {
const { partyId = '' } = useOutletContext<{ partyId: string }>();
const { isOpen, symbol, setOpen } = useAssetDetailsDialogStore();
const gridRef = useRef<AgGridReact | null>(null);
const variables = useMemo(() => ({ partyId }), [partyId]);
const update = accountsManagerUpdate(gridRef);
const update = useMemo(() => accountsManagerUpdate(gridRef), []);
const { data, error, loading } = useDataProvider<
AccountFieldsFragment[],
AccountEventsSubscription['accounts']
@@ -42,9 +37,14 @@ const AccountsManager = ({ partyId }: Props) => {
const { columnDefs, defaultColDef } = useAccountColumnDefinitions();
return (
<>
<AsyncRenderer loading={loading} error={error} data={data}>
<AsyncRenderer
loading={loading}
error={error}
data={data}
noDataMessage={NO_DATA_MESSAGE}
>
<ConsoleLiteGrid<AccountObj>
data={data as AccountObj[]}
rowData={data as AccountObj[]}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
components={{ PriceCell }}
@@ -52,9 +52,9 @@ const AccountsManager = ({ partyId }: Props) => {
/>
</AsyncRenderer>
<AssetDetailsDialog
assetSymbol={assetDetailsDialogSymbol}
open={isAssetDetailsDialogOpen}
onChange={(open) => setAssetDetailsDialogOpen(open)}
assetSymbol={symbol}
open={isOpen}
onChange={(open) => setOpen(open)}
/>
</>
);
@@ -42,8 +42,7 @@ const comparator = (
};
const useAccountColumnDefinitions = () => {
const { setAssetDetailsDialogOpen, setAssetDetailsDialogSymbol } =
useAssetDetailsDialogStore();
const { open } = useAssetDetailsDialogStore();
const columnDefs: ColDef[] = useMemo(() => {
return [
{
@@ -60,8 +59,7 @@ const useAccountColumnDefinitions = () => {
<button
className="hover:underline"
onClick={() => {
setAssetDetailsDialogOpen(true);
setAssetDetailsDialogSymbol(value);
open(value);
}}
>
{value}
@@ -97,7 +95,7 @@ const useAccountColumnDefinitions = () => {
addDecimalsFormatNumber(value, data.asset.decimals),
},
];
}, [setAssetDetailsDialogOpen, setAssetDetailsDialogSymbol]);
}, [open]);
const defaultColDef = useMemo(() => {
return {
@@ -1,17 +1,16 @@
import { useRef } from 'react';
import { useOutletContext } from 'react-router-dom';
import type { AgGridReact } from 'ag-grid-react';
import type { TradeWithMarket } from '@vegaprotocol/fills';
import { useFillsList } from '@vegaprotocol/fills';
import type { BodyScrollEndEvent, BodyScrollEvent } from 'ag-grid-community';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { ConsoleLiteGrid } from '../../console-lite-grid';
import { NO_DATA_MESSAGE } from '../../../constants';
import useColumnDefinitions from './use-column-definitions';
interface Props {
partyId: string;
}
const FillsManager = ({ partyId }: Props) => {
const FillsManager = () => {
const { partyId } = useOutletContext<{ partyId: string }>();
const { columnDefs, defaultColDef } = useColumnDefinitions({ partyId });
const gridRef = useRef<AgGridReact | null>(null);
const scrolledToTop = useRef(true);
@@ -32,7 +31,12 @@ const FillsManager = ({ partyId }: Props) => {
};
return (
<AsyncRenderer loading={loading} error={error} data={data}>
<AsyncRenderer
loading={loading}
error={error}
data={data?.length ? data : null}
noDataMessage={NO_DATA_MESSAGE}
>
<ConsoleLiteGrid<TradeWithMarket>
ref={gridRef}
rowModelType="infinite"
@@ -1 +1,6 @@
export * from './portfolio';
export * from './accounts';
export * from './fills';
export * from './orders';
export * from './positions';
export * as constants from './constants';
@@ -1,6 +1,7 @@
import { useRef, useState } from 'react';
import type { AgGridReact } from 'ag-grid-react';
import type { BodyScrollEndEvent, BodyScrollEvent } from 'ag-grid-community';
import { useOutletContext } from 'react-router-dom';
import type { OrderWithMarket } from '@vegaprotocol/orders';
import {
useOrderCancel,
@@ -14,13 +15,11 @@ import {
} from '@vegaprotocol/orders';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { ConsoleLiteGrid } from '../../console-lite-grid';
import { NO_DATA_MESSAGE } from '../../../constants';
import useColumnDefinitions from './use-column-definitions';
interface Props {
partyId: string;
}
const OrdersManager = ({ partyId }: Props) => {
const OrdersManager = () => {
const { partyId } = useOutletContext<{ partyId: string }>();
const [editOrder, setEditOrder] = useState<OrderWithMarket | null>(null);
const orderCancel = useOrderCancel();
const orderEdit = useOrderEdit(editOrder);
@@ -49,10 +48,16 @@ const OrdersManager = ({ partyId }: Props) => {
};
return (
<AsyncRenderer loading={loading} error={error} data={data}>
<AsyncRenderer
loading={loading}
error={error}
data={data?.length ? data : null}
noDataMessage={NO_DATA_MESSAGE}
>
<ConsoleLiteGrid<OrderWithMarket>
ref={gridRef}
rowModelType="infinite"
rowModelType={data?.length ? 'infinite' : 'clientSide'}
rowData={data?.length ? undefined : []}
datasource={{ getRows }}
onBodyScrollEnd={onBodyScrollEnd}
onBodyScroll={onBodyScroll}
@@ -1,54 +1,27 @@
import React, { useMemo } from 'react';
import { AccountManager } from './accounts';
import React from 'react';
import { useVegaWallet } from '@vegaprotocol/wallet';
import ConnectWallet from '../wallet-connector';
import { DepositContainer } from '../deposits';
import { useParams } from 'react-router-dom';
import { useOutlet, useLocation } from 'react-router-dom';
import { HorizontalMenu } from '../horizontal-menu';
import * as constants from './constants';
import { PositionsManager } from './positions';
import { OrdersManager } from './orders';
import { FillsManager } from './fills';
type RouterParams = {
module?: string;
};
export const Portfolio = () => {
const { keypair } = useVegaWallet();
const params = useParams<RouterParams>();
const module = useMemo(() => {
if (!keypair) {
return (
<section className="xl:w-1/2">
<ConnectWallet />
</section>
);
}
switch (params?.module) {
case constants.PORTFOLIO_ASSETS:
default:
return <AccountManager partyId={keypair.pub} />;
case constants.PORTFOLIO_POSITIONS:
return <PositionsManager partyId={keypair.pub} />;
case constants.PORTFOLIO_ORDERS:
return <OrdersManager partyId={keypair.pub} />;
case constants.PORTFOLIO_FILLS:
return <FillsManager partyId={keypair.pub} />;
case constants.PORTFOLIO_DEPOSITS:
return <DepositContainer />;
}
}, [params?.module, keypair]);
const { pathname } = useLocation();
const module = pathname.split('/portfolio/')?.[1] ?? '';
const outlet = useOutlet({ partyId: keypair?.pub || '' });
if (!keypair) {
return (
<section className="xl:w-1/2">
<ConnectWallet />
</section>
);
}
return (
<div className="h-full p-4 md:p-6 grid grid-rows-[min-content_1fr]">
<HorizontalMenu
active={params?.module}
items={constants.PORTFOLIO_ITEMS}
/>
{module}
<HorizontalMenu active={module} items={constants.PORTFOLIO_ITEMS} />
{outlet}
</div>
);
};
@@ -17,11 +17,11 @@ const getRowId = ({ data }: { data: Position }) => data.marketId;
const PositionsAsset = ({ partyId, assetSymbol }: Props) => {
const gridRef = useRef<AgGridReact | null>(null);
const { data, error, loading, getRows } = usePositionsData({
const { data, error, loading, getRows } = usePositionsData(
partyId,
assetSymbol,
gridRef,
});
assetSymbol
);
const { columnDefs, defaultColDef } = useColumnDefinitions();
return (
<AsyncRenderer loading={loading} error={error} data={data}>
@@ -47,7 +47,7 @@ const PositionsAsset = ({ partyId, assetSymbol }: Props) => {
defaultColDef={defaultColDef}
getRowId={getRowId}
rowModelType={data?.length ? 'infinite' : 'clientSide'}
data={data?.length ? undefined : []}
rowData={data?.length ? undefined : []}
datasource={{ getRows }}
components={{ PriceFlashCell }}
/>
@@ -1,19 +1,15 @@
import { useOutletContext } from 'react-router-dom';
import { t } from '@vegaprotocol/react-helpers';
import { usePositionsAssets } from '@vegaprotocol/positions';
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
import PositionsAsset from './positions-asset';
interface Props {
partyId: string;
}
const Positions = ({ partyId }: Props) => {
const { data, error, loading, assetSymbols } = usePositionsAssets({
partyId,
});
const Positions = () => {
const { partyId } = useOutletContext<{ partyId: string }>();
const { data, error, loading, assetSymbols } = usePositionsAssets(partyId);
return (
<AsyncRenderer loading={loading} error={error} data={data}>
{assetSymbols && assetSymbols.length && (
{assetSymbols && assetSymbols.length > 0 && (
<div className="w-full, h-max">
{assetSymbols?.map((assetSymbol) => (
<PositionsAsset
@@ -67,7 +67,7 @@ const SimpleMarketList = () => {
<ConsoleLiteGrid<MarketWithPercentChange>
classNamesParam="mb-32 min-h-[300px]"
columnDefs={columnDefs}
data={localData}
rowData={localData}
defaultColDef={defaultColDef}
handleRowClicked={handleRowClicked}
/>
@@ -68,9 +68,14 @@ const SimpleMarketPercentChangeWrapper = (props: Props) => {
};
const SimpleMarketPercentChange = ({ candles, marketId, setValue }: Props) => {
const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
const { data } = useDataProvider({
dataProvider: marketCandlesProvider,
variables: { marketId, interval: Interval.INTERVAL_I1D },
variables: {
marketId,
interval: Interval.INTERVAL_I1D,
since: new Date(yesterday * 1000).toISOString(),
},
});
const close = data?.map((m) => m.close);
@@ -24,3 +24,5 @@ export const MARKET_STATES_MAP: Record<MarketState | '', string> = {
[MarketState.STATE_TRADING_TERMINATED]: t('TradingTerminated'),
'': t('Unknown'),
};
export const NO_DATA_MESSAGE = t('No data to display');
@@ -16,8 +16,6 @@ interface MenuState {
export interface LocalValues {
vegaWalletDialog: VegaWalletDialogState;
menu: MenuState;
theme: 'light' | 'dark';
toggleTheme: () => void;
}
const LocalContext = createContext<LocalValues>({} as LocalValues);
@@ -10,7 +10,7 @@
export interface MarketMarkPrice_market_data {
__typename: "MarketData";
/**
* the mark price (an unsigned integer)
* The mark price (an unsigned integer)
*/
markPrice: string;
}
@@ -18,7 +18,7 @@ export interface MarketMarkPrice_market_data {
export interface MarketMarkPrice_market {
__typename: "Market";
/**
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
* The number of decimal places that an integer must be shifted by in order to get a correct
* number denominated in the currency of the market. (uint64)
*
* Examples:
@@ -60,19 +60,19 @@ export interface PartyMarketData_party_marginsConnection_edges_node_market {
export interface PartyMarketData_party_marginsConnection_edges_node {
__typename: "MarginLevels";
/**
* market in which the margin is required for this party
* Market in which the margin is required for this party
*/
market: PartyMarketData_party_marginsConnection_edges_node_market;
/**
* this is the minimum margin required for a party to place a new order on the network (unsigned integer)
* This is the minimum margin required for a party to place a new order on the network (unsigned integer)
*/
initialLevel: string;
/**
* minimal margin for the position to be maintained in the network (unsigned integer)
* Minimal margin for the position to be maintained in the network (unsigned integer)
*/
maintenanceLevel: string;
/**
* if the margin is between maintenance and search, the network will initiate a collateral search (unsigned integer)
* If the margin is between maintenance and search, the network will initiate a collateral search (unsigned integer)
*/
searchLevel: string;
}
@@ -28,7 +28,7 @@ export interface EstimateOrder_estimateOrder_fee {
export interface EstimateOrder_estimateOrder_marginLevels {
__typename: "MarginLevels";
/**
* this is the minimum margin required for a party to place a new order on the network (unsigned integer)
* This is the minimum margin required for a party to place a new order on the network (unsigned integer)
*/
initialLevel: string;
}
@@ -47,7 +47,7 @@ export interface EstimateOrder_estimateOrder {
export interface EstimateOrder {
/**
* return an estimation of the potential cost for a new order
* Return an estimation of the potential cost for a new order
*/
estimateOrder: EstimateOrder_estimateOrder;
}
@@ -67,6 +67,9 @@ export interface MarketPositions_party_positionsConnection_edges_node {
export interface MarketPositions_party_positionsConnection_edges {
__typename: "PositionEdge";
/**
* The position
*/
node: MarketPositions_party_positionsConnection_edges_node;
}
@@ -1,7 +1,7 @@
import { useMemo, useState } from 'react';
import type { LocalValues } from '../context/local-context';
const useLocalValues = (theme: 'light' | 'dark', toggleTheme: () => void) => {
const useLocalValues = () => {
const [connect, setConnect] = useState<boolean>(false);
const [manage, setManage] = useState<boolean>(false);
const [menuOpen, setMenuOpen] = useState(false);
@@ -9,10 +9,8 @@ const useLocalValues = (theme: 'light' | 'dark', toggleTheme: () => void) => {
() => ({
vegaWalletDialog: { connect, manage, setConnect, setManage },
menu: { menuOpen, setMenuOpen, onToggle: () => setMenuOpen(!menuOpen) },
theme,
toggleTheme,
}),
[connect, manage, theme, toggleTheme, menuOpen]
[connect, manage, menuOpen]
);
};
@@ -3,7 +3,7 @@ import { renderHook } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing';
import useOrderCloseOut from './use-order-closeout';
import type { Order } from '@vegaprotocol/orders';
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket';
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import type { PartyBalanceQuery } from '../components/deal-ticket/__generated__/PartyBalanceQuery';
jest.mock('@vegaprotocol/wallet', () => ({
@@ -49,7 +49,7 @@ describe('useOrderCloseOut Hook', () => {
() =>
useOrderCloseOut({
order: order as Order,
market: market as DealTicketQuery_market,
market: market as DealTicketMarketFragment,
partyData: partyData as PartyBalanceQuery,
}),
{
@@ -66,7 +66,7 @@ describe('useOrderCloseOut Hook', () => {
() =>
useOrderCloseOut({
order: { ...order, side: 'SIDE_SELL' } as Order,
market: market as DealTicketQuery_market,
market: market as DealTicketMarketFragment,
partyData: partyData as PartyBalanceQuery,
}),
{
@@ -83,7 +83,7 @@ describe('useOrderCloseOut Hook', () => {
() =>
useOrderCloseOut({
order: { ...order, side: 'SIDE_SELL' } as Order,
market: market as DealTicketQuery_market,
market: market as DealTicketMarketFragment,
}),
{
wrapper: ({ children }: { children: React.ReactNode }) => (
@@ -1,6 +1,6 @@
import { BigNumber } from 'bignumber.js';
import type { Order } from '@vegaprotocol/orders';
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket';
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import type { PartyBalanceQuery } from '../components/deal-ticket/__generated__/PartyBalanceQuery';
import { useSettlementAccount } from './use-settlement-account';
import { useVegaWallet } from '@vegaprotocol/wallet';
@@ -47,7 +47,7 @@ const CLOSEOUT_PRICE_QUERY = gql`
interface Props {
order: Order;
market: DealTicketQuery_market;
market: DealTicketMarketFragment;
partyData?: PartyBalanceQuery;
}
@@ -2,7 +2,7 @@ import { renderHook } from '@testing-library/react';
import { useQuery } from '@apollo/client';
import { BigNumber } from 'bignumber.js';
import type { Order } from '@vegaprotocol/orders';
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket';
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import type { PositionMargin } from './use-market-positions';
import useOrderMargin from './use-order-margin';
@@ -54,7 +54,7 @@ describe('useOrderMargin Hook', () => {
const { result } = renderHook(() =>
useOrderMargin({
order: order as Order,
market: market as DealTicketQuery_market,
market: market as DealTicketMarketFragment,
partyId,
})
);
@@ -72,7 +72,7 @@ describe('useOrderMargin Hook', () => {
const { result } = renderHook(() =>
useOrderMargin({
order: order as Order,
market: market as DealTicketQuery_market,
market: market as DealTicketMarketFragment,
partyId,
})
);
@@ -84,7 +84,7 @@ describe('useOrderMargin Hook', () => {
const { result } = renderHook(() =>
useOrderMargin({
order: order as Order,
market: market as DealTicketQuery_market,
market: market as DealTicketMarketFragment,
partyId,
})
);
@@ -111,7 +111,7 @@ describe('useOrderMargin Hook', () => {
const { result } = renderHook(() =>
useOrderMargin({
order: order as Order,
market: market as DealTicketQuery_market,
market: market as DealTicketMarketFragment,
partyId,
})
);
@@ -6,7 +6,7 @@ import type {
EstimateOrderVariables,
EstimateOrder_estimateOrder_fee,
} from './__generated__/estimateOrder';
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket';
import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import { Side } from '@vegaprotocol/types';
import { addDecimal, removeDecimal } from '@vegaprotocol/react-helpers';
import useMarketPositions from './use-market-positions';
@@ -47,7 +47,7 @@ export const ESTIMATE_ORDER_QUERY = gql`
interface Props {
order: Order;
market: DealTicketQuery_market;
market: DealTicketMarketFragment;
partyId: string;
}
@@ -1,7 +1,15 @@
import { t } from '@vegaprotocol/react-helpers';
import { DealTicketContainer } from '../components/deal-ticket';
import { SimpleMarketList } from '../components/simple-market-list';
import { Portfolio } from '../components/portfolio';
import {
Portfolio,
AccountManager,
PositionsManager,
OrdersManager,
FillsManager,
constants,
} from '../components/portfolio';
import { DepositContainer } from '../components/deposits';
export const ROUTES = {
MARKETS: 'markets',
@@ -51,13 +59,33 @@ export const routerConfig = [
name: 'Portfolio',
text: t('Portfolio'),
element: <Portfolio />,
children: [
{
path: ':module',
element: <Portfolio />,
},
],
icon: 'portfolio',
isNavItem: true,
children: [
{
path: '',
element: <AccountManager />,
},
{
path: constants.PORTFOLIO_ASSETS,
element: <AccountManager />,
},
{
path: constants.PORTFOLIO_POSITIONS,
element: <PositionsManager />,
},
{
path: constants.PORTFOLIO_ORDERS,
element: <OrdersManager />,
},
{
path: constants.PORTFOLIO_FILLS,
element: <FillsManager />,
},
{
path: constants.PORTFOLIO_DEPOSITS,
element: <DepositContainer />,
},
],
},
];
+1
View File
@@ -6,3 +6,4 @@ NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_VEGA_ENV=TESTNET
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_URL=https://api.n09.testnet.vega.xyz/graphql
+4 -1
View File
@@ -14,5 +14,8 @@
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
],
"env": {
"jest": true
}
}
+17 -26
View File
@@ -2,7 +2,6 @@ import { useState, useEffect } from 'react';
import * as Sentry from '@sentry/react';
import { BrowserTracing } from '@sentry/tracing';
import { useLocation } from 'react-router-dom';
import { ThemeContext, useThemeSwitcher } from '@vegaprotocol/react-helpers';
import {
EnvironmentProvider,
NetworkLoader,
@@ -18,7 +17,6 @@ import { ENV } from './config/env';
function App() {
const { VEGA_ENV } = useEnvironment();
const [theme, toggleTheme] = useThemeSwitcher();
const [menuOpen, setMenuOpen] = useState(false);
const location = useLocation();
@@ -37,31 +35,24 @@ function App() {
}, [VEGA_ENV]);
return (
<ThemeContext.Provider value={theme}>
<TendermintWebsocketProvider>
<NetworkLoader createClient={createClient}>
<div
className={`${
menuOpen && 'h-[100vh] overflow-hidden'
} antialiased m-0 bg-white dark:bg-black text-black dark:text-white`}
>
<div className="min-h-[100vh] max-w-[1300px] grid grid-rows-[repeat(2,_auto)_1fr] grid-cols-[1fr] md:grid-rows-[auto_minmax(700px,_1fr)] md:grid-cols-[300px_1fr] border-neutral-700 dark:border-neutral-300 lg:border-l lg:border-r mx-auto">
<Header
theme={theme}
toggleTheme={toggleTheme}
menuOpen={menuOpen}
setMenuOpen={setMenuOpen}
/>
<Nav menuOpen={menuOpen} />
<Main />
<footer className="grid grid-rows-2 grid-cols-[1fr_auto] text-sm md:text-md md:flex md:col-span-2 p-4 gap-4 border-t border-neutral-700 dark:border-neutral-300">
<NetworkInfo />
</footer>
</div>
<TendermintWebsocketProvider>
<NetworkLoader createClient={createClient}>
<div
className={`${
menuOpen && 'h-[100vh] overflow-hidden'
} antialiased m-0 bg-white dark:bg-black text-black dark:text-white`}
>
<div className="grid grid-rows-[repeat(2,_auto)_1fr] grid-cols-[1fr] md:grid-rows-[auto_minmax(700px,_1fr)] md:grid-cols-[300px_1fr] border-neutral-700 dark:border-neutral-300 lg:border-l lg:border-r mx-auto">
<Header menuOpen={menuOpen} setMenuOpen={setMenuOpen} />
<Nav menuOpen={menuOpen} />
<Main />
<footer className="grid grid-rows-2 grid-cols-[1fr_auto] text-sm md:text-md md:flex md:col-span-2 p-4 gap-4 border-t border-neutral-700 dark:border-neutral-300">
<NetworkInfo />
</footer>
</div>
</NetworkLoader>
</TendermintWebsocketProvider>
</ThemeContext.Provider>
</div>
</NetworkLoader>
</TendermintWebsocketProvider>
);
}
@@ -8,30 +8,24 @@ import type { Dispatch, SetStateAction } from 'react';
import { NetworkSwitcher } from '@vegaprotocol/environment';
interface ThemeToggleProps {
theme: 'light' | 'dark';
toggleTheme: () => void;
menuOpen: boolean;
setMenuOpen: Dispatch<SetStateAction<boolean>>;
}
export const Header = ({
theme,
toggleTheme,
menuOpen,
setMenuOpen,
}: ThemeToggleProps) => {
export const Header = ({ menuOpen, setMenuOpen }: ThemeToggleProps) => {
const headerClasses = classnames(
'md:col-span-2',
'grid grid-rows-2 md:grid-rows-1 grid-cols-[1fr_auto] md:grid-cols-[auto_1fr_auto] items-center',
'p-4 gap-2 md:gap-4',
'border-b border-neutral-700 dark:border-neutral-300'
'border-b border-neutral-700 dark:border-neutral-300 bg-black',
'dark text-white'
);
return (
<header className={headerClasses}>
<div className="flex h-full items-center sm:items-stretch gap-4">
<Link to={Routes.HOME}>
<h1
className="text-3xl font-alpha uppercase calt mb-0"
className="text-white text-3xl font-alpha uppercase calt mb-0"
data-testid="explorer-header"
>
{t('Vega Explorer')}
@@ -41,13 +35,13 @@ export const Header = ({
</div>
<button
data-testid="open-menu"
className="md:hidden"
className="md:hidden text-white"
onClick={() => setMenuOpen(!menuOpen)}
>
<Icon name={menuOpen ? 'cross' : 'menu'} />
</button>
<Search />
<ThemeSwitcher theme={theme} onToggle={toggleTheme} />
<ThemeSwitcher className="-my-4" />
</header>
);
};
@@ -0,0 +1 @@
export * from './info-panel';
@@ -0,0 +1,55 @@
import React from 'react';
import type { ReactNode } from 'react';
import { Panel } from '../panel';
import {
CopyWithTooltip,
Icon,
Intent,
Lozenge,
Tooltip,
} from '@vegaprotocol/ui-toolkit';
interface InfoPanelProps {
children?: ReactNode | ReactNode[];
title: string;
id: string;
type?: string;
copy?: boolean;
}
export const InfoPanel = ({
children,
title,
id,
type,
copy = true,
}: InfoPanelProps) => {
return (
<Panel>
<section className="flex gap-3 mb-1 items-center">
<h3 className="text-lg font-bold">{title}</h3>
<p title={id} className="truncate ...">
{id}
</p>
{type && (
<Lozenge
className="text-xs leading-relaxed cursor-auto"
variant={Intent.None}
>
<Tooltip side="top" description={type} align="center">
<span>{type}</span>
</Tooltip>
</Lozenge>
)}
{copy && (
<CopyWithTooltip text={id}>
<button className="underline">
<Icon name="duplicate" className="ml-2" />
</button>
</CopyWithTooltip>
)}
</section>
{children}
</Panel>
);
};
@@ -0,0 +1 @@
export * from './panel';
@@ -0,0 +1,10 @@
import classNames from 'classnames';
import type { ReactNode } from 'react';
interface PanelProps {
children: ReactNode;
className?: string;
}
export const Panel = ({ children, className }: PanelProps) => (
<div className={classNames('border p-5 mb-5', className)}>{children}</div>
);
@@ -63,6 +63,7 @@ export const Search = () => {
{...register('search')}
id="search"
data-testid="search"
className="text-white"
hasError={Boolean(error?.message)}
type="text"
placeholder={t('Enter block number or transaction hash')}
@@ -81,6 +81,9 @@ export interface AssetsQuery_assetsConnection_edges_node {
export interface AssetsQuery_assetsConnection_edges {
__typename: "AssetEdge";
/**
* The asset information
*/
node: AssetsQuery_assetsConnection_edges_node;
}
@@ -265,7 +265,7 @@ export interface ProposalsQuery_proposalsConnection_edges_node {
*/
datetime: string;
/**
* Reason for the proposal to be rejected by the core
* Why the proposal was rejected by the core
*/
rejectionReason: ProposalRejectionReason | null;
/**
@@ -104,15 +104,15 @@ export interface MarketsQuery_markets_tradableInstrument_instrument {
export interface MarketsQuery_markets_tradableInstrument_riskModel_LogNormalRiskModel_params {
__typename: "LogNormalModelParams";
/**
* r parameter
* R parameter
*/
r: number;
/**
* sigma parameter, annualised volatility of the underlying asset, must be a strictly non-negative real number
* Sigma parameter, annualised volatility of the underlying asset, must be a strictly non-negative real number
*/
sigma: number;
/**
* mu parameter, annualised growth rate of the underlying asset
* Mu parameter, annualised growth rate of the underlying asset
*/
mu: number;
}
@@ -158,15 +158,15 @@ export type MarketsQuery_markets_tradableInstrument_riskModel = MarketsQuery_mar
export interface MarketsQuery_markets_tradableInstrument_marginCalculator_scalingFactors {
__typename: "ScalingFactors";
/**
* the scaling factor that determines the margin level at which Vega has to search for more money
* The scaling factor that determines the margin level at which Vega has to search for more money
*/
searchLevel: number;
/**
* the scaling factor that determines the optimal margin level
* The scaling factor that determines the optimal margin level
*/
initialMargin: number;
/**
* the scaling factor that determines the overflow margin level
* The scaling factor that determines the overflow margin level
*/
collateralRelease: number;
}
@@ -362,47 +362,47 @@ export interface MarketsQuery_markets_data_liquidityProviderFeeShare {
export interface MarketsQuery_markets_data {
__typename: "MarketData";
/**
* the mark price (an unsigned integer)
* The mark price (an unsigned integer)
*/
markPrice: string;
/**
* the highest price level on an order book for buy orders.
* The highest price level on an order book for buy orders.
*/
bestBidPrice: string;
/**
* the aggregated volume being bid at the best bid price.
* The aggregated volume being bid at the best bid price.
*/
bestBidVolume: string;
/**
* the lowest price level on an order book for offer orders.
* The lowest price level on an order book for offer orders.
*/
bestOfferPrice: string;
/**
* the aggregated volume being offered at the best offer price.
* The aggregated volume being offered at the best offer price.
*/
bestOfferVolume: string;
/**
* the highest price level on an order book for buy orders not including pegged orders.
* The highest price level on an order book for buy orders not including pegged orders.
*/
bestStaticBidPrice: string;
/**
* the aggregated volume being offered at the best static bid price, excluding pegged orders
* The aggregated volume being offered at the best static bid price, excluding pegged orders
*/
bestStaticBidVolume: string;
/**
* the lowest price level on an order book for offer orders not including pegged orders.
* The lowest price level on an order book for offer orders not including pegged orders.
*/
bestStaticOfferPrice: string;
/**
* the aggregated volume being offered at the best static offer price, excluding pegged orders.
* The aggregated volume being offered at the best static offer price, excluding pegged orders.
*/
bestStaticOfferVolume: string;
/**
* the arithmetic average of the best bid price and best offer price.
* The arithmetic average of the best bid price and best offer price.
*/
midPrice: string;
/**
* the arithmetic average of the best static bid price and best static offer price
* The arithmetic average of the best static bid price and best static offer price
*/
staticMidPrice: string;
/**
@@ -410,7 +410,7 @@ export interface MarketsQuery_markets_data {
*/
timestamp: string;
/**
* the sum of the size of all positions greater than 0.
* The sum of the size of all positions greater than 0.
*/
openInterest: string;
/**
@@ -422,39 +422,39 @@ export interface MarketsQuery_markets_data {
*/
auctionStart: string | null;
/**
* indicative price if the auction ended now, 0 if not in auction mode
* Indicative price if the auction ended now, 0 if not in auction mode
*/
indicativePrice: string;
/**
* indicative volume if the auction ended now, 0 if not in auction mode
* Indicative volume if the auction ended now, 0 if not in auction mode
*/
indicativeVolume: string;
/**
* what triggered an auction (if an auction was started)
* What triggered an auction (if an auction was started)
*/
trigger: AuctionTrigger;
/**
* what extended the ongoing auction (if an auction was extended)
* What extended the ongoing auction (if an auction was extended)
*/
extensionTrigger: AuctionTrigger;
/**
* the amount of stake targeted for this market
* The amount of stake targeted for this market
*/
targetStake: string | null;
/**
* the supplied stake for the market
* The supplied stake for the market
*/
suppliedStake: string | null;
/**
* a list of valid price ranges per associated trigger
* A list of valid price ranges per associated trigger
*/
priceMonitoringBounds: MarketsQuery_markets_data_priceMonitoringBounds[] | null;
/**
* the market value proxy
* The market value proxy
*/
marketValueProxy: string;
/**
* the equity like share of liquidity fee for each liquidity provider
* The equity like share of liquidity fee for each liquidity provider
*/
liquidityProviderFeeShare: MarketsQuery_markets_data_liquidityProviderFeeShare[] | null;
}
@@ -474,7 +474,7 @@ export interface MarketsQuery_markets {
*/
tradableInstrument: MarketsQuery_markets_tradableInstrument;
/**
* decimalPlaces indicates the number of decimal places that an integer must be shifted by in order to get a correct
* The number of decimal places that an integer must be shifted by in order to get a correct
* number denominated in the currency of the market. (uint64)
*
* Examples:
@@ -21,7 +21,7 @@ export interface NetworkParametersQuery_networkParameters {
export interface NetworkParametersQuery {
/**
* return the full list of network parameters
* Return the full list of network parameters
*/
networkParameters: NetworkParametersQuery_networkParameters[] | null;
}
@@ -10,6 +10,7 @@ import {
formatNumber,
t,
} from '@vegaprotocol/react-helpers';
import { suitableForSyntaxHighlighter } from '@vegaprotocol/react-helpers';
import { RouteTitle } from '../../components/route-title';
import type {
NetworkParametersQuery,
@@ -58,7 +59,7 @@ export const NetworkParameterRow = ({
}: {
row: NetworkParametersQuery_networkParameters;
}) => {
const isSyntaxRow = isJsonObject(value);
const isSyntaxRow = suitableForSyntaxHighlighter(value);
return (
<KeyValueTableRow
@@ -85,14 +86,6 @@ export const NetworkParameterRow = ({
);
};
export const isJsonObject = (str: string) => {
try {
return JSON.parse(str) && Object.keys(JSON.parse(str)).length > 0;
} catch (e) {
return false;
}
};
export const NETWORK_PARAMETERS_QUERY = gql`
query NetworkParametersQuery {
networkParameters {
@@ -12,11 +12,11 @@ import { OracleSpecStatus, PropertyKeyType, ConditionOperator } from "@vegaproto
export interface OracleSpecs_oracleSpecs_filters_key {
__typename: "PropertyKey";
/**
* name is the name of the property.
* The name of the property.
*/
name: string | null;
/**
* type is the type of the property.
* The type of the property.
*/
type: PropertyKeyType;
}
@@ -24,11 +24,11 @@ export interface OracleSpecs_oracleSpecs_filters_key {
export interface OracleSpecs_oracleSpecs_filters_conditions {
__typename: "Condition";
/**
* value is used by the comparator.
* The value to compare against.
*/
value: string | null;
/**
* comparator is the type of comparison to make on the value.
* The type of comparison to make on the value.
*/
operator: ConditionOperator;
}
@@ -36,11 +36,11 @@ export interface OracleSpecs_oracleSpecs_filters_conditions {
export interface OracleSpecs_oracleSpecs_filters {
__typename: "Filter";
/**
* key is the oracle data property key targeted by the filter.
* The oracle data property key targeted by the filter.
*/
key: OracleSpecs_oracleSpecs_filters_key;
/**
* conditions are the conditions that should be matched by the data to be
* The conditions that should be matched by the data to be
* considered of interest.
*/
conditions: OracleSpecs_oracleSpecs_filters_conditions[] | null;
@@ -49,7 +49,7 @@ export interface OracleSpecs_oracleSpecs_filters {
export interface OracleSpecs_oracleSpecs_data {
__typename: "OracleData";
/**
* pubKeys is the list of public keys that signed the data
* The list of public keys that signed the data
*/
pubKeys: string[] | null;
}
@@ -57,7 +57,7 @@ export interface OracleSpecs_oracleSpecs_data {
export interface OracleSpecs_oracleSpecs {
__typename: "OracleSpec";
/**
* status describes the status of the oracle spec
* Status describes the status of the oracle spec
*/
status: OracleSpecStatus;
/**
@@ -73,18 +73,18 @@ export interface OracleSpecs_oracleSpecs {
*/
updatedAt: string | null;
/**
* pubKeys is the list of authorized public keys that signed the data for this
* The list of authorized public keys that signed the data for this
* oracle. All the public keys in the oracle data should be contained in these
* public keys.
*/
pubKeys: string[] | null;
/**
* filters describes which oracle data are considered of interest or not for
* Filters describes which oracle data are considered of interest or not for
* the product (or the risk model).
*/
filters: OracleSpecs_oracleSpecs_filters[] | null;
/**
* data list all the oracle data broadcast to this spec
* Data list all the oracle data broadcast to this spec
*/
data: OracleSpecs_oracleSpecs_data[];
}
@@ -1,11 +1,18 @@
import { useQuery } from '@apollo/client';
import { gql } from '@apollo/client';
import { t, useFetch } from '@vegaprotocol/react-helpers';
import {
t,
useFetch,
addDecimalsFormatNumber,
} from '@vegaprotocol/react-helpers';
import { AccountTypeMapping } from '@vegaprotocol/types';
import React from 'react';
import { useParams } from 'react-router-dom';
import { RouteTitle } from '../../../components/route-title';
import { SubHeading } from '../../../components/sub-heading';
import { SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
import { Panel } from '../../../components/panel';
import { InfoPanel } from '../../../components/info-panel';
import { DATA_SOURCES } from '../../../config';
import type { TendermintSearchTransactionResponse } from '../tendermint-transaction-response';
import type {
@@ -69,12 +76,80 @@ const Party = () => {
}
);
const header = data?.party?.id ? (
<InfoPanel
title={t('Address')}
id={data.party.id}
type={data.party.__typename}
/>
) : (
<Panel>
<p>No party found for key {party}</p>
</Panel>
);
const accounts = (
<section>
{data?.party?.accounts?.length ? (
data.party.accounts.map((account) => {
return (
<InfoPanel
title={account.asset.name}
id={account.asset.id}
type={`Account Type - ${AccountTypeMapping[account.type]}`}
>
<section>
<dl className="flex gap-2 font-mono">
<dt className="font-bold">
{t('Balance')} ({account.asset.symbol})
</dt>
<dd>
{addDecimalsFormatNumber(
account.balance,
account.asset.decimals
)}
</dd>
</dl>
</section>
</InfoPanel>
);
})
) : (
<Panel>
<p>No Data</p>
</Panel>
)}
</section>
);
const staking = (
<section>
{data?.party?.stake?.currentStakeAvailable ? (
<InfoPanel
title={t('Current Stake Available')}
id={data?.party?.stake?.currentStakeAvailable}
type={data?.party?.stake.__typename}
copy={false}
/>
) : (
<Panel>
<p>Nothing staked for {party}</p>
</Panel>
)}
</section>
);
return (
<section>
<RouteTitle data-testid="parties-header">{t('Party')}</RouteTitle>
{data ? (
<>
{header}
<SubHeading>{t('Asset data')}</SubHeading>
{accounts}
<SubHeading>{t('Staking')}</SubHeading>
{staking}
<SubHeading>{t('JSON')}</SubHeading>
<SyntaxHighlighter data={data} />
</>
) : null}
@@ -69,13 +69,19 @@ export interface NodesQuery_nodes {
* Amount of stake on the next epoch
*/
pendingStake: string;
/**
* Summary of epoch data across all nodes
*/
epochData: NodesQuery_nodes_epochData | null;
/**
* Validator status of the node
*/
status: NodeStatus;
}
export interface NodesQuery {
/**
* all known network nodes
* All known network nodes
*/
nodes: NodesQuery_nodes[] | null;
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -89,7 +89,7 @@
"tranche_end": "2022-10-12T00:53:20.000Z",
"total_added": "1010.000000000000000001",
"total_removed": "668.4622323651",
"locked_amount": "53.36134639776761480005283301623541348",
"locked_amount": "36.75072805682389880003638685946220188",
"deposits": [
{
"amount": "1000",
+7 -13
View File
@@ -1,24 +1,18 @@
import { EnvironmentProvider, NetworkLoader } from '@vegaprotocol/environment';
import { Header } from './components/header';
import { StatsManager } from '@vegaprotocol/network-stats';
import { ThemeContext } from '@vegaprotocol/react-helpers';
import { useThemeSwitcher } from '@vegaprotocol/react-helpers';
import { createClient } from './lib/apollo-client';
function App() {
const [theme, toggleTheme] = useThemeSwitcher();
return (
<ThemeContext.Provider value={theme}>
<NetworkLoader createClient={createClient}>
<div className="w-screen min-h-screen grid pb-24 bg-white text-neutral-900 dark:bg-black dark:text-neutral-100">
<div className="layout-grid w-screen justify-self-center">
<Header theme={theme} toggleTheme={toggleTheme} />
<StatsManager className="max-w-3xl px-24" />
</div>
<NetworkLoader createClient={createClient}>
<div className="w-screen min-h-screen grid pb-24 bg-white text-neutral-900 dark:bg-black dark:text-neutral-100">
<div className="layout-grid w-screen justify-self-center">
<Header />
<StatsManager className="max-w-3xl px-24" />
</div>
</NetworkLoader>
</ThemeContext.Provider>
</div>
</NetworkLoader>
);
}
+2 -8
View File
@@ -1,20 +1,14 @@
import { VegaLogo, ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
import { VegaBackgroundVideo } from '../videos';
interface ThemeToggleProps {
theme: 'light' | 'dark';
toggleTheme: () => void;
}
export const Header = ({ theme, toggleTheme }: ThemeToggleProps) => {
export const Header = () => {
return (
<header className="relative overflow-hidden py-8 mb-40 md:mb-64">
<VegaBackgroundVideo />
<div className="relative flex justify-center px-8 dark:bg-black bg-white">
<div className="w-full max-w-3xl p-20 flex items-center justify-between">
<VegaLogo />
<ThemeSwitcher theme={theme} onToggle={toggleTheme} />
<ThemeSwitcher />
</div>
</div>
</header>
@@ -63,7 +63,10 @@ context(
.and('have.text', 'There are no enacted or rejected proposals');
});
it('should be able to see a connect wallet button - if vega wallet disconnected and new proposal button selected', function () {
// Skipping this test for now, the new proposal button no longer takes a user directly
// to a proposal form, instead it takes them to a page where they can select a proposal type.
// Keeping this test here for now as it can be repurposed to test the new proposal forms.
it.skip('should be able to see a connect wallet button - if vega wallet disconnected and new proposal button selected', function () {
cy.get(newProposalButton).should('be.visible').click();
cy.get(connectToVegaWalletButton)
.should('be.visible')
@@ -23,6 +23,9 @@ const manageLink = '[data-testid="manage-vega-wallet"]';
const dialogVegaKey = '[data-testid="vega-public-key-full"]';
const dialogDisconnectBtn = '[data-testid="disconnect"]';
const copyPublicKeyBtn = '[data-testid="copy-vega-public-key"]';
const vegaWalletCurrencyTitle = '[data-testid="currency-title"]';
const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey');
const txTimeout = Cypress.env('txTimeout');
context(
'Vega Wallet - verify elements on widget',
@@ -282,5 +285,136 @@ context(
});
});
});
describe('when assets exist in vegawallet', function () {
before('send-faucet assets to connected vega wallet', function () {
cy.vega_wallet_receive_fauceted_asset(
'USDC (fake)',
'10',
vegaWalletPublicKey
);
cy.vega_wallet_receive_fauceted_asset(
'BTC (fake)',
'6',
vegaWalletPublicKey
);
cy.vega_wallet_receive_fauceted_asset(
'EURO (fake)',
'8',
vegaWalletPublicKey
);
cy.vega_wallet_receive_fauceted_asset(
'DAI (fake)',
'2',
vegaWalletPublicKey
);
// cy.vega_wallet_connect(); - to be changed when dialog state is fixed - https://github.com/vegaprotocol/frontend-monorepo/issues/838
// then code below can be removed
cy.get(walletContainer).within(() => {
cy.get('button')
.contains('Connect Vega wallet to use associated $VEGA')
.should('be.enabled')
.and('be.visible')
.click({ force: true });
});
cy.get(restConnectorForm).within(() => {
cy.get('#wallet').click().type(Cypress.env('vegaWalletName'));
cy.get('#passphrase')
.click()
.type(Cypress.env('vegaWalletPassphrase'));
cy.get('button').contains('Connect').click();
});
cy.ethereum_wallet_connect();
});
it('should see fUSDC assets - within vega wallet', function () {
let currency = { id: 'fUSDC', name: 'USDC (fake)' };
cy.get(walletContainer).within(() => {
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id, txTimeout)
.should('be.visible');
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id)
.parent()
.siblings()
.within(() => cy.contains_exactly('10.00000').should('be.visible'));
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id)
.parent()
.contains(currency.name);
});
});
it('should see fBTC assets - within vega wallet', function () {
let currency = { id: 'fBTC', name: 'BTC (fake)' };
cy.get(walletContainer).within(() => {
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id, txTimeout)
.should('be.visible');
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id)
.parent()
.siblings()
.within(() => cy.contains_exactly('6.00000').should('be.visible'));
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id)
.parent()
.contains(currency.name);
});
});
it('should see fEURO assets - within vega wallet', function () {
let currency = { id: 'fEURO', name: 'EURO (fake)' };
cy.get(walletContainer).within(() => {
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id, txTimeout)
.should('be.visible');
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id)
.parent()
.siblings()
.within(() => cy.contains_exactly('8.00000').should('be.visible'));
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id)
.parent()
.contains(currency.name);
});
});
it('should see fDAI assets - within vega wallet', function () {
let currency = { id: 'fDAI', name: 'DAI (fake)' };
cy.get(walletContainer).within(() => {
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id, txTimeout)
.should('be.visible');
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id)
.parent()
.siblings()
.within(() => cy.contains_exactly('2.00000').should('be.visible'));
cy.get(vegaWalletCurrencyTitle)
.contains(currency.id)
.parent()
.contains(currency.name);
});
});
after(
'teardown environment to prevent test data bleeding into other tests',
function () {
if (Cypress.env('CYPRESS_TEARDOWN_NETWORK_AFTER_FLOWS')) {
cy.restartVegacapsuleNetwork();
}
}
);
});
}
);
@@ -17,6 +17,10 @@ const navigation = {
pageSpinner: '[data-testid="splash-loader"]',
};
Cypress.Commands.add('contains_exactly', (expected_result) => {
return cy.contains(new RegExp('^' + expected_result + '$', 'g'));
});
Cypress.Commands.add('navigate_to', (page) => {
return cy.get(navigation.section, { timeout: 10000 }).within(() => {
cy.get(navigation[page]).click({ force: true });
@@ -15,12 +15,6 @@ Cypress.Commands.add('vega_wallet_import', () => {
cy.exec(
`vega wallet service run --network DV --automatic-consent --home ${vegaWalletLocation}`
);
cy.exec(`vega wallet version`)
.its('stdout')
.then((output) => {
cy.log(output);
});
});
Cypress.Commands.add('vega_wallet_connect', () => {
+1
View File
@@ -7,3 +7,4 @@ NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/docs/testnet
+1
View File
@@ -7,3 +7,4 @@ NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9
NX_ETHERSCAN_URL=https://etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/docs/mainnet
+1
View File
@@ -7,6 +7,7 @@ NX_VEGA_ENV=STAGNET3
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_EXPLORER_URL=https://staging3.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/docs/testnet
# App flags
NX_EXPLORER_ASSETS=1
+1
View File
@@ -7,3 +7,4 @@ NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9
NX_ETHERSCAN_URL=https://ropsten.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_DOCS_URL=https://docs.vega.xyz/docs/testnet
@@ -12,7 +12,7 @@ import { AccountType } from "@vegaprotocol/types";
export interface Delegations_epoch {
__typename: "Epoch";
/**
* Presumably this is an integer or something. If there's no such thing, disregard
* Numeric sequence number used to identify the epoch
*/
id: string;
}
@@ -131,7 +131,7 @@ export interface Delegations_party {
export interface Delegations {
/**
* get data for a specific epoch, if ID omitted it gets the current epoch. If the string is 'next', fetch the next epoch
* Get data for a specific epoch, if ID omitted it gets the current epoch. If the string is 'next', fetch the next epoch
*/
epoch: Delegations_epoch;
/**
+2
View File
@@ -48,6 +48,8 @@ export const ENV = {
// Environment
dsn: windowOrDefault('NX_SENTRY_DSN'),
urlConnect: TRUTHY.includes(windowOrDefault('NX_ETH_URL_CONNECT')),
explorerUrl: windowOrDefault('NX_VEGA_EXPLORER'),
docsUrl: windowOrDefault('NX_VEGA_DOCS_URL'),
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
flags: {
+1 -1
View File
@@ -1,3 +1,3 @@
export * from './flags';
export * from './links';
export * from './network-params';
export * from './env';
+1
View File
@@ -11,4 +11,5 @@ export const Links = {
STAKING_GUIDE:
'https://docs.vega.xyz/docs/mainnet/concepts/vega-chain/#staking-on-vega',
GOVERNANCE_PAGE: 'https://vega.xyz/governance',
PROPOSALS_GUIDE: 'https://docs.vega.xyz/docs/mainnet/tutorials/proposals',
};
-25
View File
@@ -1,25 +0,0 @@
export const NetworkParams = {
ETHEREUM_CONFIG: 'blockchains.ethereumConfig',
REWARD_ASSET: 'reward.asset',
REWARD_PAYOUT_DURATION: 'reward.staking.delegation.payoutDelay',
GOV_UPDATE_MARKET_REQUIRED_MAJORITY:
'governance.proposal.updateMarket.requiredMajority',
GOV_UPDATE_MARKET_REQUIRED_PARTICIPATION:
'governance.proposal.updateMarket.requiredParticipation',
GOV_NEW_MARKET_REQUIRED_MAJORITY:
'governance.proposal.market.requiredMajority',
GOV_NEW_MARKET_REQUIRED_PARTICIPATION:
'governance.proposal.market.requiredParticipation',
GOV_ASSET_REQUIRED_MAJORITY: 'governance.proposal.asset.requiredMajority',
GOV_ASSET_REQUIRED_PARTICIPATION:
'governance.proposal.asset.requiredParticipation',
GOV_UPDATE_NET_PARAM_REQUIRED_MAJORITY:
'governance.proposal.updateNetParam.requiredMajority',
GOV_UPDATE_NET_PARAM_REQUIRED_PARTICIPATION:
'governance.proposal.updateNetParam.requiredParticipation',
GOV_FREEFORM_REQUIRED_PARTICIPATION:
'governance.proposal.freeform.requiredParticipation',
GOV_FREEFORM_REQUIRED_MAJORITY:
'governance.proposal.freeform.requiredMajority',
VALIDATOR_DELEGATION_MIN_AMOUNT: 'validators.delegation.minAmount',
};
+56 -2
View File
@@ -630,8 +630,62 @@
"FilterProposalsDescription": "Filter by proposal ID or proposer ID",
"Freeform proposal": "Freeform proposal",
"NewProposal": "New proposal",
"MinProposalRequirements": "You must have at least 1 VEGA associated to make a proposal",
"ProposalTypeQuestion": "What type of proposal would you like to make?",
"NetworkParameterProposal": "Update network parameter proposal",
"NewMarketProposal": "New market proposal",
"UpdateMarketProposal": "Update market proposal",
"NewAssetProposal": "New asset proposal",
"NewFreeformProposal": "New freeform proposal",
"NewRawProposal": "New raw proposal",
"MinProposalRequirements": "You must have at least {{value}} VEGA associated to make a proposal",
"totalSupply": "Total Supply",
"viaWallet": "via wallet",
"viaContract": "via vesting"
"viaContract": "via vesting",
"ProposalDocsPrefix": "For guidance on how to make proposals, see",
"NetworkParameter": "Network parameter",
"NewMarket": "New market",
"UpdateMarket": "Update market",
"NewAsset": "New asset",
"Freeform": "Freeform",
"RawProposal": "Let me choose (raw proposal)",
"UseMin": "Use minimum",
"UseMax": "Use maximum",
"Proposal": "Proposal",
"ProposalRationale": "Proposal rationale",
"ProposalTitle": "Title",
"ProposalTitleText": "Tell people what you are proposing and why (100 characters or less)",
"ProposalsGuide": "proposals guide",
"ProposalDescription": "Description",
"ProposalDescriptionText": "Full justification for what you are proposing (20,000 characters or less). Markdown is recommended. When linking to external resources please use IPFS",
"ProposalTerms": "Proposal terms (JSON format)",
"ProposalTermsText": "For more information visit",
"ProposalReference": "Reference",
"ProposalVoteTitle": "Vote deadline",
"ProposalVoteAndEnactmentTitle": "Vote deadline and enactment",
"ProposalVoteDeadline": "Time till voting closes",
"ProposalEnactmentDeadline": "Time till enactment (after vote close)",
"ProposalValidationDeadline": "Time till ERC-20 asset validation. Maximum value is affected by the vote deadline.",
"ThisWillSetVotingDeadlineTo": "This will set the voting deadline to",
"ThisWillSetEnactmentDeadlineTo": "This will set the enactment date to",
"ThisWillSetValidationDeadlineTo": "This will set the validation deadline to",
"Hours": "hours",
"ThisWillAdd2MinutesToAllowTimeToConfirmInWallet": "Note: we add 2 minutes of extra time when you choose the minimum value. This gives you time to confirm the proposal in your wallet.",
"SelectAMarketToChange": "Select a market to change",
"MarketName": "Market name",
"MarketCode": "Market code",
"MarketId": "Market ID",
"ProposeNewMarketTerms": "terms.changes.newMarket (JSON format)",
"ProposeUpdateMarketTerms": "terms.updateMarket.changes (JSON format)",
"SelectAParameterToChange": "Select a parameter to change",
"SelectParameter": "Select parameter",
"SelectMarket": "Select market",
"CurrentValue": "Current value",
"NewProposedValue": "New proposed value",
"MoreProposalsInfo": "To see Explorer data on proposals visit",
"MoreNetParamsInfo": "To see Explorer data on network params visit",
"MoreMarketsInfo": "To see Explorer data on existing markets visit",
"MoreAssetsInfo": "To see Explorer data on existing assets visit",
"ProposalNotFound": "Proposal not found",
"ProposalNotFoundDetails": "The proposal you are looking for is not here, it may have been enacted before the last chain restore. You could check the Vega forums/discord instead for information about it.",
"FreeformProposal": "Freeform proposal"
}
+4 -1
View File
@@ -6,8 +6,11 @@ import { useEnvironment } from '@vegaprotocol/environment';
import { Heading } from '../../components/heading';
import { SplashLoader } from '../../components/splash-loader';
import { ENV } from '../../config/env';
import type { RouteChildProps } from '../index';
import { useDocumentTitle } from '../../hooks/use-document-title';
const Contracts = () => {
const Contracts = ({ name }: RouteChildProps) => {
useDocumentTitle(name);
const { config } = useEthereumConfig();
const { ETHERSCAN_URL } = useEnvironment();
@@ -49,6 +49,15 @@ fragment ProposalFields on Proposal {
value
}
}
... on UpdateAsset {
quantum
source {
... on UpdateERC20 {
lifetimeLimit
withdrawThreshold
}
}
}
}
}
votes {
@@ -33,8 +33,8 @@ export interface ProposalFields_party {
id: string;
}
export interface ProposalFields_terms_change_UpdateAsset {
__typename: "UpdateAsset" | "NewFreeform";
export interface ProposalFields_terms_change_NewFreeform {
__typename: "NewFreeform";
}
export interface ProposalFields_terms_change_NewMarket_instrument_futureProduct_settlementAsset {
@@ -133,7 +133,33 @@ export interface ProposalFields_terms_change_UpdateNetworkParameter {
networkParameter: ProposalFields_terms_change_UpdateNetworkParameter_networkParameter;
}
export type ProposalFields_terms_change = ProposalFields_terms_change_UpdateAsset | ProposalFields_terms_change_NewMarket | ProposalFields_terms_change_UpdateMarket | ProposalFields_terms_change_NewAsset | ProposalFields_terms_change_UpdateNetworkParameter;
export interface ProposalFields_terms_change_UpdateAsset_source {
__typename: "UpdateERC20";
/**
* The lifetime limits deposit per address
* Note: this is a temporary measure for alpha mainnet
*/
lifetimeLimit: string;
/**
* The maximum allowed per withdrawal
* Note: this is a temporary measure for alpha mainnet
*/
withdrawThreshold: string;
}
export interface ProposalFields_terms_change_UpdateAsset {
__typename: "UpdateAsset";
/**
* The minimum economically meaningful amount of this specific asset
*/
quantum: string;
/**
* The source of the updated asset
*/
source: ProposalFields_terms_change_UpdateAsset_source;
}
export type ProposalFields_terms_change = ProposalFields_terms_change_NewFreeform | ProposalFields_terms_change_NewMarket | ProposalFields_terms_change_UpdateMarket | ProposalFields_terms_change_NewAsset | ProposalFields_terms_change_UpdateNetworkParameter | ProposalFields_terms_change_UpdateAsset;
export interface ProposalFields_terms {
__typename: "ProposalTerms";
@@ -293,7 +319,7 @@ export interface ProposalFields {
*/
datetime: string;
/**
* Reason for the proposal to be rejected by the core
* Why the proposal was rejected by the core
*/
rejectionReason: ProposalRejectionReason | null;
/**
@@ -3,19 +3,19 @@ import { Schema as Types } from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type ProposalFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: string, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: string, enactmentDatetime?: string | null, change: { __typename: 'NewAsset', name: string, symbol: string, source: { __typename: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename: 'ERC20', contractAddress: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', decimalPlaces: number, metadata?: Array<string> | null, instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null } } };
export type ProposalFieldsFragment = { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: string, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: string, enactmentDatetime?: string | null, change: { __typename: 'NewAsset', name: string, symbol: string, source: { __typename: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename: 'ERC20', contractAddress: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', decimalPlaces: number, metadata?: Array<string> | null, instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'UpdateAsset', quantum: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null } } };
export type ProposalQueryVariables = Types.Exact<{
proposalId: Types.Scalars['ID'];
}>;
export type ProposalQuery = { __typename?: 'Query', proposal?: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: string, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: string, enactmentDatetime?: string | null, change: { __typename: 'NewAsset', name: string, symbol: string, source: { __typename: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename: 'ERC20', contractAddress: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', decimalPlaces: number, metadata?: Array<string> | null, instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null } } } | null };
export type ProposalQuery = { __typename?: 'Query', proposal?: { __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: string, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: string, enactmentDatetime?: string | null, change: { __typename: 'NewAsset', name: string, symbol: string, source: { __typename: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename: 'ERC20', contractAddress: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', decimalPlaces: number, metadata?: Array<string> | null, instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'UpdateAsset', quantum: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null } } } | null };
export type ProposalsQueryVariables = Types.Exact<{ [key: string]: never; }>;
export type ProposalsQuery = { __typename?: 'Query', proposals?: Array<{ __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: string, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: string, enactmentDatetime?: string | null, change: { __typename: 'NewAsset', name: string, symbol: string, source: { __typename: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename: 'ERC20', contractAddress: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', decimalPlaces: number, metadata?: Array<string> | null, instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'UpdateAsset' } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null } } }> | null };
export type ProposalsQuery = { __typename?: 'Query', proposals?: Array<{ __typename?: 'Proposal', id?: string | null, reference: string, state: Types.ProposalState, datetime: string, rejectionReason?: Types.ProposalRejectionReason | null, errorDetails?: string | null, party: { __typename?: 'Party', id: string }, terms: { __typename?: 'ProposalTerms', closingDatetime: string, enactmentDatetime?: string | null, change: { __typename: 'NewAsset', name: string, symbol: string, source: { __typename: 'BuiltinAsset', maxFaucetAmountMint: string } | { __typename: 'ERC20', contractAddress: string } } | { __typename?: 'NewFreeform' } | { __typename?: 'NewMarket', decimalPlaces: number, metadata?: Array<string> | null, instrument: { __typename?: 'InstrumentConfiguration', name: string, code: string, futureProduct?: { __typename?: 'FutureProduct', settlementAsset: { __typename?: 'Asset', symbol: string } } | null } } | { __typename?: 'UpdateAsset', quantum: string, source: { __typename?: 'UpdateERC20', lifetimeLimit: string, withdrawThreshold: string } } | { __typename?: 'UpdateMarket', marketId: string } | { __typename?: 'UpdateNetworkParameter', networkParameter: { __typename?: 'NetworkParameter', key: string, value: string } } }, votes: { __typename?: 'ProposalVotes', yes: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null }, no: { __typename?: 'ProposalVoteSide', totalTokens: string, totalNumber: string, votes?: Array<{ __typename?: 'Vote', value: Types.VoteValue, datetime: string, party: { __typename?: 'Party', id: string, stake: { __typename?: 'PartyStake', currentStakeAvailable: string } } }> | null } } }> | null };
export const ProposalFieldsFragmentDoc = gql`
fragment ProposalFields on Proposal {
@@ -69,6 +69,15 @@ export const ProposalFieldsFragmentDoc = gql`
value
}
}
... on UpdateAsset {
quantum
source {
... on UpdateERC20 {
lifetimeLimit
withdrawThreshold
}
}
}
}
}
votes {
@@ -63,7 +63,7 @@ export const CurrentProposalStatus = ({
<>
<span>{t('voteFailedReason')}</span>
<StatusFail>{t('participationNotMet')}</StatusFail>
<span>&nbsp;{daysClosedAgo}.</span>
<span>&nbsp;{daysClosedAgo}</span>
</>
);
}
@@ -73,7 +73,7 @@ export const CurrentProposalStatus = ({
<>
<span>{t('voteFailedReason')}</span>
<StatusFail>{t('majorityNotMet')}</StatusFail>
<span>&nbsp;{daysClosedAgo}.</span>
<span>&nbsp;{daysClosedAgo}</span>
</>
);
}
@@ -82,7 +82,7 @@ export const CurrentProposalStatus = ({
<>
<span>{t('voteFailedReason')}</span>
<StatusFail>{proposal.state}</StatusFail>
<span>&nbsp;{daysClosedAgo}.</span>
<span>&nbsp;{daysClosedAgo}</span>
</>
);
}
@@ -99,7 +99,6 @@ export const CurrentProposalStatus = ({
{proposal.state === ProposalState.STATE_ENACTED
? daysEnactedAgo
: daysClosedAgo}
.
</span>
</>
);
@@ -79,6 +79,28 @@ it('Changes data based on if data is in future or past', () => {
).toBeInTheDocument();
});
it('Does not render enactment time for freeform proposal', () => {
const proposal = generateProposal({
state: ProposalState.STATE_ENACTED,
terms: {
__typename: 'ProposalTerms',
change: {
__typename: 'NewFreeform',
},
},
});
render(<ProposalChangeTable proposal={proposal} />);
expect(screen.queryByText('Enacted on')).not.toBeInTheDocument();
expect(
screen.queryByText(
format(
new Date(proposal.terms.enactmentDatetime || 0),
DATE_FORMAT_DETAILED
)
)
).not.toBeInTheDocument();
});
it('Renders error details and rejection reason if present', () => {
const errorDetails = 'Error message';
const proposal = generateProposal({
@@ -31,12 +31,14 @@ export const ProposalChangeTable = ({ proposal }: ProposalChangeTableProps) => {
: t('closedOn')}
{format(new Date(terms.closingDatetime), DATE_FORMAT_DETAILED)}
</KeyValueTableRow>
<KeyValueTableRow>
{isFuture(new Date(terms.enactmentDatetime || 0))
? t('proposedEnactment')
: t('enactedOn')}
{format(new Date(terms.enactmentDatetime || 0), DATE_FORMAT_DETAILED)}
</KeyValueTableRow>
{terms.change.__typename !== 'NewFreeform' ? (
<KeyValueTableRow>
{isFuture(new Date(terms.enactmentDatetime || 0))
? t('proposedEnactment')
: t('enactedOn')}
{format(new Date(terms.enactmentDatetime || 0), DATE_FORMAT_DETAILED)}
</KeyValueTableRow>
) : null}
<KeyValueTableRow>
{t('proposedBy')}
<span style={{ wordBreak: 'break-word' }}>{proposal.party.id}</span>
@@ -1,9 +1,9 @@
import { render, screen } from '@testing-library/react';
import { generateProposal } from '../../test-helpers/generate-proposals';
import { ProposalHeader } from './proposal-header';
import type { Proposal_proposal } from '@vegaprotocol/governance';
import type { ProposalFields } from '../../__generated__/ProposalFields';
const renderComponent = (proposal: Proposal_proposal) => (
const renderComponent = (proposal: ProposalFields) => (
<ProposalHeader proposal={proposal} />
);
@@ -234,6 +234,23 @@ describe('Proposal header', () => {
);
});
it('Renders asset change proposal header', () => {
render(
renderComponent(
generateProposal({
terms: {
change: {
__typename: 'UpdateAsset',
},
},
})
)
);
expect(screen.getByTestId('proposal-details')).toHaveTextContent(
'Update asset'
);
});
it("Renders unknown proposal if it's a different proposal type", () => {
render(
renderComponent(
@@ -73,8 +73,11 @@ export const ProposalHeader = ({ proposal }: { proposal: ProposalFields }) => {
break;
}
case 'NewFreeform': {
details = `${proposal.id}`;
details = `${t('FreeformProposal')}: ${proposal.id}`;
break;
}
case 'UpdateAsset': {
details = `${t('Update asset')}`;
break;
}
}
@@ -0,0 +1 @@
export { ProposalNotFound } from './proposal-not-found';
@@ -0,0 +1,14 @@
import { render, screen } from '@testing-library/react';
import { ProposalNotFound } from './proposal-not-found';
describe('Proposal container', () => {
it('Renders not found if the proposal is not found', () => {
render(<ProposalNotFound />);
expect(screen.getByText('Proposal not found')).toBeInTheDocument();
expect(
screen.getByText(
'The proposal you are looking for is not here, it may have been enacted before the last chain restore. You could check the Vega forums/discord instead for information about it.'
)
).toBeInTheDocument();
});
});
@@ -0,0 +1,15 @@
import { useTranslation } from 'react-i18next';
export const ProposalNotFound = () => {
const { t } = useTranslation();
return (
<section data-testid="proposal-not-found">
<header>
<h2 className="text-lg mx-0 mt-0 mb-1 font-semibold">
{t('ProposalNotFound')}
</h2>
</header>
<p>{t('ProposalNotFoundDetails')}</p>
</section>
);
};
@@ -0,0 +1,8 @@
export * from './proposal-form-subheader';
export * from './proposal-form-min-requirements';
export * from './proposal-form-title';
export * from './proposal-form-description';
export * from './proposal-form-terms';
export * from './proposal-form-submit';
export * from './proposal-form-transaction-dialog';
export * from './proposal-form-vote-and-enactment-deadline';
@@ -0,0 +1,15 @@
import { render, screen } from '@testing-library/react';
import { ProposalFormDescription } from './proposal-form-description';
describe('Proposal Form Description', () => {
it('should display error text', () => {
const register = jest.fn();
render(
<ProposalFormDescription
registerField={register('proposalDescription')}
errorMessage="Error text"
/>
);
expect(screen.getByText('Error text')).toBeInTheDocument();
});
});
@@ -0,0 +1,32 @@
import { useTranslation } from 'react-i18next';
import { FormGroup, InputError, TextArea } from '@vegaprotocol/ui-toolkit';
import type { UseFormRegisterReturn } from 'react-hook-form';
interface ProposalFormDescriptionProps {
registerField: UseFormRegisterReturn<'proposalDescription'>;
errorMessage: string | undefined;
}
export const ProposalFormDescription = ({
registerField: register,
errorMessage,
}: ProposalFormDescriptionProps) => {
const { t } = useTranslation();
return (
<FormGroup
label={t('ProposalDescription')}
labelDescription={t('ProposalDescriptionText')}
labelFor="proposal-description"
>
<TextArea
id="proposal-description"
maxLength={20000}
className="min-h-[200px]"
hasError={Boolean(errorMessage)}
data-testid="proposal-description"
{...register}
/>
{errorMessage && <InputError intent="danger">{errorMessage}</InputError>}
</FormGroup>
);
};
@@ -0,0 +1,32 @@
import { render } from '@testing-library/react';
import { ProposalFormMinRequirements } from './proposal-form-min-requirements';
describe('ProposalFormMinRequirements', () => {
it('should render successfully with spam protection value, if larger', () => {
const { baseElement } = render(
<ProposalFormMinRequirements
minProposerBalance="1000000000000000000"
spamProtectionMin="2000000000000000000"
/>
);
expect(baseElement).toBeTruthy();
expect(baseElement).toHaveTextContent(
'You must have at least 2 VEGA associated to make a proposal'
);
});
it('should render successfully with min proposer value, if larger', () => {
const { baseElement } = render(
<ProposalFormMinRequirements
minProposerBalance="3000000000000000000"
spamProtectionMin="1000000000000000000"
/>
);
expect(baseElement).toBeTruthy();
expect(baseElement).toHaveTextContent(
'You must have at least 3 VEGA associated to make a proposal'
);
});
});
@@ -0,0 +1,30 @@
import { useTranslation } from 'react-i18next';
import BigNumber from 'bignumber.js';
import { addDecimal } from '@vegaprotocol/react-helpers';
interface ProposalFormMinRequirementsProps {
minProposerBalance: string | undefined;
spamProtectionMin: string | undefined;
}
export const ProposalFormMinRequirements = ({
minProposerBalance,
spamProtectionMin,
}: ProposalFormMinRequirementsProps) => {
const { t } = useTranslation();
const minProposerBalanceFormatted =
minProposerBalance && new BigNumber(addDecimal(minProposerBalance, 18));
const spamProtectionMinFormatted =
spamProtectionMin && new BigNumber(addDecimal(spamProtectionMin, 18));
const larger =
Number(minProposerBalanceFormatted) > (spamProtectionMinFormatted || 0)
? minProposerBalanceFormatted
: spamProtectionMinFormatted;
return (
<p className="mb-4" data-testid="min-proposal-requirements">
{t('MinProposalRequirements', { value: larger })}
</p>
);
};
@@ -0,0 +1,9 @@
import type { ReactNode } from 'react';
interface ProposalFormSubheaderProps {
children: ReactNode;
}
export const ProposalFormSubheader = ({
children,
}: ProposalFormSubheaderProps) => <h2 className="mt-8 mb-4">{children}</h2>;
@@ -0,0 +1,24 @@
import { useTranslation } from 'react-i18next';
import { Button } from '@vegaprotocol/ui-toolkit';
interface ProposalFormSubmitProps {
isSubmitting: boolean;
}
export const ProposalFormSubmit = ({
isSubmitting,
}: ProposalFormSubmitProps) => {
const { t } = useTranslation();
return (
<div className="mt-10 my-20">
<Button
variant="primary"
type="submit"
data-testid="proposal-submit"
disabled={isSubmitting}
>
{isSubmitting ? t('Submitting') : t('Submit')} {t('Proposal')}
</Button>
</div>
);
};
@@ -0,0 +1,51 @@
import { render, screen } from '@testing-library/react';
import { ProposalFormTerms } from './proposal-form-terms';
jest.mock('@vegaprotocol/environment', () => ({
useEnvironment: () => ({
VEGA_DOCS_URL: 'https://docs.vega.xyz',
}),
}));
const renderComponent = () => {
const register = jest.fn();
render(
<ProposalFormTerms
registerField={register('proposalTerms')}
errorMessage="Error text"
/>
);
};
describe('Proposal Form Terms', () => {
it('should render', () => {
renderComponent();
expect(screen.getByTestId('proposal-terms')).toBeTruthy();
});
it('should display error text', () => {
renderComponent();
expect(screen.getByText('Error text')).toBeInTheDocument();
});
it('should render the generic docs link if no custom override', () => {
renderComponent();
expect(
screen.getByText('https://docs.vega.xyz/tutorials/proposals')
).toBeInTheDocument();
});
it('should render the custom docs link if provided', () => {
const register = jest.fn();
render(
<ProposalFormTerms
registerField={register('proposalTerms')}
errorMessage="Error text"
customDocLink="/custom"
/>
);
expect(
screen.getByText('https://docs.vega.xyz/tutorials/proposals/custom')
).toBeInTheDocument();
});
});
@@ -0,0 +1,51 @@
import { useTranslation } from 'react-i18next';
import {
FormGroup,
InputError,
Link,
TextArea,
} from '@vegaprotocol/ui-toolkit';
import { useEnvironment } from '@vegaprotocol/environment';
import type { UseFormRegisterReturn } from 'react-hook-form';
interface ProposalFormTermsProps {
registerField: UseFormRegisterReturn<'proposalTerms'>;
errorMessage: string | undefined;
labelOverride?: string;
customDocLink?: string;
}
export const ProposalFormTerms = ({
registerField: register,
errorMessage,
labelOverride,
customDocLink,
}: ProposalFormTermsProps) => {
const { VEGA_DOCS_URL } = useEnvironment();
const { t } = useTranslation();
return (
<FormGroup
label={labelOverride || t('ProposalTerms')}
labelFor="proposal-terms"
>
{VEGA_DOCS_URL && (
<div className="mt-[-4px] mb-2 text-sm font-light">
<span className="mr-1">{t('ProposalTermsText')}</span>
<Link
href={`${VEGA_DOCS_URL}/tutorials/proposals${customDocLink || ''}`}
target="_blank"
>{`${VEGA_DOCS_URL}/tutorials/proposals${customDocLink || ''}`}</Link>
</div>
)}
<TextArea
id="proposal-terms"
className="min-h-[200px]"
hasError={Boolean(errorMessage)}
data-testid="proposal-terms"
{...register}
/>
{errorMessage && <InputError intent="danger">{errorMessage}</InputError>}
</FormGroup>
);
};
@@ -0,0 +1,15 @@
import { render, screen } from '@testing-library/react';
import { ProposalFormTitle } from './proposal-form-title';
describe('Proposal Form Title', () => {
it('should display error text', () => {
const register = jest.fn();
render(
<ProposalFormTitle
registerField={register('proposalTitle')}
errorMessage="Error text"
/>
);
expect(screen.getByText('Error text')).toBeInTheDocument();
});
});

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