Compare commits

..
Author SHA1 Message Date
dexturr 5b6c8b07f7 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-18 22:55:05 +02:00
botond fb451b862b feat(governance): paginate rewards (#3391) 2023-04-18 22:55:05 +02:00
Bartłomiej Głownia a3d5952074 fix(trading): update cached Order objects (#3450) 2023-04-18 22:55:05 +02:00
m.ray f1f2b58b4d feat(trading): add liquidity provision link to orders table (#3432) 2023-04-18 22:55:05 +02:00
Sam KeenandMatthew Russell 66b5e72ea4 feat(governance): full width Governance and Explorer header (#3453)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-04-18 22:55:05 +02:00
Bartłomiej Głownia 402fdf13a3 chore(trading): maintain always up to date active orders list (#3430) 2023-04-18 22:55:05 +02:00
Dariusz Majcherczyk 1bfbffa1de test: artifact path 2023-04-18 22:48:19 +02:00
dexturr b6647538ce chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-18 08:49:54 +02:00
dexturr b67ef4b2ad chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-18 08:49:54 +02:00
Dariusz Majcherczyk 2d23e86a6a test: added yarn lock 2023-04-17 22:51:51 +02:00
dexturr ee1be26f59 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
dexturr 05b63be707 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
Mikołaj Młodzikowski a8b58628e9 fix(ci): adjust timeouts 2023-04-17 22:51:51 +02:00
Mikołaj Młodzikowski 7acc7f247d feat(ci): rebuild yarn on failed build 2023-04-17 22:51:51 +02:00
dexturr 0735d23a6b chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
dexturr ae760922a8 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
dexturr bb17029837 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
dexturr 1afd9227e4 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
dexturr 7f967f49bf chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
dexturr a5b009c21d chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
dexturr 23c4252be6 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
dexturr db568a3361 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
dexturr 00cf58e5e1 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
dexturr 9fd00f52fa chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
dexturr 5739a8ed9b chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
Mikołaj Młodzikowski f97a7b2e0e feat: fix releasing dist 2023-04-17 22:51:51 +02:00
Mikołaj Młodzikowski ee8e456ca6 feat(ci): fix regressions detected after merging to develop (#3442) 2023-04-17 22:51:51 +02:00
dexturr 8cacb83637 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
Mikołaj Młodzikowski 42556af6df feat(governance,trading,explorer): pipelines improvements (#3422) 2023-04-17 22:51:51 +02:00
Sam Keen 480b667080 feat(governance): toggles design review tweaks (#3431) 2023-04-17 22:51:51 +02:00
dexturr fdde2ca8fa chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
dexturr dd44c67cdf chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
m.ray 5a1be05565 fix(trading): fix order toast intent on amendments (#3433) 2023-04-17 22:51:51 +02:00
dexturr 35f7394c29 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
dexturr 0dbe3550e2 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:51 +02:00
Maciek b364bf27f0 chore(assets): make query for asset list lighter (#3425) 2023-04-17 22:51:50 +02:00
Edd 614da1b070 fix(explorer): tweak footer to show more detail on smaller screens (#3418) 2023-04-17 22:51:50 +02:00
Joe Tsang d522af60d1 fix(governance): failing nightly tests (#3351) 2023-04-17 22:51:50 +02:00
dexturr 0eebf06589 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:50 +02:00
dexturr 78130f86a0 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:50 +02:00
dexturr 185efaf896 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:50 +02:00
m.ray 25b88d6afa fix(orders): update order toast intent and title (#3424) 2023-04-17 22:51:50 +02:00
dexturr a53c868082 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:50 +02:00
Bartłomiej Głowniaandm.ray 19433907c2 feat(withdraws): improve ux surrounding withdraw balances thresholds and delays (#3402)
Co-authored-by: m.ray <16125548+MadalinaRaicu@users.noreply.github.com>
2023-04-17 22:51:50 +02:00
Mikołaj Młodzikowski 2379d532b3 feat(governance,trading,explorer): split steps by logic (#3387) 2023-04-17 22:51:50 +02:00
dexturr 34e4311d4b chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:50 +02:00
dexturr 7d6763d7a7 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:50 +02:00
dexturr bc3620d85e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-17 22:51:50 +02:00
Maciek 8f56f26b16 fix(deposits): deposit dialog doesn't respect given assetId (#3414) 2023-04-17 22:51:50 +02:00
Dariusz Majcherczyk af2053639f test: check tests 2023-04-17 10:36:54 +02:00
Dariusz Majcherczyk 22caee162a test: remove comment 2023-04-17 10:14:14 +02:00
Dariusz Majcherczyk c3e9148127 test: test propose 2023-04-17 09:39:58 +02:00
Dariusz Majcherczyk 82b667bd1e test: mocha reporter for e2e tests 2023-04-16 22:51:03 +02:00
m.ray 03f5ca3096 fix(trading): fix formatting on clicking on orderbook cell after decimal resolution update (#3409) 2023-04-11 12:23:43 +00:00
dexturr 03d19349af chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-11 12:08:24 +00:00
daro-maj 1f53b2cbb5 test(trading): increase coverage for the remaining ACs (#3412) 2023-04-11 11:59:21 +02:00
Maciek b010c98346 fix(trading): welcome dialog with markets list click on market close window (#3404) 2023-04-11 11:34:44 +02:00
Matthew Russell 29d57af2ba fix(trading): make light theme sell volume bar match candle color (#3405) 2023-04-11 09:06:35 +02:00
Bartłomiej Głownia fd7940c4cf chore(deal-ticket): remove not used code (#3406) 2023-04-11 08:13:41 +02:00
dexturr 8ab7ac8414 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-11 06:07:03 +00:00
dexturr ce7cd03c3e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-11 00:15:30 +00:00
Matthew Russell dfa3355a68 chore(trading): prevent node poll if query fails (#3411) 2023-04-10 14:48:03 -07:00
dexturr 8553904d81 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-10 18:07:16 +00:00
dexturr 10afa3c1d4 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-10 12:10:31 +00:00
Maciek ecd362615e chore(deposits): impove UX on deposit dialog (#3401) 2023-04-10 12:59:02 +01:00
dexturr 0d9bd67465 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-10 06:07:18 +00:00
dexturr b5aa92f007 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-10 00:14:34 +00:00
dexturr 2955790be1 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-09 18:09:21 +00:00
dexturr 89ff9309e9 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-09 12:08:56 +00:00
dexturr e1df3489f6 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-09 06:09:36 +00:00
dexturr f0fa9ca5e1 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-09 00:17:04 +00:00
dexturr 9d92477c2a chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-08 18:08:30 +00:00
dexturr b1a198be85 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-08 12:09:49 +00:00
dexturr 5fb385d43c chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-08 06:07:03 +00:00
dexturr 8014b279fe chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-08 00:14:19 +00:00
dexturr f4bde57294 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-07 18:09:32 +00:00
John Walley 2e5ff07824 chore(candles-chart): upgrade pennant to v1.8.1 (#3399) 2023-04-07 10:35:10 -07:00
Bartłomiej Głownia 7accb42793 fix(market-depth): make market data up to date, use fixed number of decimals in cumulative vol (#3361) 2023-04-07 10:34:51 -07:00
Matthew Russell 9229e7f686 chore(trading): update approval amount to be max uint256 (#3395) 2023-04-07 10:33:53 -07:00
daro-maj b570b9c4c1 test(trading): tests for post and reduce functionality (#3400) 2023-04-07 13:03:15 -04:00
m.ray ed78261aad fix(trading): order tx toasts title and intent should be set by status (#3368) 2023-04-07 13:01:12 -04:00
m.ray 363ca9c6e1 fix(trading): add liquidity provision docs (#3403) 2023-04-07 13:00:57 -04:00
m.ray bafd3c384c feat(trading): include fees in transfer amount (#3345) 2023-04-07 13:00:11 -04:00
dexturr 3b830abe07 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-07 12:09:01 +00:00
dexturr 1787e22b69 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-07 06:07:23 +00:00
dexturr f105133959 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-07 00:14:21 +00:00
dexturr aff0e46d23 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-06 18:08:45 +00:00
Maciek 7e4aafcb77 chore(trading): add filters to the proposals table (#3375) 2023-04-06 15:30:21 +02:00
dexturr 643d5408cd chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-06 12:08:03 +00:00
m.ray 2a2af3ba9c fix(trading): fix docs resources (#3382) 2023-04-06 12:53:08 +01:00
Sam Keen 8d4e4a1228 fix(governance): fix incorrect validator penalties (#3381) 2023-04-06 13:31:21 +02:00
dexturr 84068c8081 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-06 06:09:30 +00:00
dexturr e1185b9a96 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-06 00:13:22 +00:00
dexturr f390448c24 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-05 18:09:37 +00:00
Maciek 70943c523c chore(deposits): persistence of deposit form state (#3348) 2023-04-05 14:53:55 +02:00
dexturr dcb79e70d3 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-05 12:10:10 +00:00
dexturr cc72cdbe16 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-05 06:08:13 +00:00
dexturr 3fd1817e1e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-05 00:15:53 +00:00
Matthew Russell b483c13f81 chore(trading): fix bad grammar on approval notification (#3354) 2023-04-04 15:14:36 -07:00
Matthew Russell bde7a9fbf9 fix(smart-contracts): add increased gas limit estimation (#3371) 2023-04-04 11:41:11 -07:00
dexturr 5fd93ee9c8 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-04 18:09:38 +00:00
botond 9ac07fd98a fix: add missing announcement config url (#3367) 2023-04-04 15:11:48 +00:00
dexturr 9c975ed822 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-04 12:10:23 +00:00
Edd 138bf7da00 build(explorer): update validator testnet be url (#3357) 2023-04-04 10:53:47 +00:00
dexturr 3e7fe517f3 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-04 06:07:34 +00:00
dexturr 4f960d09b3 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-04 00:15:07 +00:00
Bartłomiej Głownia 351a5aaf96 chore(trading): remove not used close position code and liquidity subscription (#3350) 2023-04-03 14:58:06 -07:00
Bartłomiej Głownia 381d9011a0 fix(orders): restore filter by marketId (#3342) 2023-04-03 14:20:31 -07:00
Matthew Russell 861760b4f9 chore(governance): add hardcoded token vesting contract address (#3352) 2023-04-03 21:17:32 +00:00
Matthew Russell 18f1c0014c chore(governance,explorer,multisig-signer): delete rest of sandbox/mirror env files (#3310) 2023-04-03 14:07:43 -07:00
m.ray 474543d91b fix(trading): order stopped intent toasts (#3347) 2023-04-03 19:21:56 +00:00
dexturr 662753c74b chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-03 18:09:46 +00:00
daro-majandm.ray 71aa8882bc test(trading): renders correctly liquidity in trading tab (#3343)
Co-authored-by: m.ray <16125548+MadalinaRaicu@users.noreply.github.com>
2023-04-03 14:33:10 +00:00
Mikołaj Młodzikowski ecfbccf8ed feat(trading,governance,explorer): dist on s3 (#3332) 2023-04-03 15:53:50 +02:00
Bartłomiej Głownia 2aad6b1a14 feat(deal-ticket): show total margin available for an order, and where it will come from (#3318) 2023-04-03 15:17:23 +02:00
Bartłomiej Głownia 8463d371ad chore(trading): liquidity table DRY (#3346) 2023-04-03 15:02:43 +02:00
dexturr 0914e7ce4b chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-03 12:08:48 +00:00
Maciek 7c82144f37 chore(trading): add metaKey detection - clean up some unit tests (#3337) 2023-04-03 10:20:20 +02:00
Joe Tsang 17ad0cc975 test(governance): add e2e tests for banner and footer links (#3340) 2023-04-03 09:16:42 +01:00
dexturr eb58dcd350 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-03 06:09:59 +00:00
dexturr c8c0bf2cc0 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-03 00:16:15 +00:00
dexturr 00579fcb1f chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-02 18:06:45 +00:00
dexturr 5e13173efb chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-02 12:09:35 +00:00
dexturr 3a6c0554cc chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-02 06:06:55 +00:00
dexturr d4b237a6ba chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-02 00:17:15 +00:00
dexturr 5e765f3172 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-01 18:07:57 +00:00
dexturr 5ef8c11e6e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-01 12:07:28 +00:00
dexturr 84bae12def chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-01 06:06:47 +00:00
dexturr c5b22f5bfb chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-04-01 00:14:47 +00:00
dexturr 071dcc61a8 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-31 18:09:16 +00:00
m.ray ce0ccdfebc feat(trading): add post only and reduce only orders (#3311) 2023-03-31 17:00:55 +01:00
Art f1524d3fcd feat(utils): make release script (#3290) 2023-03-31 17:01:19 +02:00
MaciekandMatthew Russell 82e5128ba1 chore(trading): add "holding CMD + click" external link (#3273)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-03-31 15:23:44 +02:00
Maciek 2bfc3abd15 chore(trading): liquidity provision, change query for set flag live on true (#3335) 2023-03-31 14:20:44 +01:00
dexturr bd3b557f3d chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-31 12:10:35 +00:00
MaciekandBartłomiej Głownia c899da52c2 fix(trading): stabilize the liquidity provision table (#3320)
Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
2023-03-31 11:41:16 +01:00
Matthew Russell b9c4057ce5 feat(oracles,trading): 3224 add oracle links to market info (#3297) 2023-03-31 09:06:21 +01:00
dexturr d02feee5c6 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-31 06:07:09 +00:00
dexturr 6d1ab36a72 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-31 00:14:21 +00:00
dexturr 5690fe91a8 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-30 18:09:18 +00:00
Joe Tsang 1daae6a233 chore(governance): additional acs added for governance proposals (#3322) 2023-03-30 17:18:41 +01:00
dexturr cd35a34246 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-30 12:10:13 +00:00
Bartłomiej Głownia 77ada964b5 feat(market-depth): always show the same number of decimal places in order book (#3317) 2023-03-30 10:54:13 +01:00
dexturr d7404bcd76 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-30 06:07:12 +00:00
dexturr 91862701a7 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-30 00:14:12 +00:00
dexturr 0136efd78f chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-29 18:14:47 +00:00
daro-maj c3a4954d0d test(trading): update live e2e tests (#3307) 2023-03-29 15:26:12 +02:00
botondandMikołaj Młodzikowski 528fd96721 feat(announcements): announcements (#3252)
Co-authored-by: Mikołaj Młodzikowski <mikolaj.mlodzikowski@gmail.com>
2023-03-29 15:20:49 +02:00
dexturr 155923ff8e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-29 12:07:49 +00:00
Matthew Russellandmaciek 5f7e60d22f chore(orders): update orders filters (#3277)
Co-authored-by: maciek <maciek@vegaprotocol.io>
2023-03-29 13:12:29 +02:00
Joe Tsang 351583ce8f chore(cypress): fix error seen in CI for staking test (#3304) 2023-03-29 11:52:46 +01:00
Maciek 88bf58b974 chore(trading): remove files of envs to kill (#3303) 2023-03-29 10:57:33 +01:00
Maciek fcda4d7fcd chore(wallet,positions): use reduceOnly and IOC order for close position tx (#3263) 2023-03-28 23:50:11 -07:00
dexturr b1b0039b33 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-29 06:08:40 +00:00
Art 6854980b32 fix(trading): volumes formatting (#3293) 2023-03-28 22:12:52 -07:00
dexturr d8aac83f2d chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-03-29 00:18:30 +00:00
Sam Keen 5c17045752 fix(governance): paginate rewards as well as delegations data (#3288) 2023-03-28 20:35:29 +01:00
Bartłomiej Głownia 8863209342 feat(trading): persist state of chart intervals studies and overlays (#3261) 2023-03-28 21:03:53 +02:00
Joe Tsang 462bf6b8b5 test(governance): my stake e2e tests (#3295) 2023-03-28 19:03:58 +01:00
305 changed files with 10260 additions and 6304 deletions
+3 -4
View File
@@ -1,15 +1,14 @@
---
name: Release
about:
A template to outline the steps needed to for a successful release of our frontend apps
about: A template to outline the steps needed to for a successful release of our frontend apps
title: 'Release [add dapp version]-core-[add core version]'
labels:
labels:
assignees: ''
---
### Tasks
- [ ] Review [link to core release](xxx)
- [ ] Review [link to core release](xxx)
- [ ] Tag frontend-monorepo
- [ ] Create release and generate release notes
- [ ] Run `@smoke` tests
+1 -1
View File
@@ -13,7 +13,7 @@ env:
jobs:
add_issue:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: 'Add issue to project board'
run: |
+190
View File
@@ -0,0 +1,190 @@
name: CI/CD
on:
push:
branches:
- release/*
- develop
pull_request:
types:
- opened
- ready_for_review
- reopened
- edited
- synchronize
jobs:
node-modules:
runs-on: ubuntu-22.04
name: 'Cache yarn modules'
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Cache node modules
id: cache
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
# comment out "resotre-keys" if you need to rebuild yarn from 0
restore-keys: |
${{ runner.os }}-cache-node-modules-
- name: Setup node
uses: actions/setup-node@v3
if: steps.cache.outputs.cache-hit != 'true'
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
- name: yarn install
if: steps.cache.outputs.cache-hit != 'true'
run: yarn install --pure-lockfile
lint-pr-title:
needs: node-modules
if: ${{ github.event_name == 'pull_request' }}
name: Verify PR title
uses: ./.github/workflows/lint-pr.yml
secrets: inherit
lint-test-build:
timeout-minutes: 20
needs: node-modules
runs-on: ubuntu-22.04
name: '(CI) lint + unit test + build'
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Setup node
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
- name: Cache node modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
- name: Derive appropriate SHAs for base and head for `nx affected` commands
uses: nrwl/nx-set-shas@v3
with:
main-branch-name: develop
- name: Check formatting
run: yarn nx format:check
- name: Lint affected
run: yarn nx affected:lint --max-warnings=0
- name: Build affected spec
run: yarn nx affected --target=build-spec
- name: Test affected
run: yarn nx affected:test
- name: Build affected
run: yarn nx affected:build || (yarn install && yarn nx affected:build)
# See affected apps
- name: See affected apps
run: |
echo ">>>> debug"
echo "NX Version: $nx_version"
echo "NX_BASE: ${{ env.NX_BASE }}"
echo "NX_HEAD: ${{ env.NX_HEAD }}"
echo ">>>> eof debug"
affected="$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)"
echo -n "Affected projects: $affected"
projects_e2e=""
if [[ $affected == *"governance"* ]]; then projects_e2e+='"governance-e2e" '; fi
if [[ $affected == *"trading"* ]]; then projects_e2e+='"trading-e2e" '; fi
if [[ $affected == *"explorer"* ]]; then projects_e2e+='"explorer-e2e" '; fi
if [[ -z "$projects_e2e" ]]; then projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" '; fi
projects_e2e=${projects_e2e%?}
projects_e2e=[${projects_e2e// /,}]
echo PROJECTS_E2E=$projects_e2e >> $GITHUB_ENV
echo PROJECTS=$(echo $projects_e2e | sed 's|-e2e||g') >> $GITHUB_ENV
outputs:
projects: ${{ env.PROJECTS }}
projects-e2e: ${{ env.PROJECTS_E2E }}
cypress:
needs: lint-test-build
name: '(CI) cypress'
if: ${{ needs.lint-test-build.outputs.projects != '[]' }}
uses: ./.github/workflows/cypress-run.yml
secrets: inherit
with:
projects: ${{ needs.lint-test-build.outputs.projects-e2e }}
tags: '@smoke @regression'
publish-dist:
needs: lint-test-build
name: '(CD) publish dist'
if: ${{ needs.lint-test-build.outputs.projects != '[]' }}
uses: ./.github/workflows/publish-dist.yml
secrets: inherit
with:
projects: ${{ needs.lint-test-build.outputs.projects }}
dist-check:
runs-on: ubuntu-latest
needs: publish-dist
if: ${{ github.event_name == 'pull_request' }}
name: '(CD) comment preview links'
steps:
- name: Find Comment
uses: peter-evans/find-comment@v2
id: fc
with:
issue-number: ${{ github.event.pull_request.number }}
body-includes: Previews
- name: Inject slug/short variables
if: ${{ steps.fc.outputs.comment-id == 0 }}
uses: rlespinasse/github-slug-action@v4
with:
prefix: CI_
- name: Create comment
if: ${{ steps.fc.outputs.comment-id == 0 }}
uses: peter-evans/create-or-update-comment@v3
with:
issue-number: ${{ github.event.pull_request.number }}
body: |
Previews
- explorer https://explorer.${{ env.CI_GITHUB_REF_NAME }}.vega.rocks
- trading https://trading.${{ env.CI_GITHUB_REF_NAME }}.vega.rocks
- governance https://governance.${{ env.CI_GITHUB_REF_NAME }}.vega.rocks
cypress-check:
name: '(CI) cypress - check'
runs-on: ubuntu-latest
needs: cypress
steps:
- run: echo Done!
# Report single result at the end, to avoid mess with required checks in PR
cypress-result:
if: ${{ always() }}
needs: cypress
runs-on: ubuntu-22.04
steps:
- run: |
result="${{ needs.cypress.result }}"
if [[ $result == "success" || $result == "skipped" ]]; then
exit 0
else
exit 1
fi
+1 -1
View File
@@ -13,7 +13,7 @@ on:
jobs:
cypress-run:
name: Run Cypress Trading tests -- live environment
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v2
+15 -3
View File
@@ -1,4 +1,4 @@
name: Cypress Run
name: (CI) Cypress Run
on:
workflow_call:
inputs:
@@ -72,6 +72,18 @@ jobs:
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
CYPRESS_VEGA_WALLET_API_TOKEN: ${{ steps.setup-vega.outputs.token }}
######
## Show test summary on github page
######
- name: Show test summary
if: success() || failure()
uses: dorny/test-reporter@v1
with:
name: UI Tests
path: mochawesome.json
reporter: mocha-json
######
## Upload logs
######
@@ -91,5 +103,5 @@ jobs:
- uses: actions/upload-artifact@v3
if: ${{ failure() }}
with:
name: logs-${{ matrix.project }}
path: /home/runner/.vegacapsule/testnet/logs
name: test-report
path: frontend-monorepo/apps/trading-e2e/reports
+12 -9
View File
@@ -8,22 +8,25 @@ on:
jobs:
master:
name: Generate Queries
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
- name: Setup node
uses: actions/setup-node@v3
with:
fetch-depth: 0
- name: Use Node.js 16
id: Node
uses: actions/setup-node@v2
with:
node-version: 16.15.1
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
- name: Install root dependencies
run: yarn install
run: yarn install --frozen-lockfile
- name: Generate queries
run: node ./scripts/get-queries.js
- uses: actions/upload-artifact@v2
with:
name: queries
+29
View File
@@ -0,0 +1,29 @@
---
name: Verify PR title
on:
workflow_call:
jobs:
lint_pr:
timeout-minutes: 10
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup node
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
- name: Cache node modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
- name: Check PR title
run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js
-23
View File
@@ -1,23 +0,0 @@
---
name: Verify PR title
on:
pull_request:
types: [opened, ready_for_review, reopened, edited, synchronize]
jobs:
lint_pr:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Use Node.js 16
id: Node
uses: actions/setup-node@v2
with:
node-version: 16.15.1
- name: Install root dependencies
run: yarn install
- name: Check PR title
run: echo "${{ github.event.pull_request.title }}" | npx commitlint --config ./commitlint.config-ci.js
-93
View File
@@ -1,93 +0,0 @@
name: PR Validations
on:
push:
branches:
- develop
- main
pull_request:
types:
- opened
- reopened
- synchronize
- ready_for_review
jobs:
pr:
runs-on: ubuntu-latest
steps:
- name: Checkout frontend mono repo
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Check node version
id: node-version
run: |
npmVersion=$(cat .nvmrc | head -n 1)
echo ::set-output name=npmVersion::${npmVersion}
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: ${{ steps.node-version.outputs.npmVersion }}
# Check SHAs
- name: Derive appropriate SHAs for base and head for `nx affected` commands
uses: nrwl/nx-set-shas@v2
with:
main-branch-name: ${{ github.base_ref || github.ref_name }}
set-environment-variables-for-job: true
# See affected apps
- name: See affected apps
run: |
nx_version=$(cat package.json | grep '"nx"' | cut -d ':' -f 2 | tr -d '",[:space:]')
rm package.json yarn.lock
yarn add nx@$nx_version
affected=$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)
echo -n "Affected projects: $affected"
projects_e2e=""
if [[ $affected == *"governance"* ]]; then projects_e2e+='"governance-e2e" '; fi
if [[ $affected == *"trading"* ]]; then projects_e2e+='"trading-e2e" '; fi
if [[ $affected == *"explorer"* ]]; then projects_e2e+='"explorer-e2e" '; fi
if [[ -z "$projects_e2e" ]]; then projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" '; fi
projects_e2e=${projects_e2e%?}
projects_e2e=[${projects_e2e// /,}]
echo PROJECTS_E2E=$projects_e2e >> $GITHUB_ENV
echo PROJECTS=$(echo $projects_e2e | sed 's|-e2e||g') >> $GITHUB_ENV
outputs:
projects: ${{ env.PROJECTS }}
projects-e2e: ${{ env.PROJECTS_E2E }}
run-cypress:
needs: pr
if: ${{ needs.pr.outputs.projects != '[]' }}
uses: ./.github/workflows/cypress-run.yml
secrets: inherit
with:
projects: ${{ needs.pr.outputs.projects-e2e }}
tags: '@smoke @regression'
run-docker-build:
needs: pr
if: ${{ needs.pr.outputs.projects != '[]' }}
uses: ./.github/workflows/publish-docker-containers.yml
secrets: inherit
with:
projects: ${{ needs.pr.outputs.projects }}
# Report single result at the end, to avoid mess with required checks in PR
result:
if: ${{ always() }}
needs: run-cypress
runs-on: ubuntu-latest
name: Cypress result
steps:
- run: |
result="${{ needs.run-cypress.result }}"
if [[ $result == "success" || $result == "skipped" ]]; then
exit 0
else
exit 1
fi
+1 -1
View File
@@ -7,7 +7,7 @@ on:
jobs:
master:
name: Generate Queries
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- name: Checkout
+171
View File
@@ -0,0 +1,171 @@
name: (CD) Publish docker + s3
on:
workflow_call:
inputs:
projects:
required: true
type: string
jobs:
publish-dist:
strategy:
fail-fast: false
matrix:
app: ${{ fromJSON(inputs.projects) }}
name: ${{ matrix.app }}
runs-on: ubuntu-22.04
timeout-minutes: 20
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up QEMU
id: quemu
uses: docker/setup-qemu-action@v2
- name: Available platforms
run: echo ${{ steps.qemu.outputs.platforms }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Setup node
uses: actions/setup-node@v3
with:
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
- name: Cache node modules
uses: actions/cache@v3
with:
path: node_modules
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
# https://docs.github.com/en/actions/learn-github-actions/contexts
- name: Define variables
run: |
envName=''
dockerfile="dist.Dockerfile"
if [[ "${{ github.event_name }}" = "push" ]]; then
domain="vega.rocks"
if [[ "${{ github.ref }}" =~ .*release/.* ]]; then
envName="$(echo ${{ github.ref }} | rev | cut -d '/' -f 1 | rev)"
if [[ "${{ github.ref }}" =~ .*mainnet.* ]]; then
domain="vega.community"
if [[ "${{ matrix.app }}" = "trading" ]]; then
dockerfile="ipfs.Dockerfile"
fi
fi
elif [[ "${{ github.ref }}" =~ .*develop$ ]]; then
envName="stagnet3"
fi
bucketName="${{ matrix.app }}.${envName}.${domain}"
echo BUCKET_NAME=${bucketName} >> $GITHUB_ENV
fi
nodeVersion=$(cat .nvmrc | head -n 1)
echo ENV_NAME=${envName} >> $GITHUB_ENV
echo NODE_VERSION=${nodeVersion} >> $GITHUB_ENV
echo DOCKERFILE=docker/${dockerfile} >> $GITHUB_ENV
- name: Build local dist
if: ${{ env.DOCKERFILE != 'docker/ipfs.Dockerfile' }}
run: |
flags=""
if [[ ! -z "${{ env.ENV_NAME }}" ]]; then
if [[ "${{ env.ENV_NAME }}" != "ops-vega" ]]; then
flags="--env=${{ env.ENV_NAME }}"
fi
fi
if [ "${{ matrix.app }}" = "trading" ]; then
yarn nx export trading $flags || (yarn install && yarn nx export trading $flags)
DIST_LOCATION=dist/apps/trading/exported
else
yarn nx build ${{ matrix.app }} $flags || (yarn install && yarn nx build ${{ matrix.app }} $flags)
DIST_LOCATION=dist/apps/${{ matrix.app }}
fi
mv $DIST_LOCATION dist-result
tree dist-result
- name: Build and export to local Docker
id: docker_build
if: ${{ github.event_name == 'pull_request' || ( env.DOCKERFILE == 'docker/ipfs.Dockerfile' && github.event_name == 'push' ) }}
uses: docker/build-push-action@v3
with:
context: .
file: ${{ env.DOCKERFILE }}
load: true
build-args: |
APP=${{ matrix.app }}
NODE_VERSION=${{ env.NODE_VERSION }}
ENV_NAME=${{ env.ENV_NAME }}
tags: |
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
- name: Image digest
if: ${{ github.event_name == 'pull_request' || ( env.DOCKERFILE == 'docker/ipfs.Dockerfile' && github.event_name == 'push' ) }}
run: echo ${{ steps.docker_build.outputs.digest }}
- name: Sanity check docker image
if: ${{ github.event_name == 'pull_request' || ( env.DOCKERFILE == 'docker/ipfs.Dockerfile' && github.event_name == 'push' ) }}
run: |
echo "Check ipfs-hash"
if [[ "${{ env.DOCKERFILE }}" = "docker/ipfs.Dockerfile" ]]; then
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash
fi
echo "List html directory"
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local sh -c 'apk add --update tree; tree .'
- name: Copy dist to local filesystem
if: ${{ env.DOCKERFILE == 'docker/ipfs.Dockerfile' && github.event_name == 'push' }}
run: |
docker create --name=dist ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
docker cp dist:/usr/share/nginx/html dist
echo "check local dist files"
tree dist/html
mv dist/html dist-result
- name: Publish dist as docker image
uses: docker/build-push-action@v3
if: ${{ github.event_name == 'pull_request' }}
with:
context: .
file: ${{ env.DOCKERFILE }}
push: true
build-args: |
APP=${{ matrix.app }}
NODE_VERSION=${{ env.NODE_VERSION }}
ENV_NAME=${{ env.ENV_NAME }}
tags: |
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:${{ github.event.pull_request.head.sha || github.sha }}
# bucket creation in github.com/vegaprotocol/terraform//frontend
- name: Publish dist to s3
uses: jakejarvis/s3-sync-action@master
if: ${{ github.event_name == 'push' }}
with:
args: --acl private --follow-symlinks --delete
env:
AWS_S3_BUCKET: ${{ env.BUCKET_NAME }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
AWS_REGION: 'eu-west-1'
SOURCE_DIR: 'dist-result'
- name: Add preview label
uses: actions-ecosystem/action-add-labels@v1
if: ${{ github.event_name == 'pull_request' }}
with:
labels: ${{ matrix.app }}-preview
number: ${{ github.event.number }}
@@ -1,94 +0,0 @@
name: Docker build
on:
workflow_call:
inputs:
projects:
required: true
type: string
jobs:
master:
strategy:
fail-fast: false
matrix:
app: ${{ fromJSON(inputs.projects) }}
name: ${{ matrix.app }}
runs-on: ubuntu-latest
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Set up QEMU
id: quemu
uses: docker/setup-qemu-action@v2
- name: Available platforms
run: echo ${{ steps.qemu.outputs.platforms }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
# https://docs.github.com/en/actions/learn-github-actions/contexts
# https://github.com/actions/checkout#Checkout-pull-request-HEAD-commit-instead-of-merge-commit
- name: Determine Docker Image tag
id: tags
run: |
npmVersion=$(cat .nvmrc | head -n 1)
versionTag=${{ startsWith(github.ref, 'refs/tags/') && github.ref_name || github.event.pull_request.head.sha }}
echo ::set-output name=npmVersion::${npmVersion}
echo ::set-output name=version::${versionTag}
- name: Print config
run: |
git rev-parse --verify HEAD
git status
echo "steps.tags.outputs.version=${{ steps.tags.outputs.version }}"
- name: Build and export to local Docker
uses: docker/build-push-action@v3
with:
load: true
build-args: |
APP=${{ matrix.app }}
NODE_VERSION=${{ steps.tags.outputs.npmVersion }}
tags: |
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
- name: Sanity check docker image
run: |
echo "Check .env file"
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat .env
echo "Check ipfs-hash"
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat ipfs-hash
echo "List html directory"
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local ls -lah
- name: Log in to the Container registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
id: docker_build
uses: docker/build-push-action@v3
with:
push: true
build-args: |
APP=${{ matrix.app }}
NODE_VERSION=${{ steps.tags.outputs.npmVersion }}
tags: |
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:latest
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:${{ steps.tags.outputs.version }}
- name: Add preview label
uses: actions-ecosystem/action-add-labels@v1
if: ${{ github.event_name == 'pull_request' }}
with:
labels: ${{ matrix.app }}-preview
number: ${{ github.event.number }}
- name: Image digest
run: echo ${{ steps.docker_build.outputs.digest }}
+10 -11
View File
@@ -8,6 +8,7 @@ on:
required: true
type: choice
options:
- announcements
- ui-toolkit
- react-helpers
- tailwindcss-config
@@ -18,29 +19,27 @@ on:
jobs:
publish:
name: Build & Publish - Tag
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
permissions:
contents: 'read'
actions: 'read'
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: User Node.js 16
id: Node
- name: Setup node
uses: actions/setup-node@v3
with:
node-version: 16.15.1
- name: Restore node_modules from cache
uses: actions/cache@v3
with:
path: '**/node_modules'
key: node_modules-${{ hashFiles('**/yarn.lock') }}
node-version-file: '.nvmrc'
# https://stackoverflow.com/questions/61010294/how-to-cache-yarn-packages-in-github-actions
cache: yarn
- name: Install root dependencies
run: yarn install --frozen-lockfile
- name: Build project
run: yarn nx build ${{inputs.project}}
- name: Publish project to @vegaprotocol
uses: JS-DevTools/npm-publish@v1
with:
-46
View File
@@ -1,46 +0,0 @@
name: Unit tests & build
on:
push:
branches:
- develop
- main
pull_request:
jobs:
pr:
name: Test and lint - PR
runs-on: ubuntu-latest
permissions:
contents: 'read'
actions: 'read'
steps:
- name: Checkout
uses: actions/checkout@v3
with:
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: ${{ github.base_ref }}
- name: Use Node.js 16
id: Node
uses: actions/setup-node@v3
with:
node-version: 16.15.1
- name: Restore node_modules from cache
uses: actions/cache@v3
with:
path: '**/node_modules'
key: node_modules-${{ hashFiles('**/yarn.lock') }}
- name: Install root dependencies
run: yarn install --frozen-lockfile
- 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
- name: Build affected spec
run: yarn nx affected --target=build-spec
+3
View File
@@ -46,3 +46,6 @@ cypress.env.json
# Next.js
.next
#cypress
/apps/trading-e2e/cypress/reports/html
+1 -1
View File
@@ -1,7 +1,7 @@
NX_TENDERMINT_URL=https://tm.n00.stagnet3.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n00.stagnet3.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet3/vegawallet-stagnet3.toml
NX_VEGA_NETWORKS='{"SANDBOX":"https://sandbox.explorer.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz", "STAGNET3":"https://stagnet3.explorer.vega.xyz","VALIDATOR_TESTNET":"https://validator-testnet.fairground.wtf","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_NETWORKS='{"STAGNET1":"https://stagnet1.token.vega.xyz", "STAGNET3":"https://stagnet3.explorer.vega.xyz","VALIDATOR_TESTNET":"https://validator-testnet.fairground.wtf","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_ENV=STAGNET3
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
+1
View File
@@ -3,6 +3,7 @@ NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_ENV=CUSTOM
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
# App flags
NX_EXPLORER_ASSETS=1
+1
View File
@@ -8,3 +8,4 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://dev.token.vega.xyz
NX_VEGA_URL=https://api.devnet1.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+1
View File
@@ -6,3 +6,4 @@ NX_VEGA_ENV=MAINNET
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest/
NX_ETHERSCAN_URL=https://etherscan.io
NX_VEGA_GOVERNANCE_URL=https://token.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
-19
View File
@@ -1,19 +0,0 @@
# App configuration variables
NX_TENDERMINT_URL=https://tm.be.mainnet-mirror.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.mainnet-mirror.vega.xyz/websocket
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
NX_VEGA_ENV=MIRROR
NX_BLOCK_EXPLORER=https://be.mainnet-mirror.vega.xyz/rest/
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://mainnet-mirror.token.vega.xyz
# App flags
NX_EXPLORER_ASSETS=1
NX_EXPLORER_GENESIS=1
NX_EXPLORER_GOVERNANCE=1
NX_EXPLORER_NETWORK_PARAMETERS=1
NX_EXPLORER_PARTIES=1
NX_EXPLORER_VALIDATORS=1
NX_EXPLORER_MARKETS=0
NX_EXPLORER_ORACLES=0
NX_EXPLORER_TXS_LIST=1
-11
View File
@@ -1,11 +0,0 @@
# App configuration variables
NX_VEGA_ENV=SANDBOX
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_TENDERMINT_URL=https://tm.sandbox.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://be.sandbox.vega.xyz/websocket
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://sandbox.token.vega.xyz
+1
View File
@@ -11,3 +11,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://stagnet1.token.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+1
View File
@@ -5,3 +5,4 @@ NX_VEGA_ENV=STAGNET3
NX_BLOCK_EXPLORER=https://be.stagnet3.vega.xyz/rest
NX_VEGA_GOVERNANCE_URL=https://stagnet3.token.vega.xyz
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega-dev-releases/releases/
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+1
View File
@@ -8,3 +8,4 @@ NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://token.fairground.wtf
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+2 -1
View File
@@ -5,8 +5,9 @@ NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
NX_VEGA_REST=https://api-validators-testnet.vega.rocks/
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_GOVERNANCE_URL=https://validator-testnet.governance.vega.xyz
NX_TENDERMINT_URL=https://tm-be.validators-testnet.vega.rocks
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/
NX_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/rest
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
+1
View File
@@ -4,3 +4,4 @@ NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26607/websocket
NX_VEGA_ENV=CUSTOM
NX_BLOCK_EXPLORER=
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
@@ -10,7 +10,7 @@ export const Footer = () => {
const [nodeSwitcherOpen, setNodeSwitcherOpen] = useState(false);
const { screenSize } = useScreenDimensions();
const showFullFeedbackLabel = useMemo(
() => ['lg', 'xl', 'xxl', 'xxxl'].includes(screenSize),
() => ['md', 'lg', 'xl', 'xxl', 'xxxl'].includes(screenSize),
[screenSize]
);
+15 -36
View File
@@ -3,16 +3,14 @@ import {
useAssetDetailsDialogStore,
} from '@vegaprotocol/assets';
import { t } from '@vegaprotocol/i18n';
import { useEnvironment } from '@vegaprotocol/environment';
import { AnnouncementBanner } from '@vegaprotocol/announcements';
import {
AnnouncementBanner,
BackgroundVideo,
BreadcrumbsContainer,
ButtonLink,
ExternalLink,
Icon,
} from '@vegaprotocol/ui-toolkit';
import classNames from 'classnames';
import { useState } from 'react';
import {
isRouteErrorResponse,
Link,
@@ -37,58 +35,39 @@ const DialogsContainer = () => {
);
};
const MainnetSimAd = () => {
const [shouldDisplayBanner, setShouldDisplayBanner] = useState<boolean>(true);
// Return an empty div so that the grid layout in _app.page.ts
// renders correctly
if (!shouldDisplayBanner) {
return <div />;
}
return (
<AnnouncementBanner>
<div className="grid grid-cols-[auto_1fr] gap-4 font-alpha calt uppercase text-center text-lg text-white">
<button
className="flex items-center"
onClick={() => setShouldDisplayBanner(false)}
>
<Icon name="cross" className="w-6 h-6" ariaLabel="dismiss" />
</button>
<div>
<span className="pr-4">Mainnet sim 3 is live!</span>
<ExternalLink href="https://fairground.wtf/">Learn more</ExternalLink>
</div>
</div>
</AnnouncementBanner>
);
};
export const Layout = () => {
const isHome = Boolean(useMatch(Routes.HOME));
const { ANNOUNCEMENTS_CONFIG_URL } = useEnvironment();
const fixedWidthClasses = 'w-full max-w-[1500px] mx-auto';
return (
<>
<div
className={classNames(
'max-w-[1500px] min-h-[100vh]',
'min-h-screen',
'mx-auto my-0',
'grid grid-rows-[auto_1fr_auto] grid-cols-1',
'border-vega-light-200 dark:border-vega-dark-200 lg:border-l lg:border-r',
'border-vega-light-200 dark:border-vega-dark-200',
'antialiased text-black dark:text-white',
'overflow-hidden relative'
)}
>
<div>
<MainnetSimAd />
{ANNOUNCEMENTS_CONFIG_URL && (
<AnnouncementBanner
app="explorer"
configUrl={ANNOUNCEMENTS_CONFIG_URL}
/>
)}
<Header />
</div>
<div>
<div className={fixedWidthClasses}>
<main className="p-4">
{!isHome && <BreadcrumbsContainer className="mb-4" />}
<Outlet />
</main>
</div>
<div>
<div className={fixedWidthClasses}>
<Footer />
</div>
</div>
+2
View File
@@ -13,6 +13,8 @@ NX_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
#Test configuration variables
CYPRESS_FAIRGROUND=false
@@ -44,7 +44,8 @@ describe(
function () {
before('connect wallets and set approval limit', function () {
cy.visit('/');
vegaWalletSetSpecifiedApprovalAmount('1000');
ethereumWalletConnect();
cy.associateTokensToVegaWallet('1');
});
beforeEach('visit proposals tab', function () {
@@ -56,7 +57,7 @@ describe(
navigateTo(navigation.proposals);
});
// 3001-VOTE-055
// 3001-VOTE-050 3001-VOTE-054 3001-VOTE-055 3002-PROP-019
it('Newly created raw proposal details - shows proposal title and full description', function () {
createRawProposal();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
@@ -213,6 +214,7 @@ describe(
// 3001-VOTE-042, 3001-VOTE-057, 3001-VOTE-058, 3001-VOTE-059, 3001-VOTE-060
it('Newly created proposal details - ability to increase associated tokens - by voting again after association', function () {
vegaWalletSetSpecifiedApprovalAmount('1000');
createRawProposal();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(rawProposal.rationale.title)
@@ -13,7 +13,6 @@ import {
createUpdateNetworkProposalTxBody,
createFreeFormProposalTxBody,
} from '../../support/proposal.functions';
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/staking.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions';
@@ -33,10 +32,6 @@ context(
before('Connect wallets and set approval', function () {
cy.visit('/');
vegaWalletSetSpecifiedApprovalAmount('1000');
cy.connectVegaWallet();
ethereumWalletConnect();
ensureSpecifiedUnstakedTokensAreAssociated('1');
cy.clearLocalStorage();
});
beforeEach('visit proposals', function () {
@@ -114,7 +109,7 @@ context(
navigateTo(navigation.proposals);
cy.reload();
waitForSpinner();
cy.get(openProposals).within(() => {
cy.get(openProposals, { timeout: 6000 }).within(() => {
cy.contains(proposalTitle)
.parentsUntil('[data-testid="proposals-list-item"]')
.within(() => cy.get(viewProposalButton).click());
@@ -128,7 +123,7 @@ context(
.and('be.visible');
});
// 3001-VOTE-048 3001-VOTE-049
// 3001-VOTE-048 3001-VOTE-049 3001-VOTE-050
it('Able to fail proposal due to lack of participation', function () {
const proposalTitle = 'Add New free form proposal with short enactment';
const proposalTx = createFreeFormProposalTxBody();
@@ -19,6 +19,7 @@ import {
waitForSpinner,
navigateTo,
navigation,
closeDialog,
} from '../../support/common.functions';
import {
clickOnValidatorFromList,
@@ -41,7 +42,6 @@ const vegaWalletNameElement = '[data-testid="wallet-name"]';
const vegaWallet = '[data-testid="vega-wallet"]';
const connectToVegaWalletButton = '[data-testid="connect-to-vega-wallet-btn"]';
const newProposalSubmitButton = '[data-testid="proposal-submit"]';
const dialogCloseButton = '[data-testid="dialog-close"]';
const viewProposalButton = '[data-testid="view-proposal-btn"]';
const rawProposalData = '[data-testid="proposal-data"]';
const minVoteButton = '[data-testid="min-vote"]';
@@ -177,7 +177,7 @@ context(
'be.visible'
);
cy.contains('Proposal rejected', proposalTimeout).should('be.visible');
cy.get(dialogCloseButton).click();
closeDialog();
waitForProposalSync();
navigateTo(navigation.proposals);
cy.get(rejectProposalsLink).click();
@@ -214,7 +214,7 @@ context(
enterRawProposalBody(createTenDigitUnixTimeStampForSpecifiedDays(8));
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
cy.get(feedbackError).should('have.text', errorMsg);
cy.get(dialogCloseButton).click();
closeDialog();
});
// 3002-PROP-009
@@ -227,12 +227,12 @@ context(
enterRawProposalBody(createTenDigitUnixTimeStampForSpecifiedDays(8));
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
cy.get(feedbackError).should('have.text', errorMsg);
cy.get(dialogCloseButton).click();
closeDialog();
});
it('Unable to create a freeform proposal - when json parent section contains unexpected field', function () {
const errorMsg =
'Invalid params: the transaction does not use a valid Vega command: unknown field unexpected" in vega.commands.v1.ProposalSubmission';
'Invalid params: the transaction does not use a valid Vega command: unknown field "unexpected" in vega.commands.v1.ProposalSubmission';
// 3001-VOTE-038 3002-PROP-013 3002-PROP-014
goToMakeNewProposal(governanceProposalType.RAW);
@@ -251,7 +251,7 @@ context(
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
cy.get(feedbackError).should('have.text', errorMsg);
cy.get(dialogCloseButton).click();
closeDialog();
cy.get(rawProposalData)
.invoke('val')
.should('contain', "i shouldn't be here");
@@ -279,7 +279,7 @@ context(
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
cy.get(feedbackError).should('have.text', errorMsg);
cy.get(dialogCloseButton).click();
closeDialog();
});
// 1005-PROP-009
@@ -313,7 +313,7 @@ context(
it('Unable to vote on a proposal - when vega wallet disconnected - option to connect from within', function () {
createRawProposal();
cy.get('[data-testid="manage-vega-wallet"]').click();
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
cy.get('[data-testid="disconnect"]').click();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(
@@ -1,4 +1,5 @@
import {
closeDialog,
navigateTo,
navigation,
waitForSpinner,
@@ -39,7 +40,6 @@ const maxVoteDeadline = '[data-testid="max-vote"]';
const minValidationDeadline = '[data-testid="min-validation"]';
const minEnactDeadline = '[data-testid="min-enactment"]';
const maxEnactDeadline = '[data-testid="max-enactment"]';
const dialogCloseButton = '[data-testid="dialog-close"]';
const inputError = '[data-testid="input-error-text"]';
const enactmentDeadlineError =
'[data-testid="enactment-before-voting-deadline"]';
@@ -48,6 +48,7 @@ const feedbackError = '[data-testid="Error"]';
const viewProposalBtn = 'view-proposal-btn';
const liquidityVoteStatus = 'liquidity-votes-status';
const tokenVoteStatus = 'token-votes-status';
const proposalTermsSection = 'proposal';
const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey');
const epochTimeout = Cypress.env('epochTimeout');
const proposalTimeout = { timeout: 14000 };
@@ -68,7 +69,6 @@ context(
{ tags: '@slow' },
function () {
before('connect wallets and set approval limit', function () {
cy.createMarket();
cy.visit('/');
vegaWalletSetSpecifiedApprovalAmount('1000');
});
@@ -78,6 +78,7 @@ context(
waitForSpinner();
cy.connectVegaWallet();
ethereumWalletConnect();
cy.createMarket();
ensureSpecifiedUnstakedTokensAreAssociated('1');
navigateTo(navigation.proposals);
});
@@ -194,7 +195,7 @@ context(
'have.text',
'Invalid params: proposal_submission.terms.closing_timestamp (cannot be after enactment time)'
);
cy.get(dialogCloseButton).click();
closeDialog();
cy.get(minVoteDeadline).click();
cy.get(enactmentDeadlineError).should('not.exist');
});
@@ -217,7 +218,7 @@ context(
it('Unable to submit new market proposal with missing/invalid fields', function () {
const errorMsg =
'Invalid params: the transaction is not a valid Vega command: unknown field "filters" in vega.DataSourceDefinition';
'Invalid params: the transaction does not use a valid Vega command: unknown field "invalid" in vega.NewMarket';
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
cy.get(newProposalSubmitButton).should('be.visible').click();
@@ -286,7 +287,7 @@ context(
);
});
// 3001-VOTE-092
// 3001-VOTE-092 3004-PMAC-001
it('Able to submit update market proposal and vote for proposal', function () {
vegaWalletFaucetAssetsWithoutCheck(
'fUSDC',
@@ -347,8 +348,9 @@ context(
// 3001-VOTE-026 3001-VOTE-027 3001-VOTE-028 3001-VOTE-095 3001-VOTE-096 3005-PASN-001
it('Able to submit new asset proposal using min deadlines', function () {
const proposalTitle = 'Test new asset proposal';
goToMakeNewProposal(governanceProposalType.NEW_ASSET);
cy.get(newProposalTitle).type('Test new asset proposal');
cy.get(newProposalTitle).type(proposalTitle);
cy.get(newProposalDescription).type('E2E test for proposals');
cy.fixture('/proposals/new-asset').then((newAssetProposal) => {
const newAssetPayload = JSON.stringify(newAssetProposal);
@@ -367,7 +369,7 @@ context(
cy.contains('Proposal waiting for node vote', proposalTimeout).should(
'be.visible'
);
cy.get(dialogCloseButton).click();
closeDialog();
cy.get(newProposalSubmitButton).should('be.visible').click();
// cannot submit a proposal with ERC20 address already in use
cy.contains('Proposal rejected', proposalTimeout).should('be.visible');
@@ -377,6 +379,17 @@ context(
'PROPOSAL_ERROR_ERC20_ADDRESS_ALREADY_IN_USE'
);
});
closeDialog();
navigateTo(navigation.proposals);
cy.contains(proposalTitle)
.parentsUntil(proposalListItem)
.within(() => {
cy.getByTestId(viewProposalBtn).click();
});
cy.getByTestId(proposalTermsSection).within(() => {
cy.contains('USDT Coin').should('be.visible');
cy.contains('USDT').should('be.visible');
});
});
it('Unable to submit new asset proposal with missing/invalid fields', function () {
@@ -415,6 +428,12 @@ context(
getProposalInformationFromTable('Proposed enactment') // 3001-VOTE-044
.invoke('text')
.should('not.be.empty');
// 3001-VOTE-030 3001-VOTE-031
cy.getByTestId(proposalTermsSection).within(() => {
cy.contains('UpdateAsset').should('be.visible');
cy.contains('UpdateERC20').should('be.visible');
cy.contains('"lifetimeLimit": "10"').should('be.visible');
});
});
it('Able to submit update asset proposal using max deadline', function () {
@@ -25,22 +25,24 @@ import {
vegaWalletSetSpecifiedApprovalAmount,
vegaWalletTeardown,
} from '../../support/wallet-teardown.functions';
const stakeValidatorListTotalStake = '[col-id="stake"] > div > span';
const stakeValidatorListTotalShare = '[col-id="stakeShare"] > div > span';
const stakeValidatorListValidatorStake = '[col-id="stake"] > div > span';
const stakeRemoveStakeRadioButton = '[data-testid="remove-stake-radio"]';
const stakeTokenAmountInputBox = '[data-testid="token-amount-input"]';
const stakeTokenSubmitButton = '[data-testid="token-input-submit-button"]';
const stakeAddStakeRadioButton = '[data-testid="add-stake-radio"]';
const stakeMaximumTokens = '[data-testid="token-amount-use-maximum"]';
const totalStake = '[data-testid="total-stake"]';
const stakeShare = '[data-testid="stake-percentage"]';
const stakeValidatorListTotalStake = 'total-stake';
const stakeValidatorListTotalShare = 'total-stake-share';
const stakeValidatorListStakePercentage = 'stake-percentage';
const userStakeBtn = 'my-stake-btn';
const userStake = 'user-stake';
const userStakeShare = 'user-stake-share';
const viewAllValidatorsToggle = 'validators-view-toggle-all';
const viewStakedByMeToggle = 'validators-view-toggle-myStake';
const stakeRemoveStakeRadioButton = 'remove-stake-radio';
const stakeTokenAmountInputBox = 'token-amount-input';
const stakeTokenSubmitButton = 'token-input-submit-button';
const stakeAddStakeRadioButton = 'add-stake-radio';
const stakeMaximumTokens = 'token-amount-use-maximum';
const vegaWalletAssociatedBalance = 'currency-value';
const vegaWalletStakedBalances = 'vega-wallet-balance-staked-validators';
const ethWalletContainer = 'ethereum-wallet';
const vegaWallet = 'vega-wallet';
const vegaWalletPublicKeyShort = Cypress.env('vegaWalletPublicKeyShort');
const vegaWalletAssociatedBalance = '[data-testid="currency-value"]';
const vegaWalletStakedBalances =
'[data-testid="vega-wallet-balance-staked-validators"]';
const ethWalletContainer = '[data-testid="ethereum-wallet"]';
const vegaWallet = '[data-testid="vega-wallet"]';
const txTimeout = Cypress.env('txTimeout');
const epochTimeout = Cypress.env('epochTimeout');
@@ -91,6 +93,39 @@ context(
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
});
it('Able to view validators staked by me', function () {
ensureSpecifiedUnstakedTokensAreAssociated('4');
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('2');
closeStakingDialog();
navigateTo(navigation.validators);
cy.getByTestId(userStake, epochTimeout)
.first()
.should('have.text', '2.00');
cy.getByTestId('total-stake').first().realHover();
cy.getByTestId('staked-by-user-tooltip')
.first()
.should('have.text', 'Staked by me: 2.00');
cy.getByTestId('total-pending-stake').first().realHover();
cy.getByTestId('pending-user-stake-tooltip')
.first()
.should('have.text', 'My pending stake: 0.00');
cy.getByTestId(userStakeShare).invoke('text').should('not.be.empty'); // Adjust when #3286 is resolved
cy.getByTestId(userStakeBtn).should('exist').click();
verifyThisEpochValue(2.0);
navigateTo(navigation.validators);
cy.getByTestId(viewStakedByMeToggle).click();
cy.getByTestId(userStakeBtn).should('have.length', 1);
cy.getByTestId(viewAllValidatorsToggle).click();
clickOnValidatorFromList(1);
stakingValidatorPageAddStake('2');
closeStakingDialog();
navigateTo(navigation.validators);
cy.getByTestId(viewStakedByMeToggle).click();
cy.getByTestId(userStakeBtn).should('have.length', 2);
});
it('Able to stake against a validator - using vega from vesting contract', function () {
stakingPageAssociateTokens('3', { type: 'contract' });
verifyUnstakedBalance(3.0);
@@ -109,14 +144,13 @@ context(
});
it('Able to stake against a validator - using vega from both wallet and vesting contract', function () {
vegaWalletTeardown();
stakingPageAssociateTokens('3', { type: 'contract' });
navigateTo(navigation.validators);
stakingPageAssociateTokens('4', { type: 'wallet' });
verifyUnstakedBalance(7.0);
verifyEthWalletTotalAssociatedBalance('3.0');
verifyEthWalletTotalAssociatedBalance('4.0');
verifyEthWalletTotalAssociatedBalance('3.0');
verifyEthWalletTotalAssociatedBalance('4.0');
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('6');
@@ -136,7 +170,7 @@ context(
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('2');
verifyUnstakedBalance(3.0);
cy.get(vegaWalletStakedBalances, txTimeout)
cy.getByTestId(vegaWalletStakedBalances, txTimeout)
.parent()
.should('contain', 2.0, txTimeout);
closeStakingDialog();
@@ -144,36 +178,36 @@ context(
clickOnValidatorFromList(1);
stakingValidatorPageAddStake('1');
verifyUnstakedBalance(2.0);
cy.get(vegaWalletStakedBalances, txTimeout)
cy.getByTestId(vegaWalletStakedBalances, txTimeout)
.should('have.length', 4, txTimeout)
.eq(0)
.should('contain', 2.0, txTimeout);
cy.get(vegaWalletStakedBalances, txTimeout)
cy.getByTestId(vegaWalletStakedBalances, txTimeout)
.eq(1)
.should('contain', 1.0, txTimeout);
closeStakingDialog();
navigateTo(navigation.validators);
cy.get(`[row-id="${0}"]`).within(() => {
cy.get(stakeValidatorListTotalStake)
cy.getByTestId(stakeValidatorListTotalStake)
.should('have.text', '2.00')
.and('be.visible');
cy.get(stakeValidatorListTotalShare)
cy.getByTestId(stakeValidatorListTotalShare)
.should('have.text', '66.67%')
.and('be.visible');
cy.get(stakeValidatorListValidatorStake)
cy.getByTestId(stakeValidatorListTotalStake)
.scrollIntoView()
.should('have.text', '2.00')
.and('be.visible');
});
cy.get(`[row-id="${1}"]`).within(() => {
cy.get(stakeValidatorListTotalStake)
cy.getByTestId(stakeValidatorListTotalStake)
.scrollIntoView()
.should('have.text', '1.00')
.and('be.visible');
cy.get(stakeValidatorListTotalShare)
cy.getByTestId(stakeValidatorListTotalShare)
.should('have.text', '33.33%')
.and('be.visible');
cy.get(stakeValidatorListValidatorStake)
cy.getByTestId(stakeValidatorListTotalStake)
.scrollIntoView()
.should('have.text', '1.00')
.and('be.visible');
@@ -203,9 +237,15 @@ context(
verifyStakedBalance(2.0);
verifyNextEpochValue(2.0);
verifyThisEpochValue(2.0);
cy.get(totalStake, epochTimeout).should('contain.text', '2');
cy.getByTestId(stakeValidatorListTotalStake, epochTimeout).should(
'contain.text',
'2'
);
waitForBeginningOfEpoch();
cy.get(stakeShare).should('have.text', '100%');
cy.getByTestId(stakeValidatorListStakePercentage).should(
'have.text',
'100%'
);
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
}
@@ -227,12 +267,16 @@ context(
verifyUnstakedBalance(3.0);
verifyNextEpochValue(0.0);
verifyThisEpochValue(0.0);
cy.get(vegaWalletStakedBalances, txTimeout).should(
cy.getByTestId(vegaWalletStakedBalances, txTimeout).should(
'not.exist',
txTimeout
);
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
cy.getByTestId(userStakeBtn).should('not.exist');
cy.getByTestId(userStake).should('not.exist');
cy.getByTestId(userStakeShare).should('not.exist');
});
it('Unable to remove a stake with a negative value for a validator', function () {
@@ -246,10 +290,10 @@ context(
closeStakingDialog();
navigateTo(navigation.validators);
clickOnValidatorFromList(0);
cy.get(stakeRemoveStakeRadioButton, txTimeout).click();
cy.get(stakeTokenAmountInputBox).type('-0.1');
cy.getByTestId(stakeRemoveStakeRadioButton, txTimeout).click();
cy.getByTestId(stakeTokenAmountInputBox).type('-0.1');
cy.contains('Waiting for next epoch to start', epochTimeout);
cy.get(stakeTokenSubmitButton)
cy.getByTestId(stakeTokenSubmitButton)
.should('be.disabled', epochTimeout)
.and('contain', `Remove -0.1 $VEGA tokens at the end of epoch`)
.and('be.visible');
@@ -266,10 +310,10 @@ context(
closeStakingDialog();
navigateTo(navigation.validators);
clickOnValidatorFromList(0);
cy.get(stakeRemoveStakeRadioButton).click();
cy.get(stakeTokenAmountInputBox).type('4');
cy.getByTestId(stakeRemoveStakeRadioButton).click();
cy.getByTestId(stakeTokenAmountInputBox).type('4');
cy.contains('Waiting for next epoch to start', epochTimeout);
cy.get(stakeTokenSubmitButton)
cy.getByTestId(stakeTokenSubmitButton)
.should('be.disabled', epochTimeout)
.and('contain', `Remove 4 $VEGA tokens at the end of epoch`)
.and('be.visible');
@@ -285,17 +329,17 @@ context(
verifyStakedBalance(2.0);
closeStakingDialog();
stakingPageDisassociateAllTokens();
cy.get(ethWalletContainer).within(() => {
cy.getByTestId(ethWalletContainer).within(() => {
cy.contains(vegaWalletPublicKeyShort, txTimeout).should('not.exist');
});
verifyEthWalletTotalAssociatedBalance('0.0');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
cy.getByTestId(vegaWallet).within(() => {
cy.getByTestId(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'0.00'
);
});
cy.get(vegaWalletStakedBalances, txTimeout).should(
cy.getByTestId(vegaWalletStakedBalances, txTimeout).should(
'not.exist',
txTimeout
);
@@ -313,17 +357,17 @@ context(
verifyStakedBalance(2.0);
closeStakingDialog();
stakingPageDisassociateAllTokens('contract');
cy.get(ethWalletContainer).within(() => {
cy.getByTestId(ethWalletContainer).within(() => {
cy.contains(vegaWalletPublicKeyShort, txTimeout).should('not.exist');
});
verifyEthWalletTotalAssociatedBalance('0.0');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
cy.getByTestId(vegaWallet).within(() => {
cy.getByTestId(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'0.00'
);
});
cy.get(vegaWalletStakedBalances, txTimeout).should(
cy.getByTestId(vegaWalletStakedBalances, txTimeout).should(
'not.exist',
txTimeout
);
@@ -342,8 +386,8 @@ context(
closeStakingDialog();
stakingPageDisassociateTokens('1');
verifyEthWalletTotalAssociatedBalance('2.0');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
cy.getByTestId(vegaWallet).within(() => {
cy.getByTestId(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'2.00'
);
@@ -409,8 +453,8 @@ context(
verifyUnstakedBalance(0.0);
closeStakingDialog();
stakingPageAssociateTokens('6');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
cy.getByTestId(vegaWallet).within(() => {
cy.getByTestId(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'12.00'
);
@@ -429,9 +473,12 @@ context(
verifyUnstakedBalance(1.0);
closeStakingDialog();
clickOnValidatorFromList(0);
cy.get(stakeAddStakeRadioButton).click();
cy.get(stakeMaximumTokens, { timeout: 60000 }).click();
cy.get(stakeTokenSubmitButton).should('contain', 'Add 1 $VEGA tokens');
cy.getByTestId(stakeAddStakeRadioButton).click();
cy.getByTestId(stakeMaximumTokens, { timeout: 60000 }).click();
cy.getByTestId(stakeTokenSubmitButton).should(
'contain',
'Add 1 $VEGA tokens'
);
});
afterEach('Teardown Wallet', function () {
@@ -25,11 +25,11 @@ const vegaWalletUnstakedBalance =
'[data-testid="vega-wallet-balance-unstaked"]';
const txTimeout = Cypress.env('txTimeout');
const vegaWalletPublicKeyShort = Cypress.env('vegaWalletPublicKeyShort');
const ethWalletAssociateButton = '[data-testid="associate-btn"]';
const ethWalletAssociateButton = '[data-testid="associate-btn"]:visible';
const associateWalletRadioButton = '[data-testid="associate-radio-wallet"]';
const tokenAmountInputBox = '[data-testid="token-amount-input"]';
const tokenSubmitButton = '[data-testid="token-input-submit-button"]';
const ethWalletDissociateButton = '[href="/token/disassociate"]';
const ethWalletDissociateButton = '[href="/token/disassociate"]:visible';
const vestingContractSection = '[data-testid="vega-in-vesting-contract"]';
const vegaInWalletSection = '[data-testid="vega-in-wallet"]';
const connectedVegaKey = '[data-testid="connected-vega-key"]';
@@ -78,12 +78,12 @@ context(
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
6
);
validateWalletCurrency('Associated', '0.00');
validateWalletCurrency('Pending association', '2.00');
validateWalletCurrency('Total associated after pending', '2.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
// 0005-ETXN-002
verifyEthWalletAssociatedBalance('2.0');
@@ -111,12 +111,12 @@ context(
stakingPageDisassociateTokens('2');
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
6
);
validateWalletCurrency('Associated', '2.00');
validateWalletCurrency('Pending association', '2.00');
validateWalletCurrency('Total associated after pending', '0.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
cy.getByTestId('eth-wallet-associated-balances', txTimeout).should(
'not.exist'
);
@@ -183,6 +183,7 @@ context(
// 1004-ASSO-018
// 1004-ASSO-024
// 1004-ASSO-023
// 1004-ASSO-032
stakingPageAssociateTokens('2', {
type: 'contract',
@@ -191,12 +192,12 @@ context(
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
6
);
validateWalletCurrency('Associated', '0.00');
validateWalletCurrency('Pending association', '2.00');
validateWalletCurrency('Total associated after pending', '2.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
verifyEthWalletAssociatedBalance('2.0');
verifyEthWalletTotalAssociatedBalance('2.0');
cy.get(vegaWallet).within(() => {
@@ -209,12 +210,12 @@ context(
});
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
6
);
validateWalletCurrency('Associated', '2.00');
validateWalletCurrency('Pending association', '1.00');
validateWalletCurrency('Total associated after pending', '1.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
verifyEthWalletAssociatedBalance('1.0');
verifyEthWalletTotalAssociatedBalance('1.0');
});
@@ -265,7 +266,7 @@ context(
// 1004-ASSO-008
// 1004-ASSO-010
// No warning visible as described in AC, but the button is disabled
cy.get(ethWalletAssociateButton).first().click();
cy.get(ethWalletAssociateButton).click();
cy.get(associateWalletRadioButton, { timeout: 30000 }).click();
cy.get(tokenSubmitButton, txTimeout).should('be.disabled'); // button disabled with no input
cy.get(tokenAmountInputBox, { timeout: 10000 }).type('6500000');
@@ -277,12 +278,12 @@ context(
vegaWalletAssociate('2');
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
6
);
validateWalletCurrency('Associated', '0.00');
validateWalletCurrency('Pending association', '2.00');
validateWalletCurrency('Total associated after pending', '2.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
validateWalletCurrency('Associated', '2.00');
});
@@ -293,24 +294,24 @@ context(
});
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
3
6
);
validateWalletCurrency('Associated', '2.00');
validateWalletCurrency('Pending association', '2.00');
validateWalletCurrency('Total associated after pending', '0.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 3);
cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
validateWalletCurrency('Associated', '0.00');
});
it('Able to associate tokens to different public key of connected vega wallet', function () {
cy.get(ethWalletAssociateButton).first().click();
cy.get(ethWalletAssociateButton).click();
cy.get(associateWalletRadioButton).click();
cy.get(connectedVegaKey).should(
'have.text',
Cypress.env('vegaWalletPublicKey')
);
cy.get('[data-testid="manage-vega-wallet"]').click();
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
cy.get('[data-testid="select-keypair-button"]').eq(0).click();
cy.get(connectedVegaKey).should(
'have.text',
@@ -6,159 +6,203 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
cy.get('nav', { timeout: 10000 }).should('be.visible');
});
describe('with wallets disconnected', function () {
describe('Links and buttons', function () {
it('should have link for proposal page', function () {
cy.getByTestId('home-proposals').within(() => {
cy.get('[href="/proposals"]')
.should('exist')
.and('have.text', 'Browse, vote, and propose');
});
});
it('should show open or enacted proposals with proposal summary', function () {
cy.get('body').then(($body) => {
if (!$body.find('[data-testid="proposals-list-item"]').length) {
cy.createMarket();
cy.reload();
waitForSpinner();
}
});
cy.getByTestId('proposals-list-item')
.should('have.length.at.least', 1)
.first()
.within(() => {
cy.getByTestId('proposal-title')
.invoke('text')
.should('not.be.empty');
cy.getByTestId('proposal-type')
.invoke('text')
.should('not.be.empty');
cy.getByTestId('proposal-description')
.invoke('text')
.should('not.be.empty');
cy.getByTestId('proposal-details')
.invoke('text')
.should('not.be.empty');
cy.getByTestId('proposal-status')
.invoke('text')
.should('not.be.empty');
cy.getByTestId('vote-details')
.invoke('text')
.should('not.be.empty');
cy.getByTestId('view-proposal-btn').should('be.visible');
});
});
it('should have external link for governance', function () {
cy.getByTestId('home-proposals').within(() => {
cy.getByTestId('external-link')
.should('have.attr', 'href')
.and('contain', 'https://vega.xyz/governance');
});
});
it('should have link for validator page', function () {
cy.getByTestId('home-validators').within(() => {
cy.get('[href="/validators"]')
.first()
.should('exist')
.and('have.text', 'Browse, and stake');
});
});
it('should have external link for validators', function () {
cy.getByTestId('home-validators').within(() => {
cy.getByTestId('external-link')
.should('have.attr', 'href')
.and(
'contain',
'https://community.vega.xyz/c/mainnet-validator-candidates'
);
});
});
it('should have information on active nodes', function () {
cy.getByTestId('node-information')
.first()
.should('contain.text', '2')
.and('contain.text', 'active nodes');
});
it('should have information on consensus nodes', function () {
cy.getByTestId('node-information')
.last()
.should('contain.text', '2')
.and('contain.text', 'consensus nodes');
});
it('should contain link to specific validators', function () {
cy.getByTestId('validators')
.should('have.length', '2')
.each(($validator) => {
cy.wrap($validator).find('a').should('have.attr', 'href');
});
});
it('should have link for rewards page', function () {
cy.getByTestId('home-rewards').within(() => {
cy.get('[href="/rewards"]')
.first()
.should('exist')
.and('have.text', 'See rewards');
});
});
it('should have link for withdrawal page', function () {
cy.getByTestId('home-vega-token').within(() => {
cy.get('[href="/token/withdraw"]')
.first()
.should('exist')
.and('have.text', 'Manage tokens');
});
describe('Links and buttons', function () {
it('should have link for proposal page', function () {
cy.getByTestId('home-proposals').within(() => {
cy.get('[href="/proposals"]')
.should('exist')
.and('have.text', 'Browse, vote, and propose');
});
});
describe('Mobile view - navigation bar', function () {
before('Change to mobile resolution', function () {
cy.viewport('iphone-xr');
});
it('should have burger button', () => {
cy.getByTestId('button-menu-drawer').should('be.visible').click();
cy.getByTestId('menu-drawer').should('be.visible');
});
it('should have link for proposal page', function () {
cy.getByTestId('menu-drawer').within(() => {
cy.get('[href="/proposals"]')
.should('exist')
.and('have.text', 'Proposals');
it('should display announcement banner', function () {
cy.getByTestId('app-announcement')
.should('be.visible')
.within(() => {
cy.getByTestId('external-link').should('exist');
});
cy.getByTestId('app-announcement-close').should('be.visible').click();
cy.getByTestId('app-announcement').should('not.exist');
});
it('should show open or enacted proposals with proposal summary', function () {
cy.get('body').then(($body) => {
if (!$body.find('[data-testid="proposals-list-item"]').length) {
cy.createMarket();
cy.reload();
waitForSpinner();
}
});
it('should have link for validator page', function () {
cy.getByTestId('menu-drawer').within(() => {
cy.get('[href="/validators"]')
cy.getByTestId('proposals-list-item')
.should('have.length.at.least', 1)
.first()
.within(() => {
cy.getByTestId('proposal-title')
.invoke('text')
.should('not.be.empty');
cy.getByTestId('proposal-type').invoke('text').should('not.be.empty');
cy.getByTestId('proposal-description')
.invoke('text')
.should('not.be.empty');
cy.getByTestId('proposal-details')
.invoke('text')
.should('not.be.empty');
cy.getByTestId('proposal-status')
.invoke('text')
.should('not.be.empty');
cy.getByTestId('vote-details').invoke('text').should('not.be.empty');
cy.getByTestId('view-proposal-btn').should('be.visible');
});
});
it('should have external link for governance', function () {
cy.getByTestId('home-proposals').within(() => {
cy.getByTestId('external-link')
.should('have.attr', 'href')
.and('contain', 'https://vega.xyz/governance');
});
});
it('should have link for validator page', function () {
cy.getByTestId('home-validators').within(() => {
cy.get('[href="/validators"]')
.first()
.should('exist')
.and('have.text', 'Browse, and stake');
});
});
it('should have external link for validators', function () {
cy.getByTestId('home-validators').within(() => {
cy.getByTestId('external-link')
.should('have.attr', 'href')
.and(
'contain',
'https://community.vega.xyz/c/mainnet-validator-candidates'
);
});
});
it('should have information on active nodes', function () {
cy.getByTestId('node-information')
.first()
.should('contain.text', '2')
.and('contain.text', 'active nodes');
});
it('should have information on consensus nodes', function () {
cy.getByTestId('node-information')
.last()
.should('contain.text', '2')
.and('contain.text', 'consensus nodes');
});
it('should contain link to specific validators', function () {
cy.getByTestId('validators')
.should('have.length', '2')
.each(($validator) => {
cy.wrap($validator).find('a').should('have.attr', 'href');
});
});
it('should have link for rewards page', function () {
cy.getByTestId('home-rewards').within(() => {
cy.get('[href="/rewards"]')
.first()
.should('exist')
.and('have.text', 'See rewards');
});
});
it('should have link for withdrawal page', function () {
cy.getByTestId('home-vega-token').within(() => {
cy.get('[href="/token/withdraw"]')
.first()
.should('exist')
.and('have.text', 'Manage tokens');
});
});
it('should display network data', function () {
cy.getByTestId('git-network-data')
.should('contain.text', 'Reading network data from')
.within(() => {
cy.get('span')
.first()
.should('exist')
.and('have.text', 'Validators');
.should('have.text', 'http://localhost:3028/query');
cy.getByTestId('link').should('exist');
});
});
});
it('should have link for rewards page', function () {
cy.getByTestId('menu-drawer').within(() => {
cy.get('[href="/rewards"]')
.first()
.should('exist')
.and('have.text', 'Rewards');
it('should display eth data', function () {
cy.getByTestId('git-eth-data')
.should('contain.text', 'Reading Ethereum data from')
.within(() => {
cy.get('span').should('have.text', 'http://localhost:8545');
});
});
it('should have link for withdrawal page', function () {
cy.getByTestId('menu-drawer').within(() => {
cy.get('[href="/token/withdraw"]')
.first()
.should('exist')
.and('have.text', 'Withdraw');
});
});
});
after(function () {
cy.viewport(
Cypress.config('viewportWidth'),
Cypress.config('viewportHeight')
);
it('should contain link for known issues on Github', function () {
cy.getByTestId('git-info').within(() => {
cy.contains('Known issues and feedback on')
.find('[data-testid="link"]')
.should(
'have.attr',
'href',
'https://github.com/vegaprotocol/feedback/discussions'
);
});
});
});
describe('Mobile view - navigation bar', function () {
before('Change to mobile resolution', function () {
cy.viewport('iphone-xr');
});
it('should have burger button', () => {
cy.getByTestId('button-menu-drawer').should('be.visible').click();
cy.getByTestId('menu-drawer').should('be.visible');
});
it('should have link for proposal page', function () {
cy.getByTestId('menu-drawer').within(() => {
cy.get('[href="/proposals"]')
.should('exist')
.and('have.text', 'Proposals');
});
});
it('should have link for validator page', function () {
cy.getByTestId('menu-drawer').within(() => {
cy.get('[href="/validators"]')
.first()
.should('exist')
.and('have.text', 'Validators');
});
});
it('should have link for rewards page', function () {
cy.getByTestId('menu-drawer').within(() => {
cy.get('[href="/rewards"]')
.first()
.should('exist')
.and('have.text', 'Rewards');
});
});
it('should have link for withdrawal page', function () {
cy.getByTestId('menu-drawer').within(() => {
cy.get('[href="/token/withdraw"]')
.first()
.should('exist')
.and('have.text', 'Withdraw');
});
});
after(function () {
cy.viewport(
Cypress.config('viewportWidth'),
Cypress.config('viewportHeight')
);
});
});
});
@@ -26,19 +26,19 @@ context('View functionality with public key', { tags: '@smoke' }, function () {
cy.connectPublicKey(vegaWalletPubKey);
});
it('Able to connect public key via wallet', function () {
verifyConnectedToPubKey();
cy.getByTestId('currency-title', { timeout: 10000 })
.should('have.length.at.least', 4)
.and('contain.text', 'USDC (fake)');
});
it('Able to connect public key using url', function () {
cy.getByTestId('exit-view').click();
cy.visit(`/?address=${vegaWalletPubKey}`);
verifyConnectedToPubKey();
});
it('Able to connect public key via wallet and view assets in wallet', function () {
verifyConnectedToPubKey();
cy.getByTestId('currency-title', { timeout: 10000 })
.should('have.length.at.least', 4)
.and('contain.text', 'USDC (fake)');
});
it('Unable to submit proposal with public key', function () {
const expectedErrorTxt = `You are connected in a view only state for public key: ${vegaWalletPubKey}. In order to send transactions you must connect to a real wallet.`;
@@ -84,3 +84,7 @@ export function verifyEthWalletAssociatedBalance(amount: string) {
.parent(txTimeout)
.should('contain', amount, txTimeout);
}
export function closeDialog() {
cy.getByTestId('dialog-close').click();
}
@@ -1,4 +1,4 @@
import { navigateTo, navigation } from './common.functions';
import { closeDialog, navigateTo, navigation } from './common.functions';
import { ensureSpecifiedUnstakedTokensAreAssociated } from './staking.functions';
const newProposalButton = '[data-testid="new-proposal-link"]';
@@ -12,7 +12,6 @@ const voteButtons = '[data-testid="vote-buttons"]';
const dialogTitle = '[data-testid="dialog-title"]';
const proposalVoteDeadline = '[data-testid="proposal-vote-deadline"]';
const newProposalSubmitButton = '[data-testid="proposal-submit"]';
const dialogCloseButton = '[data-testid="dialog-close"]';
const epochTimeout = Cypress.env('epochTimeout');
const proposalTimeout = { timeout: 14000 };
@@ -125,7 +124,7 @@ export function voteForProposal(vote: string) {
'have.text',
'Transaction complete'
);
cy.get(dialogCloseButton).click();
closeDialog();
}
export function waitForProposalSync() {
@@ -167,6 +166,7 @@ export function goToMakeNewProposal(proposalType: string) {
navigateTo(navigation.proposals);
cy.get(newProposalButton).should('be.visible').click();
cy.url().should('include', '/proposals/propose');
cy.get(navigation.pageSpinner, { timeout: 20000 }).should('not.exist');
cy.get('li').should('contain.text', proposalType).and('be.visible');
cy.get('li').contains(proposalType).click();
}
@@ -176,7 +176,7 @@ export function waitForProposalSubmitted() {
'be.visible'
);
cy.contains('Proposal submitted', proposalTimeout).should('be.visible');
cy.get(dialogCloseButton).click();
closeDialog();
}
export function createRawProposal(proposerBalance?: string) {
@@ -1,3 +1,4 @@
import { closeDialog } from './common.functions';
import { vegaWalletTeardown } from './wallet-teardown.functions';
const tokenAmountInputBox = '[data-testid="token-amount-input"]';
@@ -18,7 +19,6 @@ const stakeValidatorListTotalStake = 'total-stake';
const stakeValidatorListTotalShare = 'total-stake-share';
const stakeValidatorListName = '[col-id="validator"]';
const vegaKeySelector = '#vega-key-selector';
const dialogCloseButton = '[data-testid="dialog-close"]';
const txTimeout = Cypress.env('txTimeout');
const epochTimeout = Cypress.env('epochTimeout');
@@ -54,7 +54,7 @@ export function stakingValidatorPageRemoveStake(stake: string) {
.and('contain', `Remove ${stake} $VEGA tokens at the end of epoch`)
.and('be.visible')
.click();
cy.get(dialogCloseButton).click();
closeDialog();
}
export function stakingPageAssociateTokens(
@@ -8,6 +8,7 @@ import {
} from '@vegaprotocol/smart-contracts';
import { ethers, Wallet } from 'ethers';
const associatedAmountInWallet = '[data-testid="associated-amount"]:visible';
const vegaWalletContainer = 'aside [data-testid="vega-wallet"]';
const vegaWalletMnemonic = Cypress.env('vegaWalletMnemonic');
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey');
@@ -59,7 +60,7 @@ export async function faucetAsset(assetEthAddress: string) {
}
export async function vegaWalletTeardown() {
cy.get('[data-testid="associated-amount"]')
cy.get(associatedAmountInWallet)
.should('be.visible')
.invoke('text')
.then((associatedAmount) => {
@@ -68,15 +69,12 @@ export async function vegaWalletTeardown() {
$body.find('[data-testid="eth-wallet-associated-balances"]').length ||
associatedAmount != '0.00'
) {
vegaWalletTeardownVesting(vestingContract);
vegaWalletTeardownStaking(stakingBridgeContract);
vegaWalletTeardownVesting(vestingContract);
}
});
cy.get(vegaWalletContainer).within(() => {
cy.getByTestId('vega-wallet-balance-staked-validators', {
timeout: transactionTimeout,
}).should('not.exist');
cy.getByTestId('associated-amount', {
cy.get(associatedAmountInWallet, {
timeout: transactionTimeout,
}).contains('0.00', {
timeout: transactionTimeout,
@@ -93,7 +91,7 @@ export async function vegaWalletSetSpecifiedApprovalAmount(
await promiseWithTimeout(
token.approve(
ethStakingBridgeContractAddress,
resetAmount.concat('000000000000000000')
resetAmount + '0'.repeat(18)
),
10 * 60 * 1000,
'set approval amount'
@@ -107,12 +105,23 @@ async function vegaWalletTeardownStaking(stakingBridgeContract: StakingBridge) {
{ timeout: transactionTimeout, log: false }
).then((stakeBalance) => {
if (Number(stakeBalance) != 0) {
cy.wrap(
stakingBridgeContract.remove_stake(
String(stakeBalance),
vegaWalletPubKey
),
{ timeout: transactionTimeout, log: false }
cy.get('[data-testid="vega-wallet-balance-unstaked"]:visible').within(
() => {
cy.get(associatedAmountInWallet)
.invoke('text')
.then(($walletAmount) => {
cy.wrap(
stakingBridgeContract.remove_stake(
String(stakeBalance),
vegaWalletPubKey
),
{ timeout: transactionTimeout, log: false }
);
cy.get(associatedAmountInWallet, {
timeout: transactionTimeout,
}).should('not.have.text', $walletAmount);
});
}
);
}
});
@@ -125,6 +134,8 @@ async function vegaWalletTeardownVesting(vestingContract: TokenVesting) {
log: false,
}).then((vestingAmount) => {
if (Number(vestingAmount) != 0) {
// Wait needed to allow time for ganache to process tx for stakingBridgeContract.remove_stake
// eslint-disable-next-line cypress/no-unnecessary-waiting
cy.wrap(
vestingContract.remove_stake(String(vestingAmount), vegaWalletPubKey),
{ timeout: transactionTimeout, log: false }
+1
View File
@@ -13,6 +13,7 @@ NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
#Test configuration variables
CYPRESS_FAIRGROUND=false
+1
View File
@@ -5,6 +5,7 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_FAIRGROUND=false
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_CONFIG_URL=''
NX_VEGA_URL=http://localhost:3028/query
+1
View File
@@ -10,3 +10,4 @@ NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-devnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+1
View File
@@ -11,3 +11,4 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
-11
View File
@@ -1,11 +0,0 @@
# App configuration variables
NX_VEGA_ENV=MIRROR
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
NX_VEGA_URL=https://api.n00.mainnet-mirror.vega.xyz/graphql
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://mirror.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_DELEGATIONS_PAGINATION=50
-8
View File
@@ -1,8 +0,0 @@
# App configuration variables
NX_VEGA_URL=https://api.sandbox.vega.xyz/graphql
NX_VEGA_ENV=SANDBOX
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET3":"https://stagnet3.token.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}'
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
NX_VEGA_EXPLORER_URL=https://sandbox.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
+1
View File
@@ -7,3 +7,4 @@ NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+1
View File
@@ -8,3 +8,4 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet3-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+1
View File
@@ -11,3 +11,4 @@ NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-testnet-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
+1
View File
@@ -8,3 +8,4 @@ NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
@@ -1,15 +1,19 @@
import classNames from 'classnames';
import { useVegaWallet } from '@vegaprotocol/wallet';
import type { ReactNode } from 'react';
import { AnnouncementBanner } from '@vegaprotocol/announcements';
import { Nav } from '../nav';
import { Networks, useEnvironment } from '@vegaprotocol/environment';
import React from 'react';
interface AppLayoutProps {
children: ReactNode;
}
export const AppLayout = ({ children }: AppLayoutProps) => {
const { VEGA_ENV, ANNOUNCEMENTS_CONFIG_URL } = useEnvironment();
const { isReadOnly } = useVegaWallet();
const AppLayoutClasses = classNames(
'app w-full max-w-[1500px] mx-auto grid min-h-full',
'border-neutral-700 lg:border-l lg:border-r',
'app w-full max-w-[1500px] mx-auto grid',
'lg:text-body-large',
{
'grid-rows-[repeat(2,min-content)_1fr_min-content]': !isReadOnly,
@@ -17,5 +21,18 @@ export const AppLayout = ({ children }: AppLayoutProps) => {
}
);
return <div className={AppLayoutClasses}>{children}</div>;
return (
<div className="min-h-full">
<div className="lg:text-body-large">
{ANNOUNCEMENTS_CONFIG_URL && (
<AnnouncementBanner
app="governance"
configUrl={ANNOUNCEMENTS_CONFIG_URL}
/>
)}
<Nav theme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'dark'} />
</div>
<div className={AppLayoutClasses}>{children}</div>
</div>
);
};
@@ -1,33 +1,16 @@
import { Networks, useEnvironment } from '@vegaprotocol/environment';
import {
ViewingAsBanner,
AnnouncementBanner,
ExternalLink,
} from '@vegaprotocol/ui-toolkit';
import { ViewingAsBanner } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import React from 'react';
import { Nav } from '../nav';
export interface TemplateSidebarProps {
children: React.ReactNode;
sidebar: React.ReactNode[];
}
export function TemplateSidebar({ children, sidebar }: TemplateSidebarProps) {
const { VEGA_ENV } = useEnvironment();
const { isReadOnly, pubKey, disconnect } = useVegaWallet();
return (
<>
<AnnouncementBanner>
<div className="font-alpha calt uppercase text-center text-lg text-white">
<span className="pr-4">Wait no longer, SIM3 is here!</span>
<ExternalLink href="https://fairground.wtf/sim3">
Learn more
</ExternalLink>
</div>
</AnnouncementBanner>
<Nav theme={VEGA_ENV === Networks.TESTNET ? 'yellow' : 'dark'} />
{isReadOnly ? (
<ViewingAsBanner pubKey={pubKey} disconnect={disconnect} />
) : null}
+4 -8
View File
@@ -12,6 +12,7 @@ const TRUTHY = ['1', 'true'];
interface VegaContracts {
claimAddress: string;
lockedAddress: string;
tokenVestingAddress?: string;
}
const customClaimAddress = process.env['NX_CUSTOM_CLAIM_ADDRESS'] as string;
@@ -36,21 +37,16 @@ export const ContractAddresses: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
lockedAddress: '0x0', // TODO not deployed to this env
},
SANDBOX: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
lockedAddress: '0x0', // TODO not deployed to this env
},
TESTNET: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
lockedAddress: '0x0', // TODO not deployed to this env
},
MIRROR: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
lockedAddress: '0x0', // TODO not deployed to this env
},
VALIDATOR_TESTNET: {
claimAddress: '0x8Cef746ab7C83B61F6461cC92882bD61AB65a994', // TODO not deployed to this env, but random address so app doesn't error
lockedAddress: '0x0', // TODO not deployed to this env
// This is a fallback contract address for the validator testnet network which does not
// have a vesting contract address set and is therefore not in the ethereum config
tokenVestingAddress: '0xadFcb7f93a24F8743a8e548d74d2ecB373c92866',
},
MAINNET: {
claimAddress: '0x0ee1fb382caf98e86e97e51f9f42f8b4654020f3',
@@ -49,6 +49,13 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
signer = provider.getSigner();
}
const tokenVestingAddress =
config.token_vesting_contract?.address ||
ENV.addresses.tokenVestingAddress;
if (!tokenVestingAddress) {
throw new Error('No token vesting address found');
}
if (provider && config) {
const staking = new StakingBridge(
config.staking_bridge_contract.address,
@@ -63,7 +70,7 @@ export const ContractsProvider = ({ children }: { children: JSX.Element }) => {
signer || provider
),
vesting: new TokenVesting(
config.token_vesting_contract.address,
tokenVestingAddress,
signer || provider
),
claim: new Claim(ENV.addresses.claimAddress, signer || provider),
@@ -1,9 +1,8 @@
import type { ObservableQuery } from '@apollo/client';
import { useEffect } from 'react';
export const useRefreshAfterEpoch = (
epochExpiry: string | undefined,
refetch: ObservableQuery['refetch']
refetch: () => void
) => {
return useEffect(() => {
const epochInterval = setInterval(() => {
@@ -443,8 +443,8 @@
"rewardType": "Reward type",
"rewardsAndFeesReceived": "Rewards and fees received",
"ThisDoesNotIncludeFeesReceivedForMakersOrLiquidityProviders": "This does not include fees received for makers or liquidity providers",
"totalDistributed": "TOTAL DISTRIBUTED",
"earnedByMe": "EARNED BY ME",
"totalDistributed": "Total distributed",
"earnedByMe": "Earned by me",
"noRewardsHaveBeenDistributedYet": "NO REWARDS HAVE BEEN DISTRIBUTED YET",
"rewardsColAssetHeader": "ASSET",
"rewardsColStakingHeader": "STAKING",
@@ -0,0 +1,15 @@
export const calculateEpochOffset = ({
epochId,
page,
size,
}: {
epochId: number;
page: number;
size: number;
}) => {
// offset the epoch by the current page number times the page size while making sure it doesn't go below the minimum epoch value
return {
fromEpoch: Math.max(0, epochId - size * page) + 1,
toEpoch: epochId - size * page + size,
};
};
@@ -3,7 +3,7 @@ import { AppStateProvider } from '../../../contexts/app-state/app-state-provider
import { EpochIndividualRewardsTable } from './epoch-individual-rewards-table';
const mockData = {
epoch: '4441',
epoch: 4441,
rewards: [
{
asset: 'tDAI',
@@ -1,21 +1,38 @@
import { useMemo } from 'react';
import { useMemo, useEffect, useState, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { AsyncRenderer, Pagination } from '@vegaprotocol/ui-toolkit';
import { removePaginationWrapper } from '@vegaprotocol/utils';
import type { EpochFieldsFragment } from '../home/__generated__/Rewards';
import { useRewardsQuery } from '../home/__generated__/Rewards';
import { ENV } from '../../../config';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { EpochIndividualRewardsTable } from './epoch-individual-rewards-table';
import { generateEpochIndividualRewardsList } from './generate-epoch-individual-rewards-list';
import { calculateEpochOffset } from '../../../lib/epoch-pagination';
export const EpochIndividualRewards = () => {
const EPOCHS_PAGE_SIZE = 10;
type EpochTotalRewardsProps = {
currentEpoch: EpochFieldsFragment;
};
export const EpochIndividualRewards = ({
currentEpoch,
}: EpochTotalRewardsProps) => {
// we start from the previous epoch when displaying rewards data, because the current one has no calculated data while ongoing
const epochId = Number(currentEpoch.id) - 1;
const totalPages = Math.ceil(epochId / EPOCHS_PAGE_SIZE);
const [page, setPage] = useState(1);
const { t } = useTranslation();
const { pubKey } = useVegaWallet();
const { delegationsPagination } = ENV;
const { data, loading, error } = useRewardsQuery({
const { data, loading, error, refetch } = useRewardsQuery({
notifyOnNetworkStatusChange: true,
variables: {
partyId: pubKey || '',
fromEpoch: epochId - EPOCHS_PAGE_SIZE,
toEpoch: epochId,
delegationsPagination: delegationsPagination
? {
first: Number(delegationsPagination),
@@ -33,8 +50,37 @@ export const EpochIndividualRewards = () => {
const epochIndividualRewardSummaries = useMemo(() => {
if (!data?.party) return [];
return generateEpochIndividualRewardsList(rewards);
}, [data?.party, rewards]);
return generateEpochIndividualRewardsList({
rewards,
epochId,
page,
size: EPOCHS_PAGE_SIZE,
});
}, [data?.party, epochId, page, rewards]);
const refetchData = useCallback(
async (toPage?: number) => {
const targetPage = toPage ?? page;
await refetch({
partyId: pubKey || '',
...calculateEpochOffset({ epochId, page, size: EPOCHS_PAGE_SIZE }),
delegationsPagination: delegationsPagination
? {
first: Number(delegationsPagination),
}
: undefined,
});
setPage(targetPage);
},
[epochId, page, refetch, delegationsPagination, pubKey]
);
useEffect(() => {
// when the epoch changes, we want to refetch the data to update the current page
if (data) {
refetchData();
}
}, [epochId, data, refetchData]);
return (
<AsyncRenderer
@@ -47,17 +93,24 @@ export const EpochIndividualRewards = () => {
{t('Connected Vega key')}:{' '}
<span className="text-white">{pubKey}</span>
</p>
{epochIndividualRewardSummaries.length ? (
epochIndividualRewardSummaries.map(
(epochIndividualRewardSummary) => (
<EpochIndividualRewardsTable
data={epochIndividualRewardSummary}
/>
)
{epochIndividualRewardSummaries.map(
(epochIndividualRewardSummary) => (
<EpochIndividualRewardsTable
data={epochIndividualRewardSummary}
/>
)
) : (
<p>{t('noRewards')}</p>
)}
<Pagination
isLoading={loading}
hasPrevPage={page > 1}
hasNextPage={page < totalPages}
onBack={() => refetchData(page - 1)}
onNext={() => refetchData(page + 1)}
onFirst={() => refetchData(1)}
onLast={() => refetchData(totalPages)}
>
{t('Page')} {page}
</Pagination>
</div>
)}
/>
@@ -43,6 +43,16 @@ describe('generateEpochIndividualRewardsList', () => {
epoch: { id: '1' },
};
const reward5: RewardFieldsFragment = {
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '150',
percentageOfTotal: '0.15',
receivedAt: new Date(),
asset: { id: 'usd', symbol: 'USD', name: 'USD' },
party: { id: 'blah' },
epoch: { id: '3' },
};
const rewardWrongType: RewardFieldsFragment = {
rewardType: AccountType.ACCOUNT_TYPE_INSURANCE,
amount: '50',
@@ -54,20 +64,38 @@ describe('generateEpochIndividualRewardsList', () => {
};
it('should return an empty array if no rewards are provided', () => {
expect(generateEpochIndividualRewardsList([])).toEqual([]);
expect(
generateEpochIndividualRewardsList({ rewards: [], epochId: 1 })
).toEqual([
{
epoch: 1,
rewards: [],
},
]);
});
it('should filter out any rewards of the wrong type', () => {
const result = generateEpochIndividualRewardsList([rewardWrongType]);
const result = generateEpochIndividualRewardsList({
rewards: [rewardWrongType],
epochId: 1,
});
expect(result).toEqual([]);
expect(result).toEqual([
{
epoch: 1,
rewards: [],
},
]);
});
it('should return reward in the correct format', () => {
const result = generateEpochIndividualRewardsList([reward1]);
const result = generateEpochIndividualRewardsList({
rewards: [reward1],
epochId: 1,
});
expect(result[0]).toEqual({
epoch: '1',
epoch: 1,
rewards: [
{
asset: 'USD',
@@ -105,21 +133,24 @@ describe('generateEpochIndividualRewardsList', () => {
it('should return an array sorted by epoch descending', () => {
const rewards = [reward1, reward2, reward3, reward4];
const result1 = generateEpochIndividualRewardsList(rewards);
const result1 = generateEpochIndividualRewardsList({ rewards, epochId: 2 });
expect(result1[0].epoch).toEqual('2');
expect(result1[1].epoch).toEqual('1');
expect(result1[0].epoch).toEqual(2);
expect(result1[1].epoch).toEqual(1);
const reorderedRewards = [reward4, reward3, reward2, reward1];
const result2 = generateEpochIndividualRewardsList(reorderedRewards);
const result2 = generateEpochIndividualRewardsList({
rewards: reorderedRewards,
epochId: 2,
});
expect(result2[0].epoch).toEqual('2');
expect(result2[1].epoch).toEqual('1');
expect(result2[0].epoch).toEqual(2);
expect(result2[1].epoch).toEqual(1);
});
it('correctly calculates the total value of rewards for an asset', () => {
const rewards = [reward1, reward4];
const result = generateEpochIndividualRewardsList(rewards);
const result = generateEpochIndividualRewardsList({ rewards, epochId: 1 });
expect(result[0].rewards[0].totalAmount).toEqual('200');
});
@@ -127,11 +158,11 @@ describe('generateEpochIndividualRewardsList', () => {
it('returns data in the expected shape', () => {
// Just sanity checking the whole structure here
const rewards = [reward1, reward2, reward3, reward4];
const result = generateEpochIndividualRewardsList(rewards);
const result = generateEpochIndividualRewardsList({ rewards, epochId: 2 });
expect(result).toEqual([
{
epoch: '2',
epoch: 2,
rewards: [
{
asset: 'GBP',
@@ -196,7 +227,165 @@ describe('generateEpochIndividualRewardsList', () => {
],
},
{
epoch: '1',
epoch: 1,
rewards: [
{
asset: 'USD',
totalAmount: '200',
rewardTypes: {
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY]: {
amount: '100',
percentageOfTotal: '0.1',
},
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
amount: '100',
percentageOfTotal: '0.1',
},
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
amount: '0',
percentageOfTotal: '0',
},
},
},
],
},
]);
});
it('returns data correctly for the requested epoch range', () => {
const rewards = [reward1, reward2, reward3, reward4, reward5];
const resultPageOne = generateEpochIndividualRewardsList({
rewards,
epochId: 3,
page: 1,
size: 2,
});
expect(resultPageOne).toEqual([
{
epoch: 3,
rewards: [
{
asset: 'USD',
totalAmount: '150',
rewardTypes: {
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY]: {
amount: '150',
percentageOfTotal: '0.15',
},
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
amount: '0',
percentageOfTotal: '0',
},
},
},
],
},
{
epoch: 2,
rewards: [
{
asset: 'GBP',
totalAmount: '200',
rewardTypes: {
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY]: {
amount: '200',
percentageOfTotal: '0.2',
},
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
amount: '0',
percentageOfTotal: '0',
},
},
},
{
asset: 'EUR',
totalAmount: '50',
rewardTypes: {
[AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_GLOBAL_REWARD]: {
amount: '50',
percentageOfTotal: '0.05',
},
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES]: {
amount: '0',
percentageOfTotal: '0',
},
[AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS]: {
amount: '0',
percentageOfTotal: '0',
},
},
},
],
},
]);
const resultPageTwo = generateEpochIndividualRewardsList({
rewards,
epochId: 3,
page: 2,
size: 2,
});
expect(resultPageTwo).toEqual([
{
epoch: 1,
rewards: [
{
asset: 'USD',
@@ -2,9 +2,10 @@ import { BigNumber } from '../../../lib/bignumber';
import { RowAccountTypes } from '../shared-rewards-table-assets/shared-rewards-table-assets';
import type { RewardFieldsFragment } from '../home/__generated__/Rewards';
import type { AccountType } from '@vegaprotocol/types';
import { calculateEpochOffset } from '../../../lib/epoch-pagination';
export interface EpochIndividualReward {
epoch: string;
epoch: number;
rewards: {
asset: string;
totalAmount: string;
@@ -27,11 +28,29 @@ const emptyRowAccountTypes = accountTypes.map((type) => [
},
]);
export const generateEpochIndividualRewardsList = (
rewards: RewardFieldsFragment[]
) => {
export const generateEpochIndividualRewardsList = ({
rewards,
epochId,
page = 1,
size = 10,
}: {
rewards: RewardFieldsFragment[];
epochId: number;
page?: number;
size?: number;
}) => {
const map: Map<string, EpochIndividualReward> = new Map();
const { fromEpoch, toEpoch } = calculateEpochOffset({ epochId, page, size });
for (let i = toEpoch; i >= fromEpoch; i--) {
map.set(i.toString(), {
epoch: i,
rewards: [],
});
}
// We take the rewards and aggregate them by epoch and asset.
const epochIndividualRewards = rewards.reduce((map, reward) => {
const epochIndividualRewards = rewards.reduce((acc, reward) => {
const epochId = reward.epoch.id;
const assetName = reward.asset.name;
const rewardType = reward.rewardType;
@@ -40,14 +59,14 @@ export const generateEpochIndividualRewardsList = (
// if the rewardType is not of a type we display in the table, we skip it.
if (!accountTypes.includes(rewardType)) {
return map;
return acc;
}
if (!map.has(epochId)) {
map.set(epochId, { epoch: epochId, rewards: [] });
if (!acc.has(epochId)) {
return acc;
}
const epoch = map.get(epochId);
const epoch = acc.get(epochId);
let asset = epoch?.rewards.find((r) => r.asset === assetName);
@@ -76,8 +95,8 @@ export const generateEpochIndividualRewardsList = (
});
}
return map;
}, new Map<string, EpochIndividualReward>());
return acc;
}, map);
return Array.from(epochIndividualRewards.values()).sort(
(a, b) => Number(b.epoch) - Number(a.epoch)
@@ -1,44 +1,64 @@
import { render } from '@testing-library/react';
import { AppStateProvider } from '../../../contexts/app-state/app-state-provider';
import { EpochTotalRewardsTable } from './epoch-total-rewards-table';
import type {
AggregatedEpochRewardSummary,
RewardType,
RewardItem,
} from './generate-epoch-total-rewards-list';
import { AccountType } from '@vegaprotocol/types';
const assetId =
'b340c130096819428a62e5df407fd6abe66e444b89ad64f670beb98621c9c663';
const rewardsList = [
{
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
amount: '295',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
amount: '0',
},
];
const rewards: Map<RewardType, RewardItem> = new Map();
rewardsList.forEach((r) => {
rewards.set(r.rewardType, r);
});
const assetRewards: Map<
AggregatedEpochRewardSummary['assetId'],
AggregatedEpochRewardSummary
> = new Map();
assetRewards.set(assetId, {
assetId,
name: 'tDAI TEST',
rewards,
totalAmount: '295',
});
const mockData = {
epoch: 4431,
assetRewards: [
{
assetId:
'b340c130096819428a62e5df407fd6abe66e444b89ad64f670beb98621c9c663',
name: 'tDAI TEST',
rewards: [
{
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
amount: '295',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
amount: '0',
},
],
totalAmount: '295',
},
],
assetRewards,
};
describe('EpochTotalRewardsTable', () => {
@@ -48,17 +48,19 @@ export const EpochTotalRewardsTable = ({
}: EpochTotalRewardsGridProps) => {
return (
<RewardsTable dataTestId="epoch-total-rewards-table" epoch={data.epoch}>
{data.assetRewards.map(({ name, rewards, totalAmount }, i) => (
<div className="contents" key={i}>
<div data-testid="asset" className={`${rowGridItemStyles()} p-5`}>
{name}
{Array.from(data.assetRewards.values()).map(
({ name, rewards, totalAmount }, i) => (
<div className="contents" key={i}>
<div data-testid="asset" className={`${rowGridItemStyles()} p-5`}>
{name}
</div>
{Array.from(rewards.values()).map(({ rewardType, amount }, i) => (
<RewardItem key={i} dataTestId={rewardType} value={amount} />
))}
<RewardItem dataTestId="total" value={totalAmount} last={true} />
</div>
{rewards.map(({ rewardType, amount }, i) => (
<RewardItem key={i} dataTestId={rewardType} value={amount} />
))}
<RewardItem dataTestId="total" value={totalAmount} last={true} />
</div>
))}
)
)}
</RewardsTable>
);
};
@@ -1,21 +1,62 @@
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { useState, useCallback, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { AsyncRenderer, Pagination } from '@vegaprotocol/ui-toolkit';
import type { EpochFieldsFragment } from '../home/__generated__/Rewards';
import { useEpochAssetsRewardsQuery } from '../home/__generated__/Rewards';
import { useRefreshAfterEpoch } from '../../../hooks/use-refresh-after-epoch';
import { generateEpochTotalRewardsList } from './generate-epoch-total-rewards-list';
import { NoRewards } from '../no-rewards';
import { EpochTotalRewardsTable } from './epoch-total-rewards-table';
import { calculateEpochOffset } from '../../../lib/epoch-pagination';
export const EpochTotalRewards = () => {
const EPOCHS_PAGE_SIZE = 10;
type EpochTotalRewardsProps = {
currentEpoch: EpochFieldsFragment;
};
export const EpochTotalRewards = ({ currentEpoch }: EpochTotalRewardsProps) => {
// we start from the previous epoch when displaying rewards data, because the current one has no calculated data while ongoing
const epochId = Number(currentEpoch.id) - 1;
const totalPages = Math.ceil(epochId / EPOCHS_PAGE_SIZE);
const { t } = useTranslation();
const [page, setPage] = useState(1);
const { data, loading, error, refetch } = useEpochAssetsRewardsQuery({
notifyOnNetworkStatusChange: true,
variables: {
epochRewardSummariesPagination: {
first: 10,
epochRewardSummariesFilter: {
fromEpoch: epochId - EPOCHS_PAGE_SIZE,
},
},
});
useRefreshAfterEpoch(data?.epoch.timestamps.expiry, refetch);
const epochTotalRewardSummaries = generateEpochTotalRewardsList(data) || [];
const refetchData = useCallback(
async (toPage?: number) => {
const targetPage = toPage ?? page;
await refetch({
epochRewardSummariesFilter: calculateEpochOffset({
epochId,
page: targetPage,
size: EPOCHS_PAGE_SIZE,
}),
});
setPage(targetPage);
},
[epochId, page, refetch]
);
useEffect(() => {
// when the epoch changes, we want to refetch the data to update the current page
if (data) {
refetchData();
}
}, [epochId, data, refetchData]);
const epochTotalRewardSummaries =
generateEpochTotalRewardsList({
data,
epochId,
page,
size: EPOCHS_PAGE_SIZE,
}) || [];
return (
<AsyncRenderer
@@ -27,15 +68,22 @@ export const EpochTotalRewards = () => {
className="max-w-full overflow-auto"
data-testid="epoch-rewards-total"
>
{epochTotalRewardSummaries.length === 0 ? (
<NoRewards />
) : (
<>
{epochTotalRewardSummaries.map((epochTotalSummary, index) => (
<EpochTotalRewardsTable data={epochTotalSummary} key={index} />
))}
</>
{Array.from(epochTotalRewardSummaries.values()).map(
(epochTotalSummary, index) => (
<EpochTotalRewardsTable data={epochTotalSummary} key={index} />
)
)}
<Pagination
isLoading={loading}
hasPrevPage={page > 1}
hasNextPage={page < totalPages}
onBack={() => refetchData(page - 1)}
onNext={() => refetchData(page + 1)}
onFirst={() => refetchData(1)}
onLast={() => refetchData(totalPages)}
>
{t('Page')} {page}
</Pagination>
</div>
)}
/>
@@ -3,13 +3,23 @@ import { AccountType } from '@vegaprotocol/types';
describe('generateEpochAssetRewardsList', () => {
it('should return an empty array if data is undefined', () => {
const result = generateEpochTotalRewardsList(undefined);
const result = generateEpochTotalRewardsList({ epochId: 1 });
expect(result).toEqual([]);
expect(result).toEqual(
new Map([
[
'1',
{
epoch: 1,
assetRewards: new Map(),
},
],
])
);
});
it('should return an empty array if empty data is provided', () => {
const epochData = {
it('should return an empty map if empty data is provided', () => {
const data = {
assetsConnection: {
edges: [],
},
@@ -23,13 +33,23 @@ describe('generateEpochAssetRewardsList', () => {
},
};
const result = generateEpochTotalRewardsList(epochData);
const result = generateEpochTotalRewardsList({ data, epochId: 1 });
expect(result).toEqual([]);
expect(result).toEqual(
new Map([
[
'1',
{
epoch: 1,
assetRewards: new Map(),
},
],
])
);
});
it('should return an empty array if no epochRewardSummaries are provided', () => {
const epochData = {
it('should return an empty map if no epochRewardSummaries are provided', () => {
const data = {
assetsConnection: {
edges: [
{
@@ -56,13 +76,23 @@ describe('generateEpochAssetRewardsList', () => {
},
};
const result = generateEpochTotalRewardsList(epochData);
const result = generateEpochTotalRewardsList({ data, epochId: 1 });
expect(result).toEqual([]);
expect(result).toEqual(
new Map([
[
'1',
{
epoch: 1,
assetRewards: new Map(),
},
],
])
);
});
it('should return an array of unnamed assets if no asset names are provided (should not happen)', () => {
const epochData = {
it('should return a map of unnamed assets if no asset names are provided (should not happen)', () => {
const data = {
assetsConnection: {
edges: [],
},
@@ -85,50 +115,80 @@ describe('generateEpochAssetRewardsList', () => {
},
};
const result = generateEpochTotalRewardsList(epochData);
const result = generateEpochTotalRewardsList({ data, epochId: 1 });
expect(result).toEqual([
{
epoch: 1,
assetRewards: [
expect(result).toEqual(
new Map([
[
'1',
{
assetId: '1',
name: '',
rewards: [
{
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
amount: '123',
},
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
amount: '0',
},
],
totalAmount: '123',
epoch: 1,
assetRewards: new Map([
[
'1',
{
assetId: '1',
name: '',
rewards: new Map([
[
AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
{
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
amount: '123',
},
],
[
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
{
rewardType:
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
amount: '0',
},
],
]),
totalAmount: '123',
},
],
]),
},
],
},
]);
])
);
});
it('should return an array of aggregated epoch summaries', () => {
const epochData = {
it('should return the aggregated epoch summaries', () => {
const data = {
assetsConnection: {
edges: [
{
@@ -180,81 +240,425 @@ describe('generateEpochAssetRewardsList', () => {
},
};
const result = generateEpochTotalRewardsList(epochData);
const result = generateEpochTotalRewardsList({ data, epochId: 2 });
expect(result).toEqual([
{
epoch: 1,
assetRewards: [
expect(result).toEqual(
new Map([
[
'1',
{
assetId: '1',
name: 'Asset 1',
rewards: [
{
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
amount: '100',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
amount: '123',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
amount: '0',
},
],
totalAmount: '223',
epoch: 1,
assetRewards: new Map([
[
'1',
{
assetId: '1',
name: 'Asset 1',
rewards: new Map([
[
AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
{
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
{
rewardType:
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
amount: '100',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
amount: '123',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
amount: '0',
},
],
]),
totalAmount: '223',
},
],
]),
},
],
[
'2',
{
epoch: 2,
assetRewards: new Map([
[
'1',
{
assetId: '1',
name: 'Asset 1',
rewards: new Map([
[
AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
{
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
{
rewardType:
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '5',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
amount: '0',
},
],
]),
totalAmount: '5',
},
],
]),
},
],
])
);
});
it('should return the requested range for aggregated epoch summaries', () => {
const data = {
assetsConnection: {
edges: [
{
node: {
id: '1',
name: 'Asset 1',
},
},
{
node: {
id: '2',
name: 'Asset 2',
},
},
],
},
{
epoch: 2,
assetRewards: [
epochRewardSummaries: {
edges: [
{
assetId: '1',
name: 'Asset 1',
rewards: [
{
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
amount: '0',
},
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '5',
},
{
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
amount: '0',
},
],
totalAmount: '5',
node: {
epoch: 1,
assetId: '1',
rewardType: AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
amount: '123',
},
},
{
node: {
epoch: 1,
assetId: '1',
rewardType: AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
amount: '100',
},
},
{
node: {
epoch: 2,
assetId: '1',
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '6',
},
},
{
node: {
epoch: 2,
assetId: '1',
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '27',
},
},
{
node: {
epoch: 3,
assetId: '1',
rewardType: AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
amount: '15',
},
},
],
},
]);
epoch: {
timestamps: {
expiry: null,
},
},
};
const resultPageOne = generateEpochTotalRewardsList({
data,
epochId: 3,
page: 1,
size: 2,
});
expect(resultPageOne).toEqual(
new Map([
[
'2',
{
epoch: 2,
assetRewards: new Map([
[
'1',
{
assetId: '1',
name: 'Asset 1',
rewards: new Map([
[
AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
{
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
{
rewardType:
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '33',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
amount: '0',
},
],
]),
totalAmount: '33',
},
],
]),
},
],
[
'3',
{
epoch: 3,
assetRewards: new Map([
[
'1',
{
assetId: '1',
name: 'Asset 1',
rewards: new Map([
[
AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
{
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
{
rewardType:
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
amount: '15',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
amount: '0',
},
],
]),
totalAmount: '15',
},
],
]),
},
],
])
);
const resultPageTwo = generateEpochTotalRewardsList({
data,
epochId: 3,
page: 2,
size: 2,
});
expect(resultPageTwo).toEqual(
new Map([
[
'1',
{
epoch: 1,
assetRewards: new Map([
[
'1',
{
assetId: '1',
name: 'Asset 1',
rewards: new Map([
[
AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
{
rewardType: AccountType.ACCOUNT_TYPE_GLOBAL_REWARD,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
{
rewardType:
AccountType.ACCOUNT_TYPE_FEES_INFRASTRUCTURE,
amount: '100',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MAKER_PAID_FEES,
amount: '123',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MAKER_RECEIVED_FEES,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
{
rewardType: AccountType.ACCOUNT_TYPE_FEES_LIQUIDITY,
amount: '0',
},
],
[
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
{
rewardType:
AccountType.ACCOUNT_TYPE_REWARD_MARKET_PROPOSERS,
amount: '0',
},
],
]),
totalAmount: '223',
},
],
]),
},
],
])
);
});
});
@@ -5,127 +5,97 @@ import type {
import { removePaginationWrapper } from '@vegaprotocol/utils';
import { RowAccountTypes } from '../shared-rewards-table-assets/shared-rewards-table-assets';
import type { AccountType } from '@vegaprotocol/types';
import { BigNumber } from '../../../lib/bignumber';
import { calculateEpochOffset } from '../../../lib/epoch-pagination';
interface EpochSummaryWithNamedReward extends EpochRewardSummaryFieldsFragment {
name: string;
}
export interface AggregatedEpochRewardSummary {
export type RewardType = EpochRewardSummaryFieldsFragment['rewardType'];
export type RewardItem = Pick<
EpochRewardSummaryFieldsFragment,
'rewardType' | 'amount'
>;
export type AggregatedEpochRewardSummary = {
assetId: EpochRewardSummaryFieldsFragment['assetId'];
name: EpochSummaryWithNamedReward['name'];
rewards: {
rewardType: EpochRewardSummaryFieldsFragment['rewardType'];
amount: EpochRewardSummaryFieldsFragment['amount'];
}[];
rewards: Map<RewardType, RewardItem>;
totalAmount: string;
}
};
export interface EpochTotalSummary {
export type EpochTotalSummary = {
epoch: EpochRewardSummaryFieldsFragment['epoch'];
assetRewards: AggregatedEpochRewardSummary[];
}
assetRewards: Map<
EpochRewardSummaryFieldsFragment['assetId'],
AggregatedEpochRewardSummary
>;
};
const emptyRowAccountTypes = Object.keys(RowAccountTypes).map((type) => ({
rewardType: type as AccountType,
amount: '0',
}));
const emptyRowAccountTypes: Map<RewardType, RewardItem> = new Map();
export const generateEpochTotalRewardsList = (
epochData: EpochAssetsRewardsQuery | undefined
) => {
Object.keys(RowAccountTypes).forEach((type) => {
emptyRowAccountTypes.set(type as AccountType, {
rewardType: type as AccountType,
amount: '0',
});
});
export const generateEpochTotalRewardsList = ({
data,
epochId,
page = 1,
size = 10,
}: {
data?: EpochAssetsRewardsQuery | undefined;
epochId: number;
page?: number;
size?: number;
}) => {
const epochRewardSummaries = removePaginationWrapper(
epochData?.epochRewardSummaries?.edges
data?.epochRewardSummaries?.edges
);
const assets = removePaginationWrapper(epochData?.assetsConnection?.edges);
const assets = removePaginationWrapper(data?.assetsConnection?.edges);
// Because the epochRewardSummaries don't have the asset name, we need to find it in the assets list
const epochSummariesWithNamedReward: EpochSummaryWithNamedReward[] =
epochRewardSummaries.map((epochReward) => ({
...epochReward,
name:
assets.find((asset) => asset.id === epochReward.assetId)?.name || '',
}));
const map: Map<string, EpochTotalSummary> = new Map();
const { fromEpoch, toEpoch } = calculateEpochOffset({ epochId, page, size });
// Aggregating the epoch summaries by epoch number
const aggregatedEpochSummariesByEpochNumber =
epochSummariesWithNamedReward.reduce((acc, epochReward) => {
const epoch = epochReward.epoch;
const epochSummaryIndex = acc.findIndex(
(epochSummary) => epochSummary[0].epoch === epoch
);
if (epochSummaryIndex === -1) {
acc.push([epochReward]);
} else {
acc[epochSummaryIndex].push(epochReward);
}
return acc;
}, [] as EpochSummaryWithNamedReward[][]);
// Now aggregate the array of arrays of epoch summaries by asset rewards.
const epochTotalRewards: EpochTotalSummary[] =
aggregatedEpochSummariesByEpochNumber.map((epochSummaries) => {
const assetRewards = epochSummaries.reduce((acc, epochSummary) => {
const assetRewardIndex = acc.findIndex(
(assetReward) =>
assetReward.assetId === epochSummary.assetId &&
assetReward.name === epochSummary.name
);
if (assetRewardIndex === -1) {
acc.push({
assetId: epochSummary.assetId,
name: epochSummary.name,
rewards: [
...emptyRowAccountTypes.map((emptyRowAccountType) => {
if (
emptyRowAccountType.rewardType === epochSummary.rewardType
) {
return {
rewardType: epochSummary.rewardType,
amount: epochSummary.amount,
};
} else {
return emptyRowAccountType;
}
}),
],
totalAmount: epochSummary.amount,
});
} else {
acc[assetRewardIndex].rewards = acc[assetRewardIndex].rewards.map(
(reward) => {
if (reward.rewardType === epochSummary.rewardType) {
return {
rewardType: epochSummary.rewardType,
amount: (
Number(reward.amount) + Number(epochSummary.amount)
).toString(),
};
} else {
return reward;
}
}
);
acc[assetRewardIndex].totalAmount = (
Number(acc[assetRewardIndex].totalAmount) +
Number(epochSummary.amount)
).toString();
}
return acc;
}, [] as AggregatedEpochRewardSummary[]);
return {
epoch: epochSummaries[0].epoch,
assetRewards: assetRewards.sort((a, b) => {
return new BigNumber(b.totalAmount).comparedTo(a.totalAmount);
}),
};
for (let i = toEpoch; i >= fromEpoch; i--) {
map.set(i.toString(), {
epoch: i,
assetRewards: new Map(),
});
}
return epochTotalRewards;
return epochRewardSummaries.reduce((acc, reward) => {
const epoch = acc.get(reward.epoch.toString());
if (epoch) {
const matchingAsset = assets.find((asset) => asset.id === reward.assetId);
const assetWithRewards = epoch.assetRewards.get(reward.assetId);
const rewards =
assetWithRewards?.rewards || new Map(emptyRowAccountTypes);
const rewardItem = rewards?.get(reward.rewardType);
const amount = (
(Number(rewardItem?.amount) || 0) + Number(reward.amount)
).toString();
rewards?.set(reward.rewardType, {
rewardType: reward.rewardType,
amount,
});
epoch.assetRewards.set(reward.assetId, {
assetId: reward.assetId,
name: matchingAsset?.name || '',
rewards: rewards || new Map(emptyRowAccountTypes),
totalAmount: (
Number(reward.amount) + Number(assetWithRewards?.totalAmount || 0)
).toString(),
});
}
return acc;
}, map);
};
@@ -21,10 +21,20 @@ fragment DelegationFields on Delegation {
epoch
}
query Rewards($partyId: ID!, $delegationsPagination: Pagination) {
query Rewards(
$partyId: ID!
$fromEpoch: Int
$toEpoch: Int
$rewardsPagination: Pagination
$delegationsPagination: Pagination
) {
party(id: $partyId) {
id
rewardsConnection {
rewardsConnection(
fromEpoch: $fromEpoch
toEpoch: $toEpoch
pagination: $rewardsPagination
) {
edges {
node {
...RewardFields
@@ -39,14 +49,6 @@ query Rewards($partyId: ID!, $delegationsPagination: Pagination) {
}
}
}
epoch {
id
timestamps {
start
end
expiry
}
}
}
fragment EpochRewardSummaryFields on EpochRewardSummary {
@@ -56,7 +58,10 @@ fragment EpochRewardSummaryFields on EpochRewardSummary {
rewardType
}
query EpochAssetsRewards($epochRewardSummariesPagination: Pagination) {
query EpochAssetsRewards(
$epochRewardSummariesFilter: RewardSummaryFilter
$epochRewardSummariesPagination: Pagination
) {
assetsConnection {
edges {
node {
@@ -65,18 +70,16 @@ query EpochAssetsRewards($epochRewardSummariesPagination: Pagination) {
}
}
}
epochRewardSummaries(pagination: $epochRewardSummariesPagination) {
epochRewardSummaries(
filter: $epochRewardSummariesFilter
pagination: $epochRewardSummariesPagination
) {
edges {
node {
...EpochRewardSummaryFields
}
}
}
epoch {
timestamps {
expiry
}
}
}
fragment EpochFields on Epoch {
@@ -9,20 +9,24 @@ export type DelegationFieldsFragment = { __typename?: 'Delegation', amount: stri
export type RewardsQueryVariables = Types.Exact<{
partyId: Types.Scalars['ID'];
fromEpoch?: Types.InputMaybe<Types.Scalars['Int']>;
toEpoch?: Types.InputMaybe<Types.Scalars['Int']>;
rewardsPagination?: Types.InputMaybe<Types.Pagination>;
delegationsPagination?: Types.InputMaybe<Types.Pagination>;
}>;
export type RewardsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, rewardsConnection?: { __typename?: 'RewardsConnection', edges?: Array<{ __typename?: 'RewardEdge', node: { __typename?: 'Reward', rewardType: Types.AccountType, amount: string, percentageOfTotal: string, receivedAt: any, asset: { __typename?: 'Asset', id: string, symbol: string, name: string }, party: { __typename?: 'Party', id: string }, epoch: { __typename?: 'Epoch', id: string } } } | null> | null } | null, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number } } | null> | null } | null } | null, epoch: { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, expiry?: any | null } } };
export type RewardsQuery = { __typename?: 'Query', party?: { __typename?: 'Party', id: string, rewardsConnection?: { __typename?: 'RewardsConnection', edges?: Array<{ __typename?: 'RewardEdge', node: { __typename?: 'Reward', rewardType: Types.AccountType, amount: string, percentageOfTotal: string, receivedAt: any, asset: { __typename?: 'Asset', id: string, symbol: string, name: string }, party: { __typename?: 'Party', id: string }, epoch: { __typename?: 'Epoch', id: string } } } | null> | null } | null, delegationsConnection?: { __typename?: 'DelegationsConnection', edges?: Array<{ __typename?: 'DelegationEdge', node: { __typename?: 'Delegation', amount: string, epoch: number } } | null> | null } | null } | null };
export type EpochRewardSummaryFieldsFragment = { __typename?: 'EpochRewardSummary', epoch: number, assetId: string, amount: string, rewardType: Types.AccountType };
export type EpochAssetsRewardsQueryVariables = Types.Exact<{
epochRewardSummariesFilter?: Types.InputMaybe<Types.RewardSummaryFilter>;
epochRewardSummariesPagination?: Types.InputMaybe<Types.Pagination>;
}>;
export type EpochAssetsRewardsQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string } } | null> | null } | null, epochRewardSummaries?: { __typename?: 'EpochRewardSummaryConnection', edges?: Array<{ __typename?: 'EpochRewardSummaryEdge', node: { __typename?: 'EpochRewardSummary', epoch: number, assetId: string, amount: string, rewardType: Types.AccountType } } | null> | null } | null, epoch: { __typename?: 'Epoch', timestamps: { __typename?: 'EpochTimestamps', expiry?: any | null } } };
export type EpochAssetsRewardsQuery = { __typename?: 'Query', assetsConnection?: { __typename?: 'AssetsConnection', edges?: Array<{ __typename?: 'AssetEdge', node: { __typename?: 'Asset', id: string, name: string } } | null> | null } | null, epochRewardSummaries?: { __typename?: 'EpochRewardSummaryConnection', edges?: Array<{ __typename?: 'EpochRewardSummaryEdge', node: { __typename?: 'EpochRewardSummary', epoch: number, assetId: string, amount: string, rewardType: Types.AccountType } } | null> | null } | null };
export type EpochFieldsFragment = { __typename?: 'Epoch', id: string, timestamps: { __typename?: 'EpochTimestamps', start?: any | null, end?: any | null, expiry?: any | null } };
@@ -75,10 +79,14 @@ export const EpochFieldsFragmentDoc = gql`
}
`;
export const RewardsDocument = gql`
query Rewards($partyId: ID!, $delegationsPagination: Pagination) {
query Rewards($partyId: ID!, $fromEpoch: Int, $toEpoch: Int, $rewardsPagination: Pagination, $delegationsPagination: Pagination) {
party(id: $partyId) {
id
rewardsConnection {
rewardsConnection(
fromEpoch: $fromEpoch
toEpoch: $toEpoch
pagination: $rewardsPagination
) {
edges {
node {
...RewardFields
@@ -93,14 +101,6 @@ export const RewardsDocument = gql`
}
}
}
epoch {
id
timestamps {
start
end
expiry
}
}
}
${RewardFieldsFragmentDoc}
${DelegationFieldsFragmentDoc}`;
@@ -118,6 +118,9 @@ ${DelegationFieldsFragmentDoc}`;
* const { data, loading, error } = useRewardsQuery({
* variables: {
* partyId: // value for 'partyId'
* fromEpoch: // value for 'fromEpoch'
* toEpoch: // value for 'toEpoch'
* rewardsPagination: // value for 'rewardsPagination'
* delegationsPagination: // value for 'delegationsPagination'
* },
* });
@@ -134,7 +137,7 @@ export type RewardsQueryHookResult = ReturnType<typeof useRewardsQuery>;
export type RewardsLazyQueryHookResult = ReturnType<typeof useRewardsLazyQuery>;
export type RewardsQueryResult = Apollo.QueryResult<RewardsQuery, RewardsQueryVariables>;
export const EpochAssetsRewardsDocument = gql`
query EpochAssetsRewards($epochRewardSummariesPagination: Pagination) {
query EpochAssetsRewards($epochRewardSummariesFilter: RewardSummaryFilter, $epochRewardSummariesPagination: Pagination) {
assetsConnection {
edges {
node {
@@ -143,18 +146,16 @@ export const EpochAssetsRewardsDocument = gql`
}
}
}
epochRewardSummaries(pagination: $epochRewardSummariesPagination) {
epochRewardSummaries(
filter: $epochRewardSummariesFilter
pagination: $epochRewardSummariesPagination
) {
edges {
node {
...EpochRewardSummaryFields
}
}
}
epoch {
timestamps {
expiry
}
}
}
${EpochRewardSummaryFieldsFragmentDoc}`;
@@ -170,6 +171,7 @@ export const EpochAssetsRewardsDocument = gql`
* @example
* const { data, loading, error } = useEpochAssetsRewardsQuery({
* variables: {
* epochRewardSummariesFilter: // value for 'epochRewardSummariesFilter'
* epochRewardSummariesPagination: // value for 'epochRewardSummariesPagination'
* },
* });
@@ -114,7 +114,7 @@ export const RewardsPage = () => {
</p>
</div>
<div className="w-[440px]">
<div className="w-[360px]">
<Toggle
name="epoch-reward-view-toggle"
toggles={[
@@ -136,11 +136,15 @@ export const RewardsPage = () => {
</section>
{toggleRewardsView === 'total' ? (
<EpochTotalRewards />
epochData?.epoch ? (
<EpochTotalRewards currentEpoch={epochData?.epoch} />
) : null
) : (
<section>
{pubKey && pubKeys?.length ? (
<EpochIndividualRewards />
epochData?.epoch ? (
<EpochIndividualRewards currentEpoch={epochData?.epoch} />
) : null
) : (
<ConnectToSeeRewards />
)}
@@ -7,9 +7,10 @@ query PreviousEpoch($epochId: ID) {
id
rewardScore {
rawValidatorScore
performanceScore
}
rankingScore {
performanceScore
stakeScore
}
}
}
@@ -8,7 +8,7 @@ export type PreviousEpochQueryVariables = Types.Exact<{
}>;
export type PreviousEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, validatorsConnection?: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string } | null, rankingScore: { __typename?: 'RankingScore', performanceScore: string } } } | null> | null } | null } };
export type PreviousEpochQuery = { __typename?: 'Query', epoch: { __typename?: 'Epoch', id: string, validatorsConnection?: { __typename?: 'NodesConnection', edges?: Array<{ __typename?: 'NodeEdge', node: { __typename?: 'Node', id: string, rewardScore?: { __typename?: 'RewardScore', rawValidatorScore: string, performanceScore: string } | null, rankingScore: { __typename?: 'RankingScore', stakeScore: string } } } | null> | null } | null } };
export const PreviousEpochDocument = gql`
@@ -21,9 +21,10 @@ export const PreviousEpochDocument = gql`
id
rewardScore {
rawValidatorScore
performanceScore
}
rankingScore {
performanceScore
stakeScore
}
}
}
@@ -81,9 +81,10 @@ const MOCK_PREVIOUS_EPOCH: PreviousEpochQuery = {
id: 'ccc022b7e63a4d0a6d3a193c3940c88574060e58a184964c994998d86835a1b4',
rewardScore: {
rawValidatorScore: '0.25',
performanceScore: '0.9998677767864936',
},
rankingScore: {
performanceScore: '0.9998677767864936',
stakeScore: '0.2499583402766206',
},
},
},
@@ -92,9 +93,10 @@ const MOCK_PREVIOUS_EPOCH: PreviousEpochQuery = {
id: '966438c6bffac737cfb08173ffcb3f393c4692b099ad80cb45a82e2dc0a8cf99',
rewardScore: {
rawValidatorScore: '0.3',
performanceScore: '1',
},
rankingScore: {
performanceScore: '1',
stakeScore: '0.25',
},
},
},
@@ -103,9 +105,10 @@ const MOCK_PREVIOUS_EPOCH: PreviousEpochQuery = {
id: '12c81b738e8051152e1afe44376ec37bca9216466e6d44cdd772194bad0ada81',
rewardScore: {
rawValidatorScore: '0.35',
performanceScore: '0.999629748500531',
},
rankingScore: {
performanceScore: '0.999629748500531',
stakeScore: '0.2312',
},
},
},
@@ -10,7 +10,6 @@ import {
getFormattedPerformanceScore,
getLastEpochScoreAndPerformance,
getNormalisedVotingPower,
getOverstakedAmount,
getOverstakingPenalty,
getPerformancePenalty,
getTotalPenalties,
@@ -52,7 +51,6 @@ interface CanonisedConsensusNodeProps {
[ValidatorFields.STAKED_BY_OPERATOR]: string;
[ValidatorFields.PERFORMANCE_SCORE]: string;
[ValidatorFields.PERFORMANCE_PENALTY]: string;
[ValidatorFields.OVERSTAKED_AMOUNT]: string;
[ValidatorFields.OVERSTAKING_PENALTY]: string;
[ValidatorFields.TOTAL_PENALTIES]: string;
[ValidatorFields.PENDING_STAKE]: string;
@@ -164,14 +162,11 @@ export const ConsensusValidatorsTable = ({
pendingUserStake,
userStakeShare,
}) => {
const { rawValidatorScore, performanceScore } =
getLastEpochScoreAndPerformance(previousEpochData, id);
const overstakedAmount = getOverstakedAmount(
rawValidatorScore,
stakedTotal,
totalStake
);
const {
rawValidatorScore: previousEpochValidatorScore,
performanceScore: previousEpochPerformanceScore,
stakeScore: previousEpochStakeScore,
} = getLastEpochScoreAndPerformance(previousEpochData, id);
return {
id,
@@ -184,7 +179,7 @@ export const ConsensusValidatorsTable = ({
[ValidatorFields.NORMALISED_VOTING_POWER]:
getNormalisedVotingPower(votingPower),
[ValidatorFields.UNNORMALISED_VOTING_POWER]:
getUnnormalisedVotingPower(rawValidatorScore),
getUnnormalisedVotingPower(previousEpochValidatorScore),
[ValidatorFields.STAKE_SHARE]: stakedTotalPercentage(stakeScore),
[ValidatorFields.STAKED_BY_DELEGATES]: formatNumber(
toBigNum(stakedByDelegates, decimals),
@@ -194,18 +189,19 @@ export const ConsensusValidatorsTable = ({
toBigNum(stakedByOperator, decimals),
2
),
[ValidatorFields.PERFORMANCE_SCORE]:
getFormattedPerformanceScore(performanceScore).toString(),
[ValidatorFields.PERFORMANCE_PENALTY]:
getPerformancePenalty(performanceScore),
[ValidatorFields.OVERSTAKED_AMOUNT]: overstakedAmount.toString(),
[ValidatorFields.PERFORMANCE_SCORE]: getFormattedPerformanceScore(
previousEpochPerformanceScore
).toString(),
[ValidatorFields.PERFORMANCE_PENALTY]: getPerformancePenalty(
previousEpochPerformanceScore
),
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
overstakedAmount,
totalStake
previousEpochValidatorScore,
previousEpochStakeScore
),
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
rawValidatorScore,
performanceScore,
previousEpochValidatorScore,
previousEpochPerformanceScore,
stakedTotal,
totalStake
),
@@ -7,7 +7,6 @@ import { BigNumber } from '../../../../lib/bignumber';
import {
getFormattedPerformanceScore,
getLastEpochScoreAndPerformance,
getOverstakedAmount,
getOverstakingPenalty,
getPerformancePenalty,
getTotalPenalties,
@@ -82,21 +81,21 @@ export const StandbyPendingValidatorsTable = ({
pendingUserStake,
userStakeShare,
}) => {
const { rawValidatorScore, performanceScore } =
getLastEpochScoreAndPerformance(previousEpochData, id);
const {
rawValidatorScore: previousEpochValidatorScore,
performanceScore: previousEpochPerformanceScore,
stakeScore: previousEpochStakeScore,
} = getLastEpochScoreAndPerformance(previousEpochData, id);
const overstakedAmount = getOverstakedAmount(
rawValidatorScore,
stakedTotal,
totalStake
);
let individualStakeNeededForPromotion,
individualStakeNeededForPromotionDescription;
if (stakeNeededForPromotion && performanceScore) {
if (stakeNeededForPromotion && previousEpochPerformanceScore) {
const stakedTotalBigNum = new BigNumber(stakedTotal);
const stakeNeededBigNum = new BigNumber(stakeNeededForPromotion);
const performanceScoreBigNum = new BigNumber(performanceScore);
const performanceScoreBigNum = new BigNumber(
previousEpochPerformanceScore
);
const calc = stakeNeededBigNum
.dividedBy(performanceScoreBigNum)
@@ -142,18 +141,19 @@ export const StandbyPendingValidatorsTable = ({
toBigNum(stakedByOperator, decimals),
2
),
[ValidatorFields.PERFORMANCE_SCORE]:
getFormattedPerformanceScore(performanceScore).toString(),
[ValidatorFields.PERFORMANCE_PENALTY]:
getPerformancePenalty(performanceScore),
[ValidatorFields.OVERSTAKED_AMOUNT]: overstakedAmount.toString(),
[ValidatorFields.PERFORMANCE_SCORE]: getFormattedPerformanceScore(
previousEpochPerformanceScore
).toString(),
[ValidatorFields.PERFORMANCE_PENALTY]: getPerformancePenalty(
previousEpochPerformanceScore
),
[ValidatorFields.OVERSTAKING_PENALTY]: getOverstakingPenalty(
overstakedAmount,
totalStake
previousEpochValidatorScore,
previousEpochStakeScore
),
[ValidatorFields.TOTAL_PENALTIES]: getTotalPenalties(
rawValidatorScore,
performanceScore,
previousEpochValidatorScore,
previousEpochPerformanceScore,
stakedTotal,
totalStake
),
@@ -155,16 +155,16 @@ export const ValidatorTables = ({
return (
<section data-testid="validator-tables">
<div className="grid w-full justify-end">
<div className="w-[400px]">
<div className="w-[340px]">
<Toggle
name="validators-view-toggle"
toggles={[
{
label: t('ALL VALIDATORS'),
label: t('All validators'),
value: 'all',
},
{
label: t('STAKED BY ME'),
label: t('Staked by me'),
value: 'myStake',
},
]}
@@ -20,7 +20,6 @@ import { SubHeading } from '../../../components/heading';
import {
getLastEpochScoreAndPerformance,
getNormalisedVotingPower,
getOverstakedAmount,
getOverstakingPenalty,
getPerformancePenalty,
getTotalPenalties,
@@ -75,15 +74,9 @@ export const ValidatorTable = ({
const stakedOnNode = toBigNum(node.stakedTotal, decimals);
const { rawValidatorScore, performanceScore } =
const { rawValidatorScore, performanceScore, stakeScore } =
getLastEpochScoreAndPerformance(previousEpochData, node.id);
const overstakedAmount = getOverstakedAmount(
rawValidatorScore,
stakedTotal,
node.stakedTotal
);
const stakePercentage = getStakePercentage(total, stakedOnNode);
const totalPenaltiesAmount = getTotalPenalties(
@@ -245,7 +238,7 @@ export const ValidatorTable = ({
<Tooltip description={t('OverstakedPenaltyDescription')}>
<span data-testid="overstaking-penalty">
{getOverstakingPenalty(overstakedAmount, node.stakedTotal)}
{getOverstakingPenalty(rawValidatorScore, stakeScore)}
</span>
</Tooltip>
</KeyValueTableRow>
@@ -4,7 +4,6 @@ import {
getNormalisedVotingPower,
getUnnormalisedVotingPower,
getOverstakingPenalty,
getOverstakedAmount,
getFormattedPerformanceScore,
getPerformancePenalty,
getTotalPenalties,
@@ -22,9 +21,10 @@ describe('getLastEpochScoreAndPerformance', () => {
id: '0x123',
rewardScore: {
rawValidatorScore: '0.25',
performanceScore: '0.75',
},
rankingScore: {
performanceScore: '0.75',
stakeScore: '0.25',
},
},
},
@@ -33,9 +33,10 @@ describe('getLastEpochScoreAndPerformance', () => {
id: '0x234',
rewardScore: {
rawValidatorScore: '0.35',
performanceScore: '0.85',
},
rankingScore: {
performanceScore: '0.85',
stakeScore: '0.25',
},
},
},
@@ -50,12 +51,14 @@ describe('getLastEpochScoreAndPerformance', () => {
).toEqual({
rawValidatorScore: '0.25',
performanceScore: '0.75',
stakeScore: '0.25',
});
expect(
getLastEpochScoreAndPerformance(mockPreviousEpochData, '0x234')
).toEqual({
rawValidatorScore: '0.35',
performanceScore: '0.85',
stakeScore: '0.25',
});
});
});
@@ -79,40 +82,34 @@ describe('getUnnormalisedVotingPower', () => {
});
describe('getOverstakingPenalty', () => {
it('should return the overstaking penalty', () => {
expect(
getOverstakingPenalty(new BigNumber(100), Number(1000).toString())
).toEqual('10.00%');
expect(
getOverstakingPenalty(new BigNumber(500), Number(2000).toString())
).toEqual('25.00%');
});
});
describe('getOverstakedAmount', () => {
it('should return the overstaked amount', () => {
expect(
// If a validator score is 0, any amount staked on the node is considered overstaked
getOverstakedAmount('0', Number(100).toString(), Number(20).toString())
).toEqual(new BigNumber(20));
expect(
getOverstakedAmount('0.05', Number(100).toString(), Number(20).toString())
).toEqual(new BigNumber(15));
expect(
getOverstakedAmount('0.1', Number(100).toString(), Number(20).toString())
).toEqual(new BigNumber(10));
expect(
getOverstakedAmount('0.15', Number(100).toString(), Number(20).toString())
).toEqual(new BigNumber(5));
expect(
getOverstakedAmount('0.2', Number(100).toString(), Number(20).toString())
).toEqual(new BigNumber(0));
it('returns "0%" when both arguments are null or undefined', () => {
expect(getOverstakingPenalty(null, null)).toBe('0%');
expect(getOverstakingPenalty(undefined, undefined)).toBe('0%');
expect(getOverstakingPenalty(null, undefined)).toBe('0%');
expect(getOverstakingPenalty(undefined, null)).toBe('0%');
});
it('should return 0 if the overstaked amount is negative', () => {
expect(
getOverstakedAmount('0.8', Number(100).toString(), Number(20).toString())
).toEqual(new BigNumber(0));
it('returns "0%" when one argument is null or undefined', () => {
expect(getOverstakingPenalty('10', null)).toBe('0%');
expect(getOverstakingPenalty(null, '20')).toBe('0%');
expect(getOverstakingPenalty('10', undefined)).toBe('0%');
expect(getOverstakingPenalty(undefined, '20')).toBe('0%');
});
it('returns "0%" when validatorScore or stakeScore is zero', () => {
expect(getOverstakingPenalty('0', '20')).toBe('0%');
expect(getOverstakingPenalty('10', '0')).toBe('0%');
});
it('returns the correct overstaking penalty', () => {
expect(getOverstakingPenalty('0.18', '0.2')).toBe('10.00%');
expect(getOverstakingPenalty('0.2', '0.2')).toBe('0.00%');
expect(getOverstakingPenalty('0.04', '0.2')).toBe('80.00%');
});
it('handles string numbers with decimals', () => {
expect(getOverstakingPenalty('7.5', '15')).toBe('50.00%');
expect(getOverstakingPenalty('12.5', '25')).toBe('50.00%');
});
});
+16 -20
View File
@@ -15,7 +15,8 @@ export const getLastEpochScoreAndPerformance = (
return {
rawValidatorScore: validator?.rewardScore?.rawValidatorScore,
performanceScore: validator?.rankingScore?.performanceScore,
performanceScore: validator?.rewardScore?.performanceScore,
stakeScore: validator?.rankingScore?.stakeScore,
};
};
@@ -42,31 +43,26 @@ export const getPerformancePenalty = (performanceScore?: string) =>
2
);
export const getOverstakedAmount = (
validatorScore: string | null | undefined,
totalStake: string,
stakedOnNode: string
) => {
const toReturn = validatorScore
? new BigNumber(stakedOnNode).minus(
new BigNumber(validatorScore).times(new BigNumber(totalStake))
)
: new BigNumber(0);
return toReturn.isNegative() ? new BigNumber(0) : toReturn;
};
export const getOverstakingPenalty = (
overstakedAmount: BigNumber,
stakedOnNode: string
validatorScore: string | null | undefined,
stakeScore: string | null | undefined
) => {
if (!validatorScore || !stakeScore) {
return '0%';
}
// avoid division by zero
if (new BigNumber(stakedOnNode).isZero() || overstakedAmount.isZero()) {
return '0';
if (
new BigNumber(validatorScore).isZero() ||
new BigNumber(stakeScore).isZero()
) {
return '0%';
}
return formatNumberPercentage(
overstakedAmount.dividedBy(new BigNumber(stakedOnNode)).times(100),
new BigNumber(1)
.minus(new BigNumber(validatorScore).dividedBy(new BigNumber(stakeScore)))
.times(100),
2
);
};
@@ -14,6 +14,7 @@ import { TokenDetailsCirculating } from './token-details-circulating';
import { SplashLoader } from '../../../components/splash-loader';
import { useEthereumConfig } from '@vegaprotocol/web3';
import { useContracts } from '../../../contexts/contracts/contracts-context';
import { ENV } from '../../../config';
export const TokenDetails = ({
totalSupply,
@@ -49,6 +50,9 @@ export const TokenDetails = ({
);
}
const tokenVestingContractAddress =
config.token_vesting_contract?.address || ENV.addresses.tokenVestingAddress;
return (
<div className="token-details">
<RoundedWrapper>
@@ -65,18 +69,20 @@ export const TokenDetails = ({
{token.address}
</Link>
</KeyValueTableRow>
<KeyValueTableRow>
{t('Vesting contract').toUpperCase()}
<Link
data-testid="token-contract"
title={t('View on Etherscan (opens in a new tab)')}
className="font-mono text-white text-right"
href={`${ETHERSCAN_URL}/address/${config.token_vesting_contract.address}`}
target="_blank"
>
{config.token_vesting_contract.address}
</Link>
</KeyValueTableRow>
{tokenVestingContractAddress && (
<KeyValueTableRow>
{t('Vesting contract').toUpperCase()}
<Link
data-testid="token-contract"
title={t('View on Etherscan (opens in a new tab)')}
className="font-mono text-white text-right"
href={`${ETHERSCAN_URL}/address/${tokenVestingContractAddress}`}
target="_blank"
>
{tokenVestingContractAddress}
</Link>
</KeyValueTableRow>
)}
<KeyValueTableRow>
{t('Total supply').toUpperCase()}
<span className="font-mono" data-testid="total-supply">
-5
View File
@@ -1,5 +0,0 @@
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
NX_VEGA_URL=https://api.sandbox.vega.xyz/graphql
NX_VEGA_ENV=SANDBOX
NX_VEGA_NETWORKS={\"DEVNET\":\"https://dev.token.vega.xyz\",\"STAGNET3\":\"https://stagnet3.token.vega.xyz\",\"STAGNET1\":\"https://stagnet1.token.vega.xyz\",\"TESTNET\":\"https://token.fairground.wtf\",\"MAINNET\":\"https://token.vega.xyz\"}
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/sandbox/vegawallet-sandbox.toml
File diff suppressed because it is too large Load Diff
@@ -1,3 +0,0 @@
{
"hosts": ["https://api-n00.mainnet-mirror.vega.rocks/graphql"]
}
@@ -1,3 +0,0 @@
{
"hosts": ["https://api-n01.sandbox.vega.rocks/graphql"]
}
+2
View File
@@ -1,8 +1,10 @@
const { defineConfig } = require('cypress');
module.exports = defineConfig({
reporter: '../../node_modules/cypress-mochawesome-reporter',
e2e: {
setupNodeEvents(on, config) {
require('cypress-mochawesome-reporter/plugin')(on);
require('@cypress/grep/src/plugin')(config);
return config;
},
@@ -282,7 +282,6 @@ describe('capsule', { tags: '@slow' }, () => {
});
});
});
// comment because of bug #2695
it('can edit order', function () {
cy.getByTestId(ordersTab).click();
cy.getByTestId('edit').first().should('be.visible').click();
@@ -412,6 +411,7 @@ describe('capsule', { tags: '@slow' }, () => {
it('approved amount is less than deposit', function () {
// 1001-DEPO-006
// 1001-DEPO-007
cy.getByTestId(depositsTab).click();
cy.getByTestId('deposit-button').click();
cy.get(assetSelectField, txTimeout).select(btcName, { force: true });
@@ -431,8 +431,8 @@ describe('capsule', { tags: '@slow' }, () => {
});
it('withdraw - delay verification', function () {
// 1001-DEPO-007
// 1001-DEPO-024
// 1002-WITH-007
cy.visit('/#/portfolio');
cy.get('main[data-testid="/portfolio"]').should('exist');
+14 -1
View File
@@ -56,6 +56,15 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
);
});
it('test', () => {
cy.getByTestId('enter-pubkey-manually').click();
cy.get(toAddressField).clear().type('INVALID_DEPOSIT_TO_ADDRESS');
cy.get(`[data-testid="${formFieldError}"][aria-describedby="to"]`).should(
'have.text',
'Invalid Vega key'
);
});
it('invalid amount', () => {
mockWeb3DepositCalls({
allowance: '1000',
@@ -76,6 +85,7 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
});
it('insufficient funds', () => {
// 1001-DEPO-004
mockWeb3DepositCalls({
allowance: '1000',
depositLifetimeLimit: '1000',
@@ -87,7 +97,10 @@ describe('deposit form validation', { tags: '@smoke' }, () => {
.clear()
.type('850')
.next(`[data-testid="${formFieldError}"]`)
.should('have.text', 'Insufficient amount in Ethereum wallet');
.should(
'have.text',
"You can't deposit more than you have in your Ethereum wallet, 800 tEURO"
);
});
});
@@ -52,6 +52,8 @@ describe('Console - market list - live env', { tags: '@live' }, () => {
describe('Console - market info - live env', { tags: '@live' }, () => {
before(() => {
cy.visit('/');
cy.contains('Loading market data...').should('not.exist');
cy.getByTestId('link').should('be.visible');
cy.getByTestId('dialog-close').click();
cy.getByTestId(marketInfoBtn).click();
});
@@ -68,17 +70,20 @@ describe('Console - market info - live env', { tags: '@live' }, () => {
'Risk model',
'Risk parameters',
'Risk factors',
'Price monitoring trigger 1',
'Price monitoring bounds 1',
'Liquidity monitoring parameters',
'Liquidity',
'Liquidity price range',
'Oracle',
'Proposal',
];
it('market info titles are displayed', () => {
cy.get('.text-lg').each((element, index) => {
cy.wrap(element).should('have.text', titles[index]);
});
cy.getByTestId('split-view-view')
.find('.text-lg')
.each((element, index) => {
cy.wrap(element).should('have.text', titles[index]);
});
});
it('market info subtitles are displayed', () => {
@@ -90,6 +95,16 @@ describe('Console - market info - live env', { tags: '@live' }, () => {
cy.wrap(element).should('have.text', subtitles[index]);
});
});
it('renders correctly liquidity in trading tab', () => {
cy.getByTestId('Liquidity').click();
cy.contains('Loading').should('not.exist');
cy.contains('Something went wrong').should('not.exist');
cy.contains('Application error').should('not.exist');
cy.getByTestId('tab-liquidity').within(() => {
cy.get('[col-id="party.id"]').eq(1).should('not.be.empty');
});
});
});
describe('Console - market summary - live env', { tags: '@live' }, () => {
@@ -205,6 +220,8 @@ describe('Console - markets table - live env', { tags: '@live' }, () => {
});
function openMarketDropDown() {
cy.contains('Loading...').should('not.exist');
cy.getByTestId('link').should('be.visible');
cy.getByTestId('dialog-close').click();
cy.getByTestId('popover-trigger').click();
cy.contains('Loading market data...').should('not.exist');
@@ -39,7 +39,7 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
it('market volume displayed', () => {
cy.getByTestId(marketTitle).contains('Market volume').click();
validateMarketDataRow(0, '24 Hour Volume', '1');
validateMarketDataRow(1, 'Open Interest', '0');
validateMarketDataRow(1, 'Open Interest', '-');
validateMarketDataRow(2, 'Best Bid Volume', '1');
validateMarketDataRow(3, 'Best Offer Volume', '3');
validateMarketDataRow(4, 'Best Static Bid Volume', '2');
@@ -75,8 +75,7 @@ describe('market info is displayed', { tags: '@smoke' }, () => {
validateMarketDataRow(3, 'Quote Name', 'BTC');
});
// need to check why data are not visible
it.skip('settlement asset displayed', () => {
it('settlement asset displayed', () => {
cy.getByTestId(marketTitle).contains('Settlement asset').click();
cy.window().then((win) => {
cy.stub(win, 'prompt').returns('DISABLED WINDOW PROMPT');
+81 -1
View File
@@ -1,5 +1,5 @@
import * as Schema from '@vegaprotocol/types';
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { aliasGQLQuery, checkSorting } from '@vegaprotocol/cypress';
import { marketsQuery } from '@vegaprotocol/mock';
import { getDateTimeFormat } from '@vegaprotocol/utils';
@@ -85,6 +85,7 @@ describe('markets table', { tags: '@smoke' }, () => {
cy.getByTestId('view-market-list-link')
.should('have.attr', 'href', '#/markets/all')
.click();
cy.get('[data-testid="All markets"]').should(
'have.attr',
'data-state',
@@ -117,6 +118,85 @@ describe('markets table', { tags: '@smoke' }, () => {
`${Cypress.env('VEGA_TOKEN_URL')}/proposals/propose/new-market`
);
});
it('proposed markets tab should be sorted properly', () => {
cy.getByTestId('view-market-list-link').click();
cy.get('[data-testid="Proposed markets"]').click();
const marketColDefault = [
'ETHUSD',
'LINKUSD',
'ETHUSD',
'ETHDAI.MF21',
'AAPL.MF21',
'BTCUSD.MF21',
'TSLA.QM21',
'AAVEDAI.MF21',
'ETHBTC.QM21',
'UNIDAI.MF21',
];
const marketColAsc = [
'AAPL.MF21',
'AAVEDAI.MF21',
'BTCUSD.MF21',
'ETHBTC.QM21',
'ETHDAI.MF21',
'ETHUSD',
'ETHUSD',
'LINKUSD',
'TSLA.QM21',
'UNIDAI.MF21',
];
const marketColDesc = [
'UNIDAI.MF21',
'TSLA.QM21',
'LINKUSD',
'ETHUSD',
'ETHUSD',
'ETHDAI.MF21',
'ETHBTC.QM21',
'BTCUSD.MF21',
'AAVEDAI.MF21',
'AAPL.MF21',
];
checkSorting('market', marketColDefault, marketColAsc, marketColDesc);
const stateColDefault = [
'Open',
'Passed',
'Waiting for Node Vote',
'Open',
'Passed',
'Open',
'Passed',
'Open',
'Waiting for Node Vote',
'Open',
];
const stateColAsc = [
'Open',
'Open',
'Open',
'Open',
'Open',
'Passed',
'Passed',
'Passed',
'Waiting for Node Vote',
'Waiting for Node Vote',
];
const stateColDesc = [
'Waiting for Node Vote',
'Waiting for Node Vote',
'Passed',
'Passed',
'Passed',
'Open',
'Open',
'Open',
'Open',
'Open',
];
checkSorting('state', stateColDefault, stateColAsc, stateColDesc);
});
it('opening auction subsets should be properly displayed', () => {
cy.mockTradingPage(
@@ -41,6 +41,12 @@ describe('accounts', { tags: '@smoke' }, () => {
.should('have.text', '100,001.01');
});
it('asset detail should be properly rendered', () => {
cy.getByTestId('Collateral').click();
cy.getByTestId('asset').contains('tEURO').click();
cy.get('[data-testid$="_label"]').should('have.length', 16);
});
describe('sorting by ag-grid columns should work well', () => {
it('sorting by asset', () => {
cy.getByTestId('Collateral').click();
@@ -0,0 +1,28 @@
describe('chart', { tags: '@smoke' }, () => {
beforeEach(() => {
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
it('config should persist', () => {
cy.getByTestId('Chart').click();
cy.get('[data-testid="tab-chart"] button').as('control-buttons');
cy.get('@control-buttons').each(($button) => {
cy.wrap($button).click();
cy.get(
'[role="menuitemradio"]:first, [role="menuitemcheckbox"]:first'
).click();
});
cy.getByTestId('Depth').click();
cy.getByTestId('Chart').click();
cy.get('@control-buttons').each(($button) => {
cy.wrap($button).click();
cy.get('[role="menuitemradio"]:first, [role="menuitemcheckbox"]:first')
.within(($lastMenuItem) => {
expect($lastMenuItem.data('state')).to.equal('checked');
})
.click();
});
});
});
@@ -1,5 +1,5 @@
import * as Schema from '@vegaprotocol/types';
import { aliasGQLQuery, mockConnectWallet } from '@vegaprotocol/cypress';
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { testOrderSubmission } from '../support/order-validation';
import type { OrderSubmission } from '@vegaprotocol/wallet';
import {
@@ -13,8 +13,6 @@ const orderSizeField = 'order-size';
const orderPriceField = 'order-price';
const orderTIFDropDown = 'order-tif';
const placeOrderBtn = 'place-order';
const toggleShort = 'order-side-SIDE_SELL';
const toggleLong = 'order-side-SIDE_BUY';
const toggleLimit = 'order-type-TYPE_LIMIT';
const toggleMarket = 'order-type-TYPE_MARKET';
@@ -32,34 +30,6 @@ const displayTomorrow = () => {
return tomorrow.toISOString().substring(0, 16);
};
describe('time in force default values', () => {
before(() => {
cy.setVegaWallet();
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
it('must have market order set up to IOC by default', function () {
// 7002-SORD-031
cy.getByTestId(toggleMarket).click();
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
TIFlist.filter((item) => item.code === 'IOC')[0].text
);
});
it('must have time in force set to GTC for limit order', function () {
// 7002-SORD-031
cy.getByTestId(toggleLimit).click();
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
TIFlist.filter((item) => item.code === 'GTC')[0].text
);
});
});
describe('must submit order', { tags: '@smoke' }, () => {
// 7002-SORD-039
before(() => {
@@ -84,6 +54,8 @@ describe('must submit order', { tags: '@smoke' }, () => {
type: Schema.OrderType.TYPE_MARKET,
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_FOK,
postOnly: false,
reduceOnly: false,
size: '100',
};
createOrder(order);
@@ -98,6 +70,8 @@ describe('must submit order', { tags: '@smoke' }, () => {
side: Schema.Side.SIDE_SELL,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_IOC,
size: '100',
postOnly: false,
reduceOnly: false,
};
createOrder(order);
testOrderSubmission(order);
@@ -112,6 +86,8 @@ describe('must submit order', { tags: '@smoke' }, () => {
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
size: '100',
postOnly: false,
reduceOnly: false,
price: '200',
};
createOrder(order);
@@ -126,6 +102,8 @@ describe('must submit order', { tags: '@smoke' }, () => {
side: Schema.Side.SIDE_SELL,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GFN,
size: '100',
postOnly: false,
reduceOnly: false,
price: '50000',
};
createOrder(order);
@@ -143,6 +121,8 @@ describe('must submit order', { tags: '@smoke' }, () => {
size: '100',
price: '1.00',
expiresAt: expiresAt.toISOString().substring(0, 16),
postOnly: false,
reduceOnly: false,
};
createOrder(order);
@@ -150,6 +130,8 @@ describe('must submit order', { tags: '@smoke' }, () => {
price: '100000',
expiresAt:
new Date(order.expiresAt as string).getTime().toString() + '000000',
postOnly: false,
reduceOnly: false,
});
});
});
@@ -182,6 +164,8 @@ describe(
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
size: '100',
postOnly: false,
reduceOnly: false,
price: '200',
};
createOrder(order);
@@ -196,6 +180,8 @@ describe(
side: Schema.Side.SIDE_SELL,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
size: '100',
postOnly: false,
reduceOnly: false,
price: '50000',
};
createOrder(order);
@@ -210,12 +196,16 @@ describe(
side: Schema.Side.SIDE_SELL,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTT,
size: '100',
postOnly: false,
reduceOnly: false,
price: '1.00',
expiresAt: displayTomorrow(),
};
createOrder(order);
testOrderSubmission(order, {
price: '100000',
postOnly: false,
reduceOnly: false,
expiresAt:
new Date(order.expiresAt as string).getTime().toString() + '000000',
});
@@ -251,6 +241,8 @@ describe(
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
size: '100',
postOnly: false,
reduceOnly: false,
price: '200',
};
createOrder(order);
@@ -265,6 +257,8 @@ describe(
side: Schema.Side.SIDE_SELL,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
size: '100',
postOnly: false,
reduceOnly: false,
price: '50000',
};
createOrder(order);
@@ -281,6 +275,8 @@ describe(
size: '100',
price: '1.00',
expiresAt: displayTomorrow(),
postOnly: false,
reduceOnly: false,
};
createOrder(order);
testOrderSubmission(order, {
@@ -320,6 +316,8 @@ describe(
side: Schema.Side.SIDE_BUY,
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
size: '100',
postOnly: false,
reduceOnly: false,
price: '200',
};
createOrder(order);
@@ -335,6 +333,8 @@ describe(
timeInForce: Schema.OrderTimeInForce.TIME_IN_FORCE_GTC,
size: '100',
price: '50000',
postOnly: false,
reduceOnly: false,
};
createOrder(order);
testOrderSubmission(order, { price: '5000000000' });
@@ -350,6 +350,8 @@ describe(
size: '100',
price: '1.00',
expiresAt: displayTomorrow(),
postOnly: false,
reduceOnly: false,
};
createOrder(order);
testOrderSubmission(order, {
@@ -361,227 +363,6 @@ describe(
}
);
describe('deal ticket validation', { tags: '@smoke' }, () => {
beforeEach(() => {
cy.mockTradingPage();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
it('must show place order button and connect wallet if wallet is not connected', () => {
// 0003-WTXN-001
cy.getByTestId('connect-vega-wallet'); // Not connected
cy.getByTestId('order-connect-wallet').should('exist');
cy.getByTestId(placeOrderBtn).should('exist');
cy.getByTestId('deal-ticket-connect-wallet').should('exist');
});
it('must be able to select order direction - long/short', function () {
// 7002-SORD-004
cy.getByTestId(toggleShort).click().children('input').should('be.checked');
cy.getByTestId(toggleLong).click().children('input').should('be.checked');
});
it('must be able to select order type - limit/market', function () {
// 7002-SORD-005
// 7002-SORD-006
// 7002-SORD-007
cy.getByTestId(toggleLimit).click().children('input').should('be.checked');
cy.getByTestId(toggleMarket).click().children('input').should('be.checked');
});
it('order connect vega wallet button should connect', () => {
mockConnectWallet();
cy.getByTestId(toggleLimit).click();
cy.getByTestId(orderPriceField).clear().type('101');
cy.getByTestId('order-connect-wallet').click();
cy.getByTestId('dialog-content').should('be.visible');
cy.getByTestId('connectors-list')
.find('[data-testid="connector-jsonRpc"]')
.click();
cy.wait('@walletReq');
cy.getByTestId(placeOrderBtn).should('be.visible');
cy.getByTestId(toggleLimit).children('input').should('be.checked');
cy.getByTestId(orderPriceField).should('have.value', '101');
});
});
describe('deal ticket size validation', { tags: '@smoke' }, function () {
beforeEach(() => {
cy.setVegaWallet();
cy.mockTradingPage();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
it('must warn if order size input has too many digits after the decimal place', function () {
// 7002-SORD-016
cy.getByTestId('order-type-TYPE_MARKET').click();
cy.getByTestId(orderSizeField).clear().type('1.234');
cy.getByTestId(placeOrderBtn).should('not.be.disabled');
cy.getByTestId(placeOrderBtn).click();
cy.getByTestId(placeOrderBtn).should('be.disabled');
cy.getByTestId('dealticket-error-message-size-market').should(
'have.text',
'Size must be whole numbers for this market'
);
});
it('must warn if order size is set to 0', function () {
cy.getByTestId('order-type-TYPE_MARKET').click();
cy.getByTestId(orderSizeField).clear().type('0');
cy.getByTestId(placeOrderBtn).should('not.be.disabled');
cy.getByTestId(placeOrderBtn).click();
cy.getByTestId(placeOrderBtn).should('be.disabled');
cy.getByTestId('dealticket-error-message-size-market').should(
'have.text',
'Size cannot be lower than 1'
);
});
});
describe('limit order validations', { tags: '@smoke' }, () => {
before(() => {
cy.setVegaWallet();
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
cy.getByTestId(toggleLimit).click();
});
beforeEach(() => {
cy.setVegaWallet();
});
it('must see the price unit', function () {
// 7002-SORD-018
cy.getByTestId(orderPriceField)
.siblings('label')
.should('have.text', 'Price (DAI)');
});
it('must see warning when placing an order with expiry date in past', () => {
const expiresAt = new Date(Date.now() - 24 * 60 * 60 * 1000);
const expiresAtInputValue = expiresAt.toISOString().substring(0, 16);
cy.getByTestId(toggleLimit).click();
cy.getByTestId(orderPriceField).clear().type('0.1');
cy.getByTestId(orderSizeField).clear().type('1');
cy.getByTestId(orderTIFDropDown).select('TIME_IN_FORCE_GTT');
cy.log('choosing yesterday');
cy.getByTestId('date-picker-field').type(expiresAtInputValue);
cy.getByTestId(placeOrderBtn).click();
cy.getByTestId('dealticket-error-message-expiry').should(
'have.text',
'The expiry date that you have entered appears to be in the past'
);
});
it('must see warning if price has too many digits after decimal place', function () {
// 7002-SORD-059
cy.getByTestId(toggleLimit).click();
cy.getByTestId(orderTIFDropDown).select('TIME_IN_FORCE_GTC');
cy.getByTestId(orderSizeField).clear().type('1');
cy.getByTestId(orderPriceField).clear().type('1.123456');
cy.getByTestId('dealticket-error-message-price-limit').should(
'have.text',
'Price accepts up to 5 decimal places'
);
});
describe('time in force validations', function () {
const validTIF = TIFlist;
validTIF.forEach((tif) => {
// 7002-SORD-023
// 7002-SORD-024
// 7002-SORD-025
// 7002-SORD-026
// 7002-SORD-027
// 7002-SORD-028
it(`must be able to select ${tif.code}`, function () {
cy.getByTestId(orderTIFDropDown).select(tif.value);
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
tif.text
);
});
});
it('selections should be remembered', () => {
cy.getByTestId(orderTIFDropDown).select('TIME_IN_FORCE_GTT');
cy.getByTestId(toggleMarket).click();
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
TIFlist.filter((item) => item.code === 'IOC')[0].text
);
cy.getByTestId(orderTIFDropDown).select('TIME_IN_FORCE_FOK');
cy.getByTestId(toggleLimit).click();
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
TIFlist.filter((item) => item.code === 'GTT')[0].text
);
cy.getByTestId(toggleMarket).click();
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
TIFlist.filter((item) => item.code === 'FOK')[0].text
);
});
});
});
describe('market order validations', { tags: '@smoke' }, () => {
before(() => {
cy.setVegaWallet();
cy.mockTradingPage();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
cy.getByTestId(toggleMarket).click();
});
beforeEach(() => {
cy.setVegaWallet();
});
it('must not see the price unit', function () {
// 7002-SORD-019
cy.getByTestId(orderPriceField).should('not.exist');
});
describe('time in force validations', function () {
const validTIF = TIFlist.filter((tif) => ['FOK', 'IOC'].includes(tif.code));
const invalidTIF = TIFlist.filter(
(tif) => !['FOK', 'IOC'].includes(tif.code)
);
validTIF.forEach((tif) => {
// 7002-SORD-025
// 7002-SORD-026
it(`must be able to select ${tif.code}`, function () {
cy.getByTestId(orderTIFDropDown).select(tif.value);
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
tif.text
);
});
});
invalidTIF.forEach((tif) => {
// 7002-SORD-023
// 7002-SORD-024
// 7002-SORD-027
// 7002-SORD-028
it(`must not be able to select ${tif.code}`, function () {
cy.getByTestId(orderTIFDropDown).should('not.contain', tif.text);
});
});
});
});
describe('suspended market validation', { tags: '@regression' }, () => {
before(() => {
cy.setVegaWallet();
@@ -733,6 +514,8 @@ describe('account validation', { tags: '@regression' }, () => {
it('must show error returned by wallet ', () => {
// 0003-WTXN-009
// 0003-WTXN-011
// 0002-WCON-016
// 0003-WTXN-008
//trigger error from the wallet
cy.intercept('POST', 'http://localhost:1789/api/v2/requests', (req) => {
@@ -756,6 +539,8 @@ describe('account validation', { tags: '@regression' }, () => {
'contain.text',
'The connection to your Vega Wallet has been lost.'
);
cy.getByTestId('connect-vega-wallet').click();
cy.getByTestId('dialog-content').should('be.visible');
});
it('must see that the order was rejected by the connected wallet', () => {
@@ -0,0 +1,329 @@
import * as Schema from '@vegaprotocol/types';
import { mockConnectWallet } from '@vegaprotocol/cypress';
const orderSizeField = 'order-size';
const orderPriceField = 'order-price';
const orderTIFDropDown = 'order-tif';
const placeOrderBtn = 'place-order';
const toggleShort = 'order-side-SIDE_SELL';
const toggleLong = 'order-side-SIDE_BUY';
const toggleLimit = 'order-type-TYPE_LIMIT';
const toggleMarket = 'order-type-TYPE_MARKET';
const TIFlist = Object.values(Schema.OrderTimeInForce).map((value) => {
return {
code: Schema.OrderTimeInForceCode[value],
value,
text: Schema.OrderTimeInForceMapping[value],
};
});
describe('time in force default values', () => {
before(() => {
cy.setVegaWallet();
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
it('must have market order set up to IOC by default', function () {
// 7002-SORD-030
cy.getByTestId(toggleMarket).click();
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
TIFlist.filter((item) => item.code === 'IOC')[0].text
);
});
it('must have time in force set to GTC for limit order', function () {
// 7002-SORD-031
cy.getByTestId(toggleLimit).click();
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
TIFlist.filter((item) => item.code === 'GTC')[0].text
);
});
});
describe('deal ticket validation', { tags: '@smoke' }, () => {
beforeEach(() => {
cy.mockTradingPage();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
it('must show place order button and connect wallet if wallet is not connected', () => {
// 0003-WTXN-001
cy.getByTestId('connect-vega-wallet'); // Not connected
cy.getByTestId('order-connect-wallet').should('exist');
cy.getByTestId(placeOrderBtn).should('exist');
cy.getByTestId('deal-ticket-connect-wallet').should('exist');
});
it('must be able to select order direction - long/short', function () {
// 7002-SORD-004
cy.getByTestId(toggleShort).click().children('input').should('be.checked');
cy.getByTestId(toggleLong).click().children('input').should('be.checked');
});
it('must be able to select order type - limit/market', function () {
// 7002-SORD-005
// 7002-SORD-006
// 7002-SORD-007
cy.getByTestId(toggleLimit).click().children('input').should('be.checked');
cy.getByTestId(toggleMarket).click().children('input').should('be.checked');
});
it('order connect vega wallet button should connect', () => {
mockConnectWallet();
cy.getByTestId(toggleLimit).click();
cy.getByTestId(orderPriceField).clear().type('101');
cy.getByTestId('order-connect-wallet').click();
cy.getByTestId('dialog-content').should('be.visible');
cy.getByTestId('connectors-list')
.find('[data-testid="connector-jsonRpc"]')
.click();
cy.wait('@walletReq');
cy.getByTestId(placeOrderBtn).should('be.visible');
cy.getByTestId(toggleLimit).children('input').should('be.checked');
cy.getByTestId(orderPriceField).should('have.value', '101');
});
});
describe('deal ticket size validation', { tags: '@smoke' }, function () {
beforeEach(() => {
cy.setVegaWallet();
cy.mockTradingPage();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
});
it('must warn if order size input has too many digits after the decimal place', function () {
// 7002-SORD-016
cy.getByTestId('order-type-TYPE_MARKET').click();
cy.getByTestId(orderSizeField).clear().type('1.234');
cy.getByTestId(placeOrderBtn).should('not.be.disabled');
cy.getByTestId(placeOrderBtn).click();
cy.getByTestId(placeOrderBtn).should('be.disabled');
cy.getByTestId('dealticket-error-message-size-market').should(
'have.text',
'Size must be whole numbers for this market'
);
});
it('must warn if order size is set to 0', function () {
cy.getByTestId('order-type-TYPE_MARKET').click();
cy.getByTestId(orderSizeField).clear().type('0');
cy.getByTestId(placeOrderBtn).should('not.be.disabled');
cy.getByTestId(placeOrderBtn).click();
cy.getByTestId(placeOrderBtn).should('be.disabled');
cy.getByTestId('dealticket-error-message-size-market').should(
'have.text',
'Size cannot be lower than 1'
);
});
});
describe('limit order validations', { tags: '@smoke' }, () => {
before(() => {
cy.setVegaWallet();
cy.mockTradingPage();
cy.mockSubscription();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
cy.getByTestId(toggleLimit).click();
});
beforeEach(() => {
cy.setVegaWallet();
});
it('must see the price unit', function () {
// 7002-SORD-018
cy.getByTestId(orderPriceField)
.siblings('label')
.should('have.text', 'Price (DAI)');
});
it('must see warning when placing an order with expiry date in past', () => {
const expiresAt = new Date(Date.now() - 24 * 60 * 60 * 1000);
const expiresAtInputValue = expiresAt.toISOString().substring(0, 16);
cy.getByTestId(toggleLimit).click();
cy.getByTestId(orderPriceField).clear().type('0.1');
cy.getByTestId(orderSizeField).clear().type('1');
cy.getByTestId(orderTIFDropDown).select('TIME_IN_FORCE_GTT');
cy.log('choosing yesterday');
cy.getByTestId('date-picker-field').type(expiresAtInputValue);
cy.getByTestId(placeOrderBtn).click();
cy.getByTestId('dealticket-error-message-expiry').should(
'have.text',
'The expiry date that you have entered appears to be in the past'
);
});
it('must see warning if price has too many digits after decimal place', function () {
// 7002-SORD-059
cy.getByTestId(toggleLimit).click();
cy.getByTestId(orderTIFDropDown).select('TIME_IN_FORCE_GTC');
cy.getByTestId(orderSizeField).clear().type('1');
cy.getByTestId(orderPriceField).clear().type('1.123456');
cy.getByTestId('dealticket-error-message-price-limit').should(
'have.text',
'Price accepts up to 5 decimal places'
);
});
describe('time in force validations', function () {
const validTIF = TIFlist;
validTIF.forEach((tif) => {
// 7002-SORD-023
// 7002-SORD-024
// 7002-SORD-025
// 7002-SORD-026
// 7002-SORD-027
// 7002-SORD-028
it(`must be able to select ${tif.code}`, function () {
cy.getByTestId(orderTIFDropDown).select(tif.value);
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
tif.text
);
});
});
it('selections should be remembered', () => {
cy.getByTestId(orderTIFDropDown).select('TIME_IN_FORCE_GTT');
cy.getByTestId(toggleMarket).click();
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
TIFlist.filter((item) => item.code === 'IOC')[0].text
);
cy.getByTestId(orderTIFDropDown).select('TIME_IN_FORCE_FOK');
cy.getByTestId(toggleLimit).click();
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
TIFlist.filter((item) => item.code === 'GTT')[0].text
);
cy.getByTestId(toggleMarket).click();
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
TIFlist.filter((item) => item.code === 'FOK')[0].text
);
});
});
});
describe('market order validations', { tags: '@smoke' }, () => {
before(() => {
cy.setVegaWallet();
cy.mockTradingPage();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
cy.getByTestId(toggleMarket).click();
});
beforeEach(() => {
cy.setVegaWallet();
});
it('must not see the price unit', function () {
// 7002-SORD-019
cy.getByTestId(orderPriceField).should('not.exist');
});
describe('time in force validations', function () {
const validTIF = TIFlist.filter((tif) => ['FOK', 'IOC'].includes(tif.code));
const invalidTIF = TIFlist.filter(
(tif) => !['FOK', 'IOC'].includes(tif.code)
);
validTIF.forEach((tif) => {
// 7002-SORD-025
// 7002-SORD-026
it(`must be able to select ${tif.code}`, function () {
cy.getByTestId(orderTIFDropDown).select(tif.value);
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
tif.text
);
});
});
invalidTIF.forEach((tif) => {
// 7002-SORD-023
// 7002-SORD-024
// 7002-SORD-027
// 7002-SORD-028
it(`must not be able to select ${tif.code}`, function () {
cy.getByTestId(orderTIFDropDown).should('not.contain', tif.text);
});
});
});
});
describe('post and reduce order validations', { tags: '@smoke' }, () => {
before(() => {
cy.setVegaWallet();
cy.mockTradingPage();
cy.visit('/#/markets/market-0');
cy.wait('@Markets');
cy.getByTestId(toggleMarket).click();
});
beforeEach(() => {
cy.setVegaWallet();
});
const validTIF = TIFlist.filter((tif) => ['FOK', 'IOC'].includes(tif.code));
validTIF.forEach((tif) => {
// 7002-SORD-025
// 7002-SORD-026
it(`post and reduce order market for ${tif.code}`, function () {
cy.getByTestId(orderTIFDropDown).select(tif.value);
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
tif.text
);
cy.getByTestId('post-only').should('be.disabled');
cy.getByTestId('reduce-only').should('be.enabled');
});
});
validTIF.forEach((tif) => {
it(`post and reduce order limit for ${tif.code}`, function () {
cy.getByTestId(toggleLimit).click();
cy.getByTestId(orderTIFDropDown).select(tif.value);
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
tif.text
);
cy.getByTestId('post-only').should('be.disabled');
cy.getByTestId('reduce-only').should('be.enabled');
});
});
const validTIFLimit = TIFlist.filter((tif) =>
['GFA', 'GFN', 'GTC', 'GTT'].includes(tif.code)
);
validTIFLimit.forEach((tif) => {
it(`post and reduce order for limit ${tif.code}`, function () {
cy.getByTestId(toggleLimit).click();
cy.getByTestId(orderTIFDropDown).select(tif.value);
cy.get(`[data-testid=${orderTIFDropDown}] option:selected`).should(
'have.text',
tif.text
);
cy.getByTestId('post-only').should('be.enabled');
cy.getByTestId('reduce-only').should('be.disabled');
});
});
});
@@ -117,6 +117,7 @@ describe('connect vega wallet', { tags: '@smoke' }, () => {
// 0002-WCON-002
// 0002-WCON-005
// 0002-WCON-007
// 0002-WCON-009
mockConnectWallet();
cy.getByTestId(connectVegaBtn).click();
@@ -124,6 +125,10 @@ describe('connect vega wallet', { tags: '@smoke' }, () => {
.find('[data-testid="connector-jsonRpc"]')
.click();
cy.wait('@walletReq');
cy.getByTestId(dialogContent).should(
'contain.text',
'Approve the connection from your Vega wallet app.'
);
cy.getByTestId(dialogContent).should('not.exist');
cy.getByTestId(manageVegaBtn).should('exist');
});
@@ -132,6 +137,7 @@ describe('connect vega wallet', { tags: '@smoke' }, () => {
// 0002-WCON-002
// 0002-WCON-005
// 0002-WCON-007
// 0002-WCON-015
mockConnectWalletWithUserError();
cy.getByTestId(connectVegaBtn).click();
+1
View File
@@ -11,3 +11,4 @@ NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
+1
View File
@@ -11,6 +11,7 @@ NX_VEGA_URL=http://localhost:3028/query
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_ETH_LOCAL_PROVIDER_URL=http://localhost:8545/
NX_ETH_WALLET_MNEMONIC="ozone access unlock valid olympic save include omit supply green clown session"
+1
View File
@@ -10,4 +10,5 @@ NX_VEGA_TOKEN_URL=https://token.fairground.wtf
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega-dev-releases/releases
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
+1
View File
@@ -9,4 +9,5 @@ NX_VEGA_TOKEN_URL=https://token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports
-13
View File
@@ -1,13 +0,0 @@
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/mainnet-mirror/vegawallet-mainnet-mirror.toml
NX_VEGA_ENV=MIRROR
NX_VEGA_EXPLORER_URL=https://mainnet-mirror.explorer.vega.xyz
NX_VEGA_NETWORKS={\"TESTNET\":\"https://console.fairground.wtf\",\"STAGNET1\":\"https://stagnet1.console.vega.xyz\",\"STAGNET3\":\"https://stagnet3.console.vega.xyz\"}
NX_VEGA_TOKEN_URL=https://mainnet-mirror.token.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases
NX_VEGA_INCIDENT_URL=https://blog.vega.xyz/tagged/vega-incident-reports

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