Compare commits

...
Author SHA1 Message Date
Mikołaj Młodzikowski c2f92b5226 feat(ci): turn off nx cloud 2023-06-13 12:57:48 +02:00
Matthew Russell 8f966a4ba6 chore: remove copied dir 2023-06-12 12:38:55 -07:00
Sam Keen cc7f403718 feat(governance): hide proposal details for freeform proposals (#4073) 2023-06-12 12:31:03 +01:00
MaciekandMatthew Russell 9184c2374c fix(markets): back with updating by grid api (#4059)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-06-10 07:49:10 -07:00
MaciekandMatthew Russell 37247a504a fix(trading): update click area in network switcher (#4057)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-06-10 07:48:48 -07:00
Bartłomiej Głownia 2e7a6a6458 chore(trading): cleanup paginated data solution, improve performance (#4036) 2023-06-09 19:02:23 -07:00
Ben bf6c13f523 test(trading): 3502-POSI-e2e-tests (#4064) 2023-06-09 17:37:50 -07:00
Matthew Russell a6f3a08d2f chore(trading,governance,explorer): release v0.20.18-core-0.71.8 2023-06-09 15:50:54 -07:00
Matthew Russell f13e456a29 ci(trading,governance,explorer): remove affected project text manipulation 2023-06-09 10:56:42 -07:00
Sam Keen 5cab040189 fix(governance): temporarily skipped flaky staking tests (#4068) 2023-06-09 16:13:44 +01:00
Maciek e47b868c53 fix(withdraws): clear eth network errors (#4044) 2023-06-09 08:58:16 +02:00
Matthew Russell b6286cd0f3 fix(deal-ticket): make ticket submit button always enabled (#4055) 2023-06-08 22:30:25 -07:00
Matthew Russell f66e976b66 revert: "chore(trading): release v0.20.18-core-0.71.8" 2023-06-08 19:41:24 -07:00
Matthew Russell 866e7232db chore(trading): release v0.20.18-core-0.71.8 2023-06-08 18:22:36 -07:00
Matthew Russellandmaciek 5a8ff90890 fix(ui-toolkit): display of loader in large variant (#4056)
Co-authored-by: maciek <maciek@vegaprotocol.io>
2023-06-08 09:16:51 -07:00
Radosław Szpiech 7b8f654906 test(trading): #3505 add test coverage to 6002-MDET-market-details (#4060) 2023-06-08 15:47:23 +02:00
Ciaran McGhie d6f39049bd chore(ui-toolkit,react-helpers,utils): publish new versions of ui-toolkit, react-helpers and utils (#4049) 2023-06-07 15:58:20 -07:00
Maciek 1d06be8f4e fix: wrong css class (#4053) 2023-06-07 20:44:28 +00:00
Edd 5eba8fe28f fix(explorer): fix broken protocol upgrade tx link (#4029) 2023-06-07 14:47:55 +01:00
m.ray 2ba0e9a1b2 chore(trading): add quantum formatting to deal ticket (#4030) 2023-06-07 11:49:50 +01:00
43d3754c64 feat(trading): 3945 orderbook enhancements (#4016)
Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-06-07 10:58:34 +02:00
m.ray aae5c44fa4 fix(trading): market selector volume update (#3989) 2023-06-06 18:45:52 -07:00
Art 878bed9c7a fix(withdraws): minimal withdrawal amount validation (#3993) 2023-06-06 22:21:48 +01:00
Sam Keen 6f9f432c90 feat(governance): multisig warning (#3994) 2023-06-06 22:21:31 +01:00
Sam Keen 3f01b93159 feat(governance,proposals,web3): remove use of word "we" in copy (#4034) 2023-06-06 22:21:17 +01:00
Edd 473c244d7b chore(governance,liquidity-provision-dashboard,trading): remove broken urls (#4042) 2023-06-06 22:19:42 +01:00
Joe Tsang d6a32f5090 chore(governance): fix flaky test failures (#4043) 2023-06-06 22:19:23 +01:00
Mikołaj Młodzikowski 71540a90fb fix(ci): resolving bucket name 2023-06-06 17:02:24 +02:00
Mikołaj Młodzikowski cefdbe6a3c fix(ci): missing space on resolving projects 2023-06-06 16:46:58 +02:00
Mikołaj Młodzikowski 3928dd5c0e fix(ci): way of resolving affected 2023-06-06 15:37:06 +02:00
Ciaran McGhie 1521bab4c4 chore(react-helpers,utils,logger): create logger lib and move sentry/logger utils there (#3990) 2023-06-06 14:10:03 +01:00
Mikołaj Młodzikowski b3036d520f fix(ci): way of resolving affected 2023-06-06 15:03:18 +02:00
Mikołaj Młodzikowski 429a5a23d3 fix(ci): way of resolving affected 2023-06-06 14:48:49 +02:00
Mikołaj Młodzikowski 5b02fd5d54 fix(ci): way of resolving affected 2023-06-06 14:39:28 +02:00
Mikołaj Młodzikowski b8309a76e7 fix(ci): way of resolving affected 2023-06-06 14:29:46 +02:00
Mikołaj Młodzikowski e8ae085c06 fix(ci): typo in app name 2023-06-06 14:18:47 +02:00
Mikołaj Młodzikowski fdcd24847c fix(ci): syntax for publishing dist 2023-06-06 14:07:56 +02:00
Mikołaj Młodzikowski e054db39b5 feat(ci): add deploys for multisig-signer (#4039) 2023-06-06 13:47:42 +02:00
Joe Tsang a01e48d508 chore(governance): nightly e2e test fixes (#4038) 2023-06-06 12:12:59 +01:00
Matthew Russell 0d96c487d9 fix(trading): use ag grid to handle error,loading and no data message (#4012) 2023-06-06 00:08:19 -07:00
m.rayandMatthew Russell 011e4e4cec fix(trading): market info refactor (#3985)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-06-05 19:00:29 -07:00
Bartłomiej Głownia d6e2432955 fix(accounts): avoid last row re-rendering (#3950) 2023-06-05 12:40:34 +02:00
Ben 18c034b910 test(trading): 6501-ASSE-assets e2e tests (#4026) 2023-06-05 09:13:24 +01:00
daro-maj 849cbb43c4 test(trading): 6001-MARK-find_markets e2e tests (#4025) 2023-06-05 08:25:31 +01:00
Edd cd34cb181f feat(explorer): properly represent batch error 71 (#4019) 2023-06-02 14:43:33 +01:00
Edd 97b3f4decf feat(explorer): do not colourise votes in tx list (#3988) 2023-06-01 12:35:33 +01:00
Ben 0465fb8ca9 test(trading): key to key transfer tests (#4014) 2023-06-01 11:37:41 +01:00
daro-maj 22af89e78c test(trading): reverted node tests (#3992) 2023-06-01 08:32:31 +01:00
Matthew Russell adfd2f41b6 chore(trading,governance,explorer): release v0.20.16-core-0.71.5 2023-05-31 15:00:17 -07:00
Matthew Russell d9b1aa6da3 chore(governance): revert governance ethereum endpoint to infura (#4010) 2023-05-31 14:58:45 -07:00
daro-majandasiaznik 205f369cdc test(trading): add network param mocks (#4001)
Co-authored-by: asiaznik <artur@vegaprotocol.io>
2023-05-31 17:11:02 +01:00
Joe Tsang 9f63fde123 chore(governance): 3929 proposal acs (#4008) 2023-05-31 17:10:41 +01:00
Matthew RussellandBartłomiej Głownia f2c70e6da4 fix(trading): performance issues with many orders (#3944)
Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
2023-05-31 17:38:49 +02:00
Edd e8ff1b0b60 fix(explorer,trading): typo in release notes template (#3976) 2023-05-30 22:47:19 -07:00
Matthew Russell f5989b0022 chore(trading,explorer,governance): release v0.20.15-core0.71.5 2023-05-30 14:54:08 -07:00
Matthew Russell 653ca034f2 fix(governance): dont start listening for pending eth events until connected (#3996) 2023-05-30 13:48:01 -07:00
Edd ef25552311 fix(explorer): fix stagnet1 env (#3975) 2023-05-29 17:31:39 +01:00
daro-maj 0a8439d125 test(trading): withdrawal details for extra security e2e tests (#3977) 2023-05-29 17:31:15 +01:00
Maciek 702ea0c6b4 chore(markets): keep market list live updated (#3954) 2023-05-29 07:39:42 +00:00
m.ray 0f2b86770a fix(trading): show full node URI in trading footer (#3978) 2023-05-26 16:38:02 +00:00
m.ray cd6d350047 chore(trading): update vega.trading to console.vega.xyz (#3969) 2023-05-26 12:08:26 +01:00
Matthew Russell c5a06c57ac chore(trading,governance,explorer): update issue templates to include check in specs repo (#3964) 2023-05-25 22:37:40 -07:00
Matthew Russell 5bb31fa38d chore(trading,governance,explorer): bump to v0.20.14-core-0.71.4 2023-05-25 16:31:35 -07:00
m.ray fd8f38803c chore(trading): bump version v0.20.13-core-0.71.4 (#3968) 2023-05-25 22:01:43 +00:00
Edd a22f8f0ef1 fix(explorer,trading): remove vega.trading links (#3962) 2023-05-25 21:27:51 +00:00
Matthew Russell c2d5c71f35 chore(trading): remove stray log (#3967) 2023-05-25 11:32:31 -07:00
Joe Tsang f88c35648e chore(governance): reward tests passing (#3963) 2023-05-25 18:08:06 +00:00
Mikołaj Młodzikowski 348c61530e feat(ci): implement active checks for previews readiness (#3949) 2023-05-25 14:36:38 +02:00
Bartłomiej Głownia f364dabe2f feat(trading): show positions for all connected keys (#3858) 2023-05-25 11:59:08 +01:00
m.rayandasiaznik 1ae1fdff5e fix(trading): price and volume in the last 24h can be incorrectly reported (#3870)
Co-authored-by: asiaznik <artur@vegaprotocol.io>
2023-05-25 10:39:07 +00:00
m.ray 3ed615c36e fix(oracles): word breakdown oracles (#3946) 2023-05-25 10:07:17 +00:00
Bartłomiej Głownia 6b50816234 fix(orders): re-render last column of orders table on data change (#3927) 2023-05-25 10:37:53 +01:00
Sam Keen f5e67a0c2d fix(governance): rewards decimals set per asset (#3941) 2023-05-25 10:37:40 +01:00
Bartłomiej Głownia e4d4646878 fix(trading): skip market data query if market not present (#3928) 2023-05-25 10:37:33 +01:00
Art bbd1536c18 chore(trading): upgrade banner semver comparison (#3919) 2023-05-25 10:37:13 +01:00
Mikołaj Młodzikowski f8444c0c88 feat(ci): deploy from main branch as well 2023-05-25 10:20:58 +02:00
Mikołaj Młodzikowski b1adf776c0 feat(ci): update rollback flow 2023-05-24 16:05:15 +02:00
Mikołaj Młodzikowski ad898ab0e8 feat(ci): update rollback flow 2023-05-24 15:58:53 +02:00
Maciek 5b0fffc5cb chore(market-depth): replace bid and ask columns with a single volume column when i… (#3930) 2023-05-24 15:55:21 +02:00
Mikołaj Młodzikowski a9dbc0f6eb feat(ci): update rollback flow 2023-05-24 15:53:07 +02:00
Mikołaj Młodzikowski a71786817f fix(ci): pr creation adjust 2023-05-24 13:47:36 +02:00
Vega CI Botandvega-ci-bot 9ee0cb7b65 Automated hash update from refs/tags/v0.20.12-core-0.71.4-4 (#3933)
Co-authored-by: vega-ci-bot <vega-ci-bot@vega.xyz>
2023-05-24 13:46:01 +02:00
Mikołaj Młodzikowski 8c4aa41240 fix(ci): pr creation adjust 2023-05-24 13:37:04 +02:00
Vega CI Botandvega-ci-bot 91ac977704 Automated hash update from refs/tags/v0.20.12-core-0.71.4-3 (#3932)
Co-authored-by: vega-ci-bot <vega-ci-bot@vega.xyz>
2023-05-24 13:34:10 +02:00
Mikołaj Młodzikowski 1190033776 fix(ci): pr creation adjust 2023-05-24 13:24:28 +02:00
Mikołaj Młodzikowski b99e2235b4 fix(ci): pr creation adjust 2023-05-24 13:09:29 +02:00
Mikołaj Młodzikowski 002bc4f188 feat: regenerate hashes on interstitial page (#3926) 2023-05-24 12:36:11 +02:00
Joe Tsang 0c2af8c75f chore(governance): update nightly tests (#3913) 2023-05-24 09:23:31 +01:00
daro-maj a305c5b8a9 test(trading): capsule tests - fix for wallet connection (#3885) 2023-05-23 20:02:29 +02:00
Matthew Russell 4c3ceb94f3 chore: bump app version 2023-05-23 09:58:39 -07:00
Art 2215864d0c fix(withdraws): min withdraw amount (#3916) 2023-05-23 09:52:48 -07:00
Art 589785ce09 fix(withdraws): link to the withdrawal limits (#3914) 2023-05-23 16:39:29 +00:00
Maciek babd99088d fix(trading): make grids more responsive - suppress sizeColumnsToFit on small screens (#3906) 2023-05-23 16:08:55 +00:00
Bartłomiej Głownia d155909fe4 fix(deal-ticket): clear price error on type change (#3908) 2023-05-23 08:53:40 -07:00
Sam Keen 1d3298cdc9 fix(governance): add enactment date to proposal sorting (#3875) 2023-05-23 16:53:01 +01:00
m.ray c2baaa2dd9 fix(trading): console.fairground.wtf links update back (#3907) 2023-05-23 15:49:14 +00:00
Art e2c4c4a841 fix(deposits): validation with exempt (#3909) 2023-05-23 08:44:06 -07:00
Art 7a89dc984d feat(deposits): mark remaining deposit allowance as exempt (#3902) 2023-05-23 15:35:02 +01:00
Mikołaj Młodzikowski 19580fb9ce fix(ci): work around syntax issue on updating release notes 2023-05-23 13:43:32 +02:00
m.rayandEdd 0721099d7d chore(trading): console fairground links (#3896)
Co-authored-by: Edd <edd@vega.xyz>
2023-05-23 11:06:57 +00:00
m.rayandEdd 9ee2810c51 chore(trading): adding mainnet links (#3879)
Co-authored-by: Edd <edd@vega.xyz>
2023-05-23 10:29:09 +00:00
Edd 9f8f99b50b fix(explorer): wrap routes in suspense (#3894) 2023-05-23 11:15:13 +01:00
m.ray 3208f762fd fix(trading): hide download or export all when no entries (#3892) 2023-05-23 09:26:47 +00:00
Mikołaj Młodzikowski 7a06c946d1 feat(ci): support fairground / mainnet variables for s3 and do not deploy trading to s3 bucket on main branch 2023-05-23 11:20:54 +02:00
Maciek 70e172045d fix(trading): improve data count on propsed markets (#3890) 2023-05-23 08:53:15 +00:00
Mikołaj Młodzikowski 06c540666e feat(ci): setup correct domain for fairground deployments 2023-05-23 10:30:35 +02:00
Matthew Russell f81503b8f7 chore: bump app version for trading 2023-05-22 22:20:30 -07:00
Matthew Russell 1699e33cbd fix(trading): redirect to markets all page if no market found (#3888) 2023-05-22 22:02:55 -07:00
Matthew Russell 5280b79927 feat(trading): market selection changes (#3863) 2023-05-22 21:33:16 -07:00
Matthew Russell 34526d527e fix(trading): icon color when navbar is dark (#3887) 2023-05-22 19:07:18 -07:00
Matthew Russell 7b9aae700d chore(trading): dont show upgrade banner unless APP_VERSION is set (#3886) 2023-05-22 14:10:06 -07:00
Matthew Russell e9cb2ad217 chore(ui-toolkit): adjust nav styles and banner (#3865) 2023-05-22 13:20:17 -07:00
Edd 6dd4536fdd fix(explorer): change how internal filters are detected (#3852) 2023-05-22 21:08:57 +01:00
Bartłomiej Głownia 522eb521b9 feat(trading): show positions for all markets (#3868) 2023-05-22 12:55:15 -07:00
Edd 3aa0e974c2 feat(explorer): footer updates (#3884) 2023-05-22 12:54:37 -07:00
Art a0eb381ab1 feat(trading): upgrade banner (#3883) 2023-05-22 12:53:40 -07:00
Matthew Russell a51ab4d98d chore(governance): remove process tranches script (#3864) 2023-05-22 12:52:13 -07:00
Bartłomiej Głownia 67643afd74 fix(trading): positions and markets settlement asset column filter and sort (#3873) 2023-05-22 12:34:05 -07:00
dexturr 145539e0c0 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-22 18:07:30 +00:00
Art 48109b584c fix(ui-toolkit): test toast configuration (#3877) 2023-05-22 18:34:02 +02:00
Maciek a4512e6064 feat(trading): move trade grid panel - add back priority for chart pane (#3880) 2023-05-22 15:55:02 +00:00
m.rayandEdd 45adac2932 chore(trading): update environments. add vega.trading to network switcher (#3869)
Co-authored-by: Edd <edd@vega.xyz>
2023-05-22 15:50:13 +00:00
Maciek fff8fdd78b feat(trading): move trade grid panel - fix id of store (#3872) 2023-05-22 14:09:37 +00:00
m.rayandmaciek 079d8bc48d feat(trading): move deal ticket panel to the left (#3842)
Co-authored-by: maciek <maciek@vegaprotocol.io>
2023-05-22 15:40:42 +02:00
Eddandm.ray 9658363b56 chore(explorer): update be env for validator testnet (#3867)
Co-authored-by: m.ray <16125548+MadalinaRaicu@users.noreply.github.com>
2023-05-22 13:38:51 +00:00
dexturr e24289330e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-22 12:08:25 +00:00
Mikołaj Młodzikowski 0fbd2bfa72 feat(ci): adjust environment name 2023-05-22 11:42:09 +02:00
Mikołaj MłodzikowskiandMikołaj Młodzikowski 43ef4fad6f feat(ci): fix affected resolution (#3849)
Co-authored-by: Mikołaj Młodzikowski <mikolaj.mlodzikowski@github.com>
2023-05-22 11:16:33 +02:00
Matthew Russell 828dcf6e93 chore(governance,explorer,trading): move sentry dsn to env files (#3860) 2023-05-22 08:54:15 +02:00
dexturr 4a583ccf09 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-22 06:07:44 +00:00
dexturr 8bcad28f50 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-22 00:16:28 +00:00
dexturr b375681076 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-21 18:07:08 +00:00
dexturr 8a2db407cf chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-21 12:10:41 +00:00
dexturr 491844d3fd chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-21 06:09:53 +00:00
dexturr f1f51c5ecd chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-21 00:15:03 +00:00
dexturr 9bc78f8ccd chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-20 18:06:53 +00:00
dexturr a03031a283 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-20 12:10:14 +00:00
Matthew Russell b499c293e3 fix(trading): fix proposals not showing (#3859) 2023-05-20 10:55:52 +01:00
dexturr 65747e8d26 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-20 06:09:41 +00:00
dexturr 9a84eda21b chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-20 00:14:21 +00:00
Maciek fba98f2fd0 feat(trading,governance): improve flow of risk disclaimer presentation (#3772) 2023-05-19 21:27:45 +00:00
Matthew Russell 3e32d0f396 chore(governance,trading): update mainnet envs with new ethereum provider url (#3857) 2023-05-19 13:31:49 -07:00
Matthew Russell b75d189054 fix(trading): settlement price of closed markets (#3831) 2023-05-19 13:29:24 -07:00
Sam Keen afa627864c fix(governance): homepage proposals ordering fixed (#3856) 2023-05-19 18:12:14 +00:00
dexturr b13a866b2a chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-19 18:07:12 +00:00
daro-maj c65f07eee6 test(trading): skip failing node tests (#3854) 2023-05-19 19:54:56 +02:00
Sam Keen 5bd18cc127 feat(governance): avoid showing untitled proposals (#3851) 2023-05-19 16:19:28 +01:00
Art ff3519279d fix(governance): penalties calculation (#3850) 2023-05-19 16:19:07 +01:00
m.ray fd338c7400 fix(orders): cancel all and pegged orders amendable (#3843) 2023-05-19 14:55:08 +00:00
Sam Keen 0db5d0ce87 feat(governance): hide proposal details on market proposals (#3845) 2023-05-19 13:47:48 +00:00
Matthew Russell 42c316c8e1 feat(environment): avoid logging node check queries (#3830) 2023-05-19 14:32:27 +01:00
Sam Keen 9e2474d39a feat(governance): proposals-sort-order (#3848) 2023-05-19 14:30:08 +01:00
Joe Tsang 2533e5ec44 test(governance): 3790 proposal tests refactor (#3838) 2023-05-19 14:29:20 +01:00
dexturr 22a43249ea chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-19 12:08:42 +00:00
m.ray b40ee0caf5 fix(markets): remove queries for internal data sources (#3829) 2023-05-19 12:53:00 +01:00
Edd 95aca70434 fix(explorer): prevent render of signature component on some proposals (#3840) 2023-05-19 12:09:48 +01:00
Sam Keen 5e13266250 feat(governance): change url of upgrade proposals (#3841) 2023-05-19 12:09:40 +01:00
Edd 5c0588887c fix(explorer): fix footer links (#3825) 2023-05-19 10:37:59 +01:00
daro-maj 089a7daac7 test(trading): e2e test for select network and nodes - 0006-NETW (#3828) 2023-05-19 10:37:44 +01:00
Mikołaj Młodzikowski 02b6251b1a feat(ci): support mainnet branching strategy (#3832) 2023-05-19 10:38:36 +02:00
Bartłomiej Głownia 9ce8907861 feat(trading): do not show oracle banner when data is loading (#3821) 2023-05-19 10:01:22 +02:00
dexturr 3be9126906 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-19 06:10:00 +00:00
dexturr 77316092d1 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-19 00:15:57 +00:00
Dexter Edwards fca229e62a feat(governance): use rest to expose proposal data (#3827) 2023-05-18 22:43:32 +01:00
dexturr 162b167860 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-18 18:07:36 +00:00
Art a4149cc55e feat(web3): withdrawal details (#3701) 2023-05-18 16:50:15 +02:00
Mikołaj Młodzikowski 4161a74eaf feat(ci): fix release body (#3822) 2023-05-18 14:59:46 +01:00
Mikołaj Młodzikowski 5008e57a56 feat(ci): adjust variables during release pipeline to cover actual tag_name 2023-05-18 15:12:12 +02:00
Mikołaj Młodzikowski 89031bf826 feat(ci): append ipfs related information to release body (#3818) 2023-05-18 14:51:53 +02:00
dexturr 61501d4d14 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-18 12:10:20 +00:00
Madalina Raicu f8f3ce7df9 fix: no oracle for this market banner 2023-05-18 13:00:17 +01:00
Maciek f7aab5a78a feat(ui-toolkit,trading): allow toast box configuration (#3811) 2023-05-18 12:53:36 +01:00
Bartłomiej Głownia 2904975fd3 feat(trading): highlight negative oracle statuses in market lists (#3816) 2023-05-18 13:22:54 +02:00
Mikołaj Młodzikowski 4f55c946f0 feat(ci): add pipeline for rollback console deployments (#3817) 2023-05-18 10:11:41 +00:00
Matthew Russell de637fee13 chore(trading): show markets in opening auction in market selector (#3814) 2023-05-18 09:49:44 +01:00
dexturr 69c6db8ec2 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-18 06:09:07 +00:00
Matthew Russell 8dc465c1d1 feat(trading): additional row actions for tables (#3600) 2023-05-17 21:05:53 -07:00
dexturr 0be934edca chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-18 00:16:39 +00:00
Matthew Russell 653688c1dd fix(governance): clear wallet state if user changes to a non existent party (#3813) 2023-05-17 19:25:14 +00:00
dexturr 34400be18a chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-17 18:09:58 +00:00
Sam Keen d4a0a4a42c fix(governance): updated page titles (#3810) 2023-05-17 16:16:19 +00:00
Joe Tsang fabf643ce7 chore(ci): fix nightly test runner (#3804) 2023-05-17 16:21:10 +01:00
Sam Keen 45e210092c fix(governance): ensure no negative overstaked penalty (#3794) 2023-05-17 14:41:55 +00:00
Ciaran McGhie 1dc3b3fd05 fix(ui-toolkit): add keys to healthbar segments (#3797) 2023-05-17 15:14:11 +01:00
Sam Keen 0a80e3e39d fix(governance): avoid unknown pubkey causing validator page error (#3755) 2023-05-17 13:21:00 +00:00
Sam Keen 7b8d9dc94b feat(governance): validator tables refocused on stake (#3780) 2023-05-17 14:14:23 +01:00
Daniel c0320c2468 feat(ci): update DNS for mainnet console when new version is released (#3783) 2023-05-17 14:45:06 +02:00
Sam Keen 11173d6614 fix(governance): point to correct data for displayed LP rewards (#3800) 2023-05-17 12:20:51 +00:00
dexturr e3324331e2 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-17 12:11:33 +00:00
Maciek 0a6e3cb6f5 chore(trading): refactor docs links resolver (#3782) 2023-05-17 12:10:31 +02:00
Sam Keen 68ede90609 feat(3779): proposal terms in table, full proposal json, description … (#3793) 2023-05-17 08:23:25 +00:00
daro-maj 09778a5d3f test(trading): pegged orders e2e tests (#3787) 2023-05-17 09:54:19 +02:00
MaciekandMatthew Russell 59993e3ea6 chore(trading): suppress sentry logs when eth fails (#3726)
Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
2023-05-16 23:31:53 -07:00
dexturr 54161a6dba chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-17 06:07:24 +00:00
Matthew Russell 26f524ea07 feat(trading): sidebar market list adjustments (#3792) 2023-05-16 18:45:17 -07:00
dexturr db13e6f21d chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-17 00:17:38 +00:00
dexturr 4a679813ba chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-16 18:07:35 +00:00
Matthew Russell a4279d5b5e feat(trading): sidebar market list (#3776) 2023-05-16 16:57:36 +00:00
m.ray 1a274a67c3 feat(trading): oracle banner check termination and settlement data oracles (#3707) 2023-05-16 15:12:22 +02:00
dexturr 1e9ff31fd7 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-16 12:08:54 +00:00
Sam Keen aa2b755b93 fix(governance): reward aggregation for validator types (#3773) 2023-05-16 08:40:36 +01:00
Matthew Russell 4a7296312a fix(smart-contracts,deposits): add different abi for tether (#3775) 2023-05-16 08:40:05 +01:00
dexturr 1418a2259f chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-16 06:07:24 +00:00
dexturr 7e5ef0157a chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-16 00:14:15 +00:00
dexturr 0cf764f11e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-15 18:09:01 +00:00
Sam Keen 1c626aeeb2 fix(governance): useWeb3ConnectStore instead of app state for eth connect d… (#3750) 2023-05-15 16:21:20 +01:00
Bartłomiej Głownia c4cec47b0b feat(trading): add oracle dialog trigger to oracle banner, display status reas… (#3727) 2023-05-15 16:20:30 +01:00
dexturr 1a67c41bb4 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-15 12:08:57 +00:00
Matthew Russell fc66240390 fix(governance): check value of telemetry local storage entry (#3762) 2023-05-15 09:48:42 +01:00
Maciek fc0da98683 fix(trading): match link as active more strictly (#3754) 2023-05-15 10:08:21 +02:00
Maciek 4d0dafb113 fix(trading): match link as active more strictly (#3754) 2023-05-15 10:08:04 +02:00
dexturr eda431be9e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-15 06:07:48 +00:00
dexturr 4ff1749e54 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-15 00:17:19 +00:00
dexturr e7a108fd7a chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-14 18:07:19 +00:00
dexturr 5d3f2ea7d8 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-14 12:08:55 +00:00
dexturr 1ab27574ca chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-14 06:09:03 +00:00
dexturr 0ea3c43e78 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-14 00:17:56 +00:00
dexturr 9e183568b0 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-13 18:08:39 +00:00
dexturr 69fd5b26b6 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-13 12:09:50 +00:00
dexturr 2d5b926609 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-13 06:07:23 +00:00
dexturr 98a2ba79a8 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-13 00:13:37 +00:00
dexturr 0e6e986937 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-12 18:07:19 +00:00
Mikołaj Młodzikowski 15d6ea0c05 feat(ci): push directly to main branch on vega.xyz 2023-05-12 17:40:52 +02:00
Mikołaj Młodzikowski 0358ce6293 feat(ci): try to merge to vega.xyz using standard PR 2023-05-12 17:13:33 +02:00
Mikołaj Młodzikowski 0791be4636 feat(ci): push directly to main branch on vega.xyz 2023-05-12 16:40:45 +02:00
Dexter Edwardsandsam-keen 07442848ee fix(governance): claim not encoding ascii correctly (#3747)
Co-authored-by: sam-keen <samuel.kleinmann@gmail.com>
2023-05-12 14:04:06 +00:00
Mikołaj Młodzikowski d5f0bd419e feat(ci): update vega landing page whenever new console is released (#3751) 2023-05-12 15:18:15 +02:00
Sam KeenandBartłomiej Głownia 2c7934a8c7 fix(governance): fix time delay notice for withdrawal of 0.00 assets (#3740)
Co-authored-by: Bartłomiej Głownia <bglownia@gmail.com>
2023-05-12 15:04:53 +02:00
Joe Tsang fae61c28ca chore(cypress): remove cypress project id (#3739) 2023-05-12 13:44:22 +01:00
dexturr fcd4541625 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-12 12:10:20 +00:00
Sam KeenandJoe 8e0a92fdec fix(governance): network upgrade proposal e2e test tweak (#3748)
Co-authored-by: Joe <joe@vega.xyz>
2023-05-12 09:58:10 +01:00
dexturr 6e7109ed87 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-12 06:09:45 +00:00
dexturr f2c698ce06 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-12 00:16:15 +00:00
dexturr ad9a3a3400 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-11 18:10:08 +00:00
Sam Keen efeac49d58 feat(governance): change status labels for network upgrade proposals (#3711) 2023-05-11 15:43:27 +00:00
Mikołaj Młodzikowski 2d430710ab feat(ci): use actual secret in the script 2023-05-11 17:31:12 +02:00
Mikołaj Młodzikowski bca1a98985 fix(ci): remove old dockerfile 2023-05-11 17:16:28 +02:00
Edd 8a080d3279 fix(explorer): fix bug where no votes displayed a yes icon (#3699) 2023-05-11 14:55:00 +00:00
Mikołaj Młodzikowski f121836b4e feat(ci): fleek updates (#3724) 2023-05-11 15:42:35 +02:00
Sam Keen b641c82ad8 feat(governance): voting blog link and button title (#3717) 2023-05-11 12:59:28 +00:00
Sam Keen bf73559c30 fix(governance): change proposal sort order (#3716) 2023-05-11 12:39:30 +00:00
dexturr 653cec2592 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-11 12:07:57 +00:00
m.ray 579c884a5a feat(trading): show pegged order offset and reference in the order table (#3675) 2023-05-11 12:43:20 +01:00
Bartłomiej Głownia b2279c7e47 feat(trading): hook up new EstimatePosition and EstimateFees api methods (#3634) 2023-05-11 12:58:12 +02:00
Sam Keen a8c17b6807 fix(governance): tranches data (#3708) 2023-05-11 10:22:52 +00:00
Sam Keen b4c7dc6f59 fix(governance): more thorough catch for url in error reporting (#3686) 2023-05-11 10:21:16 +00:00
daro-maj d44392bebf test(trading): show full oracle profile info in markets test (#3695) 2023-05-11 08:18:00 +02:00
dexturr bd679957e2 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-11 06:07:33 +00:00
dexturr e30d48555e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-11 00:16:19 +00:00
Sam Keen b4b2416780 fix(governance): my stake share 2 dp (#3685) 2023-05-10 16:23:37 +00:00
Maciek dc7832ac81 chore(candles-chart): fill up missing candles (#3664) 2023-05-10 15:26:27 +00:00
Joe Tsang 91207d31ee chore(governance): fix failing validator tests (#3703) 2023-05-10 15:03:47 +00:00
dexturr 58efb460a6 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-10 12:10:00 +00:00
Mikołaj Młodzikowski 044f98777b feat(ci): lint makefile 2023-05-10 13:43:33 +02:00
Mikołaj Młodzikowski 00fdc5e81a fix(ci): preparing dist bash syntax 2023-05-10 13:33:17 +02:00
Mikołaj Młodzikowski adfad3bafb feat(ci): fix typo 2023-05-10 13:21:53 +02:00
dexturr e6ae88905c chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-10 06:07:15 +00:00
dexturr 3953ed9953 chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-10 00:15:02 +00:00
Matthew Russell b48ab58e6a chore: add VEGA_URL for explorer mainnet 2023-05-09 14:06:10 -07:00
Matthew Russell e44cf1ff53 chore(environment,trading): fix unit tests for footer and node switcher (#3682) 2023-05-09 13:39:17 -07:00
Matthew Russell bded1d32ba feat(explorer,governance): always allow selecting a node, add node guard (#3678) 2023-05-09 12:58:09 -07:00
Edd 76ddf45f4c fix(explorer): add envs back to env (#3677) 2023-05-09 12:57:38 -07:00
Dexter Edwards 6a2c9004d8 fix(governance, console, explorer): show vega node in list, cache bust (#3676) 2023-05-09 12:57:11 -07:00
dexturr 77ee88b43e chore: update tranches
Signed-off-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2023-05-09 18:09:50 +00:00
Dexter e4958ce3c0 fix: do not show validators with 0 self stake in list 2023-05-09 18:25:20 +01:00
Mikołaj Młodzikowski ecedb879f8 fix(ci): define which app ipfs hash is set for 2023-05-09 18:47:50 +02:00
m.ray 89700803d6 fix(trading): fix release script for mainnet (#3669) 2023-05-09 16:30:05 +00:00
Mikołaj Młodzikowski 65c9fa5df2 feat(ci): establish build based on docker to produce ipfs-hashes (#3612) 2023-05-09 18:24:39 +02:00
ArtandMadalina Raicu 02399c40fc fix(trading): welcome dialog links (#3656)
Co-authored-by: Madalina Raicu <madalina@raygroup.uk>
2023-05-09 15:43:36 +00:00
755 changed files with 19046 additions and 158889 deletions
+2 -3
View File
@@ -14,8 +14,7 @@ What we need to achieve and who for
## Tasks
- [ ] What do we need to do first
- [ ] and then what?
- [ ] Etc.
- [ ]
- [ ]
## Additional details / background info
+7 -4
View File
@@ -22,11 +22,14 @@ So that
## Tasks
- [ ] Explore and sketch
- [ ] UX (if needed)
- [ ] Design (if needed)
- [ ] Team and stakeholder review
- [ ] Visual Design
- [ ] Team review
- [ ] Etc.
- [ ] Specs reviewed and created or adjusted
- [ ] Implementation
- [ ] Testing (unit and/or e2e)
- [ ] Code review
- [ ] QA review
## Sketch
@@ -0,0 +1,75 @@
name: After Release
on:
release:
types: [published]
jobs:
after-release:
runs-on: ubuntu-22.04
timeout-minutes: 30
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to the Container registry (ghcr)
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to the Container registry (docker hub)
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: resolve ipfs hashes for release
run: |
echo "Tag name: ${{ github.event.release.tag_name }}"
echo "Name: ${{ github.event.release.name }}"
echo "Description: ${{ github.event.release.body }}"
until docker pull vegaprotocol/trading:${{ github.event.release.tag_name }}; do
echo "Image not pushed yet, waiting 60 seconds"
sleep 60
done
docker run --rm vegaprotocol/trading:${{ github.event.release.tag_name }} cat /ipfs-hash > ipfs-hash
curl -L https://dist.ipfs.tech/kubo/v0.20.0/kubo_v0.20.0_linux-amd64.tar.gz -o kubo.tgz
tar -xzf kubo.tgz
export PATH="$PATH:$PWD/kubo"
which ipfs
echo IPFS_V0=$(cat ipfs-hash) >> $GITHUB_ENV
echo IPFS_V1=$(ipfs cid format -v 1 -b base32 $(cat ipfs-hash)) >> $GITHUB_ENV
- name: Edit Release
uses: irongut/EditRelease@v1.2.0
with:
token: ${{ secrets.GITHUB_TOKEN }}
id: ${{ github.event.release.id }}
body: |
___
# Deployments
* https://explorer.vega.xyz
* https://governance.vega.xyz
# IPFS releases
The IPFS hash of this release of the Trading app is:
CIDv0: ${{ env.IPFS_V0 }}
CIDv1: ${{ env.IPFS_V1 }}
You can always access the latest IPFS release by visiting [console.vega.xyz](https://console.vega.xyz).
You can also access Trading directly from an IPFS gateway.
BEWARE: The Trading interface uses [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) to remember your settings, such as which tokens you have imported. You should always use an IPFS gateway that enforces [origin separation](https://ipfs.github.io/public-gateway-checker/).
Your settings are not remembered across different URLs.
IPFS gateways:
https://${{ env.IPFS_V1 }}.ipfs.dweb.link/
https://${{ env.IPFS_V1 }}.ipfs.cf-ipfs.com/
ipfs://${{ env.IPFS_V0 }}/
+74 -26
View File
@@ -5,6 +5,9 @@ on:
branches:
- release/*
- develop
- main
tags:
- v*
pull_request:
types:
- opened
@@ -96,46 +99,65 @@ jobs:
# See affected apps
- name: See affected apps
run: |
affected="$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)"
branch_slug="$(echo '${{ github.head_ref || github.ref_name }}' | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g | cut -c 1-50 )"
echo ">>>> debug"
echo "NX Version: $nx_version"
echo "NX_BASE: ${{ env.NX_BASE }}"
echo "NX_HEAD: ${{ env.NX_HEAD }}"
echo "Affected: ${affected}"
echo "Branch slug: ${branch_slug}"
echo ">>>> eof debug"
affected="$(yarn nx print-affected --base=${{ env.NX_BASE }} --head=${{ env.NX_HEAD }} --select=projects)"
echo -n "Affected projects: $affected"
branch_slug="$(echo ${{ github.head_ref || github.ref_name }} | sed -r s/[^a-zA-Z0-9]+/-/g | sed -r s/^-+\|-+$//g | cut -c 1-50 )"
projects_e2e=""
preview_governance="not deployed"
preview_trading="not deployed"
preview_explorer="not deployed"
preview_tools="not deployed"
if echo "$affected" | grep -q governance; then
echo "Governance is affected"
projects_e2e+='"governance-e2e" '
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
fi
if echo "$affected" | grep -q trading; then
echo "Trading is affected"
projects_e2e+='"trading-e2e" '
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
fi
if echo "$affected" | grep -q explorer; then
echo "Explorer is affected"
projects_e2e+='"explorer-e2e" '
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$branch_slug")
fi
if [[ -z "$projects_e2e" ]]; then
projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" '
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$branch_slug")
else
if [[ $affected == *"governance"* ]]; then
projects_e2e+='"governance-e2e" '
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
fi
projects="$(echo $projects_e2e | sed 's|-e2e||g')"
if echo "$affected" | grep -q multisig-signer; then
echo "Tools are affected"
# tools are only applicable to check previews or deploy from develop to mainnet
if [[ "${{ github.event_name }}" = "pull_request" ]]; then
echo "Deploying tools on preview"
preview_tools=$(printf "https://%s.%s.vega.rocks" "tools" "$branch_slug")
projects+=' "multisig-signer" '
fi
if [[ $affected == *"trading"* ]]; then
projects_e2e+='"trading-e2e" '
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
fi
if [[ $affected == *"explorer"* ]]; then
projects_e2e+='"explorer-e2e" '
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$branch_slug")
if [[ "${{ github.ref }}" =~ .*develop$ ]]; then
echo "Deploying tools on s3"
projects+=' "multisig-signer" '
fi
fi
projects_e2e=${projects_e2e%?}
projects_e2e=[${projects_e2e// /,}]
projects=[${projects// /,}]
echo PROJECTS_E2E=$projects_e2e >> $GITHUB_ENV
echo PROJECTS=$(echo $projects_e2e | sed 's|-e2e||g') >> $GITHUB_ENV
echo PROJECTS=$projects >> $GITHUB_ENV
echo PREVIEW_GOVERNANCE=$preview_governance >> $GITHUB_ENV
echo PREVIEW_TRADING=$preview_trading >> $GITHUB_ENV
echo PREVIEW_EXPLORER=$preview_explorer >> $GITHUB_ENV
echo PREVIEW_TOOLS=$preview_tools >> $GITHUB_ENV
outputs:
projects: ${{ env.PROJECTS }}
@@ -143,11 +165,12 @@ jobs:
preview_governance: ${{ env.PREVIEW_GOVERNANCE }}
preview_trading: ${{ env.PREVIEW_TRADING }}
preview_explorer: ${{ env.PREVIEW_EXPLORER }}
preview_tools: ${{ env.PREVIEW_TOOLS }}
cypress:
needs: lint-test-build
name: '(CI) cypress'
if: ${{ needs.lint-test-build.outputs.projects != '[]' }}
if: ${{ needs.lint-test-build.outputs.projects-e2e != '[]' }}
uses: ./.github/workflows/cypress-run.yml
secrets: inherit
with:
@@ -169,6 +192,7 @@ jobs:
- publish-dist
- lint-test-build
if: ${{ github.event_name == 'pull_request' }}
timeout-minutes: 60
name: '(CD) comment preview links'
steps:
- name: Find Comment
@@ -178,6 +202,35 @@ jobs:
issue-number: ${{ github.event.pull_request.number }}
body-includes: Previews
- name: Wait for deployments
run: |
# https://stackoverflow.com/questions/3183444/check-for-valid-link-url
regex='(https?|ftp|file)://[-[:alnum:]\+&@#/%?=~_|!:,.;]*[-[:alnum:]\+&@#/%=~_|]'
if [[ "${{ needs.lint-test-build.outputs.preview_governance }}" =~ $regex ]]; then
until curl -L --fail "${{ needs.lint-test-build.outputs.preview_governance }}"; do
echo "waiting for governance preview"
sleep 5
done
fi
if [[ "${{ needs.lint-test-build.outputs.preview_explorer }}" =~ $regex ]]; then
until curl -L --fail "${{ needs.lint-test-build.outputs.preview_explorer }}"; do
echo "waiting for explorer preview"
sleep 5
done
fi
if [[ "${{ needs.lint-test-build.outputs.preview_trading }}" =~ $regex ]]; then
until curl -L --fail "${{ needs.lint-test-build.outputs.preview_trading }}"; do
echo "waiting for trading preview"
sleep 5
done
fi
if [[ "${{ needs.lint-test-build.outputs.preview_tools }}" =~ $regex ]]; then
until curl -L --fail "${{ needs.lint-test-build.outputs.preview_tools }}"; do
echo "waiting for tools preview"
sleep 5
done
fi
- name: Create comment
uses: peter-evans/create-or-update-comment@v3
if: ${{ steps.fc.outputs.comment-id == 0 }}
@@ -188,16 +241,11 @@ jobs:
* governance: ${{ needs.lint-test-build.outputs.preview_governance }}
* explorer: ${{ needs.lint-test-build.outputs.preview_explorer }}
* trading: ${{ needs.lint-test-build.outputs.preview_trading }}
cypress-check:
name: '(CI) cypress - check'
runs-on: ubuntu-latest
needs: cypress
steps:
- run: echo Done!
* tools: ${{ needs.lint-test-build.outputs.preview_tools }}
# Report single result at the end, to avoid mess with required checks in PR
cypress-result:
cypress-check:
name: '(CI) cypress - check'
if: ${{ always() }}
needs: cypress
runs-on: ubuntu-22.04
-1
View File
@@ -33,5 +33,4 @@ jobs:
config: baseUrl=${{ github.event.inputs.url }}
env: grepTags=@live
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+3 -3
View File
@@ -20,7 +20,7 @@ jobs:
project: ${{ fromJSON(inputs.projects) }}
name: ${{ matrix.project }}
runs-on: self-hosted-runner
timeout-minutes: 40
timeout-minutes: 100
steps:
# Checks if skip cache was requested
- name: Set skip-nx-cache flag
@@ -66,7 +66,7 @@ jobs:
######
- name: Run Cypress tests
run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --record --key ${{ secrets.CYPRESS_RECORD_KEY }} --browser chrome --env.grepTags="${{ inputs.tags }}"
run: yarn nx run ${{ matrix.project }}:e2e ${{ env.SKIP_CACHE }} --browser chrome --env.grepTags="${{ inputs.tags }}"
working-directory: frontend-monorepo
env:
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
@@ -98,4 +98,4 @@ jobs:
if: ${{ failure() }}
with:
name: test-report-${{ matrix.project }}
path: frontend-monorepo/apps/trading-e2e/cypress/reports
path: frontend-monorepo/apps/${{ matrix.project }}/cypress/reports
-32
View File
@@ -1,32 +0,0 @@
name: Generate tranches
on:
schedule:
- cron: '0 */6 * * *'
jobs:
master:
name: Generate Queries
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v2
with:
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
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: Generate queries
run: node ./scripts/get-tranches.js
- uses: stefanzweifel/git-auto-commit-action@v4
with:
commit_message: 'chore: update tranches'
commit_options: '--no-verify --signoff'
skip_fetch: true
skip_checkout: true
+155 -46
View File
@@ -30,13 +30,21 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to the Container registry
- name: Log in to the Container registry (ghcr)
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to the Container registry (docker hub)
uses: docker/login-action@v2
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
with:
# registry: registry.hub.docker.com
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Setup node
uses: actions/setup-node@v3
with:
@@ -51,33 +59,50 @@ jobs:
key: ${{ runner.os }}-cache-node-modules-${{ hashFiles('yarn.lock') }}
# https://docs.github.com/en/actions/learn-github-actions/contexts
- name: Define variables
- name: Define dist variables
if: ${{ github.event_name == 'push' }}
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="stagnet1"
domain="vega.rocks"
bucketName=''
if [[ "${{ github.ref }}" =~ .*release/.* ]]; then
envName="$(echo ${{ github.ref }} | rev | cut -d '/' -f 1 | rev)"
elif [[ "${{ github.ref }}" =~ .*develop$ ]]; then
envName="stagnet1"
if [[ "${{ matrix.app }}" = "multisig-signer" ]]; then
envName="mainnet"
bucketName="tools.vega.xyz"
fi
bucketName="${{ matrix.app }}.${envName}.${domain}"
echo BUCKET_NAME=${bucketName} >> $GITHUB_ENV
elif [[ "${{ github.ref }}" =~ .*main$ ]]; then
envName="mainnet"
elif [[ "${{ matrix.app}}" = "trading" ]] && [[ "${{ startsWith(github.ref, 'refs/tags/v') && 'true' || 'false' }}" = "true" ]]; then
envName="mainnet"
fi
nodeVersion=$(cat .nvmrc | head -n 1)
if [[ "${envName}" = "mainnet" ]]; then
domain="vega.xyz"
if [[ -z "${bucketName}" ]]; then
bucketName="${{ matrix.app }}.${domain}"
fi
elif [[ "${envName}" = "testnet" ]]; then
domain="fairground.wtf"
if [[ -z "${bucketName}" ]]; then
bucketName="${{ matrix.app }}.${domain}"
fi
fi
if [[ -z "${bucketName}" ]]; then
bucketName="${{ matrix.app }}.${envName}.${domain}"
fi
echo "bucket name: ${bucketName}"
echo "env name: ${envName}"
echo BUCKET_NAME=${bucketName} >> $GITHUB_ENV
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
@@ -98,62 +123,60 @@ jobs:
- 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 }}
file: docker/node-outside-docker.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' ) }}
if: ${{ github.event_name == 'pull_request' }}
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
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash > ${{ matrix.app }}-ipfs-hash
echo "List html directory"
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local sh -c 'apk add --update tree; tree .'
docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local sh -c 'apk add --update tree; tree /usr/share/nginx/html'
- 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
- name: Publish dist as docker image (ghcr)
uses: docker/build-push-action@v3
if: ${{ github.event_name == 'pull_request' }}
if: ${{ github.event_name == 'pull_request' || (matrix.app == 'trading' && github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/v') ) }}
with:
context: .
file: ${{ env.DOCKERFILE }}
file: docker/node-outside-docker.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 }}
- name: Publish dist as docker image (docker hub)
uses: docker/build-push-action@v3
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
with:
context: .
file: docker/node-outside-docker.Dockerfile
push: true
build-args: |
APP=${{ matrix.app }}
ENV_NAME=${{ env.ENV_NAME }}
tags: |
vegaprotocol/${{ matrix.app }}:${{ github.ref_name }}
vegaprotocol/${{ matrix.app }}:mainnet
# bucket creation in github.com/vegaprotocol/terraform//frontend
- name: Publish dist to s3
uses: jakejarvis/s3-sync-action@master
if: ${{ github.event_name == 'push' }}
if: ${{ github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/v') && ( matrix.app != 'trading' || (matrix.app == 'trading' && !endsWith(github.ref, 'main') ) ) }}
with:
args: --acl private --follow-symlinks --delete
env:
@@ -169,3 +192,89 @@ jobs:
with:
labels: ${{ matrix.app }}-preview
number: ${{ github.event.number }}
- name: Trigger fleek deployment
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
run: |
# display info about app
curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
-H "Content-Type: application/json" \
-d '{"query": "query{getSiteById(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id latestDeploy{id status}}}"}' \
https://api.fleek.co/graphql
# trigger new deployment as base image is always set to vegaprotocol/trading:mainnet
curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
-H "Content-Type: application/json" \
-d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \
https://api.fleek.co/graphql
- name: Check out ipfs-redirect
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
uses: actions/checkout@v3
with:
repository: 'vegaprotocol/ipfs-redirect'
path: 'ipfs-redirect'
fetch-depth: '0'
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
- name: Update console.vega.xyz DNS to redirect to the new console
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
env:
GH_TOKEN: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
run: |
curl -L https://dist.ipfs.tech/kubo/v0.20.0/kubo_v0.20.0_linux-amd64.tar.gz -o kubo.tgz
tar -xzf kubo.tgz
export PATH="$PATH:$PWD/kubo"
which ipfs
new_hash=$(cat ${{ matrix.app }}-ipfs-hash)
new_cid=$(ipfs cid format -v 1 -b base32 $new_hash)
ls -al ipfs-redirect
echo $new_hash > ipfs-redirect/cidv0.txt
echo $new_cid > ipfs-redirect/cidv1.txt
(
cd ipfs-redirect
git status
cat .git/config
git config --global user.email "vega-ci-bot@vega.xyz"
git config --global user.name "vega-ci-bot"
branch_name="update-hash-${{ github.ref }}"
git checkout -b "$branch_name"
commit_msg="Automated hash update from ${{ github.ref }}"
git add cidv0.txt cidv1.txt
git commit -m "$commit_msg"
git push -u origin "$branch_name"
pr_url="$(gh pr create --title "${commit_msg}" --body 'automated pull request to update CIDs')"
echo $pr_url
# once auto merge get's enabled on documentation repo let's do follow up
sleep 5
gh pr merge "${pr_url}" --delete-branch --squash --admin
)
# # Generate console URL
# new_console_url_type=ipfs
# # new_console_url_type=ipns
# new_console_url_domain=cf-ipfs.com
# # new_console_url_domain=dweb.link
# new_console_url="https://${new_cid}.${new_console_url_type}.${new_console_url_domain}/"
# echo "new_console_url=${new_console_url}"
# # Update record in DNSimple
# # docs: https://developer.dnsimple.com/v2/zones/records/#updateZoneRecord
# dnsimple_account_id=84895
# dnsimple_zone_name=console.vega.xyz
# dnsimple_record_id=44409591
# # see: https://dnsimple.com/a/84895/domains/console.vega.xyz/records/44409591/edit
# curl -H 'Authorization: Bearer ${{ secrets.DNSIMPLE_API_TOKEN }}' \
# -H 'Accept: application/json' \
# -H 'Content-Type: application/json' \
# -X PATCH \
# -d "{
# \"content\": \"${new_console_url}\"
# }" \
# https://api.dnsimple.com/v2/${dnsimple_account_id}/zones/${dnsimple_zone_name}/records/${dnsimple_record_id}
+84
View File
@@ -0,0 +1,84 @@
name: 'Rollback console'
on:
workflow_dispatch:
inputs:
version:
description: 'Version that should be set on rollback'
required: true
type: string
jobs:
rollback:
runs-on: ubuntu-22.04
timeout-minutes: 10
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Log in to the Container registry (docker hub)
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Retag mainnet
run: |
docker pull vegaprotocol/trading:${{ inputs.version }}
docker tag vegaprotocol/trading:${{ inputs.version }} vegaprotocol/trading:mainnet
docker push vegaprotocol/trading:mainnet
docker run --rm vegaprotocol/trading:mainnet cat /ipfs-hash > ipfs-hash
- name: Trigger fleek deployment
run: |
# display info about app
curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
-H "Content-Type: application/json" \
-d '{"query": "query{getSiteById(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id latestDeploy{id status}}}"}' \
https://api.fleek.co/graphql
# trigger new deployment as base image is always set to vegaprotocol/trading:mainnet
curl -H "Authorization: ${{ secrets.FLEEK_API_KEY }}" \
-H "Content-Type: application/json" \
-d '{"query": "mutation{triggerDeploy(siteId:\"f8f2e051-f18e-49e6-b876-0a39369dc0d8\"){id status}}"}' \
https://api.fleek.co/graphql
- name: Check out ipfs-redirect
uses: actions/checkout@v3
with:
repository: 'vegaprotocol/ipfs-redirect'
path: 'ipfs-redirect'
fetch-depth: '0'
token: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
- name: Update console.vega.xyz DNS to redirect to the new console
env:
GH_TOKEN: ${{ secrets.VEGA_CI_BOT_GITHUB_TOKEN }}
run: |
curl -L https://dist.ipfs.tech/kubo/v0.20.0/kubo_v0.20.0_linux-amd64.tar.gz -o kubo.tgz
tar -xzf kubo.tgz
export PATH="$PATH:$PWD/kubo"
which ipfs
new_hash=$(cat ipfs-hash)
new_cid=$(ipfs cid format -v 1 -b base32 $new_hash)
git config --global user.email "vega-ci-bot@vega.xyz"
git config --global user.name "vega-ci-bot"
echo $new_hash > ipfs-redirect/cidv0.txt
echo $new_cid > ipfs-redirect/cidv1.txt
(
cd ipfs-redirect
git status
branch_name="rollback-to-$new_hash"
git checkout -b "$branch_name"
commit_msg="hash rollback to $new_hash"
git add cidv0.txt cidv1.txt
git commit -m "$commit_msg"
git push -u origin "$branch_name" --force-with-lease
pr_url="$(gh pr create --title "${commit_msg}" --body 'automated pull request to update CIDs')"
echo $pr_url
# once auto merge get's enabled on documentation repo let's do follow up
sleep 5
gh pr merge "${pr_url}" --delete-branch --squash --admin
)
+4 -1
View File
@@ -2,6 +2,7 @@
# compiled output
/dist
/dist-result
/tmp
/out-tsc
/tools/executors/**/*.js
@@ -48,4 +49,6 @@ cypress.env.json
.next
#cypress
/apps/trading-e2e/cypress/reports/
/apps/**/cypress/reports/
/apps/**/cypress/downloads/
/apps/**/fixtures/wallet/node**
+20
View File
@@ -0,0 +1,20 @@
.PHONY: latest-release
latest-release:
gh release list | head -n 1 | awk '{print $1}'
.PHONY: show-latest-release
show-latest-release:
gh release view `gh release list | head -n 1 | awk '{print $1}'`
.PHONY: recalculate-ipfs
recalculate-ipfs:
echo "ipfs hash inside the image"
docker run --rm ${TAG} cat /ipfs-hash
echo "recalculating ipfs hash"
docker run --rm ${TAG} ipfs add -r /usr/share/nginx/html
.PHONY: eject-ipfs-hash
unpack:
docker create --name=dist ${TAG}
docker cp dist:/usr/share/nginx/html dist
docker rm dist
+55 -12
View File
@@ -103,25 +103,68 @@ In CI linting, formatting and also run. These checks can be seen in the [CI work
Visit the [Nx Documentation](https://nx.dev/getting-started/intro) to learn more.
# Docker & Vegacapsule
# 🐋 Hosting a console
## Docker
To host a console there are two possible build scenarios for running the frontends: nx performed **outside** or **inside** docker build. For specific build instructions follow [build instructions](#build-instructions).
The [Dockerfile](./dockerfiles) for running the frontends is pretty basic, merely building the application with the APP arg that is passed in and serving the application from [nginx](./nginx/nginx.conf). The only complexity that exists is that there is a script which allows the passing of run time environment variables to the containers. See configuration below for how to do this.
You can build any of the containers locally with the following command:
```bash
docker build --dockerfile dockerfiles/Dockerfile.cra . --build-arg APP=[YOUR APP] --tag=[TAG]
```
In order to run a container:
In order to run a container on port 3000:
```bash
docker run -p 3000:80 [TAG]
```
Images ending with `.dist` are to pack locally created transpiled HTML files into nginx container for non-compatible with yarn architectures like M1 Mac
## Build instructions
The [`docker`](./docker) subfolder has some docker configurations for easily setting up your own hosted version of console either for the web, or ready for pinning on IPFS
### nx build outside the docker
Packaging prepared dist into [`nginx`](https://hub.docker.com/_/nginx)([server configuration](./nginx/nginx.conf)) docker image involves building the application on docker host machine from source.
As a prerequisite you need to perform build of `dist` directory and move its content for specific application to `dist-result` directory. Use following script to do it with a single command:
```bash
./docker/prepare-dist.sh
```
You can build any of the containers locally with the following command:
```bash
docker build --dockerfile docker/node-outside-docker.Dockerfile . --tag=[TAG]
```
### nx build inside the docker
Using multistage dockerfile dist is compiled using [node](https://hub.docker.com/_/node) image and later packed to nginx as in [dist build](#dist-build) example.
```bash
docker build --build-arg APP=[YOUR APP] --build-arg NODE_VERSION=$(cat .nvmrc) --build-arg ENV_NAME=mainnet -t [TAG] -f docker/node-inside-docker.Dockerfile .
```
### Computing ipfs-hash of the build
At the moment this feature is important only for `trading` (console) releases.
Each docker build finishes with hash calculation for dist directory. Resulting hash is added to file named as `/ipfs-hash`. Once docker image is produced you can run following commad to display ipfs-hash:
```bash
make recalculate-ipfs TAG=vegaprotocol/trading:{YOUR_VERSION}
```
**updating hash:** recompiling dist directory (even if there are no changed to source code) results in different hash computed by ipfs command.
### Verifying ipfs-hash of existing current application version
An IPFS CID will be attached to every [release](https://github.com/vegaprotocol/frontend-monorepo/releases). If you are intending to pin an application on IPFS, you can check that your build matches by running the following steps:
1. Show latest release by runnning: `make latest-release`. You need to configure [`gh`](https://cli.github.com/) for this step to work, otherwise please provide release manually from [github](https://github.com/vegaprotocol/frontend-monorepo/releases) or [dockerhub](https://hub.docker.com/r/vegaprotocol/trading)
2. Set RELEASE environment variable to value that you want to validate: `export RELEASE=$(make latest-release)` or `export RELEASE=vXX.XX.XX`
3. Set TAG environment variable to image that you want to validate: `export TAG=vegaprotocol/trading:$RELEASE`
4. Download docker image with the desired release `docker pull $TAG`.
5. Recalculate hash: `make recalculate-ipfs`
6. You should see exactly same hash produced by ipfs command as one placed with the release notes: `make show-latest-release`
7. If you want to extract dist from docker image to your local filesystem you can run following command: `make unpack`
8. Now `dist` directory contains valid application build. **it is not possible to calculate same ipfs hash on files that are result of copy operation**
## Config
-1
View File
@@ -1,4 +1,3 @@
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=http://localhost:26617
NX_TENDERMINT_WEBSOCKET_URL=wss://localhost:26617/websocket
NX_VEGA_URL=http://localhost:3008/graphql
-1
View File
@@ -1,5 +1,4 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://n04.d.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://n04.d.vega.xyz/tm/websocket
NX_VEGA_URL=https://api.n04.d.vega.xyz/graphql
-1
View File
@@ -1,5 +1,4 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://mainnet-observer-proxy01.ops.vega.xyz/
NX_TENDERMINT_WEBSOCKET_URL=wss://mainnet-observer-proxy01.ops.vega.xyz/websocket
NX_VEGA_URL=https://api.vega.community/graphql
-1
View File
@@ -1,5 +1,4 @@
# App configuration variables
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api
NX_TENDERMINT_URL=https://tm.n07.testnet.vega.xyz/tm
NX_TENDERMINT_WEBSOCKET_URL=wss://lb.testnet.vega.xyz/tm/websocket
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
+2 -1
View File
@@ -1,10 +1,11 @@
const { defineConfig } = require('cypress');
module.exports = defineConfig({
projectId: 'et4snf',
reporter: '../../node_modules/cypress-mochawesome-reporter',
e2e: {
setupNodeEvents(on, config) {
require('cypress-mochawesome-reporter/plugin')(on);
require('@cypress/grep/src/plugin')(config);
return config;
},
+1
View File
@@ -15,5 +15,6 @@
import '@vegaprotocol/cypress';
import './common.functions.js';
import 'cypress-mochawesome-reporter/register';
import registerCypressGrep from '@cypress/grep';
registerCypressGrep();
+7 -4
View File
@@ -3,16 +3,19 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_ENV=STAGNET1
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_TOKEN_URL=https://stagnet1.governance.vega.xyz
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
NX_VEGA_TOKEN_URL=https://governance.stagnet1.vega.rocks
NX_VEGA_WALLET_URL=http://localhost:1789
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz
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_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_VEGA_GOVERNANCE_URL=https://stagnet1.governance.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.jsoo
NX_VEGA_GOVERNANCE_URL=https://governance.stagnet1.vega.rocks
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_REPO_URL=https://github.com/vegaprotocol/vega/releases/tag/
# App flags
NX_EXPLORER_ASSETS=1
+3
View File
@@ -1,10 +1,13 @@
# App configuration variables
NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.vega.community/websocket
NX_SENTRY_DSN=https://b3a56b03eda842faad731f3ea9dfd1bc@o286262.ingest.sentry.io/6242427
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
NX_VEGA_URL=https://api.vega.community/graphql
NX_VEGA_ENV=MAINNET
NX_BLOCK_EXPLORER=https://be.vega.community/rest/
NX_ETHERSCAN_URL=https://etherscan.io
NX_VEGA_GOVERNANCE_URL=https://governance.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz/
NX_VEGA_CONSOLE_URL=https://console.vega.xyz
+2 -1
View File
@@ -1 +1,2 @@
# .env is stagnet1, so there are no overrides required
# .env is stagnet1, so there are no overrides required
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz","STAGNET1":"https://stagnet1.explorer.vega.xyz"}'
+1
View File
@@ -10,3 +10,4 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://governance.fairground.wtf
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
NX_VEGA_CONSOLE_URL=https://console.fairground.wtf
@@ -7,8 +7,9 @@ NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9
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_TENDERMINT_URL=https://tm.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
NX_VEGA_EXPLORER_URL=https://validator-testnet.explorer.vega.xyz/
NX_VEGA_GOVERNANCE_URL=https://governance.validators-testnet.vega.rocks
NX_VEGA_EXPLORER_URL=https://explorer.validators-testnet.vega.rocks/
NX_VEGA_CONSOLE_URL=https://trading.validators-testnet.vega.rocks/
+27 -2
View File
@@ -1,9 +1,19 @@
import { NetworkLoader, useInitializeEnv } from '@vegaprotocol/environment';
import {
AppFailure,
NetworkLoader,
NodeGuard,
NodeSwitcherDialog,
useEnvironment,
useInitializeEnv,
useNodeSwitcherStore,
} from '@vegaprotocol/environment';
import { TendermintWebsocketProvider } from './contexts/websocket/tendermint-websocket-provider';
import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
import { DEFAULT_CACHE_CONFIG } from '@vegaprotocol/apollo-client';
import { RouterProvider } from 'react-router-dom';
import { router } from './routes/router-config';
import { t } from '@vegaprotocol/i18n';
import { Suspense } from 'react';
const splashLoading = (
<Splash>
@@ -12,10 +22,25 @@ const splashLoading = (
);
function App() {
const { VEGA_URL } = useEnvironment();
const [nodeSwitcherOpen, setNodeSwitcherOpen] = useNodeSwitcherStore(
(store) => [store.dialogOpen, store.setDialogOpen]
);
return (
<TendermintWebsocketProvider>
<NetworkLoader cache={DEFAULT_CACHE_CONFIG}>
<RouterProvider router={router} fallbackElement={splashLoading} />
<NodeGuard
skeleton={<div>{t('Loading')}</div>}
failure={<AppFailure title={t(`Node: ${VEGA_URL} is unsuitable`)} />}
>
<Suspense fallback={splashLoading}>
<RouterProvider router={router} fallbackElement={splashLoading} />
</Suspense>
</NodeGuard>
<NodeSwitcherDialog
open={nodeSwitcherOpen}
setOpen={setNodeSwitcherOpen}
/>
</NetworkLoader>
</TendermintWebsocketProvider>
);
@@ -1,13 +1,21 @@
import { NodeSwitcherDialog, useEnvironment } from '@vegaprotocol/environment';
import {
useEnvironment,
useNodeSwitcherStore,
} from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n';
import { useScreenDimensions } from '@vegaprotocol/react-helpers';
import { ExternalLink, Link } from '@vegaprotocol/ui-toolkit';
import { useMemo, useState } from 'react';
import { Link, ExternalLink } from '@vegaprotocol/ui-toolkit';
import { useMemo } from 'react';
import { ENV } from '../../config/env';
import { Routes } from '../../routes/route-names';
import { Link as RouteLink } from 'react-router-dom';
export const Footer = () => {
const { VEGA_URL, GIT_COMMIT_HASH, GIT_ORIGIN_URL } = useEnvironment();
const [nodeSwitcherOpen, setNodeSwitcherOpen] = useState(false);
const setNodeSwitcherOpen = useNodeSwitcherStore(
(store) => store.setDialogOpen
);
const { screenSize } = useScreenDimensions();
const showFullFeedbackLabel = useMemo(
() => ['md', 'lg', 'xl', 'xxl', 'xxxl'].includes(screenSize),
@@ -15,56 +23,53 @@ export const Footer = () => {
);
return (
<>
<footer className="grid grid-rows-2 grid-cols-[1fr_auto] text-xs md:text-md md:flex md:col-span-2 px-4 py-2 gap-4 border-t border-vega-light-200 dark:border-vega-dark-200">
<div className="flex justify-between gap-2 align-middle">
{GIT_COMMIT_HASH && (
<div className="content-center flex border-r border-neutral-700 dark:border-neutral-300 pr-4">
<p data-testid="git-commit-hash">
{t('Version')}:{' '}
<Link
href={
GIT_ORIGIN_URL
? `${GIT_ORIGIN_URL}/commit/${GIT_COMMIT_HASH}`
: undefined
}
target={GIT_ORIGIN_URL ? '_blank' : undefined}
>
{GIT_COMMIT_HASH}
</Link>
</p>
</div>
)}
<div className="content-center flex pl-2 md:border-r border-neutral-700 dark:border-neutral-300 pr-4">
{VEGA_URL && <NodeUrl url={VEGA_URL} />}
<Link className="ml-2" onClick={() => setNodeSwitcherOpen(true)}>
{t('Change')}
</Link>
<footer className="grid grid-rows-2 lg:grid-cols-[1fr_auto] text-xs md:text-md lg:flex md:col-span-2 px-4 py-2 gap-4 border-t border-vega-light-200 dark:border-vega-dark-200">
<div className="flex justify-between gap-2 align-middle">
{GIT_COMMIT_HASH && (
<div className="content-center flex border-r border-neutral-700 dark:border-neutral-300 pr-4">
<p data-testid="git-commit-hash">
{t('Version')}:{' '}
<Link
href={
GIT_ORIGIN_URL
? `${GIT_ORIGIN_URL}/commit/${GIT_COMMIT_HASH}`
: undefined
}
target={GIT_ORIGIN_URL ? '_blank' : undefined}
>
{GIT_COMMIT_HASH}
</Link>
</p>
</div>
)}
<div className="content-center flex pl-2 md:border-r border-neutral-700 dark:border-neutral-300 pr-4">
{VEGA_URL && <NodeUrl url={VEGA_URL} />}
<Link className="ml-2" onClick={() => setNodeSwitcherOpen(true)}>
{t('Change')}
</Link>
</div>
{ENV.addresses.feedback ? (
<div className="flex pl-2 content-center">
<ExternalLink href={ENV.addresses.feedback}>
{showFullFeedbackLabel ? t('Share your feedback') : t('Feedback')}
</ExternalLink>
</div>
</div>
</footer>
<NodeSwitcherDialog
open={nodeSwitcherOpen}
setOpen={setNodeSwitcherOpen}
/>
</>
) : null}
</div>
<div className="pl-2 align-center lg:align-right lg:flex lg:justify-end gap-2 align-middle lg:max-w-xs lg:ml-auto">
<RouteLink to={`/${Routes.DISCLAIMER}`} className="underline">
Disclaimer
</RouteLink>
</div>
</footer>
);
};
const NodeUrl = ({ url }: { url: string }) => {
export const NodeUrl = ({ url }: { url: string }) => {
// get base url from api url, api sub domain
const urlObj = new URL(url);
const nodeUrl = urlObj.origin.replace(/^[^.]+\./g, '');
return (
<Link href={'https://' + nodeUrl} target="_blank">
{nodeUrl}
</Link>
);
return <span className="cursor-default">{nodeUrl}</span>;
};
@@ -3,6 +3,7 @@ import { Header } from './header';
import { MemoryRouter } from 'react-router-dom';
jest.mock('@vegaprotocol/environment', () => ({
...jest.requireActual('@vegaprotocol/environment'),
NetworkSwitcher: () => (
<div data-testid="network-switcher">NetworkSwitcher</div>
),
@@ -1,8 +1,9 @@
import { t } from '@vegaprotocol/i18n';
import type { MarketInfoWithData } from '@vegaprotocol/market-info';
import { LiquidityInfoPanel } from '@vegaprotocol/market-info';
import { LiquidityMonitoringParametersInfoPanel } from '@vegaprotocol/market-info';
import type { MarketInfoWithData } from '@vegaprotocol/markets';
import { PriceMonitoringBoundsInfoPanel } from '@vegaprotocol/markets';
import {
LiquidityInfoPanel,
LiquidityMonitoringParametersInfoPanel,
InstrumentInfoPanel,
KeyDetailsInfoPanel,
LiquidityPriceRangeInfoPanel,
@@ -12,20 +13,18 @@ import {
RiskModelInfoPanel,
RiskParametersInfoPanel,
SettlementAssetInfoPanel,
} from '@vegaprotocol/market-info';
import { MarketInfoTable } from '@vegaprotocol/market-info';
} from '@vegaprotocol/markets';
import { MarketInfoTable } from '@vegaprotocol/markets';
import type { DataSourceDefinition } from '@vegaprotocol/types';
import isEqual from 'lodash/isEqual';
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
if (!market) return null;
const settlementData =
market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData
.data;
const terminationData =
market.tradableInstrument.instrument.product
.dataSourceSpecForTradingTermination.data;
const settlementData = market.tradableInstrument.instrument.product
.dataSourceSpecForSettlementData.data as DataSourceDefinition;
const terminationData = market.tradableInstrument.instrument.product
.dataSourceSpecForTradingTermination.data as DataSourceDefinition;
const getSigners = (data: DataSourceDefinition) => {
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
@@ -41,133 +40,69 @@ export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
return [];
};
const oraclePanels = isEqual(
const showTwoOracles = isEqual(
getSigners(settlementData),
getSigners(terminationData)
)
? [
{
title: t('Settlement Oracle'),
content: (
<OracleInfoPanel
noBorder={false}
market={market}
type="settlementData"
/>
),
},
{
title: t('Termination Oracle'),
content: (
<OracleInfoPanel
noBorder={false}
market={market}
type="termination"
/>
),
},
]
: [
{
title: t('Oracle'),
content: (
<OracleInfoPanel
noBorder={false}
market={market}
type="settlementData"
/>
),
},
];
);
const panels = [
{
title: t('Key details'),
content: <KeyDetailsInfoPanel noBorder={false} market={market} />,
},
{
title: t('Instrument'),
content: <InstrumentInfoPanel noBorder={false} market={market} />,
},
{
title: t('Settlement asset'),
content: <SettlementAssetInfoPanel market={market} noBorder={false} />,
},
{
title: t('Metadata'),
content: <MetadataInfoPanel noBorder={false} market={market} />,
},
{
title: t('Risk model'),
content: <RiskModelInfoPanel noBorder={false} market={market} />,
},
{
title: t('Risk parameters'),
content: <RiskParametersInfoPanel noBorder={false} market={market} />,
},
{
title: t('Risk factors'),
content: <RiskFactorsInfoPanel noBorder={false} market={market} />,
},
...(market.priceMonitoringSettings?.parameters?.triggers || []).map(
(trigger, i) => ({
title: t(`Price monitoring trigger ${i + 1}`),
content: <MarketInfoTable noBorder={false} data={trigger} />,
})
),
...(market.data?.priceMonitoringBounds || []).map((trigger, i) => ({
title: t(`Price monitoring bound ${i + 1}`),
content: (
<>
<MarketInfoTable
noBorder={false}
data={{
maxValidPrice: trigger.maxValidPrice,
minValidPrice: trigger.minValidPrice,
}}
decimalPlaces={market.decimalPlaces}
/>
<MarketInfoTable
noBorder={false}
data={{ referencePrice: trigger.referencePrice }}
decimalPlaces={
market.tradableInstrument.instrument.product.settlementAsset
.decimals
}
/>
</>
),
})),
{
title: t('Liquidity monitoring parameters'),
content: (
<LiquidityMonitoringParametersInfoPanel
noBorder={false}
market={market}
/>
),
},
{
title: t('Liquidity'),
content: <LiquidityInfoPanel market={market} noBorder={false} />,
},
{
title: t('Liquidity price range'),
content: (
<LiquidityPriceRangeInfoPanel market={market} noBorder={false} />
),
},
...oraclePanels,
];
const headerClassName = 'font-alpha calt text-xl mt-4 border-b-2 pb-2';
return (
<>
{panels.map((p) => (
<div key={p.title} className="mb-3">
<h2 className="font-alpha calt text-xl">{p.title}</h2>
{p.content}
</div>
<div>
<h2 className={headerClassName}>{t('Key details')}</h2>
<KeyDetailsInfoPanel market={market} />
<h2 className={headerClassName}>{t('Instrument')}</h2>
<InstrumentInfoPanel market={market} />
<h2 className={headerClassName}>{t('Settlement asset')}</h2>
<SettlementAssetInfoPanel market={market} />
<h2 className={headerClassName}>{t('Metadata')}</h2>
<MetadataInfoPanel market={market} />
<h2 className={headerClassName}>{t('Risk model')}</h2>
<RiskModelInfoPanel market={market} />
<h2 className={headerClassName}>{t('Risk parameters')}</h2>
<RiskParametersInfoPanel market={market} />
<h2 className={headerClassName}>{t('Risk factors')}</h2>
<RiskFactorsInfoPanel market={market} />
{(market.data?.priceMonitoringBounds || []).map((trigger, i) => (
<>
<h2 className={headerClassName}>
{t('Price monitoring bounds %s', [(i + 1).toString()])}
</h2>
<PriceMonitoringBoundsInfoPanel
market={market}
triggerIndex={i + 1}
/>
</>
))}
</>
{(market.priceMonitoringSettings?.parameters?.triggers || []).map(
(trigger, i) => (
<>
<h2 className={headerClassName}>
{t('Price monitoring settings %s', [(i + 1).toString()])}
</h2>
<MarketInfoTable data={trigger} key={i} />
</>
)
)}
<h2 className={headerClassName}>{t('Liquidity monitoring')}</h2>
<LiquidityMonitoringParametersInfoPanel market={market} />
<h2 className={headerClassName}>{t('Liquidity')}</h2>
<LiquidityInfoPanel market={market} />
<h2 className={headerClassName}>{t('Liquidity price range')}</h2>
<LiquidityPriceRangeInfoPanel market={market} />
{showTwoOracles ? (
<>
<h2 className={headerClassName}>{t('Settlement oracle')}</h2>
<OracleInfoPanel market={market} type="settlementData" />
<h2 className={headerClassName}>{t('Termination oracle')}</h2>
<OracleInfoPanel market={market} type="termination" />
</>
) : (
<>
<h2 className={headerClassName}>{t('Oracle')}</h2>
<OracleInfoPanel market={market} type="settlementData" />
</>
)}
</div>
);
};
@@ -1,4 +1,4 @@
import type { MarketFieldsFragment } from '@vegaprotocol/market-list';
import type { MarketFieldsFragment } from '@vegaprotocol/markets';
import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react';
@@ -84,15 +84,17 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
<AgGridColumn
colId="asset"
headerName={t('Settlement asset')}
field="tradableInstrument.instrument.product.settlementAsset"
field="tradableInstrument.instrument.product.settlementAsset.symbol"
hide={window.innerWidth <= BREAKPOINT_MD}
cellRenderer={({
value,
data,
}: VegaICellRendererParams<
MarketFieldsFragment,
'tradableInstrument.instrument.product.settlementAsset'
>) =>
value ? (
'tradableInstrument.instrument.product.settlementAsset.symbol'
>) => {
const value =
data?.tradableInstrument.instrument.product.settlementAsset;
return value ? (
<ButtonLink
onClick={(e) => {
openAssetDetailsDialog(value.id, e.target as HTMLElement);
@@ -102,8 +104,8 @@ export const MarketsTable = ({ data }: MarketsTableProps) => {
</ButtonLink>
) : (
''
)
}
);
}}
/>
<AgGridColumn
flex={2}
@@ -1,14 +1,17 @@
import { Icon } from '@vegaprotocol/ui-toolkit';
// https://github.com/vegaprotocol/vega/blob/develop/core/blockchain/response.go
export const ErrorCodes = new Map([
[51, 'Transaction failed validation'],
[60, 'Transaction could not be decoded'],
[70, 'Error'],
[71, 'Partial success/error'],
[80, 'Unknown command'],
[89, 'Rejected as spam'],
[0, 'Success'],
]);
export const successCodes = new Set([0]);
export const successCodes = new Set([0, 71]);
interface ChainResponseCodeProps {
code: number;
@@ -27,8 +30,13 @@ export const ChainResponseCode = ({
error,
}: ChainResponseCodeProps) => {
const isSuccess = successCodes.has(code);
const icon = isSuccess ? '✅' : '❌';
const successColour =
code === 71 ? 'fill-vega-orange' : 'fill-vega-green-600';
const icon = isSuccess ? (
<Icon name="tick-circle" className={successColour} />
) : (
<Icon name="cross" className="fill-vega-pink-600" />
);
const label = ErrorCodes.get(code) || 'Unknown response code';
// Hack for batches with many errors - see https://github.com/vegaprotocol/vega/issues/7245
@@ -36,7 +44,7 @@ export const ChainResponseCode = ({
error && error.length > 100 ? error.replace(/,/g, ',\r\n') : error;
return (
<div title={`Response code: ${code} - ${label}`} className="inline-block">
<div title={`Response code: ${code} - ${label}`} className=" inline-block">
<span
className="mr-2"
aria-label={isSuccess ? 'Success' : 'Warning'}
@@ -4,6 +4,7 @@ import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint
import { TxDetailsShared } from './shared/tx-details-shared';
import { TableCell, TableRow, TableWithTbody } from '../../table';
import ProposalLink from '../../links/proposal-link/proposal-link';
import { VoteIcon } from '../../vote-icon/vote-icon';
interface TxProposalVoteProps {
txData: BlockExplorerTransactionResult | undefined;
@@ -30,27 +31,22 @@ export const TxProposalVote = ({
return <>{t('Awaiting Block Explorer transaction details')}</>;
}
const vote = txData.command.voteSubmission.value ? '👍' : '👎';
const vote = txData.command.voteSubmission.value === 'VALUE_YES';
return (
<TableWithTbody className="mb-8" allowWrap={true}>
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} />
<TableRow modifier="bordered">
<TableCell>{t('Proposal ID')}</TableCell>
<TableCell>{txData.command.voteSubmission.proposalId}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Proposal details')}</TableCell>
<TableCell>
<ProposalLink id={txData.command.voteSubmission.proposalId} />
</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Proposal')}</TableCell>
<TableCell>{txData.command.voteSubmission.proposalId}</TableCell>
</TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Vote')}</TableCell>
<TableCell>{vote}</TableCell>
<TableCell>
<VoteIcon vote={vote} />
</TableCell>
</TableRow>
</TableWithTbody>
);
@@ -0,0 +1,56 @@
import type { Proposal } from './tx-proposal';
import { proposalRequiresSignatureBundle } from './tx-proposal';
describe('proposalRequiresSignatureBundle', () => {
it('should return false for freeform proposals, which do not require a signature bundle to enact', () => {
const mock = {
terms: {
newFreeform: {},
},
};
expect(proposalRequiresSignatureBundle(mock)).toEqual(false);
});
it('should return false for newMarket proposals, which do not require a signature bundle to enact', () => {
const mock = {
terms: {
newMarket: {},
},
};
expect(proposalRequiresSignatureBundle(mock)).toEqual(false);
});
it('should return true for newAsset proposals, which do require a signature bundle to enact', () => {
const mock = {
terms: {
newAsset: {},
},
};
expect(proposalRequiresSignatureBundle(mock)).toEqual(true);
});
it('should return true for updateAsset proposals, which do require a signature bundle to enact', () => {
const mock = {
terms: {
updateAsset: {},
},
};
expect(proposalRequiresSignatureBundle(mock)).toEqual(true);
});
it('should return false when bad data is supplied', () => {
expect(
proposalRequiresSignatureBundle(false as unknown as Proposal)
).toEqual(false);
expect(
proposalRequiresSignatureBundle(undefined as unknown as Proposal)
).toEqual(false);
expect(
proposalRequiresSignatureBundle({ test: false } as unknown as Proposal)
).toEqual(false);
});
});
@@ -28,11 +28,16 @@ interface TxProposalProps {
* @returns boolean True if a signature bundle is required. Used to fetch a signature bundle
*/
export function proposalRequiresSignatureBundle(proposal?: Proposal): boolean {
const proposalsThatRequireBundles = ['newAsset', 'updateAsset'];
if (!proposal?.terms) {
return false;
}
return !!['newAsset', 'updateAsset'].filter((requiredIfExists) =>
has(proposal.terms, requiredIfExists)
return (
proposalsThatRequireBundles.filter((requiredIfExists) =>
has(proposal.terms, requiredIfExists)
).length > 0
);
}
@@ -81,6 +86,7 @@ export const TxProposal = ({ txData, pubKey, blockData }: TxProposalProps) => {
const tx = proposal.terms?.newAsset || proposal.terms?.updateAsset;
// This component is not rendered if no bundle is required
const SignatureBundleComponent = proposal.terms?.newAsset
? ProposalSignatureBundleNewAsset
: ProposalSignatureBundleUpdateAsset;
@@ -1,5 +1,6 @@
import { t } from '@vegaprotocol/i18n';
import type { components } from '../../../types/explorer';
import { VoteIcon } from '../vote-icon/vote-icon';
interface TxOrderTypeProps {
orderType: string;
@@ -137,12 +138,15 @@ export const TxOrderType = ({ orderType, command }: TxOrderTypeProps) => {
let type = displayString[orderType] || orderType;
let colours =
'text-white dark:text-white bg-vega-dark-150 dark:bg-vega-dark-150';
'text-white dark:text-white bg-vega-dark-150 dark:bg-vega-dark-250';
// This will get unwieldy and should probably produce a different colour of tag
if (type === 'Chain Event' && !!command?.chainEvent) {
type = getLabelForChainEvent(command.chainEvent);
colours = 'text-white dark-text-white bg-vega-pink dark:bg-vega-pink';
} else if (type === 'Validator Heartbeat') {
colours =
'text-white dark-text-white bg-vega-light-200 dark:bg-vega-dark-100';
} else if (type === 'Proposal' || type === 'Governance Proposal') {
if (command && !!command.proposalSubmission) {
type = getLabelForProposal(command.proposalSubmission);
@@ -150,6 +154,17 @@ export const TxOrderType = ({ orderType, command }: TxOrderTypeProps) => {
colours = 'text-black bg-vega-yellow';
}
if (type === 'Vote on Proposal') {
return (
<VoteIcon
vote={command?.voteSubmission?.value === 'VALUE_YES'}
yesText="Proposal vote"
noText="Proposal vote"
useVoteColour={false}
/>
);
}
if (type === 'Vote on Proposal' || type === 'Vote Submission') {
colours = 'text-black bg-vega-yellow';
}
@@ -98,6 +98,6 @@ describe('Txs infinite list item', () => {
expect(screen.getByTestId('pub-key')).toHaveTextContent('testPubKey');
expect(screen.getByTestId('tx-type')).toHaveTextContent('testType');
expect(screen.getByTestId('tx-block')).toHaveTextContent('1');
expect(screen.getByTestId('tx-success')).toHaveTextContent('Success: ✅');
expect(screen.getByTestId('tx-success')).toHaveTextContent('Success');
});
});
@@ -31,7 +31,7 @@ export const TxsInfiniteListItem = ({
return (
<div
data-testid="transaction-row"
className="flex items-center h-full border-t border-neutral-600 dark:border-neutral-800 txs-infinite-list-item grid grid-cols-10 py-2"
className="flex items-center h-full border-t border-neutral-600 dark:border-neutral-800 txs-infinite-list-item grid grid-cols-10"
>
<div
className="text-sm col-span-10 md:col-span-3 leading-none"
@@ -83,7 +83,7 @@ export const TxsInfiniteListItem = ({
data-testid="tx-success"
>
<span className="md:hidden uppercase text-vega-dark-300">
Success:&nbsp;
Success&nbsp;
</span>
{isNumber(code) ? (
<ChainResponseCode code={code} hideLabel={true} />
@@ -0,0 +1,50 @@
import { render } from '@testing-library/react';
import { VoteIcon } from './vote-icon';
describe('Vote TX icon', () => {
it('should use the text For by default for yes votes', () => {
const yes = render(<VoteIcon vote={true} />);
expect(yes.getByTestId('label')).toHaveTextContent('For');
});
it('should use the yesText for yes votes if specified', () => {
const yes = render(<VoteIcon vote={true} yesText="Test" />);
expect(yes.getByTestId('label')).toHaveTextContent('Test');
});
it('should display the tick icon for yes votes', () => {
const no = render(<VoteIcon vote={true} />);
expect(no.getByRole('img')).toHaveAttribute(
'aria-label',
'tick-circle icon'
);
});
it('should use the text Against by default for no votes', () => {
const no = render(<VoteIcon vote={false} />);
expect(no.getByTestId('label')).toHaveTextContent('Against');
});
it('should use the noText for no votes if specified', () => {
const no = render(<VoteIcon vote={false} noText="Test" />);
expect(no.getByTestId('label')).toHaveTextContent('Test');
});
it('should display the delete icon for no votes', () => {
const no = render(<VoteIcon vote={false} />);
expect(no.getByRole('img')).toHaveAttribute('aria-label', 'delete icon');
});
it('useVoteColour prop can be used to override coloured background', () => {
const no = render(<VoteIcon vote={false} />);
expect(no.container.children[0]).toHaveClass('bg-vega-pink-550');
const monochromeNo = render(
<VoteIcon vote={false} useVoteColour={false} />
);
expect(monochromeNo.container.children[0]).not.toHaveClass(
'bg-vega-pink-550'
);
expect(monochromeNo.container.children[0]).toHaveClass('bg-vega-dark-200');
});
});
@@ -0,0 +1,67 @@
import { Icon } from '@vegaprotocol/ui-toolkit';
import type { IconName } from '@vegaprotocol/ui-toolkit';
export interface VoteIconProps {
// True is a yes vote, false is undefined or no vorte
vote: boolean;
// Defaults to 'For', but can be any text
yesText?: string;
// Defaults to 'Against', but can be any text
noText?: string;
// If set to false the background will not be coloured
useVoteColour?: boolean;
}
function getBgColour(useVoteColour: boolean, vote: boolean) {
if (useVoteColour === false) {
return 'bg-vega-dark-200';
}
return vote ? 'bg-vega-green-550' : 'bg-vega-pink-550';
}
function getFillColour(useVoteColour: boolean, vote: boolean) {
if (useVoteColour === false) {
return 'white';
}
return vote ? 'vega-green-300' : 'vega-pink-300';
}
function getTextColour(useVoteColour: boolean, vote: boolean) {
if (useVoteColour === false) {
return 'white';
}
return vote ? 'vega-green-200' : 'vega-pink-200';
}
/**
* Displays a lozenge with an icon representing the way a user voted for a proposal.
* The yes and no text can be overridden
*
* @returns
*/
export function VoteIcon({
vote,
useVoteColour = true,
yesText = 'For',
noText = 'Against',
}: VoteIconProps) {
const label = vote ? yesText : noText;
const icon: IconName = vote ? 'tick-circle' : 'delete';
const bg = getBgColour(useVoteColour, vote);
const fill = getFillColour(useVoteColour, vote);
const text = getTextColour(useVoteColour, vote);
return (
<div
className={`voteicon inline-block my-1 py-1 px-2 py rounded-md text-white leading-one sm align-top ${bg}`}
>
<Icon name={icon} size={3} className={`mr-2 p-0 fill-${fill}`} />
<span className={`text-base text-${text}`} data-testid="label">
{label}
</span>
</div>
);
}
@@ -8,7 +8,7 @@ import { useScrollToLocation } from '../../hooks/scroll-to-location';
import { useDocumentTitle } from '../../hooks/use-document-title';
import compact from 'lodash/compact';
import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog';
import { marketInfoWithDataProvider } from '@vegaprotocol/market-info';
import { marketInfoWithDataProvider } from '@vegaprotocol/markets';
import { PageTitle } from '../../components/page-helpers/page-title';
export const MarketPage = () => {
@@ -1,6 +1,6 @@
import { useScrollToLocation } from '../../hooks/scroll-to-location';
import { useDocumentTitle } from '../../hooks/use-document-title';
import { marketsProvider } from '@vegaprotocol/market-list';
import { marketsProvider } from '@vegaprotocol/markets';
import { RouteTitle } from '../../components/route-title';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n';
@@ -1,12 +1,13 @@
import { render } from '@testing-library/react';
import { OracleDetailsType } from './oracle-details-type';
import type { SourceTypeName } from './oracle-details-type';
import { OracleDetailsType, isInternalSourceType } from './oracle-details-type';
import type { SourceType } from './oracle';
import { PropertyKeyType } from '@vegaprotocol/types';
function renderComponent(type: SourceTypeName) {
return <OracleDetailsType type={type} />;
function renderComponent(type: SourceType) {
return <OracleDetailsType sourceType={type} />;
}
function renderWrappedComponent(type: SourceTypeName) {
function renderWrappedComponent(type: SourceType) {
return (
<table>
<tbody>{renderComponent(type)}</tbody>
@@ -14,19 +15,53 @@ function renderWrappedComponent(type: SourceTypeName) {
);
}
function mock(name: string): SourceType {
return {
sourceType: {
filters: [
{
__typename: 'Filter',
key: {
name,
type: PropertyKeyType.TYPE_STRING,
},
},
],
},
};
}
describe('Oracle type view', () => {
it('Renders nothing when type is null', () => {
const res = render(renderComponent(null as unknown as SourceTypeName));
const res = render(renderComponent(null as unknown as SourceType));
expect(res.container).toBeEmptyDOMElement();
});
it('Renders Internal time for internal sources', () => {
const res = render(renderWrappedComponent('DataSourceDefinitionInternal'));
expect(res.getByText('Internal time')).toBeInTheDocument();
it('Renders Internal time for internal sources - timestamp', () => {
const s = mock('vegaprotocol.builtin.timestamp');
expect(isInternalSourceType(s)).toEqual(true);
const res = render(renderWrappedComponent(s));
expect(res.getByText('Internal data')).toBeInTheDocument();
});
it('Renders Internal time for internal sources - potential future types', () => {
const s = mock('vegaprotocol.builtin.boolean');
expect(isInternalSourceType(s)).toEqual(true);
const res = render(renderWrappedComponent(s));
expect(res.getByText('Internal data')).toBeInTheDocument();
});
it('Renders External data otherwise - prices.external.whatever', () => {
const s = mock('prices.external.whatever');
expect(isInternalSourceType(s)).toEqual(false);
const res = render(renderWrappedComponent(s));
expect(res.getByText('External data')).toBeInTheDocument();
});
it('Renders External data otherwise', () => {
const res = render(renderWrappedComponent('DataSourceDefinitionExternal'));
const s = mock('prices.external.vegaprotocol.builtin.');
expect(isInternalSourceType(s)).toEqual(false);
const res = render(renderWrappedComponent(s));
expect(res.getByText('External data')).toBeInTheDocument();
});
});
@@ -1,27 +1,51 @@
import { TableRow, TableCell, TableHeader } from '../../../components/table';
import type { SourceType } from './oracle';
export type SourceTypeName = SourceType['__typename'] | undefined;
/**
* Basic function to determine if a source is internal or external.
*
* This should be distinguishable using __typename, but the type is incorrectly
* reported at the moment, so instead we check the filters.
*
* @param s SourceType
* @returns boolean True if the source is internal
*/
export function isInternalSourceType(s: SourceType) {
if ('filters' in s.sourceType) {
const filters = s.sourceType.filters;
if (filters) {
return (
filters?.filter((f) => {
return f.key.name?.indexOf('vegaprotocol.builtin.') === 0;
}).length > 0
);
}
}
return false;
}
interface OracleDetailsTypeProps {
type: SourceTypeName;
sourceType: SourceType;
}
/**
* Renders a a single table row for the Oracle Details view that shows
* if the oracle is using the internal time oracle or external data
*/
export function OracleDetailsType({ type }: OracleDetailsTypeProps) {
if (!type) {
export function OracleDetailsType({ sourceType }: OracleDetailsTypeProps) {
if (!sourceType) {
return null;
}
const isInternal = isInternalSourceType(sourceType);
return (
<TableRow modifier="bordered">
<TableHeader scope="row">Type</TableHeader>
<TableCell modifier="bordered">
{type === 'DataSourceDefinitionInternal'
? 'Internal time'
: 'External data'}
{isInternal ? 'Internal data' : 'External data'}
</TableCell>
</TableRow>
);
@@ -53,7 +53,7 @@ export const OracleDetails = ({
<OracleLink id={id} />
</TableCell>
</TableRow>
<OracleDetailsType type={sourceType.__typename} />
<OracleDetailsType sourceType={sourceType} />
<OracleSigners sourceType={sourceType} />
<OracleMarkets id={id} />
<TableRow modifier="bordered">
@@ -0,0 +1,40 @@
import { t } from '@vegaprotocol/i18n';
import { RouteTitle } from '../../components/route-title';
export const Disclaimer = () => {
return (
<section>
<div className="px-40 max-sm:px-0 max-md:px-10 mb-4 max-w-5xl">
<RouteTitle data-testid="disclaimer-header">
{t('Disclaimer')}
</RouteTitle>
<p className="mt-3">
The Vega Block Explorer is an application that allows users to, among
other things, browse through blocks, view wallet addresses, network
hashrate, transaction data and other key information on the Vega
blockchain. It is free, public and open source software. Software
upgrades may contain bugs or security vulnerabilities that might
result in loss of functionality.
</p>
<p className="mt-3">
The Vega Block Explorer uses data from nodes on the Vega Blockchain.
The developers of the Vega Block Explorer do not operate or run the
Vega Blockchain or any other blockchain.
</p>
<p className="mt-3 font-semibold">
The Vega Block Explorer is provided as is. The developers of the
Vega Block Explorer make no representations or warranties of any kind,
whether express or implied, statutory or otherwise regarding the Vega
Block Explorer. They disclaim all warranties of merchantability,
quality, fitness for purpose. They disclaim all warranties that the
Vega Block Explorer is free of harmful components or errors.
</p>
<p className="mt-3 font-bold">
No developer of the Vega Block Explorer accepts any responsibility
for, or liability to users in connection with their use of the Vega
Block Explorer.
</p>
</div>
</section>
);
};
@@ -10,4 +10,5 @@ export const Routes = {
MARKETS: 'markets',
ORACLES: 'oracles',
NETWORK_PARAMETERS: 'network-parameters',
DISCLAIMER: 'disclaimer',
};
@@ -29,6 +29,7 @@ import { AssetLink, MarketLink } from '../components/links';
import { truncateMiddle } from '@vegaprotocol/ui-toolkit';
import { remove0x } from '@vegaprotocol/utils';
import { PartyAccountsByAsset } from './parties/id/accounts';
import { Disclaimer } from './pages/disclaimer';
export type Navigable = {
path: string;
@@ -335,6 +336,17 @@ export const routerConfig: Route[] = [
},
],
},
{
path: Routes.DISCLAIMER,
element: <Disclaimer />,
handle: {
name: t('Disclaimer'),
text: t('Disclaimer'),
breadcrumb: () => (
<Link to={Routes.DISCLAIMER}>{t('Disclaimer')}</Link>
),
},
},
...partiesRoutes,
...assetsRoutes,
...genesisRoutes,
+7 -5
View File
@@ -32,9 +32,9 @@
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
}
.vega-ag-grid .ag-row {
border-width: 1px 0;
border-bottom: 1px solid transparent;
.vega-ag-grid .ag-row,
.vega-ag-grid .ag-cell {
border-width: 0;
}
/* Light variables */
@@ -46,7 +46,6 @@
--ag-header-column-separator-color: theme(colors.neutral[300]);
--ag-row-border-color: theme(colors.white);
--ag-row-hover-color: theme(colors.neutral[100]);
--ag-font-size: 12px;
}
/* Dark variables */
@@ -58,5 +57,8 @@
--ag-header-column-separator-color: theme(colors.neutral[600]);
--ag-row-border-color: theme(colors.black);
--ag-row-hover-color: theme(colors.neutral[800]);
--ag-font-size: 12px;
}
.voteicon svg {
vertical-align: baseline;
}
+1
View File
@@ -17,6 +17,7 @@ NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
#Test configuration variables
CYPRESS_FAIRGROUND=false
+3 -1
View File
@@ -1,10 +1,11 @@
const { defineConfig } = require('cypress');
module.exports = defineConfig({
projectId: 'et4snf',
reporter: '../../node_modules/cypress-mochawesome-reporter',
e2e: {
setupNodeEvents(on, config) {
require('cypress-mochawesome-reporter/plugin')(on);
require('@cypress/grep/src/plugin')(config);
return config;
},
@@ -25,6 +26,7 @@ module.exports = defineConfig({
viewportWidth: 1440,
viewportHeight: 900,
numTestsKeptInMemory: 5,
downloadsFolder: 'cypress/downloads',
testIsolation: false,
},
env: {
@@ -0,0 +1,113 @@
{
"rationale": {
"title": "New Market Proposal E2E submission",
"description": "E2E new market proposal"
},
"terms": {
"newMarket": {
"changes": {
"decimalPlaces": "5",
"positionDecimalPlaces": "5",
"linearSlippageFactor": "0.001",
"quadraticSlippageFactor": "0",
"lpPriceRange": "10",
"instrument": {
"name": "Token test market",
"code": "TEST.24h",
"future": {
"settlementAsset": "73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0",
"quoteName": "fBTC",
"dataSourceSpecForSettlementData": {
"external": {
"oracle": {
"signers": [
{
"pubKey": {
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
}
}
],
"filters": [
{
"key": {
"name": "prices.ETH.value",
"type": "TYPE_INTEGER",
"numberDecimalPlaces": "0"
},
"conditions": [
{
"operator": "OPERATOR_GREATER_THAN",
"value": "0"
}
]
}
]
}
}
},
"dataSourceSpecForTradingTermination": {
"external": {
"oracle": {
"signers": [
{
"pubKey": {
"key": "70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680"
}
}
],
"filters": [
{
"key": {
"name": "trading.terminated.ETH5",
"type": "TYPE_BOOLEAN"
},
"conditions": [
{
"operator": "OPERATOR_EQUALS",
"value": "true"
}
]
}
]
}
}
},
"dataSourceSpecBinding": {
"settlementDataProperty": "prices.ETH.value",
"tradingTerminationProperty": "trading.terminated.ETH5"
}
}
},
"metadata": ["sector:energy", "sector:tech", "source:docs.vega.xyz"],
"priceMonitoringParameters": {
"triggers": [
{
"horizon": "43200",
"probability": "0.9999999",
"auctionExtension": "600"
}
]
},
"liquidityMonitoringParameters": {
"targetStakeParameters": {
"timeWindow": "3600",
"scalingFactor": 10
},
"triggeringRatio": "0.7",
"auctionExtension": "1"
},
"logNormal": {
"tau": 0.0001140771161,
"riskAversionParameter": 0.01,
"params": {
"mu": 0,
"r": 0.016,
"sigma": 0.5
}
}
}
},
"closingTimestamp": 0,
"enactmentTimestamp": 0
}
}
@@ -7,17 +7,12 @@ import {
import {
createRawProposal,
createTenDigitUnixTimeStampForSpecifiedDays,
enterUniqueFreeFormProposalBody,
generateFreeFormProposalTitle,
getDateFormatForSpecifiedDays,
getProposalIdFromList,
getProposalFromTitle,
getProposalInformationFromTable,
getSubmittedProposalFromProposalList,
goToMakeNewProposal,
governanceProposalType,
submitUniqueRawProposal,
voteForProposal,
waitForProposalSubmitted,
waitForProposalSync,
} from '../../../../governance-e2e/src/support/governance.functions';
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../../../governance-e2e/src/support/staking.functions';
import { ethereumWalletConnect } from '../../../../governance-e2e/src/support/wallet-eth.functions';
@@ -38,6 +33,9 @@ const proposalDetailsTitle = '[data-testid="proposal-title"]';
const proposalDetailsDescription = '[data-testid="proposal-description"]';
const openProposals = '[data-testid="open-proposals"]';
const viewProposalButton = '[data-testid="view-proposal-btn"]';
const proposalDescriptionToggle = 'proposal-description-toggle';
const voteBreakdownToggle = 'vote-breakdown-toggle';
const proposalTermsToggle = 'proposal-json-toggle';
describe(
'Governance flow for proposal details',
@@ -62,61 +60,69 @@ describe(
// 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 () {
const proposalDescription =
'I propose that everyone evaluate the following IPFS document and vote Yes if they agree. bafybeigwwctpv37xdcwacqxvekr6e4kaemqsrv34em6glkbiceo3fcy4si';
createRawProposal();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getProposalIdFromList(rawProposal.rationale.title);
cy.get('@proposalIdText').then((proposalId) => {
cy.get(openProposals).within(() => {
cy.get(`#${proposalId}`).within(() => {
cy.get(viewProposalButton).should('be.visible').click();
});
cy.get(openProposals).within(() => {
getProposalFromTitle(rawProposal.rationale.title).within(() => {
cy.get(viewProposalButton).should('be.visible').click();
});
});
cy.get(proposalDetailsTitle)
.should('contain', rawProposal.rationale.title)
.and('be.visible');
cy.get(proposalDetailsTitle).should(
'contain.text',
rawProposal.rationale.title
);
cy.getByTestId(proposalDescriptionToggle).click();
cy.getByTestId('proposal-description-toggle');
cy.get(proposalDetailsDescription)
.should('contain', rawProposal.rationale.description)
.and('be.visible');
.find('p')
.should('have.text', proposalDescription);
});
// 3001-VOTE-052
// 3001-VOTE-008
getProposalInformationFromTable('ID')
.invoke('text')
.should('not.be.empty')
.and('have.length', 64);
// 3001-VOTE-009
getProposalInformationFromTable('Proposed by')
.invoke('text')
.should('not.be.empty')
.and('have.length', 64);
cy.getByTestId(proposalTermsToggle).click();
// 3001-VOTE-052 3001-VOTE-010
cy.get('code.language-json')
.should('exist')
.within(() => {
cy.get('.hljs-string').eq(0).should('have.text', '"ProposalTerms"');
cy.get('.hljs-attr').eq(0).should('have.text', '"id"');
});
});
// 3001-VOTE-043
it('Newly created freeform proposal details - shows proposed and closing dates', function () {
const closingVoteHrs = '72';
const proposalTitle = generateFreeFormProposalTitle();
const proposalTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
goToMakeNewProposal(governanceProposalType.FREEFORM);
enterUniqueFreeFormProposalBody(closingVoteHrs, proposalTitle);
waitForProposalSubmitted();
waitForProposalSync();
submitUniqueRawProposal({
proposalTitle: proposalTitle,
closingTimestamp: proposalTimeStamp,
});
navigateTo(navigation.proposals);
getSubmittedProposalFromProposalList(proposalTitle).within(() =>
getProposalFromTitle(proposalTitle).within(() =>
cy.get(viewProposalButton).click()
);
cy.wrap(
formatDateWithLocalTimezone(new Date(proposalTimeStamp * 1000))
).then((closingDate) => {
getProposalInformationFromTable('Closes on')
.contains(closingDate)
.should('be.visible');
});
cy.wrap(
formatDateWithLocalTimezone(
new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000)
)
).then((proposalDate) => {
getProposalInformationFromTable('Proposed on')
.contains(proposalDate)
.should('be.visible');
getProposalInformationFromTable('Closes on').should(
'have.text',
closingDate
);
});
getProposalInformationFromTable('Proposed on')
.invoke('text')
.should('not.be.empty');
});
it('Newly created proposal details - shows default status set to fail', function () {
@@ -125,13 +131,14 @@ describe(
// 3001-VOTE-067
createRawProposal();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(
rawProposal.rationale.title
).within(() => cy.get(viewProposalButton).click());
getProposalFromTitle(rawProposal.rationale.title).within(() =>
cy.get(viewProposalButton).click()
);
});
cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should(
'be.visible'
);
cy.getByTestId(voteBreakdownToggle).click();
getProposalInformationFromTable('Expected to pass')
.contains('👎')
.should('be.visible');
@@ -151,9 +158,9 @@ describe(
it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () {
createRawProposal();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(
rawProposal.rationale.title
).within(() => cy.get(viewProposalButton).click());
getProposalFromTitle(rawProposal.rationale.title).within(() =>
cy.get(viewProposalButton).click()
);
});
// 3001-VOTE-080
cy.getByTestId('vote-buttons').contains('against').should('be.visible');
@@ -179,6 +186,7 @@ describe(
cy.get(proposalVoteProgressAgainstTokens)
.contains('0.00')
.and('be.visible');
cy.getByTestId(voteBreakdownToggle).click();
getProposalInformationFromTable('Tokens for proposal')
.should('have.text', (1).toFixed(2))
.and('be.visible');
@@ -220,14 +228,15 @@ describe(
vegaWalletSetSpecifiedApprovalAmount('1000');
createRawProposal();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(
rawProposal.rationale.title
).within(() => cy.get(viewProposalButton).click());
getProposalFromTitle(rawProposal.rationale.title).within(() =>
cy.get(viewProposalButton).click()
);
});
voteForProposal('for');
// 3001-VOTE-079
cy.contains('You voted: For').should('be.visible');
cy.get(proposalVoteProgressForTokens).contains('1').and('be.visible');
cy.getByTestId(voteBreakdownToggle).click();
getProposalInformationFromTable('Total Supply')
.invoke('text')
.then((totalSupply) => {
@@ -235,14 +244,15 @@ describe(
(Number(totalSupply.replace(/,/g, '')) * 0.001) /
100
).toFixed(2);
ethereumWalletConnect();
ensureSpecifiedUnstakedTokensAreAssociated(
tokensRequiredToAchieveResult
);
navigateTo(navigation.proposals);
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(
rawProposal.rationale.title
).within(() => cy.get(viewProposalButton).click());
getProposalFromTitle(rawProposal.rationale.title).within(() =>
cy.get(viewProposalButton).click()
);
});
cy.get(proposalVoteProgressForPercentage)
.contains('100.00%')
@@ -259,6 +269,7 @@ describe(
cy.get(proposalVoteProgressAgainstTokens)
.contains('0.00')
.and('be.visible');
cy.getByTestId(voteBreakdownToggle).click();
getProposalInformationFromTable('Total tokens voted percentage')
.should('have.text', '0.00%')
.and('be.visible');
@@ -14,6 +14,7 @@ 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';
@@ -43,6 +44,7 @@ context(
waitForSpinner();
cy.connectVegaWallet();
ethereumWalletConnect();
ensureSpecifiedUnstakedTokensAreAssociated('1');
navigateTo(navigation.proposals);
});
@@ -58,14 +60,12 @@ context(
.parentsUntil(proposalListItem)
.last()
.within(() => {
cy.get(proposalStatus).should('have.text', 'Enacted ');
cy.get(proposalStatus).should('have.text', 'Enacted');
cy.get(viewProposalButton).click();
});
});
cy.getByTestId('proposal-type').should('have.text', 'New market');
getProposalInformationFromTable('State')
.contains('Enacted')
.and('be.visible');
cy.get(proposalStatus).should('have.text', 'Enacted');
cy.get(votesTable).within(() => {
cy.contains('Vote passed.').should('be.visible');
cy.contains('Voting has ended.').should('be.visible');
@@ -87,16 +87,10 @@ context(
.last()
.within(() => cy.get(viewProposalButton).click());
});
getProposalInformationFromTable('State')
.contains('Open')
.and('be.visible');
cy.get(proposalStatus).should('have.text', 'Open');
voteForProposal('for');
getProposalInformationFromTable('State') // 3001-VOTE-047
.contains('Passed', proposalTimeout)
.and('be.visible');
getProposalInformationFromTable('State')
.contains('Enacted', proposalTimeout)
.and('be.visible');
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Passed');
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Enacted');
cy.get(votesTable).within(() => {
cy.contains('Vote passed.').should('be.visible');
cy.contains('Voting has ended.').should('be.visible');
@@ -121,13 +115,9 @@ context(
.last()
.within(() => cy.get(viewProposalButton).click());
});
getProposalInformationFromTable('State')
.contains('Open')
.and('be.visible');
cy.get(proposalStatus).should('have.text', 'Open');
voteForProposal('for');
getProposalInformationFromTable('State')
.contains('Enacted', proposalTimeout)
.and('be.visible');
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Enacted');
});
// 3001-VOTE-048 3001-VOTE-049 3001-VOTE-050
@@ -144,12 +134,8 @@ context(
.last()
.within(() => cy.get(viewProposalButton).click());
});
getProposalInformationFromTable('State')
.contains('Open')
.and('be.visible');
getProposalInformationFromTable('State') // 3001-VOTE-047
.contains('Declined', proposalTimeout)
.and('be.visible');
cy.get(proposalStatus).should('have.text', 'Open');
cy.get(proposalStatus, proposalTimeout).should('have.text', 'Declined');
getProposalInformationFromTable('Rejection reason')
.contains('PROPOSAL_ERROR_PARTICIPATION_THRESHOLD_NOT_REACHED')
.and('be.visible');
@@ -5,12 +5,12 @@ import {
enterRawProposalBody,
enterUniqueFreeFormProposalBody,
generateFreeFormProposalTitle,
getProposalFromTitle,
getProposalInformationFromTable,
getSubmittedProposalFromProposalList,
goToMakeNewProposal,
governanceProposalType,
submitUniqueRawProposal,
voteForProposal,
waitForProposalSubmitted,
waitForProposalSync,
} from '../../support/governance.functions';
@@ -45,11 +45,7 @@ const connectToVegaWalletButton = '[data-testid="connect-to-vega-wallet-btn"]';
const newProposalSubmitButton = '[data-testid="proposal-submit"]';
const viewProposalButton = '[data-testid="view-proposal-btn"]';
const rawProposalData = '[data-testid="proposal-data"]';
const minVoteButton = '[data-testid="min-vote"]';
const maxVoteButton = '[data-testid="max-vote"]';
const voteButtons = '[data-testid="vote-buttons"]';
const votingDate = '[data-testid="voting-date"]';
const voteTwoMinExtraNote = '[data-testid="voting-2-mins-extra"]';
const rejectProposalsLink = '[href="/proposals/rejected"]';
const feedbackError = '[data-testid="Error"]';
const noOpenProposals = '[data-testid="no-open-proposals"]';
@@ -81,7 +77,6 @@ context(
});
vegaWalletSetSpecifiedApprovalAmount('1000');
cy.associateTokensToVegaWallet('1');
});
beforeEach('visit governance tab', function () {
@@ -95,7 +90,8 @@ context(
navigateTo(navigation.proposals);
});
it('Should be able to see that no proposals exist', function () {
// Test can only pass if run before other proposal tests.
it.skip('Should be able to see that no proposals exist', function () {
// 3001-VOTE-003
cy.get(noOpenProposals)
.should('be.visible')
@@ -105,9 +101,8 @@ context(
.and('have.text', 'There are no enacted or rejected proposals');
});
// 3002-PROP-002
// 3002-PROP-003
it('Submit a proposal form - shows how many vega tokens are required to make a proposal', function () {
// 3002-PROP-002 3002-PROP-003 3001-VOTE-012 3007-PNE-020 3004-PMAC-004 3005-PASN-004 3008-PFRO-016 3003-PMAN-004
it('Proposal form - shows how many vega tokens are required to make a proposal', function () {
// 3002-PROP-005
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
cy.contains(
@@ -115,22 +110,14 @@ context(
).should('be.visible');
});
// 3002-PROP-011
// 3002-PROP-011 3008-PFRO-005
it('Able to submit a valid freeform proposal - with minimum required tokens associated', function () {
goToMakeNewProposal(governanceProposalType.FREEFORM);
cy.get(minVoteButton).should('be.visible'); // 3002-PROP-008
cy.get(maxVoteButton).should('be.visible');
cy.get(votingDate).should('not.be.empty');
cy.get(voteTwoMinExtraNote).should(
'contain.text',
'we add 2 minutes of extra time'
);
enterUniqueFreeFormProposalBody('50', generateFreeFormProposalTitle());
// 3002-PROP-012
// 3002-PROP-016
waitForProposalSubmitted();
ensureSpecifiedUnstakedTokensAreAssociated('1');
verifyUnstakedBalance(1);
createRawProposal();
});
// 3008-PFRO-002 3008-PFRO-004
it('Able to submit a valid freeform proposal - with minimum required tokens associated - but also staked', function () {
ensureSpecifiedUnstakedTokensAreAssociated('2');
verifyUnstakedBalance(2);
@@ -140,25 +127,18 @@ context(
closeStakingDialog();
cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2');
navigateTo(navigation.proposals);
goToMakeNewProposal(governanceProposalType.FREEFORM);
enterUniqueFreeFormProposalBody('50', generateFreeFormProposalTitle());
waitForProposalSubmitted();
createRawProposal();
});
it('Creating a proposal - proposal rejected - when closing time sooner than system default', function () {
it.skip('Creating a proposal - proposal rejected - when closing time sooner than system default', function () {
goToMakeNewProposal(governanceProposalType.FREEFORM);
enterUniqueFreeFormProposalBody('0.1', generateFreeFormProposalTitle());
cy.contains('Awaiting network confirmation', epochTimeout).should(
'not.exist'
);
cy.get('input:invalid')
.invoke('prop', 'validationMessage')
.should('equal', 'Value must be greater than or equal to 1.');
});
it('Creating a proposal - proposal rejected - when closing time later than system default', function () {
it.skip('Creating a proposal - proposal rejected - when closing time later than system default', function () {
goToMakeNewProposal(governanceProposalType.FREEFORM);
enterUniqueFreeFormProposalBody(
'100000',
@@ -185,17 +165,13 @@ context(
navigateTo(navigation.proposals);
cy.get(rejectProposalsLink).click();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(
rawProposal.rationale.title
).within(() => {
getProposalFromTitle(rawProposal.rationale.title).within(() => {
cy.contains('Rejected').should('be.visible');
cy.contains('Close time too late').should('be.visible');
cy.get(viewProposalButton).click();
});
});
getProposalInformationFromTable('State')
.contains('Rejected')
.and('be.visible');
cy.getByTestId('proposal-status').should('have.text', 'Rejected');
getProposalInformationFromTable('Rejection reason')
.contains('PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE')
.and('be.visible');
@@ -285,23 +261,38 @@ context(
closeDialog();
});
// 3007-PNE-022 3007-PNE-023 3004-PMAC-006 3004-PMAC-007 3005-PASN-006 3005-PASN-007
// 3006-PASC-006 3006-PASC-007 3008-PFRO-018 3008-PFRO-019 3003-PMAN-006 3003-PMAN-007
it('Unable to submit proposal without valid json', function () {
goToMakeNewProposal(governanceProposalType.RAW);
cy.get(newProposalSubmitButton).click();
cy.getByTestId('input-error-text').should('have.text', 'Required');
cy.get(rawProposalData).type('Not a valid json string');
cy.get(newProposalSubmitButton).click();
cy.getByTestId('input-error-text').should(
'have.text',
'Must be valid JSON'
);
});
// 1005-PROP-009
it('Unable to vote on a freeform proposal - when some but not enough vega associated', function () {
const proposalTitle = generateFreeFormProposalTitle();
ensureSpecifiedUnstakedTokensAreAssociated('1');
goToMakeNewProposal(governanceProposalType.FREEFORM);
enterUniqueFreeFormProposalBody('50', proposalTitle);
waitForProposalSubmitted();
submitUniqueRawProposal({ proposalTitle: proposalTitle });
ethereumWalletConnect();
stakingPageDisassociateTokens('0.0001');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'0.9999'
);
});
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'0.9999'
);
});
navigateTo(navigation.proposals);
getSubmittedProposalFromProposalList(proposalTitle).within(() =>
getProposalFromTitle(proposalTitle).within(() =>
cy.get(viewProposalButton).click()
);
cy.contains('Vote breakdown').should('be.visible', {
@@ -319,9 +310,9 @@ context(
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
cy.get('[data-testid="disconnect"]').click();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(
rawProposal.rationale.title
).within(() => cy.get(viewProposalButton).click());
getProposalFromTitle(rawProposal.rationale.title).within(() =>
cy.get(viewProposalButton).click()
);
});
// 3001-VOTE-075
// 3001-VOTE-076
@@ -1,17 +1,26 @@
import {
closeDialog,
dissociateFromSecondWalletKey,
navigateTo,
navigation,
turnTelemetryOff,
waitForSpinner,
} from '../../support/common.functions';
import {
getDownloadedProposalJsonPath,
submitUniqueRawProposal,
} from '../../support/governance.functions';
import {
getProposalInformationFromTable,
goToMakeNewProposal,
governanceProposalType,
voteForProposal,
waitForProposalSubmitted,
} from '../../support/governance.functions';
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/staking.functions';
import {
ensureSpecifiedUnstakedTokensAreAssociated,
stakingPageAssociateTokens,
stakingPageDisassociateAllTokens,
} from '../../support/staking.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import {
vegaWalletSetSpecifiedApprovalAmount,
@@ -25,15 +34,11 @@ const proposalType = '[data-testid="proposal-type"]';
const proposalDetails = '[data-testid="proposal-details"]';
const newProposalSubmitButton = '[data-testid="proposal-submit"]';
const proposalVoteDeadline = '[data-testid="proposal-vote-deadline"]';
const proposalValidationDeadline =
'[data-testid="proposal-validation-deadline"]';
const proposalParameterSelect = '[data-testid="proposal-parameter-select"]';
const proposalMarketSelect = '[data-testid="proposal-market-select"]';
const newProposalTitle = '[data-testid="proposal-title"]';
const newProposalDescription = '[data-testid="proposal-description"]';
const newProposalTerms = '[data-testid="proposal-terms"]';
const currentParameterValue =
'[data-testid="selected-proposal-param-current-value"]';
const newProposedParameterValue =
'[data-testid="selected-proposal-param-new-value"]';
const minVoteDeadline = '[data-testid="min-vote"]';
@@ -53,19 +58,8 @@ const proposalTermsSection = 'proposal';
const vegaWalletPublicKey = Cypress.env('vegaWalletPublicKey');
const fUSDCId =
'816af99af60d684502a40824758f6b5377e6af48e50a9ee8ef478ecb879ea8bc';
const epochTimeout = Cypress.env('epochTimeout');
const proposalTimeout = { timeout: 14000 };
const governanceProposalType = {
NETWORK_PARAMETER: 'Network parameter',
NEW_MARKET: 'New market',
UPDATE_MARKET: 'Update market',
NEW_ASSET: 'New asset',
UPDATE_ASSET: 'Update asset',
FREEFORM: 'Freeform',
RAW: 'raw proposal',
};
// 3001-VOTE-007
context(
'Governance flow - form validations for different governance proposals',
@@ -88,28 +82,10 @@ context(
navigateTo(navigation.proposals);
});
it('Able to submit valid update network parameter proposal', function () {
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
// 3002-PROP-006
cy.get(newProposalTitle).type('Test update network parameter proposal');
// 3002-PROP-007
cy.get(newProposalDescription).type('E2E test for proposals');
cy.get(proposalParameterSelect).find('option').should('have.length', 117);
cy.get(proposalParameterSelect).select(
// 3007-PNEC-002
'governance_proposal_asset_minEnact'
);
cy.get(currentParameterValue).should('have.value', '2s');
cy.get(newProposedParameterValue).type('5s'); // 3007-PNEC-003
cy.get(newProposalSubmitButton).should('be.visible').click();
waitForProposalSubmitted();
});
it('Unable to submit network parameter with missing/invalid fields', function () {
navigateTo(navigation.proposals);
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
cy.get(newProposalSubmitButton).should('be.visible').click();
cy.get(proposalDownloadBtn).click();
cy.get(inputError).should('have.length', 3);
cy.get(newProposalTitle).type(
'Invalid update network parameter proposal'
@@ -120,62 +96,78 @@ context(
);
cy.get(newProposedParameterValue).type('0');
cy.get(proposalVoteDeadline).clear().type('0');
cy.get(newProposalSubmitButton).click();
cy.contains('Awaiting network confirmation', epochTimeout).should(
'not.exist'
);
cy.get(proposalVoteDeadline).clear().type('9000');
cy.get(newProposalSubmitButton).click();
cy.contains('Awaiting network confirmation', epochTimeout).should(
'not.exist'
);
});
it('Able to download network param proposal json', function () {
const downloadFolder = './cypress/downloads/';
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
cy.log('Download proposal file');
cy.get(proposalDownloadBtn)
.should('be.visible')
.click()
.then(() => {
const filename =
downloadFolder +
'vega-network-param-proposal-' +
getFormattedTime() +
'.json';
cy.readFile(filename, proposalTimeout)
.its('terms.updateNetworkParameter')
.should('exist');
cy.wrap(
getDownloadedProposalJsonPath('vega-network-param-proposal-')
).then((filePath) => {
goToMakeNewProposal(governanceProposalType.RAW);
submitUniqueRawProposal({ proposalBody: filePath, submit: false });
});
});
cy.get(newProposalSubmitButton).click();
validateDialogContentMsg('PROPOSAL_ERROR_CLOSE_TIME_TOO_SOON');
});
// 3007-PNEC-001 3007-PNEC-003
it('Able to download and submit network param proposal', function () {
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
// 3007-PNEC-006
cy.get(newProposalTitle)
.siblings()
.should('contain.text', '(100 characters or less)');
// 3007-PNEC-004 3007-PNEC-005
cy.get(newProposalTitle).type('Test update network parameter proposal');
// 3007-PNEC-009
cy.get(newProposalDescription)
.siblings()
.should('contain.text', '(20,000 characters or less)');
// 3007-PNEC-007 3007-PNEC-008
cy.get(newProposalDescription).type('E2E test for downloading proposals');
// 3007-PNEC-010
cy.get(proposalParameterSelect).select(
'governance_proposal_asset_minClose'
);
// 3007-PNEC-011
cy.get(newProposedParameterValue).type('10s');
// 3007-PNEC-012
cy.get(proposalVoteDeadline).clear().type('2');
// 3007-PNEC-013 3007-PNEC-014
cy.getByTestId('voting-date').invoke('text').should('not.be.empty');
// 3007-PNEC-015
cy.get(maxEnactDeadline).click();
// 3007-PNEC-016
cy.getByTestId('enactment-date').invoke('text').should('not.be.empty');
// 3007-PNEC-017
cy.contains(
'Time till enactment (must be equal to or after vote close)'
).should('be.visible');
// 3007-PNE-018
cy.log('Download updated proposal file');
cy.get(proposalDownloadBtn)
.should('be.visible')
.click()
.then(() => {
const filename =
downloadFolder +
'vega-network-param-proposal-' +
getFormattedTime() +
'.json';
cy.get(proposalDownloadBtn).should('be.visible').click();
cy.readFile(filename, proposalTimeout).then((jsonFile) => {
cy.wrap(jsonFile)
.its('rationale.description')
.should('eq', 'E2E test for downloading proposals');
cy.wrap(jsonFile)
.its('terms.updateNetworkParameter.changes.key')
.should('eq', 'governance.proposal.asset.minClose');
cy.wrap(jsonFile)
.its('terms.updateNetworkParameter.changes.value')
.should('eq', '10s');
cy.wrap(
getDownloadedProposalJsonPath('vega-network-param-proposal-')
).then((filePath) => {
cy.readFile(String(filePath), { timeout: 14000 }).then(
(jsonFile) => {
cy.wrap(jsonFile)
.its('rationale.description')
.should('eq', 'E2E test for downloading proposals');
cy.wrap(jsonFile)
.its('terms.updateNetworkParameter.changes.key')
.should('eq', 'governance.proposal.asset.minClose');
cy.wrap(jsonFile)
.its('terms.updateNetworkParameter.changes.value')
.should('eq', '10s');
}
);
// 3007-PNE-019
goToMakeNewProposal(governanceProposalType.RAW);
submitUniqueRawProposal({ proposalBody: filePath });
});
});
});
@@ -195,14 +187,21 @@ context(
'have.text',
'Proposal will fail if enactment is earlier than the voting deadline'
);
cy.get(proposalDownloadBtn)
.should('be.visible')
.click()
.then(() => {
cy.wrap(
getDownloadedProposalJsonPath('vega-network-param-proposal-')
).then((filePath) => {
goToMakeNewProposal(governanceProposalType.RAW);
submitUniqueRawProposal({ proposalBody: filePath, submit: false });
});
});
cy.get(newProposalSubmitButton).click();
cy.get(feedbackError).should(
'have.text',
validateFeedBackMsg(
'Invalid params: proposal_submission.terms.closing_timestamp (cannot be after enactment time)'
);
closeDialog();
cy.get(minVoteDeadline).click();
cy.get(enactmentDeadlineError).should('not.exist');
});
// 3003-PMAN-001
@@ -217,8 +216,17 @@ context(
delay: 2,
});
});
cy.get(newProposalSubmitButton).should('be.visible').click();
waitForProposalSubmitted();
cy.get(proposalDownloadBtn)
.should('be.visible')
.click()
.then(() => {
cy.wrap(
getDownloadedProposalJsonPath('vega-new-market-proposal-')
).then((filePath) => {
goToMakeNewProposal(governanceProposalType.RAW);
submitUniqueRawProposal({ proposalBody: filePath }); // 3003-PMAN-003
});
});
});
it('Unable to submit new market proposal with missing/invalid fields', function () {
@@ -226,7 +234,7 @@ context(
'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();
cy.get(proposalDownloadBtn).should('be.visible').click();
cy.get(inputError).should('have.length', 3);
cy.get(newProposalTitle).type('Test new market proposal');
cy.get(newProposalDescription).type('E2E test for proposals');
@@ -238,14 +246,28 @@ context(
delay: 2,
});
});
cy.get(proposalDownloadBtn)
.should('be.visible')
.click()
.then(() => {
cy.wrap(
getDownloadedProposalJsonPath('vega-new-market-proposal-')
).then((filePath) => {
goToMakeNewProposal(governanceProposalType.RAW);
submitUniqueRawProposal({ proposalBody: filePath, submit: false });
});
});
cy.get(newProposalSubmitButton).should('be.visible').click();
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
cy.get(feedbackError).should('have.text', errorMsg);
validateFeedBackMsg(errorMsg);
});
// Will fail if run after 'Able to submit update market proposal and vote for proposal'
// 3002-PROP-022
it('Unable to submit update market proposal without equity-like share in the market', function () {
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
cy.get('[data-testid="select-keypair-button"]').eq(0).click(); // switch to second wallet pub key
stakingPageAssociateTokens('1');
goToMakeNewProposal(governanceProposalType.UPDATE_MARKET);
cy.get(newProposalTitle).type('Test update market proposal - rejected');
cy.get(newProposalDescription).type('E2E test for proposals');
@@ -257,12 +279,25 @@ context(
delay: 2,
});
});
cy.get(proposalDownloadBtn)
.should('be.visible')
.click()
.then(() => {
cy.wrap(
getDownloadedProposalJsonPath('vega-update-market-proposal-')
).then((filePath) => {
goToMakeNewProposal(governanceProposalType.RAW);
submitUniqueRawProposal({ proposalBody: filePath, submit: false });
});
});
cy.get(newProposalSubmitButton).should('be.visible').click();
cy.contains('Proposal rejected', proposalTimeout).should('be.visible');
cy.getByTestId('dialog-content')
.find('p')
.should('have.text', 'PROPOSAL_ERROR_INSUFFICIENT_EQUITY_LIKE_SHARE');
ensureSpecifiedUnstakedTokensAreAssociated('1');
validateDialogContentMsg('PROPOSAL_ERROR_INSUFFICIENT_EQUITY_LIKE_SHARE');
closeDialog();
ethereumWalletConnect();
stakingPageDisassociateAllTokens();
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
cy.get('[data-testid="select-keypair-button"]').eq(0).click();
});
// 3002-PROP-020
@@ -284,15 +319,25 @@ context(
delay: 2,
});
});
cy.get(proposalDownloadBtn)
.should('be.visible')
.click()
.then(() => {
cy.wrap(
getDownloadedProposalJsonPath('vega-update-market-proposal-')
).then((filePath) => {
goToMakeNewProposal(governanceProposalType.RAW);
submitUniqueRawProposal({ proposalBody: filePath, submit: false });
});
});
cy.get(newProposalSubmitButton).should('be.visible').click();
cy.contains('Transaction failed', proposalTimeout).should('be.visible');
cy.get(feedbackError).should(
'have.text',
validateFeedBackMsg(
'Network error: the network blocked the transaction through the spam protection: party has insufficient associated governance tokens in their staking account to submit proposal request (ABCI code 89)'
);
});
// 3001-VOTE-092 3004-PMAC-001
// 3001-VOTE-092 3004-PMAC-001 3004-PMAC-003
it('Able to submit update market proposal and vote for proposal', function () {
vegaWalletFaucetAssetsWithoutCheck(
fUSDCId,
@@ -322,11 +367,20 @@ context(
delay: 2,
});
});
cy.get(newProposalSubmitButton).should('be.visible').click();
waitForProposalSubmitted();
cy.get(proposalDownloadBtn)
.should('be.visible')
.click()
.then(() => {
cy.wrap(
getDownloadedProposalJsonPath('vega-update-market-proposal-')
).then((filePath) => {
goToMakeNewProposal(governanceProposalType.RAW);
submitUniqueRawProposal({ proposalBody: filePath });
});
});
navigateTo(navigation.proposals);
cy.get('@EnactedMarketId').then((marketId) => {
cy.contains(String(marketId))
cy.contains(String(marketId).slice(0, 6))
.parentsUntil(proposalListItem)
.last()
.within(() => {
@@ -350,12 +404,13 @@ context(
'contain.text',
'Currently expected to pass'
);
cy.getByTestId('vote-breakdown-toggle').click();
getProposalInformationFromTable('Expected to pass')
.contains('👍 by token vote')
.should('be.visible');
});
// 3001-VOTE-026 3001-VOTE-027 3001-VOTE-028 3001-VOTE-095 3001-VOTE-096 3005-PASN-001
// 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);
@@ -371,25 +426,23 @@ context(
cy.get(minVoteDeadline).click();
cy.get(minValidationDeadline).click();
cy.get(minEnactDeadline).click();
cy.get(proposalDownloadBtn)
.should('be.visible')
.click()
.then(() => {
cy.wrap(
getDownloadedProposalJsonPath('vega-new-asset-proposal-')
).then((filePath) => {
goToMakeNewProposal(governanceProposalType.RAW);
submitUniqueRawProposal({ proposalBody: filePath, submit: false }); // 3005-PASN-003
});
});
cy.get(newProposalSubmitButton).should('be.visible').click();
cy.contains('Awaiting network confirmation', epochTimeout).should(
'be.visible'
);
cy.contains('Proposal waiting for node vote', proposalTimeout).should(
'be.visible'
);
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');
cy.getByTestId('dialog-content')
.last()
.within(() => {
cy.get('p').should(
'have.text',
'PROPOSAL_ERROR_ERC20_ADDRESS_ALREADY_IN_USE'
);
});
validateDialogContentMsg('PROPOSAL_ERROR_ERC20_ADDRESS_ALREADY_IN_USE');
closeDialog();
navigateTo(navigation.proposals);
cy.contains(proposalTitle)
@@ -398,6 +451,7 @@ context(
.within(() => {
cy.getByTestId(viewProposalBtn).click();
});
cy.getByTestId('proposal-terms-toggle').click();
cy.getByTestId(proposalTermsSection).within(() => {
cy.contains('USDT Coin').should('be.visible');
cy.contains('USDT').should('be.visible');
@@ -406,15 +460,8 @@ context(
it('Unable to submit new asset proposal with missing/invalid fields', function () {
goToMakeNewProposal(governanceProposalType.NEW_ASSET);
cy.get(newProposalSubmitButton).should('be.visible').click();
cy.get(proposalDownloadBtn).should('be.visible').click();
cy.get(inputError).should('have.length', 3);
cy.get(newProposalTitle).type('Invalid new asset proposal');
cy.get(newProposalDescription).type('Invalid E2E test for proposals');
cy.get(proposalValidationDeadline).clear().type('2');
cy.get(newProposalSubmitButton).click();
cy.contains('Awaiting network confirmation', epochTimeout).should(
'not.exist'
);
});
it('Able to submit update asset proposal using min deadline', function () {
@@ -425,8 +472,17 @@ context(
enterUpdateAssetProposalDetails();
cy.get(minVoteDeadline).click();
cy.get(minEnactDeadline).click();
cy.get(newProposalSubmitButton).should('be.visible').click();
waitForProposalSubmitted();
cy.get(proposalDownloadBtn)
.should('be.visible')
.click()
.then(() => {
cy.wrap(
getDownloadedProposalJsonPath('vega-update-asset-proposal-')
).then((filePath) => {
goToMakeNewProposal(governanceProposalType.RAW);
submitUniqueRawProposal({ proposalBody: filePath });
});
});
navigateTo(navigation.proposals);
cy.get(openProposals).within(() => {
cy.get(proposalType)
@@ -434,7 +490,7 @@ context(
.parentsUntil(proposalListItem)
.last()
.within(() => {
cy.get(proposalDetails).should('contain.text', assetId); // 3001-VOTE-029
cy.get(proposalDetails).should('contain.text', assetId.slice(0, 6)); // 3001-VOTE-029
cy.getByTestId(viewProposalBtn).click();
});
});
@@ -442,37 +498,97 @@ context(
.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');
cy.getByTestId('proposal-terms-toggle').click();
cy.getByTestId('proposal-terms').within(() => {
getProposalInformationFromTable('assetId').should('have.text', assetId);
getProposalInformationFromTable('lifetimeLimit').should(
'have.text',
'10'
);
});
});
// 3006-PASC-001 3006-PASC-003
it('Able to submit update asset proposal using max deadline', function () {
goToMakeNewProposal(governanceProposalType.UPDATE_ASSET);
enterUpdateAssetProposalDetails();
cy.get(maxVoteDeadline).click();
cy.get(maxEnactDeadline).click();
cy.get(newProposalSubmitButton).should('be.visible').click();
waitForProposalSubmitted();
cy.get(proposalDownloadBtn)
.should('be.visible')
.click()
.then(() => {
cy.wrap(
getDownloadedProposalJsonPath('vega-update-asset-proposal-')
).then((filePath) => {
goToMakeNewProposal(governanceProposalType.RAW);
submitUniqueRawProposal({ proposalBody: filePath });
});
});
});
it('Unable to submit edit asset proposal with missing/invalid fields', function () {
goToMakeNewProposal(governanceProposalType.UPDATE_ASSET);
cy.get(newProposalSubmitButton).should('be.visible').click();
cy.get(proposalDownloadBtn).should('be.visible').click();
cy.get(inputError).should('have.length', 3);
});
function getFormattedTime() {
const now = new Date();
const day = now.getDate().toString().padStart(2, '0');
const month = now.toLocaleString('en-US', { month: 'short' });
const year = now.getFullYear().toString();
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
it('Able to download and submit freeform proposal', function () {
goToMakeNewProposal(governanceProposalType.FREEFORM);
// 3008-PFRO-006
cy.get(newProposalTitle)
.siblings()
.should('contain.text', '(100 characters or less)'); // 3008-PFRO-007
// 3008-PFRO-005
cy.get(newProposalTitle).type('Test freeform proposal form');
// 3008-PFRO-009
cy.get(newProposalDescription)
.siblings()
.should('contain.text', '(20,000 characters or less)'); // 3008-PFRO-010
// 3008-PFRO-008 3002-PROP-012 3002-PROP-016
cy.get(newProposalDescription).type(
'E2E test for downloading freeform proposal'
);
// 3008-PFRO-012
cy.get(minVoteDeadline).should('exist'); // 3002-PROP-008
cy.get(maxVoteDeadline).should('exist');
// 3008-PFRO-011
cy.get(proposalVoteDeadline).clear().type('2');
// 3008-PFRO-013 3008-PFRO-014
cy.getByTestId('voting-date').invoke('text').should('not.be.empty');
// 3008-PFRO-015
cy.log('Download updated proposal file');
cy.get(proposalDownloadBtn)
.should('be.visible')
.click()
.then(() => {
cy.wrap(
getDownloadedProposalJsonPath('vega-freeform-proposal-')
).then((filePath) => {
// 3008-PFRO-019
goToMakeNewProposal(governanceProposalType.RAW);
submitUniqueRawProposal({ proposalBody: filePath });
});
});
});
return `${day}-${month}-${year}-${hours}-${minutes}`;
after('Disassociate from second wallet key if present', function () {
cy.reload();
waitForSpinner();
ethereumWalletConnect();
dissociateFromSecondWalletKey();
});
function validateDialogContentMsg(expectedMsg: string) {
cy.getByTestId('dialog-content')
.last()
.within(() => {
cy.get('p').should('have.text', expectedMsg);
});
}
function validateFeedBackMsg(expectedMsg: string) {
cy.get(feedbackError).should('have.text', expectedMsg);
}
function enterUpdateAssetProposalDetails() {
@@ -6,16 +6,15 @@ import {
waitForSpinner,
} from '../../support/common.functions';
import {
createFreeformProposal,
createRawProposal,
createTenDigitUnixTimeStampForSpecifiedDays,
enterRawProposalBody,
generateFreeFormProposalTitle,
getProposalIdFromList,
getProposalFromTitle,
getProposalInformationFromTable,
getSubmittedProposalFromProposalList,
goToMakeNewProposal,
governanceProposalType,
submitUniqueRawProposal,
voteForProposal,
waitForProposalSubmitted,
waitForProposalSync,
@@ -24,10 +23,14 @@ import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/stakin
import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions';
const proposalListItem = 'proposals-list-item';
const openProposals = '[data-testid="open-proposals"]';
const voteStatus = '[data-testid="vote-status"]';
const voteStatus = 'vote-status';
const proposalType = 'proposal-type';
const proposalStatus = 'proposal-status';
const proposalClosingDate = '[data-testid="vote-details"]';
const viewProposalButton = '[data-testid="view-proposal-btn"]';
const voteBreakDownToggle = 'vote-breakdown-toggle';
describe('Governance flow for proposal list', { tags: '@slow' }, function () {
before('connect wallets and set approval limit', function () {
@@ -60,12 +63,12 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
navigateTo(navigation.proposals);
cy.get(openProposals).within(() => {
cy.get(proposalClosingDate).first().should('contain.text', 'year');
cy.get(proposalClosingDate).should('contain.text', 'months');
cy.get(proposalClosingDate)
.last()
.first()
.invoke('text')
.should('match', /days|minutes/);
cy.get(proposalClosingDate).should('contain.text', 'months');
cy.get(proposalClosingDate).last().should('contain.text', 'year');
});
});
@@ -73,36 +76,28 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
const proposerId = Cypress.env('vegaWalletPublicKey');
const proposalTitle = generateFreeFormProposalTitle();
createFreeformProposal(proposalTitle);
getProposalIdFromList(proposalTitle);
cy.get('@proposalIdText').then((proposalId) => {
cy.get('[data-testid="set-proposals-filter-visible"]').click();
cy.get('[data-testid="filter-input"]').type(proposerId);
cy.get(`#${proposalId}`).should('contain', proposalId);
});
submitUniqueRawProposal({ proposalTitle: proposalTitle });
cy.get('[data-testid="set-proposals-filter-visible"]').click();
cy.get('[data-testid="filter-input"]').type(proposerId);
// cy.get(`#${proposalId}`).should('contain', proposalId);
cy.contains(proposalTitle).should('be.visible');
cy.get('[data-testid="filter-input"]').type('123');
cy.getByTestId(proposalListItem).should('not.exist');
});
it('Newly created proposals list - shows title and portion of summary', function () {
createRawProposal(this.minProposerBalance); // 3001-VOTE-052
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getProposalIdFromList(rawProposal.rationale.title);
cy.get('@proposalIdText').then((proposalId) => {
cy.get(openProposals).within(() => {
// 3001-VOTE-008
// 3001-VOTE-034
cy.get(`#${proposalId}`)
// 3001-VOTE-097
.should('contain', rawProposal.rationale.title)
.and('be.visible');
cy.get(`#${proposalId}`)
.should(
'contain',
rawProposal.rationale.description.substring(0, 59)
)
.and('be.visible');
});
});
});
const proposalPath = 'src/fixtures/proposals/new-market-raw.json';
const proposalTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
submitUniqueRawProposal({
proposalBody: proposalPath,
enactmentTimestamp: proposalTimestamp,
closingTimestamp: proposalTimestamp,
}); // 3001-VOTE-052
// 3001-VOTE-008
// 3001-VOTE-034
// 3001-VOTE-097
cy.contains('New Market Proposal E2E submission');
cy.contains('Code: TEST.24h. fBTC settled future.').should('be.visible');
});
it('Newly created proposals list - shows open proposals in an open state', function () {
@@ -110,23 +105,11 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
// 3001-VOTE-035
createRawProposal(this.minProposerBalance);
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(rawProposal.rationale.title).within(
() => {
cy.get(viewProposalButton).should('be.visible').click();
}
);
cy.get('@proposalIdText').then((proposalId) => {
getProposalInformationFromTable('ID')
.contains(String(proposalId))
.and('be.visible');
getProposalFromTitle(rawProposal.rationale.title).within(() => {
cy.get(viewProposalButton).should('be.visible');
cy.getByTestId(proposalType).should('have.text', 'Freeform');
cy.getByTestId(proposalStatus).should('have.text', 'Open');
});
getProposalInformationFromTable('State')
.contains('Open')
.and('be.visible');
getProposalInformationFromTable('Type')
.contains('Freeform')
.and('be.visible');
});
});
@@ -134,18 +117,22 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
it('Newly created freeform proposals list - shows proposal participation - both met and not', function () {
const proposalTitle = generateFreeFormProposalTitle();
createFreeformProposal(proposalTitle);
getSubmittedProposalFromProposalList(proposalTitle).within(() => {
submitUniqueRawProposal({ proposalTitle: proposalTitle });
getProposalFromTitle(proposalTitle).within(() => {
// 3001-VOTE-039
cy.get(voteStatus).should('have.text', 'Participation not reached');
cy.getByTestId(voteStatus).should(
'have.text',
'Participation not reached'
);
cy.get(viewProposalButton).click();
});
voteForProposal('for');
navigateTo(navigation.proposals);
getSubmittedProposalFromProposalList(proposalTitle).within(() => {
cy.get(voteStatus).should('have.text', 'Set to pass');
getProposalFromTitle(proposalTitle).within(() => {
cy.getByTestId(voteStatus).should('have.text', 'Set to pass');
cy.get(viewProposalButton).click();
});
cy.getByTestId(voteBreakDownToggle).click();
getProposalInformationFromTable('Token participation met')
.contains('👍')
.should('be.visible');
@@ -7,7 +7,6 @@ import {
import {
clickOnValidatorFromList,
closeStakingDialog,
stakingPageAssociateTokens,
stakingValidatorPageAddStake,
waitForBeginningOfEpoch,
} from '../../support/staking.functions';
@@ -30,20 +29,22 @@ context('rewards - flow', { tags: '@slow' }, function () {
turnTelemetryOff();
cy.visit('/');
waitForSpinner();
depositAsset(vegaAssetAddress, '1000', 18);
cy.validatorsSelfDelegate();
ethereumWalletConnect();
cy.connectVegaWallet();
cy.VegaWalletTopUpRewardsPool(30, 200);
navigateTo(navigation.validators);
depositAsset(vegaAssetAddress, '1000', 18);
cy.getByTestId('currency-title', txTimeout).should(
'contain.text',
'Collateral'
);
vegaWalletTeardown();
stakingPageAssociateTokens('6000');
cy.associateTokensToVegaWallet('6000');
navigateTo(navigation.validators);
cy.VegaWalletTopUpRewardsPool();
cy.get(vegaWalletUnstakedBalance, txTimeout).should(
'contain',
'6,000.0',
txTimeout
);
cy.get('button').contains('Select a validator to nominate').click();
clickOnValidatorFromList(0);
stakingValidatorPageAddStake('3000');
closeStakingDialog();
@@ -7,6 +7,7 @@ import {
waitForSpinner,
navigateTo,
navigation,
turnTelemetryOff,
} from '../../support/common.functions';
import {
clickOnValidatorFromList,
@@ -62,11 +63,12 @@ context(
vegaWalletSetSpecifiedApprovalAmount('1000');
});
describe('Eth wallet - contains VEGA tokens', function () {
describe.skip('Eth wallet - contains VEGA tokens', function () {
beforeEach(
'teardown wallet & drill into a specific validator',
function () {
cy.clearLocalStorage();
turnTelemetryOff();
cy.reload();
waitForSpinner();
cy.connectVegaWallet();
@@ -94,7 +96,7 @@ context(
navigateTo(navigation.validators);
// 2002-SINC-007
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
});
it('Able to view validators staked by me', function () {
@@ -107,6 +109,7 @@ context(
cy.getByTestId(userStake, epochTimeout)
.first()
.should('have.text', '2.00');
waitForBeginningOfEpoch();
cy.getByTestId('total-stake').first().realHover();
cy.getByTestId('staked-by-user-tooltip')
.first()
@@ -144,7 +147,7 @@ context(
verifyThisEpochValue(2.0);
closeStakingDialog();
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
});
it('Able to stake against a validator - using vega from both wallet and vesting contract', function () {
@@ -164,10 +167,11 @@ context(
verifyThisEpochValue(6.0);
closeStakingDialog();
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '6.00', '100.00%');
validateValidatorListTotalStakeAndShare('0', '3,006.00', '50.05%');
});
it('Able to stake against multiple validators', function () {
vegaWalletTeardown();
stakingPageAssociateTokens('5');
verifyUnstakedBalance(5.0);
cy.get('button').contains('Select a validator to nominate').click();
@@ -195,14 +199,10 @@ context(
.eq(1)
.within(() => {
cy.getByTestId(stakeValidatorListTotalStake)
.should('have.text', '2.00')
.should('have.text', '3,002.00')
.and('be.visible');
cy.getByTestId(stakeValidatorListTotalShare)
.should('have.text', '66.67%')
.and('be.visible');
cy.getByTestId(stakeValidatorListTotalStake)
.scrollIntoView()
.should('have.text', '2.00')
.should('have.text', '50.01%')
.and('be.visible');
});
cy.get(`[row-id="${1}"]`)
@@ -210,14 +210,10 @@ context(
.within(() => {
cy.getByTestId(stakeValidatorListTotalStake)
.scrollIntoView()
.should('have.text', '1.00')
.should('have.text', '3,001.00')
.and('be.visible');
cy.getByTestId(stakeValidatorListTotalShare)
.should('have.text', '33.33%')
.and('be.visible');
cy.getByTestId(stakeValidatorListTotalStake)
.scrollIntoView()
.should('have.text', '1.00')
.should('have.text', '49.99%')
.and('be.visible');
});
});
@@ -252,10 +248,10 @@ context(
waitForBeginningOfEpoch();
cy.getByTestId(stakeValidatorListStakePercentage).should(
'have.text',
'100%'
'50.02%'
);
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
}
);
@@ -280,7 +276,7 @@ context(
txTimeout
);
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%');
cy.getByTestId(userStakeBtn).should('not.exist');
cy.getByTestId(userStake).should('not.exist');
@@ -352,7 +348,7 @@ context(
txTimeout
);
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%');
});
it('Disassociating all vesting contract tokens max - removes all staked tokens', function () {
@@ -380,10 +376,11 @@ context(
txTimeout
);
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%');
validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%');
});
it('Disassociating some tokens - prioritizes unstaked tokens', function () {
vegaWalletSetSpecifiedApprovalAmount('1000');
stakingPageAssociateTokens('3');
verifyUnstakedBalance(3.0);
cy.get('button').contains('Select a validator to nominate').click();
@@ -402,7 +399,7 @@ context(
});
verifyStakedBalance(2.0);
navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%');
validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
});
it('Associating wallet tokens - when some already staked - auto stakes tokens to staked validator', function () {
@@ -490,6 +487,7 @@ context(
});
afterEach('Teardown Wallet', function () {
navigateTo(navigation.home);
vegaWalletTeardown();
});
@@ -38,7 +38,7 @@ const associatedKey = '[data-testid="associated-key"]';
const associatedAmount = '[data-testid="associated-amount"]';
const associateCompleteText = '[data-testid="transaction-complete-body"]';
const disassociationWarning = '[data-testid="disassociation-warning"]';
const vegaWallet = '[data-testid="vega-wallet"]';
const vegaWallet = 'aside [data-testid="vega-wallet"]';
context(
'Token association flow - with eth and vega wallets connected',
@@ -78,30 +78,15 @@ context(
//0005-ETXN-003
//0005-ETXN-005
stakingPageAssociateTokens('2', { skipConfirmation: true });
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
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', 6);
// 0005-ETXN-002
verifyEthWalletAssociatedBalance('2.0');
verifyEthWalletTotalAssociatedBalance('2.0');
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
2.0
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
});
cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', 2.0);
});
@@ -111,63 +96,48 @@ context(
// 1004-ASSO-028
// 1004-ASSO-029
// 1004-ASSO-031
vegaWalletTeardown();
stakingPageAssociateTokens('2');
verifyEthWalletAssociatedBalance('2.0');
verifyEthWalletTotalAssociatedBalance('2.0');
verifyEthWalletTotalAssociatedBalance('6,002.00');
cy.get('button').contains('Select a validator to nominate').click();
cy.getByTestId('epoch-countdown').should('be.visible');
stakingPageDisassociateTokens('2');
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
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', 6);
cy.getByTestId('eth-wallet-associated-balances', txTimeout).should(
'not.exist'
);
verifyEthWalletTotalAssociatedBalance('0.00');
cy.get(
'[data-testid="eth-wallet-associated-balances"]:visible',
txTimeout
).should('have.length', 2);
verifyEthWalletTotalAssociatedBalance('6,000.00');
});
it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () {
//1004-ASSO-011
stakingPageAssociateTokens('1001', { approve: true });
verifyEthWalletAssociatedBalance('1,001.00');
verifyEthWalletTotalAssociatedBalance('1,001.00');
cy.get(vegaWallet)
.last()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'1,001.00'
);
});
verifyEthWalletTotalAssociatedBalance('7,001.00');
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
'1,001.00'
);
});
});
it('Able to disassociate a partial amount of tokens currently associated', function () {
stakingPageAssociateTokens('2');
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
2.0
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
});
cy.get('button').contains('Select a validator to nominate').click();
cy.getByTestId('epoch-countdown').should('be.visible');
stakingPageDisassociateTokens('1');
verifyEthWalletAssociatedBalance('1.0');
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
1.0
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 1.0);
});
});
it('Able to disassociate all tokens - using max', function () {
@@ -175,15 +145,11 @@ context(
const warningText =
'Warning: Any tokens that have been nominated to a node will sacrifice rewards they are due for the current epoch. If you do not wish to sacrifice these, you should remove stake from a node at the end of an epoch before disassociation.';
stakingPageAssociateTokens('2');
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
2.0
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
});
cy.get('button').contains('Select a validator to nominate').click();
cy.getByTestId('epoch-countdown').should('be.visible');
cy.get(ethWalletDissociateButton).click();
cy.get(disassociationWarning).should('contain', warningText);
stakingPageDisassociateAllTokens();
@@ -201,14 +167,9 @@ context(
'not.exist'
);
});
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
0.0
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 0.0);
});
});
it('Able to associate and disassociate vesting contract tokens', function () {
@@ -223,38 +184,22 @@ context(
type: 'contract',
skipConfirmation: true,
});
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
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', 6);
verifyEthWalletAssociatedBalance('2.0');
verifyEthWalletTotalAssociatedBalance('2.0');
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
2.0
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
});
cy.get(vegaWalletUnstakedBalance, txTimeout).should('contain', 2.0);
stakingPageDisassociateTokens('1', {
type: 'contract',
skipConfirmation: true,
});
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
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', 6);
verifyEthWalletAssociatedBalance('1.0');
verifyEthWalletTotalAssociatedBalance('1.0');
});
@@ -266,6 +211,7 @@ context(
// 1004-ASSO-022
stakingPageAssociateTokens('21', { type: 'wallet' });
cy.get('button').contains('Select a validator to nominate').click();
cy.getByTestId('epoch-countdown').should('be.visible');
stakingPageAssociateTokens('37', { type: 'contract' });
cy.get(vestingContractSection)
.first()
@@ -285,28 +231,18 @@ context(
);
cy.get(associatedAmount, txTimeout).should('contain', 21);
});
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
58
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 58);
});
stakingPageDisassociateTokens('6', { type: 'contract' });
cy.get(vestingContractSection)
.first()
.within(() => {
cy.get(associatedAmount, txTimeout).should('contain', 31);
});
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
52
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 52);
});
navigateTo(navigation.validators);
stakingPageDisassociateTokens('9', { type: 'wallet' });
cy.get(vegaInWalletSection)
@@ -314,14 +250,9 @@ context(
.within(() => {
cy.get(associatedAmount, txTimeout).should('contain', 12);
});
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
43
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 43);
});
});
it('Not able to associate more tokens than owned', function () {
@@ -338,14 +269,9 @@ context(
// 1004-ASSO-004
it('Pending association outside of app is shown', function () {
vegaWalletAssociate('2');
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
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', 6);
validateWalletCurrency('Associated', '2.00');
});
@@ -354,14 +280,9 @@ context(
cy.wrap(validateWalletCurrency('Associated', '2.00')).then(() => {
vegaWalletDisassociate('2');
});
cy.getByTestId('currency-title', txTimeout).should(
'have.length.above',
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', 6);
validateWalletCurrency('Associated', '0.00');
});
@@ -380,14 +301,9 @@ context(
Cypress.env('vegaWalletPublicKey2')
);
stakingPageAssociateTokens('2');
cy.get(vegaWallet)
.first()
.within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should(
'contain',
2.0
);
});
cy.get(vegaWallet).within(() => {
cy.get(vegaWalletAssociatedBalance, txTimeout).should('contain', 2.0);
});
cy.get(associateCompleteText).should(
'have.text',
`Vega key ${Cypress.env(
@@ -15,13 +15,7 @@ const balanceAvailable = 'BALANCE_AVAILABLE_value';
const withdrawalThreshold = 'WITHDRAWAL_THRESHOLD_value';
const delayTime = 'DELAY_TIME_value';
const submitWithdrawalButton = 'submit-withdrawal';
const dialogTitle = 'dialog-title';
const dialogClose = 'dialog-close';
const txExplorerLink = 'tx-block-explorer';
const withdrawalAssetSymbol = 'withdrawal-asset-symbol';
const withdrawalAmount = 'withdrawal-amount';
const withdrawalRecipient = 'withdrawal-recipient';
const withdrawFundsButton = 'withdraw-funds';
const completeWithdrawalButton = 'complete-withdrawal';
const tableTxHash = '[col-id="txHash"]';
const tableAssetSymbol = '[col-id="asset.symbol"]';
@@ -30,14 +24,16 @@ const tableReceiverAddress = '[col-id="details.receiverAddress"]';
const tableWithdrawnTimeStamp = '[col-id="withdrawnTimestamp"]';
const tableWithdrawnStatus = '[col-id="status"]';
const tableCreatedTimeStamp = '[col-id="createdTimestamp"]';
const toastContent = 'toast-content';
const toast = 'toast';
const toastPanel = 'toast-panel';
const toastClose = 'toast-close';
const withdrawalDialogContent = 'dialog-content';
const toastCompleteWithdrawal = 'toast-complete-withdrawal';
const usdtName = 'USDC (local)';
const usdcEthAddress = '0x1b8a1B6CBE5c93609b46D1829Cc7f3Cb8eeE23a0';
const usdcSymbol = 'tUSDC';
const usdtSelectValue =
'993ed98f4f770d91a796faab1738551193ba45c62341d20597df70fea6704ede';
const truncatedWithdrawalEthAddress = '0xEe7D…22d94F';
const formValidationError = 'input-error-text';
const txTimeout = Cypress.env('txTimeout');
@@ -47,11 +43,8 @@ context(
function () {
before('visit withdrawals and connect vega wallet', function () {
cy.visit('/');
// When running tests locally, will fail if run without restarting capsule
cy.updateCapsuleMultiSig().then(() => {
ethereumWalletConnect();
depositAsset(usdcEthAddress, '1000', 5);
});
ethereumWalletConnect();
depositAsset(usdcEthAddress, '1000', 5);
});
beforeEach('Navigate to withdrawal page', function () {
@@ -110,29 +103,35 @@ context(
cy.getByTestId(amountInput).click().type('120');
cy.getByTestId(submitWithdrawalButton).click();
});
cy.contains('Awaiting network confirmation').should('be.visible');
// assert withdrawal request
cy.getByTestId(dialogTitle, txTimeout).should(
'have.text',
'Transaction complete'
);
cy.getByTestId(txExplorerLink)
.should('have.attr', 'href')
.and('contain', '/txs/');
cy.getByTestId(withdrawalAssetSymbol).should('have.text', usdcSymbol);
cy.getByTestId(withdrawalAmount).should('have.text', '120.00');
cy.getByTestId(withdrawalRecipient)
.should('have.text', truncatedWithdrawalEthAddress)
.and('have.attr', 'href')
.and('contain', `/address/${Cypress.env('ethWalletPublicKey')}`);
cy.getByTestId(withdrawFundsButton).click();
cy.getByTestId(toast)
.first(txTimeout)
.should('contain.text', 'Funds unlocked')
.within(() => {
cy.getByTestId('external-link').should('exist');
cy.getByTestId(toastPanel).should(
'contain.text',
'Withdraw 120.00 tUSDC'
);
cy.getByTestId(toastCompleteWithdrawal).click();
cy.getByTestId(toastClose).click();
});
// withdrawal complete
cy.getByTestId(dialogTitle, txTimeout).should(
'have.text',
'Withdraw asset complete'
);
cy.getByTestId(dialogClose).click();
cy.getByTestId(toast)
.first(txTimeout)
.should('contain.text', 'The withdrawal has been approved.')
.within(() => {
cy.getByTestId(toastPanel).should(
'contain.text',
'Withdraw 120.00 tUSDC'
);
});
cy.getByTestId(toast)
.last(txTimeout)
.should('contain.text', 'Transaction confirmed')
.within(() => {
cy.getByTestId('external-link').should('exist');
});
// withdrawal history for complete withdrawal displayed
cy.get(tableWithdrawnStatus)
.eq(1, txTimeout)
@@ -171,13 +170,17 @@ context(
cy.getByTestId(submitWithdrawalButton).click();
});
cy.contains('Awaiting network confirmation').should('be.visible');
// assert withdrawal request
cy.getByTestId(dialogTitle, txTimeout).should(
'have.text',
'Transaction complete'
);
cy.getByTestId(dialogClose).click();
cy.getByTestId(toast)
.first(txTimeout)
.should('contain.text', 'Funds unlocked')
.within(() => {
cy.getByTestId('external-link').should('exist');
cy.getByTestId(toastPanel).should(
'contain.text',
'Withdraw 110.00 tUSDC'
);
cy.getByTestId(toastClose).click();
});
cy.get(tableTxHash)
.eq(1)
.should('have.text', 'Complete withdrawal')
@@ -192,28 +195,75 @@ context(
cy.get(tableCreatedTimeStamp).should('not.be.empty');
});
ethereumWalletConnect();
cy.getByTestId(completeWithdrawalButton).click();
cy.getByTestId(toastContent)
.last()
cy.getByTestId(completeWithdrawalButton).first().click();
cy.getByTestId(toast)
.last(txTimeout)
.should('contain.text', 'Awaiting confirmation')
.within(() => {
cy.getByTestId('external-link').should('exist');
});
cy.getByTestId(toastContent)
.first()
cy.getByTestId(toast)
.first(txTimeout)
.should('contain.text', 'The withdrawal has been approved.')
.within(() => {
cy.getByTestId(toastPanel).should('contain.text', '110.00', 'tUSDC');
});
cy.getByTestId(toastContent)
.last()
cy.getByTestId(toast)
.last(txTimeout)
.should('contain.text', 'Transaction confirmed')
.within(() => {
cy.getByTestId('external-link').should('exist');
});
});
it('Unable to withdraw asset on pub key view', function () {
it('Should be able to see withdrawal details from toast', function () {
cy.getByTestId(withdraw).click();
cy.getByTestId(withdrawalForm, txTimeout).within(() => {
cy.get('select').select(usdtSelectValue, { force: true });
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
cy.getByTestId(withdrawalThreshold).should(
'have.text',
'100,000.00000T'
);
cy.getByTestId(amountInput).click().type('50');
cy.getByTestId(submitWithdrawalButton).click();
});
cy.getByTestId(toast)
.first(txTimeout)
.should('contain.text', 'Funds unlocked')
.within(() => {
cy.getByTestId('external-link').should('exist');
cy.getByTestId(toastPanel).should(
'contain.text',
'Withdraw 50.00 tUSDC'
);
cy.contains('save your withdrawal details').click();
});
cy.getByTestId(withdrawalDialogContent)
.last()
.within(() => {
cy.getByTestId('assetSource_value').should(
'have.text',
'0x1b8a1B6CBE5c93609b46D1829Cc7f3Cb8eeE23a0'
);
cy.getByTestId('amount_value').should('have.text', '5000000');
cy.getByTestId('nonce_value').invoke('text').should('not.be.empty');
cy.getByTestId('signatures_value')
.invoke('text')
.should('not.be.empty');
cy.getByTestId('targetAddress_value').should(
'have.text',
Cypress.env('ethWalletPublicKey')
);
cy.getByTestId('creation_value')
.invoke('text')
.should('not.be.empty');
});
cy.getByTestId(dialogClose).click();
});
// Skipping test due to bug #3882
it.skip('Unable to withdraw asset on pub key view', function () {
const vegaWalletPubKey = Cypress.env('vegaWalletPublicKey');
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.`;
@@ -227,10 +277,11 @@ context(
cy.get('select').select(usdtSelectValue, { force: true });
cy.getByTestId(balanceAvailable, txTimeout).should('exist');
cy.getByTestId(amountInput).click().type('100');
cy.pause();
cy.getByTestId(submitWithdrawalButton).click();
});
cy.getByTestId('dialog-content')
cy.getByTestId(withdrawalDialogContent)
.last()
.within(() => {
cy.get('h1').should('have.text', 'Transaction failed');
@@ -11,7 +11,6 @@ import {
import { mockNetworkUpgradeProposal } from '../../support/proposal.functions';
const proposalDocumentationLink = '[data-testid="proposal-documentation-link"]';
const newProposalLink = '[data-testid="new-proposal-link"]';
const governanceDocsUrl = 'https://vega.xyz/governance';
const connectToVegaWalletButton = '[data-testid="connect-to-vega-wallet-btn"]';
@@ -32,6 +31,14 @@ context(
verifyPageHeader('Proposals');
});
// 3002-PROP-023 3004-PMAC-002 3005-PASN-002 3006-PASC-002 3007-PNEC-002 3008-PFRO-003
it('should have button for link to more information on proposals', function () {
const proposalsUrl = 'https://docs.vega.xyz/mainnet/tutorials/proposals';
cy.getByTestId('new-proposal-link')
.find('a')
.should('have.attr', 'href', proposalsUrl);
});
it('should be able to see a working link for - find out more about Vega governance', function () {
// 3001-VOTE-001
cy.get(proposalDocumentationLink)
@@ -54,17 +61,62 @@ context(
});
});
it.skip('should be able to see button for - new proposal', function () {
// 3001-VOTE-002
cy.get(newProposalLink)
.should('be.visible')
.and('have.text', 'New proposal')
.and('have.attr', 'href')
.and('equal', '/proposals/propose');
// 3007-PNE-021
it('should have documentation links for network parameter proposal', function () {
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
cy.getByTestId('proposal-docs-link')
.find('a')
.should('have.attr', 'href')
.and('contain', '/tutorials/proposals/network-parameter-proposal');
});
it.skip('should be able to see a connect wallet button - if vega wallet disconnected and user is submitting new proposal', function () {
goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
// 3003-PMAN-002 3003-PMAN-005
it('should have documentation links for new market proposal', function () {
goToMakeNewProposal(governanceProposalType.NEW_MARKET);
cy.getByTestId('proposal-docs-link')
.find('a')
.should('have.attr', 'href')
.and('contain', '/tutorials/proposals/new-market-proposal');
});
// 3004-PMAC-005
it('should have documentation links for update market proposal', function () {
goToMakeNewProposal(governanceProposalType.UPDATE_MARKET);
cy.getByTestId('proposal-docs-link')
.find('a')
.should('have.attr', 'href')
.and('contain', '/tutorials/proposals/update-market-proposal');
});
// 3005-PASN-002 005-PASN-005
it('should have documentation links for new asset proposal', function () {
goToMakeNewProposal(governanceProposalType.NEW_ASSET);
cy.getByTestId('proposal-docs-link')
.find('a')
.should('have.attr', 'href')
.and('contain', '/tutorials/proposals/new-asset-proposal');
});
// 3006-PASC-002 3006-PASC-005
it('should have documentation links for update asset proposal', function () {
goToMakeNewProposal(governanceProposalType.UPDATE_ASSET);
cy.getByTestId('proposal-docs-link')
.find('a')
.should('have.attr', 'href')
.and('contain', '/tutorials/proposals/update-asset-proposal');
});
// 3008-PFRO-003 3008-PFRO-017
it('should have documentation links for freeform proposal', function () {
goToMakeNewProposal(governanceProposalType.FREEFORM);
cy.getByTestId('proposal-docs-link')
.find('a')
.should('have.attr', 'href')
.and('contain', '/tutorials/proposals/freeform-proposal');
});
it('should be able to see a connect wallet button - if vega wallet disconnected and user is submitting new proposal', function () {
goToMakeNewProposal(governanceProposalType.RAW);
cy.get(connectToVegaWalletButton)
.should('be.visible')
.and('have.text', 'Connect Vega wallet');
@@ -109,7 +161,7 @@ context(
);
cy.getByTestId('protocol-upgrade-proposal-status').should(
'have.text',
'Approved '
'Approved by validators '
);
});
});
@@ -128,6 +180,7 @@ context(
.first()
.find('[data-testid="view-proposal-btn"]')
.click();
cy.url().should('contain', '/protocol-upgrades/v1');
cy.getByTestId('protocol-upgrade-proposal').within(() => {
cy.get('h1').should('have.text', 'Vega Release v1');
cy.getByTestId('protocol-upgrade-block-height').should(
@@ -136,7 +189,7 @@ context(
);
cy.getByTestId('protocol-upgrade-state').should(
'have.text',
'Approved'
'Approved by validators'
);
cy.getByTestId('protocol-upgrade-release-tag').should(
'have.text',
@@ -9,6 +9,7 @@ import {
import {
enterUniqueFreeFormProposalBody,
goToMakeNewProposal,
governanceProposalType,
} from '../../support/governance.functions';
import { vegaWalletFaucetAssetsWithoutCheck } from '../../support/wallet-vega.functions';
@@ -50,7 +51,7 @@ context('View functionality with public key', { tags: '@smoke' }, 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.`;
navigateTo(navigation.proposals);
goToMakeNewProposal('Freeform');
goToMakeNewProposal(governanceProposalType.FREEFORM);
enterUniqueFreeFormProposalBody('50', 'pub key proposal test');
cy.getByTestId('dialog-content')
.first()
@@ -63,7 +63,6 @@ context(
});
it('should have option to go to last and newest page', function () {
waitForBeginningOfEpoch();
cy.getByTestId('goto-last-page').click();
cy.getByTestId('epoch-total-rewards-table')
.last()
@@ -29,7 +29,7 @@ const performancePenaltyToolTip = '[data-testid="performance-penalty-tooltip"]';
const overstakedPenaltyToolTip = '[data-testid="overstaked-penalty-tooltip"]';
const totalPenaltyToolTip = '[data-testid="total-penalty-tooltip"]';
const epochCountDown = '[data-testid="epoch-countdown"]';
const stakeNumberRegex = /^\d*\.?\d*$/;
const stakeNumberRegex = /^\d{1,3}(,\d{3})*(\.\d+)?$/;
context('Validators Page - verify elements on page', function () {
before('navigate to validators page', function () {
@@ -84,13 +84,13 @@ context('Validators Page - verify elements on page', function () {
cy.get(stakedByOperatorToolTip)
.invoke('text')
.should('contain', 'Staked by operator: 0.00');
.should('contain', 'Staked by operator: 3,000.00');
cy.get(stakedByDelegatesToolTip)
.invoke('text')
.should('contain', 'Staked by delegates: 0.00');
cy.get(totalStakedToolTip)
.invoke('text')
.should('contain', 'Total stake: 0.00');
.should('contain', 'Total stake: 3,000.00');
});
it('Should be able to see validator normalised voting power', function () {
@@ -106,10 +106,10 @@ context('Validators Page - verify elements on page', function () {
cy.get(unnormalisedVotingPowerToolTip)
.invoke('text')
.should('contain', 'Unnormalised voting power: 0.00%');
.should('contain', 'Unnormalised voting power: 20.00%');
cy.get(normalisedVotingPowerToolTip)
.invoke('text')
.should('contain', 'Normalised voting power: 0.10%');
.should('contain', 'Normalised voting power: 50.00%');
});
// 2002-SINC-018
@@ -126,13 +126,13 @@ context('Validators Page - verify elements on page', function () {
cy.get(performancePenaltyToolTip)
.invoke('text')
.should('contain', 'Performance penalty: 100.00%');
.should('contain', 'Performance penalty: 0.00%');
cy.get(overstakedPenaltyToolTip)
.invoke('text')
.should('contain', 'Overstaked penalty:'); // value not asserted due to #2886
.should('contain', 'Overstaked penalty: 60.00%'); // value not asserted due to #2886
cy.get(totalPenaltyToolTip)
.invoke('text')
.should('contain', 'Total penalties: 0.00%');
.should('contain', 'Total penalties: 60.00%');
});
it('Should be able to see validator pending stake', function () {
@@ -1,8 +1,11 @@
import { stakingPageDisassociateAllTokens } from './staking.functions';
const tokenDropDown = 'state-trigger';
const txTimeout = Cypress.env('txTimeout');
export enum navigation {
section = 'nav',
home = '[href="/"]',
vesting = '[href="/token/redeem"]',
validators = '[href="/validators"]',
rewards = '[href="/rewards"]',
@@ -18,6 +21,7 @@ export function convertTokenValueToNumber(subject: string) {
}
const topLevelRoutes = [
navigation.home,
navigation.proposals,
navigation.validators,
navigation.rewards,
@@ -97,3 +101,25 @@ export function turnTelemetryOff() {
win.localStorage.setItem('vega_telemetry_on', 'false')
);
}
export function dissociateFromSecondWalletKey() {
const secondWalletKey = Cypress.env('vegaWalletPublicKey2Short');
cy.getByTestId('vega-in-wallet')
.first()
.within(() => {
cy.getByTestId('eth-wallet-associated-balances')
.last()
.within(() => {
cy.getByTestId('associated-key')
.invoke('text')
.as('associatedPubKey');
});
});
cy.get('@associatedPubKey').then((associatedPubKey) => {
if (associatedPubKey == secondWalletKey) {
cy.get('[data-testid="manage-vega-wallet"]:visible').click();
cy.get('[data-testid="select-keypair-button"]').eq(0).click();
stakingPageDisassociateAllTokens();
}
});
}
@@ -1,8 +1,12 @@
import { format } from 'date-fns';
import { closeDialog, navigateTo, navigation } from './common.functions';
import {
closeDialog,
navigateTo,
navigation,
waitForSpinner,
} from './common.functions';
import { ensureSpecifiedUnstakedTokensAreAssociated } from './staking.functions';
const newProposalButton = '[data-testid="new-proposal-link"]';
const proposalInformationTableRows = '[data-testid="key-value-table-row"]';
const proposalListItem = '[data-testid="proposals-list-item"]';
const newProposalTitle = '[data-testid="proposal-title"]';
@@ -46,6 +50,56 @@ export function enterRawProposalBody(timestamp: number) {
});
}
export function submitUniqueRawProposal(proposalFields: {
proposalBody?: string;
proposalTitle?: string;
proposalDescription?: string;
closingTimestamp?: number;
enactmentTimestamp?: number;
submit?: boolean;
}) {
goToMakeNewProposal(governanceProposalType.RAW);
let proposalBodyPath = 'src/fixtures/proposals/raw.json';
if (proposalFields.proposalBody) {
proposalBodyPath = proposalFields.proposalBody;
}
cy.readFile(proposalBodyPath).then((rawProposal) => {
if (proposalFields.proposalTitle) {
rawProposal.rationale.title = proposalFields.proposalTitle;
cy.wrap(proposalFields.proposalTitle).as('proposalTitle');
}
if (proposalFields.proposalDescription) {
rawProposal.rationale.description = proposalFields.proposalDescription;
}
if (proposalFields.closingTimestamp) {
rawProposal.terms.closingTimestamp = proposalFields.closingTimestamp;
} else if (
!proposalFields.closingTimestamp &&
!proposalFields.proposalBody
) {
const minTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(2);
rawProposal.terms.closingTimestamp = minTimeStamp;
}
if (proposalFields.enactmentTimestamp) {
rawProposal.terms.enactmentTimestamp = proposalFields.enactmentTimestamp;
}
const proposalPayload = JSON.stringify(rawProposal);
cy.get(rawProposalData).type(proposalPayload, {
parseSpecialCharSequences: false,
delay: 2,
});
if (proposalFields.submit !== false) {
cy.get(newProposalSubmitButton).should('be.visible').click();
cy.wrap(rawProposal).as('rawProposal');
waitForProposalSubmitted();
waitForProposalSync();
navigateTo(navigation.proposals);
}
});
}
export function enterUniqueFreeFormProposalBody(
timestamp: string,
proposalTitle: string
@@ -55,7 +109,11 @@ export function enterUniqueFreeFormProposalBody(
'this is a e2e freeform proposal description'
);
cy.get(proposalVoteDeadline).clear().click().type(timestamp);
cy.getByTestId('proposal-submit').should('be.visible').click();
cy.getByTestId('proposal-download-json').should('be.visible').click();
}
export function getProposalFromTitle(proposalTitle: string) {
return cy.contains(proposalTitle).parentsUntil(proposalListItem).last();
}
export function getSubmittedProposalFromProposalList(proposalTitle: string) {
@@ -120,15 +178,20 @@ export function waitForProposalSync() {
});
}
export function goToMakeNewProposal(proposalType: string) {
navigateTo(navigation.proposals);
cy.get(newProposalButton).should('be.visible').click();
export function goToMakeNewProposal(proposalType: governanceProposalType) {
cy.visit('/proposals/propose');
waitForSpinner();
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();
if (proposalType == governanceProposalType.RAW) {
cy.get('[href="/proposals/propose/raw"]').click();
} else {
cy.get('li').should('contain.text', proposalType).and('be.visible');
cy.get('li').contains(proposalType).click();
}
}
// 3001-VOTE-013 3001-VOTE-014
export function waitForProposalSubmitted() {
cy.contains('Awaiting network confirmation', epochTimeout).should(
'be.visible'
@@ -163,11 +226,29 @@ export function createFreeformProposal(proposalTitle: string) {
navigateTo(navigation.proposals);
}
export const governanceProposalType = {
NETWORK_PARAMETER: 'Network parameter',
NEW_MARKET: 'New market',
UPDATE_MARKET: 'Update market',
NEW_ASSET: 'New asset',
FREEFORM: 'Freeform',
RAW: 'raw proposal',
};
export function getDownloadedProposalJsonPath(proposalType: string) {
const downloadPath = './cypress/downloads/';
const filepath = downloadPath + proposalType + getFormattedTime() + '.json';
return filepath;
}
function getFormattedTime() {
const now = new Date();
const day = now.getDate().toString().padStart(2, '0');
const month = now.toLocaleString('en-US', { month: 'short' });
const year = now.getFullYear().toString();
const hours = now.getHours().toString().padStart(2, '0');
const minutes = now.getMinutes().toString().padStart(2, '0');
return `${day}-${month}-${year}-${hours}-${minutes}`;
}
export enum governanceProposalType {
NETWORK_PARAMETER = 'Network parameter',
NEW_MARKET = 'New market',
UPDATE_MARKET = 'Update market',
NEW_ASSET = 'New asset',
UPDATE_ASSET = 'Update asset',
FREEFORM = 'Freeform',
RAW = 'raw proposal',
}
+3
View File
@@ -8,6 +8,7 @@ import './wallet-eth.functions.ts';
import './wallet-teardown.functions.ts';
import './wallet-vega.functions.ts';
import './proposal.functions.ts';
import 'cypress-mochawesome-reporter/register';
import registerCypressGrep from '@cypress/grep';
import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
@@ -33,4 +34,6 @@ before(() => {
aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery());
});
// Self stake validators so they are displayed
cy.validatorsSelfDelegate();
});
@@ -85,6 +85,132 @@ export function createFreeFormProposalTxBody(): ProposalSubmissionBody {
};
}
export function createNewMarketProposalTxBody(): ProposalSubmissionBody {
const MIN_CLOSE_SEC = 5;
const MIN_ENACT_SEC = 7;
const closingDate = addSeconds(new Date(), MIN_CLOSE_SEC);
const enactmentDate = addSeconds(closingDate, MIN_ENACT_SEC);
const closingTimestamp = millisecondsToSeconds(closingDate.getTime());
const enactmentTimestamp = millisecondsToSeconds(enactmentDate.getTime());
return {
proposalSubmission: {
rationale: {
title: 'New Market Proposal E2E submission',
description: 'E2E new market proposal',
},
terms: {
newMarket: {
changes: {
decimalPlaces: '5',
positionDecimalPlaces: '5',
linearSlippageFactor: '0.001',
quadraticSlippageFactor: '0',
lpPriceRange: '10',
instrument: {
name: 'Token test market',
code: 'TEST.24h',
future: {
settlementAsset:
'73174a6fb1d5802ba0ac7bd7ab79e0a3a4837b262de0a4e80815a55442692bd0',
quoteName: 'fBTC',
dataSourceSpecForSettlementData: {
external: {
oracle: {
signers: [
{
pubKey: {
key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680',
},
},
],
filters: [
{
key: {
name: 'prices.ETH.value',
type: 'TYPE_INTEGER' as const,
numberDecimalPlaces: '0',
},
conditions: [
{
operator: 'OPERATOR_GREATER_THAN' as const,
value: '0',
},
],
},
],
},
},
},
dataSourceSpecForTradingTermination: {
external: {
oracle: {
signers: [
{
pubKey: {
key: '70d14a321e02e71992fd115563df765000ccc4775cbe71a0e2f9ff5a3b9dc680',
},
},
],
filters: [
{
key: {
name: 'trading.terminated.ETH5',
type: 'TYPE_BOOLEAN' as const,
},
conditions: [
{
operator: 'OPERATOR_EQUALS' as const,
value: 'true',
},
],
},
],
},
},
},
dataSourceSpecBinding: {
settlementDataProperty: 'prices.ETH.value',
tradingTerminationProperty: 'trading.terminated.ETH5',
},
},
},
metadata: ['sector:energy', 'sector:tech', 'source:docs.vega.xyz'],
priceMonitoringParameters: {
triggers: [
{
horizon: '43200',
probability: '0.9999999',
auctionExtension: '600',
},
],
},
liquidityMonitoringParameters: {
targetStakeParameters: {
timeWindow: '3600',
scalingFactor: 10,
},
triggeringRatio: '0.7',
auctionExtension: '1',
},
logNormal: {
tau: 0.0001140771161,
riskAversionParameter: 0.01,
params: {
mu: 0,
r: 0.016,
sigma: 0.5,
},
},
},
},
closingTimestamp,
enactmentTimestamp,
},
},
};
}
export function mockNetworkUpgradeProposal() {
cy.mockGQL((req) => {
aliasGQLQuery(req, 'Nodes', nodeData);
@@ -221,7 +221,7 @@ export function ensureSpecifiedUnstakedTokensAreAssociated(
}
export function closeStakingDialog() {
cy.getByTestId('dialog-title').should(
cy.getByTestId('dialog-title', txTimeout).should(
'contain.text',
'At the beginning of the next epoch'
);
@@ -236,8 +236,8 @@ export function validateWalletCurrency(
currencyTitle: string,
expectedAmount: string
) {
cy.get("[data-testid='currency-title']")
.contains(currencyTitle)
cy.get("[data-testid='currency-title']", txTimeout)
.contains(currencyTitle, txTimeout)
.parent()
.parent()
.within(() => {
@@ -5,7 +5,7 @@ const capsuleWalletConnectButton = '[data-testid="web3-connector-Unknown"]';
export function ethereumWalletConnect() {
cy.highlight('Connecting Eth Wallet');
cy.get(connectToEthButton).within(() => {
cy.get(connectToEthButton, { timeout: 60000 }).within(() => {
cy.contains('Connect Ethereum wallet to associate $VEGA')
.should('be.visible')
.click();
@@ -3,7 +3,6 @@ import {
StakingBridge,
Token,
TokenVesting,
TokenFaucetable,
CollateralBridge,
} from '@vegaprotocol/smart-contracts';
import { ethers, Wallet } from 'ethers';
@@ -20,7 +19,7 @@ const ethStakingBridgeContractAddress = Cypress.env(
);
const ethProviderUrl = Cypress.env('ethProviderUrl');
const getAccount = (number = 0) => `m/44'/60'/0'/0/${number}`;
const transactionTimeout = 100000;
const transactionTimeout = { timeout: 100000, log: false };
const Erc20BridgeAddress = '0x9708FF7510D4A7B9541e1699d15b53Ecb1AFDc54';
const provider = new ethers.providers.JsonRpcProvider({ url: ethProviderUrl });
@@ -41,13 +40,10 @@ export async function depositAsset(
decimalPlaces: number
) {
// Approve asset
const faucet = new TokenFaucetable(assetEthAddress, signer);
const faucet = new Token(assetEthAddress, signer);
cy.wrap(
faucet.approve(Erc20BridgeAddress, amount + '0'.repeat(decimalPlaces + 1)),
{
timeout: transactionTimeout,
log: false,
}
transactionTimeout
).then(() => {
const collateralBridge = new CollateralBridge(Erc20BridgeAddress, signer);
cy.wrap(
@@ -56,19 +52,18 @@ export async function depositAsset(
amount + '0'.repeat(decimalPlaces),
'0x' + vegaWalletPubKey
),
{ timeout: transactionTimeout, log: false }
transactionTimeout
);
});
}
export async function faucetAsset(assetEthAddress: string) {
const faucet = new TokenFaucetable(assetEthAddress, signer);
const faucet = new Token(assetEthAddress, signer);
await promiseWithTimeout(faucet.faucet(), 10 * 60 * 1000, 'faucet asset');
}
export async function vegaWalletTeardown() {
cy.get(associatedAmountInWallet)
.should('be.visible')
.invoke('text')
.then((associatedAmount) => {
cy.get('body').then(($body) => {
@@ -81,11 +76,13 @@ export async function vegaWalletTeardown() {
}
});
cy.get(vegaWalletContainer).within(() => {
cy.get(associatedAmountInWallet, {
timeout: transactionTimeout,
}).contains('0.00', {
timeout: transactionTimeout,
});
cy.get(associatedAmountInWallet, transactionTimeout).should(
'have.length',
1
);
cy.get(associatedAmountInWallet)
.first(transactionTimeout)
.should('have.text', '0.00');
});
});
}
@@ -109,7 +106,7 @@ async function vegaWalletTeardownStaking(stakingBridgeContract: StakingBridge) {
cy.highlight('Tearing down staking tokens from vega wallet if present');
cy.wrap(
stakingBridgeContract.stake_balance(ethWalletPubKey, vegaWalletPubKey),
{ timeout: transactionTimeout }
transactionTimeout
).then((stakeBalance) => {
if (Number(stakeBalance) != 0) {
cy.get(vegaWalletContainer).within(() => {
@@ -122,31 +119,25 @@ async function vegaWalletTeardownStaking(stakingBridgeContract: StakingBridge) {
String(stakeBalance),
vegaWalletPubKey
),
{ timeout: transactionTimeout }
transactionTimeout
);
cy.wrap(
vestingContract.stake_balance(ethWalletPubKey, vegaWalletPubKey),
{
timeout: transactionTimeout,
log: false,
}
transactionTimeout
).then((vestingAmount) => {
if (Number(vestingAmount) != 0) {
cy.contains('Associated', {
timeout: transactionTimeout,
})
cy.contains('Associated', transactionTimeout)
.parent()
.parent()
.within(() => {
cy.getByTestId('currency-value', {
timeout: transactionTimeout,
})
.should('have.length', 1)
cy.getByTestId('currency-value', transactionTimeout)
.first()
.invoke('text')
.as('displayedAmount');
cy.get('@displayedAmount', {
timeout: transactionTimeout,
}).should('not.eq', $associatedAmount);
cy.get('@displayedAmount', transactionTimeout).should(
'not.eq',
$associatedAmount
);
});
}
});
@@ -158,14 +149,14 @@ async function vegaWalletTeardownStaking(stakingBridgeContract: StakingBridge) {
async function vegaWalletTeardownVesting(vestingContract: TokenVesting) {
cy.highlight('Tearing down vesting tokens from vega wallet if present');
cy.wrap(vestingContract.stake_balance(ethWalletPubKey, vegaWalletPubKey), {
timeout: transactionTimeout,
log: false,
}).then((vestingAmount) => {
cy.wrap(
vestingContract.stake_balance(ethWalletPubKey, vegaWalletPubKey),
transactionTimeout
).then((vestingAmount) => {
if (Number(vestingAmount) != 0) {
cy.wrap(
vestingContract.remove_stake(String(vestingAmount), vegaWalletPubKey),
{ timeout: transactionTimeout }
transactionTimeout
);
}
});
+4 -2
View File
@@ -5,16 +5,18 @@ NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_FAIRGROUND=false
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","STAGNET1":"https://stagnet1.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","STAGNET1":"https://governance.stagnet1.vega.rocks","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
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-stagnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
#Test configuration variables
CYPRESS_FAIRGROUND=false
+1
View File
@@ -17,6 +17,7 @@ NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
#Test configuration variables
CYPRESS_FAIRGROUND=false
+3 -1
View File
@@ -6,8 +6,10 @@ NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https:/
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://dev.explorer.vega.xyz
NX_VEGA_EXPLORER_URL=#
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-devnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_REST_URL=https://api.n00.devnet1.vega.xyz/api/v2/
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
+3 -1
View File
@@ -3,12 +3,14 @@ NX_VEGA_ENV=MAINNET
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
NX_VEGA_URL=https://api.vega.community/graphql
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/3ba145ccc2884bcd91213d8dc989ca76
NX_ETHERSCAN_URL=https://etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz
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
NX_VEGA_REST_URL=https://api.vega.community/api/v2/
+3 -2
View File
@@ -1,10 +1,11 @@
# App configuration variables
NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql
NX_VEGA_ENV=STAGNET1
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","STAGNET1":"https://stagnet1.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","STAGNET1":"https://governance.stagnet1.vega.rocks","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_EXPLORER_URL=https://explorer.stagnet1.vega.rocks
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
+2
View File
@@ -12,3 +12,5 @@ NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-testnet-k8s.ops.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_REST_URL=https://api.n07.testnet.vega.xyz/api/v2/
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
@@ -7,5 +7,7 @@ NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https:/
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://dev.explorer.vega.xyz
NX_VEGA_EXPLORER_URL=https://explorer.validators-testnet.vega.rocks/
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_REST_URL=https://api-validators-testnet.vega.rocks/api/v2/
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40@o286262.ingest.sentry.io/5882996
+6
View File
@@ -0,0 +1,6 @@
function ReactMarkdown({ children }) {
// eslint-disable-next-line react/jsx-no-useless-fragment
return <>{children}</>;
}
export default ReactMarkdown;
+94 -29
View File
@@ -2,7 +2,6 @@ import './i18n';
import React, { useEffect } from 'react';
import * as Sentry from '@sentry/react';
import { Integrations } from '@sentry/tracing';
import { BrowserRouter as Router, useLocation } from 'react-router-dom';
import { AppLoader } from './app-loader';
import { NetworkInfo } from '@vegaprotocol/network-info';
@@ -17,6 +16,7 @@ import { AppStateProvider } from './contexts/app-state/app-state-provider';
import { ContractsProvider } from './contexts/contracts/contracts-provider';
import { AppRouter } from './routes';
import type { EthereumConfig } from '@vegaprotocol/web3';
import { WithdrawalApprovalDialogContainer } from '@vegaprotocol/web3';
import {
createConnectors,
useEthTransactionManager,
@@ -37,10 +37,14 @@ import {
useEnvironment,
NetworkLoader,
useInitializeEnv,
NodeGuard,
AppFailure,
NodeSwitcherDialog,
useNodeSwitcherStore,
} from '@vegaprotocol/environment';
import { ENV } from './config';
import type { InMemoryCacheConfig } from '@apollo/client';
import { WithdrawalDialog } from '@vegaprotocol/withdraws';
import { CreateWithdrawalDialog } from '@vegaprotocol/withdraws';
import { SplashLoader } from './components/splash-loader';
import { ToastsManager } from './toasts-manager';
import {
@@ -48,6 +52,8 @@ import {
TELEMETRY_ON,
} from './components/telemetry-dialog/telemetry-dialog';
import { useLocalStorage } from '@vegaprotocol/react-helpers';
import { useTranslation } from 'react-i18next';
import { isPartyNotFoundError } from './lib/party';
const cache: InMemoryCacheConfig = {
typePolicies: {
@@ -153,7 +159,8 @@ const Web3Container = ({
<InitializeHandlers />
<VegaWalletDialogs />
<TransactionModal />
<WithdrawalDialog />
<CreateWithdrawalDialog />
<WithdrawalApprovalDialogContainer />
<TelemetryDialog />
</>
</BalanceManager>
@@ -179,32 +186,82 @@ const ScrollToTop = () => {
return null;
};
const removeQueryParams = (url: string) => {
return url.split('?')[0];
};
const AppContainer = () => {
const { config, loading, error } = useEthereumConfig();
const { VEGA_ENV, GIT_COMMIT_HASH, GIT_BRANCH, ETHEREUM_PROVIDER_URL } =
useEnvironment();
const {
VEGA_ENV,
VEGA_URL,
GIT_COMMIT_HASH,
GIT_BRANCH,
ETHEREUM_PROVIDER_URL,
} = useEnvironment();
const [telemetryOn] = useLocalStorage(TELEMETRY_ON);
const { t } = useTranslation();
const [nodeSwitcherOpen, setNodeSwitcher] = useNodeSwitcherStore((store) => [
store.dialogOpen,
store.setDialogOpen,
]);
useEffect(() => {
if (ENV.dsn && telemetryOn) {
if (ENV.dsn && telemetryOn === 'true') {
Sentry.init({
dsn: ENV.dsn,
integrations: [new Integrations.BrowserTracing()],
tracesSampleRate: 0.1,
enabled: true,
environment: VEGA_ENV,
release: GIT_COMMIT_HASH,
beforeSend(event) {
if (event.request?.url?.includes('/claim?')) {
return {
...event,
request: {
...event.request,
url: event.request?.url.split('?')[0],
},
};
beforeSend(event, hint) {
const error = hint?.originalException;
const errorIsString = typeof error === 'string';
const errorIsObject = error instanceof Error;
const requestUrl = event.request?.url;
const transaction = event.transaction;
if (
(errorIsString && isPartyNotFoundError({ message: error })) ||
(errorIsObject && isPartyNotFoundError(error))
) {
// This error is caused by a pubkey making an API request before
// it has interacted with the chain. This isn't needed in Sentry.
return null;
}
return event;
const updatedRequest =
requestUrl && requestUrl.includes('/claim?')
? { ...event.request, url: removeQueryParams(requestUrl) }
: event.request;
const updatedTransaction =
transaction && transaction.includes('/claim?')
? removeQueryParams(transaction)
: transaction;
const updatedBreadcrumbs = event.breadcrumbs?.map((breadcrumb) => {
if (
breadcrumb.type === 'navigation' &&
breadcrumb.data?.to?.includes('/claim?')
) {
return {
...breadcrumb,
data: {
...breadcrumb.data,
to: removeQueryParams(breadcrumb.data.to),
},
};
}
return breadcrumb;
});
return {
...event,
request: updatedRequest,
transaction: updatedTransaction,
breadcrumbs: updatedBreadcrumbs ?? event.breadcrumbs,
};
},
});
Sentry.setTag('branch', GIT_BRANCH);
@@ -219,21 +276,29 @@ const AppContainer = () => {
<ScrollToTop />
<AppStateProvider>
<div className="grid min-h-full text-white">
<AsyncRenderer<EthereumConfig | null>
loading={loading}
data={config}
error={error}
render={(cnf) =>
cnf && (
<Web3Container
chainId={Number(cnf.chain_id)}
providerUrl={ETHEREUM_PROVIDER_URL}
/>
)
<NodeGuard
skeleton={<div>{t('Loading')}</div>}
failure={
<AppFailure title={t('NodeUnsuitable', { url: VEGA_URL })} />
}
/>
>
<AsyncRenderer<EthereumConfig | null>
loading={loading}
data={config}
error={error}
render={(cnf) =>
cnf && (
<Web3Container
chainId={Number(cnf.chain_id)}
providerUrl={ETHEREUM_PROVIDER_URL}
/>
)
}
/>
</NodeGuard>
</div>
</AppStateProvider>
<NodeSwitcherDialog open={nodeSwitcherOpen} setOpen={setNodeSwitcher} />
</Router>
);
};
@@ -1,23 +1,14 @@
import { Button } from '@vegaprotocol/ui-toolkit';
import { useTranslation } from 'react-i18next';
import {
AppStateActionType,
useAppState,
} from '../../contexts/app-state/app-state-context';
import { useWeb3ConnectStore } from '@vegaprotocol/web3';
export const EthConnectPrompt = () => {
const { t } = useTranslation();
const { appDispatch } = useAppState();
const { open } = useWeb3ConnectStore();
return (
<Button
variant="default"
onClick={() =>
appDispatch({
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
isOpen: true,
})
}
onClick={open}
fill={true}
data-testid="connect-to-eth-btn"
>
@@ -2,10 +2,7 @@ import { Button } from '@vegaprotocol/ui-toolkit';
import { useWeb3React } from '@web3-react/core';
import type { ReactElement } from 'react';
import { useTranslation } from 'react-i18next';
import {
AppStateActionType,
useAppState,
} from '../../contexts/app-state/app-state-context';
import { useWeb3ConnectStore } from '@vegaprotocol/web3';
export const EthWalletContainer = ({
children,
@@ -14,21 +11,12 @@ export const EthWalletContainer = ({
}) => {
const { account } = useWeb3React();
const { t } = useTranslation();
const { appDispatch } = useAppState();
const { open } = useWeb3ConnectStore();
if (!account) {
return (
<div className="w-full text-center">
<Button
onClick={() =>
appDispatch({
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
isOpen: true,
})
}
>
{t('connectEthWallet')}
</Button>
<Button onClick={open}>{t('connectEthWallet')}</Button>
</div>
);
}
@@ -27,7 +27,11 @@ import {
import { Loader } from '@vegaprotocol/ui-toolkit';
import colors from 'tailwindcss/colors';
import { useBalances } from '../../lib/balances/balances-store';
import { useEthereumConfig, useWeb3Disconnect } from '@vegaprotocol/web3';
import {
useEthereumConfig,
useWeb3ConnectStore,
useWeb3Disconnect,
} from '@vegaprotocol/web3';
import { getChainName } from '@vegaprotocol/web3';
const removeLeadingAddressSymbol = (key: string) => {
@@ -189,6 +193,7 @@ export const EthWallet = () => {
const pendingTxs = usePendingTransactions();
const disconnect = useWeb3Disconnect(connector);
const { config } = useEthereumConfig();
const { open } = useWeb3ConnectStore();
return (
<WalletCard>
@@ -233,12 +238,7 @@ export const EthWallet = () => {
) : (
<Button
fill={true}
onClick={() =>
appDispatch({
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
isOpen: true,
})
}
onClick={open}
data-testid="connect-to-eth-wallet-button"
>
{t('connectEthWalletToAssociate')}
@@ -0,0 +1 @@
export * from './multisig-incorrect-notice';
@@ -0,0 +1,52 @@
import { render, screen } from '@testing-library/react';
import { useEthereumConfig } from '@vegaprotocol/web3';
import { useEnvironment } from '@vegaprotocol/environment';
import { MultisigIncorrectNotice } from './multisig-incorrect-notice';
jest.mock('@vegaprotocol/web3', () => ({
useEthereumConfig: jest.fn(),
}));
jest.mock('@vegaprotocol/environment', () => ({
useEnvironment: jest.fn(),
}));
describe('MultisigIncorrectNotice', () => {
it('renders correctly when config is provided', () => {
(useEthereumConfig as jest.Mock).mockReturnValue({
config: {
multisig_control_contract: {
address: '0x1234',
},
},
});
(useEnvironment as unknown as jest.Mock).mockReturnValue({
ETHERSCAN_URL: 'https://etherscan.io',
});
render(<MultisigIncorrectNotice />);
expect(screen.getByTestId('multisig-contract-link')).toHaveAttribute(
'href',
'https://etherscan.io/address/0x1234'
);
expect(screen.getByTestId('multisig-contract-link')).toHaveAttribute(
'title',
'0x1234'
);
expect(
screen.getByTestId('multisig-validators-learn-more')
).toBeInTheDocument();
});
it('does not render when config is not provided', () => {
(useEthereumConfig as jest.Mock).mockReturnValue({
config: null,
});
const { container } = render(<MultisigIncorrectNotice />);
expect(container.firstChild).toBeNull();
});
});
@@ -0,0 +1,49 @@
import { useTranslation } from 'react-i18next';
import { Callout, Intent, Link } from '@vegaprotocol/ui-toolkit';
import { useEthereumConfig } from '@vegaprotocol/web3';
import { useEnvironment, DocsLinks } from '@vegaprotocol/environment';
import type { EthereumConfig } from '@vegaprotocol/web3';
export const MultisigIncorrectNotice = () => {
const { t } = useTranslation();
const { config } = useEthereumConfig();
const { ETHERSCAN_URL } = useEnvironment();
if (!config) {
return null;
}
const contract = config[
'multisig_control_contract' as keyof EthereumConfig
] as {
address: string;
};
return (
<div className="mb-10">
<Callout intent={Intent.Warning}>
<div>
<Link
title={contract.address}
href={`${ETHERSCAN_URL}/address/${contract.address}`}
target="_blank"
data-testid="multisig-contract-link"
>
{t('multisigContractLink')}
</Link>{' '}
{t('multisigContractIncorrect')}
</div>
<div className="mt-2">
<Link
href={DocsLinks?.VALIDATOR_SCORES_REWARDS}
target="_blank"
data-testid="multisig-validators-learn-more"
>
{t('learnMore')}
</Link>
</div>
</Callout>
</div>
);
};
@@ -0,0 +1,40 @@
import { t } from '@vegaprotocol/i18n';
import {
ExternalLink,
VegaIcon,
VegaIconNames,
} from '@vegaprotocol/ui-toolkit';
import Routes from '../../routes/routes';
export const RiskMessage = () => {
return (
<>
<div className="bg-vega-light-100 dark:bg-vega-dark-100 p-6 mb-6">
<ul className="list-[square] ml-4">
<li>
{t(
'You may encounter bugs, loss of functionality or loss of assets using the App.'
)}
</li>
<li>
{t(
'No party accepts any liability for any losses whatsoever related to its use.'
)}
</li>
</ul>
</div>
<p className="mb-8">
{t(
'By using the Vega Governance App, you acknowledge that you have read and understood the'
)}{' '}
<ExternalLink href={Routes.DISCLAIMER} className="underline">
<span className="flex items-center gap-1">
<span>{t('Vega Governance Disclaimer')}</span>
<VegaIcon name={VegaIconNames.OPEN_EXTERNAL} />
</span>
</ExternalLink>
.
</p>
</>
);
};
@@ -4,9 +4,11 @@ import {
useAppState,
} from '../../contexts/app-state/app-state-context';
import { Connectors } from '../../lib/vega-connectors';
import { RiskMessage } from './risk-message';
export const VegaWalletDialogs = () => {
const { appState, appDispatch } = useAppState();
return (
<>
<VegaConnectDialog
@@ -17,6 +19,7 @@ export const VegaWalletDialogs = () => {
isOpen: open,
})
}
riskMessage={<RiskMessage />}
/>
<VegaManageDialog
@@ -1,6 +1,6 @@
import { Link } from '@vegaprotocol/ui-toolkit';
import { useTranslation } from 'react-i18next';
import { ExternalLinks } from '@vegaprotocol/utils';
import { ExternalLinks } from '@vegaprotocol/environment';
export const DownloadWalletPrompt = () => {
const { t } = useTranslation();
@@ -26,6 +26,7 @@ import type {
WalletDelegationFieldsFragment,
} from './__generated__/Delegations';
import { DelegationsDocument } from './__generated__/Delegations';
import { isPartyNotFoundError } from '../../lib/party';
export const usePollForDelegations = () => {
const { token: vegaToken } = useContracts();
@@ -75,6 +76,7 @@ export const usePollForDelegations = () => {
})
.then((res) => {
if (!mounted) return;
const canonisedDelegations = removePaginationWrapper(
res.data.party?.delegationsConnection?.edges
);
@@ -203,6 +205,15 @@ export const usePollForDelegations = () => {
setDelegatedNodes(delegatedAmounts);
})
.catch((err: Error) => {
// if party isn't found, dont log to Sentry, just clear state as, user
// will not have any delagations or accounts
if (isPartyNotFoundError(err)) {
setDelegations([]);
setAccounts([]);
setDelegatedNodes([]);
setCurrentStakeAvailable(new BigNumber(0));
return;
}
Sentry.captureException(err);
// If query fails stop interval. Its almost certain that the query
// will just continue to fail
@@ -25,20 +25,26 @@ export function Web3Connector({
connectors,
chainId,
}: Web3ConnectorProps) {
const { appState, appDispatch } = useAppState();
const { open, close, isOpen } = useWeb3ConnectStore();
const setDialogOpen = useCallback(
(isOpen: boolean) => {
appDispatch({ type: AppStateActionType.SET_ETH_WALLET_OVERLAY, isOpen });
if (isOpen) {
open();
} else {
close();
}
},
[appDispatch]
[open, close]
);
const appChainId = Number(chainId);
return (
<>
<Web3Content appChainId={appChainId}>{children}</Web3Content>
<Web3ConnectDialog
connectors={connectors}
dialogOpen={appState.ethConnectOverlay}
dialogOpen={isOpen}
setDialogOpen={setDialogOpen}
desiredChainId={appChainId}
/>
+1
View File
@@ -62,6 +62,7 @@ export const ENV = {
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
delegationsPagination: windowOrDefault('NX_DELEGATIONS_PAGINATION'),
rest: windowOrDefault('NX_VEGA_REST_URL'),
flags: {
NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')),
MOCK: TRUTHY.includes(windowOrDefault('NX_MOCKED')),
@@ -34,9 +34,6 @@ export interface AppState {
/** Whether or not the manage VEGA wallet overlay is open */
vegaWalletManageOverlay: boolean;
/** Whether or not the connect to Ethereum wallet overlay is open */
ethConnectOverlay: boolean;
/** Whether or not the transaction modal is open */
transactionOverlay: boolean;
/**
@@ -57,7 +54,6 @@ export enum AppStateActionType {
REFRESH_BALANCES,
SET_VEGA_WALLET_OVERLAY,
SET_VEGA_WALLET_MANAGE_OVERLAY,
SET_ETH_WALLET_OVERLAY,
SET_DRAWER,
REFRESH_ASSOCIATED_BALANCES,
SET_ASSOCIATION_BREAKDOWN,
@@ -81,10 +77,6 @@ export type AppStateAction =
type: AppStateActionType.SET_VEGA_WALLET_MANAGE_OVERLAY;
isOpen: boolean;
}
| {
type: AppStateActionType.SET_ETH_WALLET_OVERLAY;
isOpen: boolean;
}
| {
type: AppStateActionType.SET_DRAWER;
isOpen: boolean;
@@ -16,7 +16,6 @@ const initialAppState: AppState = {
totalSupply: new BigNumber(0),
vegaWalletOverlay: false,
vegaWalletManageOverlay: false,
ethConnectOverlay: false,
transactionOverlay: false,
bannerMessage: '',
disconnectNotice: false,
@@ -45,12 +44,6 @@ function appStateReducer(state: AppState, action: AppStateAction): AppState {
vegaWalletOverlay: action.isOpen ? false : state.vegaWalletOverlay,
};
}
case AppStateActionType.SET_ETH_WALLET_OVERLAY: {
return {
...state,
ethConnectOverlay: action.isOpen,
};
}
case AppStateActionType.SET_DRAWER: {
return {
...state,
@@ -3,32 +3,32 @@ import { usePendingBalancesStore } from './use-pending-balances-manager';
import type { Contract } from 'ethers';
import { useListenForPendingEthEvents } from './use-listen-for-pending-eth-events';
import { prepend0x } from '@vegaprotocol/smart-contracts';
import { useWeb3React } from '@web3-react/core';
export const useListenForStakingEvents = (
contract: Contract | undefined,
vegaPublicKey: string | null,
numberOfConfirmations: number
) => {
const { account } = useWeb3React();
const { addPendingTxs, removePendingTx, resetPendingTxs } =
usePendingBalancesStore((state) => ({
addPendingTxs: state.addPendingTxs,
removePendingTx: state.removePendingTx,
resetPendingTxs: state.resetPendingTxs,
}));
const addFilter = useMemo(
() =>
vegaPublicKey && contract
? contract.filters.Stake_Deposited(null, null, prepend0x(vegaPublicKey))
: null,
[contract, vegaPublicKey]
);
const removeFilter = useMemo(
() =>
vegaPublicKey && contract
? contract.filters.Stake_Removed(null, null, prepend0x(vegaPublicKey))
: null,
[contract, vegaPublicKey]
);
const addFilter = useMemo(() => {
if (!account || !vegaPublicKey || !contract) return null;
return contract.filters.Stake_Deposited(
null,
null,
prepend0x(vegaPublicKey)
);
}, [contract, vegaPublicKey, account]);
const removeFilter = useMemo(() => {
if (!account || !vegaPublicKey || !contract) return null;
return contract.filters.Stake_Removed(null, null, prepend0x(vegaPublicKey));
}, [contract, vegaPublicKey, account]);
/**
* Listen for all add stake events
+20 -7
View File
@@ -116,7 +116,7 @@
"Showing tranches with <{{trancheMinimum}} VEGA, click to hide these tranches": "Showing tranches with ≤{{trancheMinimum}} $VEGA, click to hide these tranches",
"Not showing tranches with <{{trancheMinimum}} VEGA, click to show all tranches": "Not showing tranches with ≤{{trancheMinimum}} $VEGA, click to show all tranches",
"the holder": "the holder",
"We couldn't seem to load your data.": "We couldn't seem to load your data.",
"Your data couldn't be loaded": "Your data couldn't be loaded",
"Vesting VEGA": "Vesting VEGA",
"All the tokens in this tranche are locked and can not be redeemed yet.": "All the tokens in this tranche are locked and can not be redeemed yet.",
"Redeem unlocked VEGA from tranche {{id}}": "Redeem unlocked $VEGA from tranche {{id}}",
@@ -202,6 +202,7 @@
"tokenVotes": "Token votes",
"liquidityVotes": "Liquidity votes",
"castYourVote": "Cast your vote",
"yourVote": "Your vote",
"for": "For",
"against": "Against",
"majorityRequired": "Majority Required",
@@ -593,7 +594,9 @@
"numberOfAgainstVotes": "Number of votes against",
"yesPercentage": "Yes percentage",
"noPercentage": "No percentage",
"proposalTerms": "Proposal terms",
"proposalJson": "Full proposal JSON",
"proposalDetails": "Proposal details",
"proposalDescription": "Description",
"currentlySetTo": "Currently expected to ",
"currently": "currently",
"finalOutcomeMayDiffer": "Final outcome may differ",
@@ -725,7 +728,7 @@
"ThisWillSetEnactmentDeadlineTo": "This will set the enactment date to",
"ThisWillSetValidationDeadlineTo": "This will set the validation deadline to",
"Hours": "hours",
"ThisWillAdd2MinutesToAllowTimeToConfirmInWallet": "Note: we add 2 minutes of extra time when you choose the minimum value. This gives you time to confirm the proposal in your wallet.",
"ThisWillAdd2MinutesToAllowTimeToConfirmInWallet": "Note: 2 minutes of extra time are added when you choose the minimum value. This gives you time to confirm the proposal in your wallet.",
"ProposalWillFailIfEnactmentIsEarlierThanVotingDeadline": "Proposal will fail if enactment is earlier than the voting deadline",
"SelectAMarketToChange": "Select a market to change",
"MarketName": "Market name",
@@ -787,9 +790,9 @@
"homeVegaTokenButtonText": "Manage tokens",
"downloadProposalJson": "Download proposal as JSON",
"networkUpgrade": "Network Upgrade",
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED": "Approved",
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_PENDING": "Pending",
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_REJECTED": "Rejected",
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED": "Approved by validators",
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_PENDING": "Waiting for validator votes",
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_REJECTED": "Declined by validators",
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_UNSPECIFIED": "Unspecified",
"vegaRelease{release}": "Vega Release {{release}}",
"upgradeBlockHeight": "Upgrade block height",
@@ -811,5 +814,15 @@
"OptOutOfTelemetry": "You can opt out any time via settings",
"NoThanks": "No thanks",
"ShareData": "Share data",
"ContinueSharingData": "Continue sharing data"
"ContinueSharingData": "Continue sharing data",
"NodeUnsuitable": "Node: {{url}} is unsuitable",
"Disclaimer": "Disclaimer",
"disclaimer1": "The Vega Governance App allows the Vega network to arrive at on-chain decisions, where tokenholders can create proposals that other tokenholders can vote to approve or reject. Vega supports on-chain proposals for creating markets and assets, and changing network parameters, markets and assets. Vega also supports freeform proposals for community suggestions that will not be enacted on-chain.",
"disclaimer2": "The Vega Governance App is free, public and open source software. Software upgrades may contain bugs or security vulnerabilities that might result in loss of functionality.",
"disclaimer3": "The Vega Governance App uses data obtained from nodes on the Vega Blockchain. The developers of the Vega Governance App do not operate or run the Vega Blockchain or any other blockchain.",
"disclaimer4": "The Vega Governance App is provided “as is”. The developers of the Vega Governance App make no representations or warranties of any kind, whether express or implied, statutory or otherwise regarding the Vega Governance App. They disclaim all warranties of merchantability, quality, fitness for purpose. They disclaim all warranties that the Vega Governance App is free of harmful components or errors.",
"disclaimer5": "No developer of the Vega Governance App accepts any responsibility for, or liability to users in connection with their use of the Vega Governance App.",
"multisigContractLink": "Ethereum Multisig Contract",
"multisigContractIncorrect": "is incorrectly configured. Validator and delegator rewards will be penalised until this is resolved.",
"learnMore": "Learn more"
}
@@ -0,0 +1,70 @@
import {
getMultisigStatusInfo,
MultisigStatus,
} from './get-multisig-status-info';
import type { PreviousEpochQuery } from '../routes/staking/__generated__/PreviousEpoch';
const createNode = (id: string, multisigScore: string) => ({
node: {
id,
stakedTotal: '1000',
rewardScore: { multisigScore },
},
});
describe('getMultisigStatus', () => {
it('should return MultisigStatus.noNodes when no nodes are present', () => {
const result = getMultisigStatusInfo({
epoch: { id: '1', validatorsConnection: { edges: [] } },
} as PreviousEpochQuery);
expect(result).toEqual({
multisigStatus: MultisigStatus.noNodes,
showMultisigStatusError: true,
});
});
it('should return MultisigStatus.correct when all nodes have multisigScore of 1', () => {
const result = getMultisigStatusInfo({
epoch: {
id: '1',
validatorsConnection: {
edges: [createNode('1', '1'), createNode('2', '1')],
},
},
} as PreviousEpochQuery);
expect(result).toEqual({
multisigStatus: MultisigStatus.correct,
showMultisigStatusError: false,
});
});
it('should return MultisigStatus.nodeNeedsRemoving when all nodes have multisigScore of 0', () => {
const result = getMultisigStatusInfo({
epoch: {
id: '1',
validatorsConnection: {
edges: [createNode('1', '0'), createNode('2', '0')],
},
},
} as PreviousEpochQuery);
expect(result).toEqual({
multisigStatus: MultisigStatus.nodeNeedsRemoving,
showMultisigStatusError: true,
});
});
it('should return MultisigStatus.nodeNeedsAdding when some nodes have multisigScore of 0 and others have 1', () => {
const result = getMultisigStatusInfo({
epoch: {
id: '1',
validatorsConnection: {
edges: [createNode('1', '0'), createNode('2', '1')],
},
},
} as PreviousEpochQuery);
expect(result).toEqual({
multisigStatus: MultisigStatus.nodeNeedsAdding,
showMultisigStatusError: true,
});
});
});
@@ -0,0 +1,42 @@
import { removePaginationWrapper } from '@vegaprotocol/utils';
import type { PreviousEpochQuery } from '../routes/staking/__generated__/PreviousEpoch';
export enum MultisigStatus {
'correct' = 'correct',
'nodeNeedsAdding' = 'nodeNeedsAdding',
'nodeNeedsRemoving' = 'nodeNeedsRemoving ',
'noNodes' = 'noNodes',
}
export const getMultisigStatusInfo = (
previousEpochData: PreviousEpochQuery
) => {
let status = MultisigStatus.noNodes;
const allNodesInPreviousEpoch = removePaginationWrapper(
previousEpochData?.epoch.validatorsConnection?.edges
);
const hasZero = allNodesInPreviousEpoch.some(
(node) => Number(node?.rewardScore?.multisigScore) === 0
);
const hasOne = allNodesInPreviousEpoch.some(
(node) => Number(node?.rewardScore?.multisigScore) === 1
);
if (hasZero && hasOne) {
// If any individual node has 0 it means that node is missing from the multisig and needs to be added
status = MultisigStatus.nodeNeedsAdding;
} else if (hasZero) {
// If all nodes have 0 it means there is an incorrect address in the multisig that needs to be removed
status = MultisigStatus.nodeNeedsRemoving;
} else if (allNodesInPreviousEpoch.length > 0) {
// If all nodes have 1 it means the multisig is correct
status = MultisigStatus.correct;
}
return {
showMultisigStatusError: status !== MultisigStatus.correct,
multisigStatus: status,
};
};
+8
View File
@@ -0,0 +1,8 @@
export const PARTY_NOT_FOUND = 'failed to get party for ID';
export const isPartyNotFoundError = (error: { message: string }) => {
if (error.message.includes(PARTY_NOT_FOUND)) {
return true;
}
return false;
};
@@ -50,7 +50,22 @@ export const useTranches = create<TranchesStore>()((set) => ({
?.map((t) => {
const tranche_progress =
t.duration !== 0 ? (now - t.cliff_start) / t.duration : 0;
const lockedDecimal = tranche_progress < 0 ? 1 : 1 - tranche_progress;
let lockedDecimal;
if (t.duration !== 0) {
if (tranche_progress < 0) {
lockedDecimal = 1;
} else {
lockedDecimal = 1 - tranche_progress;
}
} else {
if (now < t.cliff_start) {
lockedDecimal = 1;
} else {
lockedDecimal = 0;
}
}
const clampedLockedDecimal = Math.max(0, Math.min(1, lockedDecimal));
return {
tranche_id: t.tranche_id,
tranche_start: secondsToDate(t.cliff_start),
@@ -60,7 +75,7 @@ export const useTranches = create<TranchesStore>()((set) => ({
toBigNum(t.current_balance, decimals)
),
locked_amount: toBigNum(t.initial_balance, decimals).times(
lockedDecimal
clampedLockedDecimal
),
users: t.users,
};
@@ -0,0 +1,21 @@
import type { RouteChildProps } from '..';
import { useDocumentTitle } from '../../hooks/use-document-title';
import { Heading } from '../../components/heading';
import { useTranslation } from 'react-i18next';
const Disclaimer = ({ name }: RouteChildProps) => {
useDocumentTitle(name);
const { t } = useTranslation();
return (
<>
<Heading title={t('Disclaimer')} />
<p className="mb-6 mt-10">{t('disclaimer1')}</p>
<p className="mb-6">{t('disclaimer2')}</p>
<p className="mb-6">{t('disclaimer3')}</p>
<p className="mb-8">{t('disclaimer4')}</p>
<p className="mb-8">{t('disclaimer5')}</p>
</>
);
};
export default Disclaimer;
+20 -7
View File
@@ -12,7 +12,8 @@ import { useRefreshAfterEpoch } from '../../hooks/use-refresh-after-epoch';
import { ProposalsListItem } from '../proposals/components/proposals-list-item';
import { ProtocolUpgradeProposalsListItem } from '../proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item';
import Routes from '../routes';
import { ExternalLinks, removePaginationWrapper } from '@vegaprotocol/utils';
import { ExternalLinks } from '@vegaprotocol/environment';
import { removePaginationWrapper } from '@vegaprotocol/utils';
import { useNodesQuery } from '../staking/home/__generated__/Nodes';
import { useProposalsQuery } from '../proposals/proposals/__generated__/Proposals';
import {
@@ -26,6 +27,10 @@ import type { ProposalFieldsFragment } from '../proposals/proposals/__generated_
import type { NodesFragmentFragment } from '../staking/home/__generated__/Nodes';
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
import {
orderByDate,
orderByUpgradeBlockHeight,
} from '../proposals/components/proposals-list/proposals-list';
const nodesToShow = 6;
@@ -199,17 +204,20 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
const proposals = useMemo(
() =>
proposalsData
? getNotRejectedProposals<ProposalFieldsFragment>(
proposalsData.proposalsConnection
)
? getNotRejectedProposals(proposalsData.proposalsConnection)
: [],
[proposalsData]
);
const sortedProposals = useMemo(
() => orderByDate(proposals).reverse(),
[proposals]
);
const protocolUpgradeProposals = useMemo(
() =>
protocolUpgradesData
? getNotRejectedProtocolUpgradeProposals<ProtocolUpgradeProposalFieldsFragment>(
? getNotRejectedProtocolUpgradeProposals(
protocolUpgradesData.protocolUpgradeProposals
).filter(
(p) =>
@@ -220,15 +228,20 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
[protocolUpgradesData]
);
const sortedProtocolUpgradeProposals = useMemo(
() => orderByUpgradeBlockHeight(protocolUpgradeProposals),
[protocolUpgradeProposals]
);
const totalProposalsDesired = 4;
const protocolUpgradeProposalsToShow = protocolUpgradeProposals.slice(
const protocolUpgradeProposalsToShow = sortedProtocolUpgradeProposals.slice(
0,
totalProposalsDesired
);
const proposalsToShow =
protocolUpgradeProposalsToShow.length === totalProposalsDesired
? []
: proposals.slice(
: sortedProposals.slice(
0,
totalProposalsDesired - protocolUpgradeProposalsToShow.length
);

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