Compare commits

...
Author SHA1 Message Date
Matthew Russell 7fc6e10d64 ci: separate capsule test run from non capsule test run 2022-09-30 19:32:15 -07:00
m.ray c221d0772c fix: 1569 trading tab navigation update (#1573)
* fix: #1569 trading tab navigation update

* fix: #1569 get market id value from init
2022-09-30 16:50:48 +01:00
Radosław Szpiech efcd128240 fix: console-lite e2e tests (#1576) 2022-09-30 16:51:41 +02:00
Radosław Szpiechandasiaznik 9a88c33458 Fix/console failing tests (#1572)
* fix: market and trading tests

* fix: trading tests

* fix: balance DP

* fix: select asset

* fix: withdrawal tests

Co-authored-by: asiaznik <artur@vegaprotocol.io>
2022-09-30 15:42:42 +02:00
mattrussell36 d2a5adf6ce chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-30 12:04:57 +00:00
Radosław Szpiech ab0065bd9a chore: env setup fixed (#1567) 2022-09-30 11:02:55 +02:00
Radosław Szpiech 5600c56da1 fix: fix (#1565) 2022-09-30 10:59:15 +02:00
Radosław Szpiech 3d7267f496 fix: fix capsule workflow (#1563) 2022-09-30 10:31:38 +02:00
mattrussell36 c87beb4050 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-30 06:25:43 +00:00
m.rayandBartłomiej Głownia 907a4e256e feat(#847): collateral table, add breakdown (#1442)
* feat: #847 show progress bar, margin accounts, no used/deposited

* feat: #847 add collateral tables

* fix: #847 add deposit asset type and fix tests

* feat: #847 show deposited value, avaliable and percentage used

* fix: #847 add styling fixes

* fix: #847 add deposit new asset button

* fix: #847 remove disabledSelect
to fix withdraw and deposit dialogs

* fix: #847 remove global reward from incoming - needs to be party specific

* fix: #847 integration tests

* fix: #847 default select deposit & withdraw

* fix: #847 default select deposit & withdraw

* fix: #847 pass asset id as default value

* fix:  #847 use only bigint no bignumber, remove NaN check

* fix:  #847 update deposit-form.spec.tsx

* fix: revert update on account fields

* feat: add storybook set up

* chore: ignore apollo errors - to be reverted after API will be fixed

* fix: container moved, progress bar in helpers

* fix: #847 UI tweaks around accounts container

* feat: #847 added useDepositAsset and useWithdrawAsset

* fix: #847 fix progress bar in accounts and positions

* feat: #847 add storybook

* fix: #847 added tooltip and updated filtering

* chore: #847 add get account data test

* fix: #847 fix lint and type in account story

* fix:  #847 update data provider

* fix: #847 fix get account data dry & lp link

* fix: #847 fix breakdown table test

* fix: #847 account data provider test

* fix: #847 remove deposit new asset button - subscription does not display a
sset data

* fix: #847 add defaultValue in select otherwise default is not set up

* feat: #847 update data provider update method and tables

* fix: #847 fix accounts tests

* fix: #847 remove unused getRows

* fix: add decimals

* fix: #847 fix imports

* fix: update ids

* Update apps/trading/pages/liquidity/[marketId].page.tsx

* fix: #847 accounts update method check delta

* fix: #847 use vega value formatters and cell renderers

* fix: #847 fix imports

* fix: #847 handle new account else block comment

* fix: accounts and breakdown tables

* fix(#847): account data provider improvments

* fix: #847 fix formatters null check and add param

* fix: #847 fix withdraw test and mock the hook

* fix: #847 fix console lite grid select market test

* fix: console lite build

* fix: revert withdraw limits

* fix: remove redundant waitFor use vega cell renderer

* fix: breakdown display only use accounts

* fix: breakdown display only use accounts

* fix: updated accounts table

* fix: move update inside try useWithdrawAsset

* fix: update trading-accounts test

* fix: portfolio-page.test.ts

Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
2022-09-29 17:40:44 -07:00
mattrussell36 835bf36393 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-30 00:17:39 +00:00
John Walley 57863a7167 chore(deps): update dependency pennant to v0.4.18 (#1557) 2022-09-29 16:47:36 -07:00
Sam KeenandDexter 4272fefb0b feat(#807): adds app for validator add and remove signer (#1402)
* Feat/807: ABI and classes for the contract methods

* Feat/807: Added a new multisig-signer app

* Feat/807: Added a new multisig-signer app

* Feat/800: Untested signer forms

* Feat/800: Moved reused bg video into ui-toolkit to use in multisig-signer project, and cleaned up some spacing that was overlooked in the stats theme changes

* Feat/800: Componentised a bit, made the app look ok

* Feat/800: Linting, prettifying, removing some unneeded tests, ensuring e2e tests run

* Feat/800: Bit of translation

* chore: fix type errors

* chore: some parts error handling

* feat: handle error and not found cases

* feat: add changes to remove signer form as well

* chore: rename component

* chore: fix type issues

* feat: add web3 connector logic

* feat: allow disconnecting and show connected eth wallet info

* Feat/800: Removed unused 'useApolloClient'

* Feat/800: Ensure bundle.nonce and bundle.signatures have '0x' prepended

* Feat/800: Removed unused e2e directory

* Feat/800: Removed unnecessary app test

* Feat/800: Removed unnecessary router

* Feat/800: Capturing GQL errors in Sentry

* Feat/800: Removing references to the unused e2e test directory

* Feat/807: Consistent react hook imports

* Feat/807: Removed unnecessary spreads

Co-authored-by: Dexter <dexter.edwards93@gmail.com>
2022-09-29 12:10:53 -07:00
mattrussell36 8fee3ca080 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-29 18:06:47 +00:00
Radosław Szpiech 98abe2910d chore: fix smoke flag meaning (#1553) 2022-09-29 19:11:52 +02:00
AndyWhiteVega 22f4edff82 test: fix mocks for console light to include id (#1551) 2022-09-29 18:06:33 +01:00
Radosław Szpiech 28aa5cd060 Chore/add skip nx cache flag (#1549)
* chore: add skip-nx-cache flag to manual flow

* chore: set --skip-nx-cache flag

* chore: set --skip-nx-cache flag

* chore: set --skip-nx-cache flag

* chore: remove log
2022-09-29 18:27:08 +02:00
Radosław Szpiech 7b0d41b4a6 fix: typo (#1547) 2022-09-29 18:02:40 +02:00
Radosław Szpiech 83ea12b4cb Fix/smoke test flag (#1545)
* fix: fix smoke test flag logic

* fix: fix smoke test flag logic
2022-09-29 16:32:43 +01:00
Dexter Edwards a7768f154b chore: relabel total associated (#1531) 2022-09-29 15:47:09 +01:00
Matthew Russell 65af6bc0a8 fix: make sparkline strokes the same thickness (#1527)
* fix: make sparkline strokes the same thickness

* fix: data test id in sparkline
2022-09-29 07:20:04 -07:00
Radosław Szpiech 93c1835cd6 Chore/1495 workflows minor improvements fixes and cleanup (#1538)
* test: try with shared actions

* test: fix env

* test: fix path

* test: fix path

* test: fix path

* test: fix path

* test: fix path

* test: fix path

* test: fix path

* test: fix path

* test: fix path

* test: fix path

* test: fix path

* test: create action for capsule build

* test: create action for capsule build

* test: create action for capsule build

* test: create action for capsule build

* fix: fix

* fix: fix

* fix: fix

* fix: fix

* chore: create action for vegawallet setup

* chore: create action for vegawallet setup

* chore: fix

* chore: fix

* chore: fix

* chore: fix

* fix: fix

* fix: fix

* fix: fix

* fix: fix

* fix: fix

* fix: fix

* fix: fix

* fix: fix

* fix: fix

* fix: fix

* chore: apply changes to all workflows

* chore: apply changes to all workflows
2022-09-29 14:13:09 +01:00
Art 446af23d9c fix: orderbook sticky behaviour and precision options (#1519)
* fix: orderbook sticky behaviour and precision options

* chore: add handling of y-axis resize

* fix: addressed PR comments

* fix: addressed PR comments

* added cy.log

* Update apps/trading-e2e/src/support/vega-wallet.ts
2022-09-29 14:23:14 +02:00
mattrussell36 2cfe8608fb chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-29 12:05:36 +00:00
Matthew Russell 032805b5b9 Feat/1500 cancel and edit buttons conditional rendering (#1528)
* feat: allow second type arg to be generic as you dont always need the value

* feat: update order data provider to include fields required to determine if editable or cancellable

* feat: use ag grid type helpers and add rendering logic to cancel and amend buttons

* feat: combine cancel/edit buttons into single cell for better spacing

* feat: add test cases for dispaly of amend/cancel buttons

* chore: add missing fields to mock generate function

* chore: remove unnecessary wait for in fills test that was sporadically failing

* fix: add missing fields to generate order function

* fix: add missing fields to generate order function for console-lite
2022-09-29 11:00:39 +02:00
Joe Tsang 7a7c4ad452 Test/governance flows update (#1523)
* test: update governance flows with new ui change

* chore: existing governance flow tests passing

* chore: remove unused import

* chore: remove unused var
2022-09-29 09:18:06 +01:00
mattrussell36 0c5b2f5c29 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-29 06:27:20 +00:00
mattrussell36 a8667eea31 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-29 00:15:10 +00: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
mattrussell36 756d4d00de chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-22 18:04:24 +00:00
Joe Tsang ac16ca9ee5 Test/783 cypress tags (#1428)
* test: add tags for slow tests

* chore: remove old flows

* test: added smoke tags to view tests

* test: add tags for trading tests

* test: tags for explorer tests added

* chore: add tags to remaining tests and tidy files

* chore: pass env in test command

* chore: fix build errors

* chore: re-add teardown for manual flow

* chore: ability to only run smoke tests in manual flow

* chore: fix manual input flow
2022-09-22 18:40:11 +01:00
Radosław Szpiech c3cdcede9f Chore/speed up manual workflow (#1436)
* chore: add similar way to speed up tests that is used in  capsule-cypress

* chore: fix typo

* chore: fix the fix

* fix: add network import

* fix: add home

* fix: another fix bites the dust
2022-09-22 18:19:18 +02:00
Radosław Szpiech 186a624466 fix: use fairground network for vega wallet if capsule is not run (#1431)
* fix: use fairground network for vega wallet if capsule is not run

* fix: this fix should fix the fix

* fix: add import fairground network

* fix: home paths added to vega wallet
2022-09-22 17:59:31 +02:00
Radosław Szpiech 4d9c43cf19 Chore/improve ci test times (#1423)
* chore: disable video record for token e2e

* chore: disable videos in all tests

* fix: change main-branch-name to base-ref

* chore: disable capsule being run when not necessary

* fix: missing true

* chore: fix typo

* chore: fix if contruction

* chore: fix env

* chore: fix envs

* chore: try to fix develop ref
2022-09-22 16:07:18 +02:00
mattrussell36 8f20216b39 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-22 12:05:39 +00:00
macqbatandmaciek 5c4af868a7 feat: [console-lite] - abstract components for portfolio page (#1306)
* feat: [console-lite] - abstract components for portfolio page

* feat: [console-lite] - abstract components for portfolio page - improvements

* feat: [console-lite] - use abstract list with accounts manager

* feat: [console-lite] - use abstract list with positions

* feat: [console-lite] - use abstract list with orders

* feat: [console-lite] - use abstract list with fills

* feat: [console-lite] - fix failings linters

* feat: [console-lite] - fix failings e2e test

* feat: [console-lite] - fix failings e2e test

* feat: [console-lite] - improve some css

* feat: [console-lite] - a bunch of fixes for positions

* feat: [console-lite] - tweaks of columns confs, bunch of e2e tests

* feat: [console-lite] - abstract components for portfolio page - after review feedback fixes

* feat: [console-lite] - abstract components for portfolio page - after review feedback fixes

* feat: [console-lite] - abstract components for portfolio page - add missing asset datails dialog

* feat: [console-lite] - portfolio abstractions - add fills hook unit tests

* feat: [console-lite] - portfolio abstractions - add orders hook unit tests

* feat: [console-lite] - portfolio abstractions - fix lint error

* feat: [console-lite] - abstract components for portfolio page -fix failings tests

* feat: [console-lite] - abstract components for portfolio page -fix failings tests

* feat: [console-lite] - abstract components for portfolio page - fix failings lint check

* feat: [console-lite] - abstract components for portfolio page - next fix

* feat: [console-lite] - abstract components for portfolio page - improve some int test

Co-authored-by: maciek <maciek@vegaprotocol.io>
2022-09-22 13:09:12 +02:00
Bartłomiej Głownia d95bfb60ea chore: mock gql subscriptions (#1419)
* chore: mock gql subscriptions

* chore: fix market info, inprove fills unit tests

* chore: fix socket mock
2022-09-22 11:15:20 +02:00
mattrussell36 792459e589 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-22 06:23:32 +00:00
mattrussell36 4ca244a975 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-22 00:11:28 +00:00
m.rayandBartłomiej Głownia 010d7e5e31 fix: order data provider error (#1420)
* chore: ignore apollo errors - to be reverted after API will be fixed

* fix: order data provider error

Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
2022-09-21 13:47:17 -07:00
mattrussell36 9b04310ab8 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-21 18:05:00 +00:00
m.ray 832327c918 fix: add back risk factors (#1397)
* fix: #1302 add back risk factors

* fix:  omit __typename is default

* fix: add risk factors in generate-market-info-query.ts
2022-09-21 08:31:11 -07:00
m.rayandBartłomiej Głownia c59aa19bd2 fix: liquidity provisions view not working after API update (#1410)
* chore: ignore apollo errors - to be reverted after API will be fixed

* fix: partyID should not be enforced in market liquidity query

* Update apps/trading/components/page-query-container/page-query-container.tsx

* Update libs/react-helpers/src/lib/generic-data-provider.ts

* fix: remove partyId from the query to avoid any confusion

Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
2022-09-21 08:26:18 -07:00
Bartłomiej Głownia efc1d909b3 chore: ignore apollo errors - to be reverted after API will be fixed (#1407) 2022-09-21 07:00:48 -07:00
Bartłomiej Głownia cc7a4f2ddd chore: downgrade to 0.55 (#1406) 2022-09-21 13:49:11 +01:00
mattrussell36 ddbaea5e3f chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-21 12:05:17 +00:00
mattrussell36 1fd325a44f chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-21 06:26:47 +00:00
mattrussell36 2ad248b6d7 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-21 00:12:01 +00:00
Matthew Russell 10e1315afa chore: fix incorrect event id mock 2022-09-20 16:05:08 -07:00
ArtandMadalina Raicu 4ddacb5269 fix: total fees calculation (#1394)
* fix: total fees calculation

* fix: total fees calculation

* fix: add two more tests

* fix: market-info.cy.ts

Co-authored-by: Madalina Raicu <madalina@vegaprotocol.io>
2022-09-20 15:13:42 -07:00
mattrussell36 597a1fa878 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-20 18:05:23 +00:00
3bf5d823ee chore: stagnet3 api updates (#1321)
* chore: update account, fills and orders subscriptions in data providers

* chore: update account, fills and orders subscriptions in data providers

* fixing console-lite

* fixing types in general - regen

* chore: update account, fills and orders subscriptions in data providers

* fixed console-lite unit tests, uncommented quote name

* chore: update account, fills and orders subscriptions in data providers

* type aligning of assets and proposals

* fixes liquidity data provider

* fixed accounts build errors and unit tests

* regen types, removed market name

* regen types

* fixed positions

* chore: handle updates in derived market provider, update orders

* removed taker fee mapping (renamed to maker fee)

* chore: update account, fills and orders subscriptions in data providers

* chore: update account, fills and orders subscriptions in data providers

* chore: fix Order type

* chore: fix possible null types

* chore: revert order-list.stories.tsx

* chore:  derivedDataProvider fixes

* fills unit tests fixes

* orders unit tests fixes

* added eslint ingore for generated files in liquidity

* added unique key to the list element of simple market toolbar

* changed main-branch-name to develop for pr workflows

* removed redundant waitFor

* increased test timeout to 10s

* removed mocked response

* chore: disable simple market list tests

* chore: fix e2e projects mock types

* feat: [subscription-update] - uncomment some console-lite tests

* cypress: trading-accounts

* chore: replace  market candles with candlesConnection

* chore: ignore gql errors, to be reverted after candlesConnectio n will be fixed

* feat: [subscription-update] - improve wrongly renamed hook

* feat: [subscription-update] - improve wrongly renamed hook

* feat: [subscription-update] - improve wrongly renamed hook 3

* chore: add pagination hangdling to derived data provier

* cypress: trading-fills

* feat: [stagnet3 api update] - remove redundant command in tests

* feat: [stagnet3 api update] - remove redundant command in tests

* chore: fix trading orders e2e tests

* chore: fix console lite e2e mocks

* chore: fix market-trade tests

* chore: use markets only in market selector, change Instrument cache policy

* chore: fix market-selector tests

* feat: [subscription-update] - improve ag grid conf for unit tests

* feat: [subscription-update] - improve ag grid conf for unit tests

* chore: fix candle types in console lite market mocks

* chore: revert error policy ignore

* chore: revert jest timeout

* chore: remove unused AccountFields

* chore: revert remove unused AccountFields

* chore: simplify node subscription probe

* chore: remove unused generated types in candles-chart

* chore: improve useMarketsList mock

* feat: [subscription-update] - increase jest timeout

* feat: [subscription-update] - fix jest timeout

* feat: [subscription-update] - fix jest timeout

* feat: [subscription-update] - try to fix failing test again

* chore: fix candles-chart types

* feat: [subscription-update] - temporary skip failing test

* feat: [subscription-update] - temporary skip failing test

* feat: [subscription-update] - temporary skip failing test

* feat: [subscription-update] - fix failling int test

* feat: [subscription-update] - try to restore commented unit tests

* feat: [subscription-update] - try to restore commented unit tests

* feat: [subscription-update] - improve fixed unit tests

Co-authored-by: asiaznik <artur@vegaprotocol.io>
Co-authored-by: maciek <maciek@vegaprotocol.io>
2022-09-20 08:24:28 -07:00
mattrussell36 df3b79478e chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-20 12:05:27 +00:00
mattrussell36 f383dedb24 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-20 06:24:20 +00:00
mattrussell36 592ec14b26 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-20 00:13:27 +00:00
mattrussell36 76126ae386 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-19 18:05:55 +00:00
c211c179b6 Create issue templates (#1386)
* Create bug issue template

* Create chore.md issue template

* Create user story issue template

* Update ---bug.md

* Update chore.md

* Update user-story.md

* test: update formatting

* fix: formatting

Co-authored-by: Gordsport <83510148+gordsport@users.noreply.github.com>
Co-authored-by: Madalina Raicu <madalina@vegaprotocol.io>
2022-09-19 15:33:23 +01:00
mattrussell36 4818b57fb2 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-19 12:05:36 +00:00
John Walley 70df56f745 fix: use correct graphql candle timestamp field (#1324) 2022-09-19 12:21:38 +01:00
mattrussell36 2b76e7d5c8 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-19 06:28:17 +00:00
mattrussell36 947180a6a6 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-19 00:10:20 +00:00
mattrussell36 d25755474f chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-18 18:04:15 +00:00
mattrussell36 888cbbec68 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-18 12:05:11 +00:00
botond 46884e3fec fix: cleanup more env things (#1383)
* fix: remove vega_rest from monorepo
* fix: mainnet api urls
* fix: remove redundant vega url from token config
* fix: lint
* chore: remove redundant env props from token app
* fix: format
2022-09-18 11:15:05 +00:00
mattrussell36 589c15de9d chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-18 06:06:08 +00:00
mattrussell36 0271e62439 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-18 00:10:24 +00:00
mattrussell36 84a5cbd44b chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-17 18:04:17 +00:00
mattrussell36 a386ea5cad chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-17 12:05:37 +00:00
mattrussell36 599ee1a360 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-17 06:04:33 +00:00
mattrussell36 d176285021 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-17 00:09:14 +00:00
mattrussell36 40337ee698 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-16 18:05:34 +00:00
AndyWhiteVega d47d754ac9 Test/governance suite expansion (#1372)
* test: initial commit

* test: commit

* test: extra tests and references added also new tag 0.55.0 for builds

* test: lint

* test: back to 0.54 for capsule cypress until tests fixed

* test: skip two tests since wallet name no longer shown soon to be fixed

* test: couple more tests to fulfill ACs

* test: lint

* test: more tests

* test: lint

* test: extra check within test

* test: lint

* test: minor

* test: improve test flake and skip test bugs outstanding

* test: lint and increase epoch length by second

* test: more tests

* test: lint

* test: lint

* test: lint

* test: teardown functionality

* test: lint

* test: epoch speed up and network restart stuff

* test: lint

* test: change epoch duration

* test: timing tweaks due to failures in CI

* test: lint

* test: more timing tweaks

* test: lint

* test: timing tweak

* test: lint

* test: lint

* test: config changes
2022-09-16 18:12:08 +01:00
Matthew Russell 666fe9aebb chore: update wallet types to align with protos (#1351) 2022-09-16 17:04:54 +01:00
Matthew Russell b8d5680011 chore: set curly eslint rule to multi line (#1322)
* chore: set curly eslint rule to multi line

* chore: fix lint

* chore: make eslint rule error and fix resulting errors
2022-09-16 17:04:32 +01:00
Dexter Edwards 4aa9bbaa23 fix: remove shortening of description content (#1346)
* fix: remove shortening of description content

* chore: remove test for removed functionality
2022-09-16 17:03:11 +01:00
Dexter Edwards 9385e0f4c3 Chore/revert changes (#1368)
* chore: revert changes to stagent3 yml

* style: lint
2022-09-16 15:49:47 +01:00
mattrussell36 03df9e9c5d chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-16 12:05:47 +00:00
Dexter Edwards e8d110d207 Chore/more env config (#1363)
* chore: remove vega URL as no longer needed

* chore: remove bad env config

* chore: remove config caching

* chore: remove silly text

* style: lint

* chore: style lint

* test: remove test for removed functionality
2022-09-16 12:32:44 +01:00
mattrussell36 6c41c0b14d chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-16 06:22:40 +00:00
mattrussell36 e4f175b691 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-16 00:11:21 +00:00
mattrussell36 4b6c7f062d chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-15 18:04:27 +00:00
Dexter Edwards 2fa80f65d0 chore: sort out environement stuff (#1345) 2022-09-15 16:39:11 +00:00
Matthew Russell 7fb3a23a5a chore: add netlify build command for lp dashboard (#1343) 2022-09-15 08:55:14 -07:00
malinantonsson 9169165a03 feat: lp dashboard setup (#1327)
* feat: generate new nx application

* feat: add env variables & render a headline

* feat: add netlify config

* feat: add cypress projectId and delete unused files
2022-09-15 08:37:02 -07:00
mattrussell36 608ecf36af chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-15 12:05:03 +00:00
Elmar df29c9ee72 fix(stats-manager): fix uptime pointing to incorrect field (#1328) 2022-09-15 11:47:51 +01:00
mattrussell36 e3809f5bc3 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-15 06:18:49 +00:00
mattrussell36 ff317f1c3a chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-15 00:10:04 +00:00
mattrussell36 e6b7f73be2 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-14 18:04:48 +00:00
mattrussell36 d65bdb1482 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-14 12:05:15 +00:00
m.rayandJoe ff7c501621 fix: decimal precision out of range (#1318)
* fix: fix fraction digits getting out of range

* fix: cumulative volume pos decimal places, number formatting tests and typos

* fix: added braces

* chore: increase request timeout

Co-authored-by: Joe <joe@vega.xyz>
2022-09-14 10:05:26 +01:00
mattrussell36 60f286c8af chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-14 06:25:03 +00:00
mattrussell36 a2c8c5a9c4 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-14 00:10:14 +00:00
mattrussell36 2eea3e2e34 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-13 18:05:16 +00:00
AndyWhiteVega 040cf0b83b Test/governance suite expansion (#1317)
* test: initial commit

* test: commit

* test: extra tests and references added also new tag 0.55.0 for builds

* test: lint

* test: back to 0.54 for capsule cypress until tests fixed

* test: skip two tests since wallet name no longer shown soon to be fixed
2022-09-13 13:28:48 +01:00
mattrussell36 9d2f2fe3aa chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-13 12:05:22 +00:00
Bartłomiej Głowniaandasiaznik a08f63c7d8 Feature/1243 market data providers refactoring (#1254)
* feat(#1243): Market data providers

* feat(#1243): Market data providers

* feat(#1243): Market data providers

* feat(#1243): refactor market lists

* feat(#1243): refactor market lists

* feat(#1243): refactor market lists

* feat(#1243): refactor orderbook data providers

* feat(#1243): refactor orderbook data providers

* feat(#1243): refactor depth chart data layer

* feat(#1243): fix market depth typing

* fixed unit tests

* feat(#1243): e2e test fixes

* feat(#1243): code style fixes

* feat(#1243): post merge fixes

* feat(#1243): fix lint issues

* feat(#1243): post merge fixes

* feat(#1243): remove market name from market

* feat(#1243): fix console lite e2e data depth mocks

* feat(#1243): fix console lite e2e market trade test

* feat(#1243): fix lint issues

* feat(#1243): fix trading e2e home test

Co-authored-by: asiaznik <artur@vegaprotocol.io>
2022-09-13 12:14:06 +02:00
Matthew Russell 3ff5bbb5a7 chore: use trading header and tidy tailwind usage (#1313)
* fix: border too thick, use grid head component

* fix: unused and superfluous classes, define border color in one place

* fix: tooltip should be on data not label
2022-09-13 09:19:41 +01:00
AndyWhiteVega 535bdb5183 Test/governance and wallet tweaks (#1309)
* test: tweaks

* test: lint

* test: lint

* test: remove unnessecary timeouts

* test: lint

* test: syntax tweak
2022-09-13 08:43:40 +01:00
mattrussell36 4505e86363 chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-13 06:26:28 +00:00
mattrussell36 7b2e86f32e chore: update tranches
Signed-off-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2022-09-13 00:12:14 +00:00
714 changed files with 27571 additions and 15671 deletions
+3 -3
View File
@@ -51,8 +51,7 @@
"ul": ["list"], "ul": ["list"],
"ol": ["list"] "ol": ["list"]
} }
], ]
"curly": "warn"
} }
}, },
{ {
@@ -75,7 +74,8 @@
"prefer": "type-imports", "prefer": "type-imports",
"disallowTypeAnnotations": true "disallowTypeAnnotations": true
} }
] ],
"curly": ["error", "multi-line"]
} }
}, },
{ {
+45
View File
@@ -0,0 +1,45 @@
---
name: "\U0001F41B Bug"
about: Create a report to help us improve
title: ''
labels: "\U0001F41B bug"
assignees: ''
---
## Description
A clear and concise description of what the bug is.
## Steps to Reproduce
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
## Expected behavior
A clear and concise description of what you expected to happen.
## Screenshots
If applicable, add screenshots to help explain your problem.
## Device details
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
## Additional context
Add any other context about the problem here.
+21
View File
@@ -0,0 +1,21 @@
---
name: Chore
about:
A template to capture non feature / enhancement work we need to do like work
to support other functions or housekeeping etc.
title: ''
labels: chore
assignees: ''
---
## The Chore
What we need to achieve and who for
## Tasks
- [ ] What do we need to do first
- [ ] and then what?
- [ ] Etc.
## Additional details / background info
+33
View File
@@ -0,0 +1,33 @@
---
name: User Story
about:
A template to describe a features or enhancements we want to make from a users
perspective to ensure we understand what is needed and the value it would add
title: ''
labels: feature
assignees: ''
---
## Story
As a
I want
So that
## Acceptance Criteria
- [ ] I can
- [ ] I can
- [ ] I can
## Tasks
- [ ] Explore and sketch
- [ ] Team and stakeholder review
- [ ] Visual Design
- [ ] Team review
- [ ] Etc.
## Sketch
## Additional details / background info
@@ -0,0 +1,31 @@
inputs:
all:
description: 'Install all binaries'
default: false
version:
description: 'Vega version'
gobin:
description: 'GOBIN path'
default: '/home/runner/go/bin'
runs:
using: 'composite'
steps:
- name: Install Vega binaries
if: ${{ inputs.all }}
shell: bash
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vega-linux-amd64.zip' -q
unzip vega-linux-amd64.zip -d ${{ inputs.gobin }}
- name: Install date-node binaries
if: ${{ inputs.all }}
shell: bash
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/data-node-linux-amd64.zip' -q
unzip data-node-linux-amd64.zip -d ${{ inputs.gobin }}
- name: Install Vega wallet binaries
shell: bash
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vegawallet-linux-amd64.zip' -q
unzip vegawallet-linux-amd64.zip -d ${{ inputs.gobin }}
@@ -0,0 +1,30 @@
inputs:
github-token:
description: 'github token'
runs:
using: 'composite'
steps:
- name: Checkout capsule
uses: actions/checkout@v2
with:
repository: vegaprotocol/vegacapsule
ref: main
token: ${{ inputs.github-token }}
path: './capsule'
- name: Build capsule
run: go install
shell: bash
working-directory: capsule
- name: Login to docker
shell: bash
run: echo -n ${{ inputs.github-token }} | docker login https://ghcr.io -u vega-ci-bot --password-stdin
- name: Start nomad
shell: bash
run: vegacapsule nomad &
- name: Bootstrap network
shell: bash
run: vegacapsule network bootstrap --config-path=./frontend-monorepo/vegacapsule/config.hcl --force
@@ -0,0 +1,30 @@
inputs:
recovery:
description: 'Recovery phrase'
passphrase:
description: 'Wallet password'
capsule:
description: 'Is Capsule network used'
default: false
runs:
using: 'composite'
steps:
- name: Create passphrase
shell: bash
run: echo "${{ inputs.passphrase }}" > ./passphrase
- name: Create recovery
shell: bash
run: echo "${{ inputs.recovery }}" > ./recovery
- name: Initialize wallet
shell: bash
run: vegawallet init -f --home ~/.vegacapsule/testnet/wallet
- name: Import wallet
shell: bash
run: vegawallet import -w UI_Trading_Test --recovery-phrase-file ./recovery -p ./passphrase --home ~/.vegacapsule/testnet/wallet
- name: Create public key 2
shell: bash
run: vegawallet key generate -w UI_Trading_Test -p ./passphrase --home ~/.vegacapsule/testnet/wallet
@@ -1,4 +1,4 @@
name: Capsule tests -- manual trigger name: Cypress tests -- manual trigger
# This workflow runs the frontend tests against chosen branch # This workflow runs the frontend tests against chosen branch
@@ -15,20 +15,43 @@ on:
- stats-e2e - stats-e2e
- token-e2e - token-e2e
- trading-e2e - trading-e2e
includeFlows: smokeOnly:
description: 'Include long flows (if any)?' description: 'Run only smoke tests?'
required: true required: true
type: boolean type: boolean
default: true default: false
skip-nx-cache:
description: 'Add --skip-nx-cache to cypress test'
required: false
type: boolean
default: false
jobs: jobs:
manual: manual:
name: Run capsule tests -- manual trigger name: Run Cypress tests -- manual trigger
runs-on: ubuntu-latest runs-on: self-hosted
env: env:
GO111MODULE: 'on' GO111MODULE: 'on'
GOPROXY: ${{ secrets.GO_PROXY }} GOBIN: /home/runner/go/bin
VEGA_VERSION: 'v0.57.0'
steps: steps:
#######
## Setup flags
#######
- name: Set smoke tag
if: ${{ github.event.inputs.smokeOnly == 'true' }}
run: echo TAGS="--env.grepTags @smoke" >> $GITHUB_ENV
- name: Set --skip-nx-cache flag
if: ${{ github.event.inputs.skip-nx-cache == 'true' }}
run: echo SKIP_NX_CACHE="--skip-nx-cache" >> $GITHUB_ENV
# See if we capsule is needed for this project
- name: Set capsule flag
if: ${{ github.event.inputs.project == 'explorer-e2e' || github.event.inputs.project == 'token-e2e' }}
run: echo RUN_CAPSULE=true >> $GITHUB_ENV
####### #######
## Setup langs ## Setup langs
####### #######
@@ -37,6 +60,7 @@ jobs:
id: go id: go
with: with:
go-version: 1.19 go-version: 1.19
- name: Set up Node 16 - name: Set up Node 16
uses: actions/setup-node@v2 uses: actions/setup-node@v2
id: npm id: npm
@@ -44,112 +68,92 @@ jobs:
node-version: 16 node-version: 16
####### #######
## Checkout capsule ## Install Yarn
#######
- name: Setup yarn
run: npm install -g yarn
#######
## Checkout repos
####### #######
# Checkout front ends # Checkout front ends
- name: Checkout frontend mono repo - name: Checkout frontend mono repo
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
ref: ${{ github.event.pull_request.head.ref }}
fetch-depth: 0 fetch-depth: 0
path: './frontend-monorepo' path: './frontend-monorepo'
# Checkout capsule to build local network # Restore node_modules from cache if possible
- name: Checkout capsule - name: Restore node_modules from cache
uses: actions/checkout@v2 uses: actions/cache@v3
with: with:
repository: vegaprotocol/vegacapsule path: |
ref: main frontend-monorepo/node_modules
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }} /home/runner/.cache/Cypress
path: './capsule' 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 ## Build and run Vegacapsule network
####### #######
- name: Build capsule
run: go install
working-directory: capsule
- 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.54.0
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
path: './vega'
- name: Install Vega binaries - name: Install Vega binaries
run: go install -v ./cmd/vega uses: ./frontend-monorepo/.github/actions/install-vega-binaries
working-directory: vega with:
all: ${{ env.RUN_CAPSULE }}
version: ${{ env.VEGA_VERSION }}
gobin: ${{ env.GOBIN }}
- name: Install Vega wallet binaries - name: Build and run Vegacapsule network
run: go install ./cmd/vegawallet if: ${{ env.RUN_CAPSULE }}
working-directory: vega uses: ./frontend-monorepo/.github/actions/run-vegacapsule
with:
- name: Install date-node binaries github-token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
run: go install ./cmd/data-node
working-directory: vega
######
## Start capsule
######
- name: Login to docker
run: echo -n ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }} | docker login https://ghcr.io -u vega-ci-bot --password-stdin
- name: Start nomad
run: vegacapsule nomad &
- name: Bootstrap network
run: vegacapsule network bootstrap --config-path=../frontend-monorepo/vegacapsule/config.hcl --force
working-directory: capsule
###### ######
## Setup a Vega wallet for our user ## Setup a Vega wallet for our user
###### ######
- name: Create passphrase
run: echo "${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}" > ./passphrase
- name: Create recovery
run: echo "${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}" > ./recovery
- name: Initialize wallet - name: Set up Vegawallet
run: vegawallet init -f --home ~/.vegacapsule/testnet/wallet uses: ./frontend-monorepo/.github/actions/setup-vegawallet
- name: Import wallet with:
run: vegawallet import -w UI_Trading_Test --recovery-phrase-file ./recovery -p ./passphrase --home ~/.vegacapsule/testnet/wallet recovery: ${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}
- name: Create public key 2 passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
run: vegawallet key generate -w UI_Trading_Test -p ./passphrase --home ~/.vegacapsule/testnet/wallet capsule: ${{ env.RUN_CAPSULE }}
- name: Start service
run: vegawallet service run --network DV --automatic-consent --home ~/.vegacapsule/testnet/wallet &
###### ######
## Run some tests ## Run some tests
###### ######
- name: Install root dependencies # To make sure that all Cypress binaries are installed properly
run: yarn install - name: Install cypress bins
run: yarn cypress install
working-directory: frontend-monorepo working-directory: frontend-monorepo
- name: Run Cypress tests - name: Run Cypress tests
run: yarn nx run ${{ github.event.inputs.project }}:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} run: yarn nx run ${{ github.event.inputs.project }}:e2e ${{ env.SKIP_NX_CACHE }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome ${{ env.TAGS }}
working-directory: frontend-monorepo working-directory: frontend-monorepo
env: env:
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }} CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }} CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPESS_ETH_WALLET_MNEMONIC }} CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPRESS_ETH_WALLET_MNEMONIC }}
CYPRESS_INCLUDE_FLOWS: ${{ github.event.inputs.includeFlows }} CYPRESS_TEARDOWN_NETWORK_AFTER_FLOWS: true
###### ######
## Upload logs ## Upload logs
###### ######
- name: Logs - name: Logs
if: ${{ always() }} if: ${{ env.RUN_CAPSULE }}
run: vegacapsule network logs > vega-capsule-logs.txt run: vegacapsule network logs > vega-capsule-logs.txt
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
if: ${{ env.RUN_CAPSULE }}
with: with:
name: logs name: logs
path: ./vega-capsule-logs.txt path: ./vega-capsule-logs.txt
+49 -67
View File
@@ -1,4 +1,4 @@
name: Capsule tests -- night run name: Cypress tests -- night run
# This workflow runs the frontend tests against latest develop of the core to preempt breaking changes # This workflow runs the frontend tests against latest develop of the core to preempt breaking changes
@@ -8,10 +8,14 @@ on:
jobs: jobs:
nightly: nightly:
name: Run capsule tests -- nightly name: Run Cypress tests -- nightly
runs-on: ubuntu-latest runs-on: self-hosted
timeout-minutes: 60
env: env:
GO111MODULE: 'on' GO111MODULE: 'on'
GOBIN: /home/runner/go/bin
VEGA_VERSION: 'v0.57.0'
RUN_CAPSULE: true
steps: steps:
####### #######
## Setup langs ## Setup langs
@@ -28,110 +32,88 @@ jobs:
node-version: 16 node-version: 16
####### #######
## Checkout capsule ## Install Yarn
#######
- name: Setup yarn
run: npm install -g yarn
#######
## Checkout repos
####### #######
# Checkout front ends # Checkout front ends
- name: Checkout frontend mono repo - name: Checkout frontend mono repo
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
ref: ${{ github.event.pull_request.head.ref }}
fetch-depth: 0 fetch-depth: 0
path: './frontend-monorepo' path: './frontend-monorepo'
# Checkout capsule to build local network # Restore node_modules from cache if possible
- name: Checkout capsule - name: Restore node_modules from cache
uses: actions/checkout@v2 uses: actions/cache@v3
with: with:
repository: vegaprotocol/vegacapsule path: |
ref: main frontend-monorepo/node_modules
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }} /home/runner/.cache/Cypress
path: './capsule' 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 ## Build and run Vegacapsule network
####### #######
- name: Build capsule
run: go install
working-directory: capsule
- 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.54.0
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
path: './vega'
- name: Install Vega binaries - name: Install Vega binaries
run: go install -v ./cmd/vega uses: ./frontend-monorepo/.github/actions/install-vega-binaries
working-directory: vega with:
all: ${{ env.RUN_CAPSULE }}
version: ${{ env.VEGA_VERSION }}
gobin: ${{ env.GOBIN }}
- name: Install Vega wallet binaries - name: Build and run Vegacapsule network
run: go install ./cmd/vegawallet if: ${{ env.RUN_CAPSULE }}
working-directory: vega uses: ./frontend-monorepo/.github/actions/run-vegacapsule
with:
- name: Install date-node binaries github-token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
run: go install ./cmd/data-node
working-directory: vega
######
## Start capsule
######
- name: Login to docker
run: echo -n ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }} | docker login https://ghcr.io -u vega-ci-bot --password-stdin
- name: Start nomad
run: vegacapsule nomad &
- name: Bootstrap network
run: vegacapsule network bootstrap --config-path=../frontend-monorepo/vegacapsule/config.hcl --force
working-directory: capsule
###### ######
## Setup a Vega wallet for our user ## Setup a Vega wallet for our user
###### ######
- name: Create passphrase
run: echo "${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}" > ./passphrase
- name: Create recovery
run: echo "${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}" > ./recovery
- name: Initialize wallet - name: Set up Vegawallet
run: vegawallet init -f --home ~/.vegacapsule/testnet/wallet uses: ./frontend-monorepo/.github/actions/setup-vegawallet
- name: Import wallet with:
run: vegawallet import -w UI_Trading_Test --recovery-phrase-file ./recovery -p ./passphrase --home ~/.vegacapsule/testnet/wallet recovery: ${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}
- name: Create public key 2 passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
run: vegawallet key generate -w UI_Trading_Test -p ./passphrase --home ~/.vegacapsule/testnet/wallet capsule: ${{ env.RUN_CAPSULE }}
- name: Start service
run: vegawallet service run --network DV --automatic-consent --home ~/.vegacapsule/testnet/wallet &
###### ######
## Run some tests ## Run some tests
###### ######
- name: Install root dependencies # To make sure that all Cypress binaries are installed properly
run: yarn install - name: Install cypress bins
run: yarn cypress install
working-directory: frontend-monorepo working-directory: frontend-monorepo
- name: Run Cypress tests - name: Run Cypress tests
run: yarn nx run-many --target=e2e --all --record --key ${{ secrets.CYPRESS_RECORD_KEY }} run: yarn nx run-many --skip-nx-cache --target=e2e --all --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome
working-directory: frontend-monorepo working-directory: frontend-monorepo
env: env:
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }} CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }} CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPESS_ETH_WALLET_MNEMONIC }} CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPRESS_ETH_WALLET_MNEMONIC }}
CYPRESS_NIGHTLY_RUN: true CYPRESS_NIGHTLY_RUN: true
CYPRESS_INCLUDE_FLOWS: true CYPRESS_TEARDOWN_NETWORK_AFTER_FLOWS: true
###### ######
## Upload logs ## Upload logs
###### ######
- name: Logs - name: Logs
if: ${{ always() }}
run: vegacapsule network logs > vega-capsule-logs.txt run: vegacapsule network logs > vega-capsule-logs.txt
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
+60 -75
View File
@@ -1,10 +1,10 @@
name: Capsule tests name: Capsule Cypress tests
on: on:
push: push:
branches: branches:
- master
- develop - develop
- main
pull_request: pull_request:
types: types:
- opened - opened
@@ -14,11 +14,13 @@ on:
jobs: jobs:
pr: pr:
name: Run capsule tests - PR name: Run Cypress tests - PR
runs-on: ubuntu-latest runs-on: self-hosted
if: ${{ github.event_name == 'pull_request' && github.event.pull_request.draft == false }} timeout-minutes: 30
env: env:
GO111MODULE: 'on' GO111MODULE: 'on'
GOBIN: /home/runner/go/bin
VEGA_VERSION: 'v0.57.0'
steps: steps:
####### #######
## Setup langs ## Setup langs
@@ -28,6 +30,7 @@ jobs:
id: go id: go
with: with:
go-version: 1.19 go-version: 1.19
- name: Set up Node 16 - name: Set up Node 16
uses: actions/setup-node@v2 uses: actions/setup-node@v2
id: npm id: npm
@@ -35,119 +38,101 @@ jobs:
node-version: 16 node-version: 16
####### #######
## Checkout capsule ## Install Yarn
#######
- name: Setup yarn
run: npm install -g yarn
#######
## Checkout repos
####### #######
# Checkout front ends # Checkout front ends
- name: Checkout frontend mono repo - name: Checkout frontend mono repo
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
ref: ${{ github.event.pull_request.head.ref }}
fetch-depth: 0 fetch-depth: 0
path: './frontend-monorepo' path: './frontend-monorepo'
# Checkout capsule to build local network # Restore node_modules from cache if possible
- name: Checkout capsule - name: Restore node_modules from cache
uses: actions/checkout@v2 uses: actions/cache@v3
with: with:
repository: vegaprotocol/vegacapsule path: |
ref: main frontend-monorepo/node_modules
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }} /home/runner/.cache/Cypress
path: './capsule' 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
# Check SHAs
- name: Derive appropriate SHAs for base and head for `nx affected` commands
uses: nrwl/nx-set-shas@v2
with:
working-directory: frontend-monorepo
main-branch-name: ${{ github.base_ref || github.ref_name }}
set-environment-variables-for-job: true
####### #######
## Build binaries ## Build and run Vegacapsule network
####### #######
- name: Build capsule
run: go install
working-directory: capsule
- 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.54.0
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
path: './vega'
- name: Install Vega binaries - name: Install Vega binaries
run: go install -v ./cmd/vega uses: ./frontend-monorepo/.github/actions/install-vega-binaries
working-directory: vega with:
version: ${{ env.VEGA_VERSION }}
gobin: ${{ env.GOBIN }}
- name: Install Vega wallet binaries - name: Build and run Vegacapsule network
run: go install ./cmd/vegawallet uses: ./frontend-monorepo/.github/actions/run-vegacapsule
working-directory: vega with:
github-token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
- name: Install date-node binaries
run: go install ./cmd/data-node
working-directory: vega
######
## Start capsule
######
- name: Login to docker
run: echo -n ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }} | docker login https://ghcr.io -u vega-ci-bot --password-stdin
- name: Start nomad
run: vegacapsule nomad &
- name: Bootstrap network
run: vegacapsule network bootstrap --config-path=../frontend-monorepo/vegacapsule/config.hcl --force
working-directory: capsule
###### ######
## Setup a Vega wallet for our user ## Setup a Vega wallet for our user
###### ######
- name: Create passphrase
run: echo "${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}" > ./passphrase
- name: Create recovery
run: echo "${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}" > ./recovery
- name: Initialize wallet - name: Set up Vegawallet
run: vegawallet init -f --home ~/.vegacapsule/testnet/wallet uses: ./frontend-monorepo/.github/actions/setup-vegawallet
- name: Import wallet with:
run: vegawallet import -w UI_Trading_Test --recovery-phrase-file ./recovery -p ./passphrase --home ~/.vegacapsule/testnet/wallet recovery: ${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}
- name: Create public key 2 passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
run: vegawallet key generate -w UI_Trading_Test -p ./passphrase --home ~/.vegacapsule/testnet/wallet capsule: true
- name: Start service
- name: Start service using capsule network
shell: bash
if: ${{ inputs.capsule }}
run: vegawallet service run --network DV --automatic-consent --home ~/.vegacapsule/testnet/wallet & run: vegawallet service run --network DV --automatic-consent --home ~/.vegacapsule/testnet/wallet &
###### ######
## Run some tests ## Run some tests
###### ######
- name: Derive appropriate SHAs for base and head for `nx affected` commands # To make sure that all Cypress binaries are installed properly
uses: nrwl/nx-set-shas@v2 - name: Install cypress bins
with: run: yarn cypress install
working-directory: frontend-monorepo
main-branch-name: master
- name: Install root dependencies
run: yarn install
working-directory: frontend-monorepo working-directory: frontend-monorepo
- name: Run Cypress tests - name: Run Cypress tests
run: npx nx affected:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} run: npx nx affected:e2e --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --env.grepTags='@smoke' --browser chrome --exclude=trading,trading-e2e,console-lite,console-lite-e2e
working-directory: frontend-monorepo working-directory: frontend-monorepo
env: env:
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }} CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }} CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPESS_ETH_WALLET_MNEMONIC }} CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPRESS_ETH_WALLET_MNEMONIC }}
CYPRESS_INCLUDE_FLOWS: false CYPRESS_TEARDOWN_NETWORK_AFTER_FLOWS: true
###### ######
## Upload logs ## Upload logs
###### ######
- name: Logs - name: Logs
if: ${{ always() }}
run: vegacapsule network logs > vega-capsule-logs.txt run: vegacapsule network logs > vega-capsule-logs.txt
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v2
if: ${{ always() }}
with: with:
name: logs name: logs
path: ./vega-capsule-logs.txt path: ./vega-capsule-logs.txt
+124
View File
@@ -0,0 +1,124 @@
name: Cypress tests
on:
push:
branches:
- develop
- main
pull_request:
types:
- opened
- reopened
- synchronize
- ready_for_review
jobs:
pr:
name: Run Cypress tests - PR
runs-on: self-hosted
timeout-minutes: 30
env:
GO111MODULE: 'on'
GOBIN: /home/runner/go/bin
VEGA_VERSION: 'v0.57.0'
steps:
#######
## Setup langs
#######
- name: Set up Go
uses: actions/setup-go@v3
id: go
with:
go-version: 1.19
- name: Set up Node 16
uses: actions/setup-node@v2
id: npm
with:
node-version: 16
#######
## Install Yarn
#######
- name: Setup yarn
run: npm install -g yarn
#######
## Checkout repos
#######
# Checkout front ends
- name: Checkout frontend mono repo
uses: actions/checkout@v2
with:
fetch-depth: 0
path: './frontend-monorepo'
# 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
# Check SHAs
- name: Derive appropriate SHAs for base and head for `nx affected` commands
uses: nrwl/nx-set-shas@v2
with:
working-directory: frontend-monorepo
main-branch-name: ${{ github.base_ref || github.ref_name }}
set-environment-variables-for-job: true
#######
## Install Vega wallet
#######
- name: Install Vega wallet binaries
shell: bash
run: |
wget 'https://github.com/vegaprotocol/vega/releases/download/${{ env.VEGA_VERSION }}/vegawallet-linux-amd64.zip' -q
unzip vegawallet-linux-amd64.zip -d ${{ env.GOBIN }}
######
## Setup a Vega wallet for our user
######
- name: Set up Vegawallet
uses: ./frontend-monorepo/.github/actions/setup-vegawallet
with:
recovery: ${{ secrets.TRADING_TEST_VEGA_WALLET_RECOVERY }}
passphrase: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
capsule: false
- name: Import fairground network
shell: bash
run: vegawallet network import --from-url="https://raw.githubusercontent.com/vegaprotocol/networks/master/fairground/fairground.toml" --force --home ~/.vegacapsule/testnet/wallet
- name: Start service using fairground network
shell: bash
run: vegawallet service run --network fairground --automatic-consent --home ~/.vegacapsule/testnet/wallet &
######
## Run some tests
######
# 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' --browser chrome --exclude=explorer,explorer-e2e,token,token-e2e
working-directory: frontend-monorepo
env:
CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE: ${{ secrets.CYPRESS_TRADING_TEST_VEGA_WALLET_PASSPHRASE }}
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
CYPRESS_ETH_WALLET_MNEMONIC: ${{ secrets.CYPRESS_ETH_WALLET_MNEMONIC }}
CYPRESS_TEARDOWN_NETWORK_AFTER_FLOWS: true
-32
View File
@@ -1,32 +0,0 @@
---
name: Deploy affected projects to IPFS
'on':
# Triggers the workflow on push to main branch
push:
branches: [master]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch: null
jobs:
master:
name: Publish NX Affected
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
ref: ${{ github.event.pull_request.head.ref }}
fetch-depth: 0
- name: Use Node.js 16
id: Node
uses: actions/setup-node@v2
with:
node-version: 16.14.0
- name: Install root dependencies
run: yarn install
- name: Run deploy for affected sites
env:
FLEEK_API_KEY: ${{ secrets.FLEEK_API_KEY }}
run: ./tools/ipfs-deploy.js
+8 -37
View File
@@ -3,50 +3,16 @@ name: Unit tests & build
on: on:
push: push:
branches: branches:
- master
- develop - develop
- main
pull_request: pull_request:
jobs: 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: pr:
name: Test and lint - PR name: Test and lint - PR
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: 'read' contents: 'read'
actions: 'read' actions: 'read'
if: ${{ github.event_name == 'pull_request' }}
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v3
@@ -55,14 +21,19 @@ jobs:
- name: Derive appropriate SHAs for base and head for `nx affected` commands - name: Derive appropriate SHAs for base and head for `nx affected` commands
uses: nrwl/nx-set-shas@v2 uses: nrwl/nx-set-shas@v2
with: with:
main-branch-name: master main-branch-name: ${{ github.base_ref }}
- name: Use Node.js 16 - name: Use Node.js 16
id: Node id: Node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
node-version: 16.14.0 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 - name: Install root dependencies
run: yarn install run: yarn install --frozen-lockfile
- name: Check formatting - name: Check formatting
run: yarn nx format:check run: yarn nx format:check
- name: Lint affected - name: Lint affected
+4
View File
@@ -30,6 +30,10 @@ An application for the status of the Vega network. Showing block height and othe
Hosting for static content being shared across apps, for example fonts. Hosting for static content being shared across apps, for example fonts.
### [Multisig-signer](./apps/multisig-signer)
The utility dApp for validators wishing to add or remove themselves as a signer of the multisig contract.
# 🧱 Libraries in this repo # 🧱 Libraries in this repo
### [UI toolkit](./libs/ui-toolkit) ### [UI toolkit](./libs/ui-toolkit)
-1
View File
@@ -23,5 +23,4 @@ NX_DEPLOY_PRIME_URL=$DEPLOY_PRIME_URL
NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql NX_VEGA_URL=https://api.n11.testnet.vega.xyz/graphql
NX_VEGA_ENV=TESTNET NX_VEGA_ENV=TESTNET
NX_VEGA_REST=https://api.n11.testnet.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789/api/v1 NX_VEGA_WALLET_URL=http://localhost:1789/api/v1
+9 -2
View File
@@ -3,14 +3,18 @@ module.exports = defineConfig({
projectId: 'et4snf', projectId: 'et4snf',
e2e: { e2e: {
setupNodeEvents(on, config) {
require('cypress-grep/src/plugin')(config);
return config;
},
baseUrl: 'http://localhost:4200', baseUrl: 'http://localhost:4200',
fileServerFolder: '.', fileServerFolder: '.',
fixturesFolder: false, fixturesFolder: false,
specPattern: './src/integration/*.ts', specPattern: './src/integration/*.ts',
excludeSpecPattern: '**/*.js', excludeSpecPattern: '**/*.js',
modifyObstructiveCode: false, modifyObstructiveCode: false,
supportFile: './src/support/index.ts', supportFile: './src/support/index.js',
video: true, video: false,
videoUploadOnPasses: false, videoUploadOnPasses: false,
videosFolder: '../../dist/cypress/apps/console-lite-e2e/videos', videosFolder: '../../dist/cypress/apps/console-lite-e2e/videos',
screenshotsFolder: '../../dist/cypress/apps/console-lite-e2e/screenshots', screenshotsFolder: '../../dist/cypress/apps/console-lite-e2e/screenshots',
@@ -35,5 +39,8 @@ module.exports = defineConfig({
TRADING_TEST_VEGA_WALLET_PASSPHRASE: '123', TRADING_TEST_VEGA_WALLET_PASSPHRASE: '123',
ETH_WALLET_MNEMONIC: ETH_WALLET_MNEMONIC:
'ugly gallery notice network true range brave clarify flat logic someone chunk', 'ugly gallery notice network true range brave clarify flat logic someone chunk',
grepTags: '@regression @smoke @slow',
grepFilterSpecs: true,
grepOmitFiltered: true,
}, },
}); });
@@ -1,4 +1,4 @@
describe('simple trading app', () => { describe('simple trading app', { tags: '@smoke' }, () => {
beforeEach(() => cy.visit('/')); beforeEach(() => cy.visit('/'));
it('render', () => { it('render', () => {
@@ -1,4 +1,4 @@
describe('console lite header', () => { describe('console lite header', { tags: '@smoke' }, () => {
beforeEach(() => { beforeEach(() => {
window.localStorage.setItem('theme', 'dark'); window.localStorage.setItem('theme', 'dark');
cy.visit('/'); cy.visit('/');
@@ -1,14 +1,19 @@
import { aliasQuery } from '@vegaprotocol/cypress'; import { aliasQuery } from '@vegaprotocol/cypress';
import type { Markets } from '@vegaprotocol/market-list';
import { import {
generateLongListMarkets, generateLongListMarkets,
generateSimpleMarkets, generateSimpleMarkets,
generateMarketsData,
generateMarketsCandles,
} from '../support/mocks/generate-markets'; } from '../support/mocks/generate-markets';
describe('market list', () => { describe('market list', { tags: '@smoke' }, () => {
describe('simple url', () => { describe('simple url', () => {
beforeEach(() => { beforeEach(() => {
cy.mockGQL((req) => { cy.mockGQL((req) => {
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets()); aliasQuery(req, 'Markets', generateSimpleMarkets());
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
}); });
cy.visit('/markets'); cy.visit('/markets');
}); });
@@ -62,7 +67,9 @@ describe('market list', () => {
describe('url params should select filters', () => { describe('url params should select filters', () => {
beforeEach(() => { beforeEach(() => {
cy.mockGQL((req) => { cy.mockGQL((req) => {
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets()); aliasQuery(req, 'Markets', generateSimpleMarkets());
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
}); });
}); });
@@ -73,10 +80,11 @@ describe('market list', () => {
it('last asset (if exists)', () => { it('last asset (if exists)', () => {
cy.visit('/markets'); cy.visit('/markets');
cy.wait('@SimpleMarkets').then((filters) => { cy.wait('@Markets').then((filters) => {
if (filters?.response?.body?.data?.markets?.length) { const data: Markets | undefined = filters?.response?.body?.data;
if (data.marketsConnection.edges.length) {
const asset = const asset =
filters.response.body.data.markets[0].tradableInstrument.instrument data.marketsConnection.edges[0].node.tradableInstrument.instrument
.product.settlementAsset.symbol; .product.settlementAsset.symbol;
cy.visit(`/markets/Suspended/Future/${asset}`); cy.visit(`/markets/Suspended/Future/${asset}`);
cy.getByTestId('market-assets-menu') cy.getByTestId('market-assets-menu')
@@ -98,7 +106,9 @@ describe('market list', () => {
it('handles 1000 markets', () => { it('handles 1000 markets', () => {
cy.viewport(1440, 900); cy.viewport(1440, 900);
cy.mockGQL((req) => { cy.mockGQL((req) => {
aliasQuery(req, 'SimpleMarkets', generateLongListMarkets(1000)); aliasQuery(req, 'Markets', generateLongListMarkets(1000));
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
}); });
performance.mark('start-1k'); performance.mark('start-1k');
cy.visit('/markets'); cy.visit('/markets');
@@ -1,6 +1,10 @@
import { connectVegaWallet } from '../support/connect-wallet'; import { connectVegaWallet } from '../support/connect-wallet';
import { aliasQuery } from '@vegaprotocol/cypress'; import { aliasQuery } from '@vegaprotocol/cypress';
import { generateSimpleMarkets } from '../support/mocks/generate-markets'; import {
generateMarketsCandles,
generateMarketsData,
generateSimpleMarkets,
} from '../support/mocks/generate-markets';
import { generateDealTicket } from '../support/mocks/generate-deal-ticket'; import { generateDealTicket } from '../support/mocks/generate-deal-ticket';
import { generateMarketTags } from '../support/mocks/generate-market-tags'; import { generateMarketTags } from '../support/mocks/generate-market-tags';
import { generateMarketPositions } from '../support/mocks/generate-market-positions'; import { generateMarketPositions } from '../support/mocks/generate-market-positions';
@@ -9,13 +13,17 @@ import { generatePartyBalance } from '../support/mocks/generate-party-balance';
import { generatePartyMarketData } from '../support/mocks/generate-party-market-data'; import { generatePartyMarketData } from '../support/mocks/generate-party-market-data';
import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price'; import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price';
import { generateMarketNames } from '../support/mocks/generate-market-names'; import { generateMarketNames } from '../support/mocks/generate-market-names';
import { generateMarketDepth } from '../support/mocks/generate-market-depth';
import type { Market, Markets } from '@vegaprotocol/market-list';
describe('market selector', () => { describe('market selector', { tags: '@smoke' }, () => {
let markets; let markets: Market[];
beforeEach(() => { beforeEach(() => {
cy.mockGQL((req) => { cy.mockGQL((req) => {
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets()); aliasQuery(req, 'Markets', generateSimpleMarkets());
aliasQuery(req, 'DealTicketQuery', generateDealTicket()); aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
aliasQuery(req, 'DealTicket', generateDealTicket());
aliasQuery(req, 'MarketTags', generateMarketTags()); aliasQuery(req, 'MarketTags', generateMarketTags());
aliasQuery(req, 'MarketPositions', generateMarketPositions()); aliasQuery(req, 'MarketPositions', generateMarketPositions());
aliasQuery(req, 'EstimateOrder', generateEstimateOrder()); aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
@@ -23,12 +31,14 @@ describe('market selector', () => {
aliasQuery(req, 'PartyMarketData', generatePartyMarketData()); aliasQuery(req, 'PartyMarketData', generatePartyMarketData());
aliasQuery(req, 'MarketMarkPrice', generateMarketMarkPrice()); aliasQuery(req, 'MarketMarkPrice', generateMarketMarkPrice());
aliasQuery(req, 'MarketNames', generateMarketNames()); aliasQuery(req, 'MarketNames', generateMarketNames());
aliasQuery(req, 'MarketDepth', generateMarketDepth());
}); });
cy.visit('/markets'); cy.visit('/markets');
cy.wait('@SimpleMarkets').then((response) => { cy.wait('@Markets').then((response) => {
if (response.response.body.data?.markets?.length) { const data: Markets | undefined = response?.response?.body?.data;
markets = response.response.body.data.markets; if (data.marketsConnection.edges.length) {
markets = data.marketsConnection.edges.map((edge) => edge.node);
} }
}); });
}); });
@@ -126,7 +136,7 @@ describe('market selector', () => {
cy.getByTestId('market-pane') cy.getByTestId('market-pane')
.children() .children()
.find('[role="button"]') .find('[role="button"]')
.should('have.length', 3); .should('have.length', 9);
cy.get('div[role="dialog"]').should('have.class', 'w-screen'); cy.get('div[role="dialog"]').should('have.class', 'w-screen');
cy.getByTestId('dialog-close').click(); cy.getByTestId('dialog-close').click();
cy.get('input[placeholder="Search"]').should( cy.get('input[placeholder="Search"]').should(
@@ -1,5 +1,9 @@
import { aliasQuery } from '@vegaprotocol/cypress'; import { aliasQuery } from '@vegaprotocol/cypress';
import { generateSimpleMarkets } from '../support/mocks/generate-markets'; import {
generateSimpleMarkets,
generateMarketsCandles,
generateMarketsData,
} from '../support/mocks/generate-markets';
import { generateDealTicket } from '../support/mocks/generate-deal-ticket'; import { generateDealTicket } from '../support/mocks/generate-deal-ticket';
import { generateMarketTags } from '../support/mocks/generate-market-tags'; import { generateMarketTags } from '../support/mocks/generate-market-tags';
import { generateMarketPositions } from '../support/mocks/generate-market-positions'; import { generateMarketPositions } from '../support/mocks/generate-market-positions';
@@ -9,13 +13,17 @@ import { generatePartyMarketData } from '../support/mocks/generate-party-market-
import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price'; import { generateMarketMarkPrice } from '../support/mocks/generate-market-mark-price';
import { generateMarketDepth } from '../support/mocks/generate-market-depth'; import { generateMarketDepth } from '../support/mocks/generate-market-depth';
import { connectVegaWallet } from '../support/connect-wallet'; import { connectVegaWallet } from '../support/connect-wallet';
import type { Markets, Market } from '@vegaprotocol/market-list';
describe('Market trade', () => { describe('Market trade', { tags: '@smoke' }, () => {
let markets; let markets: Market[];
beforeEach(() => { beforeEach(() => {
cy.mockGQL((req) => { cy.mockGQL((req) => {
aliasQuery(req, 'Markets', generateSimpleMarkets());
aliasQuery(req, 'MarketsCandlesQuery', generateMarketsCandles());
aliasQuery(req, 'MarketsDataQuery', generateMarketsData());
aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets()); aliasQuery(req, 'SimpleMarkets', generateSimpleMarkets());
aliasQuery(req, 'DealTicketQuery', generateDealTicket()); aliasQuery(req, 'DealTicket', generateDealTicket());
aliasQuery(req, 'MarketTags', generateMarketTags()); aliasQuery(req, 'MarketTags', generateMarketTags());
aliasQuery(req, 'MarketPositions', generateMarketPositions()); aliasQuery(req, 'MarketPositions', generateMarketPositions());
aliasQuery(req, 'EstimateOrder', generateEstimateOrder()); aliasQuery(req, 'EstimateOrder', generateEstimateOrder());
@@ -25,9 +33,10 @@ describe('Market trade', () => {
aliasQuery(req, 'MarketDepth', generateMarketDepth()); aliasQuery(req, 'MarketDepth', generateMarketDepth());
}); });
cy.visit('/markets'); cy.visit('/markets');
cy.wait('@SimpleMarkets').then((response) => { cy.wait('@Markets').then((response) => {
if (response.response.body.data?.markets?.length) { const data: Markets | undefined = response?.response?.body?.data;
markets = response.response.body.data.markets; if (data.marketsConnection.edges.length) {
markets = data.marketsConnection.edges.map((edge) => edge.node);
} }
}); });
}); });
@@ -290,7 +299,7 @@ describe('Market trade', () => {
cy.getByTestId('place-order').click(); cy.getByTestId('place-order').click();
cy.getByTestId('dialog-title').should( cy.getByTestId('dialog-title').should(
'have.text', 'have.text',
'Confirm transaction in wallet' 'Awaiting network confirmation'
); );
} }
}); });
@@ -2,8 +2,17 @@ import {
connectVegaWallet, connectVegaWallet,
disconnectVegaWallet, disconnectVegaWallet,
} from '../support/connect-wallet'; } from '../support/connect-wallet';
import { aliasQuery } from '@vegaprotocol/cypress';
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';
import { generateFillsMarkets } from '../support/mocks/generate-markets';
describe('Portfolio page', () => { describe('Portfolio page', { tags: '@smoke' }, () => {
afterEach(() => { afterEach(() => {
disconnectVegaWallet(); disconnectVegaWallet();
}); });
@@ -19,19 +28,129 @@ describe('Portfolio page', () => {
it('certain tabs should exist', () => { it('certain tabs should exist', () => {
cy.visit('/portfolio'); cy.visit('/portfolio');
connectVegaWallet(); connectVegaWallet();
cy.getByTestId('Assets').should('exist');
cy.getByTestId('tab-assets').should('exist');
cy.getByTestId('Positions').click(); cy.getByTestId('assets').click();
cy.getByTestId('tab-positions').should('exist'); cy.location('pathname').should('eq', '/portfolio/assets');
cy.getByTestId('Orders').click(); cy.getByTestId('positions').click();
cy.getByTestId('tab-orders').should('exist'); cy.location('pathname').should('eq', '/portfolio/positions');
cy.getByTestId('Fills').click(); cy.getByTestId('orders').click();
cy.getByTestId('tab-fills').should('exist'); cy.location('pathname').should('eq', '/portfolio/orders');
cy.getByTestId('Deposits').click(); cy.getByTestId('fills').click();
cy.getByTestId('tab-deposits').should('exist'); cy.location('pathname').should('eq', '/portfolio/fills');
cy.getByTestId('deposits').click();
cy.location('pathname').should('eq', '/portfolio/deposits');
});
describe('Assets view', () => {
beforeEach(() => {
cy.mockGQL((req) => {
aliasQuery(req, 'Positions', generatePositions());
aliasQuery(req, 'Accounts', generateAccounts());
});
cy.visit('/portfolio/assets');
connectVegaWallet();
});
it('data should be properly rendered', () => {
cy.get('.ag-center-cols-container .ag-row').should('have.length', 3);
cy.get(
'.ag-center-cols-container [row-id="ACCOUNT_TYPE_GENERAL-asset-id-null"]'
)
.find('button')
.click();
cy.getByTestId('dialog-title').should(
'have.text',
'Asset details - tEURO'
);
cy.getByTestId('dialog-close').click();
});
});
describe('Positions view', () => {
beforeEach(() => {
cy.mockGQL((req) => {
aliasQuery(req, 'Positions', generatePositions());
aliasQuery(req, 'Accounts', generateAccounts());
});
cy.visit('/portfolio/positions');
connectVegaWallet();
});
it('data should be properly rendered', () => {
cy.getByTestId('positions-asset-tDAI').should('exist');
cy.getByTestId('positions-asset-tEURO').should('exist');
});
});
describe('Orders view', () => {
beforeEach(() => {
cy.mockGQL((req) => {
aliasQuery(req, 'Orders', generateOrders());
aliasQuery(req, 'Markets', generateFillsMarkets());
});
cy.visit('/portfolio/orders');
connectVegaWallet();
});
it('data should be properly rendered', () => {
cy.get('.ag-center-cols-container .ag-row').should('have.length', 5);
});
});
describe('Fills view', () => {
beforeEach(() => {
cy.mockGQL((req) => {
aliasQuery(req, 'Fills', generateFills());
aliasQuery(req, 'Markets', generateFillsMarkets());
});
cy.visit('/portfolio/fills');
connectVegaWallet();
});
it('data should be properly rendered', () => {
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'
);
});
}); });
}); });
@@ -17,3 +17,5 @@ import '@vegaprotocol/cypress';
import 'cypress-real-events/support'; import 'cypress-real-events/support';
// Import commands.js using ES2015 syntax: // Import commands.js using ES2015 syntax:
import './commands'; import './commands';
import registerCypressGrep from 'cypress-grep';
registerCypressGrep();
@@ -1,4 +1,7 @@
const protoCandles = [ import type { Market } from '@vegaprotocol/market-list';
import { MarketState, MarketTradingMode } from '@vegaprotocol/types';
export const protoCandles = [
{ open: '9556163', close: '9587028', __typename: 'Candle' }, { open: '9556163', close: '9587028', __typename: 'Candle' },
{ {
open: '9587028', open: '9587028',
@@ -73,11 +76,29 @@ const protoCandles = [
}, },
]; ];
export const protoMarket = { export const protoMarket: Market = {
id: 'first-btcusd-id', id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
state: 'STATE_ACTIVE', tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
state: MarketState.STATE_ACTIVE,
decimalPlaces: 5,
positionDecimalPlaces: 0,
marketTimestamps: {
__typename: 'MarketTimestamps',
close: '',
open: '',
},
fees: {
__typename: 'Fees',
factors: {
__typename: 'FeeFactors',
makerFee: '',
infrastructureFee: '',
liquidityFee: '',
},
},
tradableInstrument: { tradableInstrument: {
instrument: { instrument: {
id: '',
code: 'AAVEDAI.MF21', code: 'AAVEDAI.MF21',
name: 'AAVEDAI Monthly (30 Jun 2022)', name: 'AAVEDAI Monthly (30 Jun 2022)',
metadata: { metadata: {
@@ -94,12 +115,11 @@ export const protoMarket = {
product: { product: {
__typename: 'Future', __typename: 'Future',
quoteName: 'DAI', quoteName: 'DAI',
settlementAsset: { symbol: 'tDAI', __typename: 'Asset' }, settlementAsset: { symbol: 'tDAI', __typename: 'Asset', decimals: 5 },
}, },
__typename: 'Instrument', __typename: 'Instrument',
}, },
__typename: 'TradableInstrument', __typename: 'TradableInstrument',
}, },
candles: protoCandles,
__typename: 'Market', __typename: 'Market',
}; };
@@ -0,0 +1,108 @@
import merge from 'lodash/merge';
import type { AccountsQuery } from '@vegaprotocol/accounts';
import { AccountType } from '@vegaprotocol/types';
import type { PartialDeep } from 'type-fest';
export const generateAccounts = (
override?: PartialDeep<AccountsQuery>
): AccountsQuery => {
const defaultAccounts: AccountsQuery = {
party: {
__typename: 'Party',
id: Cypress.env('VEGA_PUBLIC_KEY'),
accounts: [
{
__typename: 'Account',
type: AccountType.ACCOUNT_TYPE_GENERAL,
balance: '100000000',
market: null,
asset: {
__typename: 'Asset',
id: 'asset-id',
symbol: 'tEURO',
decimals: 5,
},
},
{
__typename: 'Account',
type: AccountType.ACCOUNT_TYPE_GENERAL,
balance: '100000000',
market: {
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: 'AAVEDAI Monthly (30 Jun 2022)',
},
},
__typename: 'Market',
},
asset: {
__typename: 'Asset',
id: 'asset-id-2',
symbol: 'tDAI',
decimals: 5,
},
},
{
__typename: 'Account',
type: AccountType.ACCOUNT_TYPE_MARGIN,
balance: '1000',
market: {
__typename: 'Market',
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: '',
},
},
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
},
asset: {
__typename: 'Asset',
id: 'asset-id',
symbol: 'tEURO',
decimals: 5,
},
},
{
__typename: 'Account',
type: AccountType.ACCOUNT_TYPE_MARGIN,
balance: '1000',
market: {
__typename: 'Market',
tradableInstrument: {
__typename: 'TradableInstrument',
instrument: {
__typename: 'Instrument',
name: '',
},
},
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
},
asset: {
__typename: 'Asset',
id: 'asset-id-2',
symbol: 'tDAI',
decimals: 5,
},
},
{
__typename: 'Account',
type: AccountType.ACCOUNT_TYPE_GENERAL,
balance: '100000000',
market: null,
asset: {
__typename: 'Asset',
id: 'asset-0',
symbol: 'AST0',
decimals: 5,
},
},
],
},
};
return merge(defaultAccounts, override);
};
@@ -1,7 +1,7 @@
export const generateDealTicket = () => { export const generateDealTicket = () => {
return { return {
market: { market: {
id: 'first-btcusd-id', id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
decimalPlaces: 5, decimalPlaces: 5,
positionDecimalPlaces: 0, positionDecimalPlaces: 0,
state: 'STATE_ACTIVE', state: 'STATE_ACTIVE',
@@ -0,0 +1,111 @@
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<FillsQuery>
): FillsQuery => {
const fills: FillFieldsFragment[] = [
generateFill({
buyer: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
},
}),
generateFill({
id: '1',
seller: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
},
aggressor: Side.SIDE_SELL,
buyerFee: {
infrastructureFee: '5000',
},
market: {
id: 'market-1',
},
}),
generateFill({
id: '2',
seller: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
},
aggressor: Side.SIDE_BUY,
}),
generateFill({
id: '3',
aggressor: Side.SIDE_SELL,
market: {
id: 'market-2',
},
buyer: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
},
}),
];
const defaultResult: FillsQuery = {
party: {
id: 'buyer-id',
tradesConnection: {
__typename: 'TradeConnection',
edges: fills.map((f) => {
return {
__typename: 'TradeEdge',
node: f,
cursor: '3',
};
}),
pageInfo: {
__typename: 'PageInfo',
startCursor: '1',
endCursor: '2',
hasNextPage: false,
hasPreviousPage: false,
},
},
__typename: 'Party',
},
};
return merge(defaultResult, override);
};
export const generateFill = (override?: PartialDeep<FillFieldsFragment>) => {
const defaultFill: FillFieldsFragment = {
__typename: 'Trade',
id: '0',
createdAt: new Date().toISOString(),
price: '10000000',
size: '50000',
buyOrder: 'buy-order',
sellOrder: 'sell-order',
aggressor: Side.SIDE_BUY,
buyer: {
__typename: 'Party',
id: 'buyer-id',
},
seller: {
__typename: 'Party',
id: 'seller-id',
},
buyerFee: {
__typename: 'TradeFee',
makerFee: '100',
infrastructureFee: '100',
liquidityFee: '100',
},
sellerFee: {
__typename: 'TradeFee',
makerFee: '200',
infrastructureFee: '200',
liquidityFee: '200',
},
market: {
__typename: 'Market',
id: 'market-0',
},
};
return merge(defaultFill, override);
};
@@ -1,24 +1,15 @@
export const generateMarketDepth = () => { import merge from 'lodash/merge';
return { import type { PartialDeep } from 'type-fest';
// eslint-disable-next-line @nrwl/nx/enforce-module-boundaries
import type { MarketDepth } from '../../../../../libs/market-depth/src/lib/__generated__/MarketDepth';
export const generateMarketDepth = (
override?: PartialDeep<MarketDepth>
): MarketDepth => {
const defaultResult: MarketDepth = {
market: { market: {
id: 'a46bd7e5277087723b7ab835844dec3cef8b4445738101269624bf5537d5d423', id: 'a46bd7e5277087723b7ab835844dec3cef8b4445738101269624bf5537d5d423',
decimalPlaces: 5,
positionDecimalPlaces: 0,
data: {
staticMidPrice: '9893006',
marketTradingMode: 'TRADING_MODE_CONTINUOUS',
indicativeVolume: '0',
indicativePrice: '0',
bestStaticBidPrice: '9893006',
bestStaticOfferPrice: '9893006',
market: {
id: 'a46bd7e5277087723b7ab835844dec3cef8b4445738101269624bf5537d5d423',
__typename: 'Market',
},
__typename: 'MarketData',
},
depth: { depth: {
lastTrade: { price: '9893006', __typename: 'Trade' },
sell: [ sell: [
{ {
price: '9893007', price: '9893007',
@@ -215,4 +206,5 @@ export const generateMarketDepth = () => {
__typename: 'Market', __typename: 'Market',
}, },
}; };
return merge(defaultResult, override);
}; };
@@ -21,7 +21,7 @@ export const generateMarketPositions = () => {
}, },
balance: '265329', balance: '265329',
market: { market: {
id: 'first-btcusd-id', id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
__typename: 'Market', __typename: 'Market',
}, },
}, },
@@ -43,7 +43,7 @@ export const generateMarketPositions = () => {
node: { node: {
openVolume: '12', openVolume: '12',
market: { market: {
id: 'first-btcusd-id', id: 'ca7768f6de84bf86a21bbb6b0109d9659c81917b0e0339b2c262566c9b581a15',
__typename: 'Market', __typename: 'Market',
}, },
__typename: 'Position', __typename: 'Position',
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,149 @@
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
import type {
Orders,
Orders_party_ordersConnection_edges_node,
} from '@vegaprotocol/orders';
import {
OrderStatus,
OrderTimeInForce,
OrderType,
Side,
} from '@vegaprotocol/types';
export const generateOrders = (override?: PartialDeep<Orders>): Orders => {
const orders: Orders_party_ordersConnection_edges_node[] = [
{
__typename: 'Order',
id: '066468C06549101DAF7BC51099E1412A0067DC08C246B7D8013C9D0CBF1E8EE7',
market: {
__typename: 'Market',
id: 'market-0',
},
size: '10',
type: OrderType.TYPE_LIMIT,
status: OrderStatus.STATUS_FILLED,
side: Side.SIDE_BUY,
remaining: '0',
price: '20000000',
timeInForce: OrderTimeInForce.TIME_IN_FORCE_GTC,
createdAt: new Date(2020, 1, 30).toISOString(),
updatedAt: null,
expiresAt: null,
rejectionReason: null,
liquidityProvision: null,
peggedOrder: null,
},
{
__typename: 'Order',
id: '48DB6767E4E4E0F649C5A13ABFADE39F8451C27DA828DAF14B7A1E8E5EBDAD99',
market: {
__typename: 'Market',
id: 'market-1',
},
size: '1',
type: OrderType.TYPE_LIMIT,
status: OrderStatus.STATUS_FILLED,
side: Side.SIDE_BUY,
remaining: '0',
price: '100',
timeInForce: OrderTimeInForce.TIME_IN_FORCE_GTC,
createdAt: new Date(2020, 1, 29).toISOString(),
updatedAt: null,
expiresAt: null,
rejectionReason: null,
liquidityProvision: null,
peggedOrder: null,
},
{
__typename: 'Order',
id: '4e93702990712c41f6995fcbbd94f60bb372ad12d64dfa7d96d205c49f790336',
market: {
__typename: 'Market',
id: 'market-2',
},
size: '1',
type: OrderType.TYPE_LIMIT,
status: OrderStatus.STATUS_FILLED,
side: Side.SIDE_BUY,
remaining: '0',
price: '20000',
timeInForce: OrderTimeInForce.TIME_IN_FORCE_GTC,
createdAt: new Date(2020, 1, 28).toISOString(),
updatedAt: null,
expiresAt: null,
rejectionReason: null,
liquidityProvision: null,
peggedOrder: null,
},
{
__typename: 'Order',
id: '94737d2bafafa4bc3b80a56ef084ae52a983b91aa067c31e243c61a0f962a836',
market: {
__typename: 'Market',
id: 'market-3',
},
size: '1',
type: OrderType.TYPE_LIMIT,
status: OrderStatus.STATUS_ACTIVE,
side: Side.SIDE_BUY,
remaining: '0',
price: '100000',
timeInForce: OrderTimeInForce.TIME_IN_FORCE_GTC,
createdAt: new Date(2020, 1, 27).toISOString(),
updatedAt: null,
expiresAt: null,
rejectionReason: null,
liquidityProvision: null,
peggedOrder: null,
},
{
__typename: 'Order',
id: '94aead3ca92dc932efcb503631b03a410e2a5d4606cae6083e2406dc38e52f78',
market: {
__typename: 'Market',
id: 'market-3',
},
size: '10',
type: OrderType.TYPE_LIMIT,
status: OrderStatus.STATUS_PARTIALLY_FILLED,
side: Side.SIDE_SELL,
remaining: '3',
price: '100000',
timeInForce: OrderTimeInForce.TIME_IN_FORCE_GTC,
createdAt: new Date(2020, 1, 27).toISOString(),
updatedAt: null,
expiresAt: null,
liquidityProvision: null,
peggedOrder: null,
rejectionReason: null,
},
];
const defaultResult: Orders = {
party: {
id: Cypress.env('VEGA_PUBLIC_KEY'),
ordersConnection: {
__typename: 'OrderConnection',
edges: orders.map((f) => {
return {
__typename: 'OrderEdge',
node: f,
cursor: f.id,
};
}),
pageInfo: {
__typename: 'PageInfo',
startCursor:
'066468C06549101DAF7BC51099E1412A0067DC08C246B7D8013C9D0CBF1E8EE7',
endCursor:
'94737d2bafafa4bc3b80a56ef084ae52a983b91aa067c31e243c61a0f962a836',
hasNextPage: false,
hasPreviousPage: false,
},
},
__typename: 'Party',
},
};
return merge(defaultResult, override);
};
@@ -0,0 +1,201 @@
import merge from 'lodash/merge';
import type { PartialDeep } from 'type-fest';
import type {
Positions,
Positions_party_positionsConnection_edges_node,
} from '@vegaprotocol/positions';
import { MarketTradingMode } from '@vegaprotocol/types';
export const generatePositions = (
override?: PartialDeep<Positions>
): Positions => {
const nodes: Positions_party_positionsConnection_edges_node[] = [
{
__typename: 'Position',
realisedPNL: '0',
openVolume: '6',
unrealisedPNL: '895000',
averageEntryPrice: '1129935',
updatedAt: '2022-07-28T15:09:34.441143Z',
marginsConnection: {
__typename: 'MarginConnection',
edges: [
{
__typename: 'MarginEdge',
node: {
__typename: 'MarginLevels',
maintenanceLevel: '0',
searchLevel: '0',
initialLevel: '0',
collateralReleaseLevel: '0',
market: {
__typename: 'Market',
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
},
asset: {
__typename: 'Asset',
symbol: 'tDAI',
},
},
},
],
},
market: {
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
data: {
markPrice: '17588787',
__typename: 'MarketData',
market: {
__typename: 'Market',
id: 'c9f5acd348796011c075077e4d58d9b7f1689b7c1c8e030a5e886b83aa96923d',
},
},
decimalPlaces: 5,
positionDecimalPlaces: 0,
tradableInstrument: {
instrument: {
name: 'UNIDAI Monthly (30 Jun 2022)',
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
__typename: 'Market',
},
},
{
__typename: 'Position',
realisedPNL: '100',
openVolume: '20',
unrealisedPNL: '895000',
averageEntryPrice: '8509338',
updatedAt: '2022-07-28T15:09:34.441143Z',
marginsConnection: {
__typename: 'MarginConnection',
edges: [
{
__typename: 'MarginEdge',
node: {
__typename: 'MarginLevels',
maintenanceLevel: '0',
searchLevel: '0',
initialLevel: '0',
collateralReleaseLevel: '0',
market: {
__typename: 'Market',
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
},
asset: {
__typename: 'Asset',
symbol: 'tDAI',
},
},
},
],
},
market: {
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
data: {
markPrice: '8649338',
__typename: 'MarketData',
market: {
__typename: 'Market',
id: '0604e8c918655474525e1a95367902266ade70d318c2c908f0cca6e3d11dcb13',
},
},
decimalPlaces: 5,
positionDecimalPlaces: 0,
tradableInstrument: {
instrument: {
name: 'AAVEDAI Monthly (30 Jun 2022)',
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
__typename: 'Market',
},
},
{
realisedPNL: '0',
openVolume: '1',
unrealisedPNL: '-22519',
averageEntryPrice: '84400088',
updatedAt: '2022-07-28T14:53:54.725477Z',
marginsConnection: {
__typename: 'MarginConnection',
edges: [
{
__typename: 'MarginEdge',
node: {
__typename: 'MarginLevels',
maintenanceLevel: '0',
searchLevel: '0',
initialLevel: '0',
collateralReleaseLevel: '0',
market: {
__typename: 'Market',
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
},
asset: {
__typename: 'Asset',
symbol: 'tEURO',
},
},
},
],
},
market: {
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
tradingMode: MarketTradingMode.TRADING_MODE_CONTINUOUS,
data: {
markPrice: '84377569',
__typename: 'MarketData',
market: {
__typename: 'Market',
id: '5a4b0b9e9c0629f0315ec56fcb7bd444b0c6e4da5ec7677719d502626658a376',
},
},
decimalPlaces: 5,
positionDecimalPlaces: 0,
tradableInstrument: {
instrument: {
name: 'Tesla Quarterly (30 Jun 2022)',
__typename: 'Instrument',
},
__typename: 'TradableInstrument',
},
__typename: 'Market',
},
__typename: 'Position',
},
];
const defaultResult: Positions = {
party: {
__typename: 'Party',
id: Cypress.env('VEGA_PUBLIC_KEY'),
positionsConnection: {
__typename: 'PositionConnection',
edges: nodes.map((node) => {
return {
__typename: 'PositionEdge',
node,
};
}),
},
},
};
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
@@ -6,7 +6,7 @@
"allowSyntheticDefaultImports": true, "allowSyntheticDefaultImports": true,
"outDir": "../../dist/out-tsc", "outDir": "../../dist/out-tsc",
"allowJs": true, "allowJs": true,
"types": ["cypress", "node", "cypress-real-events"] "types": ["cypress", "node", "cypress-real-events", "cypress-grep"]
}, },
"include": ["src/**/*.ts", "src/**/*.js"] "include": ["src/**/*.ts", "src/**/*.js"]
} }
-1
View File
@@ -1,4 +1,3 @@
# App configuration variables # App configuration variables
NX_VEGA_URL=http://localhost:3028/query NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_ENV=LOCAL NX_VEGA_ENV=LOCAL
NX_VEGA_REST=http://localhost:3029
-1
View File
@@ -2,7 +2,6 @@
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/devnet-network.json
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
NX_VEGA_ENV=DEVNET NX_VEGA_ENV=DEVNET
NX_VEGA_REST=https://api.n04.d.vega.xyz
NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\"} NX_VEGA_NETWORKS={\"MAINNET\":\"https://alpha.console.vega.xyz\"}
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8 NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://ropsten.etherscan.io NX_ETHERSCAN_URL=https://ropsten.etherscan.io
+1 -2
View File
@@ -1,8 +1,7 @@
# App configuration variables # App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/mainnet-network.json
NX_VEGA_URL=https://api.token.vega.xyz/query NX_VEGA_URL=https://api.vega.xyz/query
NX_VEGA_ENV=MAINNET NX_VEGA_ENV=MAINNET
NX_VEGA_REST=https://api.token.vega.xyz
NX_VEGA_NETWORKS='{\"MAINNET\":\"https://alpha.console.vega.xyz\"}' NX_VEGA_NETWORKS='{\"MAINNET\":\"https://alpha.console.vega.xyz\"}'
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8 NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://etherscan.io NX_ETHERSCAN_URL=https://etherscan.io
-1
View File
@@ -2,7 +2,6 @@
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/stagnet3-network.json
NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql NX_VEGA_URL=https://api.n01.stagnet3.vega.xyz/graphql
NX_VEGA_ENV=STAGNET3 NX_VEGA_ENV=STAGNET3
NX_VEGA_REST=https://api.n01.stagnet3.vega.xyz
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8 NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://ropsten.etherscan.io NX_ETHERSCAN_URL=https://ropsten.etherscan.io
NX_VEGA_EXPLORER_URL=https://staging2.explorer.vega.xyz NX_VEGA_EXPLORER_URL=https://staging2.explorer.vega.xyz
+1 -2
View File
@@ -1,8 +1,7 @@
# App configuration variables # App configuration variables
NX_VEGA_CONFIG_URL=https://static.vega.xyz/assets/testnet-network.json 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_ENV=TESTNET
NX_VEGA_REST=https://api.n11.testnet.vega.xyz
NX_VEGA_NETWORKS='{\"MAINNET\":\"https://alpha.console.vega.xyz\"}' NX_VEGA_NETWORKS='{\"MAINNET\":\"https://alpha.console.vega.xyz\"}'
NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8 NX_ETHEREUM_PROVIDER_URL=https://ropsten.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://ropsten.etherscan.io NX_ETHERSCAN_URL=https://ropsten.etherscan.io
+3
View File
@@ -1,4 +1,5 @@
import '@testing-library/jest-dom'; import '@testing-library/jest-dom';
import 'jest-canvas-mock';
import { defaultFallbackInView } from 'react-intersection-observer'; import { defaultFallbackInView } from 'react-intersection-observer';
import ResizeObserver from 'resize-observer-polyfill'; import ResizeObserver from 'resize-observer-polyfill';
@@ -38,3 +39,5 @@ Object.defineProperty(window, 'matchMedia', {
dispatchEvent: jest.fn(), dispatchEvent: jest.fn(),
})), })),
}); });
jest.setTimeout(30000);
@@ -0,0 +1,112 @@
import React, {
forwardRef,
useCallback,
useContext,
useMemo,
useRef,
} from 'react';
import classNames from 'classnames';
import type { AgGridReact } from 'ag-grid-react';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit';
import { ThemeContext, useScreenDimensions } 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 {
rowData?: T[];
datasource?: Datasource<T>;
handleRowClicked?: (event: { data: T }) => void;
components?: Record<string, unknown>;
classNamesParam?: string | string[];
}
const ConsoleLiteGrid = <T extends { id?: string }>(
{ 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 handleOnGridReady = useCallback(() => {
(
(ref as React.RefObject<AgGridReact>) || gridRef
).current?.api?.sizeColumnsToFit();
}, [gridRef, ref]);
const onTabToNextCell = useCallback((params: TabToNextCellParams) => {
const {
api,
previousCellPosition: { rowIndex },
} = params;
const rowCount = api.getDisplayedRowCount();
if (rowCount <= rowIndex + 1) {
return null;
}
return { ...params.previousCellPosition, rowIndex: rowIndex + 1 };
}, []);
const getRowIdLocal = useCallback(({ data }: GetRowIdParams) => data.id, []);
const onCellKeyDown = useCallback(
(
params: (CellKeyDownEvent | FullWidthCellKeyDownEvent) & {
event: KeyboardEvent;
}
) => {
const { event: { key = '' } = {}, data } = params;
if (key === 'Enter') {
handleRowClicked?.({ data });
}
},
[handleRowClicked]
);
const shouldSuppressHorizontalScroll = useMemo(() => {
return !isMobile && constants.LARGE_SCREENS.includes(screenSize);
}, [isMobile, screenSize]);
return (
<AgGrid
className={classNames(classNamesParam)}
rowHeight={60}
customThemeParams={
theme === 'dark'
? constants.agGridDarkVariables
: constants.agGridLightVariables
}
onGridReady={handleOnGridReady}
onRowClicked={handleRowClicked}
rowClass={isMobile ? 'mobile' : ''}
rowClassRules={constants.ROW_CLASS_RULES}
ref={ref || gridRef}
overlayNoRowsTemplate={NO_DATA_MESSAGE}
suppressContextMenu
getRowId={getRowId || getRowIdLocal}
suppressMovableColumns
suppressRowTransform
onCellKeyDown={onCellKeyDown}
tabToNextCell={onTabToNextCell}
suppressHorizontalScroll={shouldSuppressHorizontalScroll}
{...props}
/>
);
};
const ConsoleLiteGridForwarder = forwardRef(ConsoleLiteGrid) as <T>(
p: Props<T> & { ref?: React.Ref<AgGridReact> }
) => React.ReactElement;
export default ConsoleLiteGridForwarder;
@@ -0,0 +1 @@
export { default as ConsoleLiteGrid } from './console-lite-grid';
@@ -1,13 +1,13 @@
import * as React from 'react'; import * as React from 'react';
import classNames from 'classnames'; 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 type { PartyBalanceQuery_party_accounts } from './__generated__/PartyBalanceQuery';
import { useSettlementAccount } from '../../hooks/use-settlement-account'; import { useSettlementAccount } from '../../hooks/use-settlement-account';
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers'; import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
import { AccountType } from '@vegaprotocol/types'; import { AccountType } from '@vegaprotocol/types';
interface DealTicketBalanceProps { interface DealTicketBalanceProps {
settlementAsset: DealTicketQuery_market_tradableInstrument_instrument_product_settlementAsset; settlementAsset: DealTicketMarketFragment['tradableInstrument']['instrument']['product']['settlementAsset'];
accounts: PartyBalanceQuery_party_accounts[]; accounts: PartyBalanceQuery_party_accounts[];
isWalletConnected: boolean; isWalletConnected: boolean;
className?: string; className?: string;
@@ -52,6 +52,10 @@ export const DealTicketContainer = () => {
const container = marketId ? ( const container = marketId ? (
<Container marketId={marketId}> <Container marketId={marketId}>
{(data) => { {(data) => {
if (!data.market) {
return null as unknown as JSX.Element;
}
const balance = ( const balance = (
<DealTicketBalance <DealTicketBalance
className="mb-4" className="mb-4"
@@ -2,7 +2,7 @@ import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { useForm, Controller } from 'react-hook-form'; import { useForm, Controller } from 'react-hook-form';
import { Stepper } from '../stepper'; 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 { InputError } from '@vegaprotocol/ui-toolkit';
import { BigNumber } from 'bignumber.js'; import { BigNumber } from 'bignumber.js';
import { MarketSelector } from '@vegaprotocol/deal-ticket'; import { MarketSelector } from '@vegaprotocol/deal-ticket';
@@ -37,7 +37,7 @@ import { Side, OrderType } from '@vegaprotocol/types';
import { DealTicketSlippage } from './deal-ticket-slippage'; import { DealTicketSlippage } from './deal-ticket-slippage';
interface DealTicketMarketProps { interface DealTicketMarketProps {
market: DealTicketQuery_market; market: DealTicketMarketFragment;
partyData?: PartyBalanceQuery; partyData?: PartyBalanceQuery;
} }
@@ -6,7 +6,7 @@ import {
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import * as React from 'react'; import * as React from 'react';
import classNames from 'classnames'; 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 type { Order } from '@vegaprotocol/orders';
import { SIDE_NAMES } from './side-selector'; import { SIDE_NAMES } from './side-selector';
import SimpleMarketExpires from '../simple-market-list/simple-market-expires'; import SimpleMarketExpires from '../simple-market-list/simple-market-expires';
@@ -33,7 +33,7 @@ export const MARKET_TAGS_QUERY = gql`
`; `;
interface Props { interface Props {
market: DealTicketQuery_market; market: DealTicketMarketFragment;
isDisabled: boolean; isDisabled: boolean;
transactionStatus?: string; transactionStatus?: string;
order: Order; order: Order;
@@ -1,4 +1,4 @@
query Deposits { query DepositAssets {
assetsConnection { assetsConnection {
edges { edges {
node { node {
@@ -0,0 +1,75 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
import { AssetStatus } from "@vegaprotocol/types";
// ====================================================
// GraphQL query operation: DepositAssets
// ====================================================
export interface DepositAssets_assetsConnection_edges_node_source_BuiltinAsset {
__typename: "BuiltinAsset";
}
export interface DepositAssets_assetsConnection_edges_node_source_ERC20 {
__typename: "ERC20";
/**
* The address of the ERC20 contract
*/
contractAddress: string;
}
export type DepositAssets_assetsConnection_edges_node_source = DepositAssets_assetsConnection_edges_node_source_BuiltinAsset | DepositAssets_assetsConnection_edges_node_source_ERC20;
export interface DepositAssets_assetsConnection_edges_node {
__typename: "Asset";
/**
* The ID of the asset
*/
id: string;
/**
* The full name of the asset (e.g: Great British Pound)
*/
name: string;
/**
* The symbol of the asset (e.g: GBP)
*/
symbol: string;
/**
* The precision of the asset. Should match the decimal precision of the asset on its native chain, e.g: for ERC20 assets, it is often 18
*/
decimals: number;
/**
* The status of the asset in the Vega network
*/
status: AssetStatus;
/**
* The origin source of the asset (e.g: an ERC20 asset)
*/
source: DepositAssets_assetsConnection_edges_node_source;
}
export interface DepositAssets_assetsConnection_edges {
__typename: "AssetEdge";
/**
* The asset information
*/
node: DepositAssets_assetsConnection_edges_node;
}
export interface DepositAssets_assetsConnection {
__typename: "AssetsConnection";
/**
* The assets
*/
edges: (DepositAssets_assetsConnection_edges | null)[] | null;
}
export interface DepositAssets {
/**
* The list of all assets in use in the Vega network or the specified asset if ID is provided
*/
assetsConnection: DepositAssets_assetsConnection | null;
}
@@ -3,14 +3,14 @@ import { Schema as Types } from '@vegaprotocol/types';
import { gql } from '@apollo/client'; import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client'; import * as Apollo from '@apollo/client';
const defaultOptions = {} as const; 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 } }; 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` export const DepositAssetsDocument = gql`
query Deposits { query DepositAssets {
assetsConnection { assetsConnection {
edges { edges {
node { 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. * To run a query within a React component, call `useDepositAssetsQuery` 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 * 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. * 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; * @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 * @example
* const { data, loading, error } = useDepositsQuery({ * const { data, loading, error } = useDepositAssetsQuery({
* variables: { * variables: {
* }, * },
* }); * });
*/ */
export function useDepositsQuery(baseOptions?: Apollo.QueryHookOptions<DepositsQuery, DepositsQueryVariables>) { export function useDepositAssetsQuery(baseOptions?: Apollo.QueryHookOptions<DepositAssetsQuery, DepositAssetsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions} 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} 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 DepositAssetsQueryHookResult = ReturnType<typeof useDepositAssetsQuery>;
export type DepositsLazyQueryHookResult = ReturnType<typeof useDepositsLazyQuery>; export type DepositAssetsLazyQueryHookResult = ReturnType<typeof useDepositAssetsLazyQuery>;
export type DepositsQueryResult = Apollo.QueryResult<DepositsQuery, DepositsQueryVariables>; 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 { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import { Web3Container } from '@vegaprotocol/web3'; import { Web3Container } from '@vegaprotocol/web3';
import type { Deposits } from './__generated__/Deposits'; import type { DepositAssets } from './__generated__/DepositAssets';
const DEPOSITS_QUERY = gql` const DEPOSITS_QUERY = gql`
query Deposits { query DepositAssets {
assetsConnection { assetsConnection {
edges { edges {
node { node {
@@ -35,7 +35,7 @@ export const DepositContainer = () => {
const { VEGA_ENV } = useEnvironment(); const { VEGA_ENV } = useEnvironment();
const { keypair } = useVegaWallet(); const { keypair } = useVegaWallet();
const { data, loading, error } = useQuery<Deposits>(DEPOSITS_QUERY, { const { data, loading, error } = useQuery<DepositAssets>(DEPOSITS_QUERY, {
variables: { partyId: keypair?.pub }, variables: { partyId: keypair?.pub },
skip: !keypair?.pub, skip: !keypair?.pub,
}); });
@@ -43,7 +43,7 @@ export const DepositContainer = () => {
const assets = getEnabledAssets(data); const assets = getEnabledAssets(data);
return ( return (
<AsyncRenderer<Deposits> data={data} loading={loading} error={error}> <AsyncRenderer<DepositAssets> data={data} loading={loading} error={error}>
{assets.length ? ( {assets.length ? (
<Web3Container> <Web3Container>
<DepositManager <DepositManager
@@ -12,7 +12,7 @@ const Header = () => {
} = useContext(LocalContext); } = useContext(LocalContext);
return ( return (
<div <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" data-testid="header"
> >
<Logo /> <Logo />
@@ -21,12 +21,7 @@ const Header = () => {
setConnectDialog={setConnect} setConnectDialog={setConnect}
setManageDialog={setManage} setManageDialog={setManage}
/> />
<ThemeSwitcher <ThemeSwitcher theme={theme} onToggle={toggleTheme} className="-my-4" />
theme={theme}
onToggle={toggleTheme}
className="-my-4"
fixedBg="dark"
/>
</div> </div>
</div> </div>
); );
@@ -0,0 +1,103 @@
import classNames from 'classnames';
import React, { useEffect, useRef, useState } from 'react';
import { Link } from 'react-router-dom';
export interface Item {
name: string;
id: string;
url?: string;
isActive?: boolean;
color?: string;
cssClass?: string;
}
interface Props {
active?: string;
cssClass?: string[];
items: Item[];
'data-testid'?: string;
'aria-label'?: string;
}
const MenuItem = ({ id, name, url, isActive, cssClass }: Item): JSX.Element => {
if (!url) {
return <span data-testid={id}>{name}</span>;
}
return (
<Link
to={url}
aria-label={name}
className={classNames('pl-0 hover:opacity-75', cssClass, {
active: isActive,
})}
data-testid={id}
>
{name}
</Link>
);
};
const findActive = (active?: string, items?: Item[]) => {
if (!active && items?.length) {
return 0;
}
return items?.length
? items.findIndex((item) => item.id === active) || 0
: -1;
};
export const HorizontalMenu = ({
items,
active,
'data-testid': dataTestId,
'aria-label': ariaLabel,
}: Props) => {
const [activeNumber, setActiveNumber] = useState<number>(
findActive(active, items)
);
const slideContRef = useRef<HTMLUListElement | null>(null);
const [sliderStyles, setSliderStyles] = useState<Record<string, string>>({});
useEffect(() => {
setActiveNumber(findActive(active, items));
}, [active, items]);
useEffect(() => {
const contStyles = (
slideContRef.current as HTMLUListElement
).getBoundingClientRect();
const selectedStyles = (slideContRef.current as HTMLUListElement).children[
activeNumber
]?.getBoundingClientRect();
const styles: Record<string, string> = selectedStyles
? {
backgroundColor: items[activeNumber].color || '',
width: `${selectedStyles.width}px`,
left: `${selectedStyles.left - contStyles.left}px`,
}
: {};
setSliderStyles(styles);
}, [activeNumber, slideContRef, items]);
return items.length ? (
<ul
ref={slideContRef}
className="grid grid-flow-col auto-cols-min gap-4 relative pb-2 mb-2"
data-testid={dataTestId}
aria-label={ariaLabel}
>
{items.map((item, i) => (
<li key={item.id} className="md:mr-2 whitespace-nowrap">
<MenuItem {...item} isActive={i === activeNumber} />
</li>
))}
<li
className="absolute bottom-0 h-[2px] transition-left duration-300 dark:bg-white bg-black"
key="slider"
style={sliderStyles}
/>
</ul>
) : null;
};
export default HorizontalMenu;
@@ -0,0 +1,2 @@
export { default as HorizontalMenu } from './horizontal-menu';
export type { Item as HorizontalMenuItem } from './horizontal-menu';
@@ -0,0 +1,83 @@
import { useMemo, useRef, useCallback } from 'react';
import { useOutletContext } from 'react-router-dom';
import type { AgGridReact } from 'ag-grid-react';
import { PriceCell, useDataProvider } from '@vegaprotocol/react-helpers';
import type { AccountFields } from '@vegaprotocol/accounts';
import { aggregatedAccountsDataProvider, getId } from '@vegaprotocol/accounts';
import type { IGetRowsParams } from 'ag-grid-community';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import {
AssetDetailsDialog,
useAssetDetailsDialogStore,
} from '@vegaprotocol/assets';
import { NO_DATA_MESSAGE } from '../../../constants';
import { ConsoleLiteGrid } from '../../console-lite-grid';
import { useAccountColumnDefinitions } from '.';
const AccountsManager = () => {
const { partyId = '' } = useOutletContext<{ partyId: string }>();
const { isOpen, symbol, setOpen } = useAssetDetailsDialogStore();
const gridRef = useRef<AgGridReact | null>(null);
const dataRef = useRef<AccountFields[] | null>(null);
const variables = useMemo(() => ({ partyId }), [partyId]);
const update = useCallback(
({ data }: { data: AccountFields[] | null }) => {
if (!gridRef.current?.api) {
return false;
}
if (dataRef.current?.length) {
dataRef.current = data;
gridRef.current.api.refreshInfiniteCache();
return true;
}
return false;
},
[gridRef]
);
const { data, error, loading } = useDataProvider<AccountFields[], never>({
dataProvider: aggregatedAccountsDataProvider,
update,
variables,
});
dataRef.current = data;
const getRows = async ({
successCallback,
startRow,
endRow,
}: IGetRowsParams) => {
const rowsThisBlock = dataRef.current
? dataRef.current.slice(startRow, endRow)
: [];
const lastRow = dataRef.current?.length ?? -1;
successCallback(rowsThisBlock, lastRow);
};
const { columnDefs, defaultColDef } = useAccountColumnDefinitions();
return (
<>
<AsyncRenderer
loading={loading}
error={error}
data={data}
noDataMessage={NO_DATA_MESSAGE}
>
<ConsoleLiteGrid<AccountFields>
rowData={data?.length ? undefined : []}
rowModelType={data?.length ? 'infinite' : 'clientSide'}
ref={gridRef}
datasource={{ getRows }}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
components={{ PriceCell }}
getRowId={({ data }) => getId(data)}
/>
</AsyncRenderer>
<AssetDetailsDialog
assetSymbol={symbol}
open={isOpen}
onChange={(open) => setOpen(open)}
/>
</>
);
};
export default AccountsManager;
@@ -0,0 +1,2 @@
export { default as AccountManager } from './accounts';
export { default as useAccountColumnDefinitions } from './use-column-definitions';
@@ -0,0 +1,80 @@
import React, { useMemo } from 'react';
import { addDecimalsFormatNumber, t } from '@vegaprotocol/react-helpers';
import type { AccountFields } from '@vegaprotocol/accounts';
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
import type { ColDef, GroupCellRendererParams } from 'ag-grid-community';
import type { VegaValueFormatterParams } from '@vegaprotocol/ui-toolkit';
const useAccountColumnDefinitions = () => {
const { open } = useAssetDetailsDialogStore();
const columnDefs: ColDef[] = useMemo(() => {
return [
{
colId: 'account-asset',
headerName: t('Asset'),
field: 'asset.symbol',
headerClass: 'uppercase justify-start',
cellClass: 'uppercase flex h-full items-center md:pl-4',
cellRenderer: ({ value }: GroupCellRendererParams) =>
value && value.length > 0 ? (
<div className="md:pl-4 grid h-full items-center" title={value}>
<div className="truncate min-w-0">
<button
className="hover:underline"
onClick={() => {
open(value);
}}
>
{value}
</button>
</div>
</div>
) : (
''
),
},
{
colId: 'deposited',
headerName: t('Deposited'),
field: 'deposited',
cellRenderer: 'PriceCell',
valueFormatter: ({
value,
data,
}: VegaValueFormatterParams<AccountFields, 'deposited'>) => {
if (value && data) {
return addDecimalsFormatNumber(value, data.asset.decimals);
}
return '-';
},
},
{
colId: 'used',
headerName: t('Used'),
field: 'used',
cellRenderer: 'PriceCell',
valueFormatter: ({
value,
data,
}: VegaValueFormatterParams<AccountFields, 'used'>) => {
if (value && data) {
return addDecimalsFormatNumber(value, data.asset.decimals);
}
return '-';
},
},
];
}, [open]);
const defaultColDef = useMemo(() => {
return {
sortable: true,
unSortIcon: true,
headerClass: 'uppercase',
editable: false,
};
}, []);
return { columnDefs, defaultColDef };
};
export default useAccountColumnDefinitions;
@@ -0,0 +1,35 @@
import { t } from '@vegaprotocol/react-helpers';
export const PORTFOLIO_ASSETS = 'assets';
export const PORTFOLIO_POSITIONS = 'positions';
export const PORTFOLIO_ORDERS = 'orders';
export const PORTFOLIO_FILLS = 'fills';
export const PORTFOLIO_DEPOSITS = 'deposits';
export const PORTFOLIO_ITEMS = [
{
name: t('Assets'),
id: PORTFOLIO_ASSETS,
url: `/portfolio/${PORTFOLIO_ASSETS}`,
},
{
name: t('Positions'),
id: PORTFOLIO_POSITIONS,
url: `/portfolio/${PORTFOLIO_POSITIONS}`,
},
{
name: t('Orders'),
id: PORTFOLIO_ORDERS,
url: `/portfolio/${PORTFOLIO_ORDERS}`,
},
{
name: t('Fills'),
id: PORTFOLIO_FILLS,
url: `/portfolio/${PORTFOLIO_FILLS}`,
},
{
name: t('Deposits'),
id: PORTFOLIO_DEPOSITS,
url: `/portfolio/${PORTFOLIO_DEPOSITS}`,
},
];
@@ -0,0 +1,53 @@
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';
const FillsManager = () => {
const { partyId } = useOutletContext<{ partyId: string }>();
const { columnDefs, defaultColDef } = useColumnDefinitions({ partyId });
const gridRef = useRef<AgGridReact | null>(null);
const scrolledToTop = useRef(true);
const { data, error, loading, addNewRows, getRows } = useFillsList({
partyId,
gridRef,
scrolledToTop,
});
const onBodyScrollEnd = (event: BodyScrollEndEvent) => {
if (event.top === 0) {
addNewRows();
}
};
const onBodyScroll = (event: BodyScrollEvent) => {
scrolledToTop.current = event.top <= 0;
};
return (
<AsyncRenderer
loading={loading}
error={error}
data={data?.length ? data : null}
noDataMessage={NO_DATA_MESSAGE}
>
<ConsoleLiteGrid<TradeWithMarket>
ref={gridRef}
rowModelType="infinite"
datasource={{ getRows }}
onBodyScrollEnd={onBodyScrollEnd}
onBodyScroll={onBodyScroll}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
/>
</AsyncRenderer>
);
};
export default FillsManager;
@@ -0,0 +1 @@
export { default as FillsManager } from './fills';
@@ -0,0 +1,190 @@
import { useMemo } from 'react';
import type { ColDef, ValueFormatterParams } from 'ag-grid-community';
import type { TradeWithMarket } from '@vegaprotocol/fills';
import classNames from 'classnames';
import {
addDecimal,
addDecimalsFormatNumber,
formatNumber,
getDateTimeFormat,
negativeClassNames,
positiveClassNames,
t,
} from '@vegaprotocol/react-helpers';
import BigNumber from 'bignumber.js';
import { Side } from '@vegaprotocol/types';
interface Props {
partyId: string;
}
const useColumnDefinitions = ({ partyId }: Props) => {
const columnDefs: ColDef[] = useMemo(() => {
return [
{
colId: 'market',
headerName: t('Market'),
field: 'market.tradableInstrument.instrument.name',
cellClass: '!flex h-full items-center !md:pl-4',
minWidth: 150,
},
{
colId: 'size',
headerName: t('Size'),
headerClass: 'uppercase',
field: 'size',
width: 100,
cellClass: ({ data }: { data: TradeWithMarket }) => {
return classNames('!flex h-full items-center justify-center', {
[positiveClassNames]: data?.buyer.id === partyId,
[negativeClassNames]: data?.seller.id,
});
},
valueFormatter: ({ value, data }: ValueFormatterParams) => {
if (value && data?.market) {
let prefix;
if (data.buyer.id === partyId) {
prefix = '+';
} else if (data.seller.id) {
prefix = '-';
}
const size = addDecimalsFormatNumber(
value,
data.market.positionDecimalPlaces
);
return `${prefix}${size}`;
}
return '-';
},
},
{
colId: 'value',
headerName: t('Value'),
headerClass: 'uppercase text-center',
cellClass: '!flex h-full items-center',
field: 'price',
valueFormatter: ({ value, data }: ValueFormatterParams) => {
if (value && data?.market) {
const asset =
data.market.tradableInstrument.instrument.product.settlementAsset
.symbol;
const valueFormatted = addDecimalsFormatNumber(
value,
data.market.decimalPlaces
);
return `${valueFormatted} ${asset}`;
}
return '-';
},
type: 'rightAligned',
},
{
colId: 'filledvalue',
headerName: t('Filled value'),
headerClass: 'uppercase text-center',
cellClass: '!flex h-full items-center',
field: 'price',
valueFormatter: ({ value, data }: ValueFormatterParams) => {
if (value && data?.market) {
const asset =
data.market.tradableInstrument.instrument.product.settlementAsset
.symbol;
const size = new BigNumber(
addDecimal(data.size, data.market.positionDecimalPlaces)
);
const price = new BigNumber(
addDecimal(value, data.market.decimalPlaces)
);
const total = size.times(price).toString();
const valueFormatted = formatNumber(
total,
data?.market.decimalPlaces
);
return `${valueFormatted} ${asset}`;
}
return '-';
},
type: 'rightAligned',
},
{
colId: 'role',
headerName: t('Role'),
field: 'aggressor',
width: 100,
valueFormatter: ({ value, data }: ValueFormatterParams) => {
if (value && data) {
const taker = t('Taker');
const maker = t('Maker');
if (data?.buyer.id === partyId) {
if (value === Side.SIDE_BUY) {
return taker;
} else {
return maker;
}
} else if (data?.seller.id === partyId) {
if (value === Side.SIDE_SELL) {
return taker;
} else {
return maker;
}
}
}
return '-';
},
},
{
colId: 'fee',
headerName: t('Fee'),
headerClass: 'uppercase text-center',
cellClass: '!flex h-full items-center',
field: 'market.tradableInstrument.instrument.product',
valueFormatter: ({ value, data }: ValueFormatterParams) => {
if (value && data) {
const asset = value.settlementAsset;
let feesObj;
if (data.buyer.id === partyId) {
feesObj = data.buyerFee;
} else if (data?.seller.id === partyId) {
feesObj = data?.sellerFee;
} else {
return '-';
}
const fee = new BigNumber(feesObj.makerFee)
.plus(feesObj.infrastructureFee)
.plus(feesObj.liquidityFee);
const totalFees = addDecimalsFormatNumber(
fee.toString(),
asset.decimals
);
return `${totalFees} ${asset.symbol}`;
}
return '-';
},
type: 'rightAligned',
},
{
colId: 'date',
headerName: t('Date'),
field: 'createdAt',
valueFormatter: ({ value }: ValueFormatterParams) => {
return value ? getDateTimeFormat().format(new Date(value)) : '-';
},
},
];
}, [partyId]);
const defaultColDef = useMemo(() => {
return {
sortable: true,
unSortIcon: true,
headerClass: 'uppercase',
cellClass: '!flex h-full items-center',
};
}, []);
return { columnDefs, defaultColDef };
};
export default useColumnDefinitions;
@@ -1 +1,6 @@
export * from './portfolio'; export * from './portfolio';
export * from './accounts';
export * from './fills';
export * from './orders';
export * from './positions';
export * as constants from './constants';
@@ -0,0 +1 @@
export { default as OrdersManager } from './orders';
@@ -0,0 +1,101 @@
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,
useOrderListData,
useOrderEdit,
OrderFeedback,
getCancelDialogTitle,
getCancelDialogIntent,
getEditDialogTitle,
OrderEditDialog,
} 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';
const OrdersManager = () => {
const { partyId } = useOutletContext<{ partyId: string }>();
const [editOrder, setEditOrder] = useState<OrderWithMarket | null>(null);
const orderCancel = useOrderCancel();
const orderEdit = useOrderEdit(editOrder);
const { columnDefs, defaultColDef } = useColumnDefinitions({
setEditOrder,
orderCancel,
});
const gridRef = useRef<AgGridReact | null>(null);
const scrolledToTop = useRef(true);
const { data, error, loading, addNewRows, getRows } = useOrderListData({
partyId,
gridRef,
scrolledToTop,
});
const onBodyScrollEnd = (event: BodyScrollEndEvent) => {
if (event.top === 0) {
addNewRows();
}
};
const onBodyScroll = (event: BodyScrollEvent) => {
scrolledToTop.current = event.top <= 0;
};
return (
<AsyncRenderer
loading={loading}
error={error}
data={data?.length ? data : null}
noDataMessage={NO_DATA_MESSAGE}
>
<ConsoleLiteGrid<OrderWithMarket>
ref={gridRef}
rowModelType={data?.length ? 'infinite' : 'clientSide'}
rowData={data?.length ? undefined : []}
datasource={{ getRows }}
onBodyScrollEnd={onBodyScrollEnd}
onBodyScroll={onBodyScroll}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
/>
<orderCancel.Dialog
title={getCancelDialogTitle(orderCancel.cancelledOrder?.status)}
intent={getCancelDialogIntent(orderCancel.cancelledOrder?.status)}
>
<OrderFeedback
transaction={orderCancel.transaction}
order={orderCancel.cancelledOrder}
/>
</orderCancel.Dialog>
<orderEdit.Dialog
title={getEditDialogTitle(orderEdit.updatedOrder?.status)}
>
<OrderFeedback
transaction={orderEdit.transaction}
order={orderEdit.updatedOrder}
/>
</orderEdit.Dialog>
{editOrder && (
<OrderEditDialog
isOpen={Boolean(editOrder)}
onChange={(isOpen) => {
if (!isOpen) setEditOrder(null);
}}
order={editOrder}
onSubmit={(fields) => {
setEditOrder(null);
orderEdit.edit({ price: fields.entryPrice });
}}
/>
)}
</AsyncRenderer>
);
};
export default OrdersManager;
@@ -0,0 +1,287 @@
import { useMemo } from 'react';
import type {
ColDef,
ValueFormatterParams,
ICellRendererParams,
} from 'ag-grid-community';
import {
addDecimal,
getDateTimeFormat,
negativeClassNames,
positiveClassNames,
t,
} from '@vegaprotocol/react-helpers';
import type {
Orders_party_ordersConnection_edges_node,
OrderWithMarket,
CancelOrderArgs,
} from '@vegaprotocol/orders';
import { isOrderActive } from '@vegaprotocol/orders';
import {
OrderRejectionReasonMapping,
OrderStatus,
OrderType,
OrderStatusMapping,
OrderTypeMapping,
Side,
OrderTimeInForce,
OrderTimeInForceMapping,
} from '@vegaprotocol/types';
import BigNumber from 'bignumber.js';
import { Button } from '@vegaprotocol/ui-toolkit';
type StatusKey = keyof typeof OrderStatusMapping;
type RejectReasonKey = keyof typeof OrderRejectionReasonMapping;
type OrderTimeKey = keyof typeof OrderTimeInForceMapping;
interface Props {
setEditOrder: (order: OrderWithMarket) => void;
orderCancel: {
cancel: (args: CancelOrderArgs) => void;
[key: string]: unknown;
};
}
const useColumnDefinitions = ({ setEditOrder, orderCancel }: Props) => {
const columnDefs: ColDef[] = useMemo(() => {
return [
{
colId: 'market',
headerName: t('Market'),
field: 'market.tradableInstrument.instrument.code',
headerClass: 'uppercase justify-start',
cellClass: '!flex h-full items-center !md:pl-4',
},
{
colId: 'size',
headerName: t('Size'),
field: 'size',
headerClass: 'uppercase',
cellClass: 'font-mono !flex h-full items-center',
width: 80,
cellClassRules: {
[positiveClassNames]: ({
data,
}: {
data: Orders_party_ordersConnection_edges_node;
}) => data?.side === Side.SIDE_BUY,
[negativeClassNames]: ({
data,
}: {
data: Orders_party_ordersConnection_edges_node;
}) => data?.side === Side.SIDE_SELL,
},
valueFormatter: ({ value, data }: ValueFormatterParams) => {
if (value && data && data.market) {
const prefix = data
? data.side === Side.SIDE_BUY
? '+'
: '-'
: '';
return (
prefix + addDecimal(value, data.market.positionDecimalPlaces)
);
}
return '-';
},
},
{
colId: 'type',
field: 'type',
width: 80,
valueFormatter: ({
value,
}: ValueFormatterParams & {
value?: Orders_party_ordersConnection_edges_node['type'];
}) => OrderTypeMapping[value as OrderType],
},
{
colId: 'status',
field: 'status',
cellClass: 'text-center font-mono !flex h-full items-center',
valueFormatter: ({
value,
data,
}: ValueFormatterParams & {
value?: StatusKey;
}) => {
if (value && data && data.market) {
if (value === OrderStatus.STATUS_REJECTED) {
return `${OrderStatusMapping[value as StatusKey]}: ${
data.rejectionReason &&
OrderRejectionReasonMapping[
data.rejectionReason as RejectReasonKey
]
}`;
}
return OrderStatusMapping[value as StatusKey] as string;
}
return '-';
},
},
{
colId: 'filled',
headerName: t('Filled'),
headerClass: 'uppercase',
field: 'remaining',
cellClass: 'font-mono text-center !flex h-full items-center',
width: 80,
valueFormatter: ({
data,
value,
}: ValueFormatterParams & {
value?: Orders_party_ordersConnection_edges_node['remaining'];
}) => {
if (value && data && data.market) {
const dps = data.market.positionDecimalPlaces;
const size = new BigNumber(data.size);
const remaining = new BigNumber(value);
const fills = size.minus(remaining);
return `${addDecimal(fills.toString(), dps)}/${addDecimal(
size.toString(),
dps
)}`;
}
return '-';
},
},
{
colId: 'price',
field: 'price',
type: 'rightAligned',
width: 125,
headerClass: 'uppercase text-right',
cellClass: 'font-mono text-right !flex h-full items-center',
valueFormatter: ({
value,
data,
}: ValueFormatterParams & {
value?: Orders_party_ordersConnection_edges_node['price'];
}) => {
if (
value === undefined ||
!data ||
!data.market ||
data.type === OrderType.TYPE_MARKET
) {
return '-';
}
return addDecimal(value, data.market.decimalPlaces);
},
},
{
colId: 'timeInForce',
field: 'timeInForce',
minWidth: 120,
valueFormatter: ({
value,
data,
}: ValueFormatterParams & {
value?: OrderTimeKey;
}) => {
if (value && data?.market) {
if (
value === OrderTimeInForce.TIME_IN_FORCE_GTT &&
data.expiresAt
) {
const expiry = getDateTimeFormat().format(
new Date(data.expiresAt)
);
return `${
OrderTimeInForceMapping[value as OrderTimeKey]
}: ${expiry}`;
}
return OrderTimeInForceMapping[value as OrderTimeKey];
}
return '-';
},
},
{
colId: 'createdat',
field: 'createdAt',
valueFormatter: ({
value,
}: ValueFormatterParams & {
value?: Orders_party_ordersConnection_edges_node['createdAt'];
}) => {
return value ? getDateTimeFormat().format(new Date(value)) : value;
},
},
{
colId: 'updated',
field: 'updatedAt',
cellClass: '!flex h-full items-center justify-center',
valueFormatter: ({
value,
}: ValueFormatterParams & {
value?: Orders_party_ordersConnection_edges_node['updatedAt'];
}) => {
return value ? getDateTimeFormat().format(new Date(value)) : '-';
},
},
{
colId: 'edit',
field: 'edit',
width: 75,
cellRenderer: ({ data }: ICellRendererParams) => {
if (!data) return null;
if (isOrderActive(data.status)) {
return (
<Button
data-testid="edit"
onClick={() => {
setEditOrder(data);
}}
size="xs"
>
{t('Edit')}
</Button>
);
}
return null;
},
},
{
colId: 'cancel',
field: 'cancel',
minWidth: 130,
cellRenderer: ({ data }: ICellRendererParams) => {
if (!data) return null;
if (isOrderActive(data.status)) {
return (
<Button
size="xs"
data-testid="cancel"
onClick={() => {
if (data.market) {
orderCancel.cancel({
orderId: data.id,
marketId: data.market.id,
});
}
}}
>
Cancel
</Button>
);
}
return null;
},
},
];
}, [orderCancel, setEditOrder]);
const defaultColDef = useMemo(() => {
return {
sortable: true,
unSortIcon: true,
headerClass: 'uppercase',
cellClass: '!flex h-full items-center',
};
}, []);
return { columnDefs, defaultColDef };
};
export default useColumnDefinitions;
@@ -1,16 +1,15 @@
import * as React from 'react'; import React from 'react';
import { AccountsContainer } from '@vegaprotocol/accounts';
import { t } from '@vegaprotocol/react-helpers';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import { Tabs, Tab } from '@vegaprotocol/ui-toolkit';
import { OrderListContainer } from '@vegaprotocol/orders';
import { PositionsContainer } from '@vegaprotocol/positions';
import { FillsContainer } from '@vegaprotocol/fills';
import ConnectWallet from '../wallet-connector'; import ConnectWallet from '../wallet-connector';
import { DepositContainer } from '../deposits'; import { useOutlet, useLocation } from 'react-router-dom';
import { HorizontalMenu } from '../horizontal-menu';
import * as constants from './constants';
export const Portfolio = () => { export const Portfolio = () => {
const { keypair } = useVegaWallet(); const { keypair } = useVegaWallet();
const { pathname } = useLocation();
const module = pathname.split('/portfolio/')?.[1] ?? '';
const outlet = useOutlet({ partyId: keypair?.pub || '' });
if (!keypair) { if (!keypair) {
return ( return (
<section className="xl:w-1/2"> <section className="xl:w-1/2">
@@ -18,23 +17,11 @@ export const Portfolio = () => {
</section> </section>
); );
} }
return ( return (
<Tabs> <div className="h-full p-4 md:p-6 grid grid-rows-[min-content_1fr]">
<Tab id="assets" name={t('Assets')}> <HorizontalMenu active={module} items={constants.PORTFOLIO_ITEMS} />
<AccountsContainer /> {outlet}
</Tab> </div>
<Tab id="positions" name={t('Positions')}>
<PositionsContainer />
</Tab>
<Tab id="orders" name={t('Orders')}>
<OrderListContainer />
</Tab>
<Tab id="fills" name={t('Fills')}>
<FillsContainer />
</Tab>
<Tab id="deposits" name={t('Deposits')}>
<DepositContainer />
</Tab>
</Tabs>
); );
}; };
@@ -0,0 +1 @@
export { default as PositionsManager } from './positions';
@@ -0,0 +1,58 @@
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { useRef } from 'react';
import type { AgGridReact } from 'ag-grid-react';
import type { Position } from '@vegaprotocol/positions';
import { PriceFlashCell, t } from '@vegaprotocol/react-helpers';
import { AssetBalance } from '@vegaprotocol/accounts';
import { usePositionsData } from '@vegaprotocol/positions';
import { ConsoleLiteGrid } from '../../console-lite-grid';
import useColumnDefinitions from './use-column-definitions';
interface Props {
partyId: string;
assetSymbol: string;
}
const getRowId = ({ data }: { data: Position }) => data.marketId;
const PositionsAsset = ({ partyId, assetSymbol }: Props) => {
const gridRef = useRef<AgGridReact | null>(null);
const { data, error, loading, getRows } = usePositionsData(
partyId,
gridRef,
assetSymbol
);
const { columnDefs, defaultColDef } = useColumnDefinitions();
return (
<AsyncRenderer loading={loading} error={error} data={data}>
<div
data-testid={`positions-asset-${assetSymbol}`}
className="flex justify-between items-center px-4 pt-3 pb-1"
>
<h4>
{assetSymbol} {t('markets')}
</h4>
<div className="text-sm text-neutral-500 dark:text-neutral-300">
{assetSymbol} {t('balance')}:
<span data-testid="balance" className="pl-1 font-mono">
<AssetBalance partyId={partyId} assetSymbol={assetSymbol} />
</span>
</div>
</div>
<ConsoleLiteGrid<Position & { id: undefined }>
ref={gridRef}
domLayout="autoHeight"
classNamesParam="h-auto"
columnDefs={columnDefs}
defaultColDef={defaultColDef}
getRowId={getRowId}
rowModelType={data?.length ? 'infinite' : 'clientSide'}
rowData={data?.length ? undefined : []}
datasource={{ getRows }}
components={{ PriceFlashCell }}
/>
</AsyncRenderer>
);
};
export default PositionsAsset;
@@ -0,0 +1,28 @@
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';
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 > 0 && (
<div className="w-full, h-max">
{assetSymbols?.map((assetSymbol) => (
<PositionsAsset
key={assetSymbol}
partyId={partyId}
assetSymbol={assetSymbol}
/>
))}
</div>
)}
{assetSymbols?.length === 0 && <Splash>{t('No data to display')}</Splash>}
</AsyncRenderer>
);
};
export default Positions;
@@ -0,0 +1,291 @@
import { useMemo } from 'react';
import {
addDecimalsFormatNumber,
formatNumber,
getDateTimeFormat,
PriceFlashCell,
signedNumberCssClassRules,
t,
} from '@vegaprotocol/react-helpers';
import type {
PositionsTableValueFormatterParams,
Position,
} from '@vegaprotocol/positions';
import { AmountCell } from '@vegaprotocol/positions';
import type {
CellRendererSelectorResult,
ICellRendererParams,
ValueGetterParams,
GroupCellRendererParams,
ColDef,
} from 'ag-grid-community';
import { MarketTradingMode } from '@vegaprotocol/types';
import { Intent, ProgressBarCell } from '@vegaprotocol/ui-toolkit';
const EmptyCell = () => '';
const useColumnDefinitions = () => {
const columnDefs: ColDef[] = useMemo(() => {
return [
{
colId: 'market',
headerName: t('Market'),
headerClass: 'uppercase justify-start',
cellClass: '!flex h-full items-center !md:pl-4',
field: 'marketName',
cellRenderer: ({ value }: GroupCellRendererParams) => {
if (!value) {
return null;
}
const valueFormatted: [string, string?] = (() => {
// split market name into two parts, 'Part1 (Part2)' or 'Part1 - Part2'
const matches = value.match(/^(.*)(\((.*)\)| - (.*))\s*$/);
if (matches && matches[1] && matches[3]) {
return [matches[1].trim(), matches[3].trim()];
}
return [value];
})();
if (valueFormatted && valueFormatted[1]) {
return (
<div className="leading-tight">
<div>{valueFormatted[0]}</div>
<div>{valueFormatted[1]}</div>
</div>
);
}
return valueFormatted ? valueFormatted[0] : null;
},
},
{
colId: 'amount',
headerName: t('Amount'),
headerClass: 'uppercase',
cellClass: '!flex h-full items-center',
field: 'openVolume',
valueGetter: ({ node, data }: ValueGetterParams) => {
return node?.rowPinned ? data?.notional : data?.openVolume;
},
type: 'rightAligned',
cellRendererSelector: (
params: ICellRendererParams
): CellRendererSelectorResult => {
return {
component: params.node.rowPinned ? PriceFlashCell : AmountCell,
};
},
valueFormatter: ({
value,
data,
node,
}: PositionsTableValueFormatterParams & {
value: Position['openVolume'];
}) => {
let ret;
if (value && data) {
ret = node?.rowPinned
? addDecimalsFormatNumber(value, data.decimals)
: data;
}
// FIXME this column needs refactoring
return ret as unknown as string;
},
},
{
colId: 'markprice',
headerName: t('Mark price'),
headerClass: 'uppercase',
cellClass: '!flex h-full items-center justify-center',
field: 'markPrice',
cellRendererSelector: (
params: ICellRendererParams
): CellRendererSelectorResult => {
return {
component: params.node.rowPinned ? EmptyCell : PriceFlashCell,
};
},
valueFormatter: ({
value,
data,
node,
}: PositionsTableValueFormatterParams & {
value: Position['markPrice'];
}) => {
if (
data &&
value &&
node?.rowPinned &&
data.marketTradingMode ===
MarketTradingMode.TRADING_MODE_OPENING_AUCTION
) {
return addDecimalsFormatNumber(
value.toString(),
data.marketDecimalPlaces
);
}
return '-';
},
},
{
colId: 'entryprice',
headerName: t('Entry price'),
headerClass: 'uppercase',
cellClass: '!flex h-full items-center',
field: 'averageEntryPrice',
headerComponentParams: {
template:
'<div class="ag-cell-label-container" role="presentation">' +
` <span>${t('Liquidation price (est)')}</span>` +
' <span ref="eText" class="ag-header-cell-text"></span>' +
'</div>',
},
cellRenderer: ({ node, data }: GroupCellRendererParams) => {
const valueFormatted =
data && !node?.rowPinned
? (() => {
const min = BigInt(data.averageEntryPrice);
const max = BigInt(data.liquidationPrice);
const mid = BigInt(data.markPrice);
const range = max - min;
return {
low: addDecimalsFormatNumber(
min.toString(),
data.marketDecimalPlaces
),
high: addDecimalsFormatNumber(
max.toString(),
data.marketDecimalPlaces
),
value: range
? Number(((mid - min) * BigInt(100)) / range)
: 0,
intent: data.lowMarginLevel ? Intent.Warning : undefined,
};
})()
: undefined;
return node.rowPinned ? (
''
) : (
<ProgressBarCell valueFormatted={valueFormatted} />
);
},
},
{
colId: 'leverage',
headerName: t('Leverage'),
headerClass: 'uppercase',
cellClass: '!flex h-full items-center justify-center',
field: 'currentLeverage',
type: 'rightAligned',
cellRendererSelector: (
params: ICellRendererParams
): CellRendererSelectorResult => {
return {
component: params.node.rowPinned ? EmptyCell : PriceFlashCell,
};
},
valueFormatter: ({
value,
node,
}: PositionsTableValueFormatterParams & {
value: Position['currentLeverage'];
}) => (value === undefined ? '' : formatNumber(value.toString(), 1)),
},
{
colId: 'marginallocated',
headerName: t('Margin allocated'),
headerClass: 'uppercase',
cellClass: '!flex h-full flex-col justify-center',
field: 'capitalUtilisation',
type: 'rightAligned',
cellRenderer: ({ value, node, data }: GroupCellRendererParams) => {
const valueFormatted =
data && value
? (() => {
return {
low: `${formatNumber(value, 2)}%`,
high: addDecimalsFormatNumber(
data.totalBalance,
data.decimals
),
value: Number(value),
};
})()
: undefined;
return node.rowPinned ? (
''
) : (
<ProgressBarCell valueFormatted={valueFormatted} />
);
},
},
{
colId: 'realisedpnl',
headerName: t('Realised PNL'),
headerClass: 'uppercase',
cellClass: '!flex h-full items-center',
field: 'realisedPNL',
type: 'rightAligned',
cellClassRules: signedNumberCssClassRules,
valueFormatter: ({
value,
data,
}: PositionsTableValueFormatterParams & {
value: Position['realisedPNL'];
}) =>
value === undefined
? ''
: addDecimalsFormatNumber(value.toString(), data.decimals),
cellRenderer: 'PriceFlashCell',
headerTooltip: t('P&L excludes any fees paid.'),
},
{
colId: 'unrealisedpnl',
headerName: t('Unrealised PNL'),
headerClass: 'uppercase',
cellClass: '!flex h-full items-center',
field: 'unrealisedPNL',
type: 'rightAligned',
cellClassRules: signedNumberCssClassRules,
valueFormatter: ({
value,
data,
}: PositionsTableValueFormatterParams & {
value: Position['unrealisedPNL'];
}) =>
value === undefined
? ''
: addDecimalsFormatNumber(value.toString(), data.decimals),
cellRenderer: 'PriceFlashCell',
},
{
colId: 'updated',
headerName: t('Updated'),
headerClass: 'uppercase',
cellClass: '!flex h-full items-center',
field: 'updatedAt',
type: 'rightAligned',
valueFormatter: ({
value,
}: PositionsTableValueFormatterParams & {
value: Position['updatedAt'];
}) => {
if (!value) {
return '';
}
return getDateTimeFormat().format(new Date(value));
},
},
];
}, []);
const defaultColDef = useMemo(() => {
return {
sortable: true,
unSortIcon: true,
headerClass: 'uppercase',
cellClass: '!flex h-full items-center',
};
}, []);
return { columnDefs, defaultColDef };
};
export default useColumnDefinitions;
@@ -1,5 +0,0 @@
subscription CandleLive($marketId: ID!) {
candles(marketId: $marketId, interval: INTERVAL_I1H) {
close
}
}
@@ -1,44 +0,0 @@
fragment SimpleMarketDataFields on MarketData {
market {
id
state
}
}
query SimpleMarkets($CandleSince: String!) {
markets {
id
name
state
data {
...SimpleMarketDataFields
}
tradableInstrument {
instrument {
code
metadata {
tags
}
product {
__typename
... on Future {
quoteName
settlementAsset {
symbol
}
}
}
}
}
candles(interval: INTERVAL_I1H, since: $CandleSince) {
open
close
}
}
}
subscription SimpleMarketDataSub {
marketData {
...SimpleMarketDataFields
}
}
@@ -1,30 +0,0 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
import { MarketState } from "@vegaprotocol/types";
// ====================================================
// GraphQL fragment: SimpleMarketDataFields
// ====================================================
export interface SimpleMarketDataFields_market {
__typename: "Market";
/**
* Market ID
*/
id: string;
/**
* Current state of the market
*/
state: MarketState;
}
export interface SimpleMarketDataFields {
__typename: "MarketData";
/**
* market ID of the associated mark price
*/
market: SimpleMarketDataFields_market;
}
@@ -1,37 +0,0 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
import { MarketState } from "@vegaprotocol/types";
// ====================================================
// GraphQL subscription operation: SimpleMarketDataSub
// ====================================================
export interface SimpleMarketDataSub_marketData_market {
__typename: "Market";
/**
* Market ID
*/
id: string;
/**
* Current state of the market
*/
state: MarketState;
}
export interface SimpleMarketDataSub_marketData {
__typename: "MarketData";
/**
* market ID of the associated mark price
*/
market: SimpleMarketDataSub_marketData_market;
}
export interface SimpleMarketDataSub {
/**
* Subscribe to the mark price changes
*/
marketData: SimpleMarketDataSub_marketData;
}
@@ -1,109 +0,0 @@
/* tslint:disable */
/* eslint-disable */
// @generated
// This file was automatically generated and should not be edited.
import { MarketState } from "@vegaprotocol/types";
// ====================================================
// GraphQL query operation: SimpleMarkets
// ====================================================
export interface SimpleMarkets_markets_tradableInstrument_instrument_metadata {
__typename: "InstrumentMetadata";
/**
* An arbitrary list of tags to associated to associate to the Instrument (string list)
*/
tags: string[] | null;
}
export interface SimpleMarkets_markets_tradableInstrument_instrument_product_settlementAsset {
__typename: "Asset";
/**
* The symbol of the asset (e.g: GBP)
*/
symbol: string;
}
export interface SimpleMarkets_markets_tradableInstrument_instrument_product {
__typename: "Future";
/**
* String representing the quote (e.g. BTCUSD -> USD is quote)
*/
quoteName: string;
/**
* The name of the asset (string)
*/
settlementAsset: SimpleMarkets_markets_tradableInstrument_instrument_product_settlementAsset;
}
export interface SimpleMarkets_markets_tradableInstrument_instrument {
__typename: "Instrument";
/**
* A short non necessarily unique code used to easily describe the instrument (e.g: FX:BTCUSD/DEC18) (string)
*/
code: string;
/**
* Full and fairly descriptive name for the instrument
*/
name: string;
/**
* Metadata for this instrument
*/
metadata: SimpleMarkets_markets_tradableInstrument_instrument_metadata;
/**
* A reference to or instance of a fully specified product, including all required product parameters for that product (Product union)
*/
product: SimpleMarkets_markets_tradableInstrument_instrument_product;
}
export interface SimpleMarkets_markets_tradableInstrument {
__typename: "TradableInstrument";
/**
* An instance of, or reference to, a fully specified instrument.
*/
instrument: SimpleMarkets_markets_tradableInstrument_instrument;
}
export interface SimpleMarkets_markets_candles {
__typename: "Candle";
/**
* Open price (uint64)
*/
open: string;
/**
* Close price (uint64)
*/
close: string;
}
export interface SimpleMarkets_markets {
__typename: "Market";
/**
* Market ID
*/
id: string;
/**
* Current state of the market
*/
state: MarketState;
/**
* An instance of, or reference to, a tradable instrument.
*/
tradableInstrument: SimpleMarkets_markets_tradableInstrument;
/**
* Candles on a market, for the 'last' n candles, at 'interval' seconds as specified by parameters
*/
candles: (SimpleMarkets_markets_candles | null)[] | null;
}
export interface SimpleMarkets {
/**
* One or more instruments that are trading on the VEGA network
*/
markets: SimpleMarkets_markets[] | null;
}
export interface SimpleMarketsVariables {
CandleSince: string;
}
@@ -1,117 +0,0 @@
import { Schema as Types } from '@vegaprotocol/types';
import { gql } from '@apollo/client';
import * as Apollo from '@apollo/client';
const defaultOptions = {} as const;
export type SimpleMarketDataFieldsFragment = { __typename?: 'MarketData', market: { __typename?: 'Market', id: string, state: Types.MarketState } };
export type SimpleMarketsQueryVariables = Types.Exact<{
CandleSince: Types.Scalars['String'];
}>;
export type SimpleMarketsQuery = { __typename?: 'Query', markets?: Array<{ __typename?: 'Market', id: string, name: string, state: Types.MarketState, data?: { __typename?: 'MarketData', market: { __typename?: 'Market', id: string, state: Types.MarketState } } | null, tradableInstrument: { __typename?: 'TradableInstrument', instrument: { __typename?: 'Instrument', code: string, metadata: { __typename?: 'InstrumentMetadata', tags?: Array<string> | null }, product: { __typename: 'Future', quoteName: string, settlementAsset: { __typename?: 'Asset', symbol: string } } } }, candles?: Array<{ __typename?: 'Candle', open: string, close: string } | null> | null }> | null };
export type SimpleMarketDataSubSubscriptionVariables = Types.Exact<{ [key: string]: never; }>;
export type SimpleMarketDataSubSubscription = { __typename?: 'Subscription', marketData: { __typename?: 'MarketData', market: { __typename?: 'Market', id: string, state: Types.MarketState } } };
export const SimpleMarketDataFieldsFragmentDoc = gql`
fragment SimpleMarketDataFields on MarketData {
market {
id
state
}
}
`;
export const SimpleMarketsDocument = gql`
query SimpleMarkets($CandleSince: String!) {
markets {
id
name
state
data {
...SimpleMarketDataFields
}
tradableInstrument {
instrument {
code
metadata {
tags
}
product {
__typename
... on Future {
quoteName
settlementAsset {
symbol
}
}
}
}
}
candles(interval: INTERVAL_I1H, since: $CandleSince) {
open
close
}
}
}
${SimpleMarketDataFieldsFragmentDoc}`;
/**
* __useSimpleMarketsQuery__
*
* To run a query within a React component, call `useSimpleMarketsQuery` and pass it any options that fit your needs.
* When your component renders, `useSimpleMarketsQuery` 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 } = useSimpleMarketsQuery({
* variables: {
* CandleSince: // value for 'CandleSince'
* },
* });
*/
export function useSimpleMarketsQuery(baseOptions: Apollo.QueryHookOptions<SimpleMarketsQuery, SimpleMarketsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<SimpleMarketsQuery, SimpleMarketsQueryVariables>(SimpleMarketsDocument, options);
}
export function useSimpleMarketsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<SimpleMarketsQuery, SimpleMarketsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<SimpleMarketsQuery, SimpleMarketsQueryVariables>(SimpleMarketsDocument, options);
}
export type SimpleMarketsQueryHookResult = ReturnType<typeof useSimpleMarketsQuery>;
export type SimpleMarketsLazyQueryHookResult = ReturnType<typeof useSimpleMarketsLazyQuery>;
export type SimpleMarketsQueryResult = Apollo.QueryResult<SimpleMarketsQuery, SimpleMarketsQueryVariables>;
export const SimpleMarketDataSubDocument = gql`
subscription SimpleMarketDataSub {
marketData {
...SimpleMarketDataFields
}
}
${SimpleMarketDataFieldsFragmentDoc}`;
/**
* __useSimpleMarketDataSubSubscription__
*
* To run a query within a React component, call `useSimpleMarketDataSubSubscription` and pass it any options that fit your needs.
* When your component renders, `useSimpleMarketDataSubSubscription` 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 subscription, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useSimpleMarketDataSubSubscription({
* variables: {
* },
* });
*/
export function useSimpleMarketDataSubSubscription(baseOptions?: Apollo.SubscriptionHookOptions<SimpleMarketDataSubSubscription, SimpleMarketDataSubSubscriptionVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useSubscription<SimpleMarketDataSubSubscription, SimpleMarketDataSubSubscriptionVariables>(SimpleMarketDataSubDocument, options);
}
export type SimpleMarketDataSubSubscriptionHookResult = ReturnType<typeof useSimpleMarketDataSubSubscription>;
export type SimpleMarketDataSubSubscriptionResult = Apollo.SubscriptionResult<SimpleMarketDataSubSubscription>;
@@ -1,9 +1,9 @@
import { t } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import { themelite as theme } from '@vegaprotocol/tailwindcss-config'; import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
import { MarketState } from '@vegaprotocol/types'; import { MarketState } from '@vegaprotocol/types';
import { IS_MARKET_TRADABLE } from '../../constants';
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
import colors from 'tailwindcss/colors'; import colors from 'tailwindcss/colors';
import type { Market } from '@vegaprotocol/market-list';
import { IS_MARKET_TRADABLE } from '../../constants';
export const STATES_FILTER = [ export const STATES_FILTER = [
{ value: 'all', text: t('All') }, { value: 'all', text: t('All') },
@@ -192,8 +192,17 @@ export const agGridDarkVariables = `
`; `;
export const ROW_CLASS_RULES = { export const ROW_CLASS_RULES = {
'cursor-pointer': ({ data }: { data: SimpleMarkets_markets }) => 'cursor-pointer': ({ data }: { data: Market }) =>
IS_MARKET_TRADABLE(data || {}), IS_MARKET_TRADABLE(data || {}),
}; };
export const LARGE_SCREENS = ['xl', 'xxl']; export const LARGE_SCREENS = ['xl', 'xxl'];
export const ALL_PRODUCTS_ITEM = {
name: t('All Markets'),
id: 'allmarkets',
cssClass: 'text-pink',
color: theme.colors.pink,
};
export const AG_GRID_CONTAINER_STYLES = { width: '100%', height: '100%' };
@@ -1,94 +0,0 @@
import produce from 'immer';
import { gql } from '@apollo/client';
import { makeDataProvider } from '@vegaprotocol/react-helpers';
import type {
SimpleMarkets,
SimpleMarkets_markets,
} from './__generated__/SimpleMarkets';
import type {
SimpleMarketDataSub,
SimpleMarketDataSub_marketData,
} from './__generated__/SimpleMarketDataSub';
export const MARKETS_QUERY = gql`
query SimpleMarkets($CandleSince: String!) {
markets {
id
state
tradableInstrument {
instrument {
code
name
metadata {
tags
}
product {
__typename
... on Future {
quoteName
settlementAsset {
symbol
}
}
}
}
}
candles(interval: INTERVAL_I1H, since: $CandleSince) {
open
close
}
}
}
`;
const MARKET_DATA_SUB = gql`
subscription SimpleMarketDataSub {
marketData {
market {
id
state
}
}
}
`;
export const CANDLE_SUB = gql`
subscription CandleLive($marketId: ID!) {
candles(marketId: $marketId, interval: INTERVAL_I1H) {
close
}
}
`;
const update = (
data: SimpleMarkets_markets[],
delta: SimpleMarketDataSub_marketData
) => {
return produce(data, (draft) => {
const index = draft.findIndex((m) => m.id === delta.market.id);
if (index !== -1) {
draft[index].state = delta.market.state;
}
// @TODO - else push new market to draft
});
};
const getData = (responseData: SimpleMarkets) => responseData.markets;
const getDelta = (
subscriptionData: SimpleMarketDataSub
): SimpleMarketDataSub_marketData => subscriptionData.marketData;
export const dataProvider = makeDataProvider<
SimpleMarkets,
SimpleMarkets_markets[],
SimpleMarketDataSub,
SimpleMarketDataSub_marketData
>({
query: MARKETS_QUERY,
subscriptionQuery: MARKET_DATA_SUB,
update,
getData,
getDelta,
});
export default dataProvider;
@@ -4,21 +4,14 @@ import {
render, render,
screen, screen,
waitFor, waitFor,
cleanup,
getAllByRole, getAllByRole,
fireEvent, fireEvent,
} from '@testing-library/react'; } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing';
import type { MockedResponse } from '@apollo/client/testing';
import { BrowserRouter } from 'react-router-dom'; import { BrowserRouter } from 'react-router-dom';
import { MarketState } from '@vegaprotocol/types'; import { MarketState } from '@vegaprotocol/types';
import type { Market } from '@vegaprotocol/market-list';
import SimpleMarketList from './simple-market-list'; import SimpleMarketList from './simple-market-list';
import { MARKETS_QUERY } from './data-provider';
import type {
SimpleMarkets_markets,
SimpleMarkets,
} from './__generated__/SimpleMarkets';
import type { SimpleMarketDataSub_marketData } from './__generated__/SimpleMarketDataSub';
const mockedNavigate = jest.fn(); const mockedNavigate = jest.fn();
@@ -28,20 +21,11 @@ jest.mock('react-router-dom', () => ({
useParams: () => ({}), useParams: () => ({}),
})); }));
jest.mock('date-fns', () => ({ jest.mock('./simple-market-percent-change', () => jest.fn());
subDays: () => new Date('2022-06-02T11:11:21.721Z'),
}));
let updateMock: ({ let marketsMock = [
delta,
}: {
delta: SimpleMarketDataSub_marketData;
}) => boolean;
let mockData = [
{ {
id: '1', id: 'MARKET_A',
name: 'Market 1',
state: MarketState.STATE_ACTIVE, state: MarketState.STATE_ACTIVE,
tradableInstrument: { tradableInstrument: {
instrument: { instrument: {
@@ -57,8 +41,7 @@ let mockData = [
}, },
}, },
{ {
id: '2', id: 'MARKET_B',
name: 'Market 2',
state: MarketState.STATE_ACTIVE, state: MarketState.STATE_ACTIVE,
tradableInstrument: { tradableInstrument: {
instrument: { instrument: {
@@ -73,20 +56,26 @@ let mockData = [
}, },
}, },
}, },
] as unknown as SimpleMarkets_markets[]; ] as unknown as Market[];
const mockUseDataProvider = ({ update }: { update: () => boolean }) => { const LIB = '@vegaprotocol/market-list';
updateMock = update; const useMarketList = () => {
return { data: mockData, loading: false, error: false }; return {
data: {
markets: marketsMock,
marketsData: [],
marketsCandles: [],
},
loading: false,
error: false,
};
}; };
jest.mock(LIB, () => ({
jest.mock('@vegaprotocol/react-helpers', () => ({ ...jest.requireActual(LIB),
...jest.requireActual('@vegaprotocol/react-helpers'), useMarketList: jest.fn(() => useMarketList()),
useDataProvider: jest.fn((args) => mockUseDataProvider(args)),
})); }));
const mockIsTradable = jest.fn((_arg) => true); const mockIsTradable = jest.fn((_arg) => true);
jest.mock('../../constants', () => ({ jest.mock('../../constants', () => ({
...jest.requireActual('../../constants'), ...jest.requireActual('../../constants'),
IS_MARKET_TRADABLE: jest.fn((arg) => mockIsTradable(arg)), IS_MARKET_TRADABLE: jest.fn((arg) => mockIsTradable(arg)),
@@ -95,25 +84,12 @@ jest.mock('../../constants', () => ({
describe('SimpleMarketList', () => { describe('SimpleMarketList', () => {
afterEach(() => { afterEach(() => {
jest.clearAllMocks(); jest.clearAllMocks();
cleanup();
}); });
const mocks: MockedResponse<SimpleMarkets> = {
request: {
query: MARKETS_QUERY,
variables: {
CandleSince: '2022-06-02T11:11:21.721Z',
},
},
result: {
data: { markets: mockData },
},
};
it('should be properly rendered with some data', async () => { it('should be properly rendered with some data', async () => {
await act(async () => { await act(async () => {
render( render(
<MockedProvider mocks={[mocks]}> <MockedProvider mocks={[]}>
<SimpleMarketList /> <SimpleMarketList />
</MockedProvider>, </MockedProvider>,
{ wrapper: BrowserRouter } { wrapper: BrowserRouter }
@@ -124,95 +100,49 @@ describe('SimpleMarketList', () => {
expect( expect(
document.querySelector('.ag-center-cols-container') document.querySelector('.ag-center-cols-container')
).toBeInTheDocument(); ).toBeInTheDocument();
});
await waitFor(() => {
const container = document.querySelector('.ag-center-cols-container'); const container = document.querySelector('.ag-center-cols-container');
expect(getAllByRole(container as HTMLDivElement, 'row')).toHaveLength(2); expect(getAllByRole(container as HTMLDivElement, 'row')).toHaveLength(2);
}); });
}); });
it('update should return proper boolean value', async () => {
await act(async () => {
render(
<MockedProvider mocks={[mocks]}>
<SimpleMarketList />
</MockedProvider>,
{ wrapper: BrowserRouter }
);
await new Promise((resolve) => setTimeout(resolve, 0));
});
await waitFor(() => {
expect(
document.querySelector('.ag-center-cols-container')
).toBeInTheDocument();
});
await expect(
updateMock({
delta: {
__typename: 'MarketData',
market: {
__typename: 'Market',
id: '2',
state: MarketState.STATE_ACTIVE,
},
},
})
).toEqual(true);
await expect(
updateMock({
delta: {
__typename: 'MarketData',
market: {
__typename: 'Market',
id: '2',
state: MarketState.STATE_SUSPENDED,
},
},
})
).toEqual(false);
});
it('click on row should be properly handled', async () => { it('click on row should be properly handled', async () => {
await act(async () => { await act(async () => {
render( render(
<MockedProvider mocks={[mocks]}> <MockedProvider mocks={[]}>
<SimpleMarketList /> <SimpleMarketList />
</MockedProvider>, </MockedProvider>,
{ wrapper: BrowserRouter } { wrapper: BrowserRouter }
); );
await new Promise((resolve) => setTimeout(resolve, 0));
});
await waitFor(() => {
expect(
document.querySelector('.ag-center-cols-container')
).toBeInTheDocument();
}); });
mockIsTradable.mockClear(); mockIsTradable.mockClear();
const container = document.querySelector('.ag-center-cols-container'); const container = document.querySelector('.ag-center-cols-container');
const firstRow = getAllByRole(container as HTMLDivElement, 'row')[0]; const firstRow = getAllByRole(container as HTMLDivElement, 'row')[0];
expect(firstRow).toHaveAttribute('row-id', '1'); expect(firstRow).toHaveAttribute('row-id', marketsMock[0].id);
fireEvent.click(firstRow); await act(async () => {
fireEvent.click(firstRow);
});
await waitFor(() => { await waitFor(() => {
expect(mockIsTradable).toHaveBeenCalledWith({ expect(mockIsTradable).toHaveBeenCalledWith(
...mockData[0], expect.objectContaining({
percentChange: '-', id: marketsMock[0].id,
}); state: MarketState.STATE_ACTIVE,
expect(mockedNavigate).toHaveBeenCalledWith(`/trading/${mockData[0].id}`); })
);
expect(mockedNavigate).toHaveBeenCalledWith(
`/trading/${marketsMock[0].id}`
);
}); });
}); });
it('should be properly renderer as empty', async () => { it('should be properly renderer as empty', async () => {
mockData = []; marketsMock = [];
await act(async () => { await act(async () => {
render( render(
<MockedProvider mocks={[mocks]}> <MockedProvider mocks={[]}>
<SimpleMarketList /> <SimpleMarketList />
</MockedProvider>, </MockedProvider>,
{ wrapper: BrowserRouter } { wrapper: BrowserRouter }
); );
await new Promise((resolve) => setTimeout(resolve, 0));
}); });
await waitFor(() => { await waitFor(() => {
expect(screen.getByText('No data to display')).toBeInTheDocument(); expect(screen.getByText('No data to display')).toBeInTheDocument();
@@ -1,40 +1,18 @@
import React, { import React, { useCallback, useEffect, useRef } from 'react';
useCallback,
useContext,
useEffect,
useMemo,
useRef,
} from 'react';
import { useNavigate, useParams } from 'react-router-dom'; import { useNavigate, useParams } from 'react-router-dom';
import { subDays } from 'date-fns';
import type { AgGridReact } from 'ag-grid-react'; import type { AgGridReact } from 'ag-grid-react';
import { AgGridDynamic as AgGrid } from '@vegaprotocol/ui-toolkit'; import { useScreenDimensions } from '@vegaprotocol/react-helpers';
import {
useDataProvider,
useScreenDimensions,
} from '@vegaprotocol/react-helpers';
import { t } from '@vegaprotocol/react-helpers';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit'; import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { ThemeContext } from '@vegaprotocol/react-helpers';
import type { MarketState } from '@vegaprotocol/types'; import type { MarketState } from '@vegaprotocol/types';
import useMarketsFilterData from '../../hooks/use-markets-filter-data'; import useMarketsFilterData from './use-markets-filter-data';
import useColumnDefinitions from '../../hooks/use-column-definitions'; import useColumnDefinitions from './use-column-definitions';
import dataProvider from './data-provider';
import * as constants from './constants';
import SimpleMarketToolbar from './simple-market-toolbar'; import SimpleMarketToolbar from './simple-market-toolbar';
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets';
import type { SimpleMarketDataSub_marketData } from './__generated__/SimpleMarketDataSub';
import { IS_MARKET_TRADABLE } from '../../constants'; import { IS_MARKET_TRADABLE } from '../../constants';
import type { import { ConsoleLiteGrid } from '../console-lite-grid';
CellKeyDownEvent, import type { Market, MarketsListData } from '@vegaprotocol/market-list';
FullWidthCellKeyDownEvent, import { useMarketList } from '@vegaprotocol/market-list';
} from 'ag-grid-community/dist/lib/events';
import type {
GetRowIdParams,
TabToNextCellParams,
} from 'ag-grid-community/dist/lib/entities/iCallbackParams';
export type SimpleMarketsType = SimpleMarkets_markets & { export type MarketWithPercentChange = Market & {
percentChange?: number | '-'; percentChange?: number | '-';
}; };
@@ -45,33 +23,14 @@ export type RouterParams = Partial<{
}>; }>;
const SimpleMarketList = () => { const SimpleMarketList = () => {
const { isMobile, screenSize } = useScreenDimensions(); const { isMobile } = useScreenDimensions();
const navigate = useNavigate(); const navigate = useNavigate();
const params = useParams<RouterParams>(); const params = useParams<RouterParams>();
const theme = useContext(ThemeContext);
const statusesRef = useRef<Record<string, MarketState | ''>>({}); const statusesRef = useRef<Record<string, MarketState | ''>>({});
const gridRef = useRef<AgGridReact | null>(null); const gridRef = useRef<AgGridReact | null>(null);
const variables = useMemo(
() => ({
CandleSince: subDays(Date.now(), 1).toJSON(),
}),
[]
);
const update = useCallback(
({ delta }: { delta: SimpleMarketDataSub_marketData }) =>
statusesRef.current[delta.market.id] === delta.market.state,
[statusesRef]
);
const { data, error, loading } = useDataProvider({ const { data, error, loading } = useMarketList();
dataProvider, const localData = useMarketsFilterData(data as MarketsListData, params);
update,
variables,
});
const localData: Array<SimpleMarketsType> = useMarketsFilterData(
data || [],
params
);
const handleOnGridReady = useCallback(() => { const handleOnGridReady = useCallback(() => {
gridRef.current?.api?.sizeColumnsToFit(); gridRef.current?.api?.sizeColumnsToFit();
@@ -79,7 +38,7 @@ const SimpleMarketList = () => {
useEffect(() => { useEffect(() => {
const statuses: Record<string, MarketState | ''> = {}; const statuses: Record<string, MarketState | ''> = {};
data?.forEach((market) => { data?.markets?.forEach((market) => {
statuses[market.id] = market.state || ''; statuses[market.id] = market.state || '';
}); });
statusesRef.current = statuses; statusesRef.current = statuses;
@@ -92,10 +51,8 @@ const SimpleMarketList = () => {
const { columnDefs, defaultColDef } = useColumnDefinitions({ isMobile }); const { columnDefs, defaultColDef } = useColumnDefinitions({ isMobile });
const getRowId = useCallback(({ data }: GetRowIdParams) => data.id, []);
const handleRowClicked = useCallback( const handleRowClicked = useCallback(
({ data }: { data: SimpleMarketsType }) => { ({ data }: { data: Market }) => {
if (IS_MARKET_TRADABLE(data)) { if (IS_MARKET_TRADABLE(data)) {
navigate(`/trading/${data.id}`); navigate(`/trading/${data.id}`);
} }
@@ -103,64 +60,17 @@ const SimpleMarketList = () => {
[navigate] [navigate]
); );
const onTabToNextCell = useCallback((params: TabToNextCellParams) => {
const {
api,
previousCellPosition: { rowIndex },
} = params;
const rowCount = api.getDisplayedRowCount();
if (rowCount <= rowIndex + 1) {
return null;
}
return { ...params.previousCellPosition, rowIndex: rowIndex + 1 };
}, []);
const onCellKeyDown = useCallback(
(
params: (CellKeyDownEvent | FullWidthCellKeyDownEvent) & {
event: KeyboardEvent;
}
) => {
const { event: { key = '' } = {}, data } = params;
if (key === 'Enter') {
handleRowClicked({ data });
}
},
[handleRowClicked]
);
const shouldSuppressHorizontalScroll = useMemo(() => {
return !isMobile && constants.LARGE_SCREENS.includes(screenSize);
}, [isMobile, screenSize]);
return ( return (
<div className="h-full p-4 md:p-6 grid grid-rows-[min-content,1fr]"> <div className="h-full p-4 md:p-6 grid grid-rows-[min-content,1fr]">
<SimpleMarketToolbar data={data || []} /> <SimpleMarketToolbar data={data?.markets || []} />
<AsyncRenderer loading={loading} error={error} data={localData}> <AsyncRenderer loading={loading} error={error} data={localData}>
<AgGrid <ConsoleLiteGrid<MarketWithPercentChange>
className="mb-32 min-h-[300px]" classNamesParam="mb-32 min-h-[300px]"
defaultColDef={defaultColDef}
columnDefs={columnDefs} columnDefs={columnDefs}
rowData={localData} rowData={localData}
rowHeight={60} defaultColDef={defaultColDef}
customThemeParams={ handleRowClicked={handleRowClicked}
theme === 'dark' getRowId={({ data }) => data.id}
? constants.agGridDarkVariables
: constants.agGridLightVariables
}
onGridReady={handleOnGridReady}
onRowClicked={handleRowClicked}
rowClass={isMobile ? 'mobile' : ''}
rowClassRules={constants.ROW_CLASS_RULES}
ref={gridRef}
overlayNoRowsTemplate={t('No data to display')}
suppressContextMenu
getRowId={getRowId}
suppressMovableColumns
suppressRowTransform
onCellKeyDown={onCellKeyDown}
tabToNextCell={onTabToNextCell}
suppressHorizontalScroll={shouldSuppressHorizontalScroll}
/> />
</AsyncRenderer> </AsyncRenderer>
</div> </div>
@@ -2,10 +2,10 @@ import React from 'react';
import { render, screen } from '@testing-library/react'; import { render, screen } from '@testing-library/react';
import { MockedProvider } from '@apollo/react-testing'; import { MockedProvider } from '@apollo/react-testing';
import SimpleMarketPercentChange from './simple-market-percent-change'; import SimpleMarketPercentChange from './simple-market-percent-change';
import type { SimpleMarkets_markets_candles } from './__generated__/SimpleMarkets'; import type { Candle } from '@vegaprotocol/market-list';
describe('SimpleMarketPercentChange should parse proper change', () => { describe('SimpleMarketPercentChange should parse proper change', () => {
let candles: (SimpleMarkets_markets_candles | null)[] | null; let candles: (Candle | null)[] | null;
const setValue = () => undefined; const setValue = () => undefined;
it('empty array', () => { it('empty array', () => {
candles = []; candles = [];
@@ -34,11 +34,7 @@ describe('SimpleMarketPercentChange should parse proper change', () => {
expect(screen.getByText('-')).toBeInTheDocument(); expect(screen.getByText('-')).toBeInTheDocument();
}); });
it('an appreciated one', () => { it('an appreciated one', () => {
candles = [ candles = [{ open: '50' } as Candle, { close: '100' } as Candle, null];
{ open: '50' } as SimpleMarkets_markets_candles,
{ close: '100' } as SimpleMarkets_markets_candles,
null,
];
render( render(
<MockedProvider> <MockedProvider>
<SimpleMarketPercentChange <SimpleMarketPercentChange
@@ -54,11 +50,7 @@ describe('SimpleMarketPercentChange should parse proper change', () => {
); );
}); });
it('a depreciated one', () => { it('a depreciated one', () => {
candles = [ candles = [{ open: '100' } as Candle, { close: '50' } as Candle, null];
{ open: '100' } as SimpleMarkets_markets_candles,
{ close: '50' } as SimpleMarkets_markets_candles,
null,
];
render( render(
<MockedProvider> <MockedProvider>
<SimpleMarketPercentChange <SimpleMarketPercentChange
@@ -1,26 +1,20 @@
import React, { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { InView } from 'react-intersection-observer'; import { InView } from 'react-intersection-observer';
import { useSubscription } from '@apollo/client'; import { useDataProvider } from '@vegaprotocol/react-helpers';
import type { SimpleMarkets_markets_candles } from './__generated__/SimpleMarkets'; import type { Candle } from '@vegaprotocol/market-list';
import type { import { marketCandlesProvider } from '@vegaprotocol/market-list';
CandleLive, import { Interval } from '@vegaprotocol/types';
CandleLiveVariables,
} from './__generated__/CandleLive';
import { CANDLE_SUB } from './data-provider';
interface Props { interface Props {
candles: (SimpleMarkets_markets_candles | null)[] | null; candles: (Candle | null)[] | null;
marketId: string; marketId: string;
setValue: (arg: unknown) => void; setValue: (arg: unknown) => void;
} }
const EMPTY_VALUE = ' - '; const EMPTY_VALUE = ' - ';
const getChange = ( const getChange = (candles: (Candle | null)[] | null, lastClose?: string) => {
candles: (SimpleMarkets_markets_candles | null)[] | null,
lastClose?: string
) => {
if (candles) { if (candles) {
const first = parseInt(candles.find((item) => item?.open)?.open || '-1'); const first = parseInt(candles.find((item) => item?.open)?.open || '-1');
const last = const last =
@@ -74,11 +68,19 @@ const SimpleMarketPercentChangeWrapper = (props: Props) => {
}; };
const SimpleMarketPercentChange = ({ candles, marketId, setValue }: Props) => { const SimpleMarketPercentChange = ({ candles, marketId, setValue }: Props) => {
const { data: { candles: { close = undefined } = {} } = {} } = const yesterday = Math.round(new Date().getTime() / 1000) - 24 * 3600;
useSubscription<CandleLive, CandleLiveVariables>(CANDLE_SUB, { const { data } = useDataProvider({
variables: { marketId }, dataProvider: marketCandlesProvider,
}); variables: {
const change = getChange(candles, close); marketId,
interval: Interval.INTERVAL_I1D,
since: new Date(yesterday * 1000).toISOString(),
},
});
const close = data?.map((m) => m.close);
const change = getChange(candles, close?.[0]);
const colorClasses = getClassColor(change); const colorClasses = getClassColor(change);
useEffect(() => { useEffect(() => {
const value = parseFloat(change); const value = parseFloat(change);
@@ -1,36 +1,36 @@
import React from 'react'; import React from 'react';
import { render, screen } from '@testing-library/react'; import { render, screen } from '@testing-library/react';
import type { MarketNames_markets } from '@vegaprotocol/deal-ticket';
import { MarketState } from '@vegaprotocol/types'; import { MarketState } from '@vegaprotocol/types';
import MarketNameRenderer from './simple-market-renderer'; import MarketNameRenderer from './simple-market-renderer';
import type { Market } from '@vegaprotocol/market-list';
describe('SimpleMarketRenderer', () => { describe('SimpleMarketRenderer', () => {
const market = { const market = {
id: 'marketId', id: 'MARKET_A',
state: MarketState.STATE_ACTIVE, state: MarketState.STATE_ACTIVE,
tradableInstrument: { tradableInstrument: {
instrument: { instrument: {
code: 'Market code', code: 'MARKET_A_CODE',
name: 'Market Name', name: 'MARKET_A_NAME',
product: { product: {
quoteName: 'Quote name', quoteName: 'MARKET_A_QUOTE_NAME',
}, },
metadata: { metadata: {
tags: null, tags: null,
}, },
}, },
}, },
} as MarketNames_markets; } as Market;
it('should properly render not mobile', () => { it('should properly render not mobile', () => {
render(<MarketNameRenderer market={market} isMobile={false} />); render(<MarketNameRenderer market={market} isMobile={false} />);
expect(screen.getByText('Market Name')).toBeInTheDocument(); expect(screen.getByText('MARKET_A_NAME')).toBeInTheDocument();
expect(screen.getByText('Quote name')).toBeInTheDocument(); expect(screen.getByText('MARKET_A_QUOTE_NAME')).toBeInTheDocument();
}); });
it('should properly render mobile', () => { it('should properly render mobile', () => {
render(<MarketNameRenderer market={market} isMobile={true} />); render(<MarketNameRenderer market={market} isMobile={true} />);
expect(screen.getByText('Market code')).toBeInTheDocument(); expect(screen.getByText('MARKET_A_CODE')).toBeInTheDocument();
expect(screen.getByText('Quote name')).toBeInTheDocument(); expect(screen.getByText('MARKET_A_QUOTE_NAME')).toBeInTheDocument();
}); });
}); });
@@ -1,10 +1,9 @@
import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import type { MarketNames_markets } from '@vegaprotocol/deal-ticket';
import SimpleMarketExpires from './simple-market-expires'; import SimpleMarketExpires from './simple-market-expires';
import type { Market } from '@vegaprotocol/market-list';
interface Props { interface Props {
market: MarketNames_markets; market: Market;
isMobile?: boolean; isMobile?: boolean;
} }
@@ -1,4 +1,4 @@
import React, { useCallback, useEffect, useRef, useState } from 'react'; import React, { useCallback, useMemo, useState } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { useNavigate, useParams, Link } from 'react-router-dom'; import { useNavigate, useParams, Link } from 'react-router-dom';
import { import {
@@ -7,7 +7,6 @@ import {
} from '@radix-ui/react-dropdown-menu'; } from '@radix-ui/react-dropdown-menu';
import { IconNames } from '@blueprintjs/icons'; import { IconNames } from '@blueprintjs/icons';
import { t } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
import { import {
DropdownMenuCheckboxItem, DropdownMenuCheckboxItem,
DropdownMenuContent, DropdownMenuContent,
@@ -16,11 +15,13 @@ import {
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import { MarketState } from '@vegaprotocol/types'; import { MarketState } from '@vegaprotocol/types';
import useMarketFiltersData from '../../hooks/use-markets-filter'; import useMarketFiltersData from '../../hooks/use-markets-filter';
import { STATES_FILTER } from './constants'; import type { Markets_marketsConnection_edges_node } from '@vegaprotocol/market-list';
import type { SimpleMarkets_markets } from './__generated__/SimpleMarkets'; import { HorizontalMenu } from '../horizontal-menu';
import type { HorizontalMenuItem } from '../horizontal-menu';
import * as constants from './constants';
interface Props { interface Props {
data: SimpleMarkets_markets[]; data: Markets_marketsConnection_edges_node[];
} }
const SimpleMarketToolbar = ({ data }: Props) => { const SimpleMarketToolbar = ({ data }: Props) => {
@@ -28,37 +29,6 @@ const SimpleMarketToolbar = ({ data }: Props) => {
const params = useParams(); const params = useParams();
const { products, assetsPerProduct } = useMarketFiltersData(data); const { products, assetsPerProduct } = useMarketFiltersData(data);
const [isOpen, setOpen] = useState(false); const [isOpen, setOpen] = useState(false);
const [activeNumber, setActiveNumber] = useState(
products?.length ? products.indexOf(params.product || '') + 1 : -1
);
const [sliderStyles, setSliderStyles] = useState<Record<string, string>>({});
const slideContRef = useRef<HTMLUListElement | null>(null);
useEffect(() => {
if (products.length) {
setActiveNumber(products.indexOf(params.product || '') + 1);
} else {
setActiveNumber(-1);
}
}, [params, products, setActiveNumber]);
useEffect(() => {
const contStyles = (
slideContRef.current as HTMLUListElement
).getBoundingClientRect();
const selectedStyles = (slideContRef.current as HTMLUListElement).children[
activeNumber
]?.getBoundingClientRect();
const styles: Record<string, string> = selectedStyles
? {
backgroundColor: activeNumber ? '' : theme.colors.pink,
width: `${selectedStyles.width}px`,
left: `${selectedStyles.left - contStyles.left}px`,
}
: {};
setSliderStyles(styles);
}, [activeNumber, slideContRef]);
const onStateChange = useCallback( const onStateChange = useCallback(
(activeState: string) => { (activeState: string) => {
@@ -74,53 +44,33 @@ const SimpleMarketToolbar = ({ data }: Props) => {
[params, navigate] [params, navigate]
); );
const productItems = useMemo(() => {
const currentState = params.state || MarketState.STATE_ACTIVE;
const noStateSkip = currentState !== MarketState.STATE_ACTIVE;
const items: HorizontalMenuItem[] = [
{
...constants.ALL_PRODUCTS_ITEM,
url: `/markets${noStateSkip ? '/' + currentState : ''}`,
},
];
products.forEach((product) =>
items.push({
name: product,
id: product,
url: `/markets/${currentState}/${product}`,
})
);
return items;
}, [params, products]);
return ( return (
<div className="w-full max-w-full mb-2 md:mb-8 font-alpha"> <div className="w-full max-w-full mb-2 md:mb-8 font-alpha">
<ul <HorizontalMenu
ref={slideContRef} active={params.product || constants.ALL_PRODUCTS_ITEM.id}
className="grid grid-flow-col auto-cols-min gap-4 relative pb-2 mb-2" items={productItems}
data-testid="market-products-menu" data-testid="market-products-menu"
aria-label={t('Product type')} aria-label={t('Product type')}
> />
<li key="all-markets" className="md:mr-2 whitespace-nowrap">
<Link
to={`/markets${
params.state && params.state !== MarketState.STATE_ACTIVE
? '/' + params.state
: ''
}`}
aria-label={t('All markets')}
className={classNames('pl-0 text-pink hover:opacity-75', {
active: !activeNumber,
})}
>
{t('All Markets')}
</Link>
</li>
{products.map((product, i) => (
<li key={product} className="mx-2 whitespace-nowrap">
<Link
to={`/markets/${
params.state || MarketState.STATE_ACTIVE
}/${product}`}
className={classNames(
'hover:opacity-75 text-black dark:text-white',
{
active: activeNumber - 1 === i,
}
)}
aria-label={product}
>
{product}
</Link>
</li>
))}
<li
className="absolute bottom-0 h-[2px] transition-left duration-300 dark:bg-white bg-black"
key="slider"
style={sliderStyles}
/>
</ul>
<div className="grid gap-4 pb-2 mt-2 md:mt-6 md:grid-cols-[min-content,min-content,1fr]"> <div className="grid gap-4 pb-2 mt-2 md:mt-6 md:grid-cols-[min-content,min-content,1fr]">
<div className="pb-2"> <div className="pb-2">
<DropdownMenu open={isOpen} onOpenChange={(open) => setOpen(open)}> <DropdownMenu open={isOpen} onOpenChange={(open) => setOpen(open)}>
@@ -130,7 +80,7 @@ const SimpleMarketToolbar = ({ data }: Props) => {
onClick={() => setOpen(!isOpen)} onClick={() => setOpen(!isOpen)}
> >
<div className="w-full justify-between uppercase inline-flex items-center justify-center box-border"> <div className="w-full justify-between uppercase inline-flex items-center justify-center box-border">
{STATES_FILTER.find( {constants.STATES_FILTER.find(
(state) => (state) =>
state.value === params.state || state.value === params.state ||
(!params.state && state.value === MarketState.STATE_ACTIVE) (!params.state && state.value === MarketState.STATE_ACTIVE)
@@ -147,7 +97,7 @@ const SimpleMarketToolbar = ({ data }: Props) => {
</div> </div>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent> <DropdownMenuContent>
{STATES_FILTER.map(({ value, text }) => ( {constants.STATES_FILTER.map(({ value, text }) => (
<DropdownMenuCheckboxItem <DropdownMenuCheckboxItem
className="uppercase text-ui" className="uppercase text-ui"
key={value} key={value}
@@ -169,7 +119,7 @@ const SimpleMarketToolbar = ({ data }: Props) => {
<div className="hidden md:block text-deemphasise dark:text-midGrey"> <div className="hidden md:block text-deemphasise dark:text-midGrey">
| |
</div> </div>
{activeNumber > 0 && ( {params.product && (
<ul <ul
className="md:gap-x-6 gap-x-4 gap-y-1 pb-2 md:ml-2 flex flex-wrap" className="md:gap-x-6 gap-x-4 gap-y-1 pb-2 md:ml-2 flex flex-wrap"
data-testid="market-assets-menu" data-testid="market-assets-menu"
@@ -189,7 +139,7 @@ const SimpleMarketToolbar = ({ data }: Props) => {
{t('All')} {t('All')}
</Link> </Link>
</li> </li>
{assetsPerProduct[products[activeNumber - 1]]?.map((asset) => ( {assetsPerProduct[params?.product]?.map((asset) => (
<li key={asset}> <li key={asset}>
<Link <Link
to={`/markets/${params.state}/${params.product}/${asset}`} to={`/markets/${params.state}/${params.product}/${asset}`}
@@ -1,14 +1,13 @@
import React, { useMemo } from 'react'; import { useMemo } from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { t } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import type { SimpleMarkets_markets } from '../components/simple-market-list/__generated__/SimpleMarkets'; import MarketNameRenderer from './simple-market-renderer';
import MarketNameRenderer from '../components/simple-market-list/simple-market-renderer'; import SimpleMarketPercentChange from './simple-market-percent-change';
import SimpleMarketPercentChange from '../components/simple-market-list/simple-market-percent-change';
import { Icon } from '@vegaprotocol/ui-toolkit'; import { Icon } from '@vegaprotocol/ui-toolkit';
import type { ValueSetterParams } from 'ag-grid-community'; import type { ValueSetterParams } from 'ag-grid-community';
import type { SimpleMarketsType } from '../components/simple-market-list/simple-market-list';
import { IconNames } from '@blueprintjs/icons'; import { IconNames } from '@blueprintjs/icons';
import { IS_MARKET_TRADABLE, MARKET_STATES_MAP } from '../constants'; import { IS_MARKET_TRADABLE, MARKET_STATES_MAP } from '../../constants';
import type { Candle, Market } from '@vegaprotocol/market-list';
interface Props { interface Props {
isMobile: boolean; isMobile: boolean;
@@ -24,7 +23,7 @@ const useColumnDefinitions = ({ isMobile }: Props) => {
minWidth: isMobile ? 160 : 350, minWidth: isMobile ? 160 : 350,
field: 'tradableInstrument.instrument.name', field: 'tradableInstrument.instrument.name',
cellClass: 'overflow-visible', cellClass: 'overflow-visible',
cellRenderer: ({ data }: { data: SimpleMarketsType }) => ( cellRenderer: ({ data }: { data: Market }) => (
<MarketNameRenderer market={data} isMobile={isMobile} /> <MarketNameRenderer market={data} isMobile={isMobile} />
), ),
}, },
@@ -35,7 +34,7 @@ const useColumnDefinitions = ({ isMobile }: Props) => {
minWidth: isMobile ? 50 : 80, minWidth: isMobile ? 50 : 80,
cellClass: 'uppercase flex h-full items-center', cellClass: 'uppercase flex h-full items-center',
field: 'tradableInstrument.instrument.product.settlementAsset.symbol', field: 'tradableInstrument.instrument.product.settlementAsset.symbol',
cellRenderer: ({ data }: { data: SimpleMarketsType }) => ( cellRenderer: ({ data }: { data: Market }) => (
<div <div
className="grid h-full items-center text-center" className="grid h-full items-center text-center"
title={ title={
@@ -70,7 +69,7 @@ const useColumnDefinitions = ({ isMobile }: Props) => {
data, data,
setValue, setValue,
}: { }: {
data: SimpleMarketsType; data: { id: string; candles: Candle[] };
setValue: (arg: unknown) => void; setValue: (arg: unknown) => void;
}) => ( }) => (
<SimpleMarketPercentChange <SimpleMarketPercentChange
@@ -96,7 +95,7 @@ const useColumnDefinitions = ({ isMobile }: Props) => {
field: 'state', field: 'state',
headerClass: 'uppercase', headerClass: 'uppercase',
minWidth: 100, minWidth: 100,
cellRenderer: ({ data }: { data: SimpleMarkets_markets }) => ( cellRenderer: ({ data }: { data: Market }) => (
<div className="uppercase flex h-full items-center justify-center"> <div className="uppercase flex h-full items-center justify-center">
<div className="border text-center px-2 md:px-6 leading-4 md:leading-6"> <div className="border text-center px-2 md:px-6 leading-4 md:leading-6">
{MARKET_STATES_MAP[data.state || '']} {MARKET_STATES_MAP[data.state || '']}
@@ -110,7 +109,7 @@ const useColumnDefinitions = ({ isMobile }: Props) => {
headerClass: 'uppercase', headerClass: 'uppercase',
sortable: false, sortable: false,
width: isMobile ? 35 : 100, width: isMobile ? 35 : 100,
cellRenderer: ({ data }: { data: SimpleMarkets_markets }) => ( cellRenderer: ({ data }: { data: Market }) => (
<div className="h-full flex h-full items-center justify-end"> <div className="h-full flex h-full items-center justify-end">
<div className="uppercase text-center pr-2"> <div className="uppercase text-center pr-2">
{!isMobile && t('Trade')} {!isMobile && t('Trade')}
@@ -0,0 +1,52 @@
import { useMemo } from 'react';
import { MarketState } from '@vegaprotocol/types';
import type { MarketsListData } from '@vegaprotocol/market-list';
import type { RouterParams } from './simple-market-list';
const useMarketsFilterData = (data: MarketsListData, params: RouterParams) => {
return useMemo(() => {
const markets =
data?.markets?.filter((item) => {
if (
params.product &&
params.product !==
item.tradableInstrument.instrument.product.__typename
) {
return false;
}
if (
params.asset &&
params.asset !== 'all' &&
params.asset !==
item.tradableInstrument.instrument.product.settlementAsset.symbol
) {
return false;
}
const state =
params.state === 'all'
? ''
: params.state
? params.state
: MarketState.STATE_ACTIVE;
if (state && state !== item.state) {
return false;
}
return true;
}) || [];
return markets.map((market) => ({
...market,
candles: (data?.marketsCandles || [])
.filter((c) => c.marketId === market.id)
.map((c) => c.candles),
}));
}, [
data?.marketsCandles,
data?.markets,
params.product,
params.asset,
params.state,
]);
};
export default useMarketsFilterData;
+4 -2
View File
@@ -1,6 +1,6 @@
import type { SimpleMarkets_markets } from '../components/simple-market-list/__generated__/SimpleMarkets';
import { MarketState } from '@vegaprotocol/types'; import { MarketState } from '@vegaprotocol/types';
import { t } from '@vegaprotocol/react-helpers'; import { t } from '@vegaprotocol/react-helpers';
import type { Market } from '@vegaprotocol/market-list';
export const DATE_FORMAT = 'dd MMMM yyyy HH:mm'; export const DATE_FORMAT = 'dd MMMM yyyy HH:mm';
export const EXPIRE_DATE_FORMAT = 'MMM dd'; export const EXPIRE_DATE_FORMAT = 'MMM dd';
@@ -9,7 +9,7 @@ export const TRADABLE_STATES = {
[MarketState.STATE_ACTIVE]: true, [MarketState.STATE_ACTIVE]: true,
}; };
export const IS_MARKET_TRADABLE = (market: SimpleMarkets_markets) => export const IS_MARKET_TRADABLE = (market: Market) =>
Boolean((market.state ?? '') in TRADABLE_STATES && market?.id); Boolean((market.state ?? '') in TRADABLE_STATES && market?.id);
export const MARKET_STATES_MAP: Record<MarketState | '', string> = { export const MARKET_STATES_MAP: Record<MarketState | '', string> = {
@@ -24,3 +24,5 @@ export const MARKET_STATES_MAP: Record<MarketState | '', string> = {
[MarketState.STATE_TRADING_TERMINATED]: t('TradingTerminated'), [MarketState.STATE_TRADING_TERMINATED]: t('TradingTerminated'),
'': t('Unknown'), '': t('Unknown'),
}; };
export const NO_DATA_MESSAGE = t('No data to display');
@@ -10,7 +10,7 @@
export interface MarketMarkPrice_market_data { export interface MarketMarkPrice_market_data {
__typename: "MarketData"; __typename: "MarketData";
/** /**
* the mark price (an unsigned integer) * The mark price (an unsigned integer)
*/ */
markPrice: string; markPrice: string;
} }
@@ -18,7 +18,7 @@ export interface MarketMarkPrice_market_data {
export interface MarketMarkPrice_market { export interface MarketMarkPrice_market {
__typename: "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) * number denominated in the currency of the market. (uint64)
* *
* Examples: * Examples:
@@ -60,19 +60,19 @@ export interface PartyMarketData_party_marginsConnection_edges_node_market {
export interface PartyMarketData_party_marginsConnection_edges_node { export interface PartyMarketData_party_marginsConnection_edges_node {
__typename: "MarginLevels"; __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; 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; 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; 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; searchLevel: string;
} }
@@ -103,7 +103,7 @@ export interface PartyMarketData_party {
/** /**
* Margin levels for a market * Margin levels for a market
*/ */
marginsConnection: PartyMarketData_party_marginsConnection; marginsConnection: PartyMarketData_party_marginsConnection | null;
} }
export interface PartyMarketData { export interface PartyMarketData {
@@ -28,7 +28,7 @@ export interface EstimateOrder_estimateOrder_fee {
export interface EstimateOrder_estimateOrder_marginLevels { export interface EstimateOrder_estimateOrder_marginLevels {
__typename: "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; initialLevel: string;
} }
@@ -47,7 +47,7 @@ export interface EstimateOrder_estimateOrder {
export interface 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; estimateOrder: EstimateOrder_estimateOrder;
} }
@@ -67,6 +67,9 @@ export interface MarketPositions_party_positionsConnection_edges_node {
export interface MarketPositions_party_positionsConnection_edges { export interface MarketPositions_party_positionsConnection_edges {
__typename: "PositionEdge"; __typename: "PositionEdge";
/**
* The position
*/
node: MarketPositions_party_positionsConnection_edges_node; node: MarketPositions_party_positionsConnection_edges_node;
} }
@@ -91,7 +94,7 @@ export interface MarketPositions_party {
/** /**
* Trading positions relating to a party * Trading positions relating to a party
*/ */
positionsConnection: MarketPositions_party_positionsConnection; positionsConnection: MarketPositions_party_positionsConnection | null;
} }
export interface MarketPositions { export interface MarketPositions {
@@ -8,7 +8,7 @@ export type MarketPositionsQueryVariables = Types.Exact<{
}>; }>;
export type MarketPositionsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, accounts?: Array<{ __typename?: 'Account', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', decimals: number }, market?: { __typename?: 'Market', id: string } | null }> | null, positionsConnection: { __typename?: 'PositionConnection', edges?: Array<{ __typename?: 'PositionEdge', node: { __typename?: 'Position', openVolume: string, market: { __typename?: 'Market', id: string } } }> | null } } | null }; export type MarketPositionsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, accounts?: Array<{ __typename?: 'Account', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', decimals: number }, market?: { __typename?: 'Market', id: string } | null }> | null, positionsConnection?: { __typename?: 'PositionConnection', edges?: Array<{ __typename?: 'PositionEdge', node: { __typename?: 'Position', openVolume: string, market: { __typename?: 'Market', id: string } } }> | null } | null } | null };
export const MarketPositionsDocument = gql` export const MarketPositionsDocument = gql`
@@ -8,7 +8,7 @@ export type PartyMarketDataQueryVariables = Types.Exact<{
}>; }>;
export type PartyMarketDataQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, accounts?: Array<{ __typename?: 'Account', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string, decimals: number }, market?: { __typename?: 'Market', id: string } | null }> | null, marginsConnection: { __typename?: 'MarginConnection', edges?: Array<{ __typename?: 'MarginEdge', node: { __typename?: 'MarginLevels', initialLevel: string, maintenanceLevel: string, searchLevel: string, market: { __typename?: 'Market', id: string } } }> | null } } | null }; export type PartyMarketDataQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, accounts?: Array<{ __typename?: 'Account', type: Types.AccountType, balance: string, asset: { __typename?: 'Asset', id: string, decimals: number }, market?: { __typename?: 'Market', id: string } | null }> | null, marginsConnection?: { __typename?: 'MarginConnection', edges?: Array<{ __typename?: 'MarginEdge', node: { __typename?: 'MarginLevels', initialLevel: string, maintenanceLevel: string, searchLevel: string, market: { __typename?: 'Market', id: string } } }> | null } | null } | null };
export const PartyMarketDataDocument = gql` export const PartyMarketDataDocument = gql`
@@ -64,6 +64,15 @@ jest.mock('@vegaprotocol/market-depth', () => ({
useOrderBookData: jest.fn(() => mockOrderBookData), useOrderBookData: jest.fn(() => mockOrderBookData),
})); }));
jest.mock('@vegaprotocol/react-helpers', () => ({
...jest.requireActual('@vegaprotocol/react-helpers'),
useDataProvider: jest.fn(() => ({
data: {
marketsConnection: [],
},
})),
}));
describe('useCalculateSlippage Hook', () => { describe('useCalculateSlippage Hook', () => {
describe('calculate proper result', () => { describe('calculate proper result', () => {
afterEach(() => { afterEach(() => {
@@ -1,9 +1,15 @@
import { useMemo } from 'react'; import { useMemo } from 'react';
import { Side } from '@vegaprotocol/types'; import { Side } from '@vegaprotocol/types';
import { useOrderBookData } from '@vegaprotocol/market-depth'; import { useOrderBookData } from '@vegaprotocol/market-depth';
import { marketProvider } from '@vegaprotocol/market-list';
import type { Market } from '@vegaprotocol/market-list';
import type { Order } from '@vegaprotocol/orders'; import type { Order } from '@vegaprotocol/orders';
import { BigNumber } from 'bignumber.js'; import { BigNumber } from 'bignumber.js';
import { formatNumber, toBigNum } from '@vegaprotocol/react-helpers'; import {
formatNumber,
toBigNum,
useDataProvider,
} from '@vegaprotocol/react-helpers';
interface Props { interface Props {
marketId: string; marketId: string;
@@ -16,11 +22,16 @@ const useCalculateSlippage = ({ marketId, order }: Props) => {
variables, variables,
throttleMilliseconds: 5000, throttleMilliseconds: 5000,
}); });
const { data: market } = useDataProvider<Market, never>({
dataProvider: marketProvider,
noUpdate: true,
variables,
});
const volPriceArr = const volPriceArr =
data?.depth[order.side === Side.SIDE_BUY ? 'sell' : 'buy'] || []; data?.depth[order.side === Side.SIDE_BUY ? 'sell' : 'buy'] || [];
if (volPriceArr.length) { if (volPriceArr.length && market) {
const decimals = data?.decimalPlaces ?? 0; const decimals = market.decimalPlaces ?? 0;
const positionDecimals = data?.positionDecimalPlaces ?? 0; const positionDecimals = market.positionDecimalPlaces ?? 0;
const bestPrice = toBigNum(volPriceArr[0].price, decimals); const bestPrice = toBigNum(volPriceArr[0].price, decimals);
const { size } = order; const { size } = order;
let descSize = new BigNumber(size); let descSize = new BigNumber(size);
@@ -1,37 +0,0 @@
import type { SimpleMarkets_markets } from '../components/simple-market-list/__generated__/SimpleMarkets';
import type { RouterParams } from '../components/simple-market-list/simple-market-list';
import { MarketState } from '@vegaprotocol/types';
const useMarketsFilterData = (
data: SimpleMarkets_markets[] = [],
params: RouterParams
) => {
return data.filter((item) => {
if (
params.product &&
params.product !== item.tradableInstrument.instrument.product.__typename
) {
return false;
}
if (
params.asset &&
params.asset !== 'all' &&
params.asset !==
item.tradableInstrument.instrument.product.settlementAsset.symbol
) {
return false;
}
const state =
params.state === 'all'
? ''
: params.state
? params.state
: MarketState.STATE_ACTIVE;
if (state && state !== item.state) {
return false;
}
return true;
});
};
export default useMarketsFilterData;
@@ -1,7 +1,7 @@
import type { Market } from '@vegaprotocol/market-list';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import type { SimpleMarkets_markets } from '../components/simple-market-list/__generated__/SimpleMarkets';
const useMarketFilters = (data: SimpleMarkets_markets[]) => { const useMarketFilters = (data: Market[]) => {
const [products, setProducts] = useState<string[]>([]); const [products, setProducts] = useState<string[]>([]);
const [assetsPerProduct, setAssetsPerProduct] = useState< const [assetsPerProduct, setAssetsPerProduct] = useState<
Record<string, string[]> Record<string, string[]>
@@ -3,7 +3,7 @@ import { renderHook } from '@testing-library/react';
import { MockedProvider } from '@apollo/client/testing'; import { MockedProvider } from '@apollo/client/testing';
import useOrderCloseOut from './use-order-closeout'; import useOrderCloseOut from './use-order-closeout';
import type { Order } from '@vegaprotocol/orders'; 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 type { PartyBalanceQuery } from '../components/deal-ticket/__generated__/PartyBalanceQuery';
jest.mock('@vegaprotocol/wallet', () => ({ jest.mock('@vegaprotocol/wallet', () => ({
@@ -49,7 +49,7 @@ describe('useOrderCloseOut Hook', () => {
() => () =>
useOrderCloseOut({ useOrderCloseOut({
order: order as Order, order: order as Order,
market: market as DealTicketQuery_market, market: market as DealTicketMarketFragment,
partyData: partyData as PartyBalanceQuery, partyData: partyData as PartyBalanceQuery,
}), }),
{ {
@@ -66,7 +66,7 @@ describe('useOrderCloseOut Hook', () => {
() => () =>
useOrderCloseOut({ useOrderCloseOut({
order: { ...order, side: 'SIDE_SELL' } as Order, order: { ...order, side: 'SIDE_SELL' } as Order,
market: market as DealTicketQuery_market, market: market as DealTicketMarketFragment,
partyData: partyData as PartyBalanceQuery, partyData: partyData as PartyBalanceQuery,
}), }),
{ {
@@ -83,7 +83,7 @@ describe('useOrderCloseOut Hook', () => {
() => () =>
useOrderCloseOut({ useOrderCloseOut({
order: { ...order, side: 'SIDE_SELL' } as Order, order: { ...order, side: 'SIDE_SELL' } as Order,
market: market as DealTicketQuery_market, market: market as DealTicketMarketFragment,
}), }),
{ {
wrapper: ({ children }: { children: React.ReactNode }) => ( wrapper: ({ children }: { children: React.ReactNode }) => (
@@ -1,6 +1,6 @@
import { BigNumber } from 'bignumber.js'; import { BigNumber } from 'bignumber.js';
import type { Order } from '@vegaprotocol/orders'; 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 type { PartyBalanceQuery } from '../components/deal-ticket/__generated__/PartyBalanceQuery';
import { useSettlementAccount } from './use-settlement-account'; import { useSettlementAccount } from './use-settlement-account';
import { useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
@@ -47,7 +47,7 @@ const CLOSEOUT_PRICE_QUERY = gql`
interface Props { interface Props {
order: Order; order: Order;
market: DealTicketQuery_market; market: DealTicketMarketFragment;
partyData?: PartyBalanceQuery; partyData?: PartyBalanceQuery;
} }
@@ -74,7 +74,7 @@ const useOrderCloseOut = ({ order, market, partyData }: Props): string => {
const marginMaintenanceLevel = new BigNumber( const marginMaintenanceLevel = new BigNumber(
addDecimal( addDecimal(
data?.party?.marginsConnection.edges?.find( data?.party?.marginsConnection?.edges?.find(
(nodes) => nodes.node.market.id === market.id (nodes) => nodes.node.market.id === market.id
)?.node.maintenanceLevel || 0, )?.node.maintenanceLevel || 0,
market.decimalPlaces market.decimalPlaces
@@ -2,7 +2,7 @@ import { renderHook } from '@testing-library/react';
import { useQuery } from '@apollo/client'; import { useQuery } from '@apollo/client';
import { BigNumber } from 'bignumber.js'; import { BigNumber } from 'bignumber.js';
import type { Order } from '@vegaprotocol/orders'; 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 type { PositionMargin } from './use-market-positions';
import useOrderMargin from './use-order-margin'; import useOrderMargin from './use-order-margin';
@@ -54,7 +54,7 @@ describe('useOrderMargin Hook', () => {
const { result } = renderHook(() => const { result } = renderHook(() =>
useOrderMargin({ useOrderMargin({
order: order as Order, order: order as Order,
market: market as DealTicketQuery_market, market: market as DealTicketMarketFragment,
partyId, partyId,
}) })
); );
@@ -72,7 +72,7 @@ describe('useOrderMargin Hook', () => {
const { result } = renderHook(() => const { result } = renderHook(() =>
useOrderMargin({ useOrderMargin({
order: order as Order, order: order as Order,
market: market as DealTicketQuery_market, market: market as DealTicketMarketFragment,
partyId, partyId,
}) })
); );
@@ -84,7 +84,7 @@ describe('useOrderMargin Hook', () => {
const { result } = renderHook(() => const { result } = renderHook(() =>
useOrderMargin({ useOrderMargin({
order: order as Order, order: order as Order,
market: market as DealTicketQuery_market, market: market as DealTicketMarketFragment,
partyId, partyId,
}) })
); );
@@ -111,7 +111,7 @@ describe('useOrderMargin Hook', () => {
const { result } = renderHook(() => const { result } = renderHook(() =>
useOrderMargin({ useOrderMargin({
order: order as Order, order: order as Order,
market: market as DealTicketQuery_market, market: market as DealTicketMarketFragment,
partyId, partyId,
}) })
); );
@@ -6,7 +6,7 @@ import type {
EstimateOrderVariables, EstimateOrderVariables,
EstimateOrder_estimateOrder_fee, EstimateOrder_estimateOrder_fee,
} from './__generated__/estimateOrder'; } from './__generated__/estimateOrder';
import type { DealTicketQuery_market } from '@vegaprotocol/deal-ticket'; import type { DealTicketMarketFragment } from '@vegaprotocol/deal-ticket';
import { Side } from '@vegaprotocol/types'; import { Side } from '@vegaprotocol/types';
import { addDecimal, removeDecimal } from '@vegaprotocol/react-helpers'; import { addDecimal, removeDecimal } from '@vegaprotocol/react-helpers';
import useMarketPositions from './use-market-positions'; import useMarketPositions from './use-market-positions';
@@ -47,7 +47,7 @@ export const ESTIMATE_ORDER_QUERY = gql`
interface Props { interface Props {
order: Order; order: Order;
market: DealTicketQuery_market; market: DealTicketMarketFragment;
partyId: string; partyId: string;
} }

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