Compare commits

...
Author SHA1 Message Date
asiaznik 8a30cc6237 fix(ui-toolkit): test toast configuration 2023-05-22 16:55:03 +02: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
Sam Keen 2cb3b55a3b fix(governance): total supply displayed (#3666) 2023-05-09 15:33:07 +00:00
Sam Keen 3acc0e2401 fix(governance): consensus table works without previous epoch (#3663) 2023-05-09 15:14:04 +00:00
Dexter c734556eb4 ci: force build 2023-05-09 16:09:50 +01:00
Sam KeenandJoe 792ff1fc1f feat(governance): hide make proposal journey and link to docs instead (#3658)
Co-authored-by: Joe <joe@vega.xyz>
2023-05-09 14:43:39 +00:00
Sam KeenandJoe 3740a97d7e feat(governance): token references to governance (#3657)
Co-authored-by: Joe <joe@vega.xyz>
2023-05-09 14:17:40 +00:00
Dexter 20350ae2cf ci: force build 2023-05-09 15:13:53 +01:00
Dexter Edwards 50e93dad64 chore(explorer,trading,governance): new data node & explorer service urls (#3653) 2023-05-09 14:33:33 +01:00
Sam KeenandJoe c87c4bbc91 feat(governance): opt in/out telemetry (#3638)
Co-authored-by: Joe <joe@vega.xyz>
2023-05-09 13:32:16 +01:00
601 changed files with 18518 additions and 7745 deletions
@@ -0,0 +1,74 @@
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
Tye 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 [vega.trading](https://vega.trading).
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 }}/
+19 -18
View File
@@ -5,6 +5,8 @@ on:
branches: branches:
- release/* - release/*
- develop - develop
tags:
- v*
pull_request: pull_request:
types: types:
- opened - opened
@@ -96,38 +98,37 @@ jobs:
# See affected apps # See affected apps
- name: See affected apps - name: See affected apps
run: | 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 ">>>> debug"
echo "NX Version: $nx_version"
echo "NX_BASE: ${{ env.NX_BASE }}" echo "NX_BASE: ${{ env.NX_BASE }}"
echo "NX_HEAD: ${{ env.NX_HEAD }}" echo "NX_HEAD: ${{ env.NX_HEAD }}"
echo "Affected: ${affected}"
echo "Branch slug: ${branch_slug}"
echo ">>>> eof debug" 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="" projects_e2e=""
preview_governance="not deployed" preview_governance="not deployed"
preview_trading="not deployed" preview_trading="not deployed"
preview_explorer="not deployed" preview_explorer="not deployed"
if [[ $affected == *"governance"* ]]; then
projects_e2e+='"governance-e2e" '
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
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")
fi
if [[ -z "$projects_e2e" ]]; then if [[ -z "$projects_e2e" ]]; then
projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" ' projects_e2e+='"governance-e2e" "trading-e2e" "explorer-e2e" '
preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug") preview_governance=$(printf "https://%s.%s.vega.rocks" "governance" "$branch_slug")
preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug") preview_trading=$(printf "https://%s.%s.vega.rocks" "trading" "$branch_slug")
preview_explorer=$(printf "https://%s.%s.vega.rocks" "explorer" "$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
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")
fi
fi fi
projects_e2e=${projects_e2e%?} projects_e2e=${projects_e2e%?}
projects_e2e=[${projects_e2e// /,}] projects_e2e=[${projects_e2e// /,}]
-1
View File
@@ -33,5 +33,4 @@ jobs:
config: baseUrl=${{ github.event.inputs.url }} config: baseUrl=${{ github.event.inputs.url }}
env: grepTags=@live env: grepTags=@live
env: env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+3 -3
View File
@@ -20,7 +20,7 @@ jobs:
project: ${{ fromJSON(inputs.projects) }} project: ${{ fromJSON(inputs.projects) }}
name: ${{ matrix.project }} name: ${{ matrix.project }}
runs-on: self-hosted-runner runs-on: self-hosted-runner
timeout-minutes: 40 timeout-minutes: 60
steps: steps:
# Checks if skip cache was requested # Checks if skip cache was requested
- name: Set skip-nx-cache flag - name: Set skip-nx-cache flag
@@ -66,7 +66,7 @@ jobs:
###### ######
- name: Run Cypress tests - 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 working-directory: frontend-monorepo
env: env:
CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }} CYPRESS_SLACK_WEBHOOK: ${{ secrets.CYPRESS_SLACK_WEBHOOK }}
@@ -98,4 +98,4 @@ jobs:
if: ${{ failure() }} if: ${{ failure() }}
with: with:
name: test-report-${{ matrix.project }} name: test-report-${{ matrix.project }}
path: frontend-monorepo/apps/trading-e2e/cypress/reports path: frontend-monorepo/apps/${{ matrix.project }}/cypress/reports
+89 -38
View File
@@ -30,13 +30,21 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2 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 uses: docker/login-action@v2
with: with:
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }} 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 - name: Setup node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:
@@ -54,30 +62,26 @@ jobs:
- name: Define variables - name: Define variables
run: | run: |
envName='' envName=''
dockerfile="dist.Dockerfile" domain="vega.rocks"
if [[ "${{ github.event_name }}" = "push" ]]; then if [[ "${{ github.event_name }}" = "push" ]]; then
domain="vega.rocks"
if [[ "${{ github.ref }}" =~ .*release/.* ]]; then if [[ "${{ github.ref }}" =~ .*release/.* ]]; then
envName="$(echo ${{ github.ref }} | rev | cut -d '/' -f 1 | rev)" 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 elif [[ "${{ github.ref }}" =~ .*develop$ ]]; then
envName="stagnet1" envName="stagnet1"
elif [[ "${{ matrix.app}}" = "trading" ]] && [[ ${{ startsWith(github.ref, 'refs/tags/v') && 'true' || 'false' }} = "true" ]]; then
envName="mainnet"
elif [[ "${{ github.ref }}" =~ .*main$ ]]; then
envName="mainnet"
fi
if [[ "${envName}" = "mainnet" ]]; then
domain="vega.xyz"
fi fi
bucketName="${{ matrix.app }}.${envName}.${domain}" bucketName="${{ matrix.app }}.${envName}.${domain}"
echo BUCKET_NAME=${bucketName} >> $GITHUB_ENV echo BUCKET_NAME=${bucketName} >> $GITHUB_ENV
fi fi
nodeVersion=$(cat .nvmrc | head -n 1)
echo ENV_NAME=${envName} >> $GITHUB_ENV echo ENV_NAME=${envName} >> $GITHUB_ENV
echo NODE_VERSION=${nodeVersion} >> $GITHUB_ENV
echo DOCKERFILE=docker/${dockerfile} >> $GITHUB_ENV
- name: Build local dist - name: Build local dist
if: ${{ env.DOCKERFILE != 'docker/ipfs.Dockerfile' }}
run: | run: |
flags="" flags=""
if [[ ! -z "${{ env.ENV_NAME }}" ]]; then if [[ ! -z "${{ env.ENV_NAME }}" ]]; then
@@ -98,62 +102,60 @@ jobs:
- name: Build and export to local Docker - name: Build and export to local Docker
id: docker_build id: docker_build
if: ${{ github.event_name == 'pull_request' || ( env.DOCKERFILE == 'docker/ipfs.Dockerfile' && github.event_name == 'push' ) }}
uses: docker/build-push-action@v3 uses: docker/build-push-action@v3
with: with:
context: . context: .
file: ${{ env.DOCKERFILE }} file: docker/node-outside-docker.Dockerfile
load: true load: true
build-args: | build-args: |
APP=${{ matrix.app }} APP=${{ matrix.app }}
NODE_VERSION=${{ env.NODE_VERSION }}
ENV_NAME=${{ env.ENV_NAME }} ENV_NAME=${{ env.ENV_NAME }}
tags: | tags: |
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
- name: Image digest - 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 }} run: echo ${{ steps.docker_build.outputs.digest }}
- name: Sanity check docker image - name: Sanity check docker image
if: ${{ github.event_name == 'pull_request' || ( env.DOCKERFILE == 'docker/ipfs.Dockerfile' && github.event_name == 'push' ) }}
run: | run: |
echo "Check ipfs-hash" echo "Check ipfs-hash"
if [[ "${{ env.DOCKERFILE }}" = "docker/ipfs.Dockerfile" ]]; then 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 docker run --rm ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local cat /ipfs-hash > ${{ matrix.app }}-ipfs-hash
fi
echo "List html directory" 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 - name: Publish dist as docker image (ghcr)
if: ${{ env.DOCKERFILE == 'docker/ipfs.Dockerfile' && github.event_name == 'push' }}
run: |
docker create --name=dist ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:local
docker cp dist:/usr/share/nginx/html dist
echo "check local dist files"
tree dist/html
mv dist/html dist-result
- name: Publish dist as docker image
uses: docker/build-push-action@v3 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: with:
context: . context: .
file: ${{ env.DOCKERFILE }} file: docker/node-outside-docker.Dockerfile
push: true push: true
build-args: | build-args: |
APP=${{ matrix.app }} APP=${{ matrix.app }}
NODE_VERSION=${{ env.NODE_VERSION }}
ENV_NAME=${{ env.ENV_NAME }} ENV_NAME=${{ env.ENV_NAME }}
tags: | tags: |
ghcr.io/vegaprotocol/frontend/${{ matrix.app }}:${{ github.event.pull_request.head.sha || github.sha }} 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 # bucket creation in github.com/vegaprotocol/terraform//frontend
- name: Publish dist to s3 - name: Publish dist to s3
uses: jakejarvis/s3-sync-action@master uses: jakejarvis/s3-sync-action@master
if: ${{ github.event_name == 'push' }} if: ${{ github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/v') }}
with: with:
args: --acl private --follow-symlinks --delete args: --acl private --follow-symlinks --delete
env: env:
@@ -169,3 +171,52 @@ jobs:
with: with:
labels: ${{ matrix.app }}-preview labels: ${{ matrix.app }}-preview
number: ${{ github.event.number }} 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: Update vega.trading DNS to redirect to the new console
if: ${{ matrix.app == 'trading' && github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') }}
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)
# 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=vega.trading
dnsimple_record_id=44409591
# see: https://dnsimple.com/a/84895/domains/vega.trading/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}
+77
View File
@@ -0,0 +1,77 @@
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: Update vega.trading DNS to redirect to the new console
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)
# 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=vega.trading
dnsimple_record_id=44409591
# see: https://dnsimple.com/a/84895/domains/vega.trading/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}
+2 -1
View File
@@ -2,6 +2,7 @@
# compiled output # compiled output
/dist /dist
/dist-result
/tmp /tmp
/out-tsc /out-tsc
/tools/executors/**/*.js /tools/executors/**/*.js
@@ -48,4 +49,4 @@ cypress.env.json
.next .next
#cypress #cypress
/apps/trading-e2e/cypress/reports/ /apps/**/cypress/reports/
+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. 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. In order to run a container on port 3000:
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:
```bash ```bash
docker run -p 3000:80 [TAG] 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 ## Config
+1 -1
View File
@@ -2,7 +2,7 @@
NX_CHAIN_EXPLORER_URL=https://explorer.vega.trading/.netlify/functions/chain-explorer-api 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_URL=https://mainnet-observer-proxy01.ops.vega.xyz/
NX_TENDERMINT_WEBSOCKET_URL=wss://mainnet-observer-proxy01.ops.vega.xyz/websocket NX_TENDERMINT_WEBSOCKET_URL=wss://mainnet-observer-proxy01.ops.vega.xyz/websocket
NX_VEGA_URL=https://api.vega.xyz/query NX_VEGA_URL=https://api.vega.community/graphql
NX_VEGA_ENV=MAINNET NX_VEGA_ENV=MAINNET
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest
+2 -1
View File
@@ -1,10 +1,11 @@
const { defineConfig } = require('cypress'); const { defineConfig } = require('cypress');
module.exports = defineConfig({ module.exports = defineConfig({
projectId: 'et4snf', reporter: '../../node_modules/cypress-mochawesome-reporter',
e2e: { e2e: {
setupNodeEvents(on, config) { setupNodeEvents(on, config) {
require('cypress-mochawesome-reporter/plugin')(on);
require('@cypress/grep/src/plugin')(config); require('@cypress/grep/src/plugin')(config);
return config; return config;
}, },
+1
View File
@@ -15,5 +15,6 @@
import '@vegaprotocol/cypress'; import '@vegaprotocol/cypress';
import './common.functions.js'; import './common.functions.js';
import 'cypress-mochawesome-reporter/register';
import registerCypressGrep from '@cypress/grep'; import registerCypressGrep from '@cypress/grep';
registerCypressGrep(); registerCypressGrep();
+4 -2
View File
@@ -4,15 +4,17 @@ 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_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml
NX_VEGA_ENV=STAGNET1 NX_VEGA_ENV=STAGNET1
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
NX_VEGA_TOKEN_URL=https://stagnet1.token.vega.xyz NX_VEGA_TOKEN_URL=https://stagnet1.governance.vega.xyz
NX_VEGA_WALLET_URL=http://localhost:1789 NX_VEGA_WALLET_URL=http://localhost:1789
NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz NX_TENDERMINT_URL=https://tm.n01.stagnet1.vega.xyz
NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket NX_TENDERMINT_WEBSOCKET_URL=wss://tm.n01.stagnet1.vega.xyz/websocket
NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest NX_BLOCK_EXPLORER=https://be.stagnet1.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json NX_ORACLE_PROOFS_URL=https://raw.githubusercontent.com/vegaprotocol/well-known/main/__generated__/oracle-proofs.json
NX_VEGA_GOVERNANCE_URL=https://stagnet1.token.vega.xyz NX_VEGA_GOVERNANCE_URL=https://stagnet1.governance.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.jsoo NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.jsoo
NX_VEGA_NETWORKS='{"TESTNET":"https://explorer.fairground.wtf","MAINNET":"https://explorer.vega.xyz"}'
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
# App flags # App flags
NX_EXPLORER_ASSETS=1 NX_EXPLORER_ASSETS=1
+2 -2
View File
@@ -5,8 +5,8 @@ NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-inter
NX_VEGA_ENV=DEVNET NX_VEGA_ENV=DEVNET
NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest NX_BLOCK_EXPLORER=https://be.devnet1.vega.xyz/rest
NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://dev.token.vega.xyz NX_VEGA_GOVERNANCE_URL=https://dev.governance.vega.xyz
NX_VEGA_URL=https://api.devnet1.vega.xyz/graphql NX_VEGA_URL=https://api.devnet1.vega.xyz/graphql
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_EXPLORER_URL=/ NX_VEGA_EXPLORER_URL=/
+7 -5
View File
@@ -1,10 +1,12 @@
# App configuration variables # App configuration variables
NX_TENDERMINT_URL=https://be.explorer.vega.xyz NX_TENDERMINT_URL=https://be.vega.community
NX_TENDERMINT_WEBSOCKET_URL=wss://be.explorer.vega.xyz/websocket 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_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_VEGA_ENV=MAINNET
NX_BLOCK_EXPLORER=https://be.explorer.vega.xyz/rest/ NX_BLOCK_EXPLORER=https://be.vega.community/rest/
NX_ETHERSCAN_URL=https://etherscan.io NX_ETHERSCAN_URL=https://etherscan.io
NX_VEGA_GOVERNANCE_URL=https://token.vega.xyz NX_VEGA_GOVERNANCE_URL=https://governance.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/mainnet/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.vega.xyz/ NX_VEGA_EXPLORER_URL=https://explorer.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","STAGNET3":"https://stagnet3.explorer.vega.xyz"}'
+2 -2
View File
@@ -7,6 +7,6 @@ NX_VEGA_ENV=TESTNET
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_VEGA_GOVERNANCE_URL=https://token.fairground.wtf NX_VEGA_GOVERNANCE_URL=https://governance.fairground.wtf
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf NX_VEGA_EXPLORER_URL=https://explorer.fairground.wtf
@@ -8,7 +8,7 @@ NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_GOVERNANCE_URL=https://validator-testnet.governance.vega.xyz 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_BLOCK_EXPLORER=https://be.validators-testnet.vega.rocks/rest
NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket NX_TENDERMINT_WEBSOCKET_URL=wss://be.validators-testnet.vega.xyz/websocket
NX_VEGA_EXPLORER_URL=https://validator-testnet.explorer.vega.xyz/ NX_VEGA_EXPLORER_URL=https://explorer.validators-testnet.vega.rocks/
+24 -2
View File
@@ -1,9 +1,18 @@
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 { TendermintWebsocketProvider } from './contexts/websocket/tendermint-websocket-provider';
import { Loader, Splash } from '@vegaprotocol/ui-toolkit'; import { Loader, Splash } from '@vegaprotocol/ui-toolkit';
import { DEFAULT_CACHE_CONFIG } from '@vegaprotocol/apollo-client'; import { DEFAULT_CACHE_CONFIG } from '@vegaprotocol/apollo-client';
import { RouterProvider } from 'react-router-dom'; import { RouterProvider } from 'react-router-dom';
import { router } from './routes/router-config'; import { router } from './routes/router-config';
import { t } from '@vegaprotocol/i18n';
const splashLoading = ( const splashLoading = (
<Splash> <Splash>
@@ -12,10 +21,23 @@ const splashLoading = (
); );
function App() { function App() {
const { VEGA_URL } = useEnvironment();
const [nodeSwitcherOpen, setNodeSwitcherOpen] = useNodeSwitcherStore(
(store) => [store.dialogOpen, store.setDialogOpen]
);
return ( return (
<TendermintWebsocketProvider> <TendermintWebsocketProvider>
<NetworkLoader cache={DEFAULT_CACHE_CONFIG}> <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`)} />}
>
<RouterProvider router={router} fallbackElement={splashLoading} />
</NodeGuard>
<NodeSwitcherDialog
open={nodeSwitcherOpen}
setOpen={setNodeSwitcherOpen}
/>
</NetworkLoader> </NetworkLoader>
</TendermintWebsocketProvider> </TendermintWebsocketProvider>
); );
@@ -1,13 +1,19 @@
import { NodeSwitcherDialog, useEnvironment } from '@vegaprotocol/environment'; import {
useEnvironment,
useNodeSwitcherStore,
} from '@vegaprotocol/environment';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/i18n';
import { useScreenDimensions } from '@vegaprotocol/react-helpers'; import { useScreenDimensions } from '@vegaprotocol/react-helpers';
import { ExternalLink, Link } from '@vegaprotocol/ui-toolkit'; import { ExternalLink, Link } from '@vegaprotocol/ui-toolkit';
import { useMemo, useState } from 'react'; import { useMemo } from 'react';
import { ENV } from '../../config/env'; import { ENV } from '../../config/env';
export const Footer = () => { export const Footer = () => {
const { VEGA_URL, GIT_COMMIT_HASH, GIT_ORIGIN_URL } = useEnvironment(); 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 { screenSize } = useScreenDimensions();
const showFullFeedbackLabel = useMemo( const showFullFeedbackLabel = useMemo(
() => ['md', 'lg', 'xl', 'xxl', 'xxxl'].includes(screenSize), () => ['md', 'lg', 'xl', 'xxl', 'xxxl'].includes(screenSize),
@@ -15,46 +21,42 @@ export const Footer = () => {
); );
return ( 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">
<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">
<div className="flex justify-between gap-2 align-middle"> {GIT_COMMIT_HASH && (
{GIT_COMMIT_HASH && ( <div className="content-center flex border-r border-neutral-700 dark:border-neutral-300 pr-4">
<div className="content-center flex border-r border-neutral-700 dark:border-neutral-300 pr-4"> <p data-testid="git-commit-hash">
<p data-testid="git-commit-hash"> {t('Version')}:{' '}
{t('Version')}:{' '} <Link
<Link href={
href={ GIT_ORIGIN_URL
GIT_ORIGIN_URL ? `${GIT_ORIGIN_URL}/commit/${GIT_COMMIT_HASH}`
? `${GIT_ORIGIN_URL}/commit/${GIT_COMMIT_HASH}` : undefined
: undefined }
} target={GIT_ORIGIN_URL ? '_blank' : undefined}
target={GIT_ORIGIN_URL ? '_blank' : undefined} >
> {GIT_COMMIT_HASH}
{GIT_COMMIT_HASH} </Link>
</Link> </p>
</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> </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"> <div className="flex pl-2 content-center">
<ExternalLink href={ENV.addresses.feedback}> <ExternalLink href={ENV.addresses.feedback}>
{showFullFeedbackLabel ? t('Share your feedback') : t('Feedback')} {showFullFeedbackLabel ? t('Share your feedback') : t('Feedback')}
</ExternalLink> </ExternalLink>
</div> </div>
</div> ) : null}
</footer> </div>
<NodeSwitcherDialog </footer>
open={nodeSwitcherOpen}
setOpen={setNodeSwitcherOpen}
/>
</>
); );
}; };
@@ -62,9 +64,5 @@ const NodeUrl = ({ url }: { url: string }) => {
// get base url from api url, api sub domain // get base url from api url, api sub domain
const urlObj = new URL(url); const urlObj = new URL(url);
const nodeUrl = urlObj.origin.replace(/^[^.]+\./g, ''); const nodeUrl = urlObj.origin.replace(/^[^.]+\./g, '');
return ( return <span className="cursor-default">{nodeUrl}</span>;
<Link href={'https://' + nodeUrl} target="_blank">
{nodeUrl}
</Link>
);
}; };
@@ -3,6 +3,7 @@ import { Header } from './header';
import { MemoryRouter } from 'react-router-dom'; import { MemoryRouter } from 'react-router-dom';
jest.mock('@vegaprotocol/environment', () => ({ jest.mock('@vegaprotocol/environment', () => ({
...jest.requireActual('@vegaprotocol/environment'),
NetworkSwitcher: () => ( NetworkSwitcher: () => (
<div data-testid="network-switcher">NetworkSwitcher</div> <div data-testid="network-switcher">NetworkSwitcher</div>
), ),
@@ -1,8 +1,8 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/i18n';
import type { MarketInfoWithData } from '@vegaprotocol/market-info'; import type { MarketInfoWithData } from '@vegaprotocol/markets';
import { LiquidityInfoPanel } from '@vegaprotocol/market-info';
import { LiquidityMonitoringParametersInfoPanel } from '@vegaprotocol/market-info';
import { import {
LiquidityInfoPanel,
LiquidityMonitoringParametersInfoPanel,
InstrumentInfoPanel, InstrumentInfoPanel,
KeyDetailsInfoPanel, KeyDetailsInfoPanel,
LiquidityPriceRangeInfoPanel, LiquidityPriceRangeInfoPanel,
@@ -12,20 +12,18 @@ import {
RiskModelInfoPanel, RiskModelInfoPanel,
RiskParametersInfoPanel, RiskParametersInfoPanel,
SettlementAssetInfoPanel, SettlementAssetInfoPanel,
} from '@vegaprotocol/market-info'; } from '@vegaprotocol/markets';
import { MarketInfoTable } from '@vegaprotocol/market-info'; import { MarketInfoTable } from '@vegaprotocol/markets';
import type { DataSourceDefinition } from '@vegaprotocol/types'; import type { DataSourceDefinition } from '@vegaprotocol/types';
import isEqual from 'lodash/isEqual'; import isEqual from 'lodash/isEqual';
export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => { export const MarketDetails = ({ market }: { market: MarketInfoWithData }) => {
if (!market) return null; if (!market) return null;
const settlementData = const settlementData = market.tradableInstrument.instrument.product
market.tradableInstrument.instrument.product.dataSourceSpecForSettlementData .dataSourceSpecForSettlementData.data as DataSourceDefinition;
.data; const terminationData = market.tradableInstrument.instrument.product
const terminationData = .dataSourceSpecForTradingTermination.data as DataSourceDefinition;
market.tradableInstrument.instrument.product
.dataSourceSpecForTradingTermination.data;
const getSigners = (data: DataSourceDefinition) => { const getSigners = (data: DataSourceDefinition) => {
if (data.sourceType.__typename === 'DataSourceDefinitionExternal') { if (data.sourceType.__typename === 'DataSourceDefinitionExternal') {
@@ -1,4 +1,4 @@
import type { MarketFieldsFragment } from '@vegaprotocol/market-list'; import type { MarketFieldsFragment } from '@vegaprotocol/markets';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/i18n';
import { ButtonLink } from '@vegaprotocol/ui-toolkit'; import { ButtonLink } from '@vegaprotocol/ui-toolkit';
import type { AgGridReact } from 'ag-grid-react'; import type { AgGridReact } from 'ag-grid-react';
@@ -1,3 +1,5 @@
import { Icon } from '@vegaprotocol/ui-toolkit';
// https://github.com/vegaprotocol/vega/blob/develop/core/blockchain/response.go // https://github.com/vegaprotocol/vega/blob/develop/core/blockchain/response.go
export const ErrorCodes = new Map([ export const ErrorCodes = new Map([
[51, 'Transaction failed validation'], [51, 'Transaction failed validation'],
@@ -28,7 +30,11 @@ export const ChainResponseCode = ({
}: ChainResponseCodeProps) => { }: ChainResponseCodeProps) => {
const isSuccess = successCodes.has(code); const isSuccess = successCodes.has(code);
const icon = isSuccess ? '✅' : '❌'; const icon = isSuccess ? (
<Icon name="tick-circle" className="fill-vega-green-550" />
) : (
<Icon name="cross" className="fill-vega-pink-550" />
);
const label = ErrorCodes.get(code) || 'Unknown response code'; const label = ErrorCodes.get(code) || 'Unknown response code';
// Hack for batches with many errors - see https://github.com/vegaprotocol/vega/issues/7245 // Hack for batches with many errors - see https://github.com/vegaprotocol/vega/issues/7245
@@ -36,7 +42,7 @@ export const ChainResponseCode = ({
error && error.length > 100 ? error.replace(/,/g, ',\r\n') : error; error && error.length > 100 ? error.replace(/,/g, ',\r\n') : error;
return ( return (
<div title={`Response code: ${code} - ${label}`} className="inline-block"> <div title={`Response code: ${code} - ${label}`} className=" inline-block">
<span <span
className="mr-2" className="mr-2"
aria-label={isSuccess ? 'Success' : 'Warning'} aria-label={isSuccess ? 'Success' : 'Warning'}
@@ -4,6 +4,7 @@ import type { TendermintBlocksResponse } from '../../../routes/blocks/tendermint
import { TxDetailsShared } from './shared/tx-details-shared'; import { TxDetailsShared } from './shared/tx-details-shared';
import { TableCell, TableRow, TableWithTbody } from '../../table'; import { TableCell, TableRow, TableWithTbody } from '../../table';
import ProposalLink from '../../links/proposal-link/proposal-link'; import ProposalLink from '../../links/proposal-link/proposal-link';
import { VoteIcon } from '../../vote-icon/vote-icon';
interface TxProposalVoteProps { interface TxProposalVoteProps {
txData: BlockExplorerTransactionResult | undefined; txData: BlockExplorerTransactionResult | undefined;
@@ -30,27 +31,22 @@ export const TxProposalVote = ({
return <>{t('Awaiting Block Explorer transaction details')}</>; return <>{t('Awaiting Block Explorer transaction details')}</>;
} }
const vote = txData.command.voteSubmission.value ? '👍' : '👎'; const vote = txData.command.voteSubmission.value === 'VALUE_YES';
return ( return (
<TableWithTbody className="mb-8" allowWrap={true}> <TableWithTbody className="mb-8" allowWrap={true}>
<TxDetailsShared txData={txData} pubKey={pubKey} blockData={blockData} /> <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"> <TableRow modifier="bordered">
<TableCell>{t('Proposal details')}</TableCell> <TableCell>{t('Proposal details')}</TableCell>
<TableCell> <TableCell>
<ProposalLink id={txData.command.voteSubmission.proposalId} /> <ProposalLink id={txData.command.voteSubmission.proposalId} />
</TableCell> </TableCell>
</TableRow> </TableRow>
<TableRow modifier="bordered">
<TableCell>{t('Proposal')}</TableCell>
<TableCell>{txData.command.voteSubmission.proposalId}</TableCell>
</TableRow>
<TableRow modifier="bordered"> <TableRow modifier="bordered">
<TableCell>{t('Vote')}</TableCell> <TableCell>{t('Vote')}</TableCell>
<TableCell>{vote}</TableCell> <TableCell>
<VoteIcon vote={vote} />
</TableCell>
</TableRow> </TableRow>
</TableWithTbody> </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 * @returns boolean True if a signature bundle is required. Used to fetch a signature bundle
*/ */
export function proposalRequiresSignatureBundle(proposal?: Proposal): boolean { export function proposalRequiresSignatureBundle(proposal?: Proposal): boolean {
const proposalsThatRequireBundles = ['newAsset', 'updateAsset'];
if (!proposal?.terms) { if (!proposal?.terms) {
return false; 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; const tx = proposal.terms?.newAsset || proposal.terms?.updateAsset;
// This component is not rendered if no bundle is required
const SignatureBundleComponent = proposal.terms?.newAsset const SignatureBundleComponent = proposal.terms?.newAsset
? ProposalSignatureBundleNewAsset ? ProposalSignatureBundleNewAsset
: ProposalSignatureBundleUpdateAsset; : ProposalSignatureBundleUpdateAsset;
@@ -1,5 +1,6 @@
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/i18n';
import type { components } from '../../../types/explorer'; import type { components } from '../../../types/explorer';
import { VoteIcon } from '../vote-icon/vote-icon';
interface TxOrderTypeProps { interface TxOrderTypeProps {
orderType: string; orderType: string;
@@ -137,12 +138,15 @@ export const TxOrderType = ({ orderType, command }: TxOrderTypeProps) => {
let type = displayString[orderType] || orderType; let type = displayString[orderType] || orderType;
let colours = 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 // This will get unwieldy and should probably produce a different colour of tag
if (type === 'Chain Event' && !!command?.chainEvent) { if (type === 'Chain Event' && !!command?.chainEvent) {
type = getLabelForChainEvent(command.chainEvent); type = getLabelForChainEvent(command.chainEvent);
colours = 'text-white dark-text-white bg-vega-pink dark:bg-vega-pink'; 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') { } else if (type === 'Proposal' || type === 'Governance Proposal') {
if (command && !!command.proposalSubmission) { if (command && !!command.proposalSubmission) {
type = getLabelForProposal(command.proposalSubmission); type = getLabelForProposal(command.proposalSubmission);
@@ -150,6 +154,16 @@ export const TxOrderType = ({ orderType, command }: TxOrderTypeProps) => {
colours = 'text-black bg-vega-yellow'; 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"
/>
);
}
if (type === 'Vote on Proposal' || type === 'Vote Submission') { if (type === 'Vote on Proposal' || type === 'Vote Submission') {
colours = 'text-black bg-vega-yellow'; 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('pub-key')).toHaveTextContent('testPubKey');
expect(screen.getByTestId('tx-type')).toHaveTextContent('testType'); expect(screen.getByTestId('tx-type')).toHaveTextContent('testType');
expect(screen.getByTestId('tx-block')).toHaveTextContent('1'); 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 ( return (
<div <div
data-testid="transaction-row" 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 <div
className="text-sm col-span-10 md:col-span-3 leading-none" className="text-sm col-span-10 md:col-span-3 leading-none"
@@ -83,7 +83,7 @@ export const TxsInfiniteListItem = ({
data-testid="tx-success" data-testid="tx-success"
> >
<span className="md:hidden uppercase text-vega-dark-300"> <span className="md:hidden uppercase text-vega-dark-300">
Success:&nbsp; Success&nbsp;
</span> </span>
{isNumber(code) ? ( {isNumber(code) ? (
<ChainResponseCode code={code} hideLabel={true} /> <ChainResponseCode code={code} hideLabel={true} />
@@ -0,0 +1,37 @@
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');
});
});
@@ -0,0 +1,40 @@
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;
}
/**
* 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,
yesText = 'For',
noText = 'Against',
}: VoteIconProps) {
const label = vote ? yesText : noText;
const bg = vote ? 'bg-vega-green-550' : 'bg-vega-pink-550';
const icon: IconName = vote ? 'tick-circle' : 'delete';
const fill = vote ? 'vega-green-300' : 'vega-pink-300';
const text = vote ? 'vega-green-200' : 'vega-pink-200';
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 { useDocumentTitle } from '../../hooks/use-document-title';
import compact from 'lodash/compact'; import compact from 'lodash/compact';
import { JsonViewerDialog } from '../../components/dialogs/json-viewer-dialog'; 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'; import { PageTitle } from '../../components/page-helpers/page-title';
export const MarketPage = () => { export const MarketPage = () => {
@@ -1,6 +1,6 @@
import { useScrollToLocation } from '../../hooks/scroll-to-location'; import { useScrollToLocation } from '../../hooks/scroll-to-location';
import { useDocumentTitle } from '../../hooks/use-document-title'; 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 { RouteTitle } from '../../components/route-title';
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit'; import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { t } from '@vegaprotocol/i18n'; import { t } from '@vegaprotocol/i18n';
+7 -5
View File
@@ -32,9 +32,9 @@
line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px); line-height: calc(min(var(--ag-line-height, 26px), 26px) - 4px);
} }
.vega-ag-grid .ag-row { .vega-ag-grid .ag-row,
border-width: 1px 0; .vega-ag-grid .ag-cell {
border-bottom: 1px solid transparent; border-width: 0;
} }
/* Light variables */ /* Light variables */
@@ -46,7 +46,6 @@
--ag-header-column-separator-color: theme(colors.neutral[300]); --ag-header-column-separator-color: theme(colors.neutral[300]);
--ag-row-border-color: theme(colors.white); --ag-row-border-color: theme(colors.white);
--ag-row-hover-color: theme(colors.neutral[100]); --ag-row-hover-color: theme(colors.neutral[100]);
--ag-font-size: 12px;
} }
/* Dark variables */ /* Dark variables */
@@ -58,5 +57,8 @@
--ag-header-column-separator-color: theme(colors.neutral[600]); --ag-header-column-separator-color: theme(colors.neutral[600]);
--ag-row-border-color: theme(colors.black); --ag-row-border-color: theme(colors.black);
--ag-row-hover-color: theme(colors.neutral[800]); --ag-row-hover-color: theme(colors.neutral[800]);
--ag-font-size: 12px; }
.voteicon svg {
vertical-align: baseline;
} }
+2 -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_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72 NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
#Test configuration variables #Test configuration variables
CYPRESS_FAIRGROUND=false CYPRESS_FAIRGROUND=false
@@ -30,6 +31,6 @@ CYPRESS_TRUNCATED_VEGA_PUBLIC_KEY2=7f9cf0…c25535
CYPRESS_VEGA_ENV=CUSTOM CYPRESS_VEGA_ENV=CUSTOM
CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65 CYPRESS_VEGA_PUBLIC_KEY=02eceaba4df2bef76ea10caf728d8a099a2aa846cced25737cccaa9812342f65
CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535 CYPRESS_VEGA_PUBLIC_KEY2=7f9cf07d3a9905b1a61a1069f7a758855da428bc0f4a97de87f48644bfc25535
CYPRESS_VEGA_TOKEN_URL=https://token.fairground.wtf CYPRESS_VEGA_TOKEN_URL=https://governance.fairground.wtf
CYPRESS_VEGA_WALLET_URL=http://localhost:1789 CYPRESS_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_WALLET_API_TOKEN= CYPRESS_VEGA_WALLET_API_TOKEN=
+1 -1
View File
@@ -1,5 +1,5 @@
# App configuration variables # App configuration variables
NX_VEGA_ENV=MAINNET NX_VEGA_ENV=MAINNET
NX_VEGA_URL=https://api.vega.xyz/query NX_VEGA_URL=https://api.vega.community/graphql
NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8 NX_ETHEREUM_PROVIDER_URL=https://mainnet.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://etherscan.io NX_ETHERSCAN_URL=https://etherscan.io
+2 -1
View File
@@ -1,10 +1,11 @@
const { defineConfig } = require('cypress'); const { defineConfig } = require('cypress');
module.exports = defineConfig({ module.exports = defineConfig({
projectId: 'et4snf', reporter: '../../node_modules/cypress-mochawesome-reporter',
e2e: { e2e: {
setupNodeEvents(on, config) { setupNodeEvents(on, config) {
require('cypress-mochawesome-reporter/plugin')(on);
require('@cypress/grep/src/plugin')(config); require('@cypress/grep/src/plugin')(config);
return config; return config;
}, },
@@ -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
}
}
@@ -2,21 +2,17 @@ import {
navigateTo, navigateTo,
waitForSpinner, waitForSpinner,
navigation, navigation,
turnTelemetryOff,
} from '../../support/common.functions'; } from '../../support/common.functions';
import { import {
createRawProposal, createRawProposal,
createTenDigitUnixTimeStampForSpecifiedDays, createTenDigitUnixTimeStampForSpecifiedDays,
enterUniqueFreeFormProposalBody,
generateFreeFormProposalTitle, generateFreeFormProposalTitle,
getDateFormatForSpecifiedDays, getDateFormatForSpecifiedDays,
getProposalIdFromList, getProposalFromTitle,
getProposalInformationFromTable, getProposalInformationFromTable,
getSubmittedProposalFromProposalList, submitUniqueRawProposal,
goToMakeNewProposal,
governanceProposalType,
voteForProposal, voteForProposal,
waitForProposalSubmitted,
waitForProposalSync,
} from '../../../../governance-e2e/src/support/governance.functions'; } from '../../../../governance-e2e/src/support/governance.functions';
import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../../../governance-e2e/src/support/staking.functions'; import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../../../governance-e2e/src/support/staking.functions';
import { ethereumWalletConnect } from '../../../../governance-e2e/src/support/wallet-eth.functions'; import { ethereumWalletConnect } from '../../../../governance-e2e/src/support/wallet-eth.functions';
@@ -37,6 +33,8 @@ const proposalDetailsTitle = '[data-testid="proposal-title"]';
const proposalDetailsDescription = '[data-testid="proposal-description"]'; const proposalDetailsDescription = '[data-testid="proposal-description"]';
const openProposals = '[data-testid="open-proposals"]'; const openProposals = '[data-testid="open-proposals"]';
const viewProposalButton = '[data-testid="view-proposal-btn"]'; const viewProposalButton = '[data-testid="view-proposal-btn"]';
const voteBreakdownToggle = 'vote-breakdown-toggle';
const proposalTermsToggle = 'proposal-terms-toggle';
describe( describe(
'Governance flow for proposal details', 'Governance flow for proposal details',
@@ -50,6 +48,7 @@ describe(
beforeEach('visit proposals tab', function () { beforeEach('visit proposals tab', function () {
cy.clearLocalStorage(); cy.clearLocalStorage();
turnTelemetryOff();
cy.reload(); cy.reload();
waitForSpinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
@@ -60,23 +59,25 @@ describe(
// 3001-VOTE-050 3001-VOTE-054 3001-VOTE-055 3002-PROP-019 // 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 () { 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(); createRawProposal();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getProposalIdFromList(rawProposal.rationale.title); cy.get(openProposals).within(() => {
cy.get('@proposalIdText').then((proposalId) => { getProposalFromTitle(rawProposal.rationale.title).within(() => {
cy.get(openProposals).within(() => { cy.get(viewProposalButton).should('be.visible').click();
cy.get(`#${proposalId}`).within(() => {
cy.get(viewProposalButton).should('be.visible').click();
});
}); });
}); });
cy.get(proposalDetailsTitle) cy.get(proposalDetailsTitle).should(
.should('contain', rawProposal.rationale.title) 'contain.text',
.and('be.visible'); rawProposal.rationale.title
);
cy.get(proposalDetailsDescription) cy.get(proposalDetailsDescription)
.should('contain', rawProposal.rationale.description) .find('p')
.and('be.visible'); .should('have.text', proposalDescription);
}); });
cy.getByTestId(proposalTermsToggle).click();
// 3001-VOTE-052 // 3001-VOTE-052
cy.get('code.language-json') cy.get('code.language-json')
.should('exist') .should('exist')
@@ -87,33 +88,36 @@ describe(
// 3001-VOTE-043 // 3001-VOTE-043
it('Newly created freeform proposal details - shows proposed and closing dates', function () { it('Newly created freeform proposal details - shows proposed and closing dates', function () {
const closingVoteHrs = '72';
const proposalTitle = generateFreeFormProposalTitle(); const proposalTitle = generateFreeFormProposalTitle();
const proposalTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(3); const proposalTimeStamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
// const currentDate = new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000)
// const proposedDate = new Date(currentDate.getTime() + 60000)
goToMakeNewProposal(governanceProposalType.FREEFORM); submitUniqueRawProposal({
enterUniqueFreeFormProposalBody(closingVoteHrs, proposalTitle); proposalTitle: proposalTitle,
waitForProposalSubmitted(); closingTimestamp: proposalTimeStamp,
waitForProposalSync(); });
navigateTo(navigation.proposals); navigateTo(navigation.proposals);
getSubmittedProposalFromProposalList(proposalTitle).within(() => getProposalFromTitle(proposalTitle).within(() =>
cy.get(viewProposalButton).click() cy.get(viewProposalButton).click()
); );
cy.wrap( cy.wrap(
formatDateWithLocalTimezone(new Date(proposalTimeStamp * 1000)) formatDateWithLocalTimezone(new Date(proposalTimeStamp * 1000))
).then((closingDate) => { ).then((closingDate) => {
getProposalInformationFromTable('Closes on') getProposalInformationFromTable('Closes on').should(
.contains(closingDate) 'have.text',
.should('be.visible'); closingDate
);
}); });
cy.wrap( cy.wrap(
formatDateWithLocalTimezone( formatDateWithLocalTimezone(
new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000) new Date(createTenDigitUnixTimeStampForSpecifiedDays(0) * 1000)
) )
).then((proposalDate) => { ).then((proposalDate) => {
getProposalInformationFromTable('Proposed on') getProposalInformationFromTable('Proposed on').should(
.contains(proposalDate) 'have.text',
.should('be.visible'); proposalDate
);
}); });
}); });
@@ -123,13 +127,14 @@ describe(
// 3001-VOTE-067 // 3001-VOTE-067
createRawProposal(); createRawProposal();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList( getProposalFromTitle(rawProposal.rationale.title).within(() =>
rawProposal.rationale.title cy.get(viewProposalButton).click()
).within(() => cy.get(viewProposalButton).click()); );
}); });
cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should( cy.contains('Participation: Not Met 0.00 0.00%(0.00% Required)').should(
'be.visible' 'be.visible'
); );
cy.getByTestId(voteBreakdownToggle).click();
getProposalInformationFromTable('Expected to pass') getProposalInformationFromTable('Expected to pass')
.contains('👎') .contains('👎')
.should('be.visible'); .should('be.visible');
@@ -149,9 +154,9 @@ describe(
it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () { it('Newly created proposal details - ability to vote for and against proposal - with minimum required tokens associated', function () {
createRawProposal(); createRawProposal();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList( getProposalFromTitle(rawProposal.rationale.title).within(() =>
rawProposal.rationale.title cy.get(viewProposalButton).click()
).within(() => cy.get(viewProposalButton).click()); );
}); });
// 3001-VOTE-080 // 3001-VOTE-080
cy.getByTestId('vote-buttons').contains('against').should('be.visible'); cy.getByTestId('vote-buttons').contains('against').should('be.visible');
@@ -177,6 +182,7 @@ describe(
cy.get(proposalVoteProgressAgainstTokens) cy.get(proposalVoteProgressAgainstTokens)
.contains('0.00') .contains('0.00')
.and('be.visible'); .and('be.visible');
cy.getByTestId(voteBreakdownToggle).click();
getProposalInformationFromTable('Tokens for proposal') getProposalInformationFromTable('Tokens for proposal')
.should('have.text', (1).toFixed(2)) .should('have.text', (1).toFixed(2))
.and('be.visible'); .and('be.visible');
@@ -218,14 +224,15 @@ describe(
vegaWalletSetSpecifiedApprovalAmount('1000'); vegaWalletSetSpecifiedApprovalAmount('1000');
createRawProposal(); createRawProposal();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList( getProposalFromTitle(rawProposal.rationale.title).within(() =>
rawProposal.rationale.title cy.get(viewProposalButton).click()
).within(() => cy.get(viewProposalButton).click()); );
}); });
voteForProposal('for'); voteForProposal('for');
// 3001-VOTE-079 // 3001-VOTE-079
cy.contains('You voted: For').should('be.visible'); cy.contains('You voted: For').should('be.visible');
cy.get(proposalVoteProgressForTokens).contains('1').and('be.visible'); cy.get(proposalVoteProgressForTokens).contains('1').and('be.visible');
cy.getByTestId(voteBreakdownToggle).click();
getProposalInformationFromTable('Total Supply') getProposalInformationFromTable('Total Supply')
.invoke('text') .invoke('text')
.then((totalSupply) => { .then((totalSupply) => {
@@ -233,14 +240,15 @@ describe(
(Number(totalSupply.replace(/,/g, '')) * 0.001) / (Number(totalSupply.replace(/,/g, '')) * 0.001) /
100 100
).toFixed(2); ).toFixed(2);
ethereumWalletConnect();
ensureSpecifiedUnstakedTokensAreAssociated( ensureSpecifiedUnstakedTokensAreAssociated(
tokensRequiredToAchieveResult tokensRequiredToAchieveResult
); );
navigateTo(navigation.proposals); navigateTo(navigation.proposals);
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList( getProposalFromTitle(rawProposal.rationale.title).within(() =>
rawProposal.rationale.title cy.get(viewProposalButton).click()
).within(() => cy.get(viewProposalButton).click()); );
}); });
cy.get(proposalVoteProgressForPercentage) cy.get(proposalVoteProgressForPercentage)
.contains('100.00%') .contains('100.00%')
@@ -257,6 +265,7 @@ describe(
cy.get(proposalVoteProgressAgainstTokens) cy.get(proposalVoteProgressAgainstTokens)
.contains('0.00') .contains('0.00')
.and('be.visible'); .and('be.visible');
cy.getByTestId(voteBreakdownToggle).click();
getProposalInformationFromTable('Total tokens voted percentage') getProposalInformationFromTable('Total tokens voted percentage')
.should('have.text', '0.00%') .should('have.text', '0.00%')
.and('be.visible'); .and('be.visible');
@@ -2,6 +2,7 @@
import { import {
navigateTo, navigateTo,
navigation, navigation,
turnTelemetryOff,
waitForSpinner, waitForSpinner,
} from '../../support/common.functions'; } from '../../support/common.functions';
import { import {
@@ -37,6 +38,7 @@ context(
beforeEach('visit proposals', function () { beforeEach('visit proposals', function () {
cy.clearLocalStorage(); cy.clearLocalStorage();
turnTelemetryOff();
cy.reload(); cy.reload();
waitForSpinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
@@ -56,14 +58,12 @@ context(
.parentsUntil(proposalListItem) .parentsUntil(proposalListItem)
.last() .last()
.within(() => { .within(() => {
cy.get(proposalStatus).should('have.text', 'Enacted '); cy.get(proposalStatus).should('have.text', 'Enacted');
cy.get(viewProposalButton).click(); cy.get(viewProposalButton).click();
}); });
}); });
cy.getByTestId('proposal-type').should('have.text', 'New market'); cy.getByTestId('proposal-type').should('have.text', 'New market');
getProposalInformationFromTable('State') cy.get(proposalStatus).should('have.text', 'Enacted');
.contains('Enacted')
.and('be.visible');
cy.get(votesTable).within(() => { cy.get(votesTable).within(() => {
cy.contains('Vote passed.').should('be.visible'); cy.contains('Vote passed.').should('be.visible');
cy.contains('Voting has ended.').should('be.visible'); cy.contains('Voting has ended.').should('be.visible');
@@ -85,16 +85,10 @@ context(
.last() .last()
.within(() => cy.get(viewProposalButton).click()); .within(() => cy.get(viewProposalButton).click());
}); });
getProposalInformationFromTable('State') cy.get(proposalStatus).should('have.text', 'Open');
.contains('Open')
.and('be.visible');
voteForProposal('for'); voteForProposal('for');
getProposalInformationFromTable('State') // 3001-VOTE-047 cy.get(proposalStatus, proposalTimeout).should('have.text', 'Passed');
.contains('Passed', proposalTimeout) cy.get(proposalStatus, proposalTimeout).should('have.text', 'Enacted');
.and('be.visible');
getProposalInformationFromTable('State')
.contains('Enacted', proposalTimeout)
.and('be.visible');
cy.get(votesTable).within(() => { cy.get(votesTable).within(() => {
cy.contains('Vote passed.').should('be.visible'); cy.contains('Vote passed.').should('be.visible');
cy.contains('Voting has ended.').should('be.visible'); cy.contains('Voting has ended.').should('be.visible');
@@ -119,13 +113,9 @@ context(
.last() .last()
.within(() => cy.get(viewProposalButton).click()); .within(() => cy.get(viewProposalButton).click());
}); });
getProposalInformationFromTable('State') cy.get(proposalStatus).should('have.text', 'Open');
.contains('Open')
.and('be.visible');
voteForProposal('for'); voteForProposal('for');
getProposalInformationFromTable('State') cy.get(proposalStatus, proposalTimeout).should('have.text', 'Enacted');
.contains('Enacted', proposalTimeout)
.and('be.visible');
}); });
// 3001-VOTE-048 3001-VOTE-049 3001-VOTE-050 // 3001-VOTE-048 3001-VOTE-049 3001-VOTE-050
@@ -142,12 +132,8 @@ context(
.last() .last()
.within(() => cy.get(viewProposalButton).click()); .within(() => cy.get(viewProposalButton).click());
}); });
getProposalInformationFromTable('State') cy.get(proposalStatus).should('have.text', 'Open');
.contains('Open') cy.get(proposalStatus, proposalTimeout).should('have.text', 'Declined');
.and('be.visible');
getProposalInformationFromTable('State') // 3001-VOTE-047
.contains('Declined', proposalTimeout)
.and('be.visible');
getProposalInformationFromTable('Rejection reason') getProposalInformationFromTable('Rejection reason')
.contains('PROPOSAL_ERROR_PARTICIPATION_THRESHOLD_NOT_REACHED') .contains('PROPOSAL_ERROR_PARTICIPATION_THRESHOLD_NOT_REACHED')
.and('be.visible'); .and('be.visible');
@@ -5,10 +5,11 @@ import {
enterRawProposalBody, enterRawProposalBody,
enterUniqueFreeFormProposalBody, enterUniqueFreeFormProposalBody,
generateFreeFormProposalTitle, generateFreeFormProposalTitle,
getProposalFromTitle,
getProposalInformationFromTable, getProposalInformationFromTable,
getSubmittedProposalFromProposalList,
goToMakeNewProposal, goToMakeNewProposal,
governanceProposalType, governanceProposalType,
submitUniqueRawProposal,
voteForProposal, voteForProposal,
waitForProposalSubmitted, waitForProposalSubmitted,
waitForProposalSync, waitForProposalSync,
@@ -20,6 +21,7 @@ import {
navigateTo, navigateTo,
navigation, navigation,
closeDialog, closeDialog,
turnTelemetryOff,
} from '../../support/common.functions'; } from '../../support/common.functions';
import { import {
clickOnValidatorFromList, clickOnValidatorFromList,
@@ -80,11 +82,11 @@ context(
}); });
vegaWalletSetSpecifiedApprovalAmount('1000'); vegaWalletSetSpecifiedApprovalAmount('1000');
cy.associateTokensToVegaWallet('1');
}); });
beforeEach('visit governance tab', function () { beforeEach('visit governance tab', function () {
cy.clearLocalStorage(); cy.clearLocalStorage();
turnTelemetryOff();
cy.reload(); cy.reload();
waitForSpinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
@@ -93,7 +95,8 @@ context(
navigateTo(navigation.proposals); 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 // 3001-VOTE-003
cy.get(noOpenProposals) cy.get(noOpenProposals)
.should('be.visible') .should('be.visible')
@@ -105,7 +108,7 @@ context(
// 3002-PROP-002 // 3002-PROP-002
// 3002-PROP-003 // 3002-PROP-003
it('Submit a proposal form - shows how many vega tokens are required to make a proposal', function () { it('Proposal form - shows how many vega tokens are required to make a proposal', function () {
// 3002-PROP-005 // 3002-PROP-005
goToMakeNewProposal(governanceProposalType.NEW_MARKET); goToMakeNewProposal(governanceProposalType.NEW_MARKET);
cy.contains( cy.contains(
@@ -113,8 +116,9 @@ context(
).should('be.visible'); ).should('be.visible');
}); });
// Skipping as currently unable to propose using forms other than raw
// 3002-PROP-011 // 3002-PROP-011
it('Able to submit a valid freeform proposal - with minimum required tokens associated', function () { it.skip('Able to submit a valid freeform proposal - with minimum required tokens associated', function () {
goToMakeNewProposal(governanceProposalType.FREEFORM); goToMakeNewProposal(governanceProposalType.FREEFORM);
cy.get(minVoteButton).should('be.visible'); // 3002-PROP-008 cy.get(minVoteButton).should('be.visible'); // 3002-PROP-008
cy.get(maxVoteButton).should('be.visible'); cy.get(maxVoteButton).should('be.visible');
@@ -138,16 +142,13 @@ context(
closeStakingDialog(); closeStakingDialog();
cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2'); cy.get(vegaWalletStakedBalances, txTimeout).should('contain', '2');
createRawProposal();
navigateTo(navigation.proposals);
goToMakeNewProposal(governanceProposalType.FREEFORM);
enterUniqueFreeFormProposalBody('50', generateFreeFormProposalTitle());
waitForProposalSubmitted();
}); });
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); goToMakeNewProposal(governanceProposalType.FREEFORM);
enterUniqueFreeFormProposalBody('0.1', generateFreeFormProposalTitle()); enterUniqueFreeFormProposalBody('0.1', generateFreeFormProposalTitle());
cy.contains('Awaiting network confirmation', epochTimeout).should( cy.contains('Awaiting network confirmation', epochTimeout).should(
'not.exist' 'not.exist'
); );
@@ -156,7 +157,7 @@ context(
.should('equal', 'Value must be greater than or equal to 1.'); .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); goToMakeNewProposal(governanceProposalType.FREEFORM);
enterUniqueFreeFormProposalBody( enterUniqueFreeFormProposalBody(
'100000', '100000',
@@ -183,17 +184,13 @@ context(
navigateTo(navigation.proposals); navigateTo(navigation.proposals);
cy.get(rejectProposalsLink).click(); cy.get(rejectProposalsLink).click();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList( getProposalFromTitle(rawProposal.rationale.title).within(() => {
rawProposal.rationale.title
).within(() => {
cy.contains('Rejected').should('be.visible'); cy.contains('Rejected').should('be.visible');
cy.contains('Close time too late').should('be.visible'); cy.contains('Close time too late').should('be.visible');
cy.get(viewProposalButton).click(); cy.get(viewProposalButton).click();
}); });
}); });
getProposalInformationFromTable('State') cy.getByTestId('proposal-status').should('have.text', 'Rejected');
.contains('Rejected')
.and('be.visible');
getProposalInformationFromTable('Rejection reason') getProposalInformationFromTable('Rejection reason')
.contains('PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE') .contains('PROPOSAL_ERROR_CLOSE_TIME_TOO_LATE')
.and('be.visible'); .and('be.visible');
@@ -288,18 +285,19 @@ context(
const proposalTitle = generateFreeFormProposalTitle(); const proposalTitle = generateFreeFormProposalTitle();
ensureSpecifiedUnstakedTokensAreAssociated('1'); ensureSpecifiedUnstakedTokensAreAssociated('1');
goToMakeNewProposal(governanceProposalType.FREEFORM); submitUniqueRawProposal({ proposalTitle: proposalTitle });
enterUniqueFreeFormProposalBody('50', proposalTitle); ethereumWalletConnect();
waitForProposalSubmitted();
stakingPageDisassociateTokens('0.0001'); stakingPageDisassociateTokens('0.0001');
cy.get(vegaWallet).within(() => { cy.get(vegaWallet)
cy.get(vegaWalletAssociatedBalance, txTimeout).should( .first()
'contain', .within(() => {
'0.9999' cy.get(vegaWalletAssociatedBalance, txTimeout).should(
); 'contain',
}); '0.9999'
);
});
navigateTo(navigation.proposals); navigateTo(navigation.proposals);
getSubmittedProposalFromProposalList(proposalTitle).within(() => getProposalFromTitle(proposalTitle).within(() =>
cy.get(viewProposalButton).click() cy.get(viewProposalButton).click()
); );
cy.contains('Vote breakdown').should('be.visible', { cy.contains('Vote breakdown').should('be.visible', {
@@ -317,9 +315,9 @@ context(
cy.get('[data-testid="manage-vega-wallet"]:visible').click(); cy.get('[data-testid="manage-vega-wallet"]:visible').click();
cy.get('[data-testid="disconnect"]').click(); cy.get('[data-testid="disconnect"]').click();
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList( getProposalFromTitle(rawProposal.rationale.title).within(() =>
rawProposal.rationale.title cy.get(viewProposalButton).click()
).within(() => cy.get(viewProposalButton).click()); );
}); });
// 3001-VOTE-075 // 3001-VOTE-075
// 3001-VOTE-076 // 3001-VOTE-076
@@ -2,11 +2,13 @@ import {
closeDialog, closeDialog,
navigateTo, navigateTo,
navigation, navigation,
turnTelemetryOff,
waitForSpinner, waitForSpinner,
} from '../../support/common.functions'; } from '../../support/common.functions';
import { import {
getProposalInformationFromTable, getProposalInformationFromTable,
goToMakeNewProposal, goToMakeNewProposal,
governanceProposalType,
voteForProposal, voteForProposal,
waitForProposalSubmitted, waitForProposalSubmitted,
} from '../../support/governance.functions'; } from '../../support/governance.functions';
@@ -55,18 +57,8 @@ const fUSDCId =
const epochTimeout = Cypress.env('epochTimeout'); const epochTimeout = Cypress.env('epochTimeout');
const proposalTimeout = { timeout: 14000 }; 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 // 3001-VOTE-007
context( context.skip(
'Governance flow - form validations for different governance proposals', 'Governance flow - form validations for different governance proposals',
{ tags: '@slow' }, { tags: '@slow' },
function () { function () {
@@ -77,6 +69,7 @@ context(
beforeEach('visit governance tab', function () { beforeEach('visit governance tab', function () {
cy.clearLocalStorage(); cy.clearLocalStorage();
turnTelemetryOff();
cy.reload(); cy.reload();
waitForSpinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
@@ -2,19 +2,19 @@ import type { testFreeformProposal } from '../../support/common-interfaces';
import { import {
navigateTo, navigateTo,
navigation, navigation,
turnTelemetryOff,
waitForSpinner, waitForSpinner,
} from '../../support/common.functions'; } from '../../support/common.functions';
import { import {
createFreeformProposal,
createRawProposal, createRawProposal,
createTenDigitUnixTimeStampForSpecifiedDays, createTenDigitUnixTimeStampForSpecifiedDays,
enterRawProposalBody, enterRawProposalBody,
generateFreeFormProposalTitle, generateFreeFormProposalTitle,
getProposalIdFromList, getProposalFromTitle,
getProposalInformationFromTable, getProposalInformationFromTable,
getSubmittedProposalFromProposalList,
goToMakeNewProposal, goToMakeNewProposal,
governanceProposalType, governanceProposalType,
submitUniqueRawProposal,
voteForProposal, voteForProposal,
waitForProposalSubmitted, waitForProposalSubmitted,
waitForProposalSync, waitForProposalSync,
@@ -23,10 +23,14 @@ import { ensureSpecifiedUnstakedTokensAreAssociated } from '../../support/stakin
import { ethereumWalletConnect } from '../../support/wallet-eth.functions'; import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions'; import { vegaWalletSetSpecifiedApprovalAmount } from '../../support/wallet-teardown.functions';
const proposalListItem = 'proposals-list-item';
const openProposals = '[data-testid="open-proposals"]'; 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 proposalClosingDate = '[data-testid="vote-details"]';
const viewProposalButton = '[data-testid="view-proposal-btn"]'; const viewProposalButton = '[data-testid="view-proposal-btn"]';
const voteBreakDownToggle = 'vote-breakdown-toggle';
describe('Governance flow for proposal list', { tags: '@slow' }, function () { describe('Governance flow for proposal list', { tags: '@slow' }, function () {
before('connect wallets and set approval limit', function () { before('connect wallets and set approval limit', function () {
@@ -36,6 +40,7 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
beforeEach('visit proposals tab', function () { beforeEach('visit proposals tab', function () {
cy.clearLocalStorage(); cy.clearLocalStorage();
turnTelemetryOff();
cy.reload(); cy.reload();
waitForSpinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
@@ -58,12 +63,12 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
navigateTo(navigation.proposals); navigateTo(navigation.proposals);
cy.get(openProposals).within(() => { cy.get(openProposals).within(() => {
cy.get(proposalClosingDate).first().should('contain.text', 'year');
cy.get(proposalClosingDate).should('contain.text', 'months');
cy.get(proposalClosingDate) cy.get(proposalClosingDate)
.last() .first()
.invoke('text') .invoke('text')
.should('match', /days|minutes/); .should('match', /days|minutes/);
cy.get(proposalClosingDate).should('contain.text', 'months');
cy.get(proposalClosingDate).last().should('contain.text', 'year');
}); });
}); });
@@ -71,36 +76,27 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
const proposerId = Cypress.env('vegaWalletPublicKey'); const proposerId = Cypress.env('vegaWalletPublicKey');
const proposalTitle = generateFreeFormProposalTitle(); const proposalTitle = generateFreeFormProposalTitle();
createFreeformProposal(proposalTitle); submitUniqueRawProposal({ proposalTitle: proposalTitle });
getProposalIdFromList(proposalTitle); cy.get('[data-testid="set-proposals-filter-visible"]').click();
cy.get('@proposalIdText').then((proposalId) => { cy.get('[data-testid="filter-input"]').type(proposerId);
cy.get('[data-testid="set-proposals-filter-visible"]').click(); // cy.get(`#${proposalId}`).should('contain', proposalId);
cy.get('[data-testid="filter-input"]').type(proposerId); cy.contains(proposalTitle).should('be.visible');
cy.get(`#${proposalId}`).should('contain', proposalId); 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 () { it('Newly created proposals list - shows title and portion of summary', function () {
createRawProposal(this.minProposerBalance); // 3001-VOTE-052 const proposalPath = '/proposals/new-market-raw.json';
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => { const enactmentTimestamp = createTenDigitUnixTimeStampForSpecifiedDays(3);
getProposalIdFromList(rawProposal.rationale.title); submitUniqueRawProposal({
cy.get('@proposalIdText').then((proposalId) => { proposalBody: proposalPath,
cy.get(openProposals).within(() => { enactmentTimestamp: enactmentTimestamp,
// 3001-VOTE-008 }); // 3001-VOTE-052
// 3001-VOTE-034 // 3001-VOTE-008
cy.get(`#${proposalId}`) // 3001-VOTE-034
// 3001-VOTE-097 // 3001-VOTE-097
.should('contain', rawProposal.rationale.title) cy.contains('New Market Proposal E2E submission');
.and('be.visible'); cy.contains('Code: TEST.24h. fBTC settled future.').should('be.visible');
cy.get(`#${proposalId}`)
.should(
'contain',
rawProposal.rationale.description.substring(0, 59)
)
.and('be.visible');
});
});
});
}); });
it('Newly created proposals list - shows open proposals in an open state', function () { it('Newly created proposals list - shows open proposals in an open state', function () {
@@ -108,23 +104,11 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
// 3001-VOTE-035 // 3001-VOTE-035
createRawProposal(this.minProposerBalance); createRawProposal(this.minProposerBalance);
cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => { cy.get<testFreeformProposal>('@rawProposal').then((rawProposal) => {
getSubmittedProposalFromProposalList(rawProposal.rationale.title).within( getProposalFromTitle(rawProposal.rationale.title).within(() => {
() => { cy.get(viewProposalButton).should('be.visible');
cy.get(viewProposalButton).should('be.visible').click(); cy.getByTestId(proposalType).should('have.text', 'Freeform');
} cy.getByTestId(proposalStatus).should('have.text', 'Open');
);
cy.get('@proposalIdText').then((proposalId) => {
getProposalInformationFromTable('ID')
.contains(String(proposalId))
.and('be.visible');
}); });
getProposalInformationFromTable('State')
.contains('Open')
.and('be.visible');
getProposalInformationFromTable('Type')
.contains('Freeform')
.and('be.visible');
}); });
}); });
@@ -132,18 +116,22 @@ describe('Governance flow for proposal list', { tags: '@slow' }, function () {
it('Newly created freeform proposals list - shows proposal participation - both met and not', function () { it('Newly created freeform proposals list - shows proposal participation - both met and not', function () {
const proposalTitle = generateFreeFormProposalTitle(); const proposalTitle = generateFreeFormProposalTitle();
createFreeformProposal(proposalTitle); submitUniqueRawProposal({ proposalTitle: proposalTitle });
getSubmittedProposalFromProposalList(proposalTitle).within(() => { getProposalFromTitle(proposalTitle).within(() => {
// 3001-VOTE-039 // 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(); cy.get(viewProposalButton).click();
}); });
voteForProposal('for'); voteForProposal('for');
navigateTo(navigation.proposals); navigateTo(navigation.proposals);
getSubmittedProposalFromProposalList(proposalTitle).within(() => { getProposalFromTitle(proposalTitle).within(() => {
cy.get(voteStatus).should('have.text', 'Set to pass'); cy.getByTestId(voteStatus).should('have.text', 'Set to pass');
cy.get(viewProposalButton).click(); cy.get(viewProposalButton).click();
}); });
cy.getByTestId(voteBreakDownToggle).click();
getProposalInformationFromTable('Token participation met') getProposalInformationFromTable('Token participation met')
.contains('👍') .contains('👍')
.should('be.visible'); .should('be.visible');
@@ -1,6 +1,7 @@
import { import {
navigateTo, navigateTo,
navigation, navigation,
turnTelemetryOff,
waitForSpinner, waitForSpinner,
} from '../../support/common.functions'; } from '../../support/common.functions';
import { import {
@@ -26,6 +27,7 @@ const rewardsTimeOut = { timeout: 60000 };
context('rewards - flow', { tags: '@slow' }, function () { context('rewards - flow', { tags: '@slow' }, function () {
before('set up environment to allow rewards', function () { before('set up environment to allow rewards', function () {
cy.clearLocalStorage(); cy.clearLocalStorage();
turnTelemetryOff();
cy.visit('/'); cy.visit('/');
waitForSpinner(); waitForSpinner();
depositAsset(vegaAssetAddress, '1000', 18); depositAsset(vegaAssetAddress, '1000', 18);
@@ -7,6 +7,7 @@ import {
waitForSpinner, waitForSpinner,
navigateTo, navigateTo,
navigation, navigation,
turnTelemetryOff,
} from '../../support/common.functions'; } from '../../support/common.functions';
import { import {
clickOnValidatorFromList, clickOnValidatorFromList,
@@ -67,6 +68,7 @@ context(
'teardown wallet & drill into a specific validator', 'teardown wallet & drill into a specific validator',
function () { function () {
cy.clearLocalStorage(); cy.clearLocalStorage();
turnTelemetryOff();
cy.reload(); cy.reload();
waitForSpinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
@@ -94,7 +96,7 @@ context(
navigateTo(navigation.validators); navigateTo(navigation.validators);
// 2002-SINC-007 // 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 () { it('Able to view validators staked by me', function () {
@@ -144,7 +146,7 @@ context(
verifyThisEpochValue(2.0); verifyThisEpochValue(2.0);
closeStakingDialog(); closeStakingDialog();
navigateTo(navigation.validators); 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 () { it('Able to stake against a validator - using vega from both wallet and vesting contract', function () {
@@ -164,10 +166,11 @@ context(
verifyThisEpochValue(6.0); verifyThisEpochValue(6.0);
closeStakingDialog(); closeStakingDialog();
navigateTo(navigation.validators); navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '6.00', '100.00%'); validateValidatorListTotalStakeAndShare('0', '3,006.00', '50.05%');
}); });
it('Able to stake against multiple validators', function () { it('Able to stake against multiple validators', function () {
vegaWalletTeardown();
stakingPageAssociateTokens('5'); stakingPageAssociateTokens('5');
verifyUnstakedBalance(5.0); verifyUnstakedBalance(5.0);
cy.get('button').contains('Select a validator to nominate').click(); cy.get('button').contains('Select a validator to nominate').click();
@@ -195,14 +198,10 @@ context(
.eq(1) .eq(1)
.within(() => { .within(() => {
cy.getByTestId(stakeValidatorListTotalStake) cy.getByTestId(stakeValidatorListTotalStake)
.should('have.text', '2.00') .should('have.text', '3,002.00')
.and('be.visible'); .and('be.visible');
cy.getByTestId(stakeValidatorListTotalShare) cy.getByTestId(stakeValidatorListTotalShare)
.should('have.text', '66.67%') .should('have.text', '50.01%')
.and('be.visible');
cy.getByTestId(stakeValidatorListTotalStake)
.scrollIntoView()
.should('have.text', '2.00')
.and('be.visible'); .and('be.visible');
}); });
cy.get(`[row-id="${1}"]`) cy.get(`[row-id="${1}"]`)
@@ -210,14 +209,10 @@ context(
.within(() => { .within(() => {
cy.getByTestId(stakeValidatorListTotalStake) cy.getByTestId(stakeValidatorListTotalStake)
.scrollIntoView() .scrollIntoView()
.should('have.text', '1.00') .should('have.text', '3,001.00')
.and('be.visible'); .and('be.visible');
cy.getByTestId(stakeValidatorListTotalShare) cy.getByTestId(stakeValidatorListTotalShare)
.should('have.text', '33.33%') .should('have.text', '49.99%')
.and('be.visible');
cy.getByTestId(stakeValidatorListTotalStake)
.scrollIntoView()
.should('have.text', '1.00')
.and('be.visible'); .and('be.visible');
}); });
}); });
@@ -252,10 +247,10 @@ context(
waitForBeginningOfEpoch(); waitForBeginningOfEpoch();
cy.getByTestId(stakeValidatorListStakePercentage).should( cy.getByTestId(stakeValidatorListStakePercentage).should(
'have.text', 'have.text',
'100%' '50.02%'
); );
navigateTo(navigation.validators); navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '2.00', '100.00%'); validateValidatorListTotalStakeAndShare('0', '3,002.00', '50.02%');
} }
); );
@@ -280,7 +275,7 @@ context(
txTimeout txTimeout
); );
navigateTo(navigation.validators); navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%'); validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%');
cy.getByTestId(userStakeBtn).should('not.exist'); cy.getByTestId(userStakeBtn).should('not.exist');
cy.getByTestId(userStake).should('not.exist'); cy.getByTestId(userStake).should('not.exist');
@@ -352,7 +347,7 @@ context(
txTimeout txTimeout
); );
navigateTo(navigation.validators); 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 () { it('Disassociating all vesting contract tokens max - removes all staked tokens', function () {
@@ -380,7 +375,7 @@ context(
txTimeout txTimeout
); );
navigateTo(navigation.validators); navigateTo(navigation.validators);
validateValidatorListTotalStakeAndShare('0', '0.00', '0.00%'); validateValidatorListTotalStakeAndShare('0', '3,000.00', '50.00%');
}); });
it('Disassociating some tokens - prioritizes unstaked tokens', function () { it('Disassociating some tokens - prioritizes unstaked tokens', function () {
@@ -402,7 +397,7 @@ context(
}); });
verifyStakedBalance(2.0); verifyStakedBalance(2.0);
navigateTo(navigation.validators); 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 () { it('Associating wallet tokens - when some already staked - auto stakes tokens to staked validator', function () {
@@ -4,6 +4,7 @@ import {
waitForSpinner, waitForSpinner,
navigateTo, navigateTo,
navigation, navigation,
turnTelemetryOff,
} from '../../support/common.functions'; } from '../../support/common.functions';
import { import {
stakingPageAssociateTokens, stakingPageAssociateTokens,
@@ -54,6 +55,7 @@ context(
'teardown wallet & drill into a specific validator', 'teardown wallet & drill into a specific validator',
function () { function () {
cy.clearLocalStorage(); cy.clearLocalStorage();
turnTelemetryOff();
cy.reload(); cy.reload();
waitForSpinner(); waitForSpinner();
cy.connectVegaWallet(); cy.connectVegaWallet();
@@ -109,10 +111,10 @@ context(
// 1004-ASSO-028 // 1004-ASSO-028
// 1004-ASSO-029 // 1004-ASSO-029
// 1004-ASSO-031 // 1004-ASSO-031
vegaWalletTeardown();
stakingPageAssociateTokens('2'); stakingPageAssociateTokens('2');
verifyEthWalletAssociatedBalance('2.0'); verifyEthWalletAssociatedBalance('2.0');
verifyEthWalletTotalAssociatedBalance('2.0'); verifyEthWalletTotalAssociatedBalance('6,002.00');
cy.get('button').contains('Select a validator to nominate').click(); cy.get('button').contains('Select a validator to nominate').click();
stakingPageDisassociateTokens('2'); stakingPageDisassociateTokens('2');
cy.getByTestId('currency-title', txTimeout).should( cy.getByTestId('currency-title', txTimeout).should(
@@ -123,17 +125,18 @@ context(
validateWalletCurrency('Pending association', '2.00'); validateWalletCurrency('Pending association', '2.00');
validateWalletCurrency('Total associated after pending', '0.00'); validateWalletCurrency('Total associated after pending', '0.00');
cy.getByTestId('currency-title', txTimeout).should('have.length', 6); cy.getByTestId('currency-title', txTimeout).should('have.length', 6);
cy.getByTestId('eth-wallet-associated-balances', txTimeout).should( cy.get(
'not.exist' '[data-testid="eth-wallet-associated-balances"]:visible',
); txTimeout
verifyEthWalletTotalAssociatedBalance('0.00'); ).should('have.length', 2);
verifyEthWalletTotalAssociatedBalance('6,000.00');
}); });
it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () { it('Able to associate more tokens than the approved amount of 1000 - requires re-approval', function () {
//1004-ASSO-011 //1004-ASSO-011
stakingPageAssociateTokens('1001', { approve: true }); stakingPageAssociateTokens('1001', { approve: true });
verifyEthWalletAssociatedBalance('1,001.00'); verifyEthWalletAssociatedBalance('1,001.00');
verifyEthWalletTotalAssociatedBalance('1,001.00'); verifyEthWalletTotalAssociatedBalance('7,001.00');
cy.get(vegaWallet) cy.get(vegaWallet)
.last() .last()
.within(() => { .within(() => {
@@ -1,6 +1,7 @@
import { import {
navigateTo, navigateTo,
navigation, navigation,
turnTelemetryOff,
waitForSpinner, waitForSpinner,
} from '../../support/common.functions'; } from '../../support/common.functions';
import { ethereumWalletConnect } from '../../support/wallet-eth.functions'; import { ethereumWalletConnect } from '../../support/wallet-eth.functions';
@@ -46,15 +47,13 @@ context(
function () { function () {
before('visit withdrawals and connect vega wallet', function () { before('visit withdrawals and connect vega wallet', function () {
cy.visit('/'); cy.visit('/');
// When running tests locally, will fail if run without restarting capsule ethereumWalletConnect();
cy.updateCapsuleMultiSig().then(() => { depositAsset(usdcEthAddress, '1000', 5);
ethereumWalletConnect();
depositAsset(usdcEthAddress, '1000', 5);
});
}); });
beforeEach('Navigate to withdrawal page', function () { beforeEach('Navigate to withdrawal page', function () {
cy.clearLocalStorage(); cy.clearLocalStorage();
turnTelemetryOff();
cy.reload(); cy.reload();
waitForSpinner(); waitForSpinner();
navigateTo(navigation.withdraw); navigateTo(navigation.withdraw);
@@ -161,7 +161,7 @@ context('Home Page - verify elements on page', { tags: '@smoke' }, function () {
cy.getByTestId('menu-drawer').should('be.visible'); cy.getByTestId('menu-drawer').should('be.visible');
}); });
it('should have link for proposal page', function () { it.skip('should have link for proposal page', function () {
cy.getByTestId('menu-drawer').within(() => { cy.getByTestId('menu-drawer').within(() => {
cy.get('[href="/proposals"]') cy.get('[href="/proposals"]')
.should('exist') .should('exist')
@@ -54,7 +54,7 @@ context(
}); });
}); });
it('should be able to see button for - new proposal', function () { it.skip('should be able to see button for - new proposal', function () {
// 3001-VOTE-002 // 3001-VOTE-002
cy.get(newProposalLink) cy.get(newProposalLink)
.should('be.visible') .should('be.visible')
@@ -63,7 +63,7 @@ context(
.and('equal', '/proposals/propose'); .and('equal', '/proposals/propose');
}); });
it('should be able to see a connect wallet button - if vega wallet disconnected and user is submitting new proposal', function () { 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); goToMakeNewProposal(governanceProposalType.NETWORK_PARAMETER);
cy.get(connectToVegaWalletButton) cy.get(connectToVegaWalletButton)
.should('be.visible') .should('be.visible')
@@ -109,7 +109,7 @@ context(
); );
cy.getByTestId('protocol-upgrade-proposal-status').should( cy.getByTestId('protocol-upgrade-proposal-status').should(
'have.text', 'have.text',
'Approved ' 'Approved by validators '
); );
}); });
}); });
@@ -136,7 +136,7 @@ context(
); );
cy.getByTestId('protocol-upgrade-state').should( cy.getByTestId('protocol-upgrade-state').should(
'have.text', 'have.text',
'Approved' 'Approved by validators'
); );
cy.getByTestId('protocol-upgrade-release-tag').should( cy.getByTestId('protocol-upgrade-release-tag').should(
'have.text', 'have.text',
@@ -3,11 +3,13 @@
import { import {
navigateTo, navigateTo,
navigation, navigation,
turnTelemetryOff,
waitForSpinner, waitForSpinner,
} from '../../support/common.functions'; } from '../../support/common.functions';
import { import {
enterUniqueFreeFormProposalBody, enterUniqueFreeFormProposalBody,
goToMakeNewProposal, goToMakeNewProposal,
governanceProposalType,
} from '../../support/governance.functions'; } from '../../support/governance.functions';
import { vegaWalletFaucetAssetsWithoutCheck } from '../../support/wallet-vega.functions'; import { vegaWalletFaucetAssetsWithoutCheck } from '../../support/wallet-vega.functions';
@@ -26,6 +28,7 @@ context('View functionality with public key', { tags: '@smoke' }, function () {
beforeEach('visit home page', function () { beforeEach('visit home page', function () {
cy.clearLocalStorage(); cy.clearLocalStorage();
turnTelemetryOff();
cy.visit('/'); cy.visit('/');
waitForSpinner(); waitForSpinner();
cy.connectPublicKey(vegaWalletPubKey); cy.connectPublicKey(vegaWalletPubKey);
@@ -44,11 +47,11 @@ context('View functionality with public key', { tags: '@smoke' }, function () {
.and('contain.text', 'USDC (fake)'); .and('contain.text', 'USDC (fake)');
}); });
it('Unable to submit proposal with public key', function () { it.skip('Unable to submit proposal with public key', function () {
const expectedErrorTxt = `You are connected in a view only state for public key: ${vegaWalletPubKey}. In order to send transactions you must connect to a real wallet.`; 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); navigateTo(navigation.proposals);
goToMakeNewProposal('Freeform'); goToMakeNewProposal(governanceProposalType.FREEFORM);
enterUniqueFreeFormProposalBody('50', 'pub key proposal test'); enterUniqueFreeFormProposalBody('50', 'pub key proposal test');
cy.getByTestId('dialog-content') cy.getByTestId('dialog-content')
.first() .first()
@@ -13,7 +13,6 @@ context(
{ tags: '@regression' }, { tags: '@regression' },
function () { function () {
before('navigate to rewards page', function () { before('navigate to rewards page', function () {
cy.clearLocalStorage();
cy.visit('/'); cy.visit('/');
navigateTo(navigation.rewards); navigateTo(navigation.rewards);
}); });
@@ -64,7 +63,6 @@ context(
}); });
it('should have option to go to last and newest page', function () { it('should have option to go to last and newest page', function () {
waitForBeginningOfEpoch();
cy.getByTestId('goto-last-page').click(); cy.getByTestId('goto-last-page').click();
cy.getByTestId('epoch-total-rewards-table') cy.getByTestId('epoch-total-rewards-table')
.last() .last()
@@ -29,11 +29,10 @@ const performancePenaltyToolTip = '[data-testid="performance-penalty-tooltip"]';
const overstakedPenaltyToolTip = '[data-testid="overstaked-penalty-tooltip"]'; const overstakedPenaltyToolTip = '[data-testid="overstaked-penalty-tooltip"]';
const totalPenaltyToolTip = '[data-testid="total-penalty-tooltip"]'; const totalPenaltyToolTip = '[data-testid="total-penalty-tooltip"]';
const epochCountDown = '[data-testid="epoch-countdown"]'; 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 () { context('Validators Page - verify elements on page', function () {
before('navigate to validators page', function () { before('navigate to validators page', function () {
cy.clearAllLocalStorage();
cy.visit('/validators'); cy.visit('/validators');
}); });
@@ -85,13 +84,13 @@ context('Validators Page - verify elements on page', function () {
cy.get(stakedByOperatorToolTip) cy.get(stakedByOperatorToolTip)
.invoke('text') .invoke('text')
.should('contain', 'Staked by operator: 0.00'); .should('contain', 'Staked by operator: 3,000.00');
cy.get(stakedByDelegatesToolTip) cy.get(stakedByDelegatesToolTip)
.invoke('text') .invoke('text')
.should('contain', 'Staked by delegates: 0.00'); .should('contain', 'Staked by delegates: 0.00');
cy.get(totalStakedToolTip) cy.get(totalStakedToolTip)
.invoke('text') .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 () { it('Should be able to see validator normalised voting power', function () {
@@ -107,10 +106,10 @@ context('Validators Page - verify elements on page', function () {
cy.get(unnormalisedVotingPowerToolTip) cy.get(unnormalisedVotingPowerToolTip)
.invoke('text') .invoke('text')
.should('contain', 'Unnormalised voting power: 0.00%'); .should('contain', 'Unnormalised voting power: 20.00%');
cy.get(normalisedVotingPowerToolTip) cy.get(normalisedVotingPowerToolTip)
.invoke('text') .invoke('text')
.should('contain', 'Normalised voting power: 0.10%'); .should('contain', 'Normalised voting power: 50.00%');
}); });
// 2002-SINC-018 // 2002-SINC-018
@@ -127,13 +126,13 @@ context('Validators Page - verify elements on page', function () {
cy.get(performancePenaltyToolTip) cy.get(performancePenaltyToolTip)
.invoke('text') .invoke('text')
.should('contain', 'Performance penalty: 100.00%'); .should('contain', 'Performance penalty: 0.00%');
cy.get(overstakedPenaltyToolTip) cy.get(overstakedPenaltyToolTip)
.invoke('text') .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) cy.get(totalPenaltyToolTip)
.invoke('text') .invoke('text')
.should('contain', 'Total penalties: 0.00%'); .should('contain', 'Total penalties: 60.00%');
}); });
it('Should be able to see validator pending stake', function () { it('Should be able to see validator pending stake', function () {
@@ -35,7 +35,6 @@ context(
{ tags: '@regression' }, { tags: '@regression' },
() => { () => {
before('visit token home page', () => { before('visit token home page', () => {
cy.clearAllLocalStorage();
cy.visit('/'); cy.visit('/');
cy.get(walletContainer, { timeout: 60000 }).should('be.visible'); cy.get(walletContainer, { timeout: 60000 }).should('be.visible');
}); });
@@ -12,7 +12,6 @@ context(
{ tags: '@smoke' }, { tags: '@smoke' },
function () { function () {
before('navigate to withdrawals page', function () { before('navigate to withdrawals page', function () {
cy.clearAllLocalStorage();
cy.visit('/'); cy.visit('/');
navigateTo(navigation.withdraw); navigateTo(navigation.withdraw);
}); });
@@ -90,3 +90,10 @@ export function verifyEthWalletAssociatedBalance(amount: string) {
export function closeDialog() { export function closeDialog() {
cy.getByTestId('dialog-close').click(); cy.getByTestId('dialog-close').click();
} }
export function turnTelemetryOff() {
// Ensuring the telemetry modal doesn't disrupt the tests
cy.window().then((win) =>
win.localStorage.setItem('vega_telemetry_on', 'false')
);
}
@@ -1,8 +1,12 @@
import { format } from 'date-fns'; 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'; import { ensureSpecifiedUnstakedTokensAreAssociated } from './staking.functions';
const newProposalButton = '[data-testid="new-proposal-link"]';
const proposalInformationTableRows = '[data-testid="key-value-table-row"]'; const proposalInformationTableRows = '[data-testid="key-value-table-row"]';
const proposalListItem = '[data-testid="proposals-list-item"]'; const proposalListItem = '[data-testid="proposals-list-item"]';
const newProposalTitle = '[data-testid="proposal-title"]'; const newProposalTitle = '[data-testid="proposal-title"]';
@@ -46,6 +50,53 @@ 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 = '/proposals/raw.json';
if (proposalFields.proposalBody) {
proposalBodyPath = proposalFields.proposalBody;
}
cy.fixture(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 {
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( export function enterUniqueFreeFormProposalBody(
timestamp: string, timestamp: string,
proposalTitle: string proposalTitle: string
@@ -58,6 +109,10 @@ export function enterUniqueFreeFormProposalBody(
cy.getByTestId('proposal-submit').should('be.visible').click(); cy.getByTestId('proposal-submit').should('be.visible').click();
} }
export function getProposalFromTitle(proposalTitle: string) {
return cy.contains(proposalTitle).parentsUntil(proposalListItem).last();
}
export function getSubmittedProposalFromProposalList(proposalTitle: string) { export function getSubmittedProposalFromProposalList(proposalTitle: string) {
getProposalIdFromList(proposalTitle); getProposalIdFromList(proposalTitle);
cy.get('@proposalIdText').then((proposalId) => { cy.get('@proposalIdText').then((proposalId) => {
@@ -120,13 +175,17 @@ export function waitForProposalSync() {
}); });
} }
export function goToMakeNewProposal(proposalType: string) { export function goToMakeNewProposal(proposalType: governanceProposalType) {
navigateTo(navigation.proposals); cy.visit('/proposals/propose');
cy.get(newProposalButton).should('be.visible').click(); waitForSpinner();
cy.url().should('include', '/proposals/propose'); cy.url().should('include', '/proposals/propose');
cy.get(navigation.pageSpinner, { timeout: 20000 }).should('not.exist'); cy.get(navigation.pageSpinner, { timeout: 20000 }).should('not.exist');
cy.get('li').should('contain.text', proposalType).and('be.visible'); if (proposalType == governanceProposalType.RAW) {
cy.get('li').contains(proposalType).click(); cy.get('[href="/proposals/propose/raw"]').click();
} else {
cy.get('li').should('contain.text', proposalType).and('be.visible');
cy.get('li').contains(proposalType).click();
}
} }
export function waitForProposalSubmitted() { export function waitForProposalSubmitted() {
@@ -163,11 +222,12 @@ export function createFreeformProposal(proposalTitle: string) {
navigateTo(navigation.proposals); navigateTo(navigation.proposals);
} }
export const governanceProposalType = { export enum governanceProposalType {
NETWORK_PARAMETER: 'Network parameter', NETWORK_PARAMETER = 'Network parameter',
NEW_MARKET: 'New market', NEW_MARKET = 'New market',
UPDATE_MARKET: 'Update market', UPDATE_MARKET = 'Update market',
NEW_ASSET: 'New asset', NEW_ASSET = 'New asset',
FREEFORM: 'Freeform', UPDATE_ASSET = 'Update asset',
RAW: 'raw proposal', FREEFORM = 'Freeform',
}; RAW = 'raw proposal',
}
+7
View File
@@ -8,9 +8,11 @@ import './wallet-eth.functions.ts';
import './wallet-teardown.functions.ts'; import './wallet-teardown.functions.ts';
import './wallet-vega.functions.ts'; import './wallet-vega.functions.ts';
import './proposal.functions.ts'; import './proposal.functions.ts';
import 'cypress-mochawesome-reporter/register';
import registerCypressGrep from '@cypress/grep'; import registerCypressGrep from '@cypress/grep';
import { aliasGQLQuery } from '@vegaprotocol/cypress'; import { aliasGQLQuery } from '@vegaprotocol/cypress';
import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock'; import { chainIdQuery, statisticsQuery } from '@vegaprotocol/mock';
import { turnTelemetryOff } from './common.functions.ts';
registerCypressGrep(); registerCypressGrep();
// Hide fetch/XHR requests - They create a lot of noise in command log // Hide fetch/XHR requests - They create a lot of noise in command log
@@ -24,9 +26,14 @@ if (!app.document.head.querySelector('[data-hide-command-log-request]')) {
} }
before(() => { before(() => {
cy.clearLocalStorage();
// // Ensuring the telemetry modal doesn't disrupt the tests
turnTelemetryOff();
// Mock chainId fetch which happens on every page for wallet connection // Mock chainId fetch which happens on every page for wallet connection
cy.mockGQL((req) => { cy.mockGQL((req) => {
aliasGQLQuery(req, 'ChainId', chainIdQuery()); aliasGQLQuery(req, 'ChainId', chainIdQuery());
aliasGQLQuery(req, 'Statistics', statisticsQuery()); 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() { export function mockNetworkUpgradeProposal() {
cy.mockGQL((req) => { cy.mockGQL((req) => {
aliasGQLQuery(req, 'Nodes', nodeData); aliasGQLQuery(req, 'Nodes', nodeData);
@@ -3,7 +3,6 @@ import {
StakingBridge, StakingBridge,
Token, Token,
TokenVesting, TokenVesting,
TokenFaucetable,
CollateralBridge, CollateralBridge,
} from '@vegaprotocol/smart-contracts'; } from '@vegaprotocol/smart-contracts';
import { ethers, Wallet } from 'ethers'; import { ethers, Wallet } from 'ethers';
@@ -41,7 +40,7 @@ export async function depositAsset(
decimalPlaces: number decimalPlaces: number
) { ) {
// Approve asset // Approve asset
const faucet = new TokenFaucetable(assetEthAddress, signer); const faucet = new Token(assetEthAddress, signer);
cy.wrap( cy.wrap(
faucet.approve(Erc20BridgeAddress, amount + '0'.repeat(decimalPlaces + 1)), faucet.approve(Erc20BridgeAddress, amount + '0'.repeat(decimalPlaces + 1)),
{ {
@@ -62,13 +61,12 @@ export async function depositAsset(
} }
export async function faucetAsset(assetEthAddress: string) { 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'); await promiseWithTimeout(faucet.faucet(), 10 * 60 * 1000, 'faucet asset');
} }
export async function vegaWalletTeardown() { export async function vegaWalletTeardown() {
cy.get(associatedAmountInWallet) cy.get(associatedAmountInWallet)
.should('be.visible')
.invoke('text') .invoke('text')
.then((associatedAmount) => { .then((associatedAmount) => {
cy.get('body').then(($body) => { cy.get('body').then(($body) => {
@@ -83,9 +81,11 @@ export async function vegaWalletTeardown() {
cy.get(vegaWalletContainer).within(() => { cy.get(vegaWalletContainer).within(() => {
cy.get(associatedAmountInWallet, { cy.get(associatedAmountInWallet, {
timeout: transactionTimeout, timeout: transactionTimeout,
}).contains('0.00', { })
timeout: transactionTimeout, .should('have.length', 1, { timeout: transactionTimeout })
}); .contains('0.00', {
timeout: transactionTimeout,
});
}); });
}); });
} }
+2 -1
View File
@@ -5,7 +5,7 @@ NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8 NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_FAIRGROUND=false NX_FAIRGROUND=false
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}' 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_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_WALLET_URL=http://localhost:1789 NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz NX_VEGA_EXPLORER_URL=https://stagnet1.explorer.vega.xyz
@@ -15,6 +15,7 @@ NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz 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_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/main/announcements.json
NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72 NX_WALLETCONNECT_PROJECT_ID=fe8091dc35738863e509fc4947525c72
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
#Test configuration variables #Test configuration variables
CYPRESS_FAIRGROUND=false CYPRESS_FAIRGROUND=false
+2 -1
View File
@@ -3,7 +3,7 @@ NX_VEGA_ENV=CUSTOM
NX_ETHEREUM_PROVIDER_URL=http://localhost:8545 NX_ETHEREUM_PROVIDER_URL=http://localhost:8545
NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_FAIRGROUND=false NX_FAIRGROUND=false
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}' NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/test/announcements.json
NX_VEGA_CONFIG_URL='' NX_VEGA_CONFIG_URL=''
@@ -17,6 +17,7 @@ NX_VEGA_WALLET_URL=http://localhost:1789
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50 NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz
NX_VEGA_REST_URL=http://localhost:3008/api/v2/
#Test configuration variables #Test configuration variables
CYPRESS_FAIRGROUND=false CYPRESS_FAIRGROUND=false
+4 -2
View File
@@ -2,7 +2,7 @@
NX_VEGA_ENV=DEVNET NX_VEGA_ENV=DEVNET
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/devnet1/vegawallet-devnet1.toml
NX_VEGA_URL=https://api.n00.devnet1.vega.xyz/graphql NX_VEGA_URL=https://api.n00.devnet1.vega.xyz/graphql
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}' NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8 NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
@@ -10,4 +10,6 @@ NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50 NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-devnet1-k8s.ops.vega.xyz 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_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
+5 -3
View File
@@ -1,14 +1,16 @@
# App configuration variables # App configuration variables
NX_VEGA_ENV=MAINNET NX_VEGA_ENV=MAINNET
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/mainnet1/mainnet1.toml
NX_VEGA_URL=https://api.vega.xyz/query NX_VEGA_URL=https://api.vega.community/graphql
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}' 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://eth-mainnet.gateway.pokt.network/v1/lb/6684b914570bbfa533ba9324
NX_ETHERSCAN_URL=https://etherscan.io NX_ETHERSCAN_URL=https://etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions 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_EXPLORER_URL=https://explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/mainnet
NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996 NX_SENTRY_DSN=https://4b8c8a8ba07742648aa4dfe1b8d17e40:87edc2605e544f888305d7fc4a9141bd@o286262.ingest.sentry.io/5882996
NX_DELEGATIONS_PAGINATION=50 NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-mainnet-k8s.ops.vega.xyz 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_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 # App configuration variables
NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql NX_VEGA_URL=https://api.n00.stagnet1.vega.xyz/graphql
NX_VEGA_ENV=STAGNET1 NX_VEGA_ENV=STAGNET1
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","STAGNET1":"https://stagnet1.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}' 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_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/stagnet1/vegawallet-stagnet1.toml 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://stagnet1.explorer.vega.xyz
NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet NX_VEGA_DOCS_URL=https://docs.vega.xyz/testnet
NX_DELEGATIONS_PAGINATION=50 NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-stagnet1-k8s.ops.vega.xyz 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_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json
NX_VEGA_REST_URL=https://api.n00.stagnet1.vega.xyz/api/v2/
+3 -1
View File
@@ -2,7 +2,7 @@
NX_VEGA_ENV=TESTNET NX_VEGA_ENV=TESTNET
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks-internal/main/fairground/vegawallet-fairground.toml
NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql NX_VEGA_URL=https://api.n07.testnet.vega.xyz/graphql
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}' NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8 NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
@@ -12,3 +12,5 @@ NX_HOSTED_WALLET_URL=https://wallet.testnet.vega.xyz
NX_DELEGATIONS_PAGINATION=50 NX_DELEGATIONS_PAGINATION=50
NX_TRANCHES_SERVICE_URL=https://tranches-testnet-k8s.ops.vega.xyz 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_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
@@ -3,9 +3,11 @@ NX_VEGA_ENV=VALIDATOR_TESTNET
NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.toml NX_VEGA_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/networks/master/testnet2/testnet2.toml
NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql NX_VEGA_URL=https://api-validators-testnet.vega.rocks/graphql
NX_VEGA_REST=https://api-validators-testnet.vega.rocks/ NX_VEGA_REST=https://api-validators-testnet.vega.rocks/
NX_VEGA_NETWORKS='{"DEVNET":"https://dev.token.vega.xyz","TESTNET":"https://token.fairground.wtf","MAINNET":"https://token.vega.xyz"}' NX_VEGA_NETWORKS='{"DEVNET":"https://dev.governance.vega.xyz","TESTNET":"https://governance.fairground.wtf","MAINNET":"https://governance.vega.xyz"}'
NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8 NX_ETHEREUM_PROVIDER_URL=https://sepolia.infura.io/v3/4f846e79e13f44d1b51bbd7ed9edefb8
NX_ETHERSCAN_URL=https://sepolia.etherscan.io NX_ETHERSCAN_URL=https://sepolia.etherscan.io
NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions NX_GITHUB_FEEDBACK_URL=https://github.com/vegaprotocol/feedback/discussions
NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz NX_VEGA_EXPLORER_URL=https://dev.explorer.vega.xyz
NX_ANNOUNCEMENTS_CONFIG_URL=https://raw.githubusercontent.com/vegaprotocol/announcements/fairground/announcements.json 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;
+9 -3
View File
@@ -58,9 +58,15 @@ export const AppLoader = ({ children }: { children: React.ReactElement }) => {
token.decimals(), token.decimals(),
]); ]);
const totalSupply = toBigNum(supply, decimals); const totalSupply = toBigNum(supply.toString(), decimals);
const totalWallet = toBigNum(totalAssociatedWallet, decimals); const totalWallet = toBigNum(
const totalVesting = toBigNum(totalAssociatedVesting, decimals); totalAssociatedWallet.toString(),
decimals
);
const totalVesting = toBigNum(
totalAssociatedVesting.toString(),
decimals
);
appDispatch({ appDispatch({
type: AppStateActionType.SET_TOKEN, type: AppStateActionType.SET_TOKEN,
+104 -30
View File
@@ -2,7 +2,6 @@ import './i18n';
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import * as Sentry from '@sentry/react'; import * as Sentry from '@sentry/react';
import { Integrations } from '@sentry/tracing';
import { BrowserRouter as Router, useLocation } from 'react-router-dom'; import { BrowserRouter as Router, useLocation } from 'react-router-dom';
import { AppLoader } from './app-loader'; import { AppLoader } from './app-loader';
import { NetworkInfo } from '@vegaprotocol/network-info'; 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 { ContractsProvider } from './contexts/contracts/contracts-provider';
import { AppRouter } from './routes'; import { AppRouter } from './routes';
import type { EthereumConfig } from '@vegaprotocol/web3'; import type { EthereumConfig } from '@vegaprotocol/web3';
import { WithdrawalApprovalDialogContainer } from '@vegaprotocol/web3';
import { import {
createConnectors, createConnectors,
useEthTransactionManager, useEthTransactionManager,
@@ -37,12 +37,23 @@ import {
useEnvironment, useEnvironment,
NetworkLoader, NetworkLoader,
useInitializeEnv, useInitializeEnv,
NodeGuard,
AppFailure,
NodeSwitcherDialog,
useNodeSwitcherStore,
} from '@vegaprotocol/environment'; } from '@vegaprotocol/environment';
import { ENV } from './config'; import { ENV } from './config';
import type { InMemoryCacheConfig } from '@apollo/client'; import type { InMemoryCacheConfig } from '@apollo/client';
import { WithdrawalDialog } from '@vegaprotocol/withdraws'; import { CreateWithdrawalDialog } from '@vegaprotocol/withdraws';
import { SplashLoader } from './components/splash-loader'; import { SplashLoader } from './components/splash-loader';
import { ToastsManager } from './toasts-manager'; import { ToastsManager } from './toasts-manager';
import {
TelemetryDialog,
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 = { const cache: InMemoryCacheConfig = {
typePolicies: { typePolicies: {
@@ -148,7 +159,9 @@ const Web3Container = ({
<InitializeHandlers /> <InitializeHandlers />
<VegaWalletDialogs /> <VegaWalletDialogs />
<TransactionModal /> <TransactionModal />
<WithdrawalDialog /> <CreateWithdrawalDialog />
<WithdrawalApprovalDialogContainer />
<TelemetryDialog />
</> </>
</BalanceManager> </BalanceManager>
</AppLoader> </AppLoader>
@@ -173,58 +186,119 @@ const ScrollToTop = () => {
return null; return null;
}; };
const removeQueryParams = (url: string) => {
return url.split('?')[0];
};
const AppContainer = () => { const AppContainer = () => {
const { config, loading, error } = useEthereumConfig(); const { config, loading, error } = useEthereumConfig();
const { VEGA_ENV, GIT_COMMIT_HASH, GIT_BRANCH, ETHEREUM_PROVIDER_URL } = const {
useEnvironment(); 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(() => { useEffect(() => {
if (ENV.dsn) { if (ENV.dsn && telemetryOn === 'true') {
Sentry.init({ Sentry.init({
dsn: ENV.dsn, dsn: ENV.dsn,
integrations: [new Integrations.BrowserTracing()],
tracesSampleRate: 0.1, tracesSampleRate: 0.1,
enabled: true, enabled: true,
environment: VEGA_ENV, environment: VEGA_ENV,
release: GIT_COMMIT_HASH, release: GIT_COMMIT_HASH,
beforeSend(event) { beforeSend(event, hint) {
if (event.request?.url?.includes('/claim?')) { const error = hint?.originalException;
return { const errorIsString = typeof error === 'string';
...event, const errorIsObject = error instanceof Error;
request: { const requestUrl = event.request?.url;
...event.request, const transaction = event.transaction;
url: event.request?.url.split('?')[0],
}, 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); Sentry.setTag('branch', GIT_BRANCH);
Sentry.setTag('commit', GIT_COMMIT_HASH); Sentry.setTag('commit', GIT_COMMIT_HASH);
} else {
Sentry.close();
} }
}, [GIT_COMMIT_HASH, GIT_BRANCH, VEGA_ENV]); }, [GIT_COMMIT_HASH, GIT_BRANCH, VEGA_ENV, telemetryOn]);
return ( return (
<Router> <Router>
<ScrollToTop /> <ScrollToTop />
<AppStateProvider> <AppStateProvider>
<div className="grid min-h-full text-white"> <div className="grid min-h-full text-white">
<AsyncRenderer<EthereumConfig | null> <NodeGuard
loading={loading} skeleton={<div>{t('Loading')}</div>}
data={config} failure={
error={error} <AppFailure title={t('NodeUnsuitable', { url: VEGA_URL })} />
render={(cnf) =>
cnf && (
<Web3Container
chainId={Number(cnf.chain_id)}
providerUrl={ETHEREUM_PROVIDER_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> </div>
</AppStateProvider> </AppStateProvider>
<NodeSwitcherDialog open={nodeSwitcherOpen} setOpen={setNodeSwitcher} />
</Router> </Router>
); );
}; };
@@ -1,23 +1,14 @@
import { Button } from '@vegaprotocol/ui-toolkit'; import { Button } from '@vegaprotocol/ui-toolkit';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useWeb3ConnectStore } from '@vegaprotocol/web3';
import {
AppStateActionType,
useAppState,
} from '../../contexts/app-state/app-state-context';
export const EthConnectPrompt = () => { export const EthConnectPrompt = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const { appDispatch } = useAppState(); const { open } = useWeb3ConnectStore();
return ( return (
<Button <Button
variant="default" variant="default"
onClick={() => onClick={open}
appDispatch({
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
isOpen: true,
})
}
fill={true} fill={true}
data-testid="connect-to-eth-btn" data-testid="connect-to-eth-btn"
> >
@@ -2,10 +2,7 @@ import { Button } from '@vegaprotocol/ui-toolkit';
import { useWeb3React } from '@web3-react/core'; import { useWeb3React } from '@web3-react/core';
import type { ReactElement } from 'react'; import type { ReactElement } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import { useWeb3ConnectStore } from '@vegaprotocol/web3';
AppStateActionType,
useAppState,
} from '../../contexts/app-state/app-state-context';
export const EthWalletContainer = ({ export const EthWalletContainer = ({
children, children,
@@ -14,21 +11,12 @@ export const EthWalletContainer = ({
}) => { }) => {
const { account } = useWeb3React(); const { account } = useWeb3React();
const { t } = useTranslation(); const { t } = useTranslation();
const { appDispatch } = useAppState(); const { open } = useWeb3ConnectStore();
if (!account) { if (!account) {
return ( return (
<div className="w-full text-center"> <div className="w-full text-center">
<Button <Button onClick={open}>{t('connectEthWallet')}</Button>
onClick={() =>
appDispatch({
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
isOpen: true,
})
}
>
{t('connectEthWallet')}
</Button>
</div> </div>
); );
} }
@@ -27,7 +27,11 @@ import {
import { Loader } from '@vegaprotocol/ui-toolkit'; import { Loader } from '@vegaprotocol/ui-toolkit';
import colors from 'tailwindcss/colors'; import colors from 'tailwindcss/colors';
import { useBalances } from '../../lib/balances/balances-store'; 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'; import { getChainName } from '@vegaprotocol/web3';
const removeLeadingAddressSymbol = (key: string) => { const removeLeadingAddressSymbol = (key: string) => {
@@ -189,6 +193,7 @@ export const EthWallet = () => {
const pendingTxs = usePendingTransactions(); const pendingTxs = usePendingTransactions();
const disconnect = useWeb3Disconnect(connector); const disconnect = useWeb3Disconnect(connector);
const { config } = useEthereumConfig(); const { config } = useEthereumConfig();
const { open } = useWeb3ConnectStore();
return ( return (
<WalletCard> <WalletCard>
@@ -233,12 +238,7 @@ export const EthWallet = () => {
) : ( ) : (
<Button <Button
fill={true} fill={true}
onClick={() => onClick={open}
appDispatch({
type: AppStateActionType.SET_ETH_WALLET_OVERLAY,
isOpen: true,
})
}
data-testid="connect-to-eth-wallet-button" data-testid="connect-to-eth-wallet-button"
> >
{t('connectEthWalletToAssociate')} {t('connectEthWalletToAssociate')}
+21 -1
View File
@@ -11,11 +11,26 @@ import {
NavigationLink, NavigationLink,
NavigationList, NavigationList,
NavigationTrigger, NavigationTrigger,
Icon,
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import { EthWallet } from '../eth-wallet'; import { EthWallet } from '../eth-wallet';
import { VegaWallet } from '../vega-wallet'; import { VegaWallet } from '../vega-wallet';
import { useLocation, useMatch } from 'react-router-dom'; import { useLocation, useMatch } from 'react-router-dom';
import { useEffect } from 'react'; import { useEffect } from 'react';
import { useTelemetryDialog } from '../telemetry-dialog/telemetry-dialog';
export const SettingsLink = () => {
const { open, isOpen, close } = useTelemetryDialog();
return (
<button
type="button"
onClick={() => (isOpen ? close() : open())}
aria-label="Open Telemetry Settings"
>
<Icon name="cog" className="w-5 h-5 mr-2" />
</button>
);
};
export const Nav = ({ theme }: Pick<NavigationProps, 'theme'>) => { export const Nav = ({ theme }: Pick<NavigationProps, 'theme'>) => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -42,7 +57,12 @@ export const Nav = ({ theme }: Pick<NavigationProps, 'theme'>) => {
)); ));
return ( return (
<Navigation appName="Governance" theme={theme} breakpoints={[458, 959]}> <Navigation
appName="Governance"
theme={theme}
breakpoints={[458, 959]}
actions={<SettingsLink />}
>
<NavigationList <NavigationList
className="[.drawer-content_&]:border-b [.drawer-content_&]:border-b-vega-light-200 dark:[.drawer-content_&]:border-b-vega-dark-200 [.drawer-content_&]:pb-8 [.drawer-content_&]:mb-2" className="[.drawer-content_&]:border-b [.drawer-content_&]:border-b-vega-light-200 dark:[.drawer-content_&]:border-b-vega-dark-200 [.drawer-content_&]:pb-8 [.drawer-content_&]:mb-2"
hide={[NavigationBreakpoint.Small]} hide={[NavigationBreakpoint.Small]}
@@ -0,0 +1,53 @@
import { renderHook, act } from '@testing-library/react';
import { useTelemetryDialog, TELEMETRY_ON } from './telemetry-dialog';
describe('useTelemetryDialog', () => {
beforeEach(() => {
localStorage.clear();
});
it('should have the correct initial state based on localStorage', () => {
localStorage.setItem(TELEMETRY_ON, 'true');
const { result } = renderHook(() => useTelemetryDialog());
expect(result.current.isOpen).toBe(false);
expect(result.current.telemetryAccepted).toBe(true);
});
it('should update localStorage and the telemetryAccepted state when setTelemetryAccepted is called', () => {
const { result } = renderHook(() => useTelemetryDialog());
act(() => {
result.current.setTelemetryAccepted(true);
});
expect(result.current.telemetryAccepted).toBe(true);
expect(localStorage.getItem(TELEMETRY_ON)).toBe('true');
});
it('should update localStorage and the isOpen state when close is called', () => {
const { result } = renderHook(() => useTelemetryDialog());
act(() => {
result.current.close();
});
expect(result.current.isOpen).toBe(false);
});
it('should update the isOpen state when open is called', () => {
const { result } = renderHook(() => useTelemetryDialog());
act(() => {
result.current.open();
});
expect(result.current.isOpen).toBe(true);
});
it('should open the dialog if TELEMETRY_ON is not set', () => {
const { result } = renderHook(() => useTelemetryDialog());
expect(result.current.isOpen).toBe(true);
});
});
@@ -0,0 +1,102 @@
import { create } from 'zustand';
import { useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { useLocalStorage } from '@vegaprotocol/react-helpers';
import { Dialog, Icon, Button } from '@vegaprotocol/ui-toolkit';
import { Networks, useEnvironment } from '@vegaprotocol/environment';
type TelemetryDialogState = {
isOpen: boolean;
open: () => void;
close: () => void;
};
const useTelemetryDialogStore = create<TelemetryDialogState>((set) => ({
isOpen: false,
open: () => set({ isOpen: true }),
close: () => set({ isOpen: false }),
}));
export const TELEMETRY_ON = 'vega_telemetry_on';
export const useTelemetryDialog = () => {
const [telemetryOn, setTelemetryOn] = useLocalStorage(TELEMETRY_ON);
const { VEGA_ENV } = useEnvironment();
const isMainnet = VEGA_ENV === Networks.MAINNET;
const defaultTelemetryAccepted = isMainnet ? 'false' : 'true';
const { isOpen, open, close } = useTelemetryDialogStore();
useEffect(() => {
if (telemetryOn === null || telemetryOn === undefined) {
open();
setTelemetryOn(defaultTelemetryAccepted);
}
}, [defaultTelemetryAccepted, open, setTelemetryOn, telemetryOn]);
return {
isOpen,
open: open,
close: close,
telemetryAccepted: telemetryOn === 'true',
setTelemetryAccepted: (value: boolean) => {
setTelemetryOn(value.toString());
},
};
};
export const TelemetryDialog = () => {
const { t } = useTranslation();
const { isOpen, open, close, telemetryAccepted, setTelemetryAccepted } =
useTelemetryDialog();
return (
<Dialog
title={t('ImproveVegaGovernance')}
open={isOpen}
onChange={(isOpen) => (isOpen ? open() : close())}
size="small"
>
<div className="mt-6">{t('TelemetryModalIntro')}</div>
<div className="flex items-center mt-6">
<Icon name="eye-off" className="mr-6" size={6} />
<div className="flex flex-col gap-1">
<div className="font-semibold">{t('Anonymous')}</div>
<div>{t('YourIdentityAnonymous')}</div>
</div>
</div>
<div className="flex items-center mt-6">
<Icon name="cog" className="mr-6" size={6} />
<div className="flex flex-col gap-1">
<div className="font-semibold">{t('Optional')}</div>
<div>{t('OptOutOfTelemetry')}</div>
</div>
</div>
<div className="flex items-center mt-10 gap-4">
<Button
onClick={() => {
setTelemetryAccepted(false);
close();
}}
variant="default"
data-testid="do-not-share-data-button"
>
{t('NoThanks')}
</Button>
<Button
onClick={() => {
setTelemetryAccepted(true);
close();
}}
variant="primary"
data-testid="share-data-button"
>
{telemetryAccepted ? t('ContinueSharingData') : t('ShareData')}
</Button>
</div>
</Dialog>
);
};
@@ -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, useAppState,
} from '../../contexts/app-state/app-state-context'; } from '../../contexts/app-state/app-state-context';
import { Connectors } from '../../lib/vega-connectors'; import { Connectors } from '../../lib/vega-connectors';
import { RiskMessage } from './risk-message';
export const VegaWalletDialogs = () => { export const VegaWalletDialogs = () => {
const { appState, appDispatch } = useAppState(); const { appState, appDispatch } = useAppState();
return ( return (
<> <>
<VegaConnectDialog <VegaConnectDialog
@@ -17,6 +19,7 @@ export const VegaWalletDialogs = () => {
isOpen: open, isOpen: open,
}) })
} }
riskMessage={<RiskMessage />}
/> />
<VegaManageDialog <VegaManageDialog
@@ -1,6 +1,6 @@
import { Link } from '@vegaprotocol/ui-toolkit'; import { Link } from '@vegaprotocol/ui-toolkit';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { ExternalLinks } from '@vegaprotocol/utils'; import { ExternalLinks } from '@vegaprotocol/environment';
export const DownloadWalletPrompt = () => { export const DownloadWalletPrompt = () => {
const { t } = useTranslation(); const { t } = useTranslation();
@@ -26,6 +26,7 @@ import type {
WalletDelegationFieldsFragment, WalletDelegationFieldsFragment,
} from './__generated__/Delegations'; } from './__generated__/Delegations';
import { DelegationsDocument } from './__generated__/Delegations'; import { DelegationsDocument } from './__generated__/Delegations';
import { isPartyNotFoundError } from '../../lib/party';
export const usePollForDelegations = () => { export const usePollForDelegations = () => {
const { token: vegaToken } = useContracts(); const { token: vegaToken } = useContracts();
@@ -75,6 +76,7 @@ export const usePollForDelegations = () => {
}) })
.then((res) => { .then((res) => {
if (!mounted) return; if (!mounted) return;
const canonisedDelegations = removePaginationWrapper( const canonisedDelegations = removePaginationWrapper(
res.data.party?.delegationsConnection?.edges res.data.party?.delegationsConnection?.edges
); );
@@ -203,6 +205,15 @@ export const usePollForDelegations = () => {
setDelegatedNodes(delegatedAmounts); setDelegatedNodes(delegatedAmounts);
}) })
.catch((err: Error) => { .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); Sentry.captureException(err);
// If query fails stop interval. Its almost certain that the query // If query fails stop interval. Its almost certain that the query
// will just continue to fail // will just continue to fail
@@ -25,20 +25,26 @@ export function Web3Connector({
connectors, connectors,
chainId, chainId,
}: Web3ConnectorProps) { }: Web3ConnectorProps) {
const { appState, appDispatch } = useAppState(); const { open, close, isOpen } = useWeb3ConnectStore();
const setDialogOpen = useCallback( const setDialogOpen = useCallback(
(isOpen: boolean) => { (isOpen: boolean) => {
appDispatch({ type: AppStateActionType.SET_ETH_WALLET_OVERLAY, isOpen }); if (isOpen) {
open();
} else {
close();
}
}, },
[appDispatch] [open, close]
); );
const appChainId = Number(chainId); const appChainId = Number(chainId);
return ( return (
<> <>
<Web3Content appChainId={appChainId}>{children}</Web3Content> <Web3Content appChainId={appChainId}>{children}</Web3Content>
<Web3ConnectDialog <Web3ConnectDialog
connectors={connectors} connectors={connectors}
dialogOpen={appState.ethConnectOverlay} dialogOpen={isOpen}
setDialogOpen={setDialogOpen} setDialogOpen={setDialogOpen}
desiredChainId={appChainId} desiredChainId={appChainId}
/> />
+1
View File
@@ -62,6 +62,7 @@ export const ENV = {
ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'), ethWalletMnemonic: windowOrDefault('NX_ETH_WALLET_MNEMONIC'),
localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'), localProviderUrl: windowOrDefault('NX_LOCAL_PROVIDER_URL'),
delegationsPagination: windowOrDefault('NX_DELEGATIONS_PAGINATION'), delegationsPagination: windowOrDefault('NX_DELEGATIONS_PAGINATION'),
rest: windowOrDefault('NX_VEGA_REST_URL'),
flags: { flags: {
NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')), NETWORK_DOWN: TRUTHY.includes(windowOrDefault('NX_NETWORK_DOWN')),
MOCK: TRUTHY.includes(windowOrDefault('NX_MOCKED')), MOCK: TRUTHY.includes(windowOrDefault('NX_MOCKED')),
@@ -34,9 +34,6 @@ export interface AppState {
/** Whether or not the manage VEGA wallet overlay is open */ /** Whether or not the manage VEGA wallet overlay is open */
vegaWalletManageOverlay: boolean; vegaWalletManageOverlay: boolean;
/** Whether or not the connect to Ethereum wallet overlay is open */
ethConnectOverlay: boolean;
/** Whether or not the transaction modal is open */ /** Whether or not the transaction modal is open */
transactionOverlay: boolean; transactionOverlay: boolean;
/** /**
@@ -57,7 +54,6 @@ export enum AppStateActionType {
REFRESH_BALANCES, REFRESH_BALANCES,
SET_VEGA_WALLET_OVERLAY, SET_VEGA_WALLET_OVERLAY,
SET_VEGA_WALLET_MANAGE_OVERLAY, SET_VEGA_WALLET_MANAGE_OVERLAY,
SET_ETH_WALLET_OVERLAY,
SET_DRAWER, SET_DRAWER,
REFRESH_ASSOCIATED_BALANCES, REFRESH_ASSOCIATED_BALANCES,
SET_ASSOCIATION_BREAKDOWN, SET_ASSOCIATION_BREAKDOWN,
@@ -81,10 +77,6 @@ export type AppStateAction =
type: AppStateActionType.SET_VEGA_WALLET_MANAGE_OVERLAY; type: AppStateActionType.SET_VEGA_WALLET_MANAGE_OVERLAY;
isOpen: boolean; isOpen: boolean;
} }
| {
type: AppStateActionType.SET_ETH_WALLET_OVERLAY;
isOpen: boolean;
}
| { | {
type: AppStateActionType.SET_DRAWER; type: AppStateActionType.SET_DRAWER;
isOpen: boolean; isOpen: boolean;
@@ -16,7 +16,6 @@ const initialAppState: AppState = {
totalSupply: new BigNumber(0), totalSupply: new BigNumber(0),
vegaWalletOverlay: false, vegaWalletOverlay: false,
vegaWalletManageOverlay: false, vegaWalletManageOverlay: false,
ethConnectOverlay: false,
transactionOverlay: false, transactionOverlay: false,
bannerMessage: '', bannerMessage: '',
disconnectNotice: false, disconnectNotice: false,
@@ -45,12 +44,6 @@ function appStateReducer(state: AppState, action: AppStateAction): AppState {
vegaWalletOverlay: action.isOpen ? false : state.vegaWalletOverlay, vegaWalletOverlay: action.isOpen ? false : state.vegaWalletOverlay,
}; };
} }
case AppStateActionType.SET_ETH_WALLET_OVERLAY: {
return {
...state,
ethConnectOverlay: action.isOpen,
};
}
case AppStateActionType.SET_DRAWER: { case AppStateActionType.SET_DRAWER: {
return { return {
...state, ...state,
@@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
export function useDocumentTitle(name?: string) { export function useDocumentTitle(name?: string) {
const base = 'VEGA token'; const base = 'VEGA Governance';
React.useEffect(() => { React.useEffect(() => {
if (name) { if (name) {
+29 -7
View File
@@ -66,7 +66,7 @@
"claim": "This code ({{code}}) entitles <bold>{{user}}</bold> to <bold>{{amount}} $VEGA</bold> tokens from <trancheLink>{{linkText}}</trancheLink> of the vesting contract. {{expiry}}.", "claim": "This code ({{code}}) entitles <bold>{{user}}</bold> to <bold>{{amount}} $VEGA</bold> tokens from <trancheLink>{{linkText}}</trancheLink> of the vesting contract. {{expiry}}.",
"claimExpiry": "The code expires on {{date}}", "claimExpiry": "The code expires on {{date}}",
"claimNoExpiry": "It has no expiry date", "claimNoExpiry": "It has no expiry date",
"showRedeem": "You'll be able to redeem your unlocked tokens at token.vega.xyz/vesting", "showRedeem": "You'll be able to redeem your unlocked tokens at governance.vega.xyz/vesting",
"codeUsed": "Code already used", "codeUsed": "Code already used",
"codeUsedText": "Looks like that code has already been used. Check the Vesting page to see if you can redeem your tokens.", "codeUsedText": "Looks like that code has already been used. Check the Vesting page to see if you can redeem your tokens.",
"codeExpired": "Code expired", "codeExpired": "Code expired",
@@ -86,7 +86,7 @@
"Awaiting action in Ethereum wallet (e.g. MetaMask)": "Awaiting action in Ethereum wallet (e.g. MetaMask)", "Awaiting action in Ethereum wallet (e.g. MetaMask)": "Awaiting action in Ethereum wallet (e.g. MetaMask)",
"Claim {amount} Vega": "Claim {{amount}} $VEGA", "Claim {amount} Vega": "Claim {{amount}} $VEGA",
"Sorry. It is not possible to claim tokens in your country or region.": "It is not possible to claim tokens in your country or region.", "Sorry. It is not possible to claim tokens in your country or region.": "It is not possible to claim tokens in your country or region.",
"none redeemable": "Tokens in this tranche unlock on {{unlockDate}} and continue to unlock gradually until {{trancheEndDate}} when all tokens are unlocked. Come back to token.vega.xyz to redeem your tokens once they begin to unlock.", "none redeemable": "Tokens in this tranche unlock on {{unlockDate}} and continue to unlock gradually until {{trancheEndDate}} when all tokens are unlocked. Come back to governance.vega.xyz to redeem your tokens once they begin to unlock.",
"partially redeemable": "Tokens in this tranche began to unlock on {{unlockDate}} and will continue to unlock gradually until {{trancheEndDate}} when all tokens are unlocked.", "partially redeemable": "Tokens in this tranche began to unlock on {{unlockDate}} and will continue to unlock gradually until {{trancheEndDate}} when all tokens are unlocked.",
"fully redeemable": "Tokens in this tranche have fully unlocked and can be redeemed once claimed.", "fully redeemable": "Tokens in this tranche have fully unlocked and can be redeemed once claimed.",
"This page can not be found, please check the URL and try again.": "This page can not be found, please check the URL and try again.", "This page can not be found, please check the URL and try again.": "This page can not be found, please check the URL and try again.",
@@ -202,6 +202,7 @@
"tokenVotes": "Token votes", "tokenVotes": "Token votes",
"liquidityVotes": "Liquidity votes", "liquidityVotes": "Liquidity votes",
"castYourVote": "Cast your vote", "castYourVote": "Cast your vote",
"yourVote": "Your vote",
"for": "For", "for": "For",
"against": "Against", "against": "Against",
"majorityRequired": "Majority Required", "majorityRequired": "Majority Required",
@@ -593,7 +594,9 @@
"numberOfAgainstVotes": "Number of votes against", "numberOfAgainstVotes": "Number of votes against",
"yesPercentage": "Yes percentage", "yesPercentage": "Yes percentage",
"noPercentage": "No percentage", "noPercentage": "No percentage",
"proposalTerms": "Proposal terms", "proposalJson": "Full proposal JSON",
"proposalDetails": "Proposal details",
"proposalDescription": "Description",
"currentlySetTo": "Currently expected to ", "currentlySetTo": "Currently expected to ",
"currently": "currently", "currently": "currently",
"finalOutcomeMayDiffer": "Final outcome may differ", "finalOutcomeMayDiffer": "Final outcome may differ",
@@ -678,6 +681,8 @@
"FilterProposalsDescription": "Filter by proposal ID or proposer ID", "FilterProposalsDescription": "Filter by proposal ID or proposer ID",
"Freeform proposal": "Freeform proposal", "Freeform proposal": "Freeform proposal",
"NewProposal": "New proposal", "NewProposal": "New proposal",
"CreateProposalAndDownloadJSONToShare": "Create proposal and download JSON to share",
"SubmitAnAgreedProposalFromTheForum": "Submit an agreed proposal from the forum",
"ProposalTypeQuestion": "What type of proposal would you like to make?", "ProposalTypeQuestion": "What type of proposal would you like to make?",
"NetworkParameterProposal": "Update network parameter proposal", "NetworkParameterProposal": "Update network parameter proposal",
"parameter": "parameter", "parameter": "parameter",
@@ -701,6 +706,7 @@
"AssetID": "Asset ID", "AssetID": "Asset ID",
"Freeform": "Freeform", "Freeform": "Freeform",
"RawProposal": "Let me choose (raw proposal)", "RawProposal": "Let me choose (raw proposal)",
"SubmitAgreedRawProposal": "Submit agreed raw proposal",
"UseMin": "Use minimum", "UseMin": "Use minimum",
"UseMax": "Use maximum", "UseMax": "Use maximum",
"Proposal": "Proposal", "Proposal": "Proposal",
@@ -784,9 +790,9 @@
"homeVegaTokenButtonText": "Manage tokens", "homeVegaTokenButtonText": "Manage tokens",
"downloadProposalJson": "Download proposal as JSON", "downloadProposalJson": "Download proposal as JSON",
"networkUpgrade": "Network Upgrade", "networkUpgrade": "Network Upgrade",
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED": "Approved", "PROTOCOL_UPGRADE_PROPOSAL_STATUS_APPROVED": "Approved by validators",
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_PENDING": "Pending", "PROTOCOL_UPGRADE_PROPOSAL_STATUS_PENDING": "Waiting for validator votes",
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_REJECTED": "Rejected", "PROTOCOL_UPGRADE_PROPOSAL_STATUS_REJECTED": "Declined by validators",
"PROTOCOL_UPGRADE_PROPOSAL_STATUS_UNSPECIFIED": "Unspecified", "PROTOCOL_UPGRADE_PROPOSAL_STATUS_UNSPECIFIED": "Unspecified",
"vegaRelease{release}": "Vega Release {{release}}", "vegaRelease{release}": "Vega Release {{release}}",
"upgradeBlockHeight": "Upgrade block height", "upgradeBlockHeight": "Upgrade block height",
@@ -799,5 +805,21 @@
"associateVegaNow": "Associate $VEGA now", "associateVegaNow": "Associate $VEGA now",
"disconnectedNotice": "You have been disconnected. Connect your ETH wallet to the {{correctNetwork}} network to use this app.", "disconnectedNotice": "You have been disconnected. Connect your ETH wallet to the {{correctNetwork}} network to use this app.",
"connectAVegaWalletToVote": "Connect a Vega wallet with $VEGA tokens to vote on a proposal.", "connectAVegaWalletToVote": "Connect a Vega wallet with $VEGA tokens to vote on a proposal.",
"findOutMoreAboutHowToVote": "Find out more about how to vote on Vega" "findOutMoreAboutHowToVote": "Find out more about how to vote on Vega",
"ImproveVegaGovernance": "Improve Vega governance",
"TelemetryModalIntro": "Help us identify bugs and improve Vega Governance by sharing anonymous usage data.",
"Anonymous": "Anonymous",
"YourIdentityAnonymous": "Your identity is always anonymous on Vega",
"Optional": "Optional",
"OptOutOfTelemetry": "You can opt out any time via settings",
"NoThanks": "No thanks",
"ShareData": "Share 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."
} }
+1 -1
View File
@@ -24,7 +24,7 @@
type="font/woff2" type="font/woff2"
crossorigin="anonymous" crossorigin="anonymous"
/> />
<title>Vega Token dApp</title> <title>Vega Governance dApp</title>
<script src="./assets/env-config.js"></script> <script src="./assets/env-config.js"></script>
</head> </head>
<body class="h-full"> <body class="h-full">
+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) => { ?.map((t) => {
const tranche_progress = const tranche_progress =
t.duration !== 0 ? (now - t.cliff_start) / t.duration : 0; 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 { return {
tranche_id: t.tranche_id, tranche_id: t.tranche_id,
tranche_start: secondsToDate(t.cliff_start), tranche_start: secondsToDate(t.cliff_start),
@@ -60,7 +75,7 @@ export const useTranches = create<TranchesStore>()((set) => ({
toBigNum(t.current_balance, decimals) toBigNum(t.current_balance, decimals)
), ),
locked_amount: toBigNum(t.initial_balance, decimals).times( locked_amount: toBigNum(t.initial_balance, decimals).times(
lockedDecimal clampedLockedDecimal
), ),
users: t.users, 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 { ProposalsListItem } from '../proposals/components/proposals-list-item';
import { ProtocolUpgradeProposalsListItem } from '../proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item'; import { ProtocolUpgradeProposalsListItem } from '../proposals/components/protocol-upgrade-proposals-list-item/protocol-upgrade-proposals-list-item';
import Routes from '../routes'; 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 { useNodesQuery } from '../staking/home/__generated__/Nodes';
import { useProposalsQuery } from '../proposals/proposals/__generated__/Proposals'; import { useProposalsQuery } from '../proposals/proposals/__generated__/Proposals';
import { import {
@@ -26,6 +27,10 @@ import type { ProposalFieldsFragment } from '../proposals/proposals/__generated_
import type { NodesFragmentFragment } from '../staking/home/__generated__/Nodes'; import type { NodesFragmentFragment } from '../staking/home/__generated__/Nodes';
import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals'; import type { ProtocolUpgradeProposalFieldsFragment } from '@vegaprotocol/proposals';
import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals'; import { useProtocolUpgradeProposalsQuery } from '@vegaprotocol/proposals';
import {
orderByDate,
orderByUpgradeBlockHeight,
} from '../proposals/components/proposals-list/proposals-list';
const nodesToShow = 6; const nodesToShow = 6;
@@ -199,17 +204,20 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
const proposals = useMemo( const proposals = useMemo(
() => () =>
proposalsData proposalsData
? getNotRejectedProposals<ProposalFieldsFragment>( ? getNotRejectedProposals(proposalsData.proposalsConnection)
proposalsData.proposalsConnection
)
: [], : [],
[proposalsData] [proposalsData]
); );
const sortedProposals = useMemo(
() => orderByDate(proposals).reverse(),
[proposals]
);
const protocolUpgradeProposals = useMemo( const protocolUpgradeProposals = useMemo(
() => () =>
protocolUpgradesData protocolUpgradesData
? getNotRejectedProtocolUpgradeProposals<ProtocolUpgradeProposalFieldsFragment>( ? getNotRejectedProtocolUpgradeProposals(
protocolUpgradesData.protocolUpgradeProposals protocolUpgradesData.protocolUpgradeProposals
).filter( ).filter(
(p) => (p) =>
@@ -220,15 +228,20 @@ const GovernanceHome = ({ name }: RouteChildProps) => {
[protocolUpgradesData] [protocolUpgradesData]
); );
const sortedProtocolUpgradeProposals = useMemo(
() => orderByUpgradeBlockHeight(protocolUpgradeProposals),
[protocolUpgradeProposals]
);
const totalProposalsDesired = 4; const totalProposalsDesired = 4;
const protocolUpgradeProposalsToShow = protocolUpgradeProposals.slice( const protocolUpgradeProposalsToShow = sortedProtocolUpgradeProposals.slice(
0, 0,
totalProposalsDesired totalProposalsDesired
); );
const proposalsToShow = const proposalsToShow =
protocolUpgradeProposalsToShow.length === totalProposalsDesired protocolUpgradeProposalsToShow.length === totalProposalsDesired
? [] ? []
: proposals.slice( : sortedProposals.slice(
0, 0,
totalProposalsDesired - protocolUpgradeProposalsToShow.length totalProposalsDesired - protocolUpgradeProposalsToShow.length
); );
@@ -53,7 +53,6 @@ const mockAppState: AppState = {
totalSupply: new BigNumber(65000000), totalSupply: new BigNumber(65000000),
vegaWalletOverlay: false, vegaWalletOverlay: false,
vegaWalletManageOverlay: false, vegaWalletManageOverlay: false,
ethConnectOverlay: false,
transactionOverlay: false, transactionOverlay: false,
bannerMessage: '', bannerMessage: '',
disconnectNotice: false, disconnectNotice: false,
@@ -0,0 +1 @@
export { ProposalDescription } from './proposal-description';
@@ -0,0 +1,51 @@
import ReactMarkdown from 'react-markdown';
import classnames from 'classnames';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Icon, RoundedWrapper } from '@vegaprotocol/ui-toolkit';
import { SubHeading } from '../../../../components/heading';
export const ProposalDescription = ({
description,
}: {
description: string;
}) => {
const { t } = useTranslation();
const [showDescription, setShowDescription] = useState(false);
const showDescriptionIconClasses = classnames('mb-4', {
'rotate-180': showDescription,
});
return (
<section data-testid="proposal-description">
<button
onClick={() => setShowDescription(!showDescription)}
data-testid="proposal-description-toggle"
>
<div className="flex items-center gap-3">
<SubHeading title={t('proposalDescription')} />
<div className={showDescriptionIconClasses}>
<Icon name="chevron-down" size={8} />
</div>
</div>
</button>
{showDescription && (
<RoundedWrapper paddingBottom={true} marginBottomLarge={true}>
<div className="p-2">
<ReactMarkdown
className="react-markdown-container"
/* Prevents HTML embedded in the description from rendering */
skipHtml={true}
/* Stops users embedding images which could be used for tracking */
disallowedElements={['img']}
linkTarget="_blank"
>
{description}
</ReactMarkdown>
</div>
</RoundedWrapper>
)}
</section>
);
};
@@ -124,7 +124,7 @@ describe('Proposal header', () => {
}) })
); );
expect(screen.getByTestId('proposal-title')).toHaveTextContent( expect(screen.getByTestId('proposal-title')).toHaveTextContent(
'Unknown proposal' 'New asset proposal'
); );
expect(screen.getByTestId('proposal-type')).toHaveTextContent('New asset'); expect(screen.getByTestId('proposal-type')).toHaveTextContent('New asset');
expect(screen.getByTestId('proposal-details')).toHaveTextContent( expect(screen.getByTestId('proposal-details')).toHaveTextContent(
@@ -206,28 +206,6 @@ describe('Proposal header', () => {
).not.toBeInTheDocument(); ).not.toBeInTheDocument();
}); });
it('Renders Freeform proposal - long rationale (105 chars) - details', () => {
renderComponent(
generateProposal({
id: 'long',
rationale: {
title: '0x0',
description:
'Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Aenean dolor.',
},
terms: {
change: {
__typename: 'NewFreeform',
},
},
}),
false
);
expect(screen.getByTestId('proposal-description')).toHaveTextContent(
/Class aptent/
);
});
// Remove once proposals have rationale and re-enable above tests // Remove once proposals have rationale and re-enable above tests
it('Renders Freeform proposal - id for title', () => { it('Renders Freeform proposal - id for title', () => {
renderComponent( renderComponent(
@@ -5,7 +5,6 @@ import { Heading, SubHeading } from '../../../../components/heading';
import type { ReactNode } from 'react'; import type { ReactNode } from 'react';
import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals'; import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import type { ProposalQuery } from '../../proposal/__generated__/Proposal'; import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import ReactMarkdown from 'react-markdown';
import { truncateMiddle } from '../../../../lib/truncate-middle'; import { truncateMiddle } from '../../../../lib/truncate-middle';
import { CurrentProposalState } from '../current-proposal-state'; import { CurrentProposalState } from '../current-proposal-state';
import { ProposalInfoLabel } from '../proposal-info-label'; import { ProposalInfoLabel } from '../proposal-info-label';
@@ -22,19 +21,16 @@ export const ProposalHeader = ({
let details: ReactNode; let details: ReactNode;
let proposalType = ''; let proposalType = '';
let fallbackTitle = '';
let title = proposal?.rationale.title.trim(); const title = proposal?.rationale.title.trim();
let description = proposal?.rationale.description.trim();
if (title?.length === 0 && description && description.length > 0) {
title = description;
description = '';
}
const titleContent = shorten(title ?? '', 100); const titleContent = shorten(title ?? '', 100);
switch (change?.__typename) { switch (change?.__typename) {
case 'NewMarket': { case 'NewMarket': {
proposalType = 'NewMarket'; proposalType = 'NewMarket';
fallbackTitle = t('NewMarketProposal');
details = ( details = (
<> <>
<span> <span>
@@ -56,6 +52,7 @@ export const ProposalHeader = ({
} }
case 'UpdateMarket': { case 'UpdateMarket': {
proposalType = 'UpdateMarket'; proposalType = 'UpdateMarket';
fallbackTitle = t('UpdateMarketProposal');
details = ( details = (
<> <>
<span>{t('Market change')}:</span>{' '} <span>{t('Market change')}:</span>{' '}
@@ -66,6 +63,7 @@ export const ProposalHeader = ({
} }
case 'NewAsset': { case 'NewAsset': {
proposalType = 'NewAsset'; proposalType = 'NewAsset';
fallbackTitle = t('NewAssetProposal');
details = ( details = (
<> <>
<span>{t('Symbol')}:</span> <Lozenge>{change.symbol}.</Lozenge>{' '} <span>{t('Symbol')}:</span> <Lozenge>{change.symbol}.</Lozenge>{' '}
@@ -87,6 +85,7 @@ export const ProposalHeader = ({
} }
case 'UpdateNetworkParameter': { case 'UpdateNetworkParameter': {
proposalType = 'NetworkParameter'; proposalType = 'NetworkParameter';
fallbackTitle = t('NetworkParameterProposal');
details = ( details = (
<> <>
<span>{t('Change')}:</span>{' '} <span>{t('Change')}:</span>{' '}
@@ -101,11 +100,13 @@ export const ProposalHeader = ({
} }
case 'NewFreeform': { case 'NewFreeform': {
proposalType = 'Freeform'; proposalType = 'Freeform';
fallbackTitle = t('FreeformProposal');
details = <span />; details = <span />;
break; break;
} }
case 'UpdateAsset': { case 'UpdateAsset': {
proposalType = 'UpdateAsset'; proposalType = 'UpdateAsset';
fallbackTitle = t('UpdateAssetProposal');
details = ( details = (
<> <>
<span>{t('AssetID')}:</span>{' '} <span>{t('AssetID')}:</span>{' '}
@@ -121,10 +122,14 @@ export const ProposalHeader = ({
<div data-testid="proposal-title"> <div data-testid="proposal-title">
{isListItem ? ( {isListItem ? (
<header> <header>
<SubHeading title={titleContent || t('Unknown proposal')} /> <SubHeading
title={titleContent || fallbackTitle || t('Unknown proposal')}
/>
</header> </header>
) : ( ) : (
<Heading title={titleContent || t('Unknown proposal')} /> <Heading
title={titleContent || fallbackTitle || t('Unknown proposal')}
/>
)} )}
</div> </div>
@@ -145,23 +150,6 @@ export const ProposalHeader = ({
{details} {details}
</div> </div>
)} )}
{description && !isListItem && (
<div data-testid="proposal-description">
{/*<div className="uppercase mr-2">{t('ProposalDescription')}:</div>*/}
<SubHeading title={t('ProposalDescription')} />
<ReactMarkdown
className="react-markdown-container"
/* Prevents HTML embedded in the description from rendering */
skipHtml={true}
/* Stops users embedding images which could be used for tracking */
disallowedElements={['img']}
linkTarget="_blank"
>
{description}
</ReactMarkdown>
</div>
)}
</> </>
); );
}; };
@@ -0,0 +1 @@
export { ProposalJson } from './proposal-json';
@@ -1,15 +1,15 @@
import classnames from 'classnames';
import { useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { Icon, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit'; import { Icon, SyntaxHighlighter } from '@vegaprotocol/ui-toolkit';
import { SubHeading } from '../../../../components/heading'; import { SubHeading } from '../../../../components/heading';
import type { PartialDeep } from 'type-fest'; import type { ProposalFieldsFragment } from '../../proposals/__generated__/Proposals';
import type * as Schema from '@vegaprotocol/types'; import type { ProposalQuery } from '../../proposal/__generated__/Proposal';
import { useState } from 'react';
import classnames from 'classnames';
export const ProposalTermsJson = ({ export const ProposalJson = ({
terms, proposal,
}: { }: {
terms: PartialDeep<Schema.ProposalTerms>; proposal: ProposalFieldsFragment | ProposalQuery['proposal'];
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const [showDetails, setShowDetails] = useState(false); const [showDetails, setShowDetails] = useState(false);
@@ -18,20 +18,20 @@ export const ProposalTermsJson = ({
}); });
return ( return (
<section> <section data-testid="proposal-json">
<button <button
onClick={() => setShowDetails(!showDetails)} onClick={() => setShowDetails(!showDetails)}
data-testid="proposal-terms-toggle" data-testid="proposal-json-toggle"
> >
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<SubHeading title={t('proposalTerms')} /> <SubHeading title={t('proposalJson')} />
<div className={showDetailsIconClasses}> <div className={showDetailsIconClasses}>
<Icon name="chevron-down" size={8} /> <Icon name="chevron-down" size={8} />
</div> </div>
</div> </div>
</button> </button>
{showDetails && <SyntaxHighlighter data={terms} />} {showDetails && <SyntaxHighlighter data={proposal} />}
</section> </section>
); );
}; };
@@ -1 +0,0 @@
export { ProposalTermsJson } from './proposal-terms-json';
@@ -0,0 +1 @@
export { ProposalTerms } from './proposal-terms';

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